fixed-point: second check-point on quant_energy_mono()
[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 float 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       float offset2;
111       celt_word16_t offset = (error[i]+QCONST16(.5f,8))*frac[i];
112       /* FIXME: Instead of giving up without warning, we should degrade everything gracefully */
113       if (ec_enc_tell(enc, 0) - bits +EC_ILOG(frac[i])> budget)
114          break;
115 #ifdef FIXED_POINT
116       /* Has to be without rounding */
117       q2 = offset>>8;
118 #else
119       q2 = (int)floor(Q8_1*offset);
120 #endif
121       if (q2 > frac[i]-1)
122          q2 = frac[i]-1;
123       ec_enc_uint(enc, q2, frac[i]);
124       offset = (Q8*(q2+.5)/frac[i])-QCONST16(.5f,8);
125       oldEBands[i] += PSHR32(MULT16_16(DB_SCALING*6,offset),8);
126       /*printf ("%f ", error[i] - offset);*/
127    }
128    for (i=0;i<m->nbEBands;i++)
129    {
130       eBands[i] = ENER_SCALING*(pow(10, .05*DB_SCALING_1*oldEBands[i])-.3);
131       if (eBands[i] < 0)
132          eBands[i] = 0;
133    }
134    /*printf ("%d\n", ec_enc_tell(enc, 0)-9);*/
135
136    /*printf ("\n");*/
137 }
138
139 static void unquant_energy_mono(const CELTMode *m, celt_ener_t *eBands, celt_word16_t *oldEBands, int budget, ec_dec *dec)
140 {
141    int i;
142    int bits;
143    float prev = 0;
144    float coef = m->ePredCoef;
145    /* The .7 is a heuristic */
146    float beta = .7*coef;
147    bits = ec_dec_tell(dec, 0);
148    for (i=0;i<m->nbEBands;i++)
149    {
150       int qi;
151       float q;
152       float res;
153       float mean = (1-coef)*eMeans[i];
154       res = 6.;
155       /* If we didn't have enough bits to encode all the energy, just assume something safe. */
156       if (ec_dec_tell(dec, 0) - bits > budget)
157          qi = -1;
158       else
159          qi = ec_laplace_decode(dec, 6000-i*200);
160       q = qi*res;
161       
162       oldEBands[i] = DB_SCALING*(DB_SCALING_1*mean+coef*DB_SCALING_1*oldEBands[i]+prev+q);
163       
164       prev = DB_SCALING_1*mean+prev+(1-beta)*q;
165    }
166    for (i=0;i<m->nbEBands;i++)
167    {
168       int q2;
169       float offset;
170       if (ec_dec_tell(dec, 0) - bits +EC_ILOG(frac[i])> budget)
171          break;
172       q2 = ec_dec_uint(dec, frac[i]);
173       offset = ((q2+.5)/frac[i])-.5;
174       oldEBands[i] += DB_SCALING*6.*offset;
175    }
176    for (i=0;i<m->nbEBands;i++)
177    {
178       /*printf ("%f ", error[i] - offset);*/
179       eBands[i] = ENER_SCALING*(pow(10, .05*DB_SCALING_1*oldEBands[i])-.3);
180       if (eBands[i] < 0)
181          eBands[i] = 0;
182    }
183    /*printf ("\n");*/
184 }
185
186
187
188 void quant_energy(const CELTMode *m, celt_ener_t *eBands, celt_word16_t *oldEBands, int budget, ec_enc *enc)
189 {
190    int C;
191    
192    C = m->nbChannels;
193
194    if (C==1)
195       quant_energy_mono(m, eBands, oldEBands, budget, enc);
196    else 
197 #if 1
198    {
199       int c;
200       VARDECL(celt_ener_t *E);
201       ALLOC(E, m->nbEBands, celt_ener_t);
202       for (c=0;c<C;c++)
203       {
204          int i;
205          for (i=0;i<m->nbEBands;i++)
206             E[i] = eBands[C*i+c];
207          quant_energy_mono(m, E, oldEBands+c*m->nbEBands, budget/C, enc);
208          for (i=0;i<m->nbEBands;i++)
209             eBands[C*i+c] = E[i];
210       }
211    }
212 #else
213       if (C==2)
214    {
215       int i;
216       int NB = m->nbEBands;
217       float mid[NB];
218       float side[NB];
219       float left;
220       float right;
221       for (i=0;i<NB;i++)
222       {
223          //left = eBands[C*i];
224          //right = eBands[C*i+1];
225          mid[i] = ENER_SCALING_1*sqrt(eBands[C*i]*eBands[C*i] + eBands[C*i+1]*eBands[C*i+1]);
226          side[i] = 20*log10((ENER_SCALING_1*eBands[2*i]+.3)/(ENER_SCALING_1*eBands[2*i+1]+.3));
227          //printf ("%f %f ", mid[i], side[i]);
228       }
229       //printf ("\n");
230       quant_energy_mono(m, mid, oldEBands, enc);
231       for (i=0;i<NB;i++)
232          side[i] = pow(10.f,floor(.5f+side[i])/10.f);
233          
234       //quant_energy_side(m, side, oldEBands+NB, enc);
235       for (i=0;i<NB;i++)
236       {
237          eBands[C*i] = ENER_SCALING*mid[i]*sqrt(side[i]/(1.f+side[i]));
238          eBands[C*i+1] = ENER_SCALING*mid[i]*sqrt(1.f/(1.f+side[i]));
239          //printf ("%f %f ", mid[i], side[i]);
240       }
241
242    } else {
243       celt_fatal("more than 2 channels not supported");
244    }
245 #endif
246 }
247
248
249
250 void unquant_energy(const CELTMode *m, celt_ener_t *eBands, celt_word16_t *oldEBands, int budget, ec_dec *dec)
251 {
252    int C;   
253    C = m->nbChannels;
254
255    if (C==1)
256       unquant_energy_mono(m, eBands, oldEBands, budget, dec);
257    else {
258       int c;
259       VARDECL(celt_ener_t *E);
260       ALLOC(E, m->nbEBands, celt_ener_t);
261       for (c=0;c<C;c++)
262       {
263          int i;
264          unquant_energy_mono(m, E, oldEBands+c*m->nbEBands, budget/C, dec);
265          for (i=0;i<m->nbEBands;i++)
266             eBands[C*i+c] = E[i];
267       }
268    }
269 }