shithub: opus

Download patch

ref: 67217ee746a9c1cb9420b75ecc7fba20e523d42d
parent: 6384196f763633ae028376517eba3347163f925c
author: Jean-Marc Valin <[email protected]>
date: Fri May 21 09:58:51 EDT 2010

Splitting transients in time domain

--- a/libcelt/bands.c
+++ b/libcelt/bands.c
@@ -420,11 +420,45 @@
    return *last_decision;
 }
 
+static void interleave_vector(celt_norm *X, int N0, int stride)
+{
+   int i,j;
+   VARDECL(celt_norm, tmp);
+   int N;
+   SAVE_STACK;
+   N = N0*stride;
+   ALLOC(tmp, N, celt_norm);
+   for (i=0;i<stride;i++)
+      for (j=0;j<N0;j++)
+         tmp[j*stride+i] = X[i*N0+j];
+   for (j=0;j<N;j++)
+      X[j] = tmp[j];
+   RESTORE_STACK;
+}
+
+static void deinterleave_vector(celt_norm *X, int N0, int stride)
+{
+   int i,j;
+   VARDECL(celt_norm, tmp);
+   int N;
+   SAVE_STACK;
+   N = N0*stride;
+   ALLOC(tmp, N, celt_norm);
+   for (i=0;i<stride;i++)
+      for (j=0;j<N0;j++)
+         tmp[i*N0+j] = X[j*stride+i];
+   for (j=0;j<N;j++)
+      X[j] = tmp[j];
+   RESTORE_STACK;
+}
+
 /* This function is responsible for encoding and decoding a band for both
    the mono and stereo case. Even in the mono case, it can split the band
    in two and transmit the energy difference with the two half-bands. It
    can be called recursively so bands can end up being split in 8 parts. */
-static void quant_band(int encode, const CELTMode *m, int i, celt_norm *X, celt_norm *Y, int N, int b, int spread, celt_norm *lowband, int resynth, ec_enc *ec, celt_int32 *remaining_bits, int LM, celt_norm *lowband_out, const celt_ener *bandE)
+static void quant_band(int encode, const CELTMode *m, int i, celt_norm *X, celt_norm *Y,
+      int N, int b, int spread, celt_norm *lowband, int resynth, ec_enc *ec,
+      celt_int32 *remaining_bits, int LM, celt_norm *lowband_out, const celt_ener *bandE, int level)
 {
    int q;
    int curr_bits;
@@ -431,9 +465,22 @@
    int stereo, split;
    int imid=0, iside=0;
    int N0=N;
+   int N_B=N;
+   int spread0=spread;
 
+   if (spread)
+      N_B /= spread;
+
    split = stereo = Y != NULL;
 
+   if (!stereo && spread>1 && level==0)
+   {
+      if (encode)
+         deinterleave_vector(X, N_B, spread);
+      if (lowband)
+         deinterleave_vector(lowband, N_B, spread);
+   }
+
    /* If we need more than 32 bits, try splitting the band in two. */
    if (!stereo && LM != -1 && !fits_in32(N, get_pulses(bits2pulses(m, m->bits[LM][i], N, b))))
    {
@@ -443,6 +490,7 @@
          Y = X+N;
          split = 1;
          LM -= 1;
+         spread = (spread+1)>>1;
       }
    }
 
@@ -495,7 +543,7 @@
             first stereo split but a triangular one for the rest. */
          if (encode)
             itheta = (itheta+(1<<shift>>1))>>shift;
-         if (stereo || qb>9)
+         if (stereo || qb>9 || spread>1)
          {
             if (encode)
                ec_enc_uint(ec, itheta, (1<<qb)+1);
@@ -597,17 +645,17 @@
                w[0] = x2[0];
                w[1] = x2[1];
             }
+            /* Here we only need to encode a sign for the side */
+            if (v[0]*w[1] - v[1]*w[0] > 0)
+               sign = 1;
+            else
+               sign = -1;
          }
-         quant_band(encode, m, i, v, NULL, N, mbits, spread, lowband, resynth, ec, remaining_bits, LM, NULL, NULL);
+         quant_band(encode, m, i, v, NULL, N, mbits, spread, lowband, resynth, ec, remaining_bits, LM, lowband_out, NULL, level+1);
          if (sbits)
          {
             if (encode)
             {
-               /* Here we only need to encode a sign for the side */
-               if (v[0]*w[1] - v[1]*w[0] > 0)
-                  sign = 1;
-               else
-                  sign = -1;
                ec_enc_bits(ec, sign==1, 1);
             } else {
                sign = 2*ec_dec_bits((ec_dec*)ec, 1)-1;
@@ -632,6 +680,11 @@
       } else
       {
          /* "Normal" split code */
+
+         /* Give more bits to low-energy MDCTs than they would otherwise deserve */
+         if (spread>1 && !stereo)
+            delta >>= 1;
+
          mbits = (b-qalloc/2-delta)/2;
          if (mbits > b-qalloc)
             mbits = b-qalloc;
@@ -639,11 +692,14 @@
             mbits=0;
          sbits = b-qalloc-mbits;
          *remaining_bits -= qalloc;
-         quant_band(encode, m, i, X, NULL, N, mbits, spread, lowband, resynth, ec, remaining_bits, LM, NULL, NULL);
          if (stereo)
-            quant_band(encode, m, i, Y, NULL, N, sbits, spread, NULL, resynth, ec, remaining_bits, LM, NULL, NULL);
-         else
-            quant_band(encode, m, i, Y, NULL, N, sbits, spread, lowband ? lowband+N : NULL, resynth, ec, remaining_bits, LM, NULL, NULL);
+         {
+            quant_band(encode, m, i, X, NULL, N, mbits, spread, lowband, resynth, ec, remaining_bits, LM, lowband_out, NULL, level);
+            quant_band(encode, m, i, Y, NULL, N, sbits, spread, NULL, resynth, ec, remaining_bits, LM, NULL, NULL, level);
+         } else {
+            quant_band(encode, m, i, X, NULL, N, mbits, spread, lowband, resynth, ec, remaining_bits, LM, NULL, NULL, level+1);
+            quant_band(encode, m, i, Y, NULL, N, sbits, spread, lowband ? lowband+N : NULL, resynth, ec, remaining_bits, LM, NULL, NULL, level+1);
+         }
       }
 
    } else {
@@ -671,31 +727,42 @@
          alg_unquant(X, N, q, spread, lowband, (ec_dec*)ec);
    }
 
