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