Line data Source code
1 : /*====================================================================================
2 : EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0
3 : ====================================================================================*/
4 :
5 : #include <stdint.h>
6 : #include "options.h" /* Compilation switches */
7 : #include "cnst.h" /* Common constants */
8 : #include "prot_fx.h" /* Function prototypes */
9 : #include "rom_com.h"
10 : #include "ivas_rom_com.h"
11 :
12 :
13 : /*---------------------------------------------------------------------*
14 : * Local constants
15 : *---------------------------------------------------------------------*/
16 :
17 : #define A2 6554
18 : #define OmA2 ( 32768 - A2 )
19 : #define GAIN_VAR 11811 /* in Q31 divided by 2 (Q30) */
20 :
21 : const Word16 att_pow_tbl[SIZE_SCALE_TABLE_STEREO + 1] = { 9234, 10361, 13044, 16422, 22669, 31292, 32767, 26634, 28212, 20674, 16422, 27254, 30934, 32767 };
22 :
23 :
24 : /*-------------------------------------------------------*
25 : * CNG_exc()
26 : *
27 : * Comfort noise generation routine
28 : *-------------------------------------------------------*/
29 :
30 4859 : void CNG_exc_fx(
31 : const Word32 core_brate, /* i : core bitrate */
32 : const Word16 L_frame, /* i : length of the frame */
33 : Word32 *Enew, /* i/o: decoded SID energy Q6 */
34 : Word16 *seed, /* i/o: random generator seed */
35 : Word16 exc[], /* o : current non-enhanced excitation Q_new */
36 : Word16 exc2[], /* o : current enhanced excitation Q_new */
37 : Word32 *lp_ener, /* i/o: LP filtered E Q6 */
38 : const Word32 last_core_brate, /* i : previous frame core bitrate */
39 : Word16 *first_CNG, /* i/o: first CNG frame flag for energy init. */
40 : Word16 *cng_ener_seed, /* i/o: random generator seed for CNG energy */
41 : Word16 bwe_exc[], /* o : excitation for SWB TBE Q_syn */
42 : const Word16 allow_cn_step, /* i : allow CN step */
43 : Word16 *last_allow_cn_step, /* i/o: last allow step */
44 : const Word16 OldQ_exc, /* i : Old excitation scaling */
45 : const Word16 Q_exc, /* i : excitation scaling */
46 : const Word16 num_ho, /* i : number of selected hangover frames */
47 : Word32 q_env[], /*Q6*/
48 : Word32 *lp_env, /*Q6*/
49 : Word32 *old_env, /*Q6*/
50 : Word16 *exc_mem, /*Q0*/
51 : Word16 *exc_mem1, /*Q0*/
52 : Word16 *sid_bw,
53 : Word16 *cng_ener_seed1,
54 : Word16 exc3[], /*Q_exc*/
55 : Word16 Opt_AMR_WB,
56 : const Word16 element_mode /* i : IVAS Element mode */
57 : )
58 : {
59 : Word16 i, tmp, tmp2, exp, exp2, Q_ener;
60 : Word32 L_tmp_ener, L_tmp;
61 : Word16 i_subfr;
62 : Word16 pit_max;
63 : Word16 ftmp, j;
64 : Word16 *ptR, *ptI;
65 : Word16 fft_io[L_FRAME16k];
66 : Word32 itmp[129];
67 : Word32 env[NUM_ENV_CNG];
68 : Word32 enr1;
69 : Word32 denv[NUM_ENV_CNG];
70 : Word16 fra;
71 : Word16 temp_lo_fx, temp_hi_fx;
72 : Word16 exp_pow;
73 : Word32 L_tmp2;
74 : Word16 *pt_fft_io;
75 :
76 : /*------------------------------------------------------------------*
77 : * Initializations
78 : *------------------------------------------------------------------*/
79 :
80 4859 : pit_max = PIT16k_MAX;
81 4859 : move16();
82 4859 : if ( EQ_16( L_frame, L_FRAME ) )
83 : {
84 1793 : pit_max = PIT_MAX;
85 1793 : move16();
86 : }
87 :
88 : /*---------------------------------------------------------------------*
89 : * Initialization of CNG energy for the first CNG frame
90 : *---------------------------------------------------------------------*/
91 :
92 4859 : IF( *first_CNG == 0 )
93 : {
94 56 : IF( core_brate == FRAME_NO_DATA )
95 : {
96 : /* needed only in decoder when the very first SID frame was erased and this frame is FRAME_NO_DATA frame */
97 : /*fenew = dotp( fexc, fexc, pit_max )/pit_max;*/
98 0 : L_tmp_ener = Calc_Energy_Autoscaled( exc - pit_max, OldQ_exc, pit_max, &Q_ener );
99 0 : L_tmp_ener = Mult_32_16( L_tmp_ener, 9079 ); /* divide by PIT_MAX (in Q15 + Q6 to get output in Q6)*/
100 0 : L_tmp_ener = L_shr( L_tmp_ener, Q_ener ); /* -> If we want ener in Q6 */
101 :
102 0 : IF( EQ_16( L_frame, L_FRAME16k ) )
103 : {
104 0 : L_tmp_ener = Mult_32_16( L_tmp_ener, 26214 /*.8f in Q15*/ ); /* Compensate for 16kHz */
105 : }
106 0 : *Enew = L_tmp_ener;
107 0 : move32();
108 : }
109 :
110 56 : if ( element_mode == EVS_MONO )
111 : {
112 28 : *lp_ener = *Enew;
113 28 : move32();
114 : }
115 : }
116 :
117 : /*---------------------------------------------------------------------*
118 : * Update CNG energy
119 : *---------------------------------------------------------------------*/
120 4859 : test();
121 4859 : test();
122 4859 : IF( NE_32( last_core_brate, SID_1k75 ) && ( last_core_brate != FRAME_NO_DATA ) && NE_32( last_core_brate, SID_2k40 ) )
123 : {
124 : /* Partially reset CNG energy after active speech period */
125 418 : test();
126 418 : IF( allow_cn_step == 0 && *last_allow_cn_step == 0 )
127 : {
128 394 : test();
129 394 : IF( LT_16( num_ho, 3 ) || LT_32( Mult_32_16( *Enew, 21845 /*1/1.5f, Q15*/ ), *lp_ener ) )
130 : {
131 : /**lp_ener = 0.8f * *lp_ener + 0.2f * *Enew;*/
132 387 : L_tmp_ener = Mult_32_16( *lp_ener, 26214 /*.8f in Q15*/ );
133 387 : L_tmp_ener = Madd_32_16( L_tmp_ener, *Enew, 6554 /*.2f in Q15*/ );
134 : }
135 : ELSE
136 : {
137 : /**lp_ener = 0.95f * *lp_ener + 0.05f * *Enew;*/
138 7 : L_tmp_ener = Mult_32_16( *lp_ener, 31130 /*.95f in Q15*/ );
139 7 : L_tmp_ener = Madd_32_16( L_tmp_ener, *Enew, 1638 /* .05f in Q15*/ );
140 : }
141 : }
142 : ELSE
143 : {
144 24 : L_tmp_ener = *Enew;
145 24 : move32();
146 24 : *last_allow_cn_step = 0;
147 24 : move16();
148 : }
149 : }
150 : ELSE{
151 : /* normal CNG update */
152 4441 : IF( *last_allow_cn_step == 0 ){
153 : /**lp_ener = (float)(A2 * *Enew + (1-A2) * *lp_ener);*/
154 4326 : L_tmp_ener = Mult_32_16( *Enew, A2 );
155 4326 : L_tmp_ener = Madd_32_16( L_tmp_ener, *lp_ener, OmA2 );
156 : }
157 : ELSE
158 : {
159 115 : test();
160 115 : if ( EQ_32( core_brate, SID_1k75 ) || EQ_32( core_brate, SID_2k40 ) )
161 : {
162 0 : *last_allow_cn_step = 0;
163 0 : move16();
164 : }
165 :
166 115 : L_tmp_ener = *Enew;
167 115 : move32();
168 : }
169 : }
170 4859 : *lp_ener = L_max( L_tmp_ener, 1 );
171 4859 : move32(); /*To avoid / per 0*/
172 :
173 4859 : if ( EQ_16( allow_cn_step, 1 ) )
174 : {
175 24 : *last_allow_cn_step = 1;
176 24 : move16();
177 : }
178 : /* If not mono, skip CNG here */
179 4859 : IF( GT_16( element_mode, IVAS_SCE ) )
180 : {
181 1263 : return;
182 : }
183 : /*---------------------------------------------------------------------*
184 : * Generate white noise vector
185 : *---------------------------------------------------------------------*/
186 :
187 : /*for ( i=0; i<L_frame; i++ )exc2[i] = (float)own_random( seed );*/
188 3596 : Random_Fill( seed, L_frame, exc2, 4 );
189 : /*------------------------------------------------------------*
190 : * Insert random variation for excitation energy
191 : * (random variation is scaled according to *lp_ener value)
192 : *------------------------------------------------------------*/
193 :
194 20166 : FOR( i_subfr = 0; i_subfr < L_frame; i_subfr += L_SUBFR )
195 : {
196 : /* ener_lp = own_random(cng_ener_seed) * *lp_ener * GAIN_VAR + *lp_ener */
197 : /*------------------------------------------------------------*
198 : * Insert random variation for excitation energy
199 : * (random variation is scaled according to *lp_ener value)
200 : *------------------------------------------------------------*/
201 16570 : L_tmp = Mult_32_16( *lp_ener, Random( cng_ener_seed ) ); // Q6
202 16570 : L_tmp = Mult_32_16( L_tmp, GAIN_VAR ); // Q6
203 16570 : L_tmp = L_add_sat( L_tmp, *lp_ener );
204 16570 : L_tmp = L_max( L_tmp, 1 );
205 :
206 : /* enr = dot_product( exc2, exc2, L_SUBFR ) + 0.01f */
207 16570 : tmp = extract_h( Dot_product12( &exc2[i_subfr], &exc2[i_subfr], L_SUBFR, &exp ) );
208 16570 : exp = add( exp, 8 - 6 ); /* 8 from Q-4, -6 from L_SUBFR */
209 :
210 : /* enr = (float)sqrt(*lp_ener * L_SUBFR / enr) */
211 16570 : exp2 = norm_l( L_tmp );
212 16570 : tmp2 = extract_h( L_shl( L_tmp, exp2 ) );
213 16570 : exp2 = sub( 31 - 6, exp2 ); /* in Q15 (L_tmp in Q6)*/
214 :
215 16570 : exp = sub( exp, exp2 );
216 :
217 16570 : IF( GT_16( tmp, tmp2 ) )
218 : {
219 7071 : exp = add( exp, 1 );
220 : }
221 16570 : IF( GT_16( tmp, tmp2 ) )
222 : {
223 7071 : tmp = shr( tmp, 1 );
224 : }
225 16570 : tmp = div_s( tmp, tmp2 );
226 :
227 16570 : L_tmp = L_deposit_h( tmp );
228 :
229 16570 : L_tmp = Isqrt_lc( L_tmp, &exp );
230 16570 : tmp = extract_h( L_tmp );
231 :
232 16570 : exp = add( exp, 4 ); /* From Q15 to Q19 */
233 16570 : exp = add( exp, Q_exc ); /* Q_exc+ Q19 */
234 :
235 1077050 : FOR( i = 0; i < L_SUBFR; i++ )
236 : {
237 : /* exc2[i] *= enr */
238 1060480 : L_tmp = L_mult( exc2[i_subfr + i], tmp ); /* Q-4 * Q_exc+19 -> Q_exc +16 */
239 1060480 : exc2[i_subfr + i] = round_fx_sat( L_shl_sat( L_tmp, exp ) );
240 1060480 : move16();
241 : }
242 : }
243 3596 : IF( NE_16( Opt_AMR_WB, 1 ) )
244 : {
245 3596 : Copy( exc2, exc3, L_FRAME16k );
246 :
247 : /* enr1 = (float)log10( *Enew*L_frame + 0.1f ) / (float)log10( 2.0f ); */
248 3596 : exp = norm_l( *Enew );
249 3596 : L_tmp = L_shl( *Enew, exp ); /* Q(exp+6) */
250 3596 : L_tmp = Mult_32_16( L_tmp, shl( L_frame, 5 ) ); /* Q(exp+6+5-15=exp-4) */
251 3596 : L_tmp = L_shr_sat( L_tmp, sub( exp, 10 ) ); /* Q6 */
252 3596 : exp = norm_l( L_tmp );
253 3596 : fra = Log2_norm_lc( L_shl( L_tmp, exp ) );
254 3596 : exp = sub( sub( 30, exp ), 6 );
255 3596 : L_tmp = L_Comp( exp, fra );
256 : /* enr1 = round_fx(L_shl(L_tmp,8)); */ /*Q8 */
257 3596 : enr1 = L_shr( L_tmp, 10 ); /* Q6 */
258 :
259 :
260 3596 : IF( EQ_32( core_brate, SID_2k40 ) )
261 : {
262 655 : IF( *sid_bw == 0 )
263 : {
264 0 : FOR( i = 0; i < NUM_ENV_CNG; i++ )
265 : {
266 : /* get quantized envelope */
267 : /* env[i] = pow(2.0f,(enr1 - q_env[i])); */
268 0 : L_tmp = L_sub( enr1, q_env[i] ); /* Q6 */
269 0 : L_tmp = L_shl( L_tmp, 10 ); /* 16 */
270 0 : temp_lo_fx = L_Extract_lc( L_tmp, &temp_hi_fx );
271 :
272 0 : exp_pow = sub( 14, temp_hi_fx );
273 0 : L_tmp = Pow2( 14, temp_lo_fx ); /* Qexp_pow */
274 0 : env[i] = L_shl( L_tmp, sub( 6, exp_pow ) );
275 0 : move32(); /* Q6 */
276 : }
277 : }
278 :
279 : /* initialize CNG envelope */
280 655 : test();
281 655 : IF( *first_CNG == 0 && *sid_bw == 0 )
282 : {
283 0 : Copy32( env, lp_env, NUM_ENV_CNG );
284 : }
285 :
286 655 : IF( *sid_bw == 0 )
287 : {
288 0 : Copy32( env, old_env, NUM_ENV_CNG );
289 : }
290 : }
291 :
292 75516 : FOR( i = 0; i < NUM_ENV_CNG; i++ )
293 : {
294 : /* get AR low-passed envelope */
295 : /* lp_env[i] = 0.9f*lp_env[i] + (1-0.9f)*old_env[i]; */
296 71920 : L_tmp = Mult_32_16( lp_env[i], 29491 /*.9f in Q15*/ );
297 71920 : lp_env[i] = L_add( L_tmp, Mult_32_16( old_env[i], 3277 /*.1f in Q15*/ ) );
298 71920 : move32(); /* Q6 */
299 : }
300 :
301 : /* calculate the spectrum of random excitation signal */
302 3596 : Copy( exc2, fft_io, L_frame );
303 :
304 3596 : IF( EQ_16( L_frame, L_FRAME16k ) )
305 : {
306 2186 : modify_Fs_fx( fft_io, L_FRAME16k, 16000, fft_io, 12800, exc_mem1, 0 );
307 : }
308 :
309 : /* fft_rel(fft_io, L_FFT, LOG2_L_FFT); */
310 3596 : fft_rel_fx( fft_io, L_FFT, LOG2_L_FFT ); /* ??????? */
311 3596 : ptR = &fft_io[1];
312 3596 : ptI = &fft_io[L_FFT - 1];
313 75516 : FOR( i = 0; i < NUM_ENV_CNG; i++ )
314 : {
315 : /* env[i] = 2.0f*(*ptR * *ptR + *ptI * *ptI)/L_FFT; */
316 71920 : L_tmp = L_mult0( *ptR, *ptR ); /* 2*Q_exc */
317 71920 : L_tmp = L_mac0_sat( L_tmp, *ptI, *ptI ); /* 2*Q_exc */
318 71920 : L_tmp = L_shr( L_tmp, 1 ); /* 2*Q_exc+6 */
319 71920 : tmp = add( Q_exc, Q_exc );
320 71920 : env[i] = L_shr_sat( L_tmp, tmp );
321 71920 : move32(); /* Q6 */
322 71920 : ptR++;
323 71920 : ptI--;
324 : }
325 :
326 75516 : FOR( i = 0; i < NUM_ENV_CNG; i++ )
327 : {
328 : /* denv[i] = lp_env[i] + 2*(*lp_ener) - env[i]; */
329 71920 : L_tmp = L_add_sat( *lp_ener, *lp_ener );
330 71920 : denv[i] = L_sub_sat( L_add_sat( lp_env[i], L_tmp ), env[i] );
331 71920 : move32(); /* Q6 */
332 :
333 71920 : if ( denv[i] < 0 )
334 : {
335 11477 : denv[i] = 0;
336 11477 : move32();
337 : }
338 : }
339 3596 : set32_fx( itmp, 0, NUM_ENV_CNG );
340 :
341 3596 : set16_fx( fft_io, 0, L_FFT );
342 3596 : ptR = &fft_io[1];
343 3596 : ptI = &fft_io[L_FFT - 1];
344 75516 : FOR( i = 0; i < NUM_ENV_CNG; i++ )
345 : {
346 : /* *ptR = own_random( cng_ener_seed1 ); */
347 : /* *ptI = own_random( cng_ener_seed1 ); */
348 71920 : *ptR = Random( cng_ener_seed1 );
349 71920 : move16();
350 71920 : *ptI = Random( cng_ener_seed1 );
351 71920 : move16();
352 :
353 : /* env[i] = 2.0f*(*ptR * *ptR + *ptI * *ptI)/L_FFT; */
354 71920 : L_tmp = L_mult0( *ptR, *ptR ); /* Q0 */
355 71920 : L_tmp = L_mac0( L_tmp, *ptI, *ptI ); /* Q0 */
356 71920 : env[i] = L_shr( L_tmp, 1 );
357 71920 : move32(); /* Q6 */
358 71920 : ptR++;
359 71920 : ptI--;
360 : }
361 :
362 75516 : FOR( i = 0; i < NUM_ENV_CNG; i++ )
363 : {
364 : /* itmp[i] += own_random( cng_ener_seed1 )*denv[i]*0.000011f + denv[i]; */
365 71920 : L_tmp = Mult_32_16( denv[i], Random( cng_ener_seed1 ) ); // Q6
366 71920 : L_tmp = Mult_32_16( L_tmp, GAIN_VAR ); // Q6
367 71920 : L_tmp = L_add_sat( L_tmp, denv[i] );
368 71920 : itmp[i] = L_add_sat( L_tmp, itmp[i] );
369 71920 : move32(); /* Q6 */
370 :
371 71920 : if ( itmp[i] < 0 )
372 : {
373 0 : itmp[i] = 0;
374 0 : move32();
375 : }
376 : }
377 3596 : ptR = &fft_io[1];
378 3596 : ptI = &fft_io[L_FFT - 1];
379 75516 : FOR( i = 0; i < NUM_ENV_CNG; i++ )
380 : {
381 : /* *ptR *= sqrt(itmp[i]/env[i]); */
382 : /* *ptI *= sqrt(itmp[i]/env[i]); */
383 71920 : L_tmp = L_max( 1, itmp[i] ); /*Q6*/
384 71920 : exp = norm_l( L_tmp );
385 71920 : tmp = extract_h( L_shl( L_tmp, exp ) );
386 71920 : exp = sub( 31 - 6, exp ); /* in Q15 (L_tmp in Q6)*/
387 :
388 71920 : exp2 = norm_l( env[i] );
389 71920 : tmp2 = extract_h( L_shl( env[i], exp2 ) );
390 71920 : exp2 = sub( 31 - 6, exp2 ); /* in Q15 (L_tmp in Q6)*/
391 :
392 71920 : exp = sub( exp2, exp ); /* Denormalize and substract */
393 71920 : IF( GT_16( tmp2, tmp ) )
394 : {
395 43435 : exp = add( exp, 1 );
396 : }
397 71920 : IF( GT_16( tmp2, tmp ) )
398 : {
399 43435 : tmp2 = shr( tmp2, 1 );
400 : }
401 71920 : tmp = div_s( tmp2, tmp );
402 71920 : L_tmp = L_deposit_h( tmp );
403 71920 : L_tmp = Isqrt_lc( L_tmp, &exp ); /*Q(31-exp)*/
404 :
405 71920 : L_tmp2 = Mult_32_16( L_tmp, *ptR ); /*Q(16-exp)*/
406 71920 : *ptR = extract_h( L_shl_sat( L_tmp2, add( exp, Q_exc ) ) ); /*Q_exc*/
407 71920 : move16();
408 71920 : L_tmp2 = Mult_32_16( L_tmp, *ptI ); /*Q(16-exp)*/
409 71920 : *ptI = extract_h( L_shl_sat( L_tmp2, add( exp, Q_exc ) ) ); /*Q_exc*/
410 71920 : move16();
411 71920 : ptR++;
412 71920 : ptI--;
413 : }
414 :
415 3596 : ifft_rel_fx( fft_io, L_FFT, LOG2_L_FFT );
416 :
417 3596 : IF( EQ_16( L_frame, L_FRAME16k ) )
418 : {
419 2186 : modify_Fs_fx( fft_io, L_FFT, 12800, fft_io, 16000, exc_mem, 0 );
420 : }
421 :
422 : /* enr1 = dotp( fft_io, fft_io, L_frame ) / L_frame; */
423 :
424 3596 : enr1 = 1;
425 3596 : move32();
426 3596 : pt_fft_io = fft_io;
427 3596 : IF( EQ_16( L_frame, L_FRAME ) )
428 : {
429 181890 : FOR( j = 0; j < 128; j++ )
430 : {
431 180480 : L_tmp = L_mult0( *pt_fft_io, *pt_fft_io );
432 180480 : pt_fft_io++;
433 180480 : L_tmp = L_mac0( L_tmp, *pt_fft_io, *pt_fft_io ); /* 2*(Q_exc) */
434 180480 : pt_fft_io++;
435 180480 : enr1 = L_add( enr1, L_shr( L_tmp, 7 ) ); /* 2*(Q_exc)+1, divide by L_frame done here */
436 : }
437 : }
438 : ELSE /* L_FRAME16k */
439 : {
440 351946 : FOR( j = 0; j < 160; j++ )
441 : {
442 349760 : L_tmp = L_mult0( *pt_fft_io, *pt_fft_io );
443 349760 : pt_fft_io++;
444 349760 : L_tmp = L_mac0( L_tmp, *pt_fft_io, *pt_fft_io ); /* 2*(Q_exc) */
445 349760 : pt_fft_io++;
446 349760 : enr1 = L_add( enr1, L_shr( Mult_32_16( L_tmp, 26214 /* 256/320, Q15 */ ), 7 ) ); /* 2*(Q_exc)+15+1-16+1, divide by L_frame done here */
447 : }
448 : }
449 3596 : enr1 = L_shr( enr1, sub( add( Q_exc, Q_exc ), 5 ) ); /*Q6*/
450 :
451 : /* add time domain randomization */
452 20166 : FOR( i_subfr = 0; i_subfr < L_frame; i_subfr += L_SUBFR )
453 : {
454 :
455 16570 : L_tmp = Mult_32_16( enr1, Random( cng_ener_seed1 ) );
456 16570 : L_tmp = Mult_32_16( L_tmp, GAIN_VAR );
457 16570 : L_tmp = L_add( L_tmp, enr1 );
458 16570 : L_tmp = L_max( L_tmp, 1 );
459 :
460 : /* enr = dot_product( fft_io, fft_io, L_SUBFR ) + 0.01f */
461 16570 : tmp = extract_h( Dot_product12( &fft_io[i_subfr], &fft_io[i_subfr], L_SUBFR, &exp ) );
462 16570 : exp = add( exp, sub( -6, add( Q_exc, Q_exc ) ) ); /* -2*Q_exc from fft_io, -6 from L_SUBFR */
463 :
464 : /* enr = (float)sqrt( ener_lp*L_SUBFR / enr ) */
465 16570 : exp2 = norm_l( L_tmp );
466 16570 : tmp2 = extract_h( L_shl( L_tmp, exp2 ) );
467 16570 : exp2 = sub( 31 - 6, exp2 ); /* in Q15 (L_tmp in Q6)*/
468 :
469 16570 : exp = sub( exp, exp2 );
470 :
471 16570 : IF( GT_16( tmp, tmp2 ) )
472 : {
473 8933 : exp = add( exp, 1 );
474 : }
475 16570 : IF( GT_16( tmp, tmp2 ) )
476 : {
477 8933 : tmp = shr( tmp, 1 );
478 : }
479 16570 : tmp = div_s( tmp, tmp2 );
480 :
481 16570 : L_tmp = L_deposit_h( tmp );
482 16570 : L_tmp = Isqrt_lc( L_tmp, &exp ); /*Q(31-exp)*/
483 16570 : test();
484 16570 : test();
485 16570 : test();
486 16570 : IF( NE_32( last_core_brate, SID_2k40 ) && NE_32( last_core_brate, SID_1k75 ) && ( last_core_brate != FRAME_NO_DATA ) && EQ_32( core_brate, SID_2k40 ) )
487 : {
488 1456 : IF( GT_32( L_tmp, L_shl_sat( 1, sub( 31, exp ) ) ) )
489 : {
490 783 : L_tmp = L_shl( 1, sub( 31, exp ) );
491 : }
492 : }
493 :
494 16570 : tmp = extract_h( L_tmp );
495 1077050 : FOR( i = 0; i < L_SUBFR; i++ )
496 : {
497 : /* fft_io[i] *= enr */
498 1060480 : L_tmp = L_mult( fft_io[i_subfr + i], tmp ); /* Q_exc + 16 - exp */
499 1060480 : fft_io[i_subfr + i] = round_fx( L_shl( L_tmp, exp ) ); /*Q_exc*/
500 1060480 : move16();
501 : }
502 : }
503 :
504 1064076 : FOR( i = 0; i < L_frame; i++ )
505 : {
506 : /* fft_io[i] = 0.75f*fft_io[i] + exc2[i];*/
507 1060480 : tmp = mult( fft_io[i], 24576 /*.75f in Q15*/ );
508 1060480 : fft_io[i] = add_sat( tmp, exc2[i] );
509 1060480 : move16(); /*Q_exc*/
510 : }
511 :
512 : /* enr = (dotp( fft_io, fft_io, L_frame ) / L_frame) + 0.01f */
513 :
514 3596 : L_tmp2 = 1;
515 3596 : move32();
516 3596 : pt_fft_io = fft_io;
517 3596 : IF( EQ_16( L_frame, L_FRAME ) )
518 : {
519 181890 : FOR( j = 0; j < 128; j++ )
520 : {
521 180480 : L_tmp = L_mult0( *pt_fft_io, *pt_fft_io );
522 180480 : pt_fft_io++;
523 180480 : L_tmp = L_mac0_sat( L_tmp, *pt_fft_io, *pt_fft_io ); /* 2*(Q_exc) */
524 180480 : pt_fft_io++;
525 180480 : L_tmp2 = L_add_sat( L_tmp2, L_shr( L_tmp, 7 ) ); /* 2*(Q_exc)+1, divide by L_frame done here */
526 : }
527 : }
528 : ELSE /* L_FRAME16k */
529 : {
530 351946 : FOR( j = 0; j < 160; j++ )
531 : {
532 349760 : L_tmp = L_mult0( *pt_fft_io, *pt_fft_io );
533 349760 : pt_fft_io++;
534 349760 : L_tmp = L_mac0_sat( L_tmp, *pt_fft_io, *pt_fft_io ); /* 2*(Q_exc) */
535 349760 : pt_fft_io++;
536 349760 : L_tmp2 = L_add( L_tmp2, L_shr( Mult_32_16( L_tmp, 26214 /* 256/320, Q15 */ ), 7 ) ); /* 2*(Q_exc)+15+1-16+1, divide by L_frame done here */
537 : }
538 : }
539 3596 : L_tmp2 = L_shr( L_tmp2, sub( add( Q_exc, Q_exc ), 5 ) ); /*Q6*/
540 :
541 :
542 : /* enr = (*lp_ener)/enr; */
543 : /* ftmp = sqrt(enr); */
544 3596 : L_tmp = L_max( 1, *lp_ener ); /*Q6*/
545 3596 : exp = norm_l( L_tmp );
546 3596 : tmp = extract_h( L_shl( L_tmp, exp ) );
547 3596 : exp = sub( 31 - 6, exp ); /* in Q15 (L_tmp in Q6)*/
548 :
549 3596 : exp2 = norm_l( L_tmp2 );
550 3596 : tmp2 = extract_h( L_shl( L_tmp2, exp2 ) );
551 3596 : exp2 = sub( 31 - 6, exp2 ); /* in Q15 (L_tmp in Q6)*/
552 :
553 3596 : exp = sub( exp2, exp ); /* Denormalize and substract */
554 3596 : IF( GT_16( tmp2, tmp ) )
555 : {
556 1892 : exp = add( exp, 1 );
557 : }
558 3596 : IF( GT_16( tmp2, tmp ) )
559 : {
560 1892 : tmp2 = shr( tmp2, 1 );
561 : }
562 3596 : tmp = div_s( tmp2, tmp );
563 3596 : L_tmp = L_deposit_h( tmp );
564 3596 : L_tmp = Isqrt_lc( L_tmp, &exp ); /*Q(31-exp)*/
565 :
566 3596 : ftmp = extract_h( L_shl_sat( L_tmp, exp ) ); /* Q15 */
567 1064076 : FOR( i = 0; i < L_frame; i++ )
568 : {
569 : /* fft_io[i] *= ftmp;*/
570 1060480 : fft_io[i] = mult( fft_io[i], ftmp );
571 1060480 : move16(); /* Q_exc */
572 : }
573 3596 : Copy( fft_io, exc2, L_frame );
574 : }
575 3596 : IF( NE_16( Opt_AMR_WB, 1 ) )
576 : {
577 3596 : Copy( exc3, exc, L_frame );
578 : }
579 : ELSE
580 : {
581 0 : Copy( exc2, exc, L_frame );
582 : }
583 :
584 3596 : IF( EQ_16( L_frame, L_FRAME ) )
585 : {
586 1410 : interp_code_5over2_fx( exc2, bwe_exc, L_FRAME );
587 : }
588 : ELSE
589 : {
590 2186 : interp_code_4over2_fx( exc2, bwe_exc, L_frame );
591 : }
592 3596 : return;
593 : }
594 :
595 : /*-------------------------------------------------------*
596 : * cng_params_postupd_fx
597 : *
598 : * Post-update of CNG parameters
599 : *-------------------------------------------------------*/
600 0 : void cng_params_postupd_fx(
601 : const Word16 ho_circ_ptr, /* i : pointer for CNG averaging buffers Q0 */
602 : Word16 *cng_buf_cnt, /* i/o: counter for CNG store buffers Q0 */
603 : const Word16 *const cng_exc2_buf, /* i : Excitation buffer Q_exc */
604 : const Word16 *const cng_Qexc_buf, /* i : Q_exc buffer Q0 */
605 : const Word32 *const cng_brate_buf, /* i : bit rate buffer Q0 */
606 : Word32 ho_env_circ[] /* i/o: Envelope buffer Q6 */
607 : )
608 : {
609 : Word16 i, j;
610 : Word16 Q_exc;
611 : const Word16 *exc2;
612 : Word16 fft_io[L_FFT];
613 : Word32 sp[129];
614 : Word16 *ptR, *ptI;
615 : Word32 env[NUM_ENV_CNG];
616 : Word32 L_tmp;
617 : Word16 tmp;
618 : Word16 temp_lo_fx, temp_hi_fx;
619 : Word16 exp_pow;
620 : Word16 exp1;
621 : Word16 CNG_mode;
622 : Word16 ptr;
623 : Word32 last_active_brate;
624 : #ifndef ISSUE_1836_replace_overflow_libcom
625 : #ifdef BASOP_NOGLOB_DECLARE_LOCAL
626 : Flag Overflow = 0;
627 : move32();
628 : #endif
629 : #endif
630 :
631 0 : ptr = add( sub( ho_circ_ptr, *cng_buf_cnt ), 1 );
632 0 : IF( ptr < 0 )
633 : {
634 0 : ptr = add( ptr, HO_HIST_SIZE );
635 : }
636 :
637 0 : FOR( j = 0; j < *cng_buf_cnt; j++ )
638 : {
639 0 : exc2 = &cng_exc2_buf[ptr * L_FFT];
640 0 : Q_exc = cng_Qexc_buf[ptr];
641 0 : move16();
642 0 : last_active_brate = cng_brate_buf[ptr];
643 0 : move32();
644 :
645 : /* calculate the spectrum of residual signal */
646 0 : Copy( exc2, fft_io, L_FFT );
647 :
648 0 : fft_rel_fx( fft_io, L_FFT, LOG2_L_FFT );
649 :
650 0 : ptR = &fft_io[1];
651 0 : ptI = &fft_io[L_FFT - 1];
652 0 : FOR( i = 0; i < NUM_ENV_CNG; i++ )
653 : {
654 : /* sp[i] = 2.0f*(*ptR * *ptR + *ptI * *ptI)/L_FFT; */
655 : #ifdef ISSUE_1836_replace_overflow_libcom
656 0 : L_tmp = L_mult_sat( *ptR, *ptR ); /* 2*Q_exc+1 */
657 0 : L_tmp = L_add_sat( L_tmp, L_mult_sat( *ptI, *ptI ) ); /* 2*Q_exc+1 */
658 0 : L_tmp = L_add_sat( L_tmp, L_tmp ); /* 2*Q_exc+1 */
659 : #else
660 : L_tmp = L_mult_o( *ptR, *ptR, &Overflow ); /* 2*Q_exc+1 */
661 : L_tmp = L_add_o( L_tmp, L_mult_o( *ptI, *ptI, &Overflow ), &Overflow ); /* 2*Q_exc+1 */
662 : L_tmp = L_add_o( L_tmp, L_tmp, &Overflow ); /* 2*Q_exc+1 */
663 : #endif
664 0 : L_tmp = Mult_32_16( L_tmp, 128 ); /* 2*Q_exc+1 */
665 0 : tmp = add( add( Q_exc, Q_exc ), 1 );
666 0 : sp[i] = L_shr( L_tmp, sub( tmp, 6 ) );
667 0 : move32(); /* Q6 */
668 :
669 0 : ptR++;
670 0 : ptI--;
671 : }
672 :
673 0 : Copy32( sp, env, NUM_ENV_CNG );
674 : {
675 :
676 0 : CNG_mode = get_cng_mode( last_active_brate );
677 :
678 : /* att = 1/pow(2,ENR_ATT_fx[CNG_mode]); */
679 0 : L_tmp = L_shl( L_deposit_l( ENR_ATT_fx[CNG_mode] ), 8 ); /* 16 */
680 0 : temp_lo_fx = L_Extract_lc( L_tmp, &temp_hi_fx );
681 :
682 0 : exp_pow = sub( 14, temp_hi_fx );
683 0 : L_tmp = Pow2( 14, temp_lo_fx ); /* Qexp_pow */
684 0 : L_tmp = L_shl( L_tmp, sub( 13, exp_pow ) ); /* Q13 */
685 0 : tmp = extract_l( L_tmp ); /* Q13 */
686 :
687 0 : exp1 = norm_s( tmp );
688 0 : tmp = shl( tmp, exp1 ); /*Q(exp1+13) */
689 0 : tmp = div_s( 16384, tmp ); /*Q(15+14-exp1-13) */
690 0 : tmp = shr( tmp, sub( 1, exp1 ) ); /* Q15 */
691 : }
692 :
693 0 : FOR( i = 0; i < NUM_ENV_CNG; i++ )
694 : {
695 0 : env[i] = Mult_32_16( env[i], tmp );
696 0 : move32();
697 : }
698 :
699 : /* update the circular buffer of old residual envelope */
700 0 : Copy32( env, &( ho_env_circ[(ptr) *NUM_ENV_CNG] ), NUM_ENV_CNG );
701 :
702 0 : ptr = add( ptr, 1 );
703 0 : if ( EQ_16( ptr, HO_HIST_SIZE ) )
704 : {
705 0 : ptr = 0;
706 0 : move16();
707 : }
708 : }
709 :
710 0 : *cng_buf_cnt = 0;
711 0 : move16();
712 :
713 0 : return;
714 : }
715 :
716 2438 : void cng_params_postupd_ivas_fx(
717 : const Word16 ho_circ_ptr, /* i : pointer for CNG averaging buffers Q0 */
718 : Word16 *cng_buf_cnt, /* i/o: counter for CNG store buffers Q0 */
719 : const Word16 *const cng_exc2_buf, /* i : Excitation buffer Q_exc */
720 : const Word16 *const cng_Qexc_buf, /* i : Q_exc buffer Q0 */
721 : const Word32 *const cng_brate_buf, /* i : bit rate buffer Q0 */
722 : Word32 ho_env_circ[], /* i/o: Envelope buffer Q6 */
723 : const Word16 element_mode, /* i : Element mode */
724 : const Word16 bwidth /* i : Audio bandwidth */
725 : )
726 : {
727 : Word16 i, j;
728 : Word16 Q_exc;
729 : const Word16 *exc2;
730 : Word16 fft_io[L_FFT];
731 : Word32 sp[129];
732 : Word16 *ptR, *ptI;
733 : Word32 env[NUM_ENV_CNG];
734 : Word32 L_tmp;
735 : Word16 tmp;
736 : Word16 temp_lo_fx, temp_hi_fx;
737 : Word16 exp_pow;
738 : Word16 exp1;
739 : Word16 CNG_mode;
740 : Word16 ptr;
741 : Word32 last_active_brate;
742 : #ifndef ISSUE_1836_replace_overflow_libcom
743 : #ifdef BASOP_NOGLOB_DECLARE_LOCAL
744 : Flag Overflow = 0;
745 : move32();
746 : #endif
747 : #endif
748 :
749 2438 : ptr = add( sub( ho_circ_ptr, *cng_buf_cnt ), 1 );
750 2438 : IF( ptr < 0 )
751 : {
752 87 : ptr = add( ptr, HO_HIST_SIZE );
753 : }
754 :
755 3258 : FOR( j = 0; j < *cng_buf_cnt; j++ )
756 : {
757 820 : exc2 = &cng_exc2_buf[ptr * L_FFT];
758 820 : Q_exc = cng_Qexc_buf[ptr];
759 820 : move16();
760 820 : last_active_brate = cng_brate_buf[ptr];
761 820 : move32();
762 :
763 : /* calculate the spectrum of residual signal */
764 820 : Copy( exc2, fft_io, L_FFT );
765 :
766 820 : fft_rel_fx( fft_io, L_FFT, LOG2_L_FFT );
767 :
768 820 : ptR = &fft_io[1];
769 820 : ptI = &fft_io[L_FFT - 1];
770 17220 : FOR( i = 0; i < NUM_ENV_CNG; i++ )
771 : {
772 : /* sp[i] = 2.0f*(*ptR * *ptR + *ptI * *ptI)/L_FFT; */
773 : #ifdef ISSUE_1836_replace_overflow_libcom
774 16400 : L_tmp = L_mult_sat( *ptR, *ptR ); /* 2*Q_exc+1 */
775 16400 : L_tmp = L_add_sat( L_tmp, L_mult_sat( *ptI, *ptI ) ); /* 2*Q_exc+1 */
776 16400 : L_tmp = L_add_sat( L_tmp, L_tmp ); /* 2*Q_exc+1 */
777 : #else
778 : L_tmp = L_mult_o( *ptR, *ptR, &Overflow ); /* 2*Q_exc+1 */
779 : L_tmp = L_add_o( L_tmp, L_mult_o( *ptI, *ptI, &Overflow ), &Overflow ); /* 2*Q_exc+1 */
780 : L_tmp = L_add_o( L_tmp, L_tmp, &Overflow ); /* 2*Q_exc+1 */
781 : #endif
782 16400 : L_tmp = Mult_32_16( L_tmp, 128 ); /* 2*Q_exc+1 */
783 16400 : tmp = add( add( Q_exc, Q_exc ), 1 );
784 : // To do : Saturation to be re-validated.
785 16400 : sp[i] = L_shr_sat( L_tmp, sub( tmp, 6 ) );
786 16400 : move32(); /* Q6 */
787 :
788 16400 : ptR++;
789 16400 : ptI--;
790 : }
791 :
792 820 : Copy32( sp, env, NUM_ENV_CNG );
793 :
794 820 : test();
795 820 : IF( EQ_16( element_mode, IVAS_SCE ) || EQ_16( element_mode, IVAS_CPE_DFT ) )
796 820 : {
797 820 : Word32 att_fx = 0;
798 820 : move32();
799 820 : tmp = 0;
800 820 : move16();
801 820 : apply_scale( &att_fx, bwidth, last_active_brate, scaleTableStereo, SIZE_SCALE_TABLE_STEREO );
802 820 : att_fx = L_shr( Mpy_32_16_1( att_fx, 26214 ), 3 ); /* 26214 = 0.1f in Q18 */
803 820 : att_fx = BASOP_Util_fPow( 1342177280 /* 10 in Q27 */, 4, att_fx, 8, &tmp );
804 820 : tmp = extract_h( L_shl_sat( att_fx, tmp ) ); // Fix for 3gpp #1080 (tmp set to 1.0)
805 : }
806 : ELSE
807 : {
808 :
809 0 : CNG_mode = get_cng_mode( last_active_brate );
810 :
811 : /* att = 1/pow(2,ENR_ATT_fx[CNG_mode]); */
812 0 : L_tmp = L_shl( L_deposit_l( ENR_ATT_fx[CNG_mode] ), 8 ); /* 16 */
813 0 : temp_lo_fx = L_Extract_lc( L_tmp, &temp_hi_fx );
814 :
815 0 : exp_pow = sub( 14, temp_hi_fx );
816 0 : L_tmp = Pow2( 14, temp_lo_fx ); /* Qexp_pow */
817 0 : L_tmp = L_shl( L_tmp, sub( 13, exp_pow ) ); /* Q13 */
818 0 : tmp = extract_l( L_tmp ); /* Q13 */
819 :
820 0 : exp1 = norm_s( tmp );
821 0 : tmp = shl( tmp, exp1 ); /*Q(exp1+13) */
822 0 : tmp = div_s( 16384, tmp ); /*Q(15+14-exp1-13) */
823 0 : tmp = shr( tmp, sub( 1, exp1 ) ); /* Q15 */
824 : }
825 :
826 17220 : FOR( i = 0; i < NUM_ENV_CNG; i++ )
827 : {
828 16400 : env[i] = Mult_32_16( env[i], tmp );
829 16400 : move32();
830 : }
831 :
832 : /* update the circular buffer of old residual envelope */
833 820 : Copy32( env, &( ho_env_circ[(ptr) *NUM_ENV_CNG] ), NUM_ENV_CNG );
834 :
835 820 : ptr = add( ptr, 1 );
836 820 : if ( EQ_16( ptr, HO_HIST_SIZE ) )
837 : {
838 108 : ptr = 0;
839 108 : move16();
840 : }
841 : }
842 :
843 2438 : *cng_buf_cnt = 0;
844 2438 : move16();
845 :
846 2438 : return;
847 : }
848 :
849 :
850 : /*-------------------------------------------------------*
851 : * cng_params_upd_fx()
852 : *
853 : * update CNG parameters
854 : *-------------------------------------------------------*/
855 2669 : void cng_params_upd_fx(
856 : const Word16 lsp_new[], /* i : LSP aprameters Q15 */
857 : const Word16 exc2[], /* i : current enhanced excitation Q_exc */
858 : const Word16 L_frame, /* i : frame length Q0 */
859 : Word16 *ho_circ_ptr, /* i/o: pointer for CNG averaging buffers Q0 */
860 : Word32 ho_ener_circ[], /* o : energy buffer for CNG averaging Q6 */
861 : Word16 *ho_circ_size, /* i/o: size of DTX hangover history buffer for averaging Q0 */
862 : Word16 ho_lsp_circ[], /* o : old LSP buffer for CNG averaging Q15 */
863 : const Word16 Q_exc, /* i : Q value of excitation */
864 : const Word16 enc_dec_flag, /* i : Flag indicating encoder or decoder (ENC,DEC) */
865 : Word32 ho_env_circ[], /* i/o: Envelope buffer Q6 */
866 : Word16 *cng_buf_cnt, /* i/o: Counter of postponed FFT-processing instances */
867 : Word16 cng_exc2_buf[], /* i/o: Excitation buffer Q_exc */
868 : Word16 cng_Qexc_buf[], /* i/o: Q_exc buffer Q0 */
869 : Word32 cng_brate_buf[], /* i/o: last_active_brate buffer Q0 */
870 : const Word32 last_active_brate /* i : Last active bit rate Q0 */
871 : )
872 : {
873 : Word32 L_ener, L_tmp;
874 : Word16 i, j;
875 : const Word16 *pt_exc2;
876 : Word16 tmpv, maxv, scale;
877 : Word16 fft_io[L_FRAME16k];
878 : Word32 sp[129];
879 : Word16 *ptR, *ptI;
880 : Word32 env[NUM_ENV_CNG];
881 : Word16 exp1;
882 : Word16 CNG_mode;
883 : Word16 tmp;
884 : Word16 temp_lo_fx, temp_hi_fx;
885 : Word16 exp_pow;
886 : #ifndef ISSUE_1836_replace_overflow_libcom
887 : #ifdef BASOP_NOGLOB_DECLARE_LOCAL
888 : Flag Overflow = 0;
889 : move32();
890 : #endif
891 : #endif
892 :
893 :
894 : /* update the pointer to circular buffer of old LSP vectors */
895 2669 : *ho_circ_ptr = add( *ho_circ_ptr, 1 );
896 2669 : move16();
897 :
898 2669 : if ( EQ_16( *ho_circ_ptr, HO_HIST_SIZE ) )
899 : {
900 332 : *ho_circ_ptr = 0;
901 332 : move16();
902 : }
903 :
904 : /* update the circular buffer of old LSP vectors with the new LSP vector */
905 2669 : Copy( lsp_new, &( ho_lsp_circ[( *ho_circ_ptr ) * M] ), M );
906 :
907 : /* calculate the residual signal energy */
908 : /*enr = dotp( exc2, exc2, L_frame ) / L_frame; */
909 :
910 2669 : maxv = 0;
911 2669 : move16();
912 792045 : FOR( i = 0; i < L_frame; i++ )
913 : {
914 789376 : maxv = s_max( maxv, abs_s( exc2[i] ) );
915 : }
916 2669 : scale = norm_s( maxv );
917 :
918 2669 : pt_exc2 = exc2;
919 2669 : L_ener = 0;
920 2669 : move32();
921 2669 : IF( EQ_16( L_frame, L_FRAME ) )
922 : {
923 130419 : FOR( j = 0; j < 128; j++ )
924 : {
925 129408 : tmpv = shl( *pt_exc2, scale );
926 129408 : L_tmp = L_mult0( tmpv, tmpv ); /* 2*(Q_exc+scale) */
927 129408 : pt_exc2++;
928 129408 : tmpv = shl( *pt_exc2, scale );
929 : #ifdef ISSUE_1836_replace_overflow_libcom
930 129408 : L_tmp = L_mac0_sat( L_tmp, tmpv, tmpv );
931 129408 : pt_exc2++;
932 129408 : L_ener = L_add_sat( L_ener, L_shr_sat( L_tmp, 7 ) ); /* Q(2*(Q_exc+scale)+1) ,division by L_frame done here */
933 : #else
934 : L_tmp = L_mac0_o( L_tmp, tmpv, tmpv, &Overflow );
935 : pt_exc2++;
936 : L_ener = L_add_o( L_ener, L_shr_o( L_tmp, 7, &Overflow ), &Overflow ); /* Q(2*(Q_exc+scale)+1) ,division by L_frame done here */
937 : #endif
938 : }
939 : }
940 : ELSE /* L_FRAME16k */
941 : {
942 266938 : FOR( j = 0; j < 160; j++ )
943 : {
944 265280 : tmpv = shl( *pt_exc2, scale );
945 265280 : L_tmp = L_mult0( tmpv, tmpv ); /* 2*(Q_exc+scale) */
946 265280 : pt_exc2++;
947 265280 : tmpv = shl( *pt_exc2, scale );
948 : #ifdef ISSUE_1836_replace_overflow_libcom
949 265280 : L_tmp = L_mac0_sat( L_tmp, tmpv, tmpv );
950 265280 : pt_exc2++;
951 265280 : L_ener = L_add_sat( L_ener, L_shr_sat( Mult_32_16( L_tmp, 26214 /* 256/320, Q15 */ ), 7 ) ); /* Q(2*(Q_exc+scale)+15+1-16+1) ,division by L_frame done here */
952 : #else
953 : L_tmp = L_mac0_o( L_tmp, tmpv, tmpv, &Overflow );
954 : pt_exc2++;
955 : L_ener = L_add_o( L_ener, L_shr_o( Mult_32_16( L_tmp, 26214 /* 256/320, Q15 */ ), 7, &Overflow ), &Overflow ); /* Q(2*(Q_exc+scale)+15+1-16+1) ,division by L_frame done here */
956 : #endif
957 : }
958 : }
959 : #ifdef ISSUE_1836_replace_overflow_libcom
960 2669 : L_ener = L_shr_sat( L_ener, sub( shl( add( Q_exc, scale ), 1 ), 5 ) ); /* Q6 (2*(Q_exc+scale)+1-2*(Q_exc+scale)+5) */
961 : #else
962 : L_ener = L_shr_o( L_ener, sub( shl( add( Q_exc, scale ), 1 ), 5 ), &Overflow ); /* Q6 (2*(Q_exc+scale)+1-2*(Q_exc+scale)+5) */
963 : #endif
964 :
965 : /* update the circular buffer of old energies */
966 2669 : ho_ener_circ[*ho_circ_ptr] = L_ener;
967 2669 : move32();
968 :
969 2669 : IF( enc_dec_flag == ENC )
970 : {
971 : /* Store residual signal for postponed FFT-processing*/
972 0 : *cng_buf_cnt = add( *cng_buf_cnt, 1 );
973 0 : move16();
974 0 : if ( GT_16( *cng_buf_cnt, HO_HIST_SIZE ) )
975 : {
976 0 : *cng_buf_cnt = HO_HIST_SIZE;
977 0 : move16();
978 : }
979 0 : Copy( exc2, &( cng_exc2_buf[( *ho_circ_ptr ) * L_FFT] ), L_FFT );
980 0 : cng_Qexc_buf[*ho_circ_ptr] = Q_exc;
981 0 : move16();
982 0 : cng_brate_buf[*ho_circ_ptr] = last_active_brate;
983 0 : move32();
984 : }
985 : ELSE
986 : {
987 : /* calculate the spectrum of residual signal */
988 2669 : Copy( exc2, fft_io, L_frame );
989 :
990 2669 : fft_rel_fx( fft_io, L_FFT, LOG2_L_FFT );
991 :
992 2669 : ptR = &fft_io[1];
993 2669 : ptI = &fft_io[L_FFT - 1];
994 56049 : FOR( i = 0; i < NUM_ENV_CNG; i++ )
995 : {
996 : /* sp[i] = 2.0f*(*ptR * *ptR + *ptI * *ptI)/L_FFT; */
997 : #ifdef ISSUE_1836_replace_overflow_libcom
998 53380 : L_tmp = L_mult_sat( *ptR, *ptR ); /* 2*Q_exc+1 */
999 53380 : L_tmp = L_add_sat( L_tmp, L_mult_sat( *ptI, *ptI ) ); /* 2*Q_exc+1 */
1000 53380 : L_tmp = L_add_sat( L_tmp, L_tmp ); /* 2*Q_exc+1 */
1001 : #else
1002 : L_tmp = L_mult_o( *ptR, *ptR, &Overflow ); /* 2*Q_exc+1 */
1003 : L_tmp = L_add_o( L_tmp, L_mult_o( *ptI, *ptI, &Overflow ), &Overflow ); /* 2*Q_exc+1 */
1004 : L_tmp = L_add_o( L_tmp, L_tmp, &Overflow ); /* 2*Q_exc+1 */
1005 : #endif
1006 53380 : L_tmp = Mult_32_16( L_tmp, 128 ); /* 2*Q_exc+1 */
1007 53380 : tmp = add( add( Q_exc, Q_exc ), 1 );
1008 53380 : sp[i] = L_shr( L_tmp, sub( tmp, 6 ) );
1009 53380 : move32(); /* Q6 */
1010 :
1011 53380 : ptR++;
1012 53380 : ptI--;
1013 : }
1014 :
1015 2669 : Copy32( sp, env, NUM_ENV_CNG );
1016 : {
1017 2669 : CNG_mode = get_cng_mode( last_active_brate );
1018 : /* att = 1/pow(2,ENR_ATT_fx[CNG_mode]); */
1019 2669 : L_tmp = L_shl( L_deposit_l( ENR_ATT_fx[CNG_mode] ), 8 ); /* 16 */
1020 2669 : temp_lo_fx = L_Extract_lc( L_tmp, &temp_hi_fx );
1021 :
1022 2669 : exp_pow = sub( 14, temp_hi_fx );
1023 2669 : L_tmp = Pow2( 14, temp_lo_fx ); /* Qexp_pow */
1024 2669 : L_tmp = L_shl( L_tmp, sub( 13, exp_pow ) ); /* Q13 */
1025 2669 : tmp = extract_l( L_tmp ); /* Q13 */
1026 :
1027 2669 : exp1 = norm_s( tmp );
1028 2669 : tmp = shl( tmp, exp1 ); /*Q(exp1+13) */
1029 2669 : tmp = div_s( 16384, tmp ); /*Q(15+14-exp1-13) */
1030 2669 : tmp = shr( tmp, sub( 1, exp1 ) ); /* Q15 */
1031 : }
1032 :
1033 56049 : FOR( i = 0; i < NUM_ENV_CNG; i++ )
1034 : {
1035 53380 : env[i] = Mult_32_16( env[i], tmp );
1036 53380 : move32();
1037 : }
1038 :
1039 : /* update the circular buffer of old residual envelope */
1040 : /* Copy32( env, &(ho_env_circ[add(shl(*ho_circ_ptr,4),shl(*ho_circ_ptr,2))]), NUM_ENV_CNG ); */
1041 2669 : Copy32( env, &( ho_env_circ[( *ho_circ_ptr ) * NUM_ENV_CNG] ), NUM_ENV_CNG );
1042 : }
1043 2669 : *ho_circ_size = add( *ho_circ_size, 1 );
1044 2669 : move16();
1045 2669 : if ( GT_16( *ho_circ_size, HO_HIST_SIZE ) )
1046 : {
1047 2645 : *ho_circ_size = HO_HIST_SIZE;
1048 2645 : move16();
1049 : }
1050 :
1051 2669 : return;
1052 : }
1053 :
1054 208566 : void cng_params_upd_ivas_fx(
1055 : const Word16 lsp_new[], /* i : LSP aprameters Q15 */
1056 : const Word16 exc2[], /* i : current enhanced excitation Q_exc */
1057 : const Word16 L_frame, /* i : frame length Q0 */
1058 : Word16 *ho_circ_ptr, /* i/o: pointer for CNG averaging buffers Q0 */
1059 : Word32 ho_ener_circ[], /* o : energy buffer for CNG averaging Q6 */
1060 : Word16 *ho_circ_size, /* i/o: size of DTX hangover history buffer for averaging Q0 */
1061 : Word16 ho_lsp_circ[], /* o : old LSP buffer for CNG averaging Q15 */
1062 : const Word16 Q_exc, /* i : Q value of excitation */
1063 : const Word16 enc_dec_flag, /* i : Flag indicating encoder or decoder (ENC,DEC) */
1064 : Word32 ho_env_circ[], /* i/o: Envelope buffer Q(6+shift) */
1065 : Word16 *cng_buf_cnt, /* i/o: Counter of postponed FFT-processing instances */
1066 : Word16 cng_exc2_buf[], /* i/o: Excitation buffer Q_exc */
1067 : Word16 cng_Qexc_buf[], /* i/o: Q_exc buffer Q0 */
1068 : Word32 cng_brate_buf[], /* i/o: last_active_brate buffer Q0 */
1069 : const Word32 last_active_brate /* i : Last active bit rate Q0 */
1070 : ,
1071 : const Word16 element_mode, /* i : Element mode */
1072 : const Word16 bwidth /* i : Audio bandwidth */
1073 : )
1074 : {
1075 : Word32 L_ener, L_tmp;
1076 : Word16 i, j;
1077 : const Word16 *pt_exc2;
1078 : Word16 tmpv, maxv, scale;
1079 : Word16 fft_io[L_FRAME16k];
1080 : Word32 sp[129];
1081 : Word16 *ptR, *ptI;
1082 : Word32 env[NUM_ENV_CNG];
1083 : Word16 exp1;
1084 : Word16 CNG_mode;
1085 208566 : Word16 tmp = 0;
1086 208566 : move16();
1087 : Word16 temp_lo_fx, temp_hi_fx;
1088 : Word16 exp_pow;
1089 : #ifndef ISSUE_1836_replace_overflow_libcom
1090 : #ifdef BASOP_NOGLOB_DECLARE_LOCAL
1091 : Flag Overflow = 0;
1092 : move32();
1093 : #endif
1094 : #endif
1095 :
1096 : /* update the pointer to circular buffer of old LSP vectors */
1097 208566 : *ho_circ_ptr = add( *ho_circ_ptr, 1 );
1098 208566 : move16();
1099 :
1100 208566 : if ( EQ_16( *ho_circ_ptr, HO_HIST_SIZE ) )
1101 : {
1102 25370 : *ho_circ_ptr = 0;
1103 25370 : move16();
1104 : }
1105 :
1106 : /* update the circular buffer of old LSP vectors with the new LSP vector */
1107 208566 : Copy( lsp_new, &( ho_lsp_circ[( *ho_circ_ptr ) * M] ), M );
1108 :
1109 : /* calculate the residual signal energy */
1110 : /*enr = dotp( exc2, exc2, L_frame ) / L_frame; */
1111 :
1112 208566 : maxv = 0;
1113 208566 : move16();
1114 61237302 : FOR( i = 0; i < L_frame; i++ )
1115 : {
1116 61028736 : maxv = s_max( maxv, abs_s( exc2[i] ) );
1117 : }
1118 208566 : scale = norm_s( maxv );
1119 :
1120 208566 : pt_exc2 = exc2;
1121 208566 : L_ener = 0;
1122 208566 : move32();
1123 208566 : IF( EQ_16( L_frame, L_FRAME ) )
1124 : {
1125 11514024 : FOR( j = 0; j < 128; j++ )
1126 : {
1127 11424768 : tmpv = shl( *pt_exc2, scale );
1128 11424768 : L_tmp = L_mult0( tmpv, tmpv ); /* 2*(Q_exc+scale) */
1129 11424768 : pt_exc2++;
1130 11424768 : tmpv = shl( *pt_exc2, scale );
1131 : #ifdef ISSUE_1836_replace_overflow_libcom
1132 11424768 : L_tmp = L_mac0_sat( L_tmp, tmpv, tmpv );
1133 11424768 : pt_exc2++;
1134 11424768 : L_ener = L_add_sat( L_ener, L_shr_sat( L_tmp, 7 ) ); /* Q(2*(Q_exc+scale)+1) ,division by L_frame done here */
1135 : #else
1136 : L_tmp = L_mac0_o( L_tmp, tmpv, tmpv, &Overflow );
1137 : pt_exc2++;
1138 : L_ener = L_add_o( L_ener, L_shr_o( L_tmp, 7, &Overflow ), &Overflow ); /* Q(2*(Q_exc+scale)+1) ,division by L_frame done here */
1139 : #endif
1140 : }
1141 : }
1142 : ELSE /* L_FRAME16k */
1143 : {
1144 19208910 : FOR( j = 0; j < 160; j++ )
1145 : {
1146 19089600 : tmpv = shl( *pt_exc2, scale );
1147 19089600 : L_tmp = L_mult0( tmpv, tmpv ); /* 2*(Q_exc+scale) */
1148 19089600 : pt_exc2++;
1149 19089600 : tmpv = shl( *pt_exc2, scale );
1150 : #ifdef ISSUE_1836_replace_overflow_libcom
1151 19089600 : L_tmp = L_mac0_sat( L_tmp, tmpv, tmpv );
1152 19089600 : pt_exc2++;
1153 19089600 : L_ener = L_add_sat( L_ener, L_shr_sat( Mult_32_16( L_tmp, 26214 /* 256/320, Q15 */ ), 7 ) ); /* Q(2*(Q_exc+scale)+15+1-16+1) ,division by L_frame done here */
1154 : #else
1155 : L_tmp = L_mac0_o( L_tmp, tmpv, tmpv, &Overflow );
1156 : pt_exc2++;
1157 : L_ener = L_add_o( L_ener, L_shr_o( Mult_32_16( L_tmp, 26214 /* 256/320, Q15 */ ), 7, &Overflow ), &Overflow ); /* Q(2*(Q_exc+scale)+15+1-16+1) ,division by L_frame done here */
1158 : #endif
1159 : }
1160 : }
1161 : #ifdef ISSUE_1836_replace_overflow_libcom
1162 208566 : L_ener = L_shr_sat( L_ener, sub( shl( add( Q_exc, scale ), 1 ), 5 ) ); /* Q6 (2*(Q_exc+scale)+1-2*(Q_exc+scale)+5) */
1163 : #else
1164 : L_ener = L_shr_o( L_ener, sub( shl( add( Q_exc, scale ), 1 ), 5 ), &Overflow ); /* Q6 (2*(Q_exc+scale)+1-2*(Q_exc+scale)+5) */
1165 : #endif
1166 :
1167 : /* update the circular buffer of old energies */
1168 208566 : ho_ener_circ[*ho_circ_ptr] = L_ener;
1169 208566 : move32();
1170 :
1171 208566 : IF( enc_dec_flag == ENC )
1172 : {
1173 : /* Store residual signal for postponed FFT-processing*/
1174 34527 : *cng_buf_cnt = add( *cng_buf_cnt, 1 );
1175 34527 : move16();
1176 34527 : if ( GT_16( *cng_buf_cnt, HO_HIST_SIZE ) )
1177 : {
1178 32750 : *cng_buf_cnt = HO_HIST_SIZE;
1179 32750 : move16();
1180 : }
1181 34527 : Copy( exc2, &( cng_exc2_buf[( *ho_circ_ptr ) * L_FFT] ), L_FFT );
1182 34527 : cng_Qexc_buf[*ho_circ_ptr] = Q_exc;
1183 34527 : move16();
1184 34527 : cng_brate_buf[*ho_circ_ptr] = last_active_brate;
1185 34527 : move32();
1186 : }
1187 : ELSE
1188 : {
1189 : /* calculate the spectrum of residual signal */
1190 174039 : Copy( exc2, fft_io, L_frame );
1191 :
1192 174039 : fft_rel_fx( fft_io, L_FFT, LOG2_L_FFT );
1193 :
1194 174039 : ptR = &fft_io[1];
1195 174039 : ptI = &fft_io[L_FFT - 1];
1196 3654819 : FOR( i = 0; i < NUM_ENV_CNG; i++ )
1197 : {
1198 : /* sp[i] = 2.0f*(*ptR * *ptR + *ptI * *ptI)/L_FFT; */
1199 : #ifdef ISSUE_1836_replace_overflow_libcom
1200 3480780 : L_tmp = L_mult_sat( *ptR, *ptR ); /* 2*Q_exc+1 */
1201 3480780 : L_tmp = L_add_sat( L_tmp, L_mult_sat( *ptI, *ptI ) ); /* 2*Q_exc+1 */
1202 3480780 : L_tmp = L_add_sat( L_tmp, L_tmp ); /* 2*Q_exc+1 */
1203 3480780 : L_tmp = Mult_32_16( L_tmp, 128 ); /* 2*Q_exc+1 */
1204 3480780 : tmp = add( add( Q_exc, Q_exc ), 1 );
1205 3480780 : sp[i] = L_shr_sat( L_tmp, sub( tmp, 6 ) );
1206 : #else
1207 : L_tmp = L_mult_o( *ptR, *ptR, &Overflow ); /* 2*Q_exc+1 */
1208 : L_tmp = L_add_o( L_tmp, L_mult_o( *ptI, *ptI, &Overflow ), &Overflow ); /* 2*Q_exc+1 */
1209 : L_tmp = L_add_o( L_tmp, L_tmp, &Overflow ); /* 2*Q_exc+1 */
1210 : L_tmp = Mult_32_16( L_tmp, 128 ); /* 2*Q_exc+1 */
1211 : tmp = add( add( Q_exc, Q_exc ), 1 );
1212 : sp[i] = L_shr_o( L_tmp, sub( tmp, 6 ), &Overflow );
1213 : #endif
1214 3480780 : move32(); /* Q6 */
1215 3480780 : ptR++;
1216 3480780 : ptI--;
1217 : }
1218 :
1219 :
1220 174039 : Copy32( sp, env, NUM_ENV_CNG );
1221 174039 : Word16 shift = 0;
1222 174039 : move16();
1223 174039 : test();
1224 174039 : IF( EQ_16( element_mode, IVAS_SCE ) || EQ_16( element_mode, IVAS_CPE_DFT ) )
1225 170244 : {
1226 170244 : Word32 att_fx = 0;
1227 170244 : Word16 index = 0;
1228 170244 : move32();
1229 170244 : move16();
1230 170244 : apply_scale_ivas_fx( &att_fx, bwidth, last_active_brate, scaleTableStereo, SIZE_SCALE_TABLE_STEREO, &index );
1231 170244 : att_fx = pow_10_q23[index]; // Q23
1232 170244 : move32();
1233 170244 : tmp = extract_h( att_fx ); // Q7
1234 170244 : shift = 8;
1235 170244 : move16();
1236 : }
1237 : ELSE
1238 : {
1239 3795 : CNG_mode = get_cng_mode( last_active_brate );
1240 : /* att = 1/pow(2,ENR_ATT_fx[CNG_mode]); */
1241 3795 : L_tmp = L_shl( L_deposit_l( ENR_ATT_fx[CNG_mode] ), 8 ); /* 16 */
1242 3795 : temp_lo_fx = L_Extract_lc( L_tmp, &temp_hi_fx );
1243 :
1244 3795 : exp_pow = sub( 14, temp_hi_fx );
1245 3795 : L_tmp = Pow2( 14, temp_lo_fx ); /* Qexp_pow */
1246 3795 : L_tmp = L_shl( L_tmp, sub( 13, exp_pow ) ); /* Q13 */
1247 3795 : tmp = extract_l( L_tmp ); /* Q13 */
1248 :
1249 3795 : exp1 = norm_s( tmp );
1250 3795 : tmp = shl( tmp, exp1 ); /*Q(exp1+13) */
1251 3795 : tmp = div_s( 16384, tmp ); /*Q(15+14-exp1-13) */
1252 3795 : tmp = shr( tmp, sub( 1, exp1 ) ); /* Q15 */
1253 : }
1254 :
1255 3654819 : FOR( i = 0; i < NUM_ENV_CNG; i++ )
1256 : {
1257 3480780 : env[i] = Mult_32_16( env[i], tmp );
1258 3480780 : move32();
1259 : }
1260 :
1261 : /* update the circular buffer of old residual envelope */
1262 : /* Copy32( env, &(ho_env_circ[add(shl(*ho_circ_ptr,4),shl(*ho_circ_ptr,2))]), NUM_ENV_CNG ); */
1263 174039 : Copy32( env, &( ho_env_circ[( *ho_circ_ptr ) * NUM_ENV_CNG] ), NUM_ENV_CNG );
1264 174039 : scale_sig32( &( ho_env_circ[( *ho_circ_ptr ) * NUM_ENV_CNG] ), NUM_ENV_CNG, shift ); // Q(6+shift)
1265 : }
1266 208566 : *ho_circ_size = add( *ho_circ_size, 1 );
1267 208566 : move16();
1268 208566 : if ( GT_16( *ho_circ_size, HO_HIST_SIZE ) )
1269 : {
1270 198460 : *ho_circ_size = HO_HIST_SIZE;
1271 198460 : move16();
1272 : }
1273 :
1274 208566 : return;
1275 : }
1276 :
1277 : /*---------------------------------------------------------------------*
1278 : * get_cng_mode()
1279 : *
1280 : *
1281 : *---------------------------------------------------------------------*/
1282 :
1283 6467 : Word16 get_cng_mode(
1284 : const Word32 last_active_brate /* i : last active bitrate */
1285 : )
1286 : {
1287 : Word16 CNG_mode;
1288 :
1289 6467 : IF( GT_32( last_active_brate, ACELP_13k20 ) )
1290 : {
1291 4150 : CNG_mode = 4;
1292 4150 : move16();
1293 : }
1294 2317 : ELSE IF( GT_32( last_active_brate, ACELP_9k60 ) )
1295 : {
1296 1742 : CNG_mode = 3;
1297 1742 : move16();
1298 : }
1299 575 : ELSE IF( GT_32( last_active_brate, ACELP_8k00 ) )
1300 : {
1301 411 : CNG_mode = 2;
1302 411 : move16();
1303 : }
1304 164 : ELSE IF( GT_32( last_active_brate, ACELP_7k20 ) )
1305 : {
1306 161 : CNG_mode = 1;
1307 161 : move16();
1308 : }
1309 : ELSE
1310 : {
1311 3 : CNG_mode = 0;
1312 3 : move16();
1313 : }
1314 :
1315 6467 : return ( CNG_mode );
1316 : }
|