|
Packit |
664db3 |
/* (C) 2007 Jean-Marc Valin, CSIRO
|
|
Packit |
664db3 |
*/
|
|
Packit |
664db3 |
/*
|
|
Packit |
664db3 |
Redistribution and use in source and binary forms, with or without
|
|
Packit |
664db3 |
modification, are permitted provided that the following conditions
|
|
Packit |
664db3 |
are met:
|
|
Packit |
664db3 |
|
|
Packit |
664db3 |
- Redistributions of source code must retain the above copyright
|
|
Packit |
664db3 |
notice, this list of conditions and the following disclaimer.
|
|
Packit |
664db3 |
|
|
Packit |
664db3 |
- Redistributions in binary form must reproduce the above copyright
|
|
Packit |
664db3 |
notice, this list of conditions and the following disclaimer in the
|
|
Packit |
664db3 |
documentation and/or other materials provided with the distribution.
|
|
Packit |
664db3 |
|
|
Packit |
664db3 |
- Neither the name of the Xiph.org Foundation nor the names of its
|
|
Packit |
664db3 |
contributors may be used to endorse or promote products derived from
|
|
Packit |
664db3 |
this software without specific prior written permission.
|
|
Packit |
664db3 |
|
|
Packit |
664db3 |
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
Packit |
664db3 |
``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
Packit |
664db3 |
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
|
Packit |
664db3 |
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR
|
|
Packit |
664db3 |
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
|
Packit |
664db3 |
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
|
Packit |
664db3 |
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
|
Packit |
664db3 |
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
|
Packit |
664db3 |
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
|
Packit |
664db3 |
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
|
Packit |
664db3 |
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
Packit |
664db3 |
*/
|
|
Packit |
664db3 |
|
|
Packit |
664db3 |
#ifdef HAVE_CONFIG_H
|
|
Packit |
664db3 |
#include "config.h"
|
|
Packit |
664db3 |
#endif
|
|
Packit |
664db3 |
|
|
Packit |
664db3 |
#include "laplace.h"
|
|
Packit |
664db3 |
|
|
Packit |
664db3 |
int ec_laplace_get_start_freq(int decay)
|
|
Packit |
664db3 |
{
|
|
Packit |
664db3 |
return (((ec_uint32)32767)*(16384-decay))/(16384+decay);
|
|
Packit |
664db3 |
}
|
|
Packit |
664db3 |
|
|
Packit |
664db3 |
void ec_laplace_encode_start(ec_enc *enc, int *value, int decay, int fs)
|
|
Packit |
664db3 |
{
|
|
Packit |
664db3 |
int i;
|
|
Packit |
664db3 |
int fl, ft;
|
|
Packit |
664db3 |
int s = 0;
|
|
Packit |
664db3 |
int val = *value;
|
|
Packit |
664db3 |
if (val < 0)
|
|
Packit |
664db3 |
{
|
|
Packit |
664db3 |
s = 1;
|
|
Packit |
664db3 |
val = -val;
|
|
Packit |
664db3 |
}
|
|
Packit |
664db3 |
ft = 32767;
|
|
Packit |
664db3 |
fl = -fs;
|
|
Packit |
664db3 |
for (i=0;i
|
|
Packit |
664db3 |
{
|
|
Packit |
664db3 |
int tmp_l, tmp_s;
|
|
Packit |
664db3 |
tmp_l = fl;
|
|
Packit |
664db3 |
tmp_s = fs;
|
|
Packit |
664db3 |
fl += fs*2;
|
|
Packit |
664db3 |
fs = (fs*(ec_int32)decay)>>14;
|
|
Packit |
664db3 |
if (fs == 0)
|
|
Packit |
664db3 |
{
|
|
Packit |
664db3 |
fs = tmp_s;
|
|
Packit |
664db3 |
fl = tmp_l;
|
|
Packit |
664db3 |
if (s)
|
|
Packit |
664db3 |
*value = -i;
|
|
Packit |
664db3 |
else
|
|
Packit |
664db3 |
*value = i;
|
|
Packit |
664db3 |
break;
|
|
Packit |
664db3 |
}
|
|
Packit |
664db3 |
}
|
|
Packit |
664db3 |
if (fl < 0)
|
|
Packit |
664db3 |
fl = 0;
|
|
Packit |
664db3 |
if (s)
|
|
Packit |
664db3 |
fl += fs;
|
|
Packit |
664db3 |
/*DEBUG*/
|
|
Packit |
664db3 |
/*printf ("enc: %d %d %d\n", fl, fs, ft);*/
|
|
Packit |
664db3 |
ec_encode(enc, fl, fl+fs, ft);
|
|
Packit |
664db3 |
}
|
|
Packit |
664db3 |
|
|
Packit |
664db3 |
void ec_laplace_encode(ec_enc *enc, int *value, int decay)
|
|
Packit |
664db3 |
{
|
|
Packit |
664db3 |
int fs = ec_laplace_get_start_freq(decay);
|
|
Packit |
664db3 |
ec_laplace_encode_start(enc, value, decay, fs);
|
|
Packit |
664db3 |
}
|
|
Packit |
664db3 |
|
|
Packit |
664db3 |
|
|
Packit |
664db3 |
int ec_laplace_decode_start(ec_dec *dec, int decay, int fs)
|
|
Packit |
664db3 |
{
|
|
Packit |
664db3 |
int val=0;
|
|
Packit |
664db3 |
int fl, fh, ft, fm;
|
|
Packit |
664db3 |
fl = 0;
|
|
Packit |
664db3 |
ft = 32767;
|
|
Packit |
664db3 |
fh = fs;
|
|
Packit |
664db3 |
fm = ec_decode(dec, ft);
|
|
Packit |
664db3 |
/*DEBUG*/
|
|
Packit |
664db3 |
/*printf ("fm: %d/%d\n", fm, ft);*/
|
|
Packit |
664db3 |
while (fm >= fh && fs != 0)
|
|
Packit |
664db3 |
{
|
|
Packit |
664db3 |
fl = fh;
|
|
Packit |
664db3 |
fs = (fs*(ec_int32)decay)>>14;
|
|
Packit |
664db3 |
fh += fs*2;
|
|
Packit |
664db3 |
val++;
|
|
Packit |
664db3 |
}
|
|
Packit |
664db3 |
if (fl>0)
|
|
Packit |
664db3 |
{
|
|
Packit |
664db3 |
if (fm >= fl+fs)
|
|
Packit |
664db3 |
{
|
|
Packit |
664db3 |
val = -val;
|
|
Packit |
664db3 |
fl += fs;
|
|
Packit |
664db3 |
} else {
|
|
Packit |
664db3 |
fh -= fs;
|
|
Packit |
664db3 |
}
|
|
Packit |
664db3 |
}
|
|
Packit |
664db3 |
/* Preventing an infinite loop in case something screws up in the decoding */
|
|
Packit |
664db3 |
if (fl==fh)
|
|
Packit |
664db3 |
fl--;
|
|
Packit |
664db3 |
/*DEBUG*/
|
|
Packit |
664db3 |
/*printf ("update: %d %d %d\n", fl, fh, ft);*/
|
|
Packit |
664db3 |
ec_dec_update(dec, fl, fh, ft);
|
|
Packit |
664db3 |
return val;
|
|
Packit |
664db3 |
}
|
|
Packit |
664db3 |
|
|
Packit |
664db3 |
int ec_laplace_decode(ec_dec *dec, int decay)
|
|
Packit |
664db3 |
{
|
|
Packit |
664db3 |
int fs = ec_laplace_get_start_freq(decay);
|
|
Packit |
664db3 |
return ec_laplace_decode_start(dec, decay, fs);
|
|
Packit |
664db3 |
}
|