shithub: opus

Download patch

ref: cae30df09ade8ea53b0722024d627c0a12fc7f1a
parent: 4aa1b8df26d36867c87ddb7c35f84adb83721780
author: Jean-Marc Valin <[email protected]>
date: Thu May 20 20:26:03 EDT 2010

Getting rid of PVQ-level split

Adding one more level of band splitting so that splitting at the
PVQ encoding level is no longer necessary.

--- a/libcelt/bands.c
+++ b/libcelt/bands.c
@@ -316,9 +316,7 @@
    }
 }
 
-#ifndef DISABLE_STEREO
-
-static void stereo_band_mix(const CELTMode *m, celt_norm *X, celt_norm *Y, const celt_ener *bank, int stereo_mode, int bandID, int dir, int M)
+static void stereo_band_mix(const CELTMode *m, celt_norm *X, celt_norm *Y, const celt_ener *bank, int stereo_mode, int bandID, int dir, int N)
 {
    int i = bandID;
    const celt_int16 *eBands = m->eBands;
@@ -341,7 +339,7 @@
       a1 = DIV32_16(SHL32(EXTEND32(left),14),norm);
       a2 = dir*DIV32_16(SHL32(EXTEND32(right),14),norm);
    }
-   for (j=0;j<M*eBands[i+1]-M*eBands[i];j++)
+   for (j=0;j<N;j++)
    {
       celt_norm r, l;
       l = X[j];
@@ -352,8 +350,6 @@
 }
 
 
-#endif /* DISABLE_STEREO */
-
 int folding_decision(const CELTMode *m, celt_norm *X, celt_word16 *average, int *last_decision, int _C, int M)
 {
    int i, c, N0;
@@ -439,12 +435,15 @@
    split = stereo = Y != NULL;
 
    /* If we need more than 32 bits, try splitting the band in two. */
-   if (!stereo && LM>0 && !fits_in32(N, get_pulses(bits2pulses(m, m->bits[LM][i], N, b))))
+   if (!stereo && LM != -1 && !fits_in32(N, get_pulses(bits2pulses(m, m->bits[LM][i], N, b))))
    {
-      N >>= 1;
-      Y = X+N;
-      split = 1;
-      LM -= 1;
+      if (LM>0 || (N&1)==0)
+      {
+         N >>= 1;
+         Y = X+N;
+         split = 1;
+         LM -= 1;
+      }
    }
 
    if (split)
@@ -468,7 +467,7 @@
       if (encode)
       {
          if (stereo)
-            stereo_band_mix(m, X, Y, bandE, qb==0, i, 1, 1<<LM);
+            stereo_band_mix(m, X, Y, bandE, qb==0, i, 1, N);
 
          mid = renormalise_vector(X, Q15ONE, N, 1);
          side = renormalise_vector(Y, Q15ONE, N, 1);
@@ -644,10 +643,12 @@
       }
 
    } else {
-      /* This is the basis no-split case */
+      /* This is the basic no-split case */
       q = bits2pulses(m, m->bits[LM][i], N, b);
       curr_bits = pulses2bits(m->bits[LM][i], N, q);
       *remaining_bits -= curr_bits;
+
+      /* Ensures we can never bust the budget */
       while (*remaining_bits < 0 && q > 0)
       {
          *remaining_bits += curr_bits;
@@ -655,6 +656,11 @@
          curr_bits = pulses2bits(m->bits[LM][i], N, q);
          *remaining_bits -= curr_bits;
       }
+
+      /* Making sure we will *never* need more than 32 bits for the PVQ */
+      while (!fits_in32(N, get_pulses(q)))
+         q--;
+
       if (encode)
          alg_quant(X, N, q, spread, lowband, resynth, ec);
       else
@@ -746,7 +752,7 @@
 
       if (resynth && _Y != NULL)
       {
-         stereo_band_mix(m, X, Y, bandE, 0, i, -1, M);
+         stereo_band_mix(m, X, Y, bandE, 0, i, -1, N);
          renormalise_vector(X, Q15ONE, N, 1);
          renormalise_vector(Y, Q15ONE, N, 1);
       }
--- a/libcelt/celt.c
+++ b/libcelt/celt.c
@@ -141,15 +141,6 @@
          *error = CELT_INVALID_MODE;
       return NULL;
    }
-#ifdef DISABLE_STEREO
-   if (channels > 1)
-   {
-      celt_warning("Stereo support was disable from this build");
-      if (error)
-         *error = CELT_BAD_ARG;
-      return NULL;
-   }
-#endif
 
    if (channels < 0 || channels > 2)
    {
@@ -1217,15 +1208,6 @@
          *error = CELT_INVALID_MODE;
       return NULL;
    }