-   if (resynth && lowband_out)
+   if (resynth)
    {
-      int j;
-      celt_word16 n;
-      n = celt_sqrt(SHL32(EXTEND32(N0),22));
-      for (j=0;j<N0;j++)
-         lowband_out[j] = MULT16_16_Q15(n,X[j]);
-   }
-
-   if (split && resynth)
-   {
-      int j;
-      celt_word16 mid, side;
+      if (split)
+      {
+         int j;
+         celt_word16 mid, side;
 #ifdef FIXED_POINT
-      mid = imid;
-      side = iside;
+         mid = imid;
+         side = iside;
 #else
-      mid = (1.f/32768)*imid;
-      side = (1.f/32768)*iside;
+         mid = (1.f/32768)*imid;
+         side = (1.f/32768)*iside;
 #endif
-      for (j=0;j<N;j++)
-         X[j] = MULT16_16_Q15(X[j], mid);
-      for (j=0;j<N;j++)
-         Y[j] = MULT16_16_Q15(Y[j], side);
+         for (j=0;j<N;j++)
+            X[j] = MULT16_16_Q15(X[j], mid);
+         for (j=0;j<N;j++)
+            Y[j] = MULT16_16_Q15(Y[j], side);
+      }
 
+
+      if (!stereo && spread0>1 && level==0)
+      {
+         interleave_vector(X, N_B, spread0);
+         if (lowband)
+            interleave_vector(lowband, N_B, spread0);
+      }
+
+      if (lowband_out && !stereo)
+      {
+         int j;
+         celt_word16 n;
+         n = celt_sqrt(SHL32(EXTEND32(N0),22));
+         for (j=0;j<N0;j++)
+            lowband_out[j] = MULT16_16_Q15(n,X[j]);
+      }
+
       if (stereo)
       {
          stereo_band_mix(m, X, Y, bandE, 0, i, -1, N);
@@ -756,7 +823,7 @@
       if (b<0)
          b = 0;
 
-      quant_band(encode, m, i, X, Y, N, b, spread, norm+M*eBands[start], resynth, ec, &remaining_bits, LM, norm+M*eBands[i], bandE);
+      quant_band(encode, m, i, X, Y, N, b, spread, norm+M*eBands[start], resynth, ec, &remaining_bits, LM, norm+M*eBands[i], bandE, 0);
 
       balance += pulses[i] + tell;
    }
--- a/libcelt/vq.c
+++ b/libcelt/vq.c
@@ -74,6 +74,7 @@
 
 static void exp_rotation(celt_norm *X, int len, int dir, int stride, int K)
 {
+   int i;
    celt_word16 c, s;
    celt_word16 gain, theta;
    int stride2=0;
@@ -85,11 +86,6 @@
       X[14] = 1;
       K=5;
    }*/
-   /*if (stride>1)
-   {
-      pseudo_hadamard(X, len, dir, stride, K);
-      return;
-   }*/
    if (2*K>=len)
       return;
    gain = celt_div((celt_word32)MULT16_16(Q15_ONE,len),(celt_word32)(len+10*K));
@@ -99,11 +95,7 @@
    c = celt_cos_norm(EXTEND32(theta));
    s = celt_cos_norm(EXTEND32(SUB16(Q15ONE,theta))); /*  sin(theta) */
 
-#if 0
    if (len>=8*stride)
-      stride2 = stride*floor(.5+sqrt(len*1.f/stride));
-#else
-   if (len>=8*stride)
    {
       stride2 = 1;
       /* This is just a simple way of computing sqrt(len/stride) with rounding.
@@ -111,20 +103,21 @@
          I _think_ it is bit-exact */
       while ((stride2*stride2+stride2)*stride + (stride>>2) < len)
          stride2++;
-      stride2 *= stride;
    }
-#endif
-   if (dir < 0)
+   len /= stride;
+   for (i=0;i<stride;i++)
    {
-      if (stride2)
-         exp_rotation1(X, len, dir, stride2, s, c);
-      exp_rotation1(X, len, dir, stride, c, s);
-   } else {
-      exp_rotation1(X, len, dir, stride, c, s);
-      if (stride2)
-         exp_rotation1(X, len, dir, stride2, s, c);
+      if (dir < 0)
+      {
+         if (stride2)
+            exp_rotation1(X+i*len, len, dir, stride2, s, c);
+         exp_rotation1(X+i*len, len, dir, 1, c, s);
+      } else {
+         exp_rotation1(X+i*len, len, dir, 1, c, s);
+         if (stride2)
+            exp_rotation1(X+i*len, len, dir, stride2, s, c);
+      }
    }
-
    /*if (len>=30)
    {
       for (i=0;i<len;i++)