shithub: opus

Download patch

ref: 6775de3eaedad9cff7ad0ba45fdc32236955a273
parent: c890b58b69a340d33b6ee8eceaa617b9535b0bdf
author: Jean-Marc Valin <[email protected]>
date: Sat Aug 2 04:14:42 EDT 2008

Unified allocation of fine energy and pulses.

--- a/libcelt/bands.c
+++ b/libcelt/bands.c
@@ -329,14 +329,12 @@
 
 
 /* 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 total_bits, 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, ec_enc *enc)
 {
-   int i, j, bits;
+   int i, j;
    const celt_int16_t * restrict eBands = m->eBands;
    celt_norm_t * restrict norm;
    VARDECL(celt_norm_t, _norm);
-   VARDECL(int, pulses);
-   VARDECL(int, offsets);
    const int C = CHANNELS(m);
    int B;
    SAVE_STACK;
@@ -343,19 +341,11 @@
 
    B = shortBlocks ? m->nbShortMdcts : 1;
    ALLOC(_norm, C*eBands[m->nbEBands+1], celt_norm_t);
-   ALLOC(pulses, m->nbEBands, int);
-   ALLOC(offsets, m->nbEBands, int);
    norm = _norm;
 
-   for (i=0;i<m->nbEBands;i++)
-      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, stereo_mode, bits, pulses);
-   
    /*printf("bits left: %d\n", bits);
    for (i=0;i<m->nbEBands;i++)
-      printf ("%d ", pulses[i]);
+      printf ("(%d %d) ", pulses[i], ebits[i]);
    printf ("\n");*/
    /*printf ("%d %d\n", ec_enc_tell(enc, 0), compute_allocation(m, m->nbPulses));*/
    for (i=0;i<m->nbEBands;i++)
