blob: 3e4de85c007bd54154f2f807d1fe9861a51d1187 [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 Valinbd718ba2008-03-25 14:15:41 +110045static void mix_pitch_and_residual(int *iy, celt_norm_t *X, int N, int K, const celt_norm_t *P)
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
Jean-Marc Valinbd718ba2008-03-25 14:15:41 +110071 the encoded (int) one */
Jean-Marc Valind4018c32008-02-27 10:09:48 +110072 for (i=0;i<N;i++)
Jean-Marc Valinbd718ba2008-03-25 14:15:41 +110073 y[i] = SHL16(iy[i],yshift);
Jean-Marc Valind4018c32008-02-27 10:09:48 +110074
75 /* Recompute after the projection (I think it's right) */
76 Ryp = 0;
77 for (i=0;i<N;i++)
Jean-Marc Valinb50c5412008-02-27 17:05:43 +110078 Ryp = MAC16_16(Ryp,y[i],P[i]);
Jean-Marc Valind4018c32008-02-27 10:09:48 +110079
Jean-Marc Valinb50c5412008-02-27 17:05:43 +110080 Ryy = 0;
Jean-Marc Valind4018c32008-02-27 10:09:48 +110081 for (i=0;i<N;i++)
Jean-Marc Valinb50c5412008-02-27 17:05:43 +110082 Ryy = MAC16_16(Ryy, y[i],y[i]);
Jean-Marc Valind4018c32008-02-27 10:09:48 +110083
Jean-Marc Valin1ca07222008-02-27 17:23:04 +110084 /* g = (sqrt(Ryp^2 + Ryy - Rpp*Ryy)-Ryp)/Ryy */
Jean-Marc Valin9d5b4a62008-03-13 11:36:45 +110085 g = MULT16_32_Q15(
Jean-Marc Valinf5b05872008-03-21 10:46:17 +110086 celt_sqrt(MULT16_16(ROUND16(Ryp,14),ROUND16(Ryp,14)) + Ryy -
87 MULT16_16(ROUND16(Ryy,14),ROUND16(Rpp,14)))
88 - ROUND16(Ryp,14),
Jean-Marc Valin9d5b4a62008-03-13 11:36:45 +110089 celt_rcp(SHR32(Ryy,9)));
Jean-Marc Valind4018c32008-02-27 10:09:48 +110090
91 for (i=0;i<N;i++)
Jean-Marc Valinf5b05872008-03-21 10:46:17 +110092 X[i] = P[i] + ROUND16(MULT16_16(y[i], g),11);
Jean-Marc Valin8600f692008-02-29 15:14:12 +110093 RESTORE_STACK;
Jean-Marc Valind4018c32008-02-27 10:09:48 +110094}
95
Jean-Marc Valin879fbfd2008-02-20 17:17:13 +110096/** All the info necessary to keep track of a hypothesis during the search */
Jean-Marc Valin3b277dc2008-02-14 16:46:50 +110097struct NBest {
Jean-Marc Valin4e1328b2008-02-28 15:14:07 +110098 celt_word32_t score;
Jean-Marc Valin3b277dc2008-02-14 16:46:50 +110099 int sign;
100 int pos;
101 int orig;
Jean-Marc Valin4e1328b2008-02-28 15:14:07 +1100102 celt_word32_t xy;
103 celt_word32_t yy;
104 celt_word32_t yp;
Jean-Marc Valin3b277dc2008-02-14 16:46:50 +1100105};
Jean-Marc Valin41af4212007-11-30 18:35:37 +1100106
Jean-Marc Valinbd718ba2008-03-25 14:15:41 +1100107void alg_quant(celt_norm_t *X, celt_mask_t *W, int N, int K, const celt_norm_t *P, ec_enc *enc)
Jean-Marc Valin41af4212007-11-30 18:35:37 +1100108{
Jean-Marc Valin31b79d12008-03-12 17:17:23 +1100109 VARDECL(celt_norm_t, _y);
110 VARDECL(celt_norm_t, _ny);
111 VARDECL(int, _iy);
112 VARDECL(int, _iny);
Jean-Marc Valinbd718ba2008-03-25 14:15:41 +1100113 celt_norm_t *y, *ny;
114 int *iy, *iny;
115 int i, j;
Jean-Marc Valin846d4e22008-02-12 13:48:48 +1100116 int pulsesLeft;
Jean-Marc Valinbd718ba2008-03-25 14:15:41 +1100117 celt_word32_t xy, yy, yp;
118 struct NBest nbest;
Jean-Marc Valinf675adc2008-02-28 12:15:17 +1100119 celt_word32_t Rpp=0, Rxp=0;
Jean-Marc Valinf675adc2008-02-28 12:15:17 +1100120#ifdef FIXED_POINT
Jean-Marc Valind748cd52008-03-01 07:27:03 +1100121 int yshift;
122#endif
123 SAVE_STACK;
124
125#ifdef FIXED_POINT
126 yshift = 14-EC_ILOG(K);
Jean-Marc Valinf675adc2008-02-28 12:15:17 +1100127#endif
Jean-Marc Valin9d8d9b32008-02-27 16:17:39 +1100128
Jean-Marc Valinbd718ba2008-03-25 14:15:41 +1100129 ALLOC(_y, N, celt_norm_t);
130 ALLOC(_ny, N, celt_norm_t);
131 ALLOC(_iy, N, int);
132 ALLOC(_iny, N, int);
133 y = _y;
134 ny = _ny;
135 iy = _iy;
136 iny = _iny;
Jean-Marc Valinfe419832008-02-12 15:05:01 +1100137
Jean-Marc Valin41af4212007-11-30 18:35:37 +1100138 for (j=0;j<N;j++)
Jean-Marc Valin0d587d82008-02-14 21:29:50 +1100139 {
Jean-Marc Valinf675adc2008-02-28 12:15:17 +1100140 Rpp = MAC16_16(Rpp, P[j],P[j]);
141 Rxp = MAC16_16(Rxp, X[j],P[j]);
Jean-Marc Valin0d587d82008-02-14 21:29:50 +1100142 }
Jean-Marc Valinf5b05872008-03-21 10:46:17 +1100143 Rpp = ROUND16(Rpp, NORM_SHIFT);
144 Rxp = ROUND16(Rxp, NORM_SHIFT);
Jean-Marc Valinbd718ba2008-03-25 14:15:41 +1100145
Jean-Marc Valin4ff068e2008-03-15 23:34:39 +1100146 celt_assert2(Rpp<=NORM_SCALING, "Rpp should never have a norm greater than unity");
Jean-Marc Valinb60340f2008-02-26 15:41:51 +1100147
Jean-Marc Valin0d587d82008-02-14 21:29:50 +1100148 for (i=0;i<N;i++)
Jean-Marc Valinbd718ba2008-03-25 14:15:41 +1100149 y[i] = 0;
Jean-Marc Valin0d587d82008-02-14 21:29:50 +1100150 for (i=0;i<N;i++)
Jean-Marc Valinbd718ba2008-03-25 14:15:41 +1100151 iy[i] = 0;
152 xy = yy = yp = 0;
Jean-Marc Valin0d587d82008-02-14 21:29:50 +1100153
Jean-Marc Valin846d4e22008-02-12 13:48:48 +1100154 pulsesLeft = K;
155 while (pulsesLeft > 0)
Jean-Marc Valin41af4212007-11-30 18:35:37 +1100156 {
Jean-Marc Valin846d4e22008-02-12 13:48:48 +1100157 int pulsesAtOnce=1;
Jean-Marc Valin0d587d82008-02-14 21:29:50 +1100158
Jean-Marc Valinbd718ba2008-03-25 14:15:41 +1100159 /* Decide on how many pulses to find at once */
Jean-Marc Valincab576e2008-02-12 17:21:14 +1100160 pulsesAtOnce = pulsesLeft/N;
161 if (pulsesAtOnce<1)
162 pulsesAtOnce = 1;
Jean-Marc Valina85657b2008-02-20 11:59:30 +1100163 /*printf ("%d %d %d/%d %d\n", Lupdate, pulsesAtOnce, pulsesLeft, K, N);*/
Jean-Marc Valin846d4e22008-02-12 13:48:48 +1100164
Jean-Marc Valinbd718ba2008-03-25 14:15:41 +1100165 nbest.score = -VERY_LARGE32;
Jean-Marc Valin41af4212007-11-30 18:35:37 +1100166
Jean-Marc Valinbd718ba2008-03-25 14:15:41 +1100167 for (j=0;j<N;j++)
Jean-Marc Valin41af4212007-11-30 18:35:37 +1100168 {
Jean-Marc Valinbd718ba2008-03-25 14:15:41 +1100169 int sign;
170 /*fprintf (stderr, "%d/%d %d/%d %d/%d\n", i, K, m, L2, j, N);*/
171 celt_word32_t Rxy, Ryy, Ryp;
172 celt_word32_t score;
173 celt_word32_t g;
174 celt_word16_t s;
175
176 /* Select sign based on X[j] alone */
177 if (X[j]>0) sign=1; else sign=-1;
178 s = SHL16(sign*pulsesAtOnce, yshift);
179
180 /* Updating the sums of the new pulse(s) */
181 Rxy = xy + MULT16_16(s,X[j]);
182 Ryy = yy + 2*MULT16_16(s,y[j]) + MULT16_16(s,s);
183 Ryp = yp + MULT16_16(s, P[j]);
184
185 if (pulsesLeft>1)
Jean-Marc Valin41af4212007-11-30 18:35:37 +1100186 {
Jean-Marc Valinbd718ba2008-03-25 14:15:41 +1100187 score = MULT32_32_Q31(MULT16_16(ROUND16(Rxy,14),ABS16(ROUND16(Rxy,14))), celt_rcp(SHR32(Ryy,12)));
188 } else
189 {
190 /* Compute the gain such that ||p + g*y|| = 1 */
191 g = MULT16_32_Q15(
192 celt_sqrt(MULT16_16(ROUND16(Ryp,14),ROUND16(Ryp,14)) + Ryy -
193 MULT16_16(ROUND16(Ryy,14),Rpp))
194 - ROUND16(Ryp,14),
195 celt_rcp(SHR32(Ryy,12)));
196 /* Knowing that gain, what's the error: (x-g*y)^2
197 (result is negated and we discard x^2 because it's constant) */
198 /* score = 2.f*g*Rxy - 1.f*g*g*Ryy*NORM_SCALING_1;*/
199 score = 2*MULT16_32_Q14(ROUND16(Rxy,14),g)
200 - MULT16_32_Q14(EXTRACT16(MULT16_32_Q14(ROUND16(Ryy,14),g)),g);
Jean-Marc Valin41af4212007-11-30 18:35:37 +1100201 }
Jean-Marc Valinbd718ba2008-03-25 14:15:41 +1100202
203 if (score>nbest.score)
204 {
205 nbest.score = score;
206 nbest.pos = j;
207 nbest.orig = 0;
208 nbest.sign = sign;
209 nbest.xy = Rxy;
210 nbest.yy = Ryy;
211 nbest.yp = Ryp;
212 }
Jean-Marc Valin41af4212007-11-30 18:35:37 +1100213 }
Jean-Marc Valinbd718ba2008-03-25 14:15:41 +1100214
Jean-Marc Valin4ff068e2008-03-15 23:34:39 +1100215 celt_assert2(nbest[0]->score > -VERY_LARGE32, "Could not find any match in VQ codebook. Something got corrupted somewhere.");
Jean-Marc Valinbd718ba2008-03-25 14:15:41 +1100216
Jean-Marc Valin0d587d82008-02-14 21:29:50 +1100217 /* Only now that we've made the final choice, update ny/iny and others */
Jean-Marc Valin41af4212007-11-30 18:35:37 +1100218 {
Jean-Marc Valin3b277dc2008-02-14 16:46:50 +1100219 int n;
220 int is;
Jean-Marc Valin8b158f52008-02-28 14:44:19 +1100221 celt_norm_t s;
Jean-Marc Valinbd718ba2008-03-25 14:15:41 +1100222 is = nbest.sign*pulsesAtOnce;
Jean-Marc Valinf675adc2008-02-28 12:15:17 +1100223 s = SHL16(is, yshift);
Jean-Marc Valin3b277dc2008-02-14 16:46:50 +1100224 for (n=0;n<N;n++)
Jean-Marc Valinbd718ba2008-03-25 14:15:41 +1100225 ny[n] = y[n];
226 ny[nbest.pos] += s;
Jean-Marc Valin0d587d82008-02-14 21:29:50 +1100227
Jean-Marc Valin3b277dc2008-02-14 16:46:50 +1100228 for (n=0;n<N;n++)
Jean-Marc Valinbd718ba2008-03-25 14:15:41 +1100229 iny[n] = iy[n];
230 iny[nbest.pos] += is;
Jean-Marc Valin0d587d82008-02-14 21:29:50 +1100231
Jean-Marc Valinbd718ba2008-03-25 14:15:41 +1100232 xy = nbest.xy;
233 yy = nbest.yy;
234 yp = nbest.yp;
Jean-Marc Valin3b277dc2008-02-14 16:46:50 +1100235 }
Jean-Marc Valin0d587d82008-02-14 21:29:50 +1100236 /* Swap ny/iny with y/iy */
Jean-Marc Valin3b277dc2008-02-14 16:46:50 +1100237 {
Jean-Marc Valin8b158f52008-02-28 14:44:19 +1100238 celt_norm_t *tmp_ny;
Jean-Marc Valinfe419832008-02-12 15:05:01 +1100239 int *tmp_iny;
240
Jean-Marc Valinbd718ba2008-03-25 14:15:41 +1100241 tmp_ny = ny;
242 ny = y;
243 y = tmp_ny;
244 tmp_iny = iny;
245 iny = iy;
246 iy = tmp_iny;
Jean-Marc Valin41af4212007-11-30 18:35:37 +1100247 }
Jean-Marc Valin846d4e22008-02-12 13:48:48 +1100248 pulsesLeft -= pulsesAtOnce;
Jean-Marc Valin41af4212007-11-30 18:35:37 +1100249 }
250
Jean-Marc Valinbd718ba2008-03-25 14:15:41 +1100251 encode_pulses(iy, N, K, enc);
Jean-Marc Valin5fa59952008-02-14 13:50:44 +1100252
Jean-Marc Valina4833ff2008-01-10 15:34:00 +1100253 /* Recompute the gain in one pass to reduce the encoder-decoder mismatch
Jean-Marc Valinbd718ba2008-03-25 14:15:41 +1100254 due to the recursive computation used in quantisation. */
255 mix_pitch_and_residual(iy, X, N, K, P);
Jean-Marc Valin8600f692008-02-29 15:14:12 +1100256 RESTORE_STACK;
Jean-Marc Valin41af4212007-11-30 18:35:37 +1100257}
258
Jean-Marc Valinbd718ba2008-03-25 14:15:41 +1100259
Jean-Marc Valin879fbfd2008-02-20 17:17:13 +1100260/** Decode pulse vector and combine the result with the pitch vector to produce
261 the final normalised signal in the current band. */
Jean-Marc Valinbd718ba2008-03-25 14:15:41 +1100262void alg_unquant(celt_norm_t *X, int N, int K, celt_norm_t *P, ec_dec *dec)
Jean-Marc Valin0d227d82007-12-31 16:12:12 +1100263{
Jean-Marc Valin31b79d12008-03-12 17:17:23 +1100264 VARDECL(int, iy);
Jean-Marc Valin8600f692008-02-29 15:14:12 +1100265 SAVE_STACK;
Jean-Marc Valin9a0bba12008-02-20 14:08:50 +1100266 ALLOC(iy, N, int);
Jean-Marc Valin5fa59952008-02-14 13:50:44 +1100267 decode_pulses(iy, N, K, dec);
Jean-Marc Valinbd718ba2008-03-25 14:15:41 +1100268 mix_pitch_and_residual(iy, X, N, K, P);
Jean-Marc Valin8600f692008-02-29 15:14:12 +1100269 RESTORE_STACK;
Jean-Marc Valin0d227d82007-12-31 16:12:12 +1100270}
271
Jean-Marc Valin9455d1b2008-03-07 17:17:37 +1100272#ifdef FIXED_POINT
273static const celt_word16_t pg[11] = {32767, 24576, 21299, 19661, 19661, 19661, 18022, 18022, 16384, 16384, 16384};
274#else
Jean-Marc Valin3e650972008-03-07 17:38:58 +1100275static 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 +1100276#endif
Jean-Marc Valin0d227d82007-12-31 16:12:12 +1100277
Jean-Marc Valin208ae6e2008-03-25 15:25:08 +1100278#define MAX_INTRA 32
279#define LOG_MAX_INTRA 5
280
Jean-Marc Valin5f09ea52008-02-26 16:43:04 +1100281void 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 +1100282{
283 int i,j;
284 int best=0;
Jean-Marc Valin877b1972008-02-29 16:40:39 +1100285 celt_word32_t best_score=0;
286 celt_word16_t s = 1;
Jean-Marc Valin0aa39032007-12-07 15:09:58 +1100287 int sign;
Jean-Marc Valin877b1972008-02-29 16:40:39 +1100288 celt_word32_t E;
Jean-Marc Valin9455d1b2008-03-07 17:17:37 +1100289 celt_word16_t pred_gain;
Jean-Marc Valin8f0f4b92008-02-11 13:52:44 +1100290 int max_pos = N0-N/B;
Jean-Marc Valin208ae6e2008-03-25 15:25:08 +1100291 if (max_pos > MAX_INTRA)
292 max_pos = MAX_INTRA;
Jean-Marc Valin8f0f4b92008-02-11 13:52:44 +1100293
294 for (i=0;i<max_pos*B;i+=B)
Jean-Marc Valin4841a0a2007-12-03 13:54:30 +1100295 {
Jean-Marc Valin877b1972008-02-29 16:40:39 +1100296 celt_word32_t xy=0, yy=0;
Jean-Marc Valin03892c12008-03-07 17:25:47 +1100297 celt_word32_t score;
Jean-Marc Valin208ae6e2008-03-25 15:25:08 +1100298 /* If this doesn't generate a double-MAC on supported architectures,
299 complain to your compilor vendor */
Jean-Marc Valin4841a0a2007-12-03 13:54:30 +1100300 for (j=0;j<N;j++)
301 {
Jean-Marc Valin877b1972008-02-29 16:40:39 +1100302 xy = MAC16_16(xy, x[j], Y[i+N-j-1]);
303 yy = MAC16_16(yy, Y[i+N-j-1], Y[i+N-j-1]);
Jean-Marc Valin4841a0a2007-12-03 13:54:30 +1100304 }
Jean-Marc Valin208ae6e2008-03-25 15:25:08 +1100305 /* If you're really desperate for speed, just use xy as the score */
Jean-Marc Valin22823832008-03-22 21:17:45 +1100306 score = celt_div(MULT16_16(ROUND16(xy,14),ROUND16(xy,14)), ROUND16(yy,14));
Jean-Marc Valin4841a0a2007-12-03 13:54:30 +1100307 if (score > best_score)
308 {
309 best_score = score;
310 best = i;
Jean-Marc Valin208ae6e2008-03-25 15:25:08 +1100311 /* Store xy as the sign. We'll normalise it to +/- 1 later. */
312 s = ROUND16(xy,14);
Jean-Marc Valin4841a0a2007-12-03 13:54:30 +1100313 }
314 }
Jean-Marc Valin0aa39032007-12-07 15:09:58 +1100315 if (s<0)
Jean-Marc Valin208ae6e2008-03-25 15:25:08 +1100316 {
317 s = -1;
Jean-Marc Valin0aa39032007-12-07 15:09:58 +1100318 sign = 1;
Jean-Marc Valin208ae6e2008-03-25 15:25:08 +1100319 } else {
320 s = 1;
Jean-Marc Valin0aa39032007-12-07 15:09:58 +1100321 sign = 0;
Jean-Marc Valin208ae6e2008-03-25 15:25:08 +1100322 }
Jean-Marc Valina85657b2008-02-20 11:59:30 +1100323 /*printf ("%d %d ", sign, best);*/
Jean-Marc Valin208ae6e2008-03-25 15:25:08 +1100324 ec_enc_bits(enc,sign,1);
325 if (max_pos == MAX_INTRA)
326 ec_enc_bits(enc,best/B,LOG_MAX_INTRA);
327 else
328 ec_enc_uint(enc,best/B,max_pos);
329
Jean-Marc Valina85657b2008-02-20 11:59:30 +1100330 /*printf ("%d %f\n", best, best_score);*/
Jean-Marc Valin0d227d82007-12-31 16:12:12 +1100331
Jean-Marc Valin0d227d82007-12-31 16:12:12 +1100332 if (K>10)
333 pred_gain = pg[10];
334 else
335 pred_gain = pg[K];
Jean-Marc Valin03892c12008-03-07 17:25:47 +1100336 E = EPSILON;
Jean-Marc Valin0d227d82007-12-31 16:12:12 +1100337 for (j=0;j<N;j++)
Jean-Marc Valin4841a0a2007-12-03 13:54:30 +1100338 {
Jean-Marc Valind501f612008-02-21 12:16:57 +1100339 P[j] = s*Y[best+N-j-1];
Jean-Marc Valin877b1972008-02-29 16:40:39 +1100340 E = MAC16_16(E, P[j],P[j]);
Jean-Marc Valin4841a0a2007-12-03 13:54:30 +1100341 }
Jean-Marc Valin9455d1b2008-03-07 17:17:37 +1100342 /*pred_gain = pred_gain/sqrt(E);*/
Jean-Marc Valin23e82b22008-03-24 08:15:40 +1100343 pred_gain = MULT16_16_Q15(pred_gain,celt_rcp(SHL32(celt_sqrt(E),9)));
Jean-Marc Valin0d227d82007-12-31 16:12:12 +1100344 for (j=0;j<N;j++)
Jean-Marc Valin9455d1b2008-03-07 17:17:37 +1100345 P[j] = PSHR32(MULT16_16(pred_gain, P[j]),8);
Jean-Marc Valin0d227d82007-12-31 16:12:12 +1100346 if (K>0)
347 {
348 for (j=0;j<N;j++)
349 x[j] -= P[j];
350 } else {
351 for (j=0;j<N;j++)
352 x[j] = P[j];
353 }
Jean-Marc Valina85657b2008-02-20 11:59:30 +1100354 /*printf ("quant ");*/
355 /*for (j=0;j<N;j++) printf ("%f ", P[j]);*/
Jean-Marc Valin0d227d82007-12-31 16:12:12 +1100356
Jean-Marc Valin4841a0a2007-12-03 13:54:30 +1100357}
Jean-Marc Valinfc08d0a2007-12-07 13:26:15 +1100358
Jean-Marc Valin18ddc022008-02-22 14:24:50 +1100359void 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 +1100360{
Jean-Marc Valin11f01722007-12-09 01:19:36 +1100361 int j;
Jean-Marc Valin0aa39032007-12-07 15:09:58 +1100362 int sign;
Jean-Marc Valin877b1972008-02-29 16:40:39 +1100363 celt_word16_t s;
Jean-Marc Valin6e9058a2007-12-07 14:59:06 +1100364 int best;
Jean-Marc Valin877b1972008-02-29 16:40:39 +1100365 celt_word32_t E;
Jean-Marc Valin9455d1b2008-03-07 17:17:37 +1100366 celt_word16_t pred_gain;
Jean-Marc Valin8f0f4b92008-02-11 13:52:44 +1100367 int max_pos = N0-N/B;
Jean-Marc Valin208ae6e2008-03-25 15:25:08 +1100368 if (max_pos > MAX_INTRA)
369 max_pos = MAX_INTRA;
Jean-Marc Valin8f0f4b92008-02-11 13:52:44 +1100370
Jean-Marc Valin208ae6e2008-03-25 15:25:08 +1100371 sign = ec_dec_bits(dec, 1);
Jean-Marc Valin0aa39032007-12-07 15:09:58 +1100372 if (sign == 0)
Jean-Marc Valin6e9058a2007-12-07 14:59:06 +1100373 s = 1;
374 else
375 s = -1;
376
Jean-Marc Valin208ae6e2008-03-25 15:25:08 +1100377 if (max_pos == MAX_INTRA)
378 best = B*ec_dec_bits(dec, LOG_MAX_INTRA);
379 else
380 best = B*ec_dec_uint(dec, max_pos);
Jean-Marc Valina85657b2008-02-20 11:59:30 +1100381 /*printf ("%d %d ", sign, best);*/
Jean-Marc Valin6e9058a2007-12-07 14:59:06 +1100382
Jean-Marc Valin0d227d82007-12-31 16:12:12 +1100383 if (K>10)
384 pred_gain = pg[10];
385 else
386 pred_gain = pg[K];
Jean-Marc Valin9455d1b2008-03-07 17:17:37 +1100387 E = EPSILON;
Jean-Marc Valin0d227d82007-12-31 16:12:12 +1100388 for (j=0;j<N;j++)
389 {
Jean-Marc Valind501f612008-02-21 12:16:57 +1100390 P[j] = s*Y[best+N-j-1];
Jean-Marc Valin877b1972008-02-29 16:40:39 +1100391 E = MAC16_16(E, P[j],P[j]);
Jean-Marc Valin0d227d82007-12-31 16:12:12 +1100392 }
Jean-Marc Valin9455d1b2008-03-07 17:17:37 +1100393 /*pred_gain = pred_gain/sqrt(E);*/
Jean-Marc Valin23e82b22008-03-24 08:15:40 +1100394 pred_gain = MULT16_16_Q15(pred_gain,celt_rcp(SHL32(celt_sqrt(E),9)));
Jean-Marc Valin0d227d82007-12-31 16:12:12 +1100395 for (j=0;j<N;j++)
Jean-Marc Valin9455d1b2008-03-07 17:17:37 +1100396 P[j] = PSHR32(MULT16_16(pred_gain, P[j]),8);
Jean-Marc Valin6e9058a2007-12-07 14:59:06 +1100397 if (K==0)
398 {
Jean-Marc Valin6e9058a2007-12-07 14:59:06 +1100399 for (j=0;j<N;j++)
Jean-Marc Valin0d227d82007-12-31 16:12:12 +1100400 x[j] = P[j];
Jean-Marc Valin6e9058a2007-12-07 14:59:06 +1100401 }
402}
Jean-Marc Valin0e20ca02008-02-11 15:33:53 +1100403
Jean-Marc Valin18ddc022008-02-22 14:24:50 +1100404void 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 +1100405{
Jean-Marc Valin0df0eb42008-02-13 16:00:10 +1100406 int i, j;
Jean-Marc Valin877b1972008-02-29 16:40:39 +1100407 celt_word32_t E;
Jean-Marc Valinec9b6df2008-03-07 17:05:47 +1100408 celt_word16_t g;
Jean-Marc Valin0e20ca02008-02-11 15:33:53 +1100409
Jean-Marc Valinec9b6df2008-03-07 17:05:47 +1100410 E = EPSILON;
Jean-Marc Valina536f772008-03-22 09:01:50 +1100411 if (N0 >= (Nmax>>1))
Jean-Marc Valin0e20ca02008-02-11 15:33:53 +1100412 {
Jean-Marc Valin0df0eb42008-02-13 16:00:10 +1100413 for (i=0;i<B;i++)
414 {
415 for (j=0;j<N/B;j++)
416 {
417 P[j*B+i] = Y[(Nmax-N0-j-1)*B+i];
Jean-Marc Valin877b1972008-02-29 16:40:39 +1100418 E += P[j*B+i]*P[j*B+i];
Jean-Marc Valin0df0eb42008-02-13 16:00:10 +1100419 }
420 }
421 } else {
422 for (j=0;j<N;j++)
423 {
424 P[j] = Y[j];
Jean-Marc Valin877b1972008-02-29 16:40:39 +1100425 E = MAC16_16(E, P[j],P[j]);
Jean-Marc Valin0df0eb42008-02-13 16:00:10 +1100426 }
Jean-Marc Valin0e20ca02008-02-11 15:33:53 +1100427 }
Jean-Marc Valin23e82b22008-03-24 08:15:40 +1100428 g = celt_rcp(SHL32(celt_sqrt(E),9));
Jean-Marc Valin0e20ca02008-02-11 15:33:53 +1100429 for (j=0;j<N;j++)
Jean-Marc Valinec9b6df2008-03-07 17:05:47 +1100430 P[j] = PSHR32(MULT16_16(g, P[j]),8);
Jean-Marc Valin0e20ca02008-02-11 15:33:53 +1100431 for (j=0;j<N;j++)
432 x[j] = P[j];
433}
434