Line data Source code
1 : /*====================================================================================
2 : EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0
3 : ====================================================================================*/
4 :
5 : #include <assert.h>
6 : #include "options.h"
7 : //#include "prot_fx.h"
8 : #include "stl.h"
9 : #include "cnst.h"
10 : #include "basop_util.h"
11 : #include "rom_com_fx.h"
12 : #include "rom_com.h"
13 : #include "prot_fx.h" /* Function prototypes */
14 : #include "prot_fx_enc.h" /* Function prototypes */
15 :
16 27024458 : static Word32 dot( const Word16 *X, const Word16 *Y, Word16 n )
17 : {
18 : Word32 acc;
19 : Word16 i;
20 :
21 : Word64 acc_64;
22 27024458 : acc_64 = 0;
23 27024458 : move64();
24 7787033418 : FOR( i = 0; i < n; i++ )
25 : {
26 7760008960 : acc_64 = W_mac0_16_16( acc_64, X[i], Y[i] );
27 : }
28 27024458 : acc = W_sat_l( acc_64 );
29 :
30 27024458 : return acc;
31 : }
32 :
33 5345982 : static Word32 interpolate_corr( /* o : interpolated value */
34 : const Word32 *x, /* i : input vector */
35 : const Word16 frac, /* i : fraction of lag */
36 : const Word16 frac_max /* i : max fraction */
37 : )
38 : {
39 : Word32 s;
40 : const Word16 *c, *win;
41 :
42 :
43 5345982 : win = E_ROM_inter4_1_fx;
44 5345982 : if ( EQ_16( frac_max, 6 ) )
45 287667 : win = E_ROM_inter6_1_fx;
46 :
47 :
48 5345982 : s = L_deposit_l( 0 );
49 :
50 5345982 : c = &win[frac];
51 5345982 : s = L_add( s, Mpy_32_16_1( x[0], *c ) );
52 5345982 : c += frac_max;
53 5345982 : s = L_add( s, Mpy_32_16_1( x[-1], *c ) );
54 5345982 : c += frac_max;
55 5345982 : s = L_add( s, Mpy_32_16_1( x[-2], *c ) );
56 5345982 : c += frac_max;
57 5345982 : s = L_add( s, Mpy_32_16_1( x[-3], *c ) );
58 :
59 5345982 : c = &win[frac_max - frac];
60 5345982 : s = L_add( s, Mpy_32_16_1( x[1], *c ) );
61 5345982 : c += frac_max;
62 5345982 : s = L_add( s, Mpy_32_16_1( x[2], *c ) );
63 5345982 : c += frac_max;
64 5345982 : s = L_add( s, Mpy_32_16_1( x[3], *c ) );
65 5345982 : c += frac_max;
66 5345982 : s = L_add( s, Mpy_32_16_1( x[4], *c ) );
67 :
68 :
69 5345982 : return s;
70 : }
71 :
72 1312 : static void tcx_ltp_pitch_search(
73 : Word16 pitch_ol,
74 : Word16 *pitch_int,
75 : Word16 *pitch_fr,
76 : Word16 *index,
77 : Word16 *norm_corr,
78 : const Word16 len,
79 : Word16 *wsp,
80 : Word16 pitmin,
81 : Word16 pitfr1,
82 : Word16 pitfr2,
83 : Word16 pitmax,
84 : Word16 pitres )
85 : {
86 : Word16 i, t, t0, t1, step, fraction, t0_min, t0_max, t_min, t_max, delta, temp_m, temp_e, s, s_wsp;
87 : Word32 cor_max, cor[256], *pt_cor, temp;
88 : Word16 wsp2[L_FRAME_PLUS + PIT_MAX_MAX + L_INTERPOL1];
89 :
90 :
91 1312 : delta = 16;
92 1312 : move16();
93 1312 : if ( EQ_16( pitres, 6 ) )
94 : {
95 1050 : delta = 8;
96 1050 : move16();
97 : }
98 :
99 1312 : t0_min = sub( pitch_ol, shr( delta, 1 ) );
100 1312 : t0_max = sub( add( t0_min, delta ), 1 );
101 :
102 1312 : IF( LT_16( t0_min, pitmin ) )
103 : {
104 40 : t0_min = pitmin;
105 40 : move16();
106 40 : t0_max = sub( add( t0_min, delta ), 1 );
107 : }
108 :
109 1312 : IF( GT_16( t0_max, pitmax ) )
110 : {
111 18 : t0_max = pitmax;
112 18 : move16();
113 18 : t0_min = add( sub( t0_max, delta ), 1 );
114 : }
115 :
116 1312 : t_min = sub( t0_min, L_INTERPOL1 );
117 1312 : t_max = add( t0_max, L_INTERPOL1 );
118 :
119 : /* normalize wsp */
120 1312 : assert( len + t_max <= L_FRAME_PLUS + PIT_MAX_MAX + L_INTERPOL1 );
121 1312 : s_wsp = getScaleFactor16( wsp - t_max, add( len, t_max ) );
122 1312 : s_wsp = sub( s_wsp, 4 );
123 541679 : FOR( t = negate( t_max ); t < len; t++ )
124 : {
125 540367 : wsp2[t + t_max] = shl( wsp[t], s_wsp );
126 540367 : move16();
127 : }
128 1312 : wsp = wsp2 + t_max;
129 1312 : move16();
130 :
131 1312 : pt_cor = cor;
132 1312 : move32();
133 :
134 24400 : FOR( t = t_min; t <= t_max; t++ )
135 : {
136 23088 : *pt_cor = dot( wsp, wsp - t, len );
137 23088 : move32();
138 23088 : pt_cor++;
139 : }
140 :
141 1312 : pt_cor = cor + L_INTERPOL1;
142 1312 : cor_max = L_add( *pt_cor++, 0 );
143 1312 : t1 = t0_min;
144 1312 : move16();
145 1312 : move32();
146 :
147 12592 : FOR( t = t0_min + 1; t <= t0_max; t++ )
148 : {
149 11280 : IF( GT_32( *pt_cor, cor_max ) )
150 : {
151 4954 : cor_max = *pt_cor;
152 4954 : move32();
153 4954 : t1 = t;
154 4954 : move16();
155 : }
156 11280 : pt_cor++;
157 : }
158 :
159 1312 : temp = dot( wsp, wsp, len );
160 1312 : s = norm_l( temp );
161 1312 : temp_m = extract_h( L_shl( temp, s ) );
162 1312 : temp_e = negate( s );
163 :
164 1312 : temp = dot( wsp - t1, wsp - t1, len );
165 1312 : s = norm_l( temp );
166 1312 : temp_m = mult( temp_m, extract_h( L_shl( temp, s ) ) );
167 1312 : temp_e = sub( temp_e, s );
168 :
169 1312 : temp_m = Sqrt16( temp_m, &temp_e );
170 :
171 1312 : if ( temp_m == 0 )
172 : {
173 0 : temp_m = 1;
174 0 : move16();
175 : }
176 1312 : s = sub( norm_l( cor_max ), 1 );
177 1312 : temp_m = divide1616( extract_h( L_shl( cor_max, s ) ), temp_m );
178 1312 : temp_e = sub( negate( s ), temp_e );
179 :
180 1312 : *norm_corr = shl_sat( temp_m, temp_e );
181 :
182 1312 : IF( GE_16( t1, pitfr1 ) )
183 : {
184 188 : *pitch_int = t1;
185 188 : move16();
186 188 : *pitch_fr = 0;
187 188 : move16();
188 :
189 188 : *index = add( sub( t1, pitfr1 ), extract_l( L_mac0( L_mult0( sub( pitfr2, pitmin ), pitres ),
190 188 : sub( pitfr1, pitfr2 ), shr( pitres, 1 ) ) ) );
191 188 : move16();
192 :
193 188 : return;
194 : }
195 :
196 : /*------------------------------------------------------------------*
197 : * Search fractional pitch with 1/4 subsample resolution.
198 : * search the fractions around t0 and choose the one which maximizes
199 : * the interpolated normalized correlation.
200 : *-----------------------------------------------------------------*/
201 :
202 1124 : pt_cor = cor + sub( L_INTERPOL1, t0_min );
203 1124 : t0 = t1;
204 1124 : move16();
205 :
206 1124 : step = 1;
207 1124 : move16();
208 1124 : if ( GE_16( t0, pitfr2 ) )
209 : {
210 896 : step = 2;
211 896 : move16();
212 : }
213 1124 : fraction = step;
214 1124 : move16();
215 :
216 1124 : IF( EQ_16( t0, t0_min ) ) /* Limit case */
217 : {
218 127 : fraction = 0;
219 127 : move16();
220 127 : cor_max = interpolate_corr( &pt_cor[t0], fraction, pitres );
221 : }
222 : ELSE /* Process negative fractions */
223 : {
224 997 : t0 = sub( t0, 1 );
225 997 : cor_max = interpolate_corr( &pt_cor[t0], fraction, pitres );
226 :
227 2192 : FOR( i = fraction + step; i < pitres; i += step )
228 : {
229 1195 : temp = interpolate_corr( &pt_cor[t0], i, pitres );
230 :
231 1195 : IF( GT_32( temp, cor_max ) )
232 : {
233 1165 : cor_max = L_add( temp, 0 );
234 1165 : fraction = i;
235 1165 : move16();
236 : }
237 : }
238 : }
239 :
240 1124 : i = 0;
241 1124 : move16();
242 4711 : FOR( i = 0; i < pitres; i += step ) /* Process positive fractions */
243 : {
244 3587 : temp = interpolate_corr( &pt_cor[t1], i, pitres );
245 :
246 3587 : IF( GT_32( temp, cor_max ) )
247 : {
248 1100 : cor_max = L_add( temp, 0 );
249 1100 : fraction = i;
250 1100 : move16();
251 1100 : t0 = t1;
252 1100 : move16();
253 : }
254 : }
255 :
256 1124 : *pitch_int = t0;
257 1124 : move16();
258 1124 : *pitch_fr = fraction;
259 1124 : move16();
260 :
261 1124 : IF( GE_16( t0, pitfr2 ) )
262 : {
263 896 : *index = add( extract_l( L_mac0( L_mult0( sub( t0, pitfr2 ), shr( pitres, 1 ) ),
264 896 : sub( pitfr2, pitmin ), pitres ) ),
265 896 : shr( fraction, 1 ) );
266 896 : move16();
267 : }
268 : ELSE
269 : {
270 228 : *index = add( imult1616( sub( t0, pitmin ), pitres ), fraction );
271 228 : move16();
272 : }
273 : }
274 :
275 1079467 : static void tcx_ltp_pitch_search_ivas_fx(
276 : const Word16 pitch_ol,
277 : Word16 *pitch_int,
278 : Word16 *pitch_fr,
279 : Word16 *index,
280 : Word16 *norm_corr,
281 : const Word16 len,
282 : const Word16 *wsp, // Qx
283 : const Word16 pitmin,
284 : const Word16 pitfr1,
285 : const Word16 pitfr2,
286 : const Word16 pitmax,
287 : const Word16 pitres,
288 : const Word16 check_border_case,
289 : Word16 *border_case )
290 : {
291 : Word16 i, t, t0, t1, step, fraction, t0_min, t0_max, t_min, t_max, delta, temp_m, temp_e, s, s_wsp;
292 : Word32 cor_max, cor[256], *pt_cor, temp;
293 : Word16 wsp2[L_FRAME_PLUS + PIT_MAX_MAX + L_INTERPOL1];
294 :
295 1079467 : delta = 16;
296 1079467 : move16();
297 1079467 : if ( EQ_16( pitres, 6 ) )
298 : {
299 174568 : delta = 8;
300 174568 : move16();
301 : }
302 :
303 1079467 : t0_min = sub( pitch_ol, shr( delta, 1 ) );
304 1079467 : t0_max = sub( add( t0_min, delta ), 1 );
305 :
306 1079467 : IF( LT_16( t0_min, pitmin ) )
307 : {
308 86615 : t0_min = pitmin;
309 86615 : move16();
310 86615 : t0_max = sub( add( t0_min, delta ), 1 );
311 : }
312 :
313 1079467 : IF( GT_16( t0_max, pitmax ) )
314 : {
315 21937 : t0_max = pitmax;
316 21937 : move16();
317 21937 : t0_min = add( sub( t0_max, delta ), 1 );
318 : }
319 :
320 1079467 : t_min = sub( t0_min, L_INTERPOL1 );
321 1079467 : t_max = add( t0_max, L_INTERPOL1 );
322 :
323 : /* normalize wsp */
324 1079467 : s_wsp = getScaleFactor16( wsp - t_max, add( len, t_max ) );
325 1079467 : s_wsp = sub( s_wsp, 4 );
326 442869522 : FOR( t = negate( t_max ); t < len; t++ )
327 : {
328 441790055 : wsp2[t + t_max] = shl( wsp[t], s_wsp ); // Q(x + s_wsp)
329 441790055 : move16();
330 : }
331 1079467 : wsp = wsp2 + t_max;
332 :
333 1079467 : pt_cor = cor;
334 :
335 25590131 : FOR( t = t_min; t <= t_max; t++ )
336 : {
337 24510664 : *pt_cor = dot( wsp, wsp - t, len ); // 2*(x + s_wsp)
338 24510664 : move32();
339 24510664 : pt_cor++;
340 : }
341 :
342 1079467 : pt_cor = cor + L_INTERPOL1;
343 1079467 : cor_max = L_add( *pt_cor++, 0 );
344 1079467 : t1 = t0_min;
345 1079467 : move16();
346 :
347 15874928 : FOR( t = t0_min + 1; t <= t0_max; t++ )
348 : {
349 14795461 : IF( GT_32( *pt_cor, cor_max ) )
350 : {
351 5685413 : cor_max = *pt_cor;
352 5685413 : move32();
353 5685413 : t1 = t;
354 5685413 : move16();
355 : }
356 14795461 : pt_cor++;
357 : }
358 :
359 1079467 : temp = dot( wsp, wsp, len ); // 2*(x + s_wsp)
360 1079467 : s = norm_l( temp );
361 1079467 : temp_e = negate( s );
362 1079467 : temp_m = extract_h( L_shl( temp, s ) ); // Q(2*(x + s_wsp) - temp_e - 16)
363 :
364 1079467 : temp = dot( wsp - t1, wsp - t1, len ); // 2*(x + s_wsp)
365 1079467 : s = norm_l( temp );
366 1079467 : temp_m = mult( temp_m, extract_h( L_shl( temp, s ) ) ); // //Q = 4*(x + s_wsp) + s - temp_e - 47
367 1079467 : temp_e = sub( temp_e, s );
368 :
369 1079467 : temp_m = Sqrt16( temp_m, &temp_e );
370 :
371 1079467 : if ( temp_m == 0 )
372 : {
373 13869 : temp_m = 1;
374 13869 : move16();
375 : }
376 1079467 : s = sub( norm_l( cor_max ), 1 );
377 1079467 : temp_m = divide1616( extract_h( L_shl( cor_max, s ) ), temp_m );
378 1079467 : temp_e = sub( negate( s ), temp_e );
379 :
380 1079467 : *norm_corr = shl_sat( temp_m, temp_e );
381 :
382 1079467 : test();
383 1079467 : IF( check_border_case && EQ_16( t1, t0_min ) )
384 : {
385 : Word32 tmpCor;
386 380791 : FOR( t = t1 - L_INTERPOL1; t < t1; t++ )
387 : {
388 329148 : tmpCor = dot( wsp, wsp - t, len );
389 329148 : IF( GT_32( tmpCor, cor_max ) )
390 : {
391 86553 : *border_case = 1;
392 86553 : move16();
393 86553 : break;
394 : }
395 : }
396 : }
397 :
398 1079467 : IF( GE_16( t1, pitfr1 ) )
399 : {
400 232430 : *pitch_int = t1;
401 232430 : move16();
402 232430 : *pitch_fr = 0;
403 232430 : move16();
404 :
405 232430 : *index = add( sub( t1, pitfr1 ), extract_l( L_mac0( L_mult0( sub( pitfr2, pitmin ), pitres ),
406 232430 : sub( pitfr1, pitfr2 ), shr( pitres, 1 ) ) ) );
407 232430 : move16();
408 :
409 232430 : return;
410 : }
411 :
412 : /*------------------------------------------------------------------*
413 : * Search fractional pitch with 1/4 subsample resolution.
414 : * search the fractions around t0 and choose the one which maximizes
415 : * the interpolated normalized correlation.
416 : *-----------------------------------------------------------------*/
417 :
418 847037 : pt_cor = cor + sub( L_INTERPOL1, t0_min );
419 847037 : t0 = t1;
420 847037 : move16();
421 :
422 847037 : step = 1;
423 847037 : move16();
424 847037 : if ( GE_16( t0, pitfr2 ) )
425 : {
426 128492 : step = 2;
427 128492 : move16();
428 : }
429 847037 : fraction = step;
430 847037 : move16();
431 :
432 847037 : IF( EQ_16( t0, t0_min ) ) /* Limit case */
433 : {
434 111254 : fraction = 0;
435 111254 : move16();
436 111254 : cor_max = interpolate_corr( &pt_cor[t0], fraction, pitres );
437 : }
438 : ELSE /* Process negative fractions */
439 : {
440 735783 : t0 = sub( t0, 1 );
441 735783 : cor_max = interpolate_corr( &pt_cor[t0], fraction, pitres );
442 :
443 2037525 : FOR( i = fraction + step; i < pitres; i += step )
444 : {
445 1301742 : temp = interpolate_corr( &pt_cor[t0], i, pitres );
446 :
447 1301742 : IF( GT_32( temp, cor_max ) )
448 : {
449 1218470 : cor_max = L_add( temp, 0 );
450 1218470 : fraction = i;
451 1218470 : move16();
452 : }
453 : }
454 : }
455 :
456 4038334 : FOR( i = 0; i < pitres; i += step ) /* Process positive fractions */
457 : {
458 3191297 : temp = interpolate_corr( &pt_cor[t1], i, pitres );
459 :
460 3191297 : IF( GT_32( temp, cor_max ) )
461 : {
462 909222 : cor_max = L_add( temp, 0 );
463 909222 : fraction = i;
464 909222 : move16();
465 909222 : t0 = t1;
466 909222 : move16();
467 : }
468 : }
469 :
470 847037 : *pitch_int = t0;
471 847037 : move16();
472 847037 : *pitch_fr = fraction;
473 847037 : move16();
474 :
475 847037 : IF( GE_16( t0, pitfr2 ) )
476 : {
477 127653 : *index = add( extract_l( L_mac0( L_mult0( sub( t0, pitfr2 ), shr( pitres, 1 ) ),
478 127653 : sub( pitfr2, pitmin ), pitres ) ),
479 127653 : shr( fraction, 1 ) );
480 127653 : move16();
481 : }
482 : ELSE
483 : {
484 719384 : *index = add( imult1616( sub( t0, pitmin ), pitres ), fraction );
485 719384 : move16();
486 : }
487 : }
488 :
489 :
490 943 : static void tcx_ltp_find_gain( Word16 *speech, Word16 *pred_speech, Word16 L_frame, Word16 *gain, Word16 *gain_index )
491 : {
492 : Word32 corr, ener;
493 : Word16 i, g, s1, s2, tmp;
494 : #ifndef ISSUE_1867_replace_overflow_libenc
495 : #ifdef BASOP_NOGLOB_DECLARE_LOCAL
496 : Flag Overflow = 0;
497 : move32();
498 : #endif
499 : #endif
500 :
501 :
502 943 : s1 = sub( getScaleFactor16( speech, L_frame ), 4 );
503 943 : s2 = sub( getScaleFactor16( pred_speech, L_frame ), 4 );
504 :
505 : /* Find gain */
506 943 : corr = L_deposit_l( 0 );
507 943 : ener = L_deposit_l( 1 );
508 :
509 289711 : FOR( i = 0; i < L_frame; i++ )
510 : {
511 288768 : tmp = shl_sat( pred_speech[i], s2 );
512 288768 : corr = L_mac0_sat( corr, shl( speech[i], s1 ), tmp );
513 288768 : ener = L_mac0_sat( ener, tmp, tmp );
514 : }
515 :
516 943 : s1 = sub( 1, add( s1, s2 ) );
517 943 : s2 = sub( 1, shl( s2, 1 ) );
518 :
519 943 : tmp = sub( norm_l( corr ), 1 );
520 943 : corr = L_shl( corr, tmp );
521 943 : s1 = sub( s1, tmp );
522 :
523 943 : tmp = norm_l( ener );
524 943 : ener = L_shl( ener, tmp );
525 943 : s2 = sub( s2, tmp );
526 :
527 : #ifdef ISSUE_1867_replace_overflow_libenc
528 943 : g = divide1616( round_fx_sat( corr ), round_fx_sat( ener ) );
529 : #else
530 : g = divide1616( round_fx_o( corr, &Overflow ), round_fx_o( ener, &Overflow ) );
531 : #endif
532 : BASOP_SATURATE_WARNING_OFF_EVS
533 943 : g = shl_sat( g, sub( s1, s2 ) );
534 : BASOP_SATURATE_WARNING_ON_EVS
535 :
536 : /* Quantize gain */
537 : #ifdef ISSUE_1867_replace_overflow_libenc
538 943 : g = shr( sub_sat( g, 0x1000 ), 13 );
539 : #else
540 : g = shr( sub_o( g, 0x1000, &Overflow ), 13 );
541 : #endif
542 943 : g = s_max( g, -1 );
543 :
544 943 : *gain_index = g;
545 943 : move16();
546 :
547 : /* Dequantize gain */
548 943 : *gain = imult1616( add( g, 1 ), 0x1400 );
549 943 : move16();
550 943 : }
551 :
552 885784 : static void tcx_ltp_find_gain_ivas_fx( Word16 *speech /*Qx*/, Word16 *pred_speech /*Qx*/, Word16 L_frame, Word16 *gain, Word16 *gain_index )
553 : {
554 : Word32 corr, ener;
555 : Word16 i, g, s1, s2, tmp;
556 : #ifndef ISSUE_1867_replace_overflow_libenc
557 : #ifdef BASOP_NOGLOB_DECLARE_LOCAL
558 : Flag Overflow = 0;
559 : move32();
560 : #endif
561 : #endif
562 :
563 885784 : s1 = sub( getScaleFactor16( speech, L_frame ), 4 );
564 885784 : s2 = sub( getScaleFactor16( pred_speech, L_frame ), 4 );
565 :
566 : /* Find gain */
567 885784 : corr = L_deposit_l( 0 );
568 885784 : ener = L_deposit_l( 1 );
569 :
570 272397016 : FOR( i = 0; i < L_frame; i++ )
571 : {
572 271511232 : tmp = shl_sat( pred_speech[i], s2 ); // Qx + s2
573 271511232 : corr = L_mac0_sat( corr, shl( speech[i], s1 ), tmp ); // 2*Qx + s1 + s2
574 271511232 : ener = L_mac0_sat( ener, tmp, tmp ); // 2*(Qx+s2)
575 : }
576 :
577 885784 : s1 = sub( 1, add( s1, s2 ) );
578 885784 : s2 = sub( 1, shl( s2, 1 ) );
579 :
580 885784 : tmp = sub( norm_l( corr ), 1 );
581 885784 : corr = L_shl( corr, tmp );
582 885784 : s1 = sub( s1, tmp );
583 :
584 885784 : tmp = norm_l( ener );
585 885784 : ener = L_shl( ener, tmp );
586 885784 : s2 = sub( s2, tmp );
587 :
588 : #ifdef ISSUE_1867_replace_overflow_libenc
589 885784 : g = divide1616( round_fx_sat( corr ), round_fx_sat( ener ) );
590 : #else
591 : g = divide1616( round_fx_o( corr, &Overflow ), round_fx_o( ener, &Overflow ) );
592 : #endif
593 : BASOP_SATURATE_WARNING_OFF_EVS
594 885784 : g = shl_sat( g, sub( s1, s2 ) ); /*Q15*/
595 : BASOP_SATURATE_WARNING_ON_EVS
596 :
597 : /* Quantize gain */
598 885784 : g = shr_sat( sub_sat( g /*Q15*/, 0x1000 ), 13 ); // Q0
599 885784 : g = s_max( g, -1 );
600 :
601 885784 : *gain_index = g;
602 885784 : move16();
603 :
604 : /* Dequantize gain */
605 885784 : *gain = imult1616( add( g, 1 ), 0x1400 ); /*Q15*/
606 885784 : move16();
607 885784 : }
608 :
609 1312 : void tcx_ltp_encode_fx( Word16 tcxltp_on,
610 : Word8 tcxOnly,
611 : Word16 tcxMode,
612 : Word16 L_frame,
613 : Word16 L_subfr,
614 : Word16 *speech,
615 : Word16 *speech_ltp,
616 : Word16 *wsp,
617 : Word16 Top,
618 : Word16 *ltp_param,
619 : Word16 *ltp_bits,
620 : Word16 *pitch_int,
621 : Word16 *pitch_fr,
622 : Word16 *gain,
623 : Word16 *pitch_int_past,
624 : Word16 *pitch_fr_past,
625 : Word16 *gain_past,
626 : Word16 *norm_corr_past,
627 : Word16 last_core,
628 : Word16 pitmin,
629 : Word16 pitfr1,
630 : Word16 pitfr2,
631 : Word16 pitmax,
632 : Word16 pitres,
633 : struct TransientDetection const *pTransientDetection,
634 : Word8 SideInfoOnly,
635 : Word16 *A,
636 : Word16 lpcorder )
637 : {
638 : Word16 n;
639 : Word16 norm_corr;
640 : Word16 pred_speech[L_FRAME32k];
641 : Word16 tempFlatness;
642 : Word16 maxEnergyChange;
643 : Word16 buf_zir[M + L_SUBFR], *zir;
644 : Word16 Aest[M + 1];
645 : Word16 alpha, step;
646 : #ifndef ISSUE_1867_replace_overflow_libenc
647 : #ifdef BASOP_NOGLOB_DECLARE_LOCAL
648 : Flag Overflow = 0;
649 : move32();
650 : #endif
651 : #endif
652 :
653 :
654 1312 : norm_corr = 0;
655 1312 : move16();
656 :
657 : /* Reset memory if past frame is acelp */
658 1312 : IF( last_core == ACELP_CORE )
659 : {
660 627 : *pitch_int_past = L_frame;
661 627 : move16();
662 627 : *pitch_fr_past = 0;
663 627 : move16();
664 627 : *gain_past = 0;
665 627 : move16();
666 : }
667 :
668 : /* By default, LTP is off */
669 1312 : ltp_param[0] = 0;
670 1312 : move16();
671 :
672 1312 : test();
673 1312 : IF( tcxltp_on != 0 || SideInfoOnly != 0 )
674 : {
675 : Word16 nPrevSubblocks;
676 1312 : Word8 isTCX10 = 0;
677 :
678 1312 : if ( EQ_16( tcxMode, TCX_10 ) )
679 : {
680 0 : isTCX10 = 1;
681 0 : move16();
682 : }
683 :
684 : /* Find pitch lag */
685 1312 : tcx_ltp_pitch_search( Top, pitch_int, pitch_fr, <p_param[1], &norm_corr, L_frame, wsp, pitmin, pitfr1, pitfr2, pitmax, pitres );
686 :
687 1312 : nPrevSubblocks = extract_h( L_mac( 0x17fff, NSUBBLOCKS, div_s( *pitch_int, L_frame ) ) );
688 1312 : nPrevSubblocks = add( s_min( nPrevSubblocks, NSUBBLOCKS ), 1 );
689 :
690 1312 : tempFlatness = GetTCXAvgTemporalFlatnessMeasure_fx( pTransientDetection, NSUBBLOCKS, nPrevSubblocks );
691 :
692 1312 : maxEnergyChange = GetTCXMaxenergyChange_fx( pTransientDetection,
693 : (const Word8) isTCX10,
694 : NSUBBLOCKS, nPrevSubblocks );
695 :
696 : /* Switch LTP on */
697 1312 : test();
698 1312 : test();
699 1312 : test();
700 1312 : test();
701 1312 : test();
702 1312 : test();
703 1312 : test();
704 1312 : test();
705 1312 : test();
706 1312 : test();
707 1312 : test();
708 1312 : test();
709 1312 : test();
710 1312 : test();
711 1312 : test();
712 1312 : test();
713 : BASOP_SATURATE_WARNING_OFF_EVS;
714 1312 : if ( (
715 1312 : tcxOnly == 0 &&
716 2624 : EQ_16( tcxMode, TCX_20 ) &&
717 2327 : GT_16( mult( norm_corr, *norm_corr_past ), 0x2000 ) &&
718 1384 : LT_16( tempFlatness, 448 /*3.5f Q7*/ ) ) ||
719 0 : ( tcxOnly != 0 &&
720 0 : EQ_16( tcxMode, TCX_10 ) &&
721 0 : GT_16( s_max( norm_corr, *norm_corr_past ), 0x4000 ) &&
722 369 : LT_16( maxEnergyChange, 448 /*3.5f Q7*/ ) ) ||
723 : ( /* Use LTP for lower correlation when pitch lag is big, L_frame*(1.2f-norm_corr) < pitch_int <=> norm_corr > 1.2f-pitch_int/L_frame */
724 0 : tcxOnly != 0 &&
725 0 : GT_16( norm_corr, 14418 /*0.44f Q15*/ ) &&
726 0 : L_msu( L_mult( L_frame, sub( 19661 /*1.2f Q14*/, shr( norm_corr, 1 ) ) ), *pitch_int, 1 << 14 ) < 0 /* L_frame*(1.2f-norm_corr) < pitch_int */
727 369 : ) ||
728 0 : ( tcxOnly != 0 &&
729 0 : EQ_16( tcxMode, TCX_20 ) &&
730 0 : GT_16( norm_corr, 14418 /*0.44f Q15*/ ) &&
731 0 : ( LT_16( tempFlatness, 768 /*6.0f Q7*/ ) ||
732 0 : ( LT_16( tempFlatness, 896 /*7.0f Q7*/ ) &&
733 0 : LT_16( maxEnergyChange, 2816 /*22.0f Q7*/ ) ) ) ) )
734 : {
735 943 : ltp_param[0] = 1;
736 943 : move16();
737 : }
738 : BASOP_SATURATE_WARNING_ON_EVS;
739 : }
740 :
741 1312 : IF( ltp_param[0] != 0 )
742 : {
743 : /* Find predicted signal */
744 943 : predict_signal( speech, pred_speech, *pitch_int, *pitch_fr, pitres, L_frame );
745 :
746 : /* Find gain */
747 943 : tcx_ltp_find_gain( speech, pred_speech, L_frame, gain, <p_param[2] );
748 :
749 : /* Total number of bits for LTP */
750 943 : IF( NE_16( ltp_param[2], -1 ) ) /* gain > 0 */
751 : {
752 943 : *ltp_bits = 12;
753 943 : move16();
754 : }
755 : ELSE /* gain <= 0 -> turn off LTP */
756 : {
757 0 : ltp_param[0] = 0;
758 0 : move16();
759 : }
760 : }
761 :
762 1312 : IF( ltp_param[0] == 0 )
763 : {
764 : /* No LTP -> set everything to zero */
765 369 : *pitch_int = L_frame;
766 369 : move16();
767 369 : *pitch_fr = 0;
768 369 : move16();
769 369 : ltp_param[1] = 0;
770 369 : move16();
771 369 : set16_fx( pred_speech, 0, L_frame );
772 369 : *gain = 0;
773 369 : move16();
774 369 : ltp_param[2] = 0;
775 369 : move16();
776 :
777 369 : *ltp_bits = 0;
778 369 : move16();
779 369 : test();
780 369 : IF( tcxltp_on != 0 || SideInfoOnly != 0 )
781 : {
782 369 : *ltp_bits = 1;
783 369 : move16();
784 : }
785 : }
786 :
787 1312 : IF( SideInfoOnly != 0 )
788 : {
789 0 : *gain = 0;
790 0 : move16();
791 : }
792 :
793 1312 : test();
794 1312 : IF( *gain_past == 0 && *gain == 0 )
795 : {
796 301 : Copy( speech, speech_ltp, L_subfr );
797 : }
798 1011 : ELSE IF( *gain_past == 0 )
799 : {
800 532 : alpha = 0;
801 532 : move16();
802 :
803 : /* step = 1.f/(float)(L_subfr); */
804 532 : step = shl( 2, norm_s( L_subfr ) );
805 532 : IF( s_and( L_subfr, sub( L_subfr, 1 ) ) != 0 )
806 : {
807 0 : step = mult_r( step, 26214 /*64.f/80.f Q15*/ );
808 : }
809 :
810 34580 : FOR( n = 0; n < L_subfr; n++ )
811 : {
812 : #ifdef ISSUE_1867_replace_overflow_libenc
813 34048 : speech_ltp[n] = sub_sat( speech[n], mult_r_sat( *gain, mult_r_sat( alpha, pred_speech[n] ) ) );
814 : #else
815 : speech_ltp[n] = sub_o( speech[n], mult_ro( *gain, mult_ro( alpha, pred_speech[n], &Overflow ), &Overflow ), &Overflow );
816 : #endif
817 34048 : move16();
818 : BASOP_SATURATE_WARNING_OFF_EVS;
819 : #ifdef ISSUE_1867_replace_overflow_libenc
820 34048 : alpha = add_sat( alpha, step );
821 : #else
822 : alpha = add_o( alpha, step, &Overflow );
823 : #endif
824 : BASOP_SATURATE_WARNING_ON_EVS;
825 : }
826 : }
827 : ELSE
828 : {
829 479 : IF( A == NULL )
830 : {
831 0 : tcx_ltp_get_lpc( speech - L_frame, L_frame, Aest, lpcorder );
832 0 : A = Aest;
833 : }
834 :
835 479 : IF( *gain > 0 )
836 : {
837 411 : predict_signal( speech - lpcorder, buf_zir, *pitch_int, *pitch_fr, pitres, lpcorder );
838 : }
839 : ELSE
840 : {
841 68 : set16_fx( buf_zir, 0, lpcorder );
842 : }
843 :
844 8143 : FOR( n = 0; n < lpcorder; n++ )
845 : {
846 7664 : buf_zir[n] = add_sat( sub_sat( speech_ltp[n - lpcorder], speech[n - lpcorder] ), mult_r( *gain, buf_zir[n] ) );
847 7664 : move16();
848 : }
849 :
850 479 : zir = buf_zir + lpcorder;
851 :
852 479 : set16_fx( zir, 0, L_subfr );
853 :
854 479 : E_UTIL_synthesis( 0, A, zir, zir, L_subfr, buf_zir, 0, lpcorder );
855 :
856 479 : alpha = 0x7FFF;
857 479 : move16();
858 : /* step = 1.f/(float)(L_subfr/2); */
859 479 : step = shl( 4, norm_s( L_subfr ) );
860 479 : IF( s_and( L_subfr, sub( L_subfr, 1 ) ) != 0 )
861 : {
862 0 : step = mult_r( step, 26214 /*64.f/80.f Q15*/ );
863 : }
864 :
865 15807 : FOR( n = ( L_subfr >> 1 ); n < L_subfr; n++ )
866 : {
867 15328 : zir[n] = mult_r( zir[n], alpha );
868 15328 : move16();
869 15328 : alpha = sub( alpha, step );
870 : }
871 :
872 31135 : FOR( n = 0; n < L_subfr; n++ )
873 : {
874 : #ifdef ISSUE_1867_replace_overflow_libenc
875 30656 : speech_ltp[n] = add_sat( sub_sat( speech[n], mult_r_sat( *gain, pred_speech[n] ) ), zir[n] );
876 : #else
877 : speech_ltp[n] = add_o( sub_o( speech[n], mult_ro( *gain, pred_speech[n], &Overflow ), &Overflow ), zir[n], &Overflow );
878 : #endif
879 30656 : move16();
880 : }
881 : }
882 :
883 1312 : test();
884 1312 : IF( SideInfoOnly || *gain == 0 )
885 : {
886 91057 : FOR( n = L_subfr; n < L_frame; n++ )
887 : {
888 90688 : speech_ltp[n] = speech[n];
889 90688 : move16();
890 : }
891 : }
892 : ELSE
893 : {
894 229359 : FOR( n = L_subfr; n < L_frame; n++ )
895 : {
896 : #ifdef ISSUE_1867_replace_overflow_libenc
897 228416 : speech_ltp[n] = sub_sat( speech[n], mult( *gain, pred_speech[n] ) );
898 : #else
899 : speech_ltp[n] = sub_o( speech[n], mult( *gain, pred_speech[n] ), &Overflow );
900 : #endif
901 228416 : move16();
902 : }
903 : }
904 :
905 : /* Update */
906 1312 : *pitch_int_past = *pitch_int;
907 1312 : move16();
908 1312 : *pitch_fr_past = *pitch_fr;
909 1312 : move16();
910 1312 : *gain_past = *gain;
911 1312 : move16();
912 1312 : *norm_corr_past = norm_corr;
913 1312 : move16();
914 1312 : }
915 :
916 885784 : void tcx_ltp_encode_ivas_fx(
917 : Encoder_State *st,
918 : const Word16 tcxMode,
919 : const Word16 L_frame,
920 : Word16 *speech_fx,
921 : Word16 *speech_ltp_fx,
922 : const Word16 *wsp_fx,
923 : const Word16 Top[],
924 : Word16 *ltp_param,
925 : Word16 *ltp_bits,
926 : Word16 *A_fx,
927 : const Word16 disable_ltp,
928 : const Word16 element_mode )
929 : {
930 : Word16 i, n;
931 : Word16 ltp_on, tcxOnly, L_subfr, SideInfoOnly, delta;
932 : Word16 si_gain_fx; // Q15
933 : Word16 alpha_fx, step_fx; // Q15
934 : Word16 norm_corr_fx; // Q15
935 : Word16 border_case;
936 : Word16 tempFlatness_fx; // Q7
937 : Word16 maxEnergyChange_fx; // Q3
938 : Word16 pred_speech_fx[L_FRAME_PLUS]; // Qspeech
939 : Word16 buf_zir_fx[M + L_FRAME_PLUS / 4], *zir_fx; // Qspeech
940 : Word16 Aest_fx[M + 1];
941 : Word16 exponent;
942 : Word16 sqr;
943 : #ifndef ISSUE_1867_replace_overflow_libenc
944 : Flag Overflow = 0;
945 : move32();
946 : #endif
947 :
948 885784 : TCX_ENC_HANDLE hTcxEnc = st->hTcxEnc;
949 :
950 885784 : tcxOnly = st->tcxonly;
951 885784 : move16();
952 885784 : L_subfr = L_SUBFR;
953 885784 : move16();
954 885784 : SideInfoOnly = extract_l( GT_32( st->sr_core, 25600 ) );
955 885784 : move16();
956 :
957 : /* Reset memory if past frame is acelp */
958 885784 : IF( st->last_core == ACELP_CORE )
959 : {
960 9262 : hTcxEnc->tcxltp_pitch_int_past = L_frame;
961 9262 : move16();
962 9262 : hTcxEnc->tcxltp_pitch_fr_past = 0;
963 9262 : move16();
964 9262 : hTcxEnc->tcxltp_gain_past = 0;
965 9262 : move16();
966 : }
967 :
968 : /* By default, LTP is off */
969 885784 : ltp_param[0] = 0;
970 885784 : move16();
971 885784 : norm_corr_fx = 0;
972 885784 : move16();
973 885784 : border_case = 0;
974 885784 : move16();
975 :
976 885784 : test();
977 885784 : IF( hTcxEnc->tcxltp || SideInfoOnly )
978 : {
979 : Word16 nPrevSubblocks;
980 885784 : Word8 isTCX10 = 0;
981 885784 : move16();
982 :
983 : /* Find pitch lag */
984 885784 : IF( EQ_16( st->pit_res_max, 6 ) )
985 : {
986 174568 : delta = 8;
987 174568 : move16();
988 : }
989 : ELSE
990 : {
991 711216 : delta = 16;
992 711216 : move16();
993 : }
994 :
995 885784 : IF( EQ_16( st->element_mode, IVAS_CPE_MDCT ) )
996 : {
997 649353 : IF( LT_16( abs_s( sub( Top[0], Top[1] ) ), shr( delta, 1 ) ) )
998 : {
999 : /* estimates are close enough and stable, take the artihmetic mean as estimate */
1000 455670 : tcx_ltp_pitch_search_ivas_fx( shr( add( Top[0], Top[1] ), 1 ), &hTcxEnc->tcxltp_pitch_int, &hTcxEnc->tcxltp_pitch_fr, <p_param[1], &norm_corr_fx, L_frame, wsp_fx, st->pit_min, st->pit_fr1, st->pit_fr2, st->pit_max, st->pit_res_max, 1, &border_case );
1001 : }
1002 : ELSE
1003 : {
1004 : /* pitch jumps between half frames, calc ltp for both estimates, choose the better one */
1005 : Word16 pitch_int_2[2];
1006 : Word16 pitch_fr_2[2];
1007 : Word16 norm_corr_2_fx[2];
1008 : Word16 pit_param_2[2];
1009 :
1010 581049 : FOR( i = 0; i < 2; i++ )
1011 : {
1012 387366 : tcx_ltp_pitch_search_ivas_fx( Top[i], &pitch_int_2[i], &pitch_fr_2[i], &pit_param_2[i], &norm_corr_2_fx[i], L_frame, wsp_fx, st->pit_min, st->pit_fr1, st->pit_fr2, st->pit_max, st->pit_res_max, 1, &border_case );
1013 : }
1014 :
1015 193683 : IF( GT_16( norm_corr_2_fx[1], norm_corr_2_fx[0] ) )
1016 : {
1017 124637 : i = 1;
1018 : }
1019 : ELSE
1020 : {
1021 69046 : i = 0;
1022 : }
1023 193683 : move16();
1024 :
1025 193683 : hTcxEnc->tcxltp_pitch_int = pitch_int_2[i];
1026 193683 : move16();
1027 193683 : hTcxEnc->tcxltp_pitch_fr = pitch_fr_2[i];
1028 193683 : move16();
1029 193683 : ltp_param[1] = pit_param_2[i];
1030 193683 : move16();
1031 193683 : norm_corr_fx = norm_corr_2_fx[i];
1032 193683 : move16();
1033 : }
1034 : }
1035 : ELSE
1036 : {
1037 : Word16 tmp;
1038 236431 : IF( GT_16( element_mode, EVS_MONO ) )
1039 : {
1040 236431 : tmp = 1;
1041 : }
1042 : ELSE
1043 : {
1044 0 : tmp = 0;
1045 : }
1046 236431 : move16();
1047 236431 : tcx_ltp_pitch_search_ivas_fx( Top[1], &hTcxEnc->tcxltp_pitch_int, &hTcxEnc->tcxltp_pitch_fr, <p_param[1], &norm_corr_fx, L_frame, wsp_fx, st->pit_min, st->pit_fr1, st->pit_fr2, st->pit_max, st->pit_res_max, tmp, &border_case );
1048 : }
1049 :
1050 885784 : if ( border_case )
1051 : {
1052 82465 : norm_corr_fx = 0;
1053 82465 : move16();
1054 : }
1055 :
1056 : // nPrevSubblocks = ( 1 + min( NSUBBLOCKS, (int16_t) ceil( 0.5f + NSUBBLOCKS * ( 1.0f * ( hTcxEnc->tcxltp_pitch_int ) / L_frame ) ) ) );
1057 885784 : nPrevSubblocks = extract_h( L_add( L_mac( 32768, NSUBBLOCKS, div_s( hTcxEnc->tcxltp_pitch_int, L_frame ) ), 65535 ) ); // 0.5f Q16 //65535( 1.Q16 - 1) added to get the ceil
1058 885784 : nPrevSubblocks = add( s_min( nPrevSubblocks, NSUBBLOCKS ), 1 );
1059 :
1060 885784 : IF( EQ_16( st->element_mode, IVAS_CPE_DFT ) )
1061 : {
1062 14304 : tempFlatness_fx = extract_l( L_shr( GetTCXAvgTemporalFlatnessMeasure_ivas_fx( (const TransientDetection *) st->hTranDet, NSUBBLOCKS - NSUBBLOCKS_SHIFT, add( nPrevSubblocks, NSUBBLOCKS_SHIFT ) ), 14 ) ); // Q7
1063 14304 : maxEnergyChange_fx = GetTCXMaxenergyChange_ivas_fx( st->hTranDet, (const Word8) isTCX10,
1064 14304 : NSUBBLOCKS - NSUBBLOCKS_SHIFT, add( nPrevSubblocks, NSUBBLOCKS_SHIFT ) ); // Q3
1065 : }
1066 : ELSE
1067 : {
1068 871480 : tempFlatness_fx = extract_l( L_shr( ( GetTCXAvgTemporalFlatnessMeasure_ivas_fx( (const TransientDetection *) st->hTranDet, NSUBBLOCKS, nPrevSubblocks ) ), 14 ) ); // Q7
1069 871480 : maxEnergyChange_fx = GetTCXMaxenergyChange_ivas_fx( st->hTranDet, (const Word8) isTCX10,
1070 : NSUBBLOCKS, nPrevSubblocks ); // Q3
1071 : }
1072 :
1073 : /* Switch LTP on */
1074 885784 : test();
1075 885784 : test();
1076 885784 : test();
1077 885784 : test();
1078 885784 : test();
1079 885784 : test();
1080 885784 : test();
1081 885784 : test();
1082 885784 : test();
1083 885784 : test();
1084 885784 : test();
1085 885784 : test();
1086 885784 : test();
1087 885784 : test();
1088 885784 : test();
1089 885784 : test();
1090 885784 : IF( (
1091 : ( tcxOnly == 0 ) &&
1092 : EQ_16( tcxMode, TCX_20 ) &&
1093 : GT_16( mult( norm_corr_fx, hTcxEnc->tcxltp_norm_corr_past ), 0x2000 ) && /*mult returns Q15*/
1094 : LT_16( tempFlatness_fx, 448 /*3.5f Q7*/ ) ) ||
1095 : ( EQ_16( tcxOnly, 1 ) &&
1096 : EQ_16( tcxMode, TCX_10 ) &&
1097 : GT_16( s_max( norm_corr_fx, hTcxEnc->tcxltp_norm_corr_past ), 0x4000 ) &&
1098 : LT_16( maxEnergyChange_fx, 28 /*3.5f Q3*/ ) ) ||
1099 : ( /* Use LTP for lower correlation when pitch lag is big, L_frame*(1.2f-norm_corr) < pitch_int <=> norm_corr > 1.2f-pitch_int/L_frame */
1100 : EQ_16( tcxOnly, 1 ) &&
1101 : GT_16( norm_corr_fx, 14418 /*0.44f Q15*/ ) &&
1102 : L_msu( L_mult( L_frame, sub( 19661 /*1.2f Q14*/, shr( norm_corr_fx, 1 ) ) ), hTcxEnc->tcxltp_pitch_int, 1 << 14 ) < 0 /* L_frame*(1.2f-norm_corr) < pitch_int */
1103 : ) ||
1104 : ( EQ_16( tcxOnly, 1 ) &&
1105 : EQ_16( tcxMode, TCX_20 ) &&
1106 : GT_16( norm_corr_fx, 14418 /*0.44f Q15*/ ) &&
1107 : ( LT_16( tempFlatness_fx, 768 /*6.0f Q7*/ ) ||
1108 : ( LT_16( tempFlatness_fx, 896 /*7.0f Q7*/ ) &&
1109 : LT_16( maxEnergyChange_fx, 176 /*22.0f Q3*/ ) ) ) ) )
1110 : {
1111 541027 : IF( disable_ltp == 0 )
1112 : {
1113 540984 : ltp_param[0] = 1;
1114 540984 : move16();
1115 : }
1116 : }
1117 :
1118 : /* hysteresis for stable ltp prediction */
1119 885784 : ltp_on = 0;
1120 885784 : move16();
1121 :
1122 885784 : test();
1123 885784 : test();
1124 885784 : test();
1125 885784 : test();
1126 885784 : test();
1127 :
1128 885784 : exponent = 15;
1129 885784 : move16();
1130 885784 : sqr = Sqrt16( hTcxEnc->tcxltp_on_mem, &exponent );
1131 885784 : move16();
1132 885784 : IF( ( EQ_16( tcxOnly, 1 ) && EQ_16( st->element_mode, IVAS_CPE_MDCT ) && ( GT_16( ( mult( sqr, mult( ( norm_corr_fx ), 29492 ) ) ), shr( 14419, exponent ) ) && ( LT_16( tempFlatness_fx, 768 ) || ( LT_16( tempFlatness_fx, 896 ) && LT_16( maxEnergyChange_fx, 176 ) ) ) ) ) ) // 0.9f Q15, 6.0f Q7, 7.0f Q7, 22.0f Q3
1133 : {
1134 419231 : ltp_on = 1;
1135 419231 : move16();
1136 : }
1137 :
1138 885784 : test();
1139 885784 : IF( EQ_16( tcxOnly, 1 ) && EQ_16( ltp_param[0], 1 ) )
1140 : {
1141 : /* increase ltp counter */
1142 479841 : hTcxEnc->tcxltp_on_mem = s_min( 5, add( hTcxEnc->tcxltp_on_mem, 1 ) );
1143 479841 : move16();
1144 : }
1145 405943 : ELSE IF( EQ_16( ltp_on, 1 ) )
1146 : {
1147 : /* hysteresis takes effect, decrease counter */
1148 46122 : hTcxEnc->tcxltp_on_mem = s_max( 0, sub( hTcxEnc->tcxltp_on_mem, 1 ) );
1149 46122 : move16();
1150 46122 : ltp_param[0] = ltp_on;
1151 46122 : move16();
1152 : }
1153 : ELSE
1154 : {
1155 : /* no ltp in this frame, reset counter */
1156 359821 : hTcxEnc->tcxltp_on_mem = 0;
1157 359821 : move16();
1158 : }
1159 : }
1160 :
1161 : /* Find predicted signal */
1162 885784 : predict_signal( speech_fx, pred_speech_fx, hTcxEnc->tcxltp_pitch_int, hTcxEnc->tcxltp_pitch_fr, st->pit_res_max, L_frame );
1163 :
1164 : /* Find gain */
1165 885784 : tcx_ltp_find_gain_ivas_fx( speech_fx, pred_speech_fx, L_frame, &hTcxEnc->tcxltp_gain, <p_param[2] );
1166 :
1167 885784 : IF( ltp_param[0] )
1168 : {
1169 : /* Total number of bits for LTP */
1170 587106 : IF( add( ltp_param[2], 1 ) ) /* hTcxEnc->tcxltp_gain > 0 */
1171 : {
1172 587034 : *ltp_bits = 12;
1173 587034 : move16();
1174 : }
1175 : ELSE /* hTcxEnc->tcxltp_gain <= 0 -> turn off LTP */
1176 : {
1177 72 : ltp_param[0] = 0;
1178 72 : move16();
1179 : }
1180 : }
1181 :
1182 885784 : IF( !ltp_param[0] )
1183 : {
1184 : /* No LTP -> set everything to zero */
1185 298750 : hTcxEnc->tcxltp_pitch_int = L_frame;
1186 298750 : move16();
1187 298750 : hTcxEnc->tcxltp_pitch_fr = 0;
1188 298750 : move16();
1189 298750 : ltp_param[1] = 0;
1190 298750 : move16();
1191 298750 : set16_fx( pred_speech_fx, 0, L_frame );
1192 298750 : hTcxEnc->tcxltp_gain = 0;
1193 298750 : move16();
1194 298750 : ltp_param[2] = 0;
1195 298750 : move16();
1196 :
1197 298750 : test();
1198 298750 : IF( hTcxEnc->tcxltp || SideInfoOnly )
1199 : {
1200 298750 : *ltp_bits = 1;
1201 298750 : move16();
1202 : }
1203 : ELSE
1204 : {
1205 0 : *ltp_bits = 0;
1206 0 : move16();
1207 : }
1208 : }
1209 :
1210 885784 : si_gain_fx = 0;
1211 885784 : move16();
1212 :
1213 885784 : IF( SideInfoOnly )
1214 : {
1215 426181 : si_gain_fx = hTcxEnc->tcxltp_gain;
1216 426181 : move16();
1217 426181 : hTcxEnc->tcxltp_gain = 0;
1218 426181 : move16();
1219 : }
1220 :
1221 885784 : IF( speech_ltp_fx != NULL )
1222 : {
1223 222127 : test();
1224 222127 : IF( hTcxEnc->tcxltp_gain_past == 0 && hTcxEnc->tcxltp_gain == 0 )
1225 : {
1226 150842 : Copy( speech_fx, speech_ltp_fx, L_subfr );
1227 : }
1228 71285 : ELSE IF( hTcxEnc->tcxltp_gain_past == 0 )
1229 : {
1230 11609 : alpha_fx = 0;
1231 11609 : move16();
1232 :
1233 11609 : step_fx = shl( 2, norm_s( L_subfr ) );
1234 11609 : IF( s_and( L_subfr, sub( L_subfr, 1 ) ) != 0 )
1235 : {
1236 0 : step_fx = mult_r( step_fx, 26214 /*64.f/80.f Q15*/ );
1237 : }
1238 :
1239 754585 : FOR( n = 0; n < L_subfr; n++ )
1240 : {
1241 : #ifdef ISSUE_1867_replace_overflow_libenc
1242 742976 : speech_ltp_fx[n] = sub_sat( speech_fx[n], mult_r_sat( hTcxEnc->tcxltp_gain, mult_r_sat( alpha_fx, pred_speech_fx[n] ) ) );
1243 : #else
1244 : speech_ltp_fx[n] = sub_o( speech_fx[n], mult_ro( hTcxEnc->tcxltp_gain, mult_ro( alpha_fx, pred_speech_fx[n], &Overflow ), &Overflow ), &Overflow );
1245 : #endif
1246 742976 : move16();
1247 742976 : alpha_fx = add_sat( alpha_fx, step_fx );
1248 : }
1249 : }
1250 : ELSE
1251 : {
1252 59676 : IF( A_fx == NULL )
1253 : {
1254 59676 : tcx_ltp_get_lpc( speech_fx - L_frame, L_frame, Aest_fx, M );
1255 59676 : A_fx = Aest_fx;
1256 : }
1257 :
1258 59676 : IF( hTcxEnc->tcxltp_gain > 0 )
1259 : {
1260 50666 : predict_signal( speech_fx - M, buf_zir_fx, hTcxEnc->tcxltp_pitch_int, hTcxEnc->tcxltp_pitch_fr, st->pit_res_max, M );
1261 : }
1262 : ELSE
1263 : {
1264 9010 : set16_fx( buf_zir_fx, 0, M );
1265 : }
1266 :
1267 1014492 : FOR( n = 0; n < M; n++ )
1268 : {
1269 954816 : buf_zir_fx[n] = add_sat( sub_sat( speech_ltp_fx[n - M], speech_fx[n - M] ), mult_r( hTcxEnc->tcxltp_gain, buf_zir_fx[n] ) );
1270 954816 : move16();
1271 : }
1272 :
1273 59676 : zir_fx = buf_zir_fx + M;
1274 59676 : set16_fx( zir_fx, 0, L_subfr );
1275 :
1276 59676 : Syn_filt_s( 0, A_fx, M, zir_fx, zir_fx, L_subfr, buf_zir_fx, 0 );
1277 :
1278 59676 : alpha_fx = 0x7FFF; // 1.f Q15
1279 59676 : move16();
1280 59676 : step_fx = shl( 4, norm_s( L_subfr ) );
1281 59676 : IF( s_and( L_subfr, sub( L_subfr, 1 ) ) != 0 )
1282 : {
1283 0 : step_fx = mult_r( step_fx, 26214 /*64.f/80.f Q15*/ );
1284 : }
1285 :
1286 1969308 : FOR( n = L_subfr >> 1; n < L_subfr; n++ )
1287 : {
1288 1909632 : zir_fx[n] = mult_r( zir_fx[n], alpha_fx );
1289 1909632 : move16();
1290 1909632 : alpha_fx = sub( alpha_fx, step_fx );
1291 : }
1292 :
1293 3878940 : FOR( n = 0; n < L_subfr; n++ )
1294 : {
1295 : #ifdef ISSUE_1867_replace_overflow_libenc
1296 3819264 : speech_ltp_fx[n] = add_sat( sub_sat( speech_fx[n], mult_r_sat( hTcxEnc->tcxltp_gain, pred_speech_fx[n] ) ), zir_fx[n] );
1297 : #else
1298 : speech_ltp_fx[n] = add_o( sub_o( speech_fx[n], mult_ro( hTcxEnc->tcxltp_gain, pred_speech_fx[n], &Overflow ), &Overflow ), zir_fx[n], &Overflow );
1299 : #endif
1300 3819264 : move16();
1301 : }
1302 : }
1303 :
1304 222127 : test();
1305 222127 : IF( SideInfoOnly || hTcxEnc->tcxltp_gain == 0 )
1306 : {
1307 71974700 : FOR( n = L_subfr; n < L_frame; n++ )
1308 : {
1309 71814848 : speech_ltp_fx[n] = speech_fx[n];
1310 71814848 : move16();
1311 : }
1312 : }
1313 : ELSE
1314 : {
1315 15033027 : FOR( n = L_subfr; n < L_frame; n++ )
1316 : {
1317 : #ifdef ISSUE_1867_replace_overflow_libenc
1318 14970752 : speech_ltp_fx[n] = sub_sat( speech_fx[n], mult( hTcxEnc->tcxltp_gain, pred_speech_fx[n] ) );
1319 : #else
1320 : speech_ltp_fx[n] = sub_o( speech_fx[n], mult( hTcxEnc->tcxltp_gain, pred_speech_fx[n] ), &Overflow );
1321 : #endif
1322 14970752 : move16();
1323 : }
1324 : }
1325 : }
1326 :
1327 : /* Update */
1328 885784 : hTcxEnc->tcxltp_pitch_int_past = hTcxEnc->tcxltp_pitch_int;
1329 885784 : move16();
1330 885784 : hTcxEnc->tcxltp_pitch_fr_past = hTcxEnc->tcxltp_pitch_fr;
1331 885784 : move16();
1332 885784 : hTcxEnc->tcxltp_gain_past = hTcxEnc->tcxltp_gain;
1333 885784 : move16();
1334 :
1335 885784 : IF( SideInfoOnly )
1336 : {
1337 426181 : hTcxEnc->tcxltp_gain = si_gain_fx;
1338 426181 : move16();
1339 : }
1340 :
1341 885784 : hTcxEnc->tcxltp_norm_corr_past = norm_corr_fx;
1342 885784 : move16();
1343 :
1344 885784 : return;
1345 : }
|