Line data Source code
1 : /******************************************************************************************************
2 :
3 : (C) 2022-2025 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB,
4 : Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD.,
5 : Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange,
6 : Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other
7 : contributors to this repository. All Rights Reserved.
8 :
9 : This software is protected by copyright law and by international treaties.
10 : The IVAS codec Public Collaboration consisting of Dolby International AB, Ericsson AB,
11 : Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD.,
12 : Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange,
13 : Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other
14 : contributors to this repository retain full ownership rights in their respective contributions in
15 : the software. This notice grants no license of any kind, including but not limited to patent
16 : license, nor is any license granted by implication, estoppel or otherwise.
17 :
18 : Contributors are required to enter into the IVAS codec Public Collaboration agreement before making
19 : contributions.
20 :
21 : This software is provided "AS IS", without any express or implied warranties. The software is in the
22 : development stage. It is intended exclusively for experts who have experience with such software and
23 : solely for the purpose of inspection. All implied warranties of non-infringement, merchantability
24 : and fitness for a particular purpose are hereby disclaimed and excluded.
25 :
26 : Any dispute, controversy or claim arising under or in relation to providing this software shall be
27 : submitted to and settled by the final, binding jurisdiction of the courts of Munich, Germany in
28 : accordance with the laws of the Federal Republic of Germany excluding its conflict of law rules and
29 : the United Nations Convention on Contracts on the International Sales of Goods.
30 :
31 : *******************************************************************************************************/
32 :
33 : /*====================================================================================
34 : EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0
35 : ====================================================================================*/
36 :
37 : #include <assert.h>
38 : #include <stdint.h>
39 : #include "options.h"
40 : #ifdef DEBUGGING
41 : #include "debug.h"
42 : #endif
43 : #include "prot.h"
44 : #include "rom_com.h"
45 : #include "wmc_auto.h"
46 :
47 : /*-------------------------------------------------------------------
48 : * Local constants
49 : *-------------------------------------------------------------------*/
50 :
51 : #define ALPHA 0.85f
52 :
53 : /*-------------------------------------------------------------------
54 : * tcx_ltp_get_lpc()
55 : *
56 : *
57 : *-------------------------------------------------------------------*/
58 :
59 538 : static void tcx_ltp_get_lpc(
60 : float *input,
61 : const int16_t length,
62 : float *A,
63 : const int16_t lpcorder )
64 : {
65 : int16_t i, j;
66 : float s, r[TCXLTP_LTP_ORDER + 1];
67 :
68 13988 : for ( i = 0; i <= lpcorder; i++ )
69 : {
70 13450 : s = 0.0;
71 :
72 11940050 : for ( j = 0; j < length - i; j++ )
73 : {
74 11926600 : s += input[j] * input[j + i];
75 : }
76 13450 : r[i] = s;
77 : }
78 :
79 538 : if ( r[0] < 100.0f )
80 : {
81 0 : r[0] = 100.0f;
82 : }
83 538 : r[0] *= 1.0001f;
84 :
85 538 : lev_dur( A, r, lpcorder, NULL );
86 :
87 538 : return;
88 : }
89 :
90 :
91 : /*-------------------------------------------------------------------
92 : * tcx_ltp_get_zir()
93 : *
94 : *
95 : *-------------------------------------------------------------------*/
96 :
97 538 : static void tcx_ltp_get_zir(
98 : float *zir,
99 : const int16_t length,
100 : float *synth_ltp,
101 : float *synth,
102 : float *A,
103 : const int16_t lpcorder,
104 : const float gain,
105 : const int16_t pitch_int,
106 : const int16_t pitch_fr,
107 : const int16_t pitres,
108 : const int16_t filtIdx )
109 : {
110 : float buf[TCXLTP_LTP_ORDER], alpha, step;
111 : float *x0, *x1, s;
112 : float *y0, *y1, s2;
113 : const float *w0, *w1, *v0, *v1;
114 : int16_t i, j, k, L;
115 :
116 538 : x0 = &synth_ltp[-pitch_int];
117 538 : x1 = x0 - 1;
118 538 : y0 = synth;
119 538 : y1 = y0 - 1;
120 :
121 538 : assert( filtIdx >= 0 );
122 :
123 538 : w0 = &tcxLtpFilters[filtIdx].filt[pitch_fr];
124 538 : w1 = &tcxLtpFilters[filtIdx].filt[pitres - pitch_fr];
125 538 : v0 = &tcxLtpFilters[filtIdx].filt[0];
126 538 : v1 = &tcxLtpFilters[filtIdx].filt[pitres];
127 538 : L = tcxLtpFilters[filtIdx].length;
128 :
129 13450 : for ( j = 0; j < lpcorder; j++ )
130 : {
131 12912 : s = 0;
132 12912 : s2 = 0;
133 93528 : for ( i = 0, k = 0; i < L; i++, k += pitres )
134 : {
135 80616 : s += w0[k] * x0[i] + w1[k] * x1[-i];
136 80616 : s2 += v0[k] * y0[i] + v1[k] * y1[-i];
137 : }
138 12912 : s2 *= ALPHA;
139 :
140 12912 : buf[j] = ( synth[j] - gain * s2 ) - ( synth_ltp[j] - gain * s );
141 :
142 :
143 12912 : x0++;
144 12912 : x1++;
145 12912 : y0++;
146 12912 : y1++;
147 : }
148 :
149 538 : set_f( zir, 0.0f, length );
150 :
151 538 : syn_filt( A, lpcorder, zir, zir, length, buf, 0 );
152 :
153 538 : alpha = 1.f;
154 538 : step = 1.f / (float) ( length / 2 );
155 :
156 60978 : for ( j = length / 2; j < length; j++ )
157 : {
158 60440 : zir[j] *= alpha;
159 60440 : alpha -= step;
160 : }
161 :
162 538 : return;
163 : }
164 :
165 :
166 : /*-------------------------------------------------------------------
167 : * predict_signal()
168 : *
169 : *
170 : *-------------------------------------------------------------------*/
171 :
172 597581 : void predict_signal(
173 : const float excI[], /* i : input excitation buffer */
174 : float excO[], /* o : output excitation buffer */
175 : const int16_t T0, /* i : integer pitch lag */
176 : int16_t frac, /* i : fraction of lag */
177 : const int16_t frac_max, /* i : max fraction */
178 : const int16_t L_subfr /* i : subframe size */
179 : )
180 : {
181 : int16_t j;
182 : float s;
183 : const float *x0, *win;
184 :
185 597581 : x0 = &excI[-T0 - 1];
186 597581 : frac = -frac;
187 :
188 597581 : if ( frac < 0 )
189 : {
190 303618 : frac += frac_max;
191 303618 : x0--;
192 : }
193 :
194 597581 : if ( frac_max == 6 )
195 : {
196 119640 : win = &inter6_2tcx2[frac][0];
197 : }
198 : else
199 : {
200 477941 : win = &inter4_2tcx2[frac][0];
201 : }
202 :
203 168985837 : for ( j = 0; j < L_subfr; j++ )
204 : {
205 168388256 : s = win[1] * x0[1] + win[2] * x0[2];
206 168388256 : excO[j] = s + win[0] * x0[0] + win[3] * x0[3];
207 168388256 : x0++;
208 : }
209 :
210 597581 : return;
211 : }
212 :
213 :
214 : /*-------------------------------------------------------------------
215 : * tcx_ltp_synth_filter()
216 : *
217 : *
218 : *-------------------------------------------------------------------*/
219 :
220 4291998 : static void tcx_ltp_synth_filter(
221 : float *synth_ltp,
222 : float *synth,
223 : const int16_t length,
224 : const int16_t pitch_int,
225 : const int16_t pitch_fr,
226 : const float gain,
227 : const int16_t pitch_res,
228 : const int16_t filtIdx )
229 : {
230 : float *x0, *x1, s;
231 : float *y0, *y1, s2;
232 : const float *v0, *v1;
233 : const float *w0, *w1;
234 : int16_t i, j, k, L;
235 :
236 4291998 : if ( gain > 0.f )
237 : {
238 726552 : x0 = &synth_ltp[-pitch_int];
239 726552 : x1 = x0 - 1;
240 726552 : y0 = synth;
241 726552 : y1 = y0 - 1;
242 :
243 726552 : assert( filtIdx >= 0 );
244 :
245 726552 : w0 = &tcxLtpFilters[filtIdx].filt[pitch_fr];
246 726552 : w1 = &tcxLtpFilters[filtIdx].filt[pitch_res - pitch_fr];
247 726552 : v0 = &tcxLtpFilters[filtIdx].filt[0];
248 726552 : v1 = &tcxLtpFilters[filtIdx].filt[pitch_res];
249 :
250 726552 : L = tcxLtpFilters[filtIdx].length;
251 :
252 :
253 233918181 : for ( j = 0; j < length; j++ )
254 : {
255 233191629 : s = 0;
256 233191629 : s2 = 0;
257 1921566595 : for ( i = 0, k = 0; i < L; i++, k += pitch_res )
258 : {
259 1688374966 : s += w0[k] * x0[i] + w1[k] * x1[-i];
260 1688374966 : s2 += v0[k] * y0[i] + v1[k] * y1[-i];
261 : }
262 :
263 233191629 : s2 *= ALPHA;
264 233191629 : synth_ltp[j] = synth[j] - gain * s2 + gain * s;
265 :
266 233191629 : x0++;
267 233191629 : x1++;
268 233191629 : y0++;
269 233191629 : y1++;
270 : }
271 : }
272 : else
273 : {
274 3565446 : mvr2r( synth, synth_ltp, length );
275 : }
276 :
277 4291998 : return;
278 : }
279 :
280 :
281 : /*-------------------------------------------------------------------
282 : * tcx_ltp_synth_filter_zir()
283 : *
284 : *
285 : *-------------------------------------------------------------------*/
286 :
287 538 : static void tcx_ltp_synth_filter_zir(
288 : float *synth_ltp,
289 : float *synth,
290 : const int16_t length,
291 : const int16_t pitch_int,
292 : const int16_t pitch_fr,
293 : const float gain,
294 : const int16_t pitch_res,
295 : float *zir,
296 : const int16_t filtIdx )
297 : {
298 : float *x0, *x1, s;
299 : float *y0, *y1, s2;
300 : const float *v0, *v1;
301 : const float *w0, *w1;
302 : int16_t i, j, k, L;
303 :
304 538 : x0 = &synth_ltp[-pitch_int];
305 538 : x1 = x0 - 1;
306 538 : y0 = synth;
307 538 : y1 = y0 - 1;
308 :
309 538 : assert( filtIdx >= 0 );
310 :
311 538 : w0 = &tcxLtpFilters[filtIdx].filt[pitch_fr];
312 538 : w1 = &tcxLtpFilters[filtIdx].filt[pitch_res - pitch_fr];
313 538 : v0 = &tcxLtpFilters[filtIdx].filt[0];
314 538 : v1 = &tcxLtpFilters[filtIdx].filt[pitch_res];
315 538 : L = tcxLtpFilters[filtIdx].length;
316 :
317 121418 : for ( j = 0; j < length; j++ )
318 : {
319 120880 : s = 0;
320 120880 : s2 = 0;
321 :
322 885840 : for ( i = 0, k = 0; i < L; i++, k += pitch_res )
323 : {
324 764960 : s += w0[k] * x0[i] + w1[k] * x1[-i];
325 764960 : s2 += v0[k] * y0[i] + v1[k] * y1[-i];
326 : }
327 :
328 120880 : s2 *= ALPHA;
329 :
330 120880 : synth_ltp[j] = ( synth[j] - gain * s2 + gain * s ) - zir[j];
331 :
332 120880 : x0++;
333 120880 : x1++;
334 120880 : y0++;
335 120880 : y1++;
336 : }
337 :
338 538 : return;
339 : }
340 :
341 :
342 : /*-------------------------------------------------------------------
343 : * tcx_ltp_synth_filter_fadein()
344 : *
345 : *
346 : *-------------------------------------------------------------------*/
347 :
348 164 : static void tcx_ltp_synth_filter_fadein(
349 : float *synth_ltp,
350 : float *synth,
351 : const int16_t length,
352 : const int16_t pitch_int,
353 : const int16_t pitch_fr,
354 : const float gain,
355 : const int16_t pitch_res,
356 : const int16_t filtIdx )
357 : {
358 : float *x0, *x1, s;
359 : float *y0, *y1, s2;
360 : const float *v0, *v1;
361 : const float *w0, *w1;
362 : int16_t i, j, k, L;
363 : float alpha, step;
364 :
365 164 : if ( gain > 0.f )
366 : {
367 164 : x0 = &synth_ltp[-pitch_int];
368 164 : x1 = x0 - 1;
369 164 : y0 = synth;
370 164 : y1 = y0 - 1;
371 :
372 164 : assert( filtIdx >= 0 );
373 :
374 164 : w0 = &tcxLtpFilters[filtIdx].filt[pitch_fr];
375 164 : w1 = &tcxLtpFilters[filtIdx].filt[pitch_res - pitch_fr];
376 164 : v0 = &tcxLtpFilters[filtIdx].filt[0];
377 164 : v1 = &tcxLtpFilters[filtIdx].filt[pitch_res];
378 164 : L = tcxLtpFilters[filtIdx].length;
379 :
380 164 : alpha = 0.f;
381 164 : step = 1.f / (float) ( length );
382 :
383 :
384 36404 : for ( j = 0; j < length; j++ )
385 : {
386 36240 : s = 0;
387 36240 : s2 = 0;
388 :
389 262320 : for ( i = 0, k = 0; i < L; i++, k += pitch_res )
390 : {
391 226080 : s += w0[k] * x0[i] + w1[k] * x1[-i];
392 226080 : s2 += v0[k] * y0[i] + v1[k] * y1[-i];
393 : }
394 :
395 36240 : s2 *= ALPHA;
396 :
397 36240 : synth_ltp[j] = synth[j] - alpha * gain * s2 + alpha * gain * s;
398 :
399 36240 : alpha += step;
400 :
401 36240 : x0++;
402 36240 : x1++;
403 36240 : y0++;
404 36240 : y1++;
405 : }
406 : }
407 : else
408 : {
409 0 : mvr2r( synth, synth_ltp, length );
410 : }
411 :
412 164 : return;
413 : }
414 :
415 :
416 : /*-------------------------------------------------------------------
417 : * tcx_ltp_synth_filter_fadeout()
418 : *
419 : *
420 : *-------------------------------------------------------------------*/
421 :
422 163 : static void tcx_ltp_synth_filter_fadeout(
423 : float *synth_ltp,
424 : float *synth,
425 : const int16_t length,
426 : const int16_t pitch_int,
427 : const int16_t pitch_fr,
428 : const float gain,
429 : const int16_t pitch_res,
430 : const int16_t filtIdx )
431 : {
432 : float *x0, *x1, s;
433 : float *y0, *y1, s2;
434 : const float *v0, *v1;
435 : const float *w0, *w1;
436 : int16_t i, j, k, L;
437 : float alpha, step;
438 :
439 163 : if ( gain > 0.f )
440 : {
441 163 : x0 = &synth_ltp[-pitch_int];
442 163 : x1 = x0 - 1;
443 163 : y0 = synth;
444 163 : y1 = y0 - 1;
445 :
446 163 : assert( filtIdx >= 0 );
447 :
448 163 : w0 = &tcxLtpFilters[filtIdx].filt[pitch_fr];
449 163 : w1 = &tcxLtpFilters[filtIdx].filt[pitch_res - pitch_fr];
450 163 : v0 = &tcxLtpFilters[filtIdx].filt[0];
451 163 : v1 = &tcxLtpFilters[filtIdx].filt[pitch_res];
452 163 : L = tcxLtpFilters[filtIdx].length;
453 :
454 163 : alpha = 1.f;
455 163 : step = 1.f / (float) ( length );
456 :
457 36163 : for ( j = 0; j < length; j++ )
458 : {
459 36000 : s = 0;
460 36000 : s2 = 0;
461 :
462 260160 : for ( i = 0, k = 0; i < L; i++, k += pitch_res )
463 : {
464 224160 : s += w0[k] * x0[i] + w1[k] * x1[-i];
465 224160 : s2 += v0[k] * y0[i] + v1[k] * y1[-i];
466 : }
467 :
468 36000 : s2 *= ALPHA;
469 36000 : synth_ltp[j] = synth[j] - alpha * gain * s2 + alpha * gain * s;
470 36000 : alpha -= step;
471 :
472 36000 : x0++;
473 36000 : x1++;
474 36000 : y0++;
475 36000 : y1++;
476 : }
477 : }
478 : else
479 : {
480 0 : mvr2r( synth, synth_ltp, length );
481 : }
482 :
483 163 : return;
484 : }
485 :
486 :
487 : /*-------------------------------------------------------------------
488 : * tcx_ltp_decode_params()
489 : *
490 : *
491 : *-------------------------------------------------------------------*/
492 :
493 1643234 : int16_t tcx_ltp_decode_params(
494 : int16_t *ltp_param,
495 : int16_t *pitch_int,
496 : int16_t *pitch_fr,
497 : float *gain,
498 : const int16_t pitmin,
499 : const int16_t pitfr1,
500 : const int16_t pitfr2,
501 : const int16_t pitmax,
502 : const int16_t pitres )
503 : {
504 1643234 : int16_t gainbits = 2;
505 :
506 : /* Decode Pitch and Gain */
507 1643234 : if ( ( ltp_param ) && ( ltp_param[0] ) )
508 : {
509 1181971 : if ( ltp_param[1] < ( ( pitfr2 - pitmin ) * pitres ) )
510 : {
511 855091 : *pitch_int = pitmin + ( ltp_param[1] / pitres );
512 855091 : *pitch_fr = ltp_param[1] - ( *pitch_int - pitmin ) * pitres;
513 : }
514 326880 : else if ( ltp_param[1] < ( ( pitfr2 - pitmin ) * pitres + ( pitfr1 - pitfr2 ) * ( pitres >> 1 ) ) )
515 : {
516 94596 : *pitch_int = pitfr2 + ( ( ltp_param[1] - ( pitfr2 - pitmin ) * pitres ) / ( pitres >> 1 ) );
517 94596 : *pitch_fr = ( ltp_param[1] - ( pitfr2 - pitmin ) * pitres ) - ( *pitch_int - pitfr2 ) * ( pitres >> 1 );
518 94596 : *pitch_fr = *pitch_fr << 1; /* was *= (pitres>>1); */
519 : }
520 : else
521 : {
522 232284 : *pitch_int = ltp_param[1] + pitfr1 - ( ( pitfr2 - pitmin ) * pitres ) - ( ( pitfr1 - pitfr2 ) * ( pitres >> 1 ) );
523 232284 : *pitch_fr = 0;
524 : }
525 1181971 : *gain = (float) ( ltp_param[2] + 1 ) * 0.625f / (float) ( 1 << gainbits );
526 1181971 : if ( *pitch_int < PIT_MIN_SHORTER )
527 : {
528 : /*pitch out of range due to bit error */
529 0 : *pitch_int = PIT_MIN_SHORTER;
530 0 : return 1;
531 : }
532 1181971 : if ( *pitch_int > PIT_MAX_MAX )
533 : {
534 : /*pitch out of range due to bit error */
535 0 : *pitch_int = PIT_MAX_MAX;
536 0 : return 1;
537 : }
538 : }
539 : else
540 : {
541 461263 : *pitch_int = pitmax;
542 461263 : *pitch_fr = 0;
543 461263 : *gain = 0.0f;
544 : }
545 :
546 1643234 : return 0;
547 : }
548 :
549 : /*-------------------------------------------------------------------
550 : *tcx_ltp_synth_filter_10()
551 : *
552 : *
553 : ---------------------------------------------------------------------*/
554 55619 : static void tcx_ltp_synth_filter_10(
555 : float *out,
556 : float *in,
557 : const int16_t length,
558 : const int16_t pitch_int,
559 : const int16_t pitch_fr,
560 : const float gain,
561 : const int16_t pitch_res,
562 : const int16_t filtIdx )
563 : {
564 : float *x0, *x1, s;
565 : float *y0, *y1, s2;
566 : const float *v0, *v1;
567 : const float *w0, *w1;
568 : int16_t i, j, k, L;
569 : float curr_gain, gain_step;
570 :
571 55619 : x0 = &out[-pitch_int];
572 55619 : x1 = x0 - 1;
573 55619 : y0 = in;
574 55619 : y1 = y0 - 1;
575 :
576 55619 : assert( filtIdx >= 0 );
577 :
578 55619 : w0 = &tcxLtpFilters[filtIdx].filt[pitch_fr];
579 55619 : w1 = &tcxLtpFilters[filtIdx].filt[pitch_res - pitch_fr];
580 55619 : v0 = &tcxLtpFilters[filtIdx].filt[0];
581 55619 : v1 = &tcxLtpFilters[filtIdx].filt[pitch_res];
582 55619 : L = tcxLtpFilters[filtIdx].length;
583 :
584 55619 : curr_gain = gain;
585 55619 : gain_step = -gain / length;
586 :
587 12368659 : for ( j = 0; j < length; j++ )
588 : {
589 12313040 : s = 0;
590 12313040 : s2 = 0;
591 :
592 100946800 : for ( i = 0, k = 0; i < L; i++, k += pitch_res )
593 : {
594 88633760 : s += w0[k] * x0[i] + w1[k] * x1[-i];
595 88633760 : s2 += v0[k] * y0[i] + v1[k] * y1[-i];
596 : }
597 :
598 12313040 : out[j] = in[j] - curr_gain * s2 * ALPHA + curr_gain * s;
599 :
600 12313040 : x0++;
601 12313040 : x1++;
602 12313040 : y0++;
603 12313040 : y1++;
604 :
605 12313040 : curr_gain += gain_step;
606 : }
607 :
608 55619 : return;
609 : }
610 :
611 :
612 : /*-------------------------------------------------------------------
613 : *tcx_ltp_synth_filter_01()
614 : *
615 : *
616 : ---------------------------------------------------------------------*/
617 :
618 57246 : static void tcx_ltp_synth_filter_01(
619 : float *out,
620 : float *in,
621 : const int16_t length,
622 : const int16_t pitch_int,
623 : const int16_t pitch_fr,
624 : const float gain,
625 : const int16_t pitch_res,
626 : const int16_t filtIdx )
627 : {
628 : float *x0, *x1, s;
629 : float *y0, *y1, s2;
630 : const float *v0, *v1;
631 : const float *w0, *w1;
632 : int16_t i, j, k, L;
633 : float curr_gain, gain_step;
634 :
635 57246 : x0 = &out[-pitch_int];
636 57246 : x1 = x0 - 1;
637 57246 : y0 = in;
638 57246 : y1 = y0 - 1;
639 :
640 57246 : assert( filtIdx >= 0 );
641 :
642 57246 : w0 = &tcxLtpFilters[filtIdx].filt[pitch_fr];
643 57246 : w1 = &tcxLtpFilters[filtIdx].filt[pitch_res - pitch_fr];
644 57246 : v0 = &tcxLtpFilters[filtIdx].filt[0];
645 57246 : v1 = &tcxLtpFilters[filtIdx].filt[pitch_res];
646 57246 : L = tcxLtpFilters[filtIdx].length;
647 :
648 57246 : curr_gain = 0.0f;
649 57246 : gain_step = gain / length;
650 :
651 12730526 : for ( j = 0; j < length; j++ )
652 : {
653 12673280 : s = 0;
654 12673280 : s2 = 0;
655 :
656 103852720 : for ( i = 0, k = 0; i < L; i++, k += pitch_res )
657 : {
658 91179440 : s += w0[k] * x0[i] + w1[k] * x1[-i];
659 91179440 : s2 += v0[k] * y0[i] + v1[k] * y1[-i];
660 : }
661 :
662 12673280 : out[j] = in[j] - curr_gain * s2 * ALPHA + curr_gain * s;
663 :
664 12673280 : x0++;
665 12673280 : x1++;
666 12673280 : y0++;
667 12673280 : y1++;
668 :
669 12673280 : curr_gain += gain_step;
670 : }
671 :
672 57246 : return;
673 : }
674 :
675 : #define MAX_TCX_LTP_FILTER_LEN 8
676 : #define MAX_TRANSITION_LEN 240 /* L_FRAME_48K / 4 */
677 :
678 : /*-------------------------------------------------------------------
679 : *tcx_ltp_synth_filter_11_unequal_pitch()
680 : *
681 : * blend between two filters by means of OAO
682 : * filter the input signal at the initial subinterval with
683 : * the first filter unit according to parameters associated to
684 : * the preceding update interval with scaling from non-zero gain towards 0
685 : * followed by the second filter unit according to parameters associated to
686 : * the current update interval with scaling from 0 towards non-zero gain
687 : ---------------------------------------------------------------------*/
688 :
689 243946 : static void tcx_ltp_synth_filter_11_unequal_pitch(
690 : float *out,
691 : float *in,
692 : const int16_t length,
693 : const int16_t cur_pitch_int,
694 : const int16_t cur_pitch_fr,
695 : const float cur_gain,
696 : const int16_t pitch_res,
697 : const int16_t filtIdx,
698 : const int16_t prev_pitch_int,
699 : const int16_t prev_pitch_fr,
700 : const float prev_gain,
701 : const int16_t prev_pitch_res,
702 : const int16_t prev_filtIdx )
703 : {
704 : float *x0, *x1, s;
705 : float *y0, *y1, s2;
706 : float *l0, *l1, s3;
707 : float *m0, *m1, s4;
708 : const float *v0, *v1;
709 : const float *w0, *w1;
710 : const float *p0, *p1;
711 : const float *q0, *q1;
712 : int16_t i, j, k, L;
713 : int16_t prev_L;
714 : float temp_buf[MAX_TRANSITION_LEN + 2 * MAX_TCX_LTP_FILTER_LEN];
715 : float *temp_ptr;
716 : float gain, gain_step;
717 :
718 243946 : x0 = &out[-prev_pitch_int];
719 243946 : x1 = x0 - 1;
720 243946 : y0 = in;
721 243946 : y1 = y0 - 1;
722 :
723 243946 : assert( filtIdx >= 0 && prev_filtIdx >= 0 );
724 :
725 243946 : w0 = &tcxLtpFilters[prev_filtIdx].filt[prev_pitch_fr];
726 243946 : w1 = &tcxLtpFilters[prev_filtIdx].filt[prev_pitch_res - prev_pitch_fr];
727 243946 : v0 = &tcxLtpFilters[prev_filtIdx].filt[0];
728 243946 : v1 = &tcxLtpFilters[prev_filtIdx].filt[prev_pitch_res];
729 :
730 243946 : prev_L = tcxLtpFilters[prev_filtIdx].length;
731 :
732 243946 : p0 = &tcxLtpFilters[filtIdx].filt[cur_pitch_fr];
733 243946 : p1 = &tcxLtpFilters[filtIdx].filt[pitch_res - cur_pitch_fr];
734 243946 : q0 = &tcxLtpFilters[filtIdx].filt[0];
735 243946 : q1 = &tcxLtpFilters[filtIdx].filt[pitch_res];
736 :
737 243946 : L = tcxLtpFilters[filtIdx].length;
738 :
739 : /* 1. decreasing gain filter. The first filter unit with the parameters associated to the previous interval and scaling towards 0 */
740 243946 : gain = prev_gain;
741 243946 : gain_step = -prev_gain / length;
742 :
743 54438746 : for ( j = 0; j < length; j++ )
744 : {
745 54194800 : s = 0;
746 54194800 : s2 = 0;
747 :
748 448483680 : for ( i = 0, k = 0; i < prev_L; i++, k += prev_pitch_res )
749 : {
750 394288880 : s += w0[k] * x0[i] + w1[k] * x1[-i];
751 394288880 : s2 += v0[k] * y0[i] + v1[k] * y1[-i];
752 : }
753 :
754 54194800 : out[j] = in[j] - gain * s2 * ALPHA + gain * s;
755 :
756 54194800 : x0++;
757 54194800 : x1++;
758 54194800 : y0++;
759 54194800 : y1++;
760 :
761 54194800 : gain += gain_step;
762 : }
763 :
764 243946 : mvr2r( out - L, temp_buf, length + L );
765 243946 : mvr2r( in + length, temp_buf + length + L, L );
766 243946 : temp_ptr = &temp_buf[0] + L;
767 :
768 243946 : m0 = temp_ptr;
769 243946 : m1 = temp_ptr - 1;
770 243946 : l0 = &out[-cur_pitch_int];
771 243946 : l1 = l0 - 1;
772 :
773 : /* 2. increasing gain filter. The second filter unit with the parameters associated to the current interval and scaling from 0 towards current gain */
774 243946 : gain = 0.0f;
775 243946 : gain_step = cur_gain / length;
776 :
777 54438746 : for ( j = 0; j < length; j++ )
778 : {
779 54194800 : s3 = 0;
780 54194800 : s4 = 0;
781 :
782 448481600 : for ( i = 0, k = 0; i < L; i++, k += pitch_res )
783 : {
784 394286800 : s3 += p0[k] * l0[i] + p1[k] * l1[-i];
785 394286800 : s4 += q0[k] * m0[i] + q1[k] * m1[-i];
786 : }
787 :
788 54194800 : out[j] = *( temp_ptr + j ) - gain * s4 * ALPHA + gain * s3;
789 :
790 54194800 : l0++;
791 54194800 : l1++;
792 54194800 : m0++;
793 54194800 : m1++;
794 :
795 54194800 : gain += gain_step;
796 : }
797 :
798 243946 : return;
799 : }
800 :
801 :
802 : /*-------------------------------------------------------------------
803 : * tcx_ltp_post()
804 : *
805 : *
806 : *-------------------------------------------------------------------*/
807 :
808 2125267 : void tcx_ltp_post(
809 : Decoder_State *st,
810 : TCX_LTP_DEC_HANDLE hTcxLtpDec,
811 : const int16_t core,
812 : const int16_t output_frame,
813 : const int16_t delay,
814 : float sig[],
815 : const float tcx_buf[] )
816 : {
817 : int16_t tmp, L_transition, lpcorder, filtIdx;
818 : int16_t bfi, L_frame_core, SideInfoOnly;
819 : float gain, gain2;
820 : float zir[L_FRAME_PLUS / 4], A[TCXLTP_LTP_ORDER + 1];
821 : float buf_in[TCXLTP_MAX_DELAY + L_FRAME48k + TCXLTP_MAX_DELAY], buf_out[2 * L_FRAME48k];
822 : float *sig_in, *sig_out;
823 : int16_t pitch_int, pitch_fr;
824 : int16_t tcx_buf_len;
825 : int32_t total_brate;
826 :
827 2125267 : total_brate = ( st->element_mode == IVAS_CPE_MDCT ? st->bits_frame_nominal * FRAMES_PER_SEC : st->total_brate );
828 2125267 : filtIdx = 0; /* just to avoid compilation warnings */
829 2125267 : tcx_buf_len = NS2SA( st->output_Fs, TCXLTP_DELAY_NS );
830 2125267 : SideInfoOnly = 0;
831 :
832 2125267 : if ( total_brate >= HQ_96k )
833 : {
834 953790 : SideInfoOnly = 1;
835 : }
836 :
837 2125267 : L_frame_core = st->L_frame;
838 2125267 : if ( st->element_mode == IVAS_CPE_MDCT )
839 : {
840 1534862 : L_frame_core = L_FRAME;
841 : }
842 :
843 2125267 : if ( core == ACELP_CORE )
844 : {
845 297283 : bfi = 0;
846 297283 : pitch_int = 0;
847 297283 : pitch_fr = 0;
848 297283 : gain = 0.0f;
849 :
850 297283 : L_frame_core = st->L_frame_past;
851 : }
852 : else
853 : {
854 1827984 : bfi = st->bfi;
855 1827984 : pitch_int = hTcxLtpDec->tcxltp_pitch_int;
856 1827984 : pitch_fr = hTcxLtpDec->tcxltp_pitch_fr;
857 1827984 : gain = hTcxLtpDec->tcxltp_gain;
858 : }
859 :
860 : /******** Init ********/
861 :
862 : /* Parameters */
863 2125267 : L_transition = output_frame / 4;
864 2125267 : lpcorder = TCXLTP_LTP_ORDER;
865 :
866 :
867 : /* Input buffer */
868 2125267 : sig_in = buf_in + tcx_buf_len;
869 2125267 : mvr2r( hTcxLtpDec->tcxltp_mem_in, buf_in, tcx_buf_len );
870 2125267 : mvr2r( sig, buf_in + tcx_buf_len, output_frame );
871 2125267 : if ( core > ACELP_CORE )
872 : {
873 1827984 : mvr2r( tcx_buf, sig_in + output_frame, tcx_buf_len );
874 : }
875 2125267 : mvr2r( sig + output_frame - tcx_buf_len, hTcxLtpDec->tcxltp_mem_in, tcx_buf_len );
876 :
877 : /* Output buffer */
878 2125267 : sig_out = buf_out + output_frame;
879 2125267 : mvr2r( hTcxLtpDec->tcxltp_mem_out, buf_out, output_frame );
880 :
881 : /* TCX-LTP parameters: integer pitch, fractional pitch, gain */
882 :
883 2125267 : if ( !( SideInfoOnly || hTcxLtpDec->tcxltp ) || core == ACELP_CORE )
884 : {
885 : /* No LTP */
886 753375 : pitch_int = 0;
887 753375 : pitch_fr = 0;
888 753375 : gain = 0.f;
889 : }
890 1371892 : else if ( !bfi )
891 : {
892 : /* LTP and good frame */
893 1352531 : if ( output_frame != L_frame_core )
894 : {
895 1343729 : tmp = pitch_int * st->pit_res_max + pitch_fr;
896 1343729 : tmp = ( tmp * output_frame + L_frame_core / 2 ) / L_frame_core;
897 1343729 : pitch_int = tmp / st->pit_res_max;
898 1343729 : pitch_fr = tmp % st->pit_res_max;
899 : }
900 :
901 1352531 : if ( st->element_mode == EVS_MONO ) /* hard tunings for EVS_MONO, HQ_48k is TCX only */
902 : {
903 1325 : if ( total_brate == HQ_48k && L_frame_core == L_FRAME16k )
904 : {
905 0 : gain *= 0.32f;
906 : }
907 1325 : else if ( total_brate == HQ_48k && L_frame_core == 512 )
908 : {
909 0 : gain *= 0.40f;
910 : }
911 : else
912 : {
913 1325 : gain *= 0.64f;
914 : }
915 : }
916 1351206 : else if ( ( st->element_mode > IVAS_SCE ) && ( total_brate >= IVAS_96k ) )
917 : {
918 901104 : gain *= 0.40f;
919 : }
920 : else
921 : {
922 450102 : gain *= 0.64f;
923 : }
924 : }
925 : else
926 : {
927 : /* PLC: [TCX: Fade-out]
928 : * PLC: LTP and bad frame (concealment) */
929 19361 : if ( st->pit_res_max == st->pit_res_max_past ) /* ensure consistent core SR to previous frame; otherwise, set gain to 0 */
930 : {
931 19361 : pitch_int = hTcxLtpDec->tcxltp_pitch_int_post_prev;
932 19361 : pitch_fr = hTcxLtpDec->tcxltp_pitch_fr_post_prev;
933 19361 : gain = hTcxLtpDec->tcxltp_gain_post_prev * st->hTcxDec->damping;
934 : }
935 : else
936 : {
937 0 : gain = 0.f;
938 : }
939 : }
940 :
941 2125267 : if ( SideInfoOnly )
942 : {
943 953790 : gain = 0.f;
944 953790 : if ( bfi )
945 : {
946 14265 : hTcxLtpDec->tcxltp_gain_post_prev = 0.f;
947 : }
948 : }
949 2125267 : gain2 = gain;
950 :
951 2125267 : if ( L_frame_core == L_FRAME )
952 : {
953 1674381 : switch ( output_frame )
954 : {
955 0 : case L_FRAME8k:
956 0 : filtIdx = 0;
957 0 : break;
958 78740 : case L_FRAME16k:
959 78740 : filtIdx = 1;
960 78740 : break;
961 185074 : case L_FRAME32k:
962 185074 : filtIdx = 2;
963 185074 : break;
964 1410567 : case L_FRAME48k:
965 1410567 : filtIdx = 3;
966 1410567 : break;
967 0 : default:
968 0 : assert( 0 );
969 : break;
970 : }
971 : }
972 450886 : else if ( L_frame_core == L_FRAME16k )
973 : {
974 260679 : switch ( output_frame )
975 : {
976 0 : case L_FRAME8k:
977 0 : filtIdx = 4;
978 0 : break;
979 20464 : case L_FRAME16k:
980 20464 : filtIdx = 5;
981 20464 : break;
982 47292 : case L_FRAME32k:
983 47292 : filtIdx = 6;
984 47292 : break;
985 192923 : case L_FRAME48k:
986 192923 : filtIdx = 7;
987 192923 : break;
988 0 : default:
989 0 : assert( 0 );
990 : break;
991 : }
992 : }
993 190207 : else if ( L_frame_core == 512 )
994 : {
995 39871 : switch ( output_frame )
996 : {
997 0 : case L_FRAME8k:
998 0 : filtIdx = 8;
999 0 : break;
1000 135 : case L_FRAME16k:
1001 135 : filtIdx = 9;
1002 135 : break;
1003 3319 : case L_FRAME32k:
1004 3319 : filtIdx = 10;
1005 3319 : break;
1006 36417 : case L_FRAME48k:
1007 36417 : filtIdx = 11;
1008 36417 : break;
1009 0 : default:
1010 0 : assert( 0 );
1011 : break;
1012 : }
1013 : }
1014 : else
1015 : {
1016 150336 : filtIdx = -1;
1017 : }
1018 :
1019 :
1020 : /******** Previous-frame part ********/
1021 2125267 : 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, st->pit_res_max_past, hTcxLtpDec->tcxltp_filt_idx_prev );
1022 :
1023 : /******** Transition part - initial subinterval ********/
1024 :
1025 2125267 : if ( st->element_mode != EVS_MONO )
1026 : {
1027 2120117 : if ( gain == 0.f && hTcxLtpDec->tcxltp_gain_post_prev == 0.f )
1028 : {
1029 : /* The filtering is deactivated, just copy input to the output */
1030 1722112 : mvr2r( sig_in + delay, sig_out + delay, L_transition );
1031 : }
1032 398005 : else if ( gain == 0.f && hTcxLtpDec->tcxltp_gain_post_prev != 0.f )
1033 : {
1034 : /* Filtering with the first filter unit */
1035 55619 : 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 );
1036 : }
1037 342386 : else if ( gain != 0.f && hTcxLtpDec->tcxltp_gain_post_prev == 0.f )
1038 : {
1039 : /* Filtering with the second filter unit */
1040 57246 : tcx_ltp_synth_filter_01( sig_out + delay, sig_in + delay, L_transition, pitch_int, pitch_fr, gain, st->pit_res_max, filtIdx );
1041 : }
1042 285140 : else if ( gain == hTcxLtpDec->tcxltp_gain_post_prev && pitch_int == hTcxLtpDec->tcxltp_pitch_int_post_prev && pitch_fr == hTcxLtpDec->tcxltp_pitch_fr_post_prev && st->pit_res_max == st->pit_res_max_past && filtIdx == hTcxLtpDec->tcxltp_filt_idx_prev )
1043 : {
1044 41194 : tcx_ltp_synth_filter( sig_out + delay, sig_in + delay, L_transition, pitch_int, pitch_fr, gain, st->pit_res_max, filtIdx );
1045 : }
1046 : else
1047 : {
1048 : /* Filtering with the first filter unit, followed by the filtering with the second filter unit */
1049 243946 : 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,
1050 243946 : 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 );
1051 : }
1052 : }
1053 : else
1054 : {
1055 5150 : if ( gain == 0.f && hTcxLtpDec->tcxltp_gain_post_prev == 0.f )
1056 : {
1057 4015 : mvr2r( sig_in + delay, sig_out + delay, L_transition );
1058 : }
1059 1135 : else if ( hTcxLtpDec->tcxltp_gain_post_prev == 0.f )
1060 : {
1061 164 : tcx_ltp_synth_filter_fadein( sig_out + delay, sig_in + delay, L_transition, pitch_int, pitch_fr, gain, st->pit_res_max, filtIdx );
1062 : }
1063 971 : else if ( gain == 0.f )
1064 : {
1065 163 : tcx_ltp_synth_filter_fadeout( 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 );
1066 : }
1067 808 : else if ( gain == hTcxLtpDec->tcxltp_gain_post_prev && pitch_int == hTcxLtpDec->tcxltp_pitch_int_post_prev && pitch_fr == hTcxLtpDec->tcxltp_pitch_fr_post_prev )
1068 : {
1069 270 : tcx_ltp_synth_filter( sig_out + delay, sig_in + delay, L_transition, pitch_int, pitch_fr, gain, st->pit_res_max, filtIdx );
1070 : }
1071 : else
1072 : {
1073 : {
1074 538 : tcx_ltp_get_lpc( sig_out + delay - output_frame, output_frame, A, lpcorder );
1075 538 : 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 );
1076 538 : tcx_ltp_synth_filter_zir( sig_out + delay, sig_in + delay, L_transition, pitch_int, pitch_fr, gain, st->pit_res_max, zir, filtIdx );
1077 : }
1078 : }
1079 : }
1080 :
1081 : /******** Current-frame part - subsequent subinterval, filtered with the third filter unit ********/
1082 2125267 : 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, filtIdx );
1083 :
1084 : /******** Output ********/
1085 :
1086 : /* copy to output */
1087 2125267 : mvr2r( sig_out, sig, output_frame );
1088 :
1089 : /* Update */
1090 2125267 : hTcxLtpDec->tcxltp_pitch_int_post_prev = pitch_int;
1091 2125267 : hTcxLtpDec->tcxltp_pitch_fr_post_prev = pitch_fr;
1092 2125267 : hTcxLtpDec->tcxltp_gain_post_prev = gain2;
1093 2125267 : hTcxLtpDec->tcxltp_filt_idx_prev = filtIdx;
1094 2125267 : st->pit_res_max_past = st->pit_res_max;
1095 2125267 : mvr2r( sig_out, hTcxLtpDec->tcxltp_mem_out, output_frame );
1096 :
1097 2125267 : return;
1098 : }
|