blob: 440da81cc3cdf450faca77b7d6119dd211c411cb [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 Valina02ca1e2008-02-28 11:33:22 +110074 MULT16_16_Q15(alpha,MULT16_16_Q14(ROUND(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(
87 celt_sqrt(MULT16_16(ROUND(Ryp,14),ROUND(Ryp,14)) + Ryy -
88 MULT16_16(ROUND(Ryy,14),ROUND(Rpp,14)))
89 - ROUND(Ryp,14),
90 celt_rcp(SHR32(Ryy,9)));
Jean-Marc Valind4018c32008-02-27 10:09:48 +110091
92 for (i=0;i<N;i++)
Jean-Marc Valin9d5b4a62008-03-13 11:36:45 +110093 X[i] = P[i] + ROUND(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 Valinf675adc2008-02-28 12:15:17 +1100168 Rpp = ROUND(Rpp, NORM_SHIFT);
169 Rxp = ROUND(Rxp, NORM_SHIFT);
170 if (Rpp>NORM_SCALING)
Jean-Marc Valinb60340f2008-02-26 15:41:51 +1100171 celt_fatal("Rpp > 1");
172
Jean-Marc Valin0d587d82008-02-14 21:29:50 +1100173 /* We only need to initialise the zero because the first iteration only uses that */
174 for (i=0;i<N;i++)
175 y[0][i] = 0;
176 for (i=0;i<N;i++)
177 iy[0][i] = 0;
178 xy[0] = yy[0] = yp[0] = 0;
179
Jean-Marc Valin846d4e22008-02-12 13:48:48 +1100180 pulsesLeft = K;
181 while (pulsesLeft > 0)
Jean-Marc Valin41af4212007-11-30 18:35:37 +1100182 {
Jean-Marc Valin846d4e22008-02-12 13:48:48 +1100183 int pulsesAtOnce=1;
Jean-Marc Valincab576e2008-02-12 17:21:14 +1100184 int Lupdate = L;
Jean-Marc Valin41af4212007-11-30 18:35:37 +1100185 int L2 = L;
Jean-Marc Valin0d587d82008-02-14 21:29:50 +1100186
187 /* Decide on complexity strategy */
Jean-Marc Valincab576e2008-02-12 17:21:14 +1100188 pulsesAtOnce = pulsesLeft/N;
189 if (pulsesAtOnce<1)
190 pulsesAtOnce = 1;
191 if (pulsesLeft-pulsesAtOnce > 3 || N > 30)
192 Lupdate = 1;
Jean-Marc Valina85657b2008-02-20 11:59:30 +1100193 /*printf ("%d %d %d/%d %d\n", Lupdate, pulsesAtOnce, pulsesLeft, K, N);*/
Jean-Marc Valincab576e2008-02-12 17:21:14 +1100194 L2 = Lupdate;
195 if (L2>maxL)
Jean-Marc Valin41af4212007-11-30 18:35:37 +1100196 {
197 L2 = maxL;
198 maxL *= N;
199 }
Jean-Marc Valin846d4e22008-02-12 13:48:48 +1100200
Jean-Marc Valin0d587d82008-02-14 21:29:50 +1100201 for (m=0;m<Lupdate;m++)
Jean-Marc Valin4e1328b2008-02-28 15:14:07 +1100202 nbest[m]->score = -VERY_LARGE32;
Jean-Marc Valin41af4212007-11-30 18:35:37 +1100203
204 for (m=0;m<L2;m++)
205 {
206 for (j=0;j<N;j++)
207 {
Jean-Marc Valin1e7087e2007-12-04 13:05:43 +1100208 int sign;
Jean-Marc Valin0d587d82008-02-14 21:29:50 +1100209 /*if (x[j]>0) sign=1; else sign=-1;*/
Jean-Marc Valin1e7087e2007-12-04 13:05:43 +1100210 for (sign=-1;sign<=1;sign+=2)
Jean-Marc Valin41af4212007-11-30 18:35:37 +1100211 {
Jean-Marc Valina85657b2008-02-20 11:59:30 +1100212 /*fprintf (stderr, "%d/%d %d/%d %d/%d\n", i, K, m, L2, j, N);*/
Jean-Marc Valin4e1328b2008-02-28 15:14:07 +1100213 celt_word32_t Rxy, Ryy, Ryp;
214 celt_word16_t spj, aspj; /* Intermediate results */
215 celt_word32_t score;
216 celt_word32_t g;
Jean-Marc Valinc9d606f2008-02-28 13:46:20 +1100217 celt_word16_t s = SHL16(sign*pulsesAtOnce, yshift);
Jean-Marc Valinfe419832008-02-12 15:05:01 +1100218
Jean-Marc Valin9a0bba12008-02-20 14:08:50 +1100219 /* All pulses at one location must have the same sign. */
220 if (iy[m][j]*sign < 0)
221 continue;
222
Jean-Marc Valin19ae9fc2008-03-13 11:18:15 +1100223 spj = MULT16_16_Q14(s, P[j]);
224 aspj = MULT16_16_Q15(alpha, spj);
Jean-Marc Valina073c7b2008-02-14 16:58:04 +1100225 /* Updating the sums of the new pulse(s) */
Jean-Marc Valin19ae9fc2008-03-13 11:18:15 +1100226 Rxy = xy[m] + MULT16_16(s,X[j]) - MULT16_16(MULT16_16_Q15(alpha,spj),Rxp);
Jean-Marc Valin4e1328b2008-02-28 15:14:07 +1100227 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]));
228 Ryp = yp[m] + MULT16_16(spj, SUB16(QCONST16(1.f,14),MULT16_16_Q15(alpha,Rpp)));
Jean-Marc Valina073c7b2008-02-14 16:58:04 +1100229
230 /* Compute the gain such that ||p + g*y|| = 1 */
Jean-Marc Valin19ae9fc2008-03-13 11:18:15 +1100231 g = MULT16_32_Q15(
232 celt_sqrt(MULT16_16(ROUND(Ryp,14),ROUND(Ryp,14)) + Ryy -
233 MULT16_16(ROUND(Ryy,14),Rpp))
234 - ROUND(Ryp,14),
235 celt_rcp(SHR32(Ryy,12)));
Jean-Marc Valind857ac42008-03-12 13:26:37 +1100236 /* Knowing that gain, what's the error: (x-g*y)^2
Jean-Marc Valina073c7b2008-02-14 16:58:04 +1100237 (result is negated and we discard x^2 because it's constant) */
Jean-Marc Valin4e1328b2008-02-28 15:14:07 +1100238 /*score = 2.f*g*Rxy - 1.f*g*g*Ryy*NORM_SCALING_1;*/
Jean-Marc Valin19ae9fc2008-03-13 11:18:15 +1100239 score = 2*MULT16_32_Q14(ROUND(Rxy,14),g)
240 - MULT16_32_Q14(EXTRACT16(MULT16_32_Q14(ROUND(Ryy,14),g)),g);
Jean-Marc Valin41af4212007-11-30 18:35:37 +1100241
Jean-Marc Valin3b277dc2008-02-14 16:46:50 +1100242 if (score>nbest[Lupdate-1]->score)
Jean-Marc Valin1e7087e2007-12-04 13:05:43 +1100243 {
Jean-Marc Valincab576e2008-02-12 17:21:14 +1100244 int id = Lupdate-1;
Jean-Marc Valin3b277dc2008-02-14 16:46:50 +1100245 struct NBest *tmp_best;
246
247 /* Save some pointers that would be deleted and use them for the current entry*/
248 tmp_best = nbest[Lupdate-1];
249 while (id > 0 && score > nbest[id-1]->score)
Jean-Marc Valin1e7087e2007-12-04 13:05:43 +1100250 id--;
251
Jean-Marc Valincab576e2008-02-12 17:21:14 +1100252 for (k=Lupdate-1;k>id;k--)
Jean-Marc Valin3b277dc2008-02-14 16:46:50 +1100253 nbest[k] = nbest[k-1];
Jean-Marc Valin1e7087e2007-12-04 13:05:43 +1100254
Jean-Marc Valin3b277dc2008-02-14 16:46:50 +1100255 nbest[id] = tmp_best;
256 nbest[id]->score = score;
257 nbest[id]->pos = j;
258 nbest[id]->orig = m;
259 nbest[id]->sign = sign;
Jean-Marc Valin4e1328b2008-02-28 15:14:07 +1100260 nbest[id]->xy = Rxy;
261 nbest[id]->yy = Ryy;
262 nbest[id]->yp = Ryp;
Jean-Marc Valin1e7087e2007-12-04 13:05:43 +1100263 }
Jean-Marc Valin636f5c82008-02-12 17:40:27 +1100264 }
Jean-Marc Valin41af4212007-11-30 18:35:37 +1100265 }
Jean-Marc Valin636f5c82008-02-12 17:40:27 +1100266
Jean-Marc Valin41af4212007-11-30 18:35:37 +1100267 }
Jean-Marc Valinb60340f2008-02-26 15:41:51 +1100268
Jean-Marc Valin4e1328b2008-02-28 15:14:07 +1100269 if (!(nbest[0]->score > -VERY_LARGE32))
Jean-Marc Valinb60340f2008-02-26 15:41:51 +1100270 celt_fatal("Could not find any match in VQ codebook. Something got corrupted somewhere.");
Jean-Marc Valin0d587d82008-02-14 21:29:50 +1100271 /* Only now that we've made the final choice, update ny/iny and others */
Jean-Marc Valincab576e2008-02-12 17:21:14 +1100272 for (k=0;k<Lupdate;k++)
Jean-Marc Valin41af4212007-11-30 18:35:37 +1100273 {
Jean-Marc Valin3b277dc2008-02-14 16:46:50 +1100274 int n;
275 int is;
Jean-Marc Valin8b158f52008-02-28 14:44:19 +1100276 celt_norm_t s;
Jean-Marc Valin3b277dc2008-02-14 16:46:50 +1100277 is = nbest[k]->sign*pulsesAtOnce;
Jean-Marc Valinf675adc2008-02-28 12:15:17 +1100278 s = SHL16(is, yshift);
Jean-Marc Valin3b277dc2008-02-14 16:46:50 +1100279 for (n=0;n<N;n++)
Jean-Marc Valin8b158f52008-02-28 14:44:19 +1100280 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 +1100281 ny[k][nbest[k]->pos] += s;
Jean-Marc Valin0d587d82008-02-14 21:29:50 +1100282
Jean-Marc Valin3b277dc2008-02-14 16:46:50 +1100283 for (n=0;n<N;n++)
284 iny[k][n] = iy[nbest[k]->orig][n];
285 iny[k][nbest[k]->pos] += is;
Jean-Marc Valin0d587d82008-02-14 21:29:50 +1100286
Jean-Marc Valin3b277dc2008-02-14 16:46:50 +1100287 xy[k] = nbest[k]->xy;
288 yy[k] = nbest[k]->yy;
289 yp[k] = nbest[k]->yp;
290 }
Jean-Marc Valin0d587d82008-02-14 21:29:50 +1100291 /* Swap ny/iny with y/iy */
Jean-Marc Valin3b277dc2008-02-14 16:46:50 +1100292 for (k=0;k<Lupdate;k++)
293 {
Jean-Marc Valin8b158f52008-02-28 14:44:19 +1100294 celt_norm_t *tmp_ny;
Jean-Marc Valinfe419832008-02-12 15:05:01 +1100295 int *tmp_iny;
296
Jean-Marc Valinfe419832008-02-12 15:05:01 +1100297 tmp_ny = ny[k];
298 ny[k] = y[k];
299 y[k] = tmp_ny;
300 tmp_iny = iny[k];
301 iny[k] = iy[k];
302 iy[k] = tmp_iny;
Jean-Marc Valin41af4212007-11-30 18:35:37 +1100303 }
Jean-Marc Valin846d4e22008-02-12 13:48:48 +1100304 pulsesLeft -= pulsesAtOnce;
Jean-Marc Valin41af4212007-11-30 18:35:37 +1100305 }
306
Jean-Marc Valind4018c32008-02-27 10:09:48 +1100307#if 0
Jean-Marc Valinac1e03d2008-02-12 23:00:18 +1100308 if (0) {
Jean-Marc Valin877b1972008-02-29 16:40:39 +1100309 celt_word32_t err=0;
Jean-Marc Valinac1e03d2008-02-12 23:00:18 +1100310 for (i=0;i<N;i++)
Jean-Marc Valin3b277dc2008-02-14 16:46:50 +1100311 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 +1100312 /*if (N<=10)
313 printf ("%f %d %d\n", err, K, N);*/
Jean-Marc Valinac1e03d2008-02-12 23:00:18 +1100314 }
Jean-Marc Valin0d587d82008-02-14 21:29:50 +1100315 /* Sanity checks, don't bother */
Jean-Marc Valin1e7087e2007-12-04 13:05:43 +1100316 if (0) {
Jean-Marc Valind4018c32008-02-27 10:09:48 +1100317 for (i=0;i<N;i++)
318 x[i] = p[i]+nbest[0]->gain*y[0][i];
Jean-Marc Valin877b1972008-02-29 16:40:39 +1100319 celt_word32_t E=1e-15;
Jean-Marc Valin1e7087e2007-12-04 13:05:43 +1100320 int ABS = 0;
321 for (i=0;i<N;i++)
322 ABS += abs(iy[0][i]);
Jean-Marc Valina85657b2008-02-20 11:59:30 +1100323 /*if (K != ABS)
324 printf ("%d %d\n", K, ABS);*/
Jean-Marc Valin1e7087e2007-12-04 13:05:43 +1100325 for (i=0;i<N;i++)
326 E += x[i]*x[i];
Jean-Marc Valina85657b2008-02-20 11:59:30 +1100327 /*printf ("%f\n", E);*/
Jean-Marc Valin1e7087e2007-12-04 13:05:43 +1100328 E = 1/sqrt(E);
329 for (i=0;i<N;i++)
330 x[i] *= E;
331 }
Jean-Marc Valind4018c32008-02-27 10:09:48 +1100332#endif
Jean-Marc Valin5fa59952008-02-14 13:50:44 +1100333
334 encode_pulses(iy[0], N, K, enc);
335
Jean-Marc Valina4833ff2008-01-10 15:34:00 +1100336 /* Recompute the gain in one pass to reduce the encoder-decoder mismatch
Jean-Marc Valin636f5c82008-02-12 17:40:27 +1100337 due to the recursive computation used in quantisation.
338 Not quite sure whether we need that or not */
Jean-Marc Valind17edd32008-02-27 16:52:30 +1100339 mix_pitch_and_residual(iy[0], X, N, K, P, alpha);
Jean-Marc Valin8600f692008-02-29 15:14:12 +1100340 RESTORE_STACK;
Jean-Marc Valin41af4212007-11-30 18:35:37 +1100341}
342
Jean-Marc Valin879fbfd2008-02-20 17:17:13 +1100343/** Decode pulse vector and combine the result with the pitch vector to produce
344 the final normalised signal in the current band. */
Jean-Marc Valin9d8d9b32008-02-27 16:17:39 +1100345void 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 +1100346{
Jean-Marc Valin31b79d12008-03-12 17:17:23 +1100347 VARDECL(int, iy);
Jean-Marc Valin8600f692008-02-29 15:14:12 +1100348 SAVE_STACK;
Jean-Marc Valin9a0bba12008-02-20 14:08:50 +1100349 ALLOC(iy, N, int);
Jean-Marc Valin5fa59952008-02-14 13:50:44 +1100350 decode_pulses(iy, N, K, dec);
Jean-Marc Valind17edd32008-02-27 16:52:30 +1100351 mix_pitch_and_residual(iy, X, N, K, P, alpha);
Jean-Marc Valin8600f692008-02-29 15:14:12 +1100352 RESTORE_STACK;
Jean-Marc Valin0d227d82007-12-31 16:12:12 +1100353}
354
Jean-Marc Valin9455d1b2008-03-07 17:17:37 +1100355#ifdef FIXED_POINT
356static const celt_word16_t pg[11] = {32767, 24576, 21299, 19661, 19661, 19661, 18022, 18022, 16384, 16384, 16384};
357#else
Jean-Marc Valin3e650972008-03-07 17:38:58 +1100358static 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 +1100359#endif
Jean-Marc Valin0d227d82007-12-31 16:12:12 +1100360
Jean-Marc Valin5f09ea52008-02-26 16:43:04 +1100361void 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 +1100362{
363 int i,j;
364 int best=0;
Jean-Marc Valin877b1972008-02-29 16:40:39 +1100365 celt_word32_t best_score=0;
366 celt_word16_t s = 1;
Jean-Marc Valin0aa39032007-12-07 15:09:58 +1100367 int sign;
Jean-Marc Valin877b1972008-02-29 16:40:39 +1100368 celt_word32_t E;
Jean-Marc Valin9455d1b2008-03-07 17:17:37 +1100369 celt_word16_t pred_gain;
Jean-Marc Valin8f0f4b92008-02-11 13:52:44 +1100370 int max_pos = N0-N/B;
371 if (max_pos > 32)
372 max_pos = 32;
373
374 for (i=0;i<max_pos*B;i+=B)
Jean-Marc Valin4841a0a2007-12-03 13:54:30 +1100375 {
Jean-Marc Valin877b1972008-02-29 16:40:39 +1100376 celt_word32_t xy=0, yy=0;
Jean-Marc Valin03892c12008-03-07 17:25:47 +1100377 celt_word32_t score;
Jean-Marc Valin4841a0a2007-12-03 13:54:30 +1100378 for (j=0;j<N;j++)
379 {
Jean-Marc Valin877b1972008-02-29 16:40:39 +1100380 xy = MAC16_16(xy, x[j], Y[i+N-j-1]);
381 yy = MAC16_16(yy, Y[i+N-j-1], Y[i+N-j-1]);
Jean-Marc Valin4841a0a2007-12-03 13:54:30 +1100382 }
Jean-Marc Valin03892c12008-03-07 17:25:47 +1100383 score = DIV32(MULT16_16(ROUND(xy,14),ROUND(xy,14)), ROUND(yy,14));
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];
Jean-Marc Valin03892c12008-03-07 17:25:47 +1100407 E = EPSILON;
Jean-Marc Valin0d227d82007-12-31 16:12:12 +1100408 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 Valin877b1972008-02-29 16:40:39 +1100411 E = MAC16_16(E, P[j],P[j]);
Jean-Marc Valin4841a0a2007-12-03 13:54:30 +1100412 }
Jean-Marc Valin9455d1b2008-03-07 17:17:37 +1100413 /*pred_gain = pred_gain/sqrt(E);*/
414 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 +1100415 for (j=0;j<N;j++)
Jean-Marc Valin9455d1b2008-03-07 17:17:37 +1100416 P[j] = PSHR32(MULT16_16(pred_gain, P[j]),8);
Jean-Marc Valin0d227d82007-12-31 16:12:12 +1100417 if (K>0)
418 {
419 for (j=0;j<N;j++)
420 x[j] -= P[j];
421 } else {
422 for (j=0;j<N;j++)
423 x[j] = P[j];
424 }
Jean-Marc Valina85657b2008-02-20 11:59:30 +1100425 /*printf ("quant ");*/
426 /*for (j=0;j<N;j++) printf ("%f ", P[j]);*/
Jean-Marc Valin0d227d82007-12-31 16:12:12 +1100427
Jean-Marc Valin4841a0a2007-12-03 13:54:30 +1100428}
Jean-Marc Valinfc08d0a2007-12-07 13:26:15 +1100429
Jean-Marc Valin18ddc022008-02-22 14:24:50 +1100430void 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 +1100431{
Jean-Marc Valin11f01722007-12-09 01:19:36 +1100432 int j;
Jean-Marc Valin0aa39032007-12-07 15:09:58 +1100433 int sign;
Jean-Marc Valin877b1972008-02-29 16:40:39 +1100434 celt_word16_t s;
Jean-Marc Valin6e9058a2007-12-07 14:59:06 +1100435 int best;
Jean-Marc Valin877b1972008-02-29 16:40:39 +1100436 celt_word32_t E;
Jean-Marc Valin9455d1b2008-03-07 17:17:37 +1100437 celt_word16_t pred_gain;
Jean-Marc Valin8f0f4b92008-02-11 13:52:44 +1100438 int max_pos = N0-N/B;
439 if (max_pos > 32)
440 max_pos = 32;
441
Jean-Marc Valin0aa39032007-12-07 15:09:58 +1100442 sign = ec_dec_uint(dec, 2);
443 if (sign == 0)
Jean-Marc Valin6e9058a2007-12-07 14:59:06 +1100444 s = 1;
445 else
446 s = -1;
447
Jean-Marc Valin8f0f4b92008-02-11 13:52:44 +1100448 best = B*ec_dec_uint(dec, max_pos);
Jean-Marc Valina85657b2008-02-20 11:59:30 +1100449 /*printf ("%d %d ", sign, best);*/
Jean-Marc Valin6e9058a2007-12-07 14:59:06 +1100450
Jean-Marc Valin0d227d82007-12-31 16:12:12 +1100451 if (K>10)
452 pred_gain = pg[10];
453 else
454 pred_gain = pg[K];
Jean-Marc Valin9455d1b2008-03-07 17:17:37 +1100455 E = EPSILON;
Jean-Marc Valin0d227d82007-12-31 16:12:12 +1100456 for (j=0;j<N;j++)
457 {
Jean-Marc Valind501f612008-02-21 12:16:57 +1100458 P[j] = s*Y[best+N-j-1];
Jean-Marc Valin877b1972008-02-29 16:40:39 +1100459 E = MAC16_16(E, P[j],P[j]);
Jean-Marc Valin0d227d82007-12-31 16:12:12 +1100460 }
Jean-Marc Valin9455d1b2008-03-07 17:17:37 +1100461 /*pred_gain = pred_gain/sqrt(E);*/
462 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 +1100463 for (j=0;j<N;j++)
Jean-Marc Valin9455d1b2008-03-07 17:17:37 +1100464 P[j] = PSHR32(MULT16_16(pred_gain, P[j]),8);
Jean-Marc Valin6e9058a2007-12-07 14:59:06 +1100465 if (K==0)
466 {
Jean-Marc Valin6e9058a2007-12-07 14:59:06 +1100467 for (j=0;j<N;j++)
Jean-Marc Valin0d227d82007-12-31 16:12:12 +1100468 x[j] = P[j];
Jean-Marc Valin6e9058a2007-12-07 14:59:06 +1100469 }
470}
Jean-Marc Valin0e20ca02008-02-11 15:33:53 +1100471
Jean-Marc Valin18ddc022008-02-22 14:24:50 +1100472void 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 +1100473{
Jean-Marc Valin0df0eb42008-02-13 16:00:10 +1100474 int i, j;
Jean-Marc Valin877b1972008-02-29 16:40:39 +1100475 celt_word32_t E;
Jean-Marc Valinec9b6df2008-03-07 17:05:47 +1100476 celt_word16_t g;
Jean-Marc Valin0e20ca02008-02-11 15:33:53 +1100477
Jean-Marc Valinec9b6df2008-03-07 17:05:47 +1100478 E = EPSILON;
Jean-Marc Valin0df0eb42008-02-13 16:00:10 +1100479 if (N0 >= Nmax/2)
Jean-Marc Valin0e20ca02008-02-11 15:33:53 +1100480 {
Jean-Marc Valin0df0eb42008-02-13 16:00:10 +1100481 for (i=0;i<B;i++)
482 {
483 for (j=0;j<N/B;j++)
484 {
485 P[j*B+i] = Y[(Nmax-N0-j-1)*B+i];
Jean-Marc Valin877b1972008-02-29 16:40:39 +1100486 E += P[j*B+i]*P[j*B+i];
Jean-Marc Valin0df0eb42008-02-13 16:00:10 +1100487 }
488 }
489 } else {
490 for (j=0;j<N;j++)
491 {
492 P[j] = Y[j];
Jean-Marc Valin877b1972008-02-29 16:40:39 +1100493 E = MAC16_16(E, P[j],P[j]);
Jean-Marc Valin0df0eb42008-02-13 16:00:10 +1100494 }
Jean-Marc Valin0e20ca02008-02-11 15:33:53 +1100495 }
Jean-Marc Valinec9b6df2008-03-07 17:05:47 +1100496 g = DIV32_16(SHL32(EXTEND32(1),14+8),celt_sqrt(E));
Jean-Marc Valin0e20ca02008-02-11 15:33:53 +1100497 for (j=0;j<N;j++)
Jean-Marc Valinec9b6df2008-03-07 17:05:47 +1100498 P[j] = PSHR32(MULT16_16(g, P[j]),8);
Jean-Marc Valin0e20ca02008-02-11 15:33:53 +1100499 for (j=0;j<N;j++)
500 x[j] = P[j];
501}
502