blob: d7883967364bdfab80a020b083c92b65f196b7b6 [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 Valin8600f692008-02-29 15:14:12 +110072 SAVE_STACK;
Jean-Marc Valind17edd32008-02-27 16:52:30 +110073#ifdef FIXED_POINT
Jean-Marc Valin1ca07222008-02-27 17:23:04 +110074 int yshift = 14-EC_ILOG(K);
Jean-Marc Valind17edd32008-02-27 16:52:30 +110075#endif
76 ALLOC(y, N, celt_norm_t);
Jean-Marc Valind4018c32008-02-27 10:09:48 +110077
78 /*for (i=0;i<N;i++)
79 printf ("%d ", iy[i]);*/
Jean-Marc Valinb50c5412008-02-27 17:05:43 +110080 Rpp = 0;
Jean-Marc Valind4018c32008-02-27 10:09:48 +110081 for (i=0;i<N;i++)
Jean-Marc Valinb50c5412008-02-27 17:05:43 +110082 Rpp = MAC16_16(Rpp,P[i],P[i]);
Jean-Marc Valind4018c32008-02-27 10:09:48 +110083
Jean-Marc Valinb50c5412008-02-27 17:05:43 +110084 Ryp = 0;
Jean-Marc Valind4018c32008-02-27 10:09:48 +110085 for (i=0;i<N;i++)
Jean-Marc Valinb50c5412008-02-27 17:05:43 +110086 Ryp = MAC16_16(Ryp,SHL16(iy[i],yshift),P[i]);
Jean-Marc Valind4018c32008-02-27 10:09:48 +110087
Jean-Marc Valind17edd32008-02-27 16:52:30 +110088 /* Remove part of the pitch component to compute the real residual from
89 the encoded (int) one */
Jean-Marc Valind4018c32008-02-27 10:09:48 +110090 for (i=0;i<N;i++)
Jean-Marc Valind17edd32008-02-27 16:52:30 +110091 y[i] = SUB16(SHL16(iy[i],yshift),
Jean-Marc Valina02ca1e2008-02-28 11:33:22 +110092 MULT16_16_Q15(alpha,MULT16_16_Q14(ROUND(Ryp,14),P[i])));
Jean-Marc Valind4018c32008-02-27 10:09:48 +110093
94 /* Recompute after the projection (I think it's right) */
95 Ryp = 0;
96 for (i=0;i<N;i++)
Jean-Marc Valinb50c5412008-02-27 17:05:43 +110097 Ryp = MAC16_16(Ryp,y[i],P[i]);
Jean-Marc Valind4018c32008-02-27 10:09:48 +110098
Jean-Marc Valinb50c5412008-02-27 17:05:43 +110099 Ryy = 0;
Jean-Marc Valind4018c32008-02-27 10:09:48 +1100100 for (i=0;i<N;i++)
Jean-Marc Valinb50c5412008-02-27 17:05:43 +1100101 Ryy = MAC16_16(Ryy, y[i],y[i]);
Jean-Marc Valind4018c32008-02-27 10:09:48 +1100102
Jean-Marc Valin1ca07222008-02-27 17:23:04 +1100103 /* g = (sqrt(Ryp^2 + Ryy - Rpp*Ryy)-Ryp)/Ryy */
Jean-Marc Valina02ca1e2008-02-28 11:33:22 +1100104 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 +1100105
106 for (i=0;i<N;i++)
Jean-Marc Valina847b772008-02-27 17:46:49 +1100107 X[i] = P[i] + MULT16_32_Q14(y[i], g);
Jean-Marc Valin8600f692008-02-29 15:14:12 +1100108 RESTORE_STACK;
Jean-Marc Valind4018c32008-02-27 10:09:48 +1100109}
110
Jean-Marc Valin879fbfd2008-02-20 17:17:13 +1100111/** All the info necessary to keep track of a hypothesis during the search */
Jean-Marc Valin3b277dc2008-02-14 16:46:50 +1100112struct NBest {
Jean-Marc Valin4e1328b2008-02-28 15:14:07 +1100113 celt_word32_t score;
Jean-Marc Valin3b277dc2008-02-14 16:46:50 +1100114 int sign;
115 int pos;
116 int orig;
Jean-Marc Valin4e1328b2008-02-28 15:14:07 +1100117 celt_word32_t xy;
118 celt_word32_t yy;
119 celt_word32_t yp;
Jean-Marc Valin3b277dc2008-02-14 16:46:50 +1100120};
Jean-Marc Valin41af4212007-11-30 18:35:37 +1100121
Jean-Marc Valin9d8d9b32008-02-27 16:17:39 +1100122void 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 +1100123{
Jean-Marc Valin4a897682007-12-12 00:45:15 +1100124 int L = 3;
Jean-Marc Valin8b158f52008-02-28 14:44:19 +1100125 VARDECL(celt_norm_t *_y);
126 VARDECL(celt_norm_t *_ny);
Jean-Marc Valin9a0bba12008-02-20 14:08:50 +1100127 VARDECL(int *_iy);
128 VARDECL(int *_iny);
Jean-Marc Valin8b158f52008-02-28 14:44:19 +1100129 VARDECL(celt_norm_t **y);
130 VARDECL(celt_norm_t **ny);
Jean-Marc Valin9a0bba12008-02-20 14:08:50 +1100131 VARDECL(int **iy);
132 VARDECL(int **iny);
Jean-Marc Valin0d587d82008-02-14 21:29:50 +1100133 int i, j, k, m;
Jean-Marc Valin846d4e22008-02-12 13:48:48 +1100134 int pulsesLeft;
Jean-Marc Valined9e4232008-02-28 12:22:22 +1100135 VARDECL(celt_word32_t *xy);
136 VARDECL(celt_word32_t *yy);
137 VARDECL(celt_word32_t *yp);
Jean-Marc Valin9a0bba12008-02-20 14:08:50 +1100138 VARDECL(struct NBest *_nbest);
139 VARDECL(struct NBest **nbest);
Jean-Marc Valinf675adc2008-02-28 12:15:17 +1100140 celt_word32_t Rpp=0, Rxp=0;
Jean-Marc Valin41af4212007-11-30 18:35:37 +1100141 int maxL = 1;
Jean-Marc Valinf675adc2008-02-28 12:15:17 +1100142#ifdef FIXED_POINT
Jean-Marc Valind748cd52008-03-01 07:27:03 +1100143 int yshift;
144#endif
145 SAVE_STACK;
146
147#ifdef FIXED_POINT
148 yshift = 14-EC_ILOG(K);
Jean-Marc Valinf675adc2008-02-28 12:15:17 +1100149#endif
Jean-Marc Valin9d8d9b32008-02-27 16:17:39 +1100150
Jean-Marc Valin8b158f52008-02-28 14:44:19 +1100151 ALLOC(_y, L*N, celt_norm_t);
152 ALLOC(_ny, L*N, celt_norm_t);
Jean-Marc Valin9a0bba12008-02-20 14:08:50 +1100153 ALLOC(_iy, L*N, int);
154 ALLOC(_iny, L*N, int);
Jean-Marc Valincac91ec2008-02-29 17:03:34 +1100155 ALLOC(y, L, celt_norm_t*);
156 ALLOC(ny, L, celt_norm_t*);
157 ALLOC(iy, L, int*);
158 ALLOC(iny, L, int*);
Jean-Marc Valin9a0bba12008-02-20 14:08:50 +1100159
Jean-Marc Valined9e4232008-02-28 12:22:22 +1100160 ALLOC(xy, L, celt_word32_t);
161 ALLOC(yy, L, celt_word32_t);
162 ALLOC(yp, L, celt_word32_t);
Jean-Marc Valin9a0bba12008-02-20 14:08:50 +1100163 ALLOC(_nbest, L, struct NBest);
164 ALLOC(nbest, L, struct NBest *);
Jean-Marc Valinb4dfce42008-02-25 17:41:30 +1100165
Jean-Marc Valinfe419832008-02-12 15:05:01 +1100166 for (m=0;m<L;m++)
Jean-Marc Valin3b277dc2008-02-14 16:46:50 +1100167 nbest[m] = &_nbest[m];
168
169 for (m=0;m<L;m++)
Jean-Marc Valinfe419832008-02-12 15:05:01 +1100170 {
Jean-Marc Valin9a0bba12008-02-20 14:08:50 +1100171 ny[m] = &_ny[m*N];
172 iny[m] = &_iny[m*N];
173 y[m] = &_y[m*N];
174 iy[m] = &_iy[m*N];
Jean-Marc Valinfe419832008-02-12 15:05:01 +1100175 }
176
Jean-Marc Valin41af4212007-11-30 18:35:37 +1100177 for (j=0;j<N;j++)
Jean-Marc Valin0d587d82008-02-14 21:29:50 +1100178 {
Jean-Marc Valinf675adc2008-02-28 12:15:17 +1100179 Rpp = MAC16_16(Rpp, P[j],P[j]);
180 Rxp = MAC16_16(Rxp, X[j],P[j]);
Jean-Marc Valin0d587d82008-02-14 21:29:50 +1100181 }
Jean-Marc Valinf675adc2008-02-28 12:15:17 +1100182 Rpp = ROUND(Rpp, NORM_SHIFT);
183 Rxp = ROUND(Rxp, NORM_SHIFT);
184 if (Rpp>NORM_SCALING)
Jean-Marc Valinb60340f2008-02-26 15:41:51 +1100185 celt_fatal("Rpp > 1");
186
Jean-Marc Valin0d587d82008-02-14 21:29:50 +1100187 /* We only need to initialise the zero because the first iteration only uses that */
188 for (i=0;i<N;i++)
189 y[0][i] = 0;
190 for (i=0;i<N;i++)
191 iy[0][i] = 0;
192 xy[0] = yy[0] = yp[0] = 0;
193
Jean-Marc Valin846d4e22008-02-12 13:48:48 +1100194 pulsesLeft = K;
195 while (pulsesLeft > 0)
Jean-Marc Valin41af4212007-11-30 18:35:37 +1100196 {
Jean-Marc Valin846d4e22008-02-12 13:48:48 +1100197 int pulsesAtOnce=1;
Jean-Marc Valincab576e2008-02-12 17:21:14 +1100198 int Lupdate = L;
Jean-Marc Valin41af4212007-11-30 18:35:37 +1100199 int L2 = L;
Jean-Marc Valin0d587d82008-02-14 21:29:50 +1100200
201 /* Decide on complexity strategy */
Jean-Marc Valincab576e2008-02-12 17:21:14 +1100202 pulsesAtOnce = pulsesLeft/N;
203 if (pulsesAtOnce<1)
204 pulsesAtOnce = 1;
205 if (pulsesLeft-pulsesAtOnce > 3 || N > 30)
206 Lupdate = 1;
Jean-Marc Valina85657b2008-02-20 11:59:30 +1100207 /*printf ("%d %d %d/%d %d\n", Lupdate, pulsesAtOnce, pulsesLeft, K, N);*/
Jean-Marc Valincab576e2008-02-12 17:21:14 +1100208 L2 = Lupdate;
209 if (L2>maxL)
Jean-Marc Valin41af4212007-11-30 18:35:37 +1100210 {
211 L2 = maxL;
212 maxL *= N;
213 }
Jean-Marc Valin846d4e22008-02-12 13:48:48 +1100214
Jean-Marc Valin0d587d82008-02-14 21:29:50 +1100215 for (m=0;m<Lupdate;m++)
Jean-Marc Valin4e1328b2008-02-28 15:14:07 +1100216 nbest[m]->score = -VERY_LARGE32;
Jean-Marc Valin41af4212007-11-30 18:35:37 +1100217
218 for (m=0;m<L2;m++)
219 {
220 for (j=0;j<N;j++)
221 {
Jean-Marc Valin1e7087e2007-12-04 13:05:43 +1100222 int sign;
Jean-Marc Valin0d587d82008-02-14 21:29:50 +1100223 /*if (x[j]>0) sign=1; else sign=-1;*/
Jean-Marc Valin1e7087e2007-12-04 13:05:43 +1100224 for (sign=-1;sign<=1;sign+=2)
Jean-Marc Valin41af4212007-11-30 18:35:37 +1100225 {
Jean-Marc Valina85657b2008-02-20 11:59:30 +1100226 /*fprintf (stderr, "%d/%d %d/%d %d/%d\n", i, K, m, L2, j, N);*/
Jean-Marc Valin4e1328b2008-02-28 15:14:07 +1100227 celt_word32_t Rxy, Ryy, Ryp;
228 celt_word16_t spj, aspj; /* Intermediate results */
229 celt_word32_t score;
230 celt_word32_t g;
Jean-Marc Valinc9d606f2008-02-28 13:46:20 +1100231 celt_word16_t s = SHL16(sign*pulsesAtOnce, yshift);
Jean-Marc Valinfe419832008-02-12 15:05:01 +1100232
Jean-Marc Valin9a0bba12008-02-20 14:08:50 +1100233 /* All pulses at one location must have the same sign. */
234 if (iy[m][j]*sign < 0)
235 continue;
236
Jean-Marc Valinc9d606f2008-02-28 13:46:20 +1100237 spj = MULT16_16_P14(s, P[j]);
Jean-Marc Valin642ff942008-02-28 14:33:19 +1100238 aspj = MULT16_16_P15(alpha, spj);
Jean-Marc Valina073c7b2008-02-14 16:58:04 +1100239 /* Updating the sums of the new pulse(s) */
Jean-Marc Valin4e1328b2008-02-28 15:14:07 +1100240 Rxy = xy[m] + MULT16_16(s,X[j]) - MULT16_16(MULT16_16_P15(alpha,spj),Rxp);
241 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]));
242 Ryp = yp[m] + MULT16_16(spj, SUB16(QCONST16(1.f,14),MULT16_16_Q15(alpha,Rpp)));
Jean-Marc Valina073c7b2008-02-14 16:58:04 +1100243
244 /* Compute the gain such that ||p + g*y|| = 1 */
Jean-Marc Valin4e1328b2008-02-28 15:14:07 +1100245 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));
Jean-Marc Valin3e08a882008-03-03 13:49:20 +1100246
Jean-Marc Valina073c7b2008-02-14 16:58:04 +1100247 /* Knowing that gain, what the error: (x-g*y)^2
248 (result is negated and we discard x^2 because it's constant) */
Jean-Marc Valin4e1328b2008-02-28 15:14:07 +1100249 /*score = 2.f*g*Rxy - 1.f*g*g*Ryy*NORM_SCALING_1;*/
250 score = 2*MULT16_32_Q14(ROUND(Rxy,14),g) -
251 MULT16_32_Q14(EXTRACT16(MULT16_32_Q14(ROUND(Ryy,14),g)),g);
Jean-Marc Valin41af4212007-11-30 18:35:37 +1100252
Jean-Marc Valin3b277dc2008-02-14 16:46:50 +1100253 if (score>nbest[Lupdate-1]->score)
Jean-Marc Valin1e7087e2007-12-04 13:05:43 +1100254 {
Jean-Marc Valin472a5f02008-02-19 13:12:32 +1100255 int k;
Jean-Marc Valincab576e2008-02-12 17:21:14 +1100256 int id = Lupdate-1;
Jean-Marc Valin3b277dc2008-02-14 16:46:50 +1100257 struct NBest *tmp_best;
258
259 /* Save some pointers that would be deleted and use them for the current entry*/
260 tmp_best = nbest[Lupdate-1];
261 while (id > 0 && score > nbest[id-1]->score)
Jean-Marc Valin1e7087e2007-12-04 13:05:43 +1100262 id--;
263
Jean-Marc Valincab576e2008-02-12 17:21:14 +1100264 for (k=Lupdate-1;k>id;k--)
Jean-Marc Valin3b277dc2008-02-14 16:46:50 +1100265 nbest[k] = nbest[k-1];
Jean-Marc Valin1e7087e2007-12-04 13:05:43 +1100266
Jean-Marc Valin3b277dc2008-02-14 16:46:50 +1100267 nbest[id] = tmp_best;
268 nbest[id]->score = score;
269 nbest[id]->pos = j;
270 nbest[id]->orig = m;
271 nbest[id]->sign = sign;
Jean-Marc Valin4e1328b2008-02-28 15:14:07 +1100272 nbest[id]->xy = Rxy;
273 nbest[id]->yy = Ryy;
274 nbest[id]->yp = Ryp;
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
Jean-Marc Valin4e1328b2008-02-28 15:14:07 +1100281 if (!(nbest[0]->score > -VERY_LARGE32))
Jean-Marc Valinb60340f2008-02-26 15:41:51 +1100282 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;
Jean-Marc Valin8b158f52008-02-28 14:44:19 +1100288 celt_norm_t s;
Jean-Marc Valin3b277dc2008-02-14 16:46:50 +1100289 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 Valin8b158f52008-02-28 14:44:19 +1100292 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 +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 Valin8b158f52008-02-28 14:44:19 +1100306 celt_norm_t *tmp_ny;
Jean-Marc Valinfe419832008-02-12 15:05:01 +1100307 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) {
Jean-Marc Valin877b1972008-02-29 16:40:39 +1100321 celt_word32_t err=0;
Jean-Marc Valinac1e03d2008-02-12 23:00:18 +1100322 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 Valin877b1972008-02-29 16:40:39 +1100331 celt_word32_t E=1e-15;
Jean-Marc Valin1e7087e2007-12-04 13:05:43 +1100332 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 Valin8600f692008-02-29 15:14:12 +1100352 RESTORE_STACK;
Jean-Marc Valin41af4212007-11-30 18:35:37 +1100353}
354
Jean-Marc Valin879fbfd2008-02-20 17:17:13 +1100355/** Decode pulse vector and combine the result with the pitch vector to produce
356 the final normalised signal in the current band. */
Jean-Marc Valin9d8d9b32008-02-27 16:17:39 +1100357void 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 +1100358{
Jean-Marc Valin9a0bba12008-02-20 14:08:50 +1100359 VARDECL(int *iy);
Jean-Marc Valin8600f692008-02-29 15:14:12 +1100360 SAVE_STACK;
Jean-Marc Valin9a0bba12008-02-20 14:08:50 +1100361 ALLOC(iy, N, int);
Jean-Marc Valin5fa59952008-02-14 13:50:44 +1100362 decode_pulses(iy, N, K, dec);
Jean-Marc Valind17edd32008-02-27 16:52:30 +1100363 mix_pitch_and_residual(iy, X, N, K, P, alpha);
Jean-Marc Valin8600f692008-02-29 15:14:12 +1100364 RESTORE_STACK;
Jean-Marc Valin0d227d82007-12-31 16:12:12 +1100365}
366
367
368static const float pg[11] = {1.f, .75f, .65f, 0.6f, 0.6f, .6f, .55f, .55f, .5f, .5f, .5f};
369
Jean-Marc Valin5f09ea52008-02-26 16:43:04 +1100370void 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 +1100371{
372 int i,j;
373 int best=0;
Jean-Marc Valin877b1972008-02-29 16:40:39 +1100374 celt_word32_t best_score=0;
375 celt_word16_t s = 1;
Jean-Marc Valin0aa39032007-12-07 15:09:58 +1100376 int sign;
Jean-Marc Valin877b1972008-02-29 16:40:39 +1100377 celt_word32_t E;
Jean-Marc Valin9a0bba12008-02-20 14:08:50 +1100378 float pred_gain;
Jean-Marc Valin8f0f4b92008-02-11 13:52:44 +1100379 int max_pos = N0-N/B;
380 if (max_pos > 32)
381 max_pos = 32;
382
383 for (i=0;i<max_pos*B;i+=B)
Jean-Marc Valin4841a0a2007-12-03 13:54:30 +1100384 {
385 int j;
Jean-Marc Valin877b1972008-02-29 16:40:39 +1100386 celt_word32_t xy=0, yy=0;
Jean-Marc Valin4841a0a2007-12-03 13:54:30 +1100387 float score;
388 for (j=0;j<N;j++)
389 {
Jean-Marc Valin877b1972008-02-29 16:40:39 +1100390 xy = MAC16_16(xy, x[j], Y[i+N-j-1]);
391 yy = MAC16_16(yy, Y[i+N-j-1], Y[i+N-j-1]);
Jean-Marc Valin4841a0a2007-12-03 13:54:30 +1100392 }
Jean-Marc Valin877b1972008-02-29 16:40:39 +1100393 score = 1.f*xy*xy/(.001+yy);
Jean-Marc Valin4841a0a2007-12-03 13:54:30 +1100394 if (score > best_score)
395 {
396 best_score = score;
397 best = i;
Jean-Marc Valin50d11162007-12-03 14:34:52 +1100398 if (xy>0)
399 s = 1;
400 else
401 s = -1;
Jean-Marc Valin4841a0a2007-12-03 13:54:30 +1100402 }
403 }
Jean-Marc Valin0aa39032007-12-07 15:09:58 +1100404 if (s<0)
405 sign = 1;
Jean-Marc Valin6e9058a2007-12-07 14:59:06 +1100406 else
Jean-Marc Valin0aa39032007-12-07 15:09:58 +1100407 sign = 0;
Jean-Marc Valina85657b2008-02-20 11:59:30 +1100408 /*printf ("%d %d ", sign, best);*/
Jean-Marc Valin0aa39032007-12-07 15:09:58 +1100409 ec_enc_uint(enc,sign,2);
Jean-Marc Valin8f0f4b92008-02-11 13:52:44 +1100410 ec_enc_uint(enc,best/B,max_pos);
Jean-Marc Valina85657b2008-02-20 11:59:30 +1100411 /*printf ("%d %f\n", best, best_score);*/
Jean-Marc Valin0d227d82007-12-31 16:12:12 +1100412
Jean-Marc Valin0d227d82007-12-31 16:12:12 +1100413 if (K>10)
414 pred_gain = pg[10];
415 else
416 pred_gain = pg[K];
417 E = 1e-10;
418 for (j=0;j<N;j++)
Jean-Marc Valin4841a0a2007-12-03 13:54:30 +1100419 {
Jean-Marc Valind501f612008-02-21 12:16:57 +1100420 P[j] = s*Y[best+N-j-1];
Jean-Marc Valin877b1972008-02-29 16:40:39 +1100421 E = MAC16_16(E, P[j],P[j]);
Jean-Marc Valin4841a0a2007-12-03 13:54:30 +1100422 }
Jean-Marc Valin877b1972008-02-29 16:40:39 +1100423 pred_gain = NORM_SCALING*pred_gain/sqrt(E);
Jean-Marc Valin0d227d82007-12-31 16:12:12 +1100424 for (j=0;j<N;j++)
Jean-Marc Valin877b1972008-02-29 16:40:39 +1100425 P[j] *= pred_gain;
Jean-Marc Valin0d227d82007-12-31 16:12:12 +1100426 if (K>0)
427 {
428 for (j=0;j<N;j++)
429 x[j] -= P[j];
430 } else {
431 for (j=0;j<N;j++)
432 x[j] = P[j];
433 }
Jean-Marc Valina85657b2008-02-20 11:59:30 +1100434 /*printf ("quant ");*/
435 /*for (j=0;j<N;j++) printf ("%f ", P[j]);*/
Jean-Marc Valin0d227d82007-12-31 16:12:12 +1100436
Jean-Marc Valin4841a0a2007-12-03 13:54:30 +1100437}
Jean-Marc Valinfc08d0a2007-12-07 13:26:15 +1100438
Jean-Marc Valin18ddc022008-02-22 14:24:50 +1100439void 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 +1100440{
Jean-Marc Valin11f01722007-12-09 01:19:36 +1100441 int j;
Jean-Marc Valin0aa39032007-12-07 15:09:58 +1100442 int sign;
Jean-Marc Valin877b1972008-02-29 16:40:39 +1100443 celt_word16_t s;
Jean-Marc Valin6e9058a2007-12-07 14:59:06 +1100444 int best;
Jean-Marc Valin877b1972008-02-29 16:40:39 +1100445 celt_word32_t E;
Jean-Marc Valin9a0bba12008-02-20 14:08:50 +1100446 float pred_gain;
Jean-Marc Valin8f0f4b92008-02-11 13:52:44 +1100447 int max_pos = N0-N/B;
448 if (max_pos > 32)
449 max_pos = 32;
450
Jean-Marc Valin0aa39032007-12-07 15:09:58 +1100451 sign = ec_dec_uint(dec, 2);
452 if (sign == 0)
Jean-Marc Valin6e9058a2007-12-07 14:59:06 +1100453 s = 1;
454 else
455 s = -1;
456
Jean-Marc Valin8f0f4b92008-02-11 13:52:44 +1100457 best = B*ec_dec_uint(dec, max_pos);
Jean-Marc Valina85657b2008-02-20 11:59:30 +1100458 /*printf ("%d %d ", sign, best);*/
Jean-Marc Valin6e9058a2007-12-07 14:59:06 +1100459
Jean-Marc Valin0d227d82007-12-31 16:12:12 +1100460 if (K>10)
461 pred_gain = pg[10];
462 else
463 pred_gain = pg[K];
464 E = 1e-10;
465 for (j=0;j<N;j++)
466 {
Jean-Marc Valind501f612008-02-21 12:16:57 +1100467 P[j] = s*Y[best+N-j-1];
Jean-Marc Valin877b1972008-02-29 16:40:39 +1100468 E = MAC16_16(E, P[j],P[j]);
Jean-Marc Valin0d227d82007-12-31 16:12:12 +1100469 }
Jean-Marc Valin877b1972008-02-29 16:40:39 +1100470 pred_gain = NORM_SCALING*pred_gain/sqrt(E);
Jean-Marc Valin0d227d82007-12-31 16:12:12 +1100471 for (j=0;j<N;j++)
Jean-Marc Valin877b1972008-02-29 16:40:39 +1100472 P[j] *= pred_gain;
Jean-Marc Valin6e9058a2007-12-07 14:59:06 +1100473 if (K==0)
474 {
Jean-Marc Valin6e9058a2007-12-07 14:59:06 +1100475 for (j=0;j<N;j++)
Jean-Marc Valin0d227d82007-12-31 16:12:12 +1100476 x[j] = P[j];
Jean-Marc Valin6e9058a2007-12-07 14:59:06 +1100477 }
478}
Jean-Marc Valin0e20ca02008-02-11 15:33:53 +1100479
Jean-Marc Valin18ddc022008-02-22 14:24:50 +1100480void 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 +1100481{
Jean-Marc Valin0df0eb42008-02-13 16:00:10 +1100482 int i, j;
Jean-Marc Valin877b1972008-02-29 16:40:39 +1100483 celt_word32_t E;
484 float g;
Jean-Marc Valin0e20ca02008-02-11 15:33:53 +1100485
486 E = 1e-10;
Jean-Marc Valin0df0eb42008-02-13 16:00:10 +1100487 if (N0 >= Nmax/2)
Jean-Marc Valin0e20ca02008-02-11 15:33:53 +1100488 {
Jean-Marc Valin0df0eb42008-02-13 16:00:10 +1100489 for (i=0;i<B;i++)
490 {
491 for (j=0;j<N/B;j++)
492 {
493 P[j*B+i] = Y[(Nmax-N0-j-1)*B+i];
Jean-Marc Valin877b1972008-02-29 16:40:39 +1100494 E += P[j*B+i]*P[j*B+i];
Jean-Marc Valin0df0eb42008-02-13 16:00:10 +1100495 }
496 }
497 } else {
498 for (j=0;j<N;j++)
499 {
500 P[j] = Y[j];
Jean-Marc Valin877b1972008-02-29 16:40:39 +1100501 E = MAC16_16(E, P[j],P[j]);
Jean-Marc Valin0df0eb42008-02-13 16:00:10 +1100502 }
Jean-Marc Valin0e20ca02008-02-11 15:33:53 +1100503 }
Jean-Marc Valin877b1972008-02-29 16:40:39 +1100504 g = NORM_SCALING/sqrt(E);
Jean-Marc Valin0e20ca02008-02-11 15:33:53 +1100505 for (j=0;j<N;j++)
Jean-Marc Valin877b1972008-02-29 16:40:39 +1100506 P[j] *= g;
Jean-Marc Valin0e20ca02008-02-11 15:33:53 +1100507 for (j=0;j<N;j++)
508 x[j] = P[j];
509}
510