blob: c68518d8b24a98901b44d3fd844c276e007b11c8 [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 Valin8b158f52008-02-28 14:44:19 +1100124 VARDECL(celt_norm_t *_y);
125 VARDECL(celt_norm_t *_ny);
Jean-Marc Valin9a0bba12008-02-20 14:08:50 +1100126 VARDECL(int *_iy);
127 VARDECL(int *_iny);
Jean-Marc Valin8b158f52008-02-28 14:44:19 +1100128 VARDECL(celt_norm_t **y);
129 VARDECL(celt_norm_t **ny);
Jean-Marc Valin9a0bba12008-02-20 14:08:50 +1100130 VARDECL(int **iy);
131 VARDECL(int **iny);
Jean-Marc Valin0d587d82008-02-14 21:29:50 +1100132 int i, j, k, m;
Jean-Marc Valin846d4e22008-02-12 13:48:48 +1100133 int pulsesLeft;
Jean-Marc Valined9e4232008-02-28 12:22:22 +1100134 VARDECL(celt_word32_t *xy);
135 VARDECL(celt_word32_t *yy);
136 VARDECL(celt_word32_t *yp);
Jean-Marc Valin9a0bba12008-02-20 14:08:50 +1100137 VARDECL(struct NBest *_nbest);
138 VARDECL(struct NBest **nbest);
Jean-Marc Valinf675adc2008-02-28 12:15:17 +1100139 celt_word32_t Rpp=0, Rxp=0;
Jean-Marc Valin41af4212007-11-30 18:35:37 +1100140 int maxL = 1;
Jean-Marc Valinf675adc2008-02-28 12:15:17 +1100141#ifdef FIXED_POINT
142 int yshift = 14-EC_ILOG(K);
143#endif
Jean-Marc Valin9d8d9b32008-02-27 16:17:39 +1100144
Jean-Marc Valin8b158f52008-02-28 14:44:19 +1100145 ALLOC(_y, L*N, celt_norm_t);
146 ALLOC(_ny, L*N, celt_norm_t);
Jean-Marc Valin9a0bba12008-02-20 14:08:50 +1100147 ALLOC(_iy, L*N, int);
148 ALLOC(_iny, L*N, int);
Jean-Marc Valin8b158f52008-02-28 14:44:19 +1100149 ALLOC(y, L*N, celt_norm_t*);
150 ALLOC(ny, L*N, celt_norm_t*);
Jean-Marc Valin9a0bba12008-02-20 14:08:50 +1100151 ALLOC(iy, L*N, int*);
152 ALLOC(iny, L*N, int*);
153
Jean-Marc Valined9e4232008-02-28 12:22:22 +1100154 ALLOC(xy, L, celt_word32_t);
155 ALLOC(yy, L, celt_word32_t);
156 ALLOC(yp, L, celt_word32_t);
Jean-Marc Valin9a0bba12008-02-20 14:08:50 +1100157 ALLOC(_nbest, L, struct NBest);
158 ALLOC(nbest, L, struct NBest *);
Jean-Marc Valinb4dfce42008-02-25 17:41:30 +1100159
Jean-Marc Valinfe419832008-02-12 15:05:01 +1100160 for (m=0;m<L;m++)
Jean-Marc Valin3b277dc2008-02-14 16:46:50 +1100161 nbest[m] = &_nbest[m];
162
163 for (m=0;m<L;m++)
Jean-Marc Valinfe419832008-02-12 15:05:01 +1100164 {
Jean-Marc Valin9a0bba12008-02-20 14:08:50 +1100165 ny[m] = &_ny[m*N];
166 iny[m] = &_iny[m*N];
167 y[m] = &_y[m*N];
168 iy[m] = &_iy[m*N];
Jean-Marc Valinfe419832008-02-12 15:05:01 +1100169 }
170
Jean-Marc Valin41af4212007-11-30 18:35:37 +1100171 for (j=0;j<N;j++)
Jean-Marc Valin0d587d82008-02-14 21:29:50 +1100172 {
Jean-Marc Valinf675adc2008-02-28 12:15:17 +1100173 Rpp = MAC16_16(Rpp, P[j],P[j]);
174 Rxp = MAC16_16(Rxp, X[j],P[j]);
Jean-Marc Valin0d587d82008-02-14 21:29:50 +1100175 }
Jean-Marc Valinf675adc2008-02-28 12:15:17 +1100176 Rpp = ROUND(Rpp, NORM_SHIFT);
177 Rxp = ROUND(Rxp, NORM_SHIFT);
178 if (Rpp>NORM_SCALING)
Jean-Marc Valinb60340f2008-02-26 15:41:51 +1100179 celt_fatal("Rpp > 1");
180
Jean-Marc Valin0d587d82008-02-14 21:29:50 +1100181 /* We only need to initialise the zero because the first iteration only uses that */
182 for (i=0;i<N;i++)
183 y[0][i] = 0;
184 for (i=0;i<N;i++)
185 iy[0][i] = 0;
186 xy[0] = yy[0] = yp[0] = 0;
187
Jean-Marc Valin846d4e22008-02-12 13:48:48 +1100188 pulsesLeft = K;
189 while (pulsesLeft > 0)
Jean-Marc Valin41af4212007-11-30 18:35:37 +1100190 {
Jean-Marc Valin846d4e22008-02-12 13:48:48 +1100191 int pulsesAtOnce=1;
Jean-Marc Valincab576e2008-02-12 17:21:14 +1100192 int Lupdate = L;
Jean-Marc Valin41af4212007-11-30 18:35:37 +1100193 int L2 = L;
Jean-Marc Valin0d587d82008-02-14 21:29:50 +1100194
195 /* Decide on complexity strategy */
Jean-Marc Valincab576e2008-02-12 17:21:14 +1100196 pulsesAtOnce = pulsesLeft/N;
197 if (pulsesAtOnce<1)
198 pulsesAtOnce = 1;
199 if (pulsesLeft-pulsesAtOnce > 3 || N > 30)
200 Lupdate = 1;
Jean-Marc Valina85657b2008-02-20 11:59:30 +1100201 /*printf ("%d %d %d/%d %d\n", Lupdate, pulsesAtOnce, pulsesLeft, K, N);*/
Jean-Marc Valincab576e2008-02-12 17:21:14 +1100202 L2 = Lupdate;
203 if (L2>maxL)
Jean-Marc Valin41af4212007-11-30 18:35:37 +1100204 {
205 L2 = maxL;
206 maxL *= N;
207 }
Jean-Marc Valin846d4e22008-02-12 13:48:48 +1100208
Jean-Marc Valin0d587d82008-02-14 21:29:50 +1100209 for (m=0;m<Lupdate;m++)
Jean-Marc Valin883bd8e2008-02-15 00:34:01 +1100210 nbest[m]->score = -1e10f;
Jean-Marc Valin41af4212007-11-30 18:35:37 +1100211
212 for (m=0;m<L2;m++)
213 {
214 for (j=0;j<N;j++)
215 {
Jean-Marc Valin1e7087e2007-12-04 13:05:43 +1100216 int sign;
Jean-Marc Valin0d587d82008-02-14 21:29:50 +1100217 /*if (x[j]>0) sign=1; else sign=-1;*/
Jean-Marc Valin1e7087e2007-12-04 13:05:43 +1100218 for (sign=-1;sign<=1;sign+=2)
Jean-Marc Valin41af4212007-11-30 18:35:37 +1100219 {
Jean-Marc Valina85657b2008-02-20 11:59:30 +1100220 /*fprintf (stderr, "%d/%d %d/%d %d/%d\n", i, K, m, L2, j, N);*/
Jean-Marc Valined9e4232008-02-28 12:22:22 +1100221 celt_word32_t tmp_xy, tmp_yy, tmp_yp;
Jean-Marc Valin642ff942008-02-28 14:33:19 +1100222 celt_word16_t spj, aspj;
Jean-Marc Valin1e7087e2007-12-04 13:05:43 +1100223 float score;
224 float g;
Jean-Marc Valinc9d606f2008-02-28 13:46:20 +1100225 celt_word16_t s = SHL16(sign*pulsesAtOnce, yshift);
Jean-Marc Valinfe419832008-02-12 15:05:01 +1100226
Jean-Marc Valin9a0bba12008-02-20 14:08:50 +1100227 /* All pulses at one location must have the same sign. */
228 if (iy[m][j]*sign < 0)
229 continue;
230
Jean-Marc Valinc9d606f2008-02-28 13:46:20 +1100231 spj = MULT16_16_P14(s, P[j]);
Jean-Marc Valin642ff942008-02-28 14:33:19 +1100232 aspj = MULT16_16_P15(alpha, spj);
Jean-Marc Valina073c7b2008-02-14 16:58:04 +1100233 /* Updating the sums of the new pulse(s) */
Jean-Marc Valinc9d606f2008-02-28 13:46:20 +1100234 tmp_xy = xy[m] + MULT16_16(s,X[j]) - MULT16_16(MULT16_16_P15(alpha,spj),Rxp);
Jean-Marc Valin642ff942008-02-28 14:33:19 +1100235 tmp_yy = yy[m] + 2*MULT16_16(s,y[m][j]) + MULT16_16(s,s) +MULT16_16(aspj,MULT16_16_Q14(aspj,Rpp)) - 2*MULT16_32_Q14(aspj,yp[m]) - 2*MULT16_16(s,MULT16_16_Q14(aspj,P[j]));
Jean-Marc Valinc9d606f2008-02-28 13:46:20 +1100236 tmp_yp = yp[m] + MULT16_16(spj, SUB16(QCONST16(1.f,14),MULT16_16_Q15(alpha,Rpp)));
Jean-Marc Valina073c7b2008-02-14 16:58:04 +1100237
238 /* Compute the gain such that ||p + g*y|| = 1 */
Jean-Marc Valined9e4232008-02-28 12:22:22 +1100239 g = (approx_sqrt(NORM_SCALING_1*NORM_SCALING_1*tmp_yp*tmp_yp + tmp_yy - NORM_SCALING_1*tmp_yy*Rpp) - tmp_yp*NORM_SCALING_1)*approx_inv(tmp_yy);
Jean-Marc Valina073c7b2008-02-14 16:58:04 +1100240 /* Knowing that gain, what the error: (x-g*y)^2
241 (result is negated and we discard x^2 because it's constant) */
Jean-Marc Valinf675adc2008-02-28 12:15:17 +1100242 score = 2.f*g*tmp_xy*NORM_SCALING_1 - g*g*tmp_yy;
Jean-Marc Valin41af4212007-11-30 18:35:37 +1100243
Jean-Marc Valin3b277dc2008-02-14 16:46:50 +1100244 if (score>nbest[Lupdate-1]->score)
Jean-Marc Valin1e7087e2007-12-04 13:05:43 +1100245 {
Jean-Marc Valin472a5f02008-02-19 13:12:32 +1100246 int k;
Jean-Marc Valincab576e2008-02-12 17:21:14 +1100247 int id = Lupdate-1;
Jean-Marc Valin3b277dc2008-02-14 16:46:50 +1100248 struct NBest *tmp_best;
249
250 /* Save some pointers that would be deleted and use them for the current entry*/
251 tmp_best = nbest[Lupdate-1];
252 while (id > 0 && score > nbest[id-1]->score)
Jean-Marc Valin1e7087e2007-12-04 13:05:43 +1100253 id--;
254
Jean-Marc Valincab576e2008-02-12 17:21:14 +1100255 for (k=Lupdate-1;k>id;k--)
Jean-Marc Valin3b277dc2008-02-14 16:46:50 +1100256 nbest[k] = nbest[k-1];
Jean-Marc Valin1e7087e2007-12-04 13:05:43 +1100257
Jean-Marc Valin3b277dc2008-02-14 16:46:50 +1100258 nbest[id] = tmp_best;
259 nbest[id]->score = score;
260 nbest[id]->pos = j;
261 nbest[id]->orig = m;
262 nbest[id]->sign = sign;
263 nbest[id]->gain = g;
264 nbest[id]->xy = tmp_xy;
265 nbest[id]->yy = tmp_yy;
266 nbest[id]->yp = tmp_yp;
Jean-Marc Valin1e7087e2007-12-04 13:05:43 +1100267 }
Jean-Marc Valin636f5c82008-02-12 17:40:27 +1100268 }
Jean-Marc Valin41af4212007-11-30 18:35:37 +1100269 }
Jean-Marc Valin636f5c82008-02-12 17:40:27 +1100270
Jean-Marc Valin41af4212007-11-30 18:35:37 +1100271 }
Jean-Marc Valinb60340f2008-02-26 15:41:51 +1100272
273 if (!(nbest[0]->score > -1e10f))
274 celt_fatal("Could not find any match in VQ codebook. Something got corrupted somewhere.");
Jean-Marc Valin0d587d82008-02-14 21:29:50 +1100275 /* Only now that we've made the final choice, update ny/iny and others */
Jean-Marc Valincab576e2008-02-12 17:21:14 +1100276 for (k=0;k<Lupdate;k++)
Jean-Marc Valin41af4212007-11-30 18:35:37 +1100277 {
Jean-Marc Valin3b277dc2008-02-14 16:46:50 +1100278 int n;
279 int is;
Jean-Marc Valin8b158f52008-02-28 14:44:19 +1100280 celt_norm_t s;
Jean-Marc Valin3b277dc2008-02-14 16:46:50 +1100281 is = nbest[k]->sign*pulsesAtOnce;
Jean-Marc Valinf675adc2008-02-28 12:15:17 +1100282 s = SHL16(is, yshift);
Jean-Marc Valin3b277dc2008-02-14 16:46:50 +1100283 for (n=0;n<N;n++)
Jean-Marc Valin8b158f52008-02-28 14:44:19 +1100284 ny[k][n] = y[nbest[k]->orig][n] - MULT16_16_Q15(alpha,MULT16_16_Q14(s,MULT16_16_Q14(P[nbest[k]->pos],P[n])));
Jean-Marc Valin3b277dc2008-02-14 16:46:50 +1100285 ny[k][nbest[k]->pos] += s;
Jean-Marc Valin0d587d82008-02-14 21:29:50 +1100286
Jean-Marc Valin3b277dc2008-02-14 16:46:50 +1100287 for (n=0;n<N;n++)
288 iny[k][n] = iy[nbest[k]->orig][n];
289 iny[k][nbest[k]->pos] += is;
Jean-Marc Valin0d587d82008-02-14 21:29:50 +1100290
Jean-Marc Valin3b277dc2008-02-14 16:46:50 +1100291 xy[k] = nbest[k]->xy;
292 yy[k] = nbest[k]->yy;
293 yp[k] = nbest[k]->yp;
294 }
Jean-Marc Valin0d587d82008-02-14 21:29:50 +1100295 /* Swap ny/iny with y/iy */
Jean-Marc Valin3b277dc2008-02-14 16:46:50 +1100296 for (k=0;k<Lupdate;k++)
297 {
Jean-Marc Valin8b158f52008-02-28 14:44:19 +1100298 celt_norm_t *tmp_ny;
Jean-Marc Valinfe419832008-02-12 15:05:01 +1100299 int *tmp_iny;
300
Jean-Marc Valinfe419832008-02-12 15:05:01 +1100301 tmp_ny = ny[k];
302 ny[k] = y[k];
303 y[k] = tmp_ny;
304 tmp_iny = iny[k];
305 iny[k] = iy[k];
306 iy[k] = tmp_iny;
Jean-Marc Valin41af4212007-11-30 18:35:37 +1100307 }
Jean-Marc Valin846d4e22008-02-12 13:48:48 +1100308 pulsesLeft -= pulsesAtOnce;
Jean-Marc Valin41af4212007-11-30 18:35:37 +1100309 }
310
Jean-Marc Valind4018c32008-02-27 10:09:48 +1100311#if 0
Jean-Marc Valinac1e03d2008-02-12 23:00:18 +1100312 if (0) {
313 float err=0;
314 for (i=0;i<N;i++)
Jean-Marc Valin3b277dc2008-02-14 16:46:50 +1100315 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 +1100316 /*if (N<=10)
317 printf ("%f %d %d\n", err, K, N);*/
Jean-Marc Valinac1e03d2008-02-12 23:00:18 +1100318 }
Jean-Marc Valin0d587d82008-02-14 21:29:50 +1100319 /* Sanity checks, don't bother */
Jean-Marc Valin1e7087e2007-12-04 13:05:43 +1100320 if (0) {
Jean-Marc Valind4018c32008-02-27 10:09:48 +1100321 for (i=0;i<N;i++)
322 x[i] = p[i]+nbest[0]->gain*y[0][i];
Jean-Marc Valin1e7087e2007-12-04 13:05:43 +1100323 float E=1e-15;
324 int ABS = 0;
325 for (i=0;i<N;i++)
326 ABS += abs(iy[0][i]);
Jean-Marc Valina85657b2008-02-20 11:59:30 +1100327 /*if (K != ABS)
328 printf ("%d %d\n", K, ABS);*/
Jean-Marc Valin1e7087e2007-12-04 13:05:43 +1100329 for (i=0;i<N;i++)
330 E += x[i]*x[i];
Jean-Marc Valina85657b2008-02-20 11:59:30 +1100331 /*printf ("%f\n", E);*/
Jean-Marc Valin1e7087e2007-12-04 13:05:43 +1100332 E = 1/sqrt(E);
333 for (i=0;i<N;i++)
334 x[i] *= E;
335 }
Jean-Marc Valind4018c32008-02-27 10:09:48 +1100336#endif
Jean-Marc Valin5fa59952008-02-14 13:50:44 +1100337
338 encode_pulses(iy[0], N, K, enc);
339
Jean-Marc Valina4833ff2008-01-10 15:34:00 +1100340 /* Recompute the gain in one pass to reduce the encoder-decoder mismatch
Jean-Marc Valin636f5c82008-02-12 17:40:27 +1100341 due to the recursive computation used in quantisation.
342 Not quite sure whether we need that or not */
Jean-Marc Valind17edd32008-02-27 16:52:30 +1100343 mix_pitch_and_residual(iy[0], X, N, K, P, alpha);
Jean-Marc Valin41af4212007-11-30 18:35:37 +1100344}
345
Jean-Marc Valin879fbfd2008-02-20 17:17:13 +1100346/** Decode pulse vector and combine the result with the pitch vector to produce
347 the final normalised signal in the current band. */
Jean-Marc Valin9d8d9b32008-02-27 16:17:39 +1100348void 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 +1100349{
Jean-Marc Valin9a0bba12008-02-20 14:08:50 +1100350 VARDECL(int *iy);
Jean-Marc Valin9a0bba12008-02-20 14:08:50 +1100351 ALLOC(iy, N, int);
Jean-Marc Valin5fa59952008-02-14 13:50:44 +1100352 decode_pulses(iy, N, K, dec);
Jean-Marc Valind17edd32008-02-27 16:52:30 +1100353 mix_pitch_and_residual(iy, X, N, K, P, alpha);
Jean-Marc Valin0d227d82007-12-31 16:12:12 +1100354}
355
356
357static const float pg[11] = {1.f, .75f, .65f, 0.6f, 0.6f, .6f, .55f, .55f, .5f, .5f, .5f};
358
Jean-Marc Valin5f09ea52008-02-26 16:43:04 +1100359void 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 +1100360{
361 int i,j;
362 int best=0;
Jean-Marc Valin50d11162007-12-03 14:34:52 +1100363 float best_score=0;
364 float s = 1;
Jean-Marc Valin0aa39032007-12-07 15:09:58 +1100365 int sign;
Jean-Marc Valin4841a0a2007-12-03 13:54:30 +1100366 float E;
Jean-Marc Valin9a0bba12008-02-20 14:08:50 +1100367 float pred_gain;
Jean-Marc Valin8f0f4b92008-02-11 13:52:44 +1100368 int max_pos = N0-N/B;
369 if (max_pos > 32)
370 max_pos = 32;
371
372 for (i=0;i<max_pos*B;i+=B)
Jean-Marc Valin4841a0a2007-12-03 13:54:30 +1100373 {
374 int j;
375 float xy=0, yy=0;
376 float score;
377 for (j=0;j<N;j++)
378 {
Jean-Marc Valinb4dfce42008-02-25 17:41:30 +1100379 xy += 1.f*x[j]*Y[i+N-j-1];
380 yy += 1.f*Y[i+N-j-1]*Y[i+N-j-1];
Jean-Marc Valin4841a0a2007-12-03 13:54:30 +1100381 }
Jean-Marc Valin50d11162007-12-03 14:34:52 +1100382 score = xy*xy/(.001+yy);
Jean-Marc Valin4841a0a2007-12-03 13:54:30 +1100383 if (score > best_score)
384 {
385 best_score = score;
386 best = i;
Jean-Marc Valin50d11162007-12-03 14:34:52 +1100387 if (xy>0)
388 s = 1;
389 else
390 s = -1;
Jean-Marc Valin4841a0a2007-12-03 13:54:30 +1100391 }
392 }
Jean-Marc Valin0aa39032007-12-07 15:09:58 +1100393 if (s<0)
394 sign = 1;
Jean-Marc Valin6e9058a2007-12-07 14:59:06 +1100395 else
Jean-Marc Valin0aa39032007-12-07 15:09:58 +1100396 sign = 0;
Jean-Marc Valina85657b2008-02-20 11:59:30 +1100397 /*printf ("%d %d ", sign, best);*/
Jean-Marc Valin0aa39032007-12-07 15:09:58 +1100398 ec_enc_uint(enc,sign,2);
Jean-Marc Valin8f0f4b92008-02-11 13:52:44 +1100399 ec_enc_uint(enc,best/B,max_pos);
Jean-Marc Valina85657b2008-02-20 11:59:30 +1100400 /*printf ("%d %f\n", best, best_score);*/
Jean-Marc Valin0d227d82007-12-31 16:12:12 +1100401
Jean-Marc Valin0d227d82007-12-31 16:12:12 +1100402 if (K>10)
403 pred_gain = pg[10];
404 else
405 pred_gain = pg[K];
406 E = 1e-10;
407 for (j=0;j<N;j++)
Jean-Marc Valin4841a0a2007-12-03 13:54:30 +1100408 {
Jean-Marc Valind501f612008-02-21 12:16:57 +1100409 P[j] = s*Y[best+N-j-1];
Jean-Marc Valinb4dfce42008-02-25 17:41:30 +1100410 E += NORM_SCALING_1*NORM_SCALING_1*P[j]*P[j];
Jean-Marc Valin4841a0a2007-12-03 13:54:30 +1100411 }
Jean-Marc Valin0d227d82007-12-31 16:12:12 +1100412 E = pred_gain/sqrt(E);
413 for (j=0;j<N;j++)
414 P[j] *= E;
415 if (K>0)
416 {
417 for (j=0;j<N;j++)
418 x[j] -= P[j];
419 } else {
420 for (j=0;j<N;j++)
421 x[j] = P[j];
422 }
Jean-Marc Valina85657b2008-02-20 11:59:30 +1100423 /*printf ("quant ");*/
424 /*for (j=0;j<N;j++) printf ("%f ", P[j]);*/
Jean-Marc Valin0d227d82007-12-31 16:12:12 +1100425
Jean-Marc Valin4841a0a2007-12-03 13:54:30 +1100426}
Jean-Marc Valinfc08d0a2007-12-07 13:26:15 +1100427
Jean-Marc Valin18ddc022008-02-22 14:24:50 +1100428void 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 +1100429{
Jean-Marc Valin11f01722007-12-09 01:19:36 +1100430 int j;
Jean-Marc Valin0aa39032007-12-07 15:09:58 +1100431 int sign;
432 float s;
Jean-Marc Valin6e9058a2007-12-07 14:59:06 +1100433 int best;
434 float E;
Jean-Marc Valin9a0bba12008-02-20 14:08:50 +1100435 float pred_gain;
Jean-Marc Valin8f0f4b92008-02-11 13:52:44 +1100436 int max_pos = N0-N/B;
437 if (max_pos > 32)
438 max_pos = 32;
439
Jean-Marc Valin0aa39032007-12-07 15:09:58 +1100440 sign = ec_dec_uint(dec, 2);
441 if (sign == 0)
Jean-Marc Valin6e9058a2007-12-07 14:59:06 +1100442 s = 1;
443 else
444 s = -1;
445
Jean-Marc Valin8f0f4b92008-02-11 13:52:44 +1100446 best = B*ec_dec_uint(dec, max_pos);
Jean-Marc Valina85657b2008-02-20 11:59:30 +1100447 /*printf ("%d %d ", sign, best);*/
Jean-Marc Valin6e9058a2007-12-07 14:59:06 +1100448
Jean-Marc Valin0d227d82007-12-31 16:12:12 +1100449 if (K>10)
450 pred_gain = pg[10];
451 else
452 pred_gain = pg[K];
453 E = 1e-10;
454 for (j=0;j<N;j++)
455 {
Jean-Marc Valind501f612008-02-21 12:16:57 +1100456 P[j] = s*Y[best+N-j-1];
Jean-Marc Valinb4dfce42008-02-25 17:41:30 +1100457 E += NORM_SCALING_1*NORM_SCALING_1*P[j]*P[j];
Jean-Marc Valin0d227d82007-12-31 16:12:12 +1100458 }
459 E = pred_gain/sqrt(E);
460 for (j=0;j<N;j++)
461 P[j] *= E;
Jean-Marc Valin6e9058a2007-12-07 14:59:06 +1100462 if (K==0)
463 {
Jean-Marc Valin6e9058a2007-12-07 14:59:06 +1100464 for (j=0;j<N;j++)
Jean-Marc Valin0d227d82007-12-31 16:12:12 +1100465 x[j] = P[j];
Jean-Marc Valin6e9058a2007-12-07 14:59:06 +1100466 }
467}
Jean-Marc Valin0e20ca02008-02-11 15:33:53 +1100468
Jean-Marc Valin18ddc022008-02-22 14:24:50 +1100469void 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 +1100470{
Jean-Marc Valin0df0eb42008-02-13 16:00:10 +1100471 int i, j;
Jean-Marc Valin0e20ca02008-02-11 15:33:53 +1100472 float E;
473
474 E = 1e-10;
Jean-Marc Valin0df0eb42008-02-13 16:00:10 +1100475 if (N0 >= Nmax/2)
Jean-Marc Valin0e20ca02008-02-11 15:33:53 +1100476 {
Jean-Marc Valin0df0eb42008-02-13 16:00:10 +1100477 for (i=0;i<B;i++)
478 {
479 for (j=0;j<N/B;j++)
480 {
481 P[j*B+i] = Y[(Nmax-N0-j-1)*B+i];
Jean-Marc Valinb4dfce42008-02-25 17:41:30 +1100482 E += NORM_SCALING_1*NORM_SCALING_1*P[j*B+i]*P[j*B+i];
Jean-Marc Valin0df0eb42008-02-13 16:00:10 +1100483 }
484 }
485 } else {
486 for (j=0;j<N;j++)
487 {
488 P[j] = Y[j];
Jean-Marc Valinb4dfce42008-02-25 17:41:30 +1100489 E += NORM_SCALING_1*NORM_SCALING_1*P[j]*P[j];
Jean-Marc Valin0df0eb42008-02-13 16:00:10 +1100490 }
Jean-Marc Valin0e20ca02008-02-11 15:33:53 +1100491 }
492 E = 1.f/sqrt(E);
493 for (j=0;j<N;j++)
494 P[j] *= E;
495 for (j=0;j<N;j++)
496 x[j] = P[j];
497}
498