@@ -399,14 +389,12 @@
 }
 
 /* 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 total_bits, 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, ec_dec *dec)
 {
-   int i, j, bits;
+   int i, j;
    const celt_int16_t * restrict eBands = m->eBands;
    celt_norm_t * restrict norm;
    VARDECL(celt_norm_t, _norm);
-   VARDECL(int, pulses);
-   VARDECL(int, offsets);
    const int C = CHANNELS(m);
    int B;
    SAVE_STACK;
@@ -413,15 +401,7 @@
 
    B = shortBlocks ? m->nbShortMdcts : 1;
    ALLOC(_norm, C*eBands[m->nbEBands+1], celt_norm_t);
-   ALLOC(pulses, m->nbEBands, int);
-   ALLOC(offsets, m->nbEBands, int);
    norm = _norm;
-
-   for (i=0;i<m->nbEBands;i++)
-      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, stereo_mode, bits, pulses);
 
    for (i=0;i<m->nbEBands;i++)
    {
--- 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, const celt_ener_t *bandE, const int *stereo_mode, int total_bits, 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, ec_enc *enc);
 
 /** Decoding of the residual spectrum
  * @param m Mode data 
@@ -95,7 +95,7 @@
  * @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 total_bits, 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, ec_dec *dec);
 
 void stereo_decision(const CELTMode *m, celt_norm_t * restrict X, int *stereo_mode, int len);
 
--- a/libcelt/celt.c
+++ b/libcelt/celt.c
@@ -370,8 +370,10 @@
    VARDECL(celt_ener_t, bandE);
    VARDECL(celt_pgain_t, gains);
    VARDECL(int, stereo_mode);
-   VARDECL(celt_int16_t, fine_quant);
+   VARDECL(int, fine_quant);
    VARDECL(celt_word16_t, error);
+   VARDECL(int, pulses);
+   VARDECL(int, offsets);
 #ifdef EXP_PSY
    VARDECL(celt_word32_t, mask);
 #endif
@@ -529,22 +531,34 @@
          P[i] = 0;
    }
 
-   ALLOC(fine_quant, st->mode->nbEBands, celt_int16_t);
+   ALLOC(fine_quant, st->mode->nbEBands, int);
    ALLOC(error, C*st->mode->nbEBands, celt_word16_t);
-   bits = ec_enc_tell(&st->enc, 0);
    quant_coarse_energy(st->mode, bandE, st->oldBandE, 20*C+nbCompressedBytes*8, st->mode->prob, error, &st->enc);
-   compute_fine_allocation(st->mode, fine_quant, (20*C+nbCompressedBytes*8/5-(ec_enc_tell(&st->enc, 0)-bits))/C);
-   quant_fine_energy(st->mode, bandE, st->oldBandE, error, fine_quant, &st->enc);
-
+   
+   ALLOC(pulses, st->mode->nbEBands, int);
+   ALLOC(offsets, st->mode->nbEBands, int);
    ALLOC(stereo_mode, st->mode->nbEBands, int);
    stereo_decision(st->mode, X, stereo_mode, st->mode->nbEBands);
 
+   for (i=0;i<st->mode->nbEBands;i++)
+      offsets[i] = 0;
+   bits = nbCompressedBytes*8 - ec_enc_tell(&st->enc, 0) - 1;
+   compute_allocation(st->mode, offsets, stereo_mode, bits, pulses, fine_quant);
+   /*for (i=0;i<st->mode->nbEBands;i++)
+      printf("%d ", fine_quant[i]);
+   for (i=0;i<st->mode->nbEBands;i++)
+      printf("%d ", pulses[i]);
+   printf ("\n");*/
+   /*bits = ec_enc_tell(&st->enc, 0);
+   compute_fine_allocation(st->mode, fine_quant, (20*C+nbCompressedBytes*8/5-(ec_enc_tell(&st->enc, 0)-bits))/C);*/
+   quant_fine_energy(st->mode, bandE, st->oldBandE, error, fine_quant, &st->enc);
+
    pitch_quant_bands(st->mode, P, gains);
 
    /*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, nbCompressedBytes*8, shortBlocks, &st->enc);
+   quant_bands(st->mode, X, P, NULL, bandE, stereo_mode, pulses, shortBlocks, &st->enc);
    
    if (C==2)
    {
@@ -741,7 +755,7 @@
 
 int celt_decode(CELTDecoder * restrict st, unsigned char *data, int len, celt_int16_t * restrict pcm)
 {
-   int c, N, N4;
+   int i, c, N, N4;
    int has_pitch;
    int pitch_index;
    int bits;
@@ -753,7 +767,9 @@
    VARDECL(celt_ener_t, bandE);
    VARDECL(celt_pgain_t, gains);
    VARDECL(int, stereo_mode);
-   VARDECL(celt_int16_t, fine_quant);
+   VARDECL(int, fine_quant);
+   VARDECL(int, pulses);
+   VARDECL(int, offsets);
 
    int shortBlocks;
    int transient_time;
@@ -820,11 +836,23 @@
       pitch_index = 0;
    }
 
-   ALLOC(fine_quant, st->mode->nbEBands, celt_int16_t);
-   bits = ec_dec_tell(&dec, 0);
+   ALLOC(fine_quant, st->mode->nbEBands, int);
    /* Get band energies */
    unquant_coarse_energy(st->mode, bandE, st->oldBandE, 20*C+len*8, st->mode->prob, &dec);
-   compute_fine_allocation(st->mode, fine_quant, (20*C+len*8/5-(ec_dec_tell(&dec, 0)-bits))/C);
+   
+   ALLOC(pulses, st->mode->nbEBands, int);
+   ALLOC(offsets, st->mode->nbEBands, int);
+   ALLOC(stereo_mode, st->mode->nbEBands, int);
+   stereo_decision(st->mode, X, stereo_mode, st->mode->nbEBands);
+
+   for (i=0;i<st->mode->nbEBands;i++)
+      offsets[i] = 0;
+
+   bits = len*8 - ec_dec_tell(&dec, 0) - 1;
+   compute_allocation(st->mode, offsets, stereo_mode, bits, pulses, fine_quant);
+   /*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);*/
+   
    unquant_fine_energy(st->mode, bandE, st->oldBandE, fine_quant, &dec);
 
    /* Pitch MDCT */
