shithub: opus

Download patch

ref: 8ddd7f400d124ab14697409cf286ad7b3f7039fb
parent: 4989c1212a5f19c34c5575ec73a44a547e915924
author: Jean-Marc Valin <[email protected]>
date: Tue Apr 22 09:37:16 EDT 2008

mdct_backward now does the WOLA, so there isn't much left in compute_inv_mdcts

--- a/libcelt/celt.c
+++ b/libcelt/celt.c
@@ -102,7 +102,7 @@
    
    st->in_mem = celt_alloc(st->overlap*C*sizeof(celt_sig_t));
    st->mdct_overlap = celt_alloc(st->overlap*C*sizeof(celt_sig_t));
-   st->out_mem = celt_alloc(MAX_PERIOD*C*sizeof(celt_sig_t));
+   st->out_mem = celt_alloc((MAX_PERIOD+st->overlap)*C*sizeof(celt_sig_t));
 
    st->oldBandE = (celt_word16_t*)celt_alloc(C*mode->nbEBands*sizeof(celt_word16_t));
 
@@ -185,37 +185,39 @@
 static void compute_inv_mdcts(const CELTMode *mode, const celt_word16_t * restrict window, celt_sig_t *X, celt_sig_t * restrict out_mem, celt_sig_t * restrict mdct_overlap)
 {
    int c, N4;
-   VARDECL(celt_word32_t, x);
-   VARDECL(celt_word32_t, tmp);
    const int C = CHANNELS(mode);
    const mdct_lookup *lookup = MDCT(mode);
    const int N = FRAMESIZE(mode);
    const int overlap = OVERLAP(mode);
-   SAVE_STACK;
-   ALLOC(x, 2*N, celt_word32_t);
-   ALLOC(tmp, N, celt_word32_t);
    N4 = (N-overlap)>>1;
    for (c=0;c<C;c++)
    {
       int j;
       if (C==1) {
-         mdct_backward(lookup, X, x, window, overlap);
+         mdct_backward(lookup, X, out_mem+C*(MAX_PERIOD-N-N4), window, overlap);
       } else {
+         VARDECL(celt_word32_t, x);
+         VARDECL(celt_word32_t, tmp);
+         SAVE_STACK;
+         ALLOC(x, 2*N, celt_word32_t);
+         ALLOC(tmp, N, celt_word32_t);
          /* De-interleaving the sub-frames */
          for (j=0;j<N;j++)
             tmp[j] = X[C*j+c];
+         /* Prevents problems from the imdct doing the overlap-add */
+         CELT_MEMSET(x+N4, 0, overlap);
          mdct_backward(lookup, tmp, x, window, overlap);
-      }
          /* The first and last part would need to be set to zero if we actually
-      wanted to use them. */
-      for (j=0;j<overlap;j++)
-         out_mem[C*(MAX_PERIOD-N)+C*j+c] = mdct_overlap[C*j+c]+x[j+N4];
-      for (j=0;j<overlap;j++)
-         mdct_overlap[C*(overlap-j-1)+c] = x[2*N-j-N4-1];
-      for (j=0;j<2*N4;j++)
-         out_mem[C*(MAX_PERIOD-N)+C*(j+overlap)+c] = x[j+N4+overlap];
+         wanted to use them. */
+         for (j=0;j<overlap;j++)
+            out_mem[C*(MAX_PERIOD-N)+C*j+c] += x[j+N4];
+         for (j=0;j<overlap;j++)
+            out_mem[C*(MAX_PERIOD)+C*(overlap-j-1)+c] = x[2*N-j-N4-1];
+         for (j=0;j<2*N4;j++)
+            out_mem[C*(MAX_PERIOD-N)+C*(j+overlap)+c] = x[j+N4+overlap];
+         RESTORE_STACK;
+      }
    }
-   RESTORE_STACK;
 }
 
 int EXPORT celt_encode(CELTEncoder * restrict st, celt_int16_t * restrict pcm, unsigned char *compressed, int nbCompressedBytes)
@@ -358,7 +360,7 @@
    denormalise_bands(st->mode, X, freq, bandE);
 
 
-   CELT_MOVE(st->out_mem, st->out_mem+C*N, C*(MAX_PERIOD-N));
+   CELT_MOVE(st->out_mem, st->out_mem+C*N, C*(MAX_PERIOD+st->overlap-N));
 
    compute_inv_mdcts(st->mode, st->mode->window, freq, st->out_mem, st->mdct_overlap);
    /* De-emphasis and put everything back at the right place in the synthesis history */
@@ -462,7 +464,7 @@
    st->overlap = mode->overlap;
 
    st->mdct_overlap = celt_alloc(st->overlap*C*sizeof(celt_sig_t));
-   st->out_mem = celt_alloc(MAX_PERIOD*C*sizeof(celt_sig_t));
+   st->out_mem = celt_alloc((MAX_PERIOD+st->overlap)*C*sizeof(celt_sig_t));
    
    st->oldBandE = (celt_word16_t*)celt_alloc(C*mode->nbEBands*sizeof(celt_word16_t));
 
@@ -614,7 +616,7 @@
    denormalise_bands(st->mode, X, freq, bandE);
 
 
