blob: 33c920bc9a8eefd462a9d3e40308782b7939e4b5 [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 Valinb60340f2008-02-26 15:41:51 +110041#include "os_support.h"
Jean-Marc Valin41af4212007-11-30 18:35:37 +110042
Jean-Marc Valin883bd8e2008-02-15 00:34:01 +110043/* Enable this or define your own implementation if you want to speed up the
44 VQ search (used in inner loop only) */
45#if 0
46#include <xmmintrin.h>
47static inline float approx_sqrt(float x)
48{
49 _mm_store_ss(&x, _mm_sqrt_ss(_mm_set_ss(x)));
50 return x;
51}
52static inline float approx_inv(float x)
53{
54 _mm_store_ss(&x, _mm_rcp_ss(_mm_set_ss(x)));
55 return x;
56}
57#else
58#define approx_sqrt(x) (sqrt(x))
59#define approx_inv(x) (1.f/(x))
60#endif
61
Jean-Marc Valin879fbfd2008-02-20 17:17:13 +110062/** All the info necessary to keep track of a hypothesis during the search */
Jean-Marc Valin3b277dc2008-02-14 16:46:50 +110063struct NBest {
64 float score;
65 float gain;
66 int sign;
67 int pos;
68 int orig;
69 float xy;
70 float yy;
71 float yp;
72};
Jean-Marc Valin41af4212007-11-30 18:35:37 +110073
Jean-Marc Valin5f09ea52008-02-26 16:43:04 +110074void alg_quant(celt_norm_t *X, celt_mask_t *W, int N, int K, celt_norm_t *P, float alpha, ec_enc *enc)
Jean-Marc Valin41af4212007-11-30 18:35:37 +110075{
Jean-Marc Valin4a897682007-12-12 00:45:15 +110076 int L = 3;
Jean-Marc Valin2fa8aff2008-02-26 11:38:00 +110077 VARDECL(float *x);
78 VARDECL(float *p);
Jean-Marc Valin9a0bba12008-02-20 14:08:50 +110079 VARDECL(float *_y);
80 VARDECL(float *_ny);
81 VARDECL(int *_iy);
82 VARDECL(int *_iny);
83 VARDECL(float **y);
84 VARDECL(float **ny);
85 VARDECL(int **iy);
86 VARDECL(int **iny);
Jean-Marc Valin0d587d82008-02-14 21:29:50 +110087 int i, j, k, m;
Jean-Marc Valin846d4e22008-02-12 13:48:48 +110088 int pulsesLeft;
Jean-Marc Valin9a0bba12008-02-20 14:08:50 +110089 VARDECL(float *xy);
90 VARDECL(float *yy);
91 VARDECL(float *yp);
92 VARDECL(struct NBest *_nbest);
93 VARDECL(struct NBest **nbest);
Jean-Marc Valin1e7087e2007-12-04 13:05:43 +110094 float Rpp=0, Rxp=0;
Jean-Marc Valin41af4212007-11-30 18:35:37 +110095 int maxL = 1;
Jean-Marc Valin1e7087e2007-12-04 13:05:43 +110096
Jean-Marc Valin2fa8aff2008-02-26 11:38:00 +110097 ALLOC(x, N, float);
98 ALLOC(p, N, float);
Jean-Marc Valin9a0bba12008-02-20 14:08:50 +110099 ALLOC(_y, L*N, float);
100 ALLOC(_ny, L*N, float);
101 ALLOC(_iy, L*N, int);
102 ALLOC(_iny, L*N, int);
103 ALLOC(y, L*N, float*);
104 ALLOC(ny, L*N, float*);
105 ALLOC(iy, L*N, int*);
106 ALLOC(iny, L*N, int*);
107
108 ALLOC(xy, L, float);
109 ALLOC(yy, L, float);
110 ALLOC(yp, L, float);
111 ALLOC(_nbest, L, struct NBest);
112 ALLOC(nbest, L, struct NBest *);
113
Jean-Marc Valinb4dfce42008-02-25 17:41:30 +1100114 for (j=0;j<N;j++)
115 {
Jean-Marc Valin2fa8aff2008-02-26 11:38:00 +1100116 x[j] = X[j]*NORM_SCALING_1;
117 p[j] = P[j]*NORM_SCALING_1;
Jean-Marc Valinb4dfce42008-02-25 17:41:30 +1100118 }
119
Jean-Marc Valinfe419832008-02-12 15:05:01 +1100120 for (m=0;m<L;m++)
Jean-Marc Valin3b277dc2008-02-14 16:46:50 +1100121 nbest[m] = &_nbest[m];
122
123 for (m=0;m<L;m++)
Jean-Marc Valinfe419832008-02-12 15:05:01 +1100124 {
Jean-Marc Valin9a0bba12008-02-20 14:08:50 +1100125 ny[m] = &_ny[m*N];
126 iny[m] = &_iny[m*N];
127 y[m] = &_y[m*N];
128 iy[m] = &_iy[m*N];
Jean-Marc Valinfe419832008-02-12 15:05:01 +1100129 }
130
Jean-Marc Valin41af4212007-11-30 18:35:37 +1100131 for (j=0;j<N;j++)
Jean-Marc Valin0d587d82008-02-14 21:29:50 +1100132 {
Jean-Marc Valin41af4212007-11-30 18:35:37 +1100133 Rpp += p[j]*p[j];
Jean-Marc Valin1e7087e2007-12-04 13:05:43 +1100134 Rxp += x[j]*p[j];
Jean-Marc Valin0d587d82008-02-14 21:29:50 +1100135 }
Jean-Marc Valinb60340f2008-02-26 15:41:51 +1100136 if (Rpp>1)
137 celt_fatal("Rpp > 1");
138
Jean-Marc Valin0d587d82008-02-14 21:29:50 +1100139 /* We only need to initialise the zero because the first iteration only uses that */
140 for (i=0;i<N;i++)
141 y[0][i] = 0;
142 for (i=0;i<N;i++)
143 iy[0][i] = 0;
144 xy[0] = yy[0] = yp[0] = 0;
145
Jean-Marc Valin846d4e22008-02-12 13:48:48 +1100146 pulsesLeft = K;
147 while (pulsesLeft > 0)
Jean-Marc Valin41af4212007-11-30 18:35:37 +1100148 {
Jean-Marc Valin846d4e22008-02-12 13:48:48 +1100149 int pulsesAtOnce=1;
Jean-Marc Valincab576e2008-02-12 17:21:14 +1100150 int Lupdate = L;
Jean-Marc Valin41af4212007-11-30 18:35:37 +1100151 int L2 = L;
Jean-Marc Valin0d587d82008-02-14 21:29:50 +1100152
153 /* Decide on complexity strategy */
Jean-Marc Valincab576e2008-02-12 17:21:14 +1100154 pulsesAtOnce = pulsesLeft/N;
155 if (pulsesAtOnce<1)
156 pulsesAtOnce = 1;
157 if (pulsesLeft-pulsesAtOnce > 3 || N > 30)
158 Lupdate = 1;
Jean-Marc Valina85657b2008-02-20 11:59:30 +1100159 /*printf ("%d %d %d/%d %d\n", Lupdate, pulsesAtOnce, pulsesLeft, K, N);*/
Jean-Marc Valincab576e2008-02-12 17:21:14 +1100160 L2 = Lupdate;
161 if (L2>maxL)
Jean-Marc Valin41af4212007-11-30 18:35:37 +1100162 {
163 L2 = maxL;
164 maxL *= N;
165 }
Jean-Marc Valin846d4e22008-02-12 13:48:48 +1100166
Jean-Marc Valin0d587d82008-02-14 21:29:50 +1100167 for (m=0;m<Lupdate;m++)
Jean-Marc Valin883bd8e2008-02-15 00:34:01 +1100168 nbest[m]->score = -1e10f;
Jean-Marc Valin41af4212007-11-30 18:35:37 +1100169
170 for (m=0;m<L2;m++)
171 {
172 for (j=0;j<N;j++)
173 {
Jean-Marc Valin1e7087e2007-12-04 13:05:43 +1100174 int sign;
Jean-Marc Valin0d587d82008-02-14 21:29:50 +1100175 /*if (x[j]>0) sign=1; else sign=-1;*/
Jean-Marc Valin1e7087e2007-12-04 13:05:43 +1100176 for (sign=-1;sign<=1;sign+=2)
Jean-Marc Valin41af4212007-11-30 18:35:37 +1100177 {
Jean-Marc Valina85657b2008-02-20 11:59:30 +1100178 /*fprintf (stderr, "%d/%d %d/%d %d/%d\n", i, K, m, L2, j, N);*/
Jean-Marc Valin1e7087e2007-12-04 13:05:43 +1100179 float tmp_xy, tmp_yy, tmp_yp;
180 float score;
181 float g;
Jean-Marc Valin846d4e22008-02-12 13:48:48 +1100182 float s = sign*pulsesAtOnce;
Jean-Marc Valinfe419832008-02-12 15:05:01 +1100183
Jean-Marc Valin9a0bba12008-02-20 14:08:50 +1100184 /* All pulses at one location must have the same sign. */
185 if (iy[m][j]*sign < 0)
186 continue;
187
Jean-Marc Valina073c7b2008-02-14 16:58:04 +1100188 /* Updating the sums of the new pulse(s) */
Jean-Marc Valin1e7087e2007-12-04 13:05:43 +1100189 tmp_xy = xy[m] + s*x[j] - alpha*s*p[j]*Rxp;
Jean-Marc Valin883bd8e2008-02-15 00:34:01 +1100190 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];
191 tmp_yp = yp[m] + s*p[j] *(1.f-alpha*Rpp);
Jean-Marc Valina073c7b2008-02-14 16:58:04 +1100192
193 /* Compute the gain such that ||p + g*y|| = 1 */
Jean-Marc Valin883bd8e2008-02-15 00:34:01 +1100194 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 +1100195 /* Knowing that gain, what the error: (x-g*y)^2
196 (result is negated and we discard x^2 because it's constant) */
Jean-Marc Valin883bd8e2008-02-15 00:34:01 +1100197 score = 2.f*g*tmp_xy - g*g*tmp_yy;
Jean-Marc Valin41af4212007-11-30 18:35:37 +1100198
Jean-Marc Valin3b277dc2008-02-14 16:46:50 +1100199 if (score>nbest[Lupdate-1]->score)
Jean-Marc Valin1e7087e2007-12-04 13:05:43 +1100200 {
Jean-Marc Valin472a5f02008-02-19 13:12:32 +1100201 int k;
Jean-Marc Valincab576e2008-02-12 17:21:14 +1100202 int id = Lupdate-1;
Jean-Marc Valin3b277dc2008-02-14 16:46:50 +1100203 struct NBest *tmp_best;
204
205 /* Save some pointers that would be deleted and use them for the current entry*/
206 tmp_best = nbest[Lupdate-1];
207 while (id > 0 && score > nbest[id-1]->score)
Jean-Marc Valin1e7087e2007-12-04 13:05:43 +1100208 id--;
209
Jean-Marc Valincab576e2008-02-12 17:21:14 +1100210 for (k=Lupdate-1;k>id;k--)
Jean-Marc Valin3b277dc2008-02-14 16:46:50 +1100211 nbest[k] = nbest[k-1];
Jean-Marc Valin1e7087e2007-12-04 13:05:43 +1100212
Jean-Marc Valin3b277dc2008-02-14 16:46:50 +1100213 nbest[id] = tmp_best;
214 nbest[id]->score = score;
215 nbest[id]->pos = j;
216 nbest[id]->orig = m;
217 nbest[id]->sign = sign;
218 nbest[id]->gain = g;
219 nbest[id]->xy = tmp_xy;
220 nbest[id]->yy = tmp_yy;
221 nbest[id]->yp = tmp_yp;
Jean-Marc Valin1e7087e2007-12-04 13:05:43 +1100222 }
Jean-Marc Valin636f5c82008-02-12 17:40:27 +1100223 }
Jean-Marc Valin41af4212007-11-30 18:35:37 +1100224 }
Jean-Marc Valin636f5c82008-02-12 17:40:27 +1100225
Jean-Marc Valin41af4212007-11-30 18:35:37 +1100226 }
Jean-Marc Valinb60340f2008-02-26 15:41:51 +1100227
228 if (!(nbest[0]->score > -1e10f))
229 celt_fatal("Could not find any match in VQ codebook. Something got corrupted somewhere.");
Jean-Marc Valin0d587d82008-02-14 21:29:50 +1100230 /* Only now that we've made the final choice, update ny/iny and others */
Jean-Marc Valincab576e2008-02-12 17:21:14 +1100231 for (k=0;k<Lupdate;k++)
Jean-Marc Valin41af4212007-11-30 18:35:37 +1100232 {
Jean-Marc Valin3b277dc2008-02-14 16:46:50 +1100233 int n;
234 int is;
235 float s;
236 is = nbest[k]->sign*pulsesAtOnce;
237 s = is;
238 for (n=0;n<N;n++)
239 ny[k][n] = y[nbest[k]->orig][n] - alpha*s*p[nbest[k]->pos]*p[n];
240 ny[k][nbest[k]->pos] += s;
Jean-Marc Valin0d587d82008-02-14 21:29:50 +1100241
Jean-Marc Valin3b277dc2008-02-14 16:46:50 +1100242 for (n=0;n<N;n++)
243 iny[k][n] = iy[nbest[k]->orig][n];
244 iny[k][nbest[k]->pos] += is;
Jean-Marc Valin0d587d82008-02-14 21:29:50 +1100245
Jean-Marc Valin3b277dc2008-02-14 16:46:50 +1100246 xy[k] = nbest[k]->xy;
247 yy[k] = nbest[k]->yy;
248 yp[k] = nbest[k]->yp;
249 }
Jean-Marc Valin0d587d82008-02-14 21:29:50 +1100250 /* Swap ny/iny with y/iy */
Jean-Marc Valin3b277dc2008-02-14 16:46:50 +1100251 for (k=0;k<Lupdate;k++)
252 {
Jean-Marc Valinfe419832008-02-12 15:05:01 +1100253 float *tmp_ny;
254 int *tmp_iny;
255
Jean-Marc Valinfe419832008-02-12 15:05:01 +1100256 tmp_ny = ny[k];
257 ny[k] = y[k];
258 y[k] = tmp_ny;
259 tmp_iny = iny[k];
260 iny[k] = iy[k];
261 iy[k] = tmp_iny;
Jean-Marc Valin41af4212007-11-30 18:35:37 +1100262 }
Jean-Marc Valin846d4e22008-02-12 13:48:48 +1100263 pulsesLeft -= pulsesAtOnce;
Jean-Marc Valin41af4212007-11-30 18:35:37 +1100264 }
265
Jean-Marc Valinac1e03d2008-02-12 23:00:18 +1100266 if (0) {
267 float err=0;
268 for (i=0;i<N;i++)
Jean-Marc Valin3b277dc2008-02-14 16:46:50 +1100269 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 +1100270 /*if (N<=10)
271 printf ("%f %d %d\n", err, K, N);*/
Jean-Marc Valinac1e03d2008-02-12 23:00:18 +1100272 }
Jean-Marc Valin41af4212007-11-30 18:35:37 +1100273 for (i=0;i<N;i++)
Jean-Marc Valin3b277dc2008-02-14 16:46:50 +1100274 x[i] = p[i]+nbest[0]->gain*y[0][i];
Jean-Marc Valin0d587d82008-02-14 21:29:50 +1100275 /* Sanity checks, don't bother */
Jean-Marc Valin1e7087e2007-12-04 13:05:43 +1100276 if (0) {
277 float E=1e-15;
278 int ABS = 0;
279 for (i=0;i<N;i++)
280 ABS += abs(iy[0][i]);
Jean-Marc Valina85657b2008-02-20 11:59:30 +1100281 /*if (K != ABS)
282 printf ("%d %d\n", K, ABS);*/
Jean-Marc Valin1e7087e2007-12-04 13:05:43 +1100283 for (i=0;i<N;i++)
284 E += x[i]*x[i];
Jean-Marc Valina85657b2008-02-20 11:59:30 +1100285 /*printf ("%f\n", E);*/
Jean-Marc Valin1e7087e2007-12-04 13:05:43 +1100286 E = 1/sqrt(E);
287 for (i=0;i<N;i++)
288 x[i] *= E;
289 }
Jean-Marc Valin5fa59952008-02-14 13:50:44 +1100290
291 encode_pulses(iy[0], N, K, enc);
292
Jean-Marc Valina4833ff2008-01-10 15:34:00 +1100293 /* Recompute the gain in one pass to reduce the encoder-decoder mismatch
Jean-Marc Valin636f5c82008-02-12 17:40:27 +1100294 due to the recursive computation used in quantisation.
295 Not quite sure whether we need that or not */
Jean-Marc Valina4833ff2008-01-10 15:34:00 +1100296 if (1) {
Jean-Marc Valin4a897682007-12-12 00:45:15 +1100297 float Ryp=0;
Jean-Marc Valin4a897682007-12-12 00:45:15 +1100298 float Ryy=0;
299 float g=0;
Jean-Marc Valin4a897682007-12-12 00:45:15 +1100300
301 for (i=0;i<N;i++)
302 Ryp += iy[0][i]*p[i];
303
304 for (i=0;i<N;i++)
305 y[0][i] = iy[0][i] - alpha*Ryp*p[i];
306
Jean-Marc Valin4a897682007-12-12 00:45:15 +1100307 Ryp = 0;
308 for (i=0;i<N;i++)
309 Ryp += y[0][i]*p[i];
310
311 for (i=0;i<N;i++)
312 Ryy += y[0][i]*y[0][i];
313
314 g = (sqrt(Ryp*Ryp + Ryy - Ryy*Rpp) - Ryp)/Ryy;
315
316 for (i=0;i<N;i++)
317 x[i] = p[i] + g*y[0][i];
318
319 }
Jean-Marc Valinb4dfce42008-02-25 17:41:30 +1100320 for (j=0;j<N;j++)
321 {
Jean-Marc Valin2fa8aff2008-02-26 11:38:00 +1100322 X[j] = x[j] * NORM_SCALING;
323 P[j] = p[j] * NORM_SCALING;
Jean-Marc Valinb4dfce42008-02-25 17:41:30 +1100324 }
Jean-Marc Valin4a897682007-12-12 00:45:15 +1100325
Jean-Marc Valin41af4212007-11-30 18:35:37 +1100326}
327
Jean-Marc Valin879fbfd2008-02-20 17:17:13 +1100328/** Decode pulse vector and combine the result with the pitch vector to produce
329 the final normalised signal in the current band. */
Jean-Marc Valin2fa8aff2008-02-26 11:38:00 +1100330void alg_unquant(celt_norm_t *X, int N, int K, celt_norm_t *P, float alpha, ec_dec *dec)
Jean-Marc Valin0d227d82007-12-31 16:12:12 +1100331{
332 int i;
Jean-Marc Valin0d227d82007-12-31 16:12:12 +1100333 float Rpp=0, Ryp=0, Ryy=0;
334 float g;
Jean-Marc Valin9a0bba12008-02-20 14:08:50 +1100335 VARDECL(int *iy);
336 VARDECL(float *y);
Jean-Marc Valin2fa8aff2008-02-26 11:38:00 +1100337 VARDECL(float *x);
338 VARDECL(float *p);
Jean-Marc Valin9a0bba12008-02-20 14:08:50 +1100339
340 ALLOC(iy, N, int);
341 ALLOC(y, N, float);
Jean-Marc Valin2fa8aff2008-02-26 11:38:00 +1100342 ALLOC(x, N, float);
343 ALLOC(p, N, float);
Jean-Marc Valin25298f22007-12-03 15:24:11 +1100344
Jean-Marc Valin5fa59952008-02-14 13:50:44 +1100345 decode_pulses(iy, N, K, dec);
Jean-Marc Valinb4dfce42008-02-25 17:41:30 +1100346 for (i=0;i<N;i++)
347 {
Jean-Marc Valin2fa8aff2008-02-26 11:38:00 +1100348 x[i] = X[i]*NORM_SCALING_1;
349 p[i] = P[i]*NORM_SCALING_1;
Jean-Marc Valinb4dfce42008-02-25 17:41:30 +1100350 }
Jean-Marc Valin5fa59952008-02-14 13:50:44 +1100351
Jean-Marc Valina85657b2008-02-20 11:59:30 +1100352 /*for (i=0;i<N;i++)
353 printf ("%d ", iy[i]);*/
Jean-Marc Valin0d227d82007-12-31 16:12:12 +1100354 for (i=0;i<N;i++)
355 Rpp += p[i]*p[i];
356
357 for (i=0;i<N;i++)
358 Ryp += iy[i]*p[i];
359
360 for (i=0;i<N;i++)
361 y[i] = iy[i] - alpha*Ryp*p[i];
362
363 /* Recompute after the projection (I think it's right) */
364 Ryp = 0;
365 for (i=0;i<N;i++)
366 Ryp += y[i]*p[i];
367
368 for (i=0;i<N;i++)
369 Ryy += y[i]*y[i];
370
371 g = (sqrt(Ryp*Ryp + Ryy - Ryy*Rpp) - Ryp)/Ryy;
372
373 for (i=0;i<N;i++)
374 x[i] = p[i] + g*y[i];
Jean-Marc Valinb4dfce42008-02-25 17:41:30 +1100375 for (i=0;i<N;i++)
376 {
Jean-Marc Valin2fa8aff2008-02-26 11:38:00 +1100377 X[i] = x[i] * NORM_SCALING;
378 P[i] = p[i] * NORM_SCALING;
Jean-Marc Valinb4dfce42008-02-25 17:41:30 +1100379 }
380
Jean-Marc Valin0d227d82007-12-31 16:12:12 +1100381}
382
383
384static const float pg[11] = {1.f, .75f, .65f, 0.6f, 0.6f, .6f, .55f, .55f, .5f, .5f, .5f};
385
Jean-Marc Valin5f09ea52008-02-26 16:43:04 +1100386void intra_prediction(celt_norm_t *x, celt_mask_t *W, int N, int K, celt_norm_t *Y, celt_norm_t *P, int B, int N0, ec_enc *enc)
Jean-Marc Valin4841a0a2007-12-03 13:54:30 +1100387{
388 int i,j;
389 int best=0;
Jean-Marc Valin50d11162007-12-03 14:34:52 +1100390 float best_score=0;
391 float s = 1;
Jean-Marc Valin0aa39032007-12-07 15:09:58 +1100392 int sign;
Jean-Marc Valin4841a0a2007-12-03 13:54:30 +1100393 float E;
Jean-Marc Valin9a0bba12008-02-20 14:08:50 +1100394 float pred_gain;
Jean-Marc Valin8f0f4b92008-02-11 13:52:44 +1100395 int max_pos = N0-N/B;
396 if (max_pos > 32)
397 max_pos = 32;
398
399 for (i=0;i<max_pos*B;i+=B)
Jean-Marc Valin4841a0a2007-12-03 13:54:30 +1100400 {
401 int j;
402 float xy=0, yy=0;
403 float score;
404 for (j=0;j<N;j++)
405 {
Jean-Marc Valinb4dfce42008-02-25 17:41:30 +1100406 xy += 1.f*x[j]*Y[i+N-j-1];
407 yy += 1.f*Y[i+N-j-1]*Y[i+N-j-1];
Jean-Marc Valin4841a0a2007-12-03 13:54:30 +1100408 }
Jean-Marc Valin50d11162007-12-03 14:34:52 +1100409 score = xy*xy/(.001+yy);
Jean-Marc Valin4841a0a2007-12-03 13:54:30 +1100410 if (score > best_score)
411 {
412 best_score = score;
413 best = i;
Jean-Marc Valin50d11162007-12-03 14:34:52 +1100414 if (xy>0)
415 s = 1;
416 else
417 s = -1;
Jean-Marc Valin4841a0a2007-12-03 13:54:30 +1100418 }
419 }
Jean-Marc Valin0aa39032007-12-07 15:09:58 +1100420 if (s<0)
421 sign = 1;
Jean-Marc Valin6e9058a2007-12-07 14:59:06 +1100422 else
Jean-Marc Valin0aa39032007-12-07 15:09:58 +1100423 sign = 0;
Jean-Marc Valina85657b2008-02-20 11:59:30 +1100424 /*printf ("%d %d ", sign, best);*/
Jean-Marc Valin0aa39032007-12-07 15:09:58 +1100425 ec_enc_uint(enc,sign,2);
Jean-Marc Valin8f0f4b92008-02-11 13:52:44 +1100426 ec_enc_uint(enc,best/B,max_pos);
Jean-Marc Valina85657b2008-02-20 11:59:30 +1100427 /*printf ("%d %f\n", best, best_score);*/
Jean-Marc Valin0d227d82007-12-31 16:12:12 +1100428
Jean-Marc Valin0d227d82007-12-31 16:12:12 +1100429 if (K>10)
430 pred_gain = pg[10];
431 else
432 pred_gain = pg[K];
433 E = 1e-10;
434 for (j=0;j<N;j++)
Jean-Marc Valin4841a0a2007-12-03 13:54:30 +1100435 {
Jean-Marc Valind501f612008-02-21 12:16:57 +1100436 P[j] = s*Y[best+N-j-1];
Jean-Marc Valinb4dfce42008-02-25 17:41:30 +1100437 E += NORM_SCALING_1*NORM_SCALING_1*P[j]*P[j];
Jean-Marc Valin4841a0a2007-12-03 13:54:30 +1100438 }
Jean-Marc Valin0d227d82007-12-31 16:12:12 +1100439 E = pred_gain/sqrt(E);
440 for (j=0;j<N;j++)
441 P[j] *= E;
442 if (K>0)
443 {
444 for (j=0;j<N;j++)
445 x[j] -= P[j];
446 } else {
447 for (j=0;j<N;j++)
448 x[j] = P[j];
449 }
Jean-Marc Valina85657b2008-02-20 11:59:30 +1100450 /*printf ("quant ");*/
451 /*for (j=0;j<N;j++) printf ("%f ", P[j]);*/
Jean-Marc Valin0d227d82007-12-31 16:12:12 +1100452
Jean-Marc Valin4841a0a2007-12-03 13:54:30 +1100453}
Jean-Marc Valinfc08d0a2007-12-07 13:26:15 +1100454
Jean-Marc Valin18ddc022008-02-22 14:24:50 +1100455void intra_unquant(celt_norm_t *x, int N, int K, celt_norm_t *Y, celt_norm_t *P, int B, int N0, ec_dec *dec)
Jean-Marc Valin6e9058a2007-12-07 14:59:06 +1100456{
Jean-Marc Valin11f01722007-12-09 01:19:36 +1100457 int j;
Jean-Marc Valin0aa39032007-12-07 15:09:58 +1100458 int sign;
459 float s;
Jean-Marc Valin6e9058a2007-12-07 14:59:06 +1100460 int best;
461 float E;
Jean-Marc Valin9a0bba12008-02-20 14:08:50 +1100462 float pred_gain;
Jean-Marc Valin8f0f4b92008-02-11 13:52:44 +1100463 int max_pos = N0-N/B;
464 if (max_pos > 32)
465 max_pos = 32;
466
Jean-Marc Valin0aa39032007-12-07 15:09:58 +1100467 sign = ec_dec_uint(dec, 2);
468 if (sign == 0)
Jean-Marc Valin6e9058a2007-12-07 14:59:06 +1100469 s = 1;
470 else
471 s = -1;
472
Jean-Marc Valin8f0f4b92008-02-11 13:52:44 +1100473 best = B*ec_dec_uint(dec, max_pos);
Jean-Marc Valina85657b2008-02-20 11:59:30 +1100474 /*printf ("%d %d ", sign, best);*/
Jean-Marc Valin6e9058a2007-12-07 14:59:06 +1100475
Jean-Marc Valin0d227d82007-12-31 16:12:12 +1100476 if (K>10)
477 pred_gain = pg[10];
478 else
479 pred_gain = pg[K];
480 E = 1e-10;
481 for (j=0;j<N;j++)
482 {
Jean-Marc Valind501f612008-02-21 12:16:57 +1100483 P[j] = s*Y[best+N-j-1];
Jean-Marc Valinb4dfce42008-02-25 17:41:30 +1100484 E += NORM_SCALING_1*NORM_SCALING_1*P[j]*P[j];
Jean-Marc Valin0d227d82007-12-31 16:12:12 +1100485 }
486 E = pred_gain/sqrt(E);
487 for (j=0;j<N;j++)
488 P[j] *= E;
Jean-Marc Valin6e9058a2007-12-07 14:59:06 +1100489 if (K==0)
490 {
Jean-Marc Valin6e9058a2007-12-07 14:59:06 +1100491 for (j=0;j<N;j++)
Jean-Marc Valin0d227d82007-12-31 16:12:12 +1100492 x[j] = P[j];
Jean-Marc Valin6e9058a2007-12-07 14:59:06 +1100493 }
494}
Jean-Marc Valin0e20ca02008-02-11 15:33:53 +1100495
Jean-Marc Valin18ddc022008-02-22 14:24:50 +1100496void intra_fold(celt_norm_t *x, int N, celt_norm_t *Y, celt_norm_t *P, int B, int N0, int Nmax)
Jean-Marc Valin0e20ca02008-02-11 15:33:53 +1100497{
Jean-Marc Valin0df0eb42008-02-13 16:00:10 +1100498 int i, j;
Jean-Marc Valin0e20ca02008-02-11 15:33:53 +1100499 float E;
500
501 E = 1e-10;
Jean-Marc Valin0df0eb42008-02-13 16:00:10 +1100502 if (N0 >= Nmax/2)
Jean-Marc Valin0e20ca02008-02-11 15:33:53 +1100503 {
Jean-Marc Valin0df0eb42008-02-13 16:00:10 +1100504 for (i=0;i<B;i++)
505 {
506 for (j=0;j<N/B;j++)
507 {
508 P[j*B+i] = Y[(Nmax-N0-j-1)*B+i];
Jean-Marc Valinb4dfce42008-02-25 17:41:30 +1100509 E += NORM_SCALING_1*NORM_SCALING_1*P[j*B+i]*P[j*B+i];
Jean-Marc Valin0df0eb42008-02-13 16:00:10 +1100510 }
511 }
512 } else {
513 for (j=0;j<N;j++)
514 {
515 P[j] = Y[j];
Jean-Marc Valinb4dfce42008-02-25 17:41:30 +1100516 E += NORM_SCALING_1*NORM_SCALING_1*P[j]*P[j];
Jean-Marc Valin0df0eb42008-02-13 16:00:10 +1100517 }
Jean-Marc Valin0e20ca02008-02-11 15:33:53 +1100518 }
519 E = 1.f/sqrt(E);
520 for (j=0;j<N;j++)
521 P[j] *= E;
522 for (j=0;j<N;j++)
523 x[j] = P[j];
524}
525