FreeCalypso > hg > gsm-codec-lib
view amrconv/ietf2cod.c @ 478:936a08cc73ce
doc/AMR-library-API: describe the decoder
author | Mychaela Falconia <falcon@freecalypso.org> |
---|---|
date | Sun, 19 May 2024 21:32:31 +0000 |
parents | 1a7d659a952f |
children |
line wrap: on
line source
/* * This program converts an AMR-encoded speech recording from the common * IETF RFC 4867 .amr format into the 3GPP test sequence .cod format. */ #include <stdio.h> #include <stdint.h> #include <stdlib.h> #include <string.h> #include <strings.h> #include "amr_defs.h" extern unsigned amr_bit_lengths[9]; extern const char amr_file_hdr[IETF_HDR_LEN]; extern const uint8_t extra_bytes_per_ft[9]; static void bits2words(ser_bits, cod_words, nbits) uint8_t *ser_bits; uint16_t *cod_words; unsigned nbits; { uint8_t *sp = ser_bits; uint16_t *dp = cod_words; unsigned n; for (n = 0; n < nbits; n++) *dp++ = *sp++; for (; n < MAX_SERIAL_SIZE; n++) *dp++ = 0; } main(argc, argv) char **argv; { char *infname, *outfname; FILE *inf, *outf; uint8_t frm_in[MAX_IF1_BYTES]; unsigned frame_no, mode, qbit, sti, sid_mode; uint8_t ser_bits[MAX_SERIAL_SIZE]; uint16_t cod_words[COD_FORMAT_NWORDS]; int rc; if (argc != 3) { fprintf(stderr, "usage: %s input.amr output.cod\n", argv[0]); exit(1); } infname = argv[1]; outfname = argv[2]; inf = fopen(infname, "r"); if (!inf) { perror(infname); exit(1); } if (fread(frm_in, 1, IETF_HDR_LEN, inf) != IETF_HDR_LEN || bcmp(frm_in, amr_file_hdr, IETF_HDR_LEN)) { fprintf(stderr, "error: %s is not in IETF AMR format\n", infname); exit(1); } outf = fopen(outfname, "w"); if (!outf) { perror(outfname); exit(1); } /* padding words which will never be filled */ bzero(cod_words + MAX_SERIAL_SIZE + 2, sizeof(uint16_t) * 4); for (frame_no = 0; ; frame_no++) { rc = getc(inf); if (rc < 0) break; mode = (rc & 0x78) >> 3; qbit = (rc & 4) >> 2; if (mode == MODE_NO_DATA) { cod_words[0] = TX_NO_DATA; bzero(cod_words+1, sizeof(uint16_t) * MAX_SERIAL_SIZE); cod_words[245] = 0xFFFF; goto output; } if (mode > MRDTX) { fprintf(stderr, "error in frame #%u: invalid FT=%u\n", frame_no, mode); exit(1); } rc = fread(frm_in, 1, extra_bytes_per_ft[mode], inf); if (rc != extra_bytes_per_ft[mode]) { fprintf(stderr, "error: short read from %s on frame #%u\n", infname, frame_no); exit(1); } amr_if1_unpack(frm_in, ser_bits, mode); if (mode == MRDTX) { sti = (frm_in[4] & 0x10) >> 4; sid_mode = 0; if (frm_in[4] & 0x08) sid_mode |= 1; if (frm_in[4] & 0x04) sid_mode |= 2; if (frm_in[4] & 0x02) sid_mode |= 4; } bits2words(ser_bits, cod_words + 1, amr_bit_lengths[mode]); if (mode == MRDTX) { if (qbit) cod_words[0] = sti ? TX_SID_UPDATE : TX_SID_FIRST; else cod_words[0] = TX_SID_BAD; cod_words[245] = sid_mode; } else { cod_words[0] = qbit ? TX_SPEECH_GOOD : TX_SPEECH_BAD; cod_words[245] = mode; } output: fwrite(cod_words, 2, COD_FORMAT_NWORDS, outf); } fclose(outf); exit(0); }