comparison libgsmefr/dtx_common.c @ 119:c1d53064b410

libgsmefr: split dtx.c into dtx_{common,dec,enc}.c
author Mychaela Falconia <falcon@freecalypso.org>
date Sat, 10 Dec 2022 02:25:20 +0000
parents libgsmefr/dtx.c@58b64224d4ac
children 7bc011aceb7f
comparison
equal deleted inserted replaced
118:cc08498ed21b 119:c1d53064b410
1 /*
2 * This file is a product of splitting ETSI EFR dtx.c into parts;
3 * the present module is the common part for both the encoder and
4 * the decoder.
5 */
6
7 #include "gsm_efr.h"
8 #include "typedef.h"
9 #include "namespace.h"
10 #include "basic_op.h"
11 #include "cnst.h"
12 #include "sig_proc.h"
13 #include "memops.h"
14 #include "no_count.h"
15 #include "dtx.h"
16 #include "dtx_defs.h"
17
18 /*************************************************************************
19 *
20 * FUNCTION NAME: update_lsf_history
21 *
22 * PURPOSE: Update the LSF parameter history. The LSF parameters kept
23 * in the buffer are used later for computing the reference
24 * LSF parameter vector and the averaged LSF parameter vector.
25 *
26 * INPUTS: lsf1[0..9] LSF vector of the 1st half of the frame
27 * lsf2[0..9] LSF vector of the 2nd half of the frame
28 * lsf_old[0..DTX_HANGOVER-1][0..M-1]
29 * Old LSF history
30 *
31 * OUTPUTS: lsf_old[0..DTX_HANGOVER-1][0..M-1]
32 * Updated LSF history
33 *
34 * RETURN VALUE: none
35 *
36 *************************************************************************/
37
38 void update_lsf_history (
39 Word16 lsf1[M],
40 Word16 lsf2[M],
41 Word16 lsf_old[DTX_HANGOVER][M]
42 )
43 {
44 Word16 i, j, temp;
45
46 /* shift LSF data to make room for LSFs from current frame */
47 /* This can also be implemented by using circular buffering */
48
49 for (i = DTX_HANGOVER - 1; i > 0; i--)
50 {
51 for (j = 0; j < M; j++)
52 {
53 lsf_old[i][j] = lsf_old[i - 1][j]; move16 ();
54 }
55 }
56
57 /* Store new LSF data to lsf_old buffer */
58
59 for (i = 0; i < M; i++)
60 {
61 temp = add (shr (lsf1[i], 1), shr (lsf2[i], 1));
62 lsf_old[0][i] = temp; move16 ();
63 }
64
65 return;
66 }
67
68 /*************************************************************************
69 *
70 * FUNCTION NAME: update_lsf_p_CN
71 *
72 * PURPOSE: Update the reference LSF parameter vector. The reference
73 * vector is computed by averaging the quantized LSF parameter
74 * vectors which exist in the LSF parameter history.
75 *
76 * INPUTS: lsf_old[0..DTX_HANGOVER-1][0..M-1]
77 * LSF parameter history
78 *
79 * OUTPUTS: lsf_p_CN[0..9] Computed reference LSF parameter vector
80 *
81 * RETURN VALUE: none
82 *
83 *************************************************************************/
84
85 void update_lsf_p_CN (
86 Word16 lsf_old[DTX_HANGOVER][M],
87 Word16 lsf_p_CN[M]
88 )
89 {
90 Word16 i, j;
91 Word32 L_temp;
92
93 for (j = 0; j < M; j++)
94 {
95 L_temp = L_mult (INV_DTX_HANGOVER, lsf_old[0][j]);
96 for (i = 1; i < DTX_HANGOVER; i++)
97 {
98 L_temp = L_mac (L_temp, INV_DTX_HANGOVER, lsf_old[i][j]);
99 }
100 lsf_p_CN[j] = round (L_temp); move16 ();
101 }
102
103 return;
104 }
105
106 /*************************************************************************
107 *
108 * FUNCTION NAME: update_gcode0_CN
109 *
110 * PURPOSE: Update the reference fixed codebook gain parameter value.
111 * The reference value is computed by averaging the quantized
112 * fixed codebook gain parameter values which exist in the
113 * fixed codebook gain parameter history.
114 *
115 * INPUTS: gain_code_old[0..4*DTX_HANGOVER-1]
116 * fixed codebook gain parameter history
117 *
118 * OUTPUTS: none
119 *
120 * RETURN VALUE: Computed reference fixed codebook gain
121 *
122 *************************************************************************/
123
124 Word16 update_gcode0_CN (
125 Word16 gain_code_old[4 * DTX_HANGOVER]
126 )
127 {
128 Word16 i, j;
129 Word32 L_temp, L_ret;
130
131 L_ret = 0L; move32 ();
132 for (i = 0; i < DTX_HANGOVER; i++)
133 {
134 L_temp = L_mult (0x1fff, gain_code_old[4 * i]);
135 for (j = 1; j < 4; j++)
136 {
137 L_temp = L_mac (L_temp, 0x1fff, gain_code_old[4 * i + j]);
138 }
139 L_ret = L_mac (L_ret, INV_DTX_HANGOVER, extract_h (L_temp));
140 }
141
142 return extract_h (L_ret);
143 }
144
145 /*************************************************************************
146 *
147 * FUNCTION NAME: build_CN_code
148 *
149 * PURPOSE: Compute the comfort noise fixed codebook excitation. The
150 * gains of the pulses are always +/-1.
151 *
152 * INPUTS: *seed Old CN generator shift register state
153 *
154 * OUTPUTS: cod[0..39] Generated comfort noise fixed codebook vector
155 * *seed Updated CN generator shift register state
156 *
157 * RETURN VALUE: none
158 *
159 *************************************************************************/
160
161 void build_CN_code (
162 Word16 cod[],
163 Word32 *seed
164 )
165 {
166 Word16 i, j, k;
167
168 for (i = 0; i < L_SUBFR; i++)
169 {
170 cod[i] = 0; move16 ();
171 }
172
173 for (k = 0; k < NB_PULSE; k++)
174 {
175 i = pseudonoise (seed, 2); /* generate pulse position */
176 i = shr (extract_l (L_mult (i, 10)), 1);
177 i = add (i, k);
178
179 j = pseudonoise (seed, 1); /* generate sign */
180
181 test ();
182 if (j > 0)
183 {
184 cod[i] = 4096; move16 ();
185 }
186 else
187 {
188 cod[i] = -4096; move16 ();
189 }
190 }
191
192 return;
193 }
194
195 /*************************************************************************
196 *
197 * FUNCTION NAME: pseudonoise
198 *
199 * PURPOSE: Generate a random integer value to use in comfort noise
200 * generation. The algorithm uses polynomial x^31 + x^3 + 1
201 * (length of PN sequence is 2^31 - 1).
202 *
203 * INPUTS: *shift_reg Old CN generator shift register state
204 *
205 *
206 * OUTPUTS: *shift_reg Updated CN generator shift register state
207 *
208 * RETURN VALUE: Generated random integer value
209 *
210 *************************************************************************/
211
212 Word16 pseudonoise (
213 Word32 *shift_reg,
214 Word16 no_bits
215 )
216 {
217 Word16 noise_bits, Sn, i;
218
219 noise_bits = 0; move16 ();
220 for (i = 0; i < no_bits; i++)
221 {
222 /* State n == 31 */
223 test (); logic32 ();
224 if ((*shift_reg & 0x00000001L) != 0)
225 {
226 Sn = 1; move16 ();
227 }
228 else
229 {
230 Sn = 0; move16 ();
231 }
232
233 /* State n == 3 */
234 test (); logic32 ();
235 if ((*shift_reg & 0x10000000L) != 0)
236 {
237 Sn = Sn ^ 1; logic16 ();
238 }
239 else
240 {
241 Sn = Sn ^ 0; logic16 ();
242 }
243
244 noise_bits = shl (noise_bits, 1);
245 noise_bits = noise_bits | (extract_l (*shift_reg) & 1);
246 logic16 (); logic16 ();
247
248 *shift_reg = L_shr (*shift_reg, 1); move32 ();
249 test (); logic16 ();
250 if (Sn & 1)
251 {
252 *shift_reg = *shift_reg | 0x40000000L; move32 (); logic32 ();
253 }
254 }
255
256 return noise_bits;
257 }