summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJean-Marc Valin <jmvalin@amazon.com>2022-09-15 14:38:13 -0400
committerJean-Marc Valin <jmvalin@amazon.com>2022-09-15 14:40:55 -0400
commit0dec778663568e38b595c1cd2ee555784925b60d (patch)
treea0ca94bd9c7c76001e5d2b4a93045809f2ed2dd4
parent2d81acb712a10e63133296bd2eb9700c2275233b (diff)
downloadopus-exp_neural_fec2.tar.gz
More general Laplace encoderexp_neural_fec2
-rw-r--r--celt/entdec.c21
-rw-r--r--celt/entdec.h10
-rw-r--r--celt/entenc.c11
-rw-r--r--celt/entenc.h9
-rw-r--r--celt/laplace.c102
5 files changed, 153 insertions, 0 deletions
diff --git a/celt/entdec.c b/celt/entdec.c
index 0b3433ed..027aa24b 100644
--- a/celt/entdec.c
+++ b/celt/entdec.c
@@ -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;
diff --git a/celt/entdec.h b/celt/entdec.h
index 025fc187..c81f26fd 100644
--- a/celt/entdec.h
+++ b/celt/entdec.h
@@ -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.
diff --git a/celt/entenc.c b/celt/entenc.c
index f1750d25..69c6f835 100644
--- a/celt/entenc.c
+++ b/celt/entenc.c
@@ -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;
diff --git a/celt/entenc.h b/celt/entenc.h
index f502eaf6..010874bb 100644
--- a/celt/entenc.h
+++ b/celt/entenc.h
@@ -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).
diff --git a/celt/laplace.c b/celt/laplace.c
index a7bca874..3c45c3eb 100644
--- a/celt/laplace.c
+++ b/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