Improves fixed-point precision for quant_coarse_energy
[opus.git] / libcelt / quant_bands.c
1 /* Copyright (c) 2007-2008 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    - Neither the name of the Xiph.org Foundation nor the names of its
17    contributors may be used to endorse or promote products derived from
18    this software without specific prior written permission.
19    
20    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21    ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22    LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
23    A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR
24    CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
25    EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
26    PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
27    PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
28    LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
29    NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
30    SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 */
32
33 #ifdef HAVE_CONFIG_H
34 #include "config.h"
35 #endif
36
37 #include "quant_bands.h"
38 #include "laplace.h"
39 #include <math.h>
40 #include "os_support.h"
41 #include "arch.h"
42 #include "mathops.h"
43 #include "stack_alloc.h"
44
45 #define E_MEANS_SIZE (5)
46
47 #ifdef FIXED_POINT
48 const celt_word16 eMeans[E_MEANS_SIZE] = {1920, -341, -512, -107, 43};
49 #else
50 const celt_word16 eMeans[E_MEANS_SIZE] = {7.5f, -1.33f, -2.f, -0.42f, 0.17f};
51 #endif
52
53 /* FIXME: Implement for stereo */
54 int intra_decision(celt_word16 *eBands, celt_word16 *oldEBands, int len)
55 {
56    int i;
57    celt_word32 dist = 0;
58    for (i=0;i<len;i++)
59    {
60       celt_word16 d = SUB16(eBands[i], oldEBands[i]);
61       dist = MAC16_16(dist, d,d);
62    }
63    return SHR32(dist,16) > 2*len;
64 }
65
66 int *quant_prob_alloc(const CELTMode *m)
67 {
68    int i;
69    int *prob;
70    prob = celt_alloc(4*m->nbEBands*sizeof(int));
71    if (prob==NULL)
72      return NULL;
73    for (i=0;i<m->nbEBands;i++)
74    {
75       prob[2*i] = 6000-i*200;
76       prob[2*i+1] = ec_laplace_get_start_freq(prob[2*i]);
77    }
78    for (i=0;i<m->nbEBands;i++)
79    {
80       prob[2*m->nbEBands+2*i] = 9000-i*240;
81       prob[2*m->nbEBands+2*i+1] = ec_laplace_get_start_freq(prob[2*m->nbEBands+2*i]);
82    }
83    return prob;
84 }
85
86 void quant_prob_free(int *freq)
87 {
88    celt_free(freq);
89 }
90
91 unsigned quant_coarse_energy(const CELTMode *m, int start, celt_word16 *eBands, celt_word16 *oldEBands, int budget, int intra, int *prob, celt_word16 *error, ec_enc *enc, int _C)
92 {
93    int i, c;
94    unsigned bits_used = 0;
95    celt_word16 prev[2] = {0,0};
96    celt_word16 coef = m->ePredCoef;
97    celt_word16 beta;
98    const int C = CHANNELS(_C);
99
100    if (intra)
101    {
102       coef = 0;
103       prob += 2*m->nbEBands;
104    }
105    /* The .8 is a heuristic */
106    beta = MULT16_16_P15(QCONST16(.8f,15),coef);
107
108    /* Encode at a fixed coarse resolution */
109    for (i=start;i<m->nbEBands;i++)
110    {
111       c=0;
112       do {
113          int qi;
114          celt_word16 q;   /* dB */
115          celt_word16 x;   /* dB */
116          celt_word16 f;   /* Q8 */
117          celt_word16 mean =  (i < E_MEANS_SIZE) ? MULT16_16_P15(Q15ONE-coef,eMeans[i]) : 0;
118          x = eBands[i+c*m->nbEBands];
119 #ifdef FIXED_POINT
120          f = x-mean -MULT16_16_P15(coef,oldEBands[i+c*m->nbEBands])-prev[c];
121          /* Rounding to nearest integer here is really important! */
122          qi = (f+128)>>8;
123 #else
124          f = x-mean-coef*oldEBands[i+c*m->nbEBands]-prev[c];
125          /* Rounding to nearest integer here is really important! */
126          qi = (int)floor(.5f+f);
127 #endif
128          /* If we don't have enough bits to encode all the energy, just assume something safe.
129             We allow slightly busting the budget here */
130          bits_used=ec_enc_tell(enc, 0);
131          if (bits_used > budget)
132          {
133             qi = -1;
134             error[i+c*m->nbEBands] = 128;
135          } else {
136             ec_laplace_encode_start(enc, &qi, prob[2*i], prob[2*i+1]);
137             error[i+c*m->nbEBands] = f - SHL16(qi,8);
138          }
139          q = SHL16(qi,DB_SHIFT);
140          
141          oldEBands[i+c*m->nbEBands] = MULT16_16_P15(coef,oldEBands[i+c*m->nbEBands])+(mean+prev[c]+q);
142          prev[c] = mean+prev[c]+MULT16_16_P15(Q15ONE-beta,q);
143       } while (++c < C);
144    }
145    return bits_used;
146 }
147
148 void quant_fine_energy(const CELTMode *m, int start, celt_ener *eBands, celt_word16 *oldEBands, celt_word16 *error, int *fine_quant, ec_enc *enc, int _C)
149 {
150    int i, c;
151    const int C = CHANNELS(_C);
152
153    /* Encode finer resolution */
154    for (i=start;i<m->nbEBands;i++)
155    {
156       celt_int16 frac = 1<<fine_quant[i];
157       if (fine_quant[i] <= 0)
158          continue;
159       c=0;
160       do {
161          int q2;
162          celt_word16 offset;
163 #ifdef FIXED_POINT
164          /* Has to be without rounding */
165          q2 = (error[i+c*m->nbEBands]+QCONST16(.5f,8))>>(8-fine_quant[i]);
166 #else
167          q2 = (int)floor((error[i+c*m->nbEBands]+.5f)*frac);
168 #endif
169          if (q2 > frac-1)
170             q2 = frac-1;
171          ec_enc_bits(enc, q2, fine_quant[i]);
172 #ifdef FIXED_POINT
173          offset = SUB16(SHR16(SHL16(q2,8)+QCONST16(.5,8),fine_quant[i]),QCONST16(.5f,8));
174 #else
175          offset = (q2+.5f)*(1<<(14-fine_quant[i]))*(1.f/16384) - .5f;
176 #endif
177          oldEBands[i+c*m->nbEBands] += offset;
178          error[i+c*m->nbEBands] -= offset;
179          eBands[i+c*m->nbEBands] = log2Amp(oldEBands[i+c*m->nbEBands]);
180          /*printf ("%f ", error[i] - offset);*/
181       } while (++c < C);
182    }
183    for (i=start;i<C*m->nbEBands;i++)
184       eBands[i] = log2Amp(oldEBands[i]);
185 }
186
187 void quant_energy_finalise(const CELTMode *m, int start, celt_ener *eBands, celt_word16 *oldEBands, celt_word16 *error, int *fine_quant, int *fine_priority, int bits_left, ec_enc *enc, int _C)
188 {
189    int i, prio, c;
190    const int C = CHANNELS(_C);
191
192    /* Use up the remaining bits */
193    for (prio=0;prio<2;prio++)
194    {
195       for (i=start;i<m->nbEBands && bits_left>=C ;i++)
196       {
197          if (fine_quant[i] >= 7 || fine_priority[i]!=prio)
198             continue;
199          c=0;
200          do {
201             int q2;
202             celt_word16 offset;
203             q2 = error[i+c*m->nbEBands]<0 ? 0 : 1;
204             ec_enc_bits(enc, q2, 1);
205 #ifdef FIXED_POINT
206             offset = SHR16(SHL16(q2,8)-QCONST16(.5,8),fine_quant[i]+1);
207 #else
208             offset = (q2-.5f)*(1<<(14-fine_quant[i]-1))*(1.f/16384);
209 #endif
210             oldEBands[i+c*m->nbEBands] += offset;
211             bits_left--;
212          } while (++c < C);
213       }
214    }
215    for (i=start;i<C*m->nbEBands;i++)
216    {
217       eBands[i] = log2Amp(oldEBands[i]);
218       if (oldEBands[i] < -QCONST16(7.f,8))
219          oldEBands[i] = -QCONST16(7.f,8);
220    }
221 }
222
223 void unquant_coarse_energy(const CELTMode *m, int start, celt_ener *eBands, celt_word16 *oldEBands, int budget, int intra, int *prob, ec_dec *dec, int _C)
224 {
225    int i, c;
226    celt_word16 prev[2] = {0, 0};
227    celt_word16 coef = m->ePredCoef;
228    celt_word16 beta;
229    const int C = CHANNELS(_C);
230
231    if (intra)
232    {
233       coef = 0;
234       prob += 2*m->nbEBands;
235    }
236    /* The .8 is a heuristic */
237    beta = MULT16_16_P15(QCONST16(.8f,15),coef);
238
239    /* Decode at a fixed coarse resolution */
240    for (i=start;i<m->nbEBands;i++)
241    {
242       c=0; 
243       do {
244          int qi;
245          celt_word16 q;
246          celt_word16 mean =  (i < E_MEANS_SIZE) ? MULT16_16_P15(Q15ONE-coef,eMeans[i]) : 0;
247          /* If we didn't have enough bits to encode all the energy, just assume something safe.
248             We allow slightly busting the budget here */
249          if (ec_dec_tell(dec, 0) > budget)
250             qi = -1;
251          else
252             qi = ec_laplace_decode_start(dec, prob[2*i], prob[2*i+1]);
253          q = SHL16(qi,DB_SHIFT);
254
255          oldEBands[i+c*m->nbEBands] = MULT16_16_P15(coef,oldEBands[i+c*m->nbEBands])+(mean+prev[c]+q);
256          prev[c] = mean+prev[c]+MULT16_16_Q15(Q15ONE-beta,q);
257       } while (++c < C);
258    }
259 }
260
261 void unquant_fine_energy(const CELTMode *m, int start, celt_ener *eBands, celt_word16 *oldEBands, int *fine_quant, ec_dec *dec, int _C)
262 {
263    int i, c;
264    const int C = CHANNELS(_C);
265    /* Decode finer resolution */
266    for (i=start;i<m->nbEBands;i++)
267    {
268       if (fine_quant[i] <= 0)
269          continue;
270       c=0; 
271       do {
272          int q2;
273          celt_word16 offset;
274          q2 = ec_dec_bits(dec, fine_quant[i]);
275 #ifdef FIXED_POINT
276          offset = SUB16(SHR16(SHL16(q2,8)+QCONST16(.5,8),fine_quant[i]),QCONST16(.5f,8));
277 #else
278          offset = (q2+.5f)*(1<<(14-fine_quant[i]))*(1.f/16384) - .5f;
279 #endif
280          oldEBands[i+c*m->nbEBands] += offset;
281       } while (++c < C);
282    }
283    for (i=start;i<C*m->nbEBands;i++)
284       eBands[i] = log2Amp(oldEBands[i]);
285 }
286
287 void unquant_energy_finalise(const CELTMode *m, int start, celt_ener *eBands, celt_word16 *oldEBands, int *fine_quant,  int *fine_priority, int bits_left, ec_dec *dec, int _C)
288 {
289    int i, prio, c;
290    const int C = CHANNELS(_C);
291
292    /* Use up the remaining bits */
293    for (prio=0;prio<2;prio++)
294    {
295       for (i=start;i<m->nbEBands && bits_left>=C ;i++)
296       {
297          if (fine_quant[i] >= 7 || fine_priority[i]!=prio)
298             continue;
299          c=0;
300          do {
301             int q2;
302             celt_word16 offset;
303             q2 = ec_dec_bits(dec, 1);
304 #ifdef FIXED_POINT
305             offset = SHR16(SHL16(q2,8)-QCONST16(.5,8),fine_quant[i]+1);
306 #else
307             offset = (q2-.5f)*(1<<(14-fine_quant[i]-1))*(1.f/16384);
308 #endif
309             oldEBands[i+c*m->nbEBands] += offset;
310             bits_left--;
311          } while (++c < C);
312       }
313    }
314    for (i=start;i<C*m->nbEBands;i++)
315    {
316       eBands[i] = log2Amp(oldEBands[i]);
317       if (oldEBands[i] < -QCONST16(7.f,8))
318          oldEBands[i] = -QCONST16(7.f,8);
319    }
320 }