-#ifdef DISABLE_STEREO
-   if (channels > 1)
-   {
-      celt_warning("Stereo support was disable from this build");
-      if (error)
-         *error = CELT_BAD_ARG;
-      return NULL;
-   }
-#endif
 
    if (channels < 0 || channels > 2)
    {
--- a/libcelt/cwrs.c
+++ b/libcelt/cwrs.c
@@ -854,21 +854,10 @@
 
 void encode_pulses(int *_y, int N, int K, ec_enc *enc)
 {
-   if (K==0) {
-   } else if(fits_in32(N,K))
-   {
-      encode_pulses32(N, K, _y, enc);
-   } else {
-     int i;
-     int count=0;
-     int split;
-     split = (N+1)/2;
-     for (i=0;i<split;i++)
-        count += abs(_y[i]);
-     ec_enc_uint(enc,count,K+1);
-     encode_pulses(_y, split, count, enc);
-     encode_pulses(_y+split, N-split, K-count, enc);
-   }
+   if (K==0)
+      return;
+   celt_assert(fits_in32(N,K));
+   encode_pulses32(N, K, _y, enc);
 }
 
 static inline void decode_pulses32(int _n,int _k,int *_y,ec_dec *_dec){
@@ -900,14 +889,9 @@
       int i;
       for (i=0;i<N;i++)
          _y[i] = 0;
-   } else if(fits_in32(N,K))
+   } else
    {
+      celt_assert (fits_in32(N,K));
       decode_pulses32(N, K, _y, dec);
-   } else {
-     int split;
-     int count = ec_dec_uint(dec,K+1);
-     split = (N+1)/2;
-     decode_pulses(_y, split, count, dec);
-     decode_pulses(_y+split, N-split, K-count, dec);
    }
 }
--- a/libcelt/modes.c
+++ b/libcelt/modes.c
@@ -380,9 +380,15 @@
 #endif
    mode->window = window;
 
+   mode->bits = mode->_bits+1;
    for (i=0;(1<<i)<=mode->nbShortMdcts;i++)
-      mode->bits[i] = (const celt_int16 **)compute_alloc_cache(mode, 1, 1<<i);
-   if (mode->bits==NULL)
+   {
+      mode->bits[i] = (const celt_int16 **)compute_alloc_cache(mode, 1<<i);
+      if (mode->bits[i]==NULL)
+         goto failure;
+   }
+   mode->bits[-1] = (const celt_int16 **)compute_alloc_cache(mode, 0);
+   if (mode->bits[-1]==NULL)
       goto failure;
 
    logN = (celt_int16*)celt_alloc(mode->nbEBands*sizeof(celt_int16));
@@ -459,6 +465,19 @@
       }
       celt_free((celt_int16**)mode->bits[m]);
    }
+   if (mode->bits[-1]!=NULL)
+   {
+      for (i=0;i<mode->nbEBands;i++)
+      {
+         if (mode->bits[-1][i] != prevPtr)
+         {
+            prevPtr = mode->bits[-1][i];
+            celt_free((int*)mode->bits[-1][i]);
+         }
+      }
+   }
+   celt_free((celt_int16**)mode->bits[-1]);
+
    celt_free((celt_int16*)mode->eBands);
    celt_free((celt_int16*)mode->allocVectors);
    
--- a/libcelt/modes.h
+++ b/libcelt/modes.h
@@ -40,7 +40,7 @@
 #include "mdct.h"
 #include "pitch.h"
 
-#define MAX_CONFIG_SIZES 4
+#define MAX_CONFIG_SIZES 5
 
 #define CELT_BITSTREAM_VERSION 0x8000000c
 
@@ -93,7 +93,8 @@
    int          nbAllocVectors; /**< Number of lines in the matrix below */
    const celt_int16   *allocVectors;   /**< Number of bits in each band for several rates */
    
-   const celt_int16 * const *(bits[MAX_CONFIG_SIZES]); /**< Cache for pulses->bits mapping in each band */
+   const celt_int16 * const **bits;
+   const celt_int16 * const *(_bits[MAX_CONFIG_SIZES]); /**< Cache for pulses->bits mapping in each band */
 
    /* Stuff that could go in the {en,de}coder, but we save space this way */
    mdct_lookup mdct[MAX_CONFIG_SIZES];
--- a/libcelt/rate.c
+++ b/libcelt/rate.c
@@ -46,7 +46,7 @@
 
 #ifndef STATIC_MODES
 
-celt_int16 **compute_alloc_cache(CELTMode *m, int C, int M)
+celt_int16 **compute_alloc_cache(CELTMode *m, int M)
 {
    int i, prevN;
    int error = 0;
@@ -60,9 +60,18 @@
    prevN = -1;
    for (i=0;i<m->nbEBands;i++)
    {
-      int N = C*M*(eBands[i+1]-eBands[i]);
-      if (N == prevN && M*eBands[i] < m->pitchEnd)
+      int N;
+      if (M>0)
+         N = M*(eBands[i+1]-eBands[i]);
+      else
+         N = (eBands[i+1]-eBands[i])>>1;
+      if (N==0)
       {
+         bits[i] = NULL;
+         continue;
+      }
+      if (N == prevN)
+      {
          bits[i] = bits[i-1];
       } else {
          bits[i] = celt_alloc(MAX_PSEUDO*sizeof(celt_int16));
@@ -85,14 +94,14 @@
       {
          for (i=0;i<m->nbEBands;i++)
          {
-            if (bits[i] != prevPtr)
+            if (bits[i] != prevPtr && bits[i] != NULL)
             {
                prevPtr = bits[i];
                celt_free((int*)bits[i]);
             }
          }
-      free(bits);
-      bits=NULL;
+         free(bits);
+         bits=NULL;
       }   
    }
    return bits;
--- a/libcelt/rate.h
+++ b/libcelt/rate.h
@@ -155,7 +155,7 @@
 }
 
 /** Computes a cache of the pulses->bits mapping in each band */
-celt_int16 **compute_alloc_cache(CELTMode *m, int C, int M);
+celt_int16 **compute_alloc_cache(CELTMode *m, int M);
 
 /** Compute the pulse allocation, i.e. how many pulses will go in each
   * band.