Line data Source code
1 : /*====================================================================================
2 : EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0
3 : ====================================================================================*/
4 :
5 : #include <stdlib.h>
6 : #include <assert.h>
7 : #include "options.h" /* Compilation switches */
8 : #include "cnst.h" /* Common constants */
9 : #include "rom_com.h" /* Static table prototypes */
10 : #include "prot_fx.h" /* Function prototypes */
11 : #include "stl.h"
12 :
13 :
14 : #include "math_32.h"
15 :
16 :
17 1040 : static Word16 get_edxt_factor( Word16 length ) /* Returns value of sqrtf(2.f/length) in Q15 */
18 : {
19 : Word16 factor; /*Q15*/
20 1040 : factor = 0;
21 1040 : move16();
22 1040 : IF( EQ_16( length, 512 ) )
23 : {
24 262 : factor = 2048; /*0.0625 in Q15*/
25 262 : move16();
26 : }
27 778 : ELSE IF( EQ_16( length, 256 ) )
28 : {
29 5 : factor = 2896; /*0.0883 in Q15*/
30 5 : move16();
31 : }
32 773 : ELSE IF( EQ_16( length, 128 ) )
33 : {
34 7 : factor = 4096; /*0.125 in Q15*/
35 7 : move16();
36 : }
37 766 : ELSE IF( EQ_16( length, 640 ) )
38 : {
39 184 : factor = 1832; /*0.0559 in Q15*/
40 184 : move16();
41 : }
42 582 : ELSE IF( EQ_16( length, 320 ) )
43 : {
44 432 : factor = 2590; /*0.079 in Q15*/
45 432 : move16();
46 : }
47 150 : ELSE IF( EQ_16( length, 160 ) )
48 : {
49 22 : factor = 3663; /*0.1117 in Q15*/
50 22 : move16();
51 : }
52 128 : ELSE IF( EQ_16( length, 80 ) )
53 : {
54 22 : factor = 5181; /*0.1581 in Q15*/
55 22 : move16();
56 : }
57 106 : ELSE IF( EQ_16( length, 40 ) )
58 : {
59 0 : factor = 7327; /*0.223 in Q15*/
60 0 : move16();
61 : }
62 106 : ELSE IF( EQ_16( length, 960 ) )
63 : {
64 106 : factor = 1496; /*0.0456 in Q15*/
65 106 : move16();
66 : }
67 0 : ELSE IF( EQ_16( length, 480 ) )
68 : {
69 0 : factor = 2115; /*0.0645 in Q15*/
70 0 : move16();
71 : }
72 0 : ELSE IF( EQ_16( length, 240 ) )
73 : {
74 0 : factor = 2991; /*0.0912 in Q15*/
75 0 : move16();
76 : }
77 0 : ELSE IF( EQ_16( length, 120 ) )
78 : {
79 0 : factor = 4230; /*0.1290 in Q15*/
80 0 : move16();
81 : }
82 0 : ELSE IF( EQ_16( length, 1200 ) )
83 : {
84 0 : factor = 1338; /*0.040 in Q15*/
85 0 : move16();
86 : }
87 0 : ELSE IF( EQ_16( length, 800 ) )
88 : {
89 0 : factor = 1638; /*0.05 in Q15*/
90 0 : move16();
91 : }
92 0 : ELSE IF( EQ_16( length, 400 ) )
93 : {
94 0 : factor = 2317; /*0.070 in Q15*/
95 0 : move16();
96 : }
97 0 : ELSE IF( EQ_16( length, 200 ) )
98 : {
99 0 : factor = 3277; /*0.1 in Q15*/
100 0 : move16();
101 : }
102 1040 : return factor; /*Q15*/
103 : }
104 :
105 1696911 : static Word16 const *get_edct_table( Word16 length /*Q0*/, Word16 *q )
106 : {
107 : Word16 const *edct_table;
108 1696911 : edct_table = NULL;
109 1696911 : SWITCH( length )
110 : {
111 6068 : case 1200:
112 6068 : edct_table = edct_table_600_fx; /*Q17*/
113 6068 : *q = add( *q, 2 );
114 6068 : move16();
115 6068 : BREAK;
116 561022 : case 960:
117 561022 : edct_table = edct_table_480_fx; /*Q16*/
118 561022 : BREAK;
119 556988 : case 640:
120 556988 : edct_table = edct_table_320_fx; /*Q16*/
121 556988 : BREAK;
122 200421 : case 320:
123 200421 : edct_table = edct_table_160_fx; /*Q16*/
124 200421 : BREAK;
125 49188 : case 256:
126 49188 : edct_table = edct_table_128_fx; /*Q16*/
127 49188 : BREAK;
128 21498 : case 240:
129 21498 : edct_table = edct_table_120_fx; /*Q16*/
130 21498 : BREAK;
131 0 : case 200:
132 0 : edct_table = edct_table_100_fx; /*Q16*/
133 0 : BREAK;
134 42634 : case 160:
135 42634 : edct_table = edct_table_80_fx; /*Q16*/
136 42634 : BREAK;
137 0 : case 40:
138 0 : edct_table = edct_table_20_fx; /*Q16*/
139 0 : BREAK;
140 2432 : case 800:
141 2432 : edct_table = edct_table_400_fx; /*Q17*/
142 2432 : *q = add( *q, 2 );
143 2432 : move16();
144 2432 : BREAK;
145 223107 : case 512:
146 223107 : edct_table = edct_table_256_fx; /*Q16*/
147 223107 : BREAK;
148 9071 : case 480:
149 9071 : edct_table = edct_table_240_fx; /*Q16*/
150 9071 : BREAK;
151 4529 : case 400:
152 4529 : edct_table = edct_table_200_fx; /*Q16*/
153 4529 : BREAK;
154 12835 : case 128:
155 12835 : edct_table = edct_table_64_fx; /*Q16*/
156 12835 : BREAK;
157 7118 : case 80:
158 7118 : edct_table = edct_table_40_fx; /*Q16*/
159 7118 : BREAK;
160 0 : default:
161 0 : BREAK;
162 : }
163 1696911 : return edct_table;
164 : }
165 :
166 : /*-------------------------------------------------------------------------*
167 : * FUNCTION : edct_fx()
168 : *
169 : * PURPOSE : DCT transform
170 : *
171 : * INPUT ARGUMENTS :
172 : * _ (Word16) length : length
173 : * _ (Word16*) x : input signal Qx
174 : * _ (Word16*) edct_table_128_fx : edct table Q16
175 : *
176 : * OUTPUT ARGUMENTS :
177 : * _ (Word16[]) y : output transform Qx
178 : *-------------------------------------------------------------------------*/
179 1694866 : void edct_fx(
180 : const Word32 *x, /* i : input signal Qq */
181 : Word32 *y, /* o : output transform Qq */
182 : Word16 length, /* i : length Q0*/
183 : Word16 *q /* i : Q value of input signal */
184 : )
185 : {
186 : Word16 i;
187 : Word32 re;
188 : Word32 im;
189 : const Word16 *edct_table; /*Q16 */
190 : Word32 complex_buf[2 * ( L_FRAME48k / 2 + 240 )];
191 : Word32 L_tmp;
192 : Word16 tmp;
193 : Word16 len1;
194 :
195 1694866 : edct_table = get_edct_table( length, q ); /*q*/
196 1694866 : len1 = shr( length, 1 ); /*Q0*/
197 : /* Twiddling and Pre-rotate */
198 558784106 : FOR( i = 0; i < len1; i++ )
199 : {
200 557089240 : L_tmp = Mult_32_16( x[2 * i], edct_table[i] ); /*Q(q+1) */
201 557089240 : complex_buf[2 * i] = Madd_32_16( L_tmp, x[( length - ( 1 + ( i * 2 ) ) )], edct_table[( len1 - ( 1 + i ) )] ); /*Q(q+1) */
202 557089240 : move32();
203 :
204 557089240 : L_tmp = Mult_32_16( x[( length - ( 1 + ( i * 2 ) ) )], edct_table[i] ); /*Q(q+1) */
205 :
206 557089240 : complex_buf[( ( i * 2 ) + 1 )] = Msub_32_16( L_tmp, x[( i * 2 )], edct_table[( len1 - ( 1 + i ) )] ); /*Q(q+1) */
207 557089240 : move32();
208 : }
209 :
210 1694866 : *q = sub( 15, *q );
211 1694866 : move16();
212 1694866 : BASOP_cfft( (cmplx *) complex_buf, len1, q, y );
213 :
214 1694866 : tmp = div_s( 1, length ); /*Q15 */
215 1694866 : tmp = round_fx( L_shl( L_mult( tmp, 19302 /*0.75f * EVS_PI in Q13*/ ), 2 ) ); /*Q15 */
216 558784106 : FOR( i = 0; i < len1; i++ )
217 : {
218 557089240 : re = Msub_32_16( complex_buf[2 * i], complex_buf[( ( i * 2 ) + 1 )], tmp ); /*Q(q+1) */
219 557089240 : im = Madd_32_16( complex_buf[( ( i * 2 ) + 1 )], complex_buf[2 * i], tmp ); /*Q(q+1) */
220 557089240 : y[2 * i] = L_add( Mult_32_16( re, edct_table[i] ), Mult_32_16( im, edct_table[( len1 - ( 1 + i ) )] ) ); /*Q(q+2)*/
221 557089240 : move32();
222 557089240 : y[( length - ( 1 + ( i * 2 ) ) )] = L_sub( Mult_32_16( re, edct_table[( len1 - ( 1 + i ) )] ), Mult_32_16( im, edct_table[i] ) ); /*Q(q+2)*/
223 557089240 : move32();
224 : } /*Q(q-2) */
225 :
226 1694866 : *q = sub( 15 + 2, *q );
227 1694866 : move16();
228 1694866 : return;
229 : }
230 :
231 0 : void edct_ivas_fx(
232 : const Word32 *x, /* i : input signal Qq */
233 : Word32 *y, /* o : output transform Qq */
234 : Word16 length, /* i : length Q0*/
235 : Word16 *q /* i : Q value of input signal */
236 : )
237 : {
238 : Word16 i;
239 : const Word16 *edct_table; /*Q16 */
240 : Word32 re[L_FRAME_PLUS / 2];
241 : Word32 im[L_FRAME_PLUS / 2];
242 : Word32 L_tmp;
243 : Word16 tmp;
244 : Word16 len1;
245 :
246 0 : edct_table = get_edct_table( length, q ); /*q*/
247 0 : len1 = shr( length, 1 ); /*Q0*/
248 : /* Twiddling and Pre-rotate */
249 0 : FOR( i = 0; i < len1; i++ )
250 : {
251 0 : L_tmp = Mult_32_16( x[2 * i], edct_table[i] ); /*Q(q+1) */
252 0 : re[i] = Madd_32_16( L_tmp, x[( length - ( 1 + ( i * 2 ) ) )], edct_table[( len1 - ( 1 + i ) )] ); /*Q(q+1) */
253 0 : move32();
254 :
255 0 : L_tmp = Mult_32_16( x[( length - ( 1 + ( i * 2 ) ) )], edct_table[i] ); /*Q(q+1) */
256 0 : im[i] = Msub_32_16( L_tmp, x[( i * 2 )], edct_table[( len1 - ( 1 + i ) )] ); /*Q(q+1) */
257 0 : move32();
258 : }
259 :
260 0 : *q = sub( 31, *q );
261 0 : move16();
262 0 : tmp = sub( s_min( getScaleFactor32( re, len1 ), getScaleFactor32( im, len1 ) ), find_guarded_bits_fx( len1 ) );
263 0 : scale_sig32( re, len1, tmp );
264 0 : scale_sig32( im, len1, tmp );
265 :
266 0 : fft_fx( re, im, len1, 1 );
267 0 : *q = sub( *q, tmp );
268 0 : move16();
269 :
270 0 : tmp = div_s( 4, length ); /*Q17 */
271 0 : tmp = round_fx( L_mult( tmp, 19302 /*0.75f * EVS_PI in Q13*/ ) ); /*Q15 */
272 0 : FOR( i = 0; i < len1; i++ )
273 : {
274 0 : L_tmp = Msub_32_16( re[i], im[i], tmp );
275 0 : im[i] = Madd_32_16( im[i], re[i], tmp ); /*Q(q+1) */
276 0 : re[i] = L_tmp; /*Q(q+1) */
277 0 : move32();
278 0 : move32();
279 : }
280 0 : FOR( i = 0; i < len1; i++ )
281 : {
282 0 : y[2 * i] = L_add( Mult_32_16( re[i], edct_table[i] ), Mult_32_16( im[i], edct_table[( len1 - ( 1 + i ) )] ) ); /*Q(q+2)*/
283 0 : move32();
284 0 : y[( length - ( 1 + ( i * 2 ) ) )] = L_sub( Mult_32_16( re[i], edct_table[( len1 - ( 1 + i ) )] ), Mult_32_16( im[i], edct_table[i] ) ); /*Q(q+2)*/
285 0 : move32();
286 : } /*Q(q-2) */
287 :
288 0 : *q = sub( 31 + 2, *q );
289 0 : move16();
290 0 : return;
291 : }
292 : /*-------------------------------------------------------------------------*
293 : * FUNCTION : edst_fx()
294 : *
295 : * PURPOSE : DST_IV transform
296 : *
297 : * INPUT ARGUMENTS :
298 : * _ (Word16) length : length
299 : * _ (Word16*) x : input signal Qx
300 : * _ (Word16*) edct_table_128_fx : edct table Q16
301 : *
302 : * OUTPUT ARGUMENTS :
303 : * _ (Word16[]) y : output transform Qx
304 : *-------------------------------------------------------------------------*/
305 2045 : void edst_fx(
306 : const Word32 *x, /* i : input signal Qq */
307 : Word32 *y, /* o : output transform Qq */
308 : Word16 length, /* i : length */
309 : Word16 *q /* i : Q value of input signal */
310 : )
311 : {
312 : Word16 i;
313 : Word32 re;
314 : Word32 im;
315 : const Word16 *edct_table; /*Q16 */
316 : Word32 complex_buf[2 * ( L_FRAME48k / 2 + 240 )];
317 : Word32 L_tmp;
318 : Word16 tmp;
319 : Word16 len1;
320 :
321 2045 : edct_table = get_edct_table( length, q ); /*q*/
322 2045 : len1 = shr( length, 1 ); /*Q0*/
323 : /* Twiddling and Pre-rotate */
324 711421 : FOR( i = 0; i < len1; i++ )
325 : {
326 709376 : L_tmp = Mult_32_16( x[( length - ( 1 + ( i * 2 ) ) )], edct_table[i] ); /*Qq+1*/
327 709376 : complex_buf[2 * i] = Madd_32_16( L_tmp, x[2 * i], edct_table[( len1 - ( 1 + i ) )] ); /*Qq+1*/
328 709376 : move32();
329 :
330 709376 : L_tmp = Mult_32_16( x[2 * i], edct_table[i] ); /*Qq+1*/
331 709376 : complex_buf[( ( i * 2 ) + 1 )] = Msub_32_16( L_tmp, x[( length - ( 1 + ( i * 2 ) ) )], edct_table[( len1 - ( 1 + i ) )] ); /*Qq+1*/
332 709376 : move32();
333 : }
334 :
335 2045 : *q = sub( 15, *q );
336 2045 : move16();
337 2045 : BASOP_cfft( (cmplx *) complex_buf, len1, q, y );
338 :
339 2045 : tmp = div_s( 1, length ); /*Q15 */
340 2045 : tmp = round_fx( L_shl( L_mult( tmp, 19302 /*0.75f * EVS_PI in Q13*/ ), 2 ) ); /*Q15 */
341 711421 : FOR( i = 0; i < len1; i++ )
342 : {
343 709376 : re = Msub_32_16( complex_buf[2 * i], complex_buf[( ( i * 2 ) + 1 )], tmp ); /*Qq+1*/
344 709376 : im = Madd_32_16( complex_buf[( ( i * 2 ) + 1 )], complex_buf[2 * i], tmp ); /*Qq+1*/
345 709376 : y[2 * i] = L_add( Mult_32_16( re, edct_table[i] ), Mult_32_16( im, edct_table[( len1 - ( 1 + i ) )] ) ); /*Qq+2*/
346 709376 : move32();
347 709376 : y[( length - ( 1 + ( i * 2 ) ) )] = L_sub( Mult_32_16( im, edct_table[i] ), Mult_32_16( re, edct_table[( len1 - ( 1 + i ) )] ) ); /*Qq+2*/
348 709376 : move32();
349 : } /*Q(q) */
350 :
351 2045 : *q = sub( 15 + 2, *q );
352 2045 : move16();
353 :
354 2045 : return;
355 : }
356 : /*========================================================================*/
357 : /* FUNCTION : edct_fx() */
358 : /*------------------------------------------------------------------------*/
359 : /* PURPOSE : DCT transform */
360 : /*------------------------------------------------------------------------*/
361 : /* INPUT ARGUMENTS : */
362 : /* _ (Word16) length : length */
363 : /* _ (Word16*) x : input signal Qx */
364 : /* _ (Word16*) edct_table_128_fx : edct table Q15 */
365 : /*------------------------------------------------------------------------*/
366 : /* INPUT/OUTPUT ARGUMENTS : */
367 : /*------------------------------------------------------------------------*/
368 : /* OUTPUT ARGUMENTS : */
369 : /* _ (Word16[]) y : output transform Qx */
370 : /*------------------------------------------------------------------------*/
371 :
372 : /*------------------------------------------------------------------------*/
373 : /* RETURN ARGUMENTS : */
374 : /* _ None */
375 : /*========================================================================*/
376 215100 : void edct_16fx(
377 : const Word16 *x, /* i : input signal Qx */
378 : Word16 *y, /* o : output transform Qx */
379 : Word16 length, /* i : length */
380 : Word16 bh, /* bit-headroom */
381 : const Word16 element_mode
382 :
383 : )
384 : {
385 : Word16 i;
386 : Word16 re[L_FRAME48k / 2];
387 : Word16 im[L_FRAME48k / 2];
388 215100 : const Word16 *edct_table = NULL;
389 : Word16 re2[L_FRAME48k / 2];
390 : Word16 im2[L_FRAME48k / 2];
391 :
392 : Word32 L_tmp, Lacc, Lmax;
393 : Word16 tmp, fact;
394 : Word16 Q_edct;
395 : Word16 Len2, i2;
396 : const Word16 *px, *pt;
397 : Word16 *py;
398 : (void) element_mode;
399 : #ifdef BASOP_NOGLOB_DECLARE_LOCAL
400 : Flag Overflow;
401 215100 : Overflow = 0;
402 215100 : move32();
403 : #endif
404 : /*COMPLETE: some eDCT sub function are missing */
405 :
406 215100 : IF( EQ_16( length, L_FRAME32k ) )
407 : {
408 18626 : edct_table = &edct_table_320_16fx[0]; /*Q15*/
409 : }
410 196474 : ELSE IF( EQ_16( length, L_FRAME ) )
411 : {
412 120619 : edct_table = &edct_table_128_16fx[0]; /*Q15*/
413 : }
414 75855 : ELSE IF( EQ_16( length, L_FRAME16k ) )
415 : {
416 75855 : edct_table = &edct_table_160_16fx[0]; /*Q15*/
417 : }
418 : ELSE
419 : {
420 : }
421 :
422 : /* Twiddling and Pre-rotate */
423 215100 : Lmax = L_deposit_l( 0 );
424 215100 : Len2 = shr( length, 1 );
425 215100 : px = x + sub( length, 1 ); /*Qx*/
426 215100 : pt = edct_table + sub( Len2, 1 ); /*Q16*/
427 33751452 : FOR( i = 0; i < Len2; i++ )
428 : {
429 33536352 : i2 = shl( i, 1 );
430 33536352 : L_tmp = L_mult( x[i2], edct_table[i] ); /*Q(Qx+16) */
431 :
432 33536352 : Lacc = L_mac( L_tmp, *px, *pt ); /*Q(Qx+16) */
433 :
434 33536352 : Lmax = L_max( Lmax, Lacc );
435 :
436 33536352 : L_tmp = L_mult( *px, edct_table[i] ); /*Q(Qx+16) */
437 33536352 : Lacc = L_msu( L_tmp, x[i2], *pt ); /*Q(Qx+16) */
438 33536352 : Lmax = L_max( Lmax, Lacc );
439 :
440 33536352 : px -= 2;
441 33536352 : pt--;
442 : }
443 :
444 215100 : tmp = 31;
445 215100 : move16();
446 215100 : if ( Lmax != 0 )
447 : {
448 206798 : tmp = norm_l( Lmax );
449 : }
450 215100 : Q_edct = sub( tmp, bh ); /*creating a bit-headroom */
451 :
452 215100 : px = x + sub( length, 1 ); /*Qx*/
453 215100 : pt = edct_table + sub( Len2, 1 ); /*Q15*/
454 33751452 : FOR( i = 0; i < Len2; i++ )
455 : {
456 33536352 : i2 = shl( i, 1 );
457 :
458 33536352 : L_tmp = L_mult( x[i2], edct_table[i] ); /*Q(Qx+16) */
459 33536352 : Lacc = L_mac_o( L_tmp, *px, *pt, &Overflow ); /*Q(Qx+16) */
460 33536352 : re2[i] = round_fx_o( L_shl_o( Lacc, Q_edct, &Overflow ), &Overflow ); /* Q(Qx+Q_edct) */
461 33536352 : move16();
462 33536352 : L_tmp = L_mult( *px, edct_table[i] ); /*Q(Qx+16) */
463 33536352 : Lacc = L_msu_o( L_tmp, x[i2], *pt, &Overflow ); /*Q(Qx+16) */
464 33536352 : im2[i] = round_fx_o( L_shl_o( Lacc, Q_edct, &Overflow ), &Overflow ); /* Q(Qx+Q_edct) */
465 33536352 : move16();
466 33536352 : px -= 2;
467 33536352 : pt--;
468 : }
469 215100 : IF( EQ_16( length, L_FRAME32k ) )
470 : {
471 18626 : DoRTFT320_16fx( re2, im2 );
472 : }
473 196474 : ELSE IF( EQ_16( length, L_FRAME ) )
474 : {
475 120619 : DoRTFT128_16fx( re2, im2 );
476 : }
477 75855 : ELSE IF( EQ_16( length, L_FRAME16k ) )
478 : {
479 75855 : DoRTFT160_16fx( re2, im2 );
480 : }
481 : ELSE
482 : {
483 : }
484 215100 : tmp = div_s( 1, length ); /*Q15 */
485 215100 : L_tmp = L_mult( tmp, 19302 ); /*Q29, (3*PI/4) in Q13 */
486 215100 : fact = round_fx( L_shl( L_tmp, 2 ) ); /*Q15 */
487 33751452 : FOR( i = 0; i < shr( length, 1 ); i++ )
488 : {
489 33536352 : tmp = mult_r( im2[i], fact ); /*Q(Qx+Q_edct) */
490 33536352 : re[i] = sub_o( re2[i], tmp, &Overflow ); /*Q(Qx+Q_edct) */
491 33536352 : move16();
492 :
493 33536352 : tmp = mult_r( re2[i], fact ); /*Q(Qx+Q_edct) */
494 33536352 : im[i] = add_o( im2[i], tmp, &Overflow ); /*Q(Qx+Q_edct) */
495 33536352 : move16();
496 : }
497 :
498 : /* Post-rotate and obtain the output data */
499 215100 : py = y + sub( length, 1 ); /*Qx*/
500 215100 : pt = edct_table + sub( Len2, 1 ); /*Q15*/
501 33751452 : FOR( i = 0; i < Len2; i++ )
502 : {
503 33536352 : i2 = shl( i, 1 );
504 :
505 33536352 : L_tmp = L_mult( re[i], edct_table[i] ); /*Q(Qx+Q_edct+16) */
506 33536352 : Lacc = L_mac_o( L_tmp, im[i], *pt, &Overflow ); /*Q(Qx+Q_edct+16) */
507 33536352 : y[i2] = round_fx_o( L_shr_o( Lacc, Q_edct, &Overflow ), &Overflow ); /* Q(Qx) */
508 33536352 : move16();
509 :
510 33536352 : L_tmp = L_mult( re[i], edct_table[sub( shr( length, 1 ), add( 1, i ) )] ); /*Q(Qx+Q_edct+16) */
511 33536352 : Lacc = L_msu( L_tmp, im[i], edct_table[i] ); /*Q(Qx+Q_edct+16) */
512 33536352 : *py = round_fx_o( L_shr_o( Lacc, Q_edct, &Overflow ), &Overflow ); /* Q(Qx) */
513 33536352 : move16();
514 :
515 33536352 : py -= 2;
516 33536352 : pt--;
517 : }
518 215100 : return;
519 : }
520 :
521 :
522 : /*-----------------------------------------------------------------*
523 : * iedct_short_fx()
524 : *
525 : * Inverse EDCT for short frames
526 : *-----------------------------------------------------------------*/
527 :
528 4220 : void iedct_short_fx(
529 : const Word32 *in, /* i : input vector Q*/
530 : Word16 *Q, /* i/o: Q value of input */
531 : Word32 *out, /* o : output vector Q*/
532 : const Word16 segment_length /* i : length Q0*/
533 : )
534 : {
535 : Word32 alias[MAX_SEGMENT_LENGTH];
536 : Word16 seg_len_div2, seg_len_div4, seg_len_3mul_div4;
537 : Word16 i;
538 : Word16 qtmp, tmp;
539 :
540 4220 : qtmp = *Q;
541 4220 : move16();
542 4220 : tmp = 0;
543 4220 : move16();
544 4220 : seg_len_div2 = shr( segment_length, 1 ); /*Q0*/
545 4220 : seg_len_div4 = shr( segment_length, 2 ); /*Q0*/
546 4220 : seg_len_3mul_div4 = add( seg_len_div2, seg_len_div4 );
547 :
548 4220 : edct_fx( in, alias, seg_len_div2, Q );
549 4220 : FOR( i = 0; i < seg_len_div2; i++ )
550 : {
551 4220 : IF( alias[i] != 0 )
552 : {
553 4220 : tmp = 1;
554 4220 : move16();
555 4220 : BREAK;
556 : }
557 : }
558 4220 : if ( tmp == 0 )
559 : {
560 0 : *Q = qtmp;
561 0 : move16();
562 : }
563 336860 : FOR( i = 0; i < seg_len_div4; i++ )
564 : {
565 332640 : out[i] = alias[( seg_len_div4 + i )]; /*Q*/
566 332640 : move32();
567 332640 : out[( seg_len_div4 + i )] = L_negate( alias[( ( seg_len_div2 - 1 ) - i )] ); /*Q*/
568 332640 : move32();
569 332640 : out[( seg_len_div2 + i )] = L_negate( alias[( ( seg_len_div4 - 1 ) - i )] ); /*Q*/
570 332640 : move32();
571 332640 : out[( seg_len_3mul_div4 + i )] = L_negate( alias[i] ); /*Q*/
572 332640 : move32();
573 : }
574 :
575 4220 : return;
576 : }
577 :
578 : #define FAST_EDXT /* optimized FFT-based DCT/DST algorithm */
579 : /*-------------------------------------------------------------------------*
580 : * edxt_fx()
581 : *
582 : * DCT/DST-II or III transform (currently also calculates DCT-IV and DST-IV)
583 : *-------------------------------------------------------------------------*/
584 :
585 1040 : void edxt_fx(
586 : const Word32 *x, /* i : input signal Qx*/
587 : Word32 *y, /* o : output transform Qx*/
588 : const Word16 length, /* i : length Q0*/
589 : const UWord16 kernelType, /* i : kernel type (0 - 3) Q0*/
590 : const UWord16 synthesis /* i : nonzero for inverse Q0*/
591 : )
592 : {
593 1040 : Word16 k, m, fac, hdrm, tmp = 0;
594 : const Word16 *cosPtr, *sinPtr;
595 : Word16 n;
596 1040 : n = 0;
597 1040 : move16();
598 1040 : move16();
599 1040 : cosPtr = NULL;
600 1040 : sinPtr = NULL;
601 1040 : IF( EQ_16( length, 512 ) )
602 : {
603 262 : cosPtr = cos_scale_tbl_512; /*Q15*/
604 262 : sinPtr = sin_scale_tbl_512; /*Q15*/
605 262 : n = 1;
606 262 : move16();
607 : }
608 778 : ELSE IF( EQ_16( length, 256 ) )
609 : {
610 5 : cosPtr = cos_scale_tbl_512; /*Q15*/
611 5 : sinPtr = sin_scale_tbl_512; /*Q15*/
612 5 : n = 2;
613 5 : move16();
614 : }
615 773 : ELSE IF( EQ_16( length, 128 ) )
616 : {
617 7 : cosPtr = cos_scale_tbl_512; /*Q15*/
618 7 : sinPtr = sin_scale_tbl_512; /*Q15*/
619 7 : n = 4;
620 7 : move16();
621 : }
622 766 : ELSE IF( EQ_16( length, 640 ) )
623 : {
624 184 : cosPtr = cos_scale_tbl_640; /*Q15*/
625 184 : sinPtr = sin_scale_tbl_640; /*Q15*/
626 184 : n = 1;
627 184 : move16();
628 : }
629 582 : ELSE IF( EQ_16( length, 320 ) )
630 : {
631 432 : cosPtr = cos_scale_tbl_640; /*Q15*/
632 432 : sinPtr = sin_scale_tbl_640; /*Q15*/
633 432 : n = 2;
634 432 : move16();
635 : }
636 150 : ELSE IF( EQ_16( length, 160 ) )
637 : {
638 22 : cosPtr = cos_scale_tbl_640; /*Q15*/
639 22 : sinPtr = sin_scale_tbl_640; /*Q15*/
640 22 : n = 4;
641 22 : move16();
642 : }
643 128 : ELSE IF( EQ_16( length, 80 ) )
644 : {
645 22 : cosPtr = cos_scale_tbl_640; /*Q15*/
646 22 : sinPtr = sin_scale_tbl_640; /*Q15*/
647 22 : n = 8;
648 22 : move16();
649 : }
650 106 : ELSE IF( EQ_16( length, 40 ) )
651 : {
652 0 : cosPtr = cos_scale_tbl_640; /*Q15*/
653 0 : sinPtr = sin_scale_tbl_640; /*Q15*/
654 0 : n = 16;
655 0 : move16();
656 : }
657 106 : ELSE IF( EQ_16( length, 960 ) )
658 : {
659 106 : cosPtr = cos_scale_tbl_960; /*Q15*/
660 106 : sinPtr = sin_scale_tbl_960; /*Q15*/
661 106 : n = 1;
662 106 : move16();
663 : }
664 0 : ELSE IF( EQ_16( length, 480 ) )
665 : {
666 0 : cosPtr = cos_scale_tbl_960; /*Q15*/
667 0 : sinPtr = sin_scale_tbl_960; /*Q15*/
668 0 : n = 2;
669 0 : move16();
670 : }
671 0 : ELSE IF( EQ_16( length, 240 ) )
672 : {
673 0 : cosPtr = cos_scale_tbl_960; /*Q15*/
674 0 : sinPtr = sin_scale_tbl_960; /*Q15*/
675 0 : n = 4;
676 0 : move16();
677 : }
678 0 : ELSE IF( EQ_16( length, 120 ) )
679 : {
680 0 : cosPtr = cos_scale_tbl_960; /*Q15*/
681 0 : sinPtr = sin_scale_tbl_960; /*Q15*/
682 0 : n = 8;
683 0 : move16();
684 : }
685 0 : ELSE IF( EQ_16( length, 1200 ) )
686 : {
687 0 : cosPtr = cos_scale_tbl_1200; /*Q15*/
688 0 : sinPtr = sin_scale_tbl_1200; /*Q15*/
689 0 : n = 1;
690 0 : move16();
691 : }
692 0 : ELSE IF( EQ_16( length, 800 ) )
693 : {
694 0 : cosPtr = cos_scale_tbl_800; /*Q15*/
695 0 : sinPtr = sin_scale_tbl_800; /*Q15*/
696 0 : n = 1;
697 0 : move16();
698 : }
699 0 : ELSE IF( EQ_16( length, 400 ) )
700 : {
701 0 : cosPtr = cos_scale_tbl_800; /*Q15*/
702 0 : sinPtr = sin_scale_tbl_800; /*Q15*/
703 0 : n = 2;
704 0 : move16();
705 : }
706 0 : ELSE IF( EQ_16( length, 200 ) )
707 : {
708 0 : cosPtr = cos_scale_tbl_800; /*Q15*/
709 0 : sinPtr = sin_scale_tbl_800; /*Q15*/
710 0 : n = 4;
711 0 : move16();
712 : }
713 :
714 : #ifdef FAST_EDXT
715 1040 : test();
716 1040 : IF( EQ_16( kernelType, MDST_II ) || EQ_16( kernelType, MDCT_II ) )
717 : {
718 1040 : const Word16 Nm1 = sub( length, 1 );
719 1040 : const Word16 xSign = sub( imult1616( 2, shr( kernelType, 1 ) ), 1 ); /*Q0*/
720 : Word32 re[L_FRAME_PLUS];
721 : Word32 im[L_FRAME_PLUS];
722 :
723 1040 : IF( !synthesis )
724 : {
725 0 : FOR( k = ( Nm1 / 2 ); k >= 0; k-- ) /* pre-modulation of audio input */
726 : {
727 0 : re[k] = x[2 * k]; /*Qx*/
728 0 : re[( Nm1 - k )] = Mpy_32_16_1( x[( ( k * 2 ) + 1 )], shl_sat( xSign, 15 ) ); /*Qx*/
729 0 : im[k] = im[( Nm1 - k )] = 0;
730 0 : move32();
731 0 : move32();
732 0 : move32();
733 : }
734 :
735 0 : IF( EQ_16( length, 512 ) )
736 : {
737 : /* Scaling down re and im buffers to avoid overflow in DoRTFTn_fx if the minimum headroom is less than 4 bits */
738 0 : hdrm = s_min( L_norm_arr( re, 512 ), L_norm_arr( im, 512 ) );
739 0 : IF( LT_16( hdrm, 4 ) )
740 : {
741 0 : tmp = sub( hdrm, 4 );
742 0 : scale_sig32( re, 512, tmp );
743 0 : scale_sig32( im, 512, tmp );
744 : }
745 :
746 0 : DoRTFTn_fx( re, im, 512 );
747 :
748 0 : IF( LT_16( hdrm, 4 ) )
749 : {
750 0 : tmp = negate( tmp );
751 0 : scale_sig32( re, 512, tmp );
752 0 : scale_sig32( im, 512, tmp );
753 : }
754 : }
755 : ELSE /* fft() doesn't support 512 */
756 : {
757 0 : fft_fx( re, im, length, 1 );
758 : }
759 :
760 0 : IF( shr( kernelType, 1 ) )
761 : {
762 0 : FOR( k = ( Nm1 / 2 ); k > 0; k-- )
763 : {
764 : // const float wRe = cosf( scale * k );
765 : // const float wIm = sinf( scale * k );
766 0 : const Word16 wRe = cosPtr[( k * n )]; /*Q15*/
767 0 : const Word16 wIm = sinPtr[( k * n )]; /*Q15*/
768 :
769 0 : y[k] /*pt 1*/ = L_add( Mpy_32_16_1( re[k], wRe ), Mpy_32_16_1( im[k], wIm ) ); /*Qx*/
770 0 : y[( length - k )] = L_sub( Mpy_32_16_1( re[k], wIm ), Mpy_32_16_1( im[k], wRe ) ); /*Qx*/
771 0 : move32();
772 0 : move32();
773 : }
774 0 : y[( length / 2 )] = Mpy_32_16_1( re[( length / 2 )], INV_SQRT_2_Q15 ); /*Qx*/
775 0 : move32();
776 : }
777 : ELSE /* forw. DST-II */
778 : {
779 0 : FOR( k = ( Nm1 / 2 ); k > 0; k-- )
780 : {
781 : // const float wRe = cosf( scale * k );
782 : // const float wIm = sinf( scale * k );
783 0 : const Word16 wRe = cosPtr[( k * n )]; /*Q15*/
784 0 : const Word16 wIm = sinPtr[( k * n )]; /*Q15*/
785 :
786 0 : y[( Nm1 - k )] = L_add( Mpy_32_16_1( re[k], wRe ), Mpy_32_16_1( im[k], wIm ) ); /*Qx*/
787 0 : y[k - 1] = L_sub( Mpy_32_16_1( re[k], wIm ), Mpy_32_16_1( im[k], wRe ) ); /*Qx*/
788 0 : move32();
789 0 : move32();
790 : }
791 0 : y[( Nm1 / 2 )] = Mpy_32_16_1( re[( length / 2 )], INV_SQRT_2_Q15 ); /*Qx*/
792 0 : move32();
793 : }
794 :
795 0 : y[( Nm1 - ( Nm1 * ( kernelType / 2 ) ) )] = L_shr( re[0], 1 ); /*Qx*/
796 0 : move32();
797 : }
798 : ELSE /* inverse II = III */
799 : {
800 1040 : IF( shr( kernelType, 1 ) )
801 : {
802 121152 : FOR( k = ( Nm1 / 2 ); k > 0; k-- )
803 : {
804 : // const float wRe = cosf( scale * k ) * 0.5f;
805 : // const float wIm = sinf( scale * k ) * 0.5f;
806 120638 : const Word16 wRe = shr( cosPtr[imult1616( k, n )], 1 );
807 120638 : const Word16 wIm = shr( sinPtr[imult1616( k, n )], 1 );
808 :
809 120638 : re[k] = L_add( Mpy_32_16_1( x[k], wRe ), Mpy_32_16_1( x[( length - k )], wIm ) ); /*Qx*/
810 120638 : im[k] = L_sub( Mpy_32_16_1( x[( length - k )], wRe ), Mpy_32_16_1( x[k], wIm ) ); /*Qx*/
811 120638 : move32();
812 120638 : move32();
813 : }
814 514 : re[( length / 2 )] = Mpy_32_16_1( x[( length / 2 )], INV_SQRT_2_Q15 ); /*Qx*/
815 514 : move32();
816 : }
817 : ELSE /* DST type III */
818 : {
819 128528 : FOR( k = ( Nm1 / 2 ); k > 0; k-- )
820 : {
821 : // const float wRe = cosf( scale * k ) * 0.5f;
822 : // const float wIm = sinf( scale * k ) * 0.5f;
823 128002 : const Word16 wRe = shr( cosPtr[( k * n )], 1 ); /*Q15*/
824 128002 : const Word16 wIm = shr( sinPtr[( k * n )], 1 ); /*Q15*/
825 :
826 128002 : re[k] = L_add( Mpy_32_16_1( x[( Nm1 - k )], wRe ), Mpy_32_16_1( x[( k - 1 )], wIm ) ); /*Qx*/
827 128002 : im[k] = L_sub( Mpy_32_16_1( x[( k - 1 )], wRe ), Mpy_32_16_1( x[( Nm1 - k )], wIm ) ); /*Qx*/
828 128002 : move32();
829 128002 : move32();
830 : }
831 526 : re[( length / 2 )] = Mpy_32_16_1( x[( Nm1 / 2 )], INV_SQRT_2_Q15 ); /*Qx*/
832 526 : move32();
833 : }
834 :
835 1040 : re[0] = x[( Nm1 - ( Nm1 * ( kernelType / 2 ) ) )]; /*Qx*/
836 1040 : im[0] = im[( length / 2 )] = 0;
837 1040 : move32();
838 1040 : move32();
839 249680 : FOR( k = ( Nm1 / 2 ); k > 0; k-- )
840 : {
841 248640 : re[( length - k )] = re[k]; /*Qx*/
842 248640 : im[( length - k )] = L_negate( im[k] ); /*Qx*/
843 248640 : move32();
844 248640 : move32();
845 : }
846 :
847 1040 : IF( EQ_16( length, 512 ) )
848 : {
849 : /* Scaling down re and im buffers to avoid overflow in DoRTFTn_fx if the minimum headroom is less than 4 bits */
850 262 : hdrm = s_min( L_norm_arr( re, 512 ), L_norm_arr( im, 512 ) );
851 262 : IF( LT_16( hdrm, 4 ) )
852 : {
853 0 : tmp = sub( hdrm, 4 );
854 0 : scale_sig32( re, 512, tmp );
855 0 : scale_sig32( im, 512, tmp );
856 : }
857 :
858 262 : DoRTFTn_fx( re, im, 512 );
859 :
860 262 : IF( LT_16( hdrm, 4 ) )
861 : {
862 0 : tmp = negate( tmp );
863 0 : scale_sig32( re, 512, tmp );
864 0 : scale_sig32( im, 512, tmp );
865 : }
866 : }
867 : ELSE /* fft() doesn't support 512 */
868 : {
869 778 : fft_fx( re, im, length, 1 );
870 : }
871 :
872 250720 : FOR( k = ( Nm1 / 2 ); k >= 0; k-- ) /* post-modulation of FFT output */
873 : {
874 249680 : y[2 * k] = re[k]; /*Qx*/
875 249680 : move32();
876 249680 : IF( xSign != 0 )
877 : {
878 249680 : y[( ( k * 2 ) + 1 )] = Mpy_32_16_1( re[( Nm1 - k )], shl_sat( xSign, 15 ) ); /*Qx*/
879 : }
880 : ELSE
881 : {
882 0 : y[( ( k * 2 ) + 1 )] = 0; /*Qx*/
883 : }
884 249680 : move32();
885 : }
886 : }
887 : }
888 : #endif
889 : #ifdef IVAS_FLOAT_FIXED_TO_BE_DONE
890 : ELSE
891 : /* TODO: below IF and ELSE blocks are unreachable, verified on code coverage report */
892 : IF( s_and( kernelType, 1 ) ) /* DST */
893 : {
894 : const float offK = ( kernelType == MDST_II && synthesis ? 0.5f : 1.0f - 0.5f * ( kernelType >> 1 ) );
895 : const float offM = ( kernelType == MDST_II && synthesis ? 1.0f : 0.5f );
896 :
897 : FOR( k = 0; k < length; k++ )
898 : {
899 : y[k] = 0.f;
900 : FOR( m = 0; m < length; m++ )
901 : {
902 : y[k] += x[m] * sinf( pi_len * ( m + offM ) * ( k + offK ) );
903 : }
904 : }
905 : IF( offK == 1.f )
906 : {
907 : y[length - 1] *= 0.5f; /* scale Nyquist sample */
908 : }
909 : }
910 : ELSE /* kernelType 0, 2: DCT */
911 : {
912 : const float offK = ( EQ_16( kernelType, MDCT_II ) && synthesis ? 0.5f : 0.5f - shr( shr( kernelType, 1 ), 1 ) );
913 : const float offM = ( EQ_16( kernelType, MDCT_II ) && synthesis ? 0.0f : 0.5f );
914 :
915 : FOR( k = 0; k < length; k++ )
916 : {
917 : y[k] = 0.f;
918 : FOR( m = 0; m < length; m++ )
919 : {
920 : y[k] += x[m] * cosf( pi_len * ( m + offM ) * ( k + offK ) );
921 : }
922 : }
923 : IF( offK == 0.f )
924 : {
925 : y[0] *= 0.5f; /* scale lowest (i.e. DC) sample */
926 : }
927 : }
928 : #endif // IVAS_FLOAT_FIXED_TO_BE_DONE
929 : /*v_multc(y, (kernelType == MDCT_II ? -1.f : 1.f) * sqrtf(2.f / length), y, length);*/
930 1040 : fac = get_edxt_factor( length ); /* Q15 */
931 1040 : if ( EQ_16( kernelType, MDCT_II ) )
932 : {
933 514 : fac = negate( fac );
934 : }
935 :
936 500400 : FOR( m = 0; m < length; m++ )
937 : {
938 499360 : y[m] = Mpy_32_16_1( y[m], fac ); /*Qx*/
939 499360 : move32();
940 : }
941 1040 : return;
942 : }
|