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 2395346 : 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 2395346 : IF( mode != 0 )
30 : {
31 2302530 : firstLine = idiv1616U( L_frame, 6 );
32 2302530 : *noiseTiltFactor = 18432 /*0.5625f Q15*/;
33 2302530 : move16();
34 : }
35 : ELSE
36 : {
37 92816 : firstLine = shr( L_frame, 3 );
38 :
39 92816 : Copy_Scale_sig( A, As, add( lpcorder, 1 ), sub( norm_s( A[0] ), 2 ) ); // Q(12)
40 92816 : tmp = get_gain( As + 1, As, lpcorder );
41 : BASOP_SATURATE_WARNING_OFF_EVS;
42 92816 : *noiseTiltFactor = add_sat( round_fx_sat( L_shl_sat( tmp, 15 ) ), 3072 /*0.09375f Q15*/ );
43 92816 : move16();
44 : BASOP_SATURATE_WARNING_ON_EVS;
45 : }
46 :
47 :
48 2395346 : return firstLine;
49 : }
50 :
51 :
52 33246 : 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 : #ifdef BASOP_NOGLOB_DECLARE_LOCAL
65 33246 : Flag Overflow = 0;
66 33246 : move32();
67 : #endif
68 :
69 33246 : k = shr( L_frame, 6 ); /* FDNS_NPTS = 64 */
70 33246 : l = 0;
71 33246 : move16();
72 :
73 : /* get exponent */
74 33246 : xn_buf_e = 0;
75 33246 : move16();
76 2160990 : FOR( i = 0; i < FDNS_NPTS; i++ )
77 : {
78 2127744 : xn_buf_e = s_max( xn_buf_e, gainlpc_e[i] );
79 : }
80 33246 : xn_buf_e = shr( add( xn_buf_e, 1 ), 1 ); /* max exponent after sqrt */
81 33246 : xn_one = shr( 0x4000, sub( xn_buf_e, 1 ) ); /* 1.0 scaled to xn_buf_e */
82 :
83 : /* Formant enhancement via square root of the LPC gains */
84 33246 : e = gainlpc_e[0];
85 33246 : move16();
86 33246 : m = Sqrt16( gainlpc[0], &e );
87 33246 : xn_buf[0] = shl( m, sub( e, xn_buf_e ) ); // Q(15-xn_buf_e)
88 33246 : move16();
89 :
90 33246 : e = gainlpc_e[1];
91 33246 : move16();
92 33246 : m = Sqrt16( gainlpc[1], &e );
93 33246 : xn_buf[1] = shl( m, sub( e, xn_buf_e ) ); // Q(15-xn_buf_e)
94 33246 : move16();
95 :
96 33246 : fac0 = s_min( xn_buf[0], xn_buf[1] );
97 33246 : fac_e = xn_buf_e;
98 33246 : move16();
99 33246 : fac0 = Inv16( fac0, &fac_e );
100 :
101 2094498 : FOR( i = 1; i < FDNS_NPTS - 1; i++ )
102 : {
103 2061252 : e = gainlpc_e[i + 1];
104 2061252 : move16();
105 2061252 : m = Sqrt16( gainlpc[i + 1], &e );
106 2061252 : xn_buf[i + 1] = shl( m, sub( e, xn_buf_e ) ); // Q(15-xn_buf_e)
107 2061252 : move16();
108 :
109 2061252 : test();
110 2061252 : IF( ( LE_16( xn_buf[i - 1], xn_buf[i] ) ) && ( LE_16( xn_buf[i + 1], xn_buf[i] ) ) )
111 : {
112 101589 : m = s_max( xn_buf[i - 1], xn_buf[i + 1] );
113 101589 : e = xn_buf_e;
114 101589 : move16();
115 101589 : m = Inv16( m, &e );
116 :
117 101589 : fac1 = m;
118 101589 : move16();
119 101589 : tmp = sub( e, fac_e );
120 :
121 101589 : IF( tmp > 0 )
122 33616 : fac0 = shr( fac0, tmp );
123 101589 : IF( tmp < 0 )
124 8534 : fac1 = shl( fac1, tmp );
125 :
126 101589 : if ( tmp > 0 )
127 : {
128 33616 : fac_e = e;
129 33616 : move16();
130 : }
131 :
132 101589 : d = sub( fac1, fac0 );
133 101589 : n = sub( i, l );
134 101589 : assert( n <= 64 );
135 :
136 101589 : xn_buf[l] = xn_one;
137 101589 : move16();
138 1495183 : FOR( j = 1; j < n; j++ )
139 : {
140 1393594 : fac = add( fac0, mult( d, extract_l( L_mult0( j, inv_int[n] ) ) ) );
141 : BASOP_SATURATE_WARNING_OFF_EVS;
142 1393594 : xn_buf[l + j] = s_min( xn_one, shl_o( mult( xn_buf[l + j], fac ), fac_e, &Overflow ) );
143 1393594 : move16();
144 : BASOP_SATURATE_WARNING_ON_EVS;
145 : }
146 :
147 101589 : l = i;
148 101589 : move16();
149 :
150 101589 : fac0 = m;
151 101589 : move16();
152 101589 : fac_e = e;
153 101589 : move16();
154 : }
155 : }
156 : /* i = FDNS_NPTS - 1; Completing changes to gains */
157 33246 : m = s_min( xn_buf[i - 1], xn_buf[i] );
158 33246 : e = xn_buf_e;
159 33246 : move16();
160 33246 : m = Inv16( m, &e );
161 :
162 33246 : fac1 = m;
163 33246 : move16();
164 33246 : tmp = sub( e, fac_e );
165 :
166 33246 : IF( tmp > 0 )
167 15267 : fac0 = shr( fac0, tmp );
168 33246 : IF( tmp < 0 )
169 197 : fac1 = shl( fac1, tmp );
170 :
171 33246 : if ( tmp > 0 )
172 : {
173 15267 : fac_e = e;
174 15267 : move16();
175 : }
176 :
177 33246 : d = sub( fac1, fac0 );
178 33246 : n = sub( i, l );
179 33246 : assert( n <= 64 );
180 :
181 33246 : xn_buf[l] = xn_one;
182 33246 : move16();
183 599315 : FOR( j = 1; j < n; j++ )
184 : {
185 566069 : fac = add( fac0, mult( d, extract_l( L_mult0( j, inv_int[n] ) ) ) );
186 : BASOP_SATURATE_WARNING_OFF_EVS;
187 566069 : xn_buf[l + j] = s_min( xn_one, shl_sat( mult( xn_buf[l + j], fac ), fac_e ) );
188 566069 : move16();
189 : BASOP_SATURATE_WARNING_ON_EVS;
190 : }
191 :
192 33246 : xn_buf[i] = xn_one;
193 33246 : move16();
194 :
195 : /* Application of changed gains onto decoded MDCT lines */
196 2160990 : FOR( i = 0; i < L_frame; i += k )
197 : {
198 10786048 : FOR( l = 0; l < k; l++ )
199 : {
200 8658304 : *spectrum = Mpy_32_16_1( *spectrum, *xn_buf ); // Q(15-xn_buf_e)+Q(31-spectrum_e)+1 -16
201 8658304 : move32();
202 8658304 : spectrum++;
203 : }
204 2127744 : xn_buf++;
205 : }
206 :
207 33246 : tmp = sub( L_frameTCX, L_frame );
208 12781102 : FOR( i = 0; i < tmp; i++ )
209 : {
210 12747856 : spectrum[i] = L_shr( spectrum[i], xn_buf_e ); // Q(31-(specturm_e+xn_buf_e))
211 12747856 : move32();
212 : }
213 33246 : *spectrum_e = add( *spectrum_e, xn_buf_e );
214 33246 : move16();
215 33246 : }
216 :
217 26386 : void tcxFormantEnhancement_with_shift(
218 : Word16 xn_buf[], // Q(15-xn_buf_e_out)
219 : Word16 *xn_buf_e_out,
220 : const Word16 gainlpc[], // Q(15-gainlpc_e)
221 : const Word16 gainlpc_e[],
222 : Word32 spectrum[], // Q(31-spectrum_e)
223 : Word16 *spectrum_e,
224 : const Word16 L_frame,
225 : const Word16 L_frameTCX )
226 : {
227 : Word16 i, j, k, l, n;
228 : Word16 fac, fac0, fac1, fac_e, d, tmp;
229 : Word16 xn_buf_e, xn_one, m, e;
230 : #ifdef BASOP_NOGLOB_DECLARE_LOCAL
231 26386 : Flag Overflow = 0;
232 26386 : move32();
233 : #endif
234 :
235 26386 : k = shr( L_frame, 6 ); /* FDNS_NPTS = 64 */
236 26386 : l = 0;
237 26386 : move16();
238 :
239 : /* get exponent */
240 26386 : xn_buf_e = 0;
241 26386 : move16();
242 1715090 : FOR( i = 0; i < FDNS_NPTS; i++ )
243 : {
244 1688704 : xn_buf_e = s_max( xn_buf_e, gainlpc_e[i] );
245 : }
246 26386 : xn_buf_e = shr( add( xn_buf_e, 1 ), 1 ); /* max exponent after sqrt */
247 26386 : xn_one = shr( 0x4000, sub( xn_buf_e, 1 ) ); /* 1.0 scaled to xn_buf_e */
248 :
249 : /* Formant enhancement via square root of the LPC gains */
250 26386 : e = gainlpc_e[0];
251 26386 : move16();
252 26386 : m = Sqrt16( gainlpc[0], &e );
253 26386 : xn_buf[0] = shl( m, sub( e, xn_buf_e ) ); // Q(15-xn_buf_e)
254 26386 : move16();
255 :
256 26386 : e = gainlpc_e[1];
257 26386 : move16();
258 26386 : m = Sqrt16( gainlpc[1], &e );
259 26386 : xn_buf[1] = shl( m, sub( e, xn_buf_e ) ); // Q(15-xn_buf_e)
260 26386 : move16();
261 :
262 26386 : fac0 = s_min( xn_buf[0], xn_buf[1] );
263 26386 : fac_e = xn_buf_e;
264 26386 : move16();
265 26386 : fac0 = Inv16( fac0, &fac_e );
266 :
267 1662318 : FOR( i = 1; i < FDNS_NPTS - 1; i++ )
268 : {
269 1635932 : e = gainlpc_e[i + 1];
270 1635932 : move16();
271 1635932 : m = Sqrt16( gainlpc[i + 1], &e );
272 1635932 : xn_buf[i + 1] = shl( m, sub( e, xn_buf_e ) ); // Q(15-xn_buf_e)
273 1635932 : move16();
274 :
275 1635932 : test();
276 1635932 : IF( ( LE_16( xn_buf[i - 1], xn_buf[i] ) ) && ( LE_16( xn_buf[i + 1], xn_buf[i] ) ) )
277 : {
278 79543 : m = s_max( xn_buf[i - 1], xn_buf[i + 1] );
279 79543 : e = xn_buf_e;
280 79543 : move16();
281 79543 : m = Inv16( m, &e );
282 :
283 79543 : fac1 = m;
284 79543 : move16();
285 79543 : tmp = sub( e, fac_e );
286 :
287 79543 : IF( tmp > 0 )
288 : {
289 26342 : fac0 = shr( fac0, tmp );
290 : }
291 79543 : IF( tmp < 0 )
292 : {
293 6762 : fac1 = shl( fac1, tmp );
294 : }
295 :
296 79543 : IF( tmp > 0 )
297 : {
298 26342 : fac_e = e;
299 26342 : move16();
300 : }
301 :
302 79543 : d = sub( fac1, fac0 );
303 79543 : n = sub( i, l );
304 79543 : assert( n <= 64 );
305 :
306 79543 : xn_buf[l] = xn_one;
307 79543 : move16();
308 1176444 : FOR( j = 1; j < n; j++ )
309 : {
310 1096901 : fac = add( fac0, mult( d, extract_l( L_mult0( j, inv_int[n] ) ) ) );
311 : BASOP_SATURATE_WARNING_OFF_EVS;
312 1096901 : xn_buf[l + j] = s_min( xn_one, shl_o( mult( xn_buf[l + j], fac ), fac_e, &Overflow ) );
313 1096901 : move16();
314 : BASOP_SATURATE_WARNING_ON_EVS;
315 : }
316 :
317 79543 : l = i;
318 79543 : move16();
319 :
320 79543 : fac0 = m;
321 79543 : move16();
322 79543 : fac_e = e;
323 79543 : move16();
324 : }
325 : }
326 : /* i = FDNS_NPTS - 1; Completing changes to gains */
327 26386 : m = s_min( xn_buf[i - 1], xn_buf[i] );
328 26386 : e = xn_buf_e;
329 26386 : move16();
330 26386 : m = Inv16( m, &e );
331 :
332 26386 : fac1 = m;
333 26386 : move16();
334 26386 : tmp = sub( e, fac_e );
335 :
336 26386 : IF( tmp > 0 )
337 12188 : fac0 = shr( fac0, tmp );
338 26386 : IF( tmp < 0 )
339 155 : fac1 = shl( fac1, tmp );
340 :
341 26386 : if ( tmp > 0 )
342 : {
343 12188 : fac_e = e;
344 12188 : move16();
345 : }
346 :
347 26386 : d = sub( fac1, fac0 );
348 26386 : n = sub( i, l );
349 26386 : assert( n <= 64 );
350 :
351 26386 : xn_buf[l] = xn_one;
352 26386 : move16();
353 485874 : FOR( j = 1; j < n; j++ )
354 : {
355 459488 : fac = add( fac0, mult( d, extract_l( L_mult0( j, inv_int[n] ) ) ) );
356 : BASOP_SATURATE_WARNING_OFF_EVS;
357 459488 : xn_buf[l + j] = s_min( xn_one, shl_o( mult( xn_buf[l + j], fac ), fac_e, &Overflow ) );
358 459488 : move16();
359 : BASOP_SATURATE_WARNING_ON_EVS;
360 : }
361 :
362 26386 : xn_buf[i] = xn_one;
363 26386 : move16();
364 :
365 : /* Application of changed gains onto decoded MDCT lines */
366 1715090 : FOR( i = 0; i < L_frame; i += k )
367 : {
368 8554880 : FOR( l = 0; l < k; l++ )
369 : {
370 6866176 : *spectrum = Mpy_32_16_1( *spectrum, *xn_buf ); // Q(15-xn_buf_e)+Q(31-spectrum_e)+1 -16
371 6866176 : move32();
372 6866176 : spectrum++;
373 : }
374 1688704 : xn_buf++;
375 : }
376 :
377 26386 : tmp = sub( L_frameTCX, L_frame );
378 17297570 : FOR( i = 0; i < tmp; i++ )
379 : {
380 17271184 : spectrum[i] = L_shr( spectrum[i], xn_buf_e ); // Q(31-(specturm_e+xn_buf_e))
381 17271184 : move32();
382 : }
383 26386 : *spectrum_e = add( *spectrum_e, xn_buf_e );
384 26386 : move16();
385 :
386 26386 : *xn_buf_e_out = xn_buf_e;
387 26386 : move16();
388 26386 : }
389 :
390 4118 : void tcxInvertWindowGrouping(
391 : TCX_CONFIG_HANDLE hTcxCfg, /* i : configuration of TCX */
392 : Word32 xn_buf[], // Qx
393 : Word32 spectrum[], // Qx
394 : const Word16 L_frame,
395 : const Word8 fUseTns,
396 : const Word16 last_core,
397 : const Word16 index,
398 : const Word16 frame_cnt,
399 : const Word16 bfi )
400 : {
401 : Word16 i, L_win, L_spec;
402 : Word32 *p;
403 :
404 :
405 4118 : L_win = shr( L_frame, 1 );
406 4118 : L_spec = hTcxCfg->tnsConfig[0][0].iFilterBorders[0];
407 4118 : move16();
408 :
409 4118 : test();
410 4118 : test();
411 4118 : if ( ( frame_cnt != 0 ) && ( bfi == 0 ) && ( last_core != ACELP_CORE ) ) /* fix sub-window overlap */
412 : {
413 2059 : hTcxCfg->tcx_last_overlap_mode = hTcxCfg->tcx_curr_overlap_mode;
414 2059 : move16();
415 : }
416 4118 : test();
417 4118 : test();
418 4118 : test();
419 4118 : test();
420 4118 : test();
421 4118 : test();
422 4118 : test();
423 4118 : IF( ( ( bfi == 0 ) && ( ( hTcxCfg->tcx_last_overlap_mode != FULL_OVERLAP ) ||
424 : ( ( hTcxCfg->tcx_curr_overlap_mode == FULL_OVERLAP ) && ( frame_cnt == 0 ) && ( index == 0 ) ) ) ) ||
425 : ( ( bfi != 0 ) && ( ( hTcxCfg->tcx_last_overlap_mode != FULL_OVERLAP ) &&
426 : !( hTcxCfg->tcx_curr_overlap_mode == FULL_OVERLAP ) ) ) )
427 : {
428 : /* ungroup sub-windows: deinterleave MDCT bins into separate windows */
429 2197 : p = xn_buf;
430 260797 : FOR( i = 1; i < L_win; i += 2 )
431 : {
432 258600 : *p++ = spectrum[i];
433 258600 : move32();
434 : }
435 :
436 2197 : p = spectrum;
437 519397 : FOR( i = 0; i < L_frame; i += 2 )
438 : {
439 517200 : *p++ = spectrum[i];
440 517200 : move32();
441 : }
442 :
443 2197 : p = spectrum + sub( L_frame, 1 );
444 260797 : FOR( i = L_frame - 1; i > L_win; i -= 2 )
445 : {
446 258600 : *p-- = spectrum[i];
447 258600 : move32();
448 : }
449 2197 : Copy32( xn_buf, spectrum + L_win, shr( L_win, 1 ) );
450 :
451 2197 : test();
452 2197 : test();
453 2197 : IF( ( hTcxCfg->fIsTNSAllowed != 0 ) && ( bfi == 0 ) && ( fUseTns != 0 ) )
454 : {
455 : /* rearrange LF sub-window lines prior to TNS synthesis filtering */
456 1717 : IF( LT_16( L_spec, L_frame ) )
457 : {
458 1619 : Copy32( spectrum + 8, spectrum + 16, sub( shr( L_spec, 1 ), 8 ) );
459 1619 : Copy32( spectrum + shr( L_frame, 1 ), spectrum + 8, 8 );
460 1619 : Copy32( spectrum + add( shr( L_frame, 1 ), 8 ), spectrum + add( shr( L_spec, 1 ), 8 ), sub( shr( L_spec, 1 ), 8 ) );
461 : }
462 : ELSE
463 : {
464 98 : Copy32( spectrum + L_win, xn_buf, 8 );
465 98 : Copy32( spectrum + 8, spectrum + 16, sub( L_win, 8 ) );
466 98 : Copy32( xn_buf, spectrum + 8, 8 );
467 : }
468 : }
469 : }
470 4118 : }
471 :
472 : #ifdef IVAS_CODE_TCX_COM
473 :
474 : /*-------------------------------------------------------------------*
475 : * tcx5SpectrumInterleaving()
476 : *
477 : *
478 : *-------------------------------------------------------------------*/
479 :
480 : void tcx5SpectrumInterleaving(
481 : const int16_t tcx5Size,
482 : float *spectrum )
483 : {
484 : int16_t i;
485 : float interleaveBuf[N_TCX10_MAX];
486 :
487 : set_f( interleaveBuf, 0.0f, N_TCX10_MAX );
488 :
489 : /* group sub-windows: interleave bins according to their frequencies */
490 : for ( i = 0; i < tcx5Size; i++ )
491 : {
492 : interleaveBuf[2 * i] = spectrum[i];
493 : interleaveBuf[2 * i + 1] = spectrum[tcx5Size + i];
494 : }
495 :
496 : mvr2r( interleaveBuf, spectrum, 2 * tcx5Size );
497 :
498 : return;
499 : }
500 :
501 :
502 : /*-------------------------------------------------------------------*
503 : * tcx5SpectrumDeinterleaving()
504 : *
505 : *
506 : *-------------------------------------------------------------------*/
507 :
508 : void tcx5SpectrumDeinterleaving(
509 : const int16_t tcx5Size,
510 : float *spectrum )
511 : {
512 : int16_t i;
513 : float interleaveBuf[N_TCX10_MAX];
514 :
515 : set_f( interleaveBuf, 0.0f, N_TCX10_MAX );
516 :
517 : /* ungroup sub-windows: interleave bins according to their frequencies */
518 : for ( i = 0; i < tcx5Size; i++ )
519 : {
520 : interleaveBuf[i] = spectrum[2 * i];
521 : interleaveBuf[tcx5Size + i] = spectrum[2 * i + 1];
522 : }
523 :
524 : mvr2r( interleaveBuf, spectrum, 2 * tcx5Size );
525 :
526 : return;
527 : }
528 :
529 :
530 : /*-------------------------------------------------------------------*
531 : * tcx5TnsGrouping()
532 : *
533 : *
534 : *-------------------------------------------------------------------*/
535 :
536 : void tcx5TnsGrouping(
537 : const int16_t L_frame, /* i : frame length (TCX5) */
538 : const int16_t L_spec, /* i : coded spec length (TCX5, derived from filter borders*/
539 : float *spectrum )
540 : {
541 : /* rearrange LF sub-window lines prior to TNS synthesis filtering */
542 : if ( L_spec < L_frame )
543 : {
544 : mvr2r( spectrum + 8, spectrum + 16, L_spec - 8 );
545 : mvr2r( spectrum + L_frame, spectrum + 8, 8 );
546 : mvr2r( spectrum + L_frame + 8, spectrum + L_spec + 8, L_spec - 8 );
547 : }
548 : else
549 : {
550 : float buff[8]; /* Buffer for the rearrangement of LF TCX5 */
551 : mvr2r( spectrum + L_spec, buff, 8 );
552 : mvr2r( spectrum + 8, spectrum + 16, L_spec - 8 );
553 : mvr2r( buff, spectrum + 8, 8 );
554 : }
555 :
556 : return;
557 : }
558 :
559 :
560 : /*-------------------------------------------------------------------*
561 : * tcx5TnsUngrouping()
562 : *
563 : *
564 : *-------------------------------------------------------------------*/
565 :
566 : void tcx5TnsUngrouping(
567 : const int16_t L_frame, /* i : frame length (TCX5) */
568 : const int16_t L_spec, /* i : coded spec length (TCX5, derived from filter borders*/
569 : float *spectrum,
570 : const int16_t enc_dec /* i : 0: encoder, else decoder */
571 : )
572 : {
573 : /* undo rearrangement of LF sub-window lines prior to TNS analysis */
574 : if ( L_spec < L_frame )
575 : {
576 : mvr2r( spectrum + L_spec + 8, spectrum + L_frame + 8, L_spec - 8 );
577 : mvr2r( spectrum + 8, spectrum + L_frame, 8 );
578 : mvr2r( spectrum + 16, spectrum + 8, L_spec - 8 );
579 : set_zero( spectrum + L_spec, L_frame - L_spec );
580 : set_zero( spectrum + L_frame + L_spec, L_frame - L_spec );
581 : }
582 : else
583 : {
584 : float buff[8]; /* Buffer for the rearrangement of LF TCX5 */
585 :
586 : mvr2r( spectrum + 8, buff, 8 );
587 :
588 : if ( enc_dec == ENC )
589 : {
590 : mvr2r( spectrum + 16, spectrum + 8, L_frame - 8 );
591 : mvr2r( buff, spectrum + L_frame, 8 );
592 : }
593 : else
594 : {
595 : mvr2r( spectrum + 16, spectrum + 8, L_spec - 8 );
596 : mvr2r( buff, spectrum + L_spec, 8 );
597 : }
598 : }
599 :
600 : return;
601 : }
602 :
603 : #endif
604 :
605 :
606 : /*-------------------------------------------------------------------*
607 : * tcx5SpectrumInterleaving()
608 : *
609 : *
610 : *-------------------------------------------------------------------*/
611 :
612 :
613 71947 : void tcx5SpectrumInterleaving_fx(
614 : const Word16 tcx5Size,
615 : Word32 *spectrum // Qx
616 : )
617 : {
618 : Word16 i;
619 : Word32 interleaveBuf[N_TCX10_MAX];
620 :
621 71947 : set32_fx( interleaveBuf, 0, N_TCX10_MAX );
622 :
623 : /* group sub-windows: interleave bins according to their frequencies */
624 15150107 : FOR( i = 0; i < tcx5Size; i++ )
625 : {
626 15078160 : interleaveBuf[2 * i] = spectrum[i];
627 15078160 : interleaveBuf[2 * i + 1] = spectrum[tcx5Size + i];
628 15078160 : move32();
629 15078160 : move32();
630 : }
631 :
632 71947 : Copy32( interleaveBuf, spectrum, shl( tcx5Size, 1 ) );
633 :
634 71947 : return;
635 : }
636 :
637 : /*-------------------------------------------------------------------*
638 : * tcx5SpectrumDeinterleaving_fx()
639 : *
640 : *
641 : *-------------------------------------------------------------------*/
642 :
643 58691 : void tcx5SpectrumDeinterleaving_fx(
644 : const Word16 tcx5Size,
645 : Word32 *spectrum // Qx
646 : )
647 : {
648 : Word16 i;
649 : Word32 interleaveBuf[N_TCX10_MAX];
650 :
651 58691 : set32_fx( interleaveBuf, 0, N_TCX10_MAX );
652 :
653 : /* ungroup sub-windows: interleave bins according to their frequencies */
654 12379171 : FOR( i = 0; i < tcx5Size; i++ )
655 : {
656 12320480 : interleaveBuf[i] = spectrum[2 * i];
657 12320480 : interleaveBuf[tcx5Size + i] = spectrum[2 * i + 1];
658 12320480 : move32();
659 12320480 : move32();
660 : }
661 :
662 58691 : Copy32( interleaveBuf, spectrum, shl( tcx5Size, 1 ) );
663 :
664 58691 : return;
665 : }
666 :
667 : /*-------------------------------------------------------------------*
668 : * tcx5TnsGrouping()
669 : *
670 : *
671 : *-------------------------------------------------------------------*/
672 :
673 25753 : void tcx5TnsGrouping_fx(
674 : const Word16 L_frame, /* i : frame length (TCX5) */
675 : const Word16 L_spec, /* i : coded spec length (TCX5, derived from filter borders*/
676 : Word32 *spectrum /*Qx*/
677 : )
678 : {
679 : /* rearrange LF sub-window lines prior to TNS synthesis filtering */
680 25753 : IF( LT_16( L_spec, L_frame ) )
681 : {
682 13709 : Copy32( spectrum + 8, spectrum + 16, sub( L_spec, 8 ) );
683 13709 : Copy32( spectrum + L_frame, spectrum + 8, 8 );
684 13709 : Copy32( spectrum + add( L_frame, 8 ), spectrum + add( L_spec, 8 ), sub( L_spec, 8 ) );
685 : }
686 : ELSE
687 : {
688 : Word32 buff[8]; /* Buffer for the rearrangement of LF TCX5 */
689 12044 : Copy32( spectrum + L_spec, buff, 8 );
690 12044 : Copy32( spectrum + 8, spectrum + 16, sub( L_spec, 8 ) );
691 12044 : Copy32( buff, spectrum + 8, 8 );
692 : }
693 :
694 25753 : return;
695 : }
696 :
697 : /*-------------------------------------------------------------------*
698 : * tcx5TnsUngrouping()
699 : *
700 : *
701 : *-------------------------------------------------------------------*/
702 :
703 25753 : void tcx5TnsUngrouping_fx(
704 : const Word16 L_frame, /* i : frame length (TCX5) */
705 : const Word16 L_spec, /* i : coded spec length (TCX5, derived from filter borders*/
706 : Word32 *spectrum, /*Qx*/
707 : const Word16 enc_dec /* i : 0: encoder, else decoder */
708 : )
709 : {
710 : /* undo rearrangement of LF sub-window lines prior to TNS analysis */
711 25753 : IF( LT_16( L_spec, L_frame ) )
712 : {
713 14646 : Copy32( spectrum + L_spec + 8, spectrum + add( L_frame, 8 ), sub( L_spec, 8 ) );
714 14646 : Copy32( spectrum + 8, spectrum + L_frame, 8 );
715 14646 : Copy32( spectrum + 16, spectrum + 8, sub( L_spec, 8 ) );
716 14646 : set32_fx( spectrum + L_spec, 0, sub( L_frame, L_spec ) );
717 14646 : set32_fx( spectrum + add( L_frame, L_spec ), 0, sub( L_frame, L_spec ) );
718 : }
719 : ELSE
720 : {
721 : Word32 buff[8]; /* Buffer for the rearrangement of LF TCX5 */
722 :
723 11107 : Copy32( spectrum + 8, buff, 8 );
724 :
725 11107 : IF( enc_dec == ENC )
726 : {
727 6864 : Copy32( spectrum + 16, spectrum + 8, sub( L_frame, 8 ) );
728 6864 : Copy32( buff, spectrum + L_frame, 8 );
729 : }
730 : ELSE
731 : {
732 4243 : Copy32( spectrum + 16, spectrum + 8, sub( L_spec, 8 ) );
733 4243 : Copy32( buff, spectrum + L_spec, 8 );
734 : }
735 : }
736 :
737 25753 : return;
738 : }
|