shithub: opus

Download patch

ref: 66fa639c53c60ed0c8b3599457776a282f23752d
parent: c35883d74bafa558e145643a35c18d9aad6deb3a
author: Jean-Marc Valin <[email protected]>
date: Mon Feb 11 05:53:11 EST 2008

More flexible energy quantisation with nearly no penalty.

--- a/libcelt/quant_bands.c
+++ b/libcelt/quant_bands.c
@@ -35,10 +35,18 @@
 #include <math.h>
 #include "os_support.h"
 
+const float eMeans[24] = {45.f, -8.f, -12.f, -2.5f, 1.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f};
+
+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};
+
 static void quant_energy_mono(const CELTMode *m, float *eBands, float *oldEBands, ec_enc *enc)
 {
    int i;
    float prev = 0;
+   float coef = m->ePredCoef;
+   float error[m->nbEBands];
+   /* The .7 is a heuristic */
+   float beta = .7*coef;
    for (i=0;i<m->nbEBands;i++)
    {
       int qi;
@@ -45,28 +53,88 @@
       float q;
       float res;
       float x;
-      float pred = m->ePredCoef*oldEBands[i]+m->eMeans[i];
-      
+      float f;
+      float mean = (1-coef)*eMeans[i];
       x = 20*log10(.3+eBands[i]);
-      res = .25f*(i+3.f);
+      res = 6.;
       //res = 1;
-      qi = (int)floor(.5+(x-pred-prev)/res);
-      ec_laplace_encode(enc, qi, m->eDecay[i]);
+      f = (x-mean-coef*oldEBands[i]-prev)/res;
+      qi = (int)floor(.5+f);
+      //if (i> 4 && qi<-2)
+      //   qi = -2;
+      //ec_laplace_encode(enc, qi, i==0?11192:6192);
+      //ec_laplace_encode(enc, qi, 8500-i*200);
+      ec_laplace_encode(enc, qi, 6000-i*200);
       q = qi*res;
+      error[i] = f - qi;
       
       //printf("%d ", qi);
       //printf("%f %f ", pred+prev+q, x);
       //printf("%f ", x-pred);
       
-      oldEBands[i] = pred+prev+q;
+      oldEBands[i] = mean+coef*oldEBands[i]+prev+q;
+      
+      prev = mean+prev+(1-beta)*q;
+   }
+   for (i=0;i<m->nbEBands;i++)
+   {
+      int q2;
+      float offset = (error[i]+.5)*frac[i];
+      q2 = (int)floor(offset);
+      if (q2 > frac[i]-1)
+         q2 = frac[i]-1;
+      ec_enc_uint(enc, q2, frac[i]);
+      offset = ((q2+.5)/frac[i])-.5;
+      oldEBands[i] += 6.*offset;
+      //printf ("%f ", error[i] - offset);
       eBands[i] = pow(10, .05*oldEBands[i])-.3;
       if (eBands[i] < 0)
          eBands[i] = 0;
-      prev = (prev + .5*q);
    }
+   //printf ("%d\n", ec_enc_tell(enc, 0)-9);
+
    //printf ("\n");
 }
 
+static void unquant_energy_mono(const CELTMode *m, float *eBands, float *oldEBands, ec_dec *dec)
+{
+   int i;
+   float prev = 0;
+   float coef = m->ePredCoef;
+   float error[m->nbEBands];
+   /* The .7 is a heuristic */
+   float beta = .7*coef;
+   for (i=0;i<m->nbEBands;i++)
+   {
+      int qi;
+      float q;
+      float res;
+      float mean = (1-coef)*eMeans[i];
+      res = 6.;
+      qi = ec_laplace_decode(dec, 6000-i*200);
+      q = qi*res;
+      
+      oldEBands[i] = mean+coef*oldEBands[i]+prev+q;
+      
+      prev = mean+prev+(1-beta)*q;
+   }
+   for (i=0;i<m->nbEBands;i++)
+   {
+      int q2;
+      float offset;
+      q2 = ec_dec_uint(dec, frac[i]);
+      offset = ((q2+.5)/frac[i])-.5;
+      oldEBands[i] += 6.*offset;
+      //printf ("%f ", error[i] - offset);
+      eBands[i] = pow(10, .05*oldEBands[i])-.3;
+      if (eBands[i] < 0)
+         eBands[i] = 0;
+   }
+   //printf ("\n");
+}
+
+
+
 void quant_energy(const CELTMode *m, float *eBands, float *oldEBands, ec_enc *enc)
 {
    int C;
@@ -127,32 +195,6 @@
 }
 
 
-static void unquant_energy_mono(const CELTMode *m, float *eBands, float *oldEBands, ec_dec *dec)
-{
-   int i;
-   float prev = 0;
-   for (i=0;i<m->nbEBands;i++)
-   {
-      int qi;
-      float q;
-      float res;
-      float pred = m->ePredCoef*oldEBands[i]+m->eMeans[i];
-      
-      res = .25f*(i+3.f);
-      qi = ec_laplace_decode(dec, m->eDecay[i]);
-      q = qi*res;
-      //printf("%f %f ", pred+prev+q, x);
-      //printf("%d ", qi);
-      //printf("%f ", x-pred-prev);
-      
-      oldEBands[i] = pred+prev+q;
-      eBands[i] = pow(10, .05*oldEBands[i])-.3;
-      if (eBands[i] < 0)
-         eBands[i] = 0;
-      prev = (prev + .5*q);
-   }
-   //printf ("\n");
-}
 
 void unquant_energy(const CELTMode *m, float *eBands, float *oldEBands, ec_dec *dec)
 {