Line data Source code
1 : /*====================================================================================
2 : EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0
3 : ====================================================================================*/
4 :
5 : #include <stdlib.h>
6 : #include <stdio.h>
7 : #include <assert.h>
8 : #include <string.h>
9 : #include "prot_fx.h"
10 : #include "basop_util.h"
11 : #include "stat_com.h"
12 : #include "rom_com.h"
13 : #include "stl.h" /* FOR wmc_tool */
14 : #include "vad_basop.h"
15 :
16 : void get_maxConv_and_pitch_x( Word16 *s_LP, Word16 s, Word16 e, Word16 N, Word32 *maxConv, Word16 *maxConv_bits, Word16 *pitch );
17 : Word16 get_voicing_x( Word16 *s_LP, Word16 pitch, Word32 covMax, Word16 maxConv_bits, Word16 Framesize );
18 : Word32 con_Log10( Word32 i_s32Val, Word16 i_s16Q );
19 : Word16 Spl_GetScalingSquare_x( const Word16 *in_vector, const Word16 in_vector_length, Word16 times );
20 :
21 0 : Word16 vadmin( Word16 a, Word16 b ) /*i/o: Qx */
22 : {
23 0 : return s_min( a, b );
24 : }
25 :
26 0 : void set_state( Word16 *state, Word16 num, Word16 N ) /*i/o: Qx */
27 : {
28 : Word16 i, tmp;
29 :
30 0 : tmp = sub( N, 1 );
31 0 : FOR( i = 0; i < tmp; i++ )
32 : {
33 0 : state[i] = state[i + 1];
34 0 : move16();
35 : }
36 0 : state[tmp] = num;
37 0 : move16();
38 :
39 0 : return;
40 : }
41 :
42 0 : void concealment_update_x(
43 : const Word16 bfi,
44 : const Word16 core,
45 : const Word16 tonality,
46 : Word32 *invkoef /*Qinvkoef_scale*/,
47 : Word16 *invkoef_scale,
48 : T_PLCInfo_HANDLE hPlcInfo )
49 : {
50 0 : Word32 *data_reci2 = hPlcInfo->data_reci2_fx;
51 0 : Word16 *tcx_tonality = hPlcInfo->TCX_Tonality;
52 0 : Word16 L_frameTCX = hPlcInfo->L_frameTCX;
53 0 : Word16 subframe = hPlcInfo->subframe_fx;
54 : Word16 i;
55 0 : move16();
56 0 : move16();
57 :
58 0 : IF( EQ_16( core, TCX_20_CORE ) )
59 : {
60 0 : set_state( hPlcInfo->Transient, core, MAX_POST_LEN );
61 :
62 0 : FOR( i = 0; i < L_frameTCX; i++ )
63 : {
64 0 : data_reci2[i] = invkoef[i];
65 0 : move32();
66 : }
67 0 : hPlcInfo->data_reci2_scale = *invkoef_scale;
68 0 : move16();
69 0 : IF( !bfi )
70 : {
71 0 : set_state( tcx_tonality, tonality, DEC_STATE_LEN );
72 : }
73 : }
74 : ELSE
75 : {
76 :
77 0 : IF( subframe == 0 )
78 : {
79 0 : set_state( hPlcInfo->Transient, core, MAX_POST_LEN );
80 :
81 0 : IF( !bfi )
82 : {
83 0 : set_state( tcx_tonality, tonality, DEC_STATE_LEN );
84 : }
85 : }
86 : /* don't store the second subframe during frameloss; in
87 : pitch_search_fx(), low_freq_rate is derived on the last good
88 : TCX-10 spectrum */
89 0 : test();
90 0 : IF( !bfi || subframe == 0 )
91 : {
92 :
93 0 : Word32 *ptr = data_reci2 + subframe;
94 0 : Word16 FrameSize2 = shr( L_frameTCX, 1 );
95 :
96 0 : FOR( i = 0; i < FrameSize2; i++ )
97 : {
98 0 : ptr[i] = invkoef[i];
99 0 : move32();
100 : }
101 :
102 0 : hPlcInfo->data_reci2_scale = *invkoef_scale;
103 0 : move16();
104 : }
105 : }
106 :
107 0 : return;
108 : }
109 :
110 :
111 0 : static Word16 zero_pass_w32_x( const Word16 *s, const Word16 N ) /* i: Qx*/ /* o: 2*Qx-31*/
112 : {
113 : Word16 i;
114 0 : Word32 temp, zp = L_deposit_l( 0 );
115 :
116 0 : FOR( i = 1; i < N; i++ )
117 : {
118 0 : temp = L_mac0( -1L, s[i], s[i - 1] ); // 2*Qx
119 0 : zp = L_sub( zp, L_shr( temp, 31 ) ); // 2*Qx-31
120 : }
121 0 : return extract_l( zp );
122 : }
123 :
124 0 : Word16 Sqrt_x_fast( Word32 value /*Qvalue*/ ) /*o : Q11-(2*norm+1)*/
125 : {
126 : Word16 norm;
127 : Word16 result, index;
128 :
129 0 : norm = sub( 23, norm_l( value ) );
130 0 : index = extract_l( L_shr_r( value, add( norm, s_and( norm, 1 ) ) ) );
131 0 : result = shr( sqrt_table_pitch_search[index], sub( 11, shr( add( norm, 1 ), 1 ) ) ); // Q11-(2*norm+1)
132 0 : return result;
133 : }
134 :
135 0 : Word32 dot_w32_accuracy_x( Word16 *s1 /*Qs1*/, Word16 *s2 /*Qs2*/, Word16 nbits, Word16 N )
136 : {
137 : Word16 i;
138 0 : Word32 eng = L_deposit_l( 0 ), temp;
139 :
140 0 : FOR( i = 0; i < N; i++ )
141 : {
142 0 : temp = L_mult0( s1[i], s2[i] ); /*Qs1+ Qs2*/
143 0 : eng = L_add( eng, L_shr( temp, nbits ) ); /*Qs1+ Qs2-nbits*/
144 : }
145 :
146 0 : return eng;
147 : }
148 :
149 :
150 0 : Word16 int_div_s_x( Word16 a, Word16 b ) /*i/o : Q0*/
151 : {
152 0 : Word16 result = 0;
153 0 : Word16 norm, left = 0, i;
154 0 : move16();
155 0 : move16();
156 0 : test();
157 0 : IF( LT_16( a, b ) || b == 0 )
158 : {
159 0 : return 0;
160 : }
161 : ELSE
162 : {
163 0 : a = add( a, shr( b, 1 ) );
164 0 : norm = sub( norm_s( b ), norm_s( a ) );
165 :
166 0 : FOR( i = norm; i >= 0; i-- )
167 : {
168 0 : left = shr( a, i );
169 0 : result = shl( result, 1 );
170 0 : IF( GE_16( left, b ) )
171 : {
172 0 : result = add( result, 1 );
173 0 : left = sub( left, b );
174 0 : a = add( shl( left, i ), s_and( a, sub( shl( 1, i ), 1 ) ) );
175 : }
176 : }
177 : }
178 :
179 0 : return result;
180 : }
181 :
182 0 : Word16 GetW32Norm_x( Word32 *s, Word16 N ) /*i : Qx, o: Q0*/
183 : {
184 0 : Word32 smax = L_deposit_l( 0 );
185 : Word16 smax_norm, i;
186 :
187 0 : FOR( i = 0; i < N; i++ )
188 : {
189 0 : smax = L_or( smax, L_abs( s[i] ) );
190 : }
191 :
192 0 : smax_norm = norm_l( smax );
193 :
194 0 : return smax_norm;
195 : }
196 :
197 0 : Word16 harmo_x( Word32 *X, Word16 Framesize, Word16 pitch ) /*i : Qx, o: Q15*/
198 : {
199 0 : Word16 h, k, result = 0;
200 0 : Word32 ener = L_deposit_l( 0 ), ener_harmo = L_deposit_l( 0 );
201 : Word16 norm1, d1, d2;
202 : Word16 ener_w, ener_harmo_w;
203 0 : Word16 nbits = sub( 15, norm_s( Framesize ) );
204 0 : move16();
205 0 : norm1 = GetW32Norm_x( X, Framesize );
206 :
207 0 : FOR( k = 1; k < 9; k++ )
208 : {
209 0 : h = sub( int_div_s_x( extract_l( L_mult( k, Framesize ) ), pitch ), 1 );
210 :
211 0 : d1 = extract_h( L_shl( X[h], norm1 ) );
212 0 : d2 = extract_h( L_shl( X[h + 1], norm1 ) );
213 :
214 0 : ener_harmo = L_add( ener_harmo,
215 : L_shr( L_mac0( L_mult0( d1, d1 ), d2, d2 ), nbits ) );
216 : }
217 :
218 0 : FOR( k = 0; k < Framesize; k++ )
219 : {
220 0 : d1 = extract_h( L_shl( X[k], norm1 ) );
221 0 : ener = L_add( ener, L_shr( L_mult0( d1, d1 ), nbits ) );
222 : }
223 :
224 0 : norm1 = norm_l( ener );
225 0 : ener_w = extract_h( L_shl( ener, norm1 ) );
226 0 : ener_harmo_w = extract_h( L_shl( ener_harmo, norm1 ) );
227 :
228 0 : IF( GE_32( ener_harmo, ener ) )
229 : {
230 0 : return 32767;
231 : }
232 0 : test();
233 0 : IF( ( ener_harmo_w <= 0 ) || ( ener_w <= 0 ) )
234 : {
235 0 : return 0;
236 : }
237 0 : result = div_s( ener_harmo_w, ener_w );
238 0 : return result;
239 : }
240 :
241 0 : static Word16 get_low_freq_eng_rate_x( Word32 *mdct_data, /*i: Qx*/ /*o: Q0*/
242 : Word16 curr_mode,
243 : Word16 N )
244 : {
245 : Word16 N1, N2, i;
246 0 : Word32 low_eng = L_deposit_l( 0 ), eng = L_deposit_l( 0 ), smax = L_deposit_l( 0 );
247 0 : Word16 nbits, temp, norm = 0;
248 0 : move16();
249 0 : N1 = 30;
250 0 : N2 = N;
251 0 : move16();
252 0 : move16();
253 0 : IF( EQ_16( 2, curr_mode ) )
254 : {
255 0 : N1 = shr( 30, 1 );
256 0 : N2 = shr( N, 1 );
257 : }
258 :
259 0 : nbits = sub( 15, norm_s( N2 ) );
260 :
261 0 : FOR( i = 0; i < N2; i++ )
262 : {
263 0 : smax = L_or( smax, L_abs( mdct_data[i] ) );
264 : }
265 :
266 0 : norm = norm_l( smax );
267 :
268 0 : FOR( i = 0; i < N1; i++ )
269 : {
270 0 : temp = extract_h( L_shl( mdct_data[i], norm ) );
271 0 : low_eng = L_add( low_eng, L_shr( L_mult0( temp, temp ), nbits ) );
272 : }
273 :
274 0 : FOR( i = N1; i < N2; i++ )
275 : {
276 0 : temp = extract_h( L_shl( mdct_data[i], norm ) );
277 0 : eng = L_add( eng, L_shr( L_mult0( temp, temp ), nbits ) );
278 : }
279 0 : eng = L_add( low_eng, eng );
280 :
281 : /* IF (low_eng<(eng+EPSILON)*0.02) return 1;ELSE return 0; */
282 : /* smax=eng*0.02 */
283 0 : smax = L_shr( Mpy_32_16_1( eng, 5243 ), 3 );
284 :
285 0 : return ( L_sub( low_eng, smax ) <= 0 );
286 : }
287 :
288 0 : void LpFilter2_x( Word16 *x, Word16 *y, Word16 N ) /*i/o : Qx*/
289 : {
290 : Word16 i;
291 : Word16 smax, norm;
292 0 : Word16 a1 = 5898; /* W16(0.18f); */
293 0 : Word16 a2 = 20971; /* W16(0.64f); */
294 0 : move16();
295 0 : move16();
296 0 : smax = 0;
297 0 : move16();
298 0 : FOR( i = 0; i < N; i++ )
299 : {
300 0 : smax = s_or( smax, abs_s( x[i] ) );
301 : }
302 0 : norm = norm_s( smax );
303 :
304 0 : y[0] = mult( shl( x[0], norm ), a1 );
305 0 : move16();
306 0 : y[1] = add( mult( y[0], a2 ), mult( shl( x[1], norm ), a1 ) );
307 0 : move16();
308 :
309 0 : FOR( i = 2; i < N; i++ )
310 : {
311 : /* 5898*2+20971=32767 -->no overflow */
312 0 : y[i] = add( mult( y[i - 2], a1 ), add( mult( y[i - 1], a2 ), mult( shl( x[i], norm ), a1 ) ) );
313 0 : move16();
314 : }
315 0 : }
316 :
317 0 : void sig_tilt_x( Word16 *s /*Qx*/, Word16 FrameSize, Word32 *enr1 /*2*Qx-nbits*/, Word32 *enr2 /*2*Qx-nbits*/ )
318 : {
319 : Word16 subFrameSize, shIFt;
320 : Word16 *p1, *p2;
321 : Word16 nbits;
322 :
323 0 : subFrameSize = shr( FrameSize, 2 );
324 0 : p1 = s + subFrameSize;
325 0 : p2 = s + sub( subFrameSize, 2 );
326 :
327 0 : shIFt = sub( FrameSize, subFrameSize );
328 0 : nbits = sub( 15, norm_s( shIFt ) );
329 0 : *enr1 = dot_w32_accuracy_x( p1, p2, nbits, shIFt );
330 0 : move32();
331 0 : *enr2 = dot_w32_accuracy_x( p1, p1, nbits, shIFt );
332 0 : move32();
333 0 : }
334 :
335 0 : void get_maxConv_and_pitch_x( Word16 *s_LP /*Qx*/, Word16 s /*Q0*/, Word16 e /*Q0*/, Word16 N, Word32 *maxConv /*2*Qx-nbits*/, Word16 *maxConv_bits, Word16 *pitch /*Q0*/ )
336 : {
337 0 : Word16 t, cov_size, size = N;
338 0 : Word32 tmp_sigma = L_deposit_l( 0 ), cov_max_sigma = L_deposit_l( 0 );
339 0 : Word16 nbits, tmp_pitch = 0;
340 : Word32 r1_high, r2_high;
341 : UWord16 r1_low, r2_low;
342 0 : Word32 tmp_sigma_last = L_deposit_l( 0 ); /* not needed, just to avoid compiler warning */
343 0 : Word16 cov_size_last = N; /* not needed, just to avoid compiler warning */
344 0 : Word32 cov_max_sigma_tmp = L_deposit_l( 0 );
345 0 : Word16 size_tmp = N;
346 0 : move16();
347 0 : move16();
348 0 : move16();
349 0 : move16();
350 0 : nbits = sub( 15, norm_s( sub( N, s ) ) );
351 :
352 0 : FOR( t = s; t < e; t++ )
353 : {
354 0 : cov_size = sub( N, t );
355 0 : tmp_sigma = dot_w32_accuracy_x( s_LP, s_LP + t, nbits, cov_size );
356 :
357 0 : IF( GT_16( t, s ) ) /* don't use the first value */
358 : {
359 0 : Mpy_32_16_ss( tmp_sigma, cov_size_last, &r1_high, &r1_low );
360 0 : Mpy_32_16_ss( tmp_sigma_last, cov_size, &r2_high, &r2_low );
361 : /* tmp_sigma > tmp_sigma_last */
362 0 : test();
363 0 : test();
364 0 : move16();
365 0 : move16(); /* moves are for the (Word32) casts */
366 0 : IF( ( GT_32( r1_high, r2_high ) ) ||
367 : ( EQ_32( r1_high, r2_high ) && GT_32( (Word32) r1_low, (Word32) r2_low ) ) )
368 : {
369 : /* store the current cov, if it is larger than the last one */
370 0 : cov_max_sigma_tmp = tmp_sigma;
371 0 : move32();
372 0 : size_tmp = cov_size;
373 0 : move16();
374 : }
375 : ELSE
376 : {
377 0 : Mpy_32_16_ss( cov_max_sigma, size_tmp, &r1_high, &r1_low );
378 0 : Mpy_32_16_ss( cov_max_sigma_tmp, size, &r2_high, &r2_low );
379 : /* cov_max_sigma < cov_max_sigma_tmp */
380 0 : test();
381 0 : test();
382 0 : move16();
383 0 : move16(); /* moves are for the (Word32) casts */
384 0 : IF( ( LT_32( r1_high, r2_high ) ) ||
385 : ( EQ_32( r1_high, r2_high ) && LT_32( (Word32) r1_low, (Word32) r2_low ) ) )
386 : {
387 : /* otherwise */
388 : /* use the last value of cov, being a max */
389 0 : cov_max_sigma = cov_max_sigma_tmp;
390 0 : move32();
391 0 : size = cov_size;
392 0 : move16();
393 : /* and use the last index as pitch */
394 0 : tmp_pitch = sub( t, 1 );
395 : }
396 : }
397 : }
398 0 : tmp_sigma_last = tmp_sigma;
399 0 : move32();
400 0 : cov_size_last = cov_size;
401 0 : move16();
402 : }
403 0 : *pitch = tmp_pitch;
404 0 : move16();
405 0 : *maxConv = cov_max_sigma;
406 0 : move32();
407 0 : *maxConv_bits = nbits;
408 0 : move16();
409 0 : }
410 :
411 0 : Word16 get_voicing_x( Word16 *s_LP /*Qx*/, Word16 pitch /*Q0*/, Word32 covMax /*2*Qx-nbits*/, Word16 maxConv_bits, Word16 Framesize ) /*o : Q15*/
412 : {
413 0 : Word32 eng1 = L_deposit_l( 0 ), eng2 = L_deposit_l( 0 );
414 : Word16 voicing, norm;
415 : Word16 tmpLen, nbits;
416 : Word16 eng1_w, eng2_w;
417 :
418 0 : IF( covMax <= 0 )
419 : {
420 0 : return 0;
421 : }
422 : ELSE
423 : {
424 0 : tmpLen = sub( Framesize, pitch );
425 0 : nbits = maxConv_bits;
426 0 : move16();
427 :
428 0 : eng1 = dot_w32_accuracy_x( s_LP, s_LP, nbits, tmpLen );
429 0 : eng2 = dot_w32_accuracy_x( s_LP + pitch, s_LP + pitch, nbits, tmpLen );
430 :
431 0 : norm = sub( norm_l( L_or( eng1, L_or( eng2, covMax ) ) ), 1 );
432 0 : eng1 = L_shl( eng1, norm );
433 0 : eng2 = L_shl( eng2, norm );
434 0 : covMax = L_shl( covMax, norm );
435 :
436 0 : eng1_w = Sqrt_x_fast( eng1 );
437 0 : eng2_w = Sqrt_x_fast( eng2 );
438 :
439 0 : eng1 = L_mult0( eng1_w, eng2_w );
440 0 : norm = norm_l( eng1 );
441 0 : eng1_w = extract_h( L_shl( eng1, norm ) );
442 0 : eng2_w = extract_h( L_shl( covMax, norm ) );
443 :
444 0 : IF( GE_32( covMax, eng1 ) )
445 : {
446 0 : return 32767;
447 : }
448 0 : test();
449 0 : IF( ( eng2_w <= 0 ) || ( eng1_w <= 0 ) )
450 : {
451 0 : return 0;
452 : }
453 0 : voicing = div_s( eng2_w, eng1_w );
454 :
455 0 : return voicing;
456 : }
457 : }
458 :
459 0 : void pitch_modify_x( Word16 *s_LP /*Qx*/, Word16 *voicing /*Q15*/, Word16 *pitch /*Q0*/, Word16 FrameSize )
460 : {
461 : Word32 eng1, eng2, eng3;
462 0 : Word16 shIFt = shr( *pitch, 1 );
463 : Word16 tmpLen, nbits, norm, voicing2;
464 : Word16 eng1_w, eng2_w;
465 :
466 0 : tmpLen = sub( FrameSize, shIFt );
467 0 : nbits = sub( 15, norm_s( tmpLen ) );
468 :
469 0 : eng1 = dot_w32_accuracy_x( s_LP + shIFt, s_LP + shIFt, nbits, tmpLen );
470 0 : eng2 = dot_w32_accuracy_x( s_LP, s_LP, nbits, tmpLen );
471 0 : eng3 = dot_w32_accuracy_x( s_LP + shIFt, s_LP, nbits, tmpLen );
472 :
473 0 : IF( eng3 <= 0 )
474 : {
475 0 : return;
476 : }
477 :
478 0 : norm = sub( norm_l( L_or( eng1, L_or( eng2, eng3 ) ) ), 1 );
479 0 : eng1 = L_shl( eng1, norm );
480 0 : eng2 = L_shl( eng2, norm );
481 0 : eng3 = L_shl( eng3, norm );
482 :
483 0 : eng1_w = Sqrt_x_fast( eng1 );
484 0 : eng2_w = Sqrt_x_fast( eng2 );
485 :
486 0 : eng1 = L_mult0( eng1_w, eng2_w );
487 :
488 0 : norm = norm_l( eng1 );
489 0 : eng1_w = extract_h( L_shl_sat( eng1, norm ) );
490 0 : eng2_w = extract_h( L_shl_sat( eng3, norm ) );
491 :
492 0 : IF( GE_32( eng3, eng1 ) )
493 : {
494 0 : voicing2 = 32767;
495 0 : move16();
496 : }
497 : ELSE
498 : {
499 0 : test();
500 0 : IF( ( eng2_w <= 0 ) || ( eng1_w <= 0 ) )
501 : {
502 0 : voicing2 = 0;
503 0 : move16();
504 : }
505 : ELSE
506 : {
507 0 : voicing2 = div_s( eng2_w, eng1_w );
508 : }
509 : }
510 :
511 0 : IF( GT_16( voicing2, *voicing ) )
512 : {
513 0 : *pitch = shIFt;
514 0 : move16();
515 0 : *voicing = voicing2;
516 0 : move16();
517 : }
518 : }
519 :
520 0 : Word16 Is_Periodic_x( Word32 *mdct_data /*Qx*/, Word16 cov_max /*Q15*/, Word16 zp, Word32 ener /*Q8*/, Word32 ener_mean /*Q8*/, Word16 pitch /*Q0*/, Word16 Framesize ) /*o: Q0*/
521 : {
522 0 : Word16 flag = 0;
523 : Word16 harm;
524 0 : move16();
525 0 : test();
526 0 : test();
527 0 : test();
528 0 : IF( LT_32( ener, L_shl( 50, 8 ) ) || ( LT_32( ener, L_sub( ener_mean, L_shl( 8, 8 ) ) ) && LT_16( cov_max, 29491 ) ) )
529 : {
530 0 : flag = 0;
531 0 : move16();
532 : }
533 0 : ELSE IF( GT_16( cov_max, 26214 ) )
534 : {
535 0 : flag = 1;
536 0 : move16();
537 : }
538 0 : ELSE IF( GT_16( zp, 100 ) )
539 : {
540 0 : flag = 0;
541 0 : move16();
542 : }
543 0 : ELSE IF( LT_32( ener, L_sub( ener_mean, L_shl( 6, 8 ) ) ) )
544 : {
545 0 : flag = 0;
546 0 : move16();
547 : }
548 0 : ELSE IF( GT_32( ener, L_add( ener_mean, L_shl( 1, 8 ) ) ) && GT_16( cov_max, 19661 ) )
549 : {
550 0 : flag = 1;
551 0 : move16();
552 : }
553 : ELSE
554 : {
555 0 : harm = harmo_x( mdct_data, Framesize, pitch );
556 0 : flag = 1;
557 0 : move16();
558 0 : if ( LT_16( harm, 22938 ) )
559 : {
560 0 : flag = 0;
561 0 : move16();
562 : }
563 : }
564 :
565 0 : return flag;
566 : }
567 :
568 0 : Word16 get_conv_relation_x( Word16 *s_LP /*Qx*/, Word16 shIFt, Word16 N ) /*o :Q0*/
569 : {
570 : Word32 eng1, eng2, eng3;
571 : Word16 eng1_w, eng2_w;
572 : Word16 tmp, norm, nbits;
573 :
574 0 : nbits = sub( 15, norm_s( N ) );
575 0 : eng3 = dot_w32_accuracy_x( s_LP, s_LP + shIFt, nbits, N );
576 :
577 0 : IF( eng3 <= 0 )
578 : {
579 0 : return 0;
580 : }
581 :
582 0 : eng1 = dot_w32_accuracy_x( s_LP + shIFt, s_LP + shIFt, nbits, N );
583 0 : eng2 = dot_w32_accuracy_x( s_LP, s_LP, nbits, N );
584 :
585 0 : norm = sub( norm_l( L_or( eng1, L_or( eng2, eng3 ) ) ), 1 );
586 0 : eng1 = L_shl( eng1, norm );
587 0 : eng2 = L_shl( eng2, norm );
588 0 : eng3 = L_shl( eng3, norm );
589 :
590 0 : eng1_w = Sqrt_x_fast( eng1 );
591 0 : eng2_w = Sqrt_x_fast( eng2 );
592 :
593 0 : eng1 = L_mult0( eng1_w, eng2_w );
594 :
595 0 : norm = norm_l( eng1 );
596 0 : eng1_w = extract_h( L_shl( eng1, norm ) );
597 0 : eng2_w = extract_h( L_shl( eng3, norm ) );
598 :
599 0 : IF( GE_32( eng3, eng1 ) )
600 : {
601 0 : return 32767;
602 : }
603 0 : test();
604 0 : IF( ( eng2_w <= 0 ) || ( eng1_w <= 0 ) )
605 : {
606 0 : return 0;
607 : }
608 :
609 0 : tmp = div_s( eng2_w, eng1_w );
610 :
611 0 : return tmp;
612 : }
613 :
614 :
615 0 : static Word16 pitch_search_fx(
616 : Word16 *s /*Qs*/, /* lastPcmOut */
617 : Word16 *outx_new /*Qoutx_new*/,
618 : Word16 Framesize,
619 : Word16 *voicing /*Q15*/,
620 : Word16 zp, /*Q0*/
621 : Word32 ener /*Q8*/,
622 : Word32 ener_mean /*Q8*/,
623 : Word32 *mdct_data /*Qmdct*/,
624 : Word16 curr_mode )
625 : {
626 0 : Word16 pitch = 0;
627 0 : Word32 cov_max = L_deposit_l( 0 ), tilt_enr1, tilt_enr2;
628 : Word16 s_LP[L_FRAME_MAX];
629 : Word16 start_pos, end_pos;
630 : Word16 low_freq_rate_result;
631 0 : Word16 flag = 0, zp_current;
632 : Word32 *mdctPtr;
633 : Word16 curr_frmsize;
634 0 : Word16 cov_max_bits = 0;
635 : Word16 i;
636 0 : move16();
637 0 : move16();
638 0 : move16();
639 0 : *voicing = 0;
640 0 : move16();
641 0 : curr_frmsize = Framesize;
642 0 : move16();
643 0 : if ( EQ_16( 2, curr_mode ) )
644 : {
645 0 : curr_frmsize = shr( Framesize, 1 );
646 : }
647 :
648 0 : zp_current = zero_pass_w32_x( outx_new, curr_frmsize );
649 :
650 0 : if ( EQ_16( 2, curr_mode ) )
651 : {
652 0 : zp_current = shl( zp_current, 1 );
653 : }
654 0 : IF( LE_16( Framesize, 256 ) )
655 : {
656 0 : IF( GT_16( zp_current, 70 ) )
657 : {
658 0 : return 0;
659 : }
660 : }
661 : ELSE
662 : {
663 0 : IF( GT_16( zp_current, 105 ) )
664 : {
665 0 : return 0;
666 : }
667 : }
668 :
669 0 : mdctPtr = mdct_data;
670 0 : if ( EQ_16( 2, curr_mode ) )
671 : {
672 0 : mdctPtr = mdct_data + shr( Framesize, 1 );
673 : }
674 :
675 0 : low_freq_rate_result = get_low_freq_eng_rate_x( mdctPtr,
676 : curr_mode,
677 : Framesize );
678 :
679 0 : IF( low_freq_rate_result )
680 : {
681 0 : return 0;
682 : }
683 :
684 0 : LpFilter2_x( s, s_LP, Framesize );
685 0 : sig_tilt_x( s_LP, Framesize, &tilt_enr1, &tilt_enr2 );
686 0 : IF( LE_16( Framesize, 320 ) )
687 : {
688 0 : test();
689 0 : IF( ( 0 == tilt_enr2 ) ||
690 : ( LT_32( tilt_enr1, L_shr( tilt_enr2, 1 ) ) ) )
691 : {
692 0 : return 0;
693 : }
694 : }
695 : ELSE
696 : {
697 0 : test();
698 0 : IF( ( 0 == tilt_enr2 ) ||
699 : ( LT_32( tilt_enr1, Mpy_32_16_1( tilt_enr2, 22938 ) ) ) )
700 : {
701 0 : return 0;
702 : }
703 : }
704 :
705 0 : IF( LE_16( Framesize, 320 ) )
706 : {
707 0 : start_pos = extract_l( L_shr( L_mac0( 0x80, 34, Framesize ), 8 ) );
708 0 : end_pos = extract_l( L_shr( L_mac0( 0x2, 3, Framesize ), 2 ) );
709 0 : get_maxConv_and_pitch_x( s_LP, start_pos, end_pos, Framesize, &cov_max, &cov_max_bits, &pitch );
710 0 : *voicing = get_voicing_x( s_LP, pitch, cov_max, cov_max_bits, Framesize );
711 0 : move16();
712 0 : pitch_modify_x( s_LP, voicing, &pitch, Framesize );
713 : }
714 : ELSE
715 : {
716 : Word16 s_tmp[L_FRAME_MAX];
717 : Word16 Framesize_tmp;
718 : Word16 pitch_tmp[3];
719 : Word16 cov_size;
720 :
721 0 : Framesize_tmp = shr( Framesize, 1 );
722 0 : FOR( i = 0; i < Framesize_tmp; i++ )
723 : {
724 0 : s_tmp[i] = s_LP[2 * i];
725 0 : move16();
726 : }
727 :
728 0 : start_pos = extract_l( L_shr( L_mac0( 0x80, 34, Framesize_tmp ), 8 ) );
729 0 : end_pos = extract_l( L_shr( L_mac0( 0x2, 3, Framesize_tmp ), 2 ) );
730 :
731 0 : cov_max = L_deposit_l( 0 );
732 0 : pitch = 0;
733 0 : move16();
734 0 : get_maxConv_and_pitch_x( s_tmp, start_pos, end_pos, Framesize_tmp, &cov_max, &cov_max_bits, &pitch );
735 :
736 0 : IF( pitch > 0 )
737 : {
738 0 : pitch_tmp[0] = 0;
739 0 : move16();
740 0 : if ( GT_16( shl( pitch, 1 ), 1 ) )
741 : {
742 0 : pitch_tmp[0] = sub( shl( pitch, 1 ), 1 );
743 0 : move16();
744 : }
745 0 : pitch_tmp[1] = shl( pitch, 1 );
746 0 : move16();
747 0 : pitch_tmp[2] = add( shl( pitch, 1 ), 1 );
748 0 : move16();
749 0 : start_pos = 0;
750 0 : move16();
751 0 : pitch = 0;
752 0 : move16();
753 0 : FOR( i = 0; i < 3; i++ )
754 : {
755 0 : cov_size = sub( Framesize, pitch_tmp[i] );
756 0 : end_pos = get_conv_relation_x( s_LP, pitch_tmp[i], cov_size );
757 0 : IF( GT_16( end_pos, start_pos ) )
758 : {
759 0 : start_pos = end_pos;
760 0 : move16();
761 0 : pitch = pitch_tmp[i];
762 0 : move16();
763 : }
764 : }
765 0 : *voicing = start_pos;
766 0 : move16();
767 : }
768 : }
769 :
770 0 : IF( pitch > 0 )
771 : {
772 0 : flag = Is_Periodic_x( mdct_data, *voicing, zp, ener, ener_mean, pitch, Framesize );
773 : }
774 0 : if ( flag == 0 )
775 : {
776 0 : pitch = 0;
777 0 : move16();
778 : }
779 0 : return pitch;
780 : }
781 :
782 0 : void concealment_init_x(
783 : const Word16 L_frameTCX,
784 : T_PLCInfo_HANDLE hPlcInfo )
785 : {
786 : Word16 i;
787 :
788 0 : hPlcInfo->L_frameTCX = L_frameTCX;
789 0 : move16();
790 0 : hPlcInfo->Pitch_fx = 0;
791 0 : move16();
792 0 : hPlcInfo->T_bfi_fx = 0;
793 0 : move16();
794 0 : hPlcInfo->outx_new_n1_fx = 0;
795 0 : move16();
796 0 : hPlcInfo->nsapp_gain_fx = 0;
797 0 : move16();
798 0 : hPlcInfo->nsapp_gain_n_fx = 0;
799 0 : move16();
800 0 : hPlcInfo->ener_mean_fx = L_deposit_l( 15213 ); /*Q8 59.4260f*256*/
801 0 : hPlcInfo->ener_fx = L_deposit_l( 0 );
802 0 : hPlcInfo->zp_fx = L_frameTCX;
803 0 : move16();
804 0 : hPlcInfo->recovery_gain = 0;
805 0 : move16();
806 0 : hPlcInfo->step_concealgain_fx = 0;
807 0 : move16();
808 0 : hPlcInfo->concealment_method = TCX_NONTONAL;
809 0 : move16();
810 0 : hPlcInfo->subframe_fx = 0;
811 0 : move16();
812 0 : hPlcInfo->nbLostCmpt = (Word16) L_deposit_l( 0 );
813 0 : move16();
814 0 : hPlcInfo->seed = 21845;
815 0 : move16();
816 :
817 0 : FOR( i = 0; i < TCX_TONALITY_INIT_CNT; i++ )
818 : {
819 0 : hPlcInfo->TCX_Tonality[i] = 1;
820 0 : move16();
821 : }
822 0 : FOR( i = TCX_TONALITY_INIT_CNT; i < DEC_STATE_LEN; i++ )
823 : {
824 0 : hPlcInfo->TCX_Tonality[i] = 0;
825 0 : move16();
826 : }
827 :
828 0 : FOR( i = 0; i < MAX_POST_LEN; i++ )
829 : {
830 0 : hPlcInfo->Transient[i] = 1;
831 0 : move16();
832 : }
833 :
834 0 : FOR( i = 0; i < L_FRAME_MAX; i++ )
835 : {
836 0 : hPlcInfo->data_reci2_fx[i] = L_deposit_l( 0 );
837 : }
838 :
839 0 : return;
840 : }
841 :
842 :
843 0 : void concealment_init_ivas_fx(
844 : const Word16 L_frameTCX,
845 : T_PLCInfo_HANDLE hPlcInfo )
846 : {
847 : Word16 i;
848 :
849 0 : hPlcInfo->L_frameTCX = L_frameTCX;
850 0 : move16();
851 0 : hPlcInfo->Pitch_fx = 0;
852 0 : move16();
853 0 : hPlcInfo->T_bfi_fx = 0;
854 0 : move16();
855 0 : hPlcInfo->outx_new_n1_fx = 0;
856 0 : move16();
857 0 : hPlcInfo->nsapp_gain_fx = 0;
858 0 : move16();
859 0 : hPlcInfo->nsapp_gain_n_fx = 0;
860 0 : move16();
861 0 : hPlcInfo->ener_mean_fx = L_deposit_l( 15213 );
862 0 : hPlcInfo->ener_fx = L_deposit_l( 0 );
863 0 : hPlcInfo->zp_fx = L_frameTCX;
864 0 : move16();
865 0 : hPlcInfo->recovery_gain = 0;
866 0 : move16();
867 0 : hPlcInfo->step_concealgain_fx = 0;
868 0 : move16();
869 0 : hPlcInfo->concealment_method = TCX_NONTONAL;
870 0 : move16();
871 0 : hPlcInfo->subframe_fx = 0;
872 0 : move16();
873 0 : hPlcInfo->nbLostCmpt = (Word16) L_deposit_l( 0 );
874 0 : move16();
875 0 : hPlcInfo->seed = RANDOM_INITSEED;
876 0 : move16();
877 :
878 0 : FOR( i = 0; i < TCX_TONALITY_INIT_CNT; i++ )
879 : {
880 0 : hPlcInfo->TCX_Tonality[i] = 1;
881 0 : move16();
882 : }
883 0 : FOR( i = TCX_TONALITY_INIT_CNT; i < DEC_STATE_LEN; i++ )
884 : {
885 0 : hPlcInfo->TCX_Tonality[i] = 0;
886 0 : move16();
887 : }
888 0 : FOR( i = 0; i < MAX_POST_LEN; i++ )
889 : {
890 0 : hPlcInfo->Transient[i] = 1;
891 0 : move16();
892 : }
893 :
894 0 : FOR( i = 0; i < L_FRAME_MAX; i++ )
895 : {
896 0 : hPlcInfo->data_reci2_fx[i] = L_deposit_l( 0 );
897 0 : move32();
898 : }
899 0 : return;
900 : }
901 :
902 0 : static Word16 own_random_fix( /* o : output random value */
903 : Word16 *seed /* i/o: random seed Q0 */
904 : )
905 : {
906 0 : *seed = extract_l( L_mac0( 13849L, *seed, 31821 ) );
907 0 : return ( *seed );
908 : }
909 :
910 0 : void concealment_decode_fix(
911 : Word16 curr_mode,
912 : Word32 *invkoef /*Qinvkoef_scale*/,
913 : Word16 *invkoef_scale,
914 : T_PLCInfo_HANDLE hPlcInfo )
915 : {
916 : Word16 i;
917 0 : Word16 N = hPlcInfo->L_frameTCX;
918 0 : Word16 *seed = &( hPlcInfo->seed );
919 : Word16 sign;
920 0 : move16();
921 :
922 0 : IF( hPlcInfo->concealment_method == TCX_NONTONAL ) /* #define TCX_NONTONAL 0 */
923 : {
924 0 : IF( EQ_16( curr_mode, 1 ) )
925 : {
926 : /* copy the data of the last frame */
927 0 : MVR2R_WORD32( hPlcInfo->data_reci2_fx, invkoef, N );
928 0 : *invkoef_scale = hPlcInfo->data_reci2_scale;
929 0 : move16();
930 : /* sign randomization */
931 0 : FOR( i = 0; i < N; i++ )
932 : {
933 0 : sign = add( shl( shr( own_random_fix( seed ), 15 ), 1 ), 1 );
934 0 : if ( EQ_16( sign, -1 ) )
935 : {
936 0 : invkoef[i] = L_negate( invkoef[i] );
937 0 : move32();
938 : }
939 : }
940 : }
941 : }
942 :
943 0 : return;
944 : }
945 :
946 :
947 0 : Word16 Spl_GetScalingSquare_x( const Word16 *in_vector /*Qin_vector*/, const Word16 in_vector_length, Word16 times ) /*o : Q0*/
948 : {
949 0 : Word16 nbits = sub( 15, norm_s( times ) ) /*Spl_GetSizeInBits_x(times)*/;
950 : Word16 i;
951 0 : Word16 smax = -1;
952 : Word16 sabs;
953 0 : const Word16 *sptr = in_vector;
954 : Word16 t;
955 0 : move16();
956 0 : FOR( i = in_vector_length; i > 0; i-- )
957 : {
958 :
959 0 : sabs = abs_s( *sptr );
960 0 : sptr++;
961 0 : smax = s_max( sabs, smax );
962 : }
963 :
964 0 : t = norm_l( L_mult0( smax, smax ) );
965 :
966 0 : IF( smax == 0 )
967 : {
968 0 : return 0; /* Since norm(0) returns 0 */
969 : }
970 : ELSE
971 : {
972 0 : nbits = sub( nbits, t );
973 0 : nbits = s_max( 0, nbits );
974 :
975 0 : return nbits;
976 : }
977 : }
978 :
979 :
980 0 : Word32 Spl_Energy_x( const Word16 *vector /*Qvector*/, const Word16 vector_length, Word16 *scale_factor )
981 : {
982 0 : Word32 en = L_deposit_l( 0 );
983 : Word32 i;
984 0 : Word16 scaling = Spl_GetScalingSquare_x( vector, vector_length, vector_length );
985 :
986 0 : FOR( i = 0; i < vector_length; i++ )
987 : {
988 0 : en = L_add( en, L_shr( L_mult0( vector[i], vector[i] ), scaling ) );
989 : }
990 :
991 0 : move32();
992 0 : *scale_factor = scaling;
993 :
994 0 : return en;
995 : }
996 :
997 0 : void Log10OfEnergy_x( const Word16 *s /* Qs */, Word32 *enerlogval /* Q8 */, const Word16 len )
998 : {
999 0 : Word32 energy = L_deposit_l( 0 ), tmp2 = L_deposit_l( 0 );
1000 0 : Word16 shfts = 0;
1001 0 : Word32 Log10_energy = L_deposit_l( 0 ), Log10_len = L_deposit_l( 0 );
1002 0 : move16();
1003 0 : energy = Spl_Energy_x( s, len, &shfts ); /* Q:-shfts */
1004 0 : IF( energy > 0 )
1005 : {
1006 0 : Log10_energy = con_Log10( energy, negate( shfts ) ); /* Q25 */
1007 0 : Log10_len = con_Log10( L_deposit_l( len ), 0 ); /* Q25 */
1008 0 : tmp2 = L_sub( Log10_energy, Log10_len ); /* Q25 */
1009 0 : tmp2 = Mpy_32_16_1( tmp2, 20480 ); /* Q11->10 Q=25+11-15=21 */
1010 0 : *enerlogval = L_shr( tmp2, 13 ); /* Q8 */
1011 0 : move32();
1012 : }
1013 : ELSE
1014 : {
1015 0 : *enerlogval = -25600;
1016 0 : move32();
1017 : }
1018 0 : }
1019 :
1020 0 : static Word32 fnLog2( Word32 L_Input /*QL_Input*/ ) /*o :Q26*/
1021 : {
1022 :
1023 0 : Word16 swC0 = -0x2b2a, swC1 = 0x7fc5, swC2 = -0x54d0;
1024 : Word16 siShIFtCnt, swInSqrd, swIn;
1025 : Word32 LwIn;
1026 0 : move16();
1027 0 : move16();
1028 0 : move16();
1029 : /*_________________________________________________________________________
1030 : | |
1031 : | Executable Code |
1032 : |_________________________________________________________________________|
1033 : */
1034 :
1035 : /* normalize input and store shIFts required */
1036 : /* ----------------------------------------- */
1037 :
1038 0 : siShIFtCnt = norm_l( L_Input );
1039 0 : LwIn = L_shl( L_Input, siShIFtCnt );
1040 0 : siShIFtCnt = add( siShIFtCnt, 1 );
1041 0 : siShIFtCnt = negate( siShIFtCnt );
1042 :
1043 : /* calculate x*x*c0 */
1044 : /* ---------------- */
1045 :
1046 0 : swIn = extract_h( LwIn );
1047 0 : swInSqrd = mult_r( swIn, swIn );
1048 0 : LwIn = L_mult( swInSqrd, swC0 );
1049 :
1050 : /* add x*c1 */
1051 : /* --------- */
1052 :
1053 0 : LwIn = L_mac( LwIn, swIn, swC1 );
1054 :
1055 : /* add c2 */
1056 : /* ------ */
1057 :
1058 0 : LwIn = L_add( LwIn, L_deposit_h( swC2 ) );
1059 :
1060 : /* apply *(4/32) */
1061 : /* ------------- */
1062 :
1063 0 : LwIn = L_shr( LwIn, 3 );
1064 0 : LwIn = L_and( LwIn, 0x03ffffff );
1065 0 : siShIFtCnt = shl( siShIFtCnt, 10 );
1066 0 : LwIn = L_add( LwIn, L_deposit_h( siShIFtCnt ) );
1067 :
1068 : /* return log2 */
1069 : /* ----------- */
1070 :
1071 0 : return ( LwIn );
1072 : }
1073 :
1074 0 : static Word32 fnLog10( Word32 L_Input /*QL_Input*/ ) /*o :Q26*/
1075 : {
1076 :
1077 0 : Word16 Scale = 9864; /* 0.30103 = log10(2) */
1078 : Word32 LwIn;
1079 0 : move16();
1080 : /*_________________________________________________________________________
1081 : | |
1082 : | Executable Code |
1083 : |_________________________________________________________________________|
1084 : */
1085 :
1086 : /* 0.30103*log2(x) */
1087 : /* ------------------- */
1088 :
1089 0 : LwIn = fnLog2( L_Input );
1090 0 : LwIn = Mpy_32_16_1( LwIn, Scale );
1091 :
1092 0 : return ( LwIn );
1093 : }
1094 :
1095 0 : Word32 con_Log10( Word32 i_s32Val /*Qi_s32Val*/, Word16 i_s16Q /*Q0*/ ) /*o; Q26*/
1096 : {
1097 : Word32 s32Out;
1098 : Word32 s32Correct; /* corrected (31-q)*log10(2) */
1099 0 : const Word16 s16Log10_2 = 19728; /* log10(2)~Q16 */
1100 0 : move16();
1101 :
1102 0 : IF( 0 == i_s32Val )
1103 : {
1104 0 : return EVS_LW_MIN;
1105 : }
1106 :
1107 0 : s32Out = fnLog10( i_s32Val ); /* (2^26)*log10(a) */
1108 :
1109 0 : s32Correct = L_mult( sub( 31, i_s16Q ), s16Log10_2 ); /* q = 17 */
1110 0 : s32Correct = L_shl( s32Correct, 8 ); /* q = 25 */
1111 0 : s32Out = L_shr( s32Out, 1 ); /* q = 25 */
1112 :
1113 0 : s32Out = L_add( s32Out, s32Correct );
1114 :
1115 0 : return s32Out;
1116 : }
1117 :
1118 0 : void concealment_update2_x(
1119 : const Word16 *outx_new /*Qoutx_new*/,
1120 : T_PLCInfo_HANDLE hPlcInfo,
1121 : const Word16 FrameSize )
1122 : {
1123 0 : hPlcInfo->zp_fx = zero_pass_w32_x( outx_new, FrameSize );
1124 0 : move16();
1125 :
1126 0 : Log10OfEnergy_x( outx_new, &hPlcInfo->ener_fx, FrameSize ); /* Q8 */
1127 0 : test();
1128 0 : IF( LT_16( hPlcInfo->zp_fx, 100 ) && GT_32( hPlcInfo->ener_fx, L_shl( 50, 8 ) ) )
1129 : {
1130 0 : hPlcInfo->ener_mean_fx = L_add( Mpy_32_16_1( hPlcInfo->ener_mean_fx, 32112 /* 0.98 Q15 */ ),
1131 : Mpy_32_16_1( hPlcInfo->ener_fx, 655 /* 0.02 Q15 */ ) );
1132 0 : move32();
1133 : }
1134 :
1135 0 : return;
1136 : }
1137 :
1138 0 : static Word16 array_max_indx_fx(
1139 : Word16 *s /*Qs*/,
1140 : Word16 N )
1141 : {
1142 0 : Word16 i, indx = 0;
1143 0 : move16();
1144 0 : FOR( i = 0; i < N; i++ )
1145 : {
1146 0 : if ( GT_16( s[i], s[indx] ) )
1147 : {
1148 0 : indx = i;
1149 0 : move16();
1150 : }
1151 : }
1152 0 : return indx;
1153 : }
1154 :
1155 0 : Word16 ffr_getSfWord16( /* o: measured headroom in range [0..15], 0 IF all x[i] == 0 */
1156 : Word16 *x, /* i: array containing 16-bit data Qx*/
1157 : Word16 len_x ) /* i: length of the array to scan */
1158 : {
1159 : Word16 i, i_min, i_max;
1160 : Word16 x_min, x_max;
1161 :
1162 :
1163 0 : x_max = 0;
1164 0 : move16();
1165 0 : x_min = 0;
1166 0 : move16();
1167 0 : FOR( i = 0; i < len_x; i++ )
1168 : {
1169 0 : if ( x[i] >= 0 )
1170 : {
1171 0 : x_max = s_max( x_max, x[i] );
1172 : }
1173 0 : if ( x[i] < 0 )
1174 : {
1175 0 : x_min = s_min( x_min, x[i] );
1176 : }
1177 : }
1178 :
1179 0 : i_max = 0x10;
1180 0 : move16();
1181 0 : i_min = 0x10;
1182 0 : move16();
1183 :
1184 0 : if ( x_max != 0 )
1185 : {
1186 0 : i_max = norm_s( x_max );
1187 : }
1188 :
1189 0 : if ( x_min != 0 )
1190 : {
1191 0 : i_min = norm_s( x_min );
1192 : }
1193 :
1194 0 : i = s_and( s_min( i_max, i_min ), 0xF );
1195 :
1196 :
1197 0 : return i;
1198 : }
1199 :
1200 0 : static Word16 OverlapAdd_fx( Word16 *pitch125_data /*Qx*/, Word16 *sbuf /*Qx*/, Word16 n, Word16 pitch /*Q0*/, Word16 Framesize )
1201 : {
1202 : Word16 n1, n2, s, s16MaxCoefNorm, s16MaxCoefNorm2, tmp16;
1203 : Word16 i;
1204 0 : Word16 pitch125 = extract_l( L_shr( L_add( L_add( L_deposit_h( pitch ), L_mult( pitch, 8192 ) ), 32768 ), 16 ) );
1205 0 : Word16 Loverlap = sub( pitch125, pitch );
1206 0 : Word16 Framesize_sub_n = sub( Framesize, n );
1207 :
1208 0 : n1 = Framesize_sub_n;
1209 0 : move16();
1210 0 : n2 = Framesize_sub_n;
1211 0 : move16();
1212 0 : if ( LT_16( Loverlap, Framesize_sub_n ) )
1213 : {
1214 0 : n1 = Loverlap;
1215 0 : move16();
1216 : }
1217 0 : if ( LT_16( pitch125, Framesize_sub_n ) )
1218 : {
1219 0 : n2 = pitch125;
1220 0 : move16();
1221 : }
1222 0 : s16MaxCoefNorm = sub( ffr_getSfWord16( sbuf + n, n1 ), 1 );
1223 0 : s16MaxCoefNorm2 = ffr_getSfWord16( pitch125_data, n1 );
1224 0 : Loverlap = s_max( 1, Loverlap );
1225 0 : tmp16 = BASOP_Util_Divide1616_Scale( 1, Loverlap, &s );
1226 0 : FOR( i = 0; i < n1; i++ )
1227 : {
1228 : Word16 tmp;
1229 : Word16 dat;
1230 0 : dat = shl( sbuf[add( n, i )], s16MaxCoefNorm );
1231 0 : tmp = extract_l( L_shl( L_mult0( i, tmp16 ), s ) ); /* q15 */
1232 0 : sbuf[add( n, i )] = round_fx( L_add( L_shr( L_mult( dat, sub( 32767, tmp ) ), s16MaxCoefNorm ),
1233 0 : L_shr( L_mult( shl( pitch125_data[i], s16MaxCoefNorm2 ), tmp ), s16MaxCoefNorm2 ) ) );
1234 : }
1235 :
1236 0 : FOR( i = n1; i < n2; i++ )
1237 : {
1238 0 : sbuf[add( n, i )] = pitch125_data[i];
1239 0 : move16();
1240 : }
1241 :
1242 0 : pitch = add( n, pitch );
1243 :
1244 0 : return pitch;
1245 : }
1246 :
1247 0 : static void add_noise( Word16 *const sbuf, /*Qsbuf*/
1248 : Word16 *const outx_new_n1, /*Q0*/
1249 : Word16 const *const noise_seg, /*Q0*/
1250 : Word16 const Len,
1251 : Word16 *const gain, /*Q15*/
1252 : Word16 const *const gain_n, /*Q15*/
1253 : Word8 const firstFrame )
1254 : {
1255 : Word16 i;
1256 : Word16 temp_OUT;
1257 :
1258 0 : IF( !firstFrame )
1259 : {
1260 0 : temp_OUT = sub_sat( noise_seg[0], mult( ( *outx_new_n1 ), 22282 /* 0.68 Q15 */ ) );
1261 0 : sbuf[0] = add_sat( sbuf[0], mult( ( temp_OUT ), *gain ) );
1262 0 : move16();
1263 0 : *gain = mac_r_sat( L_mult_sat( 32439 /* 0.99 Q15 */, *gain ), 328 /* 0.01 Q15 */, *gain_n );
1264 : }
1265 :
1266 0 : FOR( i = 1; i < Len; i++ )
1267 : {
1268 0 : temp_OUT = sub_sat( noise_seg[i], mult( ( noise_seg[i - 1] ), 22282 /* 0.68 Q15 */ ) );
1269 0 : sbuf[i] = add_sat( sbuf[i], mult( ( temp_OUT ), *gain ) );
1270 0 : move16();
1271 0 : *gain = mac_r_sat( L_mult( 32439 /* 0.99 Q15 */, *gain ), 328 /* 0.01 Q15 */, *gain_n );
1272 : }
1273 :
1274 0 : *outx_new_n1 = noise_seg[i - 1]; /*q0*/
1275 0 : move16();
1276 :
1277 0 : return;
1278 : }
1279 :
1280 0 : static Word16 waveform_adj_fix(
1281 : T_PLCInfo_HANDLE hPlcInfo,
1282 : Word16 *overlapbuf, /*Qoverlapbuf*/
1283 : Word16 *outdata2, /*Qoutdata2*/
1284 : Word16 *outx_new, /*Qoutx_new*/
1285 : const Word16 Framesize,
1286 : const Word16 voicing, /*Q15*/
1287 : const Word16 core )
1288 : {
1289 : Word16 i, zp1, zp2, Framesizediv2, s16MaxCoefNorm, pitch;
1290 : Word16 sbuf[L_FRAME_MAX];
1291 : Word16 tmp;
1292 :
1293 0 : Framesizediv2 = shr( Framesize, 1 );
1294 0 : zp1 = zero_pass_w32_x( outdata2, Framesizediv2 );
1295 0 : zp2 = zero_pass_w32_x( outdata2 + Framesizediv2, Framesizediv2 );
1296 :
1297 0 : pitch = hPlcInfo->Pitch_fx;
1298 :
1299 : /* judge if the pitch is usable */
1300 0 : tmp = 1;
1301 0 : move16();
1302 0 : if ( GT_16( zp1, 1 ) )
1303 : {
1304 0 : tmp = zp1;
1305 0 : move16();
1306 : }
1307 0 : IF( LT_16( shl( tmp, 2 ), zp2 ) )
1308 : {
1309 0 : move16();
1310 0 : return 0;
1311 : }
1312 :
1313 : /* adjust the pitch value */
1314 0 : test();
1315 0 : test();
1316 0 : test();
1317 0 : IF( hPlcInfo->T_bfi_fx && ( LE_16( pitch, Framesizediv2 ) ) && ( GT_16( Framesize, 256 ) ) && ( EQ_16( core, 1 ) ) )
1318 : {
1319 0 : Word16 i1 = 0, i2 = 0;
1320 : Word16 pos1, pos2, pos3;
1321 0 : move16();
1322 0 : move16();
1323 0 : i1 = add( 1, array_max_indx_fx( outx_new, pitch ) );
1324 0 : i2 = add( 1, array_max_indx_fx( outx_new + pitch, pitch ) );
1325 :
1326 0 : pos1 = add( i2, sub( pitch, i1 ) );
1327 0 : pos3 = add( pos1, mult( pos1, 8192 /* 0.25 Q15 */ ) );
1328 0 : pos2 = add( pitch, mult( pitch, 8192 /* 0.25 Q15 */ ) );
1329 :
1330 0 : test();
1331 0 : test();
1332 0 : if ( ( LT_16( pos1, pos2 ) ) && ( GT_16( pos3, pitch ) ) && ( LT_16( pos1, Framesizediv2 ) ) )
1333 : {
1334 0 : pitch = add( i2, sub( pitch, i1 ) );
1335 : }
1336 : }
1337 :
1338 : {
1339 0 : Word16 pitch125 = 0, Loverlap = 0, n = 0;
1340 : Word16 pitch125_data[L_FRAME_MAX];
1341 0 : move16();
1342 0 : move16();
1343 0 : move16();
1344 0 : pitch125 = extract_l( ( L_shr( L_add( L_add( L_deposit_h( pitch ), L_mult( pitch, 8192 ) ), 32768 ), 16 ) ) );
1345 0 : Loverlap = sub( pitch125, pitch );
1346 0 : FOR( i = 0; i < pitch; i++ )
1347 : {
1348 0 : pitch125_data[i] = outdata2[add( sub( Framesize, pitch ), i )];
1349 0 : move16();
1350 : }
1351 0 : FOR( i = 0; i < Loverlap; i++ )
1352 : {
1353 0 : pitch125_data[add( pitch, i )] = outx_new[i];
1354 0 : move16();
1355 : }
1356 0 : FOR( i = 0; i < Framesize; i++ )
1357 : {
1358 0 : sbuf[i] = outx_new[i];
1359 0 : move16();
1360 : }
1361 :
1362 : {
1363 : Word16 pitch125a1;
1364 0 : Word16 tmp_buf[2 * L_FRAME_MAX], *p_tmp = tmp_buf + 1;
1365 :
1366 0 : FOR( i = 0; i < pitch125; i++ )
1367 : {
1368 0 : p_tmp[i] = pitch125_data[i];
1369 0 : move16();
1370 : }
1371 :
1372 0 : p_tmp[-1] = outdata2[sub( sub( Framesize, pitch ), 1 )];
1373 0 : move16();
1374 0 : p_tmp[pitch125] = outx_new[Loverlap];
1375 0 : move16();
1376 0 : pitch125a1 = add( pitch125, 1 );
1377 0 : s16MaxCoefNorm = sub( ffr_getSfWord16( p_tmp - 1, pitch125a1 ), 1 );
1378 0 : FOR( i = 0; i < pitch125a1; i++ )
1379 : {
1380 0 : p_tmp[i - 1] = shl( p_tmp[i - 1], s16MaxCoefNorm );
1381 0 : move16();
1382 : }
1383 0 : FOR( i = 0; i < pitch125; i++ )
1384 : {
1385 0 : pitch125_data[i] = round_fx_sat( L_shr_sat( L_add_sat( ( L_mult( p_tmp[i], 20972 ) ), L_mac_sat( L_mult( p_tmp[i - 1], 5898 ), p_tmp[i + 1], 5898 ) ), s16MaxCoefNorm ) );
1386 0 : move16();
1387 : }
1388 : }
1389 :
1390 0 : WHILE( LT_16( n, Framesize ) ) /* periodical extension */
1391 : {
1392 0 : n = OverlapAdd_fx( pitch125_data, sbuf, n, pitch, Framesize );
1393 : }
1394 :
1395 : /* maximum pitch lag is 3/4 Framesize; pitch125_data is reused for
1396 : temporary storage, since outdata2 (holding the pcm data of the
1397 : last good frame) is still needed and overlapbuf overlaps outdata2 */
1398 0 : Copy( &sbuf[Framesize / 4], pitch125_data, shr( imult1616( 3, Framesize ), 2 ) );
1399 :
1400 0 : hPlcInfo->nsapp_gain_fx = 0;
1401 0 : move16();
1402 0 : hPlcInfo->nsapp_gain_n_fx = sub( 32767, shr( voicing, 1 ) ); /* q15 */
1403 0 : tmp = Framesize;
1404 0 : move16();
1405 :
1406 : /* use last good signal for noise generation */
1407 0 : add_noise( sbuf, &( hPlcInfo->outx_new_n1_fx ), outdata2, tmp, &( hPlcInfo->nsapp_gain_fx ), &( hPlcInfo->nsapp_gain_n_fx ), 1 );
1408 :
1409 : /* save current (noisy) output from IMDCT */
1410 0 : MVR2R_WORD16( outx_new, hPlcInfo->data_noise, tmp );
1411 :
1412 : /* overlapbuf can now be filled with sbuf, needed for subsequently lost frames */
1413 0 : Copy( pitch125_data, &overlapbuf[Framesize / 4], shr( imult1616( 3, Framesize ), 2 ) );
1414 : }
1415 0 : FOR( i = 0; i < Framesize; i++ )
1416 : {
1417 0 : outx_new[i] = sbuf[i];
1418 0 : move16();
1419 : }
1420 :
1421 0 : return pitch;
1422 : }
1423 :
1424 :
1425 0 : void waveform_adj2_fix(
1426 : T_PLCInfo_HANDLE hPlcInfo,
1427 : Word16 *overlapbuf, /*Qoverlapbuf*/
1428 : Word16 *outx_new, /*Qoutx_new*/
1429 : const Word16 delay,
1430 : const Word16 bfi_cnt,
1431 : const Word16 bfi )
1432 : {
1433 : Word16 i, n, tablescale, ratio, dat, Framesizesubn, Framesizesubp, tmp16, s, ptable, temp_OUT, s16MaxCoefNorm, s16MaxCoefNorm2;
1434 : Word16 sbuf[L_FRAME_MAX];
1435 : Word16 pitch, L_frameTCX;
1436 :
1437 0 : pitch = hPlcInfo->Pitch_fx;
1438 0 : move16();
1439 0 : L_frameTCX = hPlcInfo->L_frameTCX;
1440 0 : move16();
1441 0 : n = 0;
1442 0 : move16();
1443 0 : Framesizesubn = sub( L_frameTCX, n );
1444 0 : Framesizesubp = sub( L_frameTCX, pitch );
1445 0 : IF( pitch > 0 )
1446 : {
1447 0 : WHILE( Framesizesubn > 0 )
1448 : {
1449 : /* periodical extension */
1450 0 : Word16 tmp = vadmin( pitch, Framesizesubn );
1451 0 : FOR( i = 0; i < tmp; i++ )
1452 : {
1453 0 : sbuf[add( n, i )] = overlapbuf[add( Framesizesubp, i )];
1454 0 : move16();
1455 : }
1456 0 : n = add( n, pitch );
1457 0 : Framesizesubn = sub( L_frameTCX, n );
1458 : }
1459 :
1460 0 : FOR( i = 0; i < L_frameTCX; i++ )
1461 : {
1462 0 : overlapbuf[i] = sbuf[i];
1463 0 : move16();
1464 : }
1465 :
1466 : {
1467 0 : Word16 size = L_frameTCX;
1468 0 : Word16 *noise_ptr = hPlcInfo->data_noise;
1469 0 : move16();
1470 : /* use last (noisy) output from IMDCT for noise generation */
1471 0 : add_noise( sbuf, &( hPlcInfo->outx_new_n1_fx ), noise_ptr, size, &( hPlcInfo->nsapp_gain_fx ), &( hPlcInfo->nsapp_gain_n_fx ), 0 );
1472 :
1473 : /* save current (noisy) output from IMDCT */
1474 0 : IF( bfi )
1475 : {
1476 0 : MVR2R_WORD16( outx_new, noise_ptr, size );
1477 : }
1478 : }
1479 0 : test();
1480 0 : IF( EQ_16( bfi_cnt, 4 ) || bfi == 0 )
1481 : {
1482 0 : SWITCH( L_frameTCX )
1483 : {
1484 0 : case 160:
1485 : {
1486 0 : tablescale = 8;
1487 0 : move16();
1488 0 : ptable = 26214; /* (Word16)(32767*256/160.0+0.5); q7+15 */
1489 0 : move16();
1490 0 : BREAK;
1491 : }
1492 0 : case 320:
1493 : {
1494 0 : tablescale = 9;
1495 0 : move16();
1496 0 : ptable = 26214; /* (Word16)(32767*256/320.0+0.5); q8+15 */
1497 0 : move16();
1498 0 : BREAK;
1499 : }
1500 0 : case 512:
1501 : {
1502 0 : tablescale = 10;
1503 0 : move16();
1504 0 : ptable = 32767; /* q9+15 */
1505 0 : move16();
1506 0 : BREAK;
1507 : }
1508 0 : case 640:
1509 : {
1510 0 : tablescale = 10;
1511 0 : move16();
1512 0 : ptable = 26214; /* (Word16)(32767*512/640.0+0.5); q9+15 */
1513 0 : move16();
1514 0 : BREAK;
1515 : }
1516 0 : default: /* 960 */
1517 : {
1518 0 : tablescale = 10;
1519 0 : move16();
1520 0 : ptable = 17456; /* (Word16)(32767*512/960.0); q9+15 */
1521 0 : move16();
1522 0 : BREAK;
1523 : }
1524 : }
1525 0 : IF( bfi == 0 ) /* overlap-and-add */
1526 : {
1527 0 : Word16 gain_zero_start = 10000;
1528 0 : move16();
1529 :
1530 0 : IF( hPlcInfo->step_concealgain_fx > 0 )
1531 : {
1532 0 : gain_zero_start = BASOP_Util_Divide1616_Scale( hPlcInfo->recovery_gain, hPlcInfo->step_concealgain_fx, &s );
1533 0 : gain_zero_start = shl( gain_zero_start, sub( s, 14 ) ); /* q0 */
1534 0 : gain_zero_start = add( gain_zero_start, 1 );
1535 : }
1536 :
1537 0 : if ( delay > 0 )
1538 : {
1539 0 : L_frameTCX = sub( L_frameTCX, delay );
1540 : }
1541 :
1542 0 : s16MaxCoefNorm = sub( ffr_getSfWord16( sbuf, L_frameTCX ), 1 );
1543 0 : s16MaxCoefNorm2 = ffr_getSfWord16( outx_new, L_frameTCX );
1544 0 : tmp16 = vadmin( gain_zero_start, L_frameTCX );
1545 0 : FOR( i = 0; i < tmp16; i++ )
1546 : {
1547 0 : ratio = extract_l( L_shr( L_mult( i, ptable ), tablescale ) );
1548 0 : dat = shl( sbuf[i], s16MaxCoefNorm );
1549 0 : temp_OUT = mult( hPlcInfo->recovery_gain, sub( 32767, ratio ) );
1550 0 : outx_new[i] = round_fx_sat( L_add_sat( L_shr_sat( L_mult( temp_OUT, dat ), sub( s16MaxCoefNorm, 1 ) ), L_shr_sat( L_mult( shl( outx_new[i], s16MaxCoefNorm2 ), ratio ), s16MaxCoefNorm2 ) ) );
1551 0 : move16();
1552 0 : hPlcInfo->recovery_gain = sub_sat( hPlcInfo->recovery_gain, shr_r( hPlcInfo->step_concealgain_fx, 1 ) ); /* q14 */
1553 : }
1554 0 : FOR( i = gain_zero_start; i < L_frameTCX; i++ )
1555 : {
1556 0 : ratio = extract_l( L_shr( L_mult( i, ptable ), tablescale ) );
1557 0 : outx_new[i] = round_fx_sat( L_shr_sat( L_mult( shl( outx_new[i], s16MaxCoefNorm2 ), ratio ), s16MaxCoefNorm2 ) );
1558 0 : move16();
1559 : }
1560 :
1561 0 : if ( hPlcInfo->recovery_gain < 0 )
1562 : {
1563 0 : hPlcInfo->recovery_gain = 0;
1564 0 : move16();
1565 : }
1566 : }
1567 : ELSE
1568 : {
1569 : /* overlap-and-add */
1570 : Word16 tmp;
1571 0 : s16MaxCoefNorm = sub( ffr_getSfWord16( sbuf, L_frameTCX ), 1 );
1572 0 : s16MaxCoefNorm2 = ffr_getSfWord16( outx_new, L_frameTCX );
1573 0 : FOR( i = 0; i < L_frameTCX; i++ )
1574 : {
1575 0 : dat = shl( sbuf[i], s16MaxCoefNorm );
1576 0 : tmp = extract_l( L_shr( L_mult( i, ptable ), tablescale ) );
1577 0 : outx_new[i] = round_fx( L_add( L_shr( L_mult( dat, sub( 32767, tmp ) ), s16MaxCoefNorm ), L_shr( L_mult( shl( outx_new[i], s16MaxCoefNorm2 ), tmp ), s16MaxCoefNorm2 ) ) );
1578 0 : move16();
1579 : }
1580 : }
1581 : }
1582 : ELSE
1583 : {
1584 0 : FOR( i = 0; i < L_frameTCX; i++ )
1585 : {
1586 0 : outx_new[i] = sbuf[i];
1587 0 : move16();
1588 : }
1589 : }
1590 : }
1591 0 : return;
1592 : }
1593 :
1594 0 : void concealment_signal_tuning_fx(
1595 : Decoder_State *st,
1596 : const Word16 bfi,
1597 : Word16 *outx_new_fx /*Qoutx_new_fx*/,
1598 : const Word16 past_core )
1599 : {
1600 0 : T_PLCInfo_HANDLE hPlcInfo = st->hPlcInfo;
1601 0 : Word16 L_frameTCX = hPlcInfo->L_frameTCX;
1602 0 : Word16 voicing_fx = 0;
1603 0 : Word16 *OverlapBuf_fx = st->hTonalMDCTConc->secondLastPcmOut;
1604 0 : Word16 *outdata2_fx = st->hTonalMDCTConc->lastPcmOut;
1605 0 : move16();
1606 0 : move16();
1607 0 : move16();
1608 0 : move16();
1609 :
1610 0 : IF( bfi )
1611 : {
1612 0 : test();
1613 0 : IF( st->enablePlcWaveadjust && hPlcInfo->concealment_method == TCX_NONTONAL ) /* #define TCX_NONTONAL 0 */
1614 : {
1615 0 : IF( EQ_16( st->nbLostCmpt, 1 ) )
1616 : {
1617 0 : hPlcInfo->Pitch_fx = pitch_search_fx( outdata2_fx, outx_new_fx, L_frameTCX, &voicing_fx, hPlcInfo->zp_fx, ( hPlcInfo->ener_fx ), ( hPlcInfo->ener_mean_fx ), hPlcInfo->data_reci2_fx, st->core );
1618 0 : move16();
1619 :
1620 0 : IF( hPlcInfo->Pitch_fx ) /* waveform adjustment for the first lost frame */
1621 : {
1622 0 : hPlcInfo->Pitch_fx = waveform_adj_fix( hPlcInfo, OverlapBuf_fx, outdata2_fx, outx_new_fx, L_frameTCX, voicing_fx, st->core );
1623 0 : move16();
1624 : }
1625 : }
1626 0 : ELSE IF( LT_16( st->nbLostCmpt, 5 ) ) /* waveform adjustment for the 2nd~4th lost frame */
1627 : {
1628 0 : waveform_adj2_fix( hPlcInfo, OverlapBuf_fx, outx_new_fx, 0, st->nbLostCmpt, bfi );
1629 : }
1630 : }
1631 0 : hPlcInfo->T_bfi_fx = 1;
1632 0 : move16();
1633 : }
1634 : ELSE
1635 : {
1636 0 : test();
1637 0 : test();
1638 0 : test();
1639 0 : IF( st->prev_bfi &&
1640 : past_core != ACELP_CORE &&
1641 : GE_32( st->last_total_brate, 48000 ) &&
1642 : EQ_16( st->last_codec_mode, MODE2 ) )
1643 : {
1644 0 : IF( hPlcInfo->concealment_method == TCX_NONTONAL ) /* #define TCX_NONTONAL 0 */
1645 : {
1646 0 : IF( LT_32( hPlcInfo->nbLostCmpt, 4 ) ) /* smoothing of the concealed signal with the good signal */
1647 : {
1648 0 : waveform_adj2_fix( hPlcInfo, OverlapBuf_fx, outx_new_fx, 0, add( extract_l( hPlcInfo->nbLostCmpt ), 1 ), bfi );
1649 : }
1650 : }
1651 : }
1652 : ELSE
1653 : {
1654 0 : hPlcInfo->T_bfi_fx = 0;
1655 0 : move16();
1656 : }
1657 : }
1658 0 : return;
1659 : }
|