shithub: opus

Download patch

ref: 7bd2b9e001c12952ada3b6ce48628cf1ab227949
parent: fe0b8e8db420303dc891cfe8d23eac73a5bc7846
author: Jean-Marc Valin <[email protected]>
date: Fri May 23 10:23:22 EDT 2008

More stereo infrastructure

--- a/libcelt/bands.c
+++ b/libcelt/bands.c
@@ -290,7 +290,7 @@
 }
 
 /* Quantisation of the residual */
-void quant_bands(const CELTMode *m, celt_norm_t * restrict X, celt_norm_t *P, celt_mask_t *W, int total_bits, ec_enc *enc)
+void quant_bands(const CELTMode *m, celt_norm_t * restrict X, celt_norm_t *P, celt_mask_t *W, const int *stereo_mode, int total_bits, ec_enc *enc)
 {
    int i, j, bits;
    const celt_int16_t * restrict eBands = m->eBands;
@@ -310,7 +310,7 @@
       offsets[i] = 0;
    /* Use a single-bit margin to guard against overrunning (make sure it's enough) */
    bits = total_bits - ec_enc_tell(enc, 0) - 1;
-   compute_allocation(m, offsets, bits, pulses);
+   compute_allocation(m, offsets, stereo_mode, bits, pulses);
    
    /*printf("bits left: %d\n", bits);
    for (i=0;i<m->nbEBands;i++)
@@ -353,7 +353,7 @@
 }
 
 /* Decoding of the residual */
-void unquant_bands(const CELTMode *m, celt_norm_t * restrict X, celt_norm_t *P, int total_bits, ec_dec *dec)
+void unquant_bands(const CELTMode *m, celt_norm_t * restrict X, celt_norm_t *P, const int *stereo_mode, int total_bits, ec_dec *dec)
 {
    int i, j, bits;
    const celt_int16_t * restrict eBands = m->eBands;
@@ -373,7 +373,7 @@
       offsets[i] = 0;
    /* Use a single-bit margin to guard against overrunning (make sure it's enough) */
    bits = total_bits - ec_dec_tell(dec, 0) - 1;
-   compute_allocation(m, offsets, bits, pulses);
+   compute_allocation(m, offsets, stereo_mode, bits, pulses);
 
    for (i=0;i<m->nbEBands;i++)
    {
@@ -414,11 +414,11 @@
    for (i=0;i<len-5;i++)
       stereo_mode[i] = 0;
    for (;i<len;i++)
-      stereo_mode[i] = 1;
+      stereo_mode[i] = 0;
 }
 
 
-void stereo_mix(const CELTMode *m, celt_norm_t *X, const celt_ener_t *bank, int dir)
+void stereo_mix(const CELTMode *m, celt_norm_t *X, const celt_ener_t *bank, const int *stereo_mode, int dir)
 {
    int i;
    const celt_int16_t *eBands = m->eBands;
--- a/libcelt/bands.h
+++ b/libcelt/bands.h
@@ -86,7 +86,7 @@
  * @param total_bits Total number of bits that can be used for the frame (including the ones already spent)
  * @param enc Entropy encoder
  */
-void quant_bands(const CELTMode *m, celt_norm_t * restrict X, celt_norm_t *P, celt_mask_t *W, int total_bits, ec_enc *enc);
+void quant_bands(const CELTMode *m, celt_norm_t * restrict X, celt_norm_t *P, celt_mask_t *W, const int *stereo_mode, int total_bits, ec_enc *enc);
 
 /** Decoding of the residual spectrum
  * @param m Mode data 
@@ -95,10 +95,10 @@
  * @param total_bits Total number of bits that can be used for the frame (including the ones already spent)
  * @param dec Entropy decoder
 */
-void unquant_bands(const CELTMode *m, celt_norm_t * restrict X, celt_norm_t *P, int total_bits, ec_dec *dec);
+void unquant_bands(const CELTMode *m, celt_norm_t * restrict X, celt_norm_t *P, const int *stereo_mode, int total_bits, ec_dec *dec);
 
 void stereo_decision(const CELTMode *m, celt_norm_t * restrict X, int *stereo_mode, int len);
 
-void stereo_mix(const CELTMode *m, celt_norm_t *X, const celt_ener_t *bank, int dir);
+void stereo_mix(const CELTMode *m, celt_norm_t *X, const celt_ener_t *bank, const int *stereo_mode, int dir);
 
 #endif /* BANDS_H */
--- a/libcelt/celt.c
+++ b/libcelt/celt.c
@@ -223,6 +223,7 @@
    VARDECL(celt_norm_t, P);
    VARDECL(celt_ener_t, bandE);
    VARDECL(celt_pgain_t, gains);
+   VARDECL(int, stereo_mode);
    const int C = CHANNELS(st->mode);
    SAVE_STACK;
 
@@ -323,10 +324,12 @@
    }
    quant_energy(st->mode, bandE, st->oldBandE, 20+nbCompressedBytes*8/5, st->mode->prob, &st->enc);
 
+   ALLOC(stereo_mode, st->mode->nbEBands, int);
    if (C==2)
    {
-      stereo_mix(st->mode, X, bandE, 1);
-      stereo_mix(st->mode, P, bandE, 1);
+      stereo_decision(st->mode, X, stereo_mode, st->mode->nbEBands);
+      stereo_mix(st->mode, X, bandE, stereo_mode, 1);
+      stereo_mix(st->mode, P, bandE, stereo_mode, 1);
    }
 
    pitch_quant_bands(st->mode, P, gains);
@@ -337,11 +340,11 @@
       X[i] -= P[i];
 
    /* Residual quantisation */
-   quant_bands(st->mode, X, P, NULL, nbCompressedBytes*8, &st->enc);
+   quant_bands(st->mode, X, P, NULL, stereo_mode, nbCompressedBytes*8, &st->enc);
    
    if (C==2)
    {
-      stereo_mix(st->mode, X, bandE, -1);
+      stereo_mix(st->mode, X, bandE, stereo_mode, -1);
       renormalise_bands(st->mode, X);
    }
    /* Synthesis */
@@ -545,6 +548,7 @@
    VARDECL(celt_norm_t, P);
    VARDECL(celt_ener_t, bandE);
    VARDECL(celt_pgain_t, gains);
+   VARDECL(int, stereo_mode);
    const int C = CHANNELS(st->mode);
    SAVE_STACK;
 
@@ -601,18 +605,21 @@
       normalise_bands(st->mode, freq, P, bandEp);
    }
 
+   ALLOC(stereo_mode, st->mode->nbEBands, int);
    if (C==2)
-      stereo_mix(st->mode, P, bandE, 1);
-
+   {
+      stereo_decision(st->mode, X, stereo_mode, st->mode->nbEBands);
+      stereo_mix(st->mode, P, bandE, stereo_mode, 1);
+   }
    /* Apply pitch gains */
    pitch_quant_bands(st->mode, P, gains);
 
    /* Decode fixed codebook and merge with pitch */
-   unquant_bands(st->mode, X, P, len*8, &dec);
+   unquant_bands(st->mode, X, P, stereo_mode, len*8, &dec);
 
    if (C==2)
    {
-      stereo_mix(st->mode, X, bandE, -1);
+      stereo_mix(st->mode, X, bandE, stereo_mode, -1);
       renormalise_bands(st->mode, X);
    }
    /* Synthesis */
--- a/libcelt/rate.c
+++ b/libcelt/rate.c
@@ -155,7 +155,7 @@
 
 #endif /* !STATIC_MODES */
 
-static inline int bits2pulses(const CELTMode *m, int band, int bits)
+static inline int bits2pulses(const CELTMode *m, const celt_int16_t *cache, int bits)
 {
    int i;
    int lo, hi;
@@ -169,18 +169,18 @@
    {
       int mid = (lo+hi)>>1;
       /* OPT: Make sure this is implemented with a conditional move */
-      if (m->bits[band][mid] >= bits)
+      if (cache[mid] >= bits)
          hi = mid;
       else
          lo = mid;
    }
-   if (bits-m->bits[band][lo] <= m->bits[band][hi]-bits)
+   if (bits-cache[lo] <= cache[hi]-bits)
       return lo;
    else
       return hi;
 }
 
-static int vec_bits2pulses(const CELTMode *m, int *bits, int *pulses, int len)
+static int vec_bits2pulses(const CELTMode *m, const celt_int16_t * const *cache, int *bits, int *pulses, int len)
 {
    int i;
    int sum=0;
@@ -187,14 +187,14 @@
 
    for (i=0;i<len;i++)
    {
-      pulses[i] = bits2pulses(m, i, bits[i]);
-      sum += m->bits[i][pulses[i]];
+      pulses[i] = bits2pulses(m, cache[i], bits[i]);
+      sum += cache[i][pulses[i]];
    }
    /*printf ("sum = %d\n", sum);*/
    return sum;
 }
 
-static int interp_bits2pulses(const CELTMode *m, int *bits1, int *bits2, int total, int *pulses, int len)
+static int interp_bits2pulses(const CELTMode *m, const celt_int16_t * const *cache, int *bits1, int *bits2, int total, int *pulses, int len)
 {
    int lo, hi, out;
    int j;
@@ -208,7 +208,7 @@
       int mid = (lo+hi)>>1;
       for (j=0;j<len;j++)
          bits[j] = ((1<<BITRES)-mid)*bits1[j] + mid*bits2[j];
-      if (vec_bits2pulses(m, bits, pulses, len) > total<<BITRES)
+      if (vec_bits2pulses(m, cache, bits, pulses, len) > total<<BITRES)
          hi = mid;
       else
          lo = mid;
@@ -216,16 +216,16 @@
    /*printf ("interp bisection gave %d\n", lo);*/
    for (j=0;j<len;j++)
       bits[j] = ((1<<BITRES)-lo)*bits1[j] + lo*bits2[j];
-   out = vec_bits2pulses(m, bits, pulses, len);
+   out = vec_bits2pulses(m, cache, bits, pulses, len);
    /* Do some refinement to use up all bits. In the first pass, we can only add pulses to 
       bands that are under their allocated budget. In the second pass, anything goes */
    for (j=0;j<len;j++)
    {
-      if (m->bits[j][pulses[j]] < bits[j] && pulses[j]<MAX_PULSES-1)
+      if (cache[j][pulses[j]] < bits[j] && pulses[j]<MAX_PULSES-1)
       {
-         if (out+m->bits[j][pulses[j]+1]-m->bits[j][pulses[j]] <= total<<BITRES)
+         if (out+cache[j][pulses[j]+1]-cache[j][pulses[j]] <= total<<BITRES)
          {
-            out = out+m->bits[j][pulses[j]+1]-m->bits[j][pulses[j]];
+            out = out+cache[j][pulses[j]+1]-cache[j][pulses[j]];
             pulses[j] += 1;
          }
       }
@@ -237,9 +237,9 @@
       {
          if (pulses[j]<MAX_PULSES-1)
          {
-            if (out+m->bits[j][pulses[j]+1]-m->bits[j][pulses[j]] <= total<<BITRES)
+            if (out+cache[j][pulses[j]+1]-cache[j][pulses[j]] <= total<<BITRES)
             {
-               out = out+m->bits[j][pulses[j]+1]-m->bits[j][pulses[j]];
+               out = out+cache[j][pulses[j]+1]-cache[j][pulses[j]];
                pulses[j] += 1;
                incremented = 1;
             }
@@ -252,16 +252,31 @@
    return (out+BITROUND) >> BITRES;
 }
 
-int compute_allocation(const CELTMode *m, int *offsets, int total, int *pulses)
+int compute_allocation(const CELTMode *m, int *offsets, const int *stereo_mode, int total, int *pulses)
 {
-   int lo, hi, len, ret;
+   int lo, hi, len, ret, i;
    VARDECL(int, bits1);
    VARDECL(int, bits2);
+   VARDECL(const celt_int16_t*, cache);
    SAVE_STACK;
    
    len = m->nbEBands;
    ALLOC(bits1, len, int);
    ALLOC(bits2, len, int);
+   ALLOC(cache, len, const celt_int16_t*);
+   
+   if (m->nbChannels==2)
+   {
+      for (i=0;i<len;i++)
+      {
+         if (stereo_mode[i]==0)
+            cache[i] = m->bits[i];
+      }
+   } else {
+      for (i=0;i<len;i++)
+         cache[i] = m->bits[i];
+   }
+   
    lo = 0;
    hi = m->nbAllocVectors - 1;
    while (hi-lo != 1)
@@ -276,7 +291,7 @@
          /*printf ("%d ", bits[j]);*/
       }
       /*printf ("\n");*/
-      if (vec_bits2pulses(m, bits1, pulses, len) > total<<BITRES)
+      if (vec_bits2pulses(m, cache, bits1, pulses, len) > total<<BITRES)
          hi = mid;
       else
          lo = mid;
@@ -293,7 +308,7 @@
          if (bits2[j] < 0)
             bits2[j] = 0;
       }
-      ret = interp_bits2pulses(m, bits1, bits2, total, pulses, len);
+      ret = interp_bits2pulses(m, cache, bits1, bits2, total, pulses, len);
       RESTORE_STACK;
       return ret;
    }
--- a/libcelt/rate.h
+++ b/libcelt/rate.h
@@ -47,7 +47,7 @@
  @param pulses Number of pulses per band (returned)
  @return Total number of bits allocated
 */
-int compute_allocation(const CELTMode *m, int *offsets, int total, int *pulses);
+int compute_allocation(const CELTMode *m, int *offsets, const int *stereo_mode, int total, int *pulses);
 
 
 #endif