comparison libgsmfr2/comfort_noise.c @ 256:a33edf624061

libgsmfr2: start with API definition and port of libgsmfrp code
author Mychaela Falconia <falcon@freecalypso.org>
date Fri, 12 Apr 2024 20:49:53 +0000
parents libgsmfrp/comfort_noise.c@f081a6850fb5
children 573afa985df6
comparison
equal deleted inserted replaced
255:07f936338de1 256:a33edf624061
1 /*
2 * In this module we implement comfort noise generation per GSM 06.12
3 * or 3GPP TS 46.012.
4 */
5
6 #include <stdint.h>
7 #include <string.h>
8 #include "tw_gsmfr.h"
9 #include "pp_internal.h"
10
11 static const uint8_t fold_table_8to6[24] = {
12 1, 2, 3, 4, 5, 6, 1, 2,
13 1, 2, 3, 4, 5, 6, 3, 4,
14 1, 2, 3, 4, 5, 6, 5, 6,
15 };
16
17 static const uint8_t bc[4] = {0, 0, 0, 0};
18 static const uint8_t Nc[4] = {40, 120, 40, 120};
19
20 static uint8_t random_1to6(struct gsmfr_preproc_state *st)
21 {
22 uint8_t range8, range6;
23
24 range8 = gsmfr_preproc_prng(st, 3);
25 range6 = fold_table_8to6[(st->cn_random_6fold << 3) | range8];
26 st->cn_random_6fold++;
27 if (st->cn_random_6fold >= 3)
28 st->cn_random_6fold = 0;
29 return range6;
30 }
31
32 void gsmfr_preproc_gen_cn(struct gsmfr_preproc_state *st, uint8_t *frame)
33 {
34 unsigned sub, pulse;
35 uint8_t Mc, xmc[13];
36 uint8_t *c;
37
38 /* global bytes (magic and LARc) are fixed */
39 memcpy(frame, st->sid_prefix, 5);
40 c = frame + 5;
41 /* now do the 4 subframes, mostly PRNG output */
42 for (sub = 0; sub < 4; sub++) {
43 Mc = gsmfr_preproc_prng(st, 2);
44 for (pulse = 0; pulse < 13; pulse++)
45 xmc[pulse] = random_1to6(st);
46 /* packing code from libgsm */
47 *c++ = ((Nc[sub] & 0x7F) << 1)
48 | ((bc[sub] >> 1) & 0x1);
49 *c++ = ((bc[sub] & 0x1) << 7)
50 | ((Mc & 0x3) << 5)
51 | ((st->sid_xmaxc >> 1) & 0x1F);
52 *c++ = ((st->sid_xmaxc & 0x1) << 7)
53 | ((xmc[0] & 0x7) << 4)
54 | ((xmc[1] & 0x7) << 1)
55 | ((xmc[2] >> 2) & 0x1);
56 *c++ = ((xmc[2] & 0x3) << 6)
57 | ((xmc[3] & 0x7) << 3)
58 | (xmc[4] & 0x7);
59 *c++ = ((xmc[5] & 0x7) << 5)
60 | ((xmc[6] & 0x7) << 2)
61 | ((xmc[7] >> 1) & 0x3);
62 *c++ = ((xmc[7] & 0x1) << 7)
63 | ((xmc[8] & 0x7) << 4)
64 | ((xmc[9] & 0x7) << 1)
65 | ((xmc[10] >> 2) & 0x1);
66 *c++ = ((xmc[10] & 0x3) << 6)
67 | ((xmc[11] & 0x7) << 3)
68 | (xmc[12] & 0x7);
69 }
70 }
71
72 void gsmfr_preproc_sid2cn(struct gsmfr_preproc_state *st, uint8_t *frame)
73 {
74 unsigned sub, pulse;
75 uint8_t Mc, xmc[13];
76 uint8_t *c;
77
78 /* save LARc and Xmaxc from the last subframe for subsequent CN gen */
79 memcpy(st->sid_prefix, frame, 5);
80 st->sid_xmaxc = ((frame[27] & 0x1F) << 1) | (frame[28] >> 7);
81 /* ... and turn *this* frame into very first CN output */
82 c = frame + 5;
83 for (sub = 0; sub < 4; sub++) {
84 Mc = gsmfr_preproc_prng(st, 2);
85 for (pulse = 0; pulse < 13; pulse++)
86 xmc[pulse] = random_1to6(st);
87 /* keep each of Xmaxc and replace the rest with CN */
88 *c++ = ((Nc[sub] & 0x7F) << 1)
89 | ((bc[sub] >> 1) & 0x1);
90 *c &= 0x1F;
91 *c++ |= ((bc[sub] & 0x1) << 7)
92 | ((Mc & 0x3) << 5);
93 *c &= 0x80;
94 *c++ |= ((xmc[0] & 0x7) << 4)
95 | ((xmc[1] & 0x7) << 1)
96 | ((xmc[2] >> 2) & 0x1);
97 *c++ = ((xmc[2] & 0x3) << 6)
98 | ((xmc[3] & 0x7) << 3)
99 | (xmc[4] & 0x7);
100 *c++ = ((xmc[5] & 0x7) << 5)
101 | ((xmc[6] & 0x7) << 2)
102 | ((xmc[7] >> 1) & 0x3);
103 *c++ = ((xmc[7] & 0x1) << 7)
104 | ((xmc[8] & 0x7) << 4)
105 | ((xmc[9] & 0x7) << 1)
106 | ((xmc[10] >> 2) & 0x1);
107 *c++ = ((xmc[10] & 0x3) << 6)
108 | ((xmc[11] & 0x7) << 3)
109 | (xmc[12] & 0x7);
110 }
111 }