Line data Source code
1 : /*====================================================================================
2 : EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0
3 : ====================================================================================*/
4 :
5 : #include <stdint.h>
6 : #include <assert.h>
7 : #include "options.h"
8 : #include "prot_fx.h"
9 : #include "rom_com.h"
10 : #include "rom_basop_util.h"
11 : #include "basop_util.h"
12 :
13 : #define inv_int InvIntTable
14 :
15 : /*-------------------------------------------------------------------*
16 : * getInvFrameLen()
17 : *
18 : *
19 : *-------------------------------------------------------------------*/
20 1778209 : Word16 getInvFrameLen( /* returns 1/L_frame in Q21 format */
21 : const Word16 L_frame )
22 : {
23 : Word16 idx, s;
24 :
25 1778209 : s = norm_s( L_frame );
26 1778209 : idx = shl( L_frame, s );
27 :
28 1778209 : assert( ( idx == 0x4000 ) || ( idx == 0x4B00 ) || ( idx == 0x5000 ) || ( idx == 0x5A00 ) || ( idx == 0x6000 ) || ( idx == 0x6400 ) || ( idx == 0x7800 ) );
29 :
30 1778209 : idx = mult_r( idx, 0x10 ); /* idx = shr(add(idx, 0x0400), 11); */
31 1778209 : idx = s_and( idx, 7 );
32 :
33 :
34 1778209 : return shl( L_frame_inv[idx], sub( s, 7 ) );
35 : }
36 : /*-------------------------------------------------------------------*
37 : *tcx_get_windows()
38 : *
39 : *
40 : * ------------------------------------------------------------------ - */
41 2994 : void tcx_get_windows(
42 : TCX_CONFIG_HANDLE hTcxCfg, /* i : TCX configuration */
43 : const Word16 left_mode, /* i: overlap mode of left window half Q0*/
44 : const Word16 right_mode, /* i: overlap mode of right window half Q0*/
45 : Word16 *left_overlap, /* o: left overlap length Q0*/
46 : const PWord16 **left_win, /* o: left overlap window Q15*/
47 : Word16 *right_overlap, /* o: right overlap length Q0*/
48 : const PWord16 **right_win, /* o: right overlap window Q15*/
49 : const Word8 fullband /* i: fullband flag Q0*/
50 : )
51 : { /* LFE is only FULL_OVERLAP*/
52 2994 : IF( fullband == 0 )
53 : {
54 : /* Left part */
55 0 : SWITCH( left_mode )
56 : {
57 0 : case TRANSITION_OVERLAP: /* ACELP->TCX transition */
58 0 : *left_overlap = hTcxCfg->tcx_mdct_window_trans_length; /*Q0*/
59 0 : move16();
60 0 : *left_win = hTcxCfg->tcx_mdct_window_trans; /*Q15*/
61 0 : BREAK;
62 0 : case MIN_OVERLAP:
63 0 : *left_overlap = hTcxCfg->tcx_mdct_window_min_length; /*Q0*/
64 0 : move16();
65 0 : *left_win = hTcxCfg->tcx_mdct_window_minimum; /*Q15*/
66 0 : BREAK;
67 0 : case HALF_OVERLAP:
68 0 : *left_overlap = hTcxCfg->tcx_mdct_window_half_length; /*Q0*/
69 0 : move16();
70 0 : *left_win = hTcxCfg->tcx_mdct_window_half; /*Q15*/
71 0 : BREAK;
72 0 : case FULL_OVERLAP:
73 0 : *left_overlap = hTcxCfg->tcx_mdct_window_length; /*Q0*/
74 0 : move16();
75 0 : *left_win = hTcxCfg->tcx_aldo_window_1_trunc; /*Q15*/
76 0 : BREAK;
77 0 : default:
78 0 : assert( !"Not supported overlap" );
79 : }
80 :
81 : /* Right part */
82 0 : SWITCH( right_mode )
83 : {
84 0 : case MIN_OVERLAP:
85 0 : *right_overlap = hTcxCfg->tcx_mdct_window_min_length; /*Q0*/
86 0 : move16();
87 0 : *right_win = hTcxCfg->tcx_mdct_window_minimum; /*Q15*/
88 0 : BREAK;
89 0 : case HALF_OVERLAP:
90 0 : *right_overlap = hTcxCfg->tcx_mdct_window_half_length; /*Q0*/
91 0 : move16();
92 0 : *right_win = hTcxCfg->tcx_mdct_window_half; /*Q15*/
93 0 : BREAK;
94 0 : case FULL_OVERLAP:
95 0 : *right_overlap = hTcxCfg->tcx_mdct_window_delay; /*Q0*/
96 0 : move16();
97 0 : *right_win = hTcxCfg->tcx_aldo_window_2; /*Q15*/
98 0 : BREAK;
99 0 : default:
100 0 : assert( !"Not supported overlap" );
101 : }
102 : }
103 : ELSE
104 : {
105 : /* Left part */
106 2994 : SWITCH( left_mode )
107 : {
108 0 : case TRANSITION_OVERLAP: /* ACELP->TCX transition */
109 0 : *left_overlap = hTcxCfg->tcx_mdct_window_trans_lengthFB; /*Q0*/
110 0 : move16();
111 0 : *left_win = hTcxCfg->tcx_mdct_window_transFB; /*Q15*/
112 0 : BREAK;
113 0 : case MIN_OVERLAP:
114 0 : *left_overlap = hTcxCfg->tcx_mdct_window_min_lengthFB; /*Q0*/
115 0 : move16();
116 0 : *left_win = hTcxCfg->tcx_mdct_window_minimumFB; /*Q15*/
117 0 : BREAK;
118 0 : case HALF_OVERLAP:
119 0 : *left_overlap = hTcxCfg->tcx_mdct_window_half_lengthFB; /*Q0*/
120 0 : move16();
121 0 : *left_win = hTcxCfg->tcx_mdct_window_halfFB; /*Q15*/
122 0 : BREAK;
123 0 : case RECTANGULAR_OVERLAP:
124 0 : *left_overlap = 0;
125 0 : move16();
126 0 : *left_win = NULL;
127 0 : BREAK;
128 2994 : case FULL_OVERLAP:
129 2994 : *left_overlap = hTcxCfg->tcx_mdct_window_lengthFB; /*Q0*/
130 2994 : move16();
131 2994 : *left_win = hTcxCfg->tcx_aldo_window_1_FB_trunc; /*Q15*/
132 2994 : BREAK;
133 0 : default:
134 0 : assert( !"Not supported overlap" );
135 : }
136 :
137 : /* Right part */
138 2994 : SWITCH( right_mode )
139 : {
140 0 : case MIN_OVERLAP:
141 0 : *right_overlap = hTcxCfg->tcx_mdct_window_min_lengthFB; /*Q0*/
142 0 : move16();
143 0 : *right_win = hTcxCfg->tcx_mdct_window_minimumFB; /*Q15*/
144 0 : BREAK;
145 0 : case HALF_OVERLAP:
146 0 : *right_overlap = hTcxCfg->tcx_mdct_window_half_lengthFB; /*Q0*/
147 0 : move16();
148 0 : *right_win = hTcxCfg->tcx_mdct_window_halfFB; /*Q15*/
149 0 : BREAK;
150 0 : case RECTANGULAR_OVERLAP:
151 0 : *right_overlap = 0;
152 0 : move16();
153 0 : *right_win = NULL;
154 0 : BREAK;
155 2994 : case FULL_OVERLAP:
156 2994 : *right_overlap = hTcxCfg->tcx_mdct_window_delayFB; /*Q0*/
157 2994 : move16();
158 2994 : *right_win = hTcxCfg->tcx_aldo_window_2_FB; /*Q15*/
159 2994 : BREAK;
160 0 : default:
161 0 : assert( !"Not supported overlap" );
162 : }
163 : }
164 2994 : }
165 :
166 2994 : static void tcx_windowing_analysis(
167 : Word16 const *signal, /* i: signal vector Qx*/
168 : Word16 L_frame, /* i: frame length Q0*/
169 : Word16 left_overlap, /* i: left overlap length Q0*/
170 : PWord16 const *left_win, /* i: left overlap window Q15*/
171 : Word16 right_overlap, /* i: right overlap length Q0*/
172 : PWord16 const *right_win, /* i: right overlap window Q15*/
173 : Word16 *output /* o: windowed signal vector Qx*/
174 : )
175 : {
176 : Word16 w, n;
177 :
178 : /* Left overlap */
179 2994 : n = shr( left_overlap, 1 ); /*Q0*/
180 514834 : FOR( w = 0; w < n; w++ )
181 : {
182 511840 : *output++ = mult_r( *signal++, left_win[w].v.im ); /*Qx*/
183 511840 : move16();
184 : }
185 514834 : FOR( w = 0; w < n; w++ )
186 : {
187 511840 : *output++ = mult_r( *signal++, left_win[n - 1 - w].v.re ); /*Qx*/
188 511840 : move16();
189 : }
190 :
191 : /* Non overlapping region */
192 2994 : n = sub( L_frame, shr( add( left_overlap, right_overlap ), 1 ) ); /*Q0*/
193 1319154 : FOR( w = 0; w < n; w++ )
194 : {
195 1316160 : *output++ = *signal++; /*Qx*/
196 1316160 : move16();
197 : }
198 :
199 : /* Right overlap */
200 2994 : n = shr( right_overlap, 1 ); /*Q0*/
201 514834 : FOR( w = 0; w < n; w++ )
202 : {
203 511840 : *output++ = mult_r( *signal++, right_win[w].v.re ); /*Qx*/
204 511840 : move16();
205 : }
206 514834 : FOR( w = 0; w < n; w++ )
207 : {
208 511840 : *output++ = mult_r( *signal++, right_win[n - 1 - w].v.im ); /*Qx*/
209 511840 : move16();
210 : }
211 2994 : }
212 : /*-------------------------------------------------------------------*
213 : * WindowSignal()
214 : *
215 : *
216 : *-------------------------------------------------------------------*/
217 2994 : void WindowSignal(
218 : TCX_CONFIG_HANDLE hTcxCfg, /* i : configuration of TCX */
219 : Word16 offset, /* i : left folding point offset relative to the input signal pointer Q0*/
220 : const Word16 left_overlap_mode, /* i : overlap mode of left window half Q0*/
221 : Word16 right_overlap_mode, /* i : overlap mode of right window half Q0*/
222 : Word16 *left_overlap_length, /* o : TCX window left overlap length Q0*/
223 : Word16 *right_overlap_length, /* o : TCX window right overlap length Q0*/
224 : const Word16 in[], /* i : input signal Qx*/
225 : Word16 *L_frame, /* i/o: frame length Q0*/
226 : Word16 out[], /* o : output windowed signal Qx*/
227 : const Word16 truncate_aldo, /* i : nonzero to truncate long ALDO slope Q0*/
228 : const Word8 fullband /* i : fullband flag Q0*/
229 : )
230 : {
231 : Word16 l, r;
232 : PWord16 const *left_win;
233 : PWord16 const *right_win;
234 :
235 :
236 : /*-----------------------------------------------------------*
237 : * Init *
238 : *-----------------------------------------------------------*/
239 :
240 2994 : tcx_get_windows( hTcxCfg, left_overlap_mode, right_overlap_mode, &l, &left_win, &r, &right_win, fullband );
241 :
242 : /* Init lengths */
243 :
244 : /* if past frame is ACELP */
245 2994 : IF( EQ_16( left_overlap_mode, TRANSITION_OVERLAP ) )
246 : {
247 : /* Increase frame size for 5ms */
248 0 : IF( fullband == 0 )
249 : {
250 0 : *L_frame = add( *L_frame, hTcxCfg->tcx5Size ); /*Q0*/
251 0 : move16();
252 0 : offset = negate( shr( hTcxCfg->tcx_mdct_window_trans_length, 1 ) ); /*Q0*/
253 : }
254 : ELSE
255 : {
256 0 : *L_frame = add( *L_frame, hTcxCfg->tcx5SizeFB ); /*Q0*/
257 0 : move16();
258 0 : offset = negate( shr( hTcxCfg->tcx_mdct_window_trans_lengthFB, 1 ) ); /*Q0*/
259 : }
260 : }
261 :
262 : /*-----------------------------------------------------------*
263 : * Windowing *
264 : *-----------------------------------------------------------*/
265 :
266 2994 : tcx_windowing_analysis( in - sub( shr( l, 1 ), offset ), *L_frame, l, left_win, r, right_win, out );
267 2994 : test();
268 2994 : test();
269 2994 : IF( EQ_16( left_overlap_mode, FULL_OVERLAP ) && truncate_aldo )
270 : {
271 : /* fade truncated ALDO window to avoid discontinuities */
272 : Word16 i, tmp;
273 : const PWord16 *p;
274 :
275 2994 : p = hTcxCfg->tcx_mdct_window_minimum; /*Q15*/
276 2994 : tmp = shr( hTcxCfg->tcx_mdct_window_min_length, 1 ); /*Q0*/
277 2994 : IF( fullband != 0 )
278 : {
279 2994 : p = hTcxCfg->tcx_mdct_window_minimumFB; /*Q15*/
280 2994 : tmp = shr( hTcxCfg->tcx_mdct_window_min_lengthFB, 1 ); /*Q0*/
281 : }
282 :
283 76114 : FOR( i = 0; i < tmp; i++ )
284 : {
285 73120 : out[i] = mult_r( out[i], p[i].v.im ); /*Qx*/
286 73120 : move16();
287 : }
288 76114 : FOR( i = 0; i < tmp; i++ )
289 : {
290 73120 : out[i + tmp] = mult_r( out[i + tmp], p[tmp - 1 - i].v.re ); /*Qx*/
291 73120 : move16();
292 : }
293 : }
294 :
295 2994 : *left_overlap_length = l;
296 2994 : move16();
297 2994 : *right_overlap_length = r;
298 2994 : move16();
299 2994 : }
300 : /*-------------------------------------------------------------------*
301 : * tcx_windowing_synthesis_current_frame()
302 : *
303 : *
304 : *-------------------------------------------------------------------*/
305 :
306 115738 : void tcx_windowing_synthesis_current_frame(
307 : Word16 *signal, /* i/o: signal vector Qx*/
308 : const PWord16 *window, /* i: TCX window vector Q15*/
309 : const PWord16 *window_half, /* i: TCX window vector for half-overlap window Q15*/
310 : const PWord16 *window_min, /* i: TCX minimum overlap window Q15*/
311 : const Word16 window_length, /* i: TCX window length Q0*/
312 : const Word16 window_half_length, /* i: TCX half window length Q0*/
313 : const Word16 window_min_length, /* i: TCX minimum overlap length Q0*/
314 : const Word16 left_rect, /* i: left part is rectangular Q0*/
315 : const Word16 left_mode, /* i: overlap mode of left window half Q0*/
316 : Word16 *acelp_zir, /* i: acelp ZIR Qx*/
317 : const Word16 *old_syn, /*Qx*/
318 : const Word16 *syn_overl, /*Qx*/
319 : const Word16 *A_zir, /*Q12*/
320 : const PWord16 *window_trans, /*Q15*/
321 : Word16 acelp_zir_len, /*Q0*/
322 : const Word16 acelp_mem_len, /*Q0*/
323 : const Word16 last_core_bfi, /* i : last core Q0*/
324 : const Word8 last_is_cng, /*Q0*/
325 : const Word16 fullbandScale /*Q0*/ )
326 : {
327 :
328 : Word16 i, overlap, n, tmp, tmp2;
329 : Word16 tmp_buf[L_FRAME_MAX / 2];
330 : Word32 L_tmp;
331 :
332 : /* Init */
333 :
334 115738 : overlap = shr( window_length, 1 ); /*Q0*/
335 :
336 : /* Past-frame is TCX concealed as CNG and current-frame is TCX */
337 115738 : test();
338 115738 : test();
339 115738 : test();
340 115738 : test();
341 115738 : IF( EQ_16( last_is_cng, 1 ) && left_rect == 0 )
342 : {
343 0 : IF( !fullbandScale )
344 : {
345 0 : set16_fx( acelp_zir, 0, acelp_zir_len );
346 0 : E_UTIL_synthesis( 0, A_zir, acelp_zir, acelp_zir, acelp_zir_len, signal + overlap + acelp_mem_len - M, 0, M );
347 : }
348 : ELSE
349 : {
350 0 : lerp( acelp_zir, tmp_buf, acelp_zir_len, idiv1616U( shl_sat( acelp_zir_len, LD_FSCALE_DENOM ), fullbandScale ) );
351 0 : acelp_zir = tmp_buf; /*Qx*/
352 : }
353 :
354 0 : FOR( i = 0; i < acelp_zir_len; i++ )
355 : {
356 : /*signal[i] *= (float)(i)/(float)(acelp_zir_len);
357 : signal[i] += acelp_zir[i]*(float)(acelp_zir_len-i)/(float)(acelp_zir_len);*/
358 0 : signal[i] = add( mult_r( signal[i], div_s( i, acelp_zir_len ) ), mult_r( acelp_zir[i], div_s( sub( acelp_zir_len, i ), acelp_zir_len ) ) ); /*Qx*/
359 0 : move16();
360 : }
361 : }
362 : /* Rectangular window (past-frame is ACELP) */
363 115738 : ELSE IF( EQ_16( left_rect, 1 ) && last_core_bfi == ACELP_CORE )
364 : {
365 17260 : tmp = sub( overlap, acelp_mem_len );
366 1940908 : FOR( i = 0; i < tmp; i++ )
367 : {
368 1923648 : move16();
369 1923648 : signal[i] = 0;
370 : }
371 :
372 17260 : IF( fullbandScale == 0 )
373 : {
374 :
375 8630 : tmp = shl( acelp_mem_len, 1 ); /*Qx*/
376 :
377 : /*OLA with ACELP*/
378 100668 : FOR( i = 0; i < acelp_mem_len; i++ )
379 : {
380 :
381 : /*window decoded TCX with aliasing*/
382 92038 : tmp2 = mult_r( signal[i + overlap - acelp_mem_len], window_trans[i].v.im ); /*Qx*/
383 :
384 : /*Time TDAC: 1)forward part of ACELP*/
385 92038 : tmp2 = add_sat( tmp2, mult_r( old_syn[acelp_zir_len - tmp + i], mult_r( window_trans[i].v.re, window_trans[i].v.re ) ) ); /*Qx*/
386 :
387 : /*Time TDAC: 1)reward part of ACELP*/
388 92038 : tmp2 = add_sat( tmp2, mult_r( old_syn[acelp_zir_len - i - 1], mult_r( window_trans[i].v.im, window_trans[i].v.re ) ) ); /*Qx*/
389 92038 : move16();
390 92038 : signal[i + overlap - acelp_mem_len] = tmp2; /*Qx*/
391 : }
392 100668 : FOR( ; i < tmp; i++ )
393 : {
394 :
395 : /*window decoded TCX with aliasing*/
396 92038 : tmp2 = mult_r( signal[i + overlap - acelp_mem_len], window_trans[tmp - 1 - i].v.re ); /*Qx*/
397 :
398 : /*Time TDAC: 1)forward part of ACELP*/
399 92038 : tmp2 = add_sat( tmp2, mult_r( old_syn[acelp_zir_len - tmp + i], mult_r( window_trans[tmp - 1 - i].v.im, window_trans[tmp - 1 - i].v.im ) ) ); /*Qx*/
400 : /*Time TDAC: 1)reward part of ACELP*/
401 92038 : tmp2 = add_sat( tmp2, mult_r( old_syn[acelp_zir_len - i - 1], mult_r( window_trans[tmp - 1 - i].v.re, window_trans[tmp - 1 - i].v.im ) ) ); /*Qx*/
402 92038 : move16();
403 92038 : signal[i + overlap - acelp_mem_len] = tmp2; /*Qx*/
404 : }
405 :
406 146710 : FOR( i = 0; i < M; i++ )
407 : {
408 138080 : move16();
409 138080 : signal[overlap + acelp_mem_len - M + i] = sub_sat( signal[overlap + acelp_mem_len - M + i], old_syn[acelp_zir_len - M + i] ); /*Qx*/
410 : }
411 : }
412 : /* ZIR at the end of the ACELP frame */
413 17260 : move16();
414 17260 : acelp_zir_len = 64;
415 :
416 17260 : IF( fullbandScale == 0 )
417 : {
418 8630 : set16_fx( acelp_zir, 0, acelp_zir_len );
419 8630 : E_UTIL_synthesis( 0, A_zir, acelp_zir, acelp_zir, acelp_zir_len, signal + overlap + acelp_mem_len - M, 0, M );
420 : }
421 : ELSE
422 : {
423 8630 : tmp = extract_l( L_shr( L_mult0( acelp_zir_len, fullbandScale ), LD_FSCALE_DENOM ) ); /*Q0*/
424 8630 : lerp( acelp_zir, tmp_buf, tmp, acelp_zir_len );
425 8630 : acelp_zir_len = tmp; /*Q0*/
426 8630 : move16();
427 8630 : acelp_zir = tmp_buf; /*Qx*/
428 :
429 :
430 8630 : IF( GE_16( acelp_zir_len, 2 * 64 ) )
431 : {
432 : /* apply a simple low-pass to the ZIR, to avoid potentially unmasked HF content */
433 1276637 : FOR( i = 2; i < acelp_zir_len; i++ )
434 : {
435 1270138 : L_tmp = L_mult( acelp_zir[i - 2], 8192 /*0.25 in Q15*/ );
436 1270138 : L_tmp = L_mac( L_tmp, acelp_zir[i - 1], 11469 /*0.35 in Q15*/ );
437 1270138 : acelp_zir[i] = mac_r( L_tmp, acelp_zir[i], 13107 /*0.40 in Q15*/ ); /*Qx*/
438 1270138 : move16();
439 : }
440 :
441 6499 : L_tmp = L_mult( acelp_zir[acelp_zir_len - 1], 13107 /*0.40 in Q15*/ );
442 6499 : L_tmp = L_mac( L_tmp, acelp_zir[acelp_zir_len - 1], 11469 /*0.35 in Q15*/ );
443 6499 : acelp_zir[acelp_zir_len - 1] = mac_r( L_tmp, acelp_zir[acelp_zir_len - 2], 8192 /*0.25 in Q15*/ ); /*Qx*/
444 6499 : move16();
445 6499 : L_tmp = L_mult( acelp_zir[acelp_zir_len - 2], 13107 );
446 6499 : L_tmp = L_mac( L_tmp, acelp_zir[acelp_zir_len - 1], 11469 );
447 6499 : acelp_zir[acelp_zir_len - 2] = mac_r( L_tmp, acelp_zir[acelp_zir_len - 1], 8192 ); /*Qx*/
448 6499 : move16();
449 1276637 : FOR( i = acelp_zir_len - 3; i >= 0; i-- )
450 : {
451 1270138 : L_tmp = L_mult( acelp_zir[i], 13107 );
452 1270138 : L_tmp = L_mac( L_tmp, acelp_zir[i + 1], 11469 );
453 1270138 : acelp_zir[i] = mac_r( L_tmp, acelp_zir[i + 2], 8192 ); /*Qx*/
454 1270138 : move16();
455 : }
456 : }
457 : }
458 :
459 2049604 : FOR( i = 0; i < acelp_zir_len; i++ )
460 : {
461 : /*remove reconstructed ZIR and add ACELP ZIR*/
462 2032344 : move16();
463 2032344 : signal[i + overlap + acelp_mem_len] = sub_sat( signal[i + overlap + acelp_mem_len], mult_r_sat( acelp_zir[i], div_s( sub_sat( acelp_zir_len, i ), acelp_zir_len ) ) ); /*Qx*/
464 : }
465 : }
466 : /* Rectangular window (past-frame is TCX) */
467 98478 : ELSE IF( left_rect == 1 && last_core_bfi != ACELP_CORE )
468 : {
469 460 : n = add( overlap, acelp_mem_len ); /*q0*/
470 66300 : FOR( i = 0; i < n; i++ )
471 : {
472 65840 : move16();
473 65840 : signal[i] = 0;
474 : }
475 :
476 460 : n = shr( window_length, 1 ); /*q0*/
477 58070 : FOR( i = 0; i < n; i++ )
478 : {
479 57610 : move16();
480 57610 : signal[i + overlap + acelp_mem_len] = mult_r( signal[i + overlap + acelp_mem_len], window[i].v.im ); /*Qx*/
481 : }
482 58070 : FOR( ; i < window_length; i++ )
483 : {
484 57610 : move16();
485 57610 : signal[i + overlap + acelp_mem_len] = mult_r( signal[i + overlap + acelp_mem_len], window[window_length - 1 - i].v.re ); /*Qx*/
486 : }
487 : }
488 : /* Normal window (past-frame is ACELP) */
489 98018 : ELSE IF( left_rect != 1 && last_core_bfi == ACELP_CORE )
490 : {
491 :
492 20 : n = shr( window_length, 1 ); /*q0*/
493 3086 : FOR( i = 0; i < n; i++ )
494 : {
495 3066 : move16();
496 3066 : signal[i] = mult_r( signal[i], window[i].v.im ); /*Qx*/
497 : }
498 3086 : FOR( ; i < window_length; i++ )
499 : {
500 3066 : move16();
501 3066 : signal[i] = mult_r( signal[i], window[window_length - 1 - i].v.re ); /*Qx*/
502 : }
503 :
504 6152 : FOR( i = 0; i < window_length /*acelp_zir_len*/; i++ )
505 : {
506 6132 : move16();
507 6132 : signal[i] = add( signal[i], syn_overl[i] ); /*Qx*/
508 : }
509 : }
510 : /* Normal window (past-frame is TCX) */
511 : ELSE
512 : {
513 97998 : IF( EQ_16( left_mode, 2 ) ) /* min. overlap */
514 : {
515 58868 : n = shr( sub( window_length, window_min_length ), 1 ); /*q0*/
516 2737936 : FOR( i = 0; i < n; i++ )
517 : {
518 2679068 : *signal++ = 0;
519 2679068 : move16();
520 : }
521 :
522 58868 : n = shr( window_min_length, 1 ); /*q0*/
523 1320826 : FOR( i = 0; i < n; i++ )
524 : {
525 1261958 : *signal = mult_r( *signal, window_min[i].v.im ); /*Qx*/
526 1261958 : move16();
527 1261958 : signal++;
528 : }
529 1320826 : FOR( i = 0; i < n; i++ )
530 : {
531 1261958 : *signal = mult_r( *signal, window_min[n - 1 - i].v.re ); /*Qx*/
532 1261958 : move16();
533 1261958 : signal++;
534 : }
535 : }
536 39130 : ELSE IF( EQ_16( left_mode, 3 ) ) /* half OL */
537 : {
538 : Word16 w;
539 :
540 14102 : n = shr( sub( window_length, window_half_length ), 1 );
541 344542 : FOR( i = 0; i < n; i++ )
542 : {
543 330440 : move16();
544 330440 : signal[i] = 0;
545 : }
546 14102 : n = shr( window_half_length, 1 );
547 920114 : FOR( w = 0; w < n; w++ )
548 : {
549 906012 : move16();
550 906012 : signal[i] = mult_r( signal[i], window_half[w].v.im ); /*Qx*/
551 906012 : i = add( i, 1 );
552 : }
553 920114 : FOR( w = 0; w < n; w++ )
554 : {
555 906012 : move16();
556 906012 : signal[i] = mult_r( signal[i], window_half[window_half_length / 2 - 1 - w].v.re ); /*Qx*/
557 906012 : i = add( i, 1 );
558 : }
559 : }
560 : ELSE
561 : { /* normal full/maximum overlap */
562 :
563 25028 : n = shr( window_length, 1 );
564 3809452 : FOR( i = 0; i < n; i++ )
565 : {
566 3784424 : move16();
567 3784424 : signal[i] = mult_r( signal[i], window[i].v.im ); /*Qx*/
568 : }
569 3809452 : FOR( ; i < window_length; i++ )
570 : {
571 3784424 : move16();
572 3784424 : signal[i] = mult_r( signal[i], window[window_length - 1 - i].v.re ); /*Qx*/
573 : }
574 : }
575 : }
576 :
577 : /* Right part asymmetric window : with ALDO do nothing->can be skipped*/
578 115738 : }
579 : /*-------------------------------------------------------------------*
580 : * tcx_windowing_synthesis_past_frame()
581 : *
582 : *
583 : *-------------------------------------------------------------------*/
584 117108 : void tcx_windowing_synthesis_past_frame(
585 : Word16 *signal, /* i/o: signal vector Qx*/
586 : const PWord16 *window, /* i: TCX window vector Q15*/
587 : const PWord16 *window_half, /* i: TCX window vector for half-overlap window Q15*/
588 : const PWord16 *window_min, /* i: TCX minimum overlap window Q15*/
589 : const Word16 window_length, /* i: TCX window length Q0*/
590 : const Word16 window_half_length, /* i: TCX half window length Q0*/
591 : const Word16 window_min_length, /* i: TCX minimum overlap length Q0*/
592 : const Word16 right_mode /* i: overlap mode (left_mode of current frame) Q0*/
593 : )
594 : {
595 :
596 : Word16 i, n;
597 :
598 117108 : IF( EQ_16( right_mode, 2 ) ) /* min. overlap */
599 : {
600 62446 : signal += shr( sub( window_length, window_min_length ), 1 ); /*Qx*/
601 :
602 62446 : n = shr( window_min_length, 1 );
603 1404718 : FOR( i = 0; i < n; i++ )
604 : {
605 1342272 : *signal = mult_r( *signal, window_min[i].v.re ); /*Qx*/
606 1342272 : move16();
607 1342272 : signal++;
608 : }
609 1404718 : FOR( i = 0; i < n; i++ )
610 : {
611 1342272 : *signal = mult_r( *signal, window_min[n - 1 - i].v.im ); /*Qx*/
612 1342272 : move16();
613 1342272 : signal++;
614 : }
615 :
616 62446 : n = shr( sub( window_length, window_min_length ), 1 ); /*Q0*/
617 4242618 : FOR( i = 0; i < n; i++ )
618 : {
619 4180172 : *signal = 0;
620 4180172 : move16();
621 4180172 : signal++;
622 : }
623 : }
624 54662 : ELSE IF( EQ_16( right_mode, 3 ) ) /* half OL */
625 : {
626 : Word16 w;
627 :
628 15944 : i = shr( sub( window_length, window_half_length ), 1 ); /*Q0*/
629 15944 : n = shr( window_half_length, 1 ); /*Q0*/
630 1028888 : FOR( w = 0; w < n; w++ )
631 : {
632 1012944 : signal[i] = mult_r( signal[i], window_half[w].v.re ); /*Qx*/
633 1012944 : move16();
634 1012944 : i = add( i, 1 );
635 : }
636 1028888 : FOR( w = 0; w < n; w++ )
637 : {
638 1012944 : signal[i] = mult_r( signal[i], window_half[window_half_length / 2 - 1 - w].v.im ); /*Qx*/
639 1012944 : move16();
640 1012944 : i = add( i, 1 );
641 : }
642 1366536 : FOR( ; i < window_length; i++ )
643 : {
644 1350592 : move16();
645 1350592 : signal[i] = 0;
646 : }
647 : }
648 : ELSE /* normal full/maximum overlap */
649 : {
650 :
651 38718 : n = shr( window_length, 1 ); /*Q0*/
652 5513656 : FOR( i = 0; i < n; i++ )
653 : {
654 5474938 : move16();
655 5474938 : signal[i] = mult_r( signal[i], window[i].v.re ); /*Qx*/
656 5474938 : move16();
657 5474938 : signal[window_length - 1 - i] = mult_r( signal[window_length - 1 - i], window[i].v.im ); /*Qx*/
658 : }
659 : }
660 117108 : }
661 : /*-------------------------------------------------------------------*
662 : * lpc2mdct()
663 : *
664 : *
665 : *-------------------------------------------------------------------*/
666 :
667 646 : void lpc2mdct(
668 : Word16 *lpcCoeffs, /*Q12*/
669 : const Word16 lpcOrder, /*Q0*/
670 : Word16 *mdct_gains, /*Q15 - mdct_gains_exp*/
671 : Word16 *mdct_gains_exp,
672 : Word16 *mdct_inv_gains, /*Q15 - mdct_inv_gains_exp*/
673 : Word16 *mdct_inv_gains_exp,
674 : const Word16 length, /*Q0*/
675 : const Word16 noInverse /*Q0*/ )
676 : {
677 : Word32 ComplexData[2 * FDNS_NPTS];
678 : Word16 i, j, k, sizeN, step, scale, s, tmp16;
679 : Word16 g, g_e, ig, ig_e;
680 : Word32 tmp32;
681 : const PWord16 *ptwiddle;
682 : Word32 workBuffer[2 * BASOP_CFFT_MAX_LENGTH];
683 :
684 : #ifndef IVAS_CODE_TCX_UTIL
685 : (void) noInverse;
686 : #endif
687 :
688 646 : assert( length <= FDNS_NPTS );
689 646 : sizeN = shl( length, 1 ); /*Q0*/
690 :
691 646 : BASOP_getTables( NULL, &ptwiddle, &step, sizeN );
692 : /*ODFT*/
693 646 : assert( lpcOrder < FDNS_NPTS );
694 : /* pre-twiddle */
695 11628 : FOR( i = 0; i <= lpcOrder; i++ )
696 : {
697 10982 : ComplexData[2 * i] = L_mult( lpcCoeffs[i], ptwiddle->v.re ); /*Q12*/
698 10982 : move32();
699 10982 : ComplexData[2 * i + 1] = L_negate( L_mult( lpcCoeffs[i], ptwiddle->v.im ) ); /*Q12*/
700 10982 : move32();
701 10982 : ptwiddle += step;
702 : }
703 : /* zero padding */
704 31008 : FOR( ; i < FDNS_NPTS; i++ )
705 : {
706 30362 : ComplexData[2 * i] = L_deposit_l( 0 );
707 30362 : move32();
708 30362 : ComplexData[2 * i + 1] = L_deposit_l( 0 );
709 30362 : move32();
710 : }
711 :
712 646 : move16();
713 : #ifdef IVAS_CODE_TCX_UTIL
714 : if ( noInverse )
715 : {
716 : /* half length FFT */
717 : scale = add( norm_s( lpcCoeffs[0] ), 1 );
718 : BASOP_cfft( (cmplx *) ComplexData, FDNS_NPTS, &scale, workBuffer ); // tbv -> In float the fft type changes as well
719 : /*Get amplitude*/
720 : j = sub( length, 1 );
721 : k = 0;
722 : for ( i = 0; i < length; i++ )
723 : {
724 : mdct_gains[i] = (float) ( sqrt( RealData[i] * RealData[i] + ImagData[i] * ImagData[i] ) );
725 : }
726 : }
727 : else
728 : #endif
729 : {
730 : /* half length FFT */
731 646 : scale = add( norm_s( lpcCoeffs[0] ), 1 );
732 646 : BASOP_cfft( (cmplx *) ComplexData, FDNS_NPTS, &scale, workBuffer ); /*Q31 - scale*/
733 : /*Get amplitude*/
734 646 : j = sub( length, 1 );
735 646 : k = 0;
736 21318 : FOR( i = 0; i < length / 2; i++ )
737 : {
738 20672 : s = sub( norm_l( L_max( L_abs( ComplexData[2 * i] ), L_abs( ComplexData[2 * i + 1] ) ) ), 1 );
739 20672 : tmp16 = extract_h( L_shl( ComplexData[2 * i], s ) ); /*Q15 - scale + s*/
740 20672 : tmp32 = L_mult( tmp16, tmp16 ); /*Q15 - 2*(scale - s)*/
741 20672 : tmp16 = extract_h( L_shl( ComplexData[2 * i + 1], s ) ); /*Q15 - scale + s*/
742 20672 : tmp16 = mac_r( tmp32, tmp16, tmp16 ); /*Q15 - 2*(scale - s)*/
743 20672 : s = shl( sub( scale, s ), 1 );
744 20672 : if ( tmp16 == 0 )
745 : {
746 0 : s = -16;
747 0 : move16();
748 : }
749 20672 : if ( tmp16 == 0 )
750 : {
751 0 : tmp16 = 1;
752 0 : move16();
753 : }
754 20672 : BASOP_Util_Sqrt_InvSqrt_MantExp( tmp16, s, &g, &g_e, &ig, &ig_e ); /*Q15 - ig_e*/
755 20672 : if ( mdct_gains != 0 )
756 : {
757 0 : mdct_gains[k] = g; /*Q15 - g_e*/
758 0 : move16();
759 : }
760 20672 : if ( mdct_gains_exp != 0 )
761 : {
762 0 : mdct_gains_exp[k] = g_e;
763 0 : move16();
764 : }
765 20672 : if ( mdct_inv_gains != 0 )
766 : {
767 20672 : mdct_inv_gains[k] = ig; /*Q15 - ig_e*/
768 20672 : move16();
769 : }
770 20672 : if ( mdct_inv_gains_exp != 0 )
771 : {
772 20672 : mdct_inv_gains_exp[k] = ig_e;
773 20672 : move16();
774 : }
775 20672 : k = add( k, 1 );
776 20672 : s = sub( norm_l( L_max( L_abs( ComplexData[2 * j] ), L_abs( ComplexData[2 * j + 1] ) ) ), 1 );
777 20672 : tmp16 = extract_h( L_shl( ComplexData[2 * j], s ) ); /*Q15 - scale + s*/
778 20672 : tmp32 = L_mult( tmp16, tmp16 ); /*Q15 - 2*(scale - s)*/
779 20672 : tmp16 = extract_h( L_shl( ComplexData[2 * j + 1], s ) ); /*Q15 - scale + s*/
780 20672 : tmp16 = mac_r( tmp32, tmp16, tmp16 ); /*Q15 - 2*(scale - s)*/
781 20672 : s = shl( sub( scale, s ), 1 );
782 20672 : if ( tmp16 == 0 )
783 : {
784 0 : s = -16;
785 0 : move16();
786 : }
787 20672 : if ( tmp16 == 0 )
788 : {
789 0 : tmp16 = 1;
790 0 : move16();
791 : }
792 20672 : BASOP_Util_Sqrt_InvSqrt_MantExp( tmp16, s, &g, &g_e, &ig, &ig_e );
793 20672 : if ( mdct_gains != 0 )
794 : {
795 0 : mdct_gains[k] = g; /*Q15 - g_e*/
796 0 : move16();
797 : }
798 20672 : if ( mdct_gains_exp != 0 )
799 : {
800 0 : mdct_gains_exp[k] = g_e;
801 0 : move16();
802 : }
803 20672 : if ( mdct_inv_gains != 0 )
804 : {
805 20672 : mdct_inv_gains[k] = ig; /*Q15 - ig_e*/
806 20672 : move16();
807 : }
808 20672 : if ( mdct_inv_gains_exp != 0 )
809 : {
810 20672 : mdct_inv_gains_exp[k] = ig_e;
811 20672 : move16();
812 : }
813 20672 : j = sub( j, 1 );
814 20672 : k = add( k, 1 );
815 : }
816 : }
817 646 : }
818 :
819 220416 : void lpc2mdct_2(
820 : Word16 *lpcCoeffs, /*Q12*/
821 : const Word16 lpcOrder, /*Q0*/
822 : Word16 mdct_gains_fx[], /*Q15 - mdct_gains_e*/
823 : Word16 mdct_gains_e[],
824 : Word16 mdct_inv_gains_fx[], /*Q15 - mdct_inv_gains_e*/
825 : Word16 mdct_inv_gains_e[],
826 : const Word16 length /*Q0*/ )
827 : {
828 : Word16 i, sizeN, j, k, step, scale, s, tmp16;
829 : Word16 g, g_e, ig, ig_e;
830 : Word32 tmp32;
831 : Word32 RealData_fx[2 * FDNS_NPTS], ImagData_fx[2 * FDNS_NPTS];
832 : const PWord16 *ptwiddle;
833 :
834 220416 : assert( length <= FDNS_NPTS );
835 220416 : sizeN = shl( length, 1 ); /*Q0*/
836 :
837 220416 : BASOP_getTables( NULL, &ptwiddle, &step, sizeN );
838 :
839 : /* ODFT */
840 3967488 : FOR( i = 0; i < lpcOrder + 1; i++ )
841 : {
842 3747072 : RealData_fx[i] = L_mult( lpcCoeffs[i], ptwiddle->v.re ); /*Q12*/
843 3747072 : move32();
844 3747072 : ImagData_fx[i] = L_negate( L_mult( lpcCoeffs[i], ptwiddle->v.im ) ); /*Q12*/
845 3747072 : move32();
846 3747072 : ptwiddle += step;
847 : }
848 :
849 24686592 : FOR( ; i < sizeN; i++ )
850 : {
851 24466176 : RealData_fx[i] = L_deposit_l( 0 );
852 24466176 : move32();
853 24466176 : ImagData_fx[i] = L_deposit_l( 0 );
854 24466176 : move32();
855 : }
856 :
857 : /* half length FFT */
858 220416 : scale = add( norm_s( lpcCoeffs[0] ), 1 );
859 220416 : BASOP_cfft_ivas( RealData_fx, ImagData_fx, 1, &scale ); /*Q31 - scale*/
860 :
861 : /*Get amplitude*/
862 220416 : j = sub( FDNS_NPTS, 1 );
863 220416 : move16();
864 220416 : k = 0;
865 220416 : move16();
866 :
867 7273728 : FOR( i = 0; i < FDNS_NPTS / 2; i++ )
868 : {
869 7053312 : s = sub( norm_l( L_max( L_abs( RealData_fx[i] ), L_abs( ImagData_fx[i] ) ) ), 1 );
870 :
871 7053312 : tmp16 = extract_h( L_shl( RealData_fx[i], s ) ); /*Q15 - scale + s*/
872 7053312 : tmp32 = L_mult( tmp16, tmp16 ); /*Q15 - 2*(scale - s)*/
873 :
874 7053312 : tmp16 = extract_h( L_shl( ImagData_fx[i], s ) ); /*Q15 - scale + s*/
875 7053312 : tmp16 = mac_r( tmp32, tmp16, tmp16 ); /*Q15 - 2*(scale - s)*/
876 :
877 7053312 : s = shl( sub( scale, s ), 1 );
878 :
879 7053312 : if ( tmp16 == 0 )
880 : {
881 0 : s = -16;
882 0 : move16();
883 : }
884 7053312 : if ( tmp16 == 0 )
885 : {
886 0 : tmp16 = 1;
887 0 : move16();
888 : }
889 :
890 7053312 : BASOP_Util_Sqrt_InvSqrt_MantExp( tmp16, s, &g, &g_e, &ig, &ig_e );
891 :
892 7053312 : if ( mdct_gains_fx != NULL )
893 : {
894 0 : mdct_gains_fx[k] = g; /*Q15 - g_e*/
895 0 : move16();
896 : }
897 :
898 7053312 : if ( mdct_gains_e != NULL )
899 : {
900 0 : mdct_gains_e[k] = g_e;
901 0 : move16();
902 : }
903 :
904 7053312 : if ( mdct_inv_gains_fx != NULL )
905 : {
906 7053312 : mdct_inv_gains_fx[k] = ig; /*Q15 - ig_e*/
907 7053312 : move16();
908 : }
909 :
910 7053312 : if ( mdct_inv_gains_e != NULL )
911 : {
912 7053312 : mdct_inv_gains_e[k] = ig_e;
913 7053312 : move16();
914 : }
915 :
916 7053312 : k = add( k, 1 );
917 :
918 :
919 7053312 : s = sub( norm_l( L_max( L_abs( RealData_fx[j] ), L_abs( ImagData_fx[j] ) ) ), 1 );
920 :
921 7053312 : tmp16 = extract_h( L_shl( RealData_fx[j], s ) ); /*Q15 - scale + s*/
922 7053312 : tmp32 = L_mult( tmp16, tmp16 ); /*Q15 - 2*(scale - s)*/
923 :
924 7053312 : tmp16 = extract_h( L_shl( ImagData_fx[j], s ) ); /*Q15 - scale + s*/
925 7053312 : tmp16 = mac_r( tmp32, tmp16, tmp16 ); /*Q15 - 2*(scale - s)*/
926 :
927 7053312 : s = shl( sub( scale, s ), 1 );
928 :
929 7053312 : if ( tmp16 == 0 )
930 : {
931 0 : s = -16;
932 0 : move16();
933 : }
934 7053312 : if ( tmp16 == 0 )
935 : {
936 0 : tmp16 = 1;
937 0 : move16();
938 : }
939 :
940 7053312 : BASOP_Util_Sqrt_InvSqrt_MantExp( tmp16, s, &g, &g_e, &ig, &ig_e );
941 :
942 7053312 : if ( mdct_gains_fx != NULL )
943 : {
944 0 : mdct_gains_fx[k] = g;
945 0 : move16();
946 : }
947 :
948 7053312 : if ( mdct_gains_e != NULL )
949 : {
950 0 : mdct_gains_e[k] = g_e;
951 0 : move16();
952 : }
953 :
954 7053312 : if ( mdct_inv_gains_fx != NULL )
955 : {
956 7053312 : mdct_inv_gains_fx[k] = ig;
957 7053312 : move16();
958 : }
959 :
960 7053312 : if ( mdct_inv_gains_e != NULL )
961 : {
962 7053312 : mdct_inv_gains_e[k] = ig_e;
963 7053312 : move16();
964 : }
965 :
966 7053312 : j = sub( j, 1 );
967 7053312 : k = add( k, 1 );
968 : }
969 :
970 220416 : return;
971 : }
972 : /**
973 : * \brief Perform mdct shaping. In the floating point software there are two functions,
974 : * mdct_noiseShaping and mdct_preShaping, which are combined here into a single function.
975 : * \param x spectrum mantissas
976 : * \param lg spectrum length
977 : * \param gains shaping gains mantissas
978 : * \param gains_exp shaping gains exponents
979 : */
980 872 : void mdct_shaping(
981 : Word32 x[], /*Qx*/
982 : const Word16 lg, /*Q0*/
983 : const Word16 gains[], /*Q15 - gains_exp*/
984 : const Word16 gains_exp[]
985 : /*const Word16 nBands*/ /*Parameter added in IVAS, but always equal to FDNS_NPTS */
986 : )
987 : {
988 :
989 : Word16 i, k, l;
990 : Word16 m, n, k1, k2, j;
991 872 : Word32 *px = x; /*Qx*/
992 872 : Word16 const *pgains = gains;
993 872 : Word16 const *pgainsexp = gains_exp;
994 : #ifndef ISSUE_1836_replace_overflow_libcom
995 : #ifdef BASOP_NOGLOB_DECLARE_LOCAL
996 : Flag Overflow = 0;
997 : #endif
998 : #endif
999 :
1000 : /* FDNS_NPTS = 64 */
1001 872 : k = shr( lg, 6 ); /*Q0*/
1002 872 : m = s_and( lg, 0x3F );
1003 :
1004 872 : IF( m != 0 )
1005 : {
1006 22 : IF( LE_16( m, FDNS_NPTS / 2 ) )
1007 : {
1008 22 : n = idiv1616U( FDNS_NPTS, m ); /*Q0*/
1009 22 : k1 = k;
1010 22 : move16();
1011 22 : k2 = add( k, 1 );
1012 : }
1013 : ELSE
1014 : {
1015 0 : n = idiv1616U( FDNS_NPTS, sub( FDNS_NPTS, m ) ); /*Q0*/
1016 0 : k1 = add( k, 1 );
1017 0 : k2 = k;
1018 0 : move16();
1019 : }
1020 :
1021 22 : i = 0;
1022 22 : move16();
1023 22 : j = 0;
1024 22 : move16();
1025 :
1026 1430 : WHILE( LT_16( i, lg ) )
1027 : {
1028 :
1029 1408 : k = k2;
1030 1408 : move16();
1031 1408 : if ( j != 0 )
1032 : {
1033 1056 : k = k1;
1034 1056 : move16();
1035 : }
1036 :
1037 1408 : j = add( j, 1 );
1038 1408 : if ( EQ_16( j, n ) )
1039 : {
1040 352 : j = 0;
1041 352 : move16();
1042 : }
1043 :
1044 : /* Limit number of loops, if end is reached */
1045 1408 : k = s_min( k, sub( lg, i ) );
1046 :
1047 10208 : FOR( l = 0; l < k; l++ )
1048 : {
1049 : #ifdef ISSUE_1836_replace_overflow_libcom
1050 8800 : *x = L_shl_sat( Mpy_32_16_r( *x, *gains ), *gains_exp ); /*Qx*/
1051 : #else
1052 : *x = L_shl_o( Mpy_32_16_r( *x, *gains ), *gains_exp, &Overflow ); /*Qx*/
1053 : #endif
1054 8800 : move32();
1055 8800 : x++;
1056 : }
1057 1408 : i = add( i, k );
1058 :
1059 1408 : gains++;
1060 1408 : gains_exp++;
1061 : }
1062 : }
1063 : ELSE
1064 : {
1065 5035 : FOR( l = 0; l < k; l++ )
1066 : {
1067 4185 : x = &px[l]; /*Qx*/
1068 4185 : gains = pgains;
1069 4185 : gains_exp = pgainsexp;
1070 272025 : FOR( i = 0; i < FDNS_NPTS; i++ )
1071 : {
1072 : #ifdef ISSUE_1836_replace_overflow_libcom
1073 267840 : *x = L_shl_sat( Mpy_32_16_r( *x, *gains ), *gains_exp ); /*Qx*/
1074 : #else
1075 : *x = L_shl_o( Mpy_32_16_r( *x, *gains ), *gains_exp, &Overflow ); /*Qx*/
1076 : #endif
1077 267840 : move32();
1078 267840 : x += k;
1079 267840 : gains++;
1080 267840 : gains_exp++;
1081 : }
1082 : }
1083 : }
1084 872 : }
1085 :
1086 706 : void mdct_shaping_16(
1087 : const Word16 x[], /*Qx*/
1088 : const Word16 lg, /*Q0*/
1089 : const Word16 lg_total, /*Q0*/
1090 : const Word16 gains[], /*15 - gains_exp*/
1091 : const Word16 gains_exp[],
1092 : Word16 gains_max_exp,
1093 : Word32 y[] /*Qx*/ )
1094 : {
1095 : Word16 i, k, l;
1096 : Word16 m, gain_exp;
1097 : Word16 const *px;
1098 : Word32 *py;
1099 706 : Word16 const *pgains = gains;
1100 : Word16 gains_exp_loc[FDNS_NPTS];
1101 : Word16 const *pgains_exp;
1102 :
1103 : /* FDNS_NPTS = 64 */
1104 706 : k = shr( lg, 6 ); /*Q0*/
1105 706 : m = s_and( lg, 0x3F );
1106 :
1107 706 : assert( m == 0 );
1108 : {
1109 45890 : FOR( i = 0; i < FDNS_NPTS; i++ )
1110 : {
1111 45184 : gains_exp_loc[i] = sub( gains_exp[i], gains_max_exp );
1112 45184 : move16();
1113 : }
1114 5104 : FOR( l = 0; l < k; l++ )
1115 : {
1116 4398 : px = &x[l]; /*Qx*/
1117 4398 : py = &y[l]; /*Qx*/
1118 4398 : pgains = gains; /*15 - gains_exp*/
1119 4398 : pgains_exp = gains_exp_loc;
1120 285870 : FOR( i = 0; i < FDNS_NPTS; i++ )
1121 : {
1122 281472 : *py = L_shl( L_mult( *px, *pgains ), *pgains_exp ); /*Qx*/
1123 281472 : move32();
1124 281472 : px += k;
1125 281472 : py += k;
1126 281472 : pgains++;
1127 281472 : pgains_exp++;
1128 : }
1129 : }
1130 : }
1131 :
1132 706 : gain_exp = sub( gains_exp[FDNS_NPTS - 1], gains_max_exp );
1133 19275 : FOR( i = lg; i < lg_total; i++ )
1134 : {
1135 18569 : y[i] = L_shl( L_mult( x[i], gains[FDNS_NPTS - 1] ), gain_exp ); /*Qx*/
1136 18569 : move32();
1137 : }
1138 706 : }
1139 :
1140 220608 : void mdct_noiseShaping_ivas_fx(
1141 : Word32 x_fx[], /*Q31 - x_e*/
1142 : Word16 *x_e,
1143 : const Word16 lg, /*Q0*/
1144 : const Word16 gains_fx[], /*Q15 - gains_exp*/
1145 : const Word16 gains_exp[]
1146 : /*const Word16 nBands*/ /*Parameter added in IVAS, but always equal to FDNS_NPTS */
1147 : )
1148 : {
1149 : Word16 i, j, k, l;
1150 : Word16 m, n, k1, k2;
1151 :
1152 220608 : j = 0;
1153 220608 : move16();
1154 : /* FDNS_NPTS = 64 */
1155 220608 : k = shr( lg, 6 ); /*Q0*/
1156 220608 : m = s_and( lg, 0x3F );
1157 :
1158 220608 : Word16 max_e = MIN16B;
1159 220608 : move16();
1160 14339520 : FOR( i = 0; i < FDNS_NPTS; i++ )
1161 : {
1162 14118912 : max_e = s_max( max_e, add( *x_e, gains_exp[i] ) );
1163 : }
1164 :
1165 220608 : IF( m != 0 )
1166 : {
1167 4101 : IF( LE_16( m, FDNS_NPTS / 2 ) )
1168 : {
1169 4101 : n = idiv1616U( FDNS_NPTS, m ); /*Q0*/
1170 4101 : k1 = k;
1171 4101 : move16();
1172 4101 : k2 = add( k, 1 );
1173 : }
1174 : ELSE
1175 : {
1176 0 : n = idiv1616U( FDNS_NPTS, sub( FDNS_NPTS, m ) ); /*Q0*/
1177 0 : k1 = add( k, 1 );
1178 0 : k2 = k;
1179 0 : move16();
1180 : }
1181 :
1182 4101 : i = 0;
1183 4101 : move16();
1184 4101 : j = 0;
1185 4101 : move16();
1186 :
1187 266565 : WHILE( LT_16( i, lg ) )
1188 : {
1189 262464 : IF( j % n != 0 )
1190 : {
1191 192880 : k = k1;
1192 192880 : move16();
1193 : }
1194 : ELSE
1195 : {
1196 69584 : k = k2;
1197 69584 : move16();
1198 : }
1199 :
1200 : /* Limit number of loops, if end is reached */
1201 262464 : k = s_min( k, sub( lg, i ) );
1202 :
1203 1984144 : FOR( l = 0; l < k; l++ )
1204 : {
1205 1721680 : x_fx[i] = Mpy_32_16_1( x_fx[i], gains_fx[j] ); /*Q31 - x_e*/
1206 1721680 : move32();
1207 1721680 : x_fx[i] = L_shr( x_fx[i], sub( max_e, add( *x_e, gains_exp[j] ) ) ); /*Q31 - max_e*/
1208 1721680 : move32();
1209 1721680 : i = add( i, 1 );
1210 : }
1211 262464 : j = add( j, 1 );
1212 : }
1213 : }
1214 : ELSE
1215 : {
1216 14072955 : FOR( i = 0; i < lg; )
1217 : {
1218 111296448 : FOR( l = 0; l < k; l++ )
1219 : {
1220 97440000 : x_fx[i] = Mpy_32_16_1( x_fx[i], gains_fx[j] ); /*Q31 - x_e*/
1221 97440000 : move32();
1222 97440000 : x_fx[i] = L_shr( x_fx[i], sub( max_e, add( *x_e, gains_exp[j] ) ) ); /*Q31 - max_e*/
1223 97440000 : move32();
1224 97440000 : i = add( i, 1 );
1225 : }
1226 13856448 : j = add( j, 1 );
1227 : }
1228 : }
1229 :
1230 220608 : *x_e = max_e;
1231 220608 : move16();
1232 :
1233 220608 : return;
1234 : }
1235 :
1236 :
1237 0 : void mdct_noiseShaping_interp(
1238 : Word32 x[], /*Qx*/
1239 : const Word16 lg, /*Q0*/
1240 : Word16 gains[], /*Q15 - gains_exp*/
1241 : Word16 gains_exp[] )
1242 : {
1243 : Word16 i, j, jp, jn, k, l;
1244 : Word16 g, pg, ng, e, tmp;
1245 :
1246 :
1247 0 : assert( lg % FDNS_NPTS == 0 );
1248 0 : k = shr( lg, 6 ); /* FDNS_NPTS = 64 Q0*/
1249 :
1250 0 : IF( gains )
1251 : {
1252 : /* Linear interpolation */
1253 0 : IF( EQ_16( k, 4 ) )
1254 : {
1255 0 : jp = 0;
1256 0 : move16();
1257 0 : j = 0;
1258 0 : move16();
1259 0 : jn = 1;
1260 0 : move16();
1261 :
1262 0 : FOR( i = 0; i < lg; i += 4 )
1263 : {
1264 0 : pg = gains[jp]; /*Q15 - gains_exp*/
1265 0 : move16();
1266 0 : g = gains[j]; /*Q15 - gains_exp*/
1267 0 : move16();
1268 0 : ng = gains[jn]; /*Q15 - gains_exp*/
1269 0 : move16();
1270 :
1271 : /* common exponent for pg and g */
1272 0 : tmp = sub( gains_exp[j], gains_exp[jp] );
1273 0 : if ( tmp > 0 )
1274 0 : pg = shr( pg, tmp );
1275 0 : if ( tmp < 0 )
1276 0 : g = shl( g, tmp );
1277 0 : e = s_max( gains_exp[j], gains_exp[jp] );
1278 :
1279 0 : tmp = mac_r( L_mult( pg, 12288 /*0.375f Q15*/ ), g, 20480 /*0.625f Q15*/ ); /*Q15 - gains_exp*/
1280 0 : x[i] = L_shl( Mpy_32_16_1( x[i], tmp ), e ); /*Qx*/
1281 0 : move32();
1282 :
1283 0 : tmp = mac_r( L_mult( pg, 4096 /*0.125f Q15*/ ), g, 28672 /*0.875f Q15*/ ); /*Q15 - gains_exp*/
1284 0 : x[i + 1] = L_shl( Mpy_32_16_1( x[i + 1], tmp ), e ); /*Qx*/
1285 0 : move32();
1286 :
1287 : /* common exponent for g and ng */
1288 0 : g = gains[j]; /*Q15 - gains_exp*/
1289 0 : move16();
1290 0 : tmp = sub( gains_exp[j], gains_exp[jn] );
1291 0 : if ( tmp > 0 )
1292 0 : ng = shr( ng, tmp );
1293 0 : if ( tmp < 0 )
1294 0 : g = shl( g, tmp );
1295 0 : e = s_max( gains_exp[j], gains_exp[jn] );
1296 :
1297 0 : tmp = mac_r( L_mult( g, 28672 /*0.875f Q15*/ ), ng, 4096 /*0.125f Q15*/ ); /*Q15 - gains_exp*/
1298 0 : x[i + 2] = L_shl( Mpy_32_16_1( x[i + 2], tmp ), e ); /*Qx*/
1299 0 : move32();
1300 :
1301 0 : tmp = mac_r( L_mult( g, 20480 /*0.625f Q15*/ ), ng, 12288 /*0.375f Q15*/ ); /*Q15 - gains_exp*/
1302 0 : x[i + 3] = L_shl( Mpy_32_16_1( x[i + 3], tmp ), e ); /*Qx*/
1303 0 : move32();
1304 :
1305 0 : jp = j;
1306 0 : move16();
1307 0 : j = jn;
1308 0 : move16();
1309 0 : jn = s_min( add( jn, 1 ), FDNS_NPTS - 1 );
1310 : }
1311 : }
1312 0 : ELSE IF( EQ_16( k, 5 ) )
1313 : {
1314 0 : jp = 0;
1315 0 : move16();
1316 0 : j = 0;
1317 0 : move16();
1318 0 : jn = 1;
1319 0 : move16();
1320 :
1321 0 : FOR( i = 0; i < lg; i += 5 )
1322 : {
1323 0 : pg = gains[jp]; /*Q15 - gains_exp*/
1324 0 : move16();
1325 0 : g = gains[j]; /*Q15 - gains_exp*/
1326 0 : move16();
1327 0 : ng = gains[jn]; /*Q15 - gains_exp*/
1328 0 : move16();
1329 :
1330 : /* common exponent for pg and g */
1331 0 : tmp = sub( gains_exp[j], gains_exp[jp] );
1332 0 : if ( tmp > 0 )
1333 0 : pg = shr( pg, tmp );
1334 0 : if ( tmp < 0 )
1335 0 : g = shl( g, tmp );
1336 0 : e = s_max( gains_exp[j], gains_exp[jp] );
1337 :
1338 0 : tmp = mac_r( L_mult( pg, 13107 /*0.40f Q15*/ ), g, 19661 /*0.60f Q15*/ ); /*Q15 - gains_exp*/
1339 0 : x[i] = L_shl( Mpy_32_16_1( x[i], tmp ), e ); /*Qx*/
1340 0 : move32();
1341 :
1342 0 : tmp = mac_r( L_mult( pg, 6554 /*0.20f Q15*/ ), g, 26214 /*0.80f Q15*/ ); /*Q15 - gains_exp*/
1343 0 : x[i + 1] = L_shl( Mpy_32_16_1( x[i + 1], tmp ), e ); /*Qx*/
1344 0 : move32();
1345 :
1346 :
1347 0 : x[i + 2] = L_shl( Mpy_32_16_1( x[i + 2], gains[j] ), gains_exp[j] ); /*Qx*/
1348 0 : move32();
1349 :
1350 : /* common exponent for g and ng */
1351 0 : g = gains[j]; /*Q15 - gains_exp*/
1352 0 : move16();
1353 0 : tmp = sub( gains_exp[j], gains_exp[jn] );
1354 0 : if ( tmp > 0 )
1355 0 : ng = shr( ng, tmp );
1356 0 : if ( tmp < 0 )
1357 0 : g = shl( g, tmp );
1358 0 : e = s_max( gains_exp[j], gains_exp[jn] );
1359 :
1360 0 : tmp = mac_r( L_mult( g, 26214 /*0.80f Q15*/ ), ng, 6554 /*0.20f Q15*/ ); /*Q15 - gains_exp*/
1361 0 : x[i + 3] = L_shl( Mpy_32_16_1( x[i + 3], tmp ), e ); /*Qx*/
1362 0 : move32();
1363 :
1364 0 : tmp = mac_r( L_mult( g, 19661 /*0.60f Q15*/ ), ng, 13107 /*0.40f Q15*/ ); /*Q15 - gains_exp*/
1365 0 : x[i + 4] = L_shl( Mpy_32_16_1( x[i + 4], tmp ), e ); /*Qx*/
1366 0 : move32();
1367 :
1368 0 : jp = j;
1369 0 : move16();
1370 0 : j = jn;
1371 0 : move16();
1372 0 : jn = s_min( add( jn, 1 ), FDNS_NPTS - 1 );
1373 : }
1374 : }
1375 : ELSE /* no interpolation */
1376 : {
1377 0 : FOR( i = 0; i < FDNS_NPTS; i++ )
1378 : {
1379 0 : FOR( l = 0; l < k; l++ )
1380 : {
1381 0 : *x = L_shl( Mpy_32_16_1( *x, *gains ), *gains_exp ); /*Qx*/
1382 0 : move32();
1383 0 : x++;
1384 : }
1385 :
1386 0 : gains++;
1387 0 : gains_exp++;
1388 : }
1389 : }
1390 : }
1391 0 : }
1392 :
1393 17699 : void PsychAdaptLowFreqDeemph(
1394 : Word32 x[], /*Qx*/
1395 : const Word16 lpcGains[], /*Q15 - lpcGains_e*/
1396 : const Word16 lpcGains_e[],
1397 : Word16 lf_deemph_factors[] /*Q15*/ )
1398 : {
1399 : Word16 i;
1400 : Word16 max_val, max_e, fac, min, min_e, tmp, tmp_e;
1401 : Word32 L_tmp;
1402 : #ifndef ISSUE_1836_replace_overflow_libcom
1403 : #ifdef BASOP_NOGLOB_DECLARE_LOCAL
1404 : Flag Overflow = 0;
1405 : #endif
1406 : #endif
1407 :
1408 :
1409 17699 : assert( lpcGains[0] >= 0x4000 );
1410 :
1411 17699 : max_val = lpcGains[0]; /*Q15 - lpcGains_e*/
1412 17699 : move16();
1413 17699 : max_e = lpcGains_e[0];
1414 17699 : move16();
1415 17699 : min = lpcGains[0]; /*Q15 - lpcGains_e*/
1416 17699 : move16();
1417 17699 : min_e = lpcGains_e[0];
1418 17699 : move16();
1419 :
1420 : /* find minimum (min) and maximum (max_val) of LPC gains in low frequencies */
1421 159291 : FOR( i = 1; i < 9; i++ )
1422 : {
1423 141592 : IF( compMantExp16Unorm( lpcGains[i], lpcGains_e[i], min, min_e ) < 0 )
1424 : {
1425 107113 : min = lpcGains[i]; /*Q15 - lpcGains_e*/
1426 107113 : move16();
1427 107113 : min_e = lpcGains_e[i];
1428 107113 : move16();
1429 : }
1430 :
1431 141592 : IF( compMantExp16Unorm( lpcGains[i], lpcGains_e[i], max_val, max_e ) > 0 )
1432 : {
1433 23997 : max_val = lpcGains[i]; /*Q15 - lpcGains_e*/
1434 23997 : move16();
1435 23997 : max_e = lpcGains_e[i];
1436 23997 : move16();
1437 : }
1438 : }
1439 :
1440 17699 : min_e = add( min_e, 5 ); /* min *= 32.0f; */
1441 :
1442 17699 : test();
1443 17699 : IF( ( compMantExp16Unorm( max_val, max_e, min, min_e ) < 0 ) && ( min > 0 ) )
1444 : {
1445 : /* fac = tmp = (float)pow(max_val / min, 0.0078125f); */
1446 17699 : tmp_e = min_e;
1447 17699 : move16();
1448 17699 : tmp = Inv16( min, &tmp_e ); /*Q15 - tmp_e*/
1449 17699 : L_tmp = L_shl( L_mult( tmp, max_val ), add( tmp_e, max_e ) ); /* Q31 */
1450 17699 : L_tmp = BASOP_Util_Log2( L_tmp ); /* Q25 */
1451 17699 : L_tmp = L_shr( L_tmp, 7 ); /* 0.0078125f = 1.f/(1<<7) */
1452 17699 : L_tmp = BASOP_Util_InvLog2( L_tmp ); /* Q31 */
1453 : #ifdef ISSUE_1836_replace_overflow_libcom
1454 17699 : tmp = round_fx_sat( L_tmp ); /* Q15 */
1455 : #else
1456 : tmp = round_fx_o( L_tmp, &Overflow ); /* Q15 */
1457 : #endif
1458 17699 : fac = tmp; /* Q15 */
1459 17699 : move16();
1460 :
1461 : /* gradual lowering of lowest 32 bins; DC is lowered by (max_val/tmp)^1/4 */
1462 584067 : FOR( i = 31; i >= 0; i-- )
1463 : {
1464 566368 : x[i] = Mpy_32_16_1( x[i], fac );
1465 566368 : move32();
1466 566368 : if ( lf_deemph_factors != NULL )
1467 : {
1468 448768 : lf_deemph_factors[i] = mult_r( lf_deemph_factors[i], fac );
1469 448768 : move16();
1470 : }
1471 566368 : fac = mult_r( fac, tmp ); /* Q15 */
1472 : }
1473 : }
1474 17699 : }
1475 :
1476 115729 : void AdaptLowFreqDeemph(
1477 : Word32 x[], /*Q31 - x_e*/
1478 : Word16 x_e,
1479 : Word16 tcx_lpc_shaped_ari, /*Q0*/
1480 : Word16 lpcGains[], /*Q15 - lpcGains_e*/
1481 : Word16 lpcGains_e[],
1482 : const Word16 lg, /*Q0*/
1483 : Word16 lf_deemph_factors[] /*Q15*/ )
1484 : {
1485 :
1486 : Word16 i, i_max, i_max_old, lg_4;
1487 : Word32 v2, v4, tmp32;
1488 :
1489 115729 : tmp32 = 0; /* to avoid compilation warnings */
1490 115729 : move32();
1491 :
1492 115729 : IF( tcx_lpc_shaped_ari == 0 )
1493 : {
1494 101705 : v2 = L_shl( 2, sub( 31, x_e ) ); /* 2.0 */
1495 101705 : v4 = L_shl( v2, 1 ); /* 4.0 */
1496 101705 : lg_4 = shr( lg, 2 ); /* lg/4 */
1497 :
1498 : /* 1. find first magnitude maximum in lower quarter of spectrum */
1499 101705 : i_max = -1;
1500 101705 : move16();
1501 :
1502 620943 : FOR( i = 0; i < lg_4; i++ )
1503 : {
1504 617223 : IF( GE_32( L_abs( x[i] ), v4 ) )
1505 : {
1506 :
1507 : /* Debug initialization to catch illegal x[i] values. */
1508 97985 : tmp32 = 0;
1509 97985 : move32();
1510 :
1511 97985 : if ( x[i] < 0 )
1512 49194 : tmp32 = L_add( x[i], v2 ); /*Q31 - x_e*/
1513 97985 : if ( x[i] > 0 )
1514 48791 : tmp32 = L_sub( x[i], v2 ); /*Q31 - x_e*/
1515 :
1516 97985 : assert( tmp32 != 0 );
1517 :
1518 97985 : x[i] = tmp32; /*Q31 - x_e*/
1519 97985 : move32();
1520 97985 : i_max = i;
1521 97985 : move16();
1522 97985 : BREAK;
1523 : }
1524 : }
1525 :
1526 : /* 2. expand value range of all xi up to i_max: two extra steps */
1527 339947 : FOR( i = 0; i < i_max; i++ )
1528 : {
1529 238242 : x[i] = L_shr( x[i], 1 ); /*Q31 - x_e*/
1530 238242 : move32();
1531 238242 : lf_deemph_factors[i] = shr( lf_deemph_factors[i], 1 ); /*Q15*/
1532 238242 : move16();
1533 : }
1534 :
1535 : /* 3. find first magnitude maximum in lower quarter of spectrum */
1536 101705 : i_max_old = i_max; /*Q0*/
1537 101705 : move16();
1538 :
1539 101705 : IF( i_max_old >= 0 )
1540 : {
1541 97985 : i_max = -1;
1542 97985 : move16();
1543 :
1544 494425 : FOR( i = 0; i < lg_4; i++ )
1545 : {
1546 494410 : IF( GE_32( L_abs( x[i] ), v4 ) )
1547 : {
1548 97970 : assert( x[i] != 0 );
1549 97970 : if ( x[i] < 0 )
1550 49234 : tmp32 = L_add( x[i], v2 ); /*Q31 - x_e*/
1551 97970 : if ( x[i] >= 0 )
1552 48736 : tmp32 = L_sub( x[i], v2 ); /*Q31 - x_e*/
1553 97970 : x[i] = tmp32; /*Q31 - x_e*/
1554 97970 : move32();
1555 97970 : i_max = i;
1556 97970 : move16();
1557 97970 : BREAK;
1558 : }
1559 : }
1560 : }
1561 :
1562 : /* 4. expand value range of all xi up to i_max: two extra steps */
1563 497009 : FOR( i = 0; i < i_max; i++ )
1564 : {
1565 395304 : x[i] = L_shr( x[i], 1 ); /*Q31 - x_e*/
1566 395304 : move32();
1567 395304 : lf_deemph_factors[i] = shr( lf_deemph_factors[i], 1 ); /*Q15*/
1568 395304 : move16();
1569 : }
1570 :
1571 : /* 5. always expand two lines; lines could be at index 0 and 1! */
1572 101705 : i_max = s_max( i_max, i_max_old ); /*Q0*/
1573 101705 : i = add( i_max, 1 );
1574 :
1575 101705 : IF( x[i] < 0 )
1576 : {
1577 44957 : tmp32 = L_sub( x[i], L_negate( v4 ) );
1578 :
1579 44957 : if ( tmp32 > 0 )
1580 : {
1581 15794 : lf_deemph_factors[i] = shr( lf_deemph_factors[i], 1 ); /*Q15*/
1582 15794 : move16();
1583 : }
1584 44957 : if ( tmp32 <= 0 )
1585 : {
1586 29163 : x[i] = L_add( x[i], v2 ); /*Q31 - x_e*/
1587 29163 : move32();
1588 : }
1589 44957 : if ( tmp32 > 0 )
1590 : {
1591 15794 : x[i] = L_shr( x[i], 1 ); /*Q31 - x_e*/
1592 15794 : move32();
1593 : }
1594 : }
1595 : ELSE
1596 : {
1597 56748 : tmp32 = L_sub( x[i], v4 );
1598 :
1599 56748 : if ( tmp32 < 0 )
1600 : {
1601 26512 : lf_deemph_factors[i] = shr( lf_deemph_factors[i], 1 ); /*Q15*/
1602 26512 : move16();
1603 : }
1604 56748 : if ( tmp32 >= 0 )
1605 : {
1606 30236 : x[i] = L_sub( x[i], v2 ); /*Q31 - x_e*/
1607 30236 : move32();
1608 : }
1609 56748 : if ( tmp32 < 0 )
1610 : {
1611 26512 : x[i] = L_shr( x[i], 1 ); /*Q31 - x_e*/
1612 26512 : move32();
1613 : }
1614 : }
1615 101705 : i = add( i, 1 );
1616 :
1617 101705 : IF( x[i] < 0 )
1618 : {
1619 43609 : tmp32 = L_sub( x[i], L_negate( v4 ) );
1620 :
1621 43609 : if ( tmp32 > 0 )
1622 : {
1623 16861 : lf_deemph_factors[i] = shr( lf_deemph_factors[i], 1 ); /*Q15*/
1624 16861 : move16();
1625 : }
1626 43609 : if ( tmp32 <= 0 )
1627 : {
1628 26748 : x[i] = L_add( x[i], v2 ); /*Q31 - x_e*/
1629 26748 : move32();
1630 : }
1631 43609 : if ( tmp32 > 0 )
1632 : {
1633 16861 : x[i] = L_shr( x[i], 1 ); /*Q31 - x_e*/
1634 16861 : move32();
1635 : }
1636 : }
1637 : ELSE
1638 : {
1639 58096 : tmp32 = L_sub( x[i], v4 );
1640 :
1641 58096 : if ( tmp32 < 0 )
1642 : {
1643 31699 : lf_deemph_factors[i] = shr( lf_deemph_factors[i], 1 ); /*Q15*/
1644 31699 : move16();
1645 : }
1646 58096 : if ( tmp32 >= 0 )
1647 : {
1648 26397 : x[i] = L_sub( x[i], v2 ); /*Q31 - x_e*/
1649 26397 : move32();
1650 : }
1651 58096 : if ( tmp32 < 0 )
1652 : {
1653 31699 : x[i] = L_shr( x[i], 1 ); /*Q31 - x_e*/
1654 31699 : move32();
1655 : }
1656 : }
1657 : }
1658 : ELSE /*if(!tcx_lpc_shaped_ari)*/
1659 : {
1660 14024 : PsychAdaptLowFreqDeemph( x, lpcGains, lpcGains_e, lf_deemph_factors );
1661 : } /*if(!tcx_lpc_shaped_ari)*/
1662 115729 : }
1663 :
1664 645 : void tcx_noise_filling(
1665 : Word32 *Q, /*Q31 - Q_e*/
1666 : Word16 Q_e,
1667 : Word16 seed,
1668 : const Word16 iFirstLine, /*Q0*/
1669 : const Word16 lowpassLine, /*Q0*/
1670 : const Word16 nTransWidth, /*Q0*/
1671 : const Word16 L_frame, /*Q0*/
1672 : const Word16 tiltCompFactor, /*Q15*/
1673 : Word16 fac_ns, /*Q15*/
1674 : Word16 *infoTCXNoise, /*Q0*/
1675 : const Word16 element_mode /* i : IVAS element mode Q0*/
1676 : )
1677 : {
1678 : Word16 i, m, segmentOffset;
1679 : Word16 win; /* window coefficient */
1680 : Word16 tilt_factor;
1681 : Word32 nrg;
1682 : Word16 tmp1, tmp2, s;
1683 : Word32 tmp32;
1684 :
1685 :
1686 : /* get inverse frame length */
1687 645 : tmp1 = getInvFrameLen( L_frame ); /*Q21*/
1688 :
1689 : /* tilt_factor = (float)pow(max_val(0.375f, tiltCompFactor), 1.0f/(float)L_frame); */
1690 645 : tmp32 = BASOP_Util_Log2( L_deposit_h( s_max( 0x3000, tiltCompFactor ) ) ); /* 6Q25 */
1691 645 : tmp32 = L_shr( Mpy_32_16_1( tmp32, tmp1 ), 6 ); /*Q25*/
1692 : BASOP_SATURATE_WARNING_OFF_EVS;
1693 645 : tilt_factor = round_fx_sat( BASOP_Util_InvLog2( tmp32 ) ); /*Q15*/
1694 : BASOP_SATURATE_WARNING_ON_EVS;
1695 :
1696 : /* find last nonzero line below iFirstLine, use it as start offset */
1697 645 : i = iFirstLine;
1698 645 : move16();
1699 645 : tmp1 = shr( iFirstLine, 1 ); /*Q0*/
1700 645 : IF( EQ_16( element_mode, IVAS_CPE_MDCT ) ) /* ... but only in mono or parametric stereo since it may cause binaural unmasking in discrete stereo */
1701 : {
1702 0 : segmentOffset = i;
1703 0 : move16();
1704 : }
1705 : ELSE
1706 : {
1707 2850 : FOR( ; i > tmp1; i-- )
1708 : {
1709 2844 : IF( Q[i] != 0 )
1710 : {
1711 639 : BREAK;
1712 : }
1713 : }
1714 : /* fac_ns *= (float)pow(tilt_factor, (float)i); */
1715 30073 : FOR( m = 0; m < i; m++ )
1716 : {
1717 29428 : fac_ns = mult_r( fac_ns, tilt_factor ); /*Q15*/
1718 : }
1719 645 : i = add( i, 1 );
1720 645 : segmentOffset = i;
1721 : }
1722 645 : nrg = L_deposit_l( 1 );
1723 645 : win = 0;
1724 645 : move16();
1725 :
1726 138124 : FOR( ; i < lowpassLine; i++ )
1727 : {
1728 137479 : fac_ns = mult_r( fac_ns, tilt_factor ); /*Q15*/
1729 :
1730 137479 : IF( Q[i] != 0 )
1731 : {
1732 18510 : IF( win > 0 )
1733 : {
1734 : /* RMS-normalize current noise-filled segment */
1735 12196 : tmp1 = BASOP_Util_Divide3216_Scale( nrg, sub( i, segmentOffset ), &s ); /* mean */
1736 12196 : s = add( s, 9 - 15 ); /* scaling */
1737 12196 : tmp1 = ISqrt16( tmp1, &s ); /* 1/RMS Q15 - s*/
1738 12196 : tmp1 = mult_r( tmp1, inv_int[nTransWidth] ); /* compensate win Q15 - s*/
1739 12196 : s = add( s, sub( 16, Q_e ) ); /* scaling */
1740 :
1741 12196 : tmp2 = sub( i, win );
1742 12196 : IF( LT_16( segmentOffset, tmp2 ) )
1743 : {
1744 34279 : FOR( m = segmentOffset; m < tmp2; m++ )
1745 : {
1746 31298 : Q[m] = L_shl( Mpy_32_16_1( Q[m], tmp1 ), s ); /*Q31 - Q_e*/
1747 31298 : move32();
1748 : }
1749 : }
1750 :
1751 12196 : tmp2 = mult( tmp1, inv_int[nTransWidth] );
1752 12196 : tmp1 = extract_l( L_mult0( tmp2, win ) );
1753 64745 : FOR( m = sub( i, win ); m < i; m++ )
1754 : {
1755 52549 : Q[m] = L_shl( Mpy_32_16_1( Q[m], tmp1 ), s ); /*Q31 - Q_e*/
1756 52549 : move32();
1757 52549 : win = sub( win, 1 );
1758 52549 : tmp1 = sub( tmp1, tmp2 );
1759 : }
1760 :
1761 12196 : nrg = L_deposit_l( 1 ); /* start new segment: reset noise segment energy */
1762 : }
1763 18510 : segmentOffset = add( i, 1 );
1764 : }
1765 : ELSE /* line is zero, so fill line and update window and energy */
1766 : {
1767 118969 : if ( LT_16( win, nTransWidth ) )
1768 : {
1769 56867 : win = add( win, 1 );
1770 : }
1771 :
1772 118969 : Random( &seed );
1773 118969 : Q[i] = L_mult0( mult( seed, fac_ns ), win ); /*Q31 - Q_e*/
1774 118969 : move32();
1775 :
1776 118969 : tmp1 = shr( seed, 4 );
1777 118969 : nrg = L_mac0( nrg, tmp1, tmp1 ); /* sum up energy of current noise segment */
1778 :
1779 118969 : if ( infoTCXNoise ) /* set noiseflags for IGF */
1780 : {
1781 118969 : infoTCXNoise[i] = 1;
1782 118969 : move16();
1783 : }
1784 : }
1785 : }
1786 :
1787 645 : IF( win > 0 )
1788 : {
1789 : /* RMS-normalize uppermost noise-filled segment */
1790 619 : tmp1 = BASOP_Util_Divide3216_Scale( nrg, sub( lowpassLine, segmentOffset ), &s ); /* mean */
1791 619 : s = add( s, 9 - 15 ); /* compensate energy scaling */
1792 619 : tmp1 = ISqrt16( tmp1, &s ); /* 1/RMS Q15 - s*/
1793 619 : tmp1 = mult_r( tmp1, inv_int[nTransWidth] ); /* compensate win Q15 - s*/
1794 619 : s = add( s, sub( 16, Q_e ) ); /* compensate noise scaling */
1795 :
1796 35741 : FOR( m = segmentOffset; m < lowpassLine; m++ )
1797 : {
1798 35122 : Q[m] = L_shl( Mpy_32_16_1( Q[m], tmp1 ), s ); /*Q31 - Q_e*/
1799 35122 : move32();
1800 : }
1801 : }
1802 645 : }
1803 :
1804 803199 : void tcx_noise_filling_with_shift(
1805 : Word32 *Q, /*Q31 - Q_e*/
1806 : Word16 *Q_e,
1807 : Word16 seed, /*Q0*/
1808 : const Word16 iFirstLine, /*Q0*/
1809 : const Word16 lowpassLine, /*Q0*/
1810 : const Word16 nTransWidth, /*Q0*/
1811 : const Word16 L_frame, /*Q0*/
1812 : const Word16 tiltCompFactor, /*Q0*/
1813 : Word16 fac_ns, /*Q15*/
1814 : Word16 *infoTCXNoise, /*Q0*/
1815 : const Word16 element_mode /* i : IVAS element mode Q0*/
1816 : )
1817 : {
1818 : Word16 i, m, segmentOffset;
1819 : Word16 win; /* window coefficient */
1820 : Word16 tilt_factor;
1821 : Word32 nrg;
1822 : Word16 tmp1, tmp2, s;
1823 : Word32 tmp32;
1824 : Word16 new_Q_e[N_MAX];
1825 :
1826 803199 : set16_fx( new_Q_e, *Q_e, N_MAX );
1827 :
1828 : /* get inverse frame length */
1829 803199 : tmp1 = getInvFrameLen( L_frame ); /*Q21*/
1830 :
1831 : /* tilt_factor = (float)pow(max_val(0.375f, tiltCompFactor), 1.0f/(float)L_frame); */
1832 803199 : tmp32 = BASOP_Util_Log2( L_deposit_h( s_max( 0x3000, tiltCompFactor ) ) ); /* 6Q25 */
1833 803199 : tmp32 = L_shr( Mpy_32_16_1( tmp32, tmp1 ), 6 ); /*Q25*/
1834 : BASOP_SATURATE_WARNING_OFF_EVS;
1835 803199 : tilt_factor = round_fx_sat( BASOP_Util_InvLog2( tmp32 ) ); /*Q15*/
1836 : BASOP_SATURATE_WARNING_ON_EVS;
1837 :
1838 : /* find last nonzero line below iFirstLine, use it as start offset */
1839 803199 : i = iFirstLine;
1840 803199 : move16();
1841 803199 : tmp1 = shr( iFirstLine, 1 );
1842 803199 : IF( EQ_16( element_mode, IVAS_CPE_MDCT ) ) /* ... but only in mono or parametric stereo since it may cause binaural unmasking in discrete stereo */
1843 : {
1844 598573 : segmentOffset = i;
1845 598573 : move16();
1846 : }
1847 : ELSE
1848 : {
1849 590911 : FOR( ; i > tmp1; i-- )
1850 : {
1851 589808 : IF( Q[i] != 0 )
1852 : {
1853 203523 : BREAK;
1854 : }
1855 : }
1856 : /* fac_ns *= (float)pow(tilt_factor, (float)i); */
1857 14400130 : FOR( m = 0; m < i; m++ )
1858 : {
1859 14195504 : fac_ns = mult_r( fac_ns, tilt_factor ); /*Q15*/
1860 : }
1861 204626 : i = add( i, 1 );
1862 204626 : segmentOffset = i;
1863 204626 : move16();
1864 : }
1865 803199 : nrg = L_deposit_l( 1 );
1866 803199 : win = 0;
1867 803199 : move16();
1868 :
1869 358649443 : FOR( ; i < lowpassLine; i++ )
1870 : {
1871 357846244 : fac_ns = mult_r( fac_ns, tilt_factor ); /*Q15*/
1872 :
1873 357846244 : IF( Q[i] != 0 )
1874 : {
1875 85051171 : IF( win > 0 )
1876 : {
1877 : /* RMS-normalize current noise-filled segment */
1878 39542971 : tmp1 = BASOP_Util_Divide3216_Scale( nrg, sub( i, segmentOffset ), &s ); /* mean */
1879 : // Q-factor of nrg is -8. exp = 31-(-8) = 39
1880 39542971 : s = add( s, 39 - 15 ); /* scaling */
1881 39542971 : tmp1 = ISqrt16( tmp1, &s ); /* 1/RMS Q15 - s*/
1882 39542971 : tmp1 = mult_r( tmp1, inv_int[nTransWidth] ); /* compensate win Q15 - s*/
1883 :
1884 39542971 : tmp2 = sub( i, win );
1885 39542971 : IF( LT_16( segmentOffset, tmp2 ) )
1886 : {
1887 68762404 : FOR( m = segmentOffset; m < tmp2; m++ )
1888 : {
1889 63434018 : Word16 nrm = 31;
1890 63434018 : move16();
1891 63434018 : Q[m] = Mpy_32_16_1( Q[m], tmp1 ); /*Q31 - Q_e*/
1892 63434018 : move32();
1893 63434018 : IF( Q[m] )
1894 : {
1895 63427571 : nrm = norm_l( Q[m] );
1896 : }
1897 63434018 : Q[m] = L_shl( Q[m], nrm ); /*Q31 - Q_e + nrm*/
1898 63434018 : move32();
1899 63434018 : new_Q_e[m] = sub( add( new_Q_e[m], s ), nrm );
1900 63434018 : move32();
1901 : }
1902 : }
1903 :
1904 39542971 : tmp2 = mult( tmp1, inv_int[nTransWidth] ); /*Q15 - s*/
1905 39542971 : tmp1 = extract_l( L_mult0( tmp2, win ) ); /*Q15 - s*/
1906 155149860 : FOR( m = sub( i, win ); m < i; m++ )
1907 : {
1908 115606889 : Word16 nrm = 31;
1909 :
1910 115606889 : Q[m] = Mpy_32_16_1( Q[m], tmp1 ); /*Q31 - Q_e*/
1911 115606889 : move32();
1912 115606889 : IF( Q[m] )
1913 : {
1914 115596272 : nrm = norm_l( Q[m] );
1915 : }
1916 115606889 : Q[m] = L_shl( Q[m], nrm ); /*Q31 - Q_e*/
1917 115606889 : move32();
1918 115606889 : new_Q_e[m] = sub( add( new_Q_e[m], s ), nrm );
1919 115606889 : move32();
1920 115606889 : win = sub( win, 1 );
1921 115606889 : tmp1 = sub( tmp1, tmp2 );
1922 : }
1923 :
1924 39542971 : nrg = L_deposit_l( 1 ); /* start new segment: reset noise segment energy */
1925 : }
1926 85051171 : segmentOffset = add( i, 1 );
1927 : }
1928 : ELSE /* line is zero, so fill line and update window and energy */
1929 : {
1930 272795073 : IF( LT_16( win, nTransWidth ) )
1931 : {
1932 120706883 : win = add( win, 1 );
1933 : }
1934 :
1935 272795073 : Word16 nrm = 31;
1936 272795073 : move16();
1937 :
1938 272795073 : Random( &seed );
1939 272795073 : Q[i] = L_mult0( mult( seed, fac_ns ), win );
1940 272795073 : move32();
1941 272795073 : IF( Q[i] )
1942 : {
1943 272766063 : nrm = norm_l( Q[i] );
1944 : }
1945 272795073 : Q[i] = L_shl( Q[i], nrm ); /*Q31 - Q_e*/
1946 272795073 : move32();
1947 272795073 : new_Q_e[i] = sub( 31, nrm );
1948 :
1949 272795073 : tmp1 = shr( seed, 4 );
1950 272795073 : nrg = L_mac0( nrg, tmp1, tmp1 ); /* sum up energy of current noise segment Q-8*/
1951 :
1952 272795073 : IF( infoTCXNoise ) /* set noiseflags for IGF */
1953 : {
1954 157458937 : infoTCXNoise[i] = 1;
1955 157458937 : move16();
1956 : }
1957 : }
1958 : }
1959 :
1960 803199 : IF( win > 0 )
1961 : {
1962 : /* RMS-normalize uppermost noise-filled segment */
1963 745256 : tmp1 = BASOP_Util_Divide3216_Scale( nrg, sub( lowpassLine, segmentOffset ), &s ); /* mean */
1964 : // Q-factor of nrg is -8. exp = 31-(-8) = 39
1965 745256 : s = add( s, 39 - 15 ); /* compensate energy scaling */
1966 745256 : tmp1 = ISqrt16( tmp1, &s ); /* 1/RMS Q15 - s*/
1967 745256 : tmp1 = mult_r( tmp1, inv_int[nTransWidth] ); /* compensate win Q15 - s*/
1968 :
1969 94499422 : FOR( m = segmentOffset; m < lowpassLine; m++ )
1970 : {
1971 93754166 : Word16 nrm = 31;
1972 93754166 : move16();
1973 : /*
1974 : at this point:
1975 : - flt Q[m] = (Q[m] * 2^(new_Q_e[m] - 31)) / (nTransWidth*nTransWidth)
1976 : - flt tmp1 = (tmp1 * 2^(s - 15)) * (nTransWidth*nTransWidth)
1977 : */
1978 93754166 : Q[m] = Mpy_32_16_1( Q[m], tmp1 ); /*Q15 - Q_e - s*/
1979 93754166 : move32();
1980 93754166 : IF( Q[m] )
1981 : {
1982 93742220 : nrm = norm_l( Q[m] );
1983 : }
1984 93754166 : Q[m] = L_shl( Q[m], nrm ); /*Q15 - Q_e - s + nrm*/
1985 93754166 : move32();
1986 93754166 : new_Q_e[m] = add( new_Q_e[m], s - nrm );
1987 93754166 : move32();
1988 : }
1989 : }
1990 :
1991 803199 : Word16 max_e = 0;
1992 803199 : move16();
1993 427638669 : FOR( i = 0; i < lowpassLine; i++ )
1994 : {
1995 426835470 : max_e = s_max( max_e, new_Q_e[i] );
1996 : }
1997 :
1998 427638669 : FOR( i = 0; i < lowpassLine; i++ )
1999 : {
2000 426835470 : Q[i] = L_shr( Q[i], sub( max_e, new_Q_e[i] ) ); /*Q31 - Q_e*/
2001 426835470 : move32();
2002 : }
2003 :
2004 803199 : *Q_e = max_e;
2005 803199 : move16();
2006 803199 : }
2007 :
2008 :
2009 : /*---------------------------------------------------------------
2010 : * InitTnsConfigs()
2011 : *--------------------------------------------------------------*/
2012 :
2013 :
2014 18138 : void InitTnsConfigs(
2015 : const Word16 bwidth, /*Q0*/
2016 : const Word16 L_frame, /*Q0*/
2017 : STnsConfig tnsConfig[2][2],
2018 : const Word16 igfStopFreq, /*Q0*/
2019 : const Word32 total_brate, /*Q0*/
2020 : const Word16 element_mode, /*Q0*/
2021 : const Word16 MCT_flag /*Q0*/ )
2022 : {
2023 18138 : IF( GT_32( total_brate, ACELP_32k ) )
2024 : {
2025 14792 : InitTnsConfiguration( bwidth, shr( L_frame, 1 ), &tnsConfig[0][0], igfStopFreq, total_brate, element_mode, MCT_flag );
2026 : }
2027 18138 : InitTnsConfiguration( bwidth, L_frame, &tnsConfig[1][0], igfStopFreq, total_brate, element_mode, MCT_flag );
2028 18138 : InitTnsConfiguration( bwidth, add( L_frame, shr( L_frame, 2 ) ), &tnsConfig[1][1], igfStopFreq, total_brate, element_mode, MCT_flag );
2029 18138 : }
2030 :
2031 0 : void InitTnsConfigs_ivas_fx(
2032 : const Word16 bwidth, /*Q0*/
2033 : const Word16 L_frame, /*Q0*/
2034 : STnsConfig tnsConfig[2][2],
2035 : const Word16 igfStopFreq, /*Q0*/
2036 : const Word32 total_brate, /*Q0*/
2037 : const Word16 element_mode, /*Q0*/
2038 : const Word16 MCT_flag /*Q0*/ )
2039 : {
2040 0 : IF( GT_32( total_brate, ACELP_32k ) )
2041 : {
2042 0 : InitTnsConfiguration_ivas_fx( bwidth, shr( L_frame, 1 ), &tnsConfig[0][0], igfStopFreq, total_brate, element_mode, MCT_flag );
2043 : }
2044 0 : InitTnsConfiguration_ivas_fx( bwidth, L_frame, &tnsConfig[1][0], igfStopFreq, total_brate, element_mode, MCT_flag );
2045 0 : InitTnsConfiguration_ivas_fx( bwidth, add( L_frame, shr( L_frame, 2 ) ), &tnsConfig[1][1], igfStopFreq, total_brate, element_mode, MCT_flag );
2046 0 : }
2047 :
2048 :
2049 862527 : void SetTnsConfig(
2050 : TCX_CONFIG_HANDLE hTcxCfg, /* i : configuration of TCX */
2051 : const Word16 isTCX20, /*Q0*/
2052 : const Word16 isAfterACELP /*Q0*/ )
2053 : {
2054 862527 : move16();
2055 862527 : hTcxCfg->pCurrentTnsConfig = &hTcxCfg->tnsConfig[isTCX20][isAfterACELP];
2056 862527 : assert( hTcxCfg->pCurrentTnsConfig != NULL );
2057 862527 : }
2058 : #define IVAS_CODE_TCX_UTIL
2059 : #ifdef IVAS_CODE_TCX_UTIL
2060 : /*-------------------------------------------------------------------*
2061 : * SetAllowTnsOnWhite
2062 : *
2063 : * set TNS config flag for possible application of TNS in the whitened domain
2064 : *-------------------------------------------------------------------*/
2065 :
2066 18124 : void SetAllowTnsOnWhite(
2067 : STnsConfig tnsConfig[2][2], /* o : updated TNS configurations */
2068 : const Word8 allowTnsOnWhite /* i : flag for TNS in whiteded domain mode Q0*/
2069 : )
2070 : {
2071 18124 : tnsConfig[0][0].allowTnsOnWhite = allowTnsOnWhite; /*Q0*/
2072 18124 : move16();
2073 18124 : tnsConfig[0][1].allowTnsOnWhite = allowTnsOnWhite;
2074 18124 : move16();
2075 18124 : tnsConfig[1][0].allowTnsOnWhite = allowTnsOnWhite;
2076 18124 : move16();
2077 18124 : tnsConfig[1][1].allowTnsOnWhite = allowTnsOnWhite;
2078 18124 : move16();
2079 18124 : return;
2080 : }
2081 : #endif
2082 : #undef IVAS_CODE_TCX_UTIL
2083 :
2084 0 : void tcx_get_gain(
2085 : Word32 *x, /* i: spectrum 1 Q31 - x_e*/
2086 : Word16 x_e, /* i: spectrum 1 exponent */
2087 : Word32 *y, /* i: spectrum 2 Q31 - y_e*/
2088 : Word16 y_e, /* i: spectrum 2 exponent */
2089 : Word16 n, /* i: length Q0*/
2090 : Word16 *gain, /* o: gain Q15 - gain_e*/
2091 : Word16 *gain_e, /* o: gain exponent */
2092 : Word32 *en_y, /* o: energy of y (optional) Q31 - en_y_e*/
2093 : Word16 *en_y_e /* o: energy of y exponent (optional) */
2094 : )
2095 : {
2096 : Word32 maxX, minX, maxY, minY;
2097 : Word32 corr, ener;
2098 : Word16 sx, sy, corr_e, ener_e;
2099 : Word16 i, tmp;
2100 : #ifndef ISSUE_1836_replace_overflow_libcom
2101 : #ifdef BASOP_NOGLOB_DECLARE_LOCAL
2102 : Flag Overflow = 0;
2103 : #endif
2104 : #endif
2105 :
2106 0 : maxX = L_deposit_l( 1 );
2107 0 : maxY = L_deposit_l( 1 );
2108 0 : minX = L_deposit_l( -1 );
2109 0 : minY = L_deposit_l( -1 );
2110 0 : FOR( i = 0; i < n; i++ )
2111 : {
2112 0 : if ( x[i] > 0 )
2113 0 : maxX = L_max( maxX, x[i] ); /*Q31 - x_e*/
2114 0 : if ( x[i] < 0 )
2115 0 : minX = L_min( minX, x[i] ); /*Q31 - x_e*/
2116 :
2117 0 : if ( y[i] > 0 )
2118 0 : maxY = L_max( maxY, y[i] ); /*Q31 - y_e*/
2119 0 : if ( y[i] < 0 )
2120 0 : minY = L_min( minY, y[i] ); /*Q31 - y_e*/
2121 : }
2122 0 : sx = s_min( norm_l( maxX ), norm_l( minX ) );
2123 0 : sy = s_min( norm_l( maxY ), norm_l( minY ) );
2124 0 : sx = sub( sx, 4 );
2125 0 : sy = sub( sy, 4 );
2126 :
2127 0 : ener = L_deposit_l( 0 );
2128 0 : corr = L_deposit_l( 0 );
2129 0 : FOR( i = 0; i < n; i++ )
2130 : {
2131 0 : tmp = round_fx( L_shl( y[i], sy ) ); /*Q15 - y_e + sy*/
2132 0 : ener = L_mac0( ener, tmp, tmp ); /*Q30 - 2*(y_e - sy)*/
2133 0 : corr = L_mac0( corr, tmp, round_fx( L_shl( x[i], sx ) ) ); /*Q30 - 2*(x_e - sx + y_e - sy)*/
2134 : }
2135 :
2136 0 : if ( ener == 0 )
2137 0 : ener = L_deposit_l( 1 );
2138 :
2139 0 : ener_e = add( shl( sub( y_e, sy ), 1 ), 1 );
2140 0 : corr_e = add( sub( add( x_e, y_e ), add( sx, sy ) ), 1 );
2141 :
2142 0 : tmp = sub( norm_l( corr ), 1 );
2143 0 : corr = L_shl( corr, tmp ); /*Q31 - corr_e + tmp*/
2144 0 : corr_e = sub( corr_e, tmp );
2145 :
2146 0 : tmp = norm_l( ener );
2147 0 : ener = L_shl( ener, tmp ); /*Q31 - ener_e + tmp*/
2148 0 : ener_e = sub( ener_e, tmp );
2149 :
2150 : #ifdef ISSUE_1836_replace_overflow_libcom
2151 0 : tmp = div_s( abs_s( round_fx_sat( corr ) ), round_fx_sat( ener ) ); /*Q15 - (corr_e - ener_e)*/
2152 : #else
2153 : tmp = div_s( abs_s( round_fx_o( corr, &Overflow ) ), round_fx_o( ener, &Overflow ) ); /*Q15 - (corr_e - ener_e)*/
2154 : #endif
2155 0 : if ( corr < 0 )
2156 0 : tmp = negate( tmp );
2157 :
2158 0 : *gain = tmp;
2159 0 : move16();
2160 0 : *gain_e = sub( corr_e, ener_e );
2161 0 : move16();
2162 :
2163 0 : if ( en_y != NULL )
2164 : {
2165 0 : *en_y = ener; /*Q31 - ener_e*/
2166 0 : move32();
2167 : }
2168 0 : if ( en_y_e != NULL )
2169 : {
2170 0 : *en_y_e = ener_e;
2171 0 : move16();
2172 : }
2173 0 : }
2174 41 : void init_TCX_config(
2175 : TCX_CONFIG_HANDLE hTcxCfg,
2176 : Word16 L_frame, /*Q0*/
2177 : Word16 fscale, /*Q0*/
2178 : Word16 L_frameTCX, /*Q0*/
2179 : Word16 fscaleFB /*Q0*/ )
2180 : {
2181 : /* Initialize the TCX MDCT windows */
2182 41 : hTcxCfg->tcx_mdct_window_length = extract_l( L_shr( L_mult0( L_LOOK_12k8, fscale ), LD_FSCALE_DENOM ) ); /*Q0*/
2183 41 : move16();
2184 41 : hTcxCfg->tcx_mdct_window_delay = hTcxCfg->tcx_mdct_window_length; /*Q0*/
2185 41 : move16();
2186 :
2187 41 : hTcxCfg->tcx_mdct_window_half_length = extract_l( L_shr( L_mult0( L_LOOK_12k8 - NS2SA( 12800, 5000000L ), fscale ), LD_FSCALE_DENOM ) );
2188 41 : move16();
2189 41 : hTcxCfg->tcx_mdct_window_min_length = shr( L_frame, 4 ); /* 1.25ms Q0*/
2190 41 : move16();
2191 41 : hTcxCfg->tcx_mdct_window_trans_length = shr( L_frame, 4 ); /* 1.25ms Q0*/
2192 41 : move16();
2193 41 : hTcxCfg->tcx5Size = shr( L_frame, 2 ); /* 5ms Q0*/
2194 41 : move16();
2195 41 : hTcxCfg->tcx_mdct_window_lengthFB = extract_l( L_shr( L_mult0( L_LOOK_12k8, fscaleFB ), LD_FSCALE_DENOM ) ); /*Q0*/
2196 41 : move16();
2197 41 : hTcxCfg->tcx_mdct_window_delayFB = hTcxCfg->tcx_mdct_window_lengthFB; /*Q0*/
2198 41 : move16();
2199 :
2200 41 : hTcxCfg->tcx_mdct_window_half_lengthFB = extract_l( L_shr( L_mult0( L_LOOK_12k8 - NS2SA( 12800, 5000000L ), fscaleFB ), LD_FSCALE_DENOM ) ); /*Q0*/
2201 41 : move16();
2202 41 : hTcxCfg->tcx_mdct_window_min_lengthFB = shr( L_frameTCX, 4 ); /* 1.25ms Q0*/
2203 41 : move16();
2204 41 : hTcxCfg->tcx_mdct_window_trans_lengthFB = shr( L_frameTCX, 4 ); /* 1.25ms Q0*/
2205 41 : move16();
2206 41 : hTcxCfg->tcx5SizeFB = shr( L_frameTCX, 2 ); /* 5ms Q0*/
2207 41 : move16();
2208 41 : mdct_window_sine( hTcxCfg->tcx_mdct_window, hTcxCfg->tcx_mdct_window_length );
2209 41 : mdct_window_sine( hTcxCfg->tcx_mdct_window_half, hTcxCfg->tcx_mdct_window_half_length );
2210 41 : mdct_window_sine( hTcxCfg->tcx_mdct_window_minimum, hTcxCfg->tcx_mdct_window_min_length );
2211 41 : mdct_window_sine( hTcxCfg->tcx_mdct_window_trans, hTcxCfg->tcx_mdct_window_trans_length );
2212 :
2213 41 : mdct_window_sine( hTcxCfg->tcx_mdct_windowFB, hTcxCfg->tcx_mdct_window_lengthFB );
2214 41 : mdct_window_sine( hTcxCfg->tcx_mdct_window_halfFB, hTcxCfg->tcx_mdct_window_half_lengthFB );
2215 41 : mdct_window_sine( hTcxCfg->tcx_mdct_window_minimumFB, hTcxCfg->tcx_mdct_window_min_lengthFB );
2216 41 : mdct_window_sine( hTcxCfg->tcx_mdct_window_transFB, hTcxCfg->tcx_mdct_window_trans_lengthFB );
2217 :
2218 : /*ALDO windows for MODE2*/
2219 41 : mdct_window_aldo( hTcxCfg->tcx_aldo_window_1, hTcxCfg->tcx_aldo_window_1_trunc, hTcxCfg->tcx_aldo_window_2, L_frame );
2220 41 : mdct_window_aldo( hTcxCfg->tcx_aldo_window_1_FB, hTcxCfg->tcx_aldo_window_1_FB_trunc, hTcxCfg->tcx_aldo_window_2_FB, L_frameTCX );
2221 41 : }
|