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