blob: 57969baac564bb32411be43f9ddfb4e1a8ebaa36 [file] [log] [blame]
Jean-Marc Valin41af4212007-11-30 18:35:37 +11001/* (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
Jean-Marc Valin02fa9132008-02-20 12:09:29 +110032#ifdef HAVE_CONFIG_H
33#include "config.h"
34#endif
35
Jean-Marc Valin41af4212007-11-30 18:35:37 +110036#include <math.h>
37#include <stdlib.h>
Jean-Marc Valin29ccab82007-12-06 15:39:38 +110038#include "cwrs.h"
Jean-Marc Valin9cace642007-12-06 17:44:09 +110039#include "vq.h"
Jean-Marc Valin9a0bba12008-02-20 14:08:50 +110040#include "arch.h"
Jean-Marc Valin41af4212007-11-30 18:35:37 +110041
Jean-Marc Valin883bd8e2008-02-15 00:34:01 +110042/* Enable this or define your own implementation if you want to speed up the
43 VQ search (used in inner loop only) */
44#if 0
45#include <xmmintrin.h>
46static inline float approx_sqrt(float x)
47{
48 _mm_store_ss(&x, _mm_sqrt_ss(_mm_set_ss(x)));
49 return x;
50}
51static inline float approx_inv(float x)
52{
53 _mm_store_ss(&x, _mm_rcp_ss(_mm_set_ss(x)));
54 return x;
55}
56#else
57#define approx_sqrt(x) (sqrt(x))
58#define approx_inv(x) (1.f/(x))
59#endif
60
Jean-Marc Valin3b277dc2008-02-14 16:46:50 +110061struct NBest {
62 float score;
63 float gain;
64 int sign;
65 int pos;
66 int orig;
67 float xy;
68 float yy;
69 float yp;
70};
Jean-Marc Valin41af4212007-11-30 18:35:37 +110071
72/* Improved algebraic pulse-base quantiser. The signal x is replaced by the sum of the pitch
73 a combination of pulses such that its norm is still equal to 1. The only difference with
74 the quantiser above is that the search is more complete. */
Jean-Marc Valin46014ca2007-12-14 13:47:04 +110075void alg_quant(float *x, float *W, int N, int K, float *p, float alpha, ec_enc *enc)
Jean-Marc Valin41af4212007-11-30 18:35:37 +110076{
Jean-Marc Valin4a897682007-12-12 00:45:15 +110077 int L = 3;
Jean-Marc Valin9a0bba12008-02-20 14:08:50 +110078 VARDECL(float *_y);
79 VARDECL(float *_ny);
80 VARDECL(int *_iy);
81 VARDECL(int *_iny);
82 VARDECL(float **y);
83 VARDECL(float **ny);
84 VARDECL(int **iy);
85 VARDECL(int **iny);
Jean-Marc Valin0d587d82008-02-14 21:29:50 +110086 int i, j, k, m;
Jean-Marc Valin846d4e22008-02-12 13:48:48 +110087 int pulsesLeft;
Jean-Marc Valin9a0bba12008-02-20 14:08:50 +110088 VARDECL(float *xy);
89 VARDECL(float *yy);
90 VARDECL(float *yp);
91 VARDECL(struct NBest *_nbest);
92 VARDECL(struct NBest **nbest);
Jean-Marc Valin1e7087e2007-12-04 13:05:43 +110093 float Rpp=0, Rxp=0;
Jean-Marc Valin41af4212007-11-30 18:35:37 +110094 int maxL = 1;
Jean-Marc Valin1e7087e2007-12-04 13:05:43 +110095
Jean-Marc Valin9a0bba12008-02-20 14:08:50 +110096 ALLOC(_y, L*N, float);
97 ALLOC(_ny, L*N, float);
98 ALLOC(_iy, L*N, int);
99 ALLOC(_iny, L*N, int);
100 ALLOC(y, L*N, float*);
101 ALLOC(ny, L*N, float*);
102 ALLOC(iy, L*N, int*);
103 ALLOC(iny, L*N, int*);
104
105 ALLOC(xy, L, float);
106 ALLOC(yy, L, float);
107 ALLOC(yp, L, float);
108 ALLOC(_nbest, L, struct NBest);
109 ALLOC(nbest, L, struct NBest *);
110
Jean-Marc Valinfe419832008-02-12 15:05:01 +1100111 for (m=0;m<L;m++)
Jean-Marc Valin3b277dc2008-02-14 16:46:50 +1100112 nbest[m] = &_nbest[m];
113
114 for (m=0;m<L;m++)
Jean-Marc Valinfe419832008-02-12 15:05:01 +1100115 {
Jean-Marc Valin9a0bba12008-02-20 14:08:50 +1100116 ny[m] = &_ny[m*N];
117 iny[m] = &_iny[m*N];
118 y[m] = &_y[m*N];
119 iy[m] = &_iy[m*N];
Jean-Marc Valinfe419832008-02-12 15:05:01 +1100120 }
121
Jean-Marc Valin41af4212007-11-30 18:35:37 +1100122 for (j=0;j<N;j++)
Jean-Marc Valin0d587d82008-02-14 21:29:50 +1100123 {
Jean-Marc Valin41af4212007-11-30 18:35:37 +1100124 Rpp += p[j]*p[j];
Jean-Marc Valin1e7087e2007-12-04 13:05:43 +1100125 Rxp += x[j]*p[j];
Jean-Marc Valin0d587d82008-02-14 21:29:50 +1100126 }
Jean-Marc Valin41af4212007-11-30 18:35:37 +1100127
Jean-Marc Valin0d587d82008-02-14 21:29:50 +1100128 /* We only need to initialise the zero because the first iteration only uses that */
129 for (i=0;i<N;i++)
130 y[0][i] = 0;
131 for (i=0;i<N;i++)
132 iy[0][i] = 0;
133 xy[0] = yy[0] = yp[0] = 0;
134
Jean-Marc Valin846d4e22008-02-12 13:48:48 +1100135 pulsesLeft = K;
136 while (pulsesLeft > 0)
Jean-Marc Valin41af4212007-11-30 18:35:37 +1100137 {
Jean-Marc Valin846d4e22008-02-12 13:48:48 +1100138 int pulsesAtOnce=1;
Jean-Marc Valincab576e2008-02-12 17:21:14 +1100139 int Lupdate = L;
Jean-Marc Valin41af4212007-11-30 18:35:37 +1100140 int L2 = L;
Jean-Marc Valin0d587d82008-02-14 21:29:50 +1100141
142 /* Decide on complexity strategy */
Jean-Marc Valincab576e2008-02-12 17:21:14 +1100143 pulsesAtOnce = pulsesLeft/N;
144 if (pulsesAtOnce<1)
145 pulsesAtOnce = 1;
146 if (pulsesLeft-pulsesAtOnce > 3 || N > 30)
147 Lupdate = 1;
Jean-Marc Valina85657b2008-02-20 11:59:30 +1100148 /*printf ("%d %d %d/%d %d\n", Lupdate, pulsesAtOnce, pulsesLeft, K, N);*/
Jean-Marc Valincab576e2008-02-12 17:21:14 +1100149 L2 = Lupdate;
150 if (L2>maxL)
Jean-Marc Valin41af4212007-11-30 18:35:37 +1100151 {
152 L2 = maxL;
153 maxL *= N;
154 }
Jean-Marc Valin846d4e22008-02-12 13:48:48 +1100155
Jean-Marc Valin0d587d82008-02-14 21:29:50 +1100156 for (m=0;m<Lupdate;m++)
Jean-Marc Valin883bd8e2008-02-15 00:34:01 +1100157 nbest[m]->score = -1e10f;
Jean-Marc Valin41af4212007-11-30 18:35:37 +1100158
159 for (m=0;m<L2;m++)
160 {
161 for (j=0;j<N;j++)
162 {
Jean-Marc Valin1e7087e2007-12-04 13:05:43 +1100163 int sign;
Jean-Marc Valin0d587d82008-02-14 21:29:50 +1100164 /*if (x[j]>0) sign=1; else sign=-1;*/
Jean-Marc Valin1e7087e2007-12-04 13:05:43 +1100165 for (sign=-1;sign<=1;sign+=2)
Jean-Marc Valin41af4212007-11-30 18:35:37 +1100166 {
Jean-Marc Valina85657b2008-02-20 11:59:30 +1100167 /*fprintf (stderr, "%d/%d %d/%d %d/%d\n", i, K, m, L2, j, N);*/
Jean-Marc Valin1e7087e2007-12-04 13:05:43 +1100168 float tmp_xy, tmp_yy, tmp_yp;
169 float score;
170 float g;
Jean-Marc Valin846d4e22008-02-12 13:48:48 +1100171 float s = sign*pulsesAtOnce;
Jean-Marc Valinfe419832008-02-12 15:05:01 +1100172
Jean-Marc Valin9a0bba12008-02-20 14:08:50 +1100173 /* All pulses at one location must have the same sign. */
174 if (iy[m][j]*sign < 0)
175 continue;
176
Jean-Marc Valina073c7b2008-02-14 16:58:04 +1100177 /* Updating the sums of the new pulse(s) */
Jean-Marc Valin1e7087e2007-12-04 13:05:43 +1100178 tmp_xy = xy[m] + s*x[j] - alpha*s*p[j]*Rxp;
Jean-Marc Valin883bd8e2008-02-15 00:34:01 +1100179 tmp_yy = yy[m] + 2.f*s*y[m][j] + s*s +s*s*alpha*alpha*p[j]*p[j]*Rpp - 2.f*alpha*s*p[j]*yp[m] - 2.f*s*s*alpha*p[j]*p[j];
180 tmp_yp = yp[m] + s*p[j] *(1.f-alpha*Rpp);
Jean-Marc Valina073c7b2008-02-14 16:58:04 +1100181
182 /* Compute the gain such that ||p + g*y|| = 1 */
Jean-Marc Valin883bd8e2008-02-15 00:34:01 +1100183 g = (approx_sqrt(tmp_yp*tmp_yp + tmp_yy - tmp_yy*Rpp) - tmp_yp)*approx_inv(tmp_yy);
Jean-Marc Valina073c7b2008-02-14 16:58:04 +1100184 /* Knowing that gain, what the error: (x-g*y)^2
185 (result is negated and we discard x^2 because it's constant) */
Jean-Marc Valin883bd8e2008-02-15 00:34:01 +1100186 score = 2.f*g*tmp_xy - g*g*tmp_yy;
Jean-Marc Valin41af4212007-11-30 18:35:37 +1100187
Jean-Marc Valin3b277dc2008-02-14 16:46:50 +1100188 if (score>nbest[Lupdate-1]->score)
Jean-Marc Valin1e7087e2007-12-04 13:05:43 +1100189 {
Jean-Marc Valin472a5f02008-02-19 13:12:32 +1100190 int k;
Jean-Marc Valincab576e2008-02-12 17:21:14 +1100191 int id = Lupdate-1;
Jean-Marc Valin3b277dc2008-02-14 16:46:50 +1100192 struct NBest *tmp_best;
193
194 /* Save some pointers that would be deleted and use them for the current entry*/
195 tmp_best = nbest[Lupdate-1];
196 while (id > 0 && score > nbest[id-1]->score)
Jean-Marc Valin1e7087e2007-12-04 13:05:43 +1100197 id--;
198
Jean-Marc Valincab576e2008-02-12 17:21:14 +1100199 for (k=Lupdate-1;k>id;k--)
Jean-Marc Valin3b277dc2008-02-14 16:46:50 +1100200 nbest[k] = nbest[k-1];
Jean-Marc Valin1e7087e2007-12-04 13:05:43 +1100201
Jean-Marc Valin3b277dc2008-02-14 16:46:50 +1100202 nbest[id] = tmp_best;
203 nbest[id]->score = score;
204 nbest[id]->pos = j;
205 nbest[id]->orig = m;
206 nbest[id]->sign = sign;
207 nbest[id]->gain = g;
208 nbest[id]->xy = tmp_xy;
209 nbest[id]->yy = tmp_yy;
210 nbest[id]->yp = tmp_yp;
Jean-Marc Valin1e7087e2007-12-04 13:05:43 +1100211 }
Jean-Marc Valin636f5c82008-02-12 17:40:27 +1100212 }
Jean-Marc Valin41af4212007-11-30 18:35:37 +1100213 }
Jean-Marc Valin636f5c82008-02-12 17:40:27 +1100214
Jean-Marc Valin41af4212007-11-30 18:35:37 +1100215 }
Jean-Marc Valin0d587d82008-02-14 21:29:50 +1100216 /* Only now that we've made the final choice, update ny/iny and others */
Jean-Marc Valincab576e2008-02-12 17:21:14 +1100217 for (k=0;k<Lupdate;k++)
Jean-Marc Valin41af4212007-11-30 18:35:37 +1100218 {
Jean-Marc Valin3b277dc2008-02-14 16:46:50 +1100219 int n;
220 int is;
221 float s;
222 is = nbest[k]->sign*pulsesAtOnce;
223 s = is;
224 for (n=0;n<N;n++)
225 ny[k][n] = y[nbest[k]->orig][n] - alpha*s*p[nbest[k]->pos]*p[n];
226 ny[k][nbest[k]->pos] += s;
Jean-Marc Valin0d587d82008-02-14 21:29:50 +1100227
Jean-Marc Valin3b277dc2008-02-14 16:46:50 +1100228 for (n=0;n<N;n++)
229 iny[k][n] = iy[nbest[k]->orig][n];
230 iny[k][nbest[k]->pos] += is;
Jean-Marc Valin0d587d82008-02-14 21:29:50 +1100231
Jean-Marc Valin3b277dc2008-02-14 16:46:50 +1100232 xy[k] = nbest[k]->xy;
233 yy[k] = nbest[k]->yy;
234 yp[k] = nbest[k]->yp;
235 }
Jean-Marc Valin0d587d82008-02-14 21:29:50 +1100236 /* Swap ny/iny with y/iy */
Jean-Marc Valin3b277dc2008-02-14 16:46:50 +1100237 for (k=0;k<Lupdate;k++)
238 {
Jean-Marc Valinfe419832008-02-12 15:05:01 +1100239 float *tmp_ny;
240 int *tmp_iny;
241
Jean-Marc Valinfe419832008-02-12 15:05:01 +1100242 tmp_ny = ny[k];
243 ny[k] = y[k];
244 y[k] = tmp_ny;
245 tmp_iny = iny[k];
246 iny[k] = iy[k];
247 iy[k] = tmp_iny;
Jean-Marc Valin41af4212007-11-30 18:35:37 +1100248 }
Jean-Marc Valin846d4e22008-02-12 13:48:48 +1100249 pulsesLeft -= pulsesAtOnce;
Jean-Marc Valin41af4212007-11-30 18:35:37 +1100250 }
251
Jean-Marc Valinac1e03d2008-02-12 23:00:18 +1100252 if (0) {
253 float err=0;
254 for (i=0;i<N;i++)
Jean-Marc Valin3b277dc2008-02-14 16:46:50 +1100255 err += (x[i]-nbest[0]->gain*y[0][i])*(x[i]-nbest[0]->gain*y[0][i]);
Jean-Marc Valina85657b2008-02-20 11:59:30 +1100256 /*if (N<=10)
257 printf ("%f %d %d\n", err, K, N);*/
Jean-Marc Valinac1e03d2008-02-12 23:00:18 +1100258 }
Jean-Marc Valin41af4212007-11-30 18:35:37 +1100259 for (i=0;i<N;i++)
Jean-Marc Valin3b277dc2008-02-14 16:46:50 +1100260 x[i] = p[i]+nbest[0]->gain*y[0][i];
Jean-Marc Valin0d587d82008-02-14 21:29:50 +1100261 /* Sanity checks, don't bother */
Jean-Marc Valin1e7087e2007-12-04 13:05:43 +1100262 if (0) {
263 float E=1e-15;
264 int ABS = 0;
265 for (i=0;i<N;i++)
266 ABS += abs(iy[0][i]);
Jean-Marc Valina85657b2008-02-20 11:59:30 +1100267 /*if (K != ABS)
268 printf ("%d %d\n", K, ABS);*/
Jean-Marc Valin1e7087e2007-12-04 13:05:43 +1100269 for (i=0;i<N;i++)
270 E += x[i]*x[i];
Jean-Marc Valina85657b2008-02-20 11:59:30 +1100271 /*printf ("%f\n", E);*/
Jean-Marc Valin1e7087e2007-12-04 13:05:43 +1100272 E = 1/sqrt(E);
273 for (i=0;i<N;i++)
274 x[i] *= E;
275 }
Jean-Marc Valin5fa59952008-02-14 13:50:44 +1100276
277 encode_pulses(iy[0], N, K, enc);
278
Jean-Marc Valina4833ff2008-01-10 15:34:00 +1100279 /* Recompute the gain in one pass to reduce the encoder-decoder mismatch
Jean-Marc Valin636f5c82008-02-12 17:40:27 +1100280 due to the recursive computation used in quantisation.
281 Not quite sure whether we need that or not */
Jean-Marc Valina4833ff2008-01-10 15:34:00 +1100282 if (1) {
Jean-Marc Valin4a897682007-12-12 00:45:15 +1100283 float Ryp=0;
Jean-Marc Valin4a897682007-12-12 00:45:15 +1100284 float Ryy=0;
285 float g=0;
Jean-Marc Valin4a897682007-12-12 00:45:15 +1100286
287 for (i=0;i<N;i++)
288 Ryp += iy[0][i]*p[i];
289
290 for (i=0;i<N;i++)
291 y[0][i] = iy[0][i] - alpha*Ryp*p[i];
292
Jean-Marc Valin4a897682007-12-12 00:45:15 +1100293 Ryp = 0;
294 for (i=0;i<N;i++)
295 Ryp += y[0][i]*p[i];
296
297 for (i=0;i<N;i++)
298 Ryy += y[0][i]*y[0][i];
299
300 g = (sqrt(Ryp*Ryp + Ryy - Ryy*Rpp) - Ryp)/Ryy;
301
302 for (i=0;i<N;i++)
303 x[i] = p[i] + g*y[0][i];
304
305 }
306
Jean-Marc Valin41af4212007-11-30 18:35:37 +1100307}
308
Jean-Marc Valin0d227d82007-12-31 16:12:12 +1100309void alg_unquant(float *x, int N, int K, float *p, float alpha, ec_dec *dec)
310{
311 int i;
Jean-Marc Valin0d227d82007-12-31 16:12:12 +1100312 float Rpp=0, Ryp=0, Ryy=0;
313 float g;
Jean-Marc Valin9a0bba12008-02-20 14:08:50 +1100314 VARDECL(int *iy);
315 VARDECL(float *y);
316
317 ALLOC(iy, N, int);
318 ALLOC(y, N, float);
Jean-Marc Valin25298f22007-12-03 15:24:11 +1100319
Jean-Marc Valin5fa59952008-02-14 13:50:44 +1100320 decode_pulses(iy, N, K, dec);
321
Jean-Marc Valina85657b2008-02-20 11:59:30 +1100322 /*for (i=0;i<N;i++)
323 printf ("%d ", iy[i]);*/
Jean-Marc Valin0d227d82007-12-31 16:12:12 +1100324 for (i=0;i<N;i++)
325 Rpp += p[i]*p[i];
326
327 for (i=0;i<N;i++)
328 Ryp += iy[i]*p[i];
329
330 for (i=0;i<N;i++)
331 y[i] = iy[i] - alpha*Ryp*p[i];
332
333 /* Recompute after the projection (I think it's right) */
334 Ryp = 0;
335 for (i=0;i<N;i++)
336 Ryp += y[i]*p[i];
337
338 for (i=0;i<N;i++)
339 Ryy += y[i]*y[i];
340
341 g = (sqrt(Ryp*Ryp + Ryy - Ryy*Rpp) - Ryp)/Ryy;
342
343 for (i=0;i<N;i++)
344 x[i] = p[i] + g*y[i];
345}
346
347
348static const float pg[11] = {1.f, .75f, .65f, 0.6f, 0.6f, .6f, .55f, .55f, .5f, .5f, .5f};
349
350void intra_prediction(float *x, float *W, int N, int K, float *Y, float *P, int B, int N0, ec_enc *enc)
Jean-Marc Valin4841a0a2007-12-03 13:54:30 +1100351{
352 int i,j;
353 int best=0;
Jean-Marc Valin50d11162007-12-03 14:34:52 +1100354 float best_score=0;
355 float s = 1;
Jean-Marc Valin0aa39032007-12-07 15:09:58 +1100356 int sign;
Jean-Marc Valin4841a0a2007-12-03 13:54:30 +1100357 float E;
Jean-Marc Valin9a0bba12008-02-20 14:08:50 +1100358 float pred_gain;
Jean-Marc Valin8f0f4b92008-02-11 13:52:44 +1100359 int max_pos = N0-N/B;
360 if (max_pos > 32)
361 max_pos = 32;
362
363 for (i=0;i<max_pos*B;i+=B)
Jean-Marc Valin4841a0a2007-12-03 13:54:30 +1100364 {
365 int j;
366 float xy=0, yy=0;
367 float score;
368 for (j=0;j<N;j++)
369 {
370 xy += x[j]*Y[i+j];
371 yy += Y[i+j]*Y[i+j];
372 }
Jean-Marc Valin50d11162007-12-03 14:34:52 +1100373 score = xy*xy/(.001+yy);
Jean-Marc Valin4841a0a2007-12-03 13:54:30 +1100374 if (score > best_score)
375 {
376 best_score = score;
377 best = i;
Jean-Marc Valin50d11162007-12-03 14:34:52 +1100378 if (xy>0)
379 s = 1;
380 else
381 s = -1;
Jean-Marc Valin4841a0a2007-12-03 13:54:30 +1100382 }
383 }
Jean-Marc Valin0aa39032007-12-07 15:09:58 +1100384 if (s<0)
385 sign = 1;
Jean-Marc Valin6e9058a2007-12-07 14:59:06 +1100386 else
Jean-Marc Valin0aa39032007-12-07 15:09:58 +1100387 sign = 0;
Jean-Marc Valina85657b2008-02-20 11:59:30 +1100388 /*printf ("%d %d ", sign, best);*/
Jean-Marc Valin0aa39032007-12-07 15:09:58 +1100389 ec_enc_uint(enc,sign,2);
Jean-Marc Valin8f0f4b92008-02-11 13:52:44 +1100390 ec_enc_uint(enc,best/B,max_pos);
Jean-Marc Valina85657b2008-02-20 11:59:30 +1100391 /*printf ("%d %f\n", best, best_score);*/
Jean-Marc Valin0d227d82007-12-31 16:12:12 +1100392
Jean-Marc Valin0d227d82007-12-31 16:12:12 +1100393 if (K>10)
394 pred_gain = pg[10];
395 else
396 pred_gain = pg[K];
397 E = 1e-10;
398 for (j=0;j<N;j++)
Jean-Marc Valin4841a0a2007-12-03 13:54:30 +1100399 {
Jean-Marc Valin0d227d82007-12-31 16:12:12 +1100400 P[j] = s*Y[best+j];
401 E += P[j]*P[j];
Jean-Marc Valin4841a0a2007-12-03 13:54:30 +1100402 }
Jean-Marc Valin0d227d82007-12-31 16:12:12 +1100403 E = pred_gain/sqrt(E);
404 for (j=0;j<N;j++)
405 P[j] *= E;
406 if (K>0)
407 {
408 for (j=0;j<N;j++)
409 x[j] -= P[j];
410 } else {
411 for (j=0;j<N;j++)
412 x[j] = P[j];
413 }
Jean-Marc Valina85657b2008-02-20 11:59:30 +1100414 /*printf ("quant ");*/
415 /*for (j=0;j<N;j++) printf ("%f ", P[j]);*/
Jean-Marc Valin0d227d82007-12-31 16:12:12 +1100416
Jean-Marc Valin4841a0a2007-12-03 13:54:30 +1100417}
Jean-Marc Valinfc08d0a2007-12-07 13:26:15 +1100418
Jean-Marc Valin0d227d82007-12-31 16:12:12 +1100419void intra_unquant(float *x, int N, int K, float *Y, float *P, int B, int N0, ec_dec *dec)
Jean-Marc Valin6e9058a2007-12-07 14:59:06 +1100420{
Jean-Marc Valin11f01722007-12-09 01:19:36 +1100421 int j;
Jean-Marc Valin0aa39032007-12-07 15:09:58 +1100422 int sign;
423 float s;
Jean-Marc Valin6e9058a2007-12-07 14:59:06 +1100424 int best;
425 float E;
Jean-Marc Valin9a0bba12008-02-20 14:08:50 +1100426 float pred_gain;
Jean-Marc Valin8f0f4b92008-02-11 13:52:44 +1100427 int max_pos = N0-N/B;
428 if (max_pos > 32)
429 max_pos = 32;
430
Jean-Marc Valin0aa39032007-12-07 15:09:58 +1100431 sign = ec_dec_uint(dec, 2);
432 if (sign == 0)
Jean-Marc Valin6e9058a2007-12-07 14:59:06 +1100433 s = 1;
434 else
435 s = -1;
436
Jean-Marc Valin8f0f4b92008-02-11 13:52:44 +1100437 best = B*ec_dec_uint(dec, max_pos);
Jean-Marc Valina85657b2008-02-20 11:59:30 +1100438 /*printf ("%d %d ", sign, best);*/
Jean-Marc Valin6e9058a2007-12-07 14:59:06 +1100439
Jean-Marc Valin0d227d82007-12-31 16:12:12 +1100440 if (K>10)
441 pred_gain = pg[10];
442 else
443 pred_gain = pg[K];
444 E = 1e-10;
445 for (j=0;j<N;j++)
446 {
447 P[j] = s*Y[best+j];
448 E += P[j]*P[j];
449 }
450 E = pred_gain/sqrt(E);
451 for (j=0;j<N;j++)
452 P[j] *= E;
Jean-Marc Valin6e9058a2007-12-07 14:59:06 +1100453 if (K==0)
454 {
Jean-Marc Valin6e9058a2007-12-07 14:59:06 +1100455 for (j=0;j<N;j++)
Jean-Marc Valin0d227d82007-12-31 16:12:12 +1100456 x[j] = P[j];
Jean-Marc Valin6e9058a2007-12-07 14:59:06 +1100457 }
458}
Jean-Marc Valin0e20ca02008-02-11 15:33:53 +1100459
Jean-Marc Valin0df0eb42008-02-13 16:00:10 +1100460void intra_fold(float *x, int N, float *Y, float *P, int B, int N0, int Nmax)
Jean-Marc Valin0e20ca02008-02-11 15:33:53 +1100461{
Jean-Marc Valin0df0eb42008-02-13 16:00:10 +1100462 int i, j;
Jean-Marc Valin0e20ca02008-02-11 15:33:53 +1100463 float E;
464
465 E = 1e-10;
Jean-Marc Valin0df0eb42008-02-13 16:00:10 +1100466 if (N0 >= Nmax/2)
Jean-Marc Valin0e20ca02008-02-11 15:33:53 +1100467 {
Jean-Marc Valin0df0eb42008-02-13 16:00:10 +1100468 for (i=0;i<B;i++)
469 {
470 for (j=0;j<N/B;j++)
471 {
472 P[j*B+i] = Y[(Nmax-N0-j-1)*B+i];
473 E += P[j*B+i]*P[j*B+i];
474 }
475 }
476 } else {
477 for (j=0;j<N;j++)
478 {
479 P[j] = Y[j];
480 E += P[j]*P[j];
481 }
Jean-Marc Valin0e20ca02008-02-11 15:33:53 +1100482 }
483 E = 1.f/sqrt(E);
484 for (j=0;j<N;j++)
485 P[j] *= E;
486 for (j=0;j<N;j++)
487 x[j] = P[j];
488}
489