fixed-point: unquant_energy_mono() has received the fixed-point code from
[opus.git] / libcelt / quant_bands.c
1 /* (C) 2007 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
42 #ifdef FIXED_POINT
43 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};
44 #else
45 const float 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};
46 #endif
47
48 /*const int frac[24] = {4, 3, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2};*/
49 const int frac[24] = {8, 6, 5, 4, 3, 3, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2};
50
51 #ifdef FIXED_POINT
52 #define Q8 256.f
53 #define Q8_1 (1.f/256.f)
54 #else
55 #define Q8 1.f
56 #define Q8_1 1.f
57 #endif
58 static void quant_energy_mono(const CELTMode *m, celt_ener_t *eBands, celt_word16_t *oldEBands, int budget, ec_enc *enc)
59 {
60    int i;
61    int bits;
62    celt_word16_t prev = 0;
63    float coef = m->ePredCoef;
64    VARDECL(celt_word16_t *error);
65    /* The .7 is a heuristic */
66    float beta = .7*coef;
67    
68    ALLOC(error, m->nbEBands, celt_word16_t);
69    bits = ec_enc_tell(enc, 0);
70    for (i=0;i<m->nbEBands;i++)
71    {
72       int qi;
73       celt_word16_t q;   /* dB */
74       celt_word16_t res; /* dB */
75       celt_word16_t x;   /* dB */
76       celt_word16_t f;   /* Q8 */
77       celt_word16_t mean = (1-coef)*eMeans[i];
78       x = DB_SCALING*20*log10(.3+ENER_SCALING_1*eBands[i]);
79       res = DB_SCALING*6;
80       f = QCONST16(1.f,8)*(x-mean-coef*oldEBands[i]-prev*1.f)/res;
81 #ifdef FIXED_POINT
82       /* Rounding to nearest integer here is really important! */
83       qi = (f+128)>>8;
84 #else
85       qi = (int)floor(.5+f);
86 #endif
87       /*ec_laplace_encode(enc, qi, i==0?11192:6192);*/
88       /*ec_laplace_encode(enc, qi, 8500-i*200);*/
89       /* If we don't have enough bits to encode all the energy, just assume something safe. */
90       if (ec_enc_tell(enc, 0) - bits > budget)
91          qi = -1;
92       else
93          ec_laplace_encode(enc, qi, 6000-i*200);
94       q = qi*res;
95       error[i] = f - SHL16(qi,8);
96       
97       /*printf("%d ", qi);*/
98       /*printf("%f %f ", pred+prev+q, x);*/
99       /*printf("%f ", x-pred);*/
100       
101       oldEBands[i] = mean+coef*oldEBands[i]+prev+q;
102       
103       prev = mean+prev+(1-beta)*q;
104    }
105    /*bits = ec_enc_tell(enc, 0) - bits;*/
106    /*printf ("%d\n", bits);*/
107    for (i=0;i<m->nbEBands;i++)
108    {
109       int q2;
110       celt_word16_t offset = (error[i]+QCONST16(.5f,8))*frac[i];
111       /* FIXME: Instead of giving up without warning, we should degrade everything gracefully */
112       if (ec_enc_tell(enc, 0) - bits +EC_ILOG(frac[i])> budget)
113          break;
114 #ifdef FIXED_POINT
115       /* Has to be without rounding */
116       q2 = offset>>8;
117 #else
118       q2 = (int)floor(Q8_1*offset);
119 #endif
120       if (q2 > frac[i]-1)
121          q2 = frac[i]-1;
122       ec_enc_uint(enc, q2, frac[i]);
123       offset = (Q8*(q2+.5)/frac[i])-QCONST16(.5f,8);
124       oldEBands[i] += PSHR32(MULT16_16(DB_SCALING*6,offset),8);
125       /*printf ("%f ", error[i] - offset);*/
126    }
127    for (i=0;i<m->nbEBands;i++)
128    {
129       eBands[i] = ENER_SCALING*(pow(10, .05*DB_SCALING_1*oldEBands[i])-.3);
130       if (eBands[i] < 0)
131          eBands[i] = 0;
132    }
133    /*printf ("%d\n", ec_enc_tell(enc, 0)-9);*/
134
135    /*printf ("\n");*/
136 }
137
138 static void unquant_energy_mono(const CELTMode *m, celt_ener_t *eBands, celt_word16_t *oldEBands, int budget, ec_dec *dec)
139 {
140    int i;
141    int bits;
142    celt_word16_t prev = 0;
143    float coef = m->ePredCoef;
144    /* The .7 is a heuristic */
145    float beta = .7*coef;
146    bits = ec_dec_tell(dec, 0);
147    for (i=0;i<m->nbEBands;i++)
148    {
149       int qi;
150       celt_word16_t q;
151       celt_word16_t res;
152       celt_word16_t mean = (1-coef)*eMeans[i];
153       res = DB_SCALING*6.;
154       /* If we didn't have enough bits to encode all the energy, just assume something safe. */
155       if (ec_dec_tell(dec, 0) - bits > budget)
156          qi = -1;
157       else
158          qi = ec_laplace_decode(dec, 6000-i*200);
159       q = qi*res;
160       
161       /*printf("%d ", qi);*/
162       /*printf("%f %f ", pred+prev+q, x);*/
163       /*printf("%f ", x-pred);*/
164       
165       oldEBands[i] = mean+coef*oldEBands[i]+prev+q;
166       
167       prev = mean+prev+(1-beta)*q;
168    }
169    for (i=0;i<m->nbEBands;i++)
170    {
171       int q2;
172       celt_word16_t offset;
173       if (ec_dec_tell(dec, 0) - bits +EC_ILOG(frac[i])> budget)
174          break;
175       q2 = ec_dec_uint(dec, frac[i]);
176       offset = (Q8*(q2+.5)/frac[i])-QCONST16(.5f,8);
177       oldEBands[i] += PSHR32(MULT16_16(DB_SCALING*6,offset),8);
178    }
179    for (i=0;i<m->nbEBands;i++)
180    {
181       /*printf ("%f ", error[i] - offset);*/
182       eBands[i] = ENER_SCALING*(pow(10, .05*DB_SCALING_1*oldEBands[i])-.3);
183       if (eBands[i] < 0)
184          eBands[i] = 0;
185    }
186    /*printf ("\n");*/
187 }
188
189
190
191 void quant_energy(const CELTMode *m, celt_ener_t *eBands, celt_word16_t *oldEBands, int budget, ec_enc *enc)
192 {
193    int C;
194    
195    C = m->nbChannels;
196
197    if (C==1)
198       quant_energy_mono(m, eBands, oldEBands, budget, enc);
199    else 
200 #if 1
201    {
202       int c;
203       VARDECL(celt_ener_t *E);
204       ALLOC(E, m->nbEBands, celt_ener_t);
205       for (c=0;c<C;c++)
206       {
207          int i;
208          for (i=0;i<m->nbEBands;i++)
209             E[i] = eBands[C*i+c];
210          quant_energy_mono(m, E, oldEBands+c*m->nbEBands, budget/C, enc);
211          for (i=0;i<m->nbEBands;i++)
212             eBands[C*i+c] = E[i];
213       }
214    }
215 #else
216       if (C==2)
217    {
218       int i;
219       int NB = m->nbEBands;
220       float mid[NB];
221       float side[NB];
222       float left;
223       float right;
224       for (i=0;i<NB;i++)
225       {
226          //left = eBands[C*i];
227          //right = eBands[C*i+1];
228          mid[i] = ENER_SCALING_1*sqrt(eBands[C*i]*eBands[C*i] + eBands[C*i+1]*eBands[C*i+1]);
229          side[i] = 20*log10((ENER_SCALING_1*eBands[2*i]+.3)/(ENER_SCALING_1*eBands[2*i+1]+.3));
230          //printf ("%f %f ", mid[i], side[i]);
231       }
232       //printf ("\n");
233       quant_energy_mono(m, mid, oldEBands, enc);
234       for (i=0;i<NB;i++)
235          side[i] = pow(10.f,floor(.5f+side[i])/10.f);
236          
237       //quant_energy_side(m, side, oldEBands+NB, enc);
238       for (i=0;i<NB;i++)
239       {
240          eBands[C*i] = ENER_SCALING*mid[i]*sqrt(side[i]/(1.f+side[i]));
241          eBands[C*i+1] = ENER_SCALING*mid[i]*sqrt(1.f/(1.f+side[i]));
242          //printf ("%f %f ", mid[i], side[i]);
243       }
244
245    } else {
246       celt_fatal("more than 2 channels not supported");
247    }
248 #endif
249 }
250
251
252
253 void unquant_energy(const CELTMode *m, celt_ener_t *eBands, celt_word16_t *oldEBands, int budget, ec_dec *dec)
254 {
255    int C;   
256    C = m->nbChannels;
257
258    if (C==1)
259       unquant_energy_mono(m, eBands, oldEBands, budget, dec);
260    else {
261       int c;
262       VARDECL(celt_ener_t *E);
263       ALLOC(E, m->nbEBands, celt_ener_t);
264       for (c=0;c<C;c++)
265       {
266          int i;
267          unquant_energy_mono(m, E, oldEBands+c*m->nbEBands, budget/C, dec);
268          for (i=0;i<m->nbEBands;i++)
269             eBands[C*i+c] = E[i];
270       }
271    }
272 }