X-Git-Url: http://git.xiph.org/?p=opus.git;a=blobdiff_plain;f=libcelt%2Fquant_bands.c;h=58f7ea52b7102b9b3f9e9d16a40744d07f9b4a0c;hp=042fba018c784f014d06ec212ef190c3bc936e7a;hb=18a3b79d24cf322b0ec7eec4867a1bc99d3fd1d7;hpb=adf87e261cfcc82e49f111bf9d257ca49a42b57a diff --git a/libcelt/quant_bands.c b/libcelt/quant_bands.c index 042fba01..58f7ea52 100644 --- a/libcelt/quant_bands.c +++ b/libcelt/quant_bands.c @@ -1,4 +1,4 @@ -/* (C) 2007 Jean-Marc Valin, CSIRO +/* (C) 2007-2008 Jean-Marc Valin, CSIRO */ /* Redistribution and use in source and binary forms, with or without @@ -39,6 +39,7 @@ #include "os_support.h" #include "arch.h" #include "mathops.h" +#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}; @@ -46,107 +47,148 @@ const celt_word16_t eMeans[24] = {11520, -2048, -3072, -640, 256, 0, 0, 0, 0, 0, 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}; #endif -/*const int frac[24] = {4, 3, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2};*/ -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(celt_ener_t dB) { celt_ener_t amp; + if (dB>24659) + dB=24659; amp = PSHR32(celt_exp2(MULT16_16_Q14(21771,dB)),2)-QCONST16(.3f, 14); if (amp < 0) amp = 0; - return amp; + 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 ROUND(MULT16_16(24661,celt_log2(ADD32(QCONST32(.3f,14),amp))),12); + return ROUND16(MULT16_16(24661,celt_log2(ADD32(QCONST32(.3f,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 = pow(10, .05*dB)-.3;*/ + amp = exp(0.115129f*dB)-.3f; if (amp < 0) amp = 0; return amp; } static inline celt_word16_t amp2dB(celt_ener_t amp) { - return 20*log10(.3+amp); + /*return 20*log10(.3+amp);*/ + return 8.68589f*log(.3f+amp); } #endif 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; + int *prob; + prob = celt_alloc(4*m->nbEBands*sizeof(int)); + for (i=0;inbEBands;i++) + { + prob[2*i] = 6000-i*200; + prob[2*i+1] = ec_laplace_get_start_freq(prob[2*i]); + } + for (i=0;inbEBands;i++) + { + prob[2*m->nbEBands+2*i] = 9000-i*240; + prob[2*m->nbEBands+2*i+1] = ec_laplace_get_start_freq(prob[2*m->nbEBands+2*i]); + } + return prob; +} -static void quant_energy_mono(const CELTMode *m, celt_ener_t *eBands, celt_word16_t *oldEBands, int budget, ec_enc *enc) +void quant_prob_free(int *freq) +{ + celt_free(freq); +} + +static void quant_coarse_energy_mono(const CELTMode *m, celt_ener_t *eBands, celt_word16_t *oldEBands, unsigned budget, int intra, int *prob, celt_word16_t *error, ec_enc *enc) { int i; - int bits; + unsigned bits; celt_word16_t prev = 0; - float coef = m->ePredCoef; - VARDECL(celt_word16_t *error); - /* The .7 is a heuristic */ - float beta = .7*coef; + celt_word16_t coef = m->ePredCoef; + celt_word16_t beta; + + if (intra) + { + coef = 0; + prob += 2*m->nbEBands; + } + /* The .8 is a heuristic */ + beta = MULT16_16_Q15(QCONST16(.8f,15),coef); - ALLOC(error, m->nbEBands, celt_word16_t); bits = ec_enc_tell(enc, 0); + /* Encode at a fixed coarse resolution */ for (i=0;inbEBands;i++) { int qi; celt_word16_t q; /* dB */ celt_word16_t x; /* dB */ celt_word16_t f; /* Q8 */ - celt_word16_t mean = (1-coef)*eMeans[i]; + celt_word16_t mean = MULT16_16_Q15(Q15ONE-coef,eMeans[i]); x = amp2dB(eBands[i]); - f = DIV32_16(SHL32(EXTEND32(x-mean-coef*oldEBands[i]-prev),8),base_resolution); #ifdef FIXED_POINT + f = MULT16_16_Q15(x-mean-MULT16_16_Q15(coef,oldEBands[i])-prev,base_resolution_1); /* Rounding to nearest integer here is really important! */ qi = (f+128)>>8; #else + f = (x-mean-coef*oldEBands[i]-prev)*base_resolution_1; + /* Rounding to nearest integer here is really important! */ qi = (int)floor(.5+f); #endif - /*ec_laplace_encode(enc, qi, i==0?11192:6192);*/ - /*ec_laplace_encode(enc, qi, 8500-i*200);*/ - /* If we don't have enough bits to encode all the energy, just assume something safe. */ + /* If we don't have enough bits to encode all the energy, just assume something safe. + We allow slightly busting the budget here */ if (ec_enc_tell(enc, 0) - bits > budget) + { qi = -1; - else - ec_laplace_encode(enc, qi, 6000-i*200); + error[i] = 128; + } else { + ec_laplace_encode_start(enc, &qi, prob[2*i], prob[2*i+1]); + error[i] = f - SHL16(qi,8); + } q = qi*base_resolution; - error[i] = f - SHL16(qi,8); - - /*printf("%d ", qi);*/ - /*printf("%f %f ", pred+prev+q, x);*/ - /*printf("%f ", x-pred);*/ - oldEBands[i] = mean+coef*oldEBands[i]+prev+q; - - prev = mean+prev+(1-beta)*q; + oldEBands[i] = mean+MULT16_16_Q15(coef,oldEBands[i])+prev+q; + if (oldEBands[i] < -QCONST16(12.f,8)) + oldEBands[i] = -QCONST16(12.f,8); + prev = mean+prev+MULT16_16_Q15(Q15ONE-beta,q); } - /*bits = ec_enc_tell(enc, 0) - bits;*/ - /*printf ("%d\n", bits);*/ +} + +static void quant_fine_energy_mono(const CELTMode *m, celt_ener_t *eBands, celt_word16_t *oldEBands, celt_word16_t *error, int *fine_quant, ec_enc *enc) +{ + int i; + /* Encode finer resolution */ for (i=0;inbEBands;i++) { int q2; - celt_word16_t offset = (error[i]+QCONST16(.5f,8))*frac[i]; - /* FIXME: Instead of giving up without warning, we should degrade everything gracefully */ - if (ec_enc_tell(enc, 0) - bits +EC_ILOG(frac[i])> budget) - break; + celt_int16_t frac = 1<>8; #else q2 = (int)floor(offset); #endif - if (q2 > frac[i]-1) - q2 = frac[i]-1; - ec_enc_uint(enc, q2, frac[i]); - offset = DIV32_16(SHL16(q2,8)+QCONST16(.5,8),frac[i])-QCONST16(.5f,8); + if (q2 > frac-1) + q2 = frac-1; + ec_enc_bits(enc, q2, fine_quant[i]); +#ifdef FIXED_POINT + offset = SUB16(SHR16(SHL16(q2,8)+QCONST16(.5,8),fine_quant[i]),QCONST16(.5f,8)); +#else + offset = (q2+.5f)*(1<<(14-fine_quant[i]))*(1.f/16384) - .5f; +#endif oldEBands[i] += PSHR32(MULT16_16(DB_SCALING*6,offset),8); /*printf ("%f ", error[i] - offset);*/ } @@ -159,43 +201,61 @@ static void quant_energy_mono(const CELTMode *m, celt_ener_t *eBands, celt_word1 /*printf ("\n");*/ } -static void unquant_energy_mono(const CELTMode *m, celt_ener_t *eBands, celt_word16_t *oldEBands, int budget, ec_dec *dec) +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) { int i; - int bits; + unsigned bits; celt_word16_t prev = 0; - float coef = m->ePredCoef; - /* The .7 is a heuristic */ - float beta = .7*coef; + celt_word16_t coef = m->ePredCoef; + celt_word16_t beta; + + if (intra) + { + coef = 0; + prob += 2*m->nbEBands; + } + /* The .8 is a heuristic */ + beta = MULT16_16_Q15(QCONST16(.8f,15),coef); + bits = ec_dec_tell(dec, 0); + /* Decode at a fixed coarse resolution */ for (i=0;inbEBands;i++) { int qi; celt_word16_t q; - celt_word16_t mean = (1-coef)*eMeans[i]; - /* If we didn't have enough bits to encode all the energy, just assume something safe. */ + celt_word16_t mean = MULT16_16_Q15(Q15ONE-coef,eMeans[i]); + /* If we didn't have enough bits to encode all the energy, just assume something safe. + We allow slightly busting the budget here */ if (ec_dec_tell(dec, 0) - bits > budget) qi = -1; else - qi = ec_laplace_decode(dec, 6000-i*200); + qi = ec_laplace_decode_start(dec, prob[2*i], prob[2*i+1]); q = qi*base_resolution; - /*printf("%d ", qi);*/ - /*printf("%f %f ", pred+prev+q, x);*/ - /*printf("%f ", x-pred);*/ - - oldEBands[i] = mean+coef*oldEBands[i]+prev+q; + oldEBands[i] = mean+MULT16_16_Q15(coef,oldEBands[i])+prev+q; + if (oldEBands[i] < -QCONST16(12.f,8)) + oldEBands[i] = -QCONST16(12.f,8); - prev = mean+prev+(1-beta)*q; + prev = mean+prev+MULT16_16_Q15(Q15ONE-beta,q); } +} + +static void unquant_fine_energy_mono(const CELTMode *m, celt_ener_t *eBands, celt_word16_t *oldEBands, int *fine_quant, ec_dec *dec) +{ + int i; + /* Decode finer resolution */ for (i=0;inbEBands;i++) { int q2; celt_word16_t offset; - if (ec_dec_tell(dec, 0) - bits +EC_ILOG(frac[i])> budget) - break; - q2 = ec_dec_uint(dec, frac[i]); - offset = DIV32_16(SHL16(q2,8)+QCONST16(.5,8),frac[i])-QCONST16(.5f,8); + if (fine_quant[i] <= 0) + continue; + q2 = ec_dec_bits(dec, fine_quant[i]); +#ifdef FIXED_POINT + offset = SUB16(SHR16(SHL16(q2,8)+QCONST16(.5,8),fine_quant[i]),QCONST16(.5f,8)); +#else + offset = (q2+.5f)*(1<<(14-fine_quant[i]))*(1.f/16384) - .5f; +#endif oldEBands[i] += PSHR32(MULT16_16(DB_SCALING*6,offset),8); } for (i=0;inbEBands;i++) @@ -207,83 +267,100 @@ static void unquant_energy_mono(const CELTMode *m, celt_ener_t *eBands, celt_wor -void quant_energy(const CELTMode *m, celt_ener_t *eBands, celt_word16_t *oldEBands, int budget, ec_enc *enc) +void 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; - C = m->nbChannels; if (C==1) - quant_energy_mono(m, eBands, oldEBands, budget, enc); - else -#if 1 { + quant_coarse_energy_mono(m, eBands, oldEBands, budget, intra, prob, error, enc); + } else { int c; - VARDECL(celt_ener_t *E); - ALLOC(E, m->nbEBands, celt_ener_t); for (c=0;cnbEBands, celt_ener_t); for (i=0;inbEBands;i++) E[i] = eBands[C*i+c]; - quant_energy_mono(m, E, oldEBands+c*m->nbEBands, budget/C, enc); - for (i=0;inbEBands;i++) - eBands[C*i+c] = E[i]; + quant_coarse_energy_mono(m, E, oldEBands+c*m->nbEBands, budget/C, intra, prob, error+c*m->nbEBands, enc); + RESTORE_STACK; } } -#else - if (C==2) +} + +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) +{ + int C; + C = m->nbChannels; + + if (C==1) { - int i; - int NB = m->nbEBands; - celt_ener_t mid[NB]; - celt_ener_t side[NB]; - for (i=0;inbEBands, celt_ener_t); + for (c=0;cnbEBands, error+c*m->nbEBands, fine_quant, enc); + for (i=0;inbEBands;i++) + eBands[C*i+c] = E[i]; + RESTORE_STACK; + } } -#endif } +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; -void unquant_energy(const CELTMode *m, celt_ener_t *eBands, celt_word16_t *oldEBands, int budget, ec_dec *dec) + C = m->nbChannels; + if (C==1) + { + unquant_coarse_energy_mono(m, eBands, oldEBands, budget, intra, prob, dec); + } + else { + int c; + VARDECL(celt_ener_t, E); + SAVE_STACK; + ALLOC(E, m->nbEBands, celt_ener_t); + for (c=0;cnbEBands, budget/C, intra, prob, dec); + } + RESTORE_STACK; + } +} + +void unquant_fine_energy(const CELTMode *m, celt_ener_t *eBands, celt_word16_t *oldEBands, int *fine_quant, ec_dec *dec) { int C; + C = m->nbChannels; if (C==1) - unquant_energy_mono(m, eBands, oldEBands, budget, dec); + { + unquant_fine_energy_mono(m, eBands, oldEBands, fine_quant, dec); + } else { int c; - VARDECL(celt_ener_t *E); + VARDECL(celt_ener_t, E); + SAVE_STACK; ALLOC(E, m->nbEBands, celt_ener_t); for (c=0;cnbEBands, budget/C, dec); + unquant_fine_energy_mono(m, E, oldEBands+c*m->nbEBands, fine_quant, dec); for (i=0;inbEBands;i++) eBands[C*i+c] = E[i]; } + RESTORE_STACK; } }