blob: e9a53bad6e4462b3716f984f34c6c7fefdb62822 [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 Valin3ca9b1d2008-02-27 23:50:31 +110036#include "mathops.h"
Jean-Marc Valin29ccab82007-12-06 15:39:38 +110037#include "cwrs.h"
Jean-Marc Valin9cace642007-12-06 17:44:09 +110038#include "vq.h"
Jean-Marc Valin9a0bba12008-02-20 14:08:50 +110039#include "arch.h"
Jean-Marc Valinb60340f2008-02-26 15:41:51 +110040#include "os_support.h"
Jean-Marc Valin41af4212007-11-30 18:35:37 +110041
Jean-Marc Valind4018c32008-02-27 10:09:48 +110042/** Takes the pitch vector and the decoded residual vector (non-compressed),
43 applies the compression in the pitch direction, computes the gain that will
44 give ||p+g*y||=1 and mixes the residual with the pitch. */
Jean-Marc Valin31213272008-03-03 16:52:54 +110045static void mix_pitch_and_residual(int *iy, celt_norm_t *X, int N, int K, const celt_norm_t *P, celt_word16_t alpha)
Jean-Marc Valind4018c32008-02-27 10:09:48 +110046{
47 int i;
Jean-Marc Valinb50c5412008-02-27 17:05:43 +110048 celt_word32_t Ryp, Ryy, Rpp;
Jean-Marc Valina847b772008-02-27 17:46:49 +110049 celt_word32_t g;
Jean-Marc Valin31b79d12008-03-12 17:17:23 +110050 VARDECL(celt_norm_t, y);
Jean-Marc Valind9de5932008-03-05 08:11:57 +110051#ifdef FIXED_POINT
52 int yshift;
53#endif
Jean-Marc Valin8600f692008-02-29 15:14:12 +110054 SAVE_STACK;
Jean-Marc Valind17edd32008-02-27 16:52:30 +110055#ifdef FIXED_POINT
Jean-Marc Valind9de5932008-03-05 08:11:57 +110056 yshift = 14-EC_ILOG(K);
Jean-Marc Valind17edd32008-02-27 16:52:30 +110057#endif
58 ALLOC(y, N, celt_norm_t);
Jean-Marc Valind4018c32008-02-27 10:09:48 +110059
60 /*for (i=0;i<N;i++)
61 printf ("%d ", iy[i]);*/
Jean-Marc Valinb50c5412008-02-27 17:05:43 +110062 Rpp = 0;
Jean-Marc Valind4018c32008-02-27 10:09:48 +110063 for (i=0;i<N;i++)
Jean-Marc Valinb50c5412008-02-27 17:05:43 +110064 Rpp = MAC16_16(Rpp,P[i],P[i]);
Jean-Marc Valind4018c32008-02-27 10:09:48 +110065
Jean-Marc Valinb50c5412008-02-27 17:05:43 +110066 Ryp = 0;
Jean-Marc Valind4018c32008-02-27 10:09:48 +110067 for (i=0;i<N;i++)
Jean-Marc Valinb50c5412008-02-27 17:05:43 +110068 Ryp = MAC16_16(Ryp,SHL16(iy[i],yshift),P[i]);
Jean-Marc Valind4018c32008-02-27 10:09:48 +110069
Jean-Marc Valind17edd32008-02-27 16:52:30 +110070 /* Remove part of the pitch component to compute the real residual from
71 the encoded (int) one */
Jean-Marc Valind4018c32008-02-27 10:09:48 +110072 for (i=0;i<N;i++)
Jean-Marc Valind17edd32008-02-27 16:52:30 +110073 y[i] = SUB16(SHL16(iy[i],yshift),
Jean-Marc Valinf5b05872008-03-21 10:46:17 +110074 MULT16_16_Q15(alpha,MULT16_16_Q14(ROUND16(Ryp,14),P[i])));
Jean-Marc Valind4018c32008-02-27 10:09:48 +110075
76 /* Recompute after the projection (I think it's right) */
77 Ryp = 0;
78 for (i=0;i<N;i++)
Jean-Marc Valinb50c5412008-02-27 17:05:43 +110079 Ryp = MAC16_16(Ryp,y[i],P[i]);
Jean-Marc Valind4018c32008-02-27 10:09:48 +110080
Jean-Marc Valinb50c5412008-02-27 17:05:43 +110081 Ryy = 0;
Jean-Marc Valind4018c32008-02-27 10:09:48 +110082 for (i=0;i<N;i++)
Jean-Marc Valinb50c5412008-02-27 17:05:43 +110083 Ryy = MAC16_16(Ryy, y[i],y[i]);
Jean-Marc Valind4018c32008-02-27 10:09:48 +110084
Jean-Marc Valin1ca07222008-02-27 17:23:04 +110085 /* g = (sqrt(Ryp^2 + Ryy - Rpp*Ryy)-Ryp)/Ryy */
Jean-Marc Valin9d5b4a62008-03-13 11:36:45 +110086 g = MULT16_32_Q15(
Jean-Marc Valinf5b05872008-03-21 10:46:17 +110087 celt_sqrt(MULT16_16(ROUND16(Ryp,14),ROUND16(Ryp,14)) + Ryy -
88 MULT16_16(ROUND16(Ryy,14),ROUND16(Rpp,14)))
89 - ROUND16(Ryp,14),
Jean-Marc Valin9d5b4a62008-03-13 11:36:45 +110090 celt_rcp(SHR32(Ryy,9)));
Jean-Marc Valind4018c32008-02-27 10:09:48 +110091
92 for (i=0;i<N;i++)
Jean-Marc Valinf5b05872008-03-21 10:46:17 +110093 X[i] = P[i] + ROUND16(MULT16_16(y[i], g),11);
Jean-Marc Valin8600f692008-02-29 15:14:12 +110094 RESTORE_STACK;
Jean-Marc Valind4018c32008-02-27 10:09:48 +110095}
96
Jean-Marc Valin879fbfd2008-02-20 17:17:13 +110097/** All the info necessary to keep track of a hypothesis during the search */
Jean-Marc Valin3b277dc2008-02-14 16:46:50 +110098struct NBest {
Jean-Marc Valin4e1328b2008-02-28 15:14:07 +110099 celt_word32_t score;
Jean-Marc Valin3b277dc2008-02-14 16:46:50 +1100100 int sign;
101 int pos;
102 int orig;
Jean-Marc Valin4e1328b2008-02-28 15:14:07 +1100103 celt_word32_t xy;
104 celt_word32_t yy;
105 celt_word32_t yp;
Jean-Marc Valin3b277dc2008-02-14 16:46:50 +1100106};
Jean-Marc Valin41af4212007-11-30 18:35:37 +1100107
Jean-Marc Valin31213272008-03-03 16:52:54 +1100108void alg_quant(celt_norm_t *X, celt_mask_t *W, int N, int K, const celt_norm_t *P, celt_word16_t alpha, ec_enc *enc)
Jean-Marc Valin41af4212007-11-30 18:35:37 +1100109{
Jean-Marc Valin4a897682007-12-12 00:45:15 +1100110 int L = 3;
Jean-Marc Valin31b79d12008-03-12 17:17:23 +1100111 VARDECL(celt_norm_t, _y);
112 VARDECL(celt_norm_t, _ny);
113 VARDECL(int, _iy);
114 VARDECL(int, _iny);
115 VARDECL(celt_norm_t *, y);
116 VARDECL(celt_norm_t *, ny);
117 VARDECL(int *, iy);
118 VARDECL(int *, iny);
Jean-Marc Valin0d587d82008-02-14 21:29:50 +1100119 int i, j, k, m;
Jean-Marc Valin846d4e22008-02-12 13:48:48 +1100120 int pulsesLeft;
Jean-Marc Valin31b79d12008-03-12 17:17:23 +1100121 VARDECL(celt_word32_t, xy);
122 VARDECL(celt_word32_t, yy);
123 VARDECL(celt_word32_t, yp);
124 VARDECL(struct NBest, _nbest);
125 VARDECL(struct NBest *, nbest);
Jean-Marc Valinf675adc2008-02-28 12:15:17 +1100126 celt_word32_t Rpp=0, Rxp=0;
Jean-Marc Valin41af4212007-11-30 18:35:37 +1100127 int maxL = 1;
Jean-Marc Valinf675adc2008-02-28 12:15:17 +1100128#ifdef FIXED_POINT
Jean-Marc Valind748cd52008-03-01 07:27:03 +1100129 int yshift;
130#endif
131 SAVE_STACK;
132
133#ifdef FIXED_POINT
134 yshift = 14-EC_ILOG(K);
Jean-Marc Valinf675adc2008-02-28 12:15:17 +1100135#endif
Jean-Marc Valin9d8d9b32008-02-27 16:17:39 +1100136
Jean-Marc Valin8b158f52008-02-28 14:44:19 +1100137 ALLOC(_y, L*N, celt_norm_t);
138 ALLOC(_ny, L*N, celt_norm_t);
Jean-Marc Valin9a0bba12008-02-20 14:08:50 +1100139 ALLOC(_iy, L*N, int);
140 ALLOC(_iny, L*N, int);
Jean-Marc Valincac91ec2008-02-29 17:03:34 +1100141 ALLOC(y, L, celt_norm_t*);
142 ALLOC(ny, L, celt_norm_t*);
143 ALLOC(iy, L, int*);
144 ALLOC(iny, L, int*);
Jean-Marc Valin9a0bba12008-02-20 14:08:50 +1100145
Jean-Marc Valined9e4232008-02-28 12:22:22 +1100146 ALLOC(xy, L, celt_word32_t);
147 ALLOC(yy, L, celt_word32_t);
148 ALLOC(yp, L, celt_word32_t);
Jean-Marc Valin9a0bba12008-02-20 14:08:50 +1100149 ALLOC(_nbest, L, struct NBest);
150 ALLOC(nbest, L, struct NBest *);
Jean-Marc Valinb4dfce42008-02-25 17:41:30 +1100151
Jean-Marc Valinfe419832008-02-12 15:05:01 +1100152 for (m=0;m<L;m++)
Jean-Marc Valin3b277dc2008-02-14 16:46:50 +1100153 nbest[m] = &_nbest[m];
154
155 for (m=0;m<L;m++)
Jean-Marc Valinfe419832008-02-12 15:05:01 +1100156 {
Jean-Marc Valin9a0bba12008-02-20 14:08:50 +1100157 ny[m] = &_ny[m*N];
158 iny[m] = &_iny[m*N];
159 y[m] = &_y[m*N];
160 iy[m] = &_iy[m*N];
Jean-Marc Valinfe419832008-02-12 15:05:01 +1100161 }
162
Jean-Marc Valin41af4212007-11-30 18:35:37 +1100163 for (j=0;j<N;j++)
Jean-Marc Valin0d587d82008-02-14 21:29:50 +1100164 {
Jean-Marc Valinf675adc2008-02-28 12:15:17 +1100165 Rpp = MAC16_16(Rpp, P[j],P[j]);
166 Rxp = MAC16_16(Rxp, X[j],P[j]);
Jean-Marc Valin0d587d82008-02-14 21:29:50 +1100167 }
Jean-Marc Valinf5b05872008-03-21 10:46:17 +1100168 Rpp = ROUND16(Rpp, NORM_SHIFT);
169 Rxp = ROUND16(Rxp, NORM_SHIFT);
Jean-Marc Valin4ff068e2008-03-15 23:34:39 +1100170 celt_assert2(Rpp<=NORM_SCALING, "Rpp should never have a norm greater than unity");
Jean-Marc Valinb60340f2008-02-26 15:41:51 +1100171
Jean-Marc Valin0d587d82008-02-14 21:29:50 +1100172 /* We only need to initialise the zero because the first iteration only uses that */
173 for (i=0;i<N;i++)
174 y[0][i] = 0;
175 for (i=0;i<N;i++)
176 iy[0][i] = 0;
177 xy[0] = yy[0] = yp[0] = 0;
178
Jean-Marc Valin846d4e22008-02-12 13:48:48 +1100179 pulsesLeft = K;
180 while (pulsesLeft > 0)
Jean-Marc Valin41af4212007-11-30 18:35:37 +1100181 {
Jean-Marc Valin846d4e22008-02-12 13:48:48 +1100182 int pulsesAtOnce=1;
Jean-Marc Valincab576e2008-02-12 17:21:14 +1100183 int Lupdate = L;
Jean-Marc Valin41af4212007-11-30 18:35:37 +1100184 int L2 = L;
Jean-Marc Valin0d587d82008-02-14 21:29:50 +1100185
186 /* Decide on complexity strategy */
Jean-Marc Valincab576e2008-02-12 17:21:14 +1100187 pulsesAtOnce = pulsesLeft/N;
188 if (pulsesAtOnce<1)
189 pulsesAtOnce = 1;
190 if (pulsesLeft-pulsesAtOnce > 3 || N > 30)
191 Lupdate = 1;
Jean-Marc Valina85657b2008-02-20 11:59:30 +1100192 /*printf ("%d %d %d/%d %d\n", Lupdate, pulsesAtOnce, pulsesLeft, K, N);*/
Jean-Marc Valincab576e2008-02-12 17:21:14 +1100193 L2 = Lupdate;
194 if (L2>maxL)
Jean-Marc Valin41af4212007-11-30 18:35:37 +1100195 {
196 L2 = maxL;
197 maxL *= N;
198 }
Jean-Marc Valin846d4e22008-02-12 13:48:48 +1100199
Jean-Marc Valin0d587d82008-02-14 21:29:50 +1100200 for (m=0;m<Lupdate;m++)
Jean-Marc Valin4e1328b2008-02-28 15:14:07 +1100201 nbest[m]->score = -VERY_LARGE32;
Jean-Marc Valin41af4212007-11-30 18:35:37 +1100202
203 for (m=0;m<L2;m++)
204 {
205 for (j=0;j<N;j++)
206 {
Jean-Marc Valin1e7087e2007-12-04 13:05:43 +1100207 int sign;
Jean-Marc Valin0d587d82008-02-14 21:29:50 +1100208 /*if (x[j]>0) sign=1; else sign=-1;*/
Jean-Marc Valin1e7087e2007-12-04 13:05:43 +1100209 for (sign=-1;sign<=1;sign+=2)
Jean-Marc Valin41af4212007-11-30 18:35:37 +1100210 {
Jean-Marc Valina85657b2008-02-20 11:59:30 +1100211 /*fprintf (stderr, "%d/%d %d/%d %d/%d\n", i, K, m, L2, j, N);*/
Jean-Marc Valin4e1328b2008-02-28 15:14:07 +1100212 celt_word32_t Rxy, Ryy, Ryp;
213 celt_word16_t spj, aspj; /* Intermediate results */
214 celt_word32_t score;
215 celt_word32_t g;
Jean-Marc Valinc9d606f2008-02-28 13:46:20 +1100216 celt_word16_t s = SHL16(sign*pulsesAtOnce, yshift);
Jean-Marc Valinfe419832008-02-12 15:05:01 +1100217
Jean-Marc Valin9a0bba12008-02-20 14:08:50 +1100218 /* All pulses at one location must have the same sign. */
219 if (iy[m][j]*sign < 0)
220 continue;
221
Jean-Marc Valin19ae9fc2008-03-13 11:18:15 +1100222 spj = MULT16_16_Q14(s, P[j]);
223 aspj = MULT16_16_Q15(alpha, spj);
Jean-Marc Valina073c7b2008-02-14 16:58:04 +1100224 /* Updating the sums of the new pulse(s) */
Jean-Marc Valin19ae9fc2008-03-13 11:18:15 +1100225 Rxy = xy[m] + MULT16_16(s,X[j]) - MULT16_16(MULT16_16_Q15(alpha,spj),Rxp);
Jean-Marc Valin4e1328b2008-02-28 15:14:07 +1100226 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]));
227 Ryp = yp[m] + MULT16_16(spj, SUB16(QCONST16(1.f,14),MULT16_16_Q15(alpha,Rpp)));
Jean-Marc Valina073c7b2008-02-14 16:58:04 +1100228
229 /* Compute the gain such that ||p + g*y|| = 1 */
Jean-Marc Valin19ae9fc2008-03-13 11:18:15 +1100230 g = MULT16_32_Q15(
Jean-Marc Valinf5b05872008-03-21 10:46:17 +1100231 celt_sqrt(MULT16_16(ROUND16(Ryp,14),ROUND16(Ryp,14)) + Ryy -
232 MULT16_16(ROUND16(Ryy,14),Rpp))
233 - ROUND16(Ryp,14),
Jean-Marc Valin19ae9fc2008-03-13 11:18:15 +1100234 celt_rcp(SHR32(Ryy,12)));
Jean-Marc Valind857ac42008-03-12 13:26:37 +1100235 /* Knowing that gain, what's the error: (x-g*y)^2
Jean-Marc Valina073c7b2008-02-14 16:58:04 +1100236 (result is negated and we discard x^2 because it's constant) */
Jean-Marc Valin4e1328b2008-02-28 15:14:07 +1100237 /*score = 2.f*g*Rxy - 1.f*g*g*Ryy*NORM_SCALING_1;*/
Jean-Marc Valinf5b05872008-03-21 10:46:17 +1100238 score = 2*MULT16_32_Q14(ROUND16(Rxy,14),g)
239 - MULT16_32_Q14(EXTRACT16(MULT16_32_Q14(ROUND16(Ryy,14),g)),g);
Jean-Marc Valin41af4212007-11-30 18:35:37 +1100240
Jean-Marc Valin3b277dc2008-02-14 16:46:50 +1100241 if (score>nbest[Lupdate-1]->score)
Jean-Marc Valin1e7087e2007-12-04 13:05:43 +1100242 {
Jean-Marc Valincab576e2008-02-12 17:21:14 +1100243 int id = Lupdate-1;
Jean-Marc Valin3b277dc2008-02-14 16:46:50 +1100244 struct NBest *tmp_best;
245
246 /* Save some pointers that would be deleted and use them for the current entry*/
247 tmp_best = nbest[Lupdate-1];
248 while (id > 0 && score > nbest[id-1]->score)
Jean-Marc Valin1e7087e2007-12-04 13:05:43 +1100249 id--;
250
Jean-Marc Valincab576e2008-02-12 17:21:14 +1100251 for (k=Lupdate-1;k>id;k--)
Jean-Marc Valin3b277dc2008-02-14 16:46:50 +1100252 nbest[k] = nbest[k-1];
Jean-Marc Valin1e7087e2007-12-04 13:05:43 +1100253
Jean-Marc Valin3b277dc2008-02-14 16:46:50 +1100254 nbest[id] = tmp_best;
255 nbest[id]->score = score;
256 nbest[id]->pos = j;
257 nbest[id]->orig = m;
258 nbest[id]->sign = sign;
Jean-Marc Valin4e1328b2008-02-28 15:14:07 +1100259 nbest[id]->xy = Rxy;
260 nbest[id]->yy = Ryy;
261 nbest[id]->yp = Ryp;
Jean-Marc Valin1e7087e2007-12-04 13:05:43 +1100262 }
Jean-Marc Valin636f5c82008-02-12 17:40:27 +1100263 }
Jean-Marc Valin41af4212007-11-30 18:35:37 +1100264 }
Jean-Marc Valin636f5c82008-02-12 17:40:27 +1100265
Jean-Marc Valin41af4212007-11-30 18:35:37 +1100266 }
Jean-Marc Valinb60340f2008-02-26 15:41:51 +1100267
Jean-Marc Valin4ff068e2008-03-15 23:34:39 +1100268 celt_assert2(nbest[0]->score > -VERY_LARGE32, "Could not find any match in VQ codebook. Something got corrupted somewhere.");
Jean-Marc Valin0d587d82008-02-14 21:29:50 +1100269 /* Only now that we've made the final choice, update ny/iny and others */
Jean-Marc Valincab576e2008-02-12 17:21:14 +1100270 for (k=0;k<Lupdate;k++)
Jean-Marc Valin41af4212007-11-30 18:35:37 +1100271 {
Jean-Marc Valin3b277dc2008-02-14 16:46:50 +1100272 int n;
273 int is;
Jean-Marc Valin8b158f52008-02-28 14:44:19 +1100274 celt_norm_t s;
Jean-Marc Valin3b277dc2008-02-14 16:46:50 +1100275 is = nbest[k]->sign*pulsesAtOnce;
Jean-Marc Valinf675adc2008-02-28 12:15:17 +1100276 s = SHL16(is, yshift);
Jean-Marc Valin3b277dc2008-02-14 16:46:50 +1100277 for (n=0;n<N;n++)
Jean-Marc Valin8b158f52008-02-28 14:44:19 +1100278 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 +1100279 ny[k][nbest[k]->pos] += s;
Jean-Marc Valin0d587d82008-02-14 21:29:50 +1100280
Jean-Marc Valin3b277dc2008-02-14 16:46:50 +1100281 for (n=0;n<N;n++)
282 iny[k][n] = iy[nbest[k]->orig][n];
283 iny[k][nbest[k]->pos] += is;
Jean-Marc Valin0d587d82008-02-14 21:29:50 +1100284
Jean-Marc Valin3b277dc2008-02-14 16:46:50 +1100285 xy[k] = nbest[k]->xy;
286 yy[k] = nbest[k]->yy;
287 yp[k] = nbest[k]->yp;
288 }
Jean-Marc Valin0d587d82008-02-14 21:29:50 +1100289 /* Swap ny/iny with y/iy */
Jean-Marc Valin3b277dc2008-02-14 16:46:50 +1100290 for (k=0;k<Lupdate;k++)
291 {
Jean-Marc Valin8b158f52008-02-28 14:44:19 +1100292 celt_norm_t *tmp_ny;
Jean-Marc Valinfe419832008-02-12 15:05:01 +1100293 int *tmp_iny;
294
Jean-Marc Valinfe419832008-02-12 15:05:01 +1100295 tmp_ny = ny[k];
296 ny[k] = y[k];
297 y[k] = tmp_ny;
298 tmp_iny = iny[k];
299 iny[k] = iy[k];
300 iy[k] = tmp_iny;
Jean-Marc Valin41af4212007-11-30 18:35:37 +1100301 }
Jean-Marc Valin846d4e22008-02-12 13:48:48 +1100302 pulsesLeft -= pulsesAtOnce;
Jean-Marc Valin41af4212007-11-30 18:35:37 +1100303 }
304
Jean-Marc Valind4018c32008-02-27 10:09:48 +1100305#if 0
Jean-Marc Valinac1e03d2008-02-12 23:00:18 +1100306 if (0) {
Jean-Marc Valin877b1972008-02-29 16:40:39 +1100307 celt_word32_t err=0;
Jean-Marc Valinac1e03d2008-02-12 23:00:18 +1100308 for (i=0;i<N;i++)
Jean-Marc Valin3b277dc2008-02-14 16:46:50 +1100309 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 +1100310 /*if (N<=10)
311 printf ("%f %d %d\n", err, K, N);*/
Jean-Marc Valinac1e03d2008-02-12 23:00:18 +1100312 }
Jean-Marc Valin0d587d82008-02-14 21:29:50 +1100313 /* Sanity checks, don't bother */
Jean-Marc Valin1e7087e2007-12-04 13:05:43 +1100314 if (0) {
Jean-Marc Valind4018c32008-02-27 10:09:48 +1100315 for (i=0;i<N;i++)
316 x[i] = p[i]+nbest[0]->gain*y[0][i];
Jean-Marc Valin877b1972008-02-29 16:40:39 +1100317 celt_word32_t E=1e-15;
Jean-Marc Valin1e7087e2007-12-04 13:05:43 +1100318 int ABS = 0;
319 for (i=0;i<N;i++)
320 ABS += abs(iy[0][i]);
Jean-Marc Valina85657b2008-02-20 11:59:30 +1100321 /*if (K != ABS)
322 printf ("%d %d\n", K, ABS);*/
Jean-Marc Valin1e7087e2007-12-04 13:05:43 +1100323 for (i=0;i<N;i++)
324 E += x[i]*x[i];
Jean-Marc Valina85657b2008-02-20 11:59:30 +1100325 /*printf ("%f\n", E);*/
Jean-Marc Valin1e7087e2007-12-04 13:05:43 +1100326 E = 1/sqrt(E);
327 for (i=0;i<N;i++)
328 x[i] *= E;
329 }
Jean-Marc Valind4018c32008-02-27 10:09:48 +1100330#endif
Jean-Marc Valin5fa59952008-02-14 13:50:44 +1100331
332 encode_pulses(iy[0], N, K, enc);
333
Jean-Marc Valina4833ff2008-01-10 15:34:00 +1100334 /* Recompute the gain in one pass to reduce the encoder-decoder mismatch
Jean-Marc Valin636f5c82008-02-12 17:40:27 +1100335 due to the recursive computation used in quantisation.
336 Not quite sure whether we need that or not */
Jean-Marc Valind17edd32008-02-27 16:52:30 +1100337 mix_pitch_and_residual(iy[0], X, N, K, P, alpha);
Jean-Marc Valin8600f692008-02-29 15:14:12 +1100338 RESTORE_STACK;
Jean-Marc Valin41af4212007-11-30 18:35:37 +1100339}
340
Jean-Marc Valin879fbfd2008-02-20 17:17:13 +1100341/** Decode pulse vector and combine the result with the pitch vector to produce
342 the final normalised signal in the current band. */
Jean-Marc Valin9d8d9b32008-02-27 16:17:39 +1100343void 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 +1100344{
Jean-Marc Valin31b79d12008-03-12 17:17:23 +1100345 VARDECL(int, iy);
Jean-Marc Valin8600f692008-02-29 15:14:12 +1100346 SAVE_STACK;
Jean-Marc Valin9a0bba12008-02-20 14:08:50 +1100347 ALLOC(iy, N, int);
Jean-Marc Valin5fa59952008-02-14 13:50:44 +1100348 decode_pulses(iy, N, K, dec);
Jean-Marc Valind17edd32008-02-27 16:52:30 +1100349 mix_pitch_and_residual(iy, X, N, K, P, alpha);
Jean-Marc Valin8600f692008-02-29 15:14:12 +1100350 RESTORE_STACK;
Jean-Marc Valin0d227d82007-12-31 16:12:12 +1100351}
352
Jean-Marc Valin9455d1b2008-03-07 17:17:37 +1100353#ifdef FIXED_POINT
354static const celt_word16_t pg[11] = {32767, 24576, 21299, 19661, 19661, 19661, 18022, 18022, 16384, 16384, 16384};
355#else
Jean-Marc Valin3e650972008-03-07 17:38:58 +1100356static const celt_word16_t pg[11] = {1.f, .75f, .65f, 0.6f, 0.6f, .6f, .55f, .55f, .5f, .5f, .5f};
Jean-Marc Valin9455d1b2008-03-07 17:17:37 +1100357#endif
Jean-Marc Valin0d227d82007-12-31 16:12:12 +1100358
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 Valin877b1972008-02-29 16:40:39 +1100363 celt_word32_t best_score=0;
364 celt_word16_t s = 1;
Jean-Marc Valin0aa39032007-12-07 15:09:58 +1100365 int sign;
Jean-Marc Valin877b1972008-02-29 16:40:39 +1100366 celt_word32_t E;
Jean-Marc Valin9455d1b2008-03-07 17:17:37 +1100367 celt_word16_t 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 {
Jean-Marc Valin877b1972008-02-29 16:40:39 +1100374 celt_word32_t xy=0, yy=0;
Jean-Marc Valin03892c12008-03-07 17:25:47 +1100375 celt_word32_t score;
Jean-Marc Valin4841a0a2007-12-03 13:54:30 +1100376 for (j=0;j<N;j++)
377 {
Jean-Marc Valin877b1972008-02-29 16:40:39 +1100378 xy = MAC16_16(xy, x[j], Y[i+N-j-1]);
379 yy = MAC16_16(yy, Y[i+N-j-1], Y[i+N-j-1]);
Jean-Marc Valin4841a0a2007-12-03 13:54:30 +1100380 }
Jean-Marc Valin22823832008-03-22 21:17:45 +1100381 score = celt_div(MULT16_16(ROUND16(xy,14),ROUND16(xy,14)), ROUND16(yy,14));
Jean-Marc Valin4841a0a2007-12-03 13:54:30 +1100382 if (score > best_score)
383 {
384 best_score = score;
385 best = i;
Jean-Marc Valin50d11162007-12-03 14:34:52 +1100386 if (xy>0)
387 s = 1;
388 else
389 s = -1;
Jean-Marc Valin4841a0a2007-12-03 13:54:30 +1100390 }
391 }
Jean-Marc Valin0aa39032007-12-07 15:09:58 +1100392 if (s<0)
393 sign = 1;
Jean-Marc Valin6e9058a2007-12-07 14:59:06 +1100394 else
Jean-Marc Valin0aa39032007-12-07 15:09:58 +1100395 sign = 0;
Jean-Marc Valina85657b2008-02-20 11:59:30 +1100396 /*printf ("%d %d ", sign, best);*/
Jean-Marc Valin0aa39032007-12-07 15:09:58 +1100397 ec_enc_uint(enc,sign,2);
Jean-Marc Valin8f0f4b92008-02-11 13:52:44 +1100398 ec_enc_uint(enc,best/B,max_pos);
Jean-Marc Valina85657b2008-02-20 11:59:30 +1100399 /*printf ("%d %f\n", best, best_score);*/
Jean-Marc Valin0d227d82007-12-31 16:12:12 +1100400
Jean-Marc Valin0d227d82007-12-31 16:12:12 +1100401 if (K>10)
402 pred_gain = pg[10];
403 else
404 pred_gain = pg[K];
Jean-Marc Valin03892c12008-03-07 17:25:47 +1100405 E = EPSILON;
Jean-Marc Valin0d227d82007-12-31 16:12:12 +1100406 for (j=0;j<N;j++)
Jean-Marc Valin4841a0a2007-12-03 13:54:30 +1100407 {
Jean-Marc Valind501f612008-02-21 12:16:57 +1100408 P[j] = s*Y[best+N-j-1];
Jean-Marc Valin877b1972008-02-29 16:40:39 +1100409 E = MAC16_16(E, P[j],P[j]);
Jean-Marc Valin4841a0a2007-12-03 13:54:30 +1100410 }
Jean-Marc Valin9455d1b2008-03-07 17:17:37 +1100411 /*pred_gain = pred_gain/sqrt(E);*/
412 pred_gain = MULT16_16_Q15(pred_gain,DIV32_16(SHL32(EXTEND32(1),14+8),celt_sqrt(E)));
Jean-Marc Valin0d227d82007-12-31 16:12:12 +1100413 for (j=0;j<N;j++)
Jean-Marc Valin9455d1b2008-03-07 17:17:37 +1100414 P[j] = PSHR32(MULT16_16(pred_gain, P[j]),8);
Jean-Marc Valin0d227d82007-12-31 16:12:12 +1100415 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;
Jean-Marc Valin877b1972008-02-29 16:40:39 +1100432 celt_word16_t s;
Jean-Marc Valin6e9058a2007-12-07 14:59:06 +1100433 int best;
Jean-Marc Valin877b1972008-02-29 16:40:39 +1100434 celt_word32_t E;
Jean-Marc Valin9455d1b2008-03-07 17:17:37 +1100435 celt_word16_t 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];
Jean-Marc Valin9455d1b2008-03-07 17:17:37 +1100453 E = EPSILON;
Jean-Marc Valin0d227d82007-12-31 16:12:12 +1100454 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 Valin877b1972008-02-29 16:40:39 +1100457 E = MAC16_16(E, P[j],P[j]);
Jean-Marc Valin0d227d82007-12-31 16:12:12 +1100458 }
Jean-Marc Valin9455d1b2008-03-07 17:17:37 +1100459 /*pred_gain = pred_gain/sqrt(E);*/
460 pred_gain = MULT16_16_Q15(pred_gain,DIV32_16(SHL32(EXTEND32(1),14+8),celt_sqrt(E)));
Jean-Marc Valin0d227d82007-12-31 16:12:12 +1100461 for (j=0;j<N;j++)
Jean-Marc Valin9455d1b2008-03-07 17:17:37 +1100462 P[j] = PSHR32(MULT16_16(pred_gain, P[j]),8);
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 Valin877b1972008-02-29 16:40:39 +1100473 celt_word32_t E;
Jean-Marc Valinec9b6df2008-03-07 17:05:47 +1100474 celt_word16_t g;
Jean-Marc Valin0e20ca02008-02-11 15:33:53 +1100475
Jean-Marc Valinec9b6df2008-03-07 17:05:47 +1100476 E = EPSILON;
Jean-Marc Valina536f772008-03-22 09:01:50 +1100477 if (N0 >= (Nmax>>1))
Jean-Marc Valin0e20ca02008-02-11 15:33:53 +1100478 {
Jean-Marc Valin0df0eb42008-02-13 16:00:10 +1100479 for (i=0;i<B;i++)
480 {
481 for (j=0;j<N/B;j++)
482 {
483 P[j*B+i] = Y[(Nmax-N0-j-1)*B+i];
Jean-Marc Valin877b1972008-02-29 16:40:39 +1100484 E += P[j*B+i]*P[j*B+i];
Jean-Marc Valin0df0eb42008-02-13 16:00:10 +1100485 }
486 }
487 } else {
488 for (j=0;j<N;j++)
489 {
490 P[j] = Y[j];
Jean-Marc Valin877b1972008-02-29 16:40:39 +1100491 E = MAC16_16(E, P[j],P[j]);
Jean-Marc Valin0df0eb42008-02-13 16:00:10 +1100492 }
Jean-Marc Valin0e20ca02008-02-11 15:33:53 +1100493 }
Jean-Marc Valinec9b6df2008-03-07 17:05:47 +1100494 g = DIV32_16(SHL32(EXTEND32(1),14+8),celt_sqrt(E));
Jean-Marc Valin0e20ca02008-02-11 15:33:53 +1100495 for (j=0;j<N;j++)
Jean-Marc Valinec9b6df2008-03-07 17:05:47 +1100496 P[j] = PSHR32(MULT16_16(g, P[j]),8);
Jean-Marc Valin0e20ca02008-02-11 15:33:53 +1100497 for (j=0;j<N;j++)
498 x[j] = P[j];
499}
500