blob: 9fc32ef5cc7c867fa2a021a7e2c8bf5fe0797f7b [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 {
Jean-Marc Valin4e1328b2008-02-28 15:14:07 +1100111 celt_word32_t score;
Jean-Marc Valin3b277dc2008-02-14 16:46:50 +1100112 int sign;
113 int pos;
114 int orig;
Jean-Marc Valin4e1328b2008-02-28 15:14:07 +1100115 celt_word32_t xy;
116 celt_word32_t yy;
117 celt_word32_t yp;
Jean-Marc Valin3b277dc2008-02-14 16:46:50 +1100118};
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 Valin8b158f52008-02-28 14:44:19 +1100123 VARDECL(celt_norm_t *_y);
124 VARDECL(celt_norm_t *_ny);
Jean-Marc Valin9a0bba12008-02-20 14:08:50 +1100125 VARDECL(int *_iy);
126 VARDECL(int *_iny);
Jean-Marc Valin8b158f52008-02-28 14:44:19 +1100127 VARDECL(celt_norm_t **y);
128 VARDECL(celt_norm_t **ny);
Jean-Marc Valin9a0bba12008-02-20 14:08:50 +1100129 VARDECL(int **iy);
130 VARDECL(int **iny);
Jean-Marc Valin0d587d82008-02-14 21:29:50 +1100131 int i, j, k, m;
Jean-Marc Valin846d4e22008-02-12 13:48:48 +1100132 int pulsesLeft;
Jean-Marc Valined9e4232008-02-28 12:22:22 +1100133 VARDECL(celt_word32_t *xy);
134 VARDECL(celt_word32_t *yy);
135 VARDECL(celt_word32_t *yp);
Jean-Marc Valin9a0bba12008-02-20 14:08:50 +1100136 VARDECL(struct NBest *_nbest);
137 VARDECL(struct NBest **nbest);
Jean-Marc Valinf675adc2008-02-28 12:15:17 +1100138 celt_word32_t Rpp=0, Rxp=0;
Jean-Marc Valin41af4212007-11-30 18:35:37 +1100139 int maxL = 1;
Jean-Marc Valinf675adc2008-02-28 12:15:17 +1100140#ifdef FIXED_POINT
141 int yshift = 14-EC_ILOG(K);
142#endif
Jean-Marc Valin9d8d9b32008-02-27 16:17:39 +1100143
Jean-Marc Valin8b158f52008-02-28 14:44:19 +1100144 ALLOC(_y, L*N, celt_norm_t);
145 ALLOC(_ny, L*N, celt_norm_t);
Jean-Marc Valin9a0bba12008-02-20 14:08:50 +1100146 ALLOC(_iy, L*N, int);
147 ALLOC(_iny, L*N, int);
Jean-Marc Valin8b158f52008-02-28 14:44:19 +1100148 ALLOC(y, L*N, celt_norm_t*);
149 ALLOC(ny, L*N, celt_norm_t*);
Jean-Marc Valin9a0bba12008-02-20 14:08:50 +1100150 ALLOC(iy, L*N, int*);
151 ALLOC(iny, L*N, int*);
152
Jean-Marc Valined9e4232008-02-28 12:22:22 +1100153 ALLOC(xy, L, celt_word32_t);
154 ALLOC(yy, L, celt_word32_t);
155 ALLOC(yp, L, celt_word32_t);
Jean-Marc Valin9a0bba12008-02-20 14:08:50 +1100156 ALLOC(_nbest, L, struct NBest);
157 ALLOC(nbest, L, struct NBest *);
Jean-Marc Valinb4dfce42008-02-25 17:41:30 +1100158
Jean-Marc Valinfe419832008-02-12 15:05:01 +1100159 for (m=0;m<L;m++)
Jean-Marc Valin3b277dc2008-02-14 16:46:50 +1100160 nbest[m] = &_nbest[m];
161
162 for (m=0;m<L;m++)
Jean-Marc Valinfe419832008-02-12 15:05:01 +1100163 {
Jean-Marc Valin9a0bba12008-02-20 14:08:50 +1100164 ny[m] = &_ny[m*N];
165 iny[m] = &_iny[m*N];
166 y[m] = &_y[m*N];
167 iy[m] = &_iy[m*N];
Jean-Marc Valinfe419832008-02-12 15:05:01 +1100168 }
169
Jean-Marc Valin41af4212007-11-30 18:35:37 +1100170 for (j=0;j<N;j++)
Jean-Marc Valin0d587d82008-02-14 21:29:50 +1100171 {
Jean-Marc Valinf675adc2008-02-28 12:15:17 +1100172 Rpp = MAC16_16(Rpp, P[j],P[j]);
173 Rxp = MAC16_16(Rxp, X[j],P[j]);
Jean-Marc Valin0d587d82008-02-14 21:29:50 +1100174 }
Jean-Marc Valinf675adc2008-02-28 12:15:17 +1100175 Rpp = ROUND(Rpp, NORM_SHIFT);
176 Rxp = ROUND(Rxp, NORM_SHIFT);
177 if (Rpp>NORM_SCALING)
Jean-Marc Valinb60340f2008-02-26 15:41:51 +1100178 celt_fatal("Rpp > 1");
179
Jean-Marc Valin0d587d82008-02-14 21:29:50 +1100180 /* We only need to initialise the zero because the first iteration only uses that */
181 for (i=0;i<N;i++)
182 y[0][i] = 0;
183 for (i=0;i<N;i++)
184 iy[0][i] = 0;
185 xy[0] = yy[0] = yp[0] = 0;
186
Jean-Marc Valin846d4e22008-02-12 13:48:48 +1100187 pulsesLeft = K;
188 while (pulsesLeft > 0)
Jean-Marc Valin41af4212007-11-30 18:35:37 +1100189 {
Jean-Marc Valin846d4e22008-02-12 13:48:48 +1100190 int pulsesAtOnce=1;
Jean-Marc Valincab576e2008-02-12 17:21:14 +1100191 int Lupdate = L;
Jean-Marc Valin41af4212007-11-30 18:35:37 +1100192 int L2 = L;
Jean-Marc Valin0d587d82008-02-14 21:29:50 +1100193
194 /* Decide on complexity strategy */
Jean-Marc Valincab576e2008-02-12 17:21:14 +1100195 pulsesAtOnce = pulsesLeft/N;
196 if (pulsesAtOnce<1)
197 pulsesAtOnce = 1;
198 if (pulsesLeft-pulsesAtOnce > 3 || N > 30)
199 Lupdate = 1;
Jean-Marc Valina85657b2008-02-20 11:59:30 +1100200 /*printf ("%d %d %d/%d %d\n", Lupdate, pulsesAtOnce, pulsesLeft, K, N);*/
Jean-Marc Valincab576e2008-02-12 17:21:14 +1100201 L2 = Lupdate;
202 if (L2>maxL)
Jean-Marc Valin41af4212007-11-30 18:35:37 +1100203 {
204 L2 = maxL;
205 maxL *= N;
206 }
Jean-Marc Valin846d4e22008-02-12 13:48:48 +1100207
Jean-Marc Valin0d587d82008-02-14 21:29:50 +1100208 for (m=0;m<Lupdate;m++)
Jean-Marc Valin4e1328b2008-02-28 15:14:07 +1100209 nbest[m]->score = -VERY_LARGE32;
Jean-Marc Valin41af4212007-11-30 18:35:37 +1100210
211 for (m=0;m<L2;m++)
212 {
213 for (j=0;j<N;j++)
214 {
Jean-Marc Valin1e7087e2007-12-04 13:05:43 +1100215 int sign;
Jean-Marc Valin0d587d82008-02-14 21:29:50 +1100216 /*if (x[j]>0) sign=1; else sign=-1;*/
Jean-Marc Valin1e7087e2007-12-04 13:05:43 +1100217 for (sign=-1;sign<=1;sign+=2)
Jean-Marc Valin41af4212007-11-30 18:35:37 +1100218 {
Jean-Marc Valina85657b2008-02-20 11:59:30 +1100219 /*fprintf (stderr, "%d/%d %d/%d %d/%d\n", i, K, m, L2, j, N);*/
Jean-Marc Valin4e1328b2008-02-28 15:14:07 +1100220 celt_word32_t Rxy, Ryy, Ryp;
221 celt_word16_t spj, aspj; /* Intermediate results */
222 celt_word32_t score;
223 celt_word32_t g;
Jean-Marc Valinc9d606f2008-02-28 13:46:20 +1100224 celt_word16_t s = SHL16(sign*pulsesAtOnce, yshift);
Jean-Marc Valinfe419832008-02-12 15:05:01 +1100225
Jean-Marc Valin9a0bba12008-02-20 14:08:50 +1100226 /* All pulses at one location must have the same sign. */
227 if (iy[m][j]*sign < 0)
228 continue;
229
Jean-Marc Valinc9d606f2008-02-28 13:46:20 +1100230 spj = MULT16_16_P14(s, P[j]);
Jean-Marc Valin642ff942008-02-28 14:33:19 +1100231 aspj = MULT16_16_P15(alpha, spj);
Jean-Marc Valina073c7b2008-02-14 16:58:04 +1100232 /* Updating the sums of the new pulse(s) */
Jean-Marc Valin4e1328b2008-02-28 15:14:07 +1100233 Rxy = xy[m] + MULT16_16(s,X[j]) - MULT16_16(MULT16_16_P15(alpha,spj),Rxp);
234 Ryy = 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]));
235 Ryp = yp[m] + MULT16_16(spj, SUB16(QCONST16(1.f,14),MULT16_16_Q15(alpha,Rpp)));
Jean-Marc Valina073c7b2008-02-14 16:58:04 +1100236
237 /* Compute the gain such that ||p + g*y|| = 1 */
Jean-Marc Valin4e1328b2008-02-28 15:14:07 +1100238 g = DIV32(SHL32(celt_sqrt(MULT16_16(ROUND(Ryp,14),ROUND(Ryp,14)) + Ryy - MULT16_16(ROUND(Ryy,14),Rpp)) - ROUND(Ryp,14),14),ROUND(Ryy,14));
239 //g *= NORM_SCALING_1;
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 Valin4e1328b2008-02-28 15:14:07 +1100242 /*score = 2.f*g*Rxy - 1.f*g*g*Ryy*NORM_SCALING_1;*/
243 score = 2*MULT16_32_Q14(ROUND(Rxy,14),g) -
244 MULT16_32_Q14(EXTRACT16(MULT16_32_Q14(ROUND(Ryy,14),g)),g);
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;
Jean-Marc Valin4e1328b2008-02-28 15:14:07 +1100265 nbest[id]->xy = Rxy;
266 nbest[id]->yy = Ryy;
267 nbest[id]->yp = Ryp;
Jean-Marc Valin1e7087e2007-12-04 13:05:43 +1100268 }
Jean-Marc Valin636f5c82008-02-12 17:40:27 +1100269 }
Jean-Marc Valin41af4212007-11-30 18:35:37 +1100270 }
Jean-Marc Valin636f5c82008-02-12 17:40:27 +1100271
Jean-Marc Valin41af4212007-11-30 18:35:37 +1100272 }
Jean-Marc Valinb60340f2008-02-26 15:41:51 +1100273
Jean-Marc Valin4e1328b2008-02-28 15:14:07 +1100274 if (!(nbest[0]->score > -VERY_LARGE32))
Jean-Marc Valinb60340f2008-02-26 15:41:51 +1100275 celt_fatal("Could not find any match in VQ codebook. Something got corrupted somewhere.");
Jean-Marc Valin0d587d82008-02-14 21:29:50 +1100276 /* Only now that we've made the final choice, update ny/iny and others */
Jean-Marc Valincab576e2008-02-12 17:21:14 +1100277 for (k=0;k<Lupdate;k++)
Jean-Marc Valin41af4212007-11-30 18:35:37 +1100278 {
Jean-Marc Valin3b277dc2008-02-14 16:46:50 +1100279 int n;
280 int is;
Jean-Marc Valin8b158f52008-02-28 14:44:19 +1100281 celt_norm_t s;
Jean-Marc Valin3b277dc2008-02-14 16:46:50 +1100282 is = nbest[k]->sign*pulsesAtOnce;
Jean-Marc Valinf675adc2008-02-28 12:15:17 +1100283 s = SHL16(is, yshift);
Jean-Marc Valin3b277dc2008-02-14 16:46:50 +1100284 for (n=0;n<N;n++)
Jean-Marc Valin8b158f52008-02-28 14:44:19 +1100285 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 +1100286 ny[k][nbest[k]->pos] += s;
Jean-Marc Valin0d587d82008-02-14 21:29:50 +1100287
Jean-Marc Valin3b277dc2008-02-14 16:46:50 +1100288 for (n=0;n<N;n++)
289 iny[k][n] = iy[nbest[k]->orig][n];
290 iny[k][nbest[k]->pos] += is;
Jean-Marc Valin0d587d82008-02-14 21:29:50 +1100291
Jean-Marc Valin3b277dc2008-02-14 16:46:50 +1100292 xy[k] = nbest[k]->xy;
293 yy[k] = nbest[k]->yy;
294 yp[k] = nbest[k]->yp;
295 }
Jean-Marc Valin0d587d82008-02-14 21:29:50 +1100296 /* Swap ny/iny with y/iy */
Jean-Marc Valin3b277dc2008-02-14 16:46:50 +1100297 for (k=0;k<Lupdate;k++)
298 {
Jean-Marc Valin8b158f52008-02-28 14:44:19 +1100299 celt_norm_t *tmp_ny;
Jean-Marc Valinfe419832008-02-12 15:05:01 +1100300 int *tmp_iny;
301
Jean-Marc Valinfe419832008-02-12 15:05:01 +1100302 tmp_ny = ny[k];
303 ny[k] = y[k];
304 y[k] = tmp_ny;
305 tmp_iny = iny[k];
306 iny[k] = iy[k];
307 iy[k] = tmp_iny;
Jean-Marc Valin41af4212007-11-30 18:35:37 +1100308 }
Jean-Marc Valin846d4e22008-02-12 13:48:48 +1100309 pulsesLeft -= pulsesAtOnce;
Jean-Marc Valin41af4212007-11-30 18:35:37 +1100310 }
311
Jean-Marc Valind4018c32008-02-27 10:09:48 +1100312#if 0
Jean-Marc Valinac1e03d2008-02-12 23:00:18 +1100313 if (0) {
314 float err=0;
315 for (i=0;i<N;i++)
Jean-Marc Valin3b277dc2008-02-14 16:46:50 +1100316 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 +1100317 /*if (N<=10)
318 printf ("%f %d %d\n", err, K, N);*/
Jean-Marc Valinac1e03d2008-02-12 23:00:18 +1100319 }
Jean-Marc Valin0d587d82008-02-14 21:29:50 +1100320 /* Sanity checks, don't bother */
Jean-Marc Valin1e7087e2007-12-04 13:05:43 +1100321 if (0) {
Jean-Marc Valind4018c32008-02-27 10:09:48 +1100322 for (i=0;i<N;i++)
323 x[i] = p[i]+nbest[0]->gain*y[0][i];
Jean-Marc Valin1e7087e2007-12-04 13:05:43 +1100324 float E=1e-15;
325 int ABS = 0;
326 for (i=0;i<N;i++)
327 ABS += abs(iy[0][i]);
Jean-Marc Valina85657b2008-02-20 11:59:30 +1100328 /*if (K != ABS)
329 printf ("%d %d\n", K, ABS);*/
Jean-Marc Valin1e7087e2007-12-04 13:05:43 +1100330 for (i=0;i<N;i++)
331 E += x[i]*x[i];
Jean-Marc Valina85657b2008-02-20 11:59:30 +1100332 /*printf ("%f\n", E);*/
Jean-Marc Valin1e7087e2007-12-04 13:05:43 +1100333 E = 1/sqrt(E);
334 for (i=0;i<N;i++)
335 x[i] *= E;
336 }
Jean-Marc Valind4018c32008-02-27 10:09:48 +1100337#endif
Jean-Marc Valin5fa59952008-02-14 13:50:44 +1100338
339 encode_pulses(iy[0], N, K, enc);
340
Jean-Marc Valina4833ff2008-01-10 15:34:00 +1100341 /* Recompute the gain in one pass to reduce the encoder-decoder mismatch
Jean-Marc Valin636f5c82008-02-12 17:40:27 +1100342 due to the recursive computation used in quantisation.
343 Not quite sure whether we need that or not */
Jean-Marc Valind17edd32008-02-27 16:52:30 +1100344 mix_pitch_and_residual(iy[0], X, N, K, P, alpha);
Jean-Marc Valin41af4212007-11-30 18:35:37 +1100345}
346
Jean-Marc Valin879fbfd2008-02-20 17:17:13 +1100347/** Decode pulse vector and combine the result with the pitch vector to produce
348 the final normalised signal in the current band. */
Jean-Marc Valin9d8d9b32008-02-27 16:17:39 +1100349void 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 +1100350{
Jean-Marc Valin9a0bba12008-02-20 14:08:50 +1100351 VARDECL(int *iy);
Jean-Marc Valin9a0bba12008-02-20 14:08:50 +1100352 ALLOC(iy, N, int);
Jean-Marc Valin5fa59952008-02-14 13:50:44 +1100353 decode_pulses(iy, N, K, dec);
Jean-Marc Valind17edd32008-02-27 16:52:30 +1100354 mix_pitch_and_residual(iy, X, N, K, P, alpha);
Jean-Marc Valin0d227d82007-12-31 16:12:12 +1100355}
356
357
358static const float pg[11] = {1.f, .75f, .65f, 0.6f, 0.6f, .6f, .55f, .55f, .5f, .5f, .5f};
359
Jean-Marc Valin5f09ea52008-02-26 16:43:04 +1100360void 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 +1100361{
362 int i,j;
363 int best=0;
Jean-Marc Valin50d11162007-12-03 14:34:52 +1100364 float best_score=0;
365 float s = 1;
Jean-Marc Valin0aa39032007-12-07 15:09:58 +1100366 int sign;
Jean-Marc Valin4841a0a2007-12-03 13:54:30 +1100367 float E;
Jean-Marc Valin9a0bba12008-02-20 14:08:50 +1100368 float pred_gain;
Jean-Marc Valin8f0f4b92008-02-11 13:52:44 +1100369 int max_pos = N0-N/B;
370 if (max_pos > 32)
371 max_pos = 32;
372
373 for (i=0;i<max_pos*B;i+=B)
Jean-Marc Valin4841a0a2007-12-03 13:54:30 +1100374 {
375 int j;
376 float xy=0, yy=0;
377 float score;
378 for (j=0;j<N;j++)
379 {
Jean-Marc Valinb4dfce42008-02-25 17:41:30 +1100380 xy += 1.f*x[j]*Y[i+N-j-1];
381 yy += 1.f*Y[i+N-j-1]*Y[i+N-j-1];
Jean-Marc Valin4841a0a2007-12-03 13:54:30 +1100382 }
Jean-Marc Valin50d11162007-12-03 14:34:52 +1100383 score = xy*xy/(.001+yy);
Jean-Marc Valin4841a0a2007-12-03 13:54:30 +1100384 if (score > best_score)
385 {
386 best_score = score;
387 best = i;
Jean-Marc Valin50d11162007-12-03 14:34:52 +1100388 if (xy>0)
389 s = 1;
390 else
391 s = -1;
Jean-Marc Valin4841a0a2007-12-03 13:54:30 +1100392 }
393 }
Jean-Marc Valin0aa39032007-12-07 15:09:58 +1100394 if (s<0)
395 sign = 1;
Jean-Marc Valin6e9058a2007-12-07 14:59:06 +1100396 else
Jean-Marc Valin0aa39032007-12-07 15:09:58 +1100397 sign = 0;
Jean-Marc Valina85657b2008-02-20 11:59:30 +1100398 /*printf ("%d %d ", sign, best);*/
Jean-Marc Valin0aa39032007-12-07 15:09:58 +1100399 ec_enc_uint(enc,sign,2);
Jean-Marc Valin8f0f4b92008-02-11 13:52:44 +1100400 ec_enc_uint(enc,best/B,max_pos);
Jean-Marc Valina85657b2008-02-20 11:59:30 +1100401 /*printf ("%d %f\n", best, best_score);*/
Jean-Marc Valin0d227d82007-12-31 16:12:12 +1100402
Jean-Marc Valin0d227d82007-12-31 16:12:12 +1100403 if (K>10)
404 pred_gain = pg[10];
405 else
406 pred_gain = pg[K];
407 E = 1e-10;
408 for (j=0;j<N;j++)
Jean-Marc Valin4841a0a2007-12-03 13:54:30 +1100409 {
Jean-Marc Valind501f612008-02-21 12:16:57 +1100410 P[j] = s*Y[best+N-j-1];
Jean-Marc Valinb4dfce42008-02-25 17:41:30 +1100411 E += NORM_SCALING_1*NORM_SCALING_1*P[j]*P[j];
Jean-Marc Valin4841a0a2007-12-03 13:54:30 +1100412 }
Jean-Marc Valin0d227d82007-12-31 16:12:12 +1100413 E = pred_gain/sqrt(E);
414 for (j=0;j<N;j++)
415 P[j] *= E;
416 if (K>0)
417 {
418 for (j=0;j<N;j++)
419 x[j] -= P[j];
420 } else {
421 for (j=0;j<N;j++)
422 x[j] = P[j];
423 }
Jean-Marc Valina85657b2008-02-20 11:59:30 +1100424 /*printf ("quant ");*/
425 /*for (j=0;j<N;j++) printf ("%f ", P[j]);*/
Jean-Marc Valin0d227d82007-12-31 16:12:12 +1100426
Jean-Marc Valin4841a0a2007-12-03 13:54:30 +1100427}
Jean-Marc Valinfc08d0a2007-12-07 13:26:15 +1100428
Jean-Marc Valin18ddc022008-02-22 14:24:50 +1100429void 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 +1100430{
Jean-Marc Valin11f01722007-12-09 01:19:36 +1100431 int j;
Jean-Marc Valin0aa39032007-12-07 15:09:58 +1100432 int sign;
433 float s;
Jean-Marc Valin6e9058a2007-12-07 14:59:06 +1100434 int best;
435 float E;
Jean-Marc Valin9a0bba12008-02-20 14:08:50 +1100436 float pred_gain;
Jean-Marc Valin8f0f4b92008-02-11 13:52:44 +1100437 int max_pos = N0-N/B;
438 if (max_pos > 32)
439 max_pos = 32;
440
Jean-Marc Valin0aa39032007-12-07 15:09:58 +1100441 sign = ec_dec_uint(dec, 2);
442 if (sign == 0)
Jean-Marc Valin6e9058a2007-12-07 14:59:06 +1100443 s = 1;
444 else
445 s = -1;
446
Jean-Marc Valin8f0f4b92008-02-11 13:52:44 +1100447 best = B*ec_dec_uint(dec, max_pos);
Jean-Marc Valina85657b2008-02-20 11:59:30 +1100448 /*printf ("%d %d ", sign, best);*/
Jean-Marc Valin6e9058a2007-12-07 14:59:06 +1100449
Jean-Marc Valin0d227d82007-12-31 16:12:12 +1100450 if (K>10)
451 pred_gain = pg[10];
452 else
453 pred_gain = pg[K];
454 E = 1e-10;
455 for (j=0;j<N;j++)
456 {
Jean-Marc Valind501f612008-02-21 12:16:57 +1100457 P[j] = s*Y[best+N-j-1];
Jean-Marc Valinb4dfce42008-02-25 17:41:30 +1100458 E += NORM_SCALING_1*NORM_SCALING_1*P[j]*P[j];
Jean-Marc Valin0d227d82007-12-31 16:12:12 +1100459 }
460 E = pred_gain/sqrt(E);
461 for (j=0;j<N;j++)
462 P[j] *= E;
Jean-Marc Valin6e9058a2007-12-07 14:59:06 +1100463 if (K==0)
464 {
Jean-Marc Valin6e9058a2007-12-07 14:59:06 +1100465 for (j=0;j<N;j++)
Jean-Marc Valin0d227d82007-12-31 16:12:12 +1100466 x[j] = P[j];
Jean-Marc Valin6e9058a2007-12-07 14:59:06 +1100467 }
468}
Jean-Marc Valin0e20ca02008-02-11 15:33:53 +1100469
Jean-Marc Valin18ddc022008-02-22 14:24:50 +1100470void 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 +1100471{
Jean-Marc Valin0df0eb42008-02-13 16:00:10 +1100472 int i, j;
Jean-Marc Valin0e20ca02008-02-11 15:33:53 +1100473 float E;
474
475 E = 1e-10;
Jean-Marc Valin0df0eb42008-02-13 16:00:10 +1100476 if (N0 >= Nmax/2)
Jean-Marc Valin0e20ca02008-02-11 15:33:53 +1100477 {
Jean-Marc Valin0df0eb42008-02-13 16:00:10 +1100478 for (i=0;i<B;i++)
479 {
480 for (j=0;j<N/B;j++)
481 {
482 P[j*B+i] = Y[(Nmax-N0-j-1)*B+i];
Jean-Marc Valinb4dfce42008-02-25 17:41:30 +1100483 E += NORM_SCALING_1*NORM_SCALING_1*P[j*B+i]*P[j*B+i];
Jean-Marc Valin0df0eb42008-02-13 16:00:10 +1100484 }
485 }
486 } else {
487 for (j=0;j<N;j++)
488 {
489 P[j] = Y[j];
Jean-Marc Valinb4dfce42008-02-25 17:41:30 +1100490 E += NORM_SCALING_1*NORM_SCALING_1*P[j]*P[j];
Jean-Marc Valin0df0eb42008-02-13 16:00:10 +1100491 }
Jean-Marc Valin0e20ca02008-02-11 15:33:53 +1100492 }
493 E = 1.f/sqrt(E);
494 for (j=0;j<N;j++)
495 P[j] *= E;
496 for (j=0;j<N;j++)
497 x[j] = P[j];
498}
499