This simplifies the energy quantisation by converting to the log2() scale
authorJean-Marc Valin <jean-marc.valin@usherbrooke.ca>
Sun, 7 Jun 2009 17:01:25 +0000 (13:01 -0400)
committerJean-Marc Valin <jean-marc.valin@usherbrooke.ca>
Sun, 7 Jun 2009 17:01:25 +0000 (13:01 -0400)
directly instead of converting to dB and later dividing by 6.

libcelt/mathops.h
libcelt/quant_bands.c

index 68ecdb9..08e5aea 100644 (file)
@@ -109,7 +109,8 @@ static inline celt_int16_t bitexact_cos(celt_int16_t x)
 #define celt_atan atan
 #define celt_rcp(x) (1.f/(x))
 #define celt_div(a,b) ((a)/(b))
-
+#define celt_log2(x) (1.442695*log(x))
+#define celt_exp2(x) (exp(0.69315*(x)))
 #endif
 
 
index c8fd5a1..12b5b83 100644 (file)
 #include "stack_alloc.h"
 
 #ifdef FIXED_POINT
-const celt_word16_t eMeans[24] = {11520, -2048, -3072, -640, 256, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+const celt_word16_t eMeans[24] = {1920, -341, -512, -107, 43, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
 #else
-const celt_word16_t 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 celt_word16_t eMeans[24] = {7.5f, -1.33f, -2.f, -0.42f, 0.17f, 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};
 #endif
 
+#define amp2Log(amp) celt_log2(MAX32(QCONST32(.001f,14),SHL32(amp,2)))
 
-#ifdef FIXED_POINT
-static inline celt_ener_t dB2Amp(celt_ener_t dB)
-{
-   celt_ener_t amp;
-   if (dB>24659)
-      dB=24659;
-   amp = PSHR32(celt_exp2(MULT16_16_Q14(21771,dB)),2);
-   if (amp < 0)
-      amp = 0;
-   return PSHR32(amp,2);
-}
-
-#define DBofTWO 24661
-static inline celt_word16_t amp2dB(celt_ener_t amp)
-{
-   /* equivalent to return 6.0207*log2(.3+amp) */
-   return ROUND16(MULT16_16(24661,celt_log2(MAX32(QCONST32(.001f,14),SHL32(amp,2)))),12);
-   /* return DB_SCALING*20*log10(.3+ENER_SCALING_1*amp); */
-}
-#else
-static inline celt_ener_t dB2Amp(celt_ener_t dB)
-{
-   celt_ener_t amp;
-   /*amp = pow(10, .05*dB)-.3;*/
-   amp = exp(0.115129f*dB);
-   if (amp < 0)
-      amp = 0;
-   return amp;
-}
-static inline celt_word16_t amp2dB(celt_ener_t amp)
-{
-   /*return 20*log10(.3+amp);*/
-   return 8.68589f*log(MAX32(.001f,amp));
-}
-#endif
+#define log2Amp(lg) PSHR32(celt_exp2(SHL16(lg,3)),4)
 
 int intra_decision(celt_ener_t *eBands, celt_word16_t *oldEBands, int len)
 {
@@ -90,15 +57,12 @@ int intra_decision(celt_ener_t *eBands, celt_word16_t *oldEBands, int len)
    celt_word32_t dist = 0;
    for (i=0;i<len;i++)
    {
-      celt_word16_t d = SUB16(amp2dB(eBands[i]), oldEBands[i]);
+      celt_word16_t d = SUB16(amp2Log(eBands[i]), oldEBands[i]);
       dist = MAC16_16(dist, d,d);
    }
-   return SHR32(dist,16) > 64*len;
+   return SHR32(dist,16) > 2*len;
 }
 
-static const celt_word16_t base_resolution = QCONST16(6.f,8);
-static const celt_word16_t base_resolution_1 = QCONST16(0.1666667f,15);
-
 int *quant_prob_alloc(const CELTMode *m)
 {
    int i;
@@ -150,13 +114,13 @@ static unsigned quant_coarse_energy_mono(const CELTMode *m, celt_ener_t *eBands,
       celt_word16_t x;   /* dB */
       celt_word16_t f;   /* Q8 */
       celt_word16_t mean = MULT16_16_Q15(Q15ONE-coef,eMeans[i]);
-      x = amp2dB(eBands[i]);
+      x = amp2Log(eBands[i]);
 #ifdef FIXED_POINT
-      f = MULT16_16_Q15(x-mean-MULT16_16_Q15(coef,oldEBands[i])-prev,base_resolution_1);
+      f = x-mean -MULT16_16_Q15(coef,oldEBands[i])-prev;
       /* Rounding to nearest integer here is really important! */
       qi = (f+128)>>8;
 #else
-      f = (x-mean-coef*oldEBands[i]-prev)*base_resolution_1;
+      f = x-mean-coef*oldEBands[i]-prev;
       /* Rounding to nearest integer here is really important! */
       qi = (int)floor(.5+f);
 #endif
@@ -171,9 +135,9 @@ static unsigned quant_coarse_energy_mono(const CELTMode *m, celt_ener_t *eBands,
          ec_laplace_encode_start(enc, &qi, prob[2*i], prob[2*i+1]);
          error[i] = f - SHL16(qi,8);
       }
-      q = qi*base_resolution;
-      
-      oldEBands[i] = mean+MULT16_16_Q15(coef,oldEBands[i])+prev+q;
+      q = qi*DB_SCALING;
+
+      oldEBands[i] = MULT16_16_Q15(coef,oldEBands[i])+(mean+prev+q);
       prev = mean+prev+MULT16_16_Q15(Q15ONE-beta,q);
    }
    return bits_used;
@@ -204,14 +168,14 @@ static void quant_fine_energy_mono(const CELTMode *m, celt_ener_t *eBands, celt_
 #else
       offset = (q2+.5f)*(1<<(14-fine_quant[i]))*(1.f/16384) - .5f;
 #endif
-      oldEBands[i] += PSHR32(MULT16_16(DB_SCALING*6,offset),8);
+      oldEBands[i] += PSHR32(MULT16_16(DB_SCALING,offset),8);
       /*printf ("%f ", error[i] - offset);*/
    }
    for (i=0;i<m->nbEBands;i++)
    {
-      eBands[i] = dB2Amp(oldEBands[i]);
-      if (oldEBands[i] < -QCONST16(40.f,8))
-         oldEBands[i] = -QCONST16(40.f,8);
+      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);*/
 
@@ -247,10 +211,9 @@ static void unquant_coarse_energy_mono(const CELTMode *m, celt_ener_t *eBands, c
          qi = -1;
       else
          qi = ec_laplace_decode_start(dec, prob[2*i], prob[2*i+1]);
-      q = qi*base_resolution;
-      
-      oldEBands[i] = mean+MULT16_16_Q15(coef,oldEBands[i])+prev+q;
-      
+      q = qi*DB_SCALING;
+
+      oldEBands[i] = MULT16_16_Q15(coef,oldEBands[i])+(mean+prev+q);
       prev = mean+prev+MULT16_16_Q15(Q15ONE-beta,q);
    }
 }
@@ -271,13 +234,13 @@ static void unquant_fine_energy_mono(const CELTMode *m, celt_ener_t *eBands, cel
 #else
       offset = (q2+.5f)*(1<<(14-fine_quant[i]))*(1.f/16384) - .5f;
 #endif
-      oldEBands[i] += PSHR32(MULT16_16(DB_SCALING*6,offset),8);
+      oldEBands[i] += PSHR32(MULT16_16(DB_SCALING,offset),8);
    }
    for (i=0;i<m->nbEBands;i++)
    {
-      eBands[i] = dB2Amp(oldEBands[i]);
-      if (oldEBands[i] < -QCONST16(40.f,8))
-         oldEBands[i] = -QCONST16(40.f,8);
+      eBands[i] = log2Amp(oldEBands[i]);
+      if (oldEBands[i] < -QCONST16(7.f,8))
+         oldEBands[i] = -QCONST16(7.f,8);
    }
    /*printf ("\n");*/
 }