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 1670436 : Word16 getInvFrameLen( /* returns 1/L_frame in Q21 format */
21 : const Word16 L_frame )
22 : {
23 : Word16 idx, s;
24 :
25 1670436 : s = norm_s( L_frame );
26 1670436 : idx = shl( L_frame, s );
27 :
28 1670436 : assert( ( idx == 0x4000 ) || ( idx == 0x4B00 ) || ( idx == 0x5000 ) || ( idx == 0x5A00 ) || ( idx == 0x6000 ) || ( idx == 0x6400 ) || ( idx == 0x7800 ) );
29 :
30 1670436 : idx = mult_r( idx, 0x10 ); /* idx = shr(add(idx, 0x0400), 11); */
31 1670436 : idx = s_and( idx, 7 );
32 :
33 :
34 1670436 : return shl( L_frame_inv[idx], sub( s, 7 ) );
35 : }
36 : /*-------------------------------------------------------------------*
37 : *tcx_get_windows()
38 : *
39 : *
40 : * ------------------------------------------------------------------ - */
41 2850 : 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 2850 : 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 2850 : 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 2850 : case FULL_OVERLAP:
129 2850 : *left_overlap = hTcxCfg->tcx_mdct_window_lengthFB; /*Q0*/
130 2850 : move16();
131 2850 : *left_win = hTcxCfg->tcx_aldo_window_1_FB_trunc; /*Q15*/
132 2850 : BREAK;
133 0 : default:
134 0 : assert( !"Not supported overlap" );
135 : }
136 :
137 : /* Right part */
138 2850 : 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 2850 : case FULL_OVERLAP:
156 2850 : *right_overlap = hTcxCfg->tcx_mdct_window_delayFB; /*Q0*/
157 2850 : move16();
158 2850 : *right_win = hTcxCfg->tcx_aldo_window_2_FB; /*Q15*/
159 2850 : BREAK;
160 0 : default:
161 0 : assert( !"Not supported overlap" );
162 : }
163 : }
164 2850 : }
165 :
166 2850 : 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 2850 : n = shr( left_overlap, 1 ); /*Q0*/
180 494950 : FOR( w = 0; w < n; w++ )
181 : {
182 492100 : *output++ = mult_r( *signal++, left_win[w].v.im ); /*Qx*/
183 492100 : move16();
184 : }
185 494950 : FOR( w = 0; w < n; w++ )
186 : {
187 492100 : *output++ = mult_r( *signal++, left_win[n - 1 - w].v.re ); /*Qx*/
188 492100 : move16();
189 : }
190 :
191 : /* Non overlapping region */
192 2850 : n = sub( L_frame, shr( add( left_overlap, right_overlap ), 1 ) ); /*Q0*/
193 1268250 : FOR( w = 0; w < n; w++ )
194 : {
195 1265400 : *output++ = *signal++; /*Qx*/
196 1265400 : move16();
197 : }
198 :
199 : /* Right overlap */
200 2850 : n = shr( right_overlap, 1 ); /*Q0*/
201 494950 : FOR( w = 0; w < n; w++ )
202 : {
203 492100 : *output++ = mult_r( *signal++, right_win[w].v.re ); /*Qx*/
204 492100 : move16();
205 : }
206 494950 : FOR( w = 0; w < n; w++ )
207 : {
208 492100 : *output++ = mult_r( *signal++, right_win[n - 1 - w].v.im ); /*Qx*/
209 492100 : move16();
210 : }
211 2850 : }
212 : /*-------------------------------------------------------------------*
213 : * WindowSignal()
214 : *
215 : *
216 : *-------------------------------------------------------------------*/
217 2850 : 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 2850 : 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 2850 : 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 2850 : tcx_windowing_analysis( in - sub( shr( l, 1 ), offset ), *L_frame, l, left_win, r, right_win, out );
267 2850 : test();
268 2850 : test();
269 2850 : 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 2850 : p = hTcxCfg->tcx_mdct_window_minimum; /*Q15*/
276 2850 : tmp = shr( hTcxCfg->tcx_mdct_window_min_length, 1 ); /*Q0*/
277 2850 : IF( fullband != 0 )
278 : {
279 2850 : p = hTcxCfg->tcx_mdct_window_minimumFB; /*Q15*/
280 2850 : tmp = shr( hTcxCfg->tcx_mdct_window_min_lengthFB, 1 ); /*Q0*/
281 : }
282 :
283 73150 : FOR( i = 0; i < tmp; i++ )
284 : {
285 70300 : out[i] = mult_r( out[i], p[i].v.im ); /*Qx*/
286 70300 : move16();
287 : }
288 73150 : FOR( i = 0; i < tmp; i++ )
289 : {
290 70300 : out[i + tmp] = mult_r( out[i + tmp], p[tmp - 1 - i].v.re ); /*Qx*/
291 70300 : move16();
292 : }
293 : }
294 :
295 2850 : *left_overlap_length = l;
296 2850 : move16();
297 2850 : *right_overlap_length = r;
298 2850 : move16();
299 2850 : }
300 : /*-------------------------------------------------------------------*
301 : * tcx_windowing_synthesis_current_frame()
302 : *
303 : *
304 : *-------------------------------------------------------------------*/
305 :
306 105772 : 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 105772 : overlap = shr( window_length, 1 ); /*Q0*/
335 :
336 : /* Past-frame is TCX concealed as CNG and current-frame is TCX */
337 105772 : test();
338 105772 : test();
339 105772 : test();
340 105772 : test();
341 105772 : 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 105772 : ELSE IF( EQ_16( left_rect, 1 ) && last_core_bfi == ACELP_CORE )
364 : {
365 16628 : tmp = sub( overlap, acelp_mem_len );
366 1866620 : FOR( i = 0; i < tmp; i++ )
367 : {
368 1849992 : move16();
369 1849992 : signal[i] = 0;
370 : }
371 :
372 16628 : IF( fullbandScale == 0 )
373 : {
374 :
375 8314 : tmp = shl( acelp_mem_len, 1 ); /*Qx*/
376 :
377 : /*OLA with ACELP*/
378 96836 : FOR( i = 0; i < acelp_mem_len; i++ )
379 : {
380 :
381 : /*window decoded TCX with aliasing*/
382 88522 : 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 88522 : 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 88522 : 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 88522 : move16();
390 88522 : signal[i + overlap - acelp_mem_len] = tmp2; /*Qx*/
391 : }
392 96836 : FOR( ; i < tmp; i++ )
393 : {
394 :
395 : /*window decoded TCX with aliasing*/
396 88522 : 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 88522 : 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 88522 : 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 88522 : move16();
403 88522 : signal[i + overlap - acelp_mem_len] = tmp2; /*Qx*/
404 : }
405 :
406 141338 : FOR( i = 0; i < M; i++ )
407 : {
408 133024 : move16();
409 133024 : 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 16628 : move16();
414 16628 : acelp_zir_len = 64;
415 :
416 16628 : IF( fullbandScale == 0 )
417 : {
418 8314 : set16_fx( acelp_zir, 0, acelp_zir_len );
419 8314 : 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 8314 : tmp = extract_l( L_shr( L_mult0( acelp_zir_len, fullbandScale ), LD_FSCALE_DENOM ) ); /*Q0*/
424 8314 : lerp( acelp_zir, tmp_buf, tmp, acelp_zir_len );
425 8314 : acelp_zir_len = tmp; /*Q0*/
426 8314 : move16();
427 8314 : acelp_zir = tmp_buf; /*Qx*/
428 :
429 :
430 8314 : 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 1233787 : FOR( i = 2; i < acelp_zir_len; i++ )
434 : {
435 1227510 : L_tmp = L_mult( acelp_zir[i - 2], 8192 /*0.25 in Q15*/ );
436 1227510 : L_tmp = L_mac( L_tmp, acelp_zir[i - 1], 11469 /*0.35 in Q15*/ );
437 1227510 : acelp_zir[i] = mac_r( L_tmp, acelp_zir[i], 13107 /*0.40 in Q15*/ ); /*Qx*/
438 1227510 : move16();
439 : }
440 :
441 6277 : L_tmp = L_mult( acelp_zir[acelp_zir_len - 1], 13107 /*0.40 in Q15*/ );
442 6277 : L_tmp = L_mac( L_tmp, acelp_zir[acelp_zir_len - 1], 11469 /*0.35 in Q15*/ );
443 6277 : acelp_zir[acelp_zir_len - 1] = mac_r( L_tmp, acelp_zir[acelp_zir_len - 2], 8192 /*0.25 in Q15*/ ); /*Qx*/
444 6277 : move16();
445 6277 : L_tmp = L_mult( acelp_zir[acelp_zir_len - 2], 13107 );
446 6277 : L_tmp = L_mac( L_tmp, acelp_zir[acelp_zir_len - 1], 11469 );
447 6277 : acelp_zir[acelp_zir_len - 2] = mac_r( L_tmp, acelp_zir[acelp_zir_len - 1], 8192 ); /*Qx*/
448 6277 : move16();
449 1233787 : FOR( i = acelp_zir_len - 3; i >= 0; i-- )
450 : {
451 1227510 : L_tmp = L_mult( acelp_zir[i], 13107 );
452 1227510 : L_tmp = L_mac( L_tmp, acelp_zir[i + 1], 11469 );
453 1227510 : acelp_zir[i] = mac_r( L_tmp, acelp_zir[i + 2], 8192 ); /*Qx*/
454 1227510 : move16();
455 : }
456 : }
457 : }
458 :
459 1976172 : FOR( i = 0; i < acelp_zir_len; i++ )
460 : {
461 : /*remove reconstructed ZIR and add ACELP ZIR*/
462 1959544 : move16();
463 1959544 : 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 89144 : 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 88684 : ELSE IF( left_rect != 1 && last_core_bfi == ACELP_CORE )
490 : {
491 :
492 16 : n = shr( window_length, 1 ); /*q0*/
493 2438 : FOR( i = 0; i < n; i++ )
494 : {
495 2422 : move16();
496 2422 : signal[i] = mult_r( signal[i], window[i].v.im ); /*Qx*/
497 : }
498 2438 : FOR( ; i < window_length; i++ )
499 : {
500 2422 : move16();
501 2422 : signal[i] = mult_r( signal[i], window[window_length - 1 - i].v.re ); /*Qx*/
502 : }
503 :
504 4860 : FOR( i = 0; i < window_length /*acelp_zir_len*/; i++ )
505 : {
506 4844 : move16();
507 4844 : signal[i] = add( signal[i], syn_overl[i] ); /*Qx*/
508 : }
509 : }
510 : /* Normal window (past-frame is TCX) */
511 : ELSE
512 : {
513 88668 : IF( EQ_16( left_mode, 2 ) ) /* min. overlap */
514 : {
515 53178 : n = shr( sub( window_length, window_min_length ), 1 ); /*q0*/
516 2454806 : FOR( i = 0; i < n; i++ )
517 : {
518 2401628 : *signal++ = 0;
519 2401628 : move16();
520 : }
521 :
522 53178 : n = shr( window_min_length, 1 ); /*q0*/
523 1196400 : FOR( i = 0; i < n; i++ )
524 : {
525 1143222 : *signal = mult_r( *signal, window_min[i].v.im ); /*Qx*/
526 1143222 : move16();
527 1143222 : signal++;
528 : }
529 1196400 : FOR( i = 0; i < n; i++ )
530 : {
531 1143222 : *signal = mult_r( *signal, window_min[n - 1 - i].v.re ); /*Qx*/
532 1143222 : move16();
533 1143222 : signal++;
534 : }
535 : }
536 35490 : ELSE IF( EQ_16( left_mode, 3 ) ) /* half OL */
537 : {
538 : Word16 w;
539 :
540 13058 : n = shr( sub( window_length, window_half_length ), 1 );
541 314930 : FOR( i = 0; i < n; i++ )
542 : {
543 301872 : move16();
544 301872 : signal[i] = 0;
545 : }
546 13058 : n = shr( window_half_length, 1 );
547 850550 : FOR( w = 0; w < n; w++ )
548 : {
549 837492 : move16();
550 837492 : signal[i] = mult_r( signal[i], window_half[w].v.im ); /*Qx*/
551 837492 : i = add( i, 1 );
552 : }
553 850550 : FOR( w = 0; w < n; w++ )
554 : {
555 837492 : move16();
556 837492 : signal[i] = mult_r( signal[i], window_half[window_half_length / 2 - 1 - w].v.re ); /*Qx*/
557 837492 : i = add( i, 1 );
558 : }
559 : }
560 : ELSE
561 : { /* normal full/maximum overlap */
562 :
563 22432 : n = shr( window_length, 1 );
564 3431194 : FOR( i = 0; i < n; i++ )
565 : {
566 3408762 : move16();
567 3408762 : signal[i] = mult_r( signal[i], window[i].v.im ); /*Qx*/
568 : }
569 3431194 : FOR( ; i < window_length; i++ )
570 : {
571 3408762 : move16();
572 3408762 : 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 105772 : }
579 : /*-------------------------------------------------------------------*
580 : * tcx_windowing_synthesis_past_frame()
581 : *
582 : *
583 : *-------------------------------------------------------------------*/
584 107048 : 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 107048 : IF( EQ_16( right_mode, 2 ) ) /* min. overlap */
599 : {
600 56452 : signal += shr( sub( window_length, window_min_length ), 1 ); /*Qx*/
601 :
602 56452 : n = shr( window_min_length, 1 );
603 1273044 : FOR( i = 0; i < n; i++ )
604 : {
605 1216592 : *signal = mult_r( *signal, window_min[i].v.re ); /*Qx*/
606 1216592 : move16();
607 1216592 : signal++;
608 : }
609 1273044 : FOR( i = 0; i < n; i++ )
610 : {
611 1216592 : *signal = mult_r( *signal, window_min[n - 1 - i].v.im ); /*Qx*/
612 1216592 : move16();
613 1216592 : signal++;
614 : }
615 :
616 56452 : n = shr( sub( window_length, window_min_length ), 1 ); /*Q0*/
617 3846964 : FOR( i = 0; i < n; i++ )
618 : {
619 3790512 : *signal = 0;
620 3790512 : move16();
621 3790512 : signal++;
622 : }
623 : }
624 50596 : ELSE IF( EQ_16( right_mode, 3 ) ) /* half OL */
625 : {
626 : Word16 w;
627 :
628 14872 : i = shr( sub( window_length, window_half_length ), 1 ); /*Q0*/
629 14872 : n = shr( window_half_length, 1 ); /*Q0*/
630 957652 : FOR( w = 0; w < n; w++ )
631 : {
632 942780 : signal[i] = mult_r( signal[i], window_half[w].v.re ); /*Qx*/
633 942780 : move16();
634 942780 : i = add( i, 1 );
635 : }
636 957652 : FOR( w = 0; w < n; w++ )
637 : {
638 942780 : signal[i] = mult_r( signal[i], window_half[window_half_length / 2 - 1 - w].v.im ); /*Qx*/
639 942780 : move16();
640 942780 : i = add( i, 1 );
641 : }
642 1271912 : FOR( ; i < window_length; i++ )
643 : {
644 1257040 : move16();
645 1257040 : signal[i] = 0;
646 : }
647 : }
648 : ELSE /* normal full/maximum overlap */
649 : {
650 :
651 35724 : n = shr( window_length, 1 ); /*Q0*/
652 5086504 : FOR( i = 0; i < n; i++ )
653 : {
654 5050780 : move16();
655 5050780 : signal[i] = mult_r( signal[i], window[i].v.re ); /*Qx*/
656 5050780 : move16();
657 5050780 : signal[window_length - 1 - i] = mult_r( signal[window_length - 1 - i], window[i].v.im ); /*Qx*/
658 : }
659 : }
660 107048 : }
661 : /*-------------------------------------------------------------------*
662 : * lpc2mdct()
663 : *
664 : *
665 : *-------------------------------------------------------------------*/
666 :
667 638 : 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 638 : assert( length <= FDNS_NPTS );
689 638 : sizeN = shl( length, 1 ); /*Q0*/
690 :
691 638 : BASOP_getTables( NULL, &ptwiddle, &step, sizeN );
692 : /*ODFT*/
693 638 : assert( lpcOrder < FDNS_NPTS );
694 : /* pre-twiddle */
695 11484 : FOR( i = 0; i <= lpcOrder; i++ )
696 : {
697 10846 : ComplexData[2 * i] = L_mult( lpcCoeffs[i], ptwiddle->v.re ); /*Q12*/
698 10846 : move32();
699 10846 : ComplexData[2 * i + 1] = L_negate( L_mult( lpcCoeffs[i], ptwiddle->v.im ) ); /*Q12*/
700 10846 : move32();
701 10846 : ptwiddle += step;
702 : }
703 : /* zero padding */
704 30624 : FOR( ; i < FDNS_NPTS; i++ )
705 : {
706 29986 : ComplexData[2 * i] = L_deposit_l( 0 );
707 29986 : move32();
708 29986 : ComplexData[2 * i + 1] = L_deposit_l( 0 );
709 29986 : move32();
710 : }
711 :
712 638 : 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 638 : scale = add( norm_s( lpcCoeffs[0] ), 1 );
732 638 : BASOP_cfft( (cmplx *) ComplexData, FDNS_NPTS, &scale, workBuffer ); /*Q31 - scale*/
733 : /*Get amplitude*/
734 638 : j = sub( length, 1 );
735 638 : k = 0;
736 21054 : FOR( i = 0; i < length / 2; i++ )
737 : {
738 20416 : s = sub( norm_l( L_max( L_abs( ComplexData[2 * i] ), L_abs( ComplexData[2 * i + 1] ) ) ), 1 );
739 20416 : tmp16 = extract_h( L_shl( ComplexData[2 * i], s ) ); /*Q15 - scale + s*/
740 20416 : tmp32 = L_mult( tmp16, tmp16 ); /*Q15 - 2*(scale - s)*/
741 20416 : tmp16 = extract_h( L_shl( ComplexData[2 * i + 1], s ) ); /*Q15 - scale + s*/
742 20416 : tmp16 = mac_r( tmp32, tmp16, tmp16 ); /*Q15 - 2*(scale - s)*/
743 20416 : s = shl( sub( scale, s ), 1 );
744 20416 : if ( tmp16 == 0 )
745 : {
746 0 : s = -16;
747 0 : move16();
748 : }
749 20416 : if ( tmp16 == 0 )
750 : {
751 0 : tmp16 = 1;
752 0 : move16();
753 : }
754 20416 : BASOP_Util_Sqrt_InvSqrt_MantExp( tmp16, s, &g, &g_e, &ig, &ig_e ); /*Q15 - ig_e*/
755 20416 : if ( mdct_gains != 0 )
756 : {
757 0 : mdct_gains[k] = g; /*Q15 - g_e*/
758 0 : move16();
759 : }
760 20416 : if ( mdct_gains_exp != 0 )
761 : {
762 0 : mdct_gains_exp[k] = g_e;
763 0 : move16();
764 : }
765 20416 : if ( mdct_inv_gains != 0 )
766 : {
767 20416 : mdct_inv_gains[k] = ig; /*Q15 - ig_e*/
768 20416 : move16();
769 : }
770 20416 : if ( mdct_inv_gains_exp != 0 )
771 : {
772 20416 : mdct_inv_gains_exp[k] = ig_e;
773 20416 : move16();
774 : }
775 20416 : k = add( k, 1 );
776 20416 : s = sub( norm_l( L_max( L_abs( ComplexData[2 * j] ), L_abs( ComplexData[2 * j + 1] ) ) ), 1 );
777 20416 : tmp16 = extract_h( L_shl( ComplexData[2 * j], s ) ); /*Q15 - scale + s*/
778 20416 : tmp32 = L_mult( tmp16, tmp16 ); /*Q15 - 2*(scale - s)*/
779 20416 : tmp16 = extract_h( L_shl( ComplexData[2 * j + 1], s ) ); /*Q15 - scale + s*/
780 20416 : tmp16 = mac_r( tmp32, tmp16, tmp16 ); /*Q15 - 2*(scale - s)*/
781 20416 : s = shl( sub( scale, s ), 1 );
782 20416 : if ( tmp16 == 0 )
783 : {
784 0 : s = -16;
785 0 : move16();
786 : }
787 20416 : if ( tmp16 == 0 )
788 : {
789 0 : tmp16 = 1;
790 0 : move16();
791 : }
792 20416 : BASOP_Util_Sqrt_InvSqrt_MantExp( tmp16, s, &g, &g_e, &ig, &ig_e );
793 20416 : if ( mdct_gains != 0 )
794 : {
795 0 : mdct_gains[k] = g; /*Q15 - g_e*/
796 0 : move16();
797 : }
798 20416 : if ( mdct_gains_exp != 0 )
799 : {
800 0 : mdct_gains_exp[k] = g_e;
801 0 : move16();
802 : }
803 20416 : if ( mdct_inv_gains != 0 )
804 : {
805 20416 : mdct_inv_gains[k] = ig; /*Q15 - ig_e*/
806 20416 : move16();
807 : }
808 20416 : if ( mdct_inv_gains_exp != 0 )
809 : {
810 20416 : mdct_inv_gains_exp[k] = ig_e;
811 20416 : move16();
812 : }
813 20416 : j = sub( j, 1 );
814 20416 : k = add( k, 1 );
815 : }
816 : }
817 638 : }
818 :
819 216113 : 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 216113 : assert( length <= FDNS_NPTS );
835 216113 : sizeN = shl( length, 1 ); /*Q0*/
836 :
837 216113 : BASOP_getTables( NULL, &ptwiddle, &step, sizeN );
838 :
839 : /* ODFT */
840 3890034 : FOR( i = 0; i < lpcOrder + 1; i++ )
841 : {
842 3673921 : RealData_fx[i] = L_mult( lpcCoeffs[i], ptwiddle->v.re ); /*Q12*/
843 3673921 : move32();
844 3673921 : ImagData_fx[i] = L_negate( L_mult( lpcCoeffs[i], ptwiddle->v.im ) ); /*Q12*/
845 3673921 : move32();
846 3673921 : ptwiddle += step;
847 : }
848 :
849 24204656 : FOR( ; i < sizeN; i++ )
850 : {
851 23988543 : RealData_fx[i] = L_deposit_l( 0 );
852 23988543 : move32();
853 23988543 : ImagData_fx[i] = L_deposit_l( 0 );
854 23988543 : move32();
855 : }
856 :
857 : /* half length FFT */
858 216113 : scale = add( norm_s( lpcCoeffs[0] ), 1 );
859 216113 : BASOP_cfft_ivas( RealData_fx, ImagData_fx, 1, &scale ); /*Q31 - scale*/
860 :
861 : /*Get amplitude*/
862 216113 : j = sub( FDNS_NPTS, 1 );
863 216113 : move16();
864 216113 : k = 0;
865 216113 : move16();
866 :
867 7131729 : FOR( i = 0; i < FDNS_NPTS / 2; i++ )
868 : {
869 6915616 : s = sub( norm_l( L_max( L_abs( RealData_fx[i] ), L_abs( ImagData_fx[i] ) ) ), 1 );
870 :
871 6915616 : tmp16 = extract_h( L_shl( RealData_fx[i], s ) ); /*Q15 - scale + s*/
872 6915616 : tmp32 = L_mult( tmp16, tmp16 ); /*Q15 - 2*(scale - s)*/
873 :
874 6915616 : tmp16 = extract_h( L_shl( ImagData_fx[i], s ) ); /*Q15 - scale + s*/
875 6915616 : tmp16 = mac_r( tmp32, tmp16, tmp16 ); /*Q15 - 2*(scale - s)*/
876 :
877 6915616 : s = shl( sub( scale, s ), 1 );
878 :
879 6915616 : if ( tmp16 == 0 )
880 : {
881 0 : s = -16;
882 0 : move16();
883 : }
884 6915616 : if ( tmp16 == 0 )
885 : {
886 0 : tmp16 = 1;
887 0 : move16();
888 : }
889 :
890 6915616 : BASOP_Util_Sqrt_InvSqrt_MantExp( tmp16, s, &g, &g_e, &ig, &ig_e );
891 :
892 6915616 : if ( mdct_gains_fx != NULL )
893 : {
894 0 : mdct_gains_fx[k] = g; /*Q15 - g_e*/
895 0 : move16();
896 : }
897 :
898 6915616 : if ( mdct_gains_e != NULL )
899 : {
900 0 : mdct_gains_e[k] = g_e;
901 0 : move16();
902 : }
903 :
904 6915616 : if ( mdct_inv_gains_fx != NULL )
905 : {
906 6915616 : mdct_inv_gains_fx[k] = ig; /*Q15 - ig_e*/
907 6915616 : move16();
908 : }
909 :
910 6915616 : if ( mdct_inv_gains_e != NULL )
911 : {
912 6915616 : mdct_inv_gains_e[k] = ig_e;
913 6915616 : move16();
914 : }
915 :
916 6915616 : k = add( k, 1 );
917 :
918 :
919 6915616 : s = sub( norm_l( L_max( L_abs( RealData_fx[j] ), L_abs( ImagData_fx[j] ) ) ), 1 );
920 :
921 6915616 : tmp16 = extract_h( L_shl( RealData_fx[j], s ) ); /*Q15 - scale + s*/
922 6915616 : tmp32 = L_mult( tmp16, tmp16 ); /*Q15 - 2*(scale - s)*/
923 :
924 6915616 : tmp16 = extract_h( L_shl( ImagData_fx[j], s ) ); /*Q15 - scale + s*/
925 6915616 : tmp16 = mac_r( tmp32, tmp16, tmp16 ); /*Q15 - 2*(scale - s)*/
926 :
927 6915616 : s = shl( sub( scale, s ), 1 );
928 :
929 6915616 : if ( tmp16 == 0 )
930 : {
931 0 : s = -16;
932 0 : move16();
933 : }
934 6915616 : if ( tmp16 == 0 )
935 : {
936 0 : tmp16 = 1;
937 0 : move16();
938 : }
939 :
940 6915616 : BASOP_Util_Sqrt_InvSqrt_MantExp( tmp16, s, &g, &g_e, &ig, &ig_e );
941 :
942 6915616 : if ( mdct_gains_fx != NULL )
943 : {
944 0 : mdct_gains_fx[k] = g;
945 0 : move16();
946 : }
947 :
948 6915616 : if ( mdct_gains_e != NULL )
949 : {
950 0 : mdct_gains_e[k] = g_e;
951 0 : move16();
952 : }
953 :
954 6915616 : if ( mdct_inv_gains_fx != NULL )
955 : {
956 6915616 : mdct_inv_gains_fx[k] = ig;
957 6915616 : move16();
958 : }
959 :
960 6915616 : if ( mdct_inv_gains_e != NULL )
961 : {
962 6915616 : mdct_inv_gains_e[k] = ig_e;
963 6915616 : move16();
964 : }
965 :
966 6915616 : j = sub( j, 1 );
967 6915616 : k = add( k, 1 );
968 : }
969 :
970 216113 : 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 858 : 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 858 : Word32 *px = x; /*Qx*/
992 858 : Word16 const *pgains = gains;
993 858 : Word16 const *pgainsexp = gains_exp;
994 : #ifdef BASOP_NOGLOB_DECLARE_LOCAL
995 858 : Flag Overflow = 0;
996 : #endif
997 :
998 : /* FDNS_NPTS = 64 */
999 858 : k = shr( lg, 6 ); /*Q0*/
1000 858 : m = s_and( lg, 0x3F );
1001 :
1002 858 : IF( m != 0 )
1003 : {
1004 23 : IF( LE_16( m, FDNS_NPTS / 2 ) )
1005 : {
1006 23 : n = idiv1616U( FDNS_NPTS, m ); /*Q0*/
1007 23 : k1 = k;
1008 23 : move16();
1009 23 : k2 = add( k, 1 );
1010 : }
1011 : ELSE
1012 : {
1013 0 : n = idiv1616U( FDNS_NPTS, sub( FDNS_NPTS, m ) ); /*Q0*/
1014 0 : k1 = add( k, 1 );
1015 0 : k2 = k;
1016 0 : move16();
1017 : }
1018 :
1019 23 : i = 0;
1020 23 : move16();
1021 23 : j = 0;
1022 23 : move16();
1023 :
1024 1495 : WHILE( LT_16( i, lg ) )
1025 : {
1026 :
1027 1472 : k = k2;
1028 1472 : move16();
1029 1472 : if ( j != 0 )
1030 : {
1031 1104 : k = k1;
1032 1104 : move16();
1033 : }
1034 :
1035 1472 : j = add( j, 1 );
1036 1472 : if ( EQ_16( j, n ) )
1037 : {
1038 368 : j = 0;
1039 368 : move16();
1040 : }
1041 :
1042 : /* Limit number of loops, if end is reached */
1043 1472 : k = s_min( k, sub( lg, i ) );
1044 :
1045 10672 : FOR( l = 0; l < k; l++ )
1046 : {
1047 9200 : *x = L_shl_o( Mpy_32_16_r( *x, *gains ), *gains_exp, &Overflow ); /*Qx*/
1048 9200 : move32();
1049 9200 : x++;
1050 : }
1051 1472 : i = add( i, k );
1052 :
1053 1472 : gains++;
1054 1472 : gains_exp++;
1055 : }
1056 : }
1057 : ELSE
1058 : {
1059 4959 : FOR( l = 0; l < k; l++ )
1060 : {
1061 4124 : x = &px[l]; /*Qx*/
1062 4124 : gains = pgains;
1063 4124 : gains_exp = pgainsexp;
1064 268060 : FOR( i = 0; i < FDNS_NPTS; i++ )
1065 : {
1066 263936 : *x = L_shl_o( Mpy_32_16_r( *x, *gains ), *gains_exp, &Overflow ); /*Qx*/
1067 263936 : move32();
1068 263936 : x += k;
1069 263936 : gains++;
1070 263936 : gains_exp++;
1071 : }
1072 : }
1073 : }
1074 858 : }
1075 :
1076 697 : void mdct_shaping_16(
1077 : const Word16 x[], /*Qx*/
1078 : const Word16 lg, /*Q0*/
1079 : const Word16 lg_total, /*Q0*/
1080 : const Word16 gains[], /*15 - gains_exp*/
1081 : const Word16 gains_exp[],
1082 : Word16 gains_max_exp,
1083 : Word32 y[] /*Qx*/ )
1084 : {
1085 : Word16 i, k, l;
1086 : Word16 m, gain_exp;
1087 : Word16 const *px;
1088 : Word32 *py;
1089 697 : Word16 const *pgains = gains;
1090 : Word16 gains_exp_loc[FDNS_NPTS];
1091 : Word16 const *pgains_exp;
1092 :
1093 : /* FDNS_NPTS = 64 */
1094 697 : k = shr( lg, 6 ); /*Q0*/
1095 697 : m = s_and( lg, 0x3F );
1096 :
1097 697 : assert( m == 0 );
1098 : {
1099 45305 : FOR( i = 0; i < FDNS_NPTS; i++ )
1100 : {
1101 44608 : gains_exp_loc[i] = sub( gains_exp[i], gains_max_exp );
1102 44608 : move16();
1103 : }
1104 5059 : FOR( l = 0; l < k; l++ )
1105 : {
1106 4362 : px = &x[l]; /*Qx*/
1107 4362 : py = &y[l]; /*Qx*/
1108 4362 : pgains = gains; /*15 - gains_exp*/
1109 4362 : pgains_exp = gains_exp_loc;
1110 283530 : FOR( i = 0; i < FDNS_NPTS; i++ )
1111 : {
1112 279168 : *py = L_shl( L_mult( *px, *pgains ), *pgains_exp ); /*Qx*/
1113 279168 : move32();
1114 279168 : px += k;
1115 279168 : py += k;
1116 279168 : pgains++;
1117 279168 : pgains_exp++;
1118 : }
1119 : }
1120 : }
1121 :
1122 697 : gain_exp = sub( gains_exp[FDNS_NPTS - 1], gains_max_exp );
1123 19173 : FOR( i = lg; i < lg_total; i++ )
1124 : {
1125 18476 : y[i] = L_shl( L_mult( x[i], gains[FDNS_NPTS - 1] ), gain_exp ); /*Qx*/
1126 18476 : move32();
1127 : }
1128 697 : }
1129 :
1130 216295 : void mdct_noiseShaping_ivas_fx(
1131 : Word32 x_fx[], /*Q31 - x_e*/
1132 : Word16 *x_e,
1133 : const Word16 lg, /*Q0*/
1134 : const Word16 gains_fx[], /*Q15 - gains_exp*/
1135 : const Word16 gains_exp[]
1136 : /*const Word16 nBands*/ /*Parameter added in IVAS, but always equal to FDNS_NPTS */
1137 : )
1138 : {
1139 : Word16 i, j, k, l;
1140 : Word16 m, n, k1, k2;
1141 :
1142 216295 : j = 0;
1143 216295 : move16();
1144 : /* FDNS_NPTS = 64 */
1145 216295 : k = shr( lg, 6 ); /*Q0*/
1146 216295 : m = s_and( lg, 0x3F );
1147 :
1148 216295 : Word16 max_e = MIN16B;
1149 216295 : move16();
1150 14059175 : FOR( i = 0; i < FDNS_NPTS; i++ )
1151 : {
1152 13842880 : max_e = s_max( max_e, add( *x_e, gains_exp[i] ) );
1153 : }
1154 :
1155 216295 : IF( m != 0 )
1156 : {
1157 3893 : IF( LE_16( m, FDNS_NPTS / 2 ) )
1158 : {
1159 3893 : n = idiv1616U( FDNS_NPTS, m ); /*Q0*/
1160 3893 : k1 = k;
1161 3893 : move16();
1162 3893 : k2 = add( k, 1 );
1163 : }
1164 : ELSE
1165 : {
1166 0 : n = idiv1616U( FDNS_NPTS, sub( FDNS_NPTS, m ) ); /*Q0*/
1167 0 : k1 = add( k, 1 );
1168 0 : k2 = k;
1169 0 : move16();
1170 : }
1171 :
1172 3893 : i = 0;
1173 3893 : move16();
1174 3893 : j = 0;
1175 3893 : move16();
1176 :
1177 253045 : WHILE( LT_16( i, lg ) )
1178 : {
1179 249152 : IF( j % n != 0 )
1180 : {
1181 182928 : k = k1;
1182 182928 : move16();
1183 : }
1184 : ELSE
1185 : {
1186 66224 : k = k2;
1187 66224 : move16();
1188 : }
1189 :
1190 : /* Limit number of loops, if end is reached */
1191 249152 : k = s_min( k, sub( lg, i ) );
1192 :
1193 1886832 : FOR( l = 0; l < k; l++ )
1194 : {
1195 1637680 : x_fx[i] = Mpy_32_16_1( x_fx[i], gains_fx[j] ); /*Q31 - x_e*/
1196 1637680 : move32();
1197 1637680 : x_fx[i] = L_shr( x_fx[i], sub( max_e, add( *x_e, gains_exp[j] ) ) ); /*Q31 - max_e*/
1198 1637680 : move32();
1199 1637680 : i = add( i, 1 );
1200 : }
1201 249152 : j = add( j, 1 );
1202 : }
1203 : }
1204 : ELSE
1205 : {
1206 13806130 : FOR( i = 0; i < lg; )
1207 : {
1208 109614784 : FOR( l = 0; l < k; l++ )
1209 : {
1210 96021056 : x_fx[i] = Mpy_32_16_1( x_fx[i], gains_fx[j] ); /*Q31 - x_e*/
1211 96021056 : move32();
1212 96021056 : x_fx[i] = L_shr( x_fx[i], sub( max_e, add( *x_e, gains_exp[j] ) ) ); /*Q31 - max_e*/
1213 96021056 : move32();
1214 96021056 : i = add( i, 1 );
1215 : }
1216 13593728 : j = add( j, 1 );
1217 : }
1218 : }
1219 :
1220 216295 : *x_e = max_e;
1221 216295 : move16();
1222 :
1223 216295 : return;
1224 : }
1225 :
1226 :
1227 0 : void mdct_noiseShaping_interp(
1228 : Word32 x[], /*Qx*/
1229 : const Word16 lg, /*Q0*/
1230 : Word16 gains[], /*Q15 - gains_exp*/
1231 : Word16 gains_exp[] )
1232 : {
1233 : Word16 i, j, jp, jn, k, l;
1234 : Word16 g, pg, ng, e, tmp;
1235 :
1236 :
1237 0 : assert( lg % FDNS_NPTS == 0 );
1238 0 : k = shr( lg, 6 ); /* FDNS_NPTS = 64 Q0*/
1239 :
1240 0 : IF( gains )
1241 : {
1242 : /* Linear interpolation */
1243 0 : IF( EQ_16( k, 4 ) )
1244 : {
1245 0 : jp = 0;
1246 0 : move16();
1247 0 : j = 0;
1248 0 : move16();
1249 0 : jn = 1;
1250 0 : move16();
1251 :
1252 0 : FOR( i = 0; i < lg; i += 4 )
1253 : {
1254 0 : pg = gains[jp]; /*Q15 - gains_exp*/
1255 0 : move16();
1256 0 : g = gains[j]; /*Q15 - gains_exp*/
1257 0 : move16();
1258 0 : ng = gains[jn]; /*Q15 - gains_exp*/
1259 0 : move16();
1260 :
1261 : /* common exponent for pg and g */
1262 0 : tmp = sub( gains_exp[j], gains_exp[jp] );
1263 0 : if ( tmp > 0 )
1264 0 : pg = shr( pg, tmp );
1265 0 : if ( tmp < 0 )
1266 0 : g = shl( g, tmp );
1267 0 : e = s_max( gains_exp[j], gains_exp[jp] );
1268 :
1269 0 : tmp = mac_r( L_mult( pg, 12288 /*0.375f Q15*/ ), g, 20480 /*0.625f Q15*/ ); /*Q15 - gains_exp*/
1270 0 : x[i] = L_shl( Mpy_32_16_1( x[i], tmp ), e ); /*Qx*/
1271 0 : move32();
1272 :
1273 0 : tmp = mac_r( L_mult( pg, 4096 /*0.125f Q15*/ ), g, 28672 /*0.875f Q15*/ ); /*Q15 - gains_exp*/
1274 0 : x[i + 1] = L_shl( Mpy_32_16_1( x[i + 1], tmp ), e ); /*Qx*/
1275 0 : move32();
1276 :
1277 : /* common exponent for g and ng */
1278 0 : g = gains[j]; /*Q15 - gains_exp*/
1279 0 : move16();
1280 0 : tmp = sub( gains_exp[j], gains_exp[jn] );
1281 0 : if ( tmp > 0 )
1282 0 : ng = shr( ng, tmp );
1283 0 : if ( tmp < 0 )
1284 0 : g = shl( g, tmp );
1285 0 : e = s_max( gains_exp[j], gains_exp[jn] );
1286 :
1287 0 : tmp = mac_r( L_mult( g, 28672 /*0.875f Q15*/ ), ng, 4096 /*0.125f Q15*/ ); /*Q15 - gains_exp*/
1288 0 : x[i + 2] = L_shl( Mpy_32_16_1( x[i + 2], tmp ), e ); /*Qx*/
1289 0 : move32();
1290 :
1291 0 : tmp = mac_r( L_mult( g, 20480 /*0.625f Q15*/ ), ng, 12288 /*0.375f Q15*/ ); /*Q15 - gains_exp*/
1292 0 : x[i + 3] = L_shl( Mpy_32_16_1( x[i + 3], tmp ), e ); /*Qx*/
1293 0 : move32();
1294 :
1295 0 : jp = j;
1296 0 : move16();
1297 0 : j = jn;
1298 0 : move16();
1299 0 : jn = s_min( add( jn, 1 ), FDNS_NPTS - 1 );
1300 : }
1301 : }
1302 0 : ELSE IF( EQ_16( k, 5 ) )
1303 : {
1304 0 : jp = 0;
1305 0 : move16();
1306 0 : j = 0;
1307 0 : move16();
1308 0 : jn = 1;
1309 0 : move16();
1310 :
1311 0 : FOR( i = 0; i < lg; i += 5 )
1312 : {
1313 0 : pg = gains[jp]; /*Q15 - gains_exp*/
1314 0 : move16();
1315 0 : g = gains[j]; /*Q15 - gains_exp*/
1316 0 : move16();
1317 0 : ng = gains[jn]; /*Q15 - gains_exp*/
1318 0 : move16();
1319 :
1320 : /* common exponent for pg and g */
1321 0 : tmp = sub( gains_exp[j], gains_exp[jp] );
1322 0 : if ( tmp > 0 )
1323 0 : pg = shr( pg, tmp );
1324 0 : if ( tmp < 0 )
1325 0 : g = shl( g, tmp );
1326 0 : e = s_max( gains_exp[j], gains_exp[jp] );
1327 :
1328 0 : tmp = mac_r( L_mult( pg, 13107 /*0.40f Q15*/ ), g, 19661 /*0.60f Q15*/ ); /*Q15 - gains_exp*/
1329 0 : x[i] = L_shl( Mpy_32_16_1( x[i], tmp ), e ); /*Qx*/
1330 0 : move32();
1331 :
1332 0 : tmp = mac_r( L_mult( pg, 6554 /*0.20f Q15*/ ), g, 26214 /*0.80f Q15*/ ); /*Q15 - gains_exp*/
1333 0 : x[i + 1] = L_shl( Mpy_32_16_1( x[i + 1], tmp ), e ); /*Qx*/
1334 0 : move32();
1335 :
1336 :
1337 0 : x[i + 2] = L_shl( Mpy_32_16_1( x[i + 2], gains[j] ), gains_exp[j] ); /*Qx*/
1338 0 : move32();
1339 :
1340 : /* common exponent for g and ng */
1341 0 : g = gains[j]; /*Q15 - gains_exp*/
1342 0 : move16();
1343 0 : tmp = sub( gains_exp[j], gains_exp[jn] );
1344 0 : if ( tmp > 0 )
1345 0 : ng = shr( ng, tmp );
1346 0 : if ( tmp < 0 )
1347 0 : g = shl( g, tmp );
1348 0 : e = s_max( gains_exp[j], gains_exp[jn] );
1349 :
1350 0 : tmp = mac_r( L_mult( g, 26214 /*0.80f Q15*/ ), ng, 6554 /*0.20f Q15*/ ); /*Q15 - gains_exp*/
1351 0 : x[i + 3] = L_shl( Mpy_32_16_1( x[i + 3], tmp ), e ); /*Qx*/
1352 0 : move32();
1353 :
1354 0 : tmp = mac_r( L_mult( g, 19661 /*0.60f Q15*/ ), ng, 13107 /*0.40f Q15*/ ); /*Q15 - gains_exp*/
1355 0 : x[i + 4] = L_shl( Mpy_32_16_1( x[i + 4], tmp ), e ); /*Qx*/
1356 0 : move32();
1357 :
1358 0 : jp = j;
1359 0 : move16();
1360 0 : j = jn;
1361 0 : move16();
1362 0 : jn = s_min( add( jn, 1 ), FDNS_NPTS - 1 );
1363 : }
1364 : }
1365 : ELSE /* no interpolation */
1366 : {
1367 0 : FOR( i = 0; i < FDNS_NPTS; i++ )
1368 : {
1369 0 : FOR( l = 0; l < k; l++ )
1370 : {
1371 0 : *x = L_shl( Mpy_32_16_1( *x, *gains ), *gains_exp ); /*Qx*/
1372 0 : move32();
1373 0 : x++;
1374 : }
1375 :
1376 0 : gains++;
1377 0 : gains_exp++;
1378 : }
1379 : }
1380 : }
1381 0 : }
1382 :
1383 17649 : void PsychAdaptLowFreqDeemph(
1384 : Word32 x[], /*Qx*/
1385 : const Word16 lpcGains[], /*Q15 - lpcGains_e*/
1386 : const Word16 lpcGains_e[],
1387 : Word16 lf_deemph_factors[] /*Q15*/ )
1388 : {
1389 : Word16 i;
1390 : Word16 max_val, max_e, fac, min, min_e, tmp, tmp_e;
1391 : Word32 L_tmp;
1392 : #ifdef BASOP_NOGLOB_DECLARE_LOCAL
1393 17649 : Flag Overflow = 0;
1394 : #endif
1395 :
1396 :
1397 17649 : assert( lpcGains[0] >= 0x4000 );
1398 :
1399 17649 : max_val = lpcGains[0]; /*Q15 - lpcGains_e*/
1400 17649 : move16();
1401 17649 : max_e = lpcGains_e[0];
1402 17649 : move16();
1403 17649 : min = lpcGains[0]; /*Q15 - lpcGains_e*/
1404 17649 : move16();
1405 17649 : min_e = lpcGains_e[0];
1406 17649 : move16();
1407 :
1408 : /* find minimum (min) and maximum (max_val) of LPC gains in low frequencies */
1409 158841 : FOR( i = 1; i < 9; i++ )
1410 : {
1411 141192 : IF( compMantExp16Unorm( lpcGains[i], lpcGains_e[i], min, min_e ) < 0 )
1412 : {
1413 107735 : min = lpcGains[i]; /*Q15 - lpcGains_e*/
1414 107735 : move16();
1415 107735 : min_e = lpcGains_e[i];
1416 107735 : move16();
1417 : }
1418 :
1419 141192 : IF( compMantExp16Unorm( lpcGains[i], lpcGains_e[i], max_val, max_e ) > 0 )
1420 : {
1421 23553 : max_val = lpcGains[i]; /*Q15 - lpcGains_e*/
1422 23553 : move16();
1423 23553 : max_e = lpcGains_e[i];
1424 23553 : move16();
1425 : }
1426 : }
1427 :
1428 17649 : min_e = add( min_e, 5 ); /* min *= 32.0f; */
1429 :
1430 17649 : test();
1431 17649 : IF( ( compMantExp16Unorm( max_val, max_e, min, min_e ) < 0 ) && ( min > 0 ) )
1432 : {
1433 : /* fac = tmp = (float)pow(max_val / min, 0.0078125f); */
1434 17649 : tmp_e = min_e;
1435 17649 : move16();
1436 17649 : tmp = Inv16( min, &tmp_e ); /*Q15 - tmp_e*/
1437 17649 : L_tmp = L_shl( L_mult( tmp, max_val ), add( tmp_e, max_e ) ); /* Q31 */
1438 17649 : L_tmp = BASOP_Util_Log2( L_tmp ); /* Q25 */
1439 17649 : L_tmp = L_shr( L_tmp, 7 ); /* 0.0078125f = 1.f/(1<<7) */
1440 17649 : L_tmp = BASOP_Util_InvLog2( L_tmp ); /* Q31 */
1441 17649 : tmp = round_fx_o( L_tmp, &Overflow ); /* Q15 */
1442 17649 : fac = tmp; /* Q15 */
1443 17649 : move16();
1444 :
1445 : /* gradual lowering of lowest 32 bins; DC is lowered by (max_val/tmp)^1/4 */
1446 582417 : FOR( i = 31; i >= 0; i-- )
1447 : {
1448 564768 : x[i] = Mpy_32_16_1( x[i], fac );
1449 564768 : move32();
1450 564768 : if ( lf_deemph_factors != NULL )
1451 : {
1452 447648 : lf_deemph_factors[i] = mult_r( lf_deemph_factors[i], fac );
1453 447648 : move16();
1454 : }
1455 564768 : fac = mult_r( fac, tmp ); /* Q15 */
1456 : }
1457 : }
1458 17649 : }
1459 :
1460 111836 : void AdaptLowFreqDeemph(
1461 : Word32 x[], /*Q31 - x_e*/
1462 : Word16 x_e,
1463 : Word16 tcx_lpc_shaped_ari, /*Q0*/
1464 : Word16 lpcGains[], /*Q15 - lpcGains_e*/
1465 : Word16 lpcGains_e[],
1466 : const Word16 lg, /*Q0*/
1467 : Word16 lf_deemph_factors[] /*Q15*/ )
1468 : {
1469 :
1470 : Word16 i, i_max, i_max_old, lg_4;
1471 : Word32 v2, v4, tmp32;
1472 :
1473 111836 : tmp32 = 0; /* to avoid compilation warnings */
1474 111836 : move32();
1475 :
1476 111836 : IF( tcx_lpc_shaped_ari == 0 )
1477 : {
1478 97847 : v2 = L_shl( 2, sub( 31, x_e ) ); /* 2.0 */
1479 97847 : v4 = L_shl( v2, 1 ); /* 4.0 */
1480 97847 : lg_4 = shr( lg, 2 ); /* lg/4 */
1481 :
1482 : /* 1. find first magnitude maximum in lower quarter of spectrum */
1483 97847 : i_max = -1;
1484 97847 : move16();
1485 :
1486 586530 : FOR( i = 0; i < lg_4; i++ )
1487 : {
1488 583141 : IF( GE_32( L_abs( x[i] ), v4 ) )
1489 : {
1490 :
1491 : /* Debug initialization to catch illegal x[i] values. */
1492 94458 : tmp32 = 0;
1493 94458 : move32();
1494 :
1495 94458 : if ( x[i] < 0 )
1496 47390 : tmp32 = L_add( x[i], v2 ); /*Q31 - x_e*/
1497 94458 : if ( x[i] > 0 )
1498 47068 : tmp32 = L_sub( x[i], v2 ); /*Q31 - x_e*/
1499 :
1500 94458 : assert( tmp32 != 0 );
1501 :
1502 94458 : x[i] = tmp32; /*Q31 - x_e*/
1503 94458 : move32();
1504 94458 : i_max = i;
1505 94458 : move16();
1506 94458 : BREAK;
1507 : }
1508 : }
1509 :
1510 : /* 2. expand value range of all xi up to i_max: two extra steps */
1511 332214 : FOR( i = 0; i < i_max; i++ )
1512 : {
1513 234367 : x[i] = L_shr( x[i], 1 ); /*Q31 - x_e*/
1514 234367 : move32();
1515 234367 : lf_deemph_factors[i] = shr( lf_deemph_factors[i], 1 ); /*Q15*/
1516 234367 : move16();
1517 : }
1518 :
1519 : /* 3. find first magnitude maximum in lower quarter of spectrum */
1520 97847 : i_max_old = i_max; /*Q0*/
1521 97847 : move16();
1522 :
1523 97847 : IF( i_max_old >= 0 )
1524 : {
1525 94458 : i_max = -1;
1526 94458 : move16();
1527 :
1528 484577 : FOR( i = 0; i < lg_4; i++ )
1529 : {
1530 484562 : IF( GE_32( L_abs( x[i] ), v4 ) )
1531 : {
1532 94443 : assert( x[i] != 0 );
1533 94443 : if ( x[i] < 0 )
1534 47462 : tmp32 = L_add( x[i], v2 ); /*Q31 - x_e*/
1535 94443 : if ( x[i] >= 0 )
1536 46981 : tmp32 = L_sub( x[i], v2 ); /*Q31 - x_e*/
1537 94443 : x[i] = tmp32; /*Q31 - x_e*/
1538 94443 : move32();
1539 94443 : i_max = i;
1540 94443 : move16();
1541 94443 : BREAK;
1542 : }
1543 : }
1544 : }
1545 :
1546 : /* 4. expand value range of all xi up to i_max: two extra steps */
1547 486830 : FOR( i = 0; i < i_max; i++ )
1548 : {
1549 388983 : x[i] = L_shr( x[i], 1 ); /*Q31 - x_e*/
1550 388983 : move32();
1551 388983 : lf_deemph_factors[i] = shr( lf_deemph_factors[i], 1 ); /*Q15*/
1552 388983 : move16();
1553 : }
1554 :
1555 : /* 5. always expand two lines; lines could be at index 0 and 1! */
1556 97847 : i_max = s_max( i_max, i_max_old ); /*Q0*/
1557 97847 : i = add( i_max, 1 );
1558 :
1559 97847 : IF( x[i] < 0 )
1560 : {
1561 43302 : tmp32 = L_sub( x[i], L_negate( v4 ) );
1562 :
1563 43302 : if ( tmp32 > 0 )
1564 : {
1565 15452 : lf_deemph_factors[i] = shr( lf_deemph_factors[i], 1 ); /*Q15*/
1566 15452 : move16();
1567 : }
1568 43302 : if ( tmp32 <= 0 )
1569 : {
1570 27850 : x[i] = L_add( x[i], v2 ); /*Q31 - x_e*/
1571 27850 : move32();
1572 : }
1573 43302 : if ( tmp32 > 0 )
1574 : {
1575 15452 : x[i] = L_shr( x[i], 1 ); /*Q31 - x_e*/
1576 15452 : move32();
1577 : }
1578 : }
1579 : ELSE
1580 : {
1581 54545 : tmp32 = L_sub( x[i], v4 );
1582 :
1583 54545 : if ( tmp32 < 0 )
1584 : {
1585 25695 : lf_deemph_factors[i] = shr( lf_deemph_factors[i], 1 ); /*Q15*/
1586 25695 : move16();
1587 : }
1588 54545 : if ( tmp32 >= 0 )
1589 : {
1590 28850 : x[i] = L_sub( x[i], v2 ); /*Q31 - x_e*/
1591 28850 : move32();
1592 : }
1593 54545 : if ( tmp32 < 0 )
1594 : {
1595 25695 : x[i] = L_shr( x[i], 1 ); /*Q31 - x_e*/
1596 25695 : move32();
1597 : }
1598 : }
1599 97847 : i = add( i, 1 );
1600 :
1601 97847 : IF( x[i] < 0 )
1602 : {
1603 41905 : tmp32 = L_sub( x[i], L_negate( v4 ) );
1604 :
1605 41905 : if ( tmp32 > 0 )
1606 : {
1607 16456 : lf_deemph_factors[i] = shr( lf_deemph_factors[i], 1 ); /*Q15*/
1608 16456 : move16();
1609 : }
1610 41905 : if ( tmp32 <= 0 )
1611 : {
1612 25449 : x[i] = L_add( x[i], v2 ); /*Q31 - x_e*/
1613 25449 : move32();
1614 : }
1615 41905 : if ( tmp32 > 0 )
1616 : {
1617 16456 : x[i] = L_shr( x[i], 1 ); /*Q31 - x_e*/
1618 16456 : move32();
1619 : }
1620 : }
1621 : ELSE
1622 : {
1623 55942 : tmp32 = L_sub( x[i], v4 );
1624 :
1625 55942 : if ( tmp32 < 0 )
1626 : {
1627 30786 : lf_deemph_factors[i] = shr( lf_deemph_factors[i], 1 ); /*Q15*/
1628 30786 : move16();
1629 : }
1630 55942 : if ( tmp32 >= 0 )
1631 : {
1632 25156 : x[i] = L_sub( x[i], v2 ); /*Q31 - x_e*/
1633 25156 : move32();
1634 : }
1635 55942 : if ( tmp32 < 0 )
1636 : {
1637 30786 : x[i] = L_shr( x[i], 1 ); /*Q31 - x_e*/
1638 30786 : move32();
1639 : }
1640 : }
1641 : }
1642 : ELSE /*if(!tcx_lpc_shaped_ari)*/
1643 : {
1644 13989 : PsychAdaptLowFreqDeemph( x, lpcGains, lpcGains_e, lf_deemph_factors );
1645 : } /*if(!tcx_lpc_shaped_ari)*/
1646 111836 : }
1647 :
1648 636 : void tcx_noise_filling(
1649 : Word32 *Q, /*Q31 - Q_e*/
1650 : Word16 Q_e,
1651 : Word16 seed,
1652 : const Word16 iFirstLine, /*Q0*/
1653 : const Word16 lowpassLine, /*Q0*/
1654 : const Word16 nTransWidth, /*Q0*/
1655 : const Word16 L_frame, /*Q0*/
1656 : const Word16 tiltCompFactor, /*Q15*/
1657 : Word16 fac_ns, /*Q15*/
1658 : Word16 *infoTCXNoise, /*Q0*/
1659 : const Word16 element_mode /* i : IVAS element mode Q0*/
1660 : )
1661 : {
1662 : Word16 i, m, segmentOffset;
1663 : Word16 win; /* window coefficient */
1664 : Word16 tilt_factor;
1665 : Word32 nrg;
1666 : Word16 tmp1, tmp2, s;
1667 : Word32 tmp32;
1668 :
1669 :
1670 : /* get inverse frame length */
1671 636 : tmp1 = getInvFrameLen( L_frame ); /*Q21*/
1672 :
1673 : /* tilt_factor = (float)pow(max_val(0.375f, tiltCompFactor), 1.0f/(float)L_frame); */
1674 636 : tmp32 = BASOP_Util_Log2( L_deposit_h( s_max( 0x3000, tiltCompFactor ) ) ); /* 6Q25 */
1675 636 : tmp32 = L_shr( Mpy_32_16_1( tmp32, tmp1 ), 6 ); /*Q25*/
1676 : BASOP_SATURATE_WARNING_OFF_EVS;
1677 636 : tilt_factor = round_fx_sat( BASOP_Util_InvLog2( tmp32 ) ); /*Q15*/
1678 : BASOP_SATURATE_WARNING_ON_EVS;
1679 :
1680 : /* find last nonzero line below iFirstLine, use it as start offset */
1681 636 : i = iFirstLine;
1682 636 : move16();
1683 636 : tmp1 = shr( iFirstLine, 1 ); /*Q0*/
1684 636 : IF( EQ_16( element_mode, IVAS_CPE_MDCT ) ) /* ... but only in mono or parametric stereo since it may cause binaural unmasking in discrete stereo */
1685 : {
1686 0 : segmentOffset = i;
1687 0 : move16();
1688 : }
1689 : ELSE
1690 : {
1691 2780 : FOR( ; i > tmp1; i-- )
1692 : {
1693 2775 : IF( Q[i] != 0 )
1694 : {
1695 631 : BREAK;
1696 : }
1697 : }
1698 : /* fac_ns *= (float)pow(tilt_factor, (float)i); */
1699 29760 : FOR( m = 0; m < i; m++ )
1700 : {
1701 29124 : fac_ns = mult_r( fac_ns, tilt_factor ); /*Q15*/
1702 : }
1703 636 : i = add( i, 1 );
1704 636 : segmentOffset = i;
1705 : }
1706 636 : nrg = L_deposit_l( 1 );
1707 636 : win = 0;
1708 636 : move16();
1709 :
1710 135996 : FOR( ; i < lowpassLine; i++ )
1711 : {
1712 135360 : fac_ns = mult_r( fac_ns, tilt_factor ); /*Q15*/
1713 :
1714 135360 : IF( Q[i] != 0 )
1715 : {
1716 18614 : IF( win > 0 )
1717 : {
1718 : /* RMS-normalize current noise-filled segment */
1719 12259 : tmp1 = BASOP_Util_Divide3216_Scale( nrg, sub( i, segmentOffset ), &s ); /* mean */
1720 12259 : s = add( s, 9 - 15 ); /* scaling */
1721 12259 : tmp1 = ISqrt16( tmp1, &s ); /* 1/RMS Q15 - s*/
1722 12259 : tmp1 = mult_r( tmp1, inv_int[nTransWidth] ); /* compensate win Q15 - s*/
1723 12259 : s = add( s, sub( 16, Q_e ) ); /* scaling */
1724 :
1725 12259 : tmp2 = sub( i, win );
1726 12259 : IF( LT_16( segmentOffset, tmp2 ) )
1727 : {
1728 33126 : FOR( m = segmentOffset; m < tmp2; m++ )
1729 : {
1730 30175 : Q[m] = L_shl( Mpy_32_16_1( Q[m], tmp1 ), s ); /*Q31 - Q_e*/
1731 30175 : move32();
1732 : }
1733 : }
1734 :
1735 12259 : tmp2 = mult( tmp1, inv_int[nTransWidth] );
1736 12259 : tmp1 = extract_l( L_mult0( tmp2, win ) );
1737 64603 : FOR( m = sub( i, win ); m < i; m++ )
1738 : {
1739 52344 : Q[m] = L_shl( Mpy_32_16_1( Q[m], tmp1 ), s ); /*Q31 - Q_e*/
1740 52344 : move32();
1741 52344 : win = sub( win, 1 );
1742 52344 : tmp1 = sub( tmp1, tmp2 );
1743 : }
1744 :
1745 12259 : nrg = L_deposit_l( 1 ); /* start new segment: reset noise segment energy */
1746 : }
1747 18614 : segmentOffset = add( i, 1 );
1748 : }
1749 : ELSE /* line is zero, so fill line and update window and energy */
1750 : {
1751 116746 : if ( LT_16( win, nTransWidth ) )
1752 : {
1753 56581 : win = add( win, 1 );
1754 : }
1755 :
1756 116746 : Random( &seed );
1757 116746 : Q[i] = L_mult0( mult( seed, fac_ns ), win ); /*Q31 - Q_e*/
1758 116746 : move32();
1759 :
1760 116746 : tmp1 = shr( seed, 4 );
1761 116746 : nrg = L_mac0( nrg, tmp1, tmp1 ); /* sum up energy of current noise segment */
1762 :
1763 116746 : if ( infoTCXNoise ) /* set noiseflags for IGF */
1764 : {
1765 116746 : infoTCXNoise[i] = 1;
1766 116746 : move16();
1767 : }
1768 : }
1769 : }
1770 :
1771 636 : IF( win > 0 )
1772 : {
1773 : /* RMS-normalize uppermost noise-filled segment */
1774 607 : tmp1 = BASOP_Util_Divide3216_Scale( nrg, sub( lowpassLine, segmentOffset ), &s ); /* mean */
1775 607 : s = add( s, 9 - 15 ); /* compensate energy scaling */
1776 607 : tmp1 = ISqrt16( tmp1, &s ); /* 1/RMS Q15 - s*/
1777 607 : tmp1 = mult_r( tmp1, inv_int[nTransWidth] ); /* compensate win Q15 - s*/
1778 607 : s = add( s, sub( 16, Q_e ) ); /* compensate noise scaling */
1779 :
1780 34834 : FOR( m = segmentOffset; m < lowpassLine; m++ )
1781 : {
1782 34227 : Q[m] = L_shl( Mpy_32_16_1( Q[m], tmp1 ), s ); /*Q31 - Q_e*/
1783 34227 : move32();
1784 : }
1785 : }
1786 636 : }
1787 :
1788 750780 : void tcx_noise_filling_with_shift(
1789 : Word32 *Q, /*Q31 - Q_e*/
1790 : Word16 *Q_e,
1791 : Word16 seed, /*Q0*/
1792 : const Word16 iFirstLine, /*Q0*/
1793 : const Word16 lowpassLine, /*Q0*/
1794 : const Word16 nTransWidth, /*Q0*/
1795 : const Word16 L_frame, /*Q0*/
1796 : const Word16 tiltCompFactor, /*Q0*/
1797 : Word16 fac_ns, /*Q15*/
1798 : Word16 *infoTCXNoise, /*Q0*/
1799 : const Word16 element_mode /* i : IVAS element mode Q0*/
1800 : )
1801 : {
1802 : Word16 i, m, segmentOffset;
1803 : Word16 win; /* window coefficient */
1804 : Word16 tilt_factor;
1805 : Word32 nrg;
1806 : Word16 tmp1, tmp2, s;
1807 : Word32 tmp32;
1808 : Word16 new_Q_e[N_MAX];
1809 :
1810 750780 : set16_fx( new_Q_e, *Q_e, N_MAX );
1811 :
1812 : /* get inverse frame length */
1813 750780 : tmp1 = getInvFrameLen( L_frame ); /*Q21*/
1814 :
1815 : /* tilt_factor = (float)pow(max_val(0.375f, tiltCompFactor), 1.0f/(float)L_frame); */
1816 750780 : tmp32 = BASOP_Util_Log2( L_deposit_h( s_max( 0x3000, tiltCompFactor ) ) ); /* 6Q25 */
1817 750780 : tmp32 = L_shr( Mpy_32_16_1( tmp32, tmp1 ), 6 ); /*Q25*/
1818 : BASOP_SATURATE_WARNING_OFF_EVS;
1819 750780 : tilt_factor = round_fx_sat( BASOP_Util_InvLog2( tmp32 ) ); /*Q15*/
1820 : BASOP_SATURATE_WARNING_ON_EVS;
1821 :
1822 : /* find last nonzero line below iFirstLine, use it as start offset */
1823 750780 : i = iFirstLine;
1824 750780 : move16();
1825 750780 : tmp1 = shr( iFirstLine, 1 );
1826 750780 : IF( EQ_16( element_mode, IVAS_CPE_MDCT ) ) /* ... but only in mono or parametric stereo since it may cause binaural unmasking in discrete stereo */
1827 : {
1828 550116 : segmentOffset = i;
1829 550116 : move16();
1830 : }
1831 : ELSE
1832 : {
1833 575915 : FOR( ; i > tmp1; i-- )
1834 : {
1835 574951 : IF( Q[i] != 0 )
1836 : {
1837 199700 : BREAK;
1838 : }
1839 : }
1840 : /* fac_ns *= (float)pow(tilt_factor, (float)i); */
1841 14192808 : FOR( m = 0; m < i; m++ )
1842 : {
1843 13992144 : fac_ns = mult_r( fac_ns, tilt_factor ); /*Q15*/
1844 : }
1845 200664 : i = add( i, 1 );
1846 200664 : segmentOffset = i;
1847 200664 : move16();
1848 : }
1849 750780 : nrg = L_deposit_l( 1 );
1850 750780 : win = 0;
1851 750780 : move16();
1852 :
1853 334272584 : FOR( ; i < lowpassLine; i++ )
1854 : {
1855 333521804 : fac_ns = mult_r( fac_ns, tilt_factor ); /*Q15*/
1856 :
1857 333521804 : IF( Q[i] != 0 )
1858 : {
1859 80960270 : IF( win > 0 )
1860 : {
1861 : /* RMS-normalize current noise-filled segment */
1862 37679781 : tmp1 = BASOP_Util_Divide3216_Scale( nrg, sub( i, segmentOffset ), &s ); /* mean */
1863 : // Q-factor of nrg is -8. exp = 31-(-8) = 39
1864 37679781 : s = add( s, 39 - 15 ); /* scaling */
1865 37679781 : tmp1 = ISqrt16( tmp1, &s ); /* 1/RMS Q15 - s*/
1866 37679781 : tmp1 = mult_r( tmp1, inv_int[nTransWidth] ); /* compensate win Q15 - s*/
1867 :
1868 37679781 : tmp2 = sub( i, win );
1869 37679781 : IF( LT_16( segmentOffset, tmp2 ) )
1870 : {
1871 64052917 : FOR( m = segmentOffset; m < tmp2; m++ )
1872 : {
1873 59023541 : Word16 nrm = 31;
1874 59023541 : move16();
1875 59023541 : Q[m] = Mpy_32_16_1( Q[m], tmp1 ); /*Q31 - Q_e*/
1876 59023541 : move32();
1877 59023541 : IF( Q[m] )
1878 : {
1879 59017541 : nrm = norm_l( Q[m] );
1880 : }
1881 59023541 : Q[m] = L_shl( Q[m], nrm ); /*Q31 - Q_e + nrm*/
1882 59023541 : move32();
1883 59023541 : new_Q_e[m] = sub( add( new_Q_e[m], s ), nrm );
1884 59023541 : move32();
1885 : }
1886 : }
1887 :
1888 37679781 : tmp2 = mult( tmp1, inv_int[nTransWidth] ); /*Q15 - s*/
1889 37679781 : tmp1 = extract_l( L_mult0( tmp2, win ) ); /*Q15 - s*/
1890 147393331 : FOR( m = sub( i, win ); m < i; m++ )
1891 : {
1892 109713550 : Word16 nrm = 31;
1893 :
1894 109713550 : Q[m] = Mpy_32_16_1( Q[m], tmp1 ); /*Q31 - Q_e*/
1895 109713550 : move32();
1896 109713550 : IF( Q[m] )
1897 : {
1898 109703673 : nrm = norm_l( Q[m] );
1899 : }
1900 109713550 : Q[m] = L_shl( Q[m], nrm ); /*Q31 - Q_e*/
1901 109713550 : move32();
1902 109713550 : new_Q_e[m] = sub( add( new_Q_e[m], s ), nrm );
1903 109713550 : move32();
1904 109713550 : win = sub( win, 1 );
1905 109713550 : tmp1 = sub( tmp1, tmp2 );
1906 : }
1907 :
1908 37679781 : nrg = L_deposit_l( 1 ); /* start new segment: reset noise segment energy */
1909 : }
1910 80960270 : segmentOffset = add( i, 1 );
1911 : }
1912 : ELSE /* line is zero, so fill line and update window and energy */
1913 : {
1914 252561534 : IF( LT_16( win, nTransWidth ) )
1915 : {
1916 114456180 : win = add( win, 1 );
1917 : }
1918 :
1919 252561534 : Word16 nrm = 31;
1920 252561534 : move16();
1921 :
1922 252561534 : Random( &seed );
1923 252561534 : Q[i] = L_mult0( mult( seed, fac_ns ), win );
1924 252561534 : move32();
1925 252561534 : IF( Q[i] )
1926 : {
1927 252535542 : nrm = norm_l( Q[i] );
1928 : }
1929 252561534 : Q[i] = L_shl( Q[i], nrm ); /*Q31 - Q_e*/
1930 252561534 : move32();
1931 252561534 : new_Q_e[i] = sub( 31, nrm );
1932 :
1933 252561534 : tmp1 = shr( seed, 4 );
1934 252561534 : nrg = L_mac0( nrg, tmp1, tmp1 ); /* sum up energy of current noise segment Q-8*/
1935 :
1936 252561534 : IF( infoTCXNoise ) /* set noiseflags for IGF */
1937 : {
1938 145796905 : infoTCXNoise[i] = 1;
1939 145796905 : move16();
1940 : }
1941 : }
1942 : }
1943 :
1944 750780 : IF( win > 0 )
1945 : {
1946 : /* RMS-normalize uppermost noise-filled segment */
1947 695175 : tmp1 = BASOP_Util_Divide3216_Scale( nrg, sub( lowpassLine, segmentOffset ), &s ); /* mean */
1948 : // Q-factor of nrg is -8. exp = 31-(-8) = 39
1949 695175 : s = add( s, 39 - 15 ); /* compensate energy scaling */
1950 695175 : tmp1 = ISqrt16( tmp1, &s ); /* 1/RMS Q15 - s*/
1951 695175 : tmp1 = mult_r( tmp1, inv_int[nTransWidth] ); /* compensate win Q15 - s*/
1952 :
1953 84519618 : FOR( m = segmentOffset; m < lowpassLine; m++ )
1954 : {
1955 83824443 : Word16 nrm = 31;
1956 83824443 : move16();
1957 : /*
1958 : at this point:
1959 : - flt Q[m] = (Q[m] * 2^(new_Q_e[m] - 31)) / (nTransWidth*nTransWidth)
1960 : - flt tmp1 = (tmp1 * 2^(s - 15)) * (nTransWidth*nTransWidth)
1961 : */
1962 83824443 : Q[m] = Mpy_32_16_1( Q[m], tmp1 ); /*Q15 - Q_e - s*/
1963 83824443 : move32();
1964 83824443 : IF( Q[m] )
1965 : {
1966 83814328 : nrm = norm_l( Q[m] );
1967 : }
1968 83824443 : Q[m] = L_shl( Q[m], nrm ); /*Q15 - Q_e - s + nrm*/
1969 83824443 : move32();
1970 83824443 : new_Q_e[m] = add( new_Q_e[m], s - nrm );
1971 83824443 : move32();
1972 : }
1973 : }
1974 :
1975 750780 : Word16 max_e = 0;
1976 750780 : move16();
1977 398855086 : FOR( i = 0; i < lowpassLine; i++ )
1978 : {
1979 398104306 : max_e = s_max( max_e, new_Q_e[i] );
1980 : }
1981 :
1982 398855086 : FOR( i = 0; i < lowpassLine; i++ )
1983 : {
1984 398104306 : Q[i] = L_shr( Q[i], sub( max_e, new_Q_e[i] ) ); /*Q31 - Q_e*/
1985 398104306 : move32();
1986 : }
1987 :
1988 750780 : *Q_e = max_e;
1989 750780 : move16();
1990 750780 : }
1991 :
1992 :
1993 : /*---------------------------------------------------------------
1994 : * InitTnsConfigs()
1995 : *--------------------------------------------------------------*/
1996 :
1997 :
1998 16135 : void InitTnsConfigs(
1999 : const Word16 bwidth, /*Q0*/
2000 : const Word16 L_frame, /*Q0*/
2001 : STnsConfig tnsConfig[2][2],
2002 : const Word16 igfStopFreq, /*Q0*/
2003 : const Word32 total_brate, /*Q0*/
2004 : const Word16 element_mode, /*Q0*/
2005 : const Word16 MCT_flag /*Q0*/ )
2006 : {
2007 16135 : IF( GT_32( total_brate, ACELP_32k ) )
2008 : {
2009 12995 : InitTnsConfiguration( bwidth, shr( L_frame, 1 ), &tnsConfig[0][0], igfStopFreq, total_brate, element_mode, MCT_flag );
2010 : }
2011 16135 : InitTnsConfiguration( bwidth, L_frame, &tnsConfig[1][0], igfStopFreq, total_brate, element_mode, MCT_flag );
2012 16135 : InitTnsConfiguration( bwidth, add( L_frame, shr( L_frame, 2 ) ), &tnsConfig[1][1], igfStopFreq, total_brate, element_mode, MCT_flag );
2013 16135 : }
2014 :
2015 0 : void InitTnsConfigs_ivas_fx(
2016 : const Word16 bwidth, /*Q0*/
2017 : const Word16 L_frame, /*Q0*/
2018 : STnsConfig tnsConfig[2][2],
2019 : const Word16 igfStopFreq, /*Q0*/
2020 : const Word32 total_brate, /*Q0*/
2021 : const Word16 element_mode, /*Q0*/
2022 : const Word16 MCT_flag /*Q0*/ )
2023 : {
2024 0 : IF( GT_32( total_brate, ACELP_32k ) )
2025 : {
2026 0 : InitTnsConfiguration_ivas_fx( bwidth, shr( L_frame, 1 ), &tnsConfig[0][0], igfStopFreq, total_brate, element_mode, MCT_flag );
2027 : }
2028 0 : InitTnsConfiguration_ivas_fx( bwidth, L_frame, &tnsConfig[1][0], igfStopFreq, total_brate, element_mode, MCT_flag );
2029 0 : InitTnsConfiguration_ivas_fx( bwidth, add( L_frame, shr( L_frame, 2 ) ), &tnsConfig[1][1], igfStopFreq, total_brate, element_mode, MCT_flag );
2030 0 : }
2031 :
2032 :
2033 803087 : void SetTnsConfig(
2034 : TCX_CONFIG_HANDLE hTcxCfg, /* i : configuration of TCX */
2035 : const Word16 isTCX20, /*Q0*/
2036 : const Word16 isAfterACELP /*Q0*/ )
2037 : {
2038 803087 : move16();
2039 803087 : hTcxCfg->pCurrentTnsConfig = &hTcxCfg->tnsConfig[isTCX20][isAfterACELP];
2040 803087 : assert( hTcxCfg->pCurrentTnsConfig != NULL );
2041 803087 : }
2042 : #define IVAS_CODE_TCX_UTIL
2043 : #ifdef IVAS_CODE_TCX_UTIL
2044 : /*-------------------------------------------------------------------*
2045 : * SetAllowTnsOnWhite
2046 : *
2047 : * set TNS config flag for possible application of TNS in the whitened domain
2048 : *-------------------------------------------------------------------*/
2049 :
2050 16123 : void SetAllowTnsOnWhite(
2051 : STnsConfig tnsConfig[2][2], /* o : updated TNS configurations */
2052 : const Word8 allowTnsOnWhite /* i : flag for TNS in whiteded domain mode Q0*/
2053 : )
2054 : {
2055 16123 : tnsConfig[0][0].allowTnsOnWhite = allowTnsOnWhite; /*Q0*/
2056 16123 : move16();
2057 16123 : tnsConfig[0][1].allowTnsOnWhite = allowTnsOnWhite;
2058 16123 : move16();
2059 16123 : tnsConfig[1][0].allowTnsOnWhite = allowTnsOnWhite;
2060 16123 : move16();
2061 16123 : tnsConfig[1][1].allowTnsOnWhite = allowTnsOnWhite;
2062 16123 : move16();
2063 16123 : return;
2064 : }
2065 : #endif
2066 : #undef IVAS_CODE_TCX_UTIL
2067 :
2068 0 : void tcx_get_gain(
2069 : Word32 *x, /* i: spectrum 1 Q31 - x_e*/
2070 : Word16 x_e, /* i: spectrum 1 exponent */
2071 : Word32 *y, /* i: spectrum 2 Q31 - y_e*/
2072 : Word16 y_e, /* i: spectrum 2 exponent */
2073 : Word16 n, /* i: length Q0*/
2074 : Word16 *gain, /* o: gain Q15 - gain_e*/
2075 : Word16 *gain_e, /* o: gain exponent */
2076 : Word32 *en_y, /* o: energy of y (optional) Q31 - en_y_e*/
2077 : Word16 *en_y_e /* o: energy of y exponent (optional) */
2078 : )
2079 : {
2080 : Word32 maxX, minX, maxY, minY;
2081 : Word32 corr, ener;
2082 : Word16 sx, sy, corr_e, ener_e;
2083 : Word16 i, tmp;
2084 : #ifdef BASOP_NOGLOB_DECLARE_LOCAL
2085 0 : Flag Overflow = 0;
2086 : #endif
2087 :
2088 0 : maxX = L_deposit_l( 1 );
2089 0 : maxY = L_deposit_l( 1 );
2090 0 : minX = L_deposit_l( -1 );
2091 0 : minY = L_deposit_l( -1 );
2092 0 : FOR( i = 0; i < n; i++ )
2093 : {
2094 0 : if ( x[i] > 0 )
2095 0 : maxX = L_max( maxX, x[i] ); /*Q31 - x_e*/
2096 0 : if ( x[i] < 0 )
2097 0 : minX = L_min( minX, x[i] ); /*Q31 - x_e*/
2098 :
2099 0 : if ( y[i] > 0 )
2100 0 : maxY = L_max( maxY, y[i] ); /*Q31 - y_e*/
2101 0 : if ( y[i] < 0 )
2102 0 : minY = L_min( minY, y[i] ); /*Q31 - y_e*/
2103 : }
2104 0 : sx = s_min( norm_l( maxX ), norm_l( minX ) );
2105 0 : sy = s_min( norm_l( maxY ), norm_l( minY ) );
2106 0 : sx = sub( sx, 4 );
2107 0 : sy = sub( sy, 4 );
2108 :
2109 0 : ener = L_deposit_l( 0 );
2110 0 : corr = L_deposit_l( 0 );
2111 0 : FOR( i = 0; i < n; i++ )
2112 : {
2113 0 : tmp = round_fx( L_shl( y[i], sy ) ); /*Q15 - y_e + sy*/
2114 0 : ener = L_mac0( ener, tmp, tmp ); /*Q30 - 2*(y_e - sy)*/
2115 0 : corr = L_mac0( corr, tmp, round_fx( L_shl( x[i], sx ) ) ); /*Q30 - 2*(x_e - sx + y_e - sy)*/
2116 : }
2117 :
2118 0 : if ( ener == 0 )
2119 0 : ener = L_deposit_l( 1 );
2120 :
2121 0 : ener_e = add( shl( sub( y_e, sy ), 1 ), 1 );
2122 0 : corr_e = add( sub( add( x_e, y_e ), add( sx, sy ) ), 1 );
2123 :
2124 0 : tmp = sub( norm_l( corr ), 1 );
2125 0 : corr = L_shl( corr, tmp ); /*Q31 - corr_e + tmp*/
2126 0 : corr_e = sub( corr_e, tmp );
2127 :
2128 0 : tmp = norm_l( ener );
2129 0 : ener = L_shl( ener, tmp ); /*Q31 - ener_e + tmp*/
2130 0 : ener_e = sub( ener_e, tmp );
2131 :
2132 0 : tmp = div_s( abs_s( round_fx_o( corr, &Overflow ) ), round_fx_o( ener, &Overflow ) ); /*Q15 - (corr_e - ener_e)*/
2133 0 : if ( corr < 0 )
2134 0 : tmp = negate( tmp );
2135 :
2136 0 : *gain = tmp;
2137 0 : move16();
2138 0 : *gain_e = sub( corr_e, ener_e );
2139 0 : move16();
2140 :
2141 0 : if ( en_y != NULL )
2142 : {
2143 0 : *en_y = ener; /*Q31 - ener_e*/
2144 0 : move32();
2145 : }
2146 0 : if ( en_y_e != NULL )
2147 : {
2148 0 : *en_y_e = ener_e;
2149 0 : move16();
2150 : }
2151 0 : }
2152 35 : void init_TCX_config(
2153 : TCX_CONFIG_HANDLE hTcxCfg,
2154 : Word16 L_frame, /*Q0*/
2155 : Word16 fscale, /*Q0*/
2156 : Word16 L_frameTCX, /*Q0*/
2157 : Word16 fscaleFB /*Q0*/ )
2158 : {
2159 : /* Initialize the TCX MDCT windows */
2160 35 : hTcxCfg->tcx_mdct_window_length = extract_l( L_shr( L_mult0( L_LOOK_12k8, fscale ), LD_FSCALE_DENOM ) ); /*Q0*/
2161 35 : move16();
2162 35 : hTcxCfg->tcx_mdct_window_delay = hTcxCfg->tcx_mdct_window_length; /*Q0*/
2163 35 : move16();
2164 :
2165 35 : hTcxCfg->tcx_mdct_window_half_length = extract_l( L_shr( L_mult0( L_LOOK_12k8 - NS2SA( 12800, 5000000L ), fscale ), LD_FSCALE_DENOM ) );
2166 35 : move16();
2167 35 : hTcxCfg->tcx_mdct_window_min_length = shr( L_frame, 4 ); /* 1.25ms Q0*/
2168 35 : move16();
2169 35 : hTcxCfg->tcx_mdct_window_trans_length = shr( L_frame, 4 ); /* 1.25ms Q0*/
2170 35 : move16();
2171 35 : hTcxCfg->tcx5Size = shr( L_frame, 2 ); /* 5ms Q0*/
2172 35 : move16();
2173 35 : hTcxCfg->tcx_mdct_window_lengthFB = extract_l( L_shr( L_mult0( L_LOOK_12k8, fscaleFB ), LD_FSCALE_DENOM ) ); /*Q0*/
2174 35 : move16();
2175 35 : hTcxCfg->tcx_mdct_window_delayFB = hTcxCfg->tcx_mdct_window_lengthFB; /*Q0*/
2176 35 : move16();
2177 :
2178 35 : hTcxCfg->tcx_mdct_window_half_lengthFB = extract_l( L_shr( L_mult0( L_LOOK_12k8 - NS2SA( 12800, 5000000L ), fscaleFB ), LD_FSCALE_DENOM ) ); /*Q0*/
2179 35 : move16();
2180 35 : hTcxCfg->tcx_mdct_window_min_lengthFB = shr( L_frameTCX, 4 ); /* 1.25ms Q0*/
2181 35 : move16();
2182 35 : hTcxCfg->tcx_mdct_window_trans_lengthFB = shr( L_frameTCX, 4 ); /* 1.25ms Q0*/
2183 35 : move16();
2184 35 : hTcxCfg->tcx5SizeFB = shr( L_frameTCX, 2 ); /* 5ms Q0*/
2185 35 : move16();
2186 35 : mdct_window_sine( hTcxCfg->tcx_mdct_window, hTcxCfg->tcx_mdct_window_length );
2187 35 : mdct_window_sine( hTcxCfg->tcx_mdct_window_half, hTcxCfg->tcx_mdct_window_half_length );
2188 35 : mdct_window_sine( hTcxCfg->tcx_mdct_window_minimum, hTcxCfg->tcx_mdct_window_min_length );
2189 35 : mdct_window_sine( hTcxCfg->tcx_mdct_window_trans, hTcxCfg->tcx_mdct_window_trans_length );
2190 :
2191 35 : mdct_window_sine( hTcxCfg->tcx_mdct_windowFB, hTcxCfg->tcx_mdct_window_lengthFB );
2192 35 : mdct_window_sine( hTcxCfg->tcx_mdct_window_halfFB, hTcxCfg->tcx_mdct_window_half_lengthFB );
2193 35 : mdct_window_sine( hTcxCfg->tcx_mdct_window_minimumFB, hTcxCfg->tcx_mdct_window_min_lengthFB );
2194 35 : mdct_window_sine( hTcxCfg->tcx_mdct_window_transFB, hTcxCfg->tcx_mdct_window_trans_lengthFB );
2195 :
2196 : /*ALDO windows for MODE2*/
2197 35 : mdct_window_aldo( hTcxCfg->tcx_aldo_window_1, hTcxCfg->tcx_aldo_window_1_trunc, hTcxCfg->tcx_aldo_window_2, L_frame );
2198 35 : mdct_window_aldo( hTcxCfg->tcx_aldo_window_1_FB, hTcxCfg->tcx_aldo_window_1_FB_trunc, hTcxCfg->tcx_aldo_window_2_FB, L_frameTCX );
2199 35 : }
|