FreeCalypso > hg > gsm-codec-lib
comparison libgsmefr/dtx_dec.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 | 0303ba213e1c |
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 decoder-specific part. | |
4 */ | |
5 | |
6 #include "gsm_efr.h" | |
7 #include "typedef.h" | |
8 #include "namespace.h" | |
9 #include "basic_op.h" | |
10 #include "cnst.h" | |
11 #include "sig_proc.h" | |
12 #include "memops.h" | |
13 #include "no_count.h" | |
14 #include "dtx.h" | |
15 #include "dtx_defs.h" | |
16 #include "dec_state.h" | |
17 | |
18 /************************************************************************* | |
19 * | |
20 * FUNCTION NAME: reset_rx_dtx | |
21 * | |
22 * PURPOSE: Resets the static variables of the RX DTX handler to their | |
23 * initial values | |
24 * | |
25 *************************************************************************/ | |
26 | |
27 void reset_rx_dtx (struct EFR_decoder_state *st) | |
28 { | |
29 Word16 i; | |
30 | |
31 /* suppose infinitely long speech period before start */ | |
32 | |
33 st->rxdtx_aver_period = DTX_HANGOVER; | |
34 st->rxdtx_N_elapsed = 0x7fff; | |
35 st->rxdtx_ctrl = RX_SP_FLAG; | |
36 | |
37 for (i = 0; i < DTX_HANGOVER; i++) | |
38 { | |
39 st->lsf_old_rx[i][0] = 1384; | |
40 st->lsf_old_rx[i][1] = 2077; | |
41 st->lsf_old_rx[i][2] = 3420; | |
42 st->lsf_old_rx[i][3] = 5108; | |
43 st->lsf_old_rx[i][4] = 6742; | |
44 st->lsf_old_rx[i][5] = 8122; | |
45 st->lsf_old_rx[i][6] = 9863; | |
46 st->lsf_old_rx[i][7] = 11092; | |
47 st->lsf_old_rx[i][8] = 12714; | |
48 st->lsf_old_rx[i][9] = 13701; | |
49 } | |
50 | |
51 for (i = 0; i < 4 * DTX_HANGOVER; i++) | |
52 { | |
53 st->gain_code_old_rx[i] = 0; | |
54 } | |
55 | |
56 st->L_pn_seed_rx = PN_INITIAL_SEED; | |
57 st->rx_dtx_state = CN_INT_PERIOD - 1; | |
58 | |
59 st->prev_SID_frames_lost = 0; | |
60 st->buf_p_rx = 0; | |
61 | |
62 return; | |
63 } | |
64 | |
65 /************************************************************************* | |
66 * | |
67 * FUNCTION NAME: rx_dtx | |
68 * | |
69 * PURPOSE: DTX handler of the speech decoder. Determines when to update | |
70 * the reference comfort noise parameters (LSF and gain) at the | |
71 * end of the speech burst. Also classifies the incoming frames | |
72 * according to SID flag and BFI flag | |
73 * and determines when the transmission is active during comfort | |
74 * noise insertion. This function also initializes the pseudo | |
75 * noise generator shift register. | |
76 * | |
77 * Operation of the RX DTX handler is based on measuring the | |
78 * lengths of speech bursts and the lengths of the pauses between | |
79 * speech bursts to determine when there exists a hangover period | |
80 * at the end of a speech burst. The idea is to keep in sync with | |
81 * the TX DTX handler to be able to update the reference comfort | |
82 * noise parameters at the same time instances. | |
83 * | |
84 * INPUTS: *rxdtx_ctrl Old decoder DTX control word | |
85 * TAF Time alignment flag | |
86 * bfi Bad frame indicator flag | |
87 * SID_flag Silence descriptor flag | |
88 * | |
89 * OUTPUTS: *rxdtx_ctrl Updated decoder DTX control word | |
90 * rx_dtx_state Updated state of comfort noise interpolation | |
91 * period (global variable) | |
92 * L_pn_seed_rx Initialized pseudo noise generator shift | |
93 * register (global variable) | |
94 * | |
95 * RETURN VALUE: none | |
96 * | |
97 *************************************************************************/ | |
98 | |
99 void rx_dtx ( | |
100 struct EFR_decoder_state *st, | |
101 Word16 TAF, | |
102 Word16 bfi, | |
103 Word16 SID_flag | |
104 ) | |
105 { | |
106 Word16 frame_type; | |
107 | |
108 /* Frame classification according to bfi-flag and ternary-valued | |
109 SID flag. The frames between SID updates (not actually trans- | |
110 mitted) are also classified here; they will be discarded later | |
111 and provided with "NO TRANSMISSION"-flag */ | |
112 | |
113 if ((sub (SID_flag, 2) == 0) && (bfi == 0)) | |
114 { | |
115 frame_type = VALID_SID_FRAME; move16 (); | |
116 } | |
117 else if ((SID_flag == 0) && (bfi == 0)) | |
118 { | |
119 frame_type = GOOD_SPEECH_FRAME; move16 (); | |
120 } | |
121 else if ((SID_flag == 0) && (bfi != 0)) | |
122 { | |
123 frame_type = UNUSABLE_FRAME; move16 (); | |
124 } | |
125 else | |
126 { | |
127 frame_type = INVALID_SID_FRAME; move16 (); | |
128 } | |
129 | |
130 /* Update of decoder state */ | |
131 /* Previous frame was classified as a speech frame */ | |
132 if ((st->rxdtx_ctrl & RX_SP_FLAG) != 0) | |
133 { | |
134 if (sub (frame_type, VALID_SID_FRAME) == 0) | |
135 { | |
136 st->rxdtx_ctrl = RX_FIRST_SID_UPDATE; | |
137 } | |
138 else if (sub (frame_type, INVALID_SID_FRAME) == 0) | |
139 { | |
140 st->rxdtx_ctrl = RX_FIRST_SID_UPDATE | |
141 | RX_INVALID_SID_FRAME; | |
142 } | |
143 else if (sub (frame_type, UNUSABLE_FRAME) == 0) | |
144 { | |
145 st->rxdtx_ctrl = RX_SP_FLAG; | |
146 } | |
147 else if (sub (frame_type, GOOD_SPEECH_FRAME) == 0) | |
148 { | |
149 st->rxdtx_ctrl = RX_SP_FLAG; | |
150 } | |
151 } | |
152 else | |
153 { | |
154 if (sub (frame_type, VALID_SID_FRAME) == 0) | |
155 { | |
156 st->rxdtx_ctrl = RX_CONT_SID_UPDATE; | |
157 } | |
158 else if (sub (frame_type, INVALID_SID_FRAME) == 0) | |
159 { | |
160 st->rxdtx_ctrl = RX_CONT_SID_UPDATE | |
161 | RX_INVALID_SID_FRAME; | |
162 } | |
163 else if (sub (frame_type, UNUSABLE_FRAME) == 0) | |
164 { | |
165 st->rxdtx_ctrl = RX_CNI_BFI; | |
166 } | |
167 else if (sub (frame_type, GOOD_SPEECH_FRAME) == 0) | |
168 { | |
169 /* If the previous frame (during CNI period) was muted, | |
170 raise the RX_PREV_DTX_MUTING flag */ | |
171 if ((st->rxdtx_ctrl & RX_DTX_MUTING) != 0) | |
172 { | |
173 st->rxdtx_ctrl = RX_SP_FLAG | RX_FIRST_SP_FLAG | |
174 | RX_PREV_DTX_MUTING; | |
175 } | |
176 else | |
177 { | |
178 st->rxdtx_ctrl = RX_SP_FLAG | RX_FIRST_SP_FLAG; | |
179 } | |
180 } | |
181 } | |
182 | |
183 if ((st->rxdtx_ctrl & RX_SP_FLAG) != 0) | |
184 { | |
185 st->prev_SID_frames_lost = 0; | |
186 st->rx_dtx_state = CN_INT_PERIOD - 1; | |
187 } | |
188 else | |
189 { | |
190 /* First SID frame */ | |
191 if ((st->rxdtx_ctrl & RX_FIRST_SID_UPDATE) != 0) | |
192 { | |
193 st->prev_SID_frames_lost = 0; | |
194 st->rx_dtx_state = CN_INT_PERIOD - 1; | |
195 } | |
196 | |
197 /* SID frame detected, but not the first SID */ | |
198 if ((st->rxdtx_ctrl & RX_CONT_SID_UPDATE) != 0) | |
199 { | |
200 st->prev_SID_frames_lost = 0; | |
201 | |
202 if (sub (frame_type, VALID_SID_FRAME) == 0) | |
203 { | |
204 st->rx_dtx_state = 0; | |
205 } | |
206 else if (sub (frame_type, INVALID_SID_FRAME) == 0) | |
207 { | |
208 if (sub(st->rx_dtx_state, (CN_INT_PERIOD - 1)) < 0) | |
209 { | |
210 st->rx_dtx_state = add(st->rx_dtx_state, 1); | |
211 } | |
212 } | |
213 } | |
214 | |
215 /* Bad frame received in CNI mode */ | |
216 if ((st->rxdtx_ctrl & RX_CNI_BFI) != 0) | |
217 { | |
218 if (sub (st->rx_dtx_state, (CN_INT_PERIOD - 1)) < 0) | |
219 { | |
220 st->rx_dtx_state = add (st->rx_dtx_state, 1); | |
221 } | |
222 | |
223 /* If an unusable frame is received during CNI period | |
224 when TAF == 1, the frame is classified as a lost | |
225 SID frame */ | |
226 if (sub (TAF, 1) == 0) | |
227 { | |
228 st->rxdtx_ctrl = st->rxdtx_ctrl | RX_LOST_SID_FRAME; | |
229 st->prev_SID_frames_lost = add (st->prev_SID_frames_lost, 1); | |
230 } | |
231 else /* No transmission occurred */ | |
232 { | |
233 st->rxdtx_ctrl = st->rxdtx_ctrl | RX_NO_TRANSMISSION; | |
234 } | |
235 | |
236 if (sub (st->prev_SID_frames_lost, 1) > 0) | |
237 { | |
238 st->rxdtx_ctrl = st->rxdtx_ctrl | RX_DTX_MUTING; | |
239 } | |
240 } | |
241 } | |
242 | |
243 /* N_elapsed (frames since last SID update) is incremented. If SID | |
244 is updated N_elapsed is cleared later in this function */ | |
245 | |
246 st->rxdtx_N_elapsed = add (st->rxdtx_N_elapsed, 1); | |
247 | |
248 if ((st->rxdtx_ctrl & RX_SP_FLAG) != 0) | |
249 { | |
250 st->rxdtx_aver_period = DTX_HANGOVER; | |
251 } | |
252 else | |
253 { | |
254 if (sub (st->rxdtx_N_elapsed, DTX_ELAPSED_THRESHOLD) > 0) | |
255 { | |
256 st->rxdtx_ctrl |= RX_UPD_SID_QUANT_MEM; | |
257 st->rxdtx_N_elapsed = 0; | |
258 st->rxdtx_aver_period = 0; | |
259 st->L_pn_seed_rx = PN_INITIAL_SEED; | |
260 } | |
261 else if (st->rxdtx_aver_period == 0) | |
262 { | |
263 st->rxdtx_N_elapsed = 0; | |
264 } | |
265 else | |
266 { | |
267 st->rxdtx_aver_period = sub (st->rxdtx_aver_period, 1); | |
268 } | |
269 } | |
270 | |
271 return; | |
272 } | |
273 | |
274 /************************************************************************* | |
275 * | |
276 * FUNCTION NAME: update_gain_code_history_rx | |
277 * | |
278 * PURPOSE: Update the fixed codebook gain parameter history of the | |
279 * decoder. The fixed codebook gain parameters kept in the buffer | |
280 * are used later for computing the reference fixed codebook | |
281 * gain parameter value. | |
282 * | |
283 * INPUTS: new_gain_code New fixed codebook gain value | |
284 * | |
285 * gain_code_old_tx[0..4*DTX_HANGOVER-1] | |
286 * Old fixed codebook gain history of decoder | |
287 * | |
288 * OUTPUTS: gain_code_old_tx[0..4*DTX_HANGOVER-1] | |
289 * Updated fixed codebk gain history of decoder | |
290 * | |
291 * RETURN VALUE: none | |
292 * | |
293 *************************************************************************/ | |
294 | |
295 void update_gain_code_history_rx ( | |
296 struct EFR_decoder_state *st, | |
297 Word16 new_gain_code | |
298 ) | |
299 { | |
300 /* Circular buffer */ | |
301 st->gain_code_old_rx[st->buf_p_rx] = new_gain_code; | |
302 | |
303 if (sub (st->buf_p_rx, (4 * DTX_HANGOVER - 1)) == 0) | |
304 { | |
305 st->buf_p_rx = 0; | |
306 } | |
307 else | |
308 { | |
309 st->buf_p_rx = add (st->buf_p_rx, 1); | |
310 } | |
311 | |
312 return; | |
313 } | |
314 | |
315 /************************************************************************* | |
316 * | |
317 * FUNCTION NAME: interpolate_CN_param | |
318 * | |
319 * PURPOSE: Interpolate a comfort noise parameter value over the comfort | |
320 * noise update period. | |
321 * | |
322 * INPUTS: old_param The older parameter of the interpolation | |
323 * (the endpoint the interpolation is started | |
324 * from) | |
325 * new_param The newer parameter of the interpolation | |
326 * (the endpoint the interpolation is ended to) | |
327 * rx_dtx_state State of the comfort noise insertion period | |
328 * | |
329 * OUTPUTS: none | |
330 * | |
331 * RETURN VALUE: Interpolated CN parameter value | |
332 * | |
333 *************************************************************************/ | |
334 | |
335 Word16 interpolate_CN_param ( | |
336 Word16 old_param, | |
337 Word16 new_param, | |
338 Word16 rx_dtx_state | |
339 ) | |
340 { | |
341 static const Word16 interp_factor[CN_INT_PERIOD] = | |
342 { | |
343 0x0555, 0x0aaa, 0x1000, 0x1555, 0x1aaa, 0x2000, | |
344 0x2555, 0x2aaa, 0x3000, 0x3555, 0x3aaa, 0x4000, | |
345 0x4555, 0x4aaa, 0x5000, 0x5555, 0x5aaa, 0x6000, | |
346 0x6555, 0x6aaa, 0x7000, 0x7555, 0x7aaa, 0x7fff}; | |
347 Word16 temp; | |
348 Word32 L_temp; | |
349 | |
350 L_temp = L_mult (interp_factor[rx_dtx_state], new_param); | |
351 temp = sub (0x7fff, interp_factor[rx_dtx_state]); | |
352 temp = add (temp, 1); | |
353 L_temp = L_mac (L_temp, temp, old_param); | |
354 temp = round (L_temp); | |
355 | |
356 return temp; | |
357 } | |
358 | |
359 /************************************************************************* | |
360 * | |
361 * FUNCTION NAME: interpolate_CN_lsf | |
362 * | |
363 * PURPOSE: Interpolate comfort noise LSF parameter vector over the comfort | |
364 * noise update period. | |
365 * | |
366 * INPUTS: lsf_old_CN[0..9] | |
367 * The older LSF parameter vector of the | |
368 * interpolation (the endpoint the interpolation | |
369 * is started from) | |
370 * lsf_new_CN[0..9] | |
371 * The newer LSF parameter vector of the | |
372 * interpolation (the endpoint the interpolation | |
373 * is ended to) | |
374 * rx_dtx_state State of the comfort noise insertion period | |
375 * | |
376 * OUTPUTS: lsf_interp_CN[0..9] | |
377 * Interpolated LSF parameter vector | |
378 * | |
379 * RETURN VALUE: none | |
380 * | |
381 *************************************************************************/ | |
382 | |
383 void interpolate_CN_lsf ( | |
384 Word16 lsf_old_CN[M], | |
385 Word16 lsf_new_CN[M], | |
386 Word16 lsf_interp_CN[M], | |
387 Word16 rx_dtx_state | |
388 ) | |
389 { | |
390 Word16 i; | |
391 | |
392 for (i = 0; i < M; i++) | |
393 { | |
394 lsf_interp_CN[i] = interpolate_CN_param (lsf_old_CN[i], | |
395 lsf_new_CN[i], | |
396 rx_dtx_state); move16 (); | |
397 } | |
398 | |
399 return; | |
400 } |