@@ -837,13 +865,11 @@
       normalise_bands(st->mode, freq, P, bandEp);
    }
 
-   ALLOC(stereo_mode, st->mode->nbEBands, int);
-   stereo_decision(st->mode, X, stereo_mode, st->mode->nbEBands);
    /* Apply pitch gains */
    pitch_quant_bands(st->mode, P, gains);
 
    /* Decode fixed codebook and merge with pitch */
-   unquant_bands(st->mode, X, P, bandE, stereo_mode, len*8, shortBlocks, &dec);
+   unquant_bands(st->mode, X, P, bandE, stereo_mode, pulses, shortBlocks, &dec);
 
    if (C==2)
    {
--- a/libcelt/modes.c
+++ b/libcelt/modes.c
@@ -245,6 +245,7 @@
 {
    int i, j;
    celt_int16_t *alloc;
+   const int C = CHANNELS(mode);
    
    alloc = celt_alloc(sizeof(celt_int16_t)*(mode->nbAllocVectors*(mode->nbEBands+1)));
    for (i=0;i<mode->nbAllocVectors;i++)
@@ -258,7 +259,7 @@
       for (j=0;j<mode->nbEBands;j++)
       {
          alloc[i*(mode->nbEBands+1)+j] = mode->allocVectors[i*mode->nbEBands+j]
-                                         / (mode->eBands[j+1]-mode->eBands[j]-1);
+                                         / (C*(mode->eBands[j+1]-mode->eBands[j]));
          if (alloc[i*(mode->nbEBands+1)+j]<min_bits)
             alloc[i*(mode->nbEBands+1)+j] = min_bits;
          if (alloc[i*(mode->nbEBands+1)+j]>7)
--- a/libcelt/quant_bands.c
+++ b/libcelt/quant_bands.c
@@ -50,7 +50,7 @@
 /*const int frac[24] = {4, 3, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2};*/
 /*const int frac[24] = {8, 6, 5, 4, 3, 3, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2};*/
 
-void compute_fine_allocation(const CELTMode *m, celt_int16_t *bits, int budget)
+void compute_fine_allocation(const CELTMode *m, int *bits, int budget)
 {
    int i,j;
    int len;
@@ -185,7 +185,7 @@
    }
 }
 
-static void quant_fine_energy_mono(const CELTMode *m, celt_ener_t *eBands, celt_word16_t *oldEBands, celt_word16_t *error, celt_int16_t *fine_quant, ec_enc *enc)
+static void quant_fine_energy_mono(const CELTMode *m, celt_ener_t *eBands, celt_word16_t *oldEBands, celt_word16_t *error, int *fine_quant, ec_enc *enc)
 {
    int i;
    /* Encode finer resolution */
@@ -250,7 +250,7 @@
    }
 }
 
-static void unquant_fine_energy_mono(const CELTMode *m, celt_ener_t *eBands, celt_word16_t *oldEBands, celt_int16_t *fine_quant, ec_dec *dec)
+static void unquant_fine_energy_mono(const CELTMode *m, celt_ener_t *eBands, celt_word16_t *oldEBands, int *fine_quant, ec_dec *dec)
 {
    int i;
    /* Decode finer resolution */
@@ -299,7 +299,7 @@
    }
 }
 
-void quant_fine_energy(const CELTMode *m, celt_ener_t *eBands, celt_word16_t *oldEBands, celt_word16_t *error, celt_int16_t *fine_quant, ec_enc *enc)
+void quant_fine_energy(const CELTMode *m, celt_ener_t *eBands, celt_word16_t *oldEBands, celt_word16_t *error, int *fine_quant, ec_enc *enc)
 {
    int C;
    C = m->nbChannels;
@@ -347,7 +347,7 @@
    }
 }
 
