diff --git a/libcelt/mathops.h b/libcelt/mathops.h index f19113cc..31b7966e 100644 --- a/libcelt/mathops.h +++ b/libcelt/mathops.h @@ -124,17 +124,44 @@ 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; + celt_word16_t n, frac; /*-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]))))))); + n = VSHR32(x,i-15)-32768-16384; + frac = 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); + return SHL16(i-13,8)+SHR16(frac,14-8); } +/* + K0 = 1 + K1 = log(2) + K2 = 3-4*log(2) + K3 = 3*log(2) - 2 +*/ +#define D0 16384 +#define D1 11356 +#define D2 3726 +#define D3 1301 +/* Input in Q11 format, output in Q16 */ +static inline celt_word32_t celt_exp2(celt_word16_t x) +{ + int integer; + celt_word16_t frac; + integer = SHR16(x,11); + if (integer>14) + return 0x7fffffff; + else if (integer < -15) + return 0; + frac = SHL16(x-SHL16(integer,11),3); + frac = ADD16(D0, MULT16_16_Q14(frac, ADD16(D1, MULT16_16_Q14(frac, ADD16(D2 , MULT16_16_Q14(D3,frac)))))); + return VSHR32(EXTEND32(frac), -integer-2); +} + + #endif diff --git a/libcelt/quant_bands.c b/libcelt/quant_bands.c index 7b3f3b62..01d42bf1 100644 --- a/libcelt/quant_bands.c +++ b/libcelt/quant_bands.c @@ -50,12 +50,13 @@ 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) +static inline celt_ener_t dB2Amp(celt_ener_t dB) { celt_ener_t amp; - amp = pow(10, .05*dB)-.3; + amp = PSHR32(celt_exp2(dB/6.0207*8),2)-QCONST16(.3f, 14); if (amp < 0) amp = 0; + return amp; } #define DBofTWO 24661 @@ -66,12 +67,13 @@ static inline celt_word16_t amp2dB(celt_ener_t amp) /* return DB_SCALING*20*log10(.3+ENER_SCALING_1*amp); */ } #else -static inline celt_ener_t dB2Amp( dB) +static inline celt_ener_t dB2Amp(celt_ener_t dB) { celt_ener_t amp; amp = pow(10, .05*dB)-.3; if (amp < 0) amp = 0; + return amp; } static inline celt_word16_t amp2dB(celt_ener_t amp) { @@ -158,9 +160,7 @@ static void quant_energy_mono(const CELTMode *m, celt_ener_t *eBands, celt_word1 } for (i=0;inbEBands;i++) { - eBands[i] = ENER_SCALING*(pow(10, .05*DB_SCALING_1*oldEBands[i])-.3); - if (eBands[i] < 0) - eBands[i] = 0; + eBands[i] = dB2Amp(oldEBands[i]); } /*printf ("%d\n", ec_enc_tell(enc, 0)-9);*/ @@ -210,10 +210,7 @@ static void unquant_energy_mono(const CELTMode *m, celt_ener_t *eBands, celt_wor } for (i=0;inbEBands;i++) { - /*printf ("%f ", error[i] - offset);*/ - eBands[i] = ENER_SCALING*(pow(10, .05*DB_SCALING_1*oldEBands[i])-.3); - if (eBands[i] < 0) - eBands[i] = 0; + eBands[i] = dB2Amp(oldEBands[i]); } /*printf ("\n");*/ }