| OLD | NEW |
| (Empty) | |
| 1 /*Copyright (c) 2003-2004, Mark Borgerding |
| 2 Lots of modifications by Jean-Marc Valin |
| 3 Copyright (c) 2005-2007, Xiph.Org Foundation |
| 4 Copyright (c) 2008, Xiph.Org Foundation, CSIRO |
| 5 |
| 6 All rights reserved. |
| 7 |
| 8 Redistribution and use in source and binary forms, with or without |
| 9 modification, are permitted provided that the following conditions are met: |
| 10 |
| 11 * Redistributions of source code must retain the above copyright notice, |
| 12 this list of conditions and the following disclaimer. |
| 13 * Redistributions in binary form must reproduce the above copyright notice, |
| 14 this list of conditions and the following disclaimer in the |
| 15 documentation and/or other materials provided with the distribution. |
| 16 |
| 17 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" |
| 18 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
| 19 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
| 20 ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE |
| 21 LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
| 22 CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
| 23 SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
| 24 INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
| 25 CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
| 26 ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
| 27 POSSIBILITY OF SUCH DAMAGE.*/ |
| 28 |
| 29 /* This code is originally from Mark Borgerding's KISS-FFT but has been |
| 30 heavily modified to better suit Opus */ |
| 31 |
| 32 #ifndef SKIP_CONFIG_H |
| 33 # ifdef HAVE_CONFIG_H |
| 34 # include "config.h" |
| 35 # endif |
| 36 #endif |
| 37 |
| 38 #include "_kiss_fft_guts.h" |
| 39 #include "arch.h" |
| 40 #include "os_support.h" |
| 41 #include "mathops.h" |
| 42 #include "stack_alloc.h" |
| 43 |
| 44 /* The guts header contains all the multiplication and addition macros that are
defined for |
| 45 complex numbers. It also delares the kf_ internal functions. |
| 46 */ |
| 47 |
| 48 static void kf_bfly2( |
| 49 kiss_fft_cpx * Fout, |
| 50 int m, |
| 51 int N |
| 52 ) |
| 53 { |
| 54 kiss_fft_cpx * Fout2; |
| 55 int i; |
| 56 (void)m; |
| 57 #ifdef CUSTOM_MODES |
| 58 if (m==1) |
| 59 { |
| 60 celt_assert(m==1); |
| 61 for (i=0;i<N;i++) |
| 62 { |
| 63 kiss_fft_cpx t; |
| 64 Fout2 = Fout + 1; |
| 65 t = *Fout2; |
| 66 C_SUB( *Fout2 , *Fout , t ); |
| 67 C_ADDTO( *Fout , t ); |
| 68 Fout += 2; |
| 69 } |
| 70 } else |
| 71 #endif |
| 72 { |
| 73 opus_val16 tw; |
| 74 tw = QCONST16(0.7071067812f, 15); |
| 75 /* We know that m==4 here because the radix-2 is just after a radix-4 */ |
| 76 celt_assert(m==4); |
| 77 for (i=0;i<N;i++) |
| 78 { |
| 79 kiss_fft_cpx t; |
| 80 Fout2 = Fout + 4; |
| 81 t = Fout2[0]; |
| 82 C_SUB( Fout2[0] , Fout[0] , t ); |
| 83 C_ADDTO( Fout[0] , t ); |
| 84 |
| 85 t.r = S_MUL(Fout2[1].r+Fout2[1].i, tw); |
| 86 t.i = S_MUL(Fout2[1].i-Fout2[1].r, tw); |
| 87 C_SUB( Fout2[1] , Fout[1] , t ); |
| 88 C_ADDTO( Fout[1] , t ); |
| 89 |
| 90 t.r = Fout2[2].i; |
| 91 t.i = -Fout2[2].r; |
| 92 C_SUB( Fout2[2] , Fout[2] , t ); |
| 93 C_ADDTO( Fout[2] , t ); |
| 94 |
| 95 t.r = S_MUL(Fout2[3].i-Fout2[3].r, tw); |
| 96 t.i = S_MUL(-Fout2[3].i-Fout2[3].r, tw); |
| 97 C_SUB( Fout2[3] , Fout[3] , t ); |
| 98 C_ADDTO( Fout[3] , t ); |
| 99 Fout += 8; |
| 100 } |
| 101 } |
| 102 } |
| 103 |
| 104 static void kf_bfly4( |
| 105 kiss_fft_cpx * Fout, |
| 106 const size_t fstride, |
| 107 const kiss_fft_state *st, |
| 108 int m, |
| 109 int N, |
| 110 int mm |
| 111 ) |
| 112 { |
| 113 int i; |
| 114 |
| 115 if (m==1) |
| 116 { |
| 117 /* Degenerate case where all the twiddles are 1. */ |
| 118 for (i=0;i<N;i++) |
| 119 { |
| 120 kiss_fft_cpx scratch0, scratch1; |
| 121 |
| 122 C_SUB( scratch0 , *Fout, Fout[2] ); |
| 123 C_ADDTO(*Fout, Fout[2]); |
| 124 C_ADD( scratch1 , Fout[1] , Fout[3] ); |
| 125 C_SUB( Fout[2], *Fout, scratch1 ); |
| 126 C_ADDTO( *Fout , scratch1 ); |
| 127 C_SUB( scratch1 , Fout[1] , Fout[3] ); |
| 128 |
| 129 Fout[1].r = scratch0.r + scratch1.i; |
| 130 Fout[1].i = scratch0.i - scratch1.r; |
| 131 Fout[3].r = scratch0.r - scratch1.i; |
| 132 Fout[3].i = scratch0.i + scratch1.r; |
| 133 Fout+=4; |
| 134 } |
| 135 } else { |
| 136 int j; |
| 137 kiss_fft_cpx scratch[6]; |
| 138 const kiss_twiddle_cpx *tw1,*tw2,*tw3; |
| 139 const int m2=2*m; |
| 140 const int m3=3*m; |
| 141 kiss_fft_cpx * Fout_beg = Fout; |
| 142 for (i=0;i<N;i++) |
| 143 { |
| 144 Fout = Fout_beg + i*mm; |
| 145 tw3 = tw2 = tw1 = st->twiddles; |
| 146 /* m is guaranteed to be a multiple of 4. */ |
| 147 for (j=0;j<m;j++) |
| 148 { |
| 149 C_MUL(scratch[0],Fout[m] , *tw1 ); |
| 150 C_MUL(scratch[1],Fout[m2] , *tw2 ); |
| 151 C_MUL(scratch[2],Fout[m3] , *tw3 ); |
| 152 |
| 153 C_SUB( scratch[5] , *Fout, scratch[1] ); |
| 154 C_ADDTO(*Fout, scratch[1]); |
| 155 C_ADD( scratch[3] , scratch[0] , scratch[2] ); |
| 156 C_SUB( scratch[4] , scratch[0] , scratch[2] ); |
| 157 C_SUB( Fout[m2], *Fout, scratch[3] ); |
| 158 tw1 += fstride; |
| 159 tw2 += fstride*2; |
| 160 tw3 += fstride*3; |
| 161 C_ADDTO( *Fout , scratch[3] ); |
| 162 |
| 163 Fout[m].r = scratch[5].r + scratch[4].i; |
| 164 Fout[m].i = scratch[5].i - scratch[4].r; |
| 165 Fout[m3].r = scratch[5].r - scratch[4].i; |
| 166 Fout[m3].i = scratch[5].i + scratch[4].r; |
| 167 ++Fout; |
| 168 } |
| 169 } |
| 170 } |
| 171 } |
| 172 |
| 173 |
| 174 #ifndef RADIX_TWO_ONLY |
| 175 |
| 176 static void kf_bfly3( |
| 177 kiss_fft_cpx * Fout, |
| 178 const size_t fstride, |
| 179 const kiss_fft_state *st, |
| 180 int m, |
| 181 int N, |
| 182 int mm |
| 183 ) |
| 184 { |
| 185 int i; |
| 186 size_t k; |
| 187 const size_t m2 = 2*m; |
| 188 const kiss_twiddle_cpx *tw1,*tw2; |
| 189 kiss_fft_cpx scratch[5]; |
| 190 kiss_twiddle_cpx epi3; |
| 191 |
| 192 kiss_fft_cpx * Fout_beg = Fout; |
| 193 #ifdef FIXED_POINT |
| 194 /*epi3.r = -16384;*/ /* Unused */ |
| 195 epi3.i = -28378; |
| 196 #else |
| 197 epi3 = st->twiddles[fstride*m]; |
| 198 #endif |
| 199 for (i=0;i<N;i++) |
| 200 { |
| 201 Fout = Fout_beg + i*mm; |
| 202 tw1=tw2=st->twiddles; |
| 203 /* For non-custom modes, m is guaranteed to be a multiple of 4. */ |
| 204 k=m; |
| 205 do { |
| 206 |
| 207 C_MUL(scratch[1],Fout[m] , *tw1); |
| 208 C_MUL(scratch[2],Fout[m2] , *tw2); |
| 209 |
| 210 C_ADD(scratch[3],scratch[1],scratch[2]); |
| 211 C_SUB(scratch[0],scratch[1],scratch[2]); |
| 212 tw1 += fstride; |
| 213 tw2 += fstride*2; |
| 214 |
| 215 Fout[m].r = Fout->r - HALF_OF(scratch[3].r); |
| 216 Fout[m].i = Fout->i - HALF_OF(scratch[3].i); |
| 217 |
| 218 C_MULBYSCALAR( scratch[0] , epi3.i ); |
| 219 |
| 220 C_ADDTO(*Fout,scratch[3]); |
| 221 |
| 222 Fout[m2].r = Fout[m].r + scratch[0].i; |
| 223 Fout[m2].i = Fout[m].i - scratch[0].r; |
| 224 |
| 225 Fout[m].r -= scratch[0].i; |
| 226 Fout[m].i += scratch[0].r; |
| 227 |
| 228 ++Fout; |
| 229 } while(--k); |
| 230 } |
| 231 } |
| 232 |
| 233 |
| 234 #ifndef OVERRIDE_kf_bfly5 |
| 235 static void kf_bfly5( |
| 236 kiss_fft_cpx * Fout, |
| 237 const size_t fstride, |
| 238 const kiss_fft_state *st, |
| 239 int m, |
| 240 int N, |
| 241 int mm |
| 242 ) |
| 243 { |
| 244 kiss_fft_cpx *Fout0,*Fout1,*Fout2,*Fout3,*Fout4; |
| 245 int i, u; |
| 246 kiss_fft_cpx scratch[13]; |
| 247 const kiss_twiddle_cpx *tw; |
| 248 kiss_twiddle_cpx ya,yb; |
| 249 kiss_fft_cpx * Fout_beg = Fout; |
| 250 |
| 251 #ifdef FIXED_POINT |
| 252 ya.r = 10126; |
| 253 ya.i = -31164; |
| 254 yb.r = -26510; |
| 255 yb.i = -19261; |
| 256 #else |
| 257 ya = st->twiddles[fstride*m]; |
| 258 yb = st->twiddles[fstride*2*m]; |
| 259 #endif |
| 260 tw=st->twiddles; |
| 261 |
| 262 for (i=0;i<N;i++) |
| 263 { |
| 264 Fout = Fout_beg + i*mm; |
| 265 Fout0=Fout; |
| 266 Fout1=Fout0+m; |
| 267 Fout2=Fout0+2*m; |
| 268 Fout3=Fout0+3*m; |
| 269 Fout4=Fout0+4*m; |
| 270 |
| 271 /* For non-custom modes, m is guaranteed to be a multiple of 4. */ |
| 272 for ( u=0; u<m; ++u ) { |
| 273 scratch[0] = *Fout0; |
| 274 |
| 275 C_MUL(scratch[1] ,*Fout1, tw[u*fstride]); |
| 276 C_MUL(scratch[2] ,*Fout2, tw[2*u*fstride]); |
| 277 C_MUL(scratch[3] ,*Fout3, tw[3*u*fstride]); |
| 278 C_MUL(scratch[4] ,*Fout4, tw[4*u*fstride]); |
| 279 |
| 280 C_ADD( scratch[7],scratch[1],scratch[4]); |
| 281 C_SUB( scratch[10],scratch[1],scratch[4]); |
| 282 C_ADD( scratch[8],scratch[2],scratch[3]); |
| 283 C_SUB( scratch[9],scratch[2],scratch[3]); |
| 284 |
| 285 Fout0->r += scratch[7].r + scratch[8].r; |
| 286 Fout0->i += scratch[7].i + scratch[8].i; |
| 287 |
| 288 scratch[5].r = scratch[0].r + S_MUL(scratch[7].r,ya.r) + S_MUL(scratch[
8].r,yb.r); |
| 289 scratch[5].i = scratch[0].i + S_MUL(scratch[7].i,ya.r) + S_MUL(scratch[
8].i,yb.r); |
| 290 |
| 291 scratch[6].r = S_MUL(scratch[10].i,ya.i) + S_MUL(scratch[9].i,yb.i); |
| 292 scratch[6].i = -S_MUL(scratch[10].r,ya.i) - S_MUL(scratch[9].r,yb.i); |
| 293 |
| 294 C_SUB(*Fout1,scratch[5],scratch[6]); |
| 295 C_ADD(*Fout4,scratch[5],scratch[6]); |
| 296 |
| 297 scratch[11].r = scratch[0].r + S_MUL(scratch[7].r,yb.r) + S_MUL(scratch
[8].r,ya.r); |
| 298 scratch[11].i = scratch[0].i + S_MUL(scratch[7].i,yb.r) + S_MUL(scratch
[8].i,ya.r); |
| 299 scratch[12].r = - S_MUL(scratch[10].i,yb.i) + S_MUL(scratch[9].i,ya.i); |
| 300 scratch[12].i = S_MUL(scratch[10].r,yb.i) - S_MUL(scratch[9].r,ya.i); |
| 301 |
| 302 C_ADD(*Fout2,scratch[11],scratch[12]); |
| 303 C_SUB(*Fout3,scratch[11],scratch[12]); |
| 304 |
| 305 ++Fout0;++Fout1;++Fout2;++Fout3;++Fout4; |
| 306 } |
| 307 } |
| 308 } |
| 309 #endif /* OVERRIDE_kf_bfly5 */ |
| 310 |
| 311 |
| 312 #endif |
| 313 |
| 314 |
| 315 #ifdef CUSTOM_MODES |
| 316 |
| 317 static |
| 318 void compute_bitrev_table( |
| 319 int Fout, |
| 320 opus_int16 *f, |
| 321 const size_t fstride, |
| 322 int in_stride, |
| 323 opus_int16 * factors, |
| 324 const kiss_fft_state *st |
| 325 ) |
| 326 { |
| 327 const int p=*factors++; /* the radix */ |
| 328 const int m=*factors++; /* stage's fft length/p */ |
| 329 |
| 330 /*printf ("fft %d %d %d %d %d %d\n", p*m, m, p, s2, fstride*in_stride, N);*/ |
| 331 if (m==1) |
| 332 { |
| 333 int j; |
| 334 for (j=0;j<p;j++) |
| 335 { |
| 336 *f = Fout+j; |
| 337 f += fstride*in_stride; |
| 338 } |
| 339 } else { |
| 340 int j; |
| 341 for (j=0;j<p;j++) |
| 342 { |
| 343 compute_bitrev_table( Fout , f, fstride*p, in_stride, factors,st); |
| 344 f += fstride*in_stride; |
| 345 Fout += m; |
| 346 } |
| 347 } |
| 348 } |
| 349 |
| 350 /* facbuf is populated by p1,m1,p2,m2, ... |
| 351 where |
| 352 p[i] * m[i] = m[i-1] |
| 353 m0 = n */ |
| 354 static |
| 355 int kf_factor(int n,opus_int16 * facbuf) |
| 356 { |
| 357 int p=4; |
| 358 int i; |
| 359 int stages=0; |
| 360 int nbak = n; |
| 361 |
| 362 /*factor out powers of 4, powers of 2, then any remaining primes */ |
| 363 do { |
| 364 while (n % p) { |
| 365 switch (p) { |
| 366 case 4: p = 2; break; |
| 367 case 2: p = 3; break; |
| 368 default: p += 2; break; |
| 369 } |
| 370 if (p>32000 || (opus_int32)p*(opus_int32)p > n) |
| 371 p = n; /* no more factors, skip to end */ |
| 372 } |
| 373 n /= p; |
| 374 #ifdef RADIX_TWO_ONLY |
| 375 if (p!=2 && p != 4) |
| 376 #else |
| 377 if (p>5) |
| 378 #endif |
| 379 { |
| 380 return 0; |
| 381 } |
| 382 facbuf[2*stages] = p; |
| 383 if (p==2 && stages > 1) |
| 384 { |
| 385 facbuf[2*stages] = 4; |
| 386 facbuf[2] = 2; |
| 387 } |
| 388 stages++; |
| 389 } while (n > 1); |
| 390 n = nbak; |
| 391 /* Reverse the order to get the radix 4 at the end, so we can use the |
| 392 fast degenerate case. It turns out that reversing the order also |
| 393 improves the noise behaviour. */ |
| 394 for (i=0;i<stages/2;i++) |
| 395 { |
| 396 int tmp; |
| 397 tmp = facbuf[2*i]; |
| 398 facbuf[2*i] = facbuf[2*(stages-i-1)]; |
| 399 facbuf[2*(stages-i-1)] = tmp; |
| 400 } |
| 401 for (i=0;i<stages;i++) |
| 402 { |
| 403 n /= facbuf[2*i]; |
| 404 facbuf[2*i+1] = n; |
| 405 } |
| 406 return 1; |
| 407 } |
| 408 |
| 409 static void compute_twiddles(kiss_twiddle_cpx *twiddles, int nfft) |
| 410 { |
| 411 int i; |
| 412 #ifdef FIXED_POINT |
| 413 for (i=0;i<nfft;++i) { |
| 414 opus_val32 phase = -i; |
| 415 kf_cexp2(twiddles+i, DIV32(SHL32(phase,17),nfft)); |
| 416 } |
| 417 #else |
| 418 for (i=0;i<nfft;++i) { |
| 419 const double pi=3.14159265358979323846264338327; |
| 420 double phase = ( -2*pi /nfft ) * i; |
| 421 kf_cexp(twiddles+i, phase ); |
| 422 } |
| 423 #endif |
| 424 } |
| 425 |
| 426 int opus_fft_alloc_arch_c(kiss_fft_state *st) { |
| 427 (void)st; |
| 428 return 0; |
| 429 } |
| 430 |
| 431 /* |
| 432 * |
| 433 * Allocates all necessary storage space for the fft and ifft. |
| 434 * The return value is a contiguous block of memory. As such, |
| 435 * It can be freed with free(). |
| 436 * */ |
| 437 kiss_fft_state *opus_fft_alloc_twiddles(int nfft,void * mem,size_t * lenmem, |
| 438 const kiss_fft_state *base, int arch) |
| 439 { |
| 440 kiss_fft_state *st=NULL; |
| 441 size_t memneeded = sizeof(struct kiss_fft_state); /* twiddle factors*/ |
| 442 |
| 443 if ( lenmem==NULL ) { |
| 444 st = ( kiss_fft_state*)KISS_FFT_MALLOC( memneeded ); |
| 445 }else{ |
| 446 if (mem != NULL && *lenmem >= memneeded) |
| 447 st = (kiss_fft_state*)mem; |
| 448 *lenmem = memneeded; |
| 449 } |
| 450 if (st) { |
| 451 opus_int16 *bitrev; |
| 452 kiss_twiddle_cpx *twiddles; |
| 453 |
| 454 st->nfft=nfft; |
| 455 #ifdef FIXED_POINT |
| 456 st->scale_shift = celt_ilog2(st->nfft); |
| 457 if (st->nfft == 1<<st->scale_shift) |
| 458 st->scale = Q15ONE; |
| 459 else |
| 460 st->scale = (1073741824+st->nfft/2)/st->nfft>>(15-st->scale_shift); |
| 461 #else |
| 462 st->scale = 1.f/nfft; |
| 463 #endif |
| 464 if (base != NULL) |
| 465 { |
| 466 st->twiddles = base->twiddles; |
| 467 st->shift = 0; |
| 468 while (st->shift < 32 && nfft<<st->shift != base->nfft) |
| 469 st->shift++; |
| 470 if (st->shift>=32) |
| 471 goto fail; |
| 472 } else { |
| 473 st->twiddles = twiddles = (kiss_twiddle_cpx*)KISS_FFT_MALLOC(sizeof(k
iss_twiddle_cpx)*nfft); |
| 474 compute_twiddles(twiddles, nfft); |
| 475 st->shift = -1; |
| 476 } |
| 477 if (!kf_factor(nfft,st->factors)) |
| 478 { |
| 479 goto fail; |
| 480 } |
| 481 |
| 482 /* bitrev */ |
| 483 st->bitrev = bitrev = (opus_int16*)KISS_FFT_MALLOC(sizeof(opus_int16)*nf
ft); |
| 484 if (st->bitrev==NULL) |
| 485 goto fail; |
| 486 compute_bitrev_table(0, bitrev, 1,1, st->factors,st); |
| 487 |
| 488 /* Initialize architecture specific fft parameters */ |
| 489 if (opus_fft_alloc_arch(st, arch)) |
| 490 goto fail; |
| 491 } |
| 492 return st; |
| 493 fail: |
| 494 opus_fft_free(st, arch); |
| 495 return NULL; |
| 496 } |
| 497 |
| 498 kiss_fft_state *opus_fft_alloc(int nfft,void * mem,size_t * lenmem, int arch) |
| 499 { |
| 500 return opus_fft_alloc_twiddles(nfft, mem, lenmem, NULL, arch); |
| 501 } |
| 502 |
| 503 void opus_fft_free_arch_c(kiss_fft_state *st) { |
| 504 (void)st; |
| 505 } |
| 506 |
| 507 void opus_fft_free(const kiss_fft_state *cfg, int arch) |
| 508 { |
| 509 if (cfg) |
| 510 { |
| 511 opus_fft_free_arch((kiss_fft_state *)cfg, arch); |
| 512 opus_free((opus_int16*)cfg->bitrev); |
| 513 if (cfg->shift < 0) |
| 514 opus_free((kiss_twiddle_cpx*)cfg->twiddles); |
| 515 opus_free((kiss_fft_state*)cfg); |
| 516 } |
| 517 } |
| 518 |
| 519 #endif /* CUSTOM_MODES */ |
| 520 |
| 521 void opus_fft_impl(const kiss_fft_state *st,kiss_fft_cpx *fout) |
| 522 { |
| 523 int m2, m; |
| 524 int p; |
| 525 int L; |
| 526 int fstride[MAXFACTORS]; |
| 527 int i; |
| 528 int shift; |
| 529 |
| 530 /* st->shift can be -1 */ |
| 531 shift = st->shift>0 ? st->shift : 0; |
| 532 |
| 533 fstride[0] = 1; |
| 534 L=0; |
| 535 do { |
| 536 p = st->factors[2*L]; |
| 537 m = st->factors[2*L+1]; |
| 538 fstride[L+1] = fstride[L]*p; |
| 539 L++; |
| 540 } while(m!=1); |
| 541 m = st->factors[2*L-1]; |
| 542 for (i=L-1;i>=0;i--) |
| 543 { |
| 544 if (i!=0) |
| 545 m2 = st->factors[2*i-1]; |
| 546 else |
| 547 m2 = 1; |
| 548 switch (st->factors[2*i]) |
| 549 { |
| 550 case 2: |
| 551 kf_bfly2(fout, m, fstride[i]); |
| 552 break; |
| 553 case 4: |
| 554 kf_bfly4(fout,fstride[i]<<shift,st,m, fstride[i], m2); |
| 555 break; |
| 556 #ifndef RADIX_TWO_ONLY |
| 557 case 3: |
| 558 kf_bfly3(fout,fstride[i]<<shift,st,m, fstride[i], m2); |
| 559 break; |
| 560 case 5: |
| 561 kf_bfly5(fout,fstride[i]<<shift,st,m, fstride[i], m2); |
| 562 break; |
| 563 #endif |
| 564 } |
| 565 m = m2; |
| 566 } |
| 567 } |
| 568 |
| 569 void opus_fft_c(const kiss_fft_state *st,const kiss_fft_cpx *fin,kiss_fft_cpx *f
out) |
| 570 { |
| 571 int i; |
| 572 opus_val16 scale; |
| 573 #ifdef FIXED_POINT |
| 574 /* Allows us to scale with MULT16_32_Q16(), which is faster than |
| 575 MULT16_32_Q15() on ARM. */ |
| 576 int scale_shift = st->scale_shift-1; |
| 577 #endif |
| 578 scale = st->scale; |
| 579 |
| 580 celt_assert2 (fin != fout, "In-place FFT not supported"); |
| 581 /* Bit-reverse the input */ |
| 582 for (i=0;i<st->nfft;i++) |
| 583 { |
| 584 kiss_fft_cpx x = fin[i]; |
| 585 fout[st->bitrev[i]].r = SHR32(MULT16_32_Q16(scale, x.r), scale_shift); |
| 586 fout[st->bitrev[i]].i = SHR32(MULT16_32_Q16(scale, x.i), scale_shift); |
| 587 } |
| 588 opus_fft_impl(st, fout); |
| 589 } |
| 590 |
| 591 |
| 592 void opus_ifft_c(const kiss_fft_state *st,const kiss_fft_cpx *fin,kiss_fft_cpx *
fout) |
| 593 { |
| 594 int i; |
| 595 celt_assert2 (fin != fout, "In-place FFT not supported"); |
| 596 /* Bit-reverse the input */ |
| 597 for (i=0;i<st->nfft;i++) |
| 598 fout[st->bitrev[i]] = fin[i]; |
| 599 for (i=0;i<st->nfft;i++) |
| 600 fout[i].i = -fout[i].i; |
| 601 opus_fft_impl(st, fout); |
| 602 for (i=0;i<st->nfft;i++) |
| 603 fout[i].i = -fout[i].i; |
| 604 } |
| OLD | NEW |