-void unquant_fine_energy(const CELTMode *m, celt_ener_t *eBands, celt_word16_t *oldEBands, celt_int16_t *fine_quant, ec_dec *dec)
+void unquant_fine_energy(const CELTMode *m, celt_ener_t *eBands, celt_word16_t *oldEBands, int *fine_quant, ec_dec *dec)
 {
    int C;   
 
--- a/libcelt/quant_bands.h
+++ b/libcelt/quant_bands.h
@@ -40,14 +40,14 @@
 int *quant_prob_alloc(const CELTMode *m);
 void quant_prob_free(int *freq);
 
-void compute_fine_allocation(const CELTMode *m, celt_int16_t *bits, int budget);
+void compute_fine_allocation(const CELTMode *m, int *bits, int budget);
 
 void quant_coarse_energy(const CELTMode *m, celt_ener_t *eBands, celt_word16_t *oldEBands, int budget, int *prob, celt_word16_t *error, ec_enc *enc);
 
-void quant_fine_energy(const CELTMode *m, celt_ener_t *eBands, celt_word16_t *oldEBands, celt_word16_t *error, celt_int16_t *fine_quant, ec_enc *enc);
+void quant_fine_energy(const CELTMode *m, celt_ener_t *eBands, celt_word16_t *oldEBands, celt_word16_t *error, int *fine_quant, ec_enc *enc);
 
 void unquant_coarse_energy(const CELTMode *m, celt_ener_t *eBands, celt_word16_t *oldEBands, int budget, int *prob, ec_dec *dec);
 
-void unquant_fine_energy(const CELTMode *m, celt_ener_t *eBands, celt_word16_t *oldEBands, celt_int16_t *fine_quant, ec_dec *dec);
+void unquant_fine_energy(const CELTMode *m, celt_ener_t *eBands, celt_word16_t *oldEBands, int *fine_quant, ec_dec *dec);
 
 #endif /* QUANT_BANDS */
--- a/libcelt/rate.c
+++ b/libcelt/rate.c
@@ -132,11 +132,13 @@
    return sum;
 }
 
