FreeCalypso > hg > efr-experiments
comparison src/dtx.c @ 0:56410792419a
src: original EFR source from ETSI
author | Mychaela Falconia <falcon@freecalypso.org> |
---|---|
date | Wed, 03 Apr 2024 05:31:37 +0000 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:56410792419a |
---|---|
1 /*************************************************************************** | |
2 * | |
3 * File Name: dtx.c | |
4 * | |
5 * Purpose: Contains functions for performing DTX operation and comfort | |
6 * noise generation. | |
7 * | |
8 * Below is a listing of all the functions appearing in the file. | |
9 * The functions are arranged according to their purpose. Under | |
10 * each heading, the ordering is hierarchical. | |
11 * | |
12 * Resetting of static variables of TX DTX: | |
13 * reset_tx_dtx() | |
14 * Resetting of static variables of RX DTX: | |
15 * reset_rx_dtx() | |
16 * | |
17 * TX DTX handler (called by the speech encoder): | |
18 * tx_dtx() | |
19 * RX DTX handler (called by the speech decoder): | |
20 * rx_dtx() | |
21 * Encoding of comfort noise parameters into SID frame: | |
22 * CN_encoding() | |
23 * Encoding of SID codeword into SID frame: | |
24 * sid_codeword_encoding() | |
25 * Detecting of SID codeword from a frame: | |
26 * sid_frame_detection() | |
27 * Update the LSF parameter history: | |
28 * update_lsf_history() | |
29 * Update the reference LSF parameter vector: | |
30 * update_lsf_p_CN() | |
31 * Compute the averaged LSF parameter vector: | |
32 * aver_lsf_history() | |
33 * Update the fixed codebook gain parameter history of the encoder: | |
34 * update_gain_code_history_tx() | |
35 * Update the fixed codebook gain parameter history of the decoder: | |
36 * update_gain_code_history_rx() | |
37 * Compute the unquantized fixed codebook gain: | |
38 * compute_CN_excitation_gain() | |
39 * Update the reference fixed codebook gain: | |
40 * update_gcode0_CN() | |
41 * Compute the averaged fixed codebook gain: | |
42 * aver_gain_code_history() | |
43 * Compute the comfort noise fixed codebook excitation: | |
44 * build_CN_code() | |
45 * Generate a random integer value: | |
46 * pseudonoise() | |
47 * Interpolate a comfort noise parameter value over the comfort noise | |
48 * update period: | |
49 * interpolate_CN_param() | |
50 * Interpolate comfort noise LSF pparameter values over the comfort | |
51 * noise update period: | |
52 * interpolate_CN_lsf() | |
53 * interpolate_CN_param() | |
54 * | |
55 **************************************************************************/ | |
56 | |
57 #include "typedef.h" | |
58 #include "basic_op.h" | |
59 #include "cnst.h" | |
60 #include "sig_proc.h" | |
61 #include "count.h" | |
62 #include "dtx.h" | |
63 | |
64 /* Inverse values of DTX hangover period and DTX hangover period + 1 */ | |
65 | |
66 #define INV_DTX_HANGOVER (0x7fff / DTX_HANGOVER) | |
67 #define INV_DTX_HANGOVER_P1 (0x7fff / (DTX_HANGOVER+1)) | |
68 | |
69 #define NB_PULSE 10 /* Number of pulses in fixed codebook excitation */ | |
70 | |
71 /* SID frame classification thresholds */ | |
72 | |
73 #define VALID_SID_THRESH 2 | |
74 #define INVALID_SID_THRESH 16 | |
75 | |
76 /* Constant DTX_ELAPSED_THRESHOLD is used as threshold for allowing | |
77 SID frame updating without hangover period in case when elapsed | |
78 time measured from previous SID update is below 24 */ | |
79 | |
80 #define DTX_ELAPSED_THRESHOLD (24 + DTX_HANGOVER - 1) | |
81 | |
82 /* Index map for encoding and detecting SID codeword */ | |
83 | |
84 static const Word16 SID_codeword_bit_idx[95] = | |
85 { | |
86 45, 46, 48, 49, 50, 51, 52, 53, 54, 55, | |
87 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, | |
88 66, 67, 68, 94, 95, 96, 98, 99, 100, 101, | |
89 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, | |
90 112, 113, 114, 115, 116, 117, 118, 148, 149, 150, | |
91 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, | |
92 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, | |
93 171, 196, 197, 198, 199, 200, 201, 202, 203, 204, | |
94 205, 206, 207, 208, 209, 212, 213, 214, 215, 216, | |
95 217, 218, 219, 220, 221 | |
96 }; | |
97 | |
98 Word16 txdtx_ctrl; /* Encoder DTX control word */ | |
99 Word16 rxdtx_ctrl; /* Decoder DTX control word */ | |
100 Word16 CN_excitation_gain; /* Unquantized fixed codebook gain */ | |
101 Word32 L_pn_seed_tx; /* PN generator seed (encoder) */ | |
102 Word32 L_pn_seed_rx; /* PN generator seed (decoder) */ | |
103 Word16 rx_dtx_state; /* State of comfort noise insertion period */ | |
104 | |
105 static Word16 txdtx_hangover; /* Length of hangover period (VAD=0, SP=1) */ | |
106 static Word16 rxdtx_aver_period;/* Length of hangover period (VAD=0, SP=1) */ | |
107 static Word16 txdtx_N_elapsed; /* Measured time from previous SID frame */ | |
108 static Word16 rxdtx_N_elapsed; /* Measured time from previous SID frame */ | |
109 static Word16 old_CN_mem_tx[6]; /* The most recent CN parameters are stored*/ | |
110 static Word16 prev_SID_frames_lost; /* Counter for lost SID frames */ | |
111 static Word16 buf_p_tx; /* Circular buffer pointer for gain code | |
112 history update in tx */ | |
113 static Word16 buf_p_rx; /* Circular buffer pointer for gain code | |
114 history update in rx */ | |
115 | |
116 Word16 lsf_old_tx[DTX_HANGOVER][M]; /* Comfort noise LSF averaging buffer */ | |
117 Word16 lsf_old_rx[DTX_HANGOVER][M]; /* Comfort noise LSF averaging buffer */ | |
118 | |
119 Word16 gain_code_old_tx[4 * DTX_HANGOVER]; /* Comfort noise gain averaging | |
120 buffer */ | |
121 Word16 gain_code_old_rx[4 * DTX_HANGOVER]; /* Comfort noise gain averaging | |
122 buffer */ | |
123 | |
124 /************************************************************************* | |
125 * | |
126 * FUNCTION NAME: reset_tx_dtx | |
127 * | |
128 * PURPOSE: Resets the static variables of the TX DTX handler to their | |
129 * initial values | |
130 * | |
131 *************************************************************************/ | |
132 | |
133 void reset_tx_dtx () | |
134 { | |
135 Word16 i; | |
136 | |
137 /* suppose infinitely long speech period before start */ | |
138 | |
139 txdtx_hangover = DTX_HANGOVER; | |
140 txdtx_N_elapsed = 0x7fff; | |
141 txdtx_ctrl = TX_SP_FLAG | TX_VAD_FLAG; | |
142 | |
143 for (i = 0; i < 6; i++) | |
144 { | |
145 old_CN_mem_tx[i] = 0; | |
146 } | |
147 | |
148 for (i = 0; i < DTX_HANGOVER; i++) | |
149 { | |
150 lsf_old_tx[i][0] = 1384; | |
151 lsf_old_tx[i][1] = 2077; | |
152 lsf_old_tx[i][2] = 3420; | |
153 lsf_old_tx[i][3] = 5108; | |
154 lsf_old_tx[i][4] = 6742; | |
155 lsf_old_tx[i][5] = 8122; | |
156 lsf_old_tx[i][6] = 9863; | |
157 lsf_old_tx[i][7] = 11092; | |
158 lsf_old_tx[i][8] = 12714; | |
159 lsf_old_tx[i][9] = 13701; | |
160 } | |
161 | |
162 for (i = 0; i < 4 * DTX_HANGOVER; i++) | |
163 { | |
164 gain_code_old_tx[i] = 0; | |
165 } | |
166 | |
167 L_pn_seed_tx = PN_INITIAL_SEED; | |
168 | |
169 buf_p_tx = 0; | |
170 return; | |
171 } | |
172 | |
173 /************************************************************************* | |
174 * | |
175 * FUNCTION NAME: reset_rx_dtx | |
176 * | |
177 * PURPOSE: Resets the static variables of the RX DTX handler to their | |
178 * initial values | |
179 * | |
180 *************************************************************************/ | |
181 | |
182 void reset_rx_dtx () | |
183 { | |
184 Word16 i; | |
185 | |
186 /* suppose infinitely long speech period before start */ | |
187 | |
188 rxdtx_aver_period = DTX_HANGOVER; | |
189 rxdtx_N_elapsed = 0x7fff; | |
190 rxdtx_ctrl = RX_SP_FLAG; | |
191 | |
192 for (i = 0; i < DTX_HANGOVER; i++) | |
193 { | |
194 lsf_old_rx[i][0] = 1384; | |
195 lsf_old_rx[i][1] = 2077; | |
196 lsf_old_rx[i][2] = 3420; | |
197 lsf_old_rx[i][3] = 5108; | |
198 lsf_old_rx[i][4] = 6742; | |
199 lsf_old_rx[i][5] = 8122; | |
200 lsf_old_rx[i][6] = 9863; | |
201 lsf_old_rx[i][7] = 11092; | |
202 lsf_old_rx[i][8] = 12714; | |
203 lsf_old_rx[i][9] = 13701; | |
204 } | |
205 | |
206 for (i = 0; i < 4 * DTX_HANGOVER; i++) | |
207 { | |
208 gain_code_old_rx[i] = 0; | |
209 } | |
210 | |
211 L_pn_seed_rx = PN_INITIAL_SEED; | |
212 rx_dtx_state = CN_INT_PERIOD - 1; | |
213 | |
214 prev_SID_frames_lost = 0; | |
215 buf_p_rx = 0; | |
216 | |
217 return; | |
218 } | |
219 | |
220 /************************************************************************* | |
221 * | |
222 * FUNCTION NAME: tx_dtx | |
223 * | |
224 * PURPOSE: DTX handler of the speech encoder. Determines when to add | |
225 * the hangover period to the end of the speech burst, and | |
226 * also determines when to use old SID parameters, and when | |
227 * to update the SID parameters. This function also initializes | |
228 * the pseudo noise generator shift register. | |
229 * | |
230 * Operation of the TX DTX handler is based on the VAD flag | |
231 * given as input from the speech encoder. | |
232 * | |
233 * INPUTS: VAD_flag Voice activity decision | |
234 * *txdtx_ctrl Old encoder DTX control word | |
235 * | |
236 * OUTPUTS: *txdtx_ctrl Updated encoder DTX control word | |
237 * L_pn_seed_tx Initialized pseudo noise generator shift | |
238 * register (global variable) | |
239 * | |
240 * RETURN VALUE: none | |
241 * | |
242 *************************************************************************/ | |
243 | |
244 void tx_dtx ( | |
245 Word16 VAD_flag, | |
246 Word16 *txdtx_ctrl | |
247 ) | |
248 { | |
249 | |
250 /* N_elapsed (frames since last SID update) is incremented. If SID | |
251 is updated N_elapsed is cleared later in this function */ | |
252 | |
253 txdtx_N_elapsed = add (txdtx_N_elapsed, 1); | |
254 | |
255 /* If voice activity was detected, reset hangover counter */ | |
256 | |
257 test (); | |
258 if (sub (VAD_flag, 1) == 0) | |
259 { | |
260 txdtx_hangover = DTX_HANGOVER; move16 (); | |
261 *txdtx_ctrl = TX_SP_FLAG | TX_VAD_FLAG; move16 (); logic16 (); | |
262 } | |
263 else | |
264 { | |
265 test (); | |
266 if (txdtx_hangover == 0) | |
267 { | |
268 /* Hangover period is over, SID should be updated */ | |
269 | |
270 txdtx_N_elapsed = 0; move16 (); | |
271 | |
272 /* Check if this is the first frame after hangover period */ | |
273 test (); logic16 (); | |
274 if ((*txdtx_ctrl & TX_HANGOVER_ACTIVE) != 0) | |
275 { | |
276 *txdtx_ctrl = TX_PREV_HANGOVER_ACTIVE | |
277 | TX_SID_UPDATE; move16 (); logic16 (); | |
278 L_pn_seed_tx = PN_INITIAL_SEED; move32 (); | |
279 } | |
280 else | |
281 { | |
282 *txdtx_ctrl = TX_SID_UPDATE; move16 (); | |
283 } | |
284 } | |
285 else | |
286 { | |
287 /* Hangover period is not over, update hangover counter */ | |
288 txdtx_hangover = sub (txdtx_hangover, 1); | |
289 | |
290 /* Check if elapsed time from last SID update is greater than | |
291 threshold. If not, set SP=0 (although hangover period is not | |
292 over) and use old SID parameters for new SID frame. | |
293 N_elapsed counter must be summed with hangover counter in order | |
294 to avoid erroneus SP=1 decision in case when N_elapsed is grown | |
295 bigger than threshold and hangover period is still active */ | |
296 | |
297 test (); | |
298 if (sub (add (txdtx_N_elapsed, txdtx_hangover), | |
299 DTX_ELAPSED_THRESHOLD) < 0) | |
300 { | |
301 /* old SID frame should be used */ | |
302 *txdtx_ctrl = TX_USE_OLD_SID; move16 (); | |
303 } | |
304 else | |
305 { | |
306 test (); logic16 (); | |
307 if ((*txdtx_ctrl & TX_HANGOVER_ACTIVE) != 0) | |
308 { | |
309 *txdtx_ctrl = TX_PREV_HANGOVER_ACTIVE | |
310 | TX_HANGOVER_ACTIVE | |
311 | TX_SP_FLAG; move16 (); logic16 (); logic16 (); | |
312 } | |
313 else | |
314 { | |
315 *txdtx_ctrl = TX_HANGOVER_ACTIVE | |
316 | TX_SP_FLAG; move16 (); logic16 (); | |
317 } | |
318 } | |
319 } | |
320 } | |
321 | |
322 return; | |
323 } | |
324 | |
325 /************************************************************************* | |
326 * | |
327 * FUNCTION NAME: rx_dtx | |
328 * | |
329 * PURPOSE: DTX handler of the speech decoder. Determines when to update | |
330 * the reference comfort noise parameters (LSF and gain) at the | |
331 * end of the speech burst. Also classifies the incoming frames | |
332 * according to SID flag and BFI flag | |
333 * and determines when the transmission is active during comfort | |
334 * noise insertion. This function also initializes the pseudo | |
335 * noise generator shift register. | |
336 * | |
337 * Operation of the RX DTX handler is based on measuring the | |
338 * lengths of speech bursts and the lengths of the pauses between | |
339 * speech bursts to determine when there exists a hangover period | |
340 * at the end of a speech burst. The idea is to keep in sync with | |
341 * the TX DTX handler to be able to update the reference comfort | |
342 * noise parameters at the same time instances. | |
343 * | |
344 * INPUTS: *rxdtx_ctrl Old decoder DTX control word | |
345 * TAF Time alignment flag | |
346 * bfi Bad frame indicator flag | |
347 * SID_flag Silence descriptor flag | |
348 * | |
349 * OUTPUTS: *rxdtx_ctrl Updated decoder DTX control word | |
350 * rx_dtx_state Updated state of comfort noise interpolation | |
351 * period (global variable) | |
352 * L_pn_seed_rx Initialized pseudo noise generator shift | |
353 * register (global variable) | |
354 * | |
355 * RETURN VALUE: none | |
356 * | |
357 *************************************************************************/ | |
358 | |
359 void rx_dtx ( | |
360 Word16 *rxdtx_ctrl, | |
361 Word16 TAF, | |
362 Word16 bfi, | |
363 Word16 SID_flag | |
364 ) | |
365 { | |
366 Word16 frame_type; | |
367 | |
368 /* Frame classification according to bfi-flag and ternary-valued | |
369 SID flag. The frames between SID updates (not actually trans- | |
370 mitted) are also classified here; they will be discarded later | |
371 and provided with "NO TRANSMISSION"-flag */ | |
372 | |
373 test (); test (); | |
374 test (); test (); | |
375 test (); test (); | |
376 if ((sub (SID_flag, 2) == 0) && (bfi == 0)) | |
377 { | |
378 frame_type = VALID_SID_FRAME; move16 (); | |
379 } | |
380 else if ((SID_flag == 0) && (bfi == 0)) | |
381 { | |
382 frame_type = GOOD_SPEECH_FRAME; move16 (); | |
383 } | |
384 else if ((SID_flag == 0) && (bfi != 0)) | |
385 { | |
386 frame_type = UNUSABLE_FRAME; move16 (); | |
387 } | |
388 else | |
389 { | |
390 frame_type = INVALID_SID_FRAME; move16 (); | |
391 } | |
392 | |
393 /* Update of decoder state */ | |
394 /* Previous frame was classified as a speech frame */ | |
395 test (); logic16 (); | |
396 if ((*rxdtx_ctrl & RX_SP_FLAG) != 0) | |
397 { | |
398 test (); test (); test (); test (); | |
399 if (sub (frame_type, VALID_SID_FRAME) == 0) | |
400 { | |
401 *rxdtx_ctrl = RX_FIRST_SID_UPDATE; move16 (); | |
402 } | |
403 else if (sub (frame_type, INVALID_SID_FRAME) == 0) | |
404 { | |
405 *rxdtx_ctrl = RX_FIRST_SID_UPDATE | |
406 | RX_INVALID_SID_FRAME; move16 (); logic16(); | |
407 } | |
408 else if (sub (frame_type, UNUSABLE_FRAME) == 0) | |
409 { | |
410 *rxdtx_ctrl = RX_SP_FLAG; move16 (); | |
411 } | |
412 else if (sub (frame_type, GOOD_SPEECH_FRAME) == 0) | |
413 { | |
414 *rxdtx_ctrl = RX_SP_FLAG; move16 (); | |
415 } | |
416 } | |
417 else | |
418 { | |
419 test (); test (); test (); test (); | |
420 if (sub (frame_type, VALID_SID_FRAME) == 0) | |
421 { | |
422 *rxdtx_ctrl = RX_CONT_SID_UPDATE; move16 (); | |
423 } | |
424 else if (sub (frame_type, INVALID_SID_FRAME) == 0) | |
425 { | |
426 *rxdtx_ctrl = RX_CONT_SID_UPDATE | |
427 | RX_INVALID_SID_FRAME; move16 (); logic16 (); | |
428 } | |
429 else if (sub (frame_type, UNUSABLE_FRAME) == 0) | |
430 { | |
431 *rxdtx_ctrl = RX_CNI_BFI; move16 (); | |
432 } | |
433 else if (sub (frame_type, GOOD_SPEECH_FRAME) == 0) | |
434 { | |
435 /* If the previous frame (during CNI period) was muted, | |
436 raise the RX_PREV_DTX_MUTING flag */ | |
437 test (); logic16 (); | |
438 if ((*rxdtx_ctrl & RX_DTX_MUTING) != 0) | |
439 { | |
440 *rxdtx_ctrl = RX_SP_FLAG | RX_FIRST_SP_FLAG | |
441 | RX_PREV_DTX_MUTING; move16 (); logic16 (); | |
442 logic16 (); | |
443 } | |
444 else | |
445 { | |
446 *rxdtx_ctrl = RX_SP_FLAG | RX_FIRST_SP_FLAG; move16 (); | |
447 logic16 (); | |
448 } | |
449 } | |
450 } | |
451 | |
452 | |
453 test (); logic16 (); | |
454 if ((*rxdtx_ctrl & RX_SP_FLAG) != 0) | |
455 { | |
456 prev_SID_frames_lost = 0; move16 (); | |
457 rx_dtx_state = CN_INT_PERIOD - 1; move16 (); | |
458 } | |
459 else | |
460 { | |
461 /* First SID frame */ | |
462 test (); logic16 (); | |
463 if ((*rxdtx_ctrl & RX_FIRST_SID_UPDATE) != 0) | |
464 { | |
465 prev_SID_frames_lost = 0; move16 (); | |
466 rx_dtx_state = CN_INT_PERIOD - 1; move16 (); | |
467 } | |
468 | |
469 /* SID frame detected, but not the first SID */ | |
470 test (); logic16 (); | |
471 if ((*rxdtx_ctrl & RX_CONT_SID_UPDATE) != 0) | |
472 { | |
473 prev_SID_frames_lost = 0; move16 (); | |
474 | |
475 test (); test (); | |
476 if (sub (frame_type, VALID_SID_FRAME) == 0) | |
477 { | |
478 rx_dtx_state = 0; move16 (); | |
479 } | |
480 else if (sub (frame_type, INVALID_SID_FRAME) == 0) | |
481 { | |
482 test (); | |
483 if (sub(rx_dtx_state, (CN_INT_PERIOD - 1)) < 0) | |
484 { | |
485 rx_dtx_state = add(rx_dtx_state, 1); move16 (); | |
486 } | |
487 } | |
488 } | |
489 | |
490 /* Bad frame received in CNI mode */ | |
491 test (); logic16 (); | |
492 if ((*rxdtx_ctrl & RX_CNI_BFI) != 0) | |
493 { | |
494 test (); | |
495 if (sub (rx_dtx_state, (CN_INT_PERIOD - 1)) < 0) | |
496 { | |
497 rx_dtx_state = add (rx_dtx_state, 1); move16 (); | |
498 } | |
499 | |
500 /* If an unusable frame is received during CNI period | |
501 when TAF == 1, the frame is classified as a lost | |
502 SID frame */ | |
503 test (); | |
504 if (sub (TAF, 1) == 0) | |
505 { | |
506 *rxdtx_ctrl = *rxdtx_ctrl | RX_LOST_SID_FRAME; | |
507 move16 (); logic16 (); | |
508 prev_SID_frames_lost = add (prev_SID_frames_lost, 1); | |
509 } | |
510 else /* No transmission occurred */ | |
511 { | |
512 *rxdtx_ctrl = *rxdtx_ctrl | RX_NO_TRANSMISSION; | |
513 move16 (); logic16 (); | |
514 } | |
515 | |
516 test (); | |
517 if (sub (prev_SID_frames_lost, 1) > 0) | |
518 { | |
519 *rxdtx_ctrl = *rxdtx_ctrl | RX_DTX_MUTING; | |
520 move16 (); logic16 (); | |
521 } | |
522 } | |
523 } | |
524 | |
525 /* N_elapsed (frames since last SID update) is incremented. If SID | |
526 is updated N_elapsed is cleared later in this function */ | |
527 | |
528 rxdtx_N_elapsed = add (rxdtx_N_elapsed, 1); | |
529 | |
530 test (); logic16 (); | |
531 if ((*rxdtx_ctrl & RX_SP_FLAG) != 0) | |
532 { | |
533 rxdtx_aver_period = DTX_HANGOVER; move16 (); | |
534 } | |
535 else | |
536 { | |
537 test (); test (); | |
538 if (sub (rxdtx_N_elapsed, DTX_ELAPSED_THRESHOLD) > 0) | |
539 { | |
540 *rxdtx_ctrl |= RX_UPD_SID_QUANT_MEM; move16 (); logic16 (); | |
541 rxdtx_N_elapsed = 0; move16 (); | |
542 rxdtx_aver_period = 0; move16 (); | |
543 L_pn_seed_rx = PN_INITIAL_SEED; move32 (); | |
544 } | |
545 else if (rxdtx_aver_period == 0) | |
546 { | |
547 rxdtx_N_elapsed = 0; move16 (); | |
548 } | |
549 else | |
550 { | |
551 rxdtx_aver_period = sub (rxdtx_aver_period, 1); | |
552 } | |
553 } | |
554 | |
555 return; | |
556 } | |
557 | |
558 /************************************************************************* | |
559 * | |
560 * FUNCTION NAME: CN_encoding | |
561 * | |
562 * PURPOSE: Encoding of the comfort noise parameters into a SID frame. | |
563 * Use old SID parameters if necessary. Set the parameter | |
564 * indices not used by comfort noise parameters to zero. | |
565 * | |
566 * INPUTS: params[0..56] Comfort noise parameter frame from the | |
567 * speech encoder | |
568 * txdtx_ctrl TX DTX handler control word | |
569 * | |
570 * OUTPUTS: params[0..56] Comfort noise encoded parameter frame | |
571 * | |
572 * RETURN VALUE: none | |
573 * | |
574 *************************************************************************/ | |
575 | |
576 void CN_encoding ( | |
577 Word16 params[], | |
578 Word16 txdtx_ctrl | |
579 ) | |
580 { | |
581 Word16 i; | |
582 | |
583 test (); logic16 (); | |
584 if ((txdtx_ctrl & TX_SID_UPDATE) != 0) | |
585 { | |
586 /* Store new CN parameters in memory to be used later as old | |
587 CN parameters */ | |
588 | |
589 /* LPC parameter indices */ | |
590 for (i = 0; i < 5; i++) | |
591 { | |
592 old_CN_mem_tx[i] = params[i]; move16 (); | |
593 } | |
594 /* Codebook index computed in last subframe */ | |
595 old_CN_mem_tx[5] = params[56]; move16 (); | |
596 } | |
597 test (); logic16 (); | |
598 if ((txdtx_ctrl & TX_USE_OLD_SID) != 0) | |
599 { | |
600 /* Use old CN parameters previously stored in memory */ | |
601 for (i = 0; i < 5; i++) | |
602 { | |
603 params[i] = old_CN_mem_tx[i]; move16 (); | |
604 } | |
605 params[17] = old_CN_mem_tx[5]; move16 (); | |
606 params[30] = old_CN_mem_tx[5]; move16 (); | |
607 params[43] = old_CN_mem_tx[5]; move16 (); | |
608 params[56] = old_CN_mem_tx[5]; move16 (); | |
609 } | |
610 /* Set all the rest of the parameters to zero (SID codeword will | |
611 be written later) */ | |
612 for (i = 0; i < 12; i++) | |
613 { | |
614 params[i + 5] = 0; move16 (); | |
615 params[i + 18] = 0; move16 (); | |
616 params[i + 31] = 0; move16 (); | |
617 params[i + 44] = 0; move16 (); | |
618 } | |
619 | |
620 return; | |
621 } | |
622 | |
623 /************************************************************************* | |
624 * | |
625 * FUNCTION NAME: sid_codeword_encoding | |
626 * | |
627 * PURPOSE: Encoding of the SID codeword into the SID frame. The SID | |
628 * codeword consists of 95 bits, all set to '1'. | |
629 * | |
630 * INPUTS: ser2[0..243] Serial-mode speech parameter frame before | |
631 * writing SID codeword into it | |
632 * | |
633 * OUTPUTS: ser2[0..243] Serial-mode speech parameter frame with | |
634 * SID codeword written into it | |
635 * | |
636 * RETURN VALUE: none | |
637 * | |
638 *************************************************************************/ | |
639 | |
640 void sid_codeword_encoding ( | |
641 Word16 ser2[] | |
642 ) | |
643 { | |
644 Word16 i; | |
645 | |
646 for (i = 0; i < 95; i++) | |
647 { | |
648 ser2[SID_codeword_bit_idx[i]] = 1; move16 (); | |
649 } | |
650 | |
651 return; | |
652 } | |
653 | |
654 /************************************************************************* | |
655 * | |
656 * FUNCTION NAME: sid_frame_detection | |
657 * | |
658 * PURPOSE: Detecting of SID codeword from a received frame. The frames | |
659 * are classified into three categories based on how many bit | |
660 * errors occur in the SID codeword: | |
661 * - VALID SID FRAME | |
662 * - INVALID SID FRAME | |
663 * - SPEECH FRAME | |
664 * | |
665 * INPUTS: ser2[0..243] Received serial-mode speech parameter frame | |
666 * | |
667 * OUTPUTS: none | |
668 * | |
669 * RETURN VALUE: Ternary-valued SID classification flag | |
670 * | |
671 *************************************************************************/ | |
672 | |
673 Word16 sid_frame_detection ( | |
674 Word16 ser2[] | |
675 ) | |
676 { | |
677 Word16 i, nbr_errors, sid; | |
678 | |
679 /* Search for bit errors in SID codeword */ | |
680 nbr_errors = 0; move16 (); | |
681 for (i = 0; i < 95; i++) | |
682 { | |
683 test (); | |
684 if (ser2[SID_codeword_bit_idx[i]] == 0) | |
685 { | |
686 nbr_errors = add (nbr_errors, 1); | |
687 } | |
688 } | |
689 | |
690 /* Frame classification */ | |
691 test (); test (); | |
692 if (sub (nbr_errors, VALID_SID_THRESH) < 0) | |
693 { /* Valid SID frame */ | |
694 sid = 2; move16 (); | |
695 } | |
696 else if (sub (nbr_errors, INVALID_SID_THRESH) < 0) | |
697 { /* Invalid SID frame */ | |
698 sid = 1; move16 (); | |
699 } | |
700 else | |
701 { /* Speech frame */ | |
702 sid = 0; move16 (); | |
703 } | |
704 | |
705 return sid; | |
706 } | |
707 | |
708 /************************************************************************* | |
709 * | |
710 * FUNCTION NAME: update_lsf_history | |
711 * | |
712 * PURPOSE: Update the LSF parameter history. The LSF parameters kept | |
713 * in the buffer are used later for computing the reference | |
714 * LSF parameter vector and the averaged LSF parameter vector. | |
715 * | |
716 * INPUTS: lsf1[0..9] LSF vector of the 1st half of the frame | |
717 * lsf2[0..9] LSF vector of the 2nd half of the frame | |
718 * lsf_old[0..DTX_HANGOVER-1][0..M-1] | |
719 * Old LSF history | |
720 * | |
721 * OUTPUTS: lsf_old[0..DTX_HANGOVER-1][0..M-1] | |
722 * Updated LSF history | |
723 * | |
724 * RETURN VALUE: none | |
725 * | |
726 *************************************************************************/ | |
727 | |
728 void update_lsf_history ( | |
729 Word16 lsf1[M], | |
730 Word16 lsf2[M], | |
731 Word16 lsf_old[DTX_HANGOVER][M] | |
732 ) | |
733 { | |
734 Word16 i, j, temp; | |
735 | |
736 /* shift LSF data to make room for LSFs from current frame */ | |
737 /* This can also be implemented by using circular buffering */ | |
738 | |
739 for (i = DTX_HANGOVER - 1; i > 0; i--) | |
740 { | |
741 for (j = 0; j < M; j++) | |
742 { | |
743 lsf_old[i][j] = lsf_old[i - 1][j]; move16 (); | |
744 } | |
745 } | |
746 | |
747 /* Store new LSF data to lsf_old buffer */ | |
748 | |
749 for (i = 0; i < M; i++) | |
750 { | |
751 temp = add (shr (lsf1[i], 1), shr (lsf2[i], 1)); | |
752 lsf_old[0][i] = temp; move16 (); | |
753 } | |
754 | |
755 return; | |
756 } | |
757 | |
758 /************************************************************************* | |
759 * | |
760 * FUNCTION NAME: update_lsf_p_CN | |
761 * | |
762 * PURPOSE: Update the reference LSF parameter vector. The reference | |
763 * vector is computed by averaging the quantized LSF parameter | |
764 * vectors which exist in the LSF parameter history. | |
765 * | |
766 * INPUTS: lsf_old[0..DTX_HANGOVER-1][0..M-1] | |
767 * LSF parameter history | |
768 * | |
769 * OUTPUTS: lsf_p_CN[0..9] Computed reference LSF parameter vector | |
770 * | |
771 * RETURN VALUE: none | |
772 * | |
773 *************************************************************************/ | |
774 | |
775 void update_lsf_p_CN ( | |
776 Word16 lsf_old[DTX_HANGOVER][M], | |
777 Word16 lsf_p_CN[M] | |
778 ) | |
779 { | |
780 Word16 i, j; | |
781 Word32 L_temp; | |
782 | |
783 for (j = 0; j < M; j++) | |
784 { | |
785 L_temp = L_mult (INV_DTX_HANGOVER, lsf_old[0][j]); | |
786 for (i = 1; i < DTX_HANGOVER; i++) | |
787 { | |
788 L_temp = L_mac (L_temp, INV_DTX_HANGOVER, lsf_old[i][j]); | |
789 } | |
790 lsf_p_CN[j] = round (L_temp); move16 (); | |
791 } | |
792 | |
793 return; | |
794 } | |
795 | |
796 /************************************************************************* | |
797 * | |
798 * FUNCTION NAME: aver_lsf_history | |
799 * | |
800 * PURPOSE: Compute the averaged LSF parameter vector. Computation is | |
801 * performed by averaging the LSF parameter vectors which exist | |
802 * in the LSF parameter history, together with the LSF | |
803 * parameter vectors of the current frame. | |
804 * | |
805 * INPUTS: lsf_old[0..DTX_HANGOVER-1][0..M-1] | |
806 * LSF parameter history | |
807 * lsf1[0..M-1] LSF vector of the 1st half of the frame | |
808 * lsf2[0..M-1] LSF vector of the 2nd half of the frame | |
809 * | |
810 * OUTPUTS: lsf_aver[0..M-1] Averaged LSF parameter vector | |
811 * | |
812 * RETURN VALUE: none | |
813 * | |
814 *************************************************************************/ | |
815 | |
816 void aver_lsf_history ( | |
817 Word16 lsf_old[DTX_HANGOVER][M], | |
818 Word16 lsf1[M], | |
819 Word16 lsf2[M], | |
820 Word16 lsf_aver[M] | |
821 ) | |
822 { | |
823 Word16 i, j; | |
824 Word32 L_temp; | |
825 | |
826 for (j = 0; j < M; j++) | |
827 { | |
828 L_temp = L_mult (0x3fff, lsf1[j]); | |
829 L_temp = L_mac (L_temp, 0x3fff, lsf2[j]); | |
830 L_temp = L_mult (INV_DTX_HANGOVER_P1, extract_h (L_temp)); | |
831 | |
832 for (i = 0; i < DTX_HANGOVER; i++) | |
833 { | |
834 L_temp = L_mac (L_temp, INV_DTX_HANGOVER_P1, lsf_old[i][j]); | |
835 } | |
836 | |
837 lsf_aver[j] = extract_h (L_temp); move16 (); | |
838 } | |
839 | |
840 return; | |
841 } | |
842 | |
843 /************************************************************************* | |
844 * | |
845 * FUNCTION NAME: update_gain_code_history_tx | |
846 * | |
847 * PURPOSE: Update the fixed codebook gain parameter history of the | |
848 * encoder. The fixed codebook gain parameters kept in the buffer | |
849 * are used later for computing the reference fixed codebook | |
850 * gain parameter value and the averaged fixed codebook gain | |
851 * parameter value. | |
852 * | |
853 * INPUTS: new_gain_code New fixed codebook gain value | |
854 * | |
855 * gain_code_old_tx[0..4*DTX_HANGOVER-1] | |
856 * Old fixed codebook gain history of encoder | |
857 * | |
858 * OUTPUTS: gain_code_old_tx[0..4*DTX_HANGOVER-1] | |
859 * Updated fixed codebook gain history of encoder | |
860 * | |
861 * RETURN VALUE: none | |
862 * | |
863 *************************************************************************/ | |
864 | |
865 void update_gain_code_history_tx ( | |
866 Word16 new_gain_code, | |
867 Word16 gain_code_old_tx[4 * DTX_HANGOVER] | |
868 ) | |
869 { | |
870 | |
871 /* Circular buffer */ | |
872 gain_code_old_tx[buf_p_tx] = new_gain_code; move16 (); | |
873 | |
874 test (); | |
875 if (sub (buf_p_tx, (4 * DTX_HANGOVER - 1)) == 0) | |
876 { | |
877 buf_p_tx = 0; move16 (); | |
878 } | |
879 else | |
880 { | |
881 buf_p_tx = add (buf_p_tx, 1); | |
882 } | |
883 | |
884 return; | |
885 } | |
886 | |
887 /************************************************************************* | |
888 * | |
889 * FUNCTION NAME: update_gain_code_history_rx | |
890 * | |
891 * PURPOSE: Update the fixed codebook gain parameter history of the | |
892 * decoder. The fixed codebook gain parameters kept in the buffer | |
893 * are used later for computing the reference fixed codebook | |
894 * gain parameter value. | |
895 * | |
896 * INPUTS: new_gain_code New fixed codebook gain value | |
897 * | |
898 * gain_code_old_tx[0..4*DTX_HANGOVER-1] | |
899 * Old fixed codebook gain history of decoder | |
900 * | |
901 * OUTPUTS: gain_code_old_tx[0..4*DTX_HANGOVER-1] | |
902 * Updated fixed codebk gain history of decoder | |
903 * | |
904 * RETURN VALUE: none | |
905 * | |
906 *************************************************************************/ | |
907 | |
908 void update_gain_code_history_rx ( | |
909 Word16 new_gain_code, | |
910 Word16 gain_code_old_rx[4 * DTX_HANGOVER] | |
911 ) | |
912 { | |
913 | |
914 /* Circular buffer */ | |
915 gain_code_old_rx[buf_p_rx] = new_gain_code; move16 (); | |
916 | |
917 test (); | |
918 if (sub (buf_p_rx, (4 * DTX_HANGOVER - 1)) == 0) | |
919 { | |
920 buf_p_rx = 0; move16 (); | |
921 } | |
922 else | |
923 { | |
924 buf_p_rx = add (buf_p_rx, 1); | |
925 } | |
926 | |
927 return; | |
928 } | |
929 | |
930 /************************************************************************* | |
931 * | |
932 * FUNCTION NAME: compute_CN_excitation_gain | |
933 * | |
934 * PURPOSE: Compute the unquantized fixed codebook gain. Computation is | |
935 * based on the energy of the Linear Prediction residual signal. | |
936 * | |
937 * INPUTS: res2[0..39] Linear Prediction residual signal | |
938 * | |
939 * OUTPUTS: none | |
940 * | |
941 * RETURN VALUE: Unquantized fixed codebook gain | |
942 * | |
943 *************************************************************************/ | |
944 | |
945 Word16 compute_CN_excitation_gain ( | |
946 Word16 res2[L_SUBFR] | |
947 ) | |
948 { | |
949 Word16 i, norm, norm1, temp, overfl; | |
950 Word32 L_temp; | |
951 | |
952 /* Compute the energy of the LP residual signal */ | |
953 | |
954 norm = 0; move16 (); | |
955 do | |
956 { | |
957 overfl = 0; move16 (); | |
958 | |
959 L_temp = 0L; move32 (); | |
960 for (i = 0; i < L_SUBFR; i++) | |
961 { | |
962 temp = shr (res2[i], norm); | |
963 L_temp = L_mac (L_temp, temp, temp); | |
964 } | |
965 | |
966 test (); | |
967 if (L_sub (L_temp, MAX_32) == 0) | |
968 { | |
969 norm = add (norm, 1); | |
970 overfl = 1; move16 (); /* Set the overflow flag */ | |
971 } | |
972 test (); | |
973 } | |
974 while (overfl != 0); | |
975 | |
976 L_temp = L_add (L_temp, 1L); /* Avoid the case of all zeros */ | |
977 | |
978 /* Take the square root of the obtained energy value (sqroot is a 2nd | |
979 order Taylor series approximation) */ | |
980 | |
981 norm1 = norm_l (L_temp); | |
982 temp = extract_h (L_shl (L_temp, norm1)); | |
983 L_temp = L_mult (temp, temp); | |
984 L_temp = L_sub (805306368L, L_shr (L_temp, 3)); | |
985 L_temp = L_add (L_temp, L_mult (24576, temp)); | |
986 | |
987 temp = extract_h (L_temp); | |
988 test (); logic16 (); | |
989 if ((norm1 & 0x0001) != 0) | |
990 { | |
991 temp = mult_r (temp, 23170); | |
992 norm1 = sub (norm1, 1); | |
993 } | |
994 /* Divide the result of sqroot operation by sqroot(10) */ | |
995 | |
996 temp = mult_r (temp, 10362); | |
997 | |
998 /* Re-scale to get the final value */ | |
999 | |
1000 norm1 = shr (norm1, 1); | |
1001 norm1 = sub (norm1, norm); | |
1002 | |
1003 test (); | |
1004 if (norm1 >= 0) | |
1005 { | |
1006 temp = shr (temp, norm1); | |
1007 } | |
1008 else | |
1009 { | |
1010 temp = shl (temp, abs_s (norm1)); | |
1011 } | |
1012 | |
1013 return temp; | |
1014 } | |
1015 | |
1016 /************************************************************************* | |
1017 * | |
1018 * FUNCTION NAME: update_gcode0_CN | |
1019 * | |
1020 * PURPOSE: Update the reference fixed codebook gain parameter value. | |
1021 * The reference value is computed by averaging the quantized | |
1022 * fixed codebook gain parameter values which exist in the | |
1023 * fixed codebook gain parameter history. | |
1024 * | |
1025 * INPUTS: gain_code_old[0..4*DTX_HANGOVER-1] | |
1026 * fixed codebook gain parameter history | |
1027 * | |
1028 * OUTPUTS: none | |
1029 * | |
1030 * RETURN VALUE: Computed reference fixed codebook gain | |
1031 * | |
1032 *************************************************************************/ | |
1033 | |
1034 Word16 update_gcode0_CN ( | |
1035 Word16 gain_code_old[4 * DTX_HANGOVER] | |
1036 ) | |
1037 { | |
1038 Word16 i, j; | |
1039 Word32 L_temp, L_ret; | |
1040 | |
1041 L_ret = 0L; move32 (); | |
1042 for (i = 0; i < DTX_HANGOVER; i++) | |
1043 { | |
1044 L_temp = L_mult (0x1fff, gain_code_old[4 * i]); | |
1045 for (j = 1; j < 4; j++) | |
1046 { | |
1047 L_temp = L_mac (L_temp, 0x1fff, gain_code_old[4 * i + j]); | |
1048 } | |
1049 L_ret = L_mac (L_ret, INV_DTX_HANGOVER, extract_h (L_temp)); | |
1050 } | |
1051 | |
1052 return extract_h (L_ret); | |
1053 } | |
1054 | |
1055 /************************************************************************* | |
1056 * | |
1057 * FUNCTION NAME: aver_gain_code_history | |
1058 * | |
1059 * PURPOSE: Compute the averaged fixed codebook gain parameter value. | |
1060 * Computation is performed by averaging the fixed codebook | |
1061 * gain parameter values which exist in the fixed codebook | |
1062 * gain parameter history, together with the fixed codebook | |
1063 * gain parameter value of the current subframe. | |
1064 * | |
1065 * INPUTS: CN_excitation_gain | |
1066 * Unquantized fixed codebook gain value | |
1067 * of the current subframe | |
1068 * gain_code_old[0..4*DTX_HANGOVER-1] | |
1069 * fixed codebook gain parameter history | |
1070 * | |
1071 * OUTPUTS: none | |
1072 * | |
1073 * RETURN VALUE: Averaged fixed codebook gain value | |
1074 * | |
1075 *************************************************************************/ | |
1076 | |
1077 Word16 aver_gain_code_history ( | |
1078 Word16 CN_excitation_gain, | |
1079 Word16 gain_code_old[4 * DTX_HANGOVER] | |
1080 ) | |
1081 { | |
1082 Word16 i; | |
1083 Word32 L_ret; | |
1084 | |
1085 L_ret = L_mult (0x470, CN_excitation_gain); | |
1086 | |
1087 for (i = 0; i < (4 * DTX_HANGOVER); i++) | |
1088 { | |
1089 L_ret = L_mac (L_ret, 0x470, gain_code_old[i]); | |
1090 } | |
1091 return extract_h (L_ret); | |
1092 } | |
1093 | |
1094 /************************************************************************* | |
1095 * | |
1096 * FUNCTION NAME: build_CN_code | |
1097 * | |
1098 * PURPOSE: Compute the comfort noise fixed codebook excitation. The | |
1099 * gains of the pulses are always +/-1. | |
1100 * | |
1101 * INPUTS: *seed Old CN generator shift register state | |
1102 * | |
1103 * OUTPUTS: cod[0..39] Generated comfort noise fixed codebook vector | |
1104 * *seed Updated CN generator shift register state | |
1105 * | |
1106 * RETURN VALUE: none | |
1107 * | |
1108 *************************************************************************/ | |
1109 | |
1110 void build_CN_code ( | |
1111 Word16 cod[], | |
1112 Word32 *seed | |
1113 ) | |
1114 { | |
1115 Word16 i, j, k; | |
1116 | |
1117 for (i = 0; i < L_SUBFR; i++) | |
1118 { | |
1119 cod[i] = 0; move16 (); | |
1120 } | |
1121 | |
1122 for (k = 0; k < NB_PULSE; k++) | |
1123 { | |
1124 i = pseudonoise (seed, 2); /* generate pulse position */ | |
1125 i = shr (extract_l (L_mult (i, 10)), 1); | |
1126 i = add (i, k); | |
1127 | |
1128 j = pseudonoise (seed, 1); /* generate sign */ | |
1129 | |
1130 test (); | |
1131 if (j > 0) | |
1132 { | |
1133 cod[i] = 4096; move16 (); | |
1134 } | |
1135 else | |
1136 { | |
1137 cod[i] = -4096; move16 (); | |
1138 } | |
1139 } | |
1140 | |
1141 return; | |
1142 } | |
1143 | |
1144 /************************************************************************* | |
1145 * | |
1146 * FUNCTION NAME: pseudonoise | |
1147 * | |
1148 * PURPOSE: Generate a random integer value to use in comfort noise | |
1149 * generation. The algorithm uses polynomial x^31 + x^3 + 1 | |
1150 * (length of PN sequence is 2^31 - 1). | |
1151 * | |
1152 * INPUTS: *shift_reg Old CN generator shift register state | |
1153 * | |
1154 * | |
1155 * OUTPUTS: *shift_reg Updated CN generator shift register state | |
1156 * | |
1157 * RETURN VALUE: Generated random integer value | |
1158 * | |
1159 *************************************************************************/ | |
1160 | |
1161 Word16 pseudonoise ( | |
1162 Word32 *shift_reg, | |
1163 Word16 no_bits | |
1164 ) | |
1165 { | |
1166 Word16 noise_bits, Sn, i; | |
1167 | |
1168 noise_bits = 0; move16 (); | |
1169 for (i = 0; i < no_bits; i++) | |
1170 { | |
1171 /* State n == 31 */ | |
1172 test (); logic32 (); | |
1173 if ((*shift_reg & 0x00000001L) != 0) | |
1174 { | |
1175 Sn = 1; move16 (); | |
1176 } | |
1177 else | |
1178 { | |
1179 Sn = 0; move16 (); | |
1180 } | |
1181 | |
1182 /* State n == 3 */ | |
1183 test (); logic32 (); | |
1184 if ((*shift_reg & 0x10000000L) != 0) | |
1185 { | |
1186 Sn = Sn ^ 1; logic16 (); | |
1187 } | |
1188 else | |
1189 { | |
1190 Sn = Sn ^ 0; logic16 (); | |
1191 } | |
1192 | |
1193 noise_bits = shl (noise_bits, 1); | |
1194 noise_bits = noise_bits | (extract_l (*shift_reg) & 1); | |
1195 logic16 (); logic16 (); | |
1196 | |
1197 *shift_reg = L_shr (*shift_reg, 1); move32 (); | |
1198 test (); logic16 (); | |
1199 if (Sn & 1) | |
1200 { | |
1201 *shift_reg = *shift_reg | 0x40000000L; move32 (); logic32 (); | |
1202 } | |
1203 } | |
1204 | |
1205 return noise_bits; | |
1206 } | |
1207 | |
1208 /************************************************************************* | |
1209 * | |
1210 * FUNCTION NAME: interpolate_CN_param | |
1211 * | |
1212 * PURPOSE: Interpolate a comfort noise parameter value over the comfort | |
1213 * noise update period. | |
1214 * | |
1215 * INPUTS: old_param The older parameter of the interpolation | |
1216 * (the endpoint the interpolation is started | |
1217 * from) | |
1218 * new_param The newer parameter of the interpolation | |
1219 * (the endpoint the interpolation is ended to) | |
1220 * rx_dtx_state State of the comfort noise insertion period | |
1221 * | |
1222 * OUTPUTS: none | |
1223 * | |
1224 * RETURN VALUE: Interpolated CN parameter value | |
1225 * | |
1226 *************************************************************************/ | |
1227 | |
1228 Word16 interpolate_CN_param ( | |
1229 Word16 old_param, | |
1230 Word16 new_param, | |
1231 Word16 rx_dtx_state | |
1232 ) | |
1233 { | |
1234 static const Word16 interp_factor[CN_INT_PERIOD] = | |
1235 { | |
1236 0x0555, 0x0aaa, 0x1000, 0x1555, 0x1aaa, 0x2000, | |
1237 0x2555, 0x2aaa, 0x3000, 0x3555, 0x3aaa, 0x4000, | |
1238 0x4555, 0x4aaa, 0x5000, 0x5555, 0x5aaa, 0x6000, | |
1239 0x6555, 0x6aaa, 0x7000, 0x7555, 0x7aaa, 0x7fff}; | |
1240 Word16 temp; | |
1241 Word32 L_temp; | |
1242 | |
1243 L_temp = L_mult (interp_factor[rx_dtx_state], new_param); | |
1244 temp = sub (0x7fff, interp_factor[rx_dtx_state]); | |
1245 temp = add (temp, 1); | |
1246 L_temp = L_mac (L_temp, temp, old_param); | |
1247 temp = round (L_temp); | |
1248 | |
1249 return temp; | |
1250 } | |
1251 | |
1252 /************************************************************************* | |
1253 * | |
1254 * FUNCTION NAME: interpolate_CN_lsf | |
1255 * | |
1256 * PURPOSE: Interpolate comfort noise LSF parameter vector over the comfort | |
1257 * noise update period. | |
1258 * | |
1259 * INPUTS: lsf_old_CN[0..9] | |
1260 * The older LSF parameter vector of the | |
1261 * interpolation (the endpoint the interpolation | |
1262 * is started from) | |
1263 * lsf_new_CN[0..9] | |
1264 * The newer LSF parameter vector of the | |
1265 * interpolation (the endpoint the interpolation | |
1266 * is ended to) | |
1267 * rx_dtx_state State of the comfort noise insertion period | |
1268 * | |
1269 * OUTPUTS: lsf_interp_CN[0..9] | |
1270 * Interpolated LSF parameter vector | |
1271 * | |
1272 * RETURN VALUE: none | |
1273 * | |
1274 *************************************************************************/ | |
1275 | |
1276 void interpolate_CN_lsf ( | |
1277 Word16 lsf_old_CN[M], | |
1278 Word16 lsf_new_CN[M], | |
1279 Word16 lsf_interp_CN[M], | |
1280 Word16 rx_dtx_state | |
1281 ) | |
1282 { | |
1283 Word16 i; | |
1284 | |
1285 for (i = 0; i < M; i++) | |
1286 { | |
1287 lsf_interp_CN[i] = interpolate_CN_param (lsf_old_CN[i], | |
1288 lsf_new_CN[i], | |
1289 rx_dtx_state); move16 (); | |
1290 } | |
1291 | |
1292 return; | |
1293 } |