Home | History | Annotate | Download | only in celt
      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                      const size_t fstride,
     51                      const kiss_fft_state *st,
     52                      int m,
     53                      int N,
     54                      int mm
     55                     )
     56 {
     57    kiss_fft_cpx * Fout2;
     58    const kiss_twiddle_cpx * tw1;
     59    int i,j;
     60    kiss_fft_cpx * Fout_beg = Fout;
     61    for (i=0;i<N;i++)
     62    {
     63       Fout = Fout_beg + i*mm;
     64       Fout2 = Fout + m;
     65       tw1 = st->twiddles;
     66       for(j=0;j<m;j++)
     67       {
     68          kiss_fft_cpx t;
     69          Fout->r = SHR32(Fout->r, 1);Fout->i = SHR32(Fout->i, 1);
     70          Fout2->r = SHR32(Fout2->r, 1);Fout2->i = SHR32(Fout2->i, 1);
     71          C_MUL (t,  *Fout2 , *tw1);
     72          tw1 += fstride;
     73          C_SUB( *Fout2 ,  *Fout , t );
     74          C_ADDTO( *Fout ,  t );
     75          ++Fout2;
     76          ++Fout;
     77       }
     78    }
     79 }
     80 
     81 static void ki_bfly2(
     82                      kiss_fft_cpx * Fout,
     83                      const size_t fstride,
     84                      const kiss_fft_state *st,
     85                      int m,
     86                      int N,
     87                      int mm
     88                     )
     89 {
     90    kiss_fft_cpx * Fout2;
     91    const kiss_twiddle_cpx * tw1;
     92    kiss_fft_cpx t;
     93    int i,j;
     94    kiss_fft_cpx * Fout_beg = Fout;
     95    for (i=0;i<N;i++)
     96    {
     97       Fout = Fout_beg + i*mm;
     98       Fout2 = Fout + m;
     99       tw1 = st->twiddles;
    100       for(j=0;j<m;j++)
    101       {
    102          C_MULC (t,  *Fout2 , *tw1);
    103          tw1 += fstride;
    104          C_SUB( *Fout2 ,  *Fout , t );
    105          C_ADDTO( *Fout ,  t );
    106          ++Fout2;
    107          ++Fout;
    108       }
    109    }
    110 }
    111 
    112 static void kf_bfly4(
    113                      kiss_fft_cpx * Fout,
    114                      const size_t fstride,
    115                      const kiss_fft_state *st,
    116                      int m,
    117                      int N,
    118                      int mm
    119                     )
    120 {
    121    const kiss_twiddle_cpx *tw1,*tw2,*tw3;
    122    kiss_fft_cpx scratch[6];
    123    const size_t m2=2*m;
    124    const size_t m3=3*m;
    125    int i, j;
    126 
    127    kiss_fft_cpx * Fout_beg = Fout;
    128    for (i=0;i<N;i++)
    129    {
    130       Fout = Fout_beg + i*mm;
    131       tw3 = tw2 = tw1 = st->twiddles;
    132       for (j=0;j<m;j++)
    133       {
    134          C_MUL4(scratch[0],Fout[m] , *tw1 );
    135          C_MUL4(scratch[1],Fout[m2] , *tw2 );
    136          C_MUL4(scratch[2],Fout[m3] , *tw3 );
    137 
    138          Fout->r = PSHR32(Fout->r, 2);
    139          Fout->i = PSHR32(Fout->i, 2);
    140          C_SUB( scratch[5] , *Fout, scratch[1] );
    141          C_ADDTO(*Fout, scratch[1]);
    142          C_ADD( scratch[3] , scratch[0] , scratch[2] );
    143          C_SUB( scratch[4] , scratch[0] , scratch[2] );
    144          C_SUB( Fout[m2], *Fout, scratch[3] );
    145          tw1 += fstride;
    146          tw2 += fstride*2;
    147          tw3 += fstride*3;
    148          C_ADDTO( *Fout , scratch[3] );
    149 
    150          Fout[m].r = scratch[5].r + scratch[4].i;
    151          Fout[m].i = scratch[5].i - scratch[4].r;
    152          Fout[m3].r = scratch[5].r - scratch[4].i;
    153          Fout[m3].i = scratch[5].i + scratch[4].r;
    154          ++Fout;
    155       }
    156    }
    157 }
    158 
    159 static void ki_bfly4(
    160                      kiss_fft_cpx * Fout,
    161                      const size_t fstride,
    162                      const kiss_fft_state *st,
    163                      int m,
    164                      int N,
    165                      int mm
    166                     )
    167 {
    168    const kiss_twiddle_cpx *tw1,*tw2,*tw3;
    169    kiss_fft_cpx scratch[6];
    170    const size_t m2=2*m;
    171    const size_t m3=3*m;
    172    int i, j;
    173 
    174    kiss_fft_cpx * Fout_beg = Fout;
    175    for (i=0;i<N;i++)
    176    {
    177       Fout = Fout_beg + i*mm;
    178       tw3 = tw2 = tw1 = st->twiddles;
    179       for (j=0;j<m;j++)
    180       {
    181          C_MULC(scratch[0],Fout[m] , *tw1 );
    182          C_MULC(scratch[1],Fout[m2] , *tw2 );
    183          C_MULC(scratch[2],Fout[m3] , *tw3 );
    184 
    185          C_SUB( scratch[5] , *Fout, scratch[1] );
    186          C_ADDTO(*Fout, scratch[1]);
    187          C_ADD( scratch[3] , scratch[0] , scratch[2] );
    188          C_SUB( scratch[4] , scratch[0] , scratch[2] );
    189          C_SUB( Fout[m2], *Fout, scratch[3] );
    190          tw1 += fstride;
    191          tw2 += fstride*2;
    192          tw3 += fstride*3;
    193          C_ADDTO( *Fout , scratch[3] );
    194 
    195          Fout[m].r = scratch[5].r - scratch[4].i;
    196          Fout[m].i = scratch[5].i + scratch[4].r;
    197          Fout[m3].r = scratch[5].r + scratch[4].i;
    198          Fout[m3].i = scratch[5].i - scratch[4].r;
    199          ++Fout;
    200       }
    201    }
    202 }
    203 
    204 #ifndef RADIX_TWO_ONLY
    205 
    206 static void kf_bfly3(
    207                      kiss_fft_cpx * Fout,
    208                      const size_t fstride,
    209                      const kiss_fft_state *st,
    210                      int m,
    211                      int N,
    212                      int mm
    213                     )
    214 {
    215    int i;
    216    size_t k;
    217    const size_t m2 = 2*m;
    218    const kiss_twiddle_cpx *tw1,*tw2;
    219    kiss_fft_cpx scratch[5];
    220    kiss_twiddle_cpx epi3;
    221 
    222    kiss_fft_cpx * Fout_beg = Fout;
    223    epi3 = st->twiddles[fstride*m];
    224    for (i=0;i<N;i++)
    225    {
    226       Fout = Fout_beg + i*mm;
    227       tw1=tw2=st->twiddles;
    228       k=m;
    229       do {
    230          C_FIXDIV(*Fout,3); C_FIXDIV(Fout[m],3); C_FIXDIV(Fout[m2],3);
    231 
    232          C_MUL(scratch[1],Fout[m] , *tw1);
    233          C_MUL(scratch[2],Fout[m2] , *tw2);
    234 
    235          C_ADD(scratch[3],scratch[1],scratch[2]);
    236          C_SUB(scratch[0],scratch[1],scratch[2]);
    237          tw1 += fstride;
    238          tw2 += fstride*2;
    239 
    240          Fout[m].r = Fout->r - HALF_OF(scratch[3].r);
    241          Fout[m].i = Fout->i - HALF_OF(scratch[3].i);
    242 
    243          C_MULBYSCALAR( scratch[0] , epi3.i );
    244 
    245          C_ADDTO(*Fout,scratch[3]);
    246 
    247          Fout[m2].r = Fout[m].r + scratch[0].i;
    248          Fout[m2].i = Fout[m].i - scratch[0].r;
    249 
    250          Fout[m].r -= scratch[0].i;
    251          Fout[m].i += scratch[0].r;
    252 
    253          ++Fout;
    254       } while(--k);
    255    }
    256 }
    257 
    258 static void ki_bfly3(
    259                      kiss_fft_cpx * Fout,
    260                      const size_t fstride,
    261                      const kiss_fft_state *st,
    262                      int m,
    263                      int N,
    264                      int mm
    265                     )
    266 {
    267    int i, k;
    268    const size_t m2 = 2*m;
    269    const kiss_twiddle_cpx *tw1,*tw2;
    270    kiss_fft_cpx scratch[5];
    271    kiss_twiddle_cpx epi3;
    272 
    273    kiss_fft_cpx * Fout_beg = Fout;
    274    epi3 = st->twiddles[fstride*m];
    275    for (i=0;i<N;i++)
    276    {
    277       Fout = Fout_beg + i*mm;
    278       tw1=tw2=st->twiddles;
    279       k=m;
    280       do{
    281 
    282          C_MULC(scratch[1],Fout[m] , *tw1);
    283          C_MULC(scratch[2],Fout[m2] , *tw2);
    284 
    285          C_ADD(scratch[3],scratch[1],scratch[2]);
    286          C_SUB(scratch[0],scratch[1],scratch[2]);
    287          tw1 += fstride;
    288          tw2 += fstride*2;
    289 
    290          Fout[m].r = Fout->r - HALF_OF(scratch[3].r);
    291          Fout[m].i = Fout->i - HALF_OF(scratch[3].i);
    292 
    293          C_MULBYSCALAR( scratch[0] , -epi3.i );
    294 
    295          C_ADDTO(*Fout,scratch[3]);
    296 
    297          Fout[m2].r = Fout[m].r + scratch[0].i;
    298          Fout[m2].i = Fout[m].i - scratch[0].r;
    299 
    300          Fout[m].r -= scratch[0].i;
    301          Fout[m].i += scratch[0].r;
    302 
    303          ++Fout;
    304       }while(--k);
    305    }
    306 }
    307 
    308 static void kf_bfly5(
    309                      kiss_fft_cpx * Fout,
    310                      const size_t fstride,
    311                      const kiss_fft_state *st,
    312                      int m,
    313                      int N,
    314                      int mm
    315                     )
    316 {
    317    kiss_fft_cpx *Fout0,*Fout1,*Fout2,*Fout3,*Fout4;
    318    int i, u;
    319    kiss_fft_cpx scratch[13];
    320    const kiss_twiddle_cpx * twiddles = st->twiddles;
    321    const kiss_twiddle_cpx *tw;
    322    kiss_twiddle_cpx ya,yb;
    323    kiss_fft_cpx * Fout_beg = Fout;
    324 
    325    ya = twiddles[fstride*m];
    326    yb = twiddles[fstride*2*m];
    327    tw=st->twiddles;
    328 
    329    for (i=0;i<N;i++)
    330    {
    331       Fout = Fout_beg + i*mm;
    332       Fout0=Fout;
    333       Fout1=Fout0+m;
    334       Fout2=Fout0+2*m;
    335       Fout3=Fout0+3*m;
    336       Fout4=Fout0+4*m;
    337 
    338       for ( u=0; u<m; ++u ) {
    339          C_FIXDIV( *Fout0,5); C_FIXDIV( *Fout1,5); C_FIXDIV( *Fout2,5); C_FIXDIV( *Fout3,5); C_FIXDIV( *Fout4,5);
    340          scratch[0] = *Fout0;
    341 
    342          C_MUL(scratch[1] ,*Fout1, tw[u*fstride]);
    343          C_MUL(scratch[2] ,*Fout2, tw[2*u*fstride]);
    344          C_MUL(scratch[3] ,*Fout3, tw[3*u*fstride]);
    345          C_MUL(scratch[4] ,*Fout4, tw[4*u*fstride]);
    346 
    347          C_ADD( scratch[7],scratch[1],scratch[4]);
    348          C_SUB( scratch[10],scratch[1],scratch[4]);
    349          C_ADD( scratch[8],scratch[2],scratch[3]);
    350          C_SUB( scratch[9],scratch[2],scratch[3]);
    351 
    352          Fout0->r += scratch[7].r + scratch[8].r;
    353          Fout0->i += scratch[7].i + scratch[8].i;
    354 
    355          scratch[5].r = scratch[0].r + S_MUL(scratch[7].r,ya.r) + S_MUL(scratch[8].r,yb.r);
    356          scratch[5].i = scratch[0].i + S_MUL(scratch[7].i,ya.r) + S_MUL(scratch[8].i,yb.r);
    357 
    358          scratch[6].r =  S_MUL(scratch[10].i,ya.i) + S_MUL(scratch[9].i,yb.i);
    359          scratch[6].i = -S_MUL(scratch[10].r,ya.i) - S_MUL(scratch[9].r,yb.i);
    360 
    361          C_SUB(*Fout1,scratch[5],scratch[6]);
    362          C_ADD(*Fout4,scratch[5],scratch[6]);
    363 
    364          scratch[11].r = scratch[0].r + S_MUL(scratch[7].r,yb.r) + S_MUL(scratch[8].r,ya.r);
    365          scratch[11].i = scratch[0].i + S_MUL(scratch[7].i,yb.r) + S_MUL(scratch[8].i,ya.r);
    366          scratch[12].r = - S_MUL(scratch[10].i,yb.i) + S_MUL(scratch[9].i,ya.i);
    367          scratch[12].i = S_MUL(scratch[10].r,yb.i) - S_MUL(scratch[9].r,ya.i);
    368 
    369          C_ADD(*Fout2,scratch[11],scratch[12]);
    370          C_SUB(*Fout3,scratch[11],scratch[12]);
    371 
    372          ++Fout0;++Fout1;++Fout2;++Fout3;++Fout4;
    373       }
    374    }
    375 }
    376 
    377 static void ki_bfly5(
    378                      kiss_fft_cpx * Fout,
    379                      const size_t fstride,
    380                      const kiss_fft_state *st,
    381                      int m,
    382                      int N,
    383                      int mm
    384                     )
    385 {
    386    kiss_fft_cpx *Fout0,*Fout1,*Fout2,*Fout3,*Fout4;
    387    int i, u;
    388    kiss_fft_cpx scratch[13];
    389    const kiss_twiddle_cpx * twiddles = st->twiddles;
    390    const kiss_twiddle_cpx *tw;
    391    kiss_twiddle_cpx ya,yb;
    392    kiss_fft_cpx * Fout_beg = Fout;
    393 
    394    ya = twiddles[fstride*m];
    395    yb = twiddles[fstride*2*m];
    396    tw=st->twiddles;
    397 
    398    for (i=0;i<N;i++)
    399    {
    400       Fout = Fout_beg + i*mm;
    401       Fout0=Fout;
    402       Fout1=Fout0+m;
    403       Fout2=Fout0+2*m;
    404       Fout3=Fout0+3*m;
    405       Fout4=Fout0+4*m;
    406 
    407       for ( u=0; u<m; ++u ) {
    408          scratch[0] = *Fout0;
    409 
    410          C_MULC(scratch[1] ,*Fout1, tw[u*fstride]);
    411          C_MULC(scratch[2] ,*Fout2, tw[2*u*fstride]);
    412          C_MULC(scratch[3] ,*Fout3, tw[3*u*fstride]);
    413          C_MULC(scratch[4] ,*Fout4, tw[4*u*fstride]);
    414 
    415          C_ADD( scratch[7],scratch[1],scratch[4]);
    416          C_SUB( scratch[10],scratch[1],scratch[4]);
    417          C_ADD( scratch[8],scratch[2],scratch[3]);
    418          C_SUB( scratch[9],scratch[2],scratch[3]);
    419 
    420          Fout0->r += scratch[7].r + scratch[8].r;
    421          Fout0->i += scratch[7].i + scratch[8].i;
    422 
    423          scratch[5].r = scratch[0].r + S_MUL(scratch[7].r,ya.r) + S_MUL(scratch[8].r,yb.r);
    424          scratch[5].i = scratch[0].i + S_MUL(scratch[7].i,ya.r) + S_MUL(scratch[8].i,yb.r);
    425 
    426          scratch[6].r = -S_MUL(scratch[10].i,ya.i) - S_MUL(scratch[9].i,yb.i);
    427          scratch[6].i =  S_MUL(scratch[10].r,ya.i) + S_MUL(scratch[9].r,yb.i);
    428 
    429          C_SUB(*Fout1,scratch[5],scratch[6]);
    430          C_ADD(*Fout4,scratch[5],scratch[6]);
    431 
    432          scratch[11].r = scratch[0].r + S_MUL(scratch[7].r,yb.r) + S_MUL(scratch[8].r,ya.r);
    433          scratch[11].i = scratch[0].i + S_MUL(scratch[7].i,yb.r) + S_MUL(scratch[8].i,ya.r);
    434          scratch[12].r =  S_MUL(scratch[10].i,yb.i) - S_MUL(scratch[9].i,ya.i);
    435          scratch[12].i = -S_MUL(scratch[10].r,yb.i) + S_MUL(scratch[9].r,ya.i);
    436 
    437          C_ADD(*Fout2,scratch[11],scratch[12]);
    438          C_SUB(*Fout3,scratch[11],scratch[12]);
    439 
    440          ++Fout0;++Fout1;++Fout2;++Fout3;++Fout4;
    441       }
    442    }
    443 }
    444 
    445 #endif
    446 
    447 
    448 #ifdef CUSTOM_MODES
    449 
    450 static
    451 void compute_bitrev_table(
    452          int Fout,
    453          opus_int16 *f,
    454          const size_t fstride,
    455          int in_stride,
    456          opus_int16 * factors,
    457          const kiss_fft_state *st
    458             )
    459 {
    460    const int p=*factors++; /* the radix  */
    461    const int m=*factors++; /* stage's fft length/p */
    462 
    463     /*printf ("fft %d %d %d %d %d %d\n", p*m, m, p, s2, fstride*in_stride, N);*/
    464    if (m==1)
    465    {
    466       int j;
    467       for (j=0;j<p;j++)
    468       {
    469          *f = Fout+j;
    470          f += fstride*in_stride;
    471       }
    472    } else {
    473       int j;
    474       for (j=0;j<p;j++)
    475       {
    476          compute_bitrev_table( Fout , f, fstride*p, in_stride, factors,st);
    477          f += fstride*in_stride;
    478          Fout += m;
    479       }
    480    }
    481 }
    482 
    483 /*  facbuf is populated by p1,m1,p2,m2, ...
    484     where
    485     p[i] * m[i] = m[i-1]
    486     m0 = n                  */
    487 static
    488 int kf_factor(int n,opus_int16 * facbuf)
    489 {
    490     int p=4;
    491 
    492     /*factor out powers of 4, powers of 2, then any remaining primes */
    493     do {
    494         while (n % p) {
    495             switch (p) {
    496                 case 4: p = 2; break;
    497                 case 2: p = 3; break;
    498                 default: p += 2; break;
    499             }
    500             if (p>32000 || (opus_int32)p*(opus_int32)p > n)
    501                 p = n;          /* no more factors, skip to end */
    502         }
    503         n /= p;
    504 #ifdef RADIX_TWO_ONLY
    505         if (p!=2 && p != 4)
    506 #else
    507         if (p>5)
    508 #endif
    509         {
    510            return 0;
    511         }
    512         *facbuf++ = p;
    513         *facbuf++ = n;
    514     } while (n > 1);
    515     return 1;
    516 }
    517 
    518 static void compute_twiddles(kiss_twiddle_cpx *twiddles, int nfft)
    519 {
    520    int i;
    521 #ifdef FIXED_POINT
    522    for (i=0;i<nfft;++i) {
    523       opus_val32 phase = -i;
    524       kf_cexp2(twiddles+i, DIV32(SHL32(phase,17),nfft));
    525    }
    526 #else
    527    for (i=0;i<nfft;++i) {
    528       const double pi=3.14159265358979323846264338327;
    529       double phase = ( -2*pi /nfft ) * i;
    530       kf_cexp(twiddles+i, phase );
    531    }
    532 #endif
    533 }
    534 
    535 /*
    536  *
    537  * Allocates all necessary storage space for the fft and ifft.
    538  * The return value is a contiguous block of memory.  As such,
    539  * It can be freed with free().
    540  * */
    541 kiss_fft_state *opus_fft_alloc_twiddles(int nfft,void * mem,size_t * lenmem,  const kiss_fft_state *base)
    542 {
    543     kiss_fft_state *st=NULL;
    544     size_t memneeded = sizeof(struct kiss_fft_state); /* twiddle factors*/
    545 
    546     if ( lenmem==NULL ) {
    547         st = ( kiss_fft_state*)KISS_FFT_MALLOC( memneeded );
    548     }else{
    549         if (mem != NULL && *lenmem >= memneeded)
    550             st = (kiss_fft_state*)mem;
    551         *lenmem = memneeded;
    552     }
    553     if (st) {
    554         opus_int16 *bitrev;
    555         kiss_twiddle_cpx *twiddles;
    556 
    557         st->nfft=nfft;
    558 #ifndef FIXED_POINT
    559         st->scale = 1.f/nfft;
    560 #endif
    561         if (base != NULL)
    562         {
    563            st->twiddles = base->twiddles;
    564            st->shift = 0;
    565            while (nfft<<st->shift != base->nfft && st->shift < 32)
    566               st->shift++;
    567            if (st->shift>=32)
    568               goto fail;
    569         } else {
    570            st->twiddles = twiddles = (kiss_twiddle_cpx*)KISS_FFT_MALLOC(sizeof(kiss_twiddle_cpx)*nfft);
    571            compute_twiddles(twiddles, nfft);
    572            st->shift = -1;
    573         }
    574         if (!kf_factor(nfft,st->factors))
    575         {
    576            goto fail;
    577         }
    578 
    579         /* bitrev */
    580         st->bitrev = bitrev = (opus_int16*)KISS_FFT_MALLOC(sizeof(opus_int16)*nfft);
    581         if (st->bitrev==NULL)
    582             goto fail;
    583         compute_bitrev_table(0, bitrev, 1,1, st->factors,st);
    584     }
    585     return st;
    586 fail:
    587     opus_fft_free(st);
    588     return NULL;
    589 }
    590 
    591 kiss_fft_state *opus_fft_alloc(int nfft,void * mem,size_t * lenmem )
    592 {
    593    return opus_fft_alloc_twiddles(nfft, mem, lenmem, NULL);
    594 }
    595 
    596 void opus_fft_free(const kiss_fft_state *cfg)
    597 {
    598    if (cfg)
    599    {
    600       opus_free((opus_int16*)cfg->bitrev);
    601       if (cfg->shift < 0)
    602          opus_free((kiss_twiddle_cpx*)cfg->twiddles);
    603       opus_free((kiss_fft_state*)cfg);
    604    }
    605 }
    606 
    607 #endif /* CUSTOM_MODES */
    608 
    609 void opus_fft(const kiss_fft_state *st,const kiss_fft_cpx *fin,kiss_fft_cpx *fout)
    610 {
    611     int m2, m;
    612     int p;
    613     int L;
    614     int fstride[MAXFACTORS];
    615     int i;
    616     int shift;
    617 
    618     /* st->shift can be -1 */
    619     shift = st->shift>0 ? st->shift : 0;
    620 
    621     celt_assert2 (fin != fout, "In-place FFT not supported");
    622     /* Bit-reverse the input */
    623     for (i=0;i<st->nfft;i++)
    624     {
    625        fout[st->bitrev[i]] = fin[i];
    626 #ifndef FIXED_POINT
    627        fout[st->bitrev[i]].r *= st->scale;
    628        fout[st->bitrev[i]].i *= st->scale;
    629 #endif
    630     }
    631 
    632     fstride[0] = 1;
    633     L=0;
    634     do {
    635        p = st->factors[2*L];
    636        m = st->factors[2*L+1];
    637        fstride[L+1] = fstride[L]*p;
    638        L++;
    639     } while(m!=1);
    640     m = st->factors[2*L-1];
    641     for (i=L-1;i>=0;i--)
    642     {
    643        if (i!=0)
    644           m2 = st->factors[2*i-1];
    645        else
    646           m2 = 1;
    647        switch (st->factors[2*i])
    648        {
    649        case 2:
    650           kf_bfly2(fout,fstride[i]<<shift,st,m, fstride[i], m2);
    651           break;
    652        case 4:
    653           kf_bfly4(fout,fstride[i]<<shift,st,m, fstride[i], m2);
    654           break;
    655  #ifndef RADIX_TWO_ONLY
    656        case 3:
    657           kf_bfly3(fout,fstride[i]<<shift,st,m, fstride[i], m2);
    658           break;
    659        case 5:
    660           kf_bfly5(fout,fstride[i]<<shift,st,m, fstride[i], m2);
    661           break;
    662  #endif
    663        }
    664        m = m2;
    665     }
    666 }
    667 
    668 void opus_ifft(const kiss_fft_state *st,const kiss_fft_cpx *fin,kiss_fft_cpx *fout)
    669 {
    670    int m2, m;
    671    int p;
    672    int L;
    673    int fstride[MAXFACTORS];
    674    int i;
    675    int shift;
    676 
    677    /* st->shift can be -1 */
    678    shift = st->shift>0 ? st->shift : 0;
    679    celt_assert2 (fin != fout, "In-place FFT not supported");
    680    /* Bit-reverse the input */
    681    for (i=0;i<st->nfft;i++)
    682       fout[st->bitrev[i]] = fin[i];
    683 
    684    fstride[0] = 1;
    685    L=0;
    686    do {
    687       p = st->factors[2*L];
    688       m = st->factors[2*L+1];
    689       fstride[L+1] = fstride[L]*p;
    690       L++;
    691    } while(m!=1);
    692    m = st->factors[2*L-1];
    693    for (i=L-1;i>=0;i--)
    694    {
    695       if (i!=0)
    696          m2 = st->factors[2*i-1];
    697       else
    698          m2 = 1;
    699       switch (st->factors[2*i])
    700       {
    701       case 2:
    702          ki_bfly2(fout,fstride[i]<<shift,st,m, fstride[i], m2);
    703          break;
    704       case 4:
    705          ki_bfly4(fout,fstride[i]<<shift,st,m, fstride[i], m2);
    706          break;
    707 #ifndef RADIX_TWO_ONLY
    708       case 3:
    709          ki_bfly3(fout,fstride[i]<<shift,st,m, fstride[i], m2);
    710          break;
    711       case 5:
    712          ki_bfly5(fout,fstride[i]<<shift,st,m, fstride[i], m2);
    713          break;
    714 #endif
    715       }
    716       m = m2;
    717    }
    718 }
    719 
    720