shithub: opus

Download patch

ref: 39710536fc806fdb83a369e0932cbdd5e8973201
parent: cbc2afb118f17a3c1062fc31f9c05a7d3f22b7f5
author: Jean-Marc Valin <[email protected]>
date: Mon Jun 8 20:10:32 EDT 2009

This makes it possible to use the bits left after PVQ for fine energy.

--- a/libcelt/celt.c
+++ b/libcelt/celt.c
@@ -857,6 +857,9 @@
    else
       quant_bands_stereo(st->mode, X, P, NULL, has_pitch, gains, bandE, pulses, shortBlocks, has_fold, nbCompressedBytes*8, &enc);
 #endif
+
+   quant_energy_finalise(st->mode, bandE, st->oldBandE, error, fine_quant, nbCompressedBytes*8-ec_enc_tell(&enc, 0), &enc);
+
    /* Re-synthesis of the coded audio if required */
    if (st->pitch_available>0 || optional_synthesis!=NULL)
    {
@@ -1404,6 +1407,8 @@
    else
       unquant_bands_stereo(st->mode, X, P, has_pitch, gains, bandE, pulses, shortBlocks, has_fold, len*8, &dec);
 #endif
+   unquant_energy_finalise(st->mode, bandE, st->oldBandE, fine_quant, len*8-ec_dec_tell(&dec, 0), &dec);
+   
    /* Synthesis */
    denormalise_bands(st->mode, X, freq, bandE);
 
--- a/libcelt/quant_bands.c
+++ b/libcelt/quant_bands.c
@@ -169,17 +169,39 @@
       offset = (q2+.5f)*(1<<(14-fine_quant[i]))*(1.f/16384) - .5f;
 #endif
       oldEBands[i] += offset;
+      error[i] -= offset;
       /*printf ("%f ", error[i] - offset);*/
    }
    for (i=0;i<m->nbEBands;i++)
+      eBands[i] = log2Amp(oldEBands[i]);
+}
+
+static void quant_energy_finalise_mono(const CELTMode *m, celt_ener_t *eBands, celt_word16_t *oldEBands, celt_word16_t *error, int *fine_quant, int bits_left, ec_enc *enc)
+{
+   int i;
+   /* Use up the remaining bits */
+   for (i=0;i<m->nbEBands && bits_left!=0 ;i++)
    {
+      int q2;
+      celt_word16_t offset;
+      if (fine_quant[i] >= 7)
+         continue;
+      q2 = error[i]<0 ? 0 : 1;
+      ec_enc_bits(enc, q2, 1);
+#ifdef FIXED_POINT
+      offset = SHR16(SHL16(q2,8)-QCONST16(.5,8),fine_quant[i]+1);
+#else
+      offset = (q2-.5f)*(1<<(14-fine_quant[i]-1))*(1.f/16384);
+#endif
+      oldEBands[i] += offset;
+      bits_left--;
+   }
+   for (i=0;i<m->nbEBands;i++)
+   {
       eBands[i] = log2Amp(oldEBands[i]);
       if (oldEBands[i] < -QCONST16(7.f,8))
          oldEBands[i] = -QCONST16(7.f,8);
    }
-   /*printf ("%d\n", ec_enc_tell(enc, 0)-9);*/
-
-   /*printf ("\n");*/
 }
 
 static void unquant_coarse_energy_mono(const CELTMode *m, celt_ener_t *eBands, celt_word16_t *oldEBands, unsigned budget, int intra, int *prob, ec_dec *dec)
@@ -237,16 +259,37 @@
       oldEBands[i] += offset;
    }
    for (i=0;i<m->nbEBands;i++)
