Removed a bunch of divides from the fine energy quantisation
[opus.git] / libcelt / quant_bands.c
1 /* (C) 2007-2008 Jean-Marc Valin, CSIRO
2 */
3 /*
4    Redistribution and use in source and binary forms, with or without
5    modification, are permitted provided that the following conditions
6    are met:
7    
8    - Redistributions of source code must retain the above copyright
9    notice, this list of conditions and the following disclaimer.
10    
11    - Redistributions in binary form must reproduce the above copyright
12    notice, this list of conditions and the following disclaimer in the
13    documentation and/or other materials provided with the distribution.
14    
15    - Neither the name of the Xiph.org Foundation nor the names of its
16    contributors may be used to endorse or promote products derived from
17    this software without specific prior written permission.
18    
19    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20    ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21    LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22    A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR
23    CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
24    EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
25    PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
26    PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
27    LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
28    NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
29    SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 */
31
32 #ifdef HAVE_CONFIG_H
33 #include "config.h"
34 #endif
35
36 #include "quant_bands.h"
37 #include "laplace.h"
38 #include <math.h>
39 #include "os_support.h"
40 #include "arch.h"
41 #include "mathops.h"
42 #include "stack_alloc.h"
43
44 #ifdef FIXED_POINT
45 const celt_word16_t eMeans[24] = {11520, -2048, -3072, -640, 256, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
46 #else
47 const celt_word16_t eMeans[24] = {45.f, -8.f, -12.f, -2.5f, 1.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f};
48 #endif
49
50
51 #ifdef FIXED_POINT
52 static inline celt_ener_t dB2Amp(celt_ener_t dB)
53 {
54    celt_ener_t amp;
55    if (dB>24659)
56       dB=24659;
57    amp = PSHR32(celt_exp2(MULT16_16_Q14(21771,dB)),2)-QCONST16(.3f, 14);
58    if (amp < 0)
59       amp = 0;
60    return PSHR32(amp,2);
61 }
62
63 #define DBofTWO 24661
64 static inline celt_word16_t amp2dB(celt_ener_t amp)
65 {
66    /* equivalent to return 6.0207*log2(.3+amp) */
67    return ROUND16(MULT16_16(24661,celt_log2(ADD32(QCONST32(.3f,14),SHL32(amp,2)))),12);
68    /* return DB_SCALING*20*log10(.3+ENER_SCALING_1*amp); */
69 }
70 #else
71 static inline celt_ener_t dB2Amp(celt_ener_t dB)
72 {
73    celt_ener_t amp;
74    /*amp = pow(10, .05*dB)-.3;*/
75    amp = exp(0.115129f*dB)-.3f;
76    if (amp < 0)
77       amp = 0;
78    return amp;
79 }
80 static inline celt_word16_t amp2dB(celt_ener_t amp)
81 {
82    /*return 20*log10(.3+amp);*/
83    return 8.68589f*log(.3f+amp);
84 }
85 #endif
86
87 static const celt_word16_t base_resolution = QCONST16(6.f,8);
88
89 int *quant_prob_alloc(const CELTMode *m)
90 {
91    int i;
92    int *prob;
93    prob = celt_alloc(2*m->nbEBands*sizeof(int));
94    for (i=0;i<m->nbEBands;i++)
95    {
96       prob[2*i] = 6000-i*200;
97       prob[2*i+1] = ec_laplace_get_start_freq(prob[2*i]);
98    }
99    return prob;
100 }
101
102 void quant_prob_free(int *freq)
103 {
104    celt_free(freq);
105 }
106
107 static void quant_coarse_energy_mono(const CELTMode *m, celt_ener_t *eBands, celt_word16_t *oldEBands, unsigned budget, int *prob, celt_word16_t *error, ec_enc *enc)
108 {
109    int i;
110    unsigned bits;
111    celt_word16_t prev = 0;
112    celt_word16_t coef = m->ePredCoef;
113    celt_word16_t beta;
114    /* The .7 is a heuristic */
115    beta = MULT16_16_Q15(QCONST16(.8f,15),coef);
116    
117    bits = ec_enc_tell(enc, 0);
118    /* Encode at a fixed coarse resolution */
119    for (i=0;i<m->nbEBands;i++)
120    {
121       int qi;
122       celt_word16_t q;   /* dB */
123       celt_word16_t x;   /* dB */
124       celt_word16_t f;   /* Q8 */
125       celt_word16_t mean = MULT16_16_Q15(Q15ONE-coef,eMeans[i]);
126       x = amp2dB(eBands[i]);
127       f = EXTRACT16(celt_div(SHL32(EXTEND32(x-mean-MULT16_16_Q15(coef,oldEBands[i])-prev),8),base_resolution));
128 #ifdef FIXED_POINT
129       /* Rounding to nearest integer here is really important! */
130       qi = (f+128)>>8;
131 #else
132       qi = (int)floor(.5+f);
133 #endif
134       /* If we don't have enough bits to encode all the energy, just assume something safe.
135          We allow slightly busting the budget here */
136       if (ec_enc_tell(enc, 0) - bits > budget)
137       {
138          qi = -1;
139          error[i] = 128;
140       } else {
141          ec_laplace_encode_start(enc, &qi, prob[2*i], prob[2*i+1]);
142          error[i] = f - SHL16(qi,8);
143       }
144       q = qi*base_resolution;
145       
146       oldEBands[i] = mean+MULT16_16_Q15(coef,oldEBands[i])+prev+q;
147       if (oldEBands[i] < -QCONST16(12.f,8))
148          oldEBands[i] = -QCONST16(12.f,8);
149       prev = mean+prev+MULT16_16_Q15(Q15ONE-beta,q);
150    }
151 }
152
153 static void quant_fine_energy_mono(const CELTMode *m, celt_ener_t *eBands, celt_word16_t *oldEBands, celt_word16_t *error, int *fine_quant, ec_enc *enc)
154 {
155    int i;
156    /* Encode finer resolution */
157    for (i=0;i<m->nbEBands;i++)
158    {
159       int q2;
160       celt_int16_t frac = 1<<fine_quant[i];
161       celt_word16_t offset = (error[i]+QCONST16(.5f,8))*frac;
162       if (fine_quant[i] <= 0)
163          continue;
164 #ifdef FIXED_POINT
165       /* Has to be without rounding */
166       q2 = offset>>8;
167 #else
168       q2 = (int)floor(offset);
169 #endif
170       if (q2 > frac-1)
171          q2 = frac-1;
172       ec_enc_bits(enc, q2, fine_quant[i]);
173 #ifdef FIXED_POINT
174       offset = SUB16(SHR16(SHL16(q2,8)+QCONST16(.5,8),fine_quant[i]),QCONST16(.5f,8));
175 #else
176       offset = (q2+.5f)*(1<<(14-fine_quant[i]))*(1.f/16384) - .5f;
177 #endif
178       oldEBands[i] += PSHR32(MULT16_16(DB_SCALING*6,offset),8);
179       /*printf ("%f ", error[i] - offset);*/
180    }
181    for (i=0;i<m->nbEBands;i++)
182    {
183       eBands[i] = dB2Amp(oldEBands[i]);
184    }
185    /*printf ("%d\n", ec_enc_tell(enc, 0)-9);*/
186
187    /*printf ("\n");*/
188 }
189
190 static void unquant_coarse_energy_mono(const CELTMode *m, celt_ener_t *eBands, celt_word16_t *oldEBands, unsigned budget, int *prob, ec_dec *dec)
191 {
192    int i;
193    unsigned bits;
194    celt_word16_t prev = 0;
195    celt_word16_t coef = m->ePredCoef;
196    /* The .7 is a heuristic */
197    celt_word16_t beta = MULT16_16_Q15(QCONST16(.8f,15),coef);
198    
199    bits = ec_dec_tell(dec, 0);
200    /* Decode at a fixed coarse resolution */
201    for (i=0;i<m->nbEBands;i++)
202    {
203       int qi;
204       celt_word16_t q;
205       celt_word16_t mean = MULT16_16_Q15(Q15ONE-coef,eMeans[i]);
206       /* If we didn't have enough bits to encode all the energy, just assume something safe.
207          We allow slightly busting the budget here */
208       if (ec_dec_tell(dec, 0) - bits > budget)
209          qi = -1;
210       else
211          qi = ec_laplace_decode_start(dec, prob[2*i], prob[2*i+1]);
212       q = qi*base_resolution;
213       
214       oldEBands[i] = mean+MULT16_16_Q15(coef,oldEBands[i])+prev+q;
215       if (oldEBands[i] < -QCONST16(12.f,8))
216          oldEBands[i] = -QCONST16(12.f,8);
217       
218       prev = mean+prev+MULT16_16_Q15(Q15ONE-beta,q);
219    }
220 }
221
222 static void unquant_fine_energy_mono(const CELTMode *m, celt_ener_t *eBands, celt_word16_t *oldEBands, int *fine_quant, ec_dec *dec)
223 {
224    int i;
225    /* Decode finer resolution */
226    for (i=0;i<m->nbEBands;i++)
227    {
228       int q2;
229       celt_int16_t frac = 1<<fine_quant[i];
230       celt_word16_t offset;
231       if (fine_quant[i] <= 0)
232          continue;
233       q2 = ec_dec_bits(dec, fine_quant[i]);
234 #ifdef FIXED_POINT
235       offset = SUB16(SHR16(SHL16(q2,8)+QCONST16(.5,8),fine_quant[i]),QCONST16(.5f,8));
236 #else
237       offset = (q2+.5f)*(1<<(14-fine_quant[i]))*(1.f/16384) - .5f;
238 #endif
239       oldEBands[i] += PSHR32(MULT16_16(DB_SCALING*6,offset),8);
240    }
241    for (i=0;i<m->nbEBands;i++)
242    {
243       eBands[i] = dB2Amp(oldEBands[i]);
244    }
245    /*printf ("\n");*/
246 }
247
248
249
250 void quant_coarse_energy(const CELTMode *m, celt_ener_t *eBands, celt_word16_t *oldEBands, int budget, int *prob, celt_word16_t *error, ec_enc *enc)
251 {
252    int C;
253    C = m->nbChannels;
254
255    if (C==1)
256    {
257       quant_coarse_energy_mono(m, eBands, oldEBands, budget, prob, error, enc);
258
259    } else {
260       int c;
261       for (c=0;c<C;c++)
262       {
263          int i;
264          VARDECL(celt_ener_t, E);
265          SAVE_STACK;
266          ALLOC(E, m->nbEBands, celt_ener_t);
267          for (i=0;i<m->nbEBands;i++)
268             E[i] = eBands[C*i+c];
269          quant_coarse_energy_mono(m, E, oldEBands+c*m->nbEBands, budget/C, prob, error+c*m->nbEBands, enc);
270          RESTORE_STACK;
271       }
272    }
273 }
274
275 void quant_fine_energy(const CELTMode *m, celt_ener_t *eBands, celt_word16_t *oldEBands, celt_word16_t *error, int *fine_quant, ec_enc *enc)
276 {
277    int C;
278    C = m->nbChannels;
279
280    if (C==1)
281    {
282       quant_fine_energy_mono(m, eBands, oldEBands, error, fine_quant, enc);
283
284    } else {
285       int c;
286       VARDECL(celt_ener_t, E);
287       ALLOC(E, m->nbEBands, celt_ener_t);
288       for (c=0;c<C;c++)
289       {
290          int i;
291          SAVE_STACK;
292          quant_fine_energy_mono(m, E, oldEBands+c*m->nbEBands, error+c*m->nbEBands, fine_quant, enc);
293          for (i=0;i<m->nbEBands;i++)
294             eBands[C*i+c] = E[i];
295          RESTORE_STACK;
296       }
297    }
298 }
299
300
301 void unquant_coarse_energy(const CELTMode *m, celt_ener_t *eBands, celt_word16_t *oldEBands, int budget, int *prob, ec_dec *dec)
302 {
303    int C;   
304
305    C = m->nbChannels;
306    if (C==1)
307    {
308       unquant_coarse_energy_mono(m, eBands, oldEBands, budget, prob, dec);
309    }
310    else {
311       int c;
312       VARDECL(celt_ener_t, E);
313       SAVE_STACK;
314       ALLOC(E, m->nbEBands, celt_ener_t);
315       for (c=0;c<C;c++)
316       {
317          unquant_coarse_energy_mono(m, E, oldEBands+c*m->nbEBands, budget/C, prob, dec);
318       }
319       RESTORE_STACK;
320    }
321 }
322
323 void unquant_fine_energy(const CELTMode *m, celt_ener_t *eBands, celt_word16_t *oldEBands, int *fine_quant, ec_dec *dec)
324 {
325    int C;   
326
327    C = m->nbChannels;
328
329    if (C==1)
330    {
331       unquant_fine_energy_mono(m, eBands, oldEBands, fine_quant, dec);
332    }
333    else {
334       int c;
335       VARDECL(celt_ener_t, E);
336       SAVE_STACK;
337       ALLOC(E, m->nbEBands, celt_ener_t);
338       for (c=0;c<C;c++)
339       {
340          int i;
341          unquant_fine_energy_mono(m, E, oldEBands+c*m->nbEBands, fine_quant, dec);
342          for (i=0;i<m->nbEBands;i++)
343             eBands[C*i+c] = E[i];
344       }
345       RESTORE_STACK;
346    }
347 }