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 <math.h>
8 : #include "options.h"
9 : #include "prot_fx.h"
10 : #include "basop_util.h"
11 : #include "rom_basop_util.h"
12 : #include "rom_com.h"
13 :
14 : #define inv_int InvIntTable
15 :
16 2522051 : Word16 tcxGetNoiseFillingTilt(
17 : const Word16 A[],
18 : const Word16 lpcorder,
19 : const Word16 L_frame,
20 : const Word16 mode,
21 : Word16 *noiseTiltFactor /*Q15*/
22 : )
23 : {
24 : Word16 firstLine;
25 : Word32 tmp;
26 : Word16 As[M + 1];
27 :
28 :
29 2522051 : IF( mode != 0 )
30 : {
31 2429266 : firstLine = idiv1616U( L_frame, 6 );
32 2429266 : *noiseTiltFactor = 18432 /*0.5625f Q15*/;
33 2429266 : move16();
34 : }
35 : ELSE
36 : {
37 92785 : firstLine = shr( L_frame, 3 );
38 :
39 92785 : Copy_Scale_sig( A, As, add( lpcorder, 1 ), sub( norm_s( A[0] ), 2 ) ); // Q(12)
40 92785 : tmp = get_gain( As + 1, As, lpcorder );
41 : BASOP_SATURATE_WARNING_OFF_EVS;
42 92785 : *noiseTiltFactor = add_sat( round_fx_sat( L_shl_sat( tmp, 15 ) ), 3072 /*0.09375f Q15*/ );
43 92785 : move16();
44 : BASOP_SATURATE_WARNING_ON_EVS;
45 : }
46 :
47 :
48 2522051 : return firstLine;
49 : }
50 :
51 :
52 33173 : void tcxFormantEnhancement(
53 : Word16 xn_buf[], // Q(15-xn_buf_e)
54 : const Word16 gainlpc[], // Q(15-gainlpc_e)
55 : const Word16 gainlpc_e[],
56 : Word32 spectrum[], // Q(31-spectrum_e)
57 : Word16 *spectrum_e,
58 : const Word16 L_frame,
59 : const Word16 L_frameTCX )
60 : {
61 : Word16 i, j, k, l, n;
62 : Word16 fac, fac0, fac1, fac_e, d, tmp;
63 : Word16 xn_buf_e, xn_one, m, e;
64 : #ifndef ISSUE_1836_replace_overflow_libcom
65 : #ifdef BASOP_NOGLOB_DECLARE_LOCAL
66 : Flag Overflow = 0;
67 : move32();
68 : #endif
69 : #endif
70 :
71 33173 : k = shr( L_frame, 6 ); /* FDNS_NPTS = 64 */
72 33173 : l = 0;
73 33173 : move16();
74 :
75 : /* get exponent */
76 33173 : xn_buf_e = 0;
77 33173 : move16();
78 2156245 : FOR( i = 0; i < FDNS_NPTS; i++ )
79 : {
80 2123072 : xn_buf_e = s_max( xn_buf_e, gainlpc_e[i] );
81 : }
82 33173 : xn_buf_e = shr( add( xn_buf_e, 1 ), 1 ); /* max exponent after sqrt */
83 33173 : xn_one = shr( 0x4000, sub( xn_buf_e, 1 ) ); /* 1.0 scaled to xn_buf_e */
84 :
85 : /* Formant enhancement via square root of the LPC gains */
86 33173 : e = gainlpc_e[0];
87 33173 : move16();
88 33173 : m = Sqrt16( gainlpc[0], &e );
89 33173 : xn_buf[0] = shl( m, sub( e, xn_buf_e ) ); // Q(15-xn_buf_e)
90 33173 : move16();
91 :
92 33173 : e = gainlpc_e[1];
93 33173 : move16();
94 33173 : m = Sqrt16( gainlpc[1], &e );
95 33173 : xn_buf[1] = shl( m, sub( e, xn_buf_e ) ); // Q(15-xn_buf_e)
96 33173 : move16();
97 :
98 33173 : fac0 = s_min( xn_buf[0], xn_buf[1] );
99 33173 : fac_e = xn_buf_e;
100 33173 : move16();
101 33173 : fac0 = Inv16( fac0, &fac_e );
102 :
103 2089899 : FOR( i = 1; i < FDNS_NPTS - 1; i++ )
104 : {
105 2056726 : e = gainlpc_e[i + 1];
106 2056726 : move16();
107 2056726 : m = Sqrt16( gainlpc[i + 1], &e );
108 2056726 : xn_buf[i + 1] = shl( m, sub( e, xn_buf_e ) ); // Q(15-xn_buf_e)
109 2056726 : move16();
110 :
111 2056726 : test();
112 2056726 : IF( ( LE_16( xn_buf[i - 1], xn_buf[i] ) ) && ( LE_16( xn_buf[i + 1], xn_buf[i] ) ) )
113 : {
114 101220 : m = s_max( xn_buf[i - 1], xn_buf[i + 1] );
115 101220 : e = xn_buf_e;
116 101220 : move16();
117 101220 : m = Inv16( m, &e );
118 :
119 101220 : fac1 = m;
120 101220 : move16();
121 101220 : tmp = sub( e, fac_e );
122 :
123 101220 : IF( tmp > 0 )
124 33470 : fac0 = shr( fac0, tmp );
125 101220 : IF( tmp < 0 )
126 8514 : fac1 = shl( fac1, tmp );
127 :
128 101220 : if ( tmp > 0 )
129 : {
130 33470 : fac_e = e;
131 33470 : move16();
132 : }
133 :
134 101220 : d = sub( fac1, fac0 );
135 101220 : n = sub( i, l );
136 101220 : assert( n <= 64 );
137 :
138 101220 : xn_buf[l] = xn_one;
139 101220 : move16();
140 1489727 : FOR( j = 1; j < n; j++ )
141 : {
142 1388507 : fac = add( fac0, mult( d, extract_l( L_mult0( j, inv_int[n] ) ) ) );
143 : BASOP_SATURATE_WARNING_OFF_EVS;
144 : #ifdef ISSUE_1836_replace_overflow_libcom
145 1388507 : xn_buf[l + j] = s_min( xn_one, shl_sat( mult( xn_buf[l + j], fac ), fac_e ) );
146 : #else
147 : xn_buf[l + j] = s_min( xn_one, shl_o( mult( xn_buf[l + j], fac ), fac_e, &Overflow ) );
148 : #endif
149 1388507 : move16();
150 : BASOP_SATURATE_WARNING_ON_EVS;
151 : }
152 :
153 101220 : l = i;
154 101220 : move16();
155 :
156 101220 : fac0 = m;
157 101220 : move16();
158 101220 : fac_e = e;
159 101220 : move16();
160 : }
161 : }
162 : /* i = FDNS_NPTS - 1; Completing changes to gains */
163 33173 : m = s_min( xn_buf[i - 1], xn_buf[i] );
164 33173 : e = xn_buf_e;
165 33173 : move16();
166 33173 : m = Inv16( m, &e );
167 :
168 33173 : fac1 = m;
169 33173 : move16();
170 33173 : tmp = sub( e, fac_e );
171 :
172 33173 : IF( tmp > 0 )
173 15306 : fac0 = shr( fac0, tmp );
174 33173 : IF( tmp < 0 )
175 198 : fac1 = shl( fac1, tmp );
176 :
177 33173 : if ( tmp > 0 )
178 : {
179 15306 : fac_e = e;
180 15306 : move16();
181 : }
182 :
183 33173 : d = sub( fac1, fac0 );
184 33173 : n = sub( i, l );
185 33173 : assert( n <= 64 );
186 :
187 33173 : xn_buf[l] = xn_one;
188 33173 : move16();
189 600172 : FOR( j = 1; j < n; j++ )
190 : {
191 566999 : fac = add( fac0, mult( d, extract_l( L_mult0( j, inv_int[n] ) ) ) );
192 : BASOP_SATURATE_WARNING_OFF_EVS;
193 566999 : xn_buf[l + j] = s_min( xn_one, shl_sat( mult( xn_buf[l + j], fac ), fac_e ) );
194 566999 : move16();
195 : BASOP_SATURATE_WARNING_ON_EVS;
196 : }
197 :
198 33173 : xn_buf[i] = xn_one;
199 33173 : move16();
200 :
201 : /* Application of changed gains onto decoded MDCT lines */
202 2156245 : FOR( i = 0; i < L_frame; i += k )
203 : {
204 10763200 : FOR( l = 0; l < k; l++ )
205 : {
206 8640128 : *spectrum = Mpy_32_16_1( *spectrum, *xn_buf ); // Q(15-xn_buf_e)+Q(31-spectrum_e)+1 -16
207 8640128 : move32();
208 8640128 : spectrum++;
209 : }
210 2123072 : xn_buf++;
211 : }
212 :
213 33173 : tmp = sub( L_frameTCX, L_frame );
214 12748405 : FOR( i = 0; i < tmp; i++ )
215 : {
216 12715232 : spectrum[i] = L_shr( spectrum[i], xn_buf_e ); // Q(31-(specturm_e+xn_buf_e))
217 12715232 : move32();
218 : }
219 33173 : *spectrum_e = add( *spectrum_e, xn_buf_e );
220 33173 : move16();
221 33173 : }
222 :
223 26487 : void tcxFormantEnhancement_with_shift(
224 : Word16 xn_buf[], // Q(15-xn_buf_e_out)
225 : Word16 *xn_buf_e_out,
226 : const Word16 gainlpc[], // Q(15-gainlpc_e)
227 : const Word16 gainlpc_e[],
228 : Word32 spectrum[], // Q(31-spectrum_e)
229 : Word16 *spectrum_e,
230 : const Word16 L_frame,
231 : const Word16 L_frameTCX )
232 : {
233 : Word16 i, j, k, l, n;
234 : Word16 fac, fac0, fac1, fac_e, d, tmp;
235 : Word16 xn_buf_e, xn_one, m, e;
236 : #ifndef ISSUE_1836_replace_overflow_libcom
237 : #ifdef BASOP_NOGLOB_DECLARE_LOCAL
238 : Flag Overflow = 0;
239 : move32();
240 : #endif
241 : #endif
242 :
243 26487 : k = shr( L_frame, 6 ); /* FDNS_NPTS = 64 */
244 26487 : l = 0;
245 26487 : move16();
246 :
247 : /* get exponent */
248 26487 : xn_buf_e = 0;
249 26487 : move16();
250 1721655 : FOR( i = 0; i < FDNS_NPTS; i++ )
251 : {
252 1695168 : xn_buf_e = s_max( xn_buf_e, gainlpc_e[i] );
253 : }
254 26487 : xn_buf_e = shr( add( xn_buf_e, 1 ), 1 ); /* max exponent after sqrt */
255 26487 : xn_one = shr( 0x4000, sub( xn_buf_e, 1 ) ); /* 1.0 scaled to xn_buf_e */
256 :
257 : /* Formant enhancement via square root of the LPC gains */
258 26487 : e = gainlpc_e[0];
259 26487 : move16();
260 26487 : m = Sqrt16( gainlpc[0], &e );
261 26487 : xn_buf[0] = shl( m, sub( e, xn_buf_e ) ); // Q(15-xn_buf_e)
262 26487 : move16();
263 :
264 26487 : e = gainlpc_e[1];
265 26487 : move16();
266 26487 : m = Sqrt16( gainlpc[1], &e );
267 26487 : xn_buf[1] = shl( m, sub( e, xn_buf_e ) ); // Q(15-xn_buf_e)
268 26487 : move16();
269 :
270 26487 : fac0 = s_min( xn_buf[0], xn_buf[1] );
271 26487 : fac_e = xn_buf_e;
272 26487 : move16();
273 26487 : fac0 = Inv16( fac0, &fac_e );
274 :
275 1668681 : FOR( i = 1; i < FDNS_NPTS - 1; i++ )
276 : {
277 1642194 : e = gainlpc_e[i + 1];
278 1642194 : move16();
279 1642194 : m = Sqrt16( gainlpc[i + 1], &e );
280 1642194 : xn_buf[i + 1] = shl( m, sub( e, xn_buf_e ) ); // Q(15-xn_buf_e)
281 1642194 : move16();
282 :
283 1642194 : test();
284 1642194 : IF( ( LE_16( xn_buf[i - 1], xn_buf[i] ) ) && ( LE_16( xn_buf[i + 1], xn_buf[i] ) ) )
285 : {
286 79903 : m = s_max( xn_buf[i - 1], xn_buf[i + 1] );
287 79903 : e = xn_buf_e;
288 79903 : move16();
289 79903 : m = Inv16( m, &e );
290 :
291 79903 : fac1 = m;
292 79903 : move16();
293 79903 : tmp = sub( e, fac_e );
294 :
295 79903 : IF( tmp > 0 )
296 : {
297 26504 : fac0 = shr( fac0, tmp );
298 : }
299 79903 : IF( tmp < 0 )
300 : {
301 6736 : fac1 = shl( fac1, tmp );
302 : }
303 :
304 79903 : IF( tmp > 0 )
305 : {
306 26504 : fac_e = e;
307 26504 : move16();
308 : }
309 :
310 79903 : d = sub( fac1, fac0 );
311 79903 : n = sub( i, l );
312 79903 : assert( n <= 64 );
313 :
314 79903 : xn_buf[l] = xn_one;
315 79903 : move16();
316 1185690 : FOR( j = 1; j < n; j++ )
317 : {
318 1105787 : fac = add( fac0, mult( d, extract_l( L_mult0( j, inv_int[n] ) ) ) );
319 : BASOP_SATURATE_WARNING_OFF_EVS;
320 : #ifdef ISSUE_1836_replace_overflow_libcom
321 1105787 : xn_buf[l + j] = s_min( xn_one, shl_sat( mult( xn_buf[l + j], fac ), fac_e ) );
322 : #else
323 : xn_buf[l + j] = s_min( xn_one, shl_o( mult( xn_buf[l + j], fac ), fac_e, &Overflow ) );
324 : #endif
325 1105787 : move16();
326 : BASOP_SATURATE_WARNING_ON_EVS;
327 : }
328 :
329 79903 : l = i;
330 79903 : move16();
331 :
332 79903 : fac0 = m;
333 79903 : move16();
334 79903 : fac_e = e;
335 79903 : move16();
336 : }
337 : }
338 : /* i = FDNS_NPTS - 1; Completing changes to gains */
339 26487 : m = s_min( xn_buf[i - 1], xn_buf[i] );
340 26487 : e = xn_buf_e;
341 26487 : move16();
342 26487 : m = Inv16( m, &e );
343 :
344 26487 : fac1 = m;
345 26487 : move16();
346 26487 : tmp = sub( e, fac_e );
347 :
348 26487 : IF( tmp > 0 )
349 12141 : fac0 = shr( fac0, tmp );
350 26487 : IF( tmp < 0 )
351 159 : fac1 = shl( fac1, tmp );
352 :
353 26487 : if ( tmp > 0 )
354 : {
355 12141 : fac_e = e;
356 12141 : move16();
357 : }
358 :
359 26487 : d = sub( fac1, fac0 );
360 26487 : n = sub( i, l );
361 26487 : assert( n <= 64 );
362 :
363 26487 : xn_buf[l] = xn_one;
364 26487 : move16();
365 482991 : FOR( j = 1; j < n; j++ )
366 : {
367 456504 : fac = add( fac0, mult( d, extract_l( L_mult0( j, inv_int[n] ) ) ) );
368 : BASOP_SATURATE_WARNING_OFF_EVS;
369 : #ifdef ISSUE_1836_replace_overflow_libcom
370 456504 : xn_buf[l + j] = s_min( xn_one, shl_sat( mult( xn_buf[l + j], fac ), fac_e ) );
371 : #else
372 : xn_buf[l + j] = s_min( xn_one, shl_o( mult( xn_buf[l + j], fac ), fac_e, &Overflow ) );
373 : #endif
374 456504 : move16();
375 : BASOP_SATURATE_WARNING_ON_EVS;
376 : }
377 :
378 26487 : xn_buf[i] = xn_one;
379 26487 : move16();
380 :
381 : /* Application of changed gains onto decoded MDCT lines */
382 1721655 : FOR( i = 0; i < L_frame; i += k )
383 : {
384 8588608 : FOR( l = 0; l < k; l++ )
385 : {
386 6893440 : *spectrum = Mpy_32_16_1( *spectrum, *xn_buf ); // Q(15-xn_buf_e)+Q(31-spectrum_e)+1 -16
387 6893440 : move32();
388 6893440 : spectrum++;
389 : }
390 1695168 : xn_buf++;
391 : }
392 :
393 26487 : tmp = sub( L_frameTCX, L_frame );
394 17348807 : FOR( i = 0; i < tmp; i++ )
395 : {
396 17322320 : spectrum[i] = L_shr( spectrum[i], xn_buf_e ); // Q(31-(specturm_e+xn_buf_e))
397 17322320 : move32();
398 : }
399 26487 : *spectrum_e = add( *spectrum_e, xn_buf_e );
400 26487 : move16();
401 :
402 26487 : *xn_buf_e_out = xn_buf_e;
403 26487 : move16();
404 26487 : }
405 :
406 4118 : void tcxInvertWindowGrouping(
407 : TCX_CONFIG_HANDLE hTcxCfg, /* i : configuration of TCX */
408 : Word32 xn_buf[], // Qx
409 : Word32 spectrum[], // Qx
410 : const Word16 L_frame,
411 : const Word8 fUseTns,
412 : const Word16 last_core,
413 : const Word16 index,
414 : const Word16 frame_cnt,
415 : const Word16 bfi )
416 : {
417 : Word16 i, L_win, L_spec;
418 : Word32 *p;
419 :
420 :
421 4118 : L_win = shr( L_frame, 1 );
422 4118 : L_spec = hTcxCfg->tnsConfig[0][0].iFilterBorders[0];
423 4118 : move16();
424 :
425 4118 : test();
426 4118 : test();
427 4118 : if ( ( frame_cnt != 0 ) && ( bfi == 0 ) && ( last_core != ACELP_CORE ) ) /* fix sub-window overlap */
428 : {
429 2059 : hTcxCfg->tcx_last_overlap_mode = hTcxCfg->tcx_curr_overlap_mode;
430 2059 : move16();
431 : }
432 4118 : test();
433 4118 : test();
434 4118 : test();
435 4118 : test();
436 4118 : test();
437 4118 : test();
438 4118 : test();
439 4118 : IF( ( ( bfi == 0 ) && ( ( hTcxCfg->tcx_last_overlap_mode != FULL_OVERLAP ) ||
440 : ( ( hTcxCfg->tcx_curr_overlap_mode == FULL_OVERLAP ) && ( frame_cnt == 0 ) && ( index == 0 ) ) ) ) ||
441 : ( ( bfi != 0 ) && ( ( hTcxCfg->tcx_last_overlap_mode != FULL_OVERLAP ) &&
442 : !( hTcxCfg->tcx_curr_overlap_mode == FULL_OVERLAP ) ) ) )
443 : {
444 : /* ungroup sub-windows: deinterleave MDCT bins into separate windows */
445 2197 : p = xn_buf;
446 260797 : FOR( i = 1; i < L_win; i += 2 )
447 : {
448 258600 : *p++ = spectrum[i];
449 258600 : move32();
450 : }
451 :
452 2197 : p = spectrum;
453 519397 : FOR( i = 0; i < L_frame; i += 2 )
454 : {
455 517200 : *p++ = spectrum[i];
456 517200 : move32();
457 : }
458 :
459 2197 : p = spectrum + sub( L_frame, 1 );
460 260797 : FOR( i = L_frame - 1; i > L_win; i -= 2 )
461 : {
462 258600 : *p-- = spectrum[i];
463 258600 : move32();
464 : }
465 2197 : Copy32( xn_buf, spectrum + L_win, shr( L_win, 1 ) );
466 :
467 2197 : test();
468 2197 : test();
469 2197 : IF( ( hTcxCfg->fIsTNSAllowed != 0 ) && ( bfi == 0 ) && ( fUseTns != 0 ) )
470 : {
471 : /* rearrange LF sub-window lines prior to TNS synthesis filtering */
472 1717 : IF( LT_16( L_spec, L_frame ) )
473 : {
474 1619 : Copy32( spectrum + 8, spectrum + 16, sub( shr( L_spec, 1 ), 8 ) );
475 1619 : Copy32( spectrum + shr( L_frame, 1 ), spectrum + 8, 8 );
476 1619 : Copy32( spectrum + add( shr( L_frame, 1 ), 8 ), spectrum + add( shr( L_spec, 1 ), 8 ), sub( shr( L_spec, 1 ), 8 ) );
477 : }
478 : ELSE
479 : {
480 98 : Copy32( spectrum + L_win, xn_buf, 8 );
481 98 : Copy32( spectrum + 8, spectrum + 16, sub( L_win, 8 ) );
482 98 : Copy32( xn_buf, spectrum + 8, 8 );
483 : }
484 : }
485 : }
486 4118 : }
487 :
488 : /*-------------------------------------------------------------------*
489 : * tcx5SpectrumInterleaving()
490 : *
491 : *
492 : *-------------------------------------------------------------------*/
493 :
494 :
495 78096 : void tcx5SpectrumInterleaving_fx(
496 : const Word16 tcx5Size,
497 : Word32 *spectrum // Qx
498 : )
499 : {
500 : Word16 i;
501 : Word32 interleaveBuf[N_TCX10_MAX];
502 :
503 78096 : set32_fx( interleaveBuf, 0, N_TCX10_MAX );
504 :
505 : /* group sub-windows: interleave bins according to their frequencies */
506 16511936 : FOR( i = 0; i < tcx5Size; i++ )
507 : {
508 16433840 : interleaveBuf[2 * i] = spectrum[i];
509 16433840 : interleaveBuf[2 * i + 1] = spectrum[tcx5Size + i];
510 16433840 : move32();
511 16433840 : move32();
512 : }
513 :
514 78096 : Copy32( interleaveBuf, spectrum, shl( tcx5Size, 1 ) );
515 :
516 78096 : return;
517 : }
518 :
519 : /*-------------------------------------------------------------------*
520 : * tcx5SpectrumDeinterleaving_fx()
521 : *
522 : *
523 : *-------------------------------------------------------------------*/
524 :
525 64193 : void tcx5SpectrumDeinterleaving_fx(
526 : const Word16 tcx5Size,
527 : Word32 *spectrum // Qx
528 : )
529 : {
530 : Word16 i;
531 : Word32 interleaveBuf[N_TCX10_MAX];
532 :
533 64193 : set32_fx( interleaveBuf, 0, N_TCX10_MAX );
534 :
535 : /* ungroup sub-windows: interleave bins according to their frequencies */
536 13685553 : FOR( i = 0; i < tcx5Size; i++ )
537 : {
538 13621360 : interleaveBuf[i] = spectrum[2 * i];
539 13621360 : interleaveBuf[tcx5Size + i] = spectrum[2 * i + 1];
540 13621360 : move32();
541 13621360 : move32();
542 : }
543 :
544 64193 : Copy32( interleaveBuf, spectrum, shl( tcx5Size, 1 ) );
545 :
546 64193 : return;
547 : }
548 :
549 : /*-------------------------------------------------------------------*
550 : * tcx5TnsGrouping()
551 : *
552 : *
553 : *-------------------------------------------------------------------*/
554 :
555 28109 : void tcx5TnsGrouping_fx(
556 : const Word16 L_frame, /* i : frame length (TCX5) */
557 : const Word16 L_spec, /* i : coded spec length (TCX5, derived from filter borders*/
558 : Word32 *spectrum /*Qx*/
559 : )
560 : {
561 : /* rearrange LF sub-window lines prior to TNS synthesis filtering */
562 28109 : IF( LT_16( L_spec, L_frame ) )
563 : {
564 16568 : Copy32( spectrum + 8, spectrum + 16, sub( L_spec, 8 ) );
565 16568 : Copy32( spectrum + L_frame, spectrum + 8, 8 );
566 16568 : Copy32( spectrum + add( L_frame, 8 ), spectrum + add( L_spec, 8 ), sub( L_spec, 8 ) );
567 : }
568 : ELSE
569 : {
570 : Word32 buff[8]; /* Buffer for the rearrangement of LF TCX5 */
571 11541 : Copy32( spectrum + L_spec, buff, 8 );
572 11541 : Copy32( spectrum + 8, spectrum + 16, sub( L_spec, 8 ) );
573 11541 : Copy32( buff, spectrum + 8, 8 );
574 : }
575 :
576 28109 : return;
577 : }
578 :
579 : /*-------------------------------------------------------------------*
580 : * tcx5TnsUngrouping()
581 : *
582 : *
583 : *-------------------------------------------------------------------*/
584 :
585 28109 : void tcx5TnsUngrouping_fx(
586 : const Word16 L_frame, /* i : frame length (TCX5) */
587 : const Word16 L_spec, /* i : coded spec length (TCX5, derived from filter borders*/
588 : Word32 *spectrum, /*Qx*/
589 : const Word16 enc_dec /* i : 0: encoder, else decoder */
590 : )
591 : {
592 : /* undo rearrangement of LF sub-window lines prior to TNS analysis */
593 28109 : IF( LT_16( L_spec, L_frame ) )
594 : {
595 16568 : Copy32( spectrum + L_spec + 8, spectrum + add( L_frame, 8 ), sub( L_spec, 8 ) );
596 16568 : Copy32( spectrum + 8, spectrum + L_frame, 8 );
597 16568 : Copy32( spectrum + 16, spectrum + 8, sub( L_spec, 8 ) );
598 16568 : set32_fx( spectrum + L_spec, 0, sub( L_frame, L_spec ) );
599 16568 : set32_fx( spectrum + add( L_frame, L_spec ), 0, sub( L_frame, L_spec ) );
600 : }
601 : ELSE
602 : {
603 : Word32 buff[8]; /* Buffer for the rearrangement of LF TCX5 */
604 :
605 11541 : Copy32( spectrum + 8, buff, 8 );
606 :
607 11541 : IF( enc_dec == ENC )
608 : {
609 7062 : Copy32( spectrum + 16, spectrum + 8, sub( L_frame, 8 ) );
610 7062 : Copy32( buff, spectrum + L_frame, 8 );
611 : }
612 : ELSE
613 : {
614 4479 : Copy32( spectrum + 16, spectrum + 8, sub( L_spec, 8 ) );
615 4479 : Copy32( buff, spectrum + L_spec, 8 );
616 : }
617 : }
618 :
619 28109 : return;
620 : }
|