-   CELT_MOVE(st->out_mem, st->out_mem+C*N, C*(MAX_PERIOD-N));
+   CELT_MOVE(st->out_mem, st->out_mem+C*N, C*(MAX_PERIOD+st->overlap-N));
    /* Compute inverse MDCTs */
    compute_inv_mdcts(st->mode, st->mode->window, freq, st->out_mem, st->mdct_overlap);
 
--- a/libcelt/mdct.c
+++ b/libcelt/mdct.c
@@ -189,11 +189,13 @@
    int i;
    int N, N2, N4;
    VARDECL(kiss_fft_scalar, f);
+   VARDECL(kiss_fft_scalar, f2);
    SAVE_STACK;
    N = l->n;
    N2 = N>>1;
    N4 = N>>2;
    ALLOC(f, N2, kiss_fft_scalar);
+   ALLOC(f2, N2, kiss_fft_scalar);
    
    /* Pre-rotate */
    {
@@ -200,7 +202,7 @@
       /* Temp pointers to make it really clear to the compiler what we're doing */
       const kiss_fft_scalar * restrict xp1 = in;
       const kiss_fft_scalar * restrict xp2 = in+N2-1;
-      kiss_fft_scalar * restrict yp = out;
+      kiss_fft_scalar * restrict yp = f2;
       kiss_fft_scalar *t = &l->trig[0];
       for(i=0;i<N4;i++) 
       {
@@ -213,7 +215,7 @@
    }
 
    /* Inverse N/4 complex FFT. This one should *not* downscale even in fixed-point */
-   cpx32_ifft(l->kfft, out, f, N4);
+   cpx32_ifft(l->kfft, f2, f, N4);
    
    /* Post-rotate */
    {
@@ -235,7 +237,7 @@
    {
       const kiss_fft_scalar * restrict fp1 = f;
       const kiss_fft_scalar * restrict fp2 = f+N2-1;
-      kiss_fft_scalar * restrict yp = out+N4;
+      kiss_fft_scalar * restrict yp = f2;
       for(i = 0; i < N4; i++)
       {
          *yp++ =-*fp1*2;
@@ -247,28 +249,45 @@
 
    /* Mirror on both sides for TDAC */
    {
+      kiss_fft_scalar * restrict fp1 = f2+N4-1;
       kiss_fft_scalar * restrict xp1 = out+N2-1;
-      kiss_fft_scalar * restrict xp2 = out+N2;
       kiss_fft_scalar * restrict yp1 = out+N4-overlap/2;
-      kiss_fft_scalar * restrict yp2 = out+N-1-(N4-overlap/2);
       const celt_word16_t * restrict wp1 = window;
       const celt_word16_t * restrict wp2 = window+overlap-1;
       for(i = 0; i< N4-overlap/2; i++)
       {
-         *xp1 = *xp1;
-         *xp2 = *xp2;
+         *xp1 = *fp1;
          xp1--;
+         fp1--;
+      }
+      for(; i < N4; i++)
+      {
+         kiss_fft_scalar x1;
+         x1 = *fp1--;
+         *yp1++ +=-MULT16_32_Q15(*wp1, x1);
+         *xp1-- += MULT16_32_Q15(*wp2, x1);
+         wp1++;
+         wp2--;
+      }
+   }
+   {
+      kiss_fft_scalar * restrict fp2 = f2+N4;
+      kiss_fft_scalar * restrict xp2 = out+N2;
+      kiss_fft_scalar * restrict yp2 = out+N-1-(N4-overlap/2);
+      const celt_word16_t * restrict wp1 = window;
+      const celt_word16_t * restrict wp2 = window+overlap-1;
+      for(i = 0; i< N4-overlap/2; i++)
+      {
+         *xp2 = *fp2;
          xp2++;
+         fp2++;
       }
       for(; i < N4; i++)
       {
-         kiss_fft_scalar x1, x2;
-         x1 = *xp1;
-         x2 = *xp2;
-         *yp1++ =-MULT16_32_Q15(*wp1, x1);
-         *yp2-- = MULT16_32_Q15(*wp1, x2);
-         *xp1-- = MULT16_32_Q15(*wp2, x1);
-         *xp2++ = MULT16_32_Q15(*wp2, x2);
+         kiss_fft_scalar x2;
+         x2 = *fp2++;
+         *yp2--  = MULT16_32_Q15(*wp1, x2);
+         *xp2++  = MULT16_32_Q15(*wp2, x2);
          wp1++;
          wp2--;
       }
--- a/libcelt/mdct.h
+++ b/libcelt/mdct.h
@@ -60,7 +60,7 @@
 /** Compute a forward MDCT and scale by 2/N */
 void mdct_forward(const mdct_lookup *l, kiss_fft_scalar *in, kiss_fft_scalar *out, const celt_word16_t *window, int overlap);
 
-/** Compute a backward MDCT (no scaling) */
+/** Compute a backward MDCT (no scaling) and performs weighted overlap-add */
 void mdct_backward(const mdct_lookup *l, kiss_fft_scalar *in, kiss_fft_scalar *out, const celt_word16_t * restrict window, int overlap);
 
 #endif