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 696006 : 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 696006 : x0 = &excI[-T0 - 1];
186 696006 : frac = -frac;
187 :
188 696006 : if ( frac < 0 )
189 : {
190 344306 : frac += frac_max;
191 344306 : x0--;
192 : }
193 :
194 696006 : if ( frac_max == 6 )
195 : {
196 149765 : win = &inter6_2tcx2[frac][0];
197 : }
198 : else
199 : {
200 546241 : win = &inter4_2tcx2[frac][0];
201 : }
202 :
203 198305702 : for ( j = 0; j < L_subfr; j++ )
204 : {
205 197609696 : s = win[1] * x0[1] + win[2] * x0[2];
206 197609696 : excO[j] = s + win[0] * x0[0] + win[3] * x0[3];
207 197609696 : x0++;
208 : }
209 :
210 696006 : return;
211 : }
212 :
213 :
214 : /*-------------------------------------------------------------------
215 : * tcx_ltp_synth_filter()
216 : *
217 : *
218 : *-------------------------------------------------------------------*/
219 :
220 4626435 : 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 4626435 : if ( gain > 0.f )
237 : {
238 767761 : x0 = &synth_ltp[-pitch_int];
239 767761 : x1 = x0 - 1;
240 767761 : y0 = synth;
241 767761 : y1 = y0 - 1;
242 :
243 767761 : assert( filtIdx >= 0 );
244 :
245 767761 : w0 = &tcxLtpFilters[filtIdx].filt[pitch_fr];
246 767761 : w1 = &tcxLtpFilters[filtIdx].filt[pitch_res - pitch_fr];
247 767761 : v0 = &tcxLtpFilters[filtIdx].filt[0];
248 767761 : v1 = &tcxLtpFilters[filtIdx].filt[pitch_res];
249 :
250 767761 : L = tcxLtpFilters[filtIdx].length;
251 :
252 :
253 247596900 : for ( j = 0; j < length; j++ )
254 : {
255 246829139 : s = 0;
256 246829139 : s2 = 0;
257 2031009065 : for ( i = 0, k = 0; i < L; i++, k += pitch_res )
258 : {
259 1784179926 : s += w0[k] * x0[i] + w1[k] * x1[-i];
260 1784179926 : s2 += v0[k] * y0[i] + v1[k] * y1[-i];
261 : }
262 :
263 246829139 : s2 *= ALPHA;
264 246829139 : synth_ltp[j] = synth[j] - gain * s2 + gain * s;
265 :
266 246829139 : x0++;
267 246829139 : x1++;
268 246829139 : y0++;
269 246829139 : y1++;
270 : }
271 : }
272 : else
273 : {
274 3858674 : mvr2r( synth, synth_ltp, length );
275 : }
276 :
277 4626435 : 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 1762163 : 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 1762163 : int16_t gainbits = 2;
505 :
506 : /* Decode Pitch and Gain */
507 1762163 : if ( ( ltp_param ) && ( ltp_param[0] ) )
508 : {
509 1226115 : if ( ltp_param[1] < ( ( pitfr2 - pitmin ) * pitres ) )
510 : {
511 873618 : *pitch_int = pitmin + ( ltp_param[1] / pitres );
512 873618 : *pitch_fr = ltp_param[1] - ( *pitch_int - pitmin ) * pitres;
513 : }
514 352497 : else if ( ltp_param[1] < ( ( pitfr2 - pitmin ) * pitres + ( pitfr1 - pitfr2 ) * ( pitres >> 1 ) ) )
515 : {
516 102644 : *pitch_int = pitfr2 + ( ( ltp_param[1] - ( pitfr2 - pitmin ) * pitres ) / ( pitres >> 1 ) );
517 102644 : *pitch_fr = ( ltp_param[1] - ( pitfr2 - pitmin ) * pitres ) - ( *pitch_int - pitfr2 ) * ( pitres >> 1 );
518 102644 : *pitch_fr = *pitch_fr << 1; /* was *= (pitres>>1); */
519 : }
520 : else
521 : {
522 249853 : *pitch_int = ltp_param[1] + pitfr1 - ( ( pitfr2 - pitmin ) * pitres ) - ( ( pitfr1 - pitfr2 ) * ( pitres >> 1 ) );
523 249853 : *pitch_fr = 0;
524 : }
525 1226115 : *gain = (float) ( ltp_param[2] + 1 ) * 0.625f / (float) ( 1 << gainbits );
526 1226115 : 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 1226115 : 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 536048 : *pitch_int = pitmax;
542 536048 : *pitch_fr = 0;
543 536048 : *gain = 0.0f;
544 : }
545 :
546 1762163 : return 0;
547 : }
548 :
549 : /*-------------------------------------------------------------------
550 : *tcx_ltp_synth_filter_10()
551 : *
552 : *
553 : ---------------------------------------------------------------------*/
554 60064 : 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 60064 : x0 = &out[-pitch_int];
572 60064 : x1 = x0 - 1;
573 60064 : y0 = in;
574 60064 : y1 = y0 - 1;
575 :
576 60064 : assert( filtIdx >= 0 );
577 :
578 60064 : w0 = &tcxLtpFilters[filtIdx].filt[pitch_fr];
579 60064 : w1 = &tcxLtpFilters[filtIdx].filt[pitch_res - pitch_fr];
580 60064 : v0 = &tcxLtpFilters[filtIdx].filt[0];
581 60064 : v1 = &tcxLtpFilters[filtIdx].filt[pitch_res];
582 60064 : L = tcxLtpFilters[filtIdx].length;
583 :
584 60064 : curr_gain = gain;
585 60064 : gain_step = -gain / length;
586 :
587 13383024 : for ( j = 0; j < length; j++ )
588 : {
589 13322960 : s = 0;
590 13322960 : s2 = 0;
591 :
592 109165200 : for ( i = 0, k = 0; i < L; i++, k += pitch_res )
593 : {
594 95842240 : s += w0[k] * x0[i] + w1[k] * x1[-i];
595 95842240 : s2 += v0[k] * y0[i] + v1[k] * y1[-i];
596 : }
597 :
598 13322960 : out[j] = in[j] - curr_gain * s2 * ALPHA + curr_gain * s;
599 :
600 13322960 : x0++;
601 13322960 : x1++;
602 13322960 : y0++;
603 13322960 : y1++;
604 :
605 13322960 : curr_gain += gain_step;
606 : }
607 :
608 60064 : return;
609 : }
610 :
611 :
612 : /*-------------------------------------------------------------------
613 : *tcx_ltp_synth_filter_01()
614 : *
615 : *
616 : ---------------------------------------------------------------------*/
617 :
618 61937 : 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 61937 : x0 = &out[-pitch_int];
636 61937 : x1 = x0 - 1;
637 61937 : y0 = in;
638 61937 : y1 = y0 - 1;
639 :
640 61937 : assert( filtIdx >= 0 );
641 :
642 61937 : w0 = &tcxLtpFilters[filtIdx].filt[pitch_fr];
643 61937 : w1 = &tcxLtpFilters[filtIdx].filt[pitch_res - pitch_fr];
644 61937 : v0 = &tcxLtpFilters[filtIdx].filt[0];
645 61937 : v1 = &tcxLtpFilters[filtIdx].filt[pitch_res];
646 61937 : L = tcxLtpFilters[filtIdx].length;
647 :
648 61937 : curr_gain = 0.0f;
649 61937 : gain_step = gain / length;
650 :
651 13795057 : for ( j = 0; j < length; j++ )
652 : {
653 13733120 : s = 0;
654 13733120 : s2 = 0;
655 :
656 112298800 : for ( i = 0, k = 0; i < L; i++, k += pitch_res )
657 : {
658 98565680 : s += w0[k] * x0[i] + w1[k] * x1[-i];
659 98565680 : s2 += v0[k] * y0[i] + v1[k] * y1[-i];
660 : }
661 :
662 13733120 : out[j] = in[j] - curr_gain * s2 * ALPHA + curr_gain * s;
663 :
664 13733120 : x0++;
665 13733120 : x1++;
666 13733120 : y0++;
667 13733120 : y1++;
668 :
669 13733120 : curr_gain += gain_step;
670 : }
671 :
672 61937 : 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 254968 : 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 254968 : x0 = &out[-prev_pitch_int];
719 254968 : x1 = x0 - 1;
720 254968 : y0 = in;
721 254968 : y1 = y0 - 1;
722 :
723 254968 : assert( filtIdx >= 0 && prev_filtIdx >= 0 );
724 :
725 254968 : w0 = &tcxLtpFilters[prev_filtIdx].filt[prev_pitch_fr];
726 254968 : w1 = &tcxLtpFilters[prev_filtIdx].filt[prev_pitch_res - prev_pitch_fr];
727 254968 : v0 = &tcxLtpFilters[prev_filtIdx].filt[0];
728 254968 : v1 = &tcxLtpFilters[prev_filtIdx].filt[prev_pitch_res];
729 :
730 254968 : prev_L = tcxLtpFilters[prev_filtIdx].length;
731 :
732 254968 : p0 = &tcxLtpFilters[filtIdx].filt[cur_pitch_fr];
733 254968 : p1 = &tcxLtpFilters[filtIdx].filt[pitch_res - cur_pitch_fr];
734 254968 : q0 = &tcxLtpFilters[filtIdx].filt[0];
735 254968 : q1 = &tcxLtpFilters[filtIdx].filt[pitch_res];
736 :
737 254968 : 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 254968 : gain = prev_gain;
741 254968 : gain_step = -prev_gain / length;
742 :
743 57000568 : for ( j = 0; j < length; j++ )
744 : {
745 56745600 : s = 0;
746 56745600 : s2 = 0;
747 :
748 469196080 : for ( i = 0, k = 0; i < prev_L; i++, k += prev_pitch_res )
749 : {
750 412450480 : s += w0[k] * x0[i] + w1[k] * x1[-i];
751 412450480 : s2 += v0[k] * y0[i] + v1[k] * y1[-i];
752 : }
753 :
754 56745600 : out[j] = in[j] - gain * s2 * ALPHA + gain * s;
755 :
756 56745600 : x0++;
757 56745600 : x1++;
758 56745600 : y0++;
759 56745600 : y1++;
760 :
761 56745600 : gain += gain_step;
762 : }
763 :
764 254968 : mvr2r( out - L, temp_buf, length + L );
765 254968 : mvr2r( in + length, temp_buf + length + L, L );
766 254968 : temp_ptr = &temp_buf[0] + L;
767 :
768 254968 : m0 = temp_ptr;
769 254968 : m1 = temp_ptr - 1;
770 254968 : l0 = &out[-cur_pitch_int];
771 254968 : 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 254968 : gain = 0.0f;
775 254968 : gain_step = cur_gain / length;
776 :
777 57000568 : for ( j = 0; j < length; j++ )
778 : {
779 56745600 : s3 = 0;
780 56745600 : s4 = 0;
781 :
782 469207760 : for ( i = 0, k = 0; i < L; i++, k += pitch_res )
783 : {
784 412462160 : s3 += p0[k] * l0[i] + p1[k] * l1[-i];
785 412462160 : s4 += q0[k] * m0[i] + q1[k] * m1[-i];
786 : }
787 :
788 56745600 : out[j] = *( temp_ptr + j ) - gain * s4 * ALPHA + gain * s3;
789 :
790 56745600 : l0++;
791 56745600 : l1++;
792 56745600 : m0++;
793 56745600 : m1++;
794 :
795 56745600 : gain += gain_step;
796 : }
797 :
798 254968 : return;
799 : }
800 :
801 :
802 : /*-------------------------------------------------------------------
803 : * tcx_ltp_post()
804 : *
805 : *
806 : *-------------------------------------------------------------------*/
807 :
808 2290814 : 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 2290814 : total_brate = ( st->element_mode == IVAS_CPE_MDCT ? st->bits_frame_nominal * FRAMES_PER_SEC : st->total_brate );
828 2290814 : filtIdx = 0; /* just to avoid compilation warnings */
829 2290814 : tcx_buf_len = NS2SA( st->output_Fs, TCXLTP_DELAY_NS );
830 2290814 : SideInfoOnly = 0;
831 :
832 2290814 : if ( total_brate >= HQ_96k )
833 : {
834 999014 : SideInfoOnly = 1;
835 : }
836 :
837 2290814 : L_frame_core = st->L_frame;
838 2290814 : if ( st->element_mode == IVAS_CPE_MDCT )
839 : {
840 1601838 : L_frame_core = L_FRAME;
841 : }
842 :
843 2290814 : if ( core == ACELP_CORE )
844 : {
845 332762 : bfi = 0;
846 332762 : pitch_int = 0;
847 332762 : pitch_fr = 0;
848 332762 : gain = 0.0f;
849 :
850 332762 : L_frame_core = st->L_frame_past;
851 : }
852 : else
853 : {
854 1958052 : bfi = st->bfi;
855 1958052 : pitch_int = hTcxLtpDec->tcxltp_pitch_int;
856 1958052 : pitch_fr = hTcxLtpDec->tcxltp_pitch_fr;
857 1958052 : gain = hTcxLtpDec->tcxltp_gain;
858 : }
859 :
860 : /******** Init ********/
861 :
862 : /* Parameters */
863 2290814 : L_transition = output_frame / 4;
864 2290814 : lpcorder = TCXLTP_LTP_ORDER;
865 :
866 :
867 : /* Input buffer */
868 2290814 : sig_in = buf_in + tcx_buf_len;
869 2290814 : mvr2r( hTcxLtpDec->tcxltp_mem_in, buf_in, tcx_buf_len );
870 2290814 : mvr2r( sig, buf_in + tcx_buf_len, output_frame );
871 2290814 : if ( core > ACELP_CORE )
872 : {
873 1958052 : mvr2r( tcx_buf, sig_in + output_frame, tcx_buf_len );
874 : }
875 2290814 : mvr2r( sig + output_frame - tcx_buf_len, hTcxLtpDec->tcxltp_mem_in, tcx_buf_len );
876 :
877 : /* Output buffer */
878 2290814 : sig_out = buf_out + output_frame;
879 2290814 : mvr2r( hTcxLtpDec->tcxltp_mem_out, buf_out, output_frame );
880 :
881 : /* TCX-LTP parameters: integer pitch, fractional pitch, gain */
882 :
883 2290814 : if ( !( SideInfoOnly || hTcxLtpDec->tcxltp ) || core == ACELP_CORE )
884 : {
885 : /* No LTP */
886 835931 : pitch_int = 0;
887 835931 : pitch_fr = 0;
888 835931 : gain = 0.f;
889 : }
890 1454883 : else if ( !bfi )
891 : {
892 : /* LTP and good frame */
893 1434381 : if ( output_frame != L_frame_core )
894 : {
895 1424896 : tmp = pitch_int * st->pit_res_max + pitch_fr;
896 1424896 : tmp = ( tmp * output_frame + L_frame_core / 2 ) / L_frame_core;
897 1424896 : pitch_int = tmp / st->pit_res_max;
898 1424896 : pitch_fr = tmp % st->pit_res_max;
899 : }
900 :
901 1434381 : 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 1433056 : else if ( ( st->element_mode > IVAS_SCE ) && ( total_brate >= IVAS_96k ) )
917 : {
918 938106 : gain *= 0.40f;
919 : }
920 : else
921 : {
922 494950 : gain *= 0.64f;
923 : }
924 : }
925 : else
926 : {
927 : /* PLC: [TCX: Fade-out]
928 : * PLC: LTP and bad frame (concealment) */
929 20502 : if ( st->pit_res_max == st->pit_res_max_past ) /* ensure consistent core SR to previous frame; otherwise, set gain to 0 */
930 : {
931 20502 : pitch_int = hTcxLtpDec->tcxltp_pitch_int_post_prev;
932 20502 : pitch_fr = hTcxLtpDec->tcxltp_pitch_fr_post_prev;
933 20502 : gain = hTcxLtpDec->tcxltp_gain_post_prev * st->hTcxDec->damping;
934 : }
935 : else
936 : {
937 0 : gain = 0.f;
938 : }
939 : }
940 :
941 2290814 : if ( SideInfoOnly )
942 : {
943 999014 : gain = 0.f;
944 999014 : if ( bfi )
945 : {
946 14913 : hTcxLtpDec->tcxltp_gain_post_prev = 0.f;
947 : }
948 : }
949 2290814 : gain2 = gain;
950 :
951 2290814 : if ( L_frame_core == L_FRAME )
952 : {
953 1746859 : switch ( output_frame )
954 : {
955 0 : case L_FRAME8k:
956 0 : filtIdx = 0;
957 0 : break;
958 82625 : case L_FRAME16k:
959 82625 : filtIdx = 1;
960 82625 : break;
961 189278 : case L_FRAME32k:
962 189278 : filtIdx = 2;
963 189278 : break;
964 1474956 : case L_FRAME48k:
965 1474956 : filtIdx = 3;
966 1474956 : break;
967 0 : default:
968 0 : assert( 0 );
969 : break;
970 : }
971 : }
972 543955 : else if ( L_frame_core == L_FRAME16k )
973 : {
974 329569 : switch ( output_frame )
975 : {
976 0 : case L_FRAME8k:
977 0 : filtIdx = 4;
978 0 : break;
979 22766 : case L_FRAME16k:
980 22766 : filtIdx = 5;
981 22766 : break;
982 49582 : case L_FRAME32k:
983 49582 : filtIdx = 6;
984 49582 : break;
985 257221 : case L_FRAME48k:
986 257221 : filtIdx = 7;
987 257221 : break;
988 0 : default:
989 0 : assert( 0 );
990 : break;
991 : }
992 : }
993 214386 : else if ( L_frame_core == 512 )
994 : {
995 47950 : switch ( output_frame )
996 : {
997 0 : case L_FRAME8k:
998 0 : filtIdx = 8;
999 0 : break;
1000 568 : case L_FRAME16k:
1001 568 : filtIdx = 9;
1002 568 : break;
1003 3462 : case L_FRAME32k:
1004 3462 : filtIdx = 10;
1005 3462 : break;
1006 43920 : case L_FRAME48k:
1007 43920 : filtIdx = 11;
1008 43920 : break;
1009 0 : default:
1010 0 : assert( 0 );
1011 : break;
1012 : }
1013 : }
1014 : else
1015 : {
1016 166436 : filtIdx = -1;
1017 : }
1018 :
1019 :
1020 : /******** Previous-frame part ********/
1021 2290814 : 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 2290814 : if ( st->element_mode != EVS_MONO )
1026 : {
1027 2285664 : if ( gain == 0.f && hTcxLtpDec->tcxltp_gain_post_prev == 0.f )
1028 : {
1029 : /* The filtering is deactivated, just copy input to the output */
1030 1864158 : mvr2r( sig_in + delay, sig_out + delay, L_transition );
1031 : }
1032 421506 : else if ( gain == 0.f && hTcxLtpDec->tcxltp_gain_post_prev != 0.f )
1033 : {
1034 : /* Filtering with the first filter unit */
1035 60064 : 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 361442 : else if ( gain != 0.f && hTcxLtpDec->tcxltp_gain_post_prev == 0.f )
1038 : {
1039 : /* Filtering with the second filter unit */
1040 61937 : 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 299505 : 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 44537 : 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 254968 : 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 254968 : 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 2290814 : 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 2290814 : mvr2r( sig_out, sig, output_frame );
1088 :
1089 : /* Update */
1090 2290814 : hTcxLtpDec->tcxltp_pitch_int_post_prev = pitch_int;
1091 2290814 : hTcxLtpDec->tcxltp_pitch_fr_post_prev = pitch_fr;
1092 2290814 : hTcxLtpDec->tcxltp_gain_post_prev = gain2;
1093 2290814 : hTcxLtpDec->tcxltp_filt_idx_prev = filtIdx;
1094 2290814 : st->pit_res_max_past = st->pit_res_max;
1095 2290814 : mvr2r( sig_out, hTcxLtpDec->tcxltp_mem_out, output_frame );
1096 :
1097 2290814 : return;
1098 : }
|