annotate libgsmfr2/comfort_noise.c @ 581:e2d5cad04cbf

libgsmhr1 RxFE: store CN R0+LPC separately from speech In the original GSM 06.06 code the ECU for speech mode is entirely separate from the CN generator, maintaining separate state. (The main intertie between them is the speech vs CN state variable, distinguishing between speech and CN BFIs, in addition to the CN-specific function of distinguishing between initial and update SIDs.) In the present RxFE implementation I initially thought that we could use the same saved_frame buffer for both ECU and CN, overwriting just the first 4 params (R0 and LPC) when a valid SID comes in. However, I now realize it was a bad idea: the original code has a corner case (long sequence of speech-mode BFIs to put the ECU in state 6, then SID and CN-mode BFIs, then a good speech frame) that would be broken by that buffer reuse approach. We could eliminate this corner case by resetting the ECU state when passing through a CN insertion period, but doing so would needlessly increase the behavioral diffs between GSM 06.06 and our version. Solution: use a separate CN-specific buffer for CN R0+LPC parameters, and match the behavior of GSM 06.06 code in this regard.
author Mychaela Falconia <falcon@freecalypso.org>
date Thu, 13 Feb 2025 10:02:45 +0000
parents 573afa985df6
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>
256
a33edf624061 libgsmfr2: start with API definition and port of libgsmfrp code
Mychaela Falconia <falcon@freecalypso.org>
parents: 242
diff changeset
8 #include "tw_gsmfr.h"
262
573afa985df6 libgsmfr2: split pp_state.h from pp_internal.h
Mychaela Falconia <falcon@freecalypso.org>
parents: 256
diff changeset
9 #include "pp_state.h"
256
a33edf624061 libgsmfr2: start with API definition and port of libgsmfrp code
Mychaela Falconia <falcon@freecalypso.org>
parents: 242
diff changeset
10 #include "pp_internal.h"
4
286d5f097eb4 libgsmfrp: implement comfort noise generation
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
11
286d5f097eb4 libgsmfrp: implement comfort noise generation
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
12 static const uint8_t fold_table_8to6[24] = {
286d5f097eb4 libgsmfrp: implement comfort noise generation
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
13 1, 2, 3, 4, 5, 6, 1, 2,
286d5f097eb4 libgsmfrp: implement comfort noise generation
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
14 1, 2, 3, 4, 5, 6, 3, 4,
286d5f097eb4 libgsmfrp: implement comfort noise generation
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
15 1, 2, 3, 4, 5, 6, 5, 6,
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
286d5f097eb4 libgsmfrp: implement comfort noise generation
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
18 static const uint8_t bc[4] = {0, 0, 0, 0};
286d5f097eb4 libgsmfrp: implement comfort noise generation
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
19 static const uint8_t Nc[4] = {40, 120, 40, 120};
286d5f097eb4 libgsmfrp: implement comfort noise generation
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
20
286d5f097eb4 libgsmfrp: implement comfort noise generation
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
21 static uint8_t random_1to6(struct gsmfr_preproc_state *st)
286d5f097eb4 libgsmfrp: implement comfort noise generation
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
22 {
286d5f097eb4 libgsmfrp: implement comfort noise generation
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
23 uint8_t range8, range6;
286d5f097eb4 libgsmfrp: implement comfort noise generation
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
24
108
3b64f255689a libgsmfrp: factor out PRNG into its own module,
Mychaela Falconia <falcon@freecalypso.org>
parents: 4
diff changeset
25 range8 = gsmfr_preproc_prng(st, 3);
4
286d5f097eb4 libgsmfrp: implement comfort noise generation
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
26 range6 = fold_table_8to6[(st->cn_random_6fold << 3) | range8];
286d5f097eb4 libgsmfrp: implement comfort noise generation
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
27 st->cn_random_6fold++;
286d5f097eb4 libgsmfrp: implement comfort noise generation
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
28 if (st->cn_random_6fold >= 3)
286d5f097eb4 libgsmfrp: implement comfort noise generation
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
29 st->cn_random_6fold = 0;
286d5f097eb4 libgsmfrp: implement comfort noise generation
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
30 return range6;
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
256
a33edf624061 libgsmfr2: start with API definition and port of libgsmfrp code
Mychaela Falconia <falcon@freecalypso.org>
parents: 242
diff changeset
33 void gsmfr_preproc_gen_cn(struct gsmfr_preproc_state *st, uint8_t *frame)
4
286d5f097eb4 libgsmfrp: implement comfort noise generation
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
34 {
286d5f097eb4 libgsmfrp: implement comfort noise generation
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
35 unsigned sub, pulse;
286d5f097eb4 libgsmfrp: implement comfort noise generation
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
36 uint8_t Mc, xmc[13];
256
a33edf624061 libgsmfr2: start with API definition and port of libgsmfrp code
Mychaela Falconia <falcon@freecalypso.org>
parents: 242
diff changeset
37 uint8_t *c;
4
286d5f097eb4 libgsmfrp: implement comfort noise generation
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
38
286d5f097eb4 libgsmfrp: implement comfort noise generation
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
39 /* global bytes (magic and LARc) are fixed */
286d5f097eb4 libgsmfrp: implement comfort noise generation
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
40 memcpy(frame, st->sid_prefix, 5);
286d5f097eb4 libgsmfrp: implement comfort noise generation
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
41 c = frame + 5;
286d5f097eb4 libgsmfrp: implement comfort noise generation
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
42 /* now do the 4 subframes, mostly PRNG output */
286d5f097eb4 libgsmfrp: implement comfort noise generation
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
43 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
44 Mc = gsmfr_preproc_prng(st, 2);
4
286d5f097eb4 libgsmfrp: implement comfort noise generation
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
45 for (pulse = 0; pulse < 13; pulse++)
286d5f097eb4 libgsmfrp: implement comfort noise generation
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
46 xmc[pulse] = random_1to6(st);
286d5f097eb4 libgsmfrp: implement comfort noise generation
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
47 /* packing code from libgsm */
286d5f097eb4 libgsmfrp: implement comfort noise generation
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
48 *c++ = ((Nc[sub] & 0x7F) << 1)
286d5f097eb4 libgsmfrp: implement comfort noise generation
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
49 | ((bc[sub] >> 1) & 0x1);
286d5f097eb4 libgsmfrp: implement comfort noise generation
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
50 *c++ = ((bc[sub] & 0x1) << 7)
286d5f097eb4 libgsmfrp: implement comfort noise generation
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
51 | ((Mc & 0x3) << 5)
242
f081a6850fb5 libgsmfrp: new refined implementation
Mychaela Falconia <falcon@freecalypso.org>
parents: 108
diff changeset
52 | ((st->sid_xmaxc >> 1) & 0x1F);
f081a6850fb5 libgsmfrp: new refined implementation
Mychaela Falconia <falcon@freecalypso.org>
parents: 108
diff changeset
53 *c++ = ((st->sid_xmaxc & 0x1) << 7)
4
286d5f097eb4 libgsmfrp: implement comfort noise generation
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
54 | ((xmc[0] & 0x7) << 4)
286d5f097eb4 libgsmfrp: implement comfort noise generation
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
55 | ((xmc[1] & 0x7) << 1)
286d5f097eb4 libgsmfrp: implement comfort noise generation
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
56 | ((xmc[2] >> 2) & 0x1);
286d5f097eb4 libgsmfrp: implement comfort noise generation
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
57 *c++ = ((xmc[2] & 0x3) << 6)
286d5f097eb4 libgsmfrp: implement comfort noise generation
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
58 | ((xmc[3] & 0x7) << 3)
286d5f097eb4 libgsmfrp: implement comfort noise generation
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
59 | (xmc[4] & 0x7);
286d5f097eb4 libgsmfrp: implement comfort noise generation
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
60 *c++ = ((xmc[5] & 0x7) << 5)
286d5f097eb4 libgsmfrp: implement comfort noise generation
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
61 | ((xmc[6] & 0x7) << 2)
286d5f097eb4 libgsmfrp: implement comfort noise generation
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
62 | ((xmc[7] >> 1) & 0x3);
286d5f097eb4 libgsmfrp: implement comfort noise generation
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
63 *c++ = ((xmc[7] & 0x1) << 7)
286d5f097eb4 libgsmfrp: implement comfort noise generation
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
64 | ((xmc[8] & 0x7) << 4)
286d5f097eb4 libgsmfrp: implement comfort noise generation
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
65 | ((xmc[9] & 0x7) << 1)
286d5f097eb4 libgsmfrp: implement comfort noise generation
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
66 | ((xmc[10] >> 2) & 0x1);
286d5f097eb4 libgsmfrp: implement comfort noise generation
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
67 *c++ = ((xmc[10] & 0x3) << 6)
286d5f097eb4 libgsmfrp: implement comfort noise generation
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
68 | ((xmc[11] & 0x7) << 3)
286d5f097eb4 libgsmfrp: implement comfort noise generation
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
69 | (xmc[12] & 0x7);
286d5f097eb4 libgsmfrp: implement comfort noise generation
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
70 }
286d5f097eb4 libgsmfrp: implement comfort noise generation
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
71 }
242
f081a6850fb5 libgsmfrp: new refined implementation
Mychaela Falconia <falcon@freecalypso.org>
parents: 108
diff changeset
72
256
a33edf624061 libgsmfr2: start with API definition and port of libgsmfrp code
Mychaela Falconia <falcon@freecalypso.org>
parents: 242
diff changeset
73 void gsmfr_preproc_sid2cn(struct gsmfr_preproc_state *st, uint8_t *frame)
242
f081a6850fb5 libgsmfrp: new refined implementation
Mychaela Falconia <falcon@freecalypso.org>
parents: 108
diff changeset
74 {
f081a6850fb5 libgsmfrp: new refined implementation
Mychaela Falconia <falcon@freecalypso.org>
parents: 108
diff changeset
75 unsigned sub, pulse;
f081a6850fb5 libgsmfrp: new refined implementation
Mychaela Falconia <falcon@freecalypso.org>
parents: 108
diff changeset
76 uint8_t Mc, xmc[13];
256
a33edf624061 libgsmfr2: start with API definition and port of libgsmfrp code
Mychaela Falconia <falcon@freecalypso.org>
parents: 242
diff changeset
77 uint8_t *c;
242
f081a6850fb5 libgsmfrp: new refined implementation
Mychaela Falconia <falcon@freecalypso.org>
parents: 108
diff changeset
78
f081a6850fb5 libgsmfrp: new refined implementation
Mychaela Falconia <falcon@freecalypso.org>
parents: 108
diff changeset
79 /* 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
80 memcpy(st->sid_prefix, frame, 5);
f081a6850fb5 libgsmfrp: new refined implementation
Mychaela Falconia <falcon@freecalypso.org>
parents: 108
diff changeset
81 st->sid_xmaxc = ((frame[27] & 0x1F) << 1) | (frame[28] >> 7);
f081a6850fb5 libgsmfrp: new refined implementation
Mychaela Falconia <falcon@freecalypso.org>
parents: 108
diff changeset
82 /* ... and turn *this* frame into very first CN output */
f081a6850fb5 libgsmfrp: new refined implementation
Mychaela Falconia <falcon@freecalypso.org>
parents: 108
diff changeset
83 c = frame + 5;
f081a6850fb5 libgsmfrp: new refined implementation
Mychaela Falconia <falcon@freecalypso.org>
parents: 108
diff changeset
84 for (sub = 0; sub < 4; sub++) {
f081a6850fb5 libgsmfrp: new refined implementation
Mychaela Falconia <falcon@freecalypso.org>
parents: 108
diff changeset
85 Mc = gsmfr_preproc_prng(st, 2);
f081a6850fb5 libgsmfrp: new refined implementation
Mychaela Falconia <falcon@freecalypso.org>
parents: 108
diff changeset
86 for (pulse = 0; pulse < 13; pulse++)
f081a6850fb5 libgsmfrp: new refined implementation
Mychaela Falconia <falcon@freecalypso.org>
parents: 108
diff changeset
87 xmc[pulse] = random_1to6(st);
f081a6850fb5 libgsmfrp: new refined implementation
Mychaela Falconia <falcon@freecalypso.org>
parents: 108
diff changeset
88 /* keep each of Xmaxc and replace the rest with CN */
f081a6850fb5 libgsmfrp: new refined implementation
Mychaela Falconia <falcon@freecalypso.org>
parents: 108
diff changeset
89 *c++ = ((Nc[sub] & 0x7F) << 1)
f081a6850fb5 libgsmfrp: new refined implementation
Mychaela Falconia <falcon@freecalypso.org>
parents: 108
diff changeset
90 | ((bc[sub] >> 1) & 0x1);
f081a6850fb5 libgsmfrp: new refined implementation
Mychaela Falconia <falcon@freecalypso.org>
parents: 108
diff changeset
91 *c &= 0x1F;
f081a6850fb5 libgsmfrp: new refined implementation
Mychaela Falconia <falcon@freecalypso.org>
parents: 108
diff changeset
92 *c++ |= ((bc[sub] & 0x1) << 7)
f081a6850fb5 libgsmfrp: new refined implementation
Mychaela Falconia <falcon@freecalypso.org>
parents: 108
diff changeset
93 | ((Mc & 0x3) << 5);
f081a6850fb5 libgsmfrp: new refined implementation
Mychaela Falconia <falcon@freecalypso.org>
parents: 108
diff changeset
94 *c &= 0x80;
f081a6850fb5 libgsmfrp: new refined implementation
Mychaela Falconia <falcon@freecalypso.org>
parents: 108
diff changeset
95 *c++ |= ((xmc[0] & 0x7) << 4)
f081a6850fb5 libgsmfrp: new refined implementation
Mychaela Falconia <falcon@freecalypso.org>
parents: 108
diff changeset
96 | ((xmc[1] & 0x7) << 1)
f081a6850fb5 libgsmfrp: new refined implementation
Mychaela Falconia <falcon@freecalypso.org>
parents: 108
diff changeset
97 | ((xmc[2] >> 2) & 0x1);
f081a6850fb5 libgsmfrp: new refined implementation
Mychaela Falconia <falcon@freecalypso.org>
parents: 108
diff changeset
98 *c++ = ((xmc[2] & 0x3) << 6)
f081a6850fb5 libgsmfrp: new refined implementation
Mychaela Falconia <falcon@freecalypso.org>
parents: 108
diff changeset
99 | ((xmc[3] & 0x7) << 3)
f081a6850fb5 libgsmfrp: new refined implementation
Mychaela Falconia <falcon@freecalypso.org>
parents: 108
diff changeset
100 | (xmc[4] & 0x7);
f081a6850fb5 libgsmfrp: new refined implementation
Mychaela Falconia <falcon@freecalypso.org>
parents: 108
diff changeset
101 *c++ = ((xmc[5] & 0x7) << 5)
f081a6850fb5 libgsmfrp: new refined implementation
Mychaela Falconia <falcon@freecalypso.org>
parents: 108
diff changeset
102 | ((xmc[6] & 0x7) << 2)
f081a6850fb5 libgsmfrp: new refined implementation
Mychaela Falconia <falcon@freecalypso.org>
parents: 108
diff changeset
103 | ((xmc[7] >> 1) & 0x3);
f081a6850fb5 libgsmfrp: new refined implementation
Mychaela Falconia <falcon@freecalypso.org>
parents: 108
diff changeset
104 *c++ = ((xmc[7] & 0x1) << 7)
f081a6850fb5 libgsmfrp: new refined implementation
Mychaela Falconia <falcon@freecalypso.org>
parents: 108
diff changeset
105 | ((xmc[8] & 0x7) << 4)
f081a6850fb5 libgsmfrp: new refined implementation
Mychaela Falconia <falcon@freecalypso.org>
parents: 108
diff changeset
106 | ((xmc[9] & 0x7) << 1)
f081a6850fb5 libgsmfrp: new refined implementation
Mychaela Falconia <falcon@freecalypso.org>
parents: 108
diff changeset
107 | ((xmc[10] >> 2) & 0x1);
f081a6850fb5 libgsmfrp: new refined implementation
Mychaela Falconia <falcon@freecalypso.org>
parents: 108
diff changeset
108 *c++ = ((xmc[10] & 0x3) << 6)
f081a6850fb5 libgsmfrp: new refined implementation
Mychaela Falconia <falcon@freecalypso.org>
parents: 108
diff changeset
109 | ((xmc[11] & 0x7) << 3)
f081a6850fb5 libgsmfrp: new refined implementation
Mychaela Falconia <falcon@freecalypso.org>
parents: 108
diff changeset
110 | (xmc[12] & 0x7);
f081a6850fb5 libgsmfrp: new refined implementation
Mychaela Falconia <falcon@freecalypso.org>
parents: 108
diff changeset
111 }
f081a6850fb5 libgsmfrp: new refined implementation
Mychaela Falconia <falcon@freecalypso.org>
parents: 108
diff changeset
112 }