shithub: opus

Download patch

ref: b801da5e831ea5eba0dd592a9711f05fcd97c9b4
parent: 78ea9fd02412c2e074269d577fdbaf34b0cdc113
author: Jean-Marc Valin <[email protected]>
date: Tue Sep 28 10:56:20 EDT 2010

Preventing bands from being coded at a rate below (for now) 3/8 bit/sample

--- a/libcelt/bands.c
+++ b/libcelt/bands.c
@@ -873,7 +873,7 @@
    }
 }
 
-void quant_all_bands(int encode, const CELTMode *m, int start, int end, celt_norm *_X, celt_norm *_Y, const celt_ener *bandE, int *pulses, int shortBlocks, int fold, int *tf_res, int resynth, int total_bits, void *ec, int LM)
+void quant_all_bands(int encode, const CELTMode *m, int start, int end, celt_norm *_X, celt_norm *_Y, const celt_ener *bandE, int *pulses, int shortBlocks, int fold, int *tf_res, int resynth, int total_bits, void *ec, int LM, int codedBands)
 {
    int i, balance;
    celt_int32 remaining_bits;
@@ -926,13 +926,18 @@
       if (i != start)
          balance -= tell;
       remaining_bits = (total_bits<<BITRES)-tell-1;
-      curr_balance = (end-i);
-      if (curr_balance > 3)
-         curr_balance = 3;
-      curr_balance = balance / curr_balance;
-      b = IMIN(remaining_bits+1,pulses[i]+curr_balance);
-      if (b<0)
+      if (i <= codedBands-1)
+      {
+         curr_balance = (codedBands-i);
+         if (curr_balance > 3)
+            curr_balance = 3;
+         curr_balance = balance / curr_balance;
+         b = IMIN(remaining_bits+1,pulses[i]+curr_balance);
+         if (b<0)
+            b = 0;
+      } else {
          b = 0;
+      }
       /* Prevents ridiculous bit depths */
       if (b > C*16*N<<BITRES)
          b = C*16*N<<BITRES;
--- a/libcelt/bands.h
+++ b/libcelt/bands.h
@@ -78,7 +78,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_all_bands(int encode, const CELTMode *m, int start, int end, celt_norm * X, celt_norm * Y, const celt_ener *bandE, int *pulses, int time_domain, int fold, int *tf_res, int resynth, int total_bits, void *enc, int M);
+void quant_all_bands(int encode, const CELTMode *m, int start, int end, celt_norm * X, celt_norm * Y, const celt_ener *bandE, int *pulses, int time_domain, int fold, int *tf_res, int resynth, int total_bits, void *enc, int M, int codedBands);
 
 
 void stereo_decision(const CELTMode *m, celt_norm * restrict X, int *stereo_mode, int len, int M);
--- a/libcelt/celt.c
+++ b/libcelt/celt.c
@@ -570,6 +570,7 @@
    int tf_select;
    int nbFilledBytes, nbAvailableBytes;
    int effEnd;
+   int codedBands;
    SAVE_STACK;
 
    if (nbCompressedBytes<0 || pcm==NULL)
@@ -861,7 +862,7 @@
    for (i=0;i<st->mode->nbEBands;i++)
       offsets[i] = 0;
    bits = nbCompressedBytes*8 - ec_enc_tell(enc, 0) - 1;
-   compute_allocation(st->mode, st->start, st->end, offsets, bits, pulses, fine_quant, fine_priority, C, LM);
+   codedBands = compute_allocation(st->mode, st->start, st->end, offsets, bits, pulses, fine_quant, fine_priority, C, LM);
 
    quant_fine_energy(st->mode, st->start, st->end, bandE, oldBandE, error, fine_quant, enc, C);
 
@@ -876,7 +877,7 @@
 #endif
 
    /* Residual quantisation */
-   quant_all_bands(1, st->mode, st->start, st->end, X, C==2 ? X+N : NULL, bandE, pulses, shortBlocks, has_fold, tf_res, resynth, nbCompressedBytes*8, enc, LM);
+   quant_all_bands(1, st->mode, st->start, st->end, X, C==2 ? X+N : NULL, bandE, pulses, shortBlocks, has_fold, tf_res, resynth, nbCompressedBytes*8, enc, LM, codedBands);
 
    quant_energy_finalise(st->mode, st->start, st->end, bandE, oldBandE, error, fine_quant, fine_priority, nbCompressedBytes*8-ec_enc_tell(enc, 0), enc, C);
 
@@ -1424,6 +1425,7 @@
    int LM, M;
    int nbFilledBytes, nbAvailableBytes;
    int effEnd;
+   int codedBands;
    SAVE_STACK;
 
    if (pcm==NULL)
@@ -1535,7 +1537,7 @@
 
    bits = len*8 - ec_dec_tell(dec, 0) - 1;
    ALLOC(fine_quant, st->mode->nbEBands, int);
-   compute_allocation(st->mode, st->start, st->end, offsets, bits, pulses, fine_quant, fine_priority, C, LM);
+   codedBands = compute_allocation(st->mode, st->start, st->end, offsets, bits, pulses, fine_quant, fine_priority, C, LM);
    /*bits = ec_dec_tell(dec, 0);
    compute_fine_allocation(st->mode, fine_quant, (20*C+len*8/5-(ec_dec_tell(dec, 0)-bits))/C);*/
    
@@ -1542,7 +1544,7 @@
    unquant_fine_energy(st->mode, st->start, st->end, bandE, oldBandE, fine_quant, dec, C);
 
    /* Decode fixed codebook */
-   quant_all_bands(0, st->mode, st->start, st->end, X, C==2 ? X+N : NULL, NULL, pulses, shortBlocks, has_fold, tf_res, 1, len*8, dec, LM);
+   quant_all_bands(0, st->mode, st->start, st->end, X, C==2 ? X+N : NULL, NULL, pulses, shortBlocks, has_fold, tf_res, 1, len*8, dec, LM, codedBands);
 
    unquant_energy_finalise(st->mode, st->start, st->end, bandE, oldBandE,
          fine_quant, fine_priority, len*8-ec_dec_tell(dec, 0), dec, C);
--- a/libcelt/rate.c
+++ b/libcelt/rate.c
@@ -137,20 +137,22 @@
 
 #define ALLOC_STEPS 6
 
-static inline void interp_bits2pulses(const CELTMode *m, int start, int end, int *bits1, int *bits2, int total, int *bits, int *ebits, int *fine_priority, int len, int _C, int LM)
+static inline int interp_bits2pulses(const CELTMode *m, int start, int end, int *bits1, int *bits2, int total, int *bits, int *ebits, int *fine_priority, int len, int _C, int LM)
 {
    int psum;
    int lo, hi;
    int i, j;
    int logM;
-   int psum0;
    const int C = CHANNELS(_C);
+   int codedBands=-1;
+   VARDECL(int, thresh);
    SAVE_STACK;
 
-   psum0=0;
-   for (j=start;j<end;j++)
-      psum0 += bits1[j];
+   ALLOC(thresh, len, int);
 
+   /* Threshold: don't allow any band to go below 3/8 bit/sample */
+   for (j=start;j<end;j++)
+      thresh[j] = 3*(C*(m->eBands[j+1]-m->eBands[j])<<LM<<BITRES)>>3;
    logM = LM<<BITRES;
    lo = 0;
    hi = 1<<ALLOC_STEPS;
@@ -157,9 +159,15 @@
    for (i=0;i<ALLOC_STEPS;i++)
    {
       int mid = (lo+hi)>>1;
-      psum = psum0;
+      psum = 0;
       for (j=start;j<end;j++)
-         psum += (mid*bits2[j]>>ALLOC_STEPS);
+      {
+         int tmp = bits1[j] + (mid*bits2[j]>>ALLOC_STEPS);
+         if (tmp >= thresh[j])
+            psum += tmp;
+         else if (tmp >= 1<<BITRES)
+            psum += 1<<BITRES;
+      }
       if (psum > (total<<BITRES))
          hi = mid;
       else
@@ -169,17 +177,26 @@
    /*printf ("interp bisection gave %d\n", lo);*/
    for (j=start;j<end;j++)
    {
-      bits[j] = bits1[j] + (lo*bits2[j]>>ALLOC_STEPS);
+      int tmp = bits1[j] + (lo*bits2[j]>>ALLOC_STEPS);
+      if (tmp >= thresh[j])
+      {
+         bits[j] = tmp;
+         codedBands = j;
+      } else if (tmp >= 1<<BITRES)
+         bits[j] = 1<<BITRES;
+      else
+         bits[j] = 0;
       psum += bits[j];
    }
+   codedBands++;
    /* Allocate the remaining bits */
    {
       int left, perband;
       left = (total<<BITRES)-psum;
-      perband = left/(end-start);
-      for (j=start;j<end;j++)
+      perband = left/(codedBands-start);
+      for (j=start;j<codedBands;j++)
          bits[j] += perband;
-      left = left-end*perband;
+      left = left-codedBands*perband;
       for (j=start;j<start+left;j++)
          bits[j]++;
    }
@@ -237,12 +254,14 @@
          bits[j] = 0;
    }
    RESTORE_STACK;
+   return codedBands;
 }
 
-void compute_allocation(const CELTMode *m, int start, int end, int *offsets, int total, int *pulses, int *ebits, int *fine_priority, int _C, int LM)
+int compute_allocation(const CELTMode *m, int start, int end, int *offsets, int total, int *pulses, int *ebits, int *fine_priority, int _C, int LM)
 {
    int lo, hi, len, j;
    const int C = CHANNELS(_C);
+   int codedBands;
    VARDECL(int, bits1);
    VARDECL(int, bits2);
    SAVE_STACK;
@@ -279,7 +298,8 @@
       bits2[j] = (C*N*m->allocVectors[hi*len+j]<<LM>>2) - bits1[j];
       bits1[j] += offsets[j];
    }
-   interp_bits2pulses(m, start, end, bits1, bits2, total, pulses, ebits, fine_priority, len, C, LM);
+   codedBands = interp_bits2pulses(m, start, end, bits1, bits2, total, pulses, ebits, fine_priority, len, C, LM);
    RESTORE_STACK;
+   return codedBands;
 }
 
--- a/libcelt/rate.h
+++ b/libcelt/rate.h
@@ -104,7 +104,7 @@
  @param pulses Number of pulses per band (returned)
  @return Total number of bits allocated
 */
-void compute_allocation(const CELTMode *m, int start, int end, int *offsets, int total, int *pulses, int *ebits, int *fine_priority, int _C, int LM);
+int compute_allocation(const CELTMode *m, int start, int end, int *offsets, int total, int *pulses, int *ebits, int *fine_priority, int _C, int LM);
 
 
 #endif