blob: 3835aa6f404e1d810b86b6866c769f6e30113490 [file] [log] [blame]
Jean-Marc Valin41af4212007-11-30 18:35:37 +11001/* (C) 2007 Jean-Marc Valin, CSIRO
2*/
3/*
4 Redistribution and use in source and binary forms, with or without
5 modification, are permitted provided that the following conditions
6 are met:
7
8 - Redistributions of source code must retain the above copyright
9 notice, this list of conditions and the following disclaimer.
10
11 - Redistributions in binary form must reproduce the above copyright
12 notice, this list of conditions and the following disclaimer in the
13 documentation and/or other materials provided with the distribution.
14
15 - Neither the name of the Xiph.org Foundation nor the names of its
16 contributors may be used to endorse or promote products derived from
17 this software without specific prior written permission.
18
19 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20 ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21 LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22 A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR
23 CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
24 EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
25 PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
26 PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
27 LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
28 NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
29 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30*/
31
Jean-Marc Valin02fa9132008-02-20 12:09:29 +110032#ifdef HAVE_CONFIG_H
33#include "config.h"
34#endif
35
Jean-Marc Valin41af4212007-11-30 18:35:37 +110036#include <math.h>
37#include <stdlib.h>
Jean-Marc Valin3ca9b1d2008-02-27 23:50:31 +110038#include "mathops.h"
Jean-Marc Valin29ccab82007-12-06 15:39:38 +110039#include "cwrs.h"
Jean-Marc Valin9cace642007-12-06 17:44:09 +110040#include "vq.h"
Jean-Marc Valin9a0bba12008-02-20 14:08:50 +110041#include "arch.h"
Jean-Marc Valinb60340f2008-02-26 15:41:51 +110042#include "os_support.h"
Jean-Marc Valin41af4212007-11-30 18:35:37 +110043
Jean-Marc Valin883bd8e2008-02-15 00:34:01 +110044/* Enable this or define your own implementation if you want to speed up the
45 VQ search (used in inner loop only) */
46#if 0
47#include <xmmintrin.h>
48static inline float approx_sqrt(float x)
49{
50 _mm_store_ss(&x, _mm_sqrt_ss(_mm_set_ss(x)));
51 return x;
52}
53static inline float approx_inv(float x)
54{
55 _mm_store_ss(&x, _mm_rcp_ss(_mm_set_ss(x)));
56 return x;
57}
58#else
59#define approx_sqrt(x) (sqrt(x))
60#define approx_inv(x) (1.f/(x))
61#endif
62
Jean-Marc Valind4018c32008-02-27 10:09:48 +110063/** Takes the pitch vector and the decoded residual vector (non-compressed),
64 applies the compression in the pitch direction, computes the gain that will
65 give ||p+g*y||=1 and mixes the residual with the pitch. */
Jean-Marc Valin31213272008-03-03 16:52:54 +110066static 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 +110067{
68 int i;
Jean-Marc Valinb50c5412008-02-27 17:05:43 +110069 celt_word32_t Ryp, Ryy, Rpp;
Jean-Marc Valina847b772008-02-27 17:46:49 +110070 celt_word32_t g;
Jean-Marc Valind17edd32008-02-27 16:52:30 +110071 VARDECL(celt_norm_t *y);
Jean-Marc Valind9de5932008-03-05 08:11:57 +110072#ifdef FIXED_POINT
73 int yshift;
74#endif
Jean-Marc Valin8600f692008-02-29 15:14:12 +110075 SAVE_STACK;
Jean-Marc Valind17edd32008-02-27 16:52:30 +110076#ifdef FIXED_POINT
Jean-Marc Valind9de5932008-03-05 08:11:57 +110077 yshift = 14-EC_ILOG(K);
Jean-Marc Valind17edd32008-02-27 16:52:30 +110078#endif
79 ALLOC(y, N, celt_norm_t);
Jean-Marc Valind4018c32008-02-27 10:09:48 +110080
81 /*for (i=0;i<N;i++)
82 printf ("%d ", iy[i]);*/
Jean-Marc Valinb50c5412008-02-27 17:05:43 +110083 Rpp = 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 Rpp = MAC16_16(Rpp,P[i],P[i]);
Jean-Marc Valind4018c32008-02-27 10:09:48 +110086
Jean-Marc Valinb50c5412008-02-27 17:05:43 +110087 Ryp = 0;
Jean-Marc Valind4018c32008-02-27 10:09:48 +110088 for (i=0;i<N;i++)
Jean-Marc Valinb50c5412008-02-27 17:05:43 +110089 Ryp = MAC16_16(Ryp,SHL16(iy[i],yshift),P[i]);
Jean-Marc Valind4018c32008-02-27 10:09:48 +110090
Jean-Marc Valind17edd32008-02-27 16:52:30 +110091 /* Remove part of the pitch component to compute the real residual from
92 the encoded (int) one */
Jean-Marc Valind4018c32008-02-27 10:09:48 +110093 for (i=0;i<N;i++)
Jean-Marc Valind17edd32008-02-27 16:52:30 +110094 y[i] = SUB16(SHL16(iy[i],yshift),
Jean-Marc Valina02ca1e2008-02-28 11:33:22 +110095 MULT16_16_Q15(alpha,MULT16_16_Q14(ROUND(Ryp,14),P[i])));
Jean-Marc Valind4018c32008-02-27 10:09:48 +110096
97 /* Recompute after the projection (I think it's right) */
98 Ryp = 0;
99 for (i=0;i<N;i++)
Jean-Marc Valinb50c5412008-02-27 17:05:43 +1100100 Ryp = MAC16_16(Ryp,y[i],P[i]);
Jean-Marc Valind4018c32008-02-27 10:09:48 +1100101
Jean-Marc Valinb50c5412008-02-27 17:05:43 +1100102 Ryy = 0;
Jean-Marc Valind4018c32008-02-27 10:09:48 +1100103 for (i=0;i<N;i++)
Jean-Marc Valinb50c5412008-02-27 17:05:43 +1100104 Ryy = MAC16_16(Ryy, y[i],y[i]);
Jean-Marc Valind4018c32008-02-27 10:09:48 +1100105
Jean-Marc Valin1ca07222008-02-27 17:23:04 +1100106 /* g = (sqrt(Ryp^2 + Ryy - Rpp*Ryy)-Ryp)/Ryy */
Jean-Marc Valina02ca1e2008-02-28 11:33:22 +1100107 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 +1100108
109 for (i=0;i<N;i++)
Jean-Marc Valina847b772008-02-27 17:46:49 +1100110 X[i] = P[i] + MULT16_32_Q14(y[i], g);
Jean-Marc Valin8600f692008-02-29 15:14:12 +1100111 RESTORE_STACK;
Jean-Marc Valind4018c32008-02-27 10:09:48 +1100112}
113
Jean-Marc Valin879fbfd2008-02-20 17:17:13 +1100114/** All the info necessary to keep track of a hypothesis during the search */
Jean-Marc Valin3b277dc2008-02-14 16:46:50 +1100115struct NBest {
Jean-Marc Valin4e1328b2008-02-28 15:14:07 +1100116 celt_word32_t score;
Jean-Marc Valin3b277dc2008-02-14 16:46:50 +1100117 int sign;
118 int pos;
119 int orig;
Jean-Marc Valin4e1328b2008-02-28 15:14:07 +1100120 celt_word32_t xy;
121 celt_word32_t yy;
122 celt_word32_t yp;
Jean-Marc Valin3b277dc2008-02-14 16:46:50 +1100123};
Jean-Marc Valin41af4212007-11-30 18:35:37 +1100124
Jean-Marc Valin31213272008-03-03 16:52:54 +1100125void 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 +1100126{
Jean-Marc Valin4a897682007-12-12 00:45:15 +1100127 int L = 3;
Jean-Marc Valin8b158f52008-02-28 14:44:19 +1100128 VARDECL(celt_norm_t *_y);
129 VARDECL(celt_norm_t *_ny);
Jean-Marc Valin9a0bba12008-02-20 14:08:50 +1100130 VARDECL(int *_iy);
131 VARDECL(int *_iny);
Jean-Marc Valin8b158f52008-02-28 14:44:19 +1100132 VARDECL(celt_norm_t **y);
133 VARDECL(celt_norm_t **ny);
Jean-Marc Valin9a0bba12008-02-20 14:08:50 +1100134 VARDECL(int **iy);
135 VARDECL(int **iny);
Jean-Marc Valin0d587d82008-02-14 21:29:50 +1100136 int i, j, k, m;
Jean-Marc Valin846d4e22008-02-12 13:48:48 +1100137 int pulsesLeft;
Jean-Marc Valined9e4232008-02-28 12:22:22 +1100138 VARDECL(celt_word32_t *xy);
139 VARDECL(celt_word32_t *yy);
140 VARDECL(celt_word32_t *yp);
Jean-Marc Valin9a0bba12008-02-20 14:08:50 +1100141 VARDECL(struct NBest *_nbest);
142 VARDECL(struct NBest **nbest);
Jean-Marc Valinf675adc2008-02-28 12:15:17 +1100143 celt_word32_t Rpp=0, Rxp=0;
Jean-Marc Valin41af4212007-11-30 18:35:37 +1100144 int maxL = 1;
Jean-Marc Valinf675adc2008-02-28 12:15:17 +1100145#ifdef FIXED_POINT
Jean-Marc Valind748cd52008-03-01 07:27:03 +1100146 int yshift;
147#endif
148 SAVE_STACK;
149
150#ifdef FIXED_POINT
151 yshift = 14-EC_ILOG(K);
Jean-Marc Valinf675adc2008-02-28 12:15:17 +1100152#endif
Jean-Marc Valin9d8d9b32008-02-27 16:17:39 +1100153
Jean-Marc Valin8b158f52008-02-28 14:44:19 +1100154 ALLOC(_y, L*N, celt_norm_t);
155 ALLOC(_ny, L*N, celt_norm_t);
Jean-Marc Valin9a0bba12008-02-20 14:08:50 +1100156 ALLOC(_iy, L*N, int);
157 ALLOC(_iny, L*N, int);
Jean-Marc Valincac91ec2008-02-29 17:03:34 +1100158 ALLOC(y, L, celt_norm_t*);
159 ALLOC(ny, L, celt_norm_t*);
160 ALLOC(iy, L, int*);
161 ALLOC(iny, L, int*);
Jean-Marc Valin9a0bba12008-02-20 14:08:50 +1100162
Jean-Marc Valined9e4232008-02-28 12:22:22 +1100163 ALLOC(xy, L, celt_word32_t);
164 ALLOC(yy, L, celt_word32_t);
165 ALLOC(yp, L, celt_word32_t);
Jean-Marc Valin9a0bba12008-02-20 14:08:50 +1100166 ALLOC(_nbest, L, struct NBest);
167 ALLOC(nbest, L, struct NBest *);
Jean-Marc Valinb4dfce42008-02-25 17:41:30 +1100168
Jean-Marc Valinfe419832008-02-12 15:05:01 +1100169 for (m=0;m<L;m++)
Jean-Marc Valin3b277dc2008-02-14 16:46:50 +1100170 nbest[m] = &_nbest[m];
171
172 for (m=0;m<L;m++)
Jean-Marc Valinfe419832008-02-12 15:05:01 +1100173 {
Jean-Marc Valin9a0bba12008-02-20 14:08:50 +1100174 ny[m] = &_ny[m*N];
175 iny[m] = &_iny[m*N];
176 y[m] = &_y[m*N];
177 iy[m] = &_iy[m*N];
Jean-Marc Valinfe419832008-02-12 15:05:01 +1100178 }
179
Jean-Marc Valin41af4212007-11-30 18:35:37 +1100180 for (j=0;j<N;j++)
Jean-Marc Valin0d587d82008-02-14 21:29:50 +1100181 {
Jean-Marc Valinf675adc2008-02-28 12:15:17 +1100182 Rpp = MAC16_16(Rpp, P[j],P[j]);
183 Rxp = MAC16_16(Rxp, X[j],P[j]);
Jean-Marc Valin0d587d82008-02-14 21:29:50 +1100184 }
Jean-Marc Valinf675adc2008-02-28 12:15:17 +1100185 Rpp = ROUND(Rpp, NORM_SHIFT);
186 Rxp = ROUND(Rxp, NORM_SHIFT);
187 if (Rpp>NORM_SCALING)
Jean-Marc Valinb60340f2008-02-26 15:41:51 +1100188 celt_fatal("Rpp > 1");
189
Jean-Marc Valin0d587d82008-02-14 21:29:50 +1100190 /* We only need to initialise the zero because the first iteration only uses that */
191 for (i=0;i<N;i++)
192 y[0][i] = 0;
193 for (i=0;i<N;i++)
194 iy[0][i] = 0;
195 xy[0] = yy[0] = yp[0] = 0;
196
Jean-Marc Valin846d4e22008-02-12 13:48:48 +1100197 pulsesLeft = K;
198 while (pulsesLeft > 0)
Jean-Marc Valin41af4212007-11-30 18:35:37 +1100199 {
Jean-Marc Valin846d4e22008-02-12 13:48:48 +1100200 int pulsesAtOnce=1;
Jean-Marc Valincab576e2008-02-12 17:21:14 +1100201 int Lupdate = L;
Jean-Marc Valin41af4212007-11-30 18:35:37 +1100202 int L2 = L;
Jean-Marc Valin0d587d82008-02-14 21:29:50 +1100203
204 /* Decide on complexity strategy */
Jean-Marc Valincab576e2008-02-12 17:21:14 +1100205 pulsesAtOnce = pulsesLeft/N;
206 if (pulsesAtOnce<1)
207 pulsesAtOnce = 1;
208 if (pulsesLeft-pulsesAtOnce > 3 || N > 30)
209 Lupdate = 1;
Jean-Marc Valina85657b2008-02-20 11:59:30 +1100210 /*printf ("%d %d %d/%d %d\n", Lupdate, pulsesAtOnce, pulsesLeft, K, N);*/
Jean-Marc Valincab576e2008-02-12 17:21:14 +1100211 L2 = Lupdate;
212 if (L2>maxL)
Jean-Marc Valin41af4212007-11-30 18:35:37 +1100213 {
214 L2 = maxL;
215 maxL *= N;
216 }
Jean-Marc Valin846d4e22008-02-12 13:48:48 +1100217
Jean-Marc Valin0d587d82008-02-14 21:29:50 +1100218 for (m=0;m<Lupdate;m++)
Jean-Marc Valin4e1328b2008-02-28 15:14:07 +1100219 nbest[m]->score = -VERY_LARGE32;
Jean-Marc Valin41af4212007-11-30 18:35:37 +1100220
221 for (m=0;m<L2;m++)
222 {
223 for (j=0;j<N;j++)
224 {
Jean-Marc Valin1e7087e2007-12-04 13:05:43 +1100225 int sign;
Jean-Marc Valin0d587d82008-02-14 21:29:50 +1100226 /*if (x[j]>0) sign=1; else sign=-1;*/
Jean-Marc Valin1e7087e2007-12-04 13:05:43 +1100227 for (sign=-1;sign<=1;sign+=2)
Jean-Marc Valin41af4212007-11-30 18:35:37 +1100228 {
Jean-Marc Valina85657b2008-02-20 11:59:30 +1100229 /*fprintf (stderr, "%d/%d %d/%d %d/%d\n", i, K, m, L2, j, N);*/
Jean-Marc Valin4e1328b2008-02-28 15:14:07 +1100230 celt_word32_t Rxy, Ryy, Ryp;
231 celt_word16_t spj, aspj; /* Intermediate results */
232 celt_word32_t score;
233 celt_word32_t g;
Jean-Marc Valinc9d606f2008-02-28 13:46:20 +1100234 celt_word16_t s = SHL16(sign*pulsesAtOnce, yshift);
Jean-Marc Valinfe419832008-02-12 15:05:01 +1100235
Jean-Marc Valin9a0bba12008-02-20 14:08:50 +1100236 /* All pulses at one location must have the same sign. */
237 if (iy[m][j]*sign < 0)
238 continue;
239
Jean-Marc Valinc9d606f2008-02-28 13:46:20 +1100240 spj = MULT16_16_P14(s, P[j]);
Jean-Marc Valin642ff942008-02-28 14:33:19 +1100241 aspj = MULT16_16_P15(alpha, spj);
Jean-Marc Valina073c7b2008-02-14 16:58:04 +1100242 /* Updating the sums of the new pulse(s) */
Jean-Marc Valin4e1328b2008-02-28 15:14:07 +1100243 Rxy = xy[m] + MULT16_16(s,X[j]) - MULT16_16(MULT16_16_P15(alpha,spj),Rxp);
244 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]));
245 Ryp = yp[m] + MULT16_16(spj, SUB16(QCONST16(1.f,14),MULT16_16_Q15(alpha,Rpp)));
Jean-Marc Valina073c7b2008-02-14 16:58:04 +1100246
247 /* Compute the gain such that ||p + g*y|| = 1 */
Jean-Marc Valin4e1328b2008-02-28 15:14:07 +1100248 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 +1100249
Jean-Marc Valina073c7b2008-02-14 16:58:04 +1100250 /* Knowing that gain, what the error: (x-g*y)^2
251 (result is negated and we discard x^2 because it's constant) */
Jean-Marc Valin4e1328b2008-02-28 15:14:07 +1100252 /*score = 2.f*g*Rxy - 1.f*g*g*Ryy*NORM_SCALING_1;*/
253 score = 2*MULT16_32_Q14(ROUND(Rxy,14),g) -
254 MULT16_32_Q14(EXTRACT16(MULT16_32_Q14(ROUND(Ryy,14),g)),g);
Jean-Marc Valin41af4212007-11-30 18:35:37 +1100255
Jean-Marc Valin3b277dc2008-02-14 16:46:50 +1100256 if (score>nbest[Lupdate-1]->score)
Jean-Marc Valin1e7087e2007-12-04 13:05:43 +1100257 {
Jean-Marc Valin472a5f02008-02-19 13:12:32 +1100258 int k;
Jean-Marc Valincab576e2008-02-12 17:21:14 +1100259 int id = Lupdate-1;
Jean-Marc Valin3b277dc2008-02-14 16:46:50 +1100260 struct NBest *tmp_best;
261
262 /* Save some pointers that would be deleted and use them for the current entry*/
263 tmp_best = nbest[Lupdate-1];
264 while (id > 0 && score > nbest[id-1]->score)
Jean-Marc Valin1e7087e2007-12-04 13:05:43 +1100265 id--;
266
Jean-Marc Valincab576e2008-02-12 17:21:14 +1100267 for (k=Lupdate-1;k>id;k--)
Jean-Marc Valin3b277dc2008-02-14 16:46:50 +1100268 nbest[k] = nbest[k-1];
Jean-Marc Valin1e7087e2007-12-04 13:05:43 +1100269
Jean-Marc Valin3b277dc2008-02-14 16:46:50 +1100270 nbest[id] = tmp_best;
271 nbest[id]->score = score;
272 nbest[id]->pos = j;
273 nbest[id]->orig = m;
274 nbest[id]->sign = sign;
Jean-Marc Valin4e1328b2008-02-28 15:14:07 +1100275 nbest[id]->xy = Rxy;
276 nbest[id]->yy = Ryy;
277 nbest[id]->yp = Ryp;
Jean-Marc Valin1e7087e2007-12-04 13:05:43 +1100278 }
Jean-Marc Valin636f5c82008-02-12 17:40:27 +1100279 }
Jean-Marc Valin41af4212007-11-30 18:35:37 +1100280 }
Jean-Marc Valin636f5c82008-02-12 17:40:27 +1100281
Jean-Marc Valin41af4212007-11-30 18:35:37 +1100282 }
Jean-Marc Valinb60340f2008-02-26 15:41:51 +1100283
Jean-Marc Valin4e1328b2008-02-28 15:14:07 +1100284 if (!(nbest[0]->score > -VERY_LARGE32))
Jean-Marc Valinb60340f2008-02-26 15:41:51 +1100285 celt_fatal("Could not find any match in VQ codebook. Something got corrupted somewhere.");
Jean-Marc Valin0d587d82008-02-14 21:29:50 +1100286 /* Only now that we've made the final choice, update ny/iny and others */
Jean-Marc Valincab576e2008-02-12 17:21:14 +1100287 for (k=0;k<Lupdate;k++)
Jean-Marc Valin41af4212007-11-30 18:35:37 +1100288 {
Jean-Marc Valin3b277dc2008-02-14 16:46:50 +1100289 int n;
290 int is;
Jean-Marc Valin8b158f52008-02-28 14:44:19 +1100291 celt_norm_t s;
Jean-Marc Valin3b277dc2008-02-14 16:46:50 +1100292 is = nbest[k]->sign*pulsesAtOnce;
Jean-Marc Valinf675adc2008-02-28 12:15:17 +1100293 s = SHL16(is, yshift);
Jean-Marc Valin3b277dc2008-02-14 16:46:50 +1100294 for (n=0;n<N;n++)
Jean-Marc Valin8b158f52008-02-28 14:44:19 +1100295 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 +1100296 ny[k][nbest[k]->pos] += s;
Jean-Marc Valin0d587d82008-02-14 21:29:50 +1100297
Jean-Marc Valin3b277dc2008-02-14 16:46:50 +1100298 for (n=0;n<N;n++)
299 iny[k][n] = iy[nbest[k]->orig][n];
300 iny[k][nbest[k]->pos] += is;
Jean-Marc Valin0d587d82008-02-14 21:29:50 +1100301
Jean-Marc Valin3b277dc2008-02-14 16:46:50 +1100302 xy[k] = nbest[k]->xy;
303 yy[k] = nbest[k]->yy;
304 yp[k] = nbest[k]->yp;
305 }
Jean-Marc Valin0d587d82008-02-14 21:29:50 +1100306 /* Swap ny/iny with y/iy */
Jean-Marc Valin3b277dc2008-02-14 16:46:50 +1100307 for (k=0;k<Lupdate;k++)
308 {
Jean-Marc Valin8b158f52008-02-28 14:44:19 +1100309 celt_norm_t *tmp_ny;
Jean-Marc Valinfe419832008-02-12 15:05:01 +1100310 int *tmp_iny;
311
Jean-Marc Valinfe419832008-02-12 15:05:01 +1100312 tmp_ny = ny[k];
313 ny[k] = y[k];
314 y[k] = tmp_ny;
315 tmp_iny = iny[k];
316 iny[k] = iy[k];
317 iy[k] = tmp_iny;
Jean-Marc Valin41af4212007-11-30 18:35:37 +1100318 }
Jean-Marc Valin846d4e22008-02-12 13:48:48 +1100319 pulsesLeft -= pulsesAtOnce;
Jean-Marc Valin41af4212007-11-30 18:35:37 +1100320 }
321
Jean-Marc Valind4018c32008-02-27 10:09:48 +1100322#if 0
Jean-Marc Valinac1e03d2008-02-12 23:00:18 +1100323 if (0) {
Jean-Marc Valin877b1972008-02-29 16:40:39 +1100324 celt_word32_t err=0;
Jean-Marc Valinac1e03d2008-02-12 23:00:18 +1100325 for (i=0;i<N;i++)
Jean-Marc Valin3b277dc2008-02-14 16:46:50 +1100326 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 +1100327 /*if (N<=10)
328 printf ("%f %d %d\n", err, K, N);*/
Jean-Marc Valinac1e03d2008-02-12 23:00:18 +1100329 }
Jean-Marc Valin0d587d82008-02-14 21:29:50 +1100330 /* Sanity checks, don't bother */
Jean-Marc Valin1e7087e2007-12-04 13:05:43 +1100331 if (0) {
Jean-Marc Valind4018c32008-02-27 10:09:48 +1100332 for (i=0;i<N;i++)
333 x[i] = p[i]+nbest[0]->gain*y[0][i];
Jean-Marc Valin877b1972008-02-29 16:40:39 +1100334 celt_word32_t E=1e-15;
Jean-Marc Valin1e7087e2007-12-04 13:05:43 +1100335 int ABS = 0;
336 for (i=0;i<N;i++)
337 ABS += abs(iy[0][i]);
Jean-Marc Valina85657b2008-02-20 11:59:30 +1100338 /*if (K != ABS)
339 printf ("%d %d\n", K, ABS);*/
Jean-Marc Valin1e7087e2007-12-04 13:05:43 +1100340 for (i=0;i<N;i++)
341 E += x[i]*x[i];
Jean-Marc Valina85657b2008-02-20 11:59:30 +1100342 /*printf ("%f\n", E);*/
Jean-Marc Valin1e7087e2007-12-04 13:05:43 +1100343 E = 1/sqrt(E);
344 for (i=0;i<N;i++)
345 x[i] *= E;
346 }
Jean-Marc Valind4018c32008-02-27 10:09:48 +1100347#endif
Jean-Marc Valin5fa59952008-02-14 13:50:44 +1100348
349 encode_pulses(iy[0], N, K, enc);
350
Jean-Marc Valina4833ff2008-01-10 15:34:00 +1100351 /* Recompute the gain in one pass to reduce the encoder-decoder mismatch
Jean-Marc Valin636f5c82008-02-12 17:40:27 +1100352 due to the recursive computation used in quantisation.
353 Not quite sure whether we need that or not */
Jean-Marc Valind17edd32008-02-27 16:52:30 +1100354 mix_pitch_and_residual(iy[0], X, N, K, P, alpha);
Jean-Marc Valin8600f692008-02-29 15:14:12 +1100355 RESTORE_STACK;
Jean-Marc Valin41af4212007-11-30 18:35:37 +1100356}
357
Jean-Marc Valin879fbfd2008-02-20 17:17:13 +1100358/** Decode pulse vector and combine the result with the pitch vector to produce
359 the final normalised signal in the current band. */
Jean-Marc Valin9d8d9b32008-02-27 16:17:39 +1100360void 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 +1100361{
Jean-Marc Valin9a0bba12008-02-20 14:08:50 +1100362 VARDECL(int *iy);
Jean-Marc Valin8600f692008-02-29 15:14:12 +1100363 SAVE_STACK;
Jean-Marc Valin9a0bba12008-02-20 14:08:50 +1100364 ALLOC(iy, N, int);
Jean-Marc Valin5fa59952008-02-14 13:50:44 +1100365 decode_pulses(iy, N, K, dec);
Jean-Marc Valind17edd32008-02-27 16:52:30 +1100366 mix_pitch_and_residual(iy, X, N, K, P, alpha);
Jean-Marc Valin8600f692008-02-29 15:14:12 +1100367 RESTORE_STACK;
Jean-Marc Valin0d227d82007-12-31 16:12:12 +1100368}
369
370
371static const float pg[11] = {1.f, .75f, .65f, 0.6f, 0.6f, .6f, .55f, .55f, .5f, .5f, .5f};
372
Jean-Marc Valin5f09ea52008-02-26 16:43:04 +1100373void 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 +1100374{
375 int i,j;
376 int best=0;
Jean-Marc Valin877b1972008-02-29 16:40:39 +1100377 celt_word32_t best_score=0;
378 celt_word16_t s = 1;
Jean-Marc Valin0aa39032007-12-07 15:09:58 +1100379 int sign;
Jean-Marc Valin877b1972008-02-29 16:40:39 +1100380 celt_word32_t E;
Jean-Marc Valin9a0bba12008-02-20 14:08:50 +1100381 float pred_gain;
Jean-Marc Valin8f0f4b92008-02-11 13:52:44 +1100382 int max_pos = N0-N/B;
383 if (max_pos > 32)
384 max_pos = 32;
385
386 for (i=0;i<max_pos*B;i+=B)
Jean-Marc Valin4841a0a2007-12-03 13:54:30 +1100387 {
388 int j;
Jean-Marc Valin877b1972008-02-29 16:40:39 +1100389 celt_word32_t xy=0, yy=0;
Jean-Marc Valin4841a0a2007-12-03 13:54:30 +1100390 float score;
391 for (j=0;j<N;j++)
392 {
Jean-Marc Valin877b1972008-02-29 16:40:39 +1100393 xy = MAC16_16(xy, x[j], Y[i+N-j-1]);
394 yy = MAC16_16(yy, Y[i+N-j-1], Y[i+N-j-1]);
Jean-Marc Valin4841a0a2007-12-03 13:54:30 +1100395 }
Jean-Marc Valin877b1972008-02-29 16:40:39 +1100396 score = 1.f*xy*xy/(.001+yy);
Jean-Marc Valin4841a0a2007-12-03 13:54:30 +1100397 if (score > best_score)
398 {
399 best_score = score;
400 best = i;
Jean-Marc Valin50d11162007-12-03 14:34:52 +1100401 if (xy>0)
402 s = 1;
403 else
404 s = -1;
Jean-Marc Valin4841a0a2007-12-03 13:54:30 +1100405 }
406 }
Jean-Marc Valin0aa39032007-12-07 15:09:58 +1100407 if (s<0)
408 sign = 1;
Jean-Marc Valin6e9058a2007-12-07 14:59:06 +1100409 else
Jean-Marc Valin0aa39032007-12-07 15:09:58 +1100410 sign = 0;
Jean-Marc Valina85657b2008-02-20 11:59:30 +1100411 /*printf ("%d %d ", sign, best);*/
Jean-Marc Valin0aa39032007-12-07 15:09:58 +1100412 ec_enc_uint(enc,sign,2);
Jean-Marc Valin8f0f4b92008-02-11 13:52:44 +1100413 ec_enc_uint(enc,best/B,max_pos);
Jean-Marc Valina85657b2008-02-20 11:59:30 +1100414 /*printf ("%d %f\n", best, best_score);*/
Jean-Marc Valin0d227d82007-12-31 16:12:12 +1100415
Jean-Marc Valin0d227d82007-12-31 16:12:12 +1100416 if (K>10)
417 pred_gain = pg[10];
418 else
419 pred_gain = pg[K];
420 E = 1e-10;
421 for (j=0;j<N;j++)
Jean-Marc Valin4841a0a2007-12-03 13:54:30 +1100422 {
Jean-Marc Valind501f612008-02-21 12:16:57 +1100423 P[j] = s*Y[best+N-j-1];
Jean-Marc Valin877b1972008-02-29 16:40:39 +1100424 E = MAC16_16(E, P[j],P[j]);
Jean-Marc Valin4841a0a2007-12-03 13:54:30 +1100425 }
Jean-Marc Valin877b1972008-02-29 16:40:39 +1100426 pred_gain = NORM_SCALING*pred_gain/sqrt(E);
Jean-Marc Valin0d227d82007-12-31 16:12:12 +1100427 for (j=0;j<N;j++)
Jean-Marc Valin877b1972008-02-29 16:40:39 +1100428 P[j] *= pred_gain;
Jean-Marc Valin0d227d82007-12-31 16:12:12 +1100429 if (K>0)
430 {
431 for (j=0;j<N;j++)
432 x[j] -= P[j];
433 } else {
434 for (j=0;j<N;j++)
435 x[j] = P[j];
436 }
Jean-Marc Valina85657b2008-02-20 11:59:30 +1100437 /*printf ("quant ");*/
438 /*for (j=0;j<N;j++) printf ("%f ", P[j]);*/
Jean-Marc Valin0d227d82007-12-31 16:12:12 +1100439
Jean-Marc Valin4841a0a2007-12-03 13:54:30 +1100440}
Jean-Marc Valinfc08d0a2007-12-07 13:26:15 +1100441
Jean-Marc Valin18ddc022008-02-22 14:24:50 +1100442void 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 +1100443{
Jean-Marc Valin11f01722007-12-09 01:19:36 +1100444 int j;
Jean-Marc Valin0aa39032007-12-07 15:09:58 +1100445 int sign;
Jean-Marc Valin877b1972008-02-29 16:40:39 +1100446 celt_word16_t s;
Jean-Marc Valin6e9058a2007-12-07 14:59:06 +1100447 int best;
Jean-Marc Valin877b1972008-02-29 16:40:39 +1100448 celt_word32_t E;
Jean-Marc Valin9a0bba12008-02-20 14:08:50 +1100449 float pred_gain;
Jean-Marc Valin8f0f4b92008-02-11 13:52:44 +1100450 int max_pos = N0-N/B;
451 if (max_pos > 32)
452 max_pos = 32;
453
Jean-Marc Valin0aa39032007-12-07 15:09:58 +1100454 sign = ec_dec_uint(dec, 2);
455 if (sign == 0)
Jean-Marc Valin6e9058a2007-12-07 14:59:06 +1100456 s = 1;
457 else
458 s = -1;
459
Jean-Marc Valin8f0f4b92008-02-11 13:52:44 +1100460 best = B*ec_dec_uint(dec, max_pos);
Jean-Marc Valina85657b2008-02-20 11:59:30 +1100461 /*printf ("%d %d ", sign, best);*/
Jean-Marc Valin6e9058a2007-12-07 14:59:06 +1100462
Jean-Marc Valin0d227d82007-12-31 16:12:12 +1100463 if (K>10)
464 pred_gain = pg[10];
465 else
466 pred_gain = pg[K];
467 E = 1e-10;
468 for (j=0;j<N;j++)
469 {
Jean-Marc Valind501f612008-02-21 12:16:57 +1100470 P[j] = s*Y[best+N-j-1];
Jean-Marc Valin877b1972008-02-29 16:40:39 +1100471 E = MAC16_16(E, P[j],P[j]);
Jean-Marc Valin0d227d82007-12-31 16:12:12 +1100472 }
Jean-Marc Valin877b1972008-02-29 16:40:39 +1100473 pred_gain = NORM_SCALING*pred_gain/sqrt(E);
Jean-Marc Valin0d227d82007-12-31 16:12:12 +1100474 for (j=0;j<N;j++)
Jean-Marc Valin877b1972008-02-29 16:40:39 +1100475 P[j] *= pred_gain;
Jean-Marc Valin6e9058a2007-12-07 14:59:06 +1100476 if (K==0)
477 {
Jean-Marc Valin6e9058a2007-12-07 14:59:06 +1100478 for (j=0;j<N;j++)
Jean-Marc Valin0d227d82007-12-31 16:12:12 +1100479 x[j] = P[j];
Jean-Marc Valin6e9058a2007-12-07 14:59:06 +1100480 }
481}
Jean-Marc Valin0e20ca02008-02-11 15:33:53 +1100482
Jean-Marc Valin18ddc022008-02-22 14:24:50 +1100483void 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 +1100484{
Jean-Marc Valin0df0eb42008-02-13 16:00:10 +1100485 int i, j;
Jean-Marc Valin877b1972008-02-29 16:40:39 +1100486 celt_word32_t E;
487 float g;
Jean-Marc Valin0e20ca02008-02-11 15:33:53 +1100488
489 E = 1e-10;
Jean-Marc Valin0df0eb42008-02-13 16:00:10 +1100490 if (N0 >= Nmax/2)
Jean-Marc Valin0e20ca02008-02-11 15:33:53 +1100491 {
Jean-Marc Valin0df0eb42008-02-13 16:00:10 +1100492 for (i=0;i<B;i++)
493 {
494 for (j=0;j<N/B;j++)
495 {
496 P[j*B+i] = Y[(Nmax-N0-j-1)*B+i];
Jean-Marc Valin877b1972008-02-29 16:40:39 +1100497 E += P[j*B+i]*P[j*B+i];
Jean-Marc Valin0df0eb42008-02-13 16:00:10 +1100498 }
499 }
500 } else {
501 for (j=0;j<N;j++)
502 {
503 P[j] = Y[j];
Jean-Marc Valin877b1972008-02-29 16:40:39 +1100504 E = MAC16_16(E, P[j],P[j]);
Jean-Marc Valin0df0eb42008-02-13 16:00:10 +1100505 }
Jean-Marc Valin0e20ca02008-02-11 15:33:53 +1100506 }
Jean-Marc Valin877b1972008-02-29 16:40:39 +1100507 g = NORM_SCALING/sqrt(E);
Jean-Marc Valin0e20ca02008-02-11 15:33:53 +1100508 for (j=0;j<N;j++)
Jean-Marc Valin877b1972008-02-29 16:40:39 +1100509 P[j] *= g;
Jean-Marc Valin0e20ca02008-02-11 15:33:53 +1100510 for (j=0;j<N;j++)
511 x[j] = P[j];
512}
513