Disabling mdct and fft init code with static modes
[opus.git] / libcelt / kiss_fft.c
1 /*
2 Copyright (c) 2003-2004, Mark Borgerding
3 Lots of modifications by Jean-Marc Valin
4 Copyright (c) 2005-2007, Xiph.Org Foundation
5 Copyright (c) 2008,      Xiph.Org Foundation, CSIRO
6
7 All rights reserved.
8
9 Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
10
11     * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
12     * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
13     * Neither the author nor the names of any contributors may be used to endorse or promote products derived from this software without specific prior written permission.
14
15 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
16 */
17
18 #ifndef SKIP_CONFIG_H
19 #  ifdef HAVE_CONFIG_H
20 #    include "config.h"
21 #  endif
22 #endif
23
24 #include "_kiss_fft_guts.h"
25 #include "arch.h"
26 #include "os_support.h"
27 #include "mathops.h"
28 #include "stack_alloc.h"
29
30 /* The guts header contains all the multiplication and addition macros that are defined for
31    complex numbers.  It also delares the kf_ internal functions.
32 */
33
34 static void kf_bfly2(
35                      kiss_fft_cpx * Fout,
36                      const size_t fstride,
37                      const kiss_fft_state *st,
38                      int m,
39                      int N,
40                      int mm
41                     )
42 {
43    kiss_fft_cpx * Fout2;
44    const kiss_twiddle_cpx * tw1;
45    int i,j;
46    kiss_fft_cpx * Fout_beg = Fout;
47    for (i=0;i<N;i++)
48    {
49       Fout = Fout_beg + i*mm;
50       Fout2 = Fout + m;
51       tw1 = st->twiddles;
52       for(j=0;j<m;j++)
53       {
54          kiss_fft_cpx t;
55          Fout->r = SHR(Fout->r, 1);Fout->i = SHR(Fout->i, 1);
56          Fout2->r = SHR(Fout2->r, 1);Fout2->i = SHR(Fout2->i, 1);
57          C_MUL (t,  *Fout2 , *tw1);
58          tw1 += fstride;
59          C_SUB( *Fout2 ,  *Fout , t );
60          C_ADDTO( *Fout ,  t );
61          ++Fout2;
62          ++Fout;
63       }
64    }
65 }
66
67 static void ki_bfly2(
68                      kiss_fft_cpx * Fout,
69                      const size_t fstride,
70                      const kiss_fft_state *st,
71                      int m,
72                      int N,
73                      int mm
74                     )
75 {
76    kiss_fft_cpx * Fout2;
77    const kiss_twiddle_cpx * tw1;
78    kiss_fft_cpx t;
79    int i,j;
80    kiss_fft_cpx * Fout_beg = Fout;
81    for (i=0;i<N;i++)
82    {
83       Fout = Fout_beg + i*mm;
84       Fout2 = Fout + m;
85       tw1 = st->twiddles;
86       for(j=0;j<m;j++)
87       {
88          C_MULC (t,  *Fout2 , *tw1);
89          tw1 += fstride;
90          C_SUB( *Fout2 ,  *Fout , t );
91          C_ADDTO( *Fout ,  t );
92          ++Fout2;
93          ++Fout;
94       }
95    }
96 }
97
98 static void kf_bfly4(
99                      kiss_fft_cpx * Fout,
100                      const size_t fstride,
101                      const kiss_fft_state *st,
102                      int m,
103                      int N,
104                      int mm
105                     )
106 {
107    const kiss_twiddle_cpx *tw1,*tw2,*tw3;
108    kiss_fft_cpx scratch[6];
109    const size_t m2=2*m;
110    const size_t m3=3*m;
111    int i, j;
112
113    kiss_fft_cpx * Fout_beg = Fout;
114    for (i=0;i<N;i++)
115    {
116       Fout = Fout_beg + i*mm;
117       tw3 = tw2 = tw1 = st->twiddles;
118       for (j=0;j<m;j++)
119       {
120          C_MUL4(scratch[0],Fout[m] , *tw1 );
121          C_MUL4(scratch[1],Fout[m2] , *tw2 );
122          C_MUL4(scratch[2],Fout[m3] , *tw3 );
123              
124          Fout->r = PSHR(Fout->r, 2);
125          Fout->i = PSHR(Fout->i, 2);
126          C_SUB( scratch[5] , *Fout, scratch[1] );
127          C_ADDTO(*Fout, scratch[1]);
128          C_ADD( scratch[3] , scratch[0] , scratch[2] );
129          C_SUB( scratch[4] , scratch[0] , scratch[2] );
130          Fout[m2].r = PSHR(Fout[m2].r, 2);
131          Fout[m2].i = PSHR(Fout[m2].i, 2);
132          C_SUB( Fout[m2], *Fout, scratch[3] );
133          tw1 += fstride;
134          tw2 += fstride*2;
135          tw3 += fstride*3;
136          C_ADDTO( *Fout , scratch[3] );
137              
138          Fout[m].r = scratch[5].r + scratch[4].i;
139          Fout[m].i = scratch[5].i - scratch[4].r;
140          Fout[m3].r = scratch[5].r - scratch[4].i;
141          Fout[m3].i = scratch[5].i + scratch[4].r;
142          ++Fout;
143       }
144    }
145 }
146
147 static void ki_bfly4(
148                      kiss_fft_cpx * Fout,
149                      const size_t fstride,
150                      const kiss_fft_state *st,
151                      int m,
152                      int N,
153                      int mm
154                     )
155 {
156    const kiss_twiddle_cpx *tw1,*tw2,*tw3;
157    kiss_fft_cpx scratch[6];
158    const size_t m2=2*m;
159    const size_t m3=3*m;
160    int i, j;
161
162    kiss_fft_cpx * Fout_beg = Fout;
163    for (i=0;i<N;i++)
164    {
165       Fout = Fout_beg + i*mm;
166       tw3 = tw2 = tw1 = st->twiddles;
167       for (j=0;j<m;j++)
168       {
169          C_MULC(scratch[0],Fout[m] , *tw1 );
170          C_MULC(scratch[1],Fout[m2] , *tw2 );
171          C_MULC(scratch[2],Fout[m3] , *tw3 );
172              
173          C_SUB( scratch[5] , *Fout, scratch[1] );
174          C_ADDTO(*Fout, scratch[1]);
175          C_ADD( scratch[3] , scratch[0] , scratch[2] );
176          C_SUB( scratch[4] , scratch[0] , scratch[2] );
177          C_SUB( Fout[m2], *Fout, scratch[3] );
178          tw1 += fstride;
179          tw2 += fstride*2;
180          tw3 += fstride*3;
181          C_ADDTO( *Fout , scratch[3] );
182              
183          Fout[m].r = scratch[5].r - scratch[4].i;
184          Fout[m].i = scratch[5].i + scratch[4].r;
185          Fout[m3].r = scratch[5].r + scratch[4].i;
186          Fout[m3].i = scratch[5].i - scratch[4].r;
187          ++Fout;
188       }
189    }
190 }
191
192 #ifndef RADIX_TWO_ONLY
193
194 static void kf_bfly3(
195                      kiss_fft_cpx * Fout,
196                      const size_t fstride,
197                      const kiss_fft_state *st,
198                      int m,
199                      int N,
200                      int mm
201                     )
202 {
203    int i;
204    size_t k;
205    const size_t m2 = 2*m;
206    const kiss_twiddle_cpx *tw1,*tw2;
207    kiss_fft_cpx scratch[5];
208    kiss_twiddle_cpx epi3;
209
210    kiss_fft_cpx * Fout_beg = Fout;
211    epi3 = st->twiddles[fstride*m];
212    for (i=0;i<N;i++)
213    {
214       Fout = Fout_beg + i*mm;
215       tw1=tw2=st->twiddles;
216       k=m;
217       do {
218          C_FIXDIV(*Fout,3); C_FIXDIV(Fout[m],3); C_FIXDIV(Fout[m2],3);
219
220          C_MUL(scratch[1],Fout[m] , *tw1);
221          C_MUL(scratch[2],Fout[m2] , *tw2);
222
223          C_ADD(scratch[3],scratch[1],scratch[2]);
224          C_SUB(scratch[0],scratch[1],scratch[2]);
225          tw1 += fstride;
226          tw2 += fstride*2;
227
228          Fout[m].r = Fout->r - HALF_OF(scratch[3].r);
229          Fout[m].i = Fout->i - HALF_OF(scratch[3].i);
230
231          C_MULBYSCALAR( scratch[0] , epi3.i );
232
233          C_ADDTO(*Fout,scratch[3]);
234
235          Fout[m2].r = Fout[m].r + scratch[0].i;
236          Fout[m2].i = Fout[m].i - scratch[0].r;
237
238          Fout[m].r -= scratch[0].i;
239          Fout[m].i += scratch[0].r;
240
241          ++Fout;
242       } while(--k);
243    }
244 }
245
246 static void ki_bfly3(
247                      kiss_fft_cpx * Fout,
248                      const size_t fstride,
249                      const kiss_fft_state *st,
250                      size_t m,
251                      int N,
252                      int mm
253                     )
254 {
255    size_t i, k;
256    const size_t m2 = 2*m;
257    const kiss_twiddle_cpx *tw1,*tw2;
258    kiss_fft_cpx scratch[5];
259    kiss_twiddle_cpx epi3;
260
261    kiss_fft_cpx * Fout_beg = Fout;
262    epi3 = st->twiddles[fstride*m];
263    for (i=0;i<N;i++)
264    {
265       Fout = Fout_beg + i*mm;
266       tw1=tw2=st->twiddles;
267       k=m;
268       do{
269
270          C_MULC(scratch[1],Fout[m] , *tw1);
271          C_MULC(scratch[2],Fout[m2] , *tw2);
272
273          C_ADD(scratch[3],scratch[1],scratch[2]);
274          C_SUB(scratch[0],scratch[1],scratch[2]);
275          tw1 += fstride;
276          tw2 += fstride*2;
277
278          Fout[m].r = Fout->r - HALF_OF(scratch[3].r);
279          Fout[m].i = Fout->i - HALF_OF(scratch[3].i);
280
281          C_MULBYSCALAR( scratch[0] , -epi3.i );
282
283          C_ADDTO(*Fout,scratch[3]);
284
285          Fout[m2].r = Fout[m].r + scratch[0].i;
286          Fout[m2].i = Fout[m].i - scratch[0].r;
287
288          Fout[m].r -= scratch[0].i;
289          Fout[m].i += scratch[0].r;
290
291          ++Fout;
292       }while(--k);
293    }
294 }
295
296
297 static void kf_bfly5(
298                      kiss_fft_cpx * Fout,
299                      const size_t fstride,
300                      const kiss_fft_state *st,
301                      int m,
302                      int N,
303                      int mm
304                     )
305 {
306    kiss_fft_cpx *Fout0,*Fout1,*Fout2,*Fout3,*Fout4;
307    int i, u;
308    kiss_fft_cpx scratch[13];
309    const kiss_twiddle_cpx * twiddles = st->twiddles;
310    const kiss_twiddle_cpx *tw;
311    kiss_twiddle_cpx ya,yb;
312    kiss_fft_cpx * Fout_beg = Fout;
313
314    ya = twiddles[fstride*m];
315    yb = twiddles[fstride*2*m];
316    tw=st->twiddles;
317
318    for (i=0;i<N;i++)
319    {
320       Fout = Fout_beg + i*mm;
321       Fout0=Fout;
322       Fout1=Fout0+m;
323       Fout2=Fout0+2*m;
324       Fout3=Fout0+3*m;
325       Fout4=Fout0+4*m;
326
327       for ( u=0; u<m; ++u ) {
328          C_FIXDIV( *Fout0,5); C_FIXDIV( *Fout1,5); C_FIXDIV( *Fout2,5); C_FIXDIV( *Fout3,5); C_FIXDIV( *Fout4,5);
329          scratch[0] = *Fout0;
330
331          C_MUL(scratch[1] ,*Fout1, tw[u*fstride]);
332          C_MUL(scratch[2] ,*Fout2, tw[2*u*fstride]);
333          C_MUL(scratch[3] ,*Fout3, tw[3*u*fstride]);
334          C_MUL(scratch[4] ,*Fout4, tw[4*u*fstride]);
335
336          C_ADD( scratch[7],scratch[1],scratch[4]);
337          C_SUB( scratch[10],scratch[1],scratch[4]);
338          C_ADD( scratch[8],scratch[2],scratch[3]);
339          C_SUB( scratch[9],scratch[2],scratch[3]);
340
341          Fout0->r += scratch[7].r + scratch[8].r;
342          Fout0->i += scratch[7].i + scratch[8].i;
343
344          scratch[5].r = scratch[0].r + S_MUL(scratch[7].r,ya.r) + S_MUL(scratch[8].r,yb.r);
345          scratch[5].i = scratch[0].i + S_MUL(scratch[7].i,ya.r) + S_MUL(scratch[8].i,yb.r);
346
347          scratch[6].r =  S_MUL(scratch[10].i,ya.i) + S_MUL(scratch[9].i,yb.i);
348          scratch[6].i = -S_MUL(scratch[10].r,ya.i) - S_MUL(scratch[9].r,yb.i);
349
350          C_SUB(*Fout1,scratch[5],scratch[6]);
351          C_ADD(*Fout4,scratch[5],scratch[6]);
352
353          scratch[11].r = scratch[0].r + S_MUL(scratch[7].r,yb.r) + S_MUL(scratch[8].r,ya.r);
354          scratch[11].i = scratch[0].i + S_MUL(scratch[7].i,yb.r) + S_MUL(scratch[8].i,ya.r);
355          scratch[12].r = - S_MUL(scratch[10].i,yb.i) + S_MUL(scratch[9].i,ya.i);
356          scratch[12].i = S_MUL(scratch[10].r,yb.i) - S_MUL(scratch[9].r,ya.i);
357
358          C_ADD(*Fout2,scratch[11],scratch[12]);
359          C_SUB(*Fout3,scratch[11],scratch[12]);
360
361          ++Fout0;++Fout1;++Fout2;++Fout3;++Fout4;
362       }
363    }
364 }
365
366 static void ki_bfly5(
367                      kiss_fft_cpx * Fout,
368                      const size_t fstride,
369                      const kiss_fft_state *st,
370                      int m,
371                      int N,
372                      int mm
373                     )
374 {
375    kiss_fft_cpx *Fout0,*Fout1,*Fout2,*Fout3,*Fout4;
376    int i, u;
377    kiss_fft_cpx scratch[13];
378    const kiss_twiddle_cpx * twiddles = st->twiddles;
379    const kiss_twiddle_cpx *tw;
380    kiss_twiddle_cpx ya,yb;
381    kiss_fft_cpx * Fout_beg = Fout;
382
383    ya = twiddles[fstride*m];
384    yb = twiddles[fstride*2*m];
385    tw=st->twiddles;
386
387    for (i=0;i<N;i++)
388    {
389       Fout = Fout_beg + i*mm;
390       Fout0=Fout;
391       Fout1=Fout0+m;
392       Fout2=Fout0+2*m;
393       Fout3=Fout0+3*m;
394       Fout4=Fout0+4*m;
395
396       for ( u=0; u<m; ++u ) {
397          scratch[0] = *Fout0;
398
399          C_MULC(scratch[1] ,*Fout1, tw[u*fstride]);
400          C_MULC(scratch[2] ,*Fout2, tw[2*u*fstride]);
401          C_MULC(scratch[3] ,*Fout3, tw[3*u*fstride]);
402          C_MULC(scratch[4] ,*Fout4, tw[4*u*fstride]);
403
404          C_ADD( scratch[7],scratch[1],scratch[4]);
405          C_SUB( scratch[10],scratch[1],scratch[4]);
406          C_ADD( scratch[8],scratch[2],scratch[3]);
407          C_SUB( scratch[9],scratch[2],scratch[3]);
408
409          Fout0->r += scratch[7].r + scratch[8].r;
410          Fout0->i += scratch[7].i + scratch[8].i;
411
412          scratch[5].r = scratch[0].r + S_MUL(scratch[7].r,ya.r) + S_MUL(scratch[8].r,yb.r);
413          scratch[5].i = scratch[0].i + S_MUL(scratch[7].i,ya.r) + S_MUL(scratch[8].i,yb.r);
414
415          scratch[6].r = -S_MUL(scratch[10].i,ya.i) - S_MUL(scratch[9].i,yb.i);
416          scratch[6].i =  S_MUL(scratch[10].r,ya.i) + S_MUL(scratch[9].r,yb.i);
417
418          C_SUB(*Fout1,scratch[5],scratch[6]);
419          C_ADD(*Fout4,scratch[5],scratch[6]);
420
421          scratch[11].r = scratch[0].r + S_MUL(scratch[7].r,yb.r) + S_MUL(scratch[8].r,ya.r);
422          scratch[11].i = scratch[0].i + S_MUL(scratch[7].i,yb.r) + S_MUL(scratch[8].i,ya.r);
423          scratch[12].r =  S_MUL(scratch[10].i,yb.i) - S_MUL(scratch[9].i,ya.i);
424          scratch[12].i = -S_MUL(scratch[10].r,yb.i) + S_MUL(scratch[9].r,ya.i);
425
426          C_ADD(*Fout2,scratch[11],scratch[12]);
427          C_SUB(*Fout3,scratch[11],scratch[12]);
428
429          ++Fout0;++Fout1;++Fout2;++Fout3;++Fout4;
430       }
431    }
432 }
433
434 #endif
435
436 static void kf_work(
437         kiss_fft_cpx * Fout,
438         const kiss_fft_cpx * f,
439         size_t fstride,
440         int in_stride,
441         const celt_int16 * factors,
442         const kiss_fft_state *st,
443         int N,
444         int s2,
445         int m2
446         )
447 {
448     const int p=*factors++; /* the radix  */
449     const int m=*factors++; /* stage's fft length/p */
450     /*printf ("fft %d %d %d %d %d %d %d\n", p*m, m, p, s2, fstride*in_stride, N, m2);*/
451     if (m!=1) 
452         kf_work( Fout , f, fstride*p, in_stride, factors,st, N*p, fstride*in_stride, m);
453
454     /* Compensate for longer twiddles table (when sharing) */
455     if (st->shift>0)
456        fstride <<= st->shift;
457     switch (p) {
458         case 2: kf_bfly2(Fout,fstride,st,m, N, m2); break;
459         case 4: kf_bfly4(Fout,fstride,st,m, N, m2); break;
460 #ifndef RADIX_TWO_ONLY
461         case 3: kf_bfly3(Fout,fstride,st,m, N, m2); break;
462         case 5: kf_bfly5(Fout,fstride,st,m, N, m2); break;
463 #else
464        default: celt_fatal("kiss_fft: only powers of two enabled");
465 #endif
466     }    
467 }
468
469
470 static void ki_work(
471              kiss_fft_cpx * Fout,
472              const kiss_fft_cpx * f,
473              size_t fstride,
474              int in_stride,
475              const celt_int16 * factors,
476              const kiss_fft_state *st,
477              int N,
478              int s2,
479              int m2
480             )
481 {
482    const int p=*factors++; /* the radix  */
483    const int m=*factors++; /* stage's fft length/p */
484    /*printf ("fft %d %d %d %d %d %d %d\n", p*m, m, p, s2, fstride*in_stride, N, m2);*/
485    if (m!=1) 
486       ki_work( Fout , f, fstride*p, in_stride, factors,st, N*p, fstride*in_stride, m);
487
488    /* Compensate for longer twiddles table (when sharing) */
489    if (st->shift>0)
490       fstride <<= st->shift;
491    switch (p) {
492       case 2: ki_bfly2(Fout,fstride,st,m, N, m2); break;
493       case 4: ki_bfly4(Fout,fstride,st,m, N, m2); break;
494 #ifndef RADIX_TWO_ONLY
495       case 3: ki_bfly3(Fout,fstride,st,m, N, m2); break;
496       case 5: ki_bfly5(Fout,fstride,st,m, N, m2); break;
497 #else
498       default: celt_fatal("kiss_fft: only powers of two enabled");
499 #endif
500    }    
501 }
502
503
504 #ifndef STATIC_MODES
505
506 static
507 void compute_bitrev_table(
508          int Fout,
509          celt_int16 *f,
510          const size_t fstride,
511          int in_stride,
512          celt_int16 * factors,
513          const kiss_fft_state *st
514             )
515 {
516    const int p=*factors++; /* the radix  */
517    const int m=*factors++; /* stage's fft length/p */
518
519     /*printf ("fft %d %d %d %d %d %d\n", p*m, m, p, s2, fstride*in_stride, N);*/
520    if (m==1)
521    {
522       int j;
523       for (j=0;j<p;j++)
524       {
525          *f = Fout+j;
526          f += fstride*in_stride;
527       }
528    } else {
529       int j;
530       for (j=0;j<p;j++)
531       {
532          compute_bitrev_table( Fout , f, fstride*p, in_stride, factors,st);
533          f += fstride*in_stride;
534          Fout += m;
535       }
536    }
537 }
538
539
540 /*  facbuf is populated by p1,m1,p2,m2, ...
541     where 
542     p[i] * m[i] = m[i-1]
543     m0 = n                  */
544 static 
545 int kf_factor(int n,celt_int16 * facbuf)
546 {
547     int p=4;
548
549     /*factor out powers of 4, powers of 2, then any remaining primes */
550     do {
551         while (n % p) {
552             switch (p) {
553                 case 4: p = 2; break;
554                 case 2: p = 3; break;
555                 default: p += 2; break;
556             }
557             if (p>32000 || (celt_int32)p*(celt_int32)p > n)
558                 p = n;          /* no more factors, skip to end */
559         }
560         n /= p;
561         if (p>5)
562         {
563            celt_warning("Only powers of 2, 3 and 5 are supported");
564            return 0;
565         }
566         *facbuf++ = p;
567         *facbuf++ = n;
568     } while (n > 1);
569     return 1;
570 }
571
572 static void compute_twiddles(kiss_twiddle_cpx *twiddles, int nfft)
573 {
574    int i;
575 #ifdef FIXED_POINT
576    for (i=0;i<nfft;++i) {
577       celt_word32 phase = -i;
578       kf_cexp2(twiddles+i, DIV32(SHL32(phase,17),nfft));
579    }
580 #else
581    for (i=0;i<nfft;++i) {
582       const double pi=3.14159265358979323846264338327;
583       double phase = ( -2*pi /nfft ) * i;
584       kf_cexp(twiddles+i, phase );
585    }
586 #endif
587 }
588
589
590 /*
591  *
592  * User-callable function to allocate all necessary storage space for the fft.
593  *
594  * The return value is a contiguous block of memory, allocated with malloc.  As such,
595  * It can be freed with free(), rather than a kiss_fft-specific function.
596  * */
597 kiss_fft_state *kiss_fft_alloc_twiddles(int nfft,void * mem,size_t * lenmem,  const kiss_fft_state *base)
598 {
599     kiss_fft_state *st=NULL;
600     size_t memneeded = sizeof(struct kiss_fft_state); /* twiddle factors*/
601
602     if ( lenmem==NULL ) {
603         st = ( kiss_fft_state*)KISS_FFT_MALLOC( memneeded );
604     }else{
605         if (mem != NULL && *lenmem >= memneeded)
606             st = (kiss_fft_state*)mem;
607         *lenmem = memneeded;
608     }
609     if (st) {
610         celt_int16 *bitrev;
611         kiss_twiddle_cpx *twiddles;
612
613         st->nfft=nfft;
614 #ifndef FIXED_POINT
615         st->scale = 1./nfft;
616 #endif
617         if (base != NULL)
618         {
619            st->twiddles = base->twiddles;
620            st->shift = 0;
621            while (nfft<<st->shift != base->nfft && st->shift < 32)
622               st->shift++;
623            /* FIXME: Report error and do proper cleanup */
624            if (st->shift>=32)
625               return NULL;
626         } else {
627            st->twiddles = twiddles = (kiss_twiddle_cpx*)KISS_FFT_MALLOC(sizeof(kiss_twiddle_cpx)*nfft);
628            compute_twiddles(twiddles, nfft);
629            st->shift = -1;
630         }
631         if (!kf_factor(nfft,st->factors))
632         {
633            kiss_fft_free(st);
634            return NULL;
635         }
636
637         /* bitrev */
638         st->bitrev = bitrev = (celt_int16*)KISS_FFT_MALLOC(sizeof(celt_int16)*nfft);
639         compute_bitrev_table(0, bitrev, 1,1, st->factors,st);
640     }
641     return st;
642 }
643
644 kiss_fft_state *kiss_fft_alloc(int nfft,void * mem,size_t * lenmem )
645 {
646    return kiss_fft_alloc_twiddles(nfft, mem, lenmem, NULL);
647 }
648
649 void kiss_fft_free(const kiss_fft_state *cfg)
650 {
651    celt_free((celt_int16*)cfg->bitrev);
652    if (cfg->shift < 0)
653       celt_free((kiss_twiddle_cpx*)cfg->twiddles);
654    celt_free((kiss_fft_state*)cfg);
655 }
656
657 #endif /* STATIC_MODES */
658
659 static void kiss_fft_stride(const kiss_fft_state *st,const kiss_fft_cpx *fin,kiss_fft_cpx *fout,int in_stride)
660 {
661     if (fin == fout) 
662     {
663        celt_fatal("In-place FFT not supported");
664     } else {
665        /* Bit-reverse the input */
666        int i;
667        for (i=0;i<st->nfft;i++)
668        {
669           fout[st->bitrev[i]] = fin[i];
670 #ifndef FIXED_POINT
671           fout[st->bitrev[i]].r *= st->scale;
672           fout[st->bitrev[i]].i *= st->scale;
673 #endif
674        }
675        kf_work( fout, fin, 1,in_stride, st->factors,st, 1, in_stride, 1);
676     }
677 }
678
679 void kiss_fft(const kiss_fft_state *cfg,const kiss_fft_cpx *fin,kiss_fft_cpx *fout)
680 {
681     kiss_fft_stride(cfg,fin,fout,1);
682 }
683
684 static void kiss_ifft_stride(const kiss_fft_state *st,const kiss_fft_cpx *fin,kiss_fft_cpx *fout,int in_stride)
685 {
686    if (fin == fout) 
687    {
688       celt_fatal("In-place FFT not supported");
689    } else {
690       /* Bit-reverse the input */
691       int i;
692       for (i=0;i<st->nfft;i++)
693          fout[st->bitrev[i]] = fin[i];
694       ki_work( fout, fin, 1,in_stride, st->factors,st, 1, in_stride, 1);
695    }
696 }
697
698 void kiss_ifft(const kiss_fft_state *cfg,const kiss_fft_cpx *fin,kiss_fft_cpx *fout)
699 {
700    kiss_ifft_stride(cfg,fin,fout,1);
701 }
702