blob: 7718bd8b8a11e353a66eb188b288828a80f916fc [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 Valind4018c32008-02-27 10:09:48 +110044/** Takes the pitch vector and the decoded residual vector (non-compressed),
45 applies the compression in the pitch direction, computes the gain that will
46 give ||p+g*y||=1 and mixes the residual with the pitch. */
Jean-Marc Valin31213272008-03-03 16:52:54 +110047static 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 +110048{
49 int i;
Jean-Marc Valinb50c5412008-02-27 17:05:43 +110050 celt_word32_t Ryp, Ryy, Rpp;
Jean-Marc Valina847b772008-02-27 17:46:49 +110051 celt_word32_t g;
Jean-Marc Valin31b79d12008-03-12 17:17:23 +110052 VARDECL(celt_norm_t, y);
Jean-Marc Valind9de5932008-03-05 08:11:57 +110053#ifdef FIXED_POINT
54 int yshift;
55#endif
Jean-Marc Valin8600f692008-02-29 15:14:12 +110056 SAVE_STACK;
Jean-Marc Valind17edd32008-02-27 16:52:30 +110057#ifdef FIXED_POINT
Jean-Marc Valind9de5932008-03-05 08:11:57 +110058 yshift = 14-EC_ILOG(K);
Jean-Marc Valind17edd32008-02-27 16:52:30 +110059#endif
60 ALLOC(y, N, celt_norm_t);
Jean-Marc Valind4018c32008-02-27 10:09:48 +110061
62 /*for (i=0;i<N;i++)
63 printf ("%d ", iy[i]);*/
Jean-Marc Valinb50c5412008-02-27 17:05:43 +110064 Rpp = 0;
Jean-Marc Valind4018c32008-02-27 10:09:48 +110065 for (i=0;i<N;i++)
Jean-Marc Valinb50c5412008-02-27 17:05:43 +110066 Rpp = MAC16_16(Rpp,P[i],P[i]);
Jean-Marc Valind4018c32008-02-27 10:09:48 +110067
Jean-Marc Valinb50c5412008-02-27 17:05:43 +110068 Ryp = 0;
Jean-Marc Valind4018c32008-02-27 10:09:48 +110069 for (i=0;i<N;i++)
Jean-Marc Valinb50c5412008-02-27 17:05:43 +110070 Ryp = MAC16_16(Ryp,SHL16(iy[i],yshift),P[i]);
Jean-Marc Valind4018c32008-02-27 10:09:48 +110071
Jean-Marc Valind17edd32008-02-27 16:52:30 +110072 /* Remove part of the pitch component to compute the real residual from
73 the encoded (int) one */
Jean-Marc Valind4018c32008-02-27 10:09:48 +110074 for (i=0;i<N;i++)
Jean-Marc Valind17edd32008-02-27 16:52:30 +110075 y[i] = SUB16(SHL16(iy[i],yshift),
Jean-Marc Valina02ca1e2008-02-28 11:33:22 +110076 MULT16_16_Q15(alpha,MULT16_16_Q14(ROUND(Ryp,14),P[i])));
Jean-Marc Valind4018c32008-02-27 10:09:48 +110077
78 /* Recompute after the projection (I think it's right) */
79 Ryp = 0;
80 for (i=0;i<N;i++)
Jean-Marc Valinb50c5412008-02-27 17:05:43 +110081 Ryp = MAC16_16(Ryp,y[i],P[i]);
Jean-Marc Valind4018c32008-02-27 10:09:48 +110082
Jean-Marc Valinb50c5412008-02-27 17:05:43 +110083 Ryy = 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 Ryy = MAC16_16(Ryy, y[i],y[i]);
Jean-Marc Valind4018c32008-02-27 10:09:48 +110086
Jean-Marc Valin1ca07222008-02-27 17:23:04 +110087 /* g = (sqrt(Ryp^2 + Ryy - Rpp*Ryy)-Ryp)/Ryy */
Jean-Marc Valin9d5b4a62008-03-13 11:36:45 +110088 g = MULT16_32_Q15(
89 celt_sqrt(MULT16_16(ROUND(Ryp,14),ROUND(Ryp,14)) + Ryy -
90 MULT16_16(ROUND(Ryy,14),ROUND(Rpp,14)))
91 - ROUND(Ryp,14),
92 celt_rcp(SHR32(Ryy,9)));
Jean-Marc Valind4018c32008-02-27 10:09:48 +110093
94 for (i=0;i<N;i++)
Jean-Marc Valin9d5b4a62008-03-13 11:36:45 +110095 X[i] = P[i] + ROUND(MULT16_16(y[i], g),11);
Jean-Marc Valin8600f692008-02-29 15:14:12 +110096 RESTORE_STACK;
Jean-Marc Valind4018c32008-02-27 10:09:48 +110097}
98
Jean-Marc Valin879fbfd2008-02-20 17:17:13 +110099/** All the info necessary to keep track of a hypothesis during the search */
Jean-Marc Valin3b277dc2008-02-14 16:46:50 +1100100struct NBest {
Jean-Marc Valin4e1328b2008-02-28 15:14:07 +1100101 celt_word32_t score;
Jean-Marc Valin3b277dc2008-02-14 16:46:50 +1100102 int sign;
103 int pos;
104 int orig;
Jean-Marc Valin4e1328b2008-02-28 15:14:07 +1100105 celt_word32_t xy;
106 celt_word32_t yy;
107 celt_word32_t yp;
Jean-Marc Valin3b277dc2008-02-14 16:46:50 +1100108};
Jean-Marc Valin41af4212007-11-30 18:35:37 +1100109
Jean-Marc Valin31213272008-03-03 16:52:54 +1100110void 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 +1100111{
Jean-Marc Valin4a897682007-12-12 00:45:15 +1100112 int L = 3;
Jean-Marc Valin31b79d12008-03-12 17:17:23 +1100113 VARDECL(celt_norm_t, _y);
114 VARDECL(celt_norm_t, _ny);
115 VARDECL(int, _iy);
116 VARDECL(int, _iny);
117 VARDECL(celt_norm_t *, y);
118 VARDECL(celt_norm_t *, ny);
119 VARDECL(int *, iy);
120 VARDECL(int *, iny);
Jean-Marc Valin0d587d82008-02-14 21:29:50 +1100121 int i, j, k, m;
Jean-Marc Valin846d4e22008-02-12 13:48:48 +1100122 int pulsesLeft;
Jean-Marc Valin31b79d12008-03-12 17:17:23 +1100123 VARDECL(celt_word32_t, xy);
124 VARDECL(celt_word32_t, yy);
125 VARDECL(celt_word32_t, yp);
126 VARDECL(struct NBest, _nbest);
127 VARDECL(struct NBest *, nbest);
Jean-Marc Valinf675adc2008-02-28 12:15:17 +1100128 celt_word32_t Rpp=0, Rxp=0;
Jean-Marc Valin41af4212007-11-30 18:35:37 +1100129 int maxL = 1;
Jean-Marc Valinf675adc2008-02-28 12:15:17 +1100130#ifdef FIXED_POINT
Jean-Marc Valind748cd52008-03-01 07:27:03 +1100131 int yshift;
132#endif
133 SAVE_STACK;
134
135#ifdef FIXED_POINT
136 yshift = 14-EC_ILOG(K);
Jean-Marc Valinf675adc2008-02-28 12:15:17 +1100137#endif
Jean-Marc Valin9d8d9b32008-02-27 16:17:39 +1100138
Jean-Marc Valin8b158f52008-02-28 14:44:19 +1100139 ALLOC(_y, L*N, celt_norm_t);
140 ALLOC(_ny, L*N, celt_norm_t);
Jean-Marc Valin9a0bba12008-02-20 14:08:50 +1100141 ALLOC(_iy, L*N, int);
142 ALLOC(_iny, L*N, int);
Jean-Marc Valincac91ec2008-02-29 17:03:34 +1100143 ALLOC(y, L, celt_norm_t*);
144 ALLOC(ny, L, celt_norm_t*);
145 ALLOC(iy, L, int*);
146 ALLOC(iny, L, int*);
Jean-Marc Valin9a0bba12008-02-20 14:08:50 +1100147
Jean-Marc Valined9e4232008-02-28 12:22:22 +1100148 ALLOC(xy, L, celt_word32_t);
149 ALLOC(yy, L, celt_word32_t);
150 ALLOC(yp, L, celt_word32_t);
Jean-Marc Valin9a0bba12008-02-20 14:08:50 +1100151 ALLOC(_nbest, L, struct NBest);
152 ALLOC(nbest, L, struct NBest *);
Jean-Marc Valinb4dfce42008-02-25 17:41:30 +1100153
Jean-Marc Valinfe419832008-02-12 15:05:01 +1100154 for (m=0;m<L;m++)
Jean-Marc Valin3b277dc2008-02-14 16:46:50 +1100155 nbest[m] = &_nbest[m];
156
157 for (m=0;m<L;m++)
Jean-Marc Valinfe419832008-02-12 15:05:01 +1100158 {
Jean-Marc Valin9a0bba12008-02-20 14:08:50 +1100159 ny[m] = &_ny[m*N];
160 iny[m] = &_iny[m*N];
161 y[m] = &_y[m*N];
162 iy[m] = &_iy[m*N];
Jean-Marc Valinfe419832008-02-12 15:05:01 +1100163 }
164
Jean-Marc Valin41af4212007-11-30 18:35:37 +1100165 for (j=0;j<N;j++)
Jean-Marc Valin0d587d82008-02-14 21:29:50 +1100166 {
Jean-Marc Valinf675adc2008-02-28 12:15:17 +1100167 Rpp = MAC16_16(Rpp, P[j],P[j]);
168 Rxp = MAC16_16(Rxp, X[j],P[j]);
Jean-Marc Valin0d587d82008-02-14 21:29:50 +1100169 }
Jean-Marc Valinf675adc2008-02-28 12:15:17 +1100170 Rpp = ROUND(Rpp, NORM_SHIFT);
171 Rxp = ROUND(Rxp, NORM_SHIFT);
172 if (Rpp>NORM_SCALING)
Jean-Marc Valinb60340f2008-02-26 15:41:51 +1100173 celt_fatal("Rpp > 1");
174
Jean-Marc Valin0d587d82008-02-14 21:29:50 +1100175 /* We only need to initialise the zero because the first iteration only uses that */
176 for (i=0;i<N;i++)
177 y[0][i] = 0;
178 for (i=0;i<N;i++)
179 iy[0][i] = 0;
180 xy[0] = yy[0] = yp[0] = 0;
181
Jean-Marc Valin846d4e22008-02-12 13:48:48 +1100182 pulsesLeft = K;
183 while (pulsesLeft > 0)
Jean-Marc Valin41af4212007-11-30 18:35:37 +1100184 {
Jean-Marc Valin846d4e22008-02-12 13:48:48 +1100185 int pulsesAtOnce=1;
Jean-Marc Valincab576e2008-02-12 17:21:14 +1100186 int Lupdate = L;
Jean-Marc Valin41af4212007-11-30 18:35:37 +1100187 int L2 = L;
Jean-Marc Valin0d587d82008-02-14 21:29:50 +1100188
189 /* Decide on complexity strategy */
Jean-Marc Valincab576e2008-02-12 17:21:14 +1100190 pulsesAtOnce = pulsesLeft/N;
191 if (pulsesAtOnce<1)
192 pulsesAtOnce = 1;
193 if (pulsesLeft-pulsesAtOnce > 3 || N > 30)
194 Lupdate = 1;
Jean-Marc Valina85657b2008-02-20 11:59:30 +1100195 /*printf ("%d %d %d/%d %d\n", Lupdate, pulsesAtOnce, pulsesLeft, K, N);*/
Jean-Marc Valincab576e2008-02-12 17:21:14 +1100196 L2 = Lupdate;
197 if (L2>maxL)
Jean-Marc Valin41af4212007-11-30 18:35:37 +1100198 {
199 L2 = maxL;
200 maxL *= N;
201 }
Jean-Marc Valin846d4e22008-02-12 13:48:48 +1100202
Jean-Marc Valin0d587d82008-02-14 21:29:50 +1100203 for (m=0;m<Lupdate;m++)
Jean-Marc Valin4e1328b2008-02-28 15:14:07 +1100204 nbest[m]->score = -VERY_LARGE32;
Jean-Marc Valin41af4212007-11-30 18:35:37 +1100205
206 for (m=0;m<L2;m++)
207 {
208 for (j=0;j<N;j++)
209 {
Jean-Marc Valin1e7087e2007-12-04 13:05:43 +1100210 int sign;
Jean-Marc Valin0d587d82008-02-14 21:29:50 +1100211 /*if (x[j]>0) sign=1; else sign=-1;*/
Jean-Marc Valin1e7087e2007-12-04 13:05:43 +1100212 for (sign=-1;sign<=1;sign+=2)
Jean-Marc Valin41af4212007-11-30 18:35:37 +1100213 {
Jean-Marc Valina85657b2008-02-20 11:59:30 +1100214 /*fprintf (stderr, "%d/%d %d/%d %d/%d\n", i, K, m, L2, j, N);*/
Jean-Marc Valin4e1328b2008-02-28 15:14:07 +1100215 celt_word32_t Rxy, Ryy, Ryp;
216 celt_word16_t spj, aspj; /* Intermediate results */
217 celt_word32_t score;
218 celt_word32_t g;
Jean-Marc Valinc9d606f2008-02-28 13:46:20 +1100219 celt_word16_t s = SHL16(sign*pulsesAtOnce, yshift);
Jean-Marc Valinfe419832008-02-12 15:05:01 +1100220
Jean-Marc Valin9a0bba12008-02-20 14:08:50 +1100221 /* All pulses at one location must have the same sign. */
222 if (iy[m][j]*sign < 0)
223 continue;
224
Jean-Marc Valin19ae9fc2008-03-13 11:18:15 +1100225 spj = MULT16_16_Q14(s, P[j]);
226 aspj = MULT16_16_Q15(alpha, spj);
Jean-Marc Valina073c7b2008-02-14 16:58:04 +1100227 /* Updating the sums of the new pulse(s) */
Jean-Marc Valin19ae9fc2008-03-13 11:18:15 +1100228 Rxy = xy[m] + MULT16_16(s,X[j]) - MULT16_16(MULT16_16_Q15(alpha,spj),Rxp);
Jean-Marc Valin4e1328b2008-02-28 15:14:07 +1100229 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]));
230 Ryp = yp[m] + MULT16_16(spj, SUB16(QCONST16(1.f,14),MULT16_16_Q15(alpha,Rpp)));
Jean-Marc Valina073c7b2008-02-14 16:58:04 +1100231
232 /* Compute the gain such that ||p + g*y|| = 1 */
Jean-Marc Valin19ae9fc2008-03-13 11:18:15 +1100233 g = MULT16_32_Q15(
234 celt_sqrt(MULT16_16(ROUND(Ryp,14),ROUND(Ryp,14)) + Ryy -
235 MULT16_16(ROUND(Ryy,14),Rpp))
236 - ROUND(Ryp,14),
237 celt_rcp(SHR32(Ryy,12)));
Jean-Marc Valind857ac42008-03-12 13:26:37 +1100238 /* Knowing that gain, what's the error: (x-g*y)^2
Jean-Marc Valina073c7b2008-02-14 16:58:04 +1100239 (result is negated and we discard x^2 because it's constant) */
Jean-Marc Valin4e1328b2008-02-28 15:14:07 +1100240 /*score = 2.f*g*Rxy - 1.f*g*g*Ryy*NORM_SCALING_1;*/
Jean-Marc Valin19ae9fc2008-03-13 11:18:15 +1100241 score = 2*MULT16_32_Q14(ROUND(Rxy,14),g)
242 - MULT16_32_Q14(EXTRACT16(MULT16_32_Q14(ROUND(Ryy,14),g)),g);
Jean-Marc Valin41af4212007-11-30 18:35:37 +1100243
Jean-Marc Valin3b277dc2008-02-14 16:46:50 +1100244 if (score>nbest[Lupdate-1]->score)
Jean-Marc Valin1e7087e2007-12-04 13:05:43 +1100245 {
Jean-Marc Valin472a5f02008-02-19 13:12:32 +1100246 int k;
Jean-Marc Valincab576e2008-02-12 17:21:14 +1100247 int id = Lupdate-1;
Jean-Marc Valin3b277dc2008-02-14 16:46:50 +1100248 struct NBest *tmp_best;
249
250 /* Save some pointers that would be deleted and use them for the current entry*/
251 tmp_best = nbest[Lupdate-1];
252 while (id > 0 && score > nbest[id-1]->score)
Jean-Marc Valin1e7087e2007-12-04 13:05:43 +1100253 id--;
254
Jean-Marc Valincab576e2008-02-12 17:21:14 +1100255 for (k=Lupdate-1;k>id;k--)
Jean-Marc Valin3b277dc2008-02-14 16:46:50 +1100256 nbest[k] = nbest[k-1];
Jean-Marc Valin1e7087e2007-12-04 13:05:43 +1100257
Jean-Marc Valin3b277dc2008-02-14 16:46:50 +1100258 nbest[id] = tmp_best;
259 nbest[id]->score = score;
260 nbest[id]->pos = j;
261 nbest[id]->orig = m;
262 nbest[id]->sign = sign;
Jean-Marc Valin4e1328b2008-02-28 15:14:07 +1100263 nbest[id]->xy = Rxy;
264 nbest[id]->yy = Ryy;
265 nbest[id]->yp = Ryp;
Jean-Marc Valin1e7087e2007-12-04 13:05:43 +1100266 }
Jean-Marc Valin636f5c82008-02-12 17:40:27 +1100267 }
Jean-Marc Valin41af4212007-11-30 18:35:37 +1100268 }
Jean-Marc Valin636f5c82008-02-12 17:40:27 +1100269
Jean-Marc Valin41af4212007-11-30 18:35:37 +1100270 }
Jean-Marc Valinb60340f2008-02-26 15:41:51 +1100271
Jean-Marc Valin4e1328b2008-02-28 15:14:07 +1100272 if (!(nbest[0]->score > -VERY_LARGE32))
Jean-Marc Valinb60340f2008-02-26 15:41:51 +1100273 celt_fatal("Could not find any match in VQ codebook. Something got corrupted somewhere.");
Jean-Marc Valin0d587d82008-02-14 21:29:50 +1100274 /* Only now that we've made the final choice, update ny/iny and others */
Jean-Marc Valincab576e2008-02-12 17:21:14 +1100275 for (k=0;k<Lupdate;k++)
Jean-Marc Valin41af4212007-11-30 18:35:37 +1100276 {
Jean-Marc Valin3b277dc2008-02-14 16:46:50 +1100277 int n;
278 int is;
Jean-Marc Valin8b158f52008-02-28 14:44:19 +1100279 celt_norm_t s;
Jean-Marc Valin3b277dc2008-02-14 16:46:50 +1100280 is = nbest[k]->sign*pulsesAtOnce;
Jean-Marc Valinf675adc2008-02-28 12:15:17 +1100281 s = SHL16(is, yshift);
Jean-Marc Valin3b277dc2008-02-14 16:46:50 +1100282 for (n=0;n<N;n++)
Jean-Marc Valin8b158f52008-02-28 14:44:19 +1100283 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 +1100284 ny[k][nbest[k]->pos] += s;
Jean-Marc Valin0d587d82008-02-14 21:29:50 +1100285
Jean-Marc Valin3b277dc2008-02-14 16:46:50 +1100286 for (n=0;n<N;n++)
287 iny[k][n] = iy[nbest[k]->orig][n];
288 iny[k][nbest[k]->pos] += is;
Jean-Marc Valin0d587d82008-02-14 21:29:50 +1100289
Jean-Marc Valin3b277dc2008-02-14 16:46:50 +1100290 xy[k] = nbest[k]->xy;
291 yy[k] = nbest[k]->yy;
292 yp[k] = nbest[k]->yp;
293 }
Jean-Marc Valin0d587d82008-02-14 21:29:50 +1100294 /* Swap ny/iny with y/iy */
Jean-Marc Valin3b277dc2008-02-14 16:46:50 +1100295 for (k=0;k<Lupdate;k++)
296 {
Jean-Marc Valin8b158f52008-02-28 14:44:19 +1100297 celt_norm_t *tmp_ny;
Jean-Marc Valinfe419832008-02-12 15:05:01 +1100298 int *tmp_iny;
299
Jean-Marc Valinfe419832008-02-12 15:05:01 +1100300 tmp_ny = ny[k];
301 ny[k] = y[k];
302 y[k] = tmp_ny;
303 tmp_iny = iny[k];
304 iny[k] = iy[k];
305 iy[k] = tmp_iny;
Jean-Marc Valin41af4212007-11-30 18:35:37 +1100306 }
Jean-Marc Valin846d4e22008-02-12 13:48:48 +1100307 pulsesLeft -= pulsesAtOnce;
Jean-Marc Valin41af4212007-11-30 18:35:37 +1100308 }
309
Jean-Marc Valind4018c32008-02-27 10:09:48 +1100310#if 0
Jean-Marc Valinac1e03d2008-02-12 23:00:18 +1100311 if (0) {
Jean-Marc Valin877b1972008-02-29 16:40:39 +1100312 celt_word32_t err=0;
Jean-Marc Valinac1e03d2008-02-12 23:00:18 +1100313 for (i=0;i<N;i++)
Jean-Marc Valin3b277dc2008-02-14 16:46:50 +1100314 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 +1100315 /*if (N<=10)
316 printf ("%f %d %d\n", err, K, N);*/
Jean-Marc Valinac1e03d2008-02-12 23:00:18 +1100317 }
Jean-Marc Valin0d587d82008-02-14 21:29:50 +1100318 /* Sanity checks, don't bother */
Jean-Marc Valin1e7087e2007-12-04 13:05:43 +1100319 if (0) {
Jean-Marc Valind4018c32008-02-27 10:09:48 +1100320 for (i=0;i<N;i++)
321 x[i] = p[i]+nbest[0]->gain*y[0][i];
Jean-Marc Valin877b1972008-02-29 16:40:39 +1100322 celt_word32_t E=1e-15;
Jean-Marc Valin1e7087e2007-12-04 13:05:43 +1100323 int ABS = 0;
324 for (i=0;i<N;i++)
325 ABS += abs(iy[0][i]);
Jean-Marc Valina85657b2008-02-20 11:59:30 +1100326 /*if (K != ABS)
327 printf ("%d %d\n", K, ABS);*/
Jean-Marc Valin1e7087e2007-12-04 13:05:43 +1100328 for (i=0;i<N;i++)
329 E += x[i]*x[i];
Jean-Marc Valina85657b2008-02-20 11:59:30 +1100330 /*printf ("%f\n", E);*/
Jean-Marc Valin1e7087e2007-12-04 13:05:43 +1100331 E = 1/sqrt(E);
332 for (i=0;i<N;i++)
333 x[i] *= E;
334 }
Jean-Marc Valind4018c32008-02-27 10:09:48 +1100335#endif
Jean-Marc Valin5fa59952008-02-14 13:50:44 +1100336
337 encode_pulses(iy[0], N, K, enc);
338
Jean-Marc Valina4833ff2008-01-10 15:34:00 +1100339 /* Recompute the gain in one pass to reduce the encoder-decoder mismatch
Jean-Marc Valin636f5c82008-02-12 17:40:27 +1100340 due to the recursive computation used in quantisation.
341 Not quite sure whether we need that or not */
Jean-Marc Valind17edd32008-02-27 16:52:30 +1100342 mix_pitch_and_residual(iy[0], X, N, K, P, alpha);
Jean-Marc Valin8600f692008-02-29 15:14:12 +1100343 RESTORE_STACK;
Jean-Marc Valin41af4212007-11-30 18:35:37 +1100344}
345
Jean-Marc Valin879fbfd2008-02-20 17:17:13 +1100346/** Decode pulse vector and combine the result with the pitch vector to produce
347 the final normalised signal in the current band. */
Jean-Marc Valin9d8d9b32008-02-27 16:17:39 +1100348void alg_unquant(celt_norm_t *X, int N, int K, celt_norm_t *P, celt_word16_t alpha, ec_dec *dec)
Jean-Marc Valin0d227d82007-12-31 16:12:12 +1100349{
Jean-Marc Valin31b79d12008-03-12 17:17:23 +1100350 VARDECL(int, iy);
Jean-Marc Valin8600f692008-02-29 15:14:12 +1100351 SAVE_STACK;
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 Valin8600f692008-02-29 15:14:12 +1100355 RESTORE_STACK;
Jean-Marc Valin0d227d82007-12-31 16:12:12 +1100356}
357
Jean-Marc Valin9455d1b2008-03-07 17:17:37 +1100358#ifdef FIXED_POINT
359static const celt_word16_t pg[11] = {32767, 24576, 21299, 19661, 19661, 19661, 18022, 18022, 16384, 16384, 16384};
360#else
Jean-Marc Valin3e650972008-03-07 17:38:58 +1100361static 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 +1100362#endif
Jean-Marc Valin0d227d82007-12-31 16:12:12 +1100363
Jean-Marc Valin5f09ea52008-02-26 16:43:04 +1100364void 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 +1100365{
366 int i,j;
367 int best=0;
Jean-Marc Valin877b1972008-02-29 16:40:39 +1100368 celt_word32_t best_score=0;
369 celt_word16_t s = 1;
Jean-Marc Valin0aa39032007-12-07 15:09:58 +1100370 int sign;
Jean-Marc Valin877b1972008-02-29 16:40:39 +1100371 celt_word32_t E;
Jean-Marc Valin9455d1b2008-03-07 17:17:37 +1100372 celt_word16_t pred_gain;
Jean-Marc Valin8f0f4b92008-02-11 13:52:44 +1100373 int max_pos = N0-N/B;
374 if (max_pos > 32)
375 max_pos = 32;
376
377 for (i=0;i<max_pos*B;i+=B)
Jean-Marc Valin4841a0a2007-12-03 13:54:30 +1100378 {
379 int j;
Jean-Marc Valin877b1972008-02-29 16:40:39 +1100380 celt_word32_t xy=0, yy=0;
Jean-Marc Valin03892c12008-03-07 17:25:47 +1100381 celt_word32_t score;
Jean-Marc Valin4841a0a2007-12-03 13:54:30 +1100382 for (j=0;j<N;j++)
383 {
Jean-Marc Valin877b1972008-02-29 16:40:39 +1100384 xy = MAC16_16(xy, x[j], Y[i+N-j-1]);
385 yy = MAC16_16(yy, Y[i+N-j-1], Y[i+N-j-1]);
Jean-Marc Valin4841a0a2007-12-03 13:54:30 +1100386 }
Jean-Marc Valin03892c12008-03-07 17:25:47 +1100387 score = DIV32(MULT16_16(ROUND(xy,14),ROUND(xy,14)), ROUND(yy,14));
Jean-Marc Valin4841a0a2007-12-03 13:54:30 +1100388 if (score > best_score)
389 {
390 best_score = score;
391 best = i;
Jean-Marc Valin50d11162007-12-03 14:34:52 +1100392 if (xy>0)
393 s = 1;
394 else
395 s = -1;
Jean-Marc Valin4841a0a2007-12-03 13:54:30 +1100396 }
397 }
Jean-Marc Valin0aa39032007-12-07 15:09:58 +1100398 if (s<0)
399 sign = 1;
Jean-Marc Valin6e9058a2007-12-07 14:59:06 +1100400 else
Jean-Marc Valin0aa39032007-12-07 15:09:58 +1100401 sign = 0;
Jean-Marc Valina85657b2008-02-20 11:59:30 +1100402 /*printf ("%d %d ", sign, best);*/
Jean-Marc Valin0aa39032007-12-07 15:09:58 +1100403 ec_enc_uint(enc,sign,2);
Jean-Marc Valin8f0f4b92008-02-11 13:52:44 +1100404 ec_enc_uint(enc,best/B,max_pos);
Jean-Marc Valina85657b2008-02-20 11:59:30 +1100405 /*printf ("%d %f\n", best, best_score);*/
Jean-Marc Valin0d227d82007-12-31 16:12:12 +1100406
Jean-Marc Valin0d227d82007-12-31 16:12:12 +1100407 if (K>10)
408 pred_gain = pg[10];
409 else
410 pred_gain = pg[K];
Jean-Marc Valin03892c12008-03-07 17:25:47 +1100411 E = EPSILON;
Jean-Marc Valin0d227d82007-12-31 16:12:12 +1100412 for (j=0;j<N;j++)
Jean-Marc Valin4841a0a2007-12-03 13:54:30 +1100413 {
Jean-Marc Valind501f612008-02-21 12:16:57 +1100414 P[j] = s*Y[best+N-j-1];
Jean-Marc Valin877b1972008-02-29 16:40:39 +1100415 E = MAC16_16(E, P[j],P[j]);
Jean-Marc Valin4841a0a2007-12-03 13:54:30 +1100416 }
Jean-Marc Valin9455d1b2008-03-07 17:17:37 +1100417 /*pred_gain = pred_gain/sqrt(E);*/
418 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 +1100419 for (j=0;j<N;j++)
Jean-Marc Valin9455d1b2008-03-07 17:17:37 +1100420 P[j] = PSHR32(MULT16_16(pred_gain, P[j]),8);
Jean-Marc Valin0d227d82007-12-31 16:12:12 +1100421 if (K>0)
422 {
423 for (j=0;j<N;j++)
424 x[j] -= P[j];
425 } else {
426 for (j=0;j<N;j++)
427 x[j] = P[j];
428 }
Jean-Marc Valina85657b2008-02-20 11:59:30 +1100429 /*printf ("quant ");*/
430 /*for (j=0;j<N;j++) printf ("%f ", P[j]);*/
Jean-Marc Valin0d227d82007-12-31 16:12:12 +1100431
Jean-Marc Valin4841a0a2007-12-03 13:54:30 +1100432}
Jean-Marc Valinfc08d0a2007-12-07 13:26:15 +1100433
Jean-Marc Valin18ddc022008-02-22 14:24:50 +1100434void 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 +1100435{
Jean-Marc Valin11f01722007-12-09 01:19:36 +1100436 int j;
Jean-Marc Valin0aa39032007-12-07 15:09:58 +1100437 int sign;
Jean-Marc Valin877b1972008-02-29 16:40:39 +1100438 celt_word16_t s;
Jean-Marc Valin6e9058a2007-12-07 14:59:06 +1100439 int best;
Jean-Marc Valin877b1972008-02-29 16:40:39 +1100440 celt_word32_t E;
Jean-Marc Valin9455d1b2008-03-07 17:17:37 +1100441 celt_word16_t pred_gain;
Jean-Marc Valin8f0f4b92008-02-11 13:52:44 +1100442 int max_pos = N0-N/B;
443 if (max_pos > 32)
444 max_pos = 32;
445
Jean-Marc Valin0aa39032007-12-07 15:09:58 +1100446 sign = ec_dec_uint(dec, 2);
447 if (sign == 0)
Jean-Marc Valin6e9058a2007-12-07 14:59:06 +1100448 s = 1;
449 else
450 s = -1;
451
Jean-Marc Valin8f0f4b92008-02-11 13:52:44 +1100452 best = B*ec_dec_uint(dec, max_pos);
Jean-Marc Valina85657b2008-02-20 11:59:30 +1100453 /*printf ("%d %d ", sign, best);*/
Jean-Marc Valin6e9058a2007-12-07 14:59:06 +1100454
Jean-Marc Valin0d227d82007-12-31 16:12:12 +1100455 if (K>10)
456 pred_gain = pg[10];
457 else
458 pred_gain = pg[K];
Jean-Marc Valin9455d1b2008-03-07 17:17:37 +1100459 E = EPSILON;
Jean-Marc Valin0d227d82007-12-31 16:12:12 +1100460 for (j=0;j<N;j++)
461 {
Jean-Marc Valind501f612008-02-21 12:16:57 +1100462 P[j] = s*Y[best+N-j-1];
Jean-Marc Valin877b1972008-02-29 16:40:39 +1100463 E = MAC16_16(E, P[j],P[j]);
Jean-Marc Valin0d227d82007-12-31 16:12:12 +1100464 }
Jean-Marc Valin9455d1b2008-03-07 17:17:37 +1100465 /*pred_gain = pred_gain/sqrt(E);*/
466 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 +1100467 for (j=0;j<N;j++)
Jean-Marc Valin9455d1b2008-03-07 17:17:37 +1100468 P[j] = PSHR32(MULT16_16(pred_gain, P[j]),8);
Jean-Marc Valin6e9058a2007-12-07 14:59:06 +1100469 if (K==0)
470 {
Jean-Marc Valin6e9058a2007-12-07 14:59:06 +1100471 for (j=0;j<N;j++)
Jean-Marc Valin0d227d82007-12-31 16:12:12 +1100472 x[j] = P[j];
Jean-Marc Valin6e9058a2007-12-07 14:59:06 +1100473 }
474}
Jean-Marc Valin0e20ca02008-02-11 15:33:53 +1100475
Jean-Marc Valin18ddc022008-02-22 14:24:50 +1100476void 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 +1100477{
Jean-Marc Valin0df0eb42008-02-13 16:00:10 +1100478 int i, j;
Jean-Marc Valin877b1972008-02-29 16:40:39 +1100479 celt_word32_t E;
Jean-Marc Valinec9b6df2008-03-07 17:05:47 +1100480 celt_word16_t g;
Jean-Marc Valin0e20ca02008-02-11 15:33:53 +1100481
Jean-Marc Valinec9b6df2008-03-07 17:05:47 +1100482 E = EPSILON;
Jean-Marc Valin0df0eb42008-02-13 16:00:10 +1100483 if (N0 >= Nmax/2)
Jean-Marc Valin0e20ca02008-02-11 15:33:53 +1100484 {
Jean-Marc Valin0df0eb42008-02-13 16:00:10 +1100485 for (i=0;i<B;i++)
486 {
487 for (j=0;j<N/B;j++)
488 {
489 P[j*B+i] = Y[(Nmax-N0-j-1)*B+i];
Jean-Marc Valin877b1972008-02-29 16:40:39 +1100490 E += P[j*B+i]*P[j*B+i];
Jean-Marc Valin0df0eb42008-02-13 16:00:10 +1100491 }
492 }
493 } else {
494 for (j=0;j<N;j++)
495 {
496 P[j] = Y[j];
Jean-Marc Valin877b1972008-02-29 16:40:39 +1100497 E = MAC16_16(E, P[j],P[j]);
Jean-Marc Valin0df0eb42008-02-13 16:00:10 +1100498 }
Jean-Marc Valin0e20ca02008-02-11 15:33:53 +1100499 }
Jean-Marc Valinec9b6df2008-03-07 17:05:47 +1100500 g = DIV32_16(SHL32(EXTEND32(1),14+8),celt_sqrt(E));
Jean-Marc Valin0e20ca02008-02-11 15:33:53 +1100501 for (j=0;j<N;j++)
Jean-Marc Valinec9b6df2008-03-07 17:05:47 +1100502 P[j] = PSHR32(MULT16_16(g, P[j]),8);
Jean-Marc Valin0e20ca02008-02-11 15:33:53 +1100503 for (j=0;j<N;j++)
504 x[j] = P[j];
505}
506