Line data Source code
1 : /******************************************************************************
2 : * ETSI TS 103 634 V1.5.1 *
3 : * Low Complexity Communication Codec Plus (LC3plus) *
4 : * *
5 : * Copyright licence is solely granted through ETSI Intellectual Property *
6 : * Rights Policy, 3rd April 2019. No patent licence is granted by implication, *
7 : * estoppel or otherwise. *
8 : ******************************************************************************/
9 :
10 : #include "defines.h"
11 : #include "functions.h"
12 :
13 : /*****************************************************************************/
14 :
15 : static Word16 TDC_Dot_product(const Word16 x[], const Word16 y[], const Word16 lg);
16 : static Word32 TDC_L_Dot_product(const Word16 x[], const Word16 y[], const Word16 lg);
17 : static void TDC_highPassFiltering_fx(const Word16 L_buffer, Word16 exc2[], const Word16 l_fir_fer,
18 : const Word16 *hp_filt);
19 : static Word32 TDC_calcGainp(Word16 x[], Word16 y[], Word16 lg);
20 : static void TDC_calcGainc(Word16 *exc, Word16 Q_exc, Word16 old_fpitch, Word16 lg, Word16 frame_dms, Word16 lp_gainp, Word32 *lp_gainc);
21 : static void TDC_random_fx(Word16 *seed, Word16 lg, Word16 *y);
22 : static Word16 TDC_preemph(Word16 *x, const Word16 fac, const Word16 lg);
23 : static void TDC_LPC_residu_fx(const Word16 *a, Word16 *x, Word16 *y, Word16 lg, Word16 m);
24 : static void TDC_deemph_fx(const Word16 *x, Word16 *y, const Word16 fac, const Word16 lg, const Word16 mem);
25 : static void TDC_LPC_synthesis_fx(const Word16 sh, const Word16 a[], const Word16 x[], Word16 y[], const Word16 lg,
26 : const Word16 m);
27 : static void TDC_normalize_energy_fx(Word16 *gain, Word16 *gain_exp, const Word16 *x, const Word16 lg);
28 :
29 : const Word16 beforeNextIncArray_fx[4][4] = {{0,0,0,1},
30 : {0,1,0,1},
31 : {0,1,1,1},
32 : {1,1,1,1}};
33 : const Word16 nextIncArray_fx[4][4] = {{1,0,0,0},
34 : {1,0,1,0},
35 : {1,0,1,1},
36 : {1,1,1,1}};
37 : static Word16 type_2_alpha_long(Word16 nbLostFramesInRow, Word16 frame_dms);
38 : static Word16 powWord16rest(Word16 base, Word16 exp, Word16 rest);
39 :
40 : /*****************************************************************************/
41 :
42 :
43 : /*
44 : * processTimeDomainConcealment_Apply_fx
45 : *
46 : * Parameters:
47 : * pitch_int i : integer pitch lag Q0
48 : * preemphFac_fx i : preemphase factor Q15
49 : * A_fx i : lp filter coefficients Qx
50 : * pcmbufHist_fx i : pointer to input signal Qq_fx_old_exp
51 : * frame_length i : frame length Q0
52 : * fs_idx i : sample rate index Q0
53 : * nbLostFramesInRow i : number of consecutive lost frames Q0
54 : * overlap i : overlap length Q0
55 : * stabFac_fx i : stability factor Q15
56 : * fract i/o: fraction of lag Q0
57 : * seed_fx i/o: pointer to seed Q0
58 : * gain_p_fx i/o: pointer to gainp Q15
59 : * gain_c_fx i/o: pointer to gainc 15Q16
60 : * synth_fx o : pointer to synthesized signal Q_syn
61 : * Q_syn o : exponent for synthesized signal Q0
62 : * alpha o : damping factor Q15
63 : * scratchBuffer i : scratch buffer
64 : *
65 : * Function:
66 : * Perform the time domain concealment.
67 : *
68 : * Returns:
69 : * void
70 : */
71 0 : void processTimeDomainConcealment_Apply_fx(const Word16 pitch_int, const Word16 preemphFac_fx, const Word16 *A_fx,
72 : const Word16 lpc_order, const Word16 *pcmbufHist_fx, const Word16 frame_length,
73 : const Word16 frame_dms, const Word16 fs_idx, const Word16 nbLostFramesInRow,
74 : const Word16 overlap, const Word16 stabFac_fx, Word16 *fract,
75 : Word16 *seed_fx,
76 : Word32 *gain_c_fx, Word16 *synth_fx, Word16 *Q_syn, Word16 *alpha, Word16 max_len_pcm_plc,
77 : Word16 harmonicBuf_fx[MAX_PITCH], Word16 synthHist_fx[M], Word16 *const harmonicBuf_Q,
78 : Word8 *scratchBuffer
79 : , UWord8 plc_fadeout_type
80 : , Word16 * alpha_type_2_table
81 : )
82 : {
83 : Counter i;
84 : Word16 s, s1, c1, c2, len, cnt, g_fx, ilen, Tc, nextInc, beforeNextInc;
85 : Word32 tmp32, tmp32_2, gainc_tmp;
86 : Word16 gain_p_fx;
87 : Word32 gain_c_32_fx;
88 : Word16 gain_c_16_fx, gain_c_16_fx_exp, gain_inov_fx, gain_inov_fx_exp, ilen_exp;
89 : Word16 hpBlendFac;
90 : Word16 len_pi_lf_2, frame_length_2, step_fx, step_n_fx, gain_h_fx, nbLostCmpt_loc, mem_deemph;
91 : Word16 * synth_mem_fx, *synth_tmp_fx, *exc2_fx, *exc_fx, *pt_exc, *pt1_exc, *x_pre_fx;
92 : Word16 * harmonicBufPtr;
93 0 : Word16 Q_exc = 0, exp_scale;
94 : const Word16 *hp_filt_fx, *TDC_high_harm;
95 : Word16 alphaPrev_fx;
96 : Word16 throttle;
97 : Word16 frame_dms_idx, nbLostFramesInRow_mod;
98 :
99 : #ifdef DYNMEM_COUNT
100 : Dyn_Mem_In("processTimeDomainConcealment_Apply_fx", sizeof(struct {
101 : Counter i;
102 : Word16 s, s1, c1, c2, len, cnt, g_fx, ilen, Tc, nextInc, beforeNextInc;
103 : Word32 tmp32, tmp32_2, gainc_tmp;
104 : Word16 gain_p_fx;
105 : Word32 gain_c_32_fx;
106 : Word16 gain_c_16_fx, gain_c_16_fx_exp, gain_inov_fx, gain_inov_fx_exp, ilen_exp;
107 : Word16 hpBlendFac;
108 : Word16 len_pi_lf_2, frame_length_2, step_fx, step_n_fx, gain_h_fx, nbLostCmpt_loc, mem_deemph;
109 : Word16 * synth_mem_fx, *synth_tmp_fx, *exc2_fx, *exc_fx, *pt_exc, *pt1_exc, *x_pre_fx;
110 : Word16 * harmonicBufPtr;
111 : Word16 Q_exc, exp_scale;
112 : const Word16 *hp_filt_fx, *TDC_high_harm;
113 : Word16 alphaPrev_fx;
114 : Word16 throttle;
115 : Word16 frame_dms_idx, nbLostFramesInRow_mod;
116 : }));
117 : #endif
118 :
119 0 : Word32 plc_fadeout_len = 0;
120 0 : if (plc_fadeout_type >= 1){
121 0 : plc_fadeout_len = PLC_FADEOUT_TYPE_1_IN_MS;
122 : }
123 : else{
124 0 : plc_fadeout_len = PLC_FADEOUT_IN_MS;
125 : }
126 :
127 : /* len of output signal */
128 0 : len = add(frame_length, overlap);
129 :
130 0 : nbLostFramesInRow_mod = sub(nbLostFramesInRow, 1) & 0x0003;
131 :
132 0 : frame_dms_idx = mult(frame_dms, 0x051F);
133 0 : nbLostCmpt_loc = add(shr(L_mult0(frame_dms_idx, sub(nbLostFramesInRow, 1)), 2), 1);
134 0 : frame_dms_idx = sub(frame_dms_idx, 1);
135 0 : beforeNextInc = beforeNextIncArray_fx[frame_dms_idx][nbLostFramesInRow_mod]; move16();
136 0 : nextInc = nextIncArray_fx [frame_dms_idx][nbLostFramesInRow_mod]; move16();
137 :
138 0 : IF (sub(nbLostCmpt_loc, plc_fadeout_len / 10) > 0)
139 : {
140 0 : gain_p_fx = 0; move16();
141 0 : *gain_c_fx = 0; move32();
142 0 : *Q_syn = 0; move16();
143 0 : *alpha = 0; move16();
144 0 : basop_memset(synth_fx, 0, len * sizeof(Word16));
145 : #ifdef DYNMEM_COUNT
146 : Dyn_Mem_Out();
147 : #endif
148 0 : return;
149 : }
150 :
151 0 : frame_length_2 = shr_pos(frame_length, 1);
152 :
153 0 : Tc = pitch_int; move16();
154 0 : if (sub(*fract, 0) > 0)
155 : {
156 0 : Tc = add(Tc, 1);
157 : }
158 :
159 0 : len_pi_lf_2 = add(Tc, frame_length_2);
160 :
161 : /*----------------------------------------------------------------
162 : * Buffer Initialization
163 : *
164 : * exc_fx synth_mem_fx
165 : * |--exc_buf_past--|--exc_buf_curr--|--syn_mem--|--x_pre--|
166 : * |--exc2--|
167 : * |--syn--|
168 : *
169 : *---------------------------------------------------------------*/
170 :
171 : /* pointer inits */
172 0 : exc_fx = (Word16 *)scratchAlign(scratchBuffer,
173 : sizeof(Word16) * len_pi_lf_2); /* MAX_PITCH+MAX_LEN/2 + MAX_LEN+MDCT_MEM_LEN_MAX */
174 0 : synth_mem_fx = (Word16 *)scratchAlign(exc_fx, sizeof(*exc_fx) * len); /* M */
175 0 : x_pre_fx = (Word16 *)scratchAlign(synth_mem_fx, sizeof(*synth_mem_fx) * lpc_order); /* MAX_PITCH+MAX_LEN/2+M+1 */
176 0 : exc2_fx = (Word16 *)scratchAlign(synth_mem_fx, sizeof(*synth_mem_fx) * lpc_order); /* MAX_LEN+MDCT_MEM_LEN_MAX+TDC_L_FIR_HP-1 */
177 0 : synth_tmp_fx = (Word16 *)scratchAlign(synth_mem_fx, sizeof(*synth_mem_fx) * lpc_order); /* MAX_LEN+MDCT_MEM_LEN_MAX */
178 : /* Buffers 'overlap' since they are not used at the same time */
179 :
180 : /*---------------------------------------------------------------*
181 : * LPC Residual *
182 : *---------------------------------------------------------------*/
183 0 : IF (sub(nbLostFramesInRow, 1) == 0)
184 : {
185 :
186 : /* copy buffer to pre-emphasis buffer */
187 0 : cnt = add(len_pi_lf_2, lpc_order + 1);
188 0 : basop_memmove(&x_pre_fx[0], &pcmbufHist_fx[max_len_pcm_plc - cnt], cnt * sizeof(Word16));
189 :
190 : /* apply pre-emphasis to the signal; x_pre = x_pre_flt * 2^(q_fx_old_exp-15-Q_exc+1) */
191 0 : Q_exc = TDC_preemph(&(x_pre_fx[1]), preemphFac_fx, sub(cnt, 1));
192 :
193 : /* copy memory for LPC synth */
194 0 : basop_memmove(&synth_mem_fx[0], &x_pre_fx[len_pi_lf_2 + 1], lpc_order * sizeof(Word16));
195 :
196 : /* LPC Residual; exc = exc_fx * 2^(q_fx_old_exp-15-Q_exc) */
197 0 : TDC_LPC_residu_fx(A_fx, &(x_pre_fx[lpc_order + 1]), &(exc_fx[-len_pi_lf_2]), len_pi_lf_2, lpc_order);
198 : }
199 :
200 : /*---------------------------------------------------------------*
201 : * Calculate gains *
202 : *---------------------------------------------------------------*/
203 :
204 0 : IF (sub(nbLostFramesInRow, 1) == 0)
205 : {
206 0 : IF (sub(pitch_int, Tc) == 0)
207 : {
208 : gain_p_fx =
209 0 : round_fx_sat(L_shl_sat(TDC_calcGainp(&(x_pre_fx[lpc_order + Tc + 1]), &(x_pre_fx[lpc_order + 1]), frame_length_2), 15));
210 : }
211 : ELSE
212 : {
213 0 : tmp32 = TDC_calcGainp(&(x_pre_fx[lpc_order + Tc + 1]), &(x_pre_fx[lpc_order + 2]), frame_length_2);
214 0 : tmp32_2 = TDC_calcGainp(&(x_pre_fx[lpc_order + Tc + 1]), &(x_pre_fx[lpc_order + 1]), frame_length_2);
215 :
216 0 : IF (L_sub(tmp32, tmp32_2) > 0)
217 : {
218 0 : Tc = pitch_int; move16();
219 0 : gain_p_fx = round_fx_sat(L_shl_sat(tmp32, 15));
220 0 : *fract = 0; move16();
221 : }
222 : ELSE
223 : {
224 0 : gain_p_fx = round_fx_sat(L_shl_sat(tmp32_2, 15));
225 : }
226 : }
227 :
228 0 : if (gain_p_fx < 0)
229 : {
230 0 : gain_p_fx = 0; move16();
231 : }
232 :
233 0 : IF (sub(pitch_int, Tc) == 0)
234 : {
235 : /* gain_c = gain_c_32_fx * 2^(q_fx_old_exp-31) */
236 0 : TDC_calcGainc(exc_fx, Q_exc, Tc, frame_length_2, frame_dms, gain_p_fx, &gain_c_32_fx);
237 : }
238 : ELSE
239 : {
240 0 : TDC_calcGainc(exc_fx, Q_exc, pitch_int, frame_length_2, frame_dms, gain_p_fx, &tmp32);
241 0 : TDC_calcGainc(exc_fx, Q_exc, Tc , frame_length_2, frame_dms, gain_p_fx, &gain_c_32_fx);
242 :
243 0 : gain_c_32_fx = L_min(gain_c_32_fx, tmp32); move32();
244 : }
245 : }
246 : ELSE
247 : {
248 0 : gain_c_32_fx = *gain_c_fx; move32();
249 0 : gain_p_fx = *alpha;
250 : }
251 :
252 : /*---------------------------------------------------------------*
253 : * Damping factor *
254 : *---------------------------------------------------------------*/
255 :
256 0 : alphaPrev_fx = 0x7FFF; move16();
257 0 : IF (sub(nbLostFramesInRow,1) > 0)
258 : {
259 0 : alphaPrev_fx = *alpha; move16();
260 : }
261 0 : IF (sub(plc_fadeout_type,2) == 0 ){
262 0 : *alpha = alpha_type_2_table[nbLostFramesInRow];
263 : }
264 : ELSE{
265 0 : IF (nextInc != 0)
266 : {
267 0 : IF (sub(nbLostCmpt_loc, 1) == 0)
268 : {
269 : /* Threshold 31470 is 0.98^2 in Q15 format */
270 0 : IF (sub(gain_p_fx, 31470) > 0)
271 : {
272 0 : *alpha = 0x7D71; /*0.98f*/
273 0 : move16();
274 : }
275 : /* Threshold 28037 is 0.925^2 in Q15 format */
276 0 : ELSE IF (sub(gain_p_fx, 28037) < 0)
277 : {
278 0 : *alpha = 0x7666; /*0.925f*/
279 0 : move16();
280 : }
281 : ELSE
282 : {
283 0 : exp_scale = 0;
284 0 : *alpha = Sqrt16_lc3plus(gain_p_fx, &exp_scale); move16();
285 0 : *alpha = shl(*alpha, exp_scale);
286 : }
287 : }
288 : ELSE
289 : {
290 0 : SWITCH (nbLostCmpt_loc)
291 : {
292 0 : case 2:
293 0 : c1 = 0x50A4; /*0.630f*/
294 0 : move16();
295 0 : c2 = 0x2CCD; /*0.350f*/
296 0 : move16();
297 0 : BREAK;
298 0 : default:
299 0 : c1 = 0x5375; /*0.652f*/
300 0 : move16();
301 0 : c2 = 0x29FC; /*0.328f*/
302 0 : move16();
303 0 : BREAK;
304 : }
305 :
306 0 : *alpha = mult_r(stabFac_fx, c2);
307 0 : *alpha = add(*alpha, c1);
308 :
309 0 : *alpha = mult(gain_p_fx, *alpha);
310 :
311 :
312 0 : IF (sub(nbLostCmpt_loc, 2) == 0)
313 : {
314 0 : if (sub(*alpha, 0x75A2 /*0.919f*/) < 0)
315 : {
316 0 : *alpha = 0x75A2; move16();
317 : }
318 : }
319 0 : ELSE IF (sub(nbLostCmpt_loc, 5) > 0)
320 : {
321 0 : gain_p_fx = *alpha; move16();
322 : }
323 : }
324 : }
325 :
326 0 : IF (sub(nbLostCmpt_loc,3) > 0)
327 : {
328 0 : SWITCH (frame_dms)
329 : {
330 0 : case 25: *alpha = mult(*alpha, PLC34_ATTEN_FAC_025_FX); BREAK;
331 0 : case 50: *alpha = mult(*alpha, PLC34_ATTEN_FAC_025_FX); BREAK;
332 0 : case 75: *alpha = mult(*alpha, PLC34_ATTEN_FAC_075_FX); BREAK;
333 0 : case 100: *alpha = mult(*alpha, PLC34_ATTEN_FAC_100_FX); BREAK;
334 : }
335 0 : }
336 0 : if (sub(nbLostCmpt_loc, 5) > 0)
337 : {
338 0 : gain_p_fx = *alpha; move16();
339 : }
340 : }
341 :
342 : /*---------------------------------------------------------------*
343 : * Construct the harmonic part *
344 : * Last pitch cycle of the previous frame is repeatedly copied. *
345 : *---------------------------------------------------------------*/
346 :
347 0 : pt_exc = harmonicBuf_fx; move16();
348 0 : pt1_exc = exc_fx - Tc; move16();
349 0 : s = s_min(len, Tc); move16();
350 0 : test();
351 0 : IF (sub(nbLostFramesInRow, 1) == 0)
352 : {
353 0 : *harmonicBuf_Q = Q_exc; move16();
354 0 : IF (sub(stabFac_fx, 32767 /*1.f Q15*/) >= 0)
355 : {
356 0 : basop_memmove(pt_exc, pt1_exc, Tc * sizeof(Word16));
357 : }
358 : ELSE
359 : {
360 : /* These values are necessary for the last five filtered samples */
361 0 : basop_memmove(exc_fx, &exc_fx[-Tc], (TDC_L_FIR_HP-1)/2 * sizeof(Word16));
362 0 : TDC_high_harm = TDC_high_32_harm;
363 0 : if (sub(fs_idx, 1) <= 0)
364 : {
365 0 : TDC_high_harm = TDC_high_16_harm;
366 : }
367 0 : FOR (i = 0; i < Tc; i++)
368 : {
369 0 : pt_exc[i] = TDC_Dot_product(&pt1_exc[i-(TDC_L_FIR_HP-1)/2], TDC_high_harm, TDC_L_FIR_HP);
370 : }
371 : }
372 : }
373 : ELSE
374 : {
375 0 : Q_exc = *harmonicBuf_Q; move16();
376 : }
377 :
378 :
379 : /*---------------------------------------------------------------*
380 : * Construct the random part of excitation *
381 : *---------------------------------------------------------------*/
382 :
383 0 : TDC_random_fx(seed_fx, add(len, sub(TDC_L_FIR_HP, 1)), exc2_fx);
384 :
385 : /* high pass noise */
386 0 : hp_filt_fx = TDC_high_32;
387 0 : if (sub(fs_idx, 1) <= 0)
388 : {
389 0 : hp_filt_fx = TDC_high_16;
390 : }
391 :
392 0 : IF (sub(nbLostFramesInRow, 1) == 0)
393 : {
394 0 : TDC_highPassFiltering_fx(len, exc2_fx, TDC_L_FIR_HP, hp_filt_fx);
395 : }
396 : ELSE
397 : {
398 0 : throttle = div_s(nbLostCmpt_loc, add(nbLostCmpt_loc, PLC3_HPBLENDTHROTTLE));
399 0 : hpBlendFac = mult(sub(0x7FFF, *alpha), throttle);
400 0 : c1 = sub(0x7FFF, hpBlendFac);
401 0 : FOR (i = 0; i < len; i++)
402 : {
403 : /* Return value of dot product is Q1 */
404 0 : tmp32 = Mpy_32_16_lc3plus(TDC_L_Dot_product(&exc2_fx[i], hp_filt_fx, TDC_L_FIR_HP), c1 /*Q15*/);
405 0 : exc2_fx[i] = round_fx(L_mac0(tmp32, hpBlendFac, exc2_fx[i+TDC_L_FIR_HP/2])); move16();
406 : }
407 : }
408 :
409 : /* normalize energy */
410 0 : TDC_normalize_energy_fx(&gain_inov_fx, &gain_inov_fx_exp, exc2_fx, frame_length);
411 0 : tmp32 = Mpy_32_16_lc3plus(
412 : L_sub(590558016l /*1.1 Q29*/, Mpy_32_16_lc3plus(L_shr_pos(L_deposit_h(gain_p_fx), 2), 24576 /*0.75*/)) /*Q29*/,
413 : gain_inov_fx /*Q15,gain_inov_e*/); /*Q29,gain_inov_e*/
414 0 : s = norm_l(tmp32);
415 0 : tmp32 = L_shl_pos(tmp32, s);
416 0 : tmp32 = L_min(tmp32, 0x7FFEFFFF);
417 0 : gain_inov_fx_exp = add(sub(gain_inov_fx_exp, s), 31 - 29); /*->Q31*/
418 0 : gain_inov_fx = round_fx(tmp32); /*Q15,gain_inov_e*/
419 :
420 : /* gains */
421 0 : gain_h_fx = alphaPrev_fx; move16();
422 :
423 : /* update steps */
424 0 : if (frame_length == 720)
425 : {
426 0 : ilen = BASOP_Util_Divide1616_Scale_lc3plus((Word16)1, 960, &ilen_exp);
427 : } else {
428 0 : ilen = BASOP_Util_Divide1616_Scale_lc3plus((Word16)1, frame_length, &ilen_exp);
429 : }
430 0 : step_fx = round_fx(L_shl(L_mult(sub(gain_h_fx, *alpha), ilen), ilen_exp));
431 :
432 0 : s = norm_l(gain_c_32_fx);
433 0 : tmp32 = L_shl_pos(gain_c_32_fx, s);
434 :
435 0 : gain_c_16_fx = extract_h(tmp32);
436 0 : gain_c_16_fx_exp = sub(15, s);
437 0 : gainc_tmp = L_mult (gain_c_16_fx, div_s(*alpha, s_max(alphaPrev_fx, 1)));
438 0 : tmp32 = L_sub (tmp32, gainc_tmp);
439 0 : step_n_fx = round_fx(L_shl(Mpy_32_16_lc3plus(tmp32, ilen), ilen_exp));
440 :
441 : /*---------------------------------------------------------------*
442 : * Construct the total excitation *
443 : *---------------------------------------------------------------*/
444 :
445 0 : harmonicBufPtr = harmonicBuf_fx + ((nbLostFramesInRow - 1) * frame_length) % Tc;
446 :
447 0 : s1 = add(Q_exc, add(gain_inov_fx_exp, gain_c_16_fx_exp));
448 0 : cnt = add(frame_length, TDC_L_FIR_HP / 2);
449 :
450 0 : g_fx = mult_r(gain_c_16_fx, gain_inov_fx);
451 :
452 0 : FOR (i = 0; i < len; i++)
453 : {
454 : /* harmonic */
455 0 : if (harmonicBufPtr - harmonicBuf_fx >= Tc) {
456 0 : harmonicBufPtr = harmonicBuf_fx;
457 : }
458 0 : exc_fx[i] = *harmonicBufPtr++;
459 0 : tmp32 = L_mult(exc_fx[i], gain_h_fx);
460 : /* random */
461 0 : tmp32_2 = L_shl_sat(L_mult(exc2_fx[i], g_fx), s1);
462 : /* total */
463 0 : exc_fx[i] = round_fx_sat(L_add_sat(tmp32, tmp32_2)); move16();
464 : /* update */
465 0 : gain_h_fx = s_max(sub(gain_h_fx, step_fx), 0);
466 0 : gain_c_16_fx = s_max(sub(gain_c_16_fx, step_n_fx), 0);
467 0 : g_fx = mult_r(gain_c_16_fx, gain_inov_fx);
468 : }
469 :
470 : /* update gain */
471 0 : *gain_c_fx = L_shl(gainc_tmp, sub(gain_c_16_fx_exp, 15)); move32();
472 :
473 :
474 : /*----------------------------------------------------------*
475 : * Compute the synthesis speech *
476 : *----------------------------------------------------------*/
477 :
478 : /* introduce some headroom to avoid Overflows, 2 bit seem to be sufficient */
479 0 : *Q_syn = sub(Q_exc, 2);
480 0 : *Q_syn = s_max(*Q_syn, -3);
481 :
482 0 : exp_scale = sub(*Q_syn, Q_exc - 1);
483 :
484 0 : IF (sub(nbLostFramesInRow, 1) != 0)
485 : {
486 0 : synth_mem_fx = synthHist_fx;
487 : }
488 0 : Copy_Scale_sig(synth_mem_fx, &synth_tmp_fx[-lpc_order], lpc_order, exp_scale);
489 0 : TDC_LPC_synthesis_fx(sub(Q_exc, *Q_syn), A_fx, exc_fx, synth_tmp_fx, len, lpc_order);
490 :
491 0 : FOR (i=0; i<lpc_order; i++)
492 : {
493 0 : synthHist_fx[i] = shr_sat(synth_tmp_fx[frame_length-lpc_order+i], exp_scale);
494 : }
495 :
496 : /*----------------------------------------------------------*
497 : * Deemphasis *
498 : *----------------------------------------------------------*/
499 :
500 0 : mem_deemph = shl_sat(pcmbufHist_fx[max_len_pcm_plc - 1], *Q_syn);
501 0 : TDC_deemph_fx(synth_tmp_fx, synth_fx, preemphFac_fx, len, mem_deemph);
502 :
503 : /*----------------------------------------------------------*
504 : * Fade to zero *
505 : *----------------------------------------------------------*/
506 :
507 0 : IF (beforeNextInc != 0)
508 : {
509 0 : IF (sub(nbLostCmpt_loc, plc_fadeout_len / 10) == 0)
510 : {
511 0 : gain_h_fx = (Word16)0x7FFF; move16();
512 0 : step_fx = round_fx(L_shl(L_mult(gain_h_fx, ilen), ilen_exp));
513 0 : FOR (i = 0; i < frame_length; i++)
514 : {
515 0 : assert(gain_h_fx >= 0);
516 0 : synth_fx[i] = mult(synth_fx[i], gain_h_fx);
517 0 : gain_h_fx = sub(gain_h_fx, step_fx);
518 : }
519 0 : basop_memset(&synth_fx[frame_length], 0, overlap * sizeof(Word16));
520 : }
521 : }
522 :
523 : #ifdef DYNMEM_COUNT
524 : Dyn_Mem_Out();
525 : #endif
526 : }
527 :
528 :
529 : /*****************************************************************************/
530 :
531 0 : static Word32 syn_kern_2(Word32 L_tmp, const Word16 a[], const Word16 y[])
532 : {
533 0 : L_tmp = L_msu_sat(L_tmp, y[-1], a[1]);
534 0 : L_tmp = L_msu_sat(L_tmp, y[-2], a[2]);
535 0 : return L_tmp;
536 : }
537 :
538 0 : static Word32 syn_kern_4(Word32 L_tmp, const Word16 a[], const Word16 y[])
539 : {
540 0 : L_tmp = syn_kern_2(L_tmp, a, y);
541 0 : return syn_kern_2(L_tmp, a + 2, y - 2);
542 : }
543 :
544 0 : static Word32 syn_kern_8(Word32 L_tmp, const Word16 a[], const Word16 y[])
545 : {
546 0 : L_tmp = syn_kern_4(L_tmp, a, y);
547 0 : return syn_kern_4(L_tmp, a + 4, y - 4);
548 : }
549 :
550 0 : static Word32 syn_kern_16(Word32 L_tmp, const Word16 a[], const Word16 y[])
551 : {
552 0 : L_tmp = syn_kern_8(L_tmp, a, y);
553 0 : return syn_kern_8(L_tmp, a + 8, y - 8);
554 : }
555 :
556 : /*
557 : * TDC_Dot_product
558 : *
559 : * Parameters:
560 : * x i: x vector Q0
561 : * y i: y vector Q0
562 : * lg i: vector length Q0
563 : *
564 : * Function:
565 : * dot product
566 : *
567 : * Returns:
568 : * dot product Q0
569 : */
570 0 : static Word16 TDC_Dot_product(const Word16 x[], const Word16 y[], const Word16 lg)
571 : {
572 : Dyn_Mem_Deluxe_In(
573 : Counter i;
574 : Word32 sum;
575 : );
576 :
577 0 : sum = L_mult(x[0], y[0]);
578 0 : FOR (i = 1; i < lg-1; i++)
579 : {
580 0 : sum = L_mac_sat(sum, x[i], y[i]);
581 : }
582 :
583 0 : sum = mac_r_sat(sum, x[lg-1], y[lg-1]);
584 :
585 : Dyn_Mem_Deluxe_Out();
586 :
587 0 : return sum;
588 : }
589 :
590 : /*
591 : * TDC_L_Dot_product
592 : *
593 : * Parameters:
594 : * x i: x vector Q0
595 : * y i: y vector Q0
596 : * lg i: vector length Q0
597 : *
598 : * Function:
599 : * dot product
600 : *
601 : * Returns:
602 : * dot product Q1
603 : */
604 0 : static Word32 TDC_L_Dot_product(const Word16 x[], const Word16 y[], const Word16 lg)
605 : {
606 : Dyn_Mem_Deluxe_In(
607 : Counter i;
608 : Word32 sum;
609 : );
610 :
611 0 : sum = L_mac0(1L, x[0], y[0]);
612 0 : FOR (i = 1; i < lg; i++)
613 : {
614 0 : sum = L_mac0(sum, x[i], y[i]);
615 : }
616 :
617 : Dyn_Mem_Deluxe_Out();
618 :
619 0 : return sum;
620 : }
621 :
622 : /*
623 : * TDC_highPassFiltering_fx
624 : *
625 : * Parameters:
626 : * L_buffer i: buffer length
627 : * exc2 i: unvoiced excitation before the high pass filtering Qx/Qx+1
628 : * l_fir_fer i: length highpass filter
629 : * hp_filt i: highpass filter coefficients Q15
630 : *
631 : * Function:
632 : * Highpass filter
633 : *
634 : * Returns:
635 : * void
636 : */
637 0 : static void TDC_highPassFiltering_fx(const Word16 L_buffer, Word16 exc2[], const Word16 l_fir_fer,
638 : const Word16 *hp_filt)
639 : {
640 : Dyn_Mem_Deluxe_In(
641 : Counter i;
642 : );
643 :
644 0 : FOR (i = 0; i < L_buffer; i++)
645 : {
646 0 : exc2[i] = round_fx(L_sub(TDC_L_Dot_product(&exc2[i], hp_filt, l_fir_fer), 1)); move16();
647 : }
648 :
649 : Dyn_Mem_Deluxe_Out();
650 0 : }
651 :
652 : /*
653 : * TDC_calcGainc
654 : *
655 : * Parameters:
656 : * exc i: pointer to excitation buffer
657 : * Q_exc i: Q format of excitation buffer
658 : * old_fpitch i: pitch_int
659 : * lg i: length
660 : * lp_gainp i: gain p
661 : * lp_gainc o: pointer to gain (15Q16)
662 : *
663 : * Function:
664 : * Gain calculation
665 : *
666 : * Returns:
667 : * void
668 : */
669 0 : static void TDC_calcGainc(Word16 *exc, Word16 Q_exc, Word16 old_fpitch, Word16 lg, Word16 frame_dms, Word16 lp_gainp, Word32 *lp_gainc)
670 : {
671 : Dyn_Mem_Deluxe_In(
672 : Word16 tmp16, tmp_e, tmp2_e;
673 : Word32 L_tmp, L_tmp_max;
674 : Counter i;
675 : );
676 :
677 0 : L_tmp = L_deposit_l(0);
678 :
679 0 : FOR (i = 0; i < lg; i++)
680 : {
681 : /* gain_c += ( exc[-i-1] - *gain_p * exc[-i-1-pitch_int] ) * ( exc[-i-1] - *gain_p * exc[-i-1-pitch_int] ); */
682 0 : tmp16 = sub_sat(exc[i - lg] /*Q1*/, mult_r(lp_gainp /*Q15*/, exc[i - lg - old_fpitch] /*Q1*/) /*Q1*/);
683 0 : L_tmp = L_mac0_sat(L_tmp, tmp16, tmp16); /*Q3*/
684 : }
685 :
686 0 : IF (sub(frame_dms, 100) < 0)
687 : {
688 0 : L_tmp_max = L_deposit_l(0);
689 0 : FOR (i = 0; i < lg; i++)
690 : {
691 0 : L_tmp_max = L_mac0_sat(L_tmp_max, exc[i - lg], exc[i - lg]); /*Q3*/
692 : }
693 0 : L_tmp = L_min(L_tmp, L_tmp_max);
694 : }
695 :
696 0 : tmp_e = norm_l(L_tmp);
697 0 : L_tmp = L_shl(L_tmp, tmp_e);
698 0 : tmp_e = sub(sub(31, shl_pos(Q_exc, 1)), tmp_e); /*L_tmp is Q31, now*/
699 0 : tmp16 = BASOP_Util_Divide3216_Scale_lc3plus(L_tmp /*Q31,norm,tmp_e*/, lg /*Q15,15*/, &tmp2_e) /*Q15,tmp2_e+tmp_e-15*/;
700 0 : tmp_e = sub(add(tmp2_e, tmp_e), 15);
701 :
702 0 : IF (tmp16 != 0)
703 : {
704 0 : tmp16 = Sqrt16_lc3plus(tmp16, &tmp_e); /*Q15,norm,tmp_e*/
705 0 : tmp_e = L_min(tmp_e, 15);
706 0 : *lp_gainc = L_shl_pos(L_deposit_l(tmp16), add(tmp_e, 1)); /*15Q16*/
707 0 : move32();
708 : }
709 : ELSE
710 : {
711 0 : *lp_gainc = 0;
712 : }
713 :
714 : Dyn_Mem_Deluxe_Out();
715 0 : }
716 :
717 : /*
718 : * TDC_calcGainp
719 : *
720 : * Parameters:
721 : * x i: input signal
722 : * y i: shifted input signal
723 : * lg i: vector length
724 : *
725 : * Function:
726 : * Gain calculation
727 : *
728 : * Returns:
729 : * gain (15Q16)
730 : */
731 0 : static Word32 TDC_calcGainp(Word16 x[], Word16 y[], Word16 lg)
732 : {
733 : Dyn_Mem_Deluxe_In(
734 : Word32 tcorr, tener, Lgain, L_tmp1, L_tmp2;
735 : Word16 m_corr, m_ener, negative, Q_corr, Q_ener;
736 : Counter i;
737 : );
738 :
739 0 : negative = 0; move16();
740 :
741 0 : L_tmp1 = L_deposit_l(0);
742 0 : L_tmp2 = L_deposit_l(0);
743 0 : FOR (i = 0; i < lg; i += 2)
744 : {
745 0 : L_tmp1 = L_mac0_sat(L_tmp1, x[i], y[i]);
746 0 : L_tmp2 = L_mac0_sat(L_tmp2, x[i + 1], y[i + 1]);
747 : }
748 0 : tcorr = L_add(L_shr_pos(L_tmp1, 1), L_shr_pos(L_tmp2, 1));
749 0 : Q_corr = norm_l(tcorr);
750 0 : tcorr = L_shl(tcorr, Q_corr);
751 0 : Q_corr = sub(2, Q_corr);
752 :
753 0 : L_tmp1 = L_deposit_l(0);
754 0 : L_tmp2 = L_deposit_l(0);
755 0 : FOR (i = 0; i < lg; i += 2)
756 : {
757 0 : L_tmp1 = L_mac0_sat(L_tmp1, y[i], y[i]);
758 0 : L_tmp2 = L_mac0_sat(L_tmp2, y[i + 1], y[i + 1]);
759 : }
760 0 : tener = L_add(L_shr_pos(L_tmp1, 1), L_shr_pos(L_tmp2, 1));
761 0 : Q_ener = norm_l(tener);
762 0 : tener = L_shl(tener, Q_ener);
763 0 : Q_ener = sub(2, Q_ener);
764 :
765 0 : tener = L_max(tener, 1);
766 :
767 0 : if (tcorr <= 0)
768 : {
769 0 : negative = 1; move16();
770 : }
771 0 : tcorr = L_abs(tcorr);
772 :
773 0 : m_corr = extract_h(tcorr);
774 :
775 0 : m_ener = extract_h(tener);
776 :
777 0 : IF (sub(m_corr, m_ener) > 0)
778 : {
779 0 : m_corr = shr_pos(m_corr, 1);
780 0 : Q_corr = add(Q_corr, 1);
781 : }
782 0 : if (m_ener == 0)
783 : {
784 0 : move16();
785 0 : m_corr = 0x7FFF;
786 : }
787 0 : if (m_ener != 0)
788 : {
789 0 : m_corr = div_s(m_corr, m_ener);
790 : }
791 :
792 0 : Q_corr = sub(Q_corr, Q_ener);
793 :
794 0 : Lgain = L_shl(L_deposit_l(m_corr), add(Q_corr, 1));
795 :
796 0 : if (negative != 0)
797 : {
798 0 : Lgain = L_negate(Lgain);
799 : }
800 :
801 : Dyn_Mem_Deluxe_Out();
802 :
803 0 : return Lgain;
804 : }
805 :
806 : /*
807 : * TDC_LPC_synthesis_fx
808 : *
809 : * Parameters:
810 : * sh i : scaling to apply for a[0] Q0
811 : * a[] i : LP filter coefficients Qx
812 : * x[] i : input signal Qx
813 : * y[] o : output signal Qx-s
814 : * lg i : size of filtering Q0
815 : * m i : order of LP filter Q0
816 : *
817 : * Function:
818 : * Apply LP filtering to obtain synthesis signal.
819 : * Memory size is always m.
820 : *
821 : * Returns:
822 : * void
823 : */
824 0 : static void TDC_LPC_synthesis_fx(const Word16 sh, const Word16 a[], const Word16 x[], Word16 y[], const Word16 lg,
825 : const Word16 m)
826 : {
827 : Dyn_Mem_Deluxe_In(
828 : Counter i;
829 : Word16 a0;
830 : Word16 q;
831 : Word32(*syn_kern)(Word32 L_tmp, const Word16 a[], const Word16 y[]
832 : ););
833 :
834 0 : ASSERT(m == 16 || m == 8);
835 :
836 0 : if (sub(m, 16) == 0)
837 : {
838 0 : syn_kern = syn_kern_16;
839 : }
840 0 : if (sub(m, 8) == 0)
841 : {
842 0 : syn_kern = syn_kern_8;
843 : }
844 :
845 0 : q = add(norm_s(a[0]), 1);
846 0 : a0 = shr_sat(a[0], sh);
847 :
848 0 : FOR (i = 0; i < lg; i++)
849 : {
850 0 : y[i] = round_fx_sat(L_shl_sat(syn_kern(L_mult(a0, x[i]), a, &y[i]), q)); move16();
851 : }
852 :
853 : Dyn_Mem_Deluxe_Out();
854 0 : }
855 :
856 : /* TDC_LPC_residu_fx
857 : *
858 : * Parameters:
859 : * a I: LP filter coefficients (Qx)
860 : * x I: input signal
861 : * y O: output signal
862 : * lg I: size of filtering
863 : * m I: lpc order
864 : *
865 : * Function:
866 : * Apply inverse filtering to obtain LP residual signal.
867 : *
868 : * Returns:
869 : * void
870 : */
871 0 : static void TDC_LPC_residu_fx(const Word16 *a, Word16 *x, Word16 *y, Word16 lg, Word16 m)
872 : {
873 : Dyn_Mem_Deluxe_In(
874 : Word16 a_exp;
875 : Word32 s;
876 : Counter i;
877 : );
878 :
879 0 : ASSERT(m == 16 || m == 8);
880 :
881 0 : a_exp = add(norm_s(a[0]), 1);
882 0 : a_exp = add(a_exp, 1);
883 :
884 0 : IF (sub(m, 16) == 0)
885 : {
886 0 : FOR (i = 0; i < lg; i++)
887 : {
888 0 : s = L_mult(x[i], a[0]);
889 0 : s = L_mac_sat(s, x[i - 1], a[1]);
890 0 : s = L_mac_sat(s, x[i - 2], a[2]);
891 0 : s = L_mac_sat(s, x[i - 3], a[3]);
892 0 : s = L_mac_sat(s, x[i - 4], a[4]);
893 0 : s = L_mac_sat(s, x[i - 5], a[5]);
894 0 : s = L_mac_sat(s, x[i - 6], a[6]);
895 0 : s = L_mac_sat(s, x[i - 7], a[7]);
896 0 : s = L_mac_sat(s, x[i - 8], a[8]);
897 0 : s = L_mac_sat(s, x[i - 9], a[9]);
898 0 : s = L_mac_sat(s, x[i - 10], a[10]);
899 0 : s = L_mac_sat(s, x[i - 11], a[11]);
900 0 : s = L_mac_sat(s, x[i - 12], a[12]);
901 0 : s = L_mac_sat(s, x[i - 13], a[13]);
902 0 : s = L_mac_sat(s, x[i - 14], a[14]);
903 0 : s = L_mac_sat(s, x[i - 15], a[15]);
904 0 : s = L_mac_sat(s, x[i - 16], a[16]);
905 :
906 0 : s = L_shl_sat(s, a_exp);
907 0 : y[i] = round_fx_sat(s); move16();
908 : }
909 : }
910 0 : IF (sub(m, 8) == 0)
911 : {
912 0 : FOR (i = 0; i < lg; i++)
913 : {
914 0 : s = L_mult(x[i], a[0]);
915 0 : s = L_mac_sat(s, x[i - 1], a[1]);
916 0 : s = L_mac_sat(s, x[i - 2], a[2]);
917 0 : s = L_mac_sat(s, x[i - 3], a[3]);
918 0 : s = L_mac_sat(s, x[i - 4], a[4]);
919 0 : s = L_mac_sat(s, x[i - 5], a[5]);
920 0 : s = L_mac_sat(s, x[i - 6], a[6]);
921 0 : s = L_mac_sat(s, x[i - 7], a[7]);
922 0 : s = L_mac_sat(s, x[i - 8], a[8]);
923 :
924 0 : s = L_shl_sat(s, a_exp);
925 0 : y[i] = round_fx_sat(s); move16();
926 : }
927 : }
928 :
929 : Dyn_Mem_Deluxe_Out();
930 0 : }
931 :
932 : /* TDC_random_fx
933 : *
934 : * Parameters:
935 : * seed i/o: seed for random number
936 : * lg i : vector length
937 : * y o : output values
938 : *
939 : * Function:
940 : * Uniform distributed random generator.
941 : *
942 : * Returns:
943 : * random number
944 : */
945 0 : static void TDC_random_fx(Word16 *seed, Word16 lg, Word16 *y)
946 : {
947 : Dyn_Mem_Deluxe_In(
948 : Counter i;
949 : );
950 :
951 0 : FOR (i = 0; i < lg; i++)
952 : {
953 0 : *seed = extract_l(L_mac0(16831L, *seed, 12821));
954 0 : *y++ = *seed; move16();
955 : }
956 :
957 : Dyn_Mem_Deluxe_Out();
958 0 : }
959 :
960 : /*
961 : * TDC_preemph
962 : *
963 : * Parameters:
964 : * x i/o: signal Qx
965 : * fac i: preemphasis factor Q15
966 : * lg i: vector length
967 : *
968 : * Function:
969 : * Filtering through 1 - fac z^-1
970 : *
971 : * Returns:
972 : * Q-factor
973 : */
974 0 : static Word16 TDC_preemph(Word16 *x, const Word16 fac, const Word16 lg)
975 : {
976 : Dyn_Mem_Deluxe_In(
977 : Word16 fac_sh, Q_max_value, Q_out;
978 : Word32 max_val;
979 : Counter i;
980 : );
981 :
982 0 : fac_sh = shr(fac, 3);
983 0 : Q_max_value = 4096; move16();
984 0 : Q_out = 12; move16();
985 :
986 0 : max_val = 0; move32();
987 0 : FOR (i = sub(lg, 1); i >= 0; i--)
988 : {
989 0 : max_val = L_max(L_abs(L_msu(L_mult(x[i], Q_max_value), x[i - 1], fac_sh)), max_val);
990 : }
991 :
992 0 : IF (extract_h(max_val) != 0)
993 : {
994 0 : Q_out = s_min(s_max(sub(norm_s(extract_h(max_val)), 3), 0), 12);
995 : }
996 :
997 0 : FOR (i = sub(lg, 1); i >= 0; i--)
998 : {
999 0 : x[i] = round_fx(L_shl(L_msu(L_mult(x[i], Q_max_value), x[i - 1], fac_sh), Q_out)); move16();
1000 : }
1001 :
1002 : Dyn_Mem_Deluxe_Out();
1003 :
1004 0 : return sub(Q_out, 2);
1005 : }
1006 :
1007 : /*
1008 : * TDC_deemph_fx
1009 : *
1010 : * Parameters:
1011 : * x i: input signal Qx
1012 : * y o: output signal Qx
1013 : * fac i: deemphasis factor Q15
1014 : * lg i: size of filtering Q0
1015 : * mem i: memory (x[-1])
1016 : *
1017 : * Function:
1018 : * Filtering through 1/(1-fac z^-1)
1019 : *
1020 : * Returns:
1021 : * void
1022 : */
1023 0 : static void TDC_deemph_fx(const Word16 *x, Word16 *y, const Word16 fac, const Word16 lg, const Word16 mem)
1024 : {
1025 : Dyn_Mem_Deluxe_In(
1026 : Counter i;
1027 : );
1028 :
1029 0 : y[0] = round_fx_sat(L_mac_sat(L_deposit_h(x[0]), mem, fac)); move16();
1030 0 : FOR (i = 1; i < lg; i++)
1031 : {
1032 0 : y[i] = round_fx_sat(L_mac_sat(L_deposit_h(x[i]), y[i - 1], fac)); move16();
1033 : }
1034 :
1035 : Dyn_Mem_Deluxe_Out();
1036 0 : }
1037 :
1038 : /*
1039 : * TDC_normalize_energy_fx
1040 : *
1041 : * Parameters:
1042 : * gain o: gain
1043 : * gain_exp o: exponent of gain
1044 : * x i: input signal
1045 : * lg i: length of input signal
1046 : *
1047 : * Function:
1048 : * Normalizes the energy.
1049 : *
1050 : * Returns:
1051 : * void
1052 : */
1053 0 : static void TDC_normalize_energy_fx(Word16 *gain, Word16 *gain_exp, const Word16 *x, const Word16 lg)
1054 : {
1055 : Dyn_Mem_Deluxe_In(
1056 : Counter i;
1057 : Word16 c;
1058 : Word16 e;
1059 : Word16 e1;
1060 : Word16 e2;
1061 : Word32 tmp;
1062 : Word16 tmp16;
1063 : );
1064 :
1065 0 : tmp = 0; move32();
1066 0 : FOR (i = 0; i < lg; i++)
1067 : {
1068 0 : tmp16 = mult_r(x[i], 2048);
1069 0 : tmp = L_mac(tmp, tmp16, tmp16);
1070 : }
1071 :
1072 0 : e = norm_l(tmp);
1073 0 : tmp = L_shl_pos(tmp, e);
1074 0 : e1 = sub(sub(30, e), -8); move16();
1075 0 : tmp16 = BASOP_Util_Divide3216_Scale_lc3plus(tmp, lg, &e2);
1076 :
1077 0 : e = 0; move16();
1078 0 : if (tmp16 != 0)
1079 : {
1080 0 : e = sub(add(e1, e2), 15);
1081 : }
1082 :
1083 0 : c = 0x0148; /* 0.01 */
1084 0 : move16();
1085 0 : IF (e > 0)
1086 : {
1087 0 : c = shr(c, s_min(e, 15));
1088 : }
1089 : ELSE
1090 : {
1091 0 : tmp16 = shr(tmp16, s_min(negate(e), 15));
1092 0 : e = 0; move16();
1093 : }
1094 :
1095 0 : e2 = 2; move16();
1096 0 : if (s_and(e, 1))
1097 : {
1098 0 : e2 = 1; move16();
1099 : }
1100 :
1101 0 : tmp16 = add(shr_pos(tmp16, e2), shr_pos(c, e2));
1102 0 : e = add(e, e2);
1103 :
1104 0 : tmp16 = Sqrt16_lc3plus(tmp16, &e);
1105 :
1106 0 : *gain = BASOP_Util_Divide1616_Scale_lc3plus((Word16)0x7FFF, tmp16, &e1); move16();
1107 0 : *gain_exp = sub(e1, e); move16();
1108 :
1109 : Dyn_Mem_Deluxe_Out();
1110 0 : }
1111 :
1112 0 : static Word16 type_2_alpha_long(Word16 nbLostFramesInRow, Word16 frame_dms)
1113 : {
1114 : Word16 n_help;
1115 : Word32 n_shift;
1116 :
1117 0 : if (nbLostFramesInRow <= 3*(100.0/frame_dms)){
1118 0 : n_help = (nbLostFramesInRow + (100/frame_dms) - 1) * frame_dms;
1119 0 : return powWord16rest(31129,n_help/100,n_help%100);
1120 : }
1121 : else {
1122 0 : n_shift = (nbLostFramesInRow - 3*(100/frame_dms)) * 50/frame_dms;
1123 0 : n_help = (n_shift + (100/frame_dms) - 1) * frame_dms;
1124 0 : return powWord16rest(22937,n_help/100,n_help%100);
1125 : }
1126 : }
1127 :
1128 0 : Word16 type_2_fadeout_fx(Word16 nbLostFramesInRow, Word16 frame_dms)
1129 : {
1130 : Word16 n_help;
1131 0 : Word16 selector = PLC_FADEOUT_TYPE_2_SELECTOR * 2 * (100/frame_dms);
1132 :
1133 0 : if (selector >= nbLostFramesInRow){
1134 0 : return type_2_alpha_long(nbLostFramesInRow, frame_dms);
1135 : }
1136 : else {
1137 0 : n_help = (nbLostFramesInRow + (100/frame_dms) - 1) * frame_dms;
1138 0 : return powWord16rest(16383,n_help/100, n_help%100);
1139 : }
1140 : }
1141 :
1142 0 : static Word16 powWord16rest(Word16 base, Word16 exp, Word16 rest) {
1143 0 : Word32 exp_result = 32767;
1144 : Word32 tmp_result;
1145 : Word16 root, i, exp2;
1146 :
1147 0 : FOR (i = 0; i < exp; ++i) {
1148 0 : tmp_result = (Word32)exp_result * base;
1149 0 : exp_result = (Word16)(tmp_result >> 15);
1150 : }
1151 :
1152 0 : IF (rest != 0) {
1153 0 : exp2 = 0;
1154 0 : SWITCH (rest)
1155 : {
1156 0 : case 50:
1157 0 : root = Sqrt16_lc3plus(base, &exp2);
1158 0 : shr(root,exp2);
1159 0 : exp_result = L_shr(exp_result * root,15); /* 0.5^1.5 = 0.5^(3/2) = 0.5^3*sqrt(0.5) */
1160 0 : BREAK;
1161 0 : case 25:
1162 0 : root = Sqrt16_lc3plus(base, &exp2);
1163 0 : shr(root,exp2);
1164 0 : exp2 = 0;
1165 0 : root = Sqrt16_lc3plus(root, &exp2);
1166 0 : shr(root,exp2);
1167 0 : exp_result = L_shr(exp_result * root,15); /* 0.5^(1/4) = 0.5^sqrt(sqrt(0.5)) */
1168 0 : BREAK;
1169 0 : case 75:
1170 0 : root = Sqrt16_lc3plus(base, &exp2);
1171 0 : shr(root,exp2);
1172 0 : exp2 = 0;
1173 0 : root = Sqrt16_lc3plus(root, &exp2);
1174 0 : shr(root,exp2);
1175 0 : tmp_result = powWord16rest(root, 3, 0);
1176 0 : exp_result = L_shr( exp_result * tmp_result,15);
1177 0 : BREAK;
1178 : }
1179 0 : }
1180 0 : return (Word16) exp_result;
1181 : }
|