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.
This commit is contained in:
Timothy B. Terriberry 2010-12-17 14:50:19 -08:00 committed by Jean-Marc Valin
parent 8c23a3a0fd
commit e86fb268b0
8 changed files with 61 additions and 25 deletions

View file

@ -675,9 +675,9 @@ static void quant_band(int encode, const CELTMode *m, int i, celt_norm *X, celt_
if (b>2<<BITRES && *remaining_bits > 2<<BITRES) if (b>2<<BITRES && *remaining_bits > 2<<BITRES)
{ {
if (encode) if (encode)
ec_enc_bit_prob(ec, inv, 16384); ec_enc_bit_logp(ec, inv, 2);
else else
inv = ec_dec_bit_prob(ec, 16384); inv = ec_dec_bit_logp(ec, 2);
qalloc = inv ? 16 : 4; qalloc = inv ? 16 : 4;
} else } else
inv = 0; inv = 0;

View file

@ -592,11 +592,11 @@ static int tf_analysis(const CELTMode *m, celt_word16 *bandLogE, celt_word16 *ol
static void tf_encode(int start, int end, int isTransient, int *tf_res, int LM, int tf_select, ec_enc *enc) static void tf_encode(int start, int end, int isTransient, int *tf_res, int LM, int tf_select, ec_enc *enc)
{ {
int curr, i; int curr, i;
ec_enc_bit_prob(enc, tf_res[start], isTransient ? 16384 : 4096); ec_enc_bit_logp(enc, tf_res[start], isTransient ? 2 : 4);
curr = tf_res[start]; curr = tf_res[start];
for (i=start+1;i<end;i++) for (i=start+1;i<end;i++)
{ {
ec_enc_bit_prob(enc, tf_res[i] ^ curr, isTransient ? 4096 : 2048); ec_enc_bit_logp(enc, tf_res[i] ^ curr, isTransient ? 4 : 5);
curr = tf_res[i]; curr = tf_res[i];
} }
if (LM!=0) if (LM!=0)
@ -609,11 +609,11 @@ static void tf_encode(int start, int end, int isTransient, int *tf_res, int LM,
static void tf_decode(int start, int end, int C, int isTransient, int *tf_res, int LM, ec_dec *dec) static void tf_decode(int start, int end, int C, int isTransient, int *tf_res, int LM, ec_dec *dec)
{ {
int i, curr, tf_select; int i, curr, tf_select;
tf_res[start] = ec_dec_bit_prob(dec, isTransient ? 16384 : 4096); tf_res[start] = ec_dec_bit_logp(dec, isTransient ? 2 : 4);
curr = tf_res[start]; curr = tf_res[start];
for (i=start+1;i<end;i++) for (i=start+1;i<end;i++)
{ {
tf_res[i] = ec_dec_bit_prob(dec, isTransient ? 4096 : 2048) ^ curr; tf_res[i] = ec_dec_bit_logp(dec, isTransient ? 4 : 5) ^ curr;
curr = tf_res[i]; curr = tf_res[i];
} }
if (LM!=0) if (LM!=0)
@ -850,7 +850,7 @@ int celt_encode_with_ec_float(CELTEncoder * restrict st, const celt_sig * pcm, i
} }
if (gain1<QCONST16(.2f,15) || (nbAvailableBytes<30 && gain1<QCONST16(.4f,15))) if (gain1<QCONST16(.2f,15) || (nbAvailableBytes<30 && gain1<QCONST16(.4f,15)))
{ {
ec_enc_bit_prob(enc, 0, 32768); ec_enc_bit_logp(enc, 0, 1);
gain1 = 0; gain1 = 0;
} else { } else {
int qg; int qg;
@ -860,7 +860,7 @@ int celt_encode_with_ec_float(CELTEncoder * restrict st, const celt_sig * pcm, i
#else #else
qg = floor(.5+gain1*8)-2; qg = floor(.5+gain1*8)-2;
#endif #endif
ec_enc_bit_prob(enc, 1, 32768); ec_enc_bit_logp(enc, 1, 1);
octave = EC_ILOG(pitch_index)-5; octave = EC_ILOG(pitch_index)-5;
ec_enc_uint(enc, octave, 6); ec_enc_uint(enc, octave, 6);
ec_enc_bits(enc, pitch_index-(16<<octave), 4+octave); ec_enc_bits(enc, pitch_index-(16<<octave), 4+octave);
@ -869,7 +869,7 @@ int celt_encode_with_ec_float(CELTEncoder * restrict st, const celt_sig * pcm, i
} }
/*printf("%d %f\n", pitch_index, gain1);*/ /*printf("%d %f\n", pitch_index, gain1);*/
#else /* ENABLE_POSTFILTER */ #else /* ENABLE_POSTFILTER */
ec_enc_bit_prob(enc, 0, 32768); ec_enc_bit_logp(enc, 0, 1);
#endif /* ENABLE_POSTFILTER */ #endif /* ENABLE_POSTFILTER */
c=0; do { c=0; do {
@ -942,7 +942,7 @@ int celt_encode_with_ec_float(CELTEncoder * restrict st, const celt_sig * pcm, i
&st->delayedIntra, st->complexity >= 4); &st->delayedIntra, st->complexity >= 4);
if (LM > 0) 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); 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;i<st->mode->nbEBands;i++) for (i=0;i<st->mode->nbEBands;i++)
{ {
int j; int j;
ec_enc_bit_prob(enc, offsets[i]!=0, 1024); ec_enc_bit_logp(enc, offsets[i]!=0, 6);
if (offsets[i]!=0) if (offsets[i]!=0)
{ {
for (j=0;j<offsets[i]-1;j++) for (j=0;j<offsets[i]-1;j++)
ec_enc_bit_prob(enc, 1, 32768); ec_enc_bit_logp(enc, 1, 1);
ec_enc_bit_prob(enc, 0, 32768); ec_enc_bit_logp(enc, 0, 1);
} }
offsets[i] *= (6<<BITRES); offsets[i] *= (6<<BITRES);
} }
@ -1088,7 +1088,7 @@ int celt_encode_with_ec_float(CELTEncoder * restrict st, const celt_sig * pcm, i
dual_stereo = 0; dual_stereo = 0;
else else
dual_stereo = stereo_analysis(st->mode, X, st->mode->nbEBands, LM, C, N); dual_stereo = stereo_analysis(st->mode, 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) if (C==2)
{ {
@ -1786,7 +1786,7 @@ int celt_decode_with_ec_float(CELTDecoder * restrict st, const unsigned char *da
} }
nbAvailableBytes = len-nbFilledBytes; nbAvailableBytes = len-nbFilledBytes;
if (ec_dec_bit_prob(dec, 32768)) if (ec_dec_bit_logp(dec, 1))
{ {
#ifdef ENABLE_POSTFILTER #ifdef ENABLE_POSTFILTER
int qg, octave; 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) */ /* 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 */ /* Get band energies */
unquant_coarse_energy(st->mode, st->start, st->end, bandE, oldBandE, unquant_coarse_energy(st->mode, st->start, st->end, bandE, oldBandE,
intra_ener, dec, C, LM); intra_ener, dec, C, LM);
if (LM > 0) if (LM > 0)
isTransient = ec_dec_bit_prob(dec, 8192); isTransient = ec_dec_bit_logp(dec, 3);
else else
isTransient = 0; isTransient = 0;
@ -1833,9 +1833,9 @@ int celt_decode_with_ec_float(CELTDecoder * restrict st, const unsigned char *da
offsets[i] = 0; offsets[i] = 0;
for (i=0;i<st->mode->nbEBands;i++) for (i=0;i<st->mode->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]++; offsets[i]++;
offsets[i] *= (6<<BITRES); offsets[i] *= (6<<BITRES);
@ -1847,7 +1847,7 @@ int celt_decode_with_ec_float(CELTDecoder * restrict st, const unsigned char *da
if (C==2) if (C==2)
{ {
dual_stereo = ec_dec_bit_prob(dec, 32768); dual_stereo = ec_dec_bit_logp(dec, 1);
intensity = ec_dec_uint(dec, 1+st->end-st->start); intensity = ec_dec_uint(dec, 1+st->end-st->start);
} }

View file

@ -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 */ /* Decode a bit that has a _prob/65536 probability of being a one */
int ec_dec_bit_prob(ec_dec *_this,unsigned _prob); 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. /*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 This same number can be computed by the encoder, and is suitable for making
coding decisions. coding decisions.

View file

@ -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 */ /* 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); 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. /*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 This same number can be computed by the decoder, and is suitable for making
coding decisions. coding decisions.

View file

@ -163,7 +163,7 @@ static void quant_coarse_energy_impl(const CELTMode *m, int start, int end,
celt_word16 coef; celt_word16 coef;
celt_word16 beta; celt_word16 beta;
ec_enc_bit_prob(enc, intra, 8192); ec_enc_bit_logp(enc, intra, 3);
if (intra) if (intra)
{ {
coef = 0; coef = 0;

View file

@ -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.*/ /*The probability of having a "one" is given in 1/65536.*/
int ec_dec_bit_prob(ec_dec *_this,unsigned _prob){ int ec_dec_bit_prob(ec_dec *_this,unsigned _prob){
ec_uint32 r; ec_uint32 r;
ec_uint32 s;
ec_uint32 d; ec_uint32 d;
ec_uint32 s;
int val; int val;
r=_this->rng; r=_this->rng;
d=_this->dif; d=_this->dif;
@ -203,6 +203,22 @@ int ec_dec_bit_prob(ec_dec *_this,unsigned _prob){
return val; 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=d<s;
if(!val)_this->dif=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){ int ec_dec_cdf(ec_dec *_this,const int *_cdf,unsigned _ftb){
ec_uint32 r; ec_uint32 r;
ec_uint32 d; ec_uint32 d;

View file

@ -153,6 +153,20 @@ void ec_enc_bit_prob(ec_enc *_this,int _val,unsigned _prob){
ec_enc_normalize(_this); 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){ void ec_enc_bits(ec_enc *_this,unsigned _fl,unsigned bits){
_this->nb_end_bits += bits; _this->nb_end_bits += bits;
while (bits >= _this->end_bits_left) while (bits >= _this->end_bits_left)

View file

@ -245,11 +245,11 @@ static inline int interp_bits2pulses(const CELTMode *m, int start, int end, int
fluctuating in and out.*/ fluctuating in and out.*/
if (band_bits > ((j<prev?7:9)*band_width<<LM<<BITRES)>>4) if (band_bits > ((j<prev?7:9)*band_width<<LM<<BITRES)>>4)
{ {
ec_enc_bit_prob((ec_enc *)ec, 1, 32768); ec_enc_bit_logp((ec_enc *)ec, 1, 1);
break; break;
} }
ec_enc_bit_prob((ec_enc *)ec, 0, 32768); ec_enc_bit_logp((ec_enc *)ec, 0, 1);
} else if (ec_dec_bit_prob((ec_dec *)ec, 32768)) { } else if (ec_dec_bit_logp((ec_dec *)ec, 1)) {
break; break;
} }
/*We used a bit to skip this band.*/ /*We used a bit to skip this band.*/