+      eBands[i] = log2Amp(oldEBands[i]);
+}
+
+static void unquant_energy_finalise_mono(const CELTMode *m, celt_ener_t *eBands, celt_word16_t *oldEBands, int *fine_quant, int bits_left, ec_dec *dec)
+{
+   int i;
+   /* Use up the remaining bits */
+   for (i=0;i<m->nbEBands && bits_left!=0 ;i++)
    {
+      int q2;
+      celt_word16_t offset;
+      if (fine_quant[i] >= 7)
+         continue;
+      q2 = ec_dec_bits(dec, 1);
+#ifdef FIXED_POINT
+      offset = SHR16(SHL16(q2,8)-QCONST16(.5,8),fine_quant[i]+1);
+#else
+      offset = (q2-.5f)*(1<<(14-fine_quant[i]-1))*(1.f/16384);
+#endif
+      oldEBands[i] += offset;
+      bits_left--;
+   }
+   for (i=0;i<m->nbEBands;i++)
+   {
       eBands[i] = log2Amp(oldEBands[i]);
       if (oldEBands[i] < -QCONST16(7.f,8))
          oldEBands[i] = -QCONST16(7.f,8);
    }
-   /*printf ("\n");*/
 }
 
 
-
 unsigned quant_coarse_energy(const CELTMode *m, celt_ener_t *eBands, celt_word16_t *oldEBands, int budget, int intra, int *prob, celt_word16_t *error, ec_enc *enc)
 {
    int C;
@@ -300,7 +343,31 @@
    }
 }
 
+void quant_energy_finalise(const CELTMode *m, celt_ener_t *eBands, celt_word16_t *oldEBands, celt_word16_t *error, int *fine_quant, int bits_left, ec_enc *enc)
+{
+   int C;
+   C = m->nbChannels;
 
+   if (C==1)
+   {
+      quant_energy_finalise_mono(m, eBands, oldEBands, error, fine_quant, bits_left, enc);
+
+   } else {
+      int c;
+      VARDECL(celt_ener_t, E);
+      ALLOC(E, m->nbEBands, celt_ener_t);
+      for (c=0;c<C;c++)
+      {
+         int i;
+         SAVE_STACK;
+         quant_energy_finalise_mono(m, E, oldEBands+c*m->nbEBands, error+c*m->nbEBands, fine_quant, bits_left/C, enc);
+         for (i=0;i<m->nbEBands;i++)
+            eBands[C*i+c] = E[i];
+         RESTORE_STACK;
+      }
+   }
+}
+
 void unquant_coarse_energy(const CELTMode *m, celt_ener_t *eBands, celt_word16_t *oldEBands, int budget, int intra, int *prob, ec_dec *dec)
 {
    int C;   
@@ -342,6 +409,32 @@
       {
          int i;
          unquant_fine_energy_mono(m, E, oldEBands+c*m->nbEBands, fine_quant, dec);
+         for (i=0;i<m->nbEBands;i++)
+            eBands[C*i+c] = E[i];
+      }
+      RESTORE_STACK;
+   }
+}
+
+void unquant_energy_finalise(const CELTMode *m, celt_ener_t *eBands, celt_word16_t *oldEBands, int *fine_quant, int bits_left, ec_dec *dec)
+{
+   int C;
+
+   C = m->nbChannels;
+
+   if (C==1)
+   {
+      unquant_energy_finalise_mono(m, eBands, oldEBands, fine_quant, bits_left, dec);
+   }
+   else {
+      int c;
+      VARDECL(celt_ener_t, E);
+      SAVE_STACK;
+      ALLOC(E, m->nbEBands, celt_ener_t);
+      for (c=0;c<C;c++)
+      {
+         int i;
+         unquant_energy_finalise_mono(m, E, oldEBands+c*m->nbEBands, fine_quant, bits_left/C, dec);
          for (i=0;i<m->nbEBands;i++)
             eBands[C*i+c] = E[i];
       }
--- a/libcelt/quant_bands.h
+++ b/libcelt/quant_bands.h
@@ -48,8 +48,12 @@
 
 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 quant_energy_finalise(const CELTMode *m, celt_ener_t *eBands, celt_word16_t *oldEBands, celt_word16_t *error, int *fine_quant, int bits_left, ec_enc *enc);
+
 void unquant_coarse_energy(const CELTMode *m, celt_ener_t *eBands, celt_word16_t *oldEBands, int budget, int intra, int *prob, ec_dec *dec);
 
 void unquant_fine_energy(const CELTMode *m, celt_ener_t *eBands, celt_word16_t *oldEBands, int *fine_quant, ec_dec *dec);
+
+void unquant_energy_finalise(const CELTMode *m, celt_ener_t *eBands, celt_word16_t *oldEBands, int *fine_quant, int bits_left, ec_dec *dec);
 
 #endif /* QUANT_BANDS */