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