From e86fb268b029d68d07ede37d35cfe82e8db3e86d Mon Sep 17 00:00:00 2001 From: "Timothy B. Terriberry" Date: Fri, 17 Dec 2010 14:50:19 -0800 Subject: [PATCH] Replace ec_{enc|dec}_bit_prob() with ec_{enc|dec}_bit_logp(). All of our usage of ec_{enc|dec}_bit_prob had the probability of a "one" being a power of two. This adds a new ec_{enc|dec}_bit_logp() function that takes this explicitly into account. It introduces less rounding error than the bit_prob version, does not require 17-bit integers to be emulated by ec_{encode|decode}_bin(), and does not require any multiplies or divisions at all. It is exactly equivalent to ec_encode_bin(enc,_val?0:(1<<_logp)-1,(1<<_logp)-(_val?1:0),1<<_logp) The old ec_{enc|dec}_bit_prob functions are left in place for now, because I am not sure if SILK is still using them or not when combined in Opus. --- libcelt/bands.c | 4 ++-- libcelt/celt.c | 36 ++++++++++++++++++------------------ libcelt/entdec.h | 3 +++ libcelt/entenc.h | 3 +++ libcelt/quant_bands.c | 2 +- libcelt/rangedec.c | 18 +++++++++++++++++- libcelt/rangeenc.c | 14 ++++++++++++++ libcelt/rate.c | 6 +++--- 8 files changed, 61 insertions(+), 25 deletions(-) diff --git a/libcelt/bands.c b/libcelt/bands.c index c83fdc5d..b9789618 100644 --- a/libcelt/bands.c +++ b/libcelt/bands.c @@ -675,9 +675,9 @@ static void quant_band(int encode, const CELTMode *m, int i, celt_norm *X, celt_ if (b>2< 2<delayedIntra, st->complexity >= 4); if (LM > 0) - ec_enc_bit_prob(enc, shortBlocks!=0, 8192); + ec_enc_bit_logp(enc, shortBlocks!=0, 3); tf_encode(st->start, st->end, isTransient, tf_res, LM, tf_select, enc); @@ -994,12 +994,12 @@ int celt_encode_with_ec_float(CELTEncoder * restrict st, const celt_sig * pcm, i for (i=0;imode->nbEBands;i++) { int j; - ec_enc_bit_prob(enc, offsets[i]!=0, 1024); + ec_enc_bit_logp(enc, offsets[i]!=0, 6); if (offsets[i]!=0) { for (j=0;jmode, X, st->mode->nbEBands, LM, C, N); - ec_enc_bit_prob(enc, dual_stereo, 32768); + ec_enc_bit_logp(enc, dual_stereo, 1); } if (C==2) { @@ -1786,7 +1786,7 @@ int celt_decode_with_ec_float(CELTDecoder * restrict st, const unsigned char *da } nbAvailableBytes = len-nbFilledBytes; - if (ec_dec_bit_prob(dec, 32768)) + if (ec_dec_bit_logp(dec, 1)) { #ifdef ENABLE_POSTFILTER int qg, octave; @@ -1805,13 +1805,13 @@ int celt_decode_with_ec_float(CELTDecoder * restrict st, const unsigned char *da } /* Decode the global flags (first symbols in the stream) */ - intra_ener = ec_dec_bit_prob(dec, 8192); + intra_ener = ec_dec_bit_logp(dec, 3); /* Get band energies */ unquant_coarse_energy(st->mode, st->start, st->end, bandE, oldBandE, intra_ener, dec, C, LM); if (LM > 0) - isTransient = ec_dec_bit_prob(dec, 8192); + isTransient = ec_dec_bit_logp(dec, 3); else isTransient = 0; @@ -1833,9 +1833,9 @@ int celt_decode_with_ec_float(CELTDecoder * restrict st, const unsigned char *da offsets[i] = 0; for (i=0;imode->nbEBands;i++) { - if (ec_dec_bit_prob(dec, 1024)) + if (ec_dec_bit_logp(dec, 6)) { - while (ec_dec_bit_prob(dec, 32768)) + while (ec_dec_bit_logp(dec, 1)) offsets[i]++; offsets[i]++; offsets[i] *= (6<end-st->start); } diff --git a/libcelt/entdec.h b/libcelt/entdec.h index 6a3841bf..f163b4d6 100644 --- a/libcelt/entdec.h +++ b/libcelt/entdec.h @@ -124,6 +124,9 @@ int ec_dec_cdf(ec_dec *_this,const int *_cdf,unsigned _ftb); /* Decode a bit that has a _prob/65536 probability of being a one */ int ec_dec_bit_prob(ec_dec *_this,unsigned _prob); +/* Decode a bit that has a 1/(1<<_logp) probability of being a one */ +int ec_dec_bit_logp(ec_dec *_this,unsigned _logp); + /*Returns the number of bits "used" by the encoded symbols so far. This same number can be computed by the encoder, and is suitable for making coding decisions. diff --git a/libcelt/entenc.h b/libcelt/entenc.h index d86cb7fc..2b31f96a 100644 --- a/libcelt/entenc.h +++ b/libcelt/entenc.h @@ -96,6 +96,9 @@ void ec_enc_uint(ec_enc *_this,ec_uint32 _fl,ec_uint32 _ft); /* Encode a bit that has a _prob/65536 probability of being a one */ void ec_enc_bit_prob(ec_enc *_this,int val,unsigned _prob); +/* Encode a bit that has a 1/(1<<_logp) probability of being a one */ +void ec_enc_bit_logp(ec_enc *_this,int _val,unsigned _logp); + /*Returns the number of bits "used" by the encoded symbols so far. This same number can be computed by the decoder, and is suitable for making coding decisions. diff --git a/libcelt/quant_bands.c b/libcelt/quant_bands.c index ce7cb727..e894aff1 100644 --- a/libcelt/quant_bands.c +++ b/libcelt/quant_bands.c @@ -163,7 +163,7 @@ static void quant_coarse_energy_impl(const CELTMode *m, int start, int end, celt_word16 coef; celt_word16 beta; - ec_enc_bit_prob(enc, intra, 8192); + ec_enc_bit_logp(enc, intra, 3); if (intra) { coef = 0; diff --git a/libcelt/rangedec.c b/libcelt/rangedec.c index 97dd7ff6..262c0ebd 100644 --- a/libcelt/rangedec.c +++ b/libcelt/rangedec.c @@ -190,8 +190,8 @@ void ec_dec_update(ec_dec *_this,unsigned _fl,unsigned _fh,unsigned _ft){ /*The probability of having a "one" is given in 1/65536.*/ int ec_dec_bit_prob(ec_dec *_this,unsigned _prob){ ec_uint32 r; - ec_uint32 s; ec_uint32 d; + ec_uint32 s; int val; r=_this->rng; d=_this->dif; @@ -203,6 +203,22 @@ int ec_dec_bit_prob(ec_dec *_this,unsigned _prob){ return val; } +/*The probability of having a "one" is 1/(1<<_logp).*/ +int ec_dec_bit_logp(ec_dec *_this,unsigned _logp){ + ec_uint32 r; + ec_uint32 d; + ec_uint32 s; + int val; + r=_this->rng; + d=_this->dif; + s=r>>_logp; + val=ddif=d-s; + _this->rng=val?s:r-s; + ec_dec_normalize(_this); + return val; +} + int ec_dec_cdf(ec_dec *_this,const int *_cdf,unsigned _ftb){ ec_uint32 r; ec_uint32 d; diff --git a/libcelt/rangeenc.c b/libcelt/rangeenc.c index b4a7343c..e5040e70 100644 --- a/libcelt/rangeenc.c +++ b/libcelt/rangeenc.c @@ -153,6 +153,20 @@ void ec_enc_bit_prob(ec_enc *_this,int _val,unsigned _prob){ ec_enc_normalize(_this); } +/*The probability of having a "one" is 1/(1<<_logp).*/ +void ec_enc_bit_logp(ec_enc *_this,int _val,unsigned _logp){ + ec_uint32 r; + ec_uint32 s; + ec_uint32 l; + r=_this->rng; + l=_this->low; + s=r>>_logp; + r-=s; + if(_val)_this->low=l+r; + _this->rng=_val?s:r; + ec_enc_normalize(_this); +} + void ec_enc_bits(ec_enc *_this,unsigned _fl,unsigned bits){ _this->nb_end_bits += bits; while (bits >= _this->end_bits_left) diff --git a/libcelt/rate.c b/libcelt/rate.c index 702378aa..514562c8 100644 --- a/libcelt/rate.c +++ b/libcelt/rate.c @@ -245,11 +245,11 @@ static inline int interp_bits2pulses(const CELTMode *m, int start, int end, int fluctuating in and out.*/ if (band_bits > ((j>4) { - ec_enc_bit_prob((ec_enc *)ec, 1, 32768); + ec_enc_bit_logp((ec_enc *)ec, 1, 1); break; } - ec_enc_bit_prob((ec_enc *)ec, 0, 32768); - } else if (ec_dec_bit_prob((ec_dec *)ec, 32768)) { + ec_enc_bit_logp((ec_enc *)ec, 0, 1); + } else if (ec_dec_bit_logp((ec_dec *)ec, 1)) { break; } /*We used a bit to skip this band.*/