diff options
author | Sylvain Munaut <tnt@246tNt.com> | 2015-12-23 20:53:29 +0100 |
---|---|---|
committer | Sylvain Munaut <tnt@246tNt.com> | 2015-12-23 20:53:29 +0100 |
commit | 39141a86bbaf43ccc7543e0bdf46107d59f539c0 (patch) | |
tree | f45ac20895394e558fedd9d19ce52db13fd722df /codec/ir77_ambe_decode.c | |
parent | 30e476ab5f4302f12c6f1af08d3b7c35a3cd6416 (diff) |
codec: Import current codec code
Signed-off-by: Sylvain Munaut <tnt@246tNt.com>
Diffstat (limited to 'codec/ir77_ambe_decode.c')
-rw-r--r-- | codec/ir77_ambe_decode.c | 199 |
1 files changed, 199 insertions, 0 deletions
diff --git a/codec/ir77_ambe_decode.c b/codec/ir77_ambe_decode.c new file mode 100644 index 0000000..4d8fd7b --- /dev/null +++ b/codec/ir77_ambe_decode.c @@ -0,0 +1,199 @@ +/* Iridium AMBE vocoder - Decoder tool */ + +/* (C) 2015 by Sylvain Munaut <tnt@246tNt.com> + * All Rights Reserved + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <stdio.h> +#include <string.h> + +#include "ambe.h" + + +static const uint8_t wav_hdr[] = { + /* WAV header */ + 'R', 'I', 'F', 'F', /* ChunkID */ + 0x00, 0x00, 0x00, 0x00, /* ChunkSize */ + 'W', 'A', 'V', 'E', /* Format */ + + /* Sub chunk: format */ + 'f', 'm', 't', ' ', /* Subchunk1ID */ + 0x10, 0x00, 0x00, 0x00, /* Subchunk1Size */ + 0x01, 0x00, /* AudioFormat: PCM */ + 0x01, 0x00, /* NumChannels: Mono */ + 0x40, 0x1f, 0x00, 0x00, /* SampleRate: 8000 Hz */ + 0x80, 0x3e, 0x00, 0x00, /* ByteRate: 16k/s */ + 0x02, 0x00, /* BlockAlign: 2 bytes */ + 0x10, 0x00, /* BitsPerSample: 16 */ + + /* Sub chunk: data */ + 'd', 'a', 't', 'a', /* Subchunk2ID */ + 0x00, 0x00, 0x00, 0x00, /* Subchunk2Size */ +}; + +static uint32_t +le32(uint32_t v) +{ +#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ + return v; +#else + return ((v & 0x000000ff) << 24) | + ((v & 0x0000ff00) << 8) | + ((v & 0x00ff0000) >> 8) | + ((v & 0xff000000) >> 24); +#endif +} + +static uint16_t +le16(uint16_t v) +{ +#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ + return v; +#else + return ((v & 0x00ff) << 8) | + ((v & 0xff00) >> 8); +#endif +} + +int main(int argc, char *argv[]) +{ + struct ir77_ambe_decoder *dec = NULL; + FILE *fin, *fout; + int is_wave = 0, l, rv; + + /* Arguments */ + if (argc > 3) { + fprintf(stderr, "Usage: %s [in_file [out_file]]\n", argv[0]); + return -1; + } + + if ((argc < 2) || !strcmp(argv[1], "-")) + fin = stdin; + else { + fin = fopen(argv[1], "rb"); + if (!fin) { + fprintf(stderr, "[!] Unable to open input file\n"); + return -1; + } + } + + if ((argc < 3) || !strcmp(argv[2], "-")) + fout = stdout; + else { + fout = fopen(argv[2], "wb"); + if (!fout) { + fprintf(stderr, "[!] Unable to open output file\n"); + return -1; + } + + l = strlen(argv[2]); + + if ((l > 4) && (!strcmp(".wav", &argv[2][l-4]))) + is_wave = 1; + } + + /* Write inital wave header */ + if (is_wave) { + rv = fwrite(wav_hdr, sizeof(wav_hdr), 1, fout); + if (rv != 1) { + fprintf(stderr, "[!] Failed to write WAV header\n"); + goto exit; + } + } + + /* Init decoder */ + dec = ir77_ambe_decode_alloc(); + if (!dec) + goto exit; + + /* Process all frames */ + l = 0; + + while (!feof(fin)) + { + uint8_t superframe[39]; + int16_t audio[2*360]; + int rv, i; + + /* Read input frame */ + rv = fread(superframe, 1, 39, fin); + if (rv != 39) + break; + + /* Skip dummy frames */ + if ((superframe[0] == 0xff) && (superframe[38] == 0xff)) + continue; + + /* Decompress */ + rv = ir77_ambe_decode_superframe(dec, audio, 2*360, superframe); + if (rv) { + fprintf(stderr, "[!] codec error\n"); + break; + } + + /* Write audio output */ + for (i=0; i<2*360; i++) + audio[i] = le16(audio[i]); + + rv = fwrite(audio, 2, 2*360, fout); + if (rv != 2*360) { + fprintf(stderr, "[!] short write\n"); + break; + } + + /* Keep track of number of samples */ + l += 2*360; + } + + /* Release decoder */ + ir77_ambe_decode_release(dec); + + /* Fix wave header */ + if (is_wave) + { + uint32_t v; + + /* Fixup Subchunk2Size */ + v = le32(l * 2); + + rv = fseek(fout, 40, SEEK_SET); + if (rv < 0) + goto exit; + + rv = fwrite(&v, 4, 1, fout); + if (rv < 0) + goto exit; + + /* Fixup ChunkSize */ + v = le32(l * 2 + 36); + + rv = fseek(fout, 4, SEEK_SET); + if (rv < 0) + goto exit; + + rv = fwrite(&v, 4, 1, fout); + if (rv < 0) + goto exit; + } + +exit: + /* Close in/out */ + fclose(fout); + fclose(fin); + + /* All done ! */ + return 0; +} |