blob: 307508bffd7e1c4a538f1bb0e7321bcdf5308325 [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 Valind4018c32008-02-27 10:09:48 +110062/** Takes the pitch vector and the decoded residual vector (non-compressed),
63 applies the compression in the pitch direction, computes the gain that will
64 give ||p+g*y||=1 and mixes the residual with the pitch. */
Jean-Marc Valind17edd32008-02-27 16:52:30 +110065static void mix_pitch_and_residual(int *iy, celt_norm_t *X, int N, int K, celt_norm_t *P, celt_word16_t alpha)
Jean-Marc Valind4018c32008-02-27 10:09:48 +110066{
67 int i;
Jean-Marc Valinb50c5412008-02-27 17:05:43 +110068 celt_word32_t Ryp, Ryy, Rpp;
Jean-Marc Valind4018c32008-02-27 10:09:48 +110069 float g;
Jean-Marc Valind17edd32008-02-27 16:52:30 +110070 VARDECL(celt_norm_t *y);
Jean-Marc Valind17edd32008-02-27 16:52:30 +110071#ifdef FIXED_POINT
Jean-Marc Valin1ca07222008-02-27 17:23:04 +110072 int yshift = 14-EC_ILOG(K);
Jean-Marc Valind17edd32008-02-27 16:52:30 +110073#endif
74 ALLOC(y, N, celt_norm_t);
Jean-Marc Valind4018c32008-02-27 10:09:48 +110075
76 /*for (i=0;i<N;i++)
77 printf ("%d ", iy[i]);*/
Jean-Marc Valinb50c5412008-02-27 17:05:43 +110078 Rpp = 0;
Jean-Marc Valind4018c32008-02-27 10:09:48 +110079 for (i=0;i<N;i++)
Jean-Marc Valinb50c5412008-02-27 17:05:43 +110080 Rpp = MAC16_16(Rpp,P[i],P[i]);
Jean-Marc Valind4018c32008-02-27 10:09:48 +110081
Jean-Marc Valinb50c5412008-02-27 17:05:43 +110082 Ryp = 0;
Jean-Marc Valind4018c32008-02-27 10:09:48 +110083 for (i=0;i<N;i++)
Jean-Marc Valinb50c5412008-02-27 17:05:43 +110084 Ryp = MAC16_16(Ryp,SHL16(iy[i],yshift),P[i]);
Jean-Marc Valind4018c32008-02-27 10:09:48 +110085
Jean-Marc Valind17edd32008-02-27 16:52:30 +110086 /* Remove part of the pitch component to compute the real residual from
87 the encoded (int) one */
Jean-Marc Valind4018c32008-02-27 10:09:48 +110088 for (i=0;i<N;i++)
Jean-Marc Valind17edd32008-02-27 16:52:30 +110089 y[i] = SUB16(SHL16(iy[i],yshift),
Jean-Marc Valinb50c5412008-02-27 17:05:43 +110090 MULT16_16_Q15(alpha,MULT16_16_Q14(EXTRACT16(SHR32(Ryp,14)),P[i])));
Jean-Marc Valind4018c32008-02-27 10:09:48 +110091
92 /* Recompute after the projection (I think it's right) */
93 Ryp = 0;
94 for (i=0;i<N;i++)
Jean-Marc Valinb50c5412008-02-27 17:05:43 +110095 Ryp = MAC16_16(Ryp,y[i],P[i]);
Jean-Marc Valind4018c32008-02-27 10:09:48 +110096
Jean-Marc Valinb50c5412008-02-27 17:05:43 +110097 Ryy = 0;
Jean-Marc Valind4018c32008-02-27 10:09:48 +110098 for (i=0;i<N;i++)
Jean-Marc Valinb50c5412008-02-27 17:05:43 +110099 Ryy = MAC16_16(Ryy, y[i],y[i]);
Jean-Marc Valind4018c32008-02-27 10:09:48 +1100100
Jean-Marc Valin1ca07222008-02-27 17:23:04 +1100101 /* g = (sqrt(Ryp^2 + Ryy - Rpp*Ryy)-Ryp)/Ryy */
102 g = (sqrt(MULT16_16(PSHR32(Ryp,14),PSHR32(Ryp,14)) + Ryy - MULT16_16(PSHR32(Ryy,14),PSHR32(Rpp,14))) - PSHR32(Ryp,14))/Ryy;
Jean-Marc Valind4018c32008-02-27 10:09:48 +1100103
104 for (i=0;i<N;i++)
105 X[i] = P[i] + NORM_SCALING*g*y[i];
106}
107
Jean-Marc Valin879fbfd2008-02-20 17:17:13 +1100108/** All the info necessary to keep track of a hypothesis during the search */
Jean-Marc Valin3b277dc2008-02-14 16:46:50 +1100109struct NBest {
110 float score;
111 float gain;
112 int sign;
113 int pos;
114 int orig;
115 float xy;
116 float yy;
117 float yp;
118};
Jean-Marc Valin41af4212007-11-30 18:35:37 +1100119
Jean-Marc Valin9d8d9b32008-02-27 16:17:39 +1100120void alg_quant(celt_norm_t *X, celt_mask_t *W, int N, int K, celt_norm_t *P, celt_word16_t alpha, ec_enc *enc)
Jean-Marc Valin41af4212007-11-30 18:35:37 +1100121{
Jean-Marc Valin4a897682007-12-12 00:45:15 +1100122 int L = 3;
Jean-Marc Valin2fa8aff2008-02-26 11:38:00 +1100123 VARDECL(float *x);
124 VARDECL(float *p);
Jean-Marc Valin9a0bba12008-02-20 14:08:50 +1100125 VARDECL(float *_y);
126 VARDECL(float *_ny);
127 VARDECL(int *_iy);
128 VARDECL(int *_iny);
129 VARDECL(float **y);
130 VARDECL(float **ny);
131 VARDECL(int **iy);
132 VARDECL(int **iny);
Jean-Marc Valin0d587d82008-02-14 21:29:50 +1100133 int i, j, k, m;
Jean-Marc Valin846d4e22008-02-12 13:48:48 +1100134 int pulsesLeft;
Jean-Marc Valin9a0bba12008-02-20 14:08:50 +1100135 VARDECL(float *xy);
136 VARDECL(float *yy);
137 VARDECL(float *yp);
138 VARDECL(struct NBest *_nbest);
139 VARDECL(struct NBest **nbest);
Jean-Marc Valin1e7087e2007-12-04 13:05:43 +1100140 float Rpp=0, Rxp=0;
Jean-Marc Valin41af4212007-11-30 18:35:37 +1100141 int maxL = 1;
Jean-Marc Valin9d8d9b32008-02-27 16:17:39 +1100142 float _alpha = Q15_ONE_1*alpha;
143
Jean-Marc Valin2fa8aff2008-02-26 11:38:00 +1100144 ALLOC(x, N, float);
145 ALLOC(p, N, float);
Jean-Marc Valin9a0bba12008-02-20 14:08:50 +1100146 ALLOC(_y, L*N, float);
147 ALLOC(_ny, L*N, float);
148 ALLOC(_iy, L*N, int);
149 ALLOC(_iny, L*N, int);
150 ALLOC(y, L*N, float*);
151 ALLOC(ny, L*N, float*);
152 ALLOC(iy, L*N, int*);
153 ALLOC(iny, L*N, int*);
154
155 ALLOC(xy, L, float);
156 ALLOC(yy, L, float);
157 ALLOC(yp, L, float);
158 ALLOC(_nbest, L, struct NBest);
159 ALLOC(nbest, L, struct NBest *);
160
Jean-Marc Valinb4dfce42008-02-25 17:41:30 +1100161 for (j=0;j<N;j++)
162 {
Jean-Marc Valin2fa8aff2008-02-26 11:38:00 +1100163 x[j] = X[j]*NORM_SCALING_1;
164 p[j] = P[j]*NORM_SCALING_1;
Jean-Marc Valinb4dfce42008-02-25 17:41:30 +1100165 }
166
Jean-Marc Valinfe419832008-02-12 15:05:01 +1100167 for (m=0;m<L;m++)
Jean-Marc Valin3b277dc2008-02-14 16:46:50 +1100168 nbest[m] = &_nbest[m];
169
170 for (m=0;m<L;m++)
Jean-Marc Valinfe419832008-02-12 15:05:01 +1100171 {
Jean-Marc Valin9a0bba12008-02-20 14:08:50 +1100172 ny[m] = &_ny[m*N];
173 iny[m] = &_iny[m*N];
174 y[m] = &_y[m*N];
175 iy[m] = &_iy[m*N];
Jean-Marc Valinfe419832008-02-12 15:05:01 +1100176 }
177
Jean-Marc Valin41af4212007-11-30 18:35:37 +1100178 for (j=0;j<N;j++)
Jean-Marc Valin0d587d82008-02-14 21:29:50 +1100179 {
Jean-Marc Valin41af4212007-11-30 18:35:37 +1100180 Rpp += p[j]*p[j];
Jean-Marc Valin1e7087e2007-12-04 13:05:43 +1100181 Rxp += x[j]*p[j];
Jean-Marc Valin0d587d82008-02-14 21:29:50 +1100182 }
Jean-Marc Valinb60340f2008-02-26 15:41:51 +1100183 if (Rpp>1)
184 celt_fatal("Rpp > 1");
185
Jean-Marc Valin0d587d82008-02-14 21:29:50 +1100186 /* We only need to initialise the zero because the first iteration only uses that */
187 for (i=0;i<N;i++)
188 y[0][i] = 0;
189 for (i=0;i<N;i++)
190 iy[0][i] = 0;
191 xy[0] = yy[0] = yp[0] = 0;
192
Jean-Marc Valin846d4e22008-02-12 13:48:48 +1100193 pulsesLeft = K;
194 while (pulsesLeft > 0)
Jean-Marc Valin41af4212007-11-30 18:35:37 +1100195 {
Jean-Marc Valin846d4e22008-02-12 13:48:48 +1100196 int pulsesAtOnce=1;
Jean-Marc Valincab576e2008-02-12 17:21:14 +1100197 int Lupdate = L;
Jean-Marc Valin41af4212007-11-30 18:35:37 +1100198 int L2 = L;
Jean-Marc Valin0d587d82008-02-14 21:29:50 +1100199
200 /* Decide on complexity strategy */
Jean-Marc Valincab576e2008-02-12 17:21:14 +1100201 pulsesAtOnce = pulsesLeft/N;
202 if (pulsesAtOnce<1)
203 pulsesAtOnce = 1;
204 if (pulsesLeft-pulsesAtOnce > 3 || N > 30)
205 Lupdate = 1;
Jean-Marc Valina85657b2008-02-20 11:59:30 +1100206 /*printf ("%d %d %d/%d %d\n", Lupdate, pulsesAtOnce, pulsesLeft, K, N);*/
Jean-Marc Valincab576e2008-02-12 17:21:14 +1100207 L2 = Lupdate;
208 if (L2>maxL)
Jean-Marc Valin41af4212007-11-30 18:35:37 +1100209 {
210 L2 = maxL;
211 maxL *= N;
212 }
Jean-Marc Valin846d4e22008-02-12 13:48:48 +1100213
Jean-Marc Valin0d587d82008-02-14 21:29:50 +1100214 for (m=0;m<Lupdate;m++)
Jean-Marc Valin883bd8e2008-02-15 00:34:01 +1100215 nbest[m]->score = -1e10f;
Jean-Marc Valin41af4212007-11-30 18:35:37 +1100216
217 for (m=0;m<L2;m++)
218 {
219 for (j=0;j<N;j++)
220 {
Jean-Marc Valin1e7087e2007-12-04 13:05:43 +1100221 int sign;
Jean-Marc Valin0d587d82008-02-14 21:29:50 +1100222 /*if (x[j]>0) sign=1; else sign=-1;*/
Jean-Marc Valin1e7087e2007-12-04 13:05:43 +1100223 for (sign=-1;sign<=1;sign+=2)
Jean-Marc Valin41af4212007-11-30 18:35:37 +1100224 {
Jean-Marc Valina85657b2008-02-20 11:59:30 +1100225 /*fprintf (stderr, "%d/%d %d/%d %d/%d\n", i, K, m, L2, j, N);*/
Jean-Marc Valin1e7087e2007-12-04 13:05:43 +1100226 float tmp_xy, tmp_yy, tmp_yp;
227 float score;
228 float g;
Jean-Marc Valin846d4e22008-02-12 13:48:48 +1100229 float s = sign*pulsesAtOnce;
Jean-Marc Valinfe419832008-02-12 15:05:01 +1100230
Jean-Marc Valin9a0bba12008-02-20 14:08:50 +1100231 /* All pulses at one location must have the same sign. */
232 if (iy[m][j]*sign < 0)
233 continue;
234
Jean-Marc Valina073c7b2008-02-14 16:58:04 +1100235 /* Updating the sums of the new pulse(s) */
Jean-Marc Valin9d8d9b32008-02-27 16:17:39 +1100236 tmp_xy = xy[m] + s*x[j] - _alpha*s*p[j]*Rxp;
237 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];
238 tmp_yp = yp[m] + s*p[j] *(1.f-_alpha*Rpp);
Jean-Marc Valina073c7b2008-02-14 16:58:04 +1100239
240 /* Compute the gain such that ||p + g*y|| = 1 */
Jean-Marc Valin883bd8e2008-02-15 00:34:01 +1100241 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 +1100242 /* Knowing that gain, what the error: (x-g*y)^2
243 (result is negated and we discard x^2 because it's constant) */
Jean-Marc Valin883bd8e2008-02-15 00:34:01 +1100244 score = 2.f*g*tmp_xy - g*g*tmp_yy;
Jean-Marc Valin41af4212007-11-30 18:35:37 +1100245
Jean-Marc Valin3b277dc2008-02-14 16:46:50 +1100246 if (score>nbest[Lupdate-1]->score)
Jean-Marc Valin1e7087e2007-12-04 13:05:43 +1100247 {
Jean-Marc Valin472a5f02008-02-19 13:12:32 +1100248 int k;
Jean-Marc Valincab576e2008-02-12 17:21:14 +1100249 int id = Lupdate-1;
Jean-Marc Valin3b277dc2008-02-14 16:46:50 +1100250 struct NBest *tmp_best;
251
252 /* Save some pointers that would be deleted and use them for the current entry*/
253 tmp_best = nbest[Lupdate-1];
254 while (id > 0 && score > nbest[id-1]->score)
Jean-Marc Valin1e7087e2007-12-04 13:05:43 +1100255 id--;
256
Jean-Marc Valincab576e2008-02-12 17:21:14 +1100257 for (k=Lupdate-1;k>id;k--)
Jean-Marc Valin3b277dc2008-02-14 16:46:50 +1100258 nbest[k] = nbest[k-1];
Jean-Marc Valin1e7087e2007-12-04 13:05:43 +1100259
Jean-Marc Valin3b277dc2008-02-14 16:46:50 +1100260 nbest[id] = tmp_best;
261 nbest[id]->score = score;
262 nbest[id]->pos = j;
263 nbest[id]->orig = m;
264 nbest[id]->sign = sign;
265 nbest[id]->gain = g;
266 nbest[id]->xy = tmp_xy;
267 nbest[id]->yy = tmp_yy;
268 nbest[id]->yp = tmp_yp;
Jean-Marc Valin1e7087e2007-12-04 13:05:43 +1100269 }
Jean-Marc Valin636f5c82008-02-12 17:40:27 +1100270 }
Jean-Marc Valin41af4212007-11-30 18:35:37 +1100271 }
Jean-Marc Valin636f5c82008-02-12 17:40:27 +1100272
Jean-Marc Valin41af4212007-11-30 18:35:37 +1100273 }
Jean-Marc Valinb60340f2008-02-26 15:41:51 +1100274
275 if (!(nbest[0]->score > -1e10f))
276 celt_fatal("Could not find any match in VQ codebook. Something got corrupted somewhere.");
Jean-Marc Valin0d587d82008-02-14 21:29:50 +1100277 /* Only now that we've made the final choice, update ny/iny and others */
Jean-Marc Valincab576e2008-02-12 17:21:14 +1100278 for (k=0;k<Lupdate;k++)
Jean-Marc Valin41af4212007-11-30 18:35:37 +1100279 {
Jean-Marc Valin3b277dc2008-02-14 16:46:50 +1100280 int n;
281 int is;
282 float s;
283 is = nbest[k]->sign*pulsesAtOnce;
284 s = is;
285 for (n=0;n<N;n++)
Jean-Marc Valin9d8d9b32008-02-27 16:17:39 +1100286 ny[k][n] = y[nbest[k]->orig][n] - _alpha*s*p[nbest[k]->pos]*p[n];
Jean-Marc Valin3b277dc2008-02-14 16:46:50 +1100287 ny[k][nbest[k]->pos] += s;
Jean-Marc Valin0d587d82008-02-14 21:29:50 +1100288
Jean-Marc Valin3b277dc2008-02-14 16:46:50 +1100289 for (n=0;n<N;n++)
290 iny[k][n] = iy[nbest[k]->orig][n];
291 iny[k][nbest[k]->pos] += is;
Jean-Marc Valin0d587d82008-02-14 21:29:50 +1100292
Jean-Marc Valin3b277dc2008-02-14 16:46:50 +1100293 xy[k] = nbest[k]->xy;
294 yy[k] = nbest[k]->yy;
295 yp[k] = nbest[k]->yp;
296 }
Jean-Marc Valin0d587d82008-02-14 21:29:50 +1100297 /* Swap ny/iny with y/iy */
Jean-Marc Valin3b277dc2008-02-14 16:46:50 +1100298 for (k=0;k<Lupdate;k++)
299 {
Jean-Marc Valinfe419832008-02-12 15:05:01 +1100300 float *tmp_ny;
301 int *tmp_iny;
302
Jean-Marc Valinfe419832008-02-12 15:05:01 +1100303 tmp_ny = ny[k];
304 ny[k] = y[k];
305 y[k] = tmp_ny;
306 tmp_iny = iny[k];
307 iny[k] = iy[k];
308 iy[k] = tmp_iny;
Jean-Marc Valin41af4212007-11-30 18:35:37 +1100309 }
Jean-Marc Valin846d4e22008-02-12 13:48:48 +1100310 pulsesLeft -= pulsesAtOnce;
Jean-Marc Valin41af4212007-11-30 18:35:37 +1100311 }
312
Jean-Marc Valind4018c32008-02-27 10:09:48 +1100313#if 0
Jean-Marc Valinac1e03d2008-02-12 23:00:18 +1100314 if (0) {
315 float err=0;
316 for (i=0;i<N;i++)
Jean-Marc Valin3b277dc2008-02-14 16:46:50 +1100317 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 +1100318 /*if (N<=10)
319 printf ("%f %d %d\n", err, K, N);*/
Jean-Marc Valinac1e03d2008-02-12 23:00:18 +1100320 }
Jean-Marc Valin0d587d82008-02-14 21:29:50 +1100321 /* Sanity checks, don't bother */
Jean-Marc Valin1e7087e2007-12-04 13:05:43 +1100322 if (0) {
Jean-Marc Valind4018c32008-02-27 10:09:48 +1100323 for (i=0;i<N;i++)
324 x[i] = p[i]+nbest[0]->gain*y[0][i];
Jean-Marc Valin1e7087e2007-12-04 13:05:43 +1100325 float E=1e-15;
326 int ABS = 0;
327 for (i=0;i<N;i++)
328 ABS += abs(iy[0][i]);
Jean-Marc Valina85657b2008-02-20 11:59:30 +1100329 /*if (K != ABS)
330 printf ("%d %d\n", K, ABS);*/
Jean-Marc Valin1e7087e2007-12-04 13:05:43 +1100331 for (i=0;i<N;i++)
332 E += x[i]*x[i];
Jean-Marc Valina85657b2008-02-20 11:59:30 +1100333 /*printf ("%f\n", E);*/
Jean-Marc Valin1e7087e2007-12-04 13:05:43 +1100334 E = 1/sqrt(E);
335 for (i=0;i<N;i++)
336 x[i] *= E;
337 }
Jean-Marc Valind4018c32008-02-27 10:09:48 +1100338#endif
Jean-Marc Valin5fa59952008-02-14 13:50:44 +1100339
340 encode_pulses(iy[0], N, K, enc);
341
Jean-Marc Valina4833ff2008-01-10 15:34:00 +1100342 /* Recompute the gain in one pass to reduce the encoder-decoder mismatch
Jean-Marc Valin636f5c82008-02-12 17:40:27 +1100343 due to the recursive computation used in quantisation.
344 Not quite sure whether we need that or not */
Jean-Marc Valind17edd32008-02-27 16:52:30 +1100345 mix_pitch_and_residual(iy[0], X, N, K, P, alpha);
Jean-Marc Valin41af4212007-11-30 18:35:37 +1100346}
347
Jean-Marc Valin879fbfd2008-02-20 17:17:13 +1100348/** Decode pulse vector and combine the result with the pitch vector to produce
349 the final normalised signal in the current band. */
Jean-Marc Valin9d8d9b32008-02-27 16:17:39 +1100350void alg_unquant(celt_norm_t *X, int N, int K, celt_norm_t *P, celt_word16_t alpha, ec_dec *dec)
Jean-Marc Valin0d227d82007-12-31 16:12:12 +1100351{
Jean-Marc Valin9a0bba12008-02-20 14:08:50 +1100352 VARDECL(int *iy);
Jean-Marc Valin9a0bba12008-02-20 14:08:50 +1100353 ALLOC(iy, N, int);
Jean-Marc Valin5fa59952008-02-14 13:50:44 +1100354 decode_pulses(iy, N, K, dec);
Jean-Marc Valind17edd32008-02-27 16:52:30 +1100355 mix_pitch_and_residual(iy, X, N, K, P, alpha);
Jean-Marc Valin0d227d82007-12-31 16:12:12 +1100356}
357
358
359static const float pg[11] = {1.f, .75f, .65f, 0.6f, 0.6f, .6f, .55f, .55f, .5f, .5f, .5f};
360
Jean-Marc Valin5f09ea52008-02-26 16:43:04 +1100361void 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 +1100362{
363 int i,j;
364 int best=0;
Jean-Marc Valin50d11162007-12-03 14:34:52 +1100365 float best_score=0;
366 float s = 1;
Jean-Marc Valin0aa39032007-12-07 15:09:58 +1100367 int sign;
Jean-Marc Valin4841a0a2007-12-03 13:54:30 +1100368 float E;
Jean-Marc Valin9a0bba12008-02-20 14:08:50 +1100369 float pred_gain;
Jean-Marc Valin8f0f4b92008-02-11 13:52:44 +1100370 int max_pos = N0-N/B;
371 if (max_pos > 32)
372 max_pos = 32;
373
374 for (i=0;i<max_pos*B;i+=B)
Jean-Marc Valin4841a0a2007-12-03 13:54:30 +1100375 {
376 int j;
377 float xy=0, yy=0;
378 float score;
379 for (j=0;j<N;j++)
380 {
Jean-Marc Valinb4dfce42008-02-25 17:41:30 +1100381 xy += 1.f*x[j]*Y[i+N-j-1];
382 yy += 1.f*Y[i+N-j-1]*Y[i+N-j-1];
Jean-Marc Valin4841a0a2007-12-03 13:54:30 +1100383 }
Jean-Marc Valin50d11162007-12-03 14:34:52 +1100384 score = xy*xy/(.001+yy);
Jean-Marc Valin4841a0a2007-12-03 13:54:30 +1100385 if (score > best_score)
386 {
387 best_score = score;
388 best = i;
Jean-Marc Valin50d11162007-12-03 14:34:52 +1100389 if (xy>0)
390 s = 1;
391 else
392 s = -1;
Jean-Marc Valin4841a0a2007-12-03 13:54:30 +1100393 }
394 }
Jean-Marc Valin0aa39032007-12-07 15:09:58 +1100395 if (s<0)
396 sign = 1;
Jean-Marc Valin6e9058a2007-12-07 14:59:06 +1100397 else
Jean-Marc Valin0aa39032007-12-07 15:09:58 +1100398 sign = 0;
Jean-Marc Valina85657b2008-02-20 11:59:30 +1100399 /*printf ("%d %d ", sign, best);*/
Jean-Marc Valin0aa39032007-12-07 15:09:58 +1100400 ec_enc_uint(enc,sign,2);
Jean-Marc Valin8f0f4b92008-02-11 13:52:44 +1100401 ec_enc_uint(enc,best/B,max_pos);
Jean-Marc Valina85657b2008-02-20 11:59:30 +1100402 /*printf ("%d %f\n", best, best_score);*/
Jean-Marc Valin0d227d82007-12-31 16:12:12 +1100403
Jean-Marc Valin0d227d82007-12-31 16:12:12 +1100404 if (K>10)
405 pred_gain = pg[10];
406 else
407 pred_gain = pg[K];
408 E = 1e-10;
409 for (j=0;j<N;j++)
Jean-Marc Valin4841a0a2007-12-03 13:54:30 +1100410 {
Jean-Marc Valind501f612008-02-21 12:16:57 +1100411 P[j] = s*Y[best+N-j-1];
Jean-Marc Valinb4dfce42008-02-25 17:41:30 +1100412 E += NORM_SCALING_1*NORM_SCALING_1*P[j]*P[j];
Jean-Marc Valin4841a0a2007-12-03 13:54:30 +1100413 }
Jean-Marc Valin0d227d82007-12-31 16:12:12 +1100414 E = pred_gain/sqrt(E);
415 for (j=0;j<N;j++)
416 P[j] *= E;
417 if (K>0)
418 {
419 for (j=0;j<N;j++)
420 x[j] -= P[j];
421 } else {
422 for (j=0;j<N;j++)
423 x[j] = P[j];
424 }
Jean-Marc Valina85657b2008-02-20 11:59:30 +1100425 /*printf ("quant ");*/
426 /*for (j=0;j<N;j++) printf ("%f ", P[j]);*/
Jean-Marc Valin0d227d82007-12-31 16:12:12 +1100427
Jean-Marc Valin4841a0a2007-12-03 13:54:30 +1100428}
Jean-Marc Valinfc08d0a2007-12-07 13:26:15 +1100429
Jean-Marc Valin18ddc022008-02-22 14:24:50 +1100430void 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 +1100431{
Jean-Marc Valin11f01722007-12-09 01:19:36 +1100432 int j;
Jean-Marc Valin0aa39032007-12-07 15:09:58 +1100433 int sign;
434 float s;
Jean-Marc Valin6e9058a2007-12-07 14:59:06 +1100435 int best;
436 float E;
Jean-Marc Valin9a0bba12008-02-20 14:08:50 +1100437 float pred_gain;
Jean-Marc Valin8f0f4b92008-02-11 13:52:44 +1100438 int max_pos = N0-N/B;
439 if (max_pos > 32)
440 max_pos = 32;
441
Jean-Marc Valin0aa39032007-12-07 15:09:58 +1100442 sign = ec_dec_uint(dec, 2);
443 if (sign == 0)
Jean-Marc Valin6e9058a2007-12-07 14:59:06 +1100444 s = 1;
445 else
446 s = -1;
447
Jean-Marc Valin8f0f4b92008-02-11 13:52:44 +1100448 best = B*ec_dec_uint(dec, max_pos);
Jean-Marc Valina85657b2008-02-20 11:59:30 +1100449 /*printf ("%d %d ", sign, best);*/
Jean-Marc Valin6e9058a2007-12-07 14:59:06 +1100450
Jean-Marc Valin0d227d82007-12-31 16:12:12 +1100451 if (K>10)
452 pred_gain = pg[10];
453 else
454 pred_gain = pg[K];
455 E = 1e-10;
456 for (j=0;j<N;j++)
457 {
Jean-Marc Valind501f612008-02-21 12:16:57 +1100458 P[j] = s*Y[best+N-j-1];
Jean-Marc Valinb4dfce42008-02-25 17:41:30 +1100459 E += NORM_SCALING_1*NORM_SCALING_1*P[j]*P[j];
Jean-Marc Valin0d227d82007-12-31 16:12:12 +1100460 }
461 E = pred_gain/sqrt(E);
462 for (j=0;j<N;j++)
463 P[j] *= E;
Jean-Marc Valin6e9058a2007-12-07 14:59:06 +1100464 if (K==0)
465 {
Jean-Marc Valin6e9058a2007-12-07 14:59:06 +1100466 for (j=0;j<N;j++)
Jean-Marc Valin0d227d82007-12-31 16:12:12 +1100467 x[j] = P[j];
Jean-Marc Valin6e9058a2007-12-07 14:59:06 +1100468 }
469}
Jean-Marc Valin0e20ca02008-02-11 15:33:53 +1100470
Jean-Marc Valin18ddc022008-02-22 14:24:50 +1100471void 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 +1100472{
Jean-Marc Valin0df0eb42008-02-13 16:00:10 +1100473 int i, j;
Jean-Marc Valin0e20ca02008-02-11 15:33:53 +1100474 float E;
475
476 E = 1e-10;
Jean-Marc Valin0df0eb42008-02-13 16:00:10 +1100477 if (N0 >= Nmax/2)
Jean-Marc Valin0e20ca02008-02-11 15:33:53 +1100478 {
Jean-Marc Valin0df0eb42008-02-13 16:00:10 +1100479 for (i=0;i<B;i++)
480 {
481 for (j=0;j<N/B;j++)
482 {
483 P[j*B+i] = Y[(Nmax-N0-j-1)*B+i];
Jean-Marc Valinb4dfce42008-02-25 17:41:30 +1100484 E += NORM_SCALING_1*NORM_SCALING_1*P[j*B+i]*P[j*B+i];
Jean-Marc Valin0df0eb42008-02-13 16:00:10 +1100485 }
486 }
487 } else {
488 for (j=0;j<N;j++)
489 {
490 P[j] = Y[j];
Jean-Marc Valinb4dfce42008-02-25 17:41:30 +1100491 E += NORM_SCALING_1*NORM_SCALING_1*P[j]*P[j];
Jean-Marc Valin0df0eb42008-02-13 16:00:10 +1100492 }
Jean-Marc Valin0e20ca02008-02-11 15:33:53 +1100493 }
494 E = 1.f/sqrt(E);
495 for (j=0;j<N;j++)
496 P[j] *= E;
497 for (j=0;j<N;j++)
498 x[j] = P[j];
499}
500