-static int interp_bits2pulses(const CELTMode *m, const celt_int16_t * const *cache, 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 *ebits1, int *ebits2, int total, int *pulses, int *ebits, int len)
 {
+   int esum;
    int lo, hi, out;
    int j;
    VARDECL(int, bits);
+   const int C = CHANNELS(m);
    SAVE_STACK;
    ALLOC(bits, len, int);
    lo = 0;
@@ -144,17 +146,30 @@
    while (hi-lo != 1)
    {
       int mid = (lo+hi)>>1;
+      esum = 0;
       for (j=0;j<len;j++)
-         bits[j] = ((1<<BITRES)-mid)*bits1[j] + mid*bits2[j];
-      if (vec_bits2pulses(m, cache, bits, pulses, len) > total<<BITRES)
+      {
+         ebits[j] = (((1<<BITRES)-mid)*ebits1[j] + mid*ebits2[j] + (1<<(BITRES-1)))>>BITRES;
+         esum += C*ebits[j];
+      }
+      for (j=0;j<len;j++)
+         bits[j] = ((1<<BITRES)-mid)*bits1[j] + mid*bits2[j] - C*(ebits[j]<<BITRES);
+      if (vec_bits2pulses(m, cache, bits, pulses, len) > (total-esum)<<BITRES)
          hi = mid;
       else
          lo = mid;
    }
+   esum = 0;
    /*printf ("interp bisection gave %d\n", lo);*/
    for (j=0;j<len;j++)
-      bits[j] = ((1<<BITRES)-lo)*bits1[j] + lo*bits2[j];
+   {
+      ebits[j] = (((1<<BITRES)-lo)*ebits1[j] + lo*ebits2[j] + (1<<(BITRES-1)))>>BITRES;
+      esum += C*ebits[j];
+   }
+   for (j=0;j<len;j++)
+      bits[j] = ((1<<BITRES)-lo)*bits1[j] + lo*bits2[j] - C*(ebits[j]<<BITRES);
    out = vec_bits2pulses(m, cache, bits, pulses, len);
+   /*printf ("left to allocate: %d\n", total-esum-(out>>BITRES));*/
    /* 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++)
@@ -161,7 +176,7 @@
    {
       if (cache[j][pulses[j]] < bits[j] && pulses[j]<MAX_PULSES-1)
       {
-         if (out+cache[j][pulses[j]+1]-cache[j][pulses[j]] <= total<<BITRES)
+         if (out+cache[j][pulses[j]+1]-cache[j][pulses[j]] <= (total-esum)<<BITRES)
          {
             out = out+cache[j][pulses[j]+1]-cache[j][pulses[j]];
             pulses[j] += 1;
@@ -175,7 +190,7 @@
       {
          if (pulses[j]<MAX_PULSES-1)
          {
-            if (out+cache[j][pulses[j]+1]-cache[j][pulses[j]] <= total<<BITRES)
+            if (out+cache[j][pulses[j]+1]-cache[j][pulses[j]] <= (total-esum)<<BITRES)
             {
                out = out+cache[j][pulses[j]+1]-cache[j][pulses[j]];
                pulses[j] += 1;
@@ -190,17 +205,22 @@
    return (out+BITROUND) >> BITRES;
 }
 
-int compute_allocation(const CELTMode *m, int *offsets, const int *stereo_mode, int total, int *pulses)
+int compute_allocation(const CELTMode *m, int *offsets, const int *stereo_mode, int total, int *pulses, int *ebits)
 {
    int lo, hi, len, ret, i;
    VARDECL(int, bits1);
    VARDECL(int, bits2);
+   VARDECL(int, ebits1);
+   VARDECL(int, ebits2);
    VARDECL(const celt_int16_t*, cache);
+   const int C = CHANNELS(m);
    SAVE_STACK;
    
    len = m->nbEBands;
    ALLOC(bits1, len, int);
    ALLOC(bits2, len, int);
+   ALLOC(ebits1, len, int);
+   ALLOC(ebits2, len, int);
    ALLOC(cache, len, const celt_int16_t*);
    
    if (m->nbChannels==2)
@@ -225,30 +245,33 @@
       int mid = (lo+hi) >> 1;
       for (j=0;j<len;j++)
       {
-         bits1[j] = (m->allocVectors[mid*len+j] + offsets[j])<<BITRES;
+         bits1[j] = (m->allocVectors[mid*len+j] - C*m->energy_alloc[mid*(len+1)+j] + offsets[j])<<BITRES;
          if (bits1[j] < 0)
             bits1[j] = 0;
          /*printf ("%d ", bits[j]);*/
       }
       /*printf ("\n");*/
-      if (vec_bits2pulses(m, cache, bits1, pulses, len) > total<<BITRES)
+      if (vec_bits2pulses(m, cache, bits1, pulses, len) > (total-C*m->energy_alloc[mid*(len+1)+len])<<BITRES)
          hi = mid;
       else
          lo = mid;
       /*printf ("lo = %d, hi = %d\n", lo, hi);*/
    }
+   /*printf ("interp between %d and %d\n", lo, hi);*/
    {
       int j;
       for (j=0;j<len;j++)
       {
-         bits1[j] = m->allocVectors[lo*len+j] + offsets[j];
-         bits2[j] = m->allocVectors[hi*len+j] + offsets[j];
+         ebits1[j] = m->energy_alloc[lo*(len+1)+j];
+         ebits2[j] = m->energy_alloc[hi*(len+1)+j];
+         bits1[j] = m->allocVectors[lo*len+j] + offsets[j] - 0*ebits1[j];
+         bits2[j] = m->allocVectors[hi*len+j] + offsets[j] - 0*ebits2[j];
          if (bits1[j] < 0)
             bits1[j] = 0;
          if (bits2[j] < 0)
             bits2[j] = 0;
       }
-      ret = interp_bits2pulses(m, cache, bits1, bits2, total, pulses, len);
+      ret = interp_bits2pulses(m, cache, bits1, bits2, ebits1, ebits2, total, pulses, ebits, 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, const int *stereo_mode, int total, int *pulses);
+int compute_allocation(const CELTMode *m, int *offsets, const int *stereo_mode, int total, int *pulses, int *ebits);
 
 
 #endif