blob: f447f6a6ab14bd0e788c0b0359da350e12ddfd85 [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 Valina847b772008-02-27 17:46:49 +110062#ifdef FIXED_POINT
63#define C0 3634
64#define C1 21173
65#define C2 -12627
66#define C3 4204
67
68static inline celt_word32_t celt_sqrt(celt_word32_t x)
69{
70 int k;
71 //printf ("%d ", x);
72 celt_word32_t rt;
73 /* ((EC_ILOG(x)-1)>>1) is just the int log4(x) (EC_ILOG returns log2 + 1) */
74 k = ((EC_ILOG(x)-1)>>1)-6;
75 x = VSHR32(x, (k<<1));
76 rt = ADD16(C0, MULT16_16_Q14(x, ADD16(C1, MULT16_16_Q14(x, ADD16(C2, MULT16_16_Q14(x, (C3)))))));
77 rt = VSHR32(rt,7-k);
78 //printf ("%d\n", rt);
79 return rt;
80}
81#else
82#define celt_sqrt sqrt
83#endif
84
Jean-Marc Valind4018c32008-02-27 10:09:48 +110085/** Takes the pitch vector and the decoded residual vector (non-compressed),
86 applies the compression in the pitch direction, computes the gain that will
87 give ||p+g*y||=1 and mixes the residual with the pitch. */
Jean-Marc Valind17edd32008-02-27 16:52:30 +110088static 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 +110089{
90 int i;
Jean-Marc Valinb50c5412008-02-27 17:05:43 +110091 celt_word32_t Ryp, Ryy, Rpp;
Jean-Marc Valina847b772008-02-27 17:46:49 +110092 celt_word32_t g;
Jean-Marc Valind17edd32008-02-27 16:52:30 +110093 VARDECL(celt_norm_t *y);
Jean-Marc Valind17edd32008-02-27 16:52:30 +110094#ifdef FIXED_POINT
Jean-Marc Valin1ca07222008-02-27 17:23:04 +110095 int yshift = 14-EC_ILOG(K);
Jean-Marc Valind17edd32008-02-27 16:52:30 +110096#endif
97 ALLOC(y, N, celt_norm_t);
Jean-Marc Valind4018c32008-02-27 10:09:48 +110098
99 /*for (i=0;i<N;i++)
100 printf ("%d ", iy[i]);*/
Jean-Marc Valinb50c5412008-02-27 17:05:43 +1100101 Rpp = 0;
Jean-Marc Valind4018c32008-02-27 10:09:48 +1100102 for (i=0;i<N;i++)
Jean-Marc Valinb50c5412008-02-27 17:05:43 +1100103 Rpp = MAC16_16(Rpp,P[i],P[i]);
Jean-Marc Valind4018c32008-02-27 10:09:48 +1100104
Jean-Marc Valinb50c5412008-02-27 17:05:43 +1100105 Ryp = 0;
Jean-Marc Valind4018c32008-02-27 10:09:48 +1100106 for (i=0;i<N;i++)
Jean-Marc Valinb50c5412008-02-27 17:05:43 +1100107 Ryp = MAC16_16(Ryp,SHL16(iy[i],yshift),P[i]);
Jean-Marc Valind4018c32008-02-27 10:09:48 +1100108
Jean-Marc Valind17edd32008-02-27 16:52:30 +1100109 /* Remove part of the pitch component to compute the real residual from
110 the encoded (int) one */
Jean-Marc Valind4018c32008-02-27 10:09:48 +1100111 for (i=0;i<N;i++)
Jean-Marc Valind17edd32008-02-27 16:52:30 +1100112 y[i] = SUB16(SHL16(iy[i],yshift),
Jean-Marc Valinb50c5412008-02-27 17:05:43 +1100113 MULT16_16_Q15(alpha,MULT16_16_Q14(EXTRACT16(SHR32(Ryp,14)),P[i])));
Jean-Marc Valind4018c32008-02-27 10:09:48 +1100114
115 /* Recompute after the projection (I think it's right) */
116 Ryp = 0;
117 for (i=0;i<N;i++)
Jean-Marc Valinb50c5412008-02-27 17:05:43 +1100118 Ryp = MAC16_16(Ryp,y[i],P[i]);
Jean-Marc Valind4018c32008-02-27 10:09:48 +1100119
Jean-Marc Valinb50c5412008-02-27 17:05:43 +1100120 Ryy = 0;
Jean-Marc Valind4018c32008-02-27 10:09:48 +1100121 for (i=0;i<N;i++)
Jean-Marc Valinb50c5412008-02-27 17:05:43 +1100122 Ryy = MAC16_16(Ryy, y[i],y[i]);
Jean-Marc Valind4018c32008-02-27 10:09:48 +1100123
Jean-Marc Valin1ca07222008-02-27 17:23:04 +1100124 /* g = (sqrt(Ryp^2 + Ryy - Rpp*Ryy)-Ryp)/Ryy */
Jean-Marc Valina847b772008-02-27 17:46:49 +1100125 g = DIV32(SHL32(celt_sqrt(MULT16_16(PSHR32(Ryp,14),PSHR32(Ryp,14)) + Ryy - MULT16_16(PSHR32(Ryy,14),PSHR32(Rpp,14))) - PSHR32(Ryp,14),14),PSHR32(Ryy,14));
Jean-Marc Valind4018c32008-02-27 10:09:48 +1100126
127 for (i=0;i<N;i++)
Jean-Marc Valina847b772008-02-27 17:46:49 +1100128 X[i] = P[i] + MULT16_32_Q14(y[i], g);
Jean-Marc Valind4018c32008-02-27 10:09:48 +1100129}
130
Jean-Marc Valin879fbfd2008-02-20 17:17:13 +1100131/** All the info necessary to keep track of a hypothesis during the search */
Jean-Marc Valin3b277dc2008-02-14 16:46:50 +1100132struct NBest {
133 float score;
134 float gain;
135 int sign;
136 int pos;
137 int orig;
138 float xy;
139 float yy;
140 float yp;
141};
Jean-Marc Valin41af4212007-11-30 18:35:37 +1100142
Jean-Marc Valin9d8d9b32008-02-27 16:17:39 +1100143void 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 +1100144{
Jean-Marc Valin4a897682007-12-12 00:45:15 +1100145 int L = 3;
Jean-Marc Valin2fa8aff2008-02-26 11:38:00 +1100146 VARDECL(float *x);
147 VARDECL(float *p);
Jean-Marc Valin9a0bba12008-02-20 14:08:50 +1100148 VARDECL(float *_y);
149 VARDECL(float *_ny);
150 VARDECL(int *_iy);
151 VARDECL(int *_iny);
152 VARDECL(float **y);
153 VARDECL(float **ny);
154 VARDECL(int **iy);
155 VARDECL(int **iny);
Jean-Marc Valin0d587d82008-02-14 21:29:50 +1100156 int i, j, k, m;
Jean-Marc Valin846d4e22008-02-12 13:48:48 +1100157 int pulsesLeft;
Jean-Marc Valin9a0bba12008-02-20 14:08:50 +1100158 VARDECL(float *xy);
159 VARDECL(float *yy);
160 VARDECL(float *yp);
161 VARDECL(struct NBest *_nbest);
162 VARDECL(struct NBest **nbest);
Jean-Marc Valin1e7087e2007-12-04 13:05:43 +1100163 float Rpp=0, Rxp=0;
Jean-Marc Valin41af4212007-11-30 18:35:37 +1100164 int maxL = 1;
Jean-Marc Valin9d8d9b32008-02-27 16:17:39 +1100165 float _alpha = Q15_ONE_1*alpha;
166
Jean-Marc Valin2fa8aff2008-02-26 11:38:00 +1100167 ALLOC(x, N, float);
168 ALLOC(p, N, float);
Jean-Marc Valin9a0bba12008-02-20 14:08:50 +1100169 ALLOC(_y, L*N, float);
170 ALLOC(_ny, L*N, float);
171 ALLOC(_iy, L*N, int);
172 ALLOC(_iny, L*N, int);
173 ALLOC(y, L*N, float*);
174 ALLOC(ny, L*N, float*);
175 ALLOC(iy, L*N, int*);
176 ALLOC(iny, L*N, int*);
177
178 ALLOC(xy, L, float);
179 ALLOC(yy, L, float);
180 ALLOC(yp, L, float);
181 ALLOC(_nbest, L, struct NBest);
182 ALLOC(nbest, L, struct NBest *);
183
Jean-Marc Valinb4dfce42008-02-25 17:41:30 +1100184 for (j=0;j<N;j++)
185 {
Jean-Marc Valin2fa8aff2008-02-26 11:38:00 +1100186 x[j] = X[j]*NORM_SCALING_1;
187 p[j] = P[j]*NORM_SCALING_1;
Jean-Marc Valinb4dfce42008-02-25 17:41:30 +1100188 }
189
Jean-Marc Valinfe419832008-02-12 15:05:01 +1100190 for (m=0;m<L;m++)
Jean-Marc Valin3b277dc2008-02-14 16:46:50 +1100191 nbest[m] = &_nbest[m];
192
193 for (m=0;m<L;m++)
Jean-Marc Valinfe419832008-02-12 15:05:01 +1100194 {
Jean-Marc Valin9a0bba12008-02-20 14:08:50 +1100195 ny[m] = &_ny[m*N];
196 iny[m] = &_iny[m*N];
197 y[m] = &_y[m*N];
198 iy[m] = &_iy[m*N];
Jean-Marc Valinfe419832008-02-12 15:05:01 +1100199 }
200
Jean-Marc Valin41af4212007-11-30 18:35:37 +1100201 for (j=0;j<N;j++)
Jean-Marc Valin0d587d82008-02-14 21:29:50 +1100202 {
Jean-Marc Valin41af4212007-11-30 18:35:37 +1100203 Rpp += p[j]*p[j];
Jean-Marc Valin1e7087e2007-12-04 13:05:43 +1100204 Rxp += x[j]*p[j];
Jean-Marc Valin0d587d82008-02-14 21:29:50 +1100205 }
Jean-Marc Valinb60340f2008-02-26 15:41:51 +1100206 if (Rpp>1)
207 celt_fatal("Rpp > 1");
208
Jean-Marc Valin0d587d82008-02-14 21:29:50 +1100209 /* We only need to initialise the zero because the first iteration only uses that */
210 for (i=0;i<N;i++)
211 y[0][i] = 0;
212 for (i=0;i<N;i++)
213 iy[0][i] = 0;
214 xy[0] = yy[0] = yp[0] = 0;
215
Jean-Marc Valin846d4e22008-02-12 13:48:48 +1100216 pulsesLeft = K;
217 while (pulsesLeft > 0)
Jean-Marc Valin41af4212007-11-30 18:35:37 +1100218 {
Jean-Marc Valin846d4e22008-02-12 13:48:48 +1100219 int pulsesAtOnce=1;
Jean-Marc Valincab576e2008-02-12 17:21:14 +1100220 int Lupdate = L;
Jean-Marc Valin41af4212007-11-30 18:35:37 +1100221 int L2 = L;
Jean-Marc Valin0d587d82008-02-14 21:29:50 +1100222
223 /* Decide on complexity strategy */
Jean-Marc Valincab576e2008-02-12 17:21:14 +1100224 pulsesAtOnce = pulsesLeft/N;
225 if (pulsesAtOnce<1)
226 pulsesAtOnce = 1;
227 if (pulsesLeft-pulsesAtOnce > 3 || N > 30)
228 Lupdate = 1;
Jean-Marc Valina85657b2008-02-20 11:59:30 +1100229 /*printf ("%d %d %d/%d %d\n", Lupdate, pulsesAtOnce, pulsesLeft, K, N);*/
Jean-Marc Valincab576e2008-02-12 17:21:14 +1100230 L2 = Lupdate;
231 if (L2>maxL)
Jean-Marc Valin41af4212007-11-30 18:35:37 +1100232 {
233 L2 = maxL;
234 maxL *= N;
235 }
Jean-Marc Valin846d4e22008-02-12 13:48:48 +1100236
Jean-Marc Valin0d587d82008-02-14 21:29:50 +1100237 for (m=0;m<Lupdate;m++)
Jean-Marc Valin883bd8e2008-02-15 00:34:01 +1100238 nbest[m]->score = -1e10f;
Jean-Marc Valin41af4212007-11-30 18:35:37 +1100239
240 for (m=0;m<L2;m++)
241 {
242 for (j=0;j<N;j++)
243 {
Jean-Marc Valin1e7087e2007-12-04 13:05:43 +1100244 int sign;
Jean-Marc Valin0d587d82008-02-14 21:29:50 +1100245 /*if (x[j]>0) sign=1; else sign=-1;*/
Jean-Marc Valin1e7087e2007-12-04 13:05:43 +1100246 for (sign=-1;sign<=1;sign+=2)
Jean-Marc Valin41af4212007-11-30 18:35:37 +1100247 {
Jean-Marc Valina85657b2008-02-20 11:59:30 +1100248 /*fprintf (stderr, "%d/%d %d/%d %d/%d\n", i, K, m, L2, j, N);*/
Jean-Marc Valin1e7087e2007-12-04 13:05:43 +1100249 float tmp_xy, tmp_yy, tmp_yp;
250 float score;
251 float g;
Jean-Marc Valin846d4e22008-02-12 13:48:48 +1100252 float s = sign*pulsesAtOnce;
Jean-Marc Valinfe419832008-02-12 15:05:01 +1100253
Jean-Marc Valin9a0bba12008-02-20 14:08:50 +1100254 /* All pulses at one location must have the same sign. */
255 if (iy[m][j]*sign < 0)
256 continue;
257
Jean-Marc Valina073c7b2008-02-14 16:58:04 +1100258 /* Updating the sums of the new pulse(s) */
Jean-Marc Valin9d8d9b32008-02-27 16:17:39 +1100259 tmp_xy = xy[m] + s*x[j] - _alpha*s*p[j]*Rxp;
260 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];
261 tmp_yp = yp[m] + s*p[j] *(1.f-_alpha*Rpp);
Jean-Marc Valina073c7b2008-02-14 16:58:04 +1100262
263 /* Compute the gain such that ||p + g*y|| = 1 */
Jean-Marc Valin883bd8e2008-02-15 00:34:01 +1100264 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 +1100265 /* Knowing that gain, what the error: (x-g*y)^2
266 (result is negated and we discard x^2 because it's constant) */
Jean-Marc Valin883bd8e2008-02-15 00:34:01 +1100267 score = 2.f*g*tmp_xy - g*g*tmp_yy;
Jean-Marc Valin41af4212007-11-30 18:35:37 +1100268
Jean-Marc Valin3b277dc2008-02-14 16:46:50 +1100269 if (score>nbest[Lupdate-1]->score)
Jean-Marc Valin1e7087e2007-12-04 13:05:43 +1100270 {
Jean-Marc Valin472a5f02008-02-19 13:12:32 +1100271 int k;
Jean-Marc Valincab576e2008-02-12 17:21:14 +1100272 int id = Lupdate-1;
Jean-Marc Valin3b277dc2008-02-14 16:46:50 +1100273 struct NBest *tmp_best;
274
275 /* Save some pointers that would be deleted and use them for the current entry*/
276 tmp_best = nbest[Lupdate-1];
277 while (id > 0 && score > nbest[id-1]->score)
Jean-Marc Valin1e7087e2007-12-04 13:05:43 +1100278 id--;
279
Jean-Marc Valincab576e2008-02-12 17:21:14 +1100280 for (k=Lupdate-1;k>id;k--)
Jean-Marc Valin3b277dc2008-02-14 16:46:50 +1100281 nbest[k] = nbest[k-1];
Jean-Marc Valin1e7087e2007-12-04 13:05:43 +1100282
Jean-Marc Valin3b277dc2008-02-14 16:46:50 +1100283 nbest[id] = tmp_best;
284 nbest[id]->score = score;
285 nbest[id]->pos = j;
286 nbest[id]->orig = m;
287 nbest[id]->sign = sign;
288 nbest[id]->gain = g;
289 nbest[id]->xy = tmp_xy;
290 nbest[id]->yy = tmp_yy;
291 nbest[id]->yp = tmp_yp;
Jean-Marc Valin1e7087e2007-12-04 13:05:43 +1100292 }
Jean-Marc Valin636f5c82008-02-12 17:40:27 +1100293 }
Jean-Marc Valin41af4212007-11-30 18:35:37 +1100294 }
Jean-Marc Valin636f5c82008-02-12 17:40:27 +1100295
Jean-Marc Valin41af4212007-11-30 18:35:37 +1100296 }
Jean-Marc Valinb60340f2008-02-26 15:41:51 +1100297
298 if (!(nbest[0]->score > -1e10f))
299 celt_fatal("Could not find any match in VQ codebook. Something got corrupted somewhere.");
Jean-Marc Valin0d587d82008-02-14 21:29:50 +1100300 /* Only now that we've made the final choice, update ny/iny and others */
Jean-Marc Valincab576e2008-02-12 17:21:14 +1100301 for (k=0;k<Lupdate;k++)
Jean-Marc Valin41af4212007-11-30 18:35:37 +1100302 {
Jean-Marc Valin3b277dc2008-02-14 16:46:50 +1100303 int n;
304 int is;
305 float s;
306 is = nbest[k]->sign*pulsesAtOnce;
307 s = is;
308 for (n=0;n<N;n++)
Jean-Marc Valin9d8d9b32008-02-27 16:17:39 +1100309 ny[k][n] = y[nbest[k]->orig][n] - _alpha*s*p[nbest[k]->pos]*p[n];
Jean-Marc Valin3b277dc2008-02-14 16:46:50 +1100310 ny[k][nbest[k]->pos] += s;
Jean-Marc Valin0d587d82008-02-14 21:29:50 +1100311
Jean-Marc Valin3b277dc2008-02-14 16:46:50 +1100312 for (n=0;n<N;n++)
313 iny[k][n] = iy[nbest[k]->orig][n];
314 iny[k][nbest[k]->pos] += is;
Jean-Marc Valin0d587d82008-02-14 21:29:50 +1100315
Jean-Marc Valin3b277dc2008-02-14 16:46:50 +1100316 xy[k] = nbest[k]->xy;
317 yy[k] = nbest[k]->yy;
318 yp[k] = nbest[k]->yp;
319 }
Jean-Marc Valin0d587d82008-02-14 21:29:50 +1100320 /* Swap ny/iny with y/iy */
Jean-Marc Valin3b277dc2008-02-14 16:46:50 +1100321 for (k=0;k<Lupdate;k++)
322 {
Jean-Marc Valinfe419832008-02-12 15:05:01 +1100323 float *tmp_ny;
324 int *tmp_iny;
325
Jean-Marc Valinfe419832008-02-12 15:05:01 +1100326 tmp_ny = ny[k];
327 ny[k] = y[k];
328 y[k] = tmp_ny;
329 tmp_iny = iny[k];
330 iny[k] = iy[k];
331 iy[k] = tmp_iny;
Jean-Marc Valin41af4212007-11-30 18:35:37 +1100332 }
Jean-Marc Valin846d4e22008-02-12 13:48:48 +1100333 pulsesLeft -= pulsesAtOnce;
Jean-Marc Valin41af4212007-11-30 18:35:37 +1100334 }
335
Jean-Marc Valind4018c32008-02-27 10:09:48 +1100336#if 0
Jean-Marc Valinac1e03d2008-02-12 23:00:18 +1100337 if (0) {
338 float err=0;
339 for (i=0;i<N;i++)
Jean-Marc Valin3b277dc2008-02-14 16:46:50 +1100340 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 +1100341 /*if (N<=10)
342 printf ("%f %d %d\n", err, K, N);*/
Jean-Marc Valinac1e03d2008-02-12 23:00:18 +1100343 }
Jean-Marc Valin0d587d82008-02-14 21:29:50 +1100344 /* Sanity checks, don't bother */
Jean-Marc Valin1e7087e2007-12-04 13:05:43 +1100345 if (0) {
Jean-Marc Valind4018c32008-02-27 10:09:48 +1100346 for (i=0;i<N;i++)
347 x[i] = p[i]+nbest[0]->gain*y[0][i];
Jean-Marc Valin1e7087e2007-12-04 13:05:43 +1100348 float E=1e-15;
349 int ABS = 0;
350 for (i=0;i<N;i++)
351 ABS += abs(iy[0][i]);
Jean-Marc Valina85657b2008-02-20 11:59:30 +1100352 /*if (K != ABS)
353 printf ("%d %d\n", K, ABS);*/
Jean-Marc Valin1e7087e2007-12-04 13:05:43 +1100354 for (i=0;i<N;i++)
355 E += x[i]*x[i];
Jean-Marc Valina85657b2008-02-20 11:59:30 +1100356 /*printf ("%f\n", E);*/
Jean-Marc Valin1e7087e2007-12-04 13:05:43 +1100357 E = 1/sqrt(E);
358 for (i=0;i<N;i++)
359 x[i] *= E;
360 }
Jean-Marc Valind4018c32008-02-27 10:09:48 +1100361#endif
Jean-Marc Valin5fa59952008-02-14 13:50:44 +1100362
363 encode_pulses(iy[0], N, K, enc);
364
Jean-Marc Valina4833ff2008-01-10 15:34:00 +1100365 /* Recompute the gain in one pass to reduce the encoder-decoder mismatch
Jean-Marc Valin636f5c82008-02-12 17:40:27 +1100366 due to the recursive computation used in quantisation.
367 Not quite sure whether we need that or not */
Jean-Marc Valind17edd32008-02-27 16:52:30 +1100368 mix_pitch_and_residual(iy[0], X, N, K, P, alpha);
Jean-Marc Valin41af4212007-11-30 18:35:37 +1100369}
370
Jean-Marc Valin879fbfd2008-02-20 17:17:13 +1100371/** Decode pulse vector and combine the result with the pitch vector to produce
372 the final normalised signal in the current band. */
Jean-Marc Valin9d8d9b32008-02-27 16:17:39 +1100373void 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 +1100374{
Jean-Marc Valin9a0bba12008-02-20 14:08:50 +1100375 VARDECL(int *iy);
Jean-Marc Valin9a0bba12008-02-20 14:08:50 +1100376 ALLOC(iy, N, int);
Jean-Marc Valin5fa59952008-02-14 13:50:44 +1100377 decode_pulses(iy, N, K, dec);
Jean-Marc Valind17edd32008-02-27 16:52:30 +1100378 mix_pitch_and_residual(iy, X, N, K, P, alpha);
Jean-Marc Valin0d227d82007-12-31 16:12:12 +1100379}
380
381
382static const float pg[11] = {1.f, .75f, .65f, 0.6f, 0.6f, .6f, .55f, .55f, .5f, .5f, .5f};
383
Jean-Marc Valin5f09ea52008-02-26 16:43:04 +1100384void 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 +1100385{
386 int i,j;
387 int best=0;
Jean-Marc Valin50d11162007-12-03 14:34:52 +1100388 float best_score=0;
389 float s = 1;
Jean-Marc Valin0aa39032007-12-07 15:09:58 +1100390 int sign;
Jean-Marc Valin4841a0a2007-12-03 13:54:30 +1100391 float E;
Jean-Marc Valin9a0bba12008-02-20 14:08:50 +1100392 float pred_gain;
Jean-Marc Valin8f0f4b92008-02-11 13:52:44 +1100393 int max_pos = N0-N/B;
394 if (max_pos > 32)
395 max_pos = 32;
396
397 for (i=0;i<max_pos*B;i+=B)
Jean-Marc Valin4841a0a2007-12-03 13:54:30 +1100398 {
399 int j;
400 float xy=0, yy=0;
401 float score;
402 for (j=0;j<N;j++)
403 {
Jean-Marc Valinb4dfce42008-02-25 17:41:30 +1100404 xy += 1.f*x[j]*Y[i+N-j-1];
405 yy += 1.f*Y[i+N-j-1]*Y[i+N-j-1];
Jean-Marc Valin4841a0a2007-12-03 13:54:30 +1100406 }
Jean-Marc Valin50d11162007-12-03 14:34:52 +1100407 score = xy*xy/(.001+yy);
Jean-Marc Valin4841a0a2007-12-03 13:54:30 +1100408 if (score > best_score)
409 {
410 best_score = score;
411 best = i;
Jean-Marc Valin50d11162007-12-03 14:34:52 +1100412 if (xy>0)
413 s = 1;
414 else
415 s = -1;
Jean-Marc Valin4841a0a2007-12-03 13:54:30 +1100416 }
417 }
Jean-Marc Valin0aa39032007-12-07 15:09:58 +1100418 if (s<0)
419 sign = 1;
Jean-Marc Valin6e9058a2007-12-07 14:59:06 +1100420 else
Jean-Marc Valin0aa39032007-12-07 15:09:58 +1100421 sign = 0;
Jean-Marc Valina85657b2008-02-20 11:59:30 +1100422 /*printf ("%d %d ", sign, best);*/
Jean-Marc Valin0aa39032007-12-07 15:09:58 +1100423 ec_enc_uint(enc,sign,2);
Jean-Marc Valin8f0f4b92008-02-11 13:52:44 +1100424 ec_enc_uint(enc,best/B,max_pos);
Jean-Marc Valina85657b2008-02-20 11:59:30 +1100425 /*printf ("%d %f\n", best, best_score);*/
Jean-Marc Valin0d227d82007-12-31 16:12:12 +1100426
Jean-Marc Valin0d227d82007-12-31 16:12:12 +1100427 if (K>10)
428 pred_gain = pg[10];
429 else
430 pred_gain = pg[K];
431 E = 1e-10;
432 for (j=0;j<N;j++)
Jean-Marc Valin4841a0a2007-12-03 13:54:30 +1100433 {
Jean-Marc Valind501f612008-02-21 12:16:57 +1100434 P[j] = s*Y[best+N-j-1];
Jean-Marc Valinb4dfce42008-02-25 17:41:30 +1100435 E += NORM_SCALING_1*NORM_SCALING_1*P[j]*P[j];
Jean-Marc Valin4841a0a2007-12-03 13:54:30 +1100436 }
Jean-Marc Valin0d227d82007-12-31 16:12:12 +1100437 E = pred_gain/sqrt(E);
438 for (j=0;j<N;j++)
439 P[j] *= E;
440 if (K>0)
441 {
442 for (j=0;j<N;j++)
443 x[j] -= P[j];
444 } else {
445 for (j=0;j<N;j++)
446 x[j] = P[j];
447 }
Jean-Marc Valina85657b2008-02-20 11:59:30 +1100448 /*printf ("quant ");*/
449 /*for (j=0;j<N;j++) printf ("%f ", P[j]);*/
Jean-Marc Valin0d227d82007-12-31 16:12:12 +1100450
Jean-Marc Valin4841a0a2007-12-03 13:54:30 +1100451}
Jean-Marc Valinfc08d0a2007-12-07 13:26:15 +1100452
Jean-Marc Valin18ddc022008-02-22 14:24:50 +1100453void 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 +1100454{
Jean-Marc Valin11f01722007-12-09 01:19:36 +1100455 int j;
Jean-Marc Valin0aa39032007-12-07 15:09:58 +1100456 int sign;
457 float s;
Jean-Marc Valin6e9058a2007-12-07 14:59:06 +1100458 int best;
459 float E;
Jean-Marc Valin9a0bba12008-02-20 14:08:50 +1100460 float pred_gain;
Jean-Marc Valin8f0f4b92008-02-11 13:52:44 +1100461 int max_pos = N0-N/B;
462 if (max_pos > 32)
463 max_pos = 32;
464
Jean-Marc Valin0aa39032007-12-07 15:09:58 +1100465 sign = ec_dec_uint(dec, 2);
466 if (sign == 0)
Jean-Marc Valin6e9058a2007-12-07 14:59:06 +1100467 s = 1;
468 else
469 s = -1;
470
Jean-Marc Valin8f0f4b92008-02-11 13:52:44 +1100471 best = B*ec_dec_uint(dec, max_pos);
Jean-Marc Valina85657b2008-02-20 11:59:30 +1100472 /*printf ("%d %d ", sign, best);*/
Jean-Marc Valin6e9058a2007-12-07 14:59:06 +1100473
Jean-Marc Valin0d227d82007-12-31 16:12:12 +1100474 if (K>10)
475 pred_gain = pg[10];
476 else
477 pred_gain = pg[K];
478 E = 1e-10;
479 for (j=0;j<N;j++)
480 {
Jean-Marc Valind501f612008-02-21 12:16:57 +1100481 P[j] = s*Y[best+N-j-1];
Jean-Marc Valinb4dfce42008-02-25 17:41:30 +1100482 E += NORM_SCALING_1*NORM_SCALING_1*P[j]*P[j];
Jean-Marc Valin0d227d82007-12-31 16:12:12 +1100483 }
484 E = pred_gain/sqrt(E);
485 for (j=0;j<N;j++)
486 P[j] *= E;
Jean-Marc Valin6e9058a2007-12-07 14:59:06 +1100487 if (K==0)
488 {
Jean-Marc Valin6e9058a2007-12-07 14:59:06 +1100489 for (j=0;j<N;j++)
Jean-Marc Valin0d227d82007-12-31 16:12:12 +1100490 x[j] = P[j];
Jean-Marc Valin6e9058a2007-12-07 14:59:06 +1100491 }
492}
Jean-Marc Valin0e20ca02008-02-11 15:33:53 +1100493
Jean-Marc Valin18ddc022008-02-22 14:24:50 +1100494void 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 +1100495{
Jean-Marc Valin0df0eb42008-02-13 16:00:10 +1100496 int i, j;
Jean-Marc Valin0e20ca02008-02-11 15:33:53 +1100497 float E;
498
499 E = 1e-10;
Jean-Marc Valin0df0eb42008-02-13 16:00:10 +1100500 if (N0 >= Nmax/2)
Jean-Marc Valin0e20ca02008-02-11 15:33:53 +1100501 {
Jean-Marc Valin0df0eb42008-02-13 16:00:10 +1100502 for (i=0;i<B;i++)
503 {
504 for (j=0;j<N/B;j++)
505 {
506 P[j*B+i] = Y[(Nmax-N0-j-1)*B+i];
Jean-Marc Valinb4dfce42008-02-25 17:41:30 +1100507 E += NORM_SCALING_1*NORM_SCALING_1*P[j*B+i]*P[j*B+i];
Jean-Marc Valin0df0eb42008-02-13 16:00:10 +1100508 }
509 }
510 } else {
511 for (j=0;j<N;j++)
512 {
513 P[j] = Y[j];
Jean-Marc Valinb4dfce42008-02-25 17:41:30 +1100514 E += NORM_SCALING_1*NORM_SCALING_1*P[j]*P[j];
Jean-Marc Valin0df0eb42008-02-13 16:00:10 +1100515 }
Jean-Marc Valin0e20ca02008-02-11 15:33:53 +1100516 }
517 E = 1.f/sqrt(E);
518 for (j=0;j<N;j++)
519 P[j] *= E;
520 for (j=0;j<N;j++)
521 x[j] = P[j];
522}
523