Line data Source code
1 : /* Copyright (c) 2007 CSIRO
2 : Copyright (c) 2007-2009 Xiph.Org Foundation
3 : Written by Jean-Marc Valin */
4 : /*
5 : Redistribution and use in source and binary forms, with or without
6 : modification, are permitted provided that the following conditions
7 : are met:
8 :
9 : - Redistributions of source code must retain the above copyright
10 : notice, this list of conditions and the following disclaimer.
11 :
12 : - Redistributions in binary form must reproduce the above copyright
13 : notice, this list of conditions and the following disclaimer in the
14 : documentation and/or other materials provided with the distribution.
15 :
16 : THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 : ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18 : LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19 : A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
20 : OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
21 : EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
22 : PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
23 : PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
24 : LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
25 : NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
26 : SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 : */
28 :
29 : #ifdef HAVE_CONFIG_H
30 : #include "config.h"
31 : #endif
32 :
33 : #include "laplace.h"
34 : #include "mathops.h"
35 :
36 : /* The minimum probability of an energy delta (out of 32768). */
37 : #define LAPLACE_LOG_MINP (0)
38 : #define LAPLACE_MINP (1<<LAPLACE_LOG_MINP)
39 : /* The minimum number of guaranteed representable energy deltas (in one
40 : direction). */
41 : #define LAPLACE_NMIN (16)
42 :
43 : /* When called, decay is positive and at most 11456. */
44 0 : static unsigned ec_laplace_get_freq1(unsigned fs0, int decay)
45 : {
46 : unsigned ft;
47 0 : ft = 32768 - LAPLACE_MINP*(2*LAPLACE_NMIN) - fs0;
48 0 : return ft*(opus_int32)(16384-decay)>>15;
49 : }
50 :
51 0 : void ec_laplace_encode(ec_enc *enc, int *value, unsigned fs, int decay)
52 : {
53 : unsigned fl;
54 0 : int val = *value;
55 0 : fl = 0;
56 0 : if (val)
57 : {
58 : int s;
59 : int i;
60 0 : s = -(val<0);
61 0 : val = (val+s)^s;
62 0 : fl = fs;
63 0 : fs = ec_laplace_get_freq1(fs, decay);
64 : /* Search the decaying part of the PDF.*/
65 0 : for (i=1; fs > 0 && i < val; i++)
66 : {
67 0 : fs *= 2;
68 0 : fl += fs+2*LAPLACE_MINP;
69 0 : fs = (fs*(opus_int32)decay)>>15;
70 : }
71 : /* Everything beyond that has probability LAPLACE_MINP. */
72 0 : if (!fs)
73 : {
74 : int di;
75 : int ndi_max;
76 0 : ndi_max = (32768-fl+LAPLACE_MINP-1)>>LAPLACE_LOG_MINP;
77 0 : ndi_max = (ndi_max-s)>>1;
78 0 : di = IMIN(val - i, ndi_max - 1);
79 0 : fl += (2*di+1+s)*LAPLACE_MINP;
80 0 : fs = IMIN(LAPLACE_MINP, 32768-fl);
81 0 : *value = (i+di+s)^s;
82 : }
83 : else
84 : {
85 0 : fs += LAPLACE_MINP;
86 0 : fl += fs&~s;
87 : }
88 0 : celt_assert(fl+fs<=32768);
89 0 : celt_assert(fs>0);
90 : }
91 0 : ec_encode_bin(enc, fl, fl+fs, 15);
92 0 : }
93 :
94 0 : int ec_laplace_decode(ec_dec *dec, unsigned fs, int decay)
95 : {
96 0 : int val=0;
97 : unsigned fl;
98 : unsigned fm;
99 0 : fm = ec_decode_bin(dec, 15);
100 0 : fl = 0;
101 0 : if (fm >= fs)
102 : {
103 0 : val++;
104 0 : fl = fs;
105 0 : fs = ec_laplace_get_freq1(fs, decay)+LAPLACE_MINP;
106 : /* Search the decaying part of the PDF.*/
107 0 : while(fs > LAPLACE_MINP && fm >= fl+2*fs)
108 : {
109 0 : fs *= 2;
110 0 : fl += fs;
111 0 : fs = ((fs-2*LAPLACE_MINP)*(opus_int32)decay)>>15;
112 0 : fs += LAPLACE_MINP;
113 0 : val++;
114 : }
115 : /* Everything beyond that has probability LAPLACE_MINP. */
116 0 : if (fs <= LAPLACE_MINP)
117 : {
118 : int di;
119 0 : di = (fm-fl)>>(LAPLACE_LOG_MINP+1);
120 0 : val += di;
121 0 : fl += 2*di*LAPLACE_MINP;
122 : }
123 0 : if (fm < fl+fs)
124 0 : val = -val;
125 : else
126 0 : fl += fs;
127 : }
128 0 : celt_assert(fl<32768);
129 0 : celt_assert(fs>0);
130 0 : celt_assert(fl<=fm);
131 0 : celt_assert(fm<IMIN(fl+fs,32768));
132 0 : ec_dec_update(dec, fl, IMIN(fl+fs,32768), 32768);
133 0 : return val;
134 : }
|