FreeCalypso > hg > gsm-codec-lib
comparison amrconv/ietf2cod.c @ 216:9d59df9b0e4e
amrconv: new program amr-ietf2cod
author | Mychaela Falconia <falcon@freecalypso.org> |
---|---|
date | Fri, 21 Apr 2023 21:28:02 +0000 |
parents | amrconv/cod2ietf.c@4c4649a5fec3 |
children | 1a7d659a952f |
comparison
equal
deleted
inserted
replaced
215:4c4649a5fec3 | 216:9d59df9b0e4e |
---|---|
1 /* | |
2 * This program converts an AMR-encoded speech recording from the common | |
3 * IETF RFC 4867 .amr format into the 3GPP test sequence .cod format. | |
4 */ | |
5 | |
6 #include <stdio.h> | |
7 #include <stdint.h> | |
8 #include <stdlib.h> | |
9 #include <string.h> | |
10 #include <strings.h> | |
11 #include "amr_defs.h" | |
12 | |
13 extern unsigned amr_bit_lengths[9]; | |
14 extern const char amr_file_hdr[IETF_HDR_LEN]; | |
15 extern const uint8_t extra_bytes_per_ft[9]; | |
16 | |
17 static void | |
18 bits2words(ser_bits, cod_words, nbits) | |
19 uint8_t *ser_bits; | |
20 uint16_t *cod_words; | |
21 unsigned nbits; | |
22 { | |
23 uint8_t *sp = ser_bits; | |
24 uint16_t *dp = cod_words; | |
25 unsigned n; | |
26 | |
27 for (n = 0; n < nbits; n++) | |
28 *dp++ = *sp++; | |
29 while (n < MAX_SERIAL_SIZE) | |
30 *dp++ = 0; | |
31 } | |
32 | |
33 main(argc, argv) | |
34 char **argv; | |
35 { | |
36 char *infname, *outfname; | |
37 FILE *inf, *outf; | |
38 uint8_t frm_in[MAX_IF1_BYTES]; | |
39 unsigned frame_no, mode, qbit, sti, sid_mode; | |
40 uint8_t ser_bits[MAX_SERIAL_SIZE]; | |
41 uint16_t cod_words[COD_FORMAT_NWORDS]; | |
42 int rc; | |
43 | |
44 if (argc != 3) { | |
45 fprintf(stderr, "usage: %s input.amr output.cod\n", argv[0]); | |
46 exit(1); | |
47 } | |
48 infname = argv[1]; | |
49 outfname = argv[2]; | |
50 inf = fopen(infname, "r"); | |
51 if (!inf) { | |
52 perror(infname); | |
53 exit(1); | |
54 } | |
55 if (fread(frm_in, 1, IETF_HDR_LEN, inf) != IETF_HDR_LEN || | |
56 bcmp(frm_in, amr_file_hdr, IETF_HDR_LEN)) { | |
57 fprintf(stderr, "error: %s is not in IETF AMR format\n", | |
58 infname); | |
59 exit(1); | |
60 } | |
61 outf = fopen(outfname, "w"); | |
62 if (!outf) { | |
63 perror(outfname); | |
64 exit(1); | |
65 } | |
66 /* padding words which will never be filled */ | |
67 bzero(cod_words + MAX_SERIAL_SIZE + 2, sizeof(uint16_t) * 4); | |
68 for (frame_no = 0; ; frame_no++) { | |
69 rc = getc(inf); | |
70 if (rc < 0) | |
71 break; | |
72 mode = (rc & 0x78) >> 3; | |
73 qbit = (rc & 4) >> 2; | |
74 if (mode == MODE_NO_DATA) { | |
75 cod_words[0] = TX_NO_DATA; | |
76 bzero(cod_words+1, sizeof(uint16_t) * MAX_SERIAL_SIZE); | |
77 cod_words[245] = 0xFFFF; | |
78 goto output; | |
79 } | |
80 if (mode > MRDTX) { | |
81 fprintf(stderr, "error in frame #%u: invalid FT=%u\n", | |
82 frame_no, mode); | |
83 exit(1); | |
84 } | |
85 rc = fread(frm_in, 1, extra_bytes_per_ft[mode], inf); | |
86 if (rc != extra_bytes_per_ft[mode]) { | |
87 fprintf(stderr, | |
88 "error: short read from %s on frame #%u\n", | |
89 infname, frame_no); | |
90 exit(1); | |
91 } | |
92 amr_if1_unpack(frm_in, ser_bits, mode); | |
93 if (mode == MRDTX) { | |
94 sti = (frm_in[4] & 0x10) >> 4; | |
95 sid_mode = 0; | |
96 if (frm_in[4] & 0x08) | |
97 sid_mode |= 1; | |
98 if (frm_in[4] & 0x04) | |
99 sid_mode |= 2; | |
100 if (frm_in[4] & 0x02) | |
101 sid_mode |= 4; | |
102 } | |
103 bits2words(ser_bits, cod_words + 1, amr_bit_lengths[mode]); | |
104 if (mode == MRDTX) { | |
105 if (qbit) | |
106 cod_words[0] = sti ? TX_SID_UPDATE | |
107 : TX_SID_FIRST; | |
108 else | |
109 cod_words[0] = TX_SID_BAD; | |
110 cod_words[245] = sid_mode; | |
111 } else { | |
112 cod_words[0] = qbit ? TX_SPEECH_GOOD : TX_SPEECH_BAD; | |
113 cod_words[245] = mode; | |
114 } | |
115 output: fwrite(cod_words, 2, COD_FORMAT_NWORDS, outf); | |
116 } | |
117 fclose(outf); | |
118 exit(0); | |
119 } |