blob: 4d229b70dd4e634c627914e0b20bb128bd928cef [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 Valin3ca9b1d2008-02-27 23:50:31 +110038#include "mathops.h"
Jean-Marc Valin29ccab82007-12-06 15:39:38 +110039#include "cwrs.h"
Jean-Marc Valin9cace642007-12-06 17:44:09 +110040#include "vq.h"
Jean-Marc Valin9a0bba12008-02-20 14:08:50 +110041#include "arch.h"
Jean-Marc Valinb60340f2008-02-26 15:41:51 +110042#include "os_support.h"
Jean-Marc Valin41af4212007-11-30 18:35:37 +110043
Jean-Marc Valin883bd8e2008-02-15 00:34:01 +110044/* Enable this or define your own implementation if you want to speed up the
45 VQ search (used in inner loop only) */
46#if 0
47#include <xmmintrin.h>
48static inline float approx_sqrt(float x)
49{
50 _mm_store_ss(&x, _mm_sqrt_ss(_mm_set_ss(x)));
51 return x;
52}
53static inline float approx_inv(float x)
54{
55 _mm_store_ss(&x, _mm_rcp_ss(_mm_set_ss(x)));
56 return x;
57}
58#else
59#define approx_sqrt(x) (sqrt(x))
60#define approx_inv(x) (1.f/(x))
61#endif
62
Jean-Marc Valind4018c32008-02-27 10:09:48 +110063/** Takes the pitch vector and the decoded residual vector (non-compressed),
64 applies the compression in the pitch direction, computes the gain that will
65 give ||p+g*y||=1 and mixes the residual with the pitch. */
Jean-Marc Valind17edd32008-02-27 16:52:30 +110066static 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 +110067{
68 int i;
Jean-Marc Valinb50c5412008-02-27 17:05:43 +110069 celt_word32_t Ryp, Ryy, Rpp;
Jean-Marc Valina847b772008-02-27 17:46:49 +110070 celt_word32_t g;
Jean-Marc Valind17edd32008-02-27 16:52:30 +110071 VARDECL(celt_norm_t *y);
Jean-Marc Valind17edd32008-02-27 16:52:30 +110072#ifdef FIXED_POINT
Jean-Marc Valin1ca07222008-02-27 17:23:04 +110073 int yshift = 14-EC_ILOG(K);
Jean-Marc Valind17edd32008-02-27 16:52:30 +110074#endif
75 ALLOC(y, N, celt_norm_t);
Jean-Marc Valind4018c32008-02-27 10:09:48 +110076
77 /*for (i=0;i<N;i++)
78 printf ("%d ", iy[i]);*/
Jean-Marc Valinb50c5412008-02-27 17:05:43 +110079 Rpp = 0;
Jean-Marc Valind4018c32008-02-27 10:09:48 +110080 for (i=0;i<N;i++)
Jean-Marc Valinb50c5412008-02-27 17:05:43 +110081 Rpp = MAC16_16(Rpp,P[i],P[i]);
Jean-Marc Valind4018c32008-02-27 10:09:48 +110082
Jean-Marc Valinb50c5412008-02-27 17:05:43 +110083 Ryp = 0;
Jean-Marc Valind4018c32008-02-27 10:09:48 +110084 for (i=0;i<N;i++)
Jean-Marc Valinb50c5412008-02-27 17:05:43 +110085 Ryp = MAC16_16(Ryp,SHL16(iy[i],yshift),P[i]);
Jean-Marc Valind4018c32008-02-27 10:09:48 +110086
Jean-Marc Valind17edd32008-02-27 16:52:30 +110087 /* Remove part of the pitch component to compute the real residual from
88 the encoded (int) one */
Jean-Marc Valind4018c32008-02-27 10:09:48 +110089 for (i=0;i<N;i++)
Jean-Marc Valind17edd32008-02-27 16:52:30 +110090 y[i] = SUB16(SHL16(iy[i],yshift),
Jean-Marc Valina02ca1e2008-02-28 11:33:22 +110091 MULT16_16_Q15(alpha,MULT16_16_Q14(ROUND(Ryp,14),P[i])));
Jean-Marc Valind4018c32008-02-27 10:09:48 +110092
93 /* Recompute after the projection (I think it's right) */
94 Ryp = 0;
95 for (i=0;i<N;i++)
Jean-Marc Valinb50c5412008-02-27 17:05:43 +110096 Ryp = MAC16_16(Ryp,y[i],P[i]);
Jean-Marc Valind4018c32008-02-27 10:09:48 +110097
Jean-Marc Valinb50c5412008-02-27 17:05:43 +110098 Ryy = 0;
Jean-Marc Valind4018c32008-02-27 10:09:48 +110099 for (i=0;i<N;i++)
Jean-Marc Valinb50c5412008-02-27 17:05:43 +1100100 Ryy = MAC16_16(Ryy, y[i],y[i]);
Jean-Marc Valind4018c32008-02-27 10:09:48 +1100101
Jean-Marc Valin1ca07222008-02-27 17:23:04 +1100102 /* g = (sqrt(Ryp^2 + Ryy - Rpp*Ryy)-Ryp)/Ryy */
Jean-Marc Valina02ca1e2008-02-28 11:33:22 +1100103 g = DIV32(SHL32(celt_sqrt(MULT16_16(ROUND(Ryp,14),ROUND(Ryp,14)) + Ryy - MULT16_16(ROUND(Ryy,14),ROUND(Rpp,14))) - ROUND(Ryp,14),14),ROUND(Ryy,14));
Jean-Marc Valind4018c32008-02-27 10:09:48 +1100104
105 for (i=0;i<N;i++)
Jean-Marc Valina847b772008-02-27 17:46:49 +1100106 X[i] = P[i] + MULT16_32_Q14(y[i], g);
Jean-Marc Valind4018c32008-02-27 10:09:48 +1100107}
108
Jean-Marc Valin879fbfd2008-02-20 17:17:13 +1100109/** All the info necessary to keep track of a hypothesis during the search */
Jean-Marc Valin3b277dc2008-02-14 16:46:50 +1100110struct NBest {
111 float score;
112 float gain;
113 int sign;
114 int pos;
115 int orig;
116 float xy;
117 float yy;
118 float yp;
119};
Jean-Marc Valin41af4212007-11-30 18:35:37 +1100120
Jean-Marc Valin9d8d9b32008-02-27 16:17:39 +1100121void 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 +1100122{
Jean-Marc Valin4a897682007-12-12 00:45:15 +1100123 int L = 3;
Jean-Marc Valin2fa8aff2008-02-26 11:38:00 +1100124 VARDECL(float *x);
125 VARDECL(float *p);
Jean-Marc Valin9a0bba12008-02-20 14:08:50 +1100126 VARDECL(float *_y);
127 VARDECL(float *_ny);
128 VARDECL(int *_iy);
129 VARDECL(int *_iny);
130 VARDECL(float **y);
131 VARDECL(float **ny);
132 VARDECL(int **iy);
133 VARDECL(int **iny);
Jean-Marc Valin0d587d82008-02-14 21:29:50 +1100134 int i, j, k, m;
Jean-Marc Valin846d4e22008-02-12 13:48:48 +1100135 int pulsesLeft;
Jean-Marc Valin9a0bba12008-02-20 14:08:50 +1100136 VARDECL(float *xy);
137 VARDECL(float *yy);
138 VARDECL(float *yp);
139 VARDECL(struct NBest *_nbest);
140 VARDECL(struct NBest **nbest);
Jean-Marc Valinf675adc2008-02-28 12:15:17 +1100141 celt_word32_t Rpp=0, Rxp=0;
Jean-Marc Valin41af4212007-11-30 18:35:37 +1100142 int maxL = 1;
Jean-Marc Valin9d8d9b32008-02-27 16:17:39 +1100143 float _alpha = Q15_ONE_1*alpha;
Jean-Marc Valinf675adc2008-02-28 12:15:17 +1100144#ifdef FIXED_POINT
145 int yshift = 14-EC_ILOG(K);
146#endif
Jean-Marc Valin9d8d9b32008-02-27 16:17:39 +1100147
Jean-Marc Valin2fa8aff2008-02-26 11:38:00 +1100148 ALLOC(x, N, float);
149 ALLOC(p, N, float);
Jean-Marc Valin9a0bba12008-02-20 14:08:50 +1100150 ALLOC(_y, L*N, float);
151 ALLOC(_ny, L*N, float);
152 ALLOC(_iy, L*N, int);
153 ALLOC(_iny, L*N, int);
154 ALLOC(y, L*N, float*);
155 ALLOC(ny, L*N, float*);
156 ALLOC(iy, L*N, int*);
157 ALLOC(iny, L*N, int*);
158
159 ALLOC(xy, L, float);
160 ALLOC(yy, L, float);
161 ALLOC(yp, L, float);
162 ALLOC(_nbest, L, struct NBest);
163 ALLOC(nbest, L, struct NBest *);
164
Jean-Marc Valinb4dfce42008-02-25 17:41:30 +1100165 for (j=0;j<N;j++)
166 {
Jean-Marc Valin2fa8aff2008-02-26 11:38:00 +1100167 x[j] = X[j]*NORM_SCALING_1;
168 p[j] = P[j]*NORM_SCALING_1;
Jean-Marc Valinb4dfce42008-02-25 17:41:30 +1100169 }
170
Jean-Marc Valinfe419832008-02-12 15:05:01 +1100171 for (m=0;m<L;m++)
Jean-Marc Valin3b277dc2008-02-14 16:46:50 +1100172 nbest[m] = &_nbest[m];
173
174 for (m=0;m<L;m++)
Jean-Marc Valinfe419832008-02-12 15:05:01 +1100175 {
Jean-Marc Valin9a0bba12008-02-20 14:08:50 +1100176 ny[m] = &_ny[m*N];
177 iny[m] = &_iny[m*N];
178 y[m] = &_y[m*N];
179 iy[m] = &_iy[m*N];
Jean-Marc Valinfe419832008-02-12 15:05:01 +1100180 }
181
Jean-Marc Valin41af4212007-11-30 18:35:37 +1100182 for (j=0;j<N;j++)
Jean-Marc Valin0d587d82008-02-14 21:29:50 +1100183 {
Jean-Marc Valinf675adc2008-02-28 12:15:17 +1100184 Rpp = MAC16_16(Rpp, P[j],P[j]);
185 Rxp = MAC16_16(Rxp, X[j],P[j]);
Jean-Marc Valin0d587d82008-02-14 21:29:50 +1100186 }
Jean-Marc Valinf675adc2008-02-28 12:15:17 +1100187 Rpp = ROUND(Rpp, NORM_SHIFT);
188 Rxp = ROUND(Rxp, NORM_SHIFT);
189 if (Rpp>NORM_SCALING)
Jean-Marc Valinb60340f2008-02-26 15:41:51 +1100190 celt_fatal("Rpp > 1");
191
Jean-Marc Valin0d587d82008-02-14 21:29:50 +1100192 /* We only need to initialise the zero because the first iteration only uses that */
193 for (i=0;i<N;i++)
194 y[0][i] = 0;
195 for (i=0;i<N;i++)
196 iy[0][i] = 0;
197 xy[0] = yy[0] = yp[0] = 0;
198
Jean-Marc Valin846d4e22008-02-12 13:48:48 +1100199 pulsesLeft = K;
200 while (pulsesLeft > 0)
Jean-Marc Valin41af4212007-11-30 18:35:37 +1100201 {
Jean-Marc Valin846d4e22008-02-12 13:48:48 +1100202 int pulsesAtOnce=1;
Jean-Marc Valincab576e2008-02-12 17:21:14 +1100203 int Lupdate = L;
Jean-Marc Valin41af4212007-11-30 18:35:37 +1100204 int L2 = L;
Jean-Marc Valin0d587d82008-02-14 21:29:50 +1100205
206 /* Decide on complexity strategy */
Jean-Marc Valincab576e2008-02-12 17:21:14 +1100207 pulsesAtOnce = pulsesLeft/N;
208 if (pulsesAtOnce<1)
209 pulsesAtOnce = 1;
210 if (pulsesLeft-pulsesAtOnce > 3 || N > 30)
211 Lupdate = 1;
Jean-Marc Valina85657b2008-02-20 11:59:30 +1100212 /*printf ("%d %d %d/%d %d\n", Lupdate, pulsesAtOnce, pulsesLeft, K, N);*/
Jean-Marc Valincab576e2008-02-12 17:21:14 +1100213 L2 = Lupdate;
214 if (L2>maxL)
Jean-Marc Valin41af4212007-11-30 18:35:37 +1100215 {
216 L2 = maxL;
217 maxL *= N;
218 }
Jean-Marc Valin846d4e22008-02-12 13:48:48 +1100219
Jean-Marc Valin0d587d82008-02-14 21:29:50 +1100220 for (m=0;m<Lupdate;m++)
Jean-Marc Valin883bd8e2008-02-15 00:34:01 +1100221 nbest[m]->score = -1e10f;
Jean-Marc Valin41af4212007-11-30 18:35:37 +1100222
223 for (m=0;m<L2;m++)
224 {
225 for (j=0;j<N;j++)
226 {
Jean-Marc Valin1e7087e2007-12-04 13:05:43 +1100227 int sign;
Jean-Marc Valin0d587d82008-02-14 21:29:50 +1100228 /*if (x[j]>0) sign=1; else sign=-1;*/
Jean-Marc Valin1e7087e2007-12-04 13:05:43 +1100229 for (sign=-1;sign<=1;sign+=2)
Jean-Marc Valin41af4212007-11-30 18:35:37 +1100230 {
Jean-Marc Valina85657b2008-02-20 11:59:30 +1100231 /*fprintf (stderr, "%d/%d %d/%d %d/%d\n", i, K, m, L2, j, N);*/
Jean-Marc Valin1e7087e2007-12-04 13:05:43 +1100232 float tmp_xy, tmp_yy, tmp_yp;
233 float score;
234 float g;
Jean-Marc Valinf675adc2008-02-28 12:15:17 +1100235 float s = SHL16(sign*pulsesAtOnce, yshift);
Jean-Marc Valinfe419832008-02-12 15:05:01 +1100236
Jean-Marc Valin9a0bba12008-02-20 14:08:50 +1100237 /* All pulses at one location must have the same sign. */
238 if (iy[m][j]*sign < 0)
239 continue;
240
Jean-Marc Valina073c7b2008-02-14 16:58:04 +1100241 /* Updating the sums of the new pulse(s) */
Jean-Marc Valinf675adc2008-02-28 12:15:17 +1100242 tmp_xy = xy[m] + s*X[j] - _alpha*s*P[j]*Rxp*NORM_SCALING_1;
243 tmp_yy = yy[m] + 2.f*s*y[m][j] + s*s +s*s*_alpha*_alpha*p[j]*p[j]*Rpp*NORM_SCALING_1 - 2.f*_alpha*s*p[j]*yp[m] - 2.f*s*s*_alpha*p[j]*p[j];
244 tmp_yp = yp[m] + s*p[j] *(1.f-_alpha*Rpp*NORM_SCALING_1);
Jean-Marc Valina073c7b2008-02-14 16:58:04 +1100245
246 /* Compute the gain such that ||p + g*y|| = 1 */
Jean-Marc Valinf675adc2008-02-28 12:15:17 +1100247 g = (approx_sqrt(tmp_yp*tmp_yp + tmp_yy - tmp_yy*Rpp*NORM_SCALING_1) - tmp_yp)*approx_inv(tmp_yy);
Jean-Marc Valina073c7b2008-02-14 16:58:04 +1100248 /* Knowing that gain, what the error: (x-g*y)^2
249 (result is negated and we discard x^2 because it's constant) */
Jean-Marc Valinf675adc2008-02-28 12:15:17 +1100250 score = 2.f*g*tmp_xy*NORM_SCALING_1 - g*g*tmp_yy;
Jean-Marc Valin41af4212007-11-30 18:35:37 +1100251
Jean-Marc Valin3b277dc2008-02-14 16:46:50 +1100252 if (score>nbest[Lupdate-1]->score)
Jean-Marc Valin1e7087e2007-12-04 13:05:43 +1100253 {
Jean-Marc Valin472a5f02008-02-19 13:12:32 +1100254 int k;
Jean-Marc Valincab576e2008-02-12 17:21:14 +1100255 int id = Lupdate-1;
Jean-Marc Valin3b277dc2008-02-14 16:46:50 +1100256 struct NBest *tmp_best;
257
258 /* Save some pointers that would be deleted and use them for the current entry*/
259 tmp_best = nbest[Lupdate-1];
260 while (id > 0 && score > nbest[id-1]->score)
Jean-Marc Valin1e7087e2007-12-04 13:05:43 +1100261 id--;
262
Jean-Marc Valincab576e2008-02-12 17:21:14 +1100263 for (k=Lupdate-1;k>id;k--)
Jean-Marc Valin3b277dc2008-02-14 16:46:50 +1100264 nbest[k] = nbest[k-1];
Jean-Marc Valin1e7087e2007-12-04 13:05:43 +1100265
Jean-Marc Valin3b277dc2008-02-14 16:46:50 +1100266 nbest[id] = tmp_best;
267 nbest[id]->score = score;
268 nbest[id]->pos = j;
269 nbest[id]->orig = m;
270 nbest[id]->sign = sign;
271 nbest[id]->gain = g;
272 nbest[id]->xy = tmp_xy;
273 nbest[id]->yy = tmp_yy;
274 nbest[id]->yp = tmp_yp;
Jean-Marc Valin1e7087e2007-12-04 13:05:43 +1100275 }
Jean-Marc Valin636f5c82008-02-12 17:40:27 +1100276 }
Jean-Marc Valin41af4212007-11-30 18:35:37 +1100277 }
Jean-Marc Valin636f5c82008-02-12 17:40:27 +1100278
Jean-Marc Valin41af4212007-11-30 18:35:37 +1100279 }
Jean-Marc Valinb60340f2008-02-26 15:41:51 +1100280
281 if (!(nbest[0]->score > -1e10f))
282 celt_fatal("Could not find any match in VQ codebook. Something got corrupted somewhere.");
Jean-Marc Valin0d587d82008-02-14 21:29:50 +1100283 /* Only now that we've made the final choice, update ny/iny and others */
Jean-Marc Valincab576e2008-02-12 17:21:14 +1100284 for (k=0;k<Lupdate;k++)
Jean-Marc Valin41af4212007-11-30 18:35:37 +1100285 {
Jean-Marc Valin3b277dc2008-02-14 16:46:50 +1100286 int n;
287 int is;
288 float s;
289 is = nbest[k]->sign*pulsesAtOnce;
Jean-Marc Valinf675adc2008-02-28 12:15:17 +1100290 s = SHL16(is, yshift);
Jean-Marc Valin3b277dc2008-02-14 16:46:50 +1100291 for (n=0;n<N;n++)
Jean-Marc Valin9d8d9b32008-02-27 16:17:39 +1100292 ny[k][n] = y[nbest[k]->orig][n] - _alpha*s*p[nbest[k]->pos]*p[n];
Jean-Marc Valin3b277dc2008-02-14 16:46:50 +1100293 ny[k][nbest[k]->pos] += s;
Jean-Marc Valin0d587d82008-02-14 21:29:50 +1100294
Jean-Marc Valin3b277dc2008-02-14 16:46:50 +1100295 for (n=0;n<N;n++)
296 iny[k][n] = iy[nbest[k]->orig][n];
297 iny[k][nbest[k]->pos] += is;
Jean-Marc Valin0d587d82008-02-14 21:29:50 +1100298
Jean-Marc Valin3b277dc2008-02-14 16:46:50 +1100299 xy[k] = nbest[k]->xy;
300 yy[k] = nbest[k]->yy;
301 yp[k] = nbest[k]->yp;
302 }
Jean-Marc Valin0d587d82008-02-14 21:29:50 +1100303 /* Swap ny/iny with y/iy */
Jean-Marc Valin3b277dc2008-02-14 16:46:50 +1100304 for (k=0;k<Lupdate;k++)
305 {
Jean-Marc Valinfe419832008-02-12 15:05:01 +1100306 float *tmp_ny;
307 int *tmp_iny;
308
Jean-Marc Valinfe419832008-02-12 15:05:01 +1100309 tmp_ny = ny[k];
310 ny[k] = y[k];
311 y[k] = tmp_ny;
312 tmp_iny = iny[k];
313 iny[k] = iy[k];
314 iy[k] = tmp_iny;
Jean-Marc Valin41af4212007-11-30 18:35:37 +1100315 }
Jean-Marc Valin846d4e22008-02-12 13:48:48 +1100316 pulsesLeft -= pulsesAtOnce;
Jean-Marc Valin41af4212007-11-30 18:35:37 +1100317 }
318
Jean-Marc Valind4018c32008-02-27 10:09:48 +1100319#if 0
Jean-Marc Valinac1e03d2008-02-12 23:00:18 +1100320 if (0) {
321 float err=0;
322 for (i=0;i<N;i++)
Jean-Marc Valin3b277dc2008-02-14 16:46:50 +1100323 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 +1100324 /*if (N<=10)
325 printf ("%f %d %d\n", err, K, N);*/
Jean-Marc Valinac1e03d2008-02-12 23:00:18 +1100326 }
Jean-Marc Valin0d587d82008-02-14 21:29:50 +1100327 /* Sanity checks, don't bother */
Jean-Marc Valin1e7087e2007-12-04 13:05:43 +1100328 if (0) {
Jean-Marc Valind4018c32008-02-27 10:09:48 +1100329 for (i=0;i<N;i++)
330 x[i] = p[i]+nbest[0]->gain*y[0][i];
Jean-Marc Valin1e7087e2007-12-04 13:05:43 +1100331 float E=1e-15;
332 int ABS = 0;
333 for (i=0;i<N;i++)
334 ABS += abs(iy[0][i]);
Jean-Marc Valina85657b2008-02-20 11:59:30 +1100335 /*if (K != ABS)
336 printf ("%d %d\n", K, ABS);*/
Jean-Marc Valin1e7087e2007-12-04 13:05:43 +1100337 for (i=0;i<N;i++)
338 E += x[i]*x[i];
Jean-Marc Valina85657b2008-02-20 11:59:30 +1100339 /*printf ("%f\n", E);*/
Jean-Marc Valin1e7087e2007-12-04 13:05:43 +1100340 E = 1/sqrt(E);
341 for (i=0;i<N;i++)
342 x[i] *= E;
343 }
Jean-Marc Valind4018c32008-02-27 10:09:48 +1100344#endif
Jean-Marc Valin5fa59952008-02-14 13:50:44 +1100345
346 encode_pulses(iy[0], N, K, enc);
347
Jean-Marc Valina4833ff2008-01-10 15:34:00 +1100348 /* Recompute the gain in one pass to reduce the encoder-decoder mismatch
Jean-Marc Valin636f5c82008-02-12 17:40:27 +1100349 due to the recursive computation used in quantisation.
350 Not quite sure whether we need that or not */
Jean-Marc Valind17edd32008-02-27 16:52:30 +1100351 mix_pitch_and_residual(iy[0], X, N, K, P, alpha);
Jean-Marc Valin41af4212007-11-30 18:35:37 +1100352}
353
Jean-Marc Valin879fbfd2008-02-20 17:17:13 +1100354/** Decode pulse vector and combine the result with the pitch vector to produce
355 the final normalised signal in the current band. */
Jean-Marc Valin9d8d9b32008-02-27 16:17:39 +1100356void 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 +1100357{
Jean-Marc Valin9a0bba12008-02-20 14:08:50 +1100358 VARDECL(int *iy);
Jean-Marc Valin9a0bba12008-02-20 14:08:50 +1100359 ALLOC(iy, N, int);
Jean-Marc Valin5fa59952008-02-14 13:50:44 +1100360 decode_pulses(iy, N, K, dec);
Jean-Marc Valind17edd32008-02-27 16:52:30 +1100361 mix_pitch_and_residual(iy, X, N, K, P, alpha);
Jean-Marc Valin0d227d82007-12-31 16:12:12 +1100362}
363
364
365static const float pg[11] = {1.f, .75f, .65f, 0.6f, 0.6f, .6f, .55f, .55f, .5f, .5f, .5f};
366
Jean-Marc Valin5f09ea52008-02-26 16:43:04 +1100367void 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 +1100368{
369 int i,j;
370 int best=0;
Jean-Marc Valin50d11162007-12-03 14:34:52 +1100371 float best_score=0;
372 float s = 1;
Jean-Marc Valin0aa39032007-12-07 15:09:58 +1100373 int sign;
Jean-Marc Valin4841a0a2007-12-03 13:54:30 +1100374 float E;
Jean-Marc Valin9a0bba12008-02-20 14:08:50 +1100375 float pred_gain;
Jean-Marc Valin8f0f4b92008-02-11 13:52:44 +1100376 int max_pos = N0-N/B;
377 if (max_pos > 32)
378 max_pos = 32;
379
380 for (i=0;i<max_pos*B;i+=B)
Jean-Marc Valin4841a0a2007-12-03 13:54:30 +1100381 {
382 int j;
383 float xy=0, yy=0;
384 float score;
385 for (j=0;j<N;j++)
386 {
Jean-Marc Valinb4dfce42008-02-25 17:41:30 +1100387 xy += 1.f*x[j]*Y[i+N-j-1];
388 yy += 1.f*Y[i+N-j-1]*Y[i+N-j-1];
Jean-Marc Valin4841a0a2007-12-03 13:54:30 +1100389 }
Jean-Marc Valin50d11162007-12-03 14:34:52 +1100390 score = xy*xy/(.001+yy);
Jean-Marc Valin4841a0a2007-12-03 13:54:30 +1100391 if (score > best_score)
392 {
393 best_score = score;
394 best = i;
Jean-Marc Valin50d11162007-12-03 14:34:52 +1100395 if (xy>0)
396 s = 1;
397 else
398 s = -1;
Jean-Marc Valin4841a0a2007-12-03 13:54:30 +1100399 }
400 }
Jean-Marc Valin0aa39032007-12-07 15:09:58 +1100401 if (s<0)
402 sign = 1;
Jean-Marc Valin6e9058a2007-12-07 14:59:06 +1100403 else
Jean-Marc Valin0aa39032007-12-07 15:09:58 +1100404 sign = 0;
Jean-Marc Valina85657b2008-02-20 11:59:30 +1100405 /*printf ("%d %d ", sign, best);*/
Jean-Marc Valin0aa39032007-12-07 15:09:58 +1100406 ec_enc_uint(enc,sign,2);
Jean-Marc Valin8f0f4b92008-02-11 13:52:44 +1100407 ec_enc_uint(enc,best/B,max_pos);
Jean-Marc Valina85657b2008-02-20 11:59:30 +1100408 /*printf ("%d %f\n", best, best_score);*/
Jean-Marc Valin0d227d82007-12-31 16:12:12 +1100409
Jean-Marc Valin0d227d82007-12-31 16:12:12 +1100410 if (K>10)
411 pred_gain = pg[10];
412 else
413 pred_gain = pg[K];
414 E = 1e-10;
415 for (j=0;j<N;j++)
Jean-Marc Valin4841a0a2007-12-03 13:54:30 +1100416 {
Jean-Marc Valind501f612008-02-21 12:16:57 +1100417 P[j] = s*Y[best+N-j-1];
Jean-Marc Valinb4dfce42008-02-25 17:41:30 +1100418 E += NORM_SCALING_1*NORM_SCALING_1*P[j]*P[j];
Jean-Marc Valin4841a0a2007-12-03 13:54:30 +1100419 }
Jean-Marc Valin0d227d82007-12-31 16:12:12 +1100420 E = pred_gain/sqrt(E);
421 for (j=0;j<N;j++)
422 P[j] *= E;
423 if (K>0)
424 {
425 for (j=0;j<N;j++)
426 x[j] -= P[j];
427 } else {
428 for (j=0;j<N;j++)
429 x[j] = P[j];
430 }
Jean-Marc Valina85657b2008-02-20 11:59:30 +1100431 /*printf ("quant ");*/
432 /*for (j=0;j<N;j++) printf ("%f ", P[j]);*/
Jean-Marc Valin0d227d82007-12-31 16:12:12 +1100433
Jean-Marc Valin4841a0a2007-12-03 13:54:30 +1100434}
Jean-Marc Valinfc08d0a2007-12-07 13:26:15 +1100435
Jean-Marc Valin18ddc022008-02-22 14:24:50 +1100436void 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 +1100437{
Jean-Marc Valin11f01722007-12-09 01:19:36 +1100438 int j;
Jean-Marc Valin0aa39032007-12-07 15:09:58 +1100439 int sign;
440 float s;
Jean-Marc Valin6e9058a2007-12-07 14:59:06 +1100441 int best;
442 float E;
Jean-Marc Valin9a0bba12008-02-20 14:08:50 +1100443 float pred_gain;
Jean-Marc Valin8f0f4b92008-02-11 13:52:44 +1100444 int max_pos = N0-N/B;
445 if (max_pos > 32)
446 max_pos = 32;
447
Jean-Marc Valin0aa39032007-12-07 15:09:58 +1100448 sign = ec_dec_uint(dec, 2);
449 if (sign == 0)
Jean-Marc Valin6e9058a2007-12-07 14:59:06 +1100450 s = 1;
451 else
452 s = -1;
453
Jean-Marc Valin8f0f4b92008-02-11 13:52:44 +1100454 best = B*ec_dec_uint(dec, max_pos);
Jean-Marc Valina85657b2008-02-20 11:59:30 +1100455 /*printf ("%d %d ", sign, best);*/
Jean-Marc Valin6e9058a2007-12-07 14:59:06 +1100456
Jean-Marc Valin0d227d82007-12-31 16:12:12 +1100457 if (K>10)
458 pred_gain = pg[10];
459 else
460 pred_gain = pg[K];
461 E = 1e-10;
462 for (j=0;j<N;j++)
463 {
Jean-Marc Valind501f612008-02-21 12:16:57 +1100464 P[j] = s*Y[best+N-j-1];
Jean-Marc Valinb4dfce42008-02-25 17:41:30 +1100465 E += NORM_SCALING_1*NORM_SCALING_1*P[j]*P[j];
Jean-Marc Valin0d227d82007-12-31 16:12:12 +1100466 }
467 E = pred_gain/sqrt(E);
468 for (j=0;j<N;j++)
469 P[j] *= E;
Jean-Marc Valin6e9058a2007-12-07 14:59:06 +1100470 if (K==0)
471 {
Jean-Marc Valin6e9058a2007-12-07 14:59:06 +1100472 for (j=0;j<N;j++)
Jean-Marc Valin0d227d82007-12-31 16:12:12 +1100473 x[j] = P[j];
Jean-Marc Valin6e9058a2007-12-07 14:59:06 +1100474 }
475}
Jean-Marc Valin0e20ca02008-02-11 15:33:53 +1100476
Jean-Marc Valin18ddc022008-02-22 14:24:50 +1100477void 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 +1100478{
Jean-Marc Valin0df0eb42008-02-13 16:00:10 +1100479 int i, j;
Jean-Marc Valin0e20ca02008-02-11 15:33:53 +1100480 float E;
481
482 E = 1e-10;
Jean-Marc Valin0df0eb42008-02-13 16:00:10 +1100483 if (N0 >= Nmax/2)
Jean-Marc Valin0e20ca02008-02-11 15:33:53 +1100484 {
Jean-Marc Valin0df0eb42008-02-13 16:00:10 +1100485 for (i=0;i<B;i++)
486 {
487 for (j=0;j<N/B;j++)
488 {
489 P[j*B+i] = Y[(Nmax-N0-j-1)*B+i];
Jean-Marc Valinb4dfce42008-02-25 17:41:30 +1100490 E += NORM_SCALING_1*NORM_SCALING_1*P[j*B+i]*P[j*B+i];
Jean-Marc Valin0df0eb42008-02-13 16:00:10 +1100491 }
492 }
493 } else {
494 for (j=0;j<N;j++)
495 {
496 P[j] = Y[j];
Jean-Marc Valinb4dfce42008-02-25 17:41:30 +1100497 E += NORM_SCALING_1*NORM_SCALING_1*P[j]*P[j];
Jean-Marc Valin0df0eb42008-02-13 16:00:10 +1100498 }
Jean-Marc Valin0e20ca02008-02-11 15:33:53 +1100499 }
500 E = 1.f/sqrt(E);
501 for (j=0;j<N;j++)
502 P[j] *= E;
503 for (j=0;j<N;j++)
504 x[j] = P[j];
505}
506