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 786 : 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 20436 : for ( i = 0; i <= lpcorder; i++ )
69 : {
70 19650 : s = 0.0;
71 :
72 16175850 : for ( j = 0; j < length - i; j++ )
73 : {
74 16156200 : s += input[j] * input[j + i];
75 : }
76 19650 : r[i] = s;
77 : }
78 :
79 786 : if ( r[0] < 100.0f )
80 : {
81 0 : r[0] = 100.0f;
82 : }
83 786 : r[0] *= 1.0001f;
84 :
85 786 : lev_dur( A, r, lpcorder, NULL );
86 :
87 786 : return;
88 : }
89 :
90 :
91 : /*-------------------------------------------------------------------
92 : * tcx_ltp_get_zir()
93 : *
94 : *
95 : *-------------------------------------------------------------------*/
96 :
97 786 : 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 786 : x0 = &synth_ltp[-pitch_int];
117 786 : x1 = x0 - 1;
118 786 : y0 = synth;
119 786 : y1 = y0 - 1;
120 :
121 786 : assert( filtIdx >= 0 );
122 :
123 786 : w0 = &tcxLtpFilters[filtIdx].filt[pitch_fr];
124 786 : w1 = &tcxLtpFilters[filtIdx].filt[pitres - pitch_fr];
125 786 : v0 = &tcxLtpFilters[filtIdx].filt[0];
126 786 : v1 = &tcxLtpFilters[filtIdx].filt[pitres];
127 786 : L = tcxLtpFilters[filtIdx].length;
128 :
129 19650 : for ( j = 0; j < lpcorder; j++ )
130 : {
131 18864 : s = 0;
132 18864 : s2 = 0;
133 124632 : for ( i = 0, k = 0; i < L; i++, k += pitres )
134 : {
135 105768 : s += w0[k] * x0[i] + w1[k] * x1[-i];
136 105768 : s2 += v0[k] * y0[i] + v1[k] * y1[-i];
137 : }
138 18864 : s2 *= ALPHA;
139 :
140 18864 : buf[j] = ( synth[j] - gain * s2 ) - ( synth_ltp[j] - gain * s );
141 :
142 :
143 18864 : x0++;
144 18864 : x1++;
145 18864 : y0++;
146 18864 : y1++;
147 : }
148 :
149 786 : set_f( zir, 0.0f, length );
150 :
151 786 : syn_filt( A, lpcorder, zir, zir, length, buf, 0 );
152 :
153 786 : alpha = 1.f;
154 786 : step = 1.f / (float) ( length / 2 );
155 :
156 82746 : for ( j = length / 2; j < length; j++ )
157 : {
158 81960 : zir[j] *= alpha;
159 81960 : alpha -= step;
160 : }
161 :
162 786 : return;
163 : }
164 :
165 :
166 : /*-------------------------------------------------------------------
167 : * predict_signal()
168 : *
169 : *
170 : *-------------------------------------------------------------------*/
171 :
172 933795 : 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 933795 : x0 = &excI[-T0 - 1];
186 933795 : frac = -frac;
187 :
188 933795 : if ( frac < 0 )
189 : {
190 473290 : frac += frac_max;
191 473290 : x0--;
192 : }
193 :
194 933795 : if ( frac_max == 6 )
195 : {
196 200367 : win = &inter6_2tcx2[frac][0];
197 : }
198 : else
199 : {
200 733428 : win = &inter4_2tcx2[frac][0];
201 : }
202 :
203 272699123 : for ( j = 0; j < L_subfr; j++ )
204 : {
205 271765328 : s = win[1] * x0[1] + win[2] * x0[2];
206 271765328 : excO[j] = s + win[0] * x0[0] + win[3] * x0[3];
207 271765328 : x0++;
208 : }
209 :
210 933795 : return;
211 : }
212 :
213 :
214 : /*-------------------------------------------------------------------
215 : * tcx_ltp_synth_filter()
216 : *
217 : *
218 : *-------------------------------------------------------------------*/
219 :
220 7093020 : 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 7093020 : if ( gain > 0.f )
237 : {
238 1150041 : x0 = &synth_ltp[-pitch_int];
239 1150041 : x1 = x0 - 1;
240 1150041 : y0 = synth;
241 1150041 : y1 = y0 - 1;
242 :
243 1150041 : assert( filtIdx >= 0 );
244 :
245 1150041 : w0 = &tcxLtpFilters[filtIdx].filt[pitch_fr];
246 1150041 : w1 = &tcxLtpFilters[filtIdx].filt[pitch_res - pitch_fr];
247 1150041 : v0 = &tcxLtpFilters[filtIdx].filt[0];
248 1150041 : v1 = &tcxLtpFilters[filtIdx].filt[pitch_res];
249 :
250 1150041 : L = tcxLtpFilters[filtIdx].length;
251 :
252 :
253 342225561 : for ( j = 0; j < length; j++ )
254 : {
255 341075520 : s = 0;
256 341075520 : s2 = 0;
257 2660975778 : for ( i = 0, k = 0; i < L; i++, k += pitch_res )
258 : {
259 2319900258 : s += w0[k] * x0[i] + w1[k] * x1[-i];
260 2319900258 : s2 += v0[k] * y0[i] + v1[k] * y1[-i];
261 : }
262 :
263 341075520 : s2 *= ALPHA;
264 341075520 : synth_ltp[j] = synth[j] - gain * s2 + gain * s;
265 :
266 341075520 : x0++;
267 341075520 : x1++;
268 341075520 : y0++;
269 341075520 : y1++;
270 : }
271 : }
272 : else
273 : {
274 5942979 : mvr2r( synth, synth_ltp, length );
275 : }
276 :
277 7093020 : return;
278 : }
279 :
280 :
281 : /*-------------------------------------------------------------------
282 : * tcx_ltp_synth_filter_zir()
283 : *
284 : *
285 : *-------------------------------------------------------------------*/
286 :
287 786 : 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 786 : x0 = &synth_ltp[-pitch_int];
305 786 : x1 = x0 - 1;
306 786 : y0 = synth;
307 786 : y1 = y0 - 1;
308 :
309 786 : assert( filtIdx >= 0 );
310 :
311 786 : w0 = &tcxLtpFilters[filtIdx].filt[pitch_fr];
312 786 : w1 = &tcxLtpFilters[filtIdx].filt[pitch_res - pitch_fr];
313 786 : v0 = &tcxLtpFilters[filtIdx].filt[0];
314 786 : v1 = &tcxLtpFilters[filtIdx].filt[pitch_res];
315 786 : L = tcxLtpFilters[filtIdx].length;
316 :
317 164706 : for ( j = 0; j < length; j++ )
318 : {
319 163920 : s = 0;
320 163920 : s2 = 0;
321 :
322 1098000 : for ( i = 0, k = 0; i < L; i++, k += pitch_res )
323 : {
324 934080 : s += w0[k] * x0[i] + w1[k] * x1[-i];
325 934080 : s2 += v0[k] * y0[i] + v1[k] * y1[-i];
326 : }
327 :
328 163920 : s2 *= ALPHA;
329 :
330 163920 : synth_ltp[j] = ( synth[j] - gain * s2 + gain * s ) - zir[j];
331 :
332 163920 : x0++;
333 163920 : x1++;
334 163920 : y0++;
335 163920 : y1++;
336 : }
337 :
338 786 : return;
339 : }
340 :
341 :
342 : /*-------------------------------------------------------------------
343 : * tcx_ltp_synth_filter_fadein()
344 : *
345 : *
346 : *-------------------------------------------------------------------*/
347 :
348 258 : 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 258 : if ( gain > 0.f )
366 : {
367 258 : x0 = &synth_ltp[-pitch_int];
368 258 : x1 = x0 - 1;
369 258 : y0 = synth;
370 258 : y1 = y0 - 1;
371 :
372 258 : assert( filtIdx >= 0 );
373 :
374 258 : w0 = &tcxLtpFilters[filtIdx].filt[pitch_fr];
375 258 : w1 = &tcxLtpFilters[filtIdx].filt[pitch_res - pitch_fr];
376 258 : v0 = &tcxLtpFilters[filtIdx].filt[0];
377 258 : v1 = &tcxLtpFilters[filtIdx].filt[pitch_res];
378 258 : L = tcxLtpFilters[filtIdx].length;
379 :
380 258 : alpha = 0.f;
381 258 : step = 1.f / (float) ( length );
382 :
383 :
384 52818 : for ( j = 0; j < length; j++ )
385 : {
386 52560 : s = 0;
387 52560 : s2 = 0;
388 :
389 349200 : for ( i = 0, k = 0; i < L; i++, k += pitch_res )
390 : {
391 296640 : s += w0[k] * x0[i] + w1[k] * x1[-i];
392 296640 : s2 += v0[k] * y0[i] + v1[k] * y1[-i];
393 : }
394 :
395 52560 : s2 *= ALPHA;
396 :
397 52560 : synth_ltp[j] = synth[j] - alpha * gain * s2 + alpha * gain * s;
398 :
399 52560 : alpha += step;
400 :
401 52560 : x0++;
402 52560 : x1++;
403 52560 : y0++;
404 52560 : y1++;
405 : }
406 : }
407 : else
408 : {
409 0 : mvr2r( synth, synth_ltp, length );
410 : }
411 :
412 258 : return;
413 : }
414 :
415 :
416 : /*-------------------------------------------------------------------
417 : * tcx_ltp_synth_filter_fadeout()
418 : *
419 : *
420 : *-------------------------------------------------------------------*/
421 :
422 258 : 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 258 : if ( gain > 0.f )
440 : {
441 258 : x0 = &synth_ltp[-pitch_int];
442 258 : x1 = x0 - 1;
443 258 : y0 = synth;
444 258 : y1 = y0 - 1;
445 :
446 258 : assert( filtIdx >= 0 );
447 :
448 258 : w0 = &tcxLtpFilters[filtIdx].filt[pitch_fr];
449 258 : w1 = &tcxLtpFilters[filtIdx].filt[pitch_res - pitch_fr];
450 258 : v0 = &tcxLtpFilters[filtIdx].filt[0];
451 258 : v1 = &tcxLtpFilters[filtIdx].filt[pitch_res];
452 258 : L = tcxLtpFilters[filtIdx].length;
453 :
454 258 : alpha = 1.f;
455 258 : step = 1.f / (float) ( length );
456 :
457 52818 : for ( j = 0; j < length; j++ )
458 : {
459 52560 : s = 0;
460 52560 : s2 = 0;
461 :
462 349200 : for ( i = 0, k = 0; i < L; i++, k += pitch_res )
463 : {
464 296640 : s += w0[k] * x0[i] + w1[k] * x1[-i];
465 296640 : s2 += v0[k] * y0[i] + v1[k] * y1[-i];
466 : }
467 :
468 52560 : s2 *= ALPHA;
469 52560 : synth_ltp[j] = synth[j] - alpha * gain * s2 + alpha * gain * s;
470 52560 : alpha -= step;
471 :
472 52560 : x0++;
473 52560 : x1++;
474 52560 : y0++;
475 52560 : y1++;
476 : }
477 : }
478 : else
479 : {
480 0 : mvr2r( synth, synth_ltp, length );
481 : }
482 :
483 258 : return;
484 : }
485 :
486 :
487 : /*-------------------------------------------------------------------
488 : * tcx_ltp_decode_params()
489 : *
490 : *
491 : *-------------------------------------------------------------------*/
492 :
493 2569620 : 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 2569620 : int16_t gainbits = 2;
505 :
506 : /* Decode Pitch and Gain */
507 2569620 : if ( ( ltp_param ) && ( ltp_param[0] ) )
508 : {
509 1725120 : if ( ltp_param[1] < ( ( pitfr2 - pitmin ) * pitres ) )
510 : {
511 1160817 : *pitch_int = pitmin + ( ltp_param[1] / pitres );
512 1160817 : *pitch_fr = ltp_param[1] - ( *pitch_int - pitmin ) * pitres;
513 : }
514 564303 : else if ( ltp_param[1] < ( ( pitfr2 - pitmin ) * pitres + ( pitfr1 - pitfr2 ) * ( pitres >> 1 ) ) )
515 : {
516 170175 : *pitch_int = pitfr2 + ( ( ltp_param[1] - ( pitfr2 - pitmin ) * pitres ) / ( pitres >> 1 ) );
517 170175 : *pitch_fr = ( ltp_param[1] - ( pitfr2 - pitmin ) * pitres ) - ( *pitch_int - pitfr2 ) * ( pitres >> 1 );
518 170175 : *pitch_fr = *pitch_fr << 1; /* was *= (pitres>>1); */
519 : }
520 : else
521 : {
522 394128 : *pitch_int = ltp_param[1] + pitfr1 - ( ( pitfr2 - pitmin ) * pitres ) - ( ( pitfr1 - pitfr2 ) * ( pitres >> 1 ) );
523 394128 : *pitch_fr = 0;
524 : }
525 1725120 : *gain = (float) ( ltp_param[2] + 1 ) * 0.625f / (float) ( 1 << gainbits );
526 1725120 : 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 1725120 : 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 844500 : *pitch_int = pitmax;
542 844500 : *pitch_fr = 0;
543 844500 : *gain = 0.0f;
544 : }
545 :
546 2569620 : return 0;
547 : }
548 :
549 : /*-------------------------------------------------------------------
550 : *tcx_ltp_synth_filter_10()
551 : *
552 : *
553 : ---------------------------------------------------------------------*/
554 88482 : 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 88482 : x0 = &out[-pitch_int];
572 88482 : x1 = x0 - 1;
573 88482 : y0 = in;
574 88482 : y1 = y0 - 1;
575 :
576 88482 : assert( filtIdx >= 0 );
577 :
578 88482 : w0 = &tcxLtpFilters[filtIdx].filt[pitch_fr];
579 88482 : w1 = &tcxLtpFilters[filtIdx].filt[pitch_res - pitch_fr];
580 88482 : v0 = &tcxLtpFilters[filtIdx].filt[0];
581 88482 : v1 = &tcxLtpFilters[filtIdx].filt[pitch_res];
582 88482 : L = tcxLtpFilters[filtIdx].length;
583 :
584 88482 : curr_gain = gain;
585 88482 : gain_step = -gain / length;
586 :
587 18217602 : for ( j = 0; j < length; j++ )
588 : {
589 18129120 : s = 0;
590 18129120 : s2 = 0;
591 :
592 140973600 : for ( i = 0, k = 0; i < L; i++, k += pitch_res )
593 : {
594 122844480 : s += w0[k] * x0[i] + w1[k] * x1[-i];
595 122844480 : s2 += v0[k] * y0[i] + v1[k] * y1[-i];
596 : }
597 :
598 18129120 : out[j] = in[j] - curr_gain * s2 * ALPHA + curr_gain * s;
599 :
600 18129120 : x0++;
601 18129120 : x1++;
602 18129120 : y0++;
603 18129120 : y1++;
604 :
605 18129120 : curr_gain += gain_step;
606 : }
607 :
608 88482 : return;
609 : }
610 :
611 :
612 : /*-------------------------------------------------------------------
613 : *tcx_ltp_synth_filter_01()
614 : *
615 : *
616 : ---------------------------------------------------------------------*/
617 :
618 92139 : 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 92139 : x0 = &out[-pitch_int];
636 92139 : x1 = x0 - 1;
637 92139 : y0 = in;
638 92139 : y1 = y0 - 1;
639 :
640 92139 : assert( filtIdx >= 0 );
641 :
642 92139 : w0 = &tcxLtpFilters[filtIdx].filt[pitch_fr];
643 92139 : w1 = &tcxLtpFilters[filtIdx].filt[pitch_res - pitch_fr];
644 92139 : v0 = &tcxLtpFilters[filtIdx].filt[0];
645 92139 : v1 = &tcxLtpFilters[filtIdx].filt[pitch_res];
646 92139 : L = tcxLtpFilters[filtIdx].length;
647 :
648 92139 : curr_gain = 0.0f;
649 92139 : gain_step = gain / length;
650 :
651 19008219 : for ( j = 0; j < length; j++ )
652 : {
653 18916080 : s = 0;
654 18916080 : s2 = 0;
655 :
656 147285120 : for ( i = 0, k = 0; i < L; i++, k += pitch_res )
657 : {
658 128369040 : s += w0[k] * x0[i] + w1[k] * x1[-i];
659 128369040 : s2 += v0[k] * y0[i] + v1[k] * y1[-i];
660 : }
661 :
662 18916080 : out[j] = in[j] - curr_gain * s2 * ALPHA + curr_gain * s;
663 :
664 18916080 : x0++;
665 18916080 : x1++;
666 18916080 : y0++;
667 18916080 : y1++;
668 :
669 18916080 : curr_gain += gain_step;
670 : }
671 :
672 92139 : 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 372111 : 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 372111 : x0 = &out[-prev_pitch_int];
719 372111 : x1 = x0 - 1;
720 372111 : y0 = in;
721 372111 : y1 = y0 - 1;
722 :
723 372111 : assert( filtIdx >= 0 && prev_filtIdx >= 0 );
724 :
725 372111 : w0 = &tcxLtpFilters[prev_filtIdx].filt[prev_pitch_fr];
726 372111 : w1 = &tcxLtpFilters[prev_filtIdx].filt[prev_pitch_res - prev_pitch_fr];
727 372111 : v0 = &tcxLtpFilters[prev_filtIdx].filt[0];
728 372111 : v1 = &tcxLtpFilters[prev_filtIdx].filt[prev_pitch_res];
729 :
730 372111 : prev_L = tcxLtpFilters[prev_filtIdx].length;
731 :
732 372111 : p0 = &tcxLtpFilters[filtIdx].filt[cur_pitch_fr];
733 372111 : p1 = &tcxLtpFilters[filtIdx].filt[pitch_res - cur_pitch_fr];
734 372111 : q0 = &tcxLtpFilters[filtIdx].filt[0];
735 372111 : q1 = &tcxLtpFilters[filtIdx].filt[pitch_res];
736 :
737 372111 : 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 372111 : gain = prev_gain;
741 372111 : gain_step = -prev_gain / length;
742 :
743 76621071 : for ( j = 0; j < length; j++ )
744 : {
745 76248960 : s = 0;
746 76248960 : s2 = 0;
747 :
748 597953520 : for ( i = 0, k = 0; i < prev_L; i++, k += prev_pitch_res )
749 : {
750 521704560 : s += w0[k] * x0[i] + w1[k] * x1[-i];
751 521704560 : s2 += v0[k] * y0[i] + v1[k] * y1[-i];
752 : }
753 :
754 76248960 : out[j] = in[j] - gain * s2 * ALPHA + gain * s;
755 :
756 76248960 : x0++;
757 76248960 : x1++;
758 76248960 : y0++;
759 76248960 : y1++;
760 :
761 76248960 : gain += gain_step;
762 : }
763 :
764 372111 : mvr2r( out - L, temp_buf, length + L );
765 372111 : mvr2r( in + length, temp_buf + length + L, L );
766 372111 : temp_ptr = &temp_buf[0] + L;
767 :
768 372111 : m0 = temp_ptr;
769 372111 : m1 = temp_ptr - 1;
770 372111 : l0 = &out[-cur_pitch_int];
771 372111 : 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 372111 : gain = 0.0f;
775 372111 : gain_step = cur_gain / length;
776 :
777 76621071 : for ( j = 0; j < length; j++ )
778 : {
779 76248960 : s3 = 0;
780 76248960 : s4 = 0;
781 :
782 597947280 : for ( i = 0, k = 0; i < L; i++, k += pitch_res )
783 : {
784 521698320 : s3 += p0[k] * l0[i] + p1[k] * l1[-i];
785 521698320 : s4 += q0[k] * m0[i] + q1[k] * m1[-i];
786 : }
787 :
788 76248960 : out[j] = *( temp_ptr + j ) - gain * s4 * ALPHA + gain * s3;
789 :
790 76248960 : l0++;
791 76248960 : l1++;
792 76248960 : m0++;
793 76248960 : m1++;
794 :
795 76248960 : gain += gain_step;
796 : }
797 :
798 372111 : return;
799 : }
800 :
801 :
802 : /*-------------------------------------------------------------------
803 : * tcx_ltp_post()
804 : *
805 : *
806 : *-------------------------------------------------------------------*/
807 :
808 3509325 : 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 3509325 : total_brate = ( st->element_mode == IVAS_CPE_MDCT ? st->bits_frame_nominal * FRAMES_PER_SEC : st->total_brate );
828 3509325 : filtIdx = 0; /* just to avoid compilation warnings */
829 3509325 : tcx_buf_len = NS2SA( st->output_Fs, TCXLTP_DELAY_NS );
830 3509325 : SideInfoOnly = 0;
831 :
832 3509325 : if ( total_brate >= HQ_96k )
833 : {
834 1247499 : SideInfoOnly = 1;
835 : }
836 :
837 3509325 : L_frame_core = st->L_frame;
838 3509325 : if ( st->element_mode == IVAS_CPE_MDCT )
839 : {
840 2141520 : L_frame_core = L_FRAME;
841 : }
842 :
843 3509325 : if ( core == ACELP_CORE )
844 : {
845 667896 : bfi = 0;
846 667896 : pitch_int = 0;
847 667896 : pitch_fr = 0;
848 667896 : gain = 0.0f;
849 :
850 667896 : L_frame_core = st->L_frame_past;
851 : }
852 : else
853 : {
854 2841429 : bfi = st->bfi;
855 2841429 : pitch_int = hTcxLtpDec->tcxltp_pitch_int;
856 2841429 : pitch_fr = hTcxLtpDec->tcxltp_pitch_fr;
857 2841429 : gain = hTcxLtpDec->tcxltp_gain;
858 : }
859 :
860 : /******** Init ********/
861 :
862 : /* Parameters */
863 3509325 : L_transition = output_frame / 4;
864 3509325 : lpcorder = TCXLTP_LTP_ORDER;
865 :
866 :
867 : /* Input buffer */
868 3509325 : sig_in = buf_in + tcx_buf_len;
869 3509325 : mvr2r( hTcxLtpDec->tcxltp_mem_in, buf_in, tcx_buf_len );
870 3509325 : mvr2r( sig, buf_in + tcx_buf_len, output_frame );
871 3509325 : if ( core > ACELP_CORE )
872 : {
873 2841429 : mvr2r( tcx_buf, sig_in + output_frame, tcx_buf_len );
874 : }
875 3509325 : mvr2r( sig + output_frame - tcx_buf_len, hTcxLtpDec->tcxltp_mem_in, tcx_buf_len );
876 :
877 : /* Output buffer */
878 3509325 : sig_out = buf_out + output_frame;
879 3509325 : mvr2r( hTcxLtpDec->tcxltp_mem_out, buf_out, output_frame );
880 :
881 : /* TCX-LTP parameters: integer pitch, fractional pitch, gain */
882 :
883 3509325 : if ( !( SideInfoOnly || hTcxLtpDec->tcxltp ) || core == ACELP_CORE )
884 : {
885 : /* No LTP */
886 1562130 : pitch_int = 0;
887 1562130 : pitch_fr = 0;
888 1562130 : gain = 0.f;
889 : }
890 1947195 : else if ( !bfi )
891 : {
892 : /* LTP and good frame */
893 1929189 : if ( output_frame != L_frame_core )
894 : {
895 1902783 : tmp = pitch_int * st->pit_res_max + pitch_fr;
896 1902783 : tmp = ( tmp * output_frame + L_frame_core / 2 ) / L_frame_core;
897 1902783 : pitch_int = tmp / st->pit_res_max;
898 1902783 : pitch_fr = tmp % st->pit_res_max;
899 : }
900 :
901 1929189 : if ( st->element_mode == EVS_MONO ) /* hard tunings for EVS_MONO, HQ_48k is TCX only */
902 : {
903 1938 : if ( total_brate == HQ_48k && L_frame_core == L_FRAME16k )
904 : {
905 0 : gain *= 0.32f;
906 : }
907 1938 : else if ( total_brate == HQ_48k && L_frame_core == 512 )
908 : {
909 0 : gain *= 0.40f;
910 : }
911 : else
912 : {
913 1938 : gain *= 0.64f;
914 : }
915 : }
916 1927251 : else if ( ( st->element_mode > IVAS_SCE ) && ( total_brate >= IVAS_96k ) )
917 : {
918 1178454 : gain *= 0.40f;
919 : }
920 : else
921 : {
922 748797 : gain *= 0.64f;
923 : }
924 : }
925 : else
926 : {
927 : /* PLC: [TCX: Fade-out]
928 : * PLC: LTP and bad frame (concealment) */
929 18006 : if ( st->pit_res_max == st->pit_res_max_past ) /* ensure consistent core SR to previous frame; otherwise, set gain to 0 */
930 : {
931 18006 : pitch_int = hTcxLtpDec->tcxltp_pitch_int_post_prev;
932 18006 : pitch_fr = hTcxLtpDec->tcxltp_pitch_fr_post_prev;
933 18006 : gain = hTcxLtpDec->tcxltp_gain_post_prev * st->hTcxDec->damping;
934 : }
935 : else
936 : {
937 0 : gain = 0.f;
938 : }
939 : }
940 :
941 3509325 : if ( SideInfoOnly )
942 : {
943 1247499 : gain = 0.f;
944 1247499 : if ( bfi )
945 : {
946 10881 : hTcxLtpDec->tcxltp_gain_post_prev = 0.f;
947 : }
948 : }
949 3509325 : gain2 = gain;
950 :
951 3509325 : if ( L_frame_core == L_FRAME )
952 : {
953 2518617 : switch ( output_frame )
954 : {
955 0 : case L_FRAME8k:
956 0 : filtIdx = 0;
957 0 : break;
958 236220 : case L_FRAME16k:
959 236220 : filtIdx = 1;
960 236220 : break;
961 555222 : case L_FRAME32k:
962 555222 : filtIdx = 2;
963 555222 : break;
964 1727175 : case L_FRAME48k:
965 1727175 : filtIdx = 3;
966 1727175 : break;
967 0 : default:
968 0 : assert( 0 );
969 : break;
970 : }
971 : }
972 990708 : else if ( L_frame_core == L_FRAME16k )
973 : {
974 575235 : switch ( output_frame )
975 : {
976 0 : case L_FRAME8k:
977 0 : filtIdx = 4;
978 0 : break;
979 61392 : case L_FRAME16k:
980 61392 : filtIdx = 5;
981 61392 : break;
982 141876 : case L_FRAME32k:
983 141876 : filtIdx = 6;
984 141876 : break;
985 371967 : case L_FRAME48k:
986 371967 : filtIdx = 7;
987 371967 : break;
988 0 : default:
989 0 : assert( 0 );
990 : break;
991 : }
992 : }
993 415473 : else if ( L_frame_core == 512 )
994 : {
995 45981 : switch ( output_frame )
996 : {
997 0 : case L_FRAME8k:
998 0 : filtIdx = 8;
999 0 : break;
1000 405 : case L_FRAME16k:
1001 405 : filtIdx = 9;
1002 405 : break;
1003 9957 : case L_FRAME32k:
1004 9957 : filtIdx = 10;
1005 9957 : break;
1006 35619 : case L_FRAME48k:
1007 35619 : filtIdx = 11;
1008 35619 : break;
1009 0 : default:
1010 0 : assert( 0 );
1011 : break;
1012 : }
1013 : }
1014 : else
1015 : {
1016 369492 : filtIdx = -1;
1017 : }
1018 :
1019 :
1020 : /******** Previous-frame part ********/
1021 3509325 : 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 3509325 : if ( st->element_mode != EVS_MONO )
1026 : {
1027 3500025 : if ( gain == 0.f && hTcxLtpDec->tcxltp_gain_post_prev == 0.f )
1028 : {
1029 : /* The filtering is deactivated, just copy input to the output */
1030 2873286 : mvr2r( sig_in + delay, sig_out + delay, L_transition );
1031 : }
1032 626739 : else if ( gain == 0.f && hTcxLtpDec->tcxltp_gain_post_prev != 0.f )
1033 : {
1034 : /* Filtering with the first filter unit */
1035 88482 : 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 538257 : else if ( gain != 0.f && hTcxLtpDec->tcxltp_gain_post_prev == 0.f )
1038 : {
1039 : /* Filtering with the second filter unit */
1040 92139 : 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 446118 : 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 74007 : 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 372111 : 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 372111 : 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 9300 : if ( gain == 0.f && hTcxLtpDec->tcxltp_gain_post_prev == 0.f )
1056 : {
1057 7635 : mvr2r( sig_in + delay, sig_out + delay, L_transition );
1058 : }
1059 1665 : else if ( hTcxLtpDec->tcxltp_gain_post_prev == 0.f )
1060 : {
1061 258 : 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 1407 : else if ( gain == 0.f )
1064 : {
1065 258 : 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 1149 : 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 363 : 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 786 : tcx_ltp_get_lpc( sig_out + delay - output_frame, output_frame, A, lpcorder );
1075 786 : 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 786 : 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 3509325 : 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 3509325 : mvr2r( sig_out, sig, output_frame );
1088 :
1089 : /* Update */
1090 3509325 : hTcxLtpDec->tcxltp_pitch_int_post_prev = pitch_int;
1091 3509325 : hTcxLtpDec->tcxltp_pitch_fr_post_prev = pitch_fr;
1092 3509325 : hTcxLtpDec->tcxltp_gain_post_prev = gain2;
1093 3509325 : hTcxLtpDec->tcxltp_filt_idx_prev = filtIdx;
1094 3509325 : st->pit_res_max_past = st->pit_res_max;
1095 3509325 : mvr2r( sig_out, hTcxLtpDec->tcxltp_mem_out, output_frame );
1096 :
1097 3509325 : return;
1098 : }
|