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 3144764 : Word16 getInvFrameLen( /* returns 1/L_frame in Q21 format */
21 : const Word16 L_frame )
22 : {
23 : Word16 idx, s;
24 :
25 3144764 : s = norm_s( L_frame );
26 3144764 : idx = shl( L_frame, s );
27 :
28 3144764 : assert( ( idx == 0x4000 ) || ( idx == 0x4B00 ) || ( idx == 0x5000 ) || ( idx == 0x5A00 ) || ( idx == 0x6000 ) || ( idx == 0x6400 ) || ( idx == 0x7800 ) );
29 :
30 3144764 : idx = mult_r( idx, 0x10 ); /* idx = shr(add(idx, 0x0400), 11); */
31 3144764 : idx = s_and( idx, 7 );
32 :
33 :
34 3144764 : return shl( L_frame_inv[idx], sub( s, 7 ) );
35 : }
36 : /*-------------------------------------------------------------------*
37 : *tcx_get_windows()
38 : *
39 : *
40 : * ------------------------------------------------------------------ - */
41 469465 : 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 469465 : IF( fullband == 0 )
53 : {
54 : /* Left part */
55 108933 : SWITCH( left_mode )
56 : {
57 316 : case TRANSITION_OVERLAP: /* ACELP->TCX transition */
58 316 : *left_overlap = hTcxCfg->tcx_mdct_window_trans_length; /*Q0*/
59 316 : move16();
60 316 : *left_win = hTcxCfg->tcx_mdct_window_trans; /*Q15*/
61 316 : BREAK;
62 2171 : case MIN_OVERLAP:
63 2171 : *left_overlap = hTcxCfg->tcx_mdct_window_min_length; /*Q0*/
64 2171 : move16();
65 2171 : *left_win = hTcxCfg->tcx_mdct_window_minimum; /*Q15*/
66 2171 : BREAK;
67 1711 : case HALF_OVERLAP:
68 1711 : *left_overlap = hTcxCfg->tcx_mdct_window_half_length; /*Q0*/
69 1711 : move16();
70 1711 : *left_win = hTcxCfg->tcx_mdct_window_half; /*Q15*/
71 1711 : BREAK;
72 104735 : case FULL_OVERLAP:
73 104735 : *left_overlap = hTcxCfg->tcx_mdct_window_length; /*Q0*/
74 104735 : move16();
75 104735 : *left_win = hTcxCfg->tcx_aldo_window_1_trunc; /*Q15*/
76 104735 : BREAK;
77 0 : default:
78 0 : assert( !"Not supported overlap" );
79 : }
80 :
81 : /* Right part */
82 108933 : SWITCH( right_mode )
83 : {
84 2185 : case MIN_OVERLAP:
85 2185 : *right_overlap = hTcxCfg->tcx_mdct_window_min_length; /*Q0*/
86 2185 : move16();
87 2185 : *right_win = hTcxCfg->tcx_mdct_window_minimum; /*Q15*/
88 2185 : BREAK;
89 1714 : case HALF_OVERLAP:
90 1714 : *right_overlap = hTcxCfg->tcx_mdct_window_half_length; /*Q0*/
91 1714 : move16();
92 1714 : *right_win = hTcxCfg->tcx_mdct_window_half; /*Q15*/
93 1714 : BREAK;
94 105034 : case FULL_OVERLAP:
95 105034 : *right_overlap = hTcxCfg->tcx_mdct_window_delay; /*Q0*/
96 105034 : move16();
97 105034 : *right_win = hTcxCfg->tcx_aldo_window_2; /*Q15*/
98 105034 : BREAK;
99 0 : default:
100 0 : assert( !"Not supported overlap" );
101 : }
102 : }
103 : ELSE
104 : {
105 : /* Left part */
106 360532 : SWITCH( left_mode )
107 : {
108 10821 : case TRANSITION_OVERLAP: /* ACELP->TCX transition */
109 10821 : *left_overlap = hTcxCfg->tcx_mdct_window_trans_lengthFB; /*Q0*/
110 10821 : move16();
111 10821 : *left_win = hTcxCfg->tcx_mdct_window_transFB; /*Q15*/
112 10821 : BREAK;
113 54743 : case MIN_OVERLAP:
114 54743 : *left_overlap = hTcxCfg->tcx_mdct_window_min_lengthFB; /*Q0*/
115 54743 : move16();
116 54743 : *left_win = hTcxCfg->tcx_mdct_window_minimumFB; /*Q15*/
117 54743 : BREAK;
118 14033 : case HALF_OVERLAP:
119 14033 : *left_overlap = hTcxCfg->tcx_mdct_window_half_lengthFB; /*Q0*/
120 14033 : move16();
121 14033 : *left_win = hTcxCfg->tcx_mdct_window_halfFB; /*Q15*/
122 14033 : BREAK;
123 30642 : case RECTANGULAR_OVERLAP:
124 30642 : *left_overlap = 0;
125 30642 : move16();
126 30642 : *left_win = NULL;
127 30642 : BREAK;
128 250293 : case FULL_OVERLAP:
129 250293 : *left_overlap = hTcxCfg->tcx_mdct_window_lengthFB; /*Q0*/
130 250293 : move16();
131 250293 : *left_win = hTcxCfg->tcx_aldo_window_1_FB_trunc; /*Q15*/
132 250293 : BREAK;
133 0 : default:
134 0 : assert( !"Not supported overlap" );
135 : }
136 :
137 : /* Right part */
138 360532 : SWITCH( right_mode )
139 : {
140 57544 : case MIN_OVERLAP:
141 57544 : *right_overlap = hTcxCfg->tcx_mdct_window_min_lengthFB; /*Q0*/
142 57544 : move16();
143 57544 : *right_win = hTcxCfg->tcx_mdct_window_minimumFB; /*Q15*/
144 57544 : BREAK;
145 14536 : case HALF_OVERLAP:
146 14536 : *right_overlap = hTcxCfg->tcx_mdct_window_half_lengthFB; /*Q0*/
147 14536 : move16();
148 14536 : *right_win = hTcxCfg->tcx_mdct_window_halfFB; /*Q15*/
149 14536 : BREAK;
150 30623 : case RECTANGULAR_OVERLAP:
151 30623 : *right_overlap = 0;
152 30623 : move16();
153 30623 : *right_win = NULL;
154 30623 : BREAK;
155 257829 : case FULL_OVERLAP:
156 257829 : *right_overlap = hTcxCfg->tcx_mdct_window_delayFB; /*Q0*/
157 257829 : move16();
158 257829 : *right_win = hTcxCfg->tcx_aldo_window_2_FB; /*Q15*/
159 257829 : BREAK;
160 0 : default:
161 0 : assert( !"Not supported overlap" );
162 : }
163 : }
164 469465 : }
165 :
166 469434 : 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 469434 : n = shr( left_overlap, 1 ); /*Q0*/
180 67882500 : FOR( w = 0; w < n; w++ )
181 : {
182 67413066 : *output++ = mult_r( *signal++, left_win[w].v.im ); /*Qx*/
183 67413066 : move16();
184 : }
185 67882500 : FOR( w = 0; w < n; w++ )
186 : {
187 67413066 : *output++ = mult_r( *signal++, left_win[n - 1 - w].v.re ); /*Qx*/
188 67413066 : move16();
189 : }
190 :
191 : /* Non overlapping region */
192 469434 : n = sub( L_frame, shr( add( left_overlap, right_overlap ), 1 ) ); /*Q0*/
193 192196586 : FOR( w = 0; w < n; w++ )
194 : {
195 191727152 : *output++ = *signal++; /*Qx*/
196 191727152 : move16();
197 : }
198 :
199 : /* Right overlap */
200 469434 : n = shr( right_overlap, 1 ); /*Q0*/
201 69215600 : FOR( w = 0; w < n; w++ )
202 : {
203 68746166 : *output++ = mult_r( *signal++, right_win[w].v.re ); /*Qx*/
204 68746166 : move16();
205 : }
206 69215600 : FOR( w = 0; w < n; w++ )
207 : {
208 68746166 : *output++ = mult_r( *signal++, right_win[n - 1 - w].v.im ); /*Qx*/
209 68746166 : move16();
210 : }
211 469434 : }
212 : /*-------------------------------------------------------------------*
213 : * WindowSignal()
214 : *
215 : *
216 : *-------------------------------------------------------------------*/
217 469434 : 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 469434 : 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 469434 : IF( EQ_16( left_overlap_mode, TRANSITION_OVERLAP ) )
246 : {
247 : /* Increase frame size for 5ms */
248 11137 : IF( fullband == 0 )
249 : {
250 316 : *L_frame = add( *L_frame, hTcxCfg->tcx5Size ); /*Q0*/
251 316 : move16();
252 316 : offset = negate( shr( hTcxCfg->tcx_mdct_window_trans_length, 1 ) ); /*Q0*/
253 : }
254 : ELSE
255 : {
256 10821 : *L_frame = add( *L_frame, hTcxCfg->tcx5SizeFB ); /*Q0*/
257 10821 : move16();
258 10821 : offset = negate( shr( hTcxCfg->tcx_mdct_window_trans_lengthFB, 1 ) ); /*Q0*/
259 : }
260 : }
261 :
262 : /*-----------------------------------------------------------*
263 : * Windowing *
264 : *-----------------------------------------------------------*/
265 :
266 469434 : tcx_windowing_analysis( in - sub( shr( l, 1 ), offset ), *L_frame, l, left_win, r, right_win, out );
267 469434 : test();
268 469434 : test();
269 469434 : 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 333629 : p = hTcxCfg->tcx_mdct_window_minimum; /*Q15*/
276 333629 : tmp = shr( hTcxCfg->tcx_mdct_window_min_length, 1 ); /*Q0*/
277 333629 : IF( fullband != 0 )
278 : {
279 228894 : p = hTcxCfg->tcx_mdct_window_minimumFB; /*Q15*/
280 228894 : tmp = shr( hTcxCfg->tcx_mdct_window_min_lengthFB, 1 ); /*Q0*/
281 : }
282 :
283 8964837 : FOR( i = 0; i < tmp; i++ )
284 : {
285 8631208 : out[i] = mult_r( out[i], p[i].v.im ); /*Qx*/
286 8631208 : move16();
287 : }
288 8964837 : FOR( i = 0; i < tmp; i++ )
289 : {
290 8631208 : out[i + tmp] = mult_r( out[i + tmp], p[tmp - 1 - i].v.re ); /*Qx*/
291 8631208 : move16();
292 : }
293 : }
294 :
295 469434 : *left_overlap_length = l;
296 469434 : move16();
297 469434 : *right_overlap_length = r;
298 469434 : move16();
299 469434 : }
300 : /*-------------------------------------------------------------------*
301 : * tcx_windowing_synthesis_current_frame()
302 : *
303 : *
304 : *-------------------------------------------------------------------*/
305 :
306 120186 : 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 120186 : overlap = shr( window_length, 1 ); /*Q0*/
335 :
336 : /* Past-frame is TCX concealed as CNG and current-frame is TCX */
337 120186 : test();
338 120186 : test();
339 120186 : test();
340 120186 : test();
341 120186 : 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 120186 : ELSE IF( EQ_16( left_rect, 1 ) && last_core_bfi == ACELP_CORE )
364 : {
365 24727 : tmp = sub( overlap, acelp_mem_len );
366 2333287 : FOR( i = 0; i < tmp; i++ )
367 : {
368 2308560 : move16();
369 2308560 : signal[i] = 0;
370 : }
371 :
372 24727 : IF( fullbandScale == 0 )
373 : {
374 :
375 16413 : tmp = shl( acelp_mem_len, 1 ); /*Qx*/
376 :
377 : /*OLA with ACELP*/
378 181363 : FOR( i = 0; i < acelp_mem_len; i++ )
379 : {
380 :
381 : /*window decoded TCX with aliasing*/
382 164950 : 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 164950 : 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 164950 : 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 164950 : move16();
390 164950 : signal[i + overlap - acelp_mem_len] = tmp2; /*Qx*/
391 : }
392 181363 : FOR( ; i < tmp; i++ )
393 : {
394 :
395 : /*window decoded TCX with aliasing*/
396 164950 : 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 164950 : 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 164950 : 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 164950 : move16();
403 164950 : signal[i + overlap - acelp_mem_len] = tmp2; /*Qx*/
404 : }
405 :
406 279021 : FOR( i = 0; i < M; i++ )
407 : {
408 262608 : move16();
409 262608 : 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 24727 : move16();
414 24727 : acelp_zir_len = 64;
415 :
416 24727 : IF( fullbandScale == 0 )
417 : {
418 16413 : set16_fx( acelp_zir, 0, acelp_zir_len );
419 16413 : 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 2502607 : FOR( i = 0; i < acelp_zir_len; i++ )
460 : {
461 : /*remove reconstructed ZIR and add ACELP ZIR*/
462 2477880 : move16();
463 2477880 : 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 95459 : 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 94999 : 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 94983 : IF( EQ_16( left_mode, 2 ) ) /* min. overlap */
514 : {
515 56989 : n = shr( sub( window_length, window_min_length ), 1 ); /*q0*/
516 2590297 : FOR( i = 0; i < n; i++ )
517 : {
518 2533308 : *signal++ = 0;
519 2533308 : move16();
520 : }
521 :
522 56989 : n = shr( window_min_length, 1 ); /*q0*/
523 1276191 : FOR( i = 0; i < n; i++ )
524 : {
525 1219202 : *signal = mult_r( *signal, window_min[i].v.im ); /*Qx*/
526 1219202 : move16();
527 1219202 : signal++;
528 : }
529 1276191 : FOR( i = 0; i < n; i++ )
530 : {
531 1219202 : *signal = mult_r( *signal, window_min[n - 1 - i].v.re ); /*Qx*/
532 1219202 : move16();
533 1219202 : signal++;
534 : }
535 : }
536 37994 : ELSE IF( EQ_16( left_mode, 3 ) ) /* half OL */
537 : {
538 : Word16 w;
539 :
540 14077 : n = shr( sub( window_length, window_half_length ), 1 );
541 333309 : FOR( i = 0; i < n; i++ )
542 : {
543 319232 : move16();
544 319232 : signal[i] = 0;
545 : }
546 14077 : n = shr( window_half_length, 1 );
547 912559 : FOR( w = 0; w < n; w++ )
548 : {
549 898482 : move16();
550 898482 : signal[i] = mult_r( signal[i], window_half[w].v.im ); /*Qx*/
551 898482 : i = add( i, 1 );
552 : }
553 912559 : FOR( w = 0; w < n; w++ )
554 : {
555 898482 : move16();
556 898482 : signal[i] = mult_r( signal[i], window_half[window_half_length / 2 - 1 - w].v.re ); /*Qx*/
557 898482 : i = add( i, 1 );
558 : }
559 : }
560 : ELSE
561 : { /* normal full/maximum overlap */
562 :
563 23917 : n = shr( window_length, 1 );
564 3639669 : FOR( i = 0; i < n; i++ )
565 : {
566 3615752 : move16();
567 3615752 : signal[i] = mult_r( signal[i], window[i].v.im ); /*Qx*/
568 : }
569 3639669 : FOR( ; i < window_length; i++ )
570 : {
571 3615752 : move16();
572 3615752 : 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 120186 : }
579 : /*-------------------------------------------------------------------*
580 : * tcx_windowing_synthesis_past_frame()
581 : *
582 : *
583 : *-------------------------------------------------------------------*/
584 121599 : 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 121599 : IF( EQ_16( right_mode, 2 ) ) /* min. overlap */
599 : {
600 60578 : signal += shr( sub( window_length, window_min_length ), 1 ); /*Qx*/
601 :
602 60578 : n = shr( window_min_length, 1 );
603 1359176 : FOR( i = 0; i < n; i++ )
604 : {
605 1298598 : *signal = mult_r( *signal, window_min[i].v.re ); /*Qx*/
606 1298598 : move16();
607 1298598 : signal++;
608 : }
609 1359176 : FOR( i = 0; i < n; i++ )
610 : {
611 1298598 : *signal = mult_r( *signal, window_min[n - 1 - i].v.im ); /*Qx*/
612 1298598 : move16();
613 1298598 : signal++;
614 : }
615 :
616 60578 : n = shr( sub( window_length, window_min_length ), 1 ); /*Q0*/
617 4113466 : FOR( i = 0; i < n; i++ )
618 : {
619 4052888 : *signal = 0;
620 4052888 : move16();
621 4052888 : signal++;
622 : }
623 : }
624 61021 : ELSE IF( EQ_16( right_mode, 3 ) ) /* half OL */
625 : {
626 : Word16 w;
627 :
628 16201 : i = shr( sub( window_length, window_half_length ), 1 ); /*Q0*/
629 16201 : n = shr( window_half_length, 1 ); /*Q0*/
630 1037347 : FOR( w = 0; w < n; w++ )
631 : {
632 1021146 : signal[i] = mult_r( signal[i], window_half[w].v.re ); /*Qx*/
633 1021146 : move16();
634 1021146 : i = add( i, 1 );
635 : }
636 1037347 : FOR( w = 0; w < n; w++ )
637 : {
638 1021146 : signal[i] = mult_r( signal[i], window_half[window_half_length / 2 - 1 - w].v.im ); /*Qx*/
639 1021146 : move16();
640 1021146 : i = add( i, 1 );
641 : }
642 1377729 : FOR( ; i < window_length; i++ )
643 : {
644 1361528 : move16();
645 1361528 : signal[i] = 0;
646 : }
647 : }
648 : ELSE /* normal full/maximum overlap */
649 : {
650 :
651 44820 : n = shr( window_length, 1 ); /*Q0*/
652 5774040 : FOR( i = 0; i < n; i++ )
653 : {
654 5729220 : move16();
655 5729220 : signal[i] = mult_r( signal[i], window[i].v.re ); /*Qx*/
656 5729220 : move16();
657 5729220 : signal[window_length - 1 - i] = mult_r( signal[window_length - 1 - i], window[i].v.im ); /*Qx*/
658 : }
659 : }
660 121599 : }
661 : /*-------------------------------------------------------------------*
662 : * lpc2mdct()
663 : *
664 : *
665 : *-------------------------------------------------------------------*/
666 :
667 275178 : 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 275178 : assert( length <= FDNS_NPTS );
689 275178 : sizeN = shl( length, 1 ); /*Q0*/
690 :
691 275178 : BASOP_getTables( NULL, &ptwiddle, &step, sizeN );
692 : /*ODFT*/
693 275178 : assert( lpcOrder < FDNS_NPTS );
694 : /* pre-twiddle */
695 4970699 : FOR( i = 0; i <= lpcOrder; i++ )
696 : {
697 4695521 : ComplexData[2 * i] = L_mult( lpcCoeffs[i], ptwiddle->v.re ); /*Q12*/
698 4695521 : move32();
699 4695521 : ComplexData[2 * i + 1] = L_negate( L_mult( lpcCoeffs[i], ptwiddle->v.im ) ); /*Q12*/
700 4695521 : move32();
701 4695521 : ptwiddle += step;
702 : }
703 : /* zero padding */
704 13191049 : FOR( ; i < FDNS_NPTS; i++ )
705 : {
706 12915871 : ComplexData[2 * i] = L_deposit_l( 0 );
707 12915871 : move32();
708 12915871 : ComplexData[2 * i + 1] = L_deposit_l( 0 );
709 12915871 : move32();
710 : }
711 :
712 275178 : 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 275178 : scale = add( norm_s( lpcCoeffs[0] ), 1 );
732 275178 : BASOP_cfft( (cmplx *) ComplexData, FDNS_NPTS, &scale, workBuffer ); /*Q31 - scale*/
733 : /*Get amplitude*/
734 275178 : j = sub( length, 1 );
735 275178 : k = 0;
736 9080874 : FOR( i = 0; i < length / 2; i++ )
737 : {
738 8805696 : s = sub( norm_l( L_max( L_abs( ComplexData[2 * i] ), L_abs( ComplexData[2 * i + 1] ) ) ), 1 );
739 8805696 : tmp16 = extract_h( L_shl( ComplexData[2 * i], s ) ); /*Q15 - scale + s*/
740 8805696 : tmp32 = L_mult( tmp16, tmp16 ); /*Q15 - 2*(scale - s)*/
741 8805696 : tmp16 = extract_h( L_shl( ComplexData[2 * i + 1], s ) ); /*Q15 - scale + s*/
742 8805696 : tmp16 = mac_r( tmp32, tmp16, tmp16 ); /*Q15 - 2*(scale - s)*/
743 8805696 : s = shl( sub( scale, s ), 1 );
744 8805696 : if ( tmp16 == 0 )
745 : {
746 0 : s = -16;
747 0 : move16();
748 : }
749 8805696 : if ( tmp16 == 0 )
750 : {
751 0 : tmp16 = 1;
752 0 : move16();
753 : }
754 8805696 : BASOP_Util_Sqrt_InvSqrt_MantExp( tmp16, s, &g, &g_e, &ig, &ig_e ); /*Q15 - ig_e*/
755 8805696 : if ( mdct_gains != 0 )
756 : {
757 8225440 : mdct_gains[k] = g; /*Q15 - g_e*/
758 8225440 : move16();
759 : }
760 8805696 : if ( mdct_gains_exp != 0 )
761 : {
762 8225440 : mdct_gains_exp[k] = g_e;
763 8225440 : move16();
764 : }
765 8805696 : if ( mdct_inv_gains != 0 )
766 : {
767 8212256 : mdct_inv_gains[k] = ig; /*Q15 - ig_e*/
768 8212256 : move16();
769 : }
770 8805696 : if ( mdct_inv_gains_exp != 0 )
771 : {
772 8212256 : mdct_inv_gains_exp[k] = ig_e;
773 8212256 : move16();
774 : }
775 8805696 : k = add( k, 1 );
776 8805696 : s = sub( norm_l( L_max( L_abs( ComplexData[2 * j] ), L_abs( ComplexData[2 * j + 1] ) ) ), 1 );
777 8805696 : tmp16 = extract_h( L_shl( ComplexData[2 * j], s ) ); /*Q15 - scale + s*/
778 8805696 : tmp32 = L_mult( tmp16, tmp16 ); /*Q15 - 2*(scale - s)*/
779 8805696 : tmp16 = extract_h( L_shl( ComplexData[2 * j + 1], s ) ); /*Q15 - scale + s*/
780 8805696 : tmp16 = mac_r( tmp32, tmp16, tmp16 ); /*Q15 - 2*(scale - s)*/
781 8805696 : s = shl( sub( scale, s ), 1 );
782 8805696 : if ( tmp16 == 0 )
783 : {
784 0 : s = -16;
785 0 : move16();
786 : }
787 8805696 : if ( tmp16 == 0 )
788 : {
789 0 : tmp16 = 1;
790 0 : move16();
791 : }
792 8805696 : BASOP_Util_Sqrt_InvSqrt_MantExp( tmp16, s, &g, &g_e, &ig, &ig_e );
793 8805696 : if ( mdct_gains != 0 )
794 : {
795 8225440 : mdct_gains[k] = g; /*Q15 - g_e*/
796 8225440 : move16();
797 : }
798 8805696 : if ( mdct_gains_exp != 0 )
799 : {
800 8225440 : mdct_gains_exp[k] = g_e;
801 8225440 : move16();
802 : }
803 8805696 : if ( mdct_inv_gains != 0 )
804 : {
805 8212256 : mdct_inv_gains[k] = ig; /*Q15 - ig_e*/
806 8212256 : move16();
807 : }
808 8805696 : if ( mdct_inv_gains_exp != 0 )
809 : {
810 8212256 : mdct_inv_gains_exp[k] = ig_e;
811 8212256 : move16();
812 : }
813 8805696 : j = sub( j, 1 );
814 8805696 : k = add( k, 1 );
815 : }
816 : }
817 275178 : }
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 581160 : 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 581160 : Word32 *px = x; /*Qx*/
992 581160 : Word16 const *pgains = gains;
993 581160 : Word16 const *pgainsexp = gains_exp;
994 : #ifdef BASOP_NOGLOB_DECLARE_LOCAL
995 581160 : Flag Overflow = 0;
996 : #endif
997 :
998 : /* FDNS_NPTS = 64 */
999 581160 : k = shr( lg, 6 ); /*Q0*/
1000 581160 : m = s_and( lg, 0x3F );
1001 :
1002 581160 : IF( m != 0 )
1003 : {
1004 19743 : IF( LE_16( m, FDNS_NPTS / 2 ) )
1005 : {
1006 19743 : n = idiv1616U( FDNS_NPTS, m ); /*Q0*/
1007 19743 : k1 = k;
1008 19743 : move16();
1009 19743 : 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 19743 : i = 0;
1020 19743 : move16();
1021 19743 : j = 0;
1022 19743 : move16();
1023 :
1024 1283295 : WHILE( LT_16( i, lg ) )
1025 : {
1026 :
1027 1263552 : k = k2;
1028 1263552 : move16();
1029 1263552 : if ( j != 0 )
1030 : {
1031 943632 : k = k1;
1032 943632 : move16();
1033 : }
1034 :
1035 1263552 : j = add( j, 1 );
1036 1263552 : if ( EQ_16( j, n ) )
1037 : {
1038 319920 : j = 0;
1039 319920 : move16();
1040 : }
1041 :
1042 : /* Limit number of loops, if end is reached */
1043 1263552 : k = s_min( k, sub( lg, i ) );
1044 :
1045 9243632 : FOR( l = 0; l < k; l++ )
1046 : {
1047 7980080 : *x = L_shl_o( Mpy_32_16_r( *x, *gains ), *gains_exp, &Overflow ); /*Qx*/
1048 7980080 : move32();
1049 7980080 : x++;
1050 : }
1051 1263552 : i = add( i, k );
1052 :
1053 1263552 : gains++;
1054 1263552 : gains_exp++;
1055 : }
1056 : }
1057 : ELSE
1058 : {
1059 3608180 : FOR( l = 0; l < k; l++ )
1060 : {
1061 3046763 : x = &px[l]; /*Qx*/
1062 3046763 : gains = pgains;
1063 3046763 : gains_exp = pgainsexp;
1064 198039595 : FOR( i = 0; i < FDNS_NPTS; i++ )
1065 : {
1066 194992832 : *x = L_shl_o( Mpy_32_16_r( *x, *gains ), *gains_exp, &Overflow ); /*Qx*/
1067 194992832 : move32();
1068 194992832 : x += k;
1069 194992832 : gains++;
1070 194992832 : gains_exp++;
1071 : }
1072 : }
1073 : }
1074 581160 : }
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 767661 : 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 767661 : j = 0;
1143 767661 : move16();
1144 : /* FDNS_NPTS = 64 */
1145 767661 : k = shr( lg, 6 ); /*Q0*/
1146 767661 : m = s_and( lg, 0x3F );
1147 :
1148 767661 : Word16 max_e = MIN16B;
1149 767661 : move16();
1150 49897965 : FOR( i = 0; i < FDNS_NPTS; i++ )
1151 : {
1152 49130304 : max_e = s_max( max_e, add( *x_e, gains_exp[i] ) );
1153 : }
1154 :
1155 767661 : IF( m != 0 )
1156 : {
1157 8021 : IF( LE_16( m, FDNS_NPTS / 2 ) )
1158 : {
1159 8021 : n = idiv1616U( FDNS_NPTS, m ); /*Q0*/
1160 8021 : k1 = k;
1161 8021 : move16();
1162 8021 : 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 8021 : i = 0;
1173 8021 : move16();
1174 8021 : j = 0;
1175 8021 : move16();
1176 :
1177 521365 : WHILE( LT_16( i, lg ) )
1178 : {
1179 513344 : IF( j % n != 0 )
1180 : {
1181 377040 : k = k1;
1182 377040 : move16();
1183 : }
1184 : ELSE
1185 : {
1186 136304 : k = k2;
1187 136304 : move16();
1188 : }
1189 :
1190 : /* Limit number of loops, if end is reached */
1191 513344 : k = s_min( k, sub( lg, i ) );
1192 :
1193 3885104 : FOR( l = 0; l < k; l++ )
1194 : {
1195 3371760 : x_fx[i] = Mpy_32_16_1( x_fx[i], gains_fx[j] ); /*Q31 - x_e*/
1196 3371760 : move32();
1197 3371760 : x_fx[i] = L_shr( x_fx[i], sub( max_e, add( *x_e, gains_exp[j] ) ) ); /*Q31 - max_e*/
1198 3371760 : move32();
1199 3371760 : i = add( i, 1 );
1200 : }
1201 513344 : j = add( j, 1 );
1202 : }
1203 : }
1204 : ELSE
1205 : {
1206 49376600 : FOR( i = 0; i < lg; )
1207 : {
1208 335128448 : FOR( l = 0; l < k; l++ )
1209 : {
1210 286511488 : x_fx[i] = Mpy_32_16_1( x_fx[i], gains_fx[j] ); /*Q31 - x_e*/
1211 286511488 : move32();
1212 286511488 : x_fx[i] = L_shr( x_fx[i], sub( max_e, add( *x_e, gains_exp[j] ) ) ); /*Q31 - max_e*/
1213 286511488 : move32();
1214 286511488 : i = add( i, 1 );
1215 : }
1216 48616960 : j = add( j, 1 );
1217 : }
1218 : }
1219 :
1220 767661 : *x_e = max_e;
1221 767661 : move16();
1222 :
1223 767661 : return;
1224 : }
1225 :
1226 :
1227 17495 : 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 17495 : assert( lg % FDNS_NPTS == 0 );
1238 17495 : k = shr( lg, 6 ); /* FDNS_NPTS = 64 Q0*/
1239 :
1240 17495 : IF( gains )
1241 : {
1242 : /* Linear interpolation */
1243 17495 : IF( EQ_16( k, 4 ) )
1244 : {
1245 15849 : jp = 0;
1246 15849 : move16();
1247 15849 : j = 0;
1248 15849 : move16();
1249 15849 : jn = 1;
1250 15849 : move16();
1251 :
1252 1030185 : FOR( i = 0; i < lg; i += 4 )
1253 : {
1254 1014336 : pg = gains[jp]; /*Q15 - gains_exp*/
1255 1014336 : move16();
1256 1014336 : g = gains[j]; /*Q15 - gains_exp*/
1257 1014336 : move16();
1258 1014336 : ng = gains[jn]; /*Q15 - gains_exp*/
1259 1014336 : move16();
1260 :
1261 : /* common exponent for pg and g */
1262 1014336 : tmp = sub( gains_exp[j], gains_exp[jp] );
1263 1014336 : if ( tmp > 0 )
1264 111291 : pg = shr( pg, tmp );
1265 1014336 : if ( tmp < 0 )
1266 66597 : g = shl( g, tmp );
1267 1014336 : e = s_max( gains_exp[j], gains_exp[jp] );
1268 :
1269 1014336 : tmp = mac_r( L_mult( pg, 12288 /*0.375f Q15*/ ), g, 20480 /*0.625f Q15*/ ); /*Q15 - gains_exp*/
1270 1014336 : x[i] = L_shl( Mpy_32_16_1( x[i], tmp ), e ); /*Qx*/
1271 1014336 : move32();
1272 :
1273 1014336 : tmp = mac_r( L_mult( pg, 4096 /*0.125f Q15*/ ), g, 28672 /*0.875f Q15*/ ); /*Q15 - gains_exp*/
1274 1014336 : x[i + 1] = L_shl( Mpy_32_16_1( x[i + 1], tmp ), e ); /*Qx*/
1275 1014336 : move32();
1276 :
1277 : /* common exponent for g and ng */
1278 1014336 : g = gains[j]; /*Q15 - gains_exp*/
1279 1014336 : move16();
1280 1014336 : tmp = sub( gains_exp[j], gains_exp[jn] );
1281 1014336 : if ( tmp > 0 )
1282 66597 : ng = shr( ng, tmp );
1283 1014336 : if ( tmp < 0 )
1284 111291 : g = shl( g, tmp );
1285 1014336 : e = s_max( gains_exp[j], gains_exp[jn] );
1286 :
1287 1014336 : tmp = mac_r( L_mult( g, 28672 /*0.875f Q15*/ ), ng, 4096 /*0.125f Q15*/ ); /*Q15 - gains_exp*/
1288 1014336 : x[i + 2] = L_shl( Mpy_32_16_1( x[i + 2], tmp ), e ); /*Qx*/
1289 1014336 : move32();
1290 :
1291 1014336 : tmp = mac_r( L_mult( g, 20480 /*0.625f Q15*/ ), ng, 12288 /*0.375f Q15*/ ); /*Q15 - gains_exp*/
1292 1014336 : x[i + 3] = L_shl( Mpy_32_16_1( x[i + 3], tmp ), e ); /*Qx*/
1293 1014336 : move32();
1294 :
1295 1014336 : jp = j;
1296 1014336 : move16();
1297 1014336 : j = jn;
1298 1014336 : move16();
1299 1014336 : jn = s_min( add( jn, 1 ), FDNS_NPTS - 1 );
1300 : }
1301 : }
1302 1646 : ELSE IF( EQ_16( k, 5 ) )
1303 : {
1304 1646 : jp = 0;
1305 1646 : move16();
1306 1646 : j = 0;
1307 1646 : move16();
1308 1646 : jn = 1;
1309 1646 : move16();
1310 :
1311 106990 : FOR( i = 0; i < lg; i += 5 )
1312 : {
1313 105344 : pg = gains[jp]; /*Q15 - gains_exp*/
1314 105344 : move16();
1315 105344 : g = gains[j]; /*Q15 - gains_exp*/
1316 105344 : move16();
1317 105344 : ng = gains[jn]; /*Q15 - gains_exp*/
1318 105344 : move16();
1319 :
1320 : /* common exponent for pg and g */
1321 105344 : tmp = sub( gains_exp[j], gains_exp[jp] );
1322 105344 : if ( tmp > 0 )
1323 11181 : pg = shr( pg, tmp );
1324 105344 : if ( tmp < 0 )
1325 6544 : g = shl( g, tmp );
1326 105344 : e = s_max( gains_exp[j], gains_exp[jp] );
1327 :
1328 105344 : tmp = mac_r( L_mult( pg, 13107 /*0.40f Q15*/ ), g, 19661 /*0.60f Q15*/ ); /*Q15 - gains_exp*/
1329 105344 : x[i] = L_shl( Mpy_32_16_1( x[i], tmp ), e ); /*Qx*/
1330 105344 : move32();
1331 :
1332 105344 : tmp = mac_r( L_mult( pg, 6554 /*0.20f Q15*/ ), g, 26214 /*0.80f Q15*/ ); /*Q15 - gains_exp*/
1333 105344 : x[i + 1] = L_shl( Mpy_32_16_1( x[i + 1], tmp ), e ); /*Qx*/
1334 105344 : move32();
1335 :
1336 :
1337 105344 : x[i + 2] = L_shl( Mpy_32_16_1( x[i + 2], gains[j] ), gains_exp[j] ); /*Qx*/
1338 105344 : move32();
1339 :
1340 : /* common exponent for g and ng */
1341 105344 : g = gains[j]; /*Q15 - gains_exp*/
1342 105344 : move16();
1343 105344 : tmp = sub( gains_exp[j], gains_exp[jn] );
1344 105344 : if ( tmp > 0 )
1345 6544 : ng = shr( ng, tmp );
1346 105344 : if ( tmp < 0 )
1347 11181 : g = shl( g, tmp );
1348 105344 : e = s_max( gains_exp[j], gains_exp[jn] );
1349 :
1350 105344 : tmp = mac_r( L_mult( g, 26214 /*0.80f Q15*/ ), ng, 6554 /*0.20f Q15*/ ); /*Q15 - gains_exp*/
1351 105344 : x[i + 3] = L_shl( Mpy_32_16_1( x[i + 3], tmp ), e ); /*Qx*/
1352 105344 : move32();
1353 :
1354 105344 : tmp = mac_r( L_mult( g, 19661 /*0.60f Q15*/ ), ng, 13107 /*0.40f Q15*/ ); /*Q15 - gains_exp*/
1355 105344 : x[i + 4] = L_shl( Mpy_32_16_1( x[i + 4], tmp ), e ); /*Qx*/
1356 105344 : move32();
1357 :
1358 105344 : jp = j;
1359 105344 : move16();
1360 105344 : j = jn;
1361 105344 : move16();
1362 105344 : 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 17495 : }
1382 :
1383 56365 : 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 56365 : Flag Overflow = 0;
1394 : #endif
1395 :
1396 :
1397 56365 : assert( lpcGains[0] >= 0x4000 );
1398 :
1399 56365 : max_val = lpcGains[0]; /*Q15 - lpcGains_e*/
1400 56365 : move16();
1401 56365 : max_e = lpcGains_e[0];
1402 56365 : move16();
1403 56365 : min = lpcGains[0]; /*Q15 - lpcGains_e*/
1404 56365 : move16();
1405 56365 : min_e = lpcGains_e[0];
1406 56365 : move16();
1407 :
1408 : /* find minimum (min) and maximum (max_val) of LPC gains in low frequencies */
1409 507285 : FOR( i = 1; i < 9; i++ )
1410 : {
1411 450920 : IF( compMantExp16Unorm( lpcGains[i], lpcGains_e[i], min, min_e ) < 0 )
1412 : {
1413 333520 : min = lpcGains[i]; /*Q15 - lpcGains_e*/
1414 333520 : move16();
1415 333520 : min_e = lpcGains_e[i];
1416 333520 : move16();
1417 : }
1418 :
1419 450920 : IF( compMantExp16Unorm( lpcGains[i], lpcGains_e[i], max_val, max_e ) > 0 )
1420 : {
1421 82813 : max_val = lpcGains[i]; /*Q15 - lpcGains_e*/
1422 82813 : move16();
1423 82813 : max_e = lpcGains_e[i];
1424 82813 : move16();
1425 : }
1426 : }
1427 :
1428 56365 : min_e = add( min_e, 5 ); /* min *= 32.0f; */
1429 :
1430 56365 : test();
1431 56365 : IF( ( compMantExp16Unorm( max_val, max_e, min, min_e ) < 0 ) && ( min > 0 ) )
1432 : {
1433 : /* fac = tmp = (float)pow(max_val / min, 0.0078125f); */
1434 56365 : tmp_e = min_e;
1435 56365 : move16();
1436 56365 : tmp = Inv16( min, &tmp_e ); /*Q15 - tmp_e*/
1437 56365 : L_tmp = L_shl( L_mult( tmp, max_val ), add( tmp_e, max_e ) ); /* Q31 */
1438 56365 : L_tmp = BASOP_Util_Log2( L_tmp ); /* Q25 */
1439 56365 : L_tmp = L_shr( L_tmp, 7 ); /* 0.0078125f = 1.f/(1<<7) */
1440 56365 : L_tmp = BASOP_Util_InvLog2( L_tmp ); /* Q31 */
1441 56365 : tmp = round_fx_o( L_tmp, &Overflow ); /* Q15 */
1442 56365 : fac = tmp; /* Q15 */
1443 56365 : move16();
1444 :
1445 : /* gradual lowering of lowest 32 bins; DC is lowered by (max_val/tmp)^1/4 */
1446 1860045 : FOR( i = 31; i >= 0; i-- )
1447 : {
1448 1803680 : x[i] = Mpy_32_16_1( x[i], fac );
1449 1803680 : move32();
1450 1803680 : if ( lf_deemph_factors != NULL )
1451 : {
1452 1007488 : lf_deemph_factors[i] = mult_r( lf_deemph_factors[i], fac );
1453 1007488 : move16();
1454 : }
1455 1803680 : fac = mult_r( fac, tmp ); /* Q15 */
1456 : }
1457 : }
1458 56365 : }
1459 :
1460 258898 : 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 258898 : tmp32 = 0; /* to avoid compilation warnings */
1474 258898 : move32();
1475 :
1476 258898 : IF( tcx_lpc_shaped_ari == 0 )
1477 : {
1478 209919 : v2 = L_shl( 2, sub( 31, x_e ) ); /* 2.0 */
1479 209919 : v4 = L_shl( v2, 1 ); /* 4.0 */
1480 209919 : lg_4 = shr( lg, 2 ); /* lg/4 */
1481 :
1482 : /* 1. find first magnitude maximum in lower quarter of spectrum */
1483 209919 : i_max = -1;
1484 209919 : move16();
1485 :
1486 1241984 : FOR( i = 0; i < lg_4; i++ )
1487 : {
1488 1234851 : IF( GE_32( L_abs( x[i] ), v4 ) )
1489 : {
1490 :
1491 : /* Debug initialization to catch illegal x[i] values. */
1492 202786 : tmp32 = 0;
1493 202786 : move32();
1494 :
1495 202786 : if ( x[i] < 0 )
1496 101465 : tmp32 = L_add( x[i], v2 ); /*Q31 - x_e*/
1497 202786 : if ( x[i] > 0 )
1498 101321 : tmp32 = L_sub( x[i], v2 ); /*Q31 - x_e*/
1499 :
1500 202786 : assert( tmp32 != 0 );
1501 :
1502 202786 : x[i] = tmp32; /*Q31 - x_e*/
1503 202786 : move32();
1504 202786 : i_max = i;
1505 202786 : move16();
1506 202786 : BREAK;
1507 : }
1508 : }
1509 :
1510 : /* 2. expand value range of all xi up to i_max: two extra steps */
1511 707544 : FOR( i = 0; i < i_max; i++ )
1512 : {
1513 497625 : x[i] = L_shr( x[i], 1 ); /*Q31 - x_e*/
1514 497625 : move32();
1515 497625 : lf_deemph_factors[i] = shr( lf_deemph_factors[i], 1 ); /*Q15*/
1516 497625 : move16();
1517 : }
1518 :
1519 : /* 3. find first magnitude maximum in lower quarter of spectrum */
1520 209919 : i_max_old = i_max; /*Q0*/
1521 209919 : move16();
1522 :
1523 209919 : IF( i_max_old >= 0 )
1524 : {
1525 202786 : i_max = -1;
1526 202786 : move16();
1527 :
1528 1035191 : FOR( i = 0; i < lg_4; i++ )
1529 : {
1530 1035170 : IF( GE_32( L_abs( x[i] ), v4 ) )
1531 : {
1532 202765 : assert( x[i] != 0 );
1533 202765 : if ( x[i] < 0 )
1534 101790 : tmp32 = L_add( x[i], v2 ); /*Q31 - x_e*/
1535 202765 : if ( x[i] >= 0 )
1536 100975 : tmp32 = L_sub( x[i], v2 ); /*Q31 - x_e*/
1537 202765 : x[i] = tmp32; /*Q31 - x_e*/
1538 202765 : move32();
1539 202765 : i_max = i;
1540 202765 : move16();
1541 202765 : BREAK;
1542 : }
1543 : }
1544 : }
1545 :
1546 : /* 4. expand value range of all xi up to i_max: two extra steps */
1547 1040788 : FOR( i = 0; i < i_max; i++ )
1548 : {
1549 830869 : x[i] = L_shr( x[i], 1 ); /*Q31 - x_e*/
1550 830869 : move32();
1551 830869 : lf_deemph_factors[i] = shr( lf_deemph_factors[i], 1 ); /*Q15*/
1552 830869 : move16();
1553 : }
1554 :
1555 : /* 5. always expand two lines; lines could be at index 0 and 1! */
1556 209919 : i_max = s_max( i_max, i_max_old ); /*Q0*/
1557 209919 : i = add( i_max, 1 );
1558 :
1559 209919 : IF( x[i] < 0 )
1560 : {
1561 93095 : tmp32 = L_sub( x[i], L_negate( v4 ) );
1562 :
1563 93095 : if ( tmp32 > 0 )
1564 : {
1565 33351 : lf_deemph_factors[i] = shr( lf_deemph_factors[i], 1 ); /*Q15*/
1566 33351 : move16();
1567 : }
1568 93095 : if ( tmp32 <= 0 )
1569 : {
1570 59744 : x[i] = L_add( x[i], v2 ); /*Q31 - x_e*/
1571 59744 : move32();
1572 : }
1573 93095 : if ( tmp32 > 0 )
1574 : {
1575 33351 : x[i] = L_shr( x[i], 1 ); /*Q31 - x_e*/
1576 33351 : move32();
1577 : }
1578 : }
1579 : ELSE
1580 : {
1581 116824 : tmp32 = L_sub( x[i], v4 );
1582 :
1583 116824 : if ( tmp32 < 0 )
1584 : {
1585 55199 : lf_deemph_factors[i] = shr( lf_deemph_factors[i], 1 ); /*Q15*/
1586 55199 : move16();
1587 : }
1588 116824 : if ( tmp32 >= 0 )
1589 : {
1590 61625 : x[i] = L_sub( x[i], v2 ); /*Q31 - x_e*/
1591 61625 : move32();
1592 : }
1593 116824 : if ( tmp32 < 0 )
1594 : {
1595 55199 : x[i] = L_shr( x[i], 1 ); /*Q31 - x_e*/
1596 55199 : move32();
1597 : }
1598 : }
1599 209919 : i = add( i, 1 );
1600 :
1601 209919 : IF( x[i] < 0 )
1602 : {
1603 89674 : tmp32 = L_sub( x[i], L_negate( v4 ) );
1604 :
1605 89674 : if ( tmp32 > 0 )
1606 : {
1607 35340 : lf_deemph_factors[i] = shr( lf_deemph_factors[i], 1 ); /*Q15*/
1608 35340 : move16();
1609 : }
1610 89674 : if ( tmp32 <= 0 )
1611 : {
1612 54334 : x[i] = L_add( x[i], v2 ); /*Q31 - x_e*/
1613 54334 : move32();
1614 : }
1615 89674 : if ( tmp32 > 0 )
1616 : {
1617 35340 : x[i] = L_shr( x[i], 1 ); /*Q31 - x_e*/
1618 35340 : move32();
1619 : }
1620 : }
1621 : ELSE
1622 : {
1623 120245 : tmp32 = L_sub( x[i], v4 );
1624 :
1625 120245 : if ( tmp32 < 0 )
1626 : {
1627 66288 : lf_deemph_factors[i] = shr( lf_deemph_factors[i], 1 ); /*Q15*/
1628 66288 : move16();
1629 : }
1630 120245 : if ( tmp32 >= 0 )
1631 : {
1632 53957 : x[i] = L_sub( x[i], v2 ); /*Q31 - x_e*/
1633 53957 : move32();
1634 : }
1635 120245 : if ( tmp32 < 0 )
1636 : {
1637 66288 : x[i] = L_shr( x[i], 1 ); /*Q31 - x_e*/
1638 66288 : move32();
1639 : }
1640 : }
1641 : }
1642 : ELSE /*if(!tcx_lpc_shaped_ari)*/
1643 : {
1644 48979 : PsychAdaptLowFreqDeemph( x, lpcGains, lpcGains_e, lf_deemph_factors );
1645 : } /*if(!tcx_lpc_shaped_ari)*/
1646 258898 : }
1647 :
1648 220495 : 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 220495 : tmp1 = getInvFrameLen( L_frame ); /*Q21*/
1672 :
1673 : /* tilt_factor = (float)pow(max_val(0.375f, tiltCompFactor), 1.0f/(float)L_frame); */
1674 220495 : tmp32 = BASOP_Util_Log2( L_deposit_h( s_max( 0x3000, tiltCompFactor ) ) ); /* 6Q25 */
1675 220495 : tmp32 = L_shr( Mpy_32_16_1( tmp32, tmp1 ), 6 ); /*Q25*/
1676 : BASOP_SATURATE_WARNING_OFF_EVS;
1677 220495 : 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 220495 : i = iFirstLine;
1682 220495 : move16();
1683 220495 : tmp1 = shr( iFirstLine, 1 ); /*Q0*/
1684 220495 : 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 656069 : FOR( ; i > tmp1; i-- )
1692 : {
1693 654791 : IF( Q[i] != 0 )
1694 : {
1695 219217 : BREAK;
1696 : }
1697 : }
1698 : /* fac_ns *= (float)pow(tilt_factor, (float)i); */
1699 15087268 : FOR( m = 0; m < i; m++ )
1700 : {
1701 14866773 : fac_ns = mult_r( fac_ns, tilt_factor ); /*Q15*/
1702 : }
1703 220495 : i = add( i, 1 );
1704 220495 : segmentOffset = i;
1705 : }
1706 220495 : nrg = L_deposit_l( 1 );
1707 220495 : win = 0;
1708 220495 : move16();
1709 :
1710 66421881 : FOR( ; i < lowpassLine; i++ )
1711 : {
1712 66201386 : fac_ns = mult_r( fac_ns, tilt_factor ); /*Q15*/
1713 :
1714 66201386 : IF( Q[i] != 0 )
1715 : {
1716 18797467 : IF( win > 0 )
1717 : {
1718 : /* RMS-normalize current noise-filled segment */
1719 9430721 : tmp1 = BASOP_Util_Divide3216_Scale( nrg, sub( i, segmentOffset ), &s ); /* mean */
1720 9430721 : s = add( s, 9 - 15 ); /* scaling */
1721 9430721 : tmp1 = ISqrt16( tmp1, &s ); /* 1/RMS Q15 - s*/
1722 9430721 : tmp1 = mult_r( tmp1, inv_int[nTransWidth] ); /* compensate win Q15 - s*/
1723 9430721 : s = add( s, sub( 16, Q_e ) ); /* scaling */
1724 :
1725 9430721 : tmp2 = sub( i, win );
1726 9430721 : IF( LT_16( segmentOffset, tmp2 ) )
1727 : {
1728 9984835 : FOR( m = segmentOffset; m < tmp2; m++ )
1729 : {
1730 8783123 : Q[m] = L_shl( Mpy_32_16_1( Q[m], tmp1 ), s ); /*Q31 - Q_e*/
1731 8783123 : move32();
1732 : }
1733 : }
1734 :
1735 9430721 : tmp2 = mult( tmp1, inv_int[nTransWidth] );
1736 9430721 : tmp1 = extract_l( L_mult0( tmp2, win ) );
1737 36356261 : FOR( m = sub( i, win ); m < i; m++ )
1738 : {
1739 26925540 : Q[m] = L_shl( Mpy_32_16_1( Q[m], tmp1 ), s ); /*Q31 - Q_e*/
1740 26925540 : move32();
1741 26925540 : win = sub( win, 1 );
1742 26925540 : tmp1 = sub( tmp1, tmp2 );
1743 : }
1744 :
1745 9430721 : nrg = L_deposit_l( 1 ); /* start new segment: reset noise segment energy */
1746 : }
1747 18797467 : segmentOffset = add( i, 1 );
1748 : }
1749 : ELSE /* line is zero, so fill line and update window and energy */
1750 : {
1751 47403919 : if ( LT_16( win, nTransWidth ) )
1752 : {
1753 28241703 : win = add( win, 1 );
1754 : }
1755 :
1756 47403919 : Random( &seed );
1757 47403919 : Q[i] = L_mult0( mult( seed, fac_ns ), win ); /*Q31 - Q_e*/
1758 47403919 : move32();
1759 :
1760 47403919 : tmp1 = shr( seed, 4 );
1761 47403919 : nrg = L_mac0( nrg, tmp1, tmp1 ); /* sum up energy of current noise segment */
1762 :
1763 47403919 : if ( infoTCXNoise ) /* set noiseflags for IGF */
1764 : {
1765 116746 : infoTCXNoise[i] = 1;
1766 116746 : move16();
1767 : }
1768 : }
1769 : }
1770 :
1771 220495 : IF( win > 0 )
1772 : {
1773 : /* RMS-normalize uppermost noise-filled segment */
1774 204483 : tmp1 = BASOP_Util_Divide3216_Scale( nrg, sub( lowpassLine, segmentOffset ), &s ); /* mean */
1775 204483 : s = add( s, 9 - 15 ); /* compensate energy scaling */
1776 204483 : tmp1 = ISqrt16( tmp1, &s ); /* 1/RMS Q15 - s*/
1777 204483 : tmp1 = mult_r( tmp1, inv_int[nTransWidth] ); /* compensate win Q15 - s*/
1778 204483 : s = add( s, sub( 16, Q_e ) ); /* compensate noise scaling */
1779 :
1780 11899739 : FOR( m = segmentOffset; m < lowpassLine; m++ )
1781 : {
1782 11695256 : Q[m] = L_shl( Mpy_32_16_1( Q[m], tmp1 ), s ); /*Q31 - Q_e*/
1783 11695256 : move32();
1784 : }
1785 : }
1786 220495 : }
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 16180 : 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 16180 : IF( GT_32( total_brate, ACELP_32k ) )
2008 : {
2009 12996 : InitTnsConfiguration( bwidth, shr( L_frame, 1 ), &tnsConfig[0][0], igfStopFreq, total_brate, element_mode, MCT_flag );
2010 : }
2011 16180 : InitTnsConfiguration( bwidth, L_frame, &tnsConfig[1][0], igfStopFreq, total_brate, element_mode, MCT_flag );
2012 16180 : InitTnsConfiguration( bwidth, add( L_frame, shr( L_frame, 2 ) ), &tnsConfig[1][1], igfStopFreq, total_brate, element_mode, MCT_flag );
2013 16180 : }
2014 :
2015 30763 : 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 30763 : IF( GT_32( total_brate, ACELP_32k ) )
2025 : {
2026 20835 : InitTnsConfiguration_ivas_fx( bwidth, shr( L_frame, 1 ), &tnsConfig[0][0], igfStopFreq, total_brate, element_mode, MCT_flag );
2027 : }
2028 30763 : InitTnsConfiguration_ivas_fx( bwidth, L_frame, &tnsConfig[1][0], igfStopFreq, total_brate, element_mode, MCT_flag );
2029 30763 : InitTnsConfiguration_ivas_fx( bwidth, add( L_frame, shr( L_frame, 2 ) ), &tnsConfig[1][1], igfStopFreq, total_brate, element_mode, MCT_flag );
2030 30763 : }
2031 :
2032 :
2033 1750761 : void SetTnsConfig(
2034 : TCX_CONFIG_HANDLE hTcxCfg, /* i : configuration of TCX */
2035 : const Word16 isTCX20, /*Q0*/
2036 : const Word16 isAfterACELP /*Q0*/ )
2037 : {
2038 1750761 : move16();
2039 1750761 : hTcxCfg->pCurrentTnsConfig = &hTcxCfg->tnsConfig[isTCX20][isAfterACELP];
2040 1750761 : assert( hTcxCfg->pCurrentTnsConfig != NULL );
2041 1750761 : }
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 46886 : 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 46886 : tnsConfig[0][0].allowTnsOnWhite = allowTnsOnWhite; /*Q0*/
2056 46886 : move16();
2057 46886 : tnsConfig[0][1].allowTnsOnWhite = allowTnsOnWhite;
2058 46886 : move16();
2059 46886 : tnsConfig[1][0].allowTnsOnWhite = allowTnsOnWhite;
2060 46886 : move16();
2061 46886 : tnsConfig[1][1].allowTnsOnWhite = allowTnsOnWhite;
2062 46886 : move16();
2063 46886 : return;
2064 : }
2065 : #endif
2066 : #undef IVAS_CODE_TCX_UTIL
2067 :
2068 862103 : 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 862103 : Flag Overflow = 0;
2086 : #endif
2087 :
2088 862103 : maxX = L_deposit_l( 1 );
2089 862103 : maxY = L_deposit_l( 1 );
2090 862103 : minX = L_deposit_l( -1 );
2091 862103 : minY = L_deposit_l( -1 );
2092 699463223 : FOR( i = 0; i < n; i++ )
2093 : {
2094 698601120 : if ( x[i] > 0 )
2095 228444084 : maxX = L_max( maxX, x[i] ); /*Q31 - x_e*/
2096 698601120 : if ( x[i] < 0 )
2097 228498921 : minX = L_min( minX, x[i] ); /*Q31 - x_e*/
2098 :
2099 698601120 : if ( y[i] > 0 )
2100 73868394 : maxY = L_max( maxY, y[i] ); /*Q31 - y_e*/
2101 698601120 : if ( y[i] < 0 )
2102 74017975 : minY = L_min( minY, y[i] ); /*Q31 - y_e*/
2103 : }
2104 862103 : sx = s_min( norm_l( maxX ), norm_l( minX ) );
2105 862103 : sy = s_min( norm_l( maxY ), norm_l( minY ) );
2106 862103 : sx = sub( sx, 4 );
2107 862103 : sy = sub( sy, 4 );
2108 :
2109 862103 : ener = L_deposit_l( 0 );
2110 862103 : corr = L_deposit_l( 0 );
2111 699463223 : FOR( i = 0; i < n; i++ )
2112 : {
2113 698601120 : tmp = round_fx( L_shl( y[i], sy ) ); /*Q15 - y_e + sy*/
2114 698601120 : ener = L_mac0( ener, tmp, tmp ); /*Q30 - 2*(y_e - sy)*/
2115 698601120 : corr = L_mac0( corr, tmp, round_fx( L_shl( x[i], sx ) ) ); /*Q30 - 2*(x_e - sx + y_e - sy)*/
2116 : }
2117 :
2118 862103 : if ( ener == 0 )
2119 2289 : ener = L_deposit_l( 1 );
2120 :
2121 862103 : ener_e = add( shl( sub( y_e, sy ), 1 ), 1 );
2122 862103 : corr_e = add( sub( add( x_e, y_e ), add( sx, sy ) ), 1 );
2123 :
2124 862103 : tmp = sub( norm_l( corr ), 1 );
2125 862103 : corr = L_shl( corr, tmp ); /*Q31 - corr_e + tmp*/
2126 862103 : corr_e = sub( corr_e, tmp );
2127 :
2128 862103 : tmp = norm_l( ener );
2129 862103 : ener = L_shl( ener, tmp ); /*Q31 - ener_e + tmp*/
2130 862103 : ener_e = sub( ener_e, tmp );
2131 :
2132 862103 : tmp = div_s( abs_s( round_fx_o( corr, &Overflow ) ), round_fx_o( ener, &Overflow ) ); /*Q15 - (corr_e - ener_e)*/
2133 862103 : if ( corr < 0 )
2134 0 : tmp = negate( tmp );
2135 :
2136 862103 : *gain = tmp;
2137 862103 : move16();
2138 862103 : *gain_e = sub( corr_e, ener_e );
2139 862103 : move16();
2140 :
2141 862103 : if ( en_y != NULL )
2142 : {
2143 862103 : *en_y = ener; /*Q31 - ener_e*/
2144 862103 : move32();
2145 : }
2146 862103 : if ( en_y_e != NULL )
2147 : {
2148 862103 : *en_y_e = ener_e;
2149 862103 : move16();
2150 : }
2151 862103 : }
2152 101 : 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 101 : hTcxCfg->tcx_mdct_window_length = extract_l( L_shr( L_mult0( L_LOOK_12k8, fscale ), LD_FSCALE_DENOM ) ); /*Q0*/
2161 101 : move16();
2162 101 : hTcxCfg->tcx_mdct_window_delay = hTcxCfg->tcx_mdct_window_length; /*Q0*/
2163 101 : move16();
2164 :
2165 101 : hTcxCfg->tcx_mdct_window_half_length = extract_l( L_shr( L_mult0( L_LOOK_12k8 - NS2SA( 12800, 5000000L ), fscale ), LD_FSCALE_DENOM ) );
2166 101 : move16();
2167 101 : hTcxCfg->tcx_mdct_window_min_length = shr( L_frame, 4 ); /* 1.25ms Q0*/
2168 101 : move16();
2169 101 : hTcxCfg->tcx_mdct_window_trans_length = shr( L_frame, 4 ); /* 1.25ms Q0*/
2170 101 : move16();
2171 101 : hTcxCfg->tcx5Size = shr( L_frame, 2 ); /* 5ms Q0*/
2172 101 : move16();
2173 101 : hTcxCfg->tcx_mdct_window_lengthFB = extract_l( L_shr( L_mult0( L_LOOK_12k8, fscaleFB ), LD_FSCALE_DENOM ) ); /*Q0*/
2174 101 : move16();
2175 101 : hTcxCfg->tcx_mdct_window_delayFB = hTcxCfg->tcx_mdct_window_lengthFB; /*Q0*/
2176 101 : move16();
2177 :
2178 101 : hTcxCfg->tcx_mdct_window_half_lengthFB = extract_l( L_shr( L_mult0( L_LOOK_12k8 - NS2SA( 12800, 5000000L ), fscaleFB ), LD_FSCALE_DENOM ) ); /*Q0*/
2179 101 : move16();
2180 101 : hTcxCfg->tcx_mdct_window_min_lengthFB = shr( L_frameTCX, 4 ); /* 1.25ms Q0*/
2181 101 : move16();
2182 101 : hTcxCfg->tcx_mdct_window_trans_lengthFB = shr( L_frameTCX, 4 ); /* 1.25ms Q0*/
2183 101 : move16();
2184 101 : hTcxCfg->tcx5SizeFB = shr( L_frameTCX, 2 ); /* 5ms Q0*/
2185 101 : move16();
2186 101 : mdct_window_sine( hTcxCfg->tcx_mdct_window, hTcxCfg->tcx_mdct_window_length );
2187 101 : mdct_window_sine( hTcxCfg->tcx_mdct_window_half, hTcxCfg->tcx_mdct_window_half_length );
2188 101 : mdct_window_sine( hTcxCfg->tcx_mdct_window_minimum, hTcxCfg->tcx_mdct_window_min_length );
2189 101 : mdct_window_sine( hTcxCfg->tcx_mdct_window_trans, hTcxCfg->tcx_mdct_window_trans_length );
2190 :
2191 101 : mdct_window_sine( hTcxCfg->tcx_mdct_windowFB, hTcxCfg->tcx_mdct_window_lengthFB );
2192 101 : mdct_window_sine( hTcxCfg->tcx_mdct_window_halfFB, hTcxCfg->tcx_mdct_window_half_lengthFB );
2193 101 : mdct_window_sine( hTcxCfg->tcx_mdct_window_minimumFB, hTcxCfg->tcx_mdct_window_min_lengthFB );
2194 101 : mdct_window_sine( hTcxCfg->tcx_mdct_window_transFB, hTcxCfg->tcx_mdct_window_trans_lengthFB );
2195 :
2196 : /*ALDO windows for MODE2*/
2197 101 : mdct_window_aldo( hTcxCfg->tcx_aldo_window_1, hTcxCfg->tcx_aldo_window_1_trunc, hTcxCfg->tcx_aldo_window_2, L_frame );
2198 101 : 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 101 : }
|