One-at-a-time allocator now uses direct feedback from ec_*_tell().
authorJean-Marc Valin <jean-marc.valin@usherbrooke.ca>
Thu, 11 Sep 2008 04:20:08 +0000 (00:20 -0400)
committerJean-Marc Valin <jean-marc.valin@usherbrooke.ca>
Thu, 11 Sep 2008 04:20:08 +0000 (00:20 -0400)
libcelt/bands.c
libcelt/bands.h
libcelt/celt.c
libcelt/rate.c
libcelt/rate.h
libcelt/testcelt.c

index 2287663..c088c4f 100644 (file)
@@ -41,6 +41,7 @@
 #include "stack_alloc.h"
 #include "os_support.h"
 #include "mathops.h"
+#include "rate.h"
 
 const celt_word16_t sqrtC_1[2] = {QCONST16(1.f, 14), QCONST16(1.414214f, 14)};
 
@@ -329,9 +330,9 @@ void stereo_decision(const CELTMode *m, celt_norm_t * restrict X, int *stereo_mo
 
 
 /* Quantisation of the residual */
-void quant_bands(const CELTMode *m, celt_norm_t * restrict X, celt_norm_t *P, celt_mask_t *W, const celt_ener_t *bandE, const int *stereo_mode, int *pulses, int shortBlocks, ec_enc *enc)
+void quant_bands(const CELTMode *m, celt_norm_t * restrict X, celt_norm_t *P, celt_mask_t *W, const celt_ener_t *bandE, const int *stereo_mode, int *pulses, int shortBlocks, int total_bits, ec_enc *enc)
 {
-   int i, j;
+   int i, j, remaining_bits, balance;
    const celt_int16_t * restrict eBands = m->eBands;
    celt_norm_t * restrict norm;
    VARDECL(celt_norm_t, _norm);
@@ -343,6 +344,7 @@ void quant_bands(const CELTMode *m, celt_norm_t * restrict X, celt_norm_t *P, ce
    ALLOC(_norm, C*eBands[m->nbEBands+1], celt_norm_t);
    norm = _norm;
 
+   balance = 0;
    /*printf("bits left: %d\n", bits);
    for (i=0;i<m->nbEBands;i++)
       printf ("(%d %d) ", pulses[i], ebits[i]);
@@ -350,9 +352,32 @@ void quant_bands(const CELTMode *m, celt_norm_t * restrict X, celt_norm_t *P, ce
    /*printf ("%d %d\n", ec_enc_tell(enc, 0), compute_allocation(m, m->nbPulses));*/
    for (i=0;i<m->nbEBands;i++)
    {
+      int tell;
       int q;
       celt_word16_t n;
-      q = pulses[i];
+      
+      int curr_balance, curr_bits;
+      
+      tell = ec_enc_tell(enc, 4);
+      if (i != 0)
+         balance -= tell;
+      remaining_bits = (total_bits<<BITRES)-tell-1;
+      curr_balance = (m->nbEBands-i);
+      if (curr_balance > 3)
+         curr_balance = 3;
+      curr_balance = balance / curr_balance;
+      q = bits2pulses(m, m->bits[i], pulses[i]+curr_balance);
+      curr_bits = m->bits[i][q];
+      remaining_bits -= curr_bits;
+      if (remaining_bits < 0)
+      {
+         q--;
+         remaining_bits += curr_bits;
+         curr_bits = m->bits[i][q];
+         remaining_bits -= curr_bits;
+      }
+      balance += pulses[i] + tell;
+      
       n = SHL16(celt_sqrt(C*(eBands[i+1]-eBands[i])),11);
 
       /* If pitch isn't available, use intra-frame prediction */
@@ -389,9 +414,9 @@ void quant_bands(const CELTMode *m, celt_norm_t * restrict X, celt_norm_t *P, ce
 }
 
 /* Decoding of the residual */
-void unquant_bands(const CELTMode *m, celt_norm_t * restrict X, celt_norm_t *P, const celt_ener_t *bandE, const int *stereo_mode, int *pulses, int shortBlocks, ec_dec *dec)
+void unquant_bands(const CELTMode *m, celt_norm_t * restrict X, celt_norm_t *P, const celt_ener_t *bandE, const int *stereo_mode, int *pulses, int shortBlocks, int total_bits, ec_dec *dec)
 {
-   int i, j;
+   int i, j, remaining_bits, balance;
    const celt_int16_t * restrict eBands = m->eBands;
    celt_norm_t * restrict norm;
    VARDECL(celt_norm_t, _norm);
@@ -403,11 +428,35 @@ void unquant_bands(const CELTMode *m, celt_norm_t * restrict X, celt_norm_t *P,
    ALLOC(_norm, C*eBands[m->nbEBands+1], celt_norm_t);
    norm = _norm;
 
+   balance = 0;
    for (i=0;i<m->nbEBands;i++)
    {
+      int tell;
       int q;
       celt_word16_t n;
-      q = pulses[i];
+      
+      int curr_balance, curr_bits;
+      
+      tell = ec_dec_tell(dec, 4);
+      if (i != 0)
+         balance -= tell;
+      remaining_bits = (total_bits<<BITRES)-tell-1;
+      curr_balance = (m->nbEBands-i);
+      if (curr_balance > 3)
+         curr_balance = 3;
+      curr_balance = balance / curr_balance;
+      q = bits2pulses(m, m->bits[i], pulses[i]+curr_balance);
+      curr_bits = m->bits[i][q];
+      remaining_bits -= curr_bits;
+      if (remaining_bits < 0)
+      {
+         q--;
+         remaining_bits += curr_bits;
+         curr_bits = m->bits[i][q];
+         remaining_bits -= curr_bits;
+      }
+      balance += pulses[i] + tell;
+
       n = SHL16(celt_sqrt(C*(eBands[i+1]-eBands[i])),11);
 
       /* If pitch isn't available, use intra-frame prediction */
index 0f132ae..cc9d546 100644 (file)
@@ -86,7 +86,7 @@ void pitch_quant_bands(const CELTMode *m, celt_norm_t * restrict P, const celt_p
  * @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, const celt_ener_t *bandE, const int *stereo_mode, int *pulses, int time_domain, ec_enc *enc);
+void quant_bands(const CELTMode *m, celt_norm_t * restrict X, celt_norm_t *P, celt_mask_t *W, const celt_ener_t *bandE, const int *stereo_mode, int *pulses, int time_domain, int total_bits, ec_enc *enc);
 
 /** Decoding of the residual spectrum
  * @param m Mode data 
@@ -95,7 +95,7 @@ void quant_bands(const CELTMode *m, celt_norm_t * restrict X, celt_norm_t *P, ce
  * @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, const celt_ener_t *bandE, const int *stereo_mode, int *pulses, int time_domain, ec_dec *dec);
+void unquant_bands(const CELTMode *m, celt_norm_t * restrict X, celt_norm_t *P, const celt_ener_t *bandE, const int *stereo_mode, int *pulses, int time_domain, int total_bits, ec_dec *dec);
 
 void stereo_decision(const CELTMode *m, celt_norm_t * restrict X, int *stereo_mode, int len);
 
index b99bbf0..3d44852 100644 (file)
@@ -597,7 +597,7 @@ int celt_encode_float(CELTEncoder * restrict st, celt_sig_t * restrict pcm, unsi
    /*for (i=0;i<B*N;i++) printf("%f ",P[i]);printf("\n");*/
 
    /* Residual quantisation */
-   quant_bands(st->mode, X, P, NULL, bandE, stereo_mode, pulses, shortBlocks, &st->enc);
+   quant_bands(st->mode, X, P, NULL, bandE, stereo_mode, pulses, shortBlocks, nbCompressedBytes*8, &st->enc);
    
    if (st->pitch_enabled)
    {
@@ -625,6 +625,7 @@ int celt_encode_float(CELTEncoder * restrict st, celt_sig_t * restrict pcm, unsi
       }
 #endif
    }
+   /*fprintf (stderr, "remaining bits after encode = %d\n", nbCompressedBytes*8-ec_enc_tell(&st->enc, 0));*/
    /*if (ec_enc_tell(&st->enc, 0) < nbCompressedBytes*8 - 7)
       celt_warning_int ("many unused bits: ", nbCompressedBytes*8-ec_enc_tell(&st->enc, 0));*/
    /*printf ("%d\n", ec_enc_tell(&st->enc, 0)-8*nbCompressedBytes);*/
@@ -974,7 +975,7 @@ int celt_decode_float(CELTDecoder * restrict st, unsigned char *data, int len, c
    pitch_quant_bands(st->mode, P, gains);
 
    /* Decode fixed codebook and merge with pitch */
-   unquant_bands(st->mode, X, P, bandE, stereo_mode, pulses, shortBlocks, &dec);
+   unquant_bands(st->mode, X, P, bandE, stereo_mode, pulses, shortBlocks, len*8, &dec);
 
    if (C==2)
    {
index 3fad0a6..c84e536 100644 (file)
@@ -42,9 +42,6 @@
 #include "entcode.h"
 #include "rate.h"
 
-#define BITRES 4
-#define BITROUND 8
-#define BITOVERFLOW 30000
 
 #ifndef STATIC_MODES
 
@@ -93,30 +90,7 @@ celt_int16_t **compute_alloc_cache(CELTMode *m, int C)
 
 #endif /* !STATIC_MODES */
 
-static inline int bits2pulses(const CELTMode *m, const celt_int16_t *cache, int bits)
-{
-   int i;
-   int lo, hi;
-   lo = 0;
-   hi = MAX_PULSES-1;
-   
-   /* Instead of using the "bisection condition" we use a fixed number of 
-      iterations because it should be faster */
-   /*while (hi-lo != 1)*/
-   for (i=0;i<LOG_MAX_PULSES;i++)
-   {
-      int mid = (lo+hi)>>1;
-      /* OPT: Make sure this is implemented with a conditional move */
-      if (cache[mid] >= bits)
-         hi = mid;
-      else
-         lo = mid;
-   }
-   if (bits-cache[lo] <= cache[hi]-bits)
-      return lo;
-   else
-      return hi;
-}
+
 
 static int interp_bits2pulses(const CELTMode *m, const celt_int16_t * const *cache, int *bits1, int *bits2, int *ebits1, int *ebits2, int total, int *pulses, int *bits, int *ebits, int len)
 {
@@ -238,6 +212,7 @@ void compute_allocation(const CELTMode *m, int *offsets, const int *stereo_mode,
       if (bits2[j] < 0)
          bits2[j] = 0;
    }
+#if 0
    remaining_bits = interp_bits2pulses(m, cache, bits1, bits2, ebits1, ebits2, total, pulses, bits, ebits, len);
    {
       int balance = 0;
@@ -260,8 +235,13 @@ void compute_allocation(const CELTMode *m, int *offsets, const int *stereo_mode,
          }
          balance += bits[i] - curr_bits;
          pulses[i] = P;
+         printf ("%d ", P);
       }
+      printf ("\n");
    }
+#else
+   remaining_bits = interp_bits2pulses(m, cache, bits1, bits2, ebits1, ebits2, total, bits, pulses, ebits, len);
+#endif
    RESTORE_STACK;
 }
 
index 47eac72..8f931ff 100644 (file)
 #define MAX_PULSES 128
 #define LOG_MAX_PULSES 7
 
+#define BITRES 4
+#define BITROUND 8
+#define BITOVERFLOW 30000
+
+static inline int bits2pulses(const CELTMode *m, const celt_int16_t *cache, int bits)
+{
+   int i;
+   int lo, hi;
+   lo = 0;
+   hi = MAX_PULSES-1;
+   
+   /* Instead of using the "bisection condition" we use a fixed number of 
+   iterations because it should be faster */
+   /*while (hi-lo != 1)*/
+   for (i=0;i<LOG_MAX_PULSES;i++)
+   {
+      int mid = (lo+hi)>>1;
+      /* OPT: Make sure this is implemented with a conditional move */
+      if (cache[mid] >= bits)
+         hi = mid;
+      else
+         lo = mid;
+   }
+   if (bits-cache[lo] <= cache[hi]-bits)
+      return lo;
+   else
+      return hi;
+}
+
 /** Computes a cache of the pulses->bits mapping in each band */
 celt_int16_t **compute_alloc_cache(CELTMode *m, int C);
 
index dbfd950..a4038a4 100644 (file)
@@ -139,12 +139,17 @@ int main(int argc, char *argv[])
       else if (errors%2 == 1)
          data[rand()%8] ^= 1<<rand()%8;
 #endif
+#if 1 /* Set to zero to use the encoder's output instead */
       /* This is to simulate packet loss */
       if (argc==9 && rand()%1000<atoi(argv[7]))
       /*if (errors && (errors%2==0))*/
          celt_decode(dec, NULL, len, out);
       else
          celt_decode(dec, data, len, out);
+#else
+      for (i=0;i<frame_size*channels;i++)
+         out[i] = in[i];
+#endif
 #if !(defined (FIXED_POINT) && defined(STATIC_MODES))
       for (i=0;i<frame_size*channels;i++)
       {