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 (encode)
ec_enc_bit_prob(ec, inv, 16384);
ec_enc_bit_logp(ec, inv, 2);
else
inv = ec_dec_bit_prob(ec, 16384);
inv = ec_dec_bit_logp(ec, 2);
qalloc = inv ? 16 : 4;
} else
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)
{
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];
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];
}
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)
{
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];
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];
}
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)))
{
ec_enc_bit_prob(enc, 0, 32768);
ec_enc_bit_logp(enc, 0, 1);
gain1 = 0;
} else {
int qg;
@ -860,7 +860,7 @@ int celt_encode_with_ec_float(CELTEncoder * restrict st, const celt_sig * pcm, i
#else
qg = floor(.5+gain1*8)-2;
#endif
ec_enc_bit_prob(enc, 1, 32768);
ec_enc_bit_logp(enc, 1, 1);
octave = EC_ILOG(pitch_index)-5;
ec_enc_uint(enc, octave, 6);
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);*/
#else /* ENABLE_POSTFILTER */
ec_enc_bit_prob(enc, 0, 32768);
ec_enc_bit_logp(enc, 0, 1);
#endif /* ENABLE_POSTFILTER */
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);
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;i<st->mode->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;j<offsets[i]-1;j++)
ec_enc_bit_prob(enc, 1, 32768);
ec_enc_bit_prob(enc, 0, 32768);
ec_enc_bit_logp(enc, 1, 1);
ec_enc_bit_logp(enc, 0, 1);
}
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;
else
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)
{
@ -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;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] *= (6<<BITRES);
@ -1847,7 +1847,7 @@ int celt_decode_with_ec_float(CELTDecoder * restrict st, const unsigned char *da
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);
}

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 */
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.

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 */
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.

View file

@ -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;

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.*/
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=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){
ec_uint32 r;
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);
}
/*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)

View file

@ -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<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;
}
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.*/