blob: 0fe25262dd97bbfdd9ad4bb8fb6ed3c61be4c58f [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 Valind17edd32008-02-27 16:52:30 +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 Valina02ca1e2008-02-28 11:33:22 +110088 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 +110089
90 for (i=0;i<N;i++)
Jean-Marc Valina847b772008-02-27 17:46:49 +110091 X[i] = P[i] + MULT16_32_Q14(y[i], g);
Jean-Marc Valin8600f692008-02-29 15:14:12 +110092 RESTORE_STACK;
Jean-Marc Valind4018c32008-02-27 10:09:48 +110093}
94
Jean-Marc Valin879fbfd2008-02-20 17:17:13 +110095/** All the info necessary to keep track of a hypothesis during the search */
Jean-Marc Valin3b277dc2008-02-14 16:46:50 +110096struct NBest {
Jean-Marc Valin4e1328b2008-02-28 15:14:07 +110097 celt_word32_t score;
Jean-Marc Valin3b277dc2008-02-14 16:46:50 +110098 int sign;
99 int pos;
100 int orig;
Jean-Marc Valin4e1328b2008-02-28 15:14:07 +1100101 celt_word32_t xy;
102 celt_word32_t yy;
103 celt_word32_t yp;
Jean-Marc Valin3b277dc2008-02-14 16:46:50 +1100104};
Jean-Marc Valin41af4212007-11-30 18:35:37 +1100105
Jean-Marc Valin31213272008-03-03 16:52:54 +1100106void 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 +1100107{
Jean-Marc Valin4a897682007-12-12 00:45:15 +1100108 int L = 3;
Jean-Marc Valin8b158f52008-02-28 14:44:19 +1100109 VARDECL(celt_norm_t *_y);
110 VARDECL(celt_norm_t *_ny);
Jean-Marc Valin9a0bba12008-02-20 14:08:50 +1100111 VARDECL(int *_iy);
112 VARDECL(int *_iny);
Jean-Marc Valin8b158f52008-02-28 14:44:19 +1100113 VARDECL(celt_norm_t **y);
114 VARDECL(celt_norm_t **ny);
Jean-Marc Valin9a0bba12008-02-20 14:08:50 +1100115 VARDECL(int **iy);
116 VARDECL(int **iny);
Jean-Marc Valin0d587d82008-02-14 21:29:50 +1100117 int i, j, k, m;
Jean-Marc Valin846d4e22008-02-12 13:48:48 +1100118 int pulsesLeft;
Jean-Marc Valined9e4232008-02-28 12:22:22 +1100119 VARDECL(celt_word32_t *xy);
120 VARDECL(celt_word32_t *yy);
121 VARDECL(celt_word32_t *yp);
Jean-Marc Valin9a0bba12008-02-20 14:08:50 +1100122 VARDECL(struct NBest *_nbest);
123 VARDECL(struct NBest **nbest);
Jean-Marc Valinf675adc2008-02-28 12:15:17 +1100124 celt_word32_t Rpp=0, Rxp=0;
Jean-Marc Valin41af4212007-11-30 18:35:37 +1100125 int maxL = 1;
Jean-Marc Valinf675adc2008-02-28 12:15:17 +1100126#ifdef FIXED_POINT
Jean-Marc Valind748cd52008-03-01 07:27:03 +1100127 int yshift;
128#endif
129 SAVE_STACK;
130
131#ifdef FIXED_POINT
132 yshift = 14-EC_ILOG(K);
Jean-Marc Valinf675adc2008-02-28 12:15:17 +1100133#endif
Jean-Marc Valin9d8d9b32008-02-27 16:17:39 +1100134
Jean-Marc Valin8b158f52008-02-28 14:44:19 +1100135 ALLOC(_y, L*N, celt_norm_t);
136 ALLOC(_ny, L*N, celt_norm_t);
Jean-Marc Valin9a0bba12008-02-20 14:08:50 +1100137 ALLOC(_iy, L*N, int);
138 ALLOC(_iny, L*N, int);
Jean-Marc Valincac91ec2008-02-29 17:03:34 +1100139 ALLOC(y, L, celt_norm_t*);
140 ALLOC(ny, L, celt_norm_t*);
141 ALLOC(iy, L, int*);
142 ALLOC(iny, L, int*);
Jean-Marc Valin9a0bba12008-02-20 14:08:50 +1100143
Jean-Marc Valined9e4232008-02-28 12:22:22 +1100144 ALLOC(xy, L, celt_word32_t);
145 ALLOC(yy, L, celt_word32_t);
146 ALLOC(yp, L, celt_word32_t);
Jean-Marc Valin9a0bba12008-02-20 14:08:50 +1100147 ALLOC(_nbest, L, struct NBest);
148 ALLOC(nbest, L, struct NBest *);
Jean-Marc Valinb4dfce42008-02-25 17:41:30 +1100149
Jean-Marc Valinfe419832008-02-12 15:05:01 +1100150 for (m=0;m<L;m++)
Jean-Marc Valin3b277dc2008-02-14 16:46:50 +1100151 nbest[m] = &_nbest[m];
152
153 for (m=0;m<L;m++)
Jean-Marc Valinfe419832008-02-12 15:05:01 +1100154 {
Jean-Marc Valin9a0bba12008-02-20 14:08:50 +1100155 ny[m] = &_ny[m*N];
156 iny[m] = &_iny[m*N];
157 y[m] = &_y[m*N];
158 iy[m] = &_iy[m*N];
Jean-Marc Valinfe419832008-02-12 15:05:01 +1100159 }
160
Jean-Marc Valin41af4212007-11-30 18:35:37 +1100161 for (j=0;j<N;j++)
Jean-Marc Valin0d587d82008-02-14 21:29:50 +1100162 {
Jean-Marc Valinf675adc2008-02-28 12:15:17 +1100163 Rpp = MAC16_16(Rpp, P[j],P[j]);
164 Rxp = MAC16_16(Rxp, X[j],P[j]);
Jean-Marc Valin0d587d82008-02-14 21:29:50 +1100165 }
Jean-Marc Valinf675adc2008-02-28 12:15:17 +1100166 Rpp = ROUND(Rpp, NORM_SHIFT);
167 Rxp = ROUND(Rxp, NORM_SHIFT);
168 if (Rpp>NORM_SCALING)
Jean-Marc Valinb60340f2008-02-26 15:41:51 +1100169 celt_fatal("Rpp > 1");
170
Jean-Marc Valin0d587d82008-02-14 21:29:50 +1100171 /* We only need to initialise the zero because the first iteration only uses that */
172 for (i=0;i<N;i++)
173 y[0][i] = 0;
174 for (i=0;i<N;i++)
175 iy[0][i] = 0;
176 xy[0] = yy[0] = yp[0] = 0;
177
Jean-Marc Valin846d4e22008-02-12 13:48:48 +1100178 pulsesLeft = K;
179 while (pulsesLeft > 0)
Jean-Marc Valin41af4212007-11-30 18:35:37 +1100180 {
Jean-Marc Valin846d4e22008-02-12 13:48:48 +1100181 int pulsesAtOnce=1;
Jean-Marc Valincab576e2008-02-12 17:21:14 +1100182 int Lupdate = L;
Jean-Marc Valin41af4212007-11-30 18:35:37 +1100183 int L2 = L;
Jean-Marc Valin0d587d82008-02-14 21:29:50 +1100184
185 /* Decide on complexity strategy */
Jean-Marc Valincab576e2008-02-12 17:21:14 +1100186 pulsesAtOnce = pulsesLeft/N;
187 if (pulsesAtOnce<1)
188 pulsesAtOnce = 1;
189 if (pulsesLeft-pulsesAtOnce > 3 || N > 30)
190 Lupdate = 1;
Jean-Marc Valina85657b2008-02-20 11:59:30 +1100191 /*printf ("%d %d %d/%d %d\n", Lupdate, pulsesAtOnce, pulsesLeft, K, N);*/
Jean-Marc Valincab576e2008-02-12 17:21:14 +1100192 L2 = Lupdate;
193 if (L2>maxL)
Jean-Marc Valin41af4212007-11-30 18:35:37 +1100194 {
195 L2 = maxL;
196 maxL *= N;
197 }
Jean-Marc Valin846d4e22008-02-12 13:48:48 +1100198
Jean-Marc Valin0d587d82008-02-14 21:29:50 +1100199 for (m=0;m<Lupdate;m++)
Jean-Marc Valin4e1328b2008-02-28 15:14:07 +1100200 nbest[m]->score = -VERY_LARGE32;
Jean-Marc Valin41af4212007-11-30 18:35:37 +1100201
202 for (m=0;m<L2;m++)
203 {
204 for (j=0;j<N;j++)
205 {
Jean-Marc Valin1e7087e2007-12-04 13:05:43 +1100206 int sign;
Jean-Marc Valin0d587d82008-02-14 21:29:50 +1100207 /*if (x[j]>0) sign=1; else sign=-1;*/
Jean-Marc Valin1e7087e2007-12-04 13:05:43 +1100208 for (sign=-1;sign<=1;sign+=2)
Jean-Marc Valin41af4212007-11-30 18:35:37 +1100209 {
Jean-Marc Valina85657b2008-02-20 11:59:30 +1100210 /*fprintf (stderr, "%d/%d %d/%d %d/%d\n", i, K, m, L2, j, N);*/
Jean-Marc Valin4e1328b2008-02-28 15:14:07 +1100211 celt_word32_t Rxy, Ryy, Ryp;
212 celt_word16_t spj, aspj; /* Intermediate results */
213 celt_word32_t score;
214 celt_word32_t g;
Jean-Marc Valinc9d606f2008-02-28 13:46:20 +1100215 celt_word16_t s = SHL16(sign*pulsesAtOnce, yshift);
Jean-Marc Valinfe419832008-02-12 15:05:01 +1100216
Jean-Marc Valin9a0bba12008-02-20 14:08:50 +1100217 /* All pulses at one location must have the same sign. */
218 if (iy[m][j]*sign < 0)
219 continue;
220
Jean-Marc Valinc9d606f2008-02-28 13:46:20 +1100221 spj = MULT16_16_P14(s, P[j]);
Jean-Marc Valin642ff942008-02-28 14:33:19 +1100222 aspj = MULT16_16_P15(alpha, spj);
Jean-Marc Valina073c7b2008-02-14 16:58:04 +1100223 /* Updating the sums of the new pulse(s) */
Jean-Marc Valin4e1328b2008-02-28 15:14:07 +1100224 Rxy = xy[m] + MULT16_16(s,X[j]) - MULT16_16(MULT16_16_P15(alpha,spj),Rxp);
225 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]));
226 Ryp = yp[m] + MULT16_16(spj, SUB16(QCONST16(1.f,14),MULT16_16_Q15(alpha,Rpp)));
Jean-Marc Valina073c7b2008-02-14 16:58:04 +1100227
228 /* Compute the gain such that ||p + g*y|| = 1 */
Jean-Marc Valin4e1328b2008-02-28 15:14:07 +1100229 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 +1100230
Jean-Marc Valina073c7b2008-02-14 16:58:04 +1100231 /* Knowing that gain, what the error: (x-g*y)^2
232 (result is negated and we discard x^2 because it's constant) */
Jean-Marc Valin4e1328b2008-02-28 15:14:07 +1100233 /*score = 2.f*g*Rxy - 1.f*g*g*Ryy*NORM_SCALING_1;*/
234 score = 2*MULT16_32_Q14(ROUND(Rxy,14),g) -
235 MULT16_32_Q14(EXTRACT16(MULT16_32_Q14(ROUND(Ryy,14),g)),g);
Jean-Marc Valin41af4212007-11-30 18:35:37 +1100236
Jean-Marc Valin3b277dc2008-02-14 16:46:50 +1100237 if (score>nbest[Lupdate-1]->score)
Jean-Marc Valin1e7087e2007-12-04 13:05:43 +1100238 {
Jean-Marc Valin472a5f02008-02-19 13:12:32 +1100239 int k;
Jean-Marc Valincab576e2008-02-12 17:21:14 +1100240 int id = Lupdate-1;
Jean-Marc Valin3b277dc2008-02-14 16:46:50 +1100241 struct NBest *tmp_best;
242
243 /* Save some pointers that would be deleted and use them for the current entry*/
244 tmp_best = nbest[Lupdate-1];
245 while (id > 0 && score > nbest[id-1]->score)
Jean-Marc Valin1e7087e2007-12-04 13:05:43 +1100246 id--;
247
Jean-Marc Valincab576e2008-02-12 17:21:14 +1100248 for (k=Lupdate-1;k>id;k--)
Jean-Marc Valin3b277dc2008-02-14 16:46:50 +1100249 nbest[k] = nbest[k-1];
Jean-Marc Valin1e7087e2007-12-04 13:05:43 +1100250
Jean-Marc Valin3b277dc2008-02-14 16:46:50 +1100251 nbest[id] = tmp_best;
252 nbest[id]->score = score;
253 nbest[id]->pos = j;
254 nbest[id]->orig = m;
255 nbest[id]->sign = sign;
Jean-Marc Valin4e1328b2008-02-28 15:14:07 +1100256 nbest[id]->xy = Rxy;
257 nbest[id]->yy = Ryy;
258 nbest[id]->yp = Ryp;
Jean-Marc Valin1e7087e2007-12-04 13:05:43 +1100259 }
Jean-Marc Valin636f5c82008-02-12 17:40:27 +1100260 }
Jean-Marc Valin41af4212007-11-30 18:35:37 +1100261 }
Jean-Marc Valin636f5c82008-02-12 17:40:27 +1100262
Jean-Marc Valin41af4212007-11-30 18:35:37 +1100263 }
Jean-Marc Valinb60340f2008-02-26 15:41:51 +1100264
Jean-Marc Valin4e1328b2008-02-28 15:14:07 +1100265 if (!(nbest[0]->score > -VERY_LARGE32))
Jean-Marc Valinb60340f2008-02-26 15:41:51 +1100266 celt_fatal("Could not find any match in VQ codebook. Something got corrupted somewhere.");
Jean-Marc Valin0d587d82008-02-14 21:29:50 +1100267 /* Only now that we've made the final choice, update ny/iny and others */
Jean-Marc Valincab576e2008-02-12 17:21:14 +1100268 for (k=0;k<Lupdate;k++)
Jean-Marc Valin41af4212007-11-30 18:35:37 +1100269 {
Jean-Marc Valin3b277dc2008-02-14 16:46:50 +1100270 int n;
271 int is;
Jean-Marc Valin8b158f52008-02-28 14:44:19 +1100272 celt_norm_t s;
Jean-Marc Valin3b277dc2008-02-14 16:46:50 +1100273 is = nbest[k]->sign*pulsesAtOnce;
Jean-Marc Valinf675adc2008-02-28 12:15:17 +1100274 s = SHL16(is, yshift);
Jean-Marc Valin3b277dc2008-02-14 16:46:50 +1100275 for (n=0;n<N;n++)
Jean-Marc Valin8b158f52008-02-28 14:44:19 +1100276 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 +1100277 ny[k][nbest[k]->pos] += s;
Jean-Marc Valin0d587d82008-02-14 21:29:50 +1100278
Jean-Marc Valin3b277dc2008-02-14 16:46:50 +1100279 for (n=0;n<N;n++)
280 iny[k][n] = iy[nbest[k]->orig][n];
281 iny[k][nbest[k]->pos] += is;
Jean-Marc Valin0d587d82008-02-14 21:29:50 +1100282
Jean-Marc Valin3b277dc2008-02-14 16:46:50 +1100283 xy[k] = nbest[k]->xy;
284 yy[k] = nbest[k]->yy;
285 yp[k] = nbest[k]->yp;
286 }
Jean-Marc Valin0d587d82008-02-14 21:29:50 +1100287 /* Swap ny/iny with y/iy */
Jean-Marc Valin3b277dc2008-02-14 16:46:50 +1100288 for (k=0;k<Lupdate;k++)
289 {
Jean-Marc Valin8b158f52008-02-28 14:44:19 +1100290 celt_norm_t *tmp_ny;
Jean-Marc Valinfe419832008-02-12 15:05:01 +1100291 int *tmp_iny;
292
Jean-Marc Valinfe419832008-02-12 15:05:01 +1100293 tmp_ny = ny[k];
294 ny[k] = y[k];
295 y[k] = tmp_ny;
296 tmp_iny = iny[k];
297 iny[k] = iy[k];
298 iy[k] = tmp_iny;
Jean-Marc Valin41af4212007-11-30 18:35:37 +1100299 }
Jean-Marc Valin846d4e22008-02-12 13:48:48 +1100300 pulsesLeft -= pulsesAtOnce;
Jean-Marc Valin41af4212007-11-30 18:35:37 +1100301 }
302
Jean-Marc Valind4018c32008-02-27 10:09:48 +1100303#if 0
Jean-Marc Valinac1e03d2008-02-12 23:00:18 +1100304 if (0) {
Jean-Marc Valin877b1972008-02-29 16:40:39 +1100305 celt_word32_t err=0;
Jean-Marc Valinac1e03d2008-02-12 23:00:18 +1100306 for (i=0;i<N;i++)
Jean-Marc Valin3b277dc2008-02-14 16:46:50 +1100307 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 +1100308 /*if (N<=10)
309 printf ("%f %d %d\n", err, K, N);*/
Jean-Marc Valinac1e03d2008-02-12 23:00:18 +1100310 }
Jean-Marc Valin0d587d82008-02-14 21:29:50 +1100311 /* Sanity checks, don't bother */
Jean-Marc Valin1e7087e2007-12-04 13:05:43 +1100312 if (0) {
Jean-Marc Valind4018c32008-02-27 10:09:48 +1100313 for (i=0;i<N;i++)
314 x[i] = p[i]+nbest[0]->gain*y[0][i];
Jean-Marc Valin877b1972008-02-29 16:40:39 +1100315 celt_word32_t E=1e-15;
Jean-Marc Valin1e7087e2007-12-04 13:05:43 +1100316 int ABS = 0;
317 for (i=0;i<N;i++)
318 ABS += abs(iy[0][i]);
Jean-Marc Valina85657b2008-02-20 11:59:30 +1100319 /*if (K != ABS)
320 printf ("%d %d\n", K, ABS);*/
Jean-Marc Valin1e7087e2007-12-04 13:05:43 +1100321 for (i=0;i<N;i++)
322 E += x[i]*x[i];
Jean-Marc Valina85657b2008-02-20 11:59:30 +1100323 /*printf ("%f\n", E);*/
Jean-Marc Valin1e7087e2007-12-04 13:05:43 +1100324 E = 1/sqrt(E);
325 for (i=0;i<N;i++)
326 x[i] *= E;
327 }
Jean-Marc Valind4018c32008-02-27 10:09:48 +1100328#endif
Jean-Marc Valin5fa59952008-02-14 13:50:44 +1100329
330 encode_pulses(iy[0], N, K, enc);
331
Jean-Marc Valina4833ff2008-01-10 15:34:00 +1100332 /* Recompute the gain in one pass to reduce the encoder-decoder mismatch
Jean-Marc Valin636f5c82008-02-12 17:40:27 +1100333 due to the recursive computation used in quantisation.
334 Not quite sure whether we need that or not */
Jean-Marc Valind17edd32008-02-27 16:52:30 +1100335 mix_pitch_and_residual(iy[0], X, N, K, P, alpha);
Jean-Marc Valin8600f692008-02-29 15:14:12 +1100336 RESTORE_STACK;
Jean-Marc Valin41af4212007-11-30 18:35:37 +1100337}
338
Jean-Marc Valin879fbfd2008-02-20 17:17:13 +1100339/** Decode pulse vector and combine the result with the pitch vector to produce
340 the final normalised signal in the current band. */
Jean-Marc Valin9d8d9b32008-02-27 16:17:39 +1100341void 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 +1100342{
Jean-Marc Valin9a0bba12008-02-20 14:08:50 +1100343 VARDECL(int *iy);
Jean-Marc Valin8600f692008-02-29 15:14:12 +1100344 SAVE_STACK;
Jean-Marc Valin9a0bba12008-02-20 14:08:50 +1100345 ALLOC(iy, N, int);
Jean-Marc Valin5fa59952008-02-14 13:50:44 +1100346 decode_pulses(iy, N, K, dec);
Jean-Marc Valind17edd32008-02-27 16:52:30 +1100347 mix_pitch_and_residual(iy, X, N, K, P, alpha);
Jean-Marc Valin8600f692008-02-29 15:14:12 +1100348 RESTORE_STACK;
Jean-Marc Valin0d227d82007-12-31 16:12:12 +1100349}
350
Jean-Marc Valin9455d1b2008-03-07 17:17:37 +1100351#ifdef FIXED_POINT
352static const celt_word16_t pg[11] = {32767, 24576, 21299, 19661, 19661, 19661, 18022, 18022, 16384, 16384, 16384};
353#else
Jean-Marc Valin3e650972008-03-07 17:38:58 +1100354static 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 +1100355#endif
Jean-Marc Valin0d227d82007-12-31 16:12:12 +1100356
Jean-Marc Valin5f09ea52008-02-26 16:43:04 +1100357void 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 +1100358{
359 int i,j;
360 int best=0;
Jean-Marc Valin877b1972008-02-29 16:40:39 +1100361 celt_word32_t best_score=0;
362 celt_word16_t s = 1;
Jean-Marc Valin0aa39032007-12-07 15:09:58 +1100363 int sign;
Jean-Marc Valin877b1972008-02-29 16:40:39 +1100364 celt_word32_t E;
Jean-Marc Valin9455d1b2008-03-07 17:17:37 +1100365 celt_word16_t pred_gain;
Jean-Marc Valin8f0f4b92008-02-11 13:52:44 +1100366 int max_pos = N0-N/B;
367 if (max_pos > 32)
368 max_pos = 32;
369
370 for (i=0;i<max_pos*B;i+=B)
Jean-Marc Valin4841a0a2007-12-03 13:54:30 +1100371 {
372 int j;
Jean-Marc Valin877b1972008-02-29 16:40:39 +1100373 celt_word32_t xy=0, yy=0;
Jean-Marc Valin03892c12008-03-07 17:25:47 +1100374 celt_word32_t score;
Jean-Marc Valin4841a0a2007-12-03 13:54:30 +1100375 for (j=0;j<N;j++)
376 {
Jean-Marc Valin877b1972008-02-29 16:40:39 +1100377 xy = MAC16_16(xy, x[j], Y[i+N-j-1]);
378 yy = MAC16_16(yy, Y[i+N-j-1], Y[i+N-j-1]);
Jean-Marc Valin4841a0a2007-12-03 13:54:30 +1100379 }
Jean-Marc Valin03892c12008-03-07 17:25:47 +1100380 score = DIV32(MULT16_16(ROUND(xy,14),ROUND(xy,14)), ROUND(yy,14));
Jean-Marc Valin4841a0a2007-12-03 13:54:30 +1100381 if (score > best_score)
382 {
383 best_score = score;
384 best = i;
Jean-Marc Valin50d11162007-12-03 14:34:52 +1100385 if (xy>0)
386 s = 1;
387 else
388 s = -1;
Jean-Marc Valin4841a0a2007-12-03 13:54:30 +1100389 }
390 }
Jean-Marc Valin0aa39032007-12-07 15:09:58 +1100391 if (s<0)
392 sign = 1;
Jean-Marc Valin6e9058a2007-12-07 14:59:06 +1100393 else
Jean-Marc Valin0aa39032007-12-07 15:09:58 +1100394 sign = 0;
Jean-Marc Valina85657b2008-02-20 11:59:30 +1100395 /*printf ("%d %d ", sign, best);*/
Jean-Marc Valin0aa39032007-12-07 15:09:58 +1100396 ec_enc_uint(enc,sign,2);
Jean-Marc Valin8f0f4b92008-02-11 13:52:44 +1100397 ec_enc_uint(enc,best/B,max_pos);
Jean-Marc Valina85657b2008-02-20 11:59:30 +1100398 /*printf ("%d %f\n", best, best_score);*/
Jean-Marc Valin0d227d82007-12-31 16:12:12 +1100399
Jean-Marc Valin0d227d82007-12-31 16:12:12 +1100400 if (K>10)
401 pred_gain = pg[10];
402 else
403 pred_gain = pg[K];
Jean-Marc Valin03892c12008-03-07 17:25:47 +1100404 E = EPSILON;
Jean-Marc Valin0d227d82007-12-31 16:12:12 +1100405 for (j=0;j<N;j++)
Jean-Marc Valin4841a0a2007-12-03 13:54:30 +1100406 {
Jean-Marc Valind501f612008-02-21 12:16:57 +1100407 P[j] = s*Y[best+N-j-1];
Jean-Marc Valin877b1972008-02-29 16:40:39 +1100408 E = MAC16_16(E, P[j],P[j]);
Jean-Marc Valin4841a0a2007-12-03 13:54:30 +1100409 }
Jean-Marc Valin9455d1b2008-03-07 17:17:37 +1100410 /*pred_gain = pred_gain/sqrt(E);*/
411 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 +1100412 for (j=0;j<N;j++)
Jean-Marc Valin9455d1b2008-03-07 17:17:37 +1100413 P[j] = PSHR32(MULT16_16(pred_gain, P[j]),8);
Jean-Marc Valin0d227d82007-12-31 16:12:12 +1100414 if (K>0)
415 {
416 for (j=0;j<N;j++)
417 x[j] -= P[j];
418 } else {
419 for (j=0;j<N;j++)
420 x[j] = P[j];
421 }
Jean-Marc Valina85657b2008-02-20 11:59:30 +1100422 /*printf ("quant ");*/
423 /*for (j=0;j<N;j++) printf ("%f ", P[j]);*/
Jean-Marc Valin0d227d82007-12-31 16:12:12 +1100424
Jean-Marc Valin4841a0a2007-12-03 13:54:30 +1100425}
Jean-Marc Valinfc08d0a2007-12-07 13:26:15 +1100426
Jean-Marc Valin18ddc022008-02-22 14:24:50 +1100427void 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 +1100428{
Jean-Marc Valin11f01722007-12-09 01:19:36 +1100429 int j;
Jean-Marc Valin0aa39032007-12-07 15:09:58 +1100430 int sign;
Jean-Marc Valin877b1972008-02-29 16:40:39 +1100431 celt_word16_t s;
Jean-Marc Valin6e9058a2007-12-07 14:59:06 +1100432 int best;
Jean-Marc Valin877b1972008-02-29 16:40:39 +1100433 celt_word32_t E;
Jean-Marc Valin9455d1b2008-03-07 17:17:37 +1100434 celt_word16_t pred_gain;
Jean-Marc Valin8f0f4b92008-02-11 13:52:44 +1100435 int max_pos = N0-N/B;
436 if (max_pos > 32)
437 max_pos = 32;
438
Jean-Marc Valin0aa39032007-12-07 15:09:58 +1100439 sign = ec_dec_uint(dec, 2);
440 if (sign == 0)
Jean-Marc Valin6e9058a2007-12-07 14:59:06 +1100441 s = 1;
442 else
443 s = -1;
444
Jean-Marc Valin8f0f4b92008-02-11 13:52:44 +1100445 best = B*ec_dec_uint(dec, max_pos);
Jean-Marc Valina85657b2008-02-20 11:59:30 +1100446 /*printf ("%d %d ", sign, best);*/
Jean-Marc Valin6e9058a2007-12-07 14:59:06 +1100447
Jean-Marc Valin0d227d82007-12-31 16:12:12 +1100448 if (K>10)
449 pred_gain = pg[10];
450 else
451 pred_gain = pg[K];
Jean-Marc Valin9455d1b2008-03-07 17:17:37 +1100452 E = EPSILON;
Jean-Marc Valin0d227d82007-12-31 16:12:12 +1100453 for (j=0;j<N;j++)
454 {
Jean-Marc Valind501f612008-02-21 12:16:57 +1100455 P[j] = s*Y[best+N-j-1];
Jean-Marc Valin877b1972008-02-29 16:40:39 +1100456 E = MAC16_16(E, P[j],P[j]);
Jean-Marc Valin0d227d82007-12-31 16:12:12 +1100457 }
Jean-Marc Valin9455d1b2008-03-07 17:17:37 +1100458 /*pred_gain = pred_gain/sqrt(E);*/
459 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 +1100460 for (j=0;j<N;j++)
Jean-Marc Valin9455d1b2008-03-07 17:17:37 +1100461 P[j] = PSHR32(MULT16_16(pred_gain, P[j]),8);
Jean-Marc Valin6e9058a2007-12-07 14:59:06 +1100462 if (K==0)
463 {
Jean-Marc Valin6e9058a2007-12-07 14:59:06 +1100464 for (j=0;j<N;j++)
Jean-Marc Valin0d227d82007-12-31 16:12:12 +1100465 x[j] = P[j];
Jean-Marc Valin6e9058a2007-12-07 14:59:06 +1100466 }
467}
Jean-Marc Valin0e20ca02008-02-11 15:33:53 +1100468
Jean-Marc Valin18ddc022008-02-22 14:24:50 +1100469void 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 +1100470{
Jean-Marc Valin0df0eb42008-02-13 16:00:10 +1100471 int i, j;
Jean-Marc Valin877b1972008-02-29 16:40:39 +1100472 celt_word32_t E;
Jean-Marc Valinec9b6df2008-03-07 17:05:47 +1100473 celt_word16_t g;
Jean-Marc Valin0e20ca02008-02-11 15:33:53 +1100474
Jean-Marc Valinec9b6df2008-03-07 17:05:47 +1100475 E = EPSILON;
Jean-Marc Valin0df0eb42008-02-13 16:00:10 +1100476 if (N0 >= Nmax/2)
Jean-Marc Valin0e20ca02008-02-11 15:33:53 +1100477 {
Jean-Marc Valin0df0eb42008-02-13 16:00:10 +1100478 for (i=0;i<B;i++)
479 {
480 for (j=0;j<N/B;j++)
481 {
482 P[j*B+i] = Y[(Nmax-N0-j-1)*B+i];
Jean-Marc Valin877b1972008-02-29 16:40:39 +1100483 E += P[j*B+i]*P[j*B+i];
Jean-Marc Valin0df0eb42008-02-13 16:00:10 +1100484 }
485 }
486 } else {
487 for (j=0;j<N;j++)
488 {
489 P[j] = Y[j];
Jean-Marc Valin877b1972008-02-29 16:40:39 +1100490 E = MAC16_16(E, P[j],P[j]);
Jean-Marc Valin0df0eb42008-02-13 16:00:10 +1100491 }
Jean-Marc Valin0e20ca02008-02-11 15:33:53 +1100492 }
Jean-Marc Valinec9b6df2008-03-07 17:05:47 +1100493 g = DIV32_16(SHL32(EXTEND32(1),14+8),celt_sqrt(E));
Jean-Marc Valin0e20ca02008-02-11 15:33:53 +1100494 for (j=0;j<N;j++)
Jean-Marc Valinec9b6df2008-03-07 17:05:47 +1100495 P[j] = PSHR32(MULT16_16(g, P[j]),8);
Jean-Marc Valin0e20ca02008-02-11 15:33:53 +1100496 for (j=0;j<N;j++)
497 x[j] = P[j];
498}
499