fixed-point: log approximation
authorJean-Marc Valin <jean-marc.valin@usherbrooke.ca>
Thu, 28 Feb 2008 11:14:54 +0000 (22:14 +1100)
committerJean-Marc Valin <jean-marc.valin@usherbrooke.ca>
Thu, 28 Feb 2008 11:14:54 +0000 (22:14 +1100)
libcelt/mathops.h
libcelt/quant_bands.c

index 6bc24f0..f19113c 100644 (file)
 
 #include "entcode.h"
 
+static inline celt_int16_t celt_ilog2(celt_word32_t x)
+{
+   return EC_ILOG(x)-1;
+}
+
 #define C0 3634
 #define C1 21173
 #define C2 -12627
@@ -116,6 +121,19 @@ static inline celt_word16_t celt_cos_norm(celt_word32_t x)
    }
 }
 
+static inline celt_word16_t celt_log2(celt_word32_t x)
+{
+   int i;
+   /*-0.41446   0.96093  -0.33981   0.15600 */
+   const celt_word16_t C[4] = {-6791, 7872, -1392, 319};
+   if (x==0)
+      return -32767;
+   i = celt_ilog2(x);
+   celt_word16_t n = VSHR32(x,i-15)-32768-16384;
+   celt_word16_t ret = ADD16(C[0], MULT16_16_Q14(n, ADD16(C[1], MULT16_16_Q14(n, ADD16(C[2], MULT16_16_Q14(n, (C[3])))))));
+   /*printf ("%d %d %d %d\n", x, n, ret, SHL16(i-13,8)+SHR16(ret,14-8));*/
+   return SHL16(i-13,8)+SHR16(ret,14-8);
+}
 
 #endif
 
index a54a78d..7b3f3b6 100644 (file)
@@ -38,6 +38,7 @@
 #include <math.h>
 #include "os_support.h"
 #include "arch.h"
+#include "mathops.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};
@@ -49,6 +50,37 @@ const float eMeans[24] = {45.f, -8.f, -12.f, -2.5f, 1.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};
 
 #ifdef FIXED_POINT
+static inline celt_ener_t dB2Amp( dB)
+{
+   celt_ener_t amp;
+   amp = pow(10, .05*dB)-.3;
+   if (amp < 0)
+      amp = 0;
+}
+
+#define DBofTWO 24661
+static inline celt_word16_t amp2dB(celt_ener_t amp)
+{
+   /* equivalent to return 6.0207*log2(.3+amp) */
+   return ROUND(MULT16_16(24661,celt_log2(ADD32(QCONST32(.3f,14),amp))),12);
+   /* return DB_SCALING*20*log10(.3+ENER_SCALING_1*amp); */
+}
+#else
+static inline celt_ener_t dB2Amp( dB)
+{
+   celt_ener_t amp;
+   amp = pow(10, .05*dB)-.3;
+   if (amp < 0)
+      amp = 0;
+}
+static inline celt_word16_t amp2dB(celt_ener_t amp)
+{
+   return 20*log10(.3+amp);
+}
+#endif
+
+
+#ifdef FIXED_POINT
 #define Q8 256.f
 #define Q8_1 (1.f/256.f)
 #else
@@ -75,7 +107,7 @@ static void quant_energy_mono(const CELTMode *m, celt_ener_t *eBands, celt_word1
       celt_word16_t x;   /* dB */
       celt_word16_t f;   /* Q8 */
       celt_word16_t mean = (1-coef)*eMeans[i];
-      x = DB_SCALING*20*log10(.3+ENER_SCALING_1*eBands[i]);
+      x = amp2dB(eBands[i]);
       res = DB_SCALING*6;
       f = QCONST16(1.f,8)*(x-mean-coef*oldEBands[i]-prev*1.f)/res;
 #ifdef FIXED_POINT