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 }