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 0 : Word16 sign = 0;
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 : Word16 rnd;
934 0 : rnd = own_random_fix( seed );
935 0 : IF( GE_16( rnd, 0 ) )
936 : {
937 0 : sign = 1;
938 : }
939 0 : ELSE IF( LT_16( rnd, 0 ) )
940 : {
941 0 : sign = -1;
942 : }
943 0 : if ( EQ_16( sign, -1 ) )
944 : {
945 0 : invkoef[i] = L_negate( invkoef[i] );
946 0 : move32();
947 : }
948 : }
949 : }
950 : }
951 :
952 0 : return;
953 : }
954 :
955 :
956 0 : Word16 Spl_GetScalingSquare_x( const Word16 *in_vector /*Qin_vector*/, const Word16 in_vector_length, Word16 times ) /*o : Q0*/
957 : {
958 0 : Word16 nbits = sub( 15, norm_s( times ) ) /*Spl_GetSizeInBits_x(times)*/;
959 : Word16 i;
960 0 : Word16 smax = -1;
961 : Word16 sabs;
962 0 : const Word16 *sptr = in_vector;
963 : Word16 t;
964 0 : move16();
965 0 : FOR( i = in_vector_length; i > 0; i-- )
966 : {
967 :
968 0 : sabs = abs_s( *sptr );
969 0 : sptr++;
970 0 : smax = s_max( sabs, smax );
971 : }
972 :
973 0 : t = norm_l( L_mult0( smax, smax ) );
974 :
975 0 : IF( smax == 0 )
976 : {
977 0 : return 0; /* Since norm(0) returns 0 */
978 : }
979 : ELSE
980 : {
981 0 : nbits = sub( nbits, t );
982 0 : nbits = s_max( 0, nbits );
983 :
984 0 : return nbits;
985 : }
986 : }
987 :
988 :
989 0 : Word32 Spl_Energy_x( const Word16 *vector /*Qvector*/, const Word16 vector_length, Word16 *scale_factor )
990 : {
991 0 : Word32 en = L_deposit_l( 0 );
992 : Word32 i;
993 0 : Word16 scaling = Spl_GetScalingSquare_x( vector, vector_length, vector_length );
994 :
995 0 : FOR( i = 0; i < vector_length; i++ )
996 : {
997 0 : en = L_add( en, L_shr( L_mult0( vector[i], vector[i] ), scaling ) );
998 : }
999 :
1000 0 : move32();
1001 0 : *scale_factor = scaling;
1002 :
1003 0 : return en;
1004 : }
1005 :
1006 0 : void Log10OfEnergy_x( const Word16 *s /* Qs */, Word32 *enerlogval /* Q8 */, const Word16 len )
1007 : {
1008 0 : Word32 energy = L_deposit_l( 0 ), tmp2 = L_deposit_l( 0 );
1009 0 : Word16 shfts = 0;
1010 0 : Word32 Log10_energy = L_deposit_l( 0 ), Log10_len = L_deposit_l( 0 );
1011 0 : move16();
1012 0 : energy = Spl_Energy_x( s, len, &shfts ); /* Q:-shfts */
1013 0 : IF( energy > 0 )
1014 : {
1015 0 : Log10_energy = con_Log10( energy, negate( shfts ) ); /* Q25 */
1016 0 : Log10_len = con_Log10( L_deposit_l( len ), 0 ); /* Q25 */
1017 0 : tmp2 = L_sub( Log10_energy, Log10_len ); /* Q25 */
1018 0 : tmp2 = Mpy_32_16_1( tmp2, 20480 ); /* Q11->10 Q=25+11-15=21 */
1019 0 : *enerlogval = L_shr( tmp2, 13 ); /* Q8 */
1020 0 : move32();
1021 : }
1022 : ELSE
1023 : {
1024 0 : *enerlogval = -25600;
1025 0 : move32();
1026 : }
1027 0 : }
1028 :
1029 0 : static Word32 fnLog2( Word32 L_Input /*QL_Input*/ ) /*o :Q26*/
1030 : {
1031 :
1032 0 : Word16 swC0 = -0x2b2a, swC1 = 0x7fc5, swC2 = -0x54d0;
1033 : Word16 siShIFtCnt, swInSqrd, swIn;
1034 : Word32 LwIn;
1035 0 : move16();
1036 0 : move16();
1037 0 : move16();
1038 : /*_________________________________________________________________________
1039 : | |
1040 : | Executable Code |
1041 : |_________________________________________________________________________|
1042 : */
1043 :
1044 : /* normalize input and store shIFts required */
1045 : /* ----------------------------------------- */
1046 :
1047 0 : siShIFtCnt = norm_l( L_Input );
1048 0 : LwIn = L_shl( L_Input, siShIFtCnt );
1049 0 : siShIFtCnt = add( siShIFtCnt, 1 );
1050 0 : siShIFtCnt = negate( siShIFtCnt );
1051 :
1052 : /* calculate x*x*c0 */
1053 : /* ---------------- */
1054 :
1055 0 : swIn = extract_h( LwIn );
1056 0 : swInSqrd = mult_r( swIn, swIn );
1057 0 : LwIn = L_mult( swInSqrd, swC0 );
1058 :
1059 : /* add x*c1 */
1060 : /* --------- */
1061 :
1062 0 : LwIn = L_mac( LwIn, swIn, swC1 );
1063 :
1064 : /* add c2 */
1065 : /* ------ */
1066 :
1067 0 : LwIn = L_add( LwIn, L_deposit_h( swC2 ) );
1068 :
1069 : /* apply *(4/32) */
1070 : /* ------------- */
1071 :
1072 0 : LwIn = L_shr( LwIn, 3 );
1073 0 : LwIn = L_and( LwIn, 0x03ffffff );
1074 0 : siShIFtCnt = shl( siShIFtCnt, 10 );
1075 0 : LwIn = L_add( LwIn, L_deposit_h( siShIFtCnt ) );
1076 :
1077 : /* return log2 */
1078 : /* ----------- */
1079 :
1080 0 : return ( LwIn );
1081 : }
1082 :
1083 0 : static Word32 fnLog10( Word32 L_Input /*QL_Input*/ ) /*o :Q26*/
1084 : {
1085 :
1086 0 : Word16 Scale = 9864; /* 0.30103 = log10(2) */
1087 : Word32 LwIn;
1088 0 : move16();
1089 : /*_________________________________________________________________________
1090 : | |
1091 : | Executable Code |
1092 : |_________________________________________________________________________|
1093 : */
1094 :
1095 : /* 0.30103*log2(x) */
1096 : /* ------------------- */
1097 :
1098 0 : LwIn = fnLog2( L_Input );
1099 0 : LwIn = Mpy_32_16_1( LwIn, Scale );
1100 :
1101 0 : return ( LwIn );
1102 : }
1103 :
1104 0 : Word32 con_Log10( Word32 i_s32Val /*Qi_s32Val*/, Word16 i_s16Q /*Q0*/ ) /*o; Q26*/
1105 : {
1106 : Word32 s32Out;
1107 : Word32 s32Correct; /* corrected (31-q)*log10(2) */
1108 0 : const Word16 s16Log10_2 = 19728; /* log10(2)~Q16 */
1109 0 : move16();
1110 :
1111 0 : IF( 0 == i_s32Val )
1112 : {
1113 0 : return EVS_LW_MIN;
1114 : }
1115 :
1116 0 : s32Out = fnLog10( i_s32Val ); /* (2^26)*log10(a) */
1117 :
1118 0 : s32Correct = L_mult( sub( 31, i_s16Q ), s16Log10_2 ); /* q = 17 */
1119 0 : s32Correct = L_shl( s32Correct, 8 ); /* q = 25 */
1120 0 : s32Out = L_shr( s32Out, 1 ); /* q = 25 */
1121 :
1122 0 : s32Out = L_add( s32Out, s32Correct );
1123 :
1124 0 : return s32Out;
1125 : }
1126 :
1127 0 : void concealment_update2_x(
1128 : const Word16 *outx_new /*Qoutx_new*/,
1129 : T_PLCInfo_HANDLE hPlcInfo,
1130 : const Word16 FrameSize )
1131 : {
1132 0 : hPlcInfo->zp_fx = zero_pass_w32_x( outx_new, FrameSize );
1133 0 : move16();
1134 :
1135 0 : Log10OfEnergy_x( outx_new, &hPlcInfo->ener_fx, FrameSize ); /* Q8 */
1136 0 : test();
1137 0 : IF( LT_16( hPlcInfo->zp_fx, 100 ) && GT_32( hPlcInfo->ener_fx, L_shl( 50, 8 ) ) )
1138 : {
1139 0 : hPlcInfo->ener_mean_fx = L_add( Mpy_32_16_1( hPlcInfo->ener_mean_fx, 32112 /* 0.98 Q15 */ ),
1140 : Mpy_32_16_1( hPlcInfo->ener_fx, 655 /* 0.02 Q15 */ ) );
1141 0 : move32();
1142 : }
1143 :
1144 0 : return;
1145 : }
1146 :
1147 0 : static Word16 array_max_indx_fx(
1148 : Word16 *s /*Qs*/,
1149 : Word16 N )
1150 : {
1151 0 : Word16 i, indx = 0;
1152 0 : move16();
1153 0 : FOR( i = 0; i < N; i++ )
1154 : {
1155 0 : if ( GT_16( s[i], s[indx] ) )
1156 : {
1157 0 : indx = i;
1158 0 : move16();
1159 : }
1160 : }
1161 0 : return indx;
1162 : }
1163 :
1164 0 : Word16 ffr_getSfWord16( /* o: measured headroom in range [0..15], 0 IF all x[i] == 0 */
1165 : Word16 *x, /* i: array containing 16-bit data Qx*/
1166 : Word16 len_x ) /* i: length of the array to scan */
1167 : {
1168 : Word16 i, i_min, i_max;
1169 : Word16 x_min, x_max;
1170 :
1171 :
1172 0 : x_max = 0;
1173 0 : move16();
1174 0 : x_min = 0;
1175 0 : move16();
1176 0 : FOR( i = 0; i < len_x; i++ )
1177 : {
1178 0 : if ( x[i] >= 0 )
1179 : {
1180 0 : x_max = s_max( x_max, x[i] );
1181 : }
1182 0 : if ( x[i] < 0 )
1183 : {
1184 0 : x_min = s_min( x_min, x[i] );
1185 : }
1186 : }
1187 :
1188 0 : i_max = 0x10;
1189 0 : move16();
1190 0 : i_min = 0x10;
1191 0 : move16();
1192 :
1193 0 : if ( x_max != 0 )
1194 : {
1195 0 : i_max = norm_s( x_max );
1196 : }
1197 :
1198 0 : if ( x_min != 0 )
1199 : {
1200 0 : i_min = norm_s( x_min );
1201 : }
1202 :
1203 0 : i = s_and( s_min( i_max, i_min ), 0xF );
1204 :
1205 :
1206 0 : return i;
1207 : }
1208 :
1209 0 : static Word16 OverlapAdd_fx( Word16 *pitch125_data /*Qx*/, Word16 *sbuf /*Qx*/, Word16 n, Word16 pitch /*Q0*/, Word16 Framesize )
1210 : {
1211 : Word16 n1, n2, s, s16MaxCoefNorm, s16MaxCoefNorm2, tmp16;
1212 : Word16 i;
1213 0 : Word16 pitch125 = extract_l( L_shr( L_add( L_add( L_deposit_h( pitch ), L_mult( pitch, 8192 ) ), 32768 ), 16 ) );
1214 0 : Word16 Loverlap = sub( pitch125, pitch );
1215 0 : Word16 Framesize_sub_n = sub( Framesize, n );
1216 :
1217 0 : n1 = Framesize_sub_n;
1218 0 : move16();
1219 0 : n2 = Framesize_sub_n;
1220 0 : move16();
1221 0 : if ( LT_16( Loverlap, Framesize_sub_n ) )
1222 : {
1223 0 : n1 = Loverlap;
1224 0 : move16();
1225 : }
1226 0 : if ( LT_16( pitch125, Framesize_sub_n ) )
1227 : {
1228 0 : n2 = pitch125;
1229 0 : move16();
1230 : }
1231 0 : s16MaxCoefNorm = sub( ffr_getSfWord16( sbuf + n, n1 ), 1 );
1232 0 : s16MaxCoefNorm2 = ffr_getSfWord16( pitch125_data, n1 );
1233 0 : Loverlap = s_max( 1, Loverlap );
1234 0 : tmp16 = BASOP_Util_Divide1616_Scale( 1, Loverlap, &s );
1235 0 : FOR( i = 0; i < n1; i++ )
1236 : {
1237 : Word16 tmp;
1238 : Word16 dat;
1239 0 : dat = shl( sbuf[add( n, i )], s16MaxCoefNorm );
1240 0 : tmp = extract_l( L_shl( L_mult0( i, tmp16 ), s ) ); /* q15 */
1241 0 : sbuf[add( n, i )] = round_fx( L_add( L_shr( L_mult( dat, sub( 32767, tmp ) ), s16MaxCoefNorm ),
1242 0 : L_shr( L_mult( shl( pitch125_data[i], s16MaxCoefNorm2 ), tmp ), s16MaxCoefNorm2 ) ) );
1243 : }
1244 :
1245 0 : FOR( i = n1; i < n2; i++ )
1246 : {
1247 0 : sbuf[add( n, i )] = pitch125_data[i];
1248 0 : move16();
1249 : }
1250 :
1251 0 : pitch = add( n, pitch );
1252 :
1253 0 : return pitch;
1254 : }
1255 :
1256 0 : static void add_noise( Word16 *const sbuf, /*Qsbuf*/
1257 : Word16 *const outx_new_n1, /*Q0*/
1258 : Word16 const *const noise_seg, /*Q0*/
1259 : Word16 const Len,
1260 : Word16 *const gain, /*Q15*/
1261 : Word16 const *const gain_n, /*Q15*/
1262 : Word8 const firstFrame )
1263 : {
1264 : Word16 i;
1265 : Word16 temp_OUT;
1266 :
1267 0 : IF( !firstFrame )
1268 : {
1269 0 : temp_OUT = sub_sat( noise_seg[0], mult( ( *outx_new_n1 ), 22282 /* 0.68 Q15 */ ) );
1270 0 : sbuf[0] = add_sat( sbuf[0], mult( ( temp_OUT ), *gain ) );
1271 0 : move16();
1272 0 : *gain = mac_r_sat( L_mult_sat( 32439 /* 0.99 Q15 */, *gain ), 328 /* 0.01 Q15 */, *gain_n );
1273 : }
1274 :
1275 0 : FOR( i = 1; i < Len; i++ )
1276 : {
1277 0 : temp_OUT = sub_sat( noise_seg[i], mult( ( noise_seg[i - 1] ), 22282 /* 0.68 Q15 */ ) );
1278 0 : sbuf[i] = add_sat( sbuf[i], mult( ( temp_OUT ), *gain ) );
1279 0 : move16();
1280 0 : *gain = mac_r_sat( L_mult( 32439 /* 0.99 Q15 */, *gain ), 328 /* 0.01 Q15 */, *gain_n );
1281 : }
1282 :
1283 0 : *outx_new_n1 = noise_seg[i - 1]; /*q0*/
1284 0 : move16();
1285 :
1286 0 : return;
1287 : }
1288 :
1289 0 : static Word16 waveform_adj_fix(
1290 : T_PLCInfo_HANDLE hPlcInfo,
1291 : Word16 *overlapbuf, /*Qoverlapbuf*/
1292 : Word16 *outdata2, /*Qoutdata2*/
1293 : Word16 *outx_new, /*Qoutx_new*/
1294 : const Word16 Framesize,
1295 : const Word16 voicing, /*Q15*/
1296 : const Word16 core )
1297 : {
1298 : Word16 i, zp1, zp2, Framesizediv2, s16MaxCoefNorm, pitch;
1299 : Word16 sbuf[L_FRAME_MAX];
1300 : Word16 tmp;
1301 :
1302 0 : Framesizediv2 = shr( Framesize, 1 );
1303 0 : zp1 = zero_pass_w32_x( outdata2, Framesizediv2 );
1304 0 : zp2 = zero_pass_w32_x( outdata2 + Framesizediv2, Framesizediv2 );
1305 :
1306 0 : pitch = hPlcInfo->Pitch_fx;
1307 :
1308 : /* judge if the pitch is usable */
1309 0 : tmp = 1;
1310 0 : move16();
1311 0 : if ( GT_16( zp1, 1 ) )
1312 : {
1313 0 : tmp = zp1;
1314 0 : move16();
1315 : }
1316 0 : IF( LT_16( shl( tmp, 2 ), zp2 ) )
1317 : {
1318 0 : move16();
1319 0 : return 0;
1320 : }
1321 :
1322 : /* adjust the pitch value */
1323 0 : test();
1324 0 : test();
1325 0 : test();
1326 0 : IF( hPlcInfo->T_bfi_fx && ( LE_16( pitch, Framesizediv2 ) ) && ( GT_16( Framesize, 256 ) ) && ( EQ_16( core, 1 ) ) )
1327 : {
1328 0 : Word16 i1 = 0, i2 = 0;
1329 : Word16 pos1, pos2, pos3;
1330 0 : move16();
1331 0 : move16();
1332 0 : i1 = add( 1, array_max_indx_fx( outx_new, pitch ) );
1333 0 : i2 = add( 1, array_max_indx_fx( outx_new + pitch, pitch ) );
1334 :
1335 0 : pos1 = add( i2, sub( pitch, i1 ) );
1336 0 : pos3 = add( pos1, mult( pos1, 8192 /* 0.25 Q15 */ ) );
1337 0 : pos2 = add( pitch, mult( pitch, 8192 /* 0.25 Q15 */ ) );
1338 :
1339 0 : test();
1340 0 : test();
1341 0 : if ( ( LT_16( pos1, pos2 ) ) && ( GT_16( pos3, pitch ) ) && ( LT_16( pos1, Framesizediv2 ) ) )
1342 : {
1343 0 : pitch = add( i2, sub( pitch, i1 ) );
1344 : }
1345 : }
1346 :
1347 : {
1348 0 : Word16 pitch125 = 0, Loverlap = 0, n = 0;
1349 : Word16 pitch125_data[L_FRAME_MAX];
1350 0 : move16();
1351 0 : move16();
1352 0 : move16();
1353 0 : pitch125 = extract_l( ( L_shr( L_add( L_add( L_deposit_h( pitch ), L_mult( pitch, 8192 ) ), 32768 ), 16 ) ) );
1354 0 : Loverlap = sub( pitch125, pitch );
1355 0 : FOR( i = 0; i < pitch; i++ )
1356 : {
1357 0 : pitch125_data[i] = outdata2[add( sub( Framesize, pitch ), i )];
1358 0 : move16();
1359 : }
1360 0 : FOR( i = 0; i < Loverlap; i++ )
1361 : {
1362 0 : pitch125_data[add( pitch, i )] = outx_new[i];
1363 0 : move16();
1364 : }
1365 0 : FOR( i = 0; i < Framesize; i++ )
1366 : {
1367 0 : sbuf[i] = outx_new[i];
1368 0 : move16();
1369 : }
1370 :
1371 : {
1372 : Word16 pitch125a1;
1373 0 : Word16 tmp_buf[2 * L_FRAME_MAX], *p_tmp = tmp_buf + 1;
1374 :
1375 0 : FOR( i = 0; i < pitch125; i++ )
1376 : {
1377 0 : p_tmp[i] = pitch125_data[i];
1378 0 : move16();
1379 : }
1380 :
1381 0 : p_tmp[-1] = outdata2[sub( sub( Framesize, pitch ), 1 )];
1382 0 : move16();
1383 0 : p_tmp[pitch125] = outx_new[Loverlap];
1384 0 : move16();
1385 0 : pitch125a1 = add( pitch125, 1 );
1386 0 : s16MaxCoefNorm = sub( ffr_getSfWord16( p_tmp - 1, pitch125a1 ), 1 );
1387 0 : FOR( i = 0; i < pitch125a1; i++ )
1388 : {
1389 0 : p_tmp[i - 1] = shl( p_tmp[i - 1], s16MaxCoefNorm );
1390 0 : move16();
1391 : }
1392 0 : FOR( i = 0; i < pitch125; i++ )
1393 : {
1394 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 ) );
1395 0 : move16();
1396 : }
1397 : }
1398 :
1399 0 : WHILE( LT_16( n, Framesize ) ) /* periodical extension */
1400 : {
1401 0 : n = OverlapAdd_fx( pitch125_data, sbuf, n, pitch, Framesize );
1402 : }
1403 :
1404 : /* maximum pitch lag is 3/4 Framesize; pitch125_data is reused for
1405 : temporary storage, since outdata2 (holding the pcm data of the
1406 : last good frame) is still needed and overlapbuf overlaps outdata2 */
1407 0 : Copy( &sbuf[Framesize / 4], pitch125_data, shr( imult1616( 3, Framesize ), 2 ) );
1408 :
1409 0 : hPlcInfo->nsapp_gain_fx = 0;
1410 0 : move16();
1411 0 : hPlcInfo->nsapp_gain_n_fx = sub( 32767, shr( voicing, 1 ) ); /* q15 */
1412 0 : tmp = Framesize;
1413 0 : move16();
1414 :
1415 : /* use last good signal for noise generation */
1416 0 : add_noise( sbuf, &( hPlcInfo->outx_new_n1_fx ), outdata2, tmp, &( hPlcInfo->nsapp_gain_fx ), &( hPlcInfo->nsapp_gain_n_fx ), 1 );
1417 :
1418 : /* save current (noisy) output from IMDCT */
1419 0 : MVR2R_WORD16( outx_new, hPlcInfo->data_noise, tmp );
1420 :
1421 : /* overlapbuf can now be filled with sbuf, needed for subsequently lost frames */
1422 0 : Copy( pitch125_data, &overlapbuf[Framesize / 4], shr( imult1616( 3, Framesize ), 2 ) );
1423 : }
1424 0 : FOR( i = 0; i < Framesize; i++ )
1425 : {
1426 0 : outx_new[i] = sbuf[i];
1427 0 : move16();
1428 : }
1429 :
1430 0 : return pitch;
1431 : }
1432 :
1433 :
1434 0 : void waveform_adj2_fix(
1435 : T_PLCInfo_HANDLE hPlcInfo,
1436 : Word16 *overlapbuf, /*Qoverlapbuf*/
1437 : Word16 *outx_new, /*Qoutx_new*/
1438 : const Word16 delay,
1439 : const Word16 bfi_cnt,
1440 : const Word16 bfi )
1441 : {
1442 : Word16 i, n, tablescale, ratio, dat, Framesizesubn, Framesizesubp, tmp16, s, ptable, temp_OUT, s16MaxCoefNorm, s16MaxCoefNorm2;
1443 : Word16 sbuf[L_FRAME_MAX];
1444 : Word16 pitch, L_frameTCX;
1445 :
1446 0 : pitch = hPlcInfo->Pitch_fx;
1447 0 : move16();
1448 0 : L_frameTCX = hPlcInfo->L_frameTCX;
1449 0 : move16();
1450 0 : n = 0;
1451 0 : move16();
1452 0 : Framesizesubn = sub( L_frameTCX, n );
1453 0 : Framesizesubp = sub( L_frameTCX, pitch );
1454 0 : IF( pitch > 0 )
1455 : {
1456 0 : WHILE( Framesizesubn > 0 )
1457 : {
1458 : /* periodical extension */
1459 0 : Word16 tmp = vadmin( pitch, Framesizesubn );
1460 0 : FOR( i = 0; i < tmp; i++ )
1461 : {
1462 0 : sbuf[add( n, i )] = overlapbuf[add( Framesizesubp, i )];
1463 0 : move16();
1464 : }
1465 0 : n = add( n, pitch );
1466 0 : Framesizesubn = sub( L_frameTCX, n );
1467 : }
1468 :
1469 0 : FOR( i = 0; i < L_frameTCX; i++ )
1470 : {
1471 0 : overlapbuf[i] = sbuf[i];
1472 0 : move16();
1473 : }
1474 :
1475 : {
1476 0 : Word16 size = L_frameTCX;
1477 0 : Word16 *noise_ptr = hPlcInfo->data_noise;
1478 0 : move16();
1479 : /* use last (noisy) output from IMDCT for noise generation */
1480 0 : add_noise( sbuf, &( hPlcInfo->outx_new_n1_fx ), noise_ptr, size, &( hPlcInfo->nsapp_gain_fx ), &( hPlcInfo->nsapp_gain_n_fx ), 0 );
1481 :
1482 : /* save current (noisy) output from IMDCT */
1483 0 : IF( bfi )
1484 : {
1485 0 : MVR2R_WORD16( outx_new, noise_ptr, size );
1486 : }
1487 : }
1488 0 : test();
1489 0 : IF( EQ_16( bfi_cnt, 4 ) || bfi == 0 )
1490 : {
1491 0 : SWITCH( L_frameTCX )
1492 : {
1493 0 : case 160:
1494 : {
1495 0 : tablescale = 8;
1496 0 : move16();
1497 0 : ptable = 26214; /* (Word16)(32767*256/160.0+0.5); q7+15 */
1498 0 : move16();
1499 0 : BREAK;
1500 : }
1501 0 : case 320:
1502 : {
1503 0 : tablescale = 9;
1504 0 : move16();
1505 0 : ptable = 26214; /* (Word16)(32767*256/320.0+0.5); q8+15 */
1506 0 : move16();
1507 0 : BREAK;
1508 : }
1509 0 : case 512:
1510 : {
1511 0 : tablescale = 10;
1512 0 : move16();
1513 0 : ptable = 32767; /* q9+15 */
1514 0 : move16();
1515 0 : BREAK;
1516 : }
1517 0 : case 640:
1518 : {
1519 0 : tablescale = 10;
1520 0 : move16();
1521 0 : ptable = 26214; /* (Word16)(32767*512/640.0+0.5); q9+15 */
1522 0 : move16();
1523 0 : BREAK;
1524 : }
1525 0 : default: /* 960 */
1526 : {
1527 0 : tablescale = 10;
1528 0 : move16();
1529 0 : ptable = 17456; /* (Word16)(32767*512/960.0); q9+15 */
1530 0 : move16();
1531 0 : BREAK;
1532 : }
1533 : }
1534 0 : IF( bfi == 0 ) /* overlap-and-add */
1535 : {
1536 0 : Word16 gain_zero_start = 10000;
1537 0 : move16();
1538 :
1539 0 : IF( hPlcInfo->step_concealgain_fx > 0 )
1540 : {
1541 0 : gain_zero_start = BASOP_Util_Divide1616_Scale( hPlcInfo->recovery_gain, hPlcInfo->step_concealgain_fx, &s );
1542 0 : gain_zero_start = shl( gain_zero_start, sub( s, 14 ) ); /* q0 */
1543 0 : gain_zero_start = add( gain_zero_start, 1 );
1544 : }
1545 :
1546 0 : if ( delay > 0 )
1547 : {
1548 0 : L_frameTCX = sub( L_frameTCX, delay );
1549 : }
1550 :
1551 0 : s16MaxCoefNorm = sub( ffr_getSfWord16( sbuf, L_frameTCX ), 1 );
1552 0 : s16MaxCoefNorm2 = ffr_getSfWord16( outx_new, L_frameTCX );
1553 0 : tmp16 = vadmin( gain_zero_start, L_frameTCX );
1554 0 : FOR( i = 0; i < tmp16; i++ )
1555 : {
1556 0 : ratio = extract_l( L_shr( L_mult( i, ptable ), tablescale ) );
1557 0 : dat = shl( sbuf[i], s16MaxCoefNorm );
1558 0 : temp_OUT = mult( hPlcInfo->recovery_gain, sub( 32767, ratio ) );
1559 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 ) ) );
1560 0 : move16();
1561 0 : hPlcInfo->recovery_gain = sub_sat( hPlcInfo->recovery_gain, shr_r( hPlcInfo->step_concealgain_fx, 1 ) ); /* q14 */
1562 : }
1563 0 : FOR( i = gain_zero_start; i < L_frameTCX; i++ )
1564 : {
1565 0 : ratio = extract_l( L_shr( L_mult( i, ptable ), tablescale ) );
1566 0 : outx_new[i] = round_fx_sat( L_shr_sat( L_mult( shl( outx_new[i], s16MaxCoefNorm2 ), ratio ), s16MaxCoefNorm2 ) );
1567 0 : move16();
1568 : }
1569 :
1570 0 : if ( hPlcInfo->recovery_gain < 0 )
1571 : {
1572 0 : hPlcInfo->recovery_gain = 0;
1573 0 : move16();
1574 : }
1575 : }
1576 : ELSE
1577 : {
1578 : /* overlap-and-add */
1579 : Word16 tmp;
1580 0 : s16MaxCoefNorm = sub( ffr_getSfWord16( sbuf, L_frameTCX ), 1 );
1581 0 : s16MaxCoefNorm2 = ffr_getSfWord16( outx_new, L_frameTCX );
1582 0 : FOR( i = 0; i < L_frameTCX; i++ )
1583 : {
1584 0 : dat = shl( sbuf[i], s16MaxCoefNorm );
1585 0 : tmp = extract_l( L_shr( L_mult( i, ptable ), tablescale ) );
1586 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 ) ) );
1587 0 : move16();
1588 : }
1589 : }
1590 : }
1591 : ELSE
1592 : {
1593 0 : FOR( i = 0; i < L_frameTCX; i++ )
1594 : {
1595 0 : outx_new[i] = sbuf[i];
1596 0 : move16();
1597 : }
1598 : }
1599 : }
1600 0 : return;
1601 : }
1602 :
1603 0 : void concealment_signal_tuning_fx(
1604 : Decoder_State *st,
1605 : const Word16 bfi,
1606 : Word16 *outx_new_fx /*Qoutx_new_fx*/,
1607 : const Word16 past_core )
1608 : {
1609 0 : T_PLCInfo_HANDLE hPlcInfo = st->hPlcInfo;
1610 0 : Word16 L_frameTCX = hPlcInfo->L_frameTCX;
1611 0 : Word16 voicing_fx = 0;
1612 0 : Word16 *OverlapBuf_fx = st->hTonalMDCTConc->secondLastPcmOut;
1613 0 : Word16 *outdata2_fx = st->hTonalMDCTConc->lastPcmOut;
1614 0 : move16();
1615 0 : move16();
1616 0 : move16();
1617 0 : move16();
1618 :
1619 0 : IF( bfi )
1620 : {
1621 0 : test();
1622 0 : IF( st->enablePlcWaveadjust && hPlcInfo->concealment_method == TCX_NONTONAL ) /* #define TCX_NONTONAL 0 */
1623 : {
1624 0 : IF( EQ_16( st->nbLostCmpt, 1 ) )
1625 : {
1626 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 );
1627 0 : move16();
1628 :
1629 0 : IF( hPlcInfo->Pitch_fx ) /* waveform adjustment for the first lost frame */
1630 : {
1631 0 : hPlcInfo->Pitch_fx = waveform_adj_fix( hPlcInfo, OverlapBuf_fx, outdata2_fx, outx_new_fx, L_frameTCX, voicing_fx, st->core );
1632 0 : move16();
1633 : }
1634 : }
1635 0 : ELSE IF( LT_16( st->nbLostCmpt, 5 ) ) /* waveform adjustment for the 2nd~4th lost frame */
1636 : {
1637 0 : waveform_adj2_fix( hPlcInfo, OverlapBuf_fx, outx_new_fx, 0, st->nbLostCmpt, bfi );
1638 : }
1639 : }
1640 0 : hPlcInfo->T_bfi_fx = 1;
1641 0 : move16();
1642 : }
1643 : ELSE
1644 : {
1645 0 : test();
1646 0 : test();
1647 0 : test();
1648 0 : IF( st->prev_bfi &&
1649 : past_core != ACELP_CORE &&
1650 : GE_32( st->last_total_brate, 48000 ) &&
1651 : EQ_16( st->last_codec_mode, MODE2 ) )
1652 : {
1653 0 : IF( hPlcInfo->concealment_method == TCX_NONTONAL ) /* #define TCX_NONTONAL 0 */
1654 : {
1655 0 : IF( LT_32( hPlcInfo->nbLostCmpt, 4 ) ) /* smoothing of the concealed signal with the good signal */
1656 : {
1657 0 : waveform_adj2_fix( hPlcInfo, OverlapBuf_fx, outx_new_fx, 0, add( extract_l( hPlcInfo->nbLostCmpt ), 1 ), bfi );
1658 : }
1659 : }
1660 : }
1661 : ELSE
1662 : {
1663 0 : hPlcInfo->T_bfi_fx = 0;
1664 0 : move16();
1665 : }
1666 : }
1667 0 : return;
1668 : }
|