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 <math.h>
44 : #include "cnst.h"
45 : #include "rom_com.h"
46 : #include "prot.h"
47 : #include "wmc_auto.h"
48 :
49 : /*-------------------------------------------------------------------*
50 : * tcx_get_windows()
51 : *
52 : *
53 : *-------------------------------------------------------------------*/
54 287491 : void tcx_get_windows(
55 : TCX_CONFIG_HANDLE hTcxCfg, /* i : TCX configuration */
56 : const int16_t left_mode, /* i : overlap mode of left window half */
57 : const int16_t right_mode, /* i : overlap mode of right window half */
58 : int16_t *left_overlap, /* o : left overlap length */
59 : const float **left_win, /* o : left overlap window */
60 : int16_t *right_overlap, /* o : right overlap length */
61 : const float **right_win, /* o : right overlap window */
62 : const int16_t fullband /* i : fullband flag */
63 : )
64 : {
65 287491 : if ( !fullband )
66 : {
67 : /* Left part */
68 :
69 54649 : if ( left_mode == TRANSITION_OVERLAP )
70 : {
71 : /* ACELP->TCX transition */
72 187 : *left_overlap = hTcxCfg->tcx_mdct_window_trans_length;
73 187 : *left_win = hTcxCfg->tcx_mdct_window_trans;
74 : }
75 54462 : else if ( left_mode == MIN_OVERLAP )
76 : {
77 1133 : *left_overlap = hTcxCfg->tcx_mdct_window_min_length;
78 1133 : *left_win = hTcxCfg->tcx_mdct_window_minimum;
79 : }
80 53329 : else if ( left_mode == HALF_OVERLAP )
81 : {
82 884 : *left_overlap = hTcxCfg->tcx_mdct_window_half_length;
83 884 : *left_win = hTcxCfg->tcx_mdct_window_half;
84 : }
85 52445 : else if ( left_mode == FULL_OVERLAP )
86 : {
87 52445 : *left_overlap = hTcxCfg->tcx_mdct_window_length;
88 52445 : *left_win = hTcxCfg->tcx_aldo_window_1_trunc;
89 : }
90 : else
91 : {
92 0 : assert( !"Not supported overlap" );
93 : }
94 :
95 : /* Right part */
96 :
97 54649 : if ( right_mode == MIN_OVERLAP )
98 : {
99 1138 : *right_overlap = hTcxCfg->tcx_mdct_window_min_length;
100 1138 : *right_win = hTcxCfg->tcx_mdct_window_minimum;
101 : }
102 53511 : else if ( right_mode == HALF_OVERLAP )
103 : {
104 886 : *right_overlap = hTcxCfg->tcx_mdct_window_half_length;
105 886 : *right_win = hTcxCfg->tcx_mdct_window_half;
106 : }
107 52625 : else if ( right_mode == FULL_OVERLAP )
108 : {
109 52625 : *right_overlap = hTcxCfg->tcx_mdct_window_delay;
110 52625 : *right_win = hTcxCfg->tcx_aldo_window_2;
111 : }
112 : else
113 : {
114 0 : assert( !"Not supported overlap" );
115 : }
116 : }
117 : else
118 : {
119 : /* Left part */
120 :
121 232842 : if ( left_mode == TRANSITION_OVERLAP )
122 : {
123 : /* ACELP->TCX transition */
124 6826 : *left_overlap = hTcxCfg->tcx_mdct_window_trans_lengthFB;
125 6826 : *left_win = hTcxCfg->tcx_mdct_window_transFB;
126 : }
127 226016 : else if ( left_mode == MIN_OVERLAP )
128 : {
129 37296 : *left_overlap = hTcxCfg->tcx_mdct_window_min_lengthFB;
130 37296 : *left_win = hTcxCfg->tcx_mdct_window_minimumFB;
131 : }
132 188720 : else if ( left_mode == HALF_OVERLAP )
133 : {
134 8874 : *left_overlap = hTcxCfg->tcx_mdct_window_half_lengthFB;
135 8874 : *left_win = hTcxCfg->tcx_mdct_window_halfFB;
136 : }
137 179846 : else if ( left_mode == RECTANGULAR_OVERLAP )
138 : {
139 20765 : *left_overlap = 0;
140 20765 : *left_win = NULL;
141 : }
142 159081 : else if ( left_mode == FULL_OVERLAP )
143 : {
144 159081 : *left_overlap = hTcxCfg->tcx_mdct_window_lengthFB;
145 159081 : *left_win = hTcxCfg->tcx_aldo_window_1_FB_trunc;
146 : }
147 : else
148 : {
149 0 : assert( !"Not supported overlap" );
150 : }
151 :
152 : /* Right part */
153 :
154 232842 : if ( right_mode == MIN_OVERLAP )
155 : {
156 39272 : *right_overlap = hTcxCfg->tcx_mdct_window_min_lengthFB;
157 39272 : *right_win = hTcxCfg->tcx_mdct_window_minimumFB;
158 : }
159 193570 : else if ( right_mode == HALF_OVERLAP )
160 : {
161 9303 : *right_overlap = hTcxCfg->tcx_mdct_window_half_lengthFB;
162 9303 : *right_win = hTcxCfg->tcx_mdct_window_halfFB;
163 : }
164 184267 : else if ( right_mode == RECTANGULAR_OVERLAP )
165 : {
166 20749 : *right_overlap = 0;
167 20749 : *right_win = NULL;
168 : }
169 163518 : else if ( right_mode == FULL_OVERLAP )
170 : {
171 163518 : *right_overlap = hTcxCfg->tcx_mdct_window_delayFB;
172 163518 : *right_win = hTcxCfg->tcx_aldo_window_2_FB;
173 : }
174 : else
175 : {
176 0 : assert( !"Not supported overlap" );
177 : }
178 : }
179 :
180 287491 : return;
181 : }
182 :
183 : /*-------------------------------------------------------------------*
184 : * tcx_windowing_analysis()
185 : *
186 : *
187 : *-------------------------------------------------------------------*/
188 :
189 287465 : void tcx_windowing_analysis(
190 : const float *signal, /* i : signal vector */
191 : const int16_t L_frame, /* i : frame length */
192 : const int16_t left_overlap, /* i : left overlap length */
193 : const float *left_win, /* i : left overlap window */
194 : const int16_t right_overlap, /* i : right overlap length */
195 : const float *right_win, /* i : right overlap window */
196 : float *output /* o : windowed signal vector */
197 : )
198 : {
199 : int16_t w;
200 :
201 : /* Left overlap */
202 82101269 : for ( w = 0; w < left_overlap; w++ )
203 : {
204 81813804 : *output++ = *signal++ * left_win[w];
205 : }
206 :
207 : /* Non overlapping region */
208 117278745 : for ( w = 0; w < L_frame - ( left_overlap + right_overlap ) / 2; w++ )
209 : {
210 116991280 : *output++ = *signal++;
211 : }
212 :
213 : /* Right overlap */
214 83736413 : for ( w = 0; w < right_overlap; w++ )
215 : {
216 83448948 : *output++ = *signal++ * right_win[right_overlap - 1 - w];
217 : }
218 :
219 287465 : return;
220 : }
221 :
222 :
223 : /*-------------------------------------------------------------------*
224 : * WindowSignal()
225 : *
226 : *
227 : *-------------------------------------------------------------------*/
228 :
229 287465 : void WindowSignal(
230 : TCX_CONFIG_HANDLE hTcxCfg, /* i : configuration of TCX */
231 : int16_t offset, /* i : left folding point offset relative to the input signal pointer */
232 : const int16_t left_overlap_mode, /* i : overlap mode of left window half */
233 : const int16_t right_overlap_mode, /* i : overlap mode of right window half */
234 : int16_t *left_overlap_length, /* o : TCX window left overlap length */
235 : int16_t *right_overlap_length, /* o : TCX window right overlap length */
236 : const float in[], /* i : input signal */
237 : int16_t *L_frame, /* i/o: frame length */
238 : float out[], /* o : output windowed signal */
239 : const int16_t truncate_aldo, /* i : nonzero to truncate long ALDO slope */
240 : const int16_t fullband /* i : fullband flag */
241 : )
242 : {
243 : int16_t l, r;
244 : const float *left_win;
245 : const float *right_win;
246 :
247 : /*-----------------------------------------------------------*
248 : * Init *
249 : *-----------------------------------------------------------*/
250 :
251 287465 : tcx_get_windows( hTcxCfg, left_overlap_mode, right_overlap_mode, &l, &left_win, &r, &right_win, fullband );
252 :
253 : /* Init lengths */
254 :
255 : /* if past frame is ACELP */
256 287465 : if ( left_overlap_mode == TRANSITION_OVERLAP )
257 : {
258 : /* Increase frame size for 5ms */
259 7013 : if ( !fullband )
260 : {
261 187 : *L_frame += hTcxCfg->tcx5Size;
262 187 : offset = -hTcxCfg->tcx_mdct_window_trans_length / 2;
263 : }
264 : else
265 : {
266 6826 : *L_frame += hTcxCfg->tcx5SizeFB;
267 6826 : offset = -hTcxCfg->tcx_mdct_window_trans_lengthFB / 2;
268 : }
269 : }
270 :
271 : /*-----------------------------------------------------------*
272 : * Windowing *
273 : *-----------------------------------------------------------*/
274 :
275 287465 : tcx_windowing_analysis( in - l / 2 + offset, *L_frame, l, left_win, r, right_win, out );
276 :
277 287465 : if ( left_overlap_mode == FULL_OVERLAP && truncate_aldo )
278 : {
279 : /* fade truncated ALDO window to avoid discontinuities */
280 196476 : if ( !fullband )
281 : {
282 52445 : v_mult( out, hTcxCfg->tcx_mdct_window_minimum, out, hTcxCfg->tcx_mdct_window_min_length );
283 : }
284 : else
285 : {
286 144031 : v_mult( out, hTcxCfg->tcx_mdct_window_minimumFB, out, hTcxCfg->tcx_mdct_window_min_lengthFB );
287 : }
288 : }
289 :
290 287465 : *left_overlap_length = l;
291 287465 : *right_overlap_length = r;
292 :
293 287465 : return;
294 : }
295 :
296 :
297 : /*-------------------------------------------------------------------*
298 : * tcx_windowing_synthesis_current_frame()
299 : *
300 : *
301 : *-------------------------------------------------------------------*/
302 :
303 193065 : void tcx_windowing_synthesis_current_frame(
304 : float *signal, /* i/o: signal vector */
305 : const float *window, /* i : TCX window vector */
306 : const float *window_half, /* i : TCX window vector for half-overlap window */
307 : const float *window_min, /* i : TCX minimum overlap window */
308 : const int16_t window_length, /* i : TCX window length */
309 : const int16_t window_half_length, /* i : TCX half window length */
310 : const int16_t window_min_length, /* i : TCX minimum overlap length */
311 : const int16_t left_rect, /* i : left part is rectangular */
312 : const int16_t left_mode, /* i : overlap mode of left window half */
313 : float *acelp_zir, /* i/o: acelp ZIR */
314 : const float *old_syn, /* i : old synthesis */
315 : const float *syn_overl, /* i : overlap synthesis */
316 : const float *A_zir,
317 : const float *window_trans,
318 : int16_t acelp_zir_len,
319 : const int16_t acelp_mem_len,
320 : const int16_t last_core_bfi, /* i : last mode */
321 : const int16_t last_is_cng,
322 : const int16_t fullbandScale )
323 : {
324 : int16_t i, w, overlap;
325 : float tmp[L_FRAME_MAX / 2];
326 :
327 : /* Init */
328 193065 : overlap = window_length >> 1;
329 :
330 : /* Past-frame is TCX concealed as CNG and current-frame is TCX */
331 193065 : if ( last_is_cng == 1 && left_rect == 0 )
332 : {
333 0 : if ( !fullbandScale )
334 : {
335 0 : set_zero( acelp_zir, acelp_zir_len );
336 0 : syn_filt( A_zir, M, acelp_zir, acelp_zir, acelp_zir_len, signal + overlap + acelp_mem_len - M, 0 );
337 : }
338 : else
339 : {
340 0 : lerp( acelp_zir, tmp, acelp_zir_len, acelp_zir_len * FSCALE_DENOM / fullbandScale );
341 0 : acelp_zir = tmp;
342 : }
343 :
344 0 : for ( i = 0; i < acelp_zir_len; i++ )
345 : {
346 0 : signal[i] *= (float) ( i ) / (float) ( acelp_zir_len );
347 0 : signal[i] += acelp_zir[i] * (float) ( acelp_zir_len - i ) / (float) ( acelp_zir_len );
348 : }
349 : }
350 193065 : else if ( left_rect == 1 && last_core_bfi == ACELP_CORE ) /* Rectangular window (past-frame is ACELP) */
351 : {
352 2798084 : for ( i = 0; i < overlap - acelp_mem_len; i++ )
353 : {
354 2770920 : signal[i] = 0;
355 : }
356 :
357 27164 : if ( fullbandScale == 0 )
358 : {
359 : /*OLA with ACELP*/
360 345372 : for ( i = 0; i < 2 * acelp_mem_len; i++ )
361 : {
362 : /*window decoded TCX with aliasing*/
363 329120 : signal[i + overlap - acelp_mem_len] *= window_trans[i];
364 : /*Time TDAC: 1)forward part of ACELP*/
365 329120 : signal[i + overlap - acelp_mem_len] += old_syn[acelp_zir_len - 2 * acelp_mem_len + i] * window_trans[2 * acelp_mem_len - i - 1] * window_trans[2 * acelp_mem_len - i - 1];
366 :
367 : /*Time TDAC: 1)reward part of ACELP*/
368 329120 : signal[i + overlap - acelp_mem_len] += old_syn[acelp_zir_len - i - 1] * window_trans[i] * window_trans[2 * acelp_mem_len - i - 1];
369 : }
370 :
371 276284 : for ( i = 0; i < M; i++ )
372 : {
373 260032 : signal[overlap + acelp_mem_len - M + i] -= old_syn[acelp_zir_len - M + i];
374 : }
375 : }
376 :
377 : /* ZIR at the end of the ACELP frame */
378 27164 : acelp_zir_len = 64;
379 :
380 27164 : if ( !fullbandScale )
381 : {
382 16252 : set_zero( acelp_zir, acelp_zir_len );
383 16252 : syn_filt( A_zir, M, acelp_zir, acelp_zir, acelp_zir_len, signal + overlap + acelp_mem_len - M, 0 );
384 : }
385 : else
386 : {
387 10912 : lerp( acelp_zir, tmp, acelp_zir_len * fullbandScale / FSCALE_DENOM, acelp_zir_len );
388 10912 : acelp_zir_len = acelp_zir_len * fullbandScale / FSCALE_DENOM;
389 10912 : acelp_zir = tmp;
390 :
391 10912 : if ( acelp_zir_len >= 2.0f * 64 )
392 : {
393 : /* apply a simple low-pass to the ZIR, to avoid potentially unmasked HF content */
394 1721901 : for ( i = 2; i < acelp_zir_len; i++ )
395 : {
396 1713274 : acelp_zir[i] = 0.25f * acelp_zir[i - 2] + 0.35f * acelp_zir[i - 1] + 0.40f * acelp_zir[i];
397 : }
398 8627 : acelp_zir[acelp_zir_len - 1] = 0.40f * acelp_zir[acelp_zir_len - 1] + 0.35f * acelp_zir[acelp_zir_len - 1] + 0.25f * acelp_zir[acelp_zir_len - 2];
399 8627 : acelp_zir[acelp_zir_len - 2] = 0.40f * acelp_zir[acelp_zir_len - 2] + 0.35f * acelp_zir[acelp_zir_len - 1] + 0.25f * acelp_zir[acelp_zir_len - 1];
400 1721901 : for ( i = acelp_zir_len - 3; i >= 0; i-- )
401 : {
402 1713274 : acelp_zir[i] = 0.40f * acelp_zir[i] + 0.35f * acelp_zir[i + 1] + 0.25f * acelp_zir[i + 2];
403 : }
404 : }
405 : }
406 :
407 3011588 : for ( i = 0; i < acelp_zir_len; i++ )
408 : {
409 : /*remove reconstructed ZIR and add ACELP ZIR*/
410 2984424 : signal[i + overlap + acelp_mem_len] -= acelp_zir[i] * (float) ( acelp_zir_len - i ) / (float) acelp_zir_len;
411 : }
412 : }
413 165901 : else if ( left_rect == 1 && last_core_bfi != 0 ) /* Rectangular window (past-frame is TCX) */
414 : {
415 101654 : for ( i = 0; i < overlap + acelp_mem_len; i++ )
416 : {
417 100944 : signal[i] = 0;
418 : }
419 177362 : for ( i = 0; i < window_length; i++ )
420 : {
421 176652 : signal[i + overlap + acelp_mem_len] *= window[i];
422 : }
423 : }
424 165191 : else if ( left_rect != 1 && last_core_bfi == 0 ) /* Normal window (past-frame is ACELP) */
425 : {
426 23744 : for ( i = 0; i < window_length; i++ )
427 : {
428 23660 : signal[i] *= window[i];
429 : }
430 :
431 23744 : for ( i = 0; i < window_length; i++ )
432 : {
433 23660 : signal[i] += syn_overl[i];
434 : }
435 : }
436 : else /* Normal window (past-frame is TCX) */
437 : {
438 165107 : if ( left_mode == 2 )
439 : {
440 : /* min. overlap */
441 4816966 : for ( i = 0; i < ( window_length - window_min_length ) / 2; i++ )
442 : {
443 4720632 : signal[i] = 0.0f;
444 : }
445 4383174 : for ( w = 0; w < window_min_length; i++, w++ )
446 : {
447 4286840 : signal[i] *= window_min[w];
448 : }
449 : }
450 68773 : else if ( left_mode == 3 )
451 : {
452 : /* half OL */
453 585219 : for ( i = 0; i < ( window_length - window_half_length ) / 2; i++ )
454 : {
455 560248 : signal[i] = 0.0f;
456 : }
457 3363503 : for ( w = 0; w < window_half_length; i++, w++ )
458 : {
459 3338532 : signal[i] *= window_half[w];
460 : }
461 : }
462 : else
463 : {
464 : /* normal full/maximum overlap */
465 13801322 : for ( i = 0; i < window_length; i++ )
466 : {
467 13757520 : signal[i] *= window[i];
468 : }
469 : }
470 : }
471 :
472 193065 : return;
473 : }
474 :
475 :
476 : /*-------------------------------------------------------------------*
477 : * tcx_windowing_synthesis_past_frame()
478 : *
479 : *
480 : *-------------------------------------------------------------------*/
481 :
482 195054 : void tcx_windowing_synthesis_past_frame(
483 : float *signal, /* i/o: signal vector */
484 : const float *window, /* i : TCX window vector */
485 : const float *window_half, /* i : TCX window vector for half-overlap window */
486 : const float *window_min, /* i : TCX minimum overlap window */
487 : const int16_t window_length, /* i : TCX window length */
488 : const int16_t window_half_length, /* i : TCX half window length */
489 : const int16_t window_min_length, /* i : TCX minimum overlap length */
490 : const int16_t right_mode /* i : overlap mode (left_mode of current frame) */
491 : )
492 : {
493 : int16_t i, w;
494 :
495 195054 : if ( right_mode == MIN_OVERLAP )
496 : {
497 : /* min. overlap */
498 4639693 : for ( i = ( window_length - window_min_length ) / 2, w = 0; w < window_min_length; i++, w++ )
499 : {
500 4537900 : signal[i] *= window_min[window_min_length - 1 - w];
501 : }
502 7051985 : for ( ; i < window_length; i++ )
503 : {
504 6950192 : signal[i] = 0.0f;
505 : }
506 : }
507 93261 : else if ( right_mode == HALF_OVERLAP )
508 : {
509 : /* half OL */
510 3978072 : for ( i = ( window_length - window_half_length ) / 2, w = 0; w < window_half_length; i++, w++ )
511 : {
512 3948420 : signal[i] *= window_half[window_half_length - 1 - w];
513 : }
514 2661932 : for ( ; i < window_length; i++ )
515 : {
516 2632280 : signal[i] = 0.0f;
517 : }
518 : }
519 63609 : else if ( right_mode == FULL_OVERLAP )
520 : {
521 : /* normal full/maximum overlap */
522 17893253 : for ( i = 0; i < window_length; i++ )
523 : {
524 17829644 : signal[i] *= window[window_length - 1 - i];
525 : }
526 : }
527 :
528 195054 : return;
529 : }
530 :
531 :
532 : /*-------------------------------------------------------------------*
533 : * lpc2mdct()
534 : *
535 : *
536 : *-------------------------------------------------------------------*/
537 :
538 649988 : void lpc2mdct(
539 : float *lpcCoeffs,
540 : const int16_t lpcOrder,
541 : float mdct_gains[],
542 : const int16_t length,
543 : const int16_t noInverse )
544 : {
545 : float RealData[2 * FDNS_NPTS], ImagData[2 * FDNS_NPTS];
546 : float tmp;
547 : int16_t i, sizeN;
548 :
549 649988 : assert( length <= FDNS_NPTS );
550 :
551 649988 : sizeN = 2 * length;
552 :
553 : /* ODFT */
554 11699784 : for ( i = 0; i < lpcOrder + 1; i++ )
555 : {
556 11049796 : tmp = (float) ( ( (float) i ) * EVS_PI / (float) ( sizeN ) );
557 11049796 : RealData[i] = (float) ( lpcCoeffs[i] * cos( tmp ) );
558 11049796 : ImagData[i] = (float) ( -lpcCoeffs[i] * sin( tmp ) );
559 : }
560 :
561 72798656 : for ( ; i < sizeN; i++ )
562 : {
563 72148668 : RealData[i] = 0.f;
564 72148668 : ImagData[i] = 0.f;
565 : }
566 :
567 649988 : DoFFT( RealData, ImagData, sizeN );
568 :
569 649988 : if ( noInverse )
570 : {
571 0 : assert( !"not supported option in lpc2mdct()" );
572 : }
573 : else
574 : {
575 : /* Get amplitude */
576 42249220 : for ( i = 0; i < length; i++ )
577 : {
578 41599232 : mdct_gains[i] = (float) ( 1.0f / max( EPSILON, sqrt( RealData[i] * RealData[i] + ImagData[i] * ImagData[i] ) ) );
579 : }
580 : }
581 :
582 649988 : return;
583 : }
584 :
585 :
586 : /*-------------------------------------------------------------------*
587 : * mdct_noiseShaping()
588 : *
589 : *
590 : *-------------------------------------------------------------------*/
591 :
592 642302 : void mdct_noiseShaping(
593 : float x[],
594 : const int16_t lg,
595 : const float gains[],
596 : const int16_t nBands )
597 : {
598 : int16_t i, j, k, l;
599 : float g;
600 : int16_t m, n, k1, k2;
601 :
602 642302 : j = 0;
603 642302 : assert( nBands != 0 );
604 642302 : k = lg / nBands;
605 642302 : m = lg % nBands;
606 :
607 642302 : if ( m )
608 : {
609 8269 : if ( m <= ( FDNS_NPTS / 2 ) )
610 : {
611 8269 : n = FDNS_NPTS / m;
612 8269 : k1 = k;
613 8269 : k2 = k + 1;
614 : }
615 : else
616 : {
617 0 : n = FDNS_NPTS / ( FDNS_NPTS - m );
618 0 : k1 = k + 1;
619 0 : k2 = k;
620 : }
621 :
622 537485 : for ( i = 0; i < lg; )
623 : {
624 529216 : if ( j % n )
625 : {
626 389760 : k = k1;
627 : }
628 : else
629 : {
630 139456 : k = k2;
631 : }
632 529216 : g = gains[j++];
633 :
634 : /* Limit number of loops, if end is reached */
635 529216 : k = min( k, lg - i );
636 :
637 3979776 : for ( l = 0; l < k; l++ )
638 : {
639 3450560 : x[i++] *= g;
640 : }
641 : }
642 : }
643 : else
644 : {
645 41212145 : for ( i = 0; i < lg; )
646 : {
647 40578112 : g = gains[j++];
648 :
649 286805248 : for ( l = 0; l < k; l++ )
650 : {
651 246227136 : x[i++] *= g;
652 : }
653 : }
654 : }
655 :
656 642302 : return;
657 : }
658 :
659 :
660 : /*-------------------------------------------------------------------*
661 : * PsychAdaptLowFreqDeemph()
662 : *
663 : *
664 : *-------------------------------------------------------------------*/
665 :
666 42719 : void PsychAdaptLowFreqDeemph(
667 : float x[],
668 : const float lpcGains[],
669 : float lf_deemph_factors[] )
670 : {
671 : int16_t i;
672 : float max_val, fac, tmp;
673 :
674 42719 : max_val = tmp = lpcGains[0];
675 :
676 : /* find minimum (tmp) and maximum (max) of LPC gains in low frequencies */
677 384471 : for ( i = 1; i < 9; i++ )
678 : {
679 341752 : if ( tmp > lpcGains[i] )
680 : {
681 255955 : tmp = lpcGains[i];
682 : }
683 341752 : if ( max_val < lpcGains[i] )
684 : {
685 57780 : max_val = lpcGains[i];
686 : }
687 : }
688 :
689 42719 : tmp *= 32.0f;
690 :
691 42719 : if ( ( max_val < tmp ) && ( tmp > FLT_MIN ) )
692 : {
693 42719 : fac = tmp = (float) pow( max_val / tmp, 0.0078125f );
694 :
695 42719 : if ( lf_deemph_factors )
696 : {
697 : /* gradual lowering of lowest 32 bins; DC is lowered by (max/tmp)^1/4 */
698 926211 : for ( i = 31; i >= 0; i-- )
699 : {
700 898144 : x[i] *= fac;
701 898144 : lf_deemph_factors[i] *= fac;
702 898144 : fac *= tmp;
703 : }
704 : }
705 : else
706 : {
707 : /* gradual lowering of lowest 32 bins; DC is lowered by (max/tmp)^1/4 */
708 483516 : for ( i = 31; i >= 0; i-- )
709 : {
710 468864 : x[i] *= fac;
711 468864 : fac *= tmp;
712 : }
713 : }
714 : }
715 :
716 42719 : return;
717 : }
718 :
719 :
720 : /*-------------------------------------------------------------------*
721 : * AdaptLowFreqDeemph()
722 : *
723 : *
724 : *-------------------------------------------------------------------*/
725 :
726 240479 : void AdaptLowFreqDeemph(
727 : float x[],
728 : int16_t tcx_lpc_shaped_ari,
729 : const float lpcGains[],
730 : const int16_t lg,
731 : float lf_deemph_factors[] )
732 : {
733 : int16_t i, i_max_old, i_max;
734 :
735 240479 : if ( !tcx_lpc_shaped_ari )
736 : {
737 : /* 1. find first magnitude maximum in lower quarter of spectrum */
738 212412 : i_max = -1;
739 :
740 1198000 : for ( i = 0; i < lg / 4; i++ )
741 : {
742 1191089 : if ( ( x[i] <= -4.0f ) || ( x[i] >= 4.0f ) )
743 : {
744 205501 : x[i] += ( x[i] < 0.0f ) ? 2.0f : -2.0f;
745 205501 : i_max = i;
746 205501 : break;
747 : }
748 : }
749 : /* 2. expand value range of all xi up to i_max: two extra steps */
750 :
751 677240 : for ( i = 0; i < i_max; i++ )
752 : {
753 464828 : x[i] *= 0.5f;
754 464828 : lf_deemph_factors[i] *= 0.5f;
755 : }
756 : /* 3. find first magnitude maximum in lower quarter of spectrum */
757 212412 : i_max_old = i_max;
758 :
759 212412 : if ( i_max_old > -1 )
760 : {
761 205501 : i_max = -1;
762 :
763 987402 : for ( i = 0; i < lg / 4; i++ )
764 : {
765 987372 : if ( ( x[i] <= -4.0f ) || ( x[i] >= 4.0f ) )
766 : {
767 205471 : x[i] += ( x[i] < 0.0f ) ? 2.0f : -2.0f;
768 205471 : i_max = i;
769 205471 : break;
770 : }
771 : }
772 : }
773 : /* 4. expand value range of all xi up to i_max: two extra steps */
774 992041 : for ( i = 0; i < i_max; i++ )
775 : {
776 779629 : x[i] *= 0.5f;
777 779629 : lf_deemph_factors[i] *= 0.5f;
778 : }
779 : /* 5. always expand two lines; lines could be at index 0 and 1! */
780 212412 : if ( i_max < i_max_old )
781 : {
782 30 : i_max = i_max_old;
783 : }
784 212412 : i = i_max + 1;
785 212412 : if ( x[i] < 0.0f )
786 : {
787 95519 : if ( x[i] > -4.0f )
788 : {
789 33388 : lf_deemph_factors[i] *= 0.5f;
790 : }
791 95519 : x[i] = ( x[i] <= -4.0f ) ? x[i] + 2.0f : x[i] * 0.5f;
792 : }
793 : else
794 : {
795 116893 : if ( x[i] < 4.0f )
796 : {
797 53590 : lf_deemph_factors[i] *= 0.5f;
798 : }
799 116893 : x[i] = ( x[i] >= 4.0f ) ? x[i] - 2.0f : x[i] * 0.5f;
800 : }
801 212412 : i++;
802 212412 : if ( x[i] < 0.0f )
803 : {
804 91768 : if ( x[i] > -4.0f )
805 : {
806 35118 : lf_deemph_factors[i] *= 0.5f;
807 : }
808 91768 : x[i] = ( x[i] <= -4.0f ) ? x[i] + 2.0f : x[i] * 0.5f;
809 : }
810 : else
811 : {
812 120644 : if ( x[i] < 4.0f )
813 : {
814 64739 : lf_deemph_factors[i] *= 0.5f;
815 : }
816 120644 : x[i] = ( x[i] >= 4.0f ) ? x[i] - 2.0f : x[i] * 0.5f;
817 : }
818 : }
819 : else
820 : {
821 28067 : PsychAdaptLowFreqDeemph( x, lpcGains, lf_deemph_factors );
822 : }
823 :
824 240479 : return;
825 : }
826 :
827 :
828 : /*-------------------------------------------------------------------*
829 : * tcx_noise_filling()
830 : *
831 : *
832 : *-------------------------------------------------------------------*/
833 :
834 1714898 : void tcx_noise_filling(
835 : float *Q,
836 : const int16_t noiseFillSeed,
837 : const int16_t iFirstLine,
838 : const int16_t lowpassLine,
839 : const int16_t nTransWidth,
840 : const int16_t L_frame,
841 : const float tiltCompFactor,
842 : float fac_ns,
843 : uint8_t *infoTCXNoise,
844 : const int16_t element_mode /* i : IVAS element mode */
845 : )
846 : {
847 : int16_t i, m, segmentOffset;
848 : int16_t win; /* window coefficient */
849 : Word16 seed;
850 : float tilt_factor, nrg, tmp1, tmp2;
851 :
852 : /* 16-bit random number generator seed for generating filled lines */
853 1714898 : seed = (Word16) noiseFillSeed;
854 :
855 1714898 : tilt_factor = (float) pow( max( 0.375f, tiltCompFactor ), 1.0f / (float) L_frame );
856 1714898 : fac_ns /= (float) ( nTransWidth * nTransWidth );
857 :
858 : /* find last nonzero line below iFirstLine, use it as start offset */
859 1714898 : i = iFirstLine;
860 :
861 1714898 : if ( element_mode == IVAS_CPE_MDCT ) /* ... but only in mono or parametric stereo since it may cause binaural unmasking in discrete stereo */
862 : {
863 1324806 : segmentOffset = i;
864 : }
865 : else
866 : {
867 1112894 : for ( ; i > ( iFirstLine >> 1 ); i-- )
868 : {
869 1110931 : if ( Q[i] != 0.0f )
870 : {
871 388129 : break;
872 : }
873 : }
874 :
875 390092 : fac_ns *= (float) pow( tilt_factor, (float) i );
876 390092 : segmentOffset = ++i;
877 : }
878 :
879 1714898 : nrg = 1e-9f;
880 1714898 : win = 0;
881 :
882 817291236 : for ( ; i < lowpassLine; i++ )
883 : {
884 815576338 : fac_ns *= tilt_factor;
885 :
886 815576338 : if ( Q[i] != 0.0f )
887 : {
888 191629662 : if ( win > 0 )
889 : {
890 : /* RMS-normalize current noise-filled segment */
891 90139122 : tmp1 = (float) sqrt( ( i - segmentOffset ) / nrg );
892 90139122 : tmp2 = tmp1 * (float) nTransWidth;
893 :
894 224146709 : for ( m = segmentOffset; m < i - win; m++ )
895 : {
896 134007587 : Q[m] *= tmp2;
897 : }
898 :
899 351382788 : for ( ; win > 0; win-- )
900 : {
901 261243666 : Q[m++] *= tmp1 * (float) win;
902 : }
903 90139122 : nrg = 1e-9f; /* start new segment: reset noise segment energy */
904 : }
905 191629662 : segmentOffset = i + 1;
906 : }
907 : else
908 : {
909 : /* line is zero, so fill line and update window and energy */
910 623946676 : if ( win < nTransWidth )
911 : {
912 272450091 : win++;
913 : }
914 623946676 : tmp1 = (float) own_random( &seed );
915 623946676 : nrg += tmp1 * tmp1; /* sum up energy of current noise segment */
916 623946676 : Q[i] = tmp1 * (float) win * fac_ns;
917 :
918 623946676 : if ( infoTCXNoise )
919 : {
920 : /* set noiseflags for IGF */
921 346863644 : infoTCXNoise[i] = 1;
922 : }
923 : }
924 : }
925 :
926 1714898 : if ( win > 0 )
927 : {
928 : /* RMS-normalize uppermost noise-filled segment */
929 1564634 : tmp1 = (float) sqrt( ( lowpassLine - segmentOffset ) / nrg );
930 1564634 : tmp2 = tmp1 * (float) nTransWidth;
931 :
932 230260057 : for ( m = segmentOffset; m < lowpassLine; m++ )
933 : {
934 228695423 : Q[m] *= tmp2;
935 : }
936 : }
937 :
938 1714898 : return;
939 : }
940 :
941 :
942 : /*-------------------------------------------------------------------*
943 : * InitTnsConfigs()
944 : *
945 : *
946 : *-------------------------------------------------------------------*/
947 :
948 48057 : void InitTnsConfigs(
949 : const int16_t bwidth,
950 : const int16_t L_frame,
951 : STnsConfig tnsConfig[2][2],
952 : const int16_t igfStopFreq,
953 : const int32_t total_brate,
954 : const int16_t element_mode,
955 : const int16_t MCT_flag )
956 : {
957 48057 : if ( total_brate > ACELP_32k )
958 : {
959 36420 : InitTnsConfiguration( bwidth, L_frame / 2, &tnsConfig[0][0], igfStopFreq, total_brate, element_mode, MCT_flag );
960 : }
961 :
962 48057 : InitTnsConfiguration( bwidth, L_frame, &tnsConfig[1][0], igfStopFreq, total_brate, element_mode, MCT_flag );
963 :
964 48057 : InitTnsConfiguration( bwidth, L_frame + L_frame / 4, &tnsConfig[1][1], igfStopFreq, total_brate, element_mode, MCT_flag );
965 :
966 48057 : return;
967 : }
968 :
969 :
970 : /*-------------------------------------------------------------------*
971 : * SetAllowTnsOnWhite
972 : *
973 : * set TNS config flag for possible application of TNS in the whitened domain
974 : *-------------------------------------------------------------------*/
975 :
976 48057 : void SetAllowTnsOnWhite(
977 : STnsConfig tnsConfig[2][2], /* o : updated TNS configurations */
978 : const int8_t allowTnsOnWhite /* i : flag for TNS in whiteded domain mode */
979 : )
980 : {
981 48057 : tnsConfig[0][0].allowTnsOnWhite = allowTnsOnWhite;
982 48057 : tnsConfig[0][1].allowTnsOnWhite = allowTnsOnWhite;
983 48057 : tnsConfig[1][0].allowTnsOnWhite = allowTnsOnWhite;
984 48057 : tnsConfig[1][1].allowTnsOnWhite = allowTnsOnWhite;
985 :
986 48057 : return;
987 : }
988 :
989 :
990 : /*-------------------------------------------------------------------*
991 : * SetTnsConfig()
992 : *
993 : *
994 : *-------------------------------------------------------------------*/
995 :
996 2363001 : void SetTnsConfig(
997 : TCX_CONFIG_HANDLE hTcxCfg,
998 : const int16_t isTCX20,
999 : const int16_t isAfterACELP )
1000 : {
1001 2363001 : hTcxCfg->pCurrentTnsConfig = &hTcxCfg->tnsConfig[isTCX20][isAfterACELP];
1002 2363001 : assert( hTcxCfg->pCurrentTnsConfig != NULL );
1003 :
1004 2363001 : return;
1005 : }
|