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