Using high-band noise less aggressively
[opus.git] / libcelt / kiss_fft.c
index 82f918a..138bb4f 100644 (file)
@@ -34,14 +34,14 @@ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
 static void kf_bfly2(
                      kiss_fft_cpx * Fout,
                      const size_t fstride,
-                     const kiss_fft_cfg st,
+                     const kiss_fft_state *st,
                      int m,
                      int N,
                      int mm
                     )
 {
    kiss_fft_cpx * Fout2;
-   kiss_twiddle_cpx * tw1;
+   const kiss_twiddle_cpx * tw1;
    int i,j;
    kiss_fft_cpx * Fout_beg = Fout;
    for (i=0;i<N;i++)
@@ -67,14 +67,14 @@ static void kf_bfly2(
 static void ki_bfly2(
                      kiss_fft_cpx * Fout,
                      const size_t fstride,
-                     const kiss_fft_cfg st,
+                     const kiss_fft_state *st,
                      int m,
                      int N,
                      int mm
                     )
 {
    kiss_fft_cpx * Fout2;
-   kiss_twiddle_cpx * tw1;
+   const kiss_twiddle_cpx * tw1;
    kiss_fft_cpx t;
    int i,j;
    kiss_fft_cpx * Fout_beg = Fout;
@@ -98,13 +98,13 @@ static void ki_bfly2(
 static void kf_bfly4(
                      kiss_fft_cpx * Fout,
                      const size_t fstride,
-                     const kiss_fft_cfg st,
+                     const kiss_fft_state *st,
                      int m,
                      int N,
                      int mm
                     )
 {
-   kiss_twiddle_cpx *tw1,*tw2,*tw3;
+   const kiss_twiddle_cpx *tw1,*tw2,*tw3;
    kiss_fft_cpx scratch[6];
    const size_t m2=2*m;
    const size_t m3=3*m;
@@ -147,13 +147,13 @@ static void kf_bfly4(
 static void ki_bfly4(
                      kiss_fft_cpx * Fout,
                      const size_t fstride,
-                     const kiss_fft_cfg st,
+                     const kiss_fft_state *st,
                      int m,
                      int N,
                      int mm
                     )
 {
-   kiss_twiddle_cpx *tw1,*tw2,*tw3;
+   const kiss_twiddle_cpx *tw1,*tw2,*tw3;
    kiss_fft_cpx scratch[6];
    const size_t m2=2*m;
    const size_t m3=3*m;
@@ -194,7 +194,7 @@ static void ki_bfly4(
 static void kf_bfly3(
                      kiss_fft_cpx * Fout,
                      const size_t fstride,
-                     const kiss_fft_cfg st,
+                     const kiss_fft_state *st,
                      int m,
                      int N,
                      int mm
@@ -203,7 +203,7 @@ static void kf_bfly3(
    int i;
    size_t k;
    const size_t m2 = 2*m;
-   kiss_twiddle_cpx *tw1,*tw2;
+   const kiss_twiddle_cpx *tw1,*tw2;
    kiss_fft_cpx scratch[5];
    kiss_twiddle_cpx epi3;
 
@@ -246,7 +246,7 @@ static void kf_bfly3(
 static void ki_bfly3(
                      kiss_fft_cpx * Fout,
                      const size_t fstride,
-                     const kiss_fft_cfg st,
+                     const kiss_fft_state *st,
                      size_t m,
                      int N,
                      int mm
@@ -254,7 +254,7 @@ static void ki_bfly3(
 {
    size_t i, k;
    const size_t m2 = 2*m;
-   kiss_twiddle_cpx *tw1,*tw2;
+   const kiss_twiddle_cpx *tw1,*tw2;
    kiss_fft_cpx scratch[5];
    kiss_twiddle_cpx epi3;
 
@@ -297,7 +297,7 @@ static void ki_bfly3(
 static void kf_bfly5(
                      kiss_fft_cpx * Fout,
                      const size_t fstride,
-                     const kiss_fft_cfg st,
+                     const kiss_fft_state *st,
                      int m,
                      int N,
                      int mm
@@ -306,8 +306,8 @@ static void kf_bfly5(
    kiss_fft_cpx *Fout0,*Fout1,*Fout2,*Fout3,*Fout4;
    int i, u;
    kiss_fft_cpx scratch[13];
-   kiss_twiddle_cpx * twiddles = st->twiddles;
-   kiss_twiddle_cpx *tw;
+   const kiss_twiddle_cpx * twiddles = st->twiddles;
+   const kiss_twiddle_cpx *tw;
    kiss_twiddle_cpx ya,yb;
    kiss_fft_cpx * Fout_beg = Fout;
 
@@ -366,7 +366,7 @@ static void kf_bfly5(
 static void ki_bfly5(
                      kiss_fft_cpx * Fout,
                      const size_t fstride,
-                     const kiss_fft_cfg st,
+                     const kiss_fft_state *st,
                      int m,
                      int N,
                      int mm
@@ -375,8 +375,8 @@ static void ki_bfly5(
    kiss_fft_cpx *Fout0,*Fout1,*Fout2,*Fout3,*Fout4;
    int i, u;
    kiss_fft_cpx scratch[13];
-   kiss_twiddle_cpx * twiddles = st->twiddles;
-   kiss_twiddle_cpx *tw;
+   const kiss_twiddle_cpx * twiddles = st->twiddles;
+   const kiss_twiddle_cpx *tw;
    kiss_twiddle_cpx ya,yb;
    kiss_fft_cpx * Fout_beg = Fout;
 
@@ -433,47 +433,13 @@ static void ki_bfly5(
 
 #endif
 
-static
-void compute_bitrev_table(
-         int Fout,
-         celt_int16 *f,
-         const size_t fstride,
-         int in_stride,
-         int * factors,
-         const kiss_fft_cfg st
-            )
-{
-   const int p=*factors++; /* the radix  */
-   const int m=*factors++; /* stage's fft length/p */
-   
-    /*printf ("fft %d %d %d %d %d %d\n", p*m, m, p, s2, fstride*in_stride, N);*/
-   if (m==1)
-   {
-      int j;
-      for (j=0;j<p;j++)
-      {
-         *f = Fout+j;
-         f += fstride*in_stride;
-      }
-   } else {
-      int j;
-      for (j=0;j<p;j++)
-      {
-         compute_bitrev_table( Fout , f, fstride*p, in_stride, factors,st);
-         f += fstride*in_stride;
-         Fout += m;
-      }
-   }
-}
-
-
 static void kf_work(
         kiss_fft_cpx * Fout,
         const kiss_fft_cpx * f,
         size_t fstride,
         int in_stride,
-        int * factors,
-        const kiss_fft_cfg st,
+        const celt_int16 * factors,
+        const kiss_fft_state *st,
         int N,
         int s2,
         int m2
@@ -494,8 +460,6 @@ static void kf_work(
 #ifndef RADIX_TWO_ONLY
         case 3: kf_bfly3(Fout,fstride,st,m, N, m2); break;
         case 5: kf_bfly5(Fout,fstride,st,m, N, m2); break;
-#else
-       default: celt_fatal("kiss_fft: only powers of two enabled");
 #endif
     }    
 }
@@ -506,8 +470,8 @@ static void ki_work(
              const kiss_fft_cpx * f,
              size_t fstride,
              int in_stride,
-             int * factors,
-             const kiss_fft_cfg st,
+             const celt_int16 * factors,
+             const kiss_fft_state *st,
              int N,
              int s2,
              int m2
@@ -528,18 +492,53 @@ static void ki_work(
 #ifndef RADIX_TWO_ONLY
       case 3: ki_bfly3(Fout,fstride,st,m, N, m2); break;
       case 5: ki_bfly5(Fout,fstride,st,m, N, m2); break;
-#else
-      default: celt_fatal("kiss_fft: only powers of two enabled");
 #endif
    }    
 }
 
+
+#ifndef STATIC_MODES
+
+static
+void compute_bitrev_table(
+         int Fout,
+         celt_int16 *f,
+         const size_t fstride,
+         int in_stride,
+         celt_int16 * factors,
+         const kiss_fft_state *st
+            )
+{
+   const int p=*factors++; /* the radix  */
+   const int m=*factors++; /* stage's fft length/p */
+
+    /*printf ("fft %d %d %d %d %d %d\n", p*m, m, p, s2, fstride*in_stride, N);*/
+   if (m==1)
+   {
+      int j;
+      for (j=0;j<p;j++)
+      {
+         *f = Fout+j;
+         f += fstride*in_stride;
+      }
+   } else {
+      int j;
+      for (j=0;j<p;j++)
+      {
+         compute_bitrev_table( Fout , f, fstride*p, in_stride, factors,st);
+         f += fstride*in_stride;
+         Fout += m;
+      }
+   }
+}
+
+
 /*  facbuf is populated by p1,m1,p2,m2, ...
     where 
     p[i] * m[i] = m[i-1]
     m0 = n                  */
 static 
-int kf_factor(int n,int * facbuf)
+int kf_factor(int n,celt_int16 * facbuf)
 {
     int p=4;
 
@@ -555,9 +554,12 @@ int kf_factor(int n,int * facbuf)
                 p = n;          /* no more factors, skip to end */
         }
         n /= p;
+#ifdef RADIX_TWO_ONLY
+        if (p!=2 && p != 4)
+#else
         if (p>5)
+#endif
         {
-           celt_warning("Only powers of 2, 3 and 5 are supported");
            return 0;
         }
         *facbuf++ = p;
@@ -569,7 +571,7 @@ int kf_factor(int n,int * facbuf)
 static void compute_twiddles(kiss_twiddle_cpx *twiddles, int nfft)
 {
    int i;
-#if defined(FIXED_POINT) && (!defined(DOUBLE_PRECISION) || defined(MIXED_PRECISION))
+#ifdef FIXED_POINT
    for (i=0;i<nfft;++i) {
       celt_word32 phase = -i;
       kf_cexp2(twiddles+i, DIV32(SHL32(phase,17),nfft));
@@ -591,19 +593,22 @@ static void compute_twiddles(kiss_twiddle_cpx *twiddles, int nfft)
  * The return value is a contiguous block of memory, allocated with malloc.  As such,
  * It can be freed with free(), rather than a kiss_fft-specific function.
  * */
-kiss_fft_cfg kiss_fft_alloc_twiddles(int nfft,void * mem,size_t * lenmem,  kiss_fft_cfg base)
+kiss_fft_state *kiss_fft_alloc_twiddles(int nfft,void * mem,size_t * lenmem,  const kiss_fft_state *base)
 {
-    kiss_fft_cfg st=NULL;
+    kiss_fft_state *st=NULL;
     size_t memneeded = sizeof(struct kiss_fft_state); /* twiddle factors*/
 
     if ( lenmem==NULL ) {
-        st = ( kiss_fft_cfg)KISS_FFT_MALLOC( memneeded );
+        st = ( kiss_fft_state*)KISS_FFT_MALLOC( memneeded );
     }else{
         if (mem != NULL && *lenmem >= memneeded)
-            st = (kiss_fft_cfg)mem;
+            st = (kiss_fft_state*)mem;
         *lenmem = memneeded;
     }
     if (st) {
+        celt_int16 *bitrev;
+        kiss_twiddle_cpx *twiddles;
+
         st->nfft=nfft;
 #ifndef FIXED_POINT
         st->scale = 1./nfft;
@@ -618,8 +623,8 @@ kiss_fft_cfg kiss_fft_alloc_twiddles(int nfft,void * mem,size_t * lenmem,  kiss_
            if (st->shift>=32)
               return NULL;
         } else {
-           st->twiddles = (kiss_twiddle_cpx*)KISS_FFT_MALLOC(sizeof(kiss_twiddle_cpx)*nfft);
-           compute_twiddles(st->twiddles, nfft);
+           st->twiddles = twiddles = (kiss_twiddle_cpx*)KISS_FFT_MALLOC(sizeof(kiss_twiddle_cpx)*nfft);
+           compute_twiddles(twiddles, nfft);
            st->shift = -1;
         }
         if (!kf_factor(nfft,st->factors))
@@ -627,68 +632,62 @@ kiss_fft_cfg kiss_fft_alloc_twiddles(int nfft,void * mem,size_t * lenmem,  kiss_
            kiss_fft_free(st);
            return NULL;
         }
-        
+
         /* bitrev */
-        st->bitrev = (celt_int16*)KISS_FFT_MALLOC(sizeof(celt_int16)*nfft);
-        compute_bitrev_table(0, st->bitrev, 1,1, st->factors,st);
+        st->bitrev = bitrev = (celt_int16*)KISS_FFT_MALLOC(sizeof(celt_int16)*nfft);
+        compute_bitrev_table(0, bitrev, 1,1, st->factors,st);
     }
     return st;
 }
 
-kiss_fft_cfg kiss_fft_alloc(int nfft,void * mem,size_t * lenmem )
+kiss_fft_state *kiss_fft_alloc(int nfft,void * mem,size_t * lenmem )
 {
    return kiss_fft_alloc_twiddles(nfft, mem, lenmem, NULL);
 }
 
-    
-static void kiss_fft_stride(kiss_fft_cfg st,const kiss_fft_cpx *fin,kiss_fft_cpx *fout,int in_stride)
+void kiss_fft_free(const kiss_fft_state *cfg)
+{
+   celt_free((celt_int16*)cfg->bitrev);
+   if (cfg->shift < 0)
+      celt_free((kiss_twiddle_cpx*)cfg->twiddles);
+   celt_free((kiss_fft_state*)cfg);
+}
+
+#endif /* STATIC_MODES */
+
+static void kiss_fft_stride(const kiss_fft_state *st,const kiss_fft_cpx *fin,kiss_fft_cpx *fout,int in_stride)
 {
-    if (fin == fout) 
+    int i;
+    celt_assert2 (fin != fout, "In-place FFT not supported");
+    /* Bit-reverse the input */
+    for (i=0;i<st->nfft;i++)
     {
-       celt_fatal("In-place FFT not supported");
-    } else {
-       /* Bit-reverse the input */
-       int i;
-       for (i=0;i<st->nfft;i++)
-       {
-          fout[st->bitrev[i]] = fin[i];
+       fout[st->bitrev[i]] = fin[i];
 #ifndef FIXED_POINT
-          fout[st->bitrev[i]].r *= st->scale;
-          fout[st->bitrev[i]].i *= st->scale;
+       fout[st->bitrev[i]].r *= st->scale;
+       fout[st->bitrev[i]].i *= st->scale;
 #endif
-       }
-       kf_work( fout, fin, 1,in_stride, st->factors,st, 1, in_stride, 1);
     }
+    kf_work( fout, fin, 1,in_stride, st->factors,st, 1, in_stride, 1);
 }
 
-void kiss_fft(kiss_fft_cfg cfg,const kiss_fft_cpx *fin,kiss_fft_cpx *fout)
+void kiss_fft(const kiss_fft_state *cfg,const kiss_fft_cpx *fin,kiss_fft_cpx *fout)
 {
     kiss_fft_stride(cfg,fin,fout,1);
 }
 
-static void kiss_ifft_stride(kiss_fft_cfg st,const kiss_fft_cpx *fin,kiss_fft_cpx *fout,int in_stride)
+static void kiss_ifft_stride(const kiss_fft_state *st,const kiss_fft_cpx *fin,kiss_fft_cpx *fout,int in_stride)
 {
-   if (fin == fout) 
-   {
-      celt_fatal("In-place FFT not supported");
-   } else {
-      /* Bit-reverse the input */
-      int i;
-      for (i=0;i<st->nfft;i++)
-         fout[st->bitrev[i]] = fin[i];
-      ki_work( fout, fin, 1,in_stride, st->factors,st, 1, in_stride, 1);
-   }
+   int i;
+   celt_assert2 (fin != fout, "In-place FFT not supported");
+   /* Bit-reverse the input */
+   for (i=0;i<st->nfft;i++)
+      fout[st->bitrev[i]] = fin[i];
+   ki_work( fout, fin, 1,in_stride, st->factors,st, 1, in_stride, 1);
 }
 
-void kiss_ifft(kiss_fft_cfg cfg,const kiss_fft_cpx *fin,kiss_fft_cpx *fout)
+void kiss_ifft(const kiss_fft_state *cfg,const kiss_fft_cpx *fin,kiss_fft_cpx *fout)
 {
    kiss_ifft_stride(cfg,fin,fout,1);
 }
 
-void kiss_fft_free(kiss_fft_cfg cfg)
-{
-   celt_free(cfg->bitrev);
-   if (cfg->shift < 0)
-      celt_free(cfg->twiddles);
-   celt_free(cfg);
-}