mirror of
https://github.com/xiph/opus.git
synced 2025-05-15 07:58:29 +00:00
More general Laplace encoder
This commit is contained in:
parent
4414db08f9
commit
59dce643b1
5 changed files with 153 additions and 0 deletions
|
@ -195,6 +195,27 @@ int ec_dec_icdf(ec_dec *_this,const unsigned char *_icdf,unsigned _ftb){
|
|||
return ret;
|
||||
}
|
||||
|
||||
int ec_dec_icdf16(ec_dec *_this,const opus_uint16 *_icdf,unsigned _ftb){
|
||||
opus_uint32 r;
|
||||
opus_uint32 d;
|
||||
opus_uint32 s;
|
||||
opus_uint32 t;
|
||||
int ret;
|
||||
s=_this->rng;
|
||||
d=_this->val;
|
||||
r=s>>_ftb;
|
||||
ret=-1;
|
||||
do{
|
||||
t=s;
|
||||
s=IMUL32(r,_icdf[++ret]);
|
||||
}
|
||||
while(d<s);
|
||||
_this->val=d-s;
|
||||
_this->rng=t-s;
|
||||
ec_dec_normalize(_this);
|
||||
return ret;
|
||||
}
|
||||
|
||||
opus_uint32 ec_dec_uint(ec_dec *_this,opus_uint32 _ft){
|
||||
unsigned ft;
|
||||
unsigned s;
|
||||
|
|
|
@ -81,6 +81,16 @@ int ec_dec_bit_logp(ec_dec *_this,unsigned _logp);
|
|||
Return: The decoded symbol s.*/
|
||||
int ec_dec_icdf(ec_dec *_this,const unsigned char *_icdf,unsigned _ftb);
|
||||
|
||||
/*Decodes a symbol given an "inverse" CDF table.
|
||||
No call to ec_dec_update() is necessary after this call.
|
||||
_icdf: The "inverse" CDF, such that symbol s falls in the range
|
||||
[s>0?ft-_icdf[s-1]:0,ft-_icdf[s]), where ft=1<<_ftb.
|
||||
The values must be monotonically non-increasing, and the last value
|
||||
must be 0.
|
||||
_ftb: The number of bits of precision in the cumulative distribution.
|
||||
Return: The decoded symbol s.*/
|
||||
int ec_dec_icdf16(ec_dec *_this,const opus_uint16 *_icdf,unsigned _ftb);
|
||||
|
||||
/*Extracts a raw unsigned integer with a non-power-of-2 range from the stream.
|
||||
The bits must have been encoded with ec_enc_uint().
|
||||
No call to ec_dec_update() is necessary after this call.
|
||||
|
|
|
@ -172,6 +172,17 @@ void ec_enc_icdf(ec_enc *_this,int _s,const unsigned char *_icdf,unsigned _ftb){
|
|||
ec_enc_normalize(_this);
|
||||
}
|
||||
|
||||
void ec_enc_icdf16(ec_enc *_this,int _s,const opus_uint16 *_icdf,unsigned _ftb){
|
||||
opus_uint32 r;
|
||||
r=_this->rng>>_ftb;
|
||||
if(_s>0){
|
||||
_this->val+=_this->rng-IMUL32(r,_icdf[_s-1]);
|
||||
_this->rng=IMUL32(r,_icdf[_s-1]-_icdf[_s]);
|
||||
}
|
||||
else _this->rng-=IMUL32(r,_icdf[_s]);
|
||||
ec_enc_normalize(_this);
|
||||
}
|
||||
|
||||
void ec_enc_uint(ec_enc *_this,opus_uint32 _fl,opus_uint32 _ft){
|
||||
unsigned ft;
|
||||
unsigned fl;
|
||||
|
|
|
@ -64,6 +64,15 @@ void ec_enc_bit_logp(ec_enc *_this,int _val,unsigned _logp);
|
|||
_ftb: The number of bits of precision in the cumulative distribution.*/
|
||||
void ec_enc_icdf(ec_enc *_this,int _s,const unsigned char *_icdf,unsigned _ftb);
|
||||
|
||||
/*Encodes a symbol given an "inverse" CDF table.
|
||||
_s: The index of the symbol to encode.
|
||||
_icdf: The "inverse" CDF, such that symbol _s falls in the range
|
||||
[_s>0?ft-_icdf[_s-1]:0,ft-_icdf[_s]), where ft=1<<_ftb.
|
||||
The values must be monotonically non-increasing, and the last value
|
||||
must be 0.
|
||||
_ftb: The number of bits of precision in the cumulative distribution.*/
|
||||
void ec_enc_icdf16(ec_enc *_this,int _s,const opus_uint16 *_icdf,unsigned _ftb);
|
||||
|
||||
/*Encodes a raw unsigned integer in the stream.
|
||||
_fl: The integer to encode.
|
||||
_ft: The number of integers that can be encoded (one more than the max).
|
||||
|
|
102
celt/laplace.c
102
celt/laplace.c
|
@ -132,3 +132,105 @@ int ec_laplace_decode(ec_dec *dec, unsigned fs, int decay)
|
|||
ec_dec_update(dec, fl, IMIN(fl+fs,32768), 32768);
|
||||
return val;
|
||||
}
|
||||
|
||||
|
||||
void ec_laplace_encode_p0(ec_enc *enc, int value, opus_uint16 p0, opus_uint16 decay)
|
||||
{
|
||||
int s;
|
||||
opus_uint16 sign_icdf[3];
|
||||
sign_icdf[0] = 32768-p0;
|
||||
sign_icdf[1] = sign_icdf[0]/2;
|
||||
sign_icdf[2] = 0;
|
||||
s = value == 0 ? 0 : (value > 0 ? 1 : 2);
|
||||
ec_enc_icdf16(enc, s, sign_icdf, 15);
|
||||
value = abs(value);
|
||||
if (value)
|
||||
{
|
||||
int i;
|
||||
opus_uint16 icdf[8];
|
||||
icdf[0] = decay;
|
||||
for (i=1;i<7;i++)
|
||||
{
|
||||
icdf[i] = IMAX(7-i, (icdf[i-1] * (opus_int32)decay) >> 15);
|
||||
}
|
||||
icdf[7] = 0;
|
||||
value--;
|
||||
do {
|
||||
ec_enc_icdf16(enc, IMIN(value, 7), icdf, 15);
|
||||
value -= 7;
|
||||
} while (value >= 0);
|
||||
}
|
||||
}
|
||||
|
||||
int ec_laplace_decode_p0(ec_dec *dec, opus_uint16 p0, opus_uint16 decay)
|
||||
{
|
||||
int s;
|
||||
int value;
|
||||
opus_uint16 sign_icdf[3];
|
||||
sign_icdf[0] = 32768-p0;
|
||||
sign_icdf[1] = sign_icdf[0]/2;
|
||||
sign_icdf[2] = 0;
|
||||
s = ec_dec_icdf16(dec, sign_icdf, 15);
|
||||
if (s==2) s = -1;
|
||||
if (s != 0)
|
||||
{
|
||||
int i;
|
||||
int v;
|
||||
opus_uint16 icdf[8];
|
||||
icdf[0] = decay;
|
||||
for (i=1;i<7;i++)
|
||||
{
|
||||
icdf[i] = IMAX(7-i, (icdf[i-1] * (opus_int32)decay) >> 15);
|
||||
}
|
||||
icdf[7] = 0;
|
||||
value = 1;
|
||||
do {
|
||||
v = ec_dec_icdf16(dec, icdf, 15);
|
||||
value += v;
|
||||
} while (v == 7);
|
||||
return s*value;
|
||||
} else return 0;
|
||||
}
|
||||
|
||||
#if 0
|
||||
|
||||
#include <stdio.h>
|
||||
#define NB_VALS 10
|
||||
#define DATA_SIZE 10000
|
||||
int main() {
|
||||
ec_enc enc;
|
||||
ec_dec dec;
|
||||
unsigned char *ptr;
|
||||
int i;
|
||||
int decay, p0;
|
||||
int val[NB_VALS] = {6, 7, 8, 9, 10, 11, 12, 13, 14, 15};
|
||||
/*for (i=0;i<NB_VALS;i++) {
|
||||
val[i] = -log(rand()/(float)RAND_MAX);
|
||||
if (rand()%2) val[i] = -val[i];
|
||||
}*/
|
||||
p0 = 16000;
|
||||
decay = 16000;
|
||||
ptr = (unsigned char *)malloc(DATA_SIZE);
|
||||
ec_enc_init(&enc,ptr,DATA_SIZE);
|
||||
for (i=0;i<NB_VALS;i++) {
|
||||
printf("%d ", val[i]);
|
||||
}
|
||||
printf("\n");
|
||||
for (i=0;i<NB_VALS;i++) {
|
||||
ec_laplace_encode_p0(&enc, val[i], p0, decay);
|
||||
}
|
||||
|
||||
ec_enc_done(&enc);
|
||||
|
||||
ec_dec_init(&dec,ec_get_buffer(&enc),ec_range_bytes(&enc));
|
||||
|
||||
for (i=0;i<NB_VALS;i++) {
|
||||
val[i] = ec_laplace_decode_p0(&dec, p0, decay);
|
||||
}
|
||||
for (i=0;i<NB_VALS;i++) {
|
||||
printf("%d ", val[i]);
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue