Line data Source code
1 : /*====================================================================================
2 : EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0
3 : ====================================================================================*/
4 : #include <stdint.h>
5 : #include "options.h"
6 : #include "prot_fx.h"
7 : #include "cnst.h"
8 : #include "basop_util.h"
9 : #include "rom_com.h"
10 :
11 : /*-------------------------------------------------------------------
12 : * Local constants
13 : *-------------------------------------------------------------------*/
14 :
15 : #define ALPHA 27853 /*0.85f Q15*/
16 : #define MAX_TCX_LTP_FILTER_LEN 8
17 : #define MAX_TRANSITION_LEN 240 /* L_FRAME_48K / 4 */
18 :
19 262 : void tcx_ltp_get_lpc(
20 : Word16 *x, /* Qx */
21 : const Word16 L, /* Q0 */
22 : Word16 *A, /* Qx */
23 : const Word16 order /* Q0 */
24 : )
25 : {
26 : Word16 i, j, s, s2, tmp;
27 : Word32 r, L_tmp;
28 :
29 262 : Word16 tmpbuf[L_FRAME_MAX], *p = x;
30 : Word16 r_l[TCXLTP_LTP_ORDER + 1], r_h[TCXLTP_LTP_ORDER + 1];
31 :
32 :
33 262 : assert( L <= L_FRAME_MAX );
34 :
35 : /* calc r[0], determine shift */
36 262 : s = 0;
37 262 : move16();
38 262 : r = L_deposit_l( 0 );
39 218822 : FOR( j = 0; j < L; j++ )
40 : {
41 218560 : L_tmp = L_sub( r, 0x40000000 /* 1 in Q30 */ ); /* Q30 */
42 218560 : if ( L_tmp > 0 )
43 137 : s = sub( s, 1 );
44 218560 : if ( L_tmp > 0 )
45 137 : r = L_shr( r, 2 );
46 :
47 218560 : tmp = shl( x[j], s ); /* Qx + s */
48 218560 : r = L_mac0_sat( r, tmp, tmp ); /* Q30 */
49 : }
50 262 : r = L_max( r, L_shl( 100, shl( s, 1 ) ) ); /* Q30 */
51 262 : r = Mpy_32_16_1( r, 16386 /*1.0001f Q14*/ ); /* Q29 */
52 262 : s2 = norm_l( r );
53 262 : r = L_shl( r, s2 );
54 262 : s2 = sub( s2, 1 );
55 262 : r_l[0] = L_Extract_lc( r, &r_h[0] ); /* Q14 */
56 262 : move16();
57 262 : move16();
58 :
59 262 : IF( s < 0 )
60 : {
61 : /* shift buffer by s, recompute r[0] to reduce risk of instable LPC */
62 81 : r = L_deposit_l( 0 );
63 81 : tmp = lshl( (Word16) 0x8000, s ); /* factor corresponding to right shift by -s */
64 :
65 : {
66 81 : Word64 r64 = 0;
67 81 : move64();
68 69841 : FOR( j = 0; j < L; j++ )
69 : {
70 69760 : tmpbuf[j] = mult_r( x[j], tmp ); /* Qx */
71 69760 : move16();
72 69760 : r64 = W_mac0_16_16( r64, tmpbuf[j], tmpbuf[j] ); /* Q30 */
73 : }
74 81 : r = W_sat_l( r64 ); /* Q30 */
75 : }
76 81 : r = L_max( r, L_shl( 100, shl( s, 1 ) ) ); /* Q30 */
77 81 : r = Mpy_32_16_1( r, 16386 /*1.0001f Q14*/ ); /* Q29 */
78 81 : s2 = norm_l( r );
79 81 : r = L_shl( r, s2 );
80 81 : s2 = sub( s2, 1 );
81 81 : r_l[0] = L_Extract_lc( r, &r_h[0] ); /* Q14 */
82 81 : move16();
83 81 : move16();
84 :
85 81 : p = tmpbuf;
86 : }
87 :
88 : /* calc r[1...] */
89 6550 : FOR( i = 1; i <= order; i++ )
90 : {
91 6288 : r = L_deposit_l( 0 );
92 :
93 6288 : tmp = sub( L, i );
94 : {
95 6288 : Word64 r64 = 0;
96 6288 : move64();
97 5173128 : FOR( j = 0; j < tmp; j++ )
98 : {
99 5166840 : r64 = W_mac0_16_16( r64, p[j], p[j + i] ); /* Q30 */
100 : }
101 6288 : r = W_sat_l( r64 );
102 : }
103 6288 : r = L_shl( r, s2 );
104 6288 : r_l[i] = L_Extract_lc( r, &r_h[i] ); /* Q14 */
105 6288 : move16();
106 6288 : move16();
107 : }
108 :
109 262 : E_LPC_lev_dur( r_h, r_l, A, NULL, order, NULL );
110 262 : }
111 :
112 0 : void tcx_ltp_get_lpc_fx(
113 : Word32 *x, /* Qx */
114 : const Word16 L, /* Q0 */
115 : Word32 *A, /* Qx */
116 : const Word16 order /* Q0 */
117 : )
118 : {
119 : Word16 i, j, s, s2;
120 : Word32 r, tmp, L_tmp;
121 :
122 0 : Word32 tmpbuf[L_FRAME_MAX], *p = x;
123 : Word16 r_l[TCXLTP_LTP_ORDER + 1], r_h[TCXLTP_LTP_ORDER + 1];
124 :
125 :
126 0 : assert( L <= L_FRAME_MAX );
127 :
128 : /* calc r[0], determine shift */
129 0 : s = 0;
130 0 : move16();
131 0 : r = L_deposit_l( 0 );
132 0 : FOR( j = 0; j < L; j++ )
133 : {
134 0 : L_tmp = L_sub( r, 0x40000000 /* 1 in Q30 */ ); /* Q30 */
135 0 : if ( L_tmp > 0 )
136 0 : s = sub( s, 1 );
137 0 : if ( L_tmp > 0 )
138 0 : r = L_shr( r, 2 );
139 :
140 0 : tmp = L_shl( x[j], s ); /* Qx + s */
141 0 : r = Madd_32_32( r, tmp, tmp );
142 : }
143 0 : r = L_max( r, L_shl( 100, shl( s, 1 ) ) ); /* Q30 */
144 0 : r = Mpy_32_16_1( r, 16386 /*1.0001f Q14*/ ); /* Q29 */
145 0 : s2 = norm_l( r );
146 0 : r = L_shl( r, s2 );
147 0 : s2 = sub( s2, 1 );
148 0 : r_l[0] = L_Extract_lc( r, &r_h[0] ); /* Q14 */
149 0 : move16();
150 0 : move16();
151 :
152 0 : IF( s < 0 )
153 : {
154 : /* shift buffer by s, recompute r[0] to reduce risk of instable LPC */
155 0 : r = L_deposit_l( 0 );
156 0 : tmp = lshl( (Word16) 0x8000, s ); /* factor corresponding to right shift by -s */
157 :
158 : {
159 0 : Word64 r64 = 0;
160 0 : move64();
161 0 : FOR( j = 0; j < L; j++ )
162 : {
163 0 : tmpbuf[j] = Mpy_32_32( x[j], tmp );
164 0 : move32();
165 0 : r64 = W_add( r64, W_mult0_32_32( tmpbuf[j], tmpbuf[j] ) );
166 : }
167 0 : r = W_sat_l( r64 );
168 : }
169 0 : r = L_max( r, L_shl( 100, shl( s, 1 ) ) ); /* Q30 */
170 0 : r = Mpy_32_16_1( r, 16386 /*1.0001f Q14*/ ); /* Q29 */
171 0 : s2 = norm_l( r );
172 0 : r = L_shl( r, s2 );
173 0 : s2 = sub( s2, 1 );
174 0 : r_l[0] = L_Extract_lc( r, &r_h[0] ); /* Q14 */
175 0 : move16();
176 0 : move16();
177 :
178 0 : p = tmpbuf;
179 : }
180 :
181 : /* calc r[1...] */
182 0 : FOR( i = 1; i <= order; i++ )
183 : {
184 0 : r = L_deposit_l( 0 );
185 :
186 0 : tmp = sub( L, i );
187 : {
188 0 : Word64 r64 = 0;
189 0 : move64();
190 0 : FOR( j = 0; j < tmp; j++ )
191 : {
192 0 : r64 = W_add( r64, Mpy_32_32( p[j], p[j + i] ) ); /* Q30 */
193 : }
194 0 : r = W_sat_l( r64 );
195 : }
196 0 : r = L_shl( r, s2 );
197 0 : r_l[i] = L_Extract_lc( r, &r_h[i] ); /* Q14 */
198 0 : move16();
199 0 : move16();
200 : }
201 :
202 0 : E_LPC_lev_dur_fx( r_h, r_l, A, NULL, order, NULL );
203 0 : }
204 :
205 262 : static void tcx_ltp_get_zir(
206 : Word16 *zir, /* Qx */
207 : const Word16 length, /* Q0 */
208 : Word16 *synth_ltp, /* Qx */
209 : Word16 *synth, /* Qx */
210 : Word16 *A, /* Qx */
211 : const Word16 lpcorder, /* Q0 */
212 : const Word16 gain, /* Q15 */
213 : const Word16 pitch_int, /* Q0 */
214 : const Word16 pitch_fr, /* Q0 */
215 : const Word16 pitres, /* Q0 */
216 : const Word16 filtIdx /* Q0 */
217 : )
218 : {
219 : Word16 buf[TCXLTP_LTP_ORDER], alpha, step;
220 : Word16 *x0, *x1;
221 : Word16 *y0, *y1;
222 : Word32 s, s2;
223 : const Word16 *w0, *w1, *v0, *v1;
224 : Word16 i, j, k, L;
225 :
226 262 : x0 = &synth_ltp[-pitch_int]; /* Qx */
227 262 : x1 = x0 - 1;
228 262 : y0 = synth; /* Qx */
229 262 : y1 = y0 - 1;
230 :
231 262 : assert( filtIdx >= 0 );
232 :
233 262 : w0 = &tcxLtpFilters[filtIdx].filt[pitch_fr]; /* Q15 */
234 262 : w1 = &tcxLtpFilters[filtIdx].filt[pitres - pitch_fr]; /* Q15 */
235 262 : v0 = &tcxLtpFilters[filtIdx].filt[0]; /* Q15 */
236 262 : v1 = &tcxLtpFilters[filtIdx].filt[pitres]; /* Q15 */
237 262 : L = tcxLtpFilters[filtIdx].length; /* Q0 */
238 262 : move16();
239 :
240 6550 : FOR( j = 0; j < lpcorder; j++ )
241 : {
242 6288 : s = L_deposit_l( 0 );
243 6288 : s2 = L_deposit_l( 0 );
244 6288 : k = 0;
245 6288 : move16();
246 41544 : FOR( i = 0; i < L; i++ )
247 : {
248 35256 : s = L_mac_sat( L_mac_sat( s, w0[k], x0[i] ), w1[k], x1[-i] ); /* Qx */
249 35256 : s2 = L_mac_sat( L_mac_sat( s2, v0[k], y0[i] ), v1[k], y1[-i] ); /* Qx */
250 35256 : k = k + pitres;
251 : }
252 :
253 : /* s2 *= ALPHA;
254 : buf[j] = ( synth[j] - gain * s2 ) - ( synth_ltp[j] - gain * s ); */
255 6288 : i = sub_sat( round_fx_sat( s ), mult_r_sat( round_fx_sat( s2 ), ALPHA ) );
256 6288 : buf[j] = add_sat( sub_sat( synth[j], synth_ltp[j] ), mult_r_sat( gain, i ) ); /* Qx */
257 6288 : move16();
258 :
259 6288 : x0++;
260 6288 : x1++;
261 6288 : y0++;
262 6288 : y1++;
263 : }
264 :
265 262 : set16_fx( zir, 0, length );
266 :
267 262 : E_UTIL_synthesis( 0, A, zir, zir, length, buf, 0, lpcorder );
268 :
269 262 : alpha = 0x7FFF; /* 1 in Q15 */
270 262 : move16();
271 : /* step = 1.f/(float)(length/2); */
272 262 : step = shl( 4, norm_s( length ) );
273 262 : if ( s_and( length, sub( length, 1 ) ) != 0 )
274 : {
275 262 : step = mult_r( step, 26214 /*64.f/80.f Q15*/ ); /* Q15 */
276 : }
277 262 : if ( EQ_16( length, 240 ) )
278 : {
279 159 : step = 273 /*1.f/120.f Q15*/;
280 159 : move16();
281 : }
282 :
283 27582 : FOR( j = length / 2; j < length; j++ )
284 : {
285 27320 : zir[j] = mult_r( zir[j], alpha ); /* Qx */
286 27320 : move16();
287 27320 : alpha = sub( alpha, step );
288 : }
289 262 : }
290 :
291 0 : static void tcx_ltp_get_zir_fx(
292 : Word32 *zir, /* Qx */
293 : const Word16 length, /* Q0 */
294 : Word32 *synth_ltp, /* Qx */
295 : Word32 *synth, /* Qx */
296 : Word32 *A, /* Qx */
297 : const Word16 lpcorder, /* Q0 */
298 : const Word16 gain, /* Q15 */
299 : const Word16 pitch_int, /* Q0 */
300 : const Word16 pitch_fr, /* Q0 */
301 : const Word16 pitres, /* Q0 */
302 : const Word16 filtIdx /* Q0 */
303 : )
304 : {
305 : Word32 buf[TCXLTP_LTP_ORDER];
306 : Word16 alpha, step;
307 : Word32 *x0, *x1;
308 : Word32 *y0, *y1;
309 : Word32 s, s2;
310 : const Word16 *w0, *w1, *v0, *v1;
311 : Word32 i;
312 : Word16 j, k, L;
313 :
314 0 : x0 = &synth_ltp[-pitch_int]; /* Qx */
315 0 : x1 = x0 - 1;
316 0 : y0 = synth; /* Qx */
317 0 : y1 = y0 - 1;
318 :
319 0 : assert( filtIdx >= 0 );
320 :
321 0 : w0 = &tcxLtpFilters[filtIdx].filt[pitch_fr]; /* Q15 */
322 0 : w1 = &tcxLtpFilters[filtIdx].filt[pitres - pitch_fr]; /* Q15 */
323 0 : v0 = &tcxLtpFilters[filtIdx].filt[0]; /* Q15 */
324 0 : v1 = &tcxLtpFilters[filtIdx].filt[pitres]; /* Q15 */
325 0 : L = tcxLtpFilters[filtIdx].length; /* Q0 */
326 0 : move16();
327 :
328 0 : FOR( j = 0; j < lpcorder; j++ )
329 : {
330 0 : s = L_deposit_l( 0 );
331 0 : s2 = L_deposit_l( 0 );
332 0 : k = 0;
333 0 : move16();
334 0 : FOR( i = 0; i < L; i++ )
335 : {
336 0 : s = Madd_32_16_r( Madd_32_16_r( s, x0[i], w0[k] ), x1[-i], w1[k] ); /* Qx */
337 0 : s2 = Madd_32_16_r( Madd_32_16_r( s2, y0[i], v0[k] ), y1[-i], v1[k] ); /* Qx */
338 0 : k = k + pitres;
339 : }
340 :
341 : /* s2 *= ALPHA;
342 : buf[j] = ( synth[j] - gain * s2 ) - ( synth_ltp[j] - gain * s ); */
343 0 : i = L_sub_sat( s, Mpy_32_16_1( s2, ALPHA ) ); /* Qx */
344 0 : buf[j] = L_add_sat( L_sub_sat( synth[j], synth_ltp[j] ), Mpy_32_16_1( i, gain ) ); /* Qx */
345 :
346 0 : move16();
347 :
348 0 : x0++;
349 0 : x1++;
350 0 : y0++;
351 0 : y1++;
352 : }
353 :
354 0 : set32_fx( zir, 0, length );
355 :
356 0 : E_UTIL_synthesis_fx( 0, A, zir, zir, length, buf, 0, lpcorder );
357 :
358 0 : alpha = 0x7FFF; /* 1 in Q15 */
359 0 : move16();
360 : /* step = 1.f/(float)(length/2); */
361 0 : step = shl( 4, norm_s( length ) );
362 0 : if ( s_and( length, sub( length, 1 ) ) != 0 )
363 : {
364 0 : step = mult_r( step, 26214 /*64.f/80.f Q15*/ ); /* Q15 */
365 : }
366 0 : if ( EQ_16( length, 240 ) )
367 : {
368 0 : step = 273 /*1.f/120.f Q15*/;
369 0 : move16();
370 : }
371 :
372 0 : FOR( j = shr( length, 1 ); j < length; j++ )
373 : {
374 0 : zir[j] = Mpy_32_16_r( zir[j], alpha ); /* Qx */
375 0 : move32();
376 0 : alpha = sub( alpha, step );
377 : }
378 0 : }
379 :
380 0 : void predict_signal(
381 : const Word16 excI[], /* i : input excitation buffer Qx*/
382 : Word16 excO[], /* o : output excitation buffer Qx*/
383 : const Word16 T0, /* i : integer pitch lag Q0*/
384 : Word16 frac, /* i : fraction of lag Q0*/
385 : const Word16 frac_max, /* i : max fraction Q0*/
386 : const Word16 L_subfr /* i : subframe size Q0*/
387 : )
388 : {
389 : Word16 j;
390 : Word32 s;
391 : const Word16 *x0, *win;
392 : #ifndef ISSUE_1836_replace_overflow_libcom
393 : #ifdef BASOP_NOGLOB_DECLARE_LOCAL
394 : Flag Overflow = 0;
395 : move32();
396 : #endif
397 : #endif
398 0 : x0 = &excI[-T0 - 1];
399 0 : frac = negate( frac );
400 :
401 0 : IF( frac < 0 )
402 : {
403 0 : frac = add( frac, frac_max );
404 0 : x0--;
405 : }
406 :
407 0 : win = &inter4_2tcx2[frac][0]; /* Q15 */
408 0 : if ( EQ_16( frac_max, 6 ) )
409 0 : win = &inter6_2tcx2[frac][0]; /* Q15 */
410 :
411 0 : FOR( j = 0; j < L_subfr; j++ )
412 : {
413 : #ifdef ISSUE_1836_replace_overflow_libcom
414 0 : s = L_mult_sat( win[0], x0[0] ); /* Qx + 16 */
415 0 : s = L_mac_sat( s, win[1], x0[1] ); /* Qx + 16 */
416 0 : s = L_mac_sat( s, win[2], x0[2] ); /* Qx + 16 */
417 0 : excO[j] = mac_r_sat( s, win[3], x0[3] ); /* Qx + 16 */
418 : #else
419 : s = L_mult_o( win[0], x0[0], &Overflow ); /* Qx + 16 */
420 : s = L_mac_o( s, win[1], x0[1], &Overflow ); /* Qx + 16 */
421 : s = L_mac_o( s, win[2], x0[2], &Overflow ); /* Qx + 16 */
422 : excO[j] = mac_ro( s, win[3], x0[3], &Overflow ); /* Qx + 16 */
423 : #endif
424 0 : move16();
425 :
426 0 : x0++;
427 : }
428 0 : }
429 :
430 6755 : static void tcx_ltp_synth_filter(
431 : Word16 *synth_ltp, /* Qx */
432 : Word16 *synth, /* Qx */
433 : Word16 length, /* Q0 */
434 : Word16 pitch_int, /* Q0 */
435 : Word16 pitch_fr, /* Q0 */
436 : Word16 gain, /* Q15 */
437 : Word16 pitch_res, /* Q0 */
438 : Word16 *zir, /* can be NULL */
439 : Word16 fade, /* 0=normal, +1=fade-in, -1=fade-out Q0*/
440 : Word16 filtIdx /* Q0 */
441 : )
442 : {
443 : Word16 *x0, *x1;
444 : Word16 *y0, *y1;
445 : Word32 s, s2;
446 : const Word16 *v0, *v1;
447 : const Word16 *w0, *w1;
448 6755 : Word16 alpha, step = 0; /* initialize just to avoid compiler warning */
449 6755 : move16();
450 : Word16 i, j, k, L;
451 :
452 6755 : IF( gain > 0 )
453 : {
454 1493 : x0 = &synth_ltp[-pitch_int]; /* Qx */
455 1493 : x1 = x0 - 1;
456 1493 : y0 = synth; /* Qx */
457 1493 : y1 = y0 - 1;
458 :
459 1493 : assert( filtIdx >= 0 );
460 :
461 1493 : w0 = &tcxLtpFilters[filtIdx].filt[pitch_fr]; /* Q15 */
462 1493 : w1 = &tcxLtpFilters[filtIdx].filt[pitch_res - pitch_fr]; /* Q15 */
463 1493 : v0 = &tcxLtpFilters[filtIdx].filt[0]; /* Q15 */
464 1493 : v1 = &tcxLtpFilters[filtIdx].filt[pitch_res]; /* Q15 */
465 :
466 1493 : L = tcxLtpFilters[filtIdx].length; /* Q0 */
467 1493 : move16();
468 :
469 1493 : alpha = 0;
470 1493 : move16();
471 1493 : IF( fade != 0 )
472 : {
473 172 : if ( fade < 0 )
474 : {
475 86 : alpha = 0x7FFF; /* 1 in Q15 */
476 86 : move16();
477 : }
478 :
479 : /* step = 1.f/(float)(length); */
480 172 : step = shl( 2, norm_s( length ) );
481 172 : if ( s_and( length, sub( length, 1 ) ) != 0 )
482 : {
483 172 : step = mult_r( step, 26214 /*64.f/80.f Q15*/ ); /* Q15 */
484 : }
485 172 : if ( EQ_16( length, 240 ) )
486 : {
487 94 : step = 137 /*1.f/240.f Q15*/;
488 94 : move16();
489 : }
490 :
491 172 : if ( fade < 0 )
492 86 : step = negate( step );
493 : }
494 :
495 393373 : FOR( j = 0; j < length; j++ )
496 : {
497 391880 : s = L_deposit_l( 0 );
498 391880 : s2 = L_deposit_l( 0 );
499 391880 : k = 0;
500 391880 : move16();
501 2604276 : FOR( i = 0; i < L; i++ )
502 : {
503 2212396 : s = L_mac_sat( L_mac_sat( s, w0[k], x0[i] ), w1[k], x1[-i] ); /* Qx */
504 2212396 : s2 = L_mac_sat( L_mac_sat( s2, v0[k], y0[i] ), v1[k], y1[-i] ); /* Qx */
505 2212396 : k = k + pitch_res;
506 : }
507 :
508 : /* s2 *= ALPHA;
509 : normal: synth_ltp[j] = synth[j] - gain * s2 + gain * s;
510 : zir: synth_ltp[j] = synth[j] - gain * s2 + gain * s - zir[j];
511 : fade-in/out: synth_ltp[j] = synth[j] - alpha * gain * s2 + alpha * gain * s; */
512 391880 : i = sub_sat( round_fx_sat( s ), mult_r_sat( round_fx_sat( s2 ), ALPHA ) ); /* Qx */
513 391880 : k = mult_r( gain, i ); /* Qx */
514 391880 : if ( fade != 0 )
515 35040 : k = mult_r( k, alpha ); /* Qx */
516 391880 : k = add_sat( synth[j], k ); /* Qx */
517 391880 : if ( zir != NULL )
518 : {
519 54640 : k = sub_sat( k, zir[j] ); /* Qx */
520 : }
521 :
522 391880 : synth_ltp[j] = k; /* Qx */
523 391880 : move16();
524 :
525 : BASOP_SATURATE_WARNING_OFF_EVS;
526 391880 : if ( fade != 0 )
527 : {
528 35040 : alpha = add_sat( alpha, step );
529 : }
530 : BASOP_SATURATE_WARNING_ON_EVS;
531 :
532 391880 : x0++;
533 391880 : x1++;
534 391880 : y0++;
535 391880 : y1++;
536 : }
537 : }
538 : ELSE
539 : {
540 5262 : Copy( synth, synth_ltp, length ); /* Qx */
541 : }
542 6755 : }
543 :
544 2263889 : static void tcx_ltp_synth_filter32(
545 : Word32 *synth_ltp, /* Qx */
546 : Word32 *synth, /* Qx */
547 : Word16 length, /* Q0 */
548 : Word16 pitch_int, /* Q0 */
549 : Word16 pitch_fr, /* Q0 */
550 : Word16 gain, /* Q15 */
551 : Word16 pitch_res, /* Q0 */
552 : Word32 *zir, /* can be NULL Qx*/
553 : Word16 fade, /* 0=normal, +1=fade-in, -1=fade-out Q0*/
554 : Word16 filtIdx /* Q0 */
555 : )
556 : {
557 : Word32 *x0, *x1;
558 : Word32 *y0, *y1;
559 : Word32 s, s2;
560 : const Word16 *v0, *v1;
561 : const Word16 *w0, *w1;
562 2263889 : Word16 alpha, step = 0; /* initialize just to avoid compiler warning */
563 : Word16 i, j, k, L;
564 : Word32 L_tmp, L_tmp2;
565 :
566 2263889 : IF( gain > 0 )
567 : {
568 363496 : x0 = &synth_ltp[-pitch_int]; /* Qx */
569 363496 : x1 = x0 - 1;
570 363496 : y0 = synth; /* Qx */
571 363496 : y1 = y0 - 1;
572 :
573 363496 : assert( filtIdx >= 0 );
574 :
575 363496 : w0 = &tcxLtpFilters[filtIdx].filt[pitch_fr]; /* Q15 */
576 363496 : w1 = &tcxLtpFilters[filtIdx].filt[pitch_res - pitch_fr]; /* Q15 */
577 363496 : v0 = &tcxLtpFilters[filtIdx].filt[0]; /* Q15 */
578 363496 : v1 = &tcxLtpFilters[filtIdx].filt[pitch_res]; /* Q15 */
579 :
580 363496 : L = tcxLtpFilters[filtIdx].length; /* Q0 */
581 363496 : move16();
582 :
583 363496 : alpha = 0;
584 363496 : move16();
585 363496 : IF( fade != 0 )
586 : {
587 0 : if ( fade < 0 )
588 : {
589 0 : alpha = 0x7FFF; /* 1 in Q15 */
590 0 : move16();
591 : }
592 :
593 : /* step = 1.f/(float)(length); */
594 0 : step = shl( 2, norm_s( length ) );
595 0 : if ( s_and( length, sub( length, 1 ) ) != 0 )
596 : {
597 0 : step = mult_r( step, 26214 /*64.f/80.f Q15*/ ); /* Q15 */
598 : }
599 0 : if ( EQ_16( length, 240 ) )
600 : {
601 0 : step = 137 /*1.f/240.f Q15*/;
602 0 : move16();
603 : }
604 :
605 0 : if ( fade < 0 )
606 0 : step = negate( step );
607 : }
608 :
609 107384146 : FOR( j = 0; j < length; j++ )
610 : {
611 107020650 : s = L_deposit_l( 0 );
612 107020650 : s2 = L_deposit_l( 0 );
613 107020650 : k = 0;
614 107020650 : move16();
615 829507430 : FOR( i = 0; i < L; i++ )
616 : {
617 722486780 : s = Madd_32_16_r( Madd_32_16_r( s, x0[i], w0[k] ), x1[-i], w1[k] ); /* Qx */
618 722486780 : s2 = Madd_32_16_r( Madd_32_16_r( s2, y0[i], v0[k] ), y1[-i], v1[k] ); /* Qx */
619 722486780 : k = k + pitch_res;
620 : }
621 :
622 : /* s2 *= ALPHA;
623 : normal: synth_ltp[j] = synth[j] - gain * s2 + gain * s;
624 : zir: synth_ltp[j] = synth[j] - gain * s2 + gain * s - zir[j];
625 : fade-in/out: synth_ltp[j] = synth[j] - alpha * gain * s2 + alpha * gain * s; */
626 107020650 : L_tmp = L_sub_sat( s, Mpy_32_16_r( s2, ALPHA ) ); /* Qx */
627 107020650 : L_tmp2 = Mpy_32_16_r( L_tmp, gain ); /* Qx */
628 107020650 : IF( fade != 0 )
629 0 : L_tmp2 = Mpy_32_16_r( L_tmp2, alpha ); /* Qx */
630 107020650 : L_tmp2 = L_add_sat( synth[j], L_tmp2 ); /* Qx */
631 107020650 : if ( zir != NULL )
632 : {
633 0 : L_tmp2 = L_sub_sat( L_tmp2, zir[j] ); /* Qx */
634 : }
635 :
636 107020650 : synth_ltp[j] = L_tmp2; /* Qx */
637 107020650 : move16();
638 :
639 : BASOP_SATURATE_WARNING_OFF_EVS;
640 107020650 : if ( fade != 0 )
641 : {
642 0 : alpha = add_sat( alpha, step );
643 : }
644 : BASOP_SATURATE_WARNING_ON_EVS;
645 :
646 107020650 : x0++;
647 107020650 : x1++;
648 107020650 : y0++;
649 107020650 : y1++;
650 : }
651 : }
652 : ELSE
653 : {
654 1900393 : Copy32( synth, synth_ltp, length ); /* Qx */
655 : }
656 2263889 : }
657 :
658 0 : static void tcx_ltp_synth_filter_10(
659 : Word16 *out, /* Qx */
660 : Word16 *in, /* Qx */
661 : const Word16 length, /* Q0 */
662 : const Word16 pitch_int, /* Q0 */
663 : const Word16 pitch_fr, /* Q0 */
664 : const Word16 gain, /* Q15 */
665 : const Word16 pitch_res, /* Q0 */
666 : const Word16 filtIdx /* Q0 */
667 : )
668 : {
669 : Word16 *x0, *x1;
670 : Word16 *y0, *y1;
671 : Word32 s, s2;
672 : const Word16 *v0, *v1;
673 : const Word16 *w0, *w1;
674 : Word16 i, j, k, L;
675 : Word16 curr_gain, gain_step;
676 :
677 0 : x0 = &out[-pitch_int]; /* Qx */
678 0 : x1 = x0 - 1;
679 0 : y0 = in; /* Qx */
680 0 : y1 = y0 - 1;
681 :
682 0 : assert( GE_16( filtIdx, 0 ) );
683 :
684 0 : w0 = &tcxLtpFilters[filtIdx].filt[pitch_fr]; /* Q15 */
685 0 : w1 = &tcxLtpFilters[filtIdx].filt[pitch_res - pitch_fr]; /* Q15 */
686 0 : v0 = &tcxLtpFilters[filtIdx].filt[0]; /* Q15 */
687 0 : v1 = &tcxLtpFilters[filtIdx].filt[pitch_res]; /* Q15 */
688 0 : L = tcxLtpFilters[filtIdx].length; /* Q0 */
689 :
690 0 : curr_gain = gain;
691 0 : move16();
692 :
693 0 : gain_step = div_s( negate( gain ), length ); /* Q15 */
694 :
695 0 : FOR( j = 0; j < length; j++ )
696 : {
697 0 : s = 0;
698 0 : s2 = 0;
699 0 : move32();
700 0 : move32();
701 0 : k = 0;
702 0 : move16();
703 0 : FOR( i = 0; i < L; i++ )
704 : {
705 0 : s = L_mac_sat( L_mac_sat( s, w0[k], x0[i] ), w1[k], x1[-i] ); /* Qx */
706 0 : s2 = L_mac_sat( L_mac_sat( s2, v0[k], y0[i] ), v1[k], y1[-i] ); /* Qx */
707 0 : k = add( k, pitch_res );
708 : }
709 :
710 0 : out[j] = add_sat( in[j], mult_r_sat( curr_gain, sub_sat( round_fx_sat( s ), mult_r_sat( round_fx_sat( s2 ), ALPHA ) ) ) ); /* Qx */
711 :
712 0 : x0++;
713 0 : x1++;
714 0 : y0++;
715 0 : y1++;
716 :
717 0 : curr_gain = add( curr_gain, gain_step );
718 : }
719 :
720 0 : return;
721 : }
722 :
723 27598 : static void tcx_ltp_synth_filter_10_fx(
724 : Word32 *out, /* Qx */
725 : Word32 *in, /* Qx */
726 : const Word16 length, /* Q0 */
727 : const Word16 pitch_int, /* Q0 */
728 : const Word16 pitch_fr, /* Q0 */
729 : const Word16 gain, /* Q15 */
730 : const Word16 pitch_res, /* Q0 */
731 : const Word16 filtIdx /* Q0 */
732 : )
733 : {
734 : Word32 *x0, *x1;
735 : Word32 *y0, *y1;
736 : Word32 s, s2;
737 : const Word16 *v0, *v1;
738 : const Word16 *w0, *w1;
739 : Word16 i, j, k, L;
740 : Word16 curr_gain, gain_step;
741 :
742 27598 : x0 = &out[-pitch_int]; /* Qx */
743 27598 : x1 = x0 - 1;
744 27598 : y0 = in; /* Qx */
745 27598 : y1 = y0 - 1;
746 :
747 27598 : assert( filtIdx >= 0 );
748 :
749 27598 : w0 = &tcxLtpFilters[filtIdx].filt[pitch_fr]; /* Q15 */
750 27598 : w1 = &tcxLtpFilters[filtIdx].filt[pitch_res - pitch_fr]; /* Q15 */
751 27598 : v0 = &tcxLtpFilters[filtIdx].filt[0]; /* Q15 */
752 27598 : v1 = &tcxLtpFilters[filtIdx].filt[pitch_res]; /* Q15 */
753 27598 : L = tcxLtpFilters[filtIdx].length; /* Q0 */
754 :
755 27598 : curr_gain = gain;
756 27598 : move16();
757 27598 : gain_step = idiv1616( negate( gain ), length ); // TODO
758 :
759 5621198 : FOR( j = 0; j < length; j++ )
760 : {
761 5593600 : s = 0;
762 5593600 : move16();
763 5593600 : s2 = 0;
764 5593600 : move16();
765 5593600 : k = 0;
766 5593600 : move16();
767 43103840 : FOR( i = 0; i < L; i++ )
768 : {
769 37510240 : s = Madd_32_16_r( Madd_32_16_r( s, x0[i], w0[k] ), x1[-i], w1[k] ); /* Qx */
770 37510240 : s2 = Madd_32_16_r( Madd_32_16_r( s2, y0[i], v0[k] ), y1[-i], v1[k] ); /* Qx */
771 37510240 : k = k + pitch_res;
772 : }
773 :
774 5593600 : out[j] = L_add_sat( in[j], Mpy_32_16_1( L_sub_sat( s, Mpy_32_16_1( s2, ALPHA ) ), curr_gain ) ); /* Qx */
775 5593600 : move32();
776 5593600 : x0++;
777 5593600 : x1++;
778 5593600 : y0++;
779 5593600 : y1++;
780 :
781 5593600 : curr_gain = add( curr_gain, gain_step );
782 : }
783 :
784 27598 : return;
785 : }
786 :
787 0 : static void tcx_ltp_synth_filter_01(
788 : Word16 *out, /* Qx */
789 : Word16 *in, /* Qx */
790 : const Word16 length, /* Q0 */
791 : const Word16 pitch_int, /* Q0 */
792 : const Word16 pitch_fr, /* Q0 */
793 : const Word16 gain, /* Q15 */
794 : const Word16 pitch_res, /* Q0 */
795 : const Word16 filtIdx /* Q0 */
796 : )
797 : {
798 : Word16 *x0, *x1;
799 : Word16 *y0, *y1;
800 : Word32 s, s2;
801 : const Word16 *v0, *v1;
802 : const Word16 *w0, *w1;
803 : Word16 i, j, k, L;
804 : Word16 curr_gain, gain_step;
805 :
806 0 : x0 = &out[-( pitch_int )]; /* Qx */
807 0 : x1 = x0 - 1;
808 0 : y0 = in; /* Qx */
809 0 : y1 = y0 - 1;
810 :
811 0 : assert( filtIdx >= 0 );
812 :
813 0 : w0 = &tcxLtpFilters[filtIdx].filt[pitch_fr]; /* Q15 */
814 0 : w1 = &tcxLtpFilters[filtIdx].filt[pitch_res - pitch_fr]; /* Q15 */
815 0 : v0 = &tcxLtpFilters[filtIdx].filt[0]; /* Q15 */
816 0 : v1 = &tcxLtpFilters[filtIdx].filt[pitch_res]; /* Q15 */
817 0 : L = tcxLtpFilters[filtIdx].length; /* Q0 */
818 :
819 0 : curr_gain = 0;
820 0 : move16();
821 0 : gain_step = idiv1616( gain, length ); // TODO
822 :
823 0 : for ( j = 0; j < length; j++ )
824 : {
825 0 : s = 0;
826 0 : move16();
827 0 : s2 = 0;
828 0 : move16();
829 :
830 0 : for ( i = 0, k = 0; i < L; i++, k = k + pitch_res )
831 : {
832 0 : s = L_mac_sat( L_mac_sat( s, w0[k], x0[i] ), w1[k], x1[-i] ); /* Qx */
833 0 : s2 = L_mac_sat( L_mac_sat( s2, v0[k], y0[i] ), v1[k], y1[-i] ); /* Qx */
834 : }
835 :
836 0 : out[j] = add_sat( in[j], mult_r_sat( curr_gain, sub_sat( round_fx_sat( s ), mult_r_sat( round_fx_sat( s2 ), ALPHA ) ) ) ); /* Qx */
837 0 : move32();
838 :
839 0 : x0++;
840 0 : x1++;
841 0 : y0++;
842 0 : y1++;
843 :
844 0 : curr_gain = add( curr_gain, gain_step );
845 : }
846 :
847 0 : return;
848 : }
849 :
850 28759 : static void tcx_ltp_synth_filter_01_fx(
851 : Word32 *out, /* Qx */
852 : Word32 *in, /* Qx */
853 : const Word16 length, /* Q0 */
854 : const Word16 pitch_int, /* Q0 */
855 : const Word16 pitch_fr, /* Q0 */
856 : const Word16 gain, /* Q15 */
857 : const Word16 pitch_res, /* Q0 */
858 : const Word16 filtIdx /* Q0 */
859 : )
860 : {
861 : Word32 *x0, *x1;
862 : Word32 *y0, *y1;
863 : Word32 s, s2;
864 : const Word16 *v0, *v1;
865 : const Word16 *w0, *w1;
866 : Word16 i, j, k, L;
867 : Word16 curr_gain, gain_step;
868 :
869 28759 : x0 = &out[-( pitch_int )]; /* Qx */
870 28759 : x1 = x0 - 1;
871 28759 : y0 = in; /* Qx */
872 28759 : y1 = y0 - 1;
873 :
874 28759 : assert( filtIdx >= 0 );
875 :
876 28759 : w0 = &tcxLtpFilters[filtIdx].filt[pitch_fr]; /* Q15 */
877 28759 : w1 = &tcxLtpFilters[filtIdx].filt[pitch_res - pitch_fr]; /* Q15 */
878 28759 : v0 = &tcxLtpFilters[filtIdx].filt[0]; /* Q15 */
879 28759 : v1 = &tcxLtpFilters[filtIdx].filt[pitch_res]; /* Q15 */
880 28759 : L = tcxLtpFilters[filtIdx].length; /* Q0 */
881 :
882 28759 : curr_gain = 0;
883 28759 : move16();
884 28759 : gain_step = idiv1616( gain, length );
885 :
886 5870199 : FOR( j = 0; j < length; j++ )
887 : {
888 5841440 : s = 0;
889 5841440 : move16();
890 5841440 : s2 = 0;
891 5841440 : move16();
892 5841440 : k = 0;
893 5841440 : move16();
894 45081440 : FOR( i = 0; i < L; i++ )
895 : {
896 39240000 : s = Madd_32_16_r( Madd_32_16_r( s, x0[i], w0[k] ), x1[-i], w1[k] ); /* Qx */
897 39240000 : s2 = Madd_32_16_r( Madd_32_16_r( s2, y0[i], v0[k] ), y1[-i], v1[k] ); /* Qx */
898 39240000 : k = k + pitch_res;
899 : }
900 :
901 5841440 : out[j] = L_add_sat( in[j], Mpy_32_16_r( L_sub_sat( s, Mpy_32_16_1( s2, ALPHA ) ), curr_gain ) ); /* Qx */
902 5841440 : move32();
903 :
904 5841440 : x0++;
905 5841440 : x1++;
906 5841440 : y0++;
907 5841440 : y1++;
908 :
909 5841440 : curr_gain = add( curr_gain, gain_step );
910 : }
911 :
912 28759 : return;
913 : }
914 :
915 : /*-------------------------------------------------------------------
916 : *tcx_ltp_synth_filter_11_unequal_pitch_flt()
917 : *
918 : * blend between two filters by means of OAO
919 : * filter the input signal at the initial subinterval with
920 : * the first filter unit according to parameters associated to
921 : * the preceding update interval with scaling from non-zero gain towards 0
922 : * followed by the second filter unit according to parameters associated to
923 : * the current update interval with scaling from 0 towards non-zero gain
924 : ---------------------------------------------------------------------*/
925 :
926 0 : static void tcx_ltp_synth_filter_11_unequal_pitch(
927 : Word16 *out, /* Qx */
928 : Word16 *in, /* Qx */
929 : const Word16 length, /* Q0 */
930 : const Word16 cur_pitch_int, /* Q0 */
931 : const Word16 cur_pitch_fr, /* Q0 */
932 : const Word16 cur_gain, /* Q15 */
933 : const Word16 pitch_res, /* Q0 */
934 : const Word16 filtIdx, /* Q0 */
935 : const Word16 prev_pitch_int, /* Q0 */
936 : const Word16 prev_pitch_fr, /* Q0 */
937 : const Word16 prev_gain, /* Q15 */
938 : const Word16 prev_pitch_res, /* Q0 */
939 : const Word16 prev_filtIdx /* Q0 */
940 : )
941 : {
942 : Word16 *x0, *x1;
943 : Word16 *y0, *y1;
944 : Word16 *l0, *l1;
945 : Word16 *m0, *m1;
946 : Word32 s, s2, s3, s4;
947 : const Word16 *v0, *v1;
948 : const Word16 *w0, *w1;
949 : const Word16 *p0, *p1;
950 : const Word16 *q0, *q1;
951 : Word16 i, j, k, L;
952 : Word16 prev_L;
953 : Word16 temp_buf[MAX_TRANSITION_LEN + 2 * MAX_TCX_LTP_FILTER_LEN];
954 : Word16 *temp_ptr;
955 : Word16 gain, gain_step;
956 :
957 0 : x0 = &out[-( prev_pitch_int )];
958 0 : x1 = x0 - 1;
959 0 : y0 = in;
960 0 : y1 = y0 - 1;
961 :
962 0 : assert( ( filtIdx >= 0 ) && ( prev_filtIdx >= 0 ) );
963 :
964 0 : w0 = &tcxLtpFilters[prev_filtIdx].filt[prev_pitch_fr]; /* Q15 */
965 0 : w1 = &tcxLtpFilters[prev_filtIdx].filt[prev_pitch_res - prev_pitch_fr]; /* Q15 */
966 0 : v0 = &tcxLtpFilters[prev_filtIdx].filt[0]; /* Q15 */
967 0 : v1 = &tcxLtpFilters[prev_filtIdx].filt[prev_pitch_res]; /* Q15 */
968 :
969 0 : prev_L = tcxLtpFilters[prev_filtIdx].length; /* Q0 */
970 0 : move16();
971 :
972 0 : p0 = &tcxLtpFilters[filtIdx].filt[cur_pitch_fr]; /* Q15 */
973 0 : p1 = &tcxLtpFilters[filtIdx].filt[pitch_res - cur_pitch_fr]; /* Q15 */
974 0 : q0 = &tcxLtpFilters[filtIdx].filt[0]; /* Q15 */
975 0 : q1 = &tcxLtpFilters[filtIdx].filt[pitch_res]; /* Q15 */
976 :
977 0 : L = tcxLtpFilters[filtIdx].length; /* Q0 */
978 0 : move16();
979 :
980 : /* 1. decreasing gain filter. The first filter unit with the parameters associated to the previous interval and scaling towards 0 */
981 0 : gain = prev_gain;
982 0 : move16();
983 0 : gain_step = idiv1616( negate( prev_gain ), length );
984 :
985 0 : FOR( j = 0; j < length; j++ )
986 : {
987 0 : s = 0;
988 0 : move16();
989 0 : s2 = 0;
990 0 : move16();
991 0 : k = 0;
992 0 : move16();
993 0 : FOR( i = 0; i < prev_L; i++ )
994 : {
995 0 : s = L_mac_sat( L_mac_sat( s, w0[k], x0[i] ), w1[k], x1[-i] ); /* Qx */
996 0 : s2 = L_mac_sat( L_mac_sat( s2, v0[k], y0[i] ), v1[k], y1[-i] ); /* Qx */
997 0 : k = k + prev_pitch_res;
998 : }
999 :
1000 0 : out[j] = add_sat( in[j], mult_r_sat( gain, sub_sat( round_fx_sat( s ), mult_r_sat( round_fx_sat( s2 ), ALPHA ) ) ) ); /* Qx */
1001 :
1002 0 : x0++;
1003 0 : x1++;
1004 0 : y0++;
1005 0 : y1++;
1006 :
1007 0 : gain = add( gain, gain_step );
1008 : }
1009 :
1010 0 : Copy( out - L, temp_buf, length + L ); /* Qx */
1011 0 : Copy( in + length, temp_buf + length + L, L ); /* Qx */
1012 0 : temp_ptr = &temp_buf[0] + L;
1013 :
1014 0 : m0 = temp_ptr; /* Qx */
1015 0 : m1 = temp_ptr - 1; /* Qx */
1016 0 : l0 = &out[-( cur_pitch_int )]; /* Qx */
1017 0 : l1 = l0 - 1;
1018 :
1019 : /* 2. increasing gain filter. The second filter unit with the parameters associated to the current interval and scaling from 0 towards current gain */
1020 0 : gain = 0;
1021 0 : move16();
1022 0 : gain_step = idiv1616( cur_gain, length );
1023 :
1024 0 : FOR( j = 0; j < length; j++ )
1025 : {
1026 0 : s3 = 0;
1027 0 : move16();
1028 0 : s4 = 0;
1029 0 : move16();
1030 0 : k = 0;
1031 0 : move16();
1032 0 : FOR( i = 0; i < L; i++ )
1033 : {
1034 0 : s3 = L_mac_sat( L_mac_sat( s3, p0[k], l0[i] ), p1[k], l1[-i] ); /* Qx */
1035 0 : s4 = L_mac_sat( L_mac_sat( s4, q0[k], m0[i] ), q1[k], m1[-i] ); /* Qx */
1036 0 : k = k + pitch_res;
1037 : }
1038 :
1039 0 : out[j] = add_sat( *( temp_ptr + j ), mult_r_sat( gain, sub_sat( round_fx_sat( s3 ), mult_r_sat( round_fx_sat( s4 ), ALPHA ) ) ) ); /* Qx */
1040 0 : move32();
1041 :
1042 0 : l0++;
1043 0 : l1++;
1044 0 : m0++;
1045 0 : m1++;
1046 :
1047 0 : gain = add( gain, gain_step );
1048 : }
1049 :
1050 0 : return;
1051 : }
1052 :
1053 118792 : static void tcx_ltp_synth_filter_11_unequal_pitch_fx(
1054 : Word32 *out, /* Qx */
1055 : Word32 *in, /* Qx */
1056 : const Word16 length, /* Q0 */
1057 : const Word16 cur_pitch_int, /* Q0 */
1058 : const Word16 cur_pitch_fr, /* Q0 */
1059 : const Word16 cur_gain, /* Q15 */
1060 : const Word16 pitch_res, /* Q0 */
1061 : const Word16 filtIdx, /* Q0 */
1062 : const Word16 prev_pitch_int, /* Q0 */
1063 : const Word16 prev_pitch_fr, /* Q0 */
1064 : const Word16 prev_gain, /* Q15 */
1065 : const Word16 prev_pitch_res, /* Q0 */
1066 : const Word16 prev_filtIdx /* Q0 */
1067 : )
1068 : {
1069 : Word32 *x0, *x1;
1070 : Word32 *y0, *y1;
1071 : Word32 *l0, *l1;
1072 : Word32 *m0, *m1;
1073 : Word32 s, s2, s3, s4;
1074 : const Word16 *v0, *v1;
1075 : const Word16 *w0, *w1;
1076 : const Word16 *p0, *p1;
1077 : const Word16 *q0, *q1;
1078 : Word16 i, j, k, L;
1079 : Word16 prev_L;
1080 : Word32 temp_buf[MAX_TRANSITION_LEN + 2 * MAX_TCX_LTP_FILTER_LEN];
1081 : Word32 *temp_ptr;
1082 : Word16 gain, gain_step;
1083 :
1084 118792 : x0 = &out[-( prev_pitch_int )]; /* Qx */
1085 118792 : x1 = x0 - 1;
1086 118792 : y0 = in; /* Qx */
1087 118792 : y1 = y0 - 1;
1088 :
1089 118792 : assert( GE_16( filtIdx, 0 ) && GE_16( prev_filtIdx, 0 ) );
1090 :
1091 118792 : w0 = &tcxLtpFilters[prev_filtIdx].filt[prev_pitch_fr]; /* Q15 */
1092 118792 : w1 = &tcxLtpFilters[prev_filtIdx].filt[prev_pitch_res - prev_pitch_fr]; /* Q15 */
1093 118792 : v0 = &tcxLtpFilters[prev_filtIdx].filt[0]; /* Q15 */
1094 118792 : v1 = &tcxLtpFilters[prev_filtIdx].filt[prev_pitch_res]; /* Q15 */
1095 :
1096 118792 : prev_L = tcxLtpFilters[prev_filtIdx].length; /* Q0 */
1097 118792 : move16();
1098 :
1099 118792 : p0 = &tcxLtpFilters[filtIdx].filt[cur_pitch_fr]; /* Q15 */
1100 118792 : p1 = &tcxLtpFilters[filtIdx].filt[pitch_res - cur_pitch_fr]; /* Q15 */
1101 118792 : q0 = &tcxLtpFilters[filtIdx].filt[0]; /* Q15 */
1102 118792 : q1 = &tcxLtpFilters[filtIdx].filt[pitch_res]; /* Q15 */
1103 :
1104 118792 : L = tcxLtpFilters[filtIdx].length; /* Q0 */
1105 118792 : move16();
1106 :
1107 : /* 1. decreasing gain filter. The first filter unit with the parameters associated to the previous interval and scaling towards 0 */
1108 118792 : gain = prev_gain;
1109 118792 : move16();
1110 118792 : gain_step = idiv1616( negate( prev_gain ), length ); // TODOD
1111 :
1112 24240152 : FOR( j = 0; j < length; j++ )
1113 : {
1114 24121360 : s = 0;
1115 24121360 : move16();
1116 24121360 : s2 = 0;
1117 24121360 : move16();
1118 24121360 : k = 0;
1119 24121360 : move16();
1120 187953840 : FOR( i = 0; i < prev_L; i++ )
1121 : {
1122 163832480 : s = Madd_32_16_r( Madd_32_16_r( s, x0[i], w0[k] ), x1[-i], w1[k] ); /* Qx */
1123 163832480 : s2 = Madd_32_16_r( Madd_32_16_r( s2, y0[i], v0[k] ), y1[-i], v1[k] ); /* Qx */
1124 163832480 : k += prev_pitch_res;
1125 : }
1126 :
1127 24121360 : out[j] = L_add_sat( in[j], Mpy_32_16_r( L_sub_sat( s, Mpy_32_16_1( s2, ALPHA ) ), gain ) ); /* Qx */
1128 24121360 : move32();
1129 24121360 : x0++;
1130 24121360 : x1++;
1131 24121360 : y0++;
1132 24121360 : y1++;
1133 :
1134 24121360 : gain = add( gain, gain_step );
1135 : }
1136 :
1137 118792 : Copy32( out - L, temp_buf, length + L ); /* Qx */
1138 118792 : Copy32( in + length, temp_buf + length + L, L ); /* Qx */
1139 118792 : temp_ptr = &temp_buf[0] + L; /* Qx */
1140 :
1141 118792 : m0 = temp_ptr; /* Qx */
1142 118792 : m1 = temp_ptr - 1;
1143 118792 : l0 = &out[-( cur_pitch_int )]; /* Qx */
1144 118792 : l1 = l0 - 1;
1145 :
1146 : /* 2. increasing gain filter. The second filter unit with the parameters associated to the current interval and scaling from 0 towards current gain */
1147 118792 : gain = 0;
1148 118792 : move16();
1149 118792 : gain_step = idiv1616( cur_gain, length );
1150 :
1151 24240152 : FOR( j = 0; j < length; j++ )
1152 : {
1153 24121360 : s3 = 0;
1154 24121360 : move16();
1155 24121360 : s4 = 0;
1156 24121360 : move16();
1157 24121360 : k = 0;
1158 187950640 : FOR( i = 0; i < L; i++ )
1159 : {
1160 163829280 : s3 = Madd_32_16_r( Madd_32_16_r( s3, l0[i], p0[k] ), l1[-i], p1[k] ); /* Qx */
1161 163829280 : s4 = Madd_32_16_r( Madd_32_16_r( s4, m0[i], q0[k] ), m1[-i], q1[k] ); /* Qx */
1162 163829280 : k = add( k, pitch_res );
1163 : }
1164 :
1165 24121360 : out[j] = L_add_sat( *( temp_ptr + j ), Mpy_32_16_r( L_sub_sat( s3, Mpy_32_16_1( s4, ALPHA ) ), gain ) ); /* Qx */
1166 24121360 : move32();
1167 :
1168 24121360 : l0++;
1169 24121360 : l1++;
1170 24121360 : m0++;
1171 24121360 : m1++;
1172 :
1173 24121360 : gain = add( gain, gain_step );
1174 : }
1175 :
1176 118792 : return;
1177 : }
1178 :
1179 826215 : Word16 tcx_ltp_decode_params(
1180 : Word16 *ltp_param, /* Q0 */
1181 : Word16 *pitch_int, /* Q0 */
1182 : Word16 *pitch_fr, /* Q0 */
1183 : Word16 *gain, /* Q13 */
1184 : const Word16 pitmin, /* Q0 */
1185 : const Word16 pitfr1, /* Q0 */
1186 : const Word16 pitfr2, /* Q0 */
1187 : const Word16 pitmax, /* Q0 */
1188 : const Word16 pitres /* Q0 */
1189 : )
1190 : {
1191 : Word16 tmp, tmp2;
1192 :
1193 :
1194 : /* Decode Pitch and Gain */
1195 826215 : test();
1196 826215 : IF( ltp_param != 0 && ltp_param[0] != 0 )
1197 : {
1198 555661 : tmp = imult1616( sub( pitfr2, pitmin ), pitres ); /* Q0 */
1199 :
1200 555661 : IF( LT_16( ltp_param[1], tmp ) )
1201 : {
1202 375340 : tmp2 = idiv1616U( ltp_param[1], pitres );
1203 :
1204 375340 : *pitch_int = add( pitmin, tmp2 ); /* Q0 */
1205 375340 : move16();
1206 375340 : tmp2 = sub( *pitch_int, pitmin ); /* Q0 */
1207 375340 : *pitch_fr = sub( ltp_param[1], imult1616( tmp2, pitres ) ); /* Q0 */
1208 375340 : move16();
1209 : }
1210 : ELSE
1211 : {
1212 180321 : tmp2 = imult1616( sub( pitfr1, pitfr2 ), shr( pitres, 1 ) ); /* Q0 */
1213 :
1214 180321 : IF( LT_16( ltp_param[1], add( tmp, tmp2 ) ) )
1215 : {
1216 54230 : tmp2 = idiv1616U( sub( ltp_param[1], tmp ), shr( pitres, 1 ) ); /* Q0 */
1217 :
1218 54230 : *pitch_int = add( pitfr2, tmp2 ); /* Q0 */
1219 54230 : move16();
1220 54230 : *pitch_fr = shl( sub( sub( ltp_param[1], tmp ), imult1616( tmp2, shr( pitres, 1 ) ) ), 1 ); /* Q0 */
1221 54230 : move16();
1222 : }
1223 : ELSE
1224 : {
1225 126091 : *pitch_int = sub( add( ltp_param[1], pitfr1 ), add( tmp, tmp2 ) ); /* Q0 */
1226 126091 : move16();
1227 126091 : *pitch_fr = 0;
1228 126091 : move16();
1229 : }
1230 : }
1231 :
1232 555661 : *gain = imult1616( add( ltp_param[2], 1 ), 0x1400 /* 0.625 in Q13 */ ); /* Q13 */
1233 555661 : move16();
1234 :
1235 555661 : IF( LT_16( *pitch_int, PIT_MIN_SHORTER ) )
1236 : {
1237 : /*pitch out of range due to bit error */
1238 0 : *pitch_int = PIT_MIN_SHORTER; /* Q0 */
1239 0 : move16();
1240 0 : return 1;
1241 : }
1242 :
1243 555661 : IF( GT_16( *pitch_int, PIT_MAX_MAX ) )
1244 : {
1245 : /*pitch out of range due to bit error */
1246 0 : *pitch_int = PIT_MAX_MAX; /* Q0 */
1247 0 : move16();
1248 0 : return 1;
1249 : }
1250 : }
1251 : ELSE
1252 : {
1253 270554 : *pitch_int = pitmax; /* Q0 */
1254 270554 : move16();
1255 270554 : *pitch_fr = 0;
1256 270554 : move16();
1257 270554 : *gain = 0;
1258 270554 : move16();
1259 : }
1260 :
1261 826215 : return 0;
1262 : }
1263 :
1264 3100 : void tcx_ltp_post_fx(
1265 : Decoder_State *st,
1266 : TCX_LTP_DEC_HANDLE hTcxLtpDec,
1267 : Word16 core, /* Q0 */
1268 : Word16 output_frame, /* Q0 */
1269 : Word16 delay, /* Q0 */
1270 : Word16 *sig, /* Qx */
1271 : Word16 *tcx_buf /* Qx */
1272 : )
1273 : {
1274 : Word16 tmp, L_transition, lpcorder, filtIdx;
1275 : Word16 gain, gain2;
1276 : Word32 tmp32;
1277 : Word16 zir[L_FRAME_PLUS / 4], A[TCXLTP_LTP_ORDER + 1];
1278 : Word16 buf_in[TCXLTP_MAX_DELAY + L_FRAME48k + TCXLTP_MAX_DELAY], buf_out[2 * L_FRAME48k];
1279 : Word16 *sig_in, *sig_out;
1280 : Word16 pitch_int, pitch_fr;
1281 : Word16 tcx_buf_len, bfi, L_frame_core, SideInfoOnly;
1282 : Word32 total_brate;
1283 :
1284 3100 : total_brate = st->total_brate; /* Q0 */
1285 3100 : move32();
1286 3100 : IF( EQ_16( st->element_mode, IVAS_CPE_MDCT ) )
1287 : {
1288 0 : total_brate = L_mult0( st->bits_frame_nominal, FRAMES_PER_SEC ); /* Q0 */
1289 0 : move32();
1290 : }
1291 :
1292 3100 : filtIdx = 0; /* just to avoid comilation warnings */
1293 3100 : move16();
1294 3100 : tcx_buf_len = NS2SA_FX2( st->output_Fs, TCXLTP_DELAY_NS ); /* Q0 */
1295 3100 : SideInfoOnly = 0;
1296 3100 : move16();
1297 3100 : if ( GE_32( total_brate, HQ_96k ) )
1298 : {
1299 0 : SideInfoOnly = 1;
1300 0 : move16();
1301 : }
1302 :
1303 3100 : L_frame_core = st->L_frame; /* Q0 */
1304 3100 : move16();
1305 :
1306 3100 : if ( EQ_16( st->element_mode, IVAS_CPE_MDCT ) )
1307 : {
1308 0 : L_frame_core = L_FRAME; /* Q0 */
1309 0 : move16();
1310 : }
1311 :
1312 3100 : IF( EQ_16( core, ACELP_CORE ) )
1313 : {
1314 2454 : bfi = 0;
1315 2454 : move16();
1316 2454 : pitch_int = 0;
1317 2454 : move16();
1318 2454 : pitch_fr = 0;
1319 2454 : move16();
1320 2454 : gain = 0;
1321 2454 : move16();
1322 2454 : L_frame_core = st->L_frame_past; /* Q0 */
1323 2454 : move16();
1324 : }
1325 : ELSE
1326 : {
1327 646 : bfi = st->bfi; /* Q0 */
1328 646 : pitch_int = hTcxLtpDec->tcxltp_pitch_int; /* Q0 */
1329 646 : pitch_fr = hTcxLtpDec->tcxltp_pitch_fr; /* Q0 */
1330 646 : gain = hTcxLtpDec->tcxltp_gain; /* Q15 */
1331 646 : move16();
1332 646 : move16();
1333 646 : move16();
1334 646 : move16();
1335 : }
1336 : /******** Init ********/
1337 :
1338 :
1339 : /* Parameters */
1340 3100 : L_transition = shr( output_frame, 2 ); /* Q0 */
1341 3100 : lpcorder = TCXLTP_LTP_ORDER;
1342 3100 : move16();
1343 :
1344 : /* Input buffer */
1345 3100 : sig_in = buf_in + tcx_buf_len;
1346 3100 : Copy( hTcxLtpDec->tcxltp_mem_in, buf_in, tcx_buf_len ); /* exp(exp_tcxltp_mem_in) */
1347 3100 : Copy( sig, buf_in + tcx_buf_len, output_frame ); /* Qx */
1348 3100 : IF( GT_16( core, ACELP_CORE ) )
1349 : {
1350 646 : Copy( tcx_buf, sig_in + output_frame, tcx_buf_len ); /* Qx */
1351 : }
1352 3100 : Copy( sig + output_frame - tcx_buf_len, hTcxLtpDec->tcxltp_mem_in, tcx_buf_len ); /* Qx */
1353 :
1354 : /* Output buffer */
1355 3100 : sig_out = buf_out + output_frame;
1356 3100 : Copy( hTcxLtpDec->tcxltp_mem_out, buf_out, output_frame ); /* exp(exp_tcxltp_mem_out) */
1357 :
1358 : /* TCX-LTP parameters: integer pitch, fractional pitch, gain */
1359 3100 : test();
1360 3100 : test();
1361 3100 : IF( !( SideInfoOnly != 0 || hTcxLtpDec->tcxltp != 0 ) || EQ_16( core, ACELP_CORE ) )
1362 : {
1363 : /* No LTP */
1364 2454 : pitch_int = 0;
1365 2454 : move16();
1366 2454 : pitch_fr = 0;
1367 2454 : move16();
1368 2454 : gain = 0;
1369 2454 : move16();
1370 : }
1371 646 : ELSE IF( bfi == 0 )
1372 : {
1373 : /* LTP and good frame */
1374 646 : test();
1375 646 : IF( EQ_16( st->element_mode, EVS_MONO ) ) /* hard tunings for EVS_MONO, HQ_48k is TCX only */
1376 : {
1377 646 : IF( NE_16( output_frame, L_frame_core ) )
1378 : {
1379 646 : tmp = div_s( output_frame, shl( L_frame_core, 2 ) ); /* Q13 */
1380 646 : tmp32 = L_mult0( add( imult1616( pitch_int, st->pit_res_max ), pitch_fr ), tmp ); /* Q13 */
1381 646 : tmp = round_fx( L_shl( tmp32, 3 ) ); /* Q0 */
1382 646 : pitch_int = idiv1616U( tmp, st->pit_res_max );
1383 646 : pitch_fr = sub( tmp, imult1616( pitch_int, st->pit_res_max ) ); /* Q0 */
1384 : }
1385 646 : test();
1386 646 : test();
1387 646 : IF( EQ_32( total_brate, 48000 ) && EQ_16( L_frame_core, L_FRAME16k ) )
1388 : {
1389 0 : gain = mult_r( gain, 10486 /*0.32f Q15*/ ); /* Q15 */
1390 : }
1391 646 : ELSE IF( EQ_32( total_brate, 48000 ) && EQ_16( L_frame_core, 512 ) )
1392 : {
1393 0 : gain = mult_r( gain, 13107 /*0.40f Q15*/ ); /* Q15 */
1394 : }
1395 : ELSE
1396 : {
1397 646 : gain = mult_r( gain, 20972 /*0.64f Q15*/ ); /* Q15 */
1398 : }
1399 : }
1400 0 : ELSE IF( GT_16( st->element_mode, IVAS_SCE ) && GE_32( total_brate, IVAS_96k ) )
1401 : {
1402 0 : gain = mult_r( gain, 13107 /*0.40f Q15*/ ); /* Q15 */
1403 : }
1404 : ELSE
1405 : {
1406 0 : gain = mult_r( gain, 20972 /*0.64f Q15*/ ); /* Q15 */
1407 : }
1408 : }
1409 : ELSE
1410 : {
1411 : /* PLC: [TCX: Fade-out]
1412 : * PLC: LTP and bad frame (concealment) */
1413 0 : IF( EQ_16( st->pit_res_max, st->pit_res_max_past ) ) /* ensure consistent core SR to previous frame; otherwise, set gain to 0 */
1414 : {
1415 0 : pitch_int = hTcxLtpDec->tcxltp_pitch_int_post_prev;
1416 0 : move16();
1417 0 : pitch_fr = hTcxLtpDec->tcxltp_pitch_fr_post_prev;
1418 0 : move16();
1419 0 : gain = shl( mult_r( hTcxLtpDec->tcxltp_gain_post_prev, st->hTcxDec->damping ), 1 );
1420 : }
1421 : ELSE
1422 : {
1423 0 : gain = 0;
1424 0 : move16();
1425 : }
1426 : }
1427 :
1428 :
1429 3100 : IF( SideInfoOnly != 0 )
1430 : {
1431 0 : gain = 0;
1432 0 : move16();
1433 0 : if ( bfi != 0 )
1434 : {
1435 0 : hTcxLtpDec->tcxltp_gain_post_prev = 0;
1436 0 : move16();
1437 : }
1438 : }
1439 3100 : gain2 = gain;
1440 3100 : move16();
1441 :
1442 3100 : IF( EQ_16( L_frame_core, L_FRAME ) )
1443 : {
1444 1828 : SWITCH( output_frame )
1445 : {
1446 0 : case L_FRAME8k:
1447 0 : filtIdx = 0;
1448 0 : move16();
1449 0 : BREAK;
1450 0 : case L_FRAME16k:
1451 0 : filtIdx = 1;
1452 0 : move16();
1453 0 : BREAK;
1454 828 : case L_FRAME32k:
1455 828 : filtIdx = 2;
1456 828 : move16();
1457 828 : BREAK;
1458 1000 : case L_FRAME48k:
1459 1000 : filtIdx = 3;
1460 1000 : move16();
1461 1000 : BREAK;
1462 0 : default:
1463 0 : assert( 0 );
1464 : }
1465 : }
1466 1272 : ELSE IF( EQ_16( L_frame_core, L_FRAME16k ) )
1467 : {
1468 1255 : SWITCH( output_frame )
1469 : {
1470 0 : case L_FRAME8k:
1471 0 : filtIdx = 4;
1472 0 : move16();
1473 0 : BREAK;
1474 0 : case L_FRAME16k:
1475 0 : filtIdx = 5;
1476 0 : move16();
1477 0 : BREAK;
1478 222 : case L_FRAME32k:
1479 222 : filtIdx = 6;
1480 222 : move16();
1481 222 : BREAK;
1482 1033 : case L_FRAME48k:
1483 1033 : filtIdx = 7;
1484 1033 : move16();
1485 1033 : BREAK;
1486 0 : default:
1487 0 : assert( 0 );
1488 : }
1489 : }
1490 17 : ELSE IF( EQ_16( L_frame_core, 512 ) )
1491 : {
1492 0 : SWITCH( output_frame )
1493 : {
1494 0 : case L_FRAME8k:
1495 0 : filtIdx = 8;
1496 0 : move16();
1497 0 : BREAK;
1498 0 : case L_FRAME16k:
1499 0 : filtIdx = 9;
1500 0 : move16();
1501 0 : BREAK;
1502 0 : case L_FRAME32k:
1503 0 : filtIdx = 10;
1504 0 : move16();
1505 0 : BREAK;
1506 0 : case L_FRAME48k:
1507 0 : filtIdx = 11;
1508 0 : move16();
1509 0 : BREAK;
1510 0 : default:
1511 0 : assert( 0 );
1512 : }
1513 : }
1514 : ELSE
1515 : {
1516 17 : filtIdx = -1;
1517 17 : move16();
1518 : }
1519 :
1520 :
1521 : /******** Previous-frame part ********/
1522 :
1523 3100 : tcx_ltp_synth_filter( sig_out, sig_in, delay, hTcxLtpDec->tcxltp_pitch_int_post_prev, hTcxLtpDec->tcxltp_pitch_fr_post_prev, hTcxLtpDec->tcxltp_gain_post_prev,
1524 3100 : st->pit_res_max_past, NULL, 0, hTcxLtpDec->tcxltp_filt_idx_prev );
1525 :
1526 : /******** Transition part ********/
1527 :
1528 3100 : test();
1529 3100 : test();
1530 3100 : test();
1531 : // #ifdef IVAS_CODE_TCX_LTP
1532 3100 : IF( NE_16( st->element_mode, EVS_MONO ) )
1533 : {
1534 0 : test();
1535 0 : test();
1536 0 : test();
1537 0 : test();
1538 0 : test();
1539 0 : test();
1540 0 : test();
1541 0 : IF( gain == 0 && hTcxLtpDec->tcxltp_gain_post_prev == 0 )
1542 : {
1543 : /* The filtering is deactivated, just copy input to the output */
1544 0 : Copy( sig_in + delay, sig_out + delay, L_transition ); /* Qx */
1545 : }
1546 0 : ELSE IF( gain == 0 && hTcxLtpDec->tcxltp_gain_post_prev != 0 )
1547 : {
1548 : /* Filtering with the first filter unit */
1549 0 : tcx_ltp_synth_filter_10( sig_out + delay, sig_in + delay, L_transition, hTcxLtpDec->tcxltp_pitch_int_post_prev, hTcxLtpDec->tcxltp_pitch_fr_post_prev, hTcxLtpDec->tcxltp_gain_post_prev, st->pit_res_max_past, hTcxLtpDec->tcxltp_filt_idx_prev );
1550 : }
1551 0 : ELSE IF( gain != 0 && hTcxLtpDec->tcxltp_gain_post_prev == 0 )
1552 : {
1553 : /* Filtering with the second filter unit */
1554 0 : tcx_ltp_synth_filter_01( sig_out + delay, sig_in + delay, L_transition, pitch_int, pitch_fr, gain, st->pit_res_max, filtIdx );
1555 : }
1556 0 : ELSE IF( EQ_16( gain, hTcxLtpDec->tcxltp_gain_post_prev ) && EQ_16( pitch_int, hTcxLtpDec->tcxltp_pitch_int_post_prev ) && EQ_16( pitch_fr, hTcxLtpDec->tcxltp_pitch_fr_post_prev ) && EQ_16( st->pit_res_max, st->pit_res_max_past ) && EQ_16( filtIdx, hTcxLtpDec->tcxltp_filt_idx_prev ) )
1557 : {
1558 0 : tcx_ltp_synth_filter( sig_out + delay, sig_in + delay, L_transition, pitch_int, pitch_fr, gain, st->pit_res_max, NULL, 0, filtIdx );
1559 : }
1560 : ELSE
1561 : {
1562 : /* Filtering with the first filter unit, followed by the filtering with the second filter unit */
1563 0 : tcx_ltp_synth_filter_11_unequal_pitch( sig_out + delay, sig_in + delay, L_transition, pitch_int, pitch_fr, gain, st->pit_res_max, filtIdx,
1564 0 : hTcxLtpDec->tcxltp_pitch_int_post_prev, hTcxLtpDec->tcxltp_pitch_fr_post_prev, hTcxLtpDec->tcxltp_gain_post_prev, st->pit_res_max_past, hTcxLtpDec->tcxltp_filt_idx_prev );
1565 : }
1566 : }
1567 : ELSE
1568 : {
1569 3100 : test();
1570 3100 : test();
1571 3100 : test();
1572 3100 : test();
1573 3100 : IF( gain == 0 && hTcxLtpDec->tcxltp_gain_post_prev == 0 )
1574 : {
1575 2545 : Copy( sig_in + delay, sig_out + delay, L_transition ); /* Qx */
1576 : }
1577 555 : ELSE IF( hTcxLtpDec->tcxltp_gain_post_prev == 0 )
1578 : {
1579 86 : tcx_ltp_synth_filter( sig_out + delay, sig_in + delay, L_transition, pitch_int,
1580 86 : pitch_fr, gain, st->pit_res_max, NULL, 1, filtIdx );
1581 : }
1582 469 : ELSE IF( gain == 0 )
1583 : {
1584 86 : tcx_ltp_synth_filter( sig_out + delay, sig_in + delay, L_transition, hTcxLtpDec->tcxltp_pitch_int_post_prev, hTcxLtpDec->tcxltp_pitch_fr_post_prev,
1585 86 : hTcxLtpDec->tcxltp_gain_post_prev, st->pit_res_max_past, NULL, -1, hTcxLtpDec->tcxltp_filt_idx_prev );
1586 : }
1587 383 : ELSE IF( EQ_16( gain, hTcxLtpDec->tcxltp_gain_post_prev ) && EQ_16( pitch_int, hTcxLtpDec->tcxltp_pitch_int_post_prev ) && EQ_16( pitch_fr, hTcxLtpDec->tcxltp_pitch_fr_post_prev ) )
1588 : {
1589 121 : tcx_ltp_synth_filter( sig_out + delay, sig_in + delay, L_transition, pitch_int, pitch_fr, gain, st->pit_res_max, NULL, 0, filtIdx );
1590 : }
1591 : ELSE
1592 : {
1593 262 : tcx_ltp_get_lpc( sig_out + delay - output_frame, output_frame, A, lpcorder );
1594 :
1595 262 : tcx_ltp_get_zir( zir, L_transition, sig_out + delay - lpcorder, sig_in + delay - lpcorder, A, lpcorder, gain, pitch_int, pitch_fr, st->pit_res_max, filtIdx );
1596 :
1597 262 : tcx_ltp_synth_filter( sig_out + delay, sig_in + delay, L_transition, pitch_int, pitch_fr, gain, st->pit_res_max, zir, 0, filtIdx );
1598 : }
1599 : }
1600 :
1601 : /******** Current-frame part - subsequent subinterval, filtered with the third filter unit ********/
1602 :
1603 3100 : tcx_ltp_synth_filter( sig_out + ( delay + L_transition ), sig_in + ( delay + L_transition ), output_frame - ( delay + L_transition ), pitch_int, pitch_fr, gain, st->pit_res_max, NULL, 0, filtIdx );
1604 :
1605 :
1606 : /******** Output ********/
1607 :
1608 :
1609 : /* copy to output */
1610 :
1611 3100 : Copy( sig_out, sig, output_frame ); /* Qx */
1612 :
1613 : /* Update */
1614 3100 : hTcxLtpDec->tcxltp_pitch_int_post_prev = pitch_int;
1615 3100 : move16();
1616 3100 : hTcxLtpDec->tcxltp_pitch_fr_post_prev = pitch_fr;
1617 3100 : move16();
1618 3100 : hTcxLtpDec->tcxltp_gain_post_prev = gain2;
1619 3100 : move16();
1620 3100 : hTcxLtpDec->tcxltp_filt_idx_prev = filtIdx;
1621 3100 : move16();
1622 3100 : st->pit_res_max_past = st->pit_res_max;
1623 3100 : move16();
1624 3100 : Copy( sig_out, hTcxLtpDec->tcxltp_mem_out, output_frame ); /* Qx */
1625 3100 : }
1626 :
1627 :
1628 : /* IVAS 32-bit variant */
1629 1120352 : void tcx_ltp_post_fx32(
1630 : Decoder_State *st,
1631 : TCX_LTP_DEC_HANDLE hTcxLtpDec,
1632 : Word16 core, /* Q0 */
1633 : Word16 output_frame, /* Q0 */
1634 : Word16 delay, /* Q0 */
1635 : Word32 *sig, /* sig_q */
1636 : Word32 *tcx_buf, /* sig_q */
1637 : Word16 sig_q )
1638 : {
1639 : Word16 tmp, L_transition, lpcorder, filtIdx;
1640 : Word16 gain, gain2;
1641 : Word32 tmp32;
1642 : Word32 zir[L_FRAME_PLUS / 4], A[TCXLTP_LTP_ORDER + 1];
1643 : Word32 buf_in[TCXLTP_MAX_DELAY + L_FRAME48k + TCXLTP_MAX_DELAY], buf_out[2 * L_FRAME48k];
1644 : Word32 *sig_in, *sig_out;
1645 : Word16 pitch_int, pitch_fr;
1646 : Word16 tcx_buf_len, bfi, L_frame_core, SideInfoOnly;
1647 : Word32 total_brate;
1648 :
1649 1120352 : total_brate = st->total_brate;
1650 1120352 : move32();
1651 1120352 : IF( EQ_16( st->element_mode, IVAS_CPE_MDCT ) )
1652 : {
1653 694688 : total_brate = L_mult0( st->bits_frame_nominal, FRAMES_PER_SEC ); // TDO
1654 694688 : move32();
1655 : }
1656 :
1657 1120352 : filtIdx = 0; /* just to avoid comilation warnings */
1658 1120352 : move16();
1659 1120352 : tcx_buf_len = NS2SA_FX2( st->output_Fs, TCXLTP_DELAY_NS ); /* Q0 */
1660 1120352 : move16();
1661 1120352 : SideInfoOnly = 0;
1662 1120352 : move16();
1663 1120352 : if ( GE_32( total_brate, HQ_96k ) )
1664 : {
1665 400596 : SideInfoOnly = 1;
1666 400596 : move16();
1667 : }
1668 :
1669 1120352 : L_frame_core = st->L_frame; /* Q0 */
1670 1120352 : move16();
1671 :
1672 1120352 : if ( EQ_16( st->element_mode, IVAS_CPE_MDCT ) )
1673 : {
1674 694688 : L_frame_core = L_FRAME;
1675 694688 : move16();
1676 : }
1677 :
1678 1120352 : IF( EQ_16( core, ACELP_CORE ) )
1679 : {
1680 207269 : bfi = 0;
1681 207269 : pitch_int = 0;
1682 207269 : pitch_fr = 0;
1683 207269 : gain = 0;
1684 207269 : L_frame_core = st->L_frame_past; /* Q0 */
1685 207269 : move16();
1686 207269 : move16();
1687 207269 : move16();
1688 207269 : move16();
1689 : }
1690 : ELSE
1691 : {
1692 913083 : bfi = st->bfi; /* Q0 */
1693 913083 : pitch_int = hTcxLtpDec->tcxltp_pitch_int; /* Q0 */
1694 913083 : pitch_fr = hTcxLtpDec->tcxltp_pitch_fr; /* Q0 */
1695 913083 : gain = hTcxLtpDec->tcxltp_gain; /* Q15 */
1696 913083 : move16();
1697 913083 : move16();
1698 913083 : move16();
1699 913083 : move16();
1700 : }
1701 : /******** Init ********/
1702 :
1703 :
1704 : /* Parameters */
1705 1120352 : L_transition = shr( output_frame, 2 ); /* Q0 */
1706 1120352 : lpcorder = TCXLTP_LTP_ORDER;
1707 1120352 : move16();
1708 :
1709 : /* Input buffer */
1710 1120352 : sig_in = buf_in + tcx_buf_len;
1711 1120352 : Copy32( hTcxLtpDec->tcxltp_mem_in_32, buf_in, tcx_buf_len ); /* exp(exp_tcxltp_mem_in)*/
1712 1120352 : scale_sig32( buf_in, tcx_buf_len, sub( hTcxLtpDec->exp_tcxltp_mem_in, sub( 31, sig_q ) ) );
1713 1120352 : Copy32( sig, buf_in + tcx_buf_len, output_frame ); /* sig_q */
1714 1120352 : IF( core > ACELP_CORE )
1715 : {
1716 913083 : Copy32( tcx_buf, sig_in + output_frame, tcx_buf_len ); /* sig_q */
1717 : }
1718 1120352 : Copy32( sig + output_frame - tcx_buf_len, hTcxLtpDec->tcxltp_mem_in_32, tcx_buf_len ); /* sig_q */
1719 1120352 : hTcxLtpDec->exp_tcxltp_mem_in = sub( 31, sig_q );
1720 1120352 : move16();
1721 : /* Output buffer */
1722 1120352 : sig_out = buf_out + output_frame;
1723 1120352 : Copy32( hTcxLtpDec->tcxltp_mem_out_32, buf_out, output_frame ); /* exp(exp_tcxltp_mem_out) */
1724 1120352 : scale_sig32( buf_out, output_frame, sub( hTcxLtpDec->exp_tcxltp_mem_out, sub( 31, sig_q ) ) );
1725 :
1726 : /* TCX-LTP parameters: integer pitch, fractional pitch, gain */
1727 1120352 : test();
1728 1120352 : test();
1729 1120352 : IF( !( SideInfoOnly != 0 || hTcxLtpDec->tcxltp != 0 ) || EQ_16( core, ACELP_CORE ) )
1730 : {
1731 : /* No LTP */
1732 498766 : pitch_int = 0;
1733 498766 : move16();
1734 498766 : pitch_fr = 0;
1735 498766 : move16();
1736 498766 : gain = 0;
1737 498766 : move16();
1738 : }
1739 621586 : ELSE IF( bfi == 0 )
1740 : {
1741 : /* LTP and good frame */
1742 617134 : IF( NE_16( output_frame, L_frame_core ) )
1743 : {
1744 608215 : tmp = div_s( output_frame, shl( L_frame_core, 2 ) ); /* Q13 */
1745 608215 : tmp32 = L_mult0( add( imult1616( pitch_int, st->pit_res_max ), pitch_fr ), tmp ); /* Q13 */
1746 608215 : tmp = round_fx( L_shl( tmp32, 3 ) ); /* Q0 */
1747 608215 : pitch_int = idiv1616U( tmp, st->pit_res_max );
1748 608215 : pitch_fr = sub( tmp, imult1616( pitch_int, st->pit_res_max ) ); /* Q0 */
1749 : }
1750 617134 : IF( st->element_mode == EVS_MONO ) /* hard tunings for EVS_MONO, HQ_48k is TCX only */
1751 : {
1752 0 : test();
1753 0 : test();
1754 0 : IF( EQ_32( total_brate, 48000 ) && EQ_16( L_frame_core, L_FRAME16k ) )
1755 : {
1756 0 : gain = mult_r( gain, 10486 /*0.32f Q15*/ ); /* Q15 */
1757 : }
1758 0 : ELSE IF( EQ_32( total_brate, 48000 ) && EQ_16( L_frame_core, 512 ) )
1759 : {
1760 0 : gain = mult_r( gain, 13107 /*0.40f Q15*/ ); /* Q15 */
1761 : }
1762 : ELSE
1763 : {
1764 0 : gain = mult_r( gain, 20972 /*0.64f Q15*/ ); /* Q15 */
1765 : }
1766 : }
1767 617134 : ELSE IF( GT_16( st->element_mode, IVAS_SCE ) && GE_32( total_brate, IVAS_96k ) )
1768 : {
1769 382830 : gain = mult_r( gain, 13107 /*0.40f Q15*/ ); /* Q15 */
1770 : }
1771 : ELSE
1772 : {
1773 234304 : gain = mult_r( gain, 20972 /*0.64f Q15*/ ); /* Q15 */
1774 : }
1775 : }
1776 : ELSE
1777 : {
1778 : /* PLC: [TCX: Fade-out]
1779 : * PLC: LTP and bad frame (concealment) */
1780 4452 : IF( st->pit_res_max == st->pit_res_max_past ) /* ensure consistent core SR to previous frame; otherwise, set gain to 0 */
1781 : {
1782 4452 : pitch_int = hTcxLtpDec->tcxltp_pitch_int_post_prev; /* Q0 */
1783 4452 : move16();
1784 4452 : pitch_fr = hTcxLtpDec->tcxltp_pitch_fr_post_prev; /* Q0 */
1785 4452 : move16();
1786 4452 : gain = shl( mult_r( hTcxLtpDec->tcxltp_gain_post_prev, st->hTcxDec->damping ), 1 ); /* Q15 */
1787 : }
1788 : ELSE
1789 : {
1790 0 : gain = 0;
1791 0 : move16();
1792 : }
1793 : }
1794 :
1795 :
1796 1120352 : IF( SideInfoOnly != 0 )
1797 : {
1798 400596 : gain = 0;
1799 400596 : move16();
1800 400596 : if ( bfi != 0 )
1801 : {
1802 2835 : hTcxLtpDec->tcxltp_gain_post_prev = 0;
1803 2835 : move16();
1804 : }
1805 : }
1806 1120352 : gain2 = gain;
1807 1120352 : move16();
1808 :
1809 1120352 : IF( EQ_16( L_frame_core, L_FRAME ) )
1810 : {
1811 803937 : SWITCH( output_frame )
1812 : {
1813 0 : case L_FRAME8k:
1814 0 : filtIdx = 0;
1815 0 : move16();
1816 0 : BREAK;
1817 78783 : case L_FRAME16k:
1818 78783 : filtIdx = 1;
1819 78783 : move16();
1820 78783 : BREAK;
1821 184352 : case L_FRAME32k:
1822 184352 : filtIdx = 2;
1823 184352 : move16();
1824 184352 : BREAK;
1825 540802 : case L_FRAME48k:
1826 540802 : filtIdx = 3;
1827 540802 : move16();
1828 540802 : BREAK;
1829 0 : default:
1830 0 : assert( 0 );
1831 : }
1832 : }
1833 316415 : ELSE IF( EQ_16( L_frame_core, L_FRAME16k ) )
1834 : {
1835 182533 : SWITCH( output_frame )
1836 : {
1837 0 : case L_FRAME8k:
1838 0 : filtIdx = 4;
1839 0 : move16();
1840 0 : BREAK;
1841 20336 : case L_FRAME16k:
1842 20336 : filtIdx = 5;
1843 20336 : move16();
1844 20336 : BREAK;
1845 47045 : case L_FRAME32k:
1846 47045 : filtIdx = 6;
1847 47045 : move16();
1848 47045 : BREAK;
1849 115152 : case L_FRAME48k:
1850 115152 : filtIdx = 7;
1851 115152 : move16();
1852 115152 : BREAK;
1853 0 : default:
1854 0 : assert( 0 );
1855 : }
1856 : }
1857 133882 : ELSE IF( EQ_16( L_frame_core, 512 ) )
1858 : {
1859 15257 : SWITCH( output_frame )
1860 : {
1861 0 : case L_FRAME8k:
1862 0 : filtIdx = 8;
1863 0 : move16();
1864 0 : BREAK;
1865 139 : case L_FRAME16k:
1866 139 : filtIdx = 9;
1867 139 : move16();
1868 139 : BREAK;
1869 3396 : case L_FRAME32k:
1870 3396 : filtIdx = 10;
1871 3396 : move16();
1872 3396 : BREAK;
1873 11722 : case L_FRAME48k:
1874 11722 : filtIdx = 11;
1875 11722 : move16();
1876 11722 : BREAK;
1877 0 : default:
1878 0 : assert( 0 );
1879 : }
1880 : }
1881 : ELSE
1882 : {
1883 118625 : filtIdx = -1;
1884 118625 : move16();
1885 : }
1886 :
1887 :
1888 : /******** Previous-frame part ********/
1889 :
1890 1120352 : tcx_ltp_synth_filter32( sig_out, sig_in, delay, hTcxLtpDec->tcxltp_pitch_int_post_prev, hTcxLtpDec->tcxltp_pitch_fr_post_prev, hTcxLtpDec->tcxltp_gain_post_prev,
1891 1120352 : st->pit_res_max_past, NULL, 0, hTcxLtpDec->tcxltp_filt_idx_prev );
1892 :
1893 : /******** Transition part ********/
1894 1120352 : IF( NE_16( st->element_mode, EVS_MONO ) )
1895 : {
1896 1120352 : test();
1897 1120352 : test();
1898 1120352 : test();
1899 1120352 : test();
1900 1120352 : test();
1901 1120352 : test();
1902 1120352 : test();
1903 1120352 : test();
1904 1120352 : IF( gain == 0 && hTcxLtpDec->tcxltp_gain_post_prev == 0 )
1905 : {
1906 : /* The filtering is deactivated, just copy input to the output */
1907 922018 : Copy32( sig_in + delay, sig_out + delay, L_transition ); /* sig_q */
1908 : }
1909 198334 : ELSE IF( gain == 0 && hTcxLtpDec->tcxltp_gain_post_prev != 0 )
1910 : {
1911 : /* Filtering with the first filter unit */
1912 27598 : tcx_ltp_synth_filter_10_fx( sig_out + delay, sig_in + delay, L_transition, hTcxLtpDec->tcxltp_pitch_int_post_prev, hTcxLtpDec->tcxltp_pitch_fr_post_prev, hTcxLtpDec->tcxltp_gain_post_prev, st->pit_res_max_past, hTcxLtpDec->tcxltp_filt_idx_prev );
1913 : }
1914 170736 : ELSE IF( gain != 0 && hTcxLtpDec->tcxltp_gain_post_prev == 0 )
1915 : {
1916 : /* Filtering with the second filter unit */
1917 28759 : tcx_ltp_synth_filter_01_fx( sig_out + delay, sig_in + delay, L_transition, pitch_int, pitch_fr, gain, st->pit_res_max, filtIdx );
1918 : }
1919 141977 : ELSE IF( EQ_16( gain, hTcxLtpDec->tcxltp_gain_post_prev ) && EQ_16( pitch_int, hTcxLtpDec->tcxltp_pitch_int_post_prev ) && EQ_16( pitch_fr, hTcxLtpDec->tcxltp_pitch_fr_post_prev ) && EQ_16( st->pit_res_max, st->pit_res_max_past ) && EQ_16( filtIdx, hTcxLtpDec->tcxltp_filt_idx_prev ) )
1920 : {
1921 23185 : tcx_ltp_synth_filter32( sig_out + delay, sig_in + delay, L_transition, pitch_int, pitch_fr, gain, st->pit_res_max, NULL, 0, filtIdx );
1922 : }
1923 : ELSE
1924 : {
1925 : /* Filtering with the first filter unit, followed by the filtering with the second filter unit */
1926 118792 : tcx_ltp_synth_filter_11_unequal_pitch_fx( sig_out + delay, sig_in + delay, L_transition, pitch_int, pitch_fr, gain, st->pit_res_max, filtIdx,
1927 118792 : hTcxLtpDec->tcxltp_pitch_int_post_prev, hTcxLtpDec->tcxltp_pitch_fr_post_prev, hTcxLtpDec->tcxltp_gain_post_prev, st->pit_res_max_past, hTcxLtpDec->tcxltp_filt_idx_prev );
1928 : }
1929 : }
1930 : ELSE
1931 : {
1932 0 : test();
1933 0 : test();
1934 0 : test();
1935 0 : IF( gain == 0 && hTcxLtpDec->tcxltp_gain_post_prev == 0 )
1936 : {
1937 0 : Copy32( sig_in + delay, sig_out + delay, L_transition ); /* sig_q */
1938 : }
1939 0 : ELSE IF( hTcxLtpDec->tcxltp_gain_post_prev == 0 )
1940 : {
1941 0 : tcx_ltp_synth_filter32( sig_out + delay, sig_in + delay, L_transition, pitch_int,
1942 0 : pitch_fr, gain, st->pit_res_max, NULL, 1, filtIdx );
1943 : }
1944 0 : ELSE IF( gain == 0 )
1945 : {
1946 0 : tcx_ltp_synth_filter32( sig_out + delay, sig_in + delay, L_transition, hTcxLtpDec->tcxltp_pitch_int_post_prev, hTcxLtpDec->tcxltp_pitch_fr_post_prev,
1947 0 : hTcxLtpDec->tcxltp_gain_post_prev, st->pit_res_max_past, NULL, -1, hTcxLtpDec->tcxltp_filt_idx_prev );
1948 : }
1949 0 : ELSE IF( EQ_16( gain, hTcxLtpDec->tcxltp_gain_post_prev ) && EQ_16( pitch_int, hTcxLtpDec->tcxltp_pitch_int_post_prev ) && EQ_16( pitch_fr, hTcxLtpDec->tcxltp_pitch_fr_post_prev ) )
1950 : {
1951 0 : tcx_ltp_synth_filter32( sig_out + delay, sig_in + delay, L_transition, pitch_int, pitch_fr, gain, st->pit_res_max, NULL, 0, filtIdx );
1952 : }
1953 : ELSE
1954 : {
1955 0 : tcx_ltp_get_lpc_fx( sig_out + delay - output_frame, output_frame, A, lpcorder );
1956 :
1957 0 : tcx_ltp_get_zir_fx( zir, L_transition, sig_out + delay - lpcorder, sig_in + delay - lpcorder, A, lpcorder, gain, pitch_int, pitch_fr, st->pit_res_max, filtIdx );
1958 :
1959 0 : tcx_ltp_synth_filter32( sig_out + delay, sig_in + delay, L_transition, pitch_int, pitch_fr, gain, st->pit_res_max, zir, 0, filtIdx );
1960 : }
1961 : }
1962 :
1963 : /******** Current-frame part - subsequent subinterval, filtered with the third filter unit ********/
1964 :
1965 1120352 : tcx_ltp_synth_filter32( sig_out + ( delay + L_transition ), sig_in + ( delay + L_transition ), output_frame - ( delay + L_transition ), pitch_int, pitch_fr, gain, st->pit_res_max, NULL, 0, filtIdx );
1966 :
1967 :
1968 : /******** Output ********/
1969 :
1970 :
1971 : /* copy to output */
1972 :
1973 1120352 : Copy32( sig_out, sig, output_frame ); /* sig_q */
1974 :
1975 : /* Update */
1976 1120352 : hTcxLtpDec->tcxltp_pitch_int_post_prev = pitch_int;
1977 1120352 : move16();
1978 1120352 : hTcxLtpDec->tcxltp_pitch_fr_post_prev = pitch_fr;
1979 1120352 : move16();
1980 1120352 : hTcxLtpDec->tcxltp_gain_post_prev = gain2;
1981 1120352 : move16();
1982 1120352 : hTcxLtpDec->tcxltp_filt_idx_prev = filtIdx;
1983 1120352 : move16();
1984 1120352 : st->pit_res_max_past = st->pit_res_max;
1985 1120352 : Copy32( sig_out, hTcxLtpDec->tcxltp_mem_out_32, output_frame ); /* sig_q */
1986 1120352 : hTcxLtpDec->exp_tcxltp_mem_out = sub( 31, sig_q );
1987 1120352 : move16();
1988 1120352 : }
|