annotate libgsmfrp/comfort_noise.c @ 242:f081a6850fb5

libgsmfrp: new refined implementation The previous implementation exhibited the following defects, which are now fixed: 1) The last received valid SID was cached forever for the purpose of handling future invalid SIDs - we could have received some valid SID ages ago, then lots of speech or NO_DATA, and if we then get an invalid SID, we would resurrect the last valid SID from ancient history - a bad design. In our new design, we handle invalid SID based on the current state, much like BFI. 2) GSM 06.11 spec says clearly that after the second lost SID (received BFI=1 && TAF=1 in CN state) we need to gradually decrease the output level, rather than jump directly to emitting silence frames - we previously failed to implement such logic. 3) Per GSM 06.12 section 5.2, Xmaxc should be the same in all 4 subframes in a SID frame. What should we do if we receive an otherwise valid SID frame with different Xmaxc? Our previous approach would replicate this Xmaxc oddity in every subsequent generated CN frame, which is rather bad. In our new design, the very first CN frame (which can be seen as a transformation of the SID frame itself) retains the original 4 distinct Xmaxc, but all subsequent CN frames are based on the Xmaxc from the last subframe of the most recent SID.
author Mychaela Falconia <falcon@freecalypso.org>
date Tue, 09 May 2023 05:16:31 +0000
parents 3b64f255689a
children
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
4
286d5f097eb4 libgsmfrp: implement comfort noise generation
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
1 /*
286d5f097eb4 libgsmfrp: implement comfort noise generation
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
2 * In this module we implement comfort noise generation per GSM 06.12
286d5f097eb4 libgsmfrp: implement comfort noise generation
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
3 * or 3GPP TS 46.012.
286d5f097eb4 libgsmfrp: implement comfort noise generation
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
4 */
286d5f097eb4 libgsmfrp: implement comfort noise generation
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
5
286d5f097eb4 libgsmfrp: implement comfort noise generation
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
6 #include <stdint.h>
286d5f097eb4 libgsmfrp: implement comfort noise generation
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
7 #include <string.h>
286d5f097eb4 libgsmfrp: implement comfort noise generation
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
8 #include "gsm_fr_preproc.h"
286d5f097eb4 libgsmfrp: implement comfort noise generation
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
9 #include "internal.h"
286d5f097eb4 libgsmfrp: implement comfort noise generation
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
10
286d5f097eb4 libgsmfrp: implement comfort noise generation
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
11 static const uint8_t fold_table_8to6[24] = {
286d5f097eb4 libgsmfrp: implement comfort noise generation
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
12 1, 2, 3, 4, 5, 6, 1, 2,
286d5f097eb4 libgsmfrp: implement comfort noise generation
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
13 1, 2, 3, 4, 5, 6, 3, 4,
286d5f097eb4 libgsmfrp: implement comfort noise generation
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
14 1, 2, 3, 4, 5, 6, 5, 6,
286d5f097eb4 libgsmfrp: implement comfort noise generation
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
15 };
286d5f097eb4 libgsmfrp: implement comfort noise generation
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
16
286d5f097eb4 libgsmfrp: implement comfort noise generation
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
17 static const uint8_t bc[4] = {0, 0, 0, 0};
286d5f097eb4 libgsmfrp: implement comfort noise generation
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
18 static const uint8_t Nc[4] = {40, 120, 40, 120};
286d5f097eb4 libgsmfrp: implement comfort noise generation
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
19
286d5f097eb4 libgsmfrp: implement comfort noise generation
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
20 static uint8_t random_1to6(struct gsmfr_preproc_state *st)
286d5f097eb4 libgsmfrp: implement comfort noise generation
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
21 {
286d5f097eb4 libgsmfrp: implement comfort noise generation
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
22 uint8_t range8, range6;
286d5f097eb4 libgsmfrp: implement comfort noise generation
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
23
108
3b64f255689a libgsmfrp: factor out PRNG into its own module,
Mychaela Falconia <falcon@freecalypso.org>
parents: 4
diff changeset
24 range8 = gsmfr_preproc_prng(st, 3);
4
286d5f097eb4 libgsmfrp: implement comfort noise generation
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
25 range6 = fold_table_8to6[(st->cn_random_6fold << 3) | range8];
286d5f097eb4 libgsmfrp: implement comfort noise generation
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
26 st->cn_random_6fold++;
286d5f097eb4 libgsmfrp: implement comfort noise generation
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
27 if (st->cn_random_6fold >= 3)
286d5f097eb4 libgsmfrp: implement comfort noise generation
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
28 st->cn_random_6fold = 0;
286d5f097eb4 libgsmfrp: implement comfort noise generation
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
29 return range6;
286d5f097eb4 libgsmfrp: implement comfort noise generation
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
30 }
286d5f097eb4 libgsmfrp: implement comfort noise generation
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
31
286d5f097eb4 libgsmfrp: implement comfort noise generation
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
32 void gsmfr_preproc_gen_cn(struct gsmfr_preproc_state *st, gsm_byte *frame)
286d5f097eb4 libgsmfrp: implement comfort noise generation
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
33 {
286d5f097eb4 libgsmfrp: implement comfort noise generation
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
34 unsigned sub, pulse;
286d5f097eb4 libgsmfrp: implement comfort noise generation
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
35 uint8_t Mc, xmc[13];
286d5f097eb4 libgsmfrp: implement comfort noise generation
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
36 gsm_byte *c;
286d5f097eb4 libgsmfrp: implement comfort noise generation
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
37
286d5f097eb4 libgsmfrp: implement comfort noise generation
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
38 /* global bytes (magic and LARc) are fixed */
286d5f097eb4 libgsmfrp: implement comfort noise generation
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
39 memcpy(frame, st->sid_prefix, 5);
286d5f097eb4 libgsmfrp: implement comfort noise generation
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
40 c = frame + 5;
286d5f097eb4 libgsmfrp: implement comfort noise generation
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
41 /* now do the 4 subframes, mostly PRNG output */
286d5f097eb4 libgsmfrp: implement comfort noise generation
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
42 for (sub = 0; sub < 4; sub++) {
108
3b64f255689a libgsmfrp: factor out PRNG into its own module,
Mychaela Falconia <falcon@freecalypso.org>
parents: 4
diff changeset
43 Mc = gsmfr_preproc_prng(st, 2);
4
286d5f097eb4 libgsmfrp: implement comfort noise generation
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
44 for (pulse = 0; pulse < 13; pulse++)
286d5f097eb4 libgsmfrp: implement comfort noise generation
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
45 xmc[pulse] = random_1to6(st);
286d5f097eb4 libgsmfrp: implement comfort noise generation
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
46 /* packing code from libgsm */
286d5f097eb4 libgsmfrp: implement comfort noise generation
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
47 *c++ = ((Nc[sub] & 0x7F) << 1)
286d5f097eb4 libgsmfrp: implement comfort noise generation
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
48 | ((bc[sub] >> 1) & 0x1);
286d5f097eb4 libgsmfrp: implement comfort noise generation
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
49 *c++ = ((bc[sub] & 0x1) << 7)
286d5f097eb4 libgsmfrp: implement comfort noise generation
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
50 | ((Mc & 0x3) << 5)
242
f081a6850fb5 libgsmfrp: new refined implementation
Mychaela Falconia <falcon@freecalypso.org>
parents: 108
diff changeset
51 | ((st->sid_xmaxc >> 1) & 0x1F);
f081a6850fb5 libgsmfrp: new refined implementation
Mychaela Falconia <falcon@freecalypso.org>
parents: 108
diff changeset
52 *c++ = ((st->sid_xmaxc & 0x1) << 7)
4
286d5f097eb4 libgsmfrp: implement comfort noise generation
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
53 | ((xmc[0] & 0x7) << 4)
286d5f097eb4 libgsmfrp: implement comfort noise generation
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
54 | ((xmc[1] & 0x7) << 1)
286d5f097eb4 libgsmfrp: implement comfort noise generation
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
55 | ((xmc[2] >> 2) & 0x1);
286d5f097eb4 libgsmfrp: implement comfort noise generation
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
56 *c++ = ((xmc[2] & 0x3) << 6)
286d5f097eb4 libgsmfrp: implement comfort noise generation
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
57 | ((xmc[3] & 0x7) << 3)
286d5f097eb4 libgsmfrp: implement comfort noise generation
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
58 | (xmc[4] & 0x7);
286d5f097eb4 libgsmfrp: implement comfort noise generation
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
59 *c++ = ((xmc[5] & 0x7) << 5)
286d5f097eb4 libgsmfrp: implement comfort noise generation
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
60 | ((xmc[6] & 0x7) << 2)
286d5f097eb4 libgsmfrp: implement comfort noise generation
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
61 | ((xmc[7] >> 1) & 0x3);
286d5f097eb4 libgsmfrp: implement comfort noise generation
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
62 *c++ = ((xmc[7] & 0x1) << 7)
286d5f097eb4 libgsmfrp: implement comfort noise generation
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
63 | ((xmc[8] & 0x7) << 4)
286d5f097eb4 libgsmfrp: implement comfort noise generation
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
64 | ((xmc[9] & 0x7) << 1)
286d5f097eb4 libgsmfrp: implement comfort noise generation
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
65 | ((xmc[10] >> 2) & 0x1);
286d5f097eb4 libgsmfrp: implement comfort noise generation
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
66 *c++ = ((xmc[10] & 0x3) << 6)
286d5f097eb4 libgsmfrp: implement comfort noise generation
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
67 | ((xmc[11] & 0x7) << 3)
286d5f097eb4 libgsmfrp: implement comfort noise generation
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
68 | (xmc[12] & 0x7);
286d5f097eb4 libgsmfrp: implement comfort noise generation
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
69 }
286d5f097eb4 libgsmfrp: implement comfort noise generation
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
70 }
242
f081a6850fb5 libgsmfrp: new refined implementation
Mychaela Falconia <falcon@freecalypso.org>
parents: 108
diff changeset
71
f081a6850fb5 libgsmfrp: new refined implementation
Mychaela Falconia <falcon@freecalypso.org>
parents: 108
diff changeset
72 void gsmfr_preproc_sid2cn(struct gsmfr_preproc_state *st, gsm_byte *frame)
f081a6850fb5 libgsmfrp: new refined implementation
Mychaela Falconia <falcon@freecalypso.org>
parents: 108
diff changeset
73 {
f081a6850fb5 libgsmfrp: new refined implementation
Mychaela Falconia <falcon@freecalypso.org>
parents: 108
diff changeset
74 unsigned sub, pulse;
f081a6850fb5 libgsmfrp: new refined implementation
Mychaela Falconia <falcon@freecalypso.org>
parents: 108
diff changeset
75 uint8_t Mc, xmc[13];
f081a6850fb5 libgsmfrp: new refined implementation
Mychaela Falconia <falcon@freecalypso.org>
parents: 108
diff changeset
76 gsm_byte *c;
f081a6850fb5 libgsmfrp: new refined implementation
Mychaela Falconia <falcon@freecalypso.org>
parents: 108
diff changeset
77
f081a6850fb5 libgsmfrp: new refined implementation
Mychaela Falconia <falcon@freecalypso.org>
parents: 108
diff changeset
78 /* save LARc and Xmaxc from the last subframe for subsequent CN gen */
f081a6850fb5 libgsmfrp: new refined implementation
Mychaela Falconia <falcon@freecalypso.org>
parents: 108
diff changeset
79 memcpy(st->sid_prefix, frame, 5);
f081a6850fb5 libgsmfrp: new refined implementation
Mychaela Falconia <falcon@freecalypso.org>
parents: 108
diff changeset
80 st->sid_xmaxc = ((frame[27] & 0x1F) << 1) | (frame[28] >> 7);
f081a6850fb5 libgsmfrp: new refined implementation
Mychaela Falconia <falcon@freecalypso.org>
parents: 108
diff changeset
81 /* ... and turn *this* frame into very first CN output */
f081a6850fb5 libgsmfrp: new refined implementation
Mychaela Falconia <falcon@freecalypso.org>
parents: 108
diff changeset
82 c = frame + 5;
f081a6850fb5 libgsmfrp: new refined implementation
Mychaela Falconia <falcon@freecalypso.org>
parents: 108
diff changeset
83 for (sub = 0; sub < 4; sub++) {
f081a6850fb5 libgsmfrp: new refined implementation
Mychaela Falconia <falcon@freecalypso.org>
parents: 108
diff changeset
84 Mc = gsmfr_preproc_prng(st, 2);
f081a6850fb5 libgsmfrp: new refined implementation
Mychaela Falconia <falcon@freecalypso.org>
parents: 108
diff changeset
85 for (pulse = 0; pulse < 13; pulse++)
f081a6850fb5 libgsmfrp: new refined implementation
Mychaela Falconia <falcon@freecalypso.org>
parents: 108
diff changeset
86 xmc[pulse] = random_1to6(st);
f081a6850fb5 libgsmfrp: new refined implementation
Mychaela Falconia <falcon@freecalypso.org>
parents: 108
diff changeset
87 /* keep each of Xmaxc and replace the rest with CN */
f081a6850fb5 libgsmfrp: new refined implementation
Mychaela Falconia <falcon@freecalypso.org>
parents: 108
diff changeset
88 *c++ = ((Nc[sub] & 0x7F) << 1)
f081a6850fb5 libgsmfrp: new refined implementation
Mychaela Falconia <falcon@freecalypso.org>
parents: 108
diff changeset
89 | ((bc[sub] >> 1) & 0x1);
f081a6850fb5 libgsmfrp: new refined implementation
Mychaela Falconia <falcon@freecalypso.org>
parents: 108
diff changeset
90 *c &= 0x1F;
f081a6850fb5 libgsmfrp: new refined implementation
Mychaela Falconia <falcon@freecalypso.org>
parents: 108
diff changeset
91 *c++ |= ((bc[sub] & 0x1) << 7)
f081a6850fb5 libgsmfrp: new refined implementation
Mychaela Falconia <falcon@freecalypso.org>
parents: 108
diff changeset
92 | ((Mc & 0x3) << 5);
f081a6850fb5 libgsmfrp: new refined implementation
Mychaela Falconia <falcon@freecalypso.org>
parents: 108
diff changeset
93 *c &= 0x80;
f081a6850fb5 libgsmfrp: new refined implementation
Mychaela Falconia <falcon@freecalypso.org>
parents: 108
diff changeset
94 *c++ |= ((xmc[0] & 0x7) << 4)
f081a6850fb5 libgsmfrp: new refined implementation
Mychaela Falconia <falcon@freecalypso.org>
parents: 108
diff changeset
95 | ((xmc[1] & 0x7) << 1)
f081a6850fb5 libgsmfrp: new refined implementation
Mychaela Falconia <falcon@freecalypso.org>
parents: 108
diff changeset
96 | ((xmc[2] >> 2) & 0x1);
f081a6850fb5 libgsmfrp: new refined implementation
Mychaela Falconia <falcon@freecalypso.org>
parents: 108
diff changeset
97 *c++ = ((xmc[2] & 0x3) << 6)
f081a6850fb5 libgsmfrp: new refined implementation
Mychaela Falconia <falcon@freecalypso.org>
parents: 108
diff changeset
98 | ((xmc[3] & 0x7) << 3)
f081a6850fb5 libgsmfrp: new refined implementation
Mychaela Falconia <falcon@freecalypso.org>
parents: 108
diff changeset
99 | (xmc[4] & 0x7);
f081a6850fb5 libgsmfrp: new refined implementation
Mychaela Falconia <falcon@freecalypso.org>
parents: 108
diff changeset
100 *c++ = ((xmc[5] & 0x7) << 5)
f081a6850fb5 libgsmfrp: new refined implementation
Mychaela Falconia <falcon@freecalypso.org>
parents: 108
diff changeset
101 | ((xmc[6] & 0x7) << 2)
f081a6850fb5 libgsmfrp: new refined implementation
Mychaela Falconia <falcon@freecalypso.org>
parents: 108
diff changeset
102 | ((xmc[7] >> 1) & 0x3);
f081a6850fb5 libgsmfrp: new refined implementation
Mychaela Falconia <falcon@freecalypso.org>
parents: 108
diff changeset
103 *c++ = ((xmc[7] & 0x1) << 7)
f081a6850fb5 libgsmfrp: new refined implementation
Mychaela Falconia <falcon@freecalypso.org>
parents: 108
diff changeset
104 | ((xmc[8] & 0x7) << 4)
f081a6850fb5 libgsmfrp: new refined implementation
Mychaela Falconia <falcon@freecalypso.org>
parents: 108
diff changeset
105 | ((xmc[9] & 0x7) << 1)
f081a6850fb5 libgsmfrp: new refined implementation
Mychaela Falconia <falcon@freecalypso.org>
parents: 108
diff changeset
106 | ((xmc[10] >> 2) & 0x1);
f081a6850fb5 libgsmfrp: new refined implementation
Mychaela Falconia <falcon@freecalypso.org>
parents: 108
diff changeset
107 *c++ = ((xmc[10] & 0x3) << 6)
f081a6850fb5 libgsmfrp: new refined implementation
Mychaela Falconia <falcon@freecalypso.org>
parents: 108
diff changeset
108 | ((xmc[11] & 0x7) << 3)
f081a6850fb5 libgsmfrp: new refined implementation
Mychaela Falconia <falcon@freecalypso.org>
parents: 108
diff changeset
109 | (xmc[12] & 0x7);
f081a6850fb5 libgsmfrp: new refined implementation
Mychaela Falconia <falcon@freecalypso.org>
parents: 108
diff changeset
110 }
f081a6850fb5 libgsmfrp: new refined implementation
Mychaela Falconia <falcon@freecalypso.org>
parents: 108
diff changeset
111 }