blob: f6389d29a53d74d49c576156a0e855d8c1e2f5c6 [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;
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 Valinbd718ba2008-03-25 14:15:41 +1100106void 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 +1100107{
Jean-Marc Valin31b79d12008-03-12 17:17:23 +1100108 VARDECL(celt_norm_t, _y);
109 VARDECL(celt_norm_t, _ny);
110 VARDECL(int, _iy);
111 VARDECL(int, _iny);
Jean-Marc Valin49134382008-03-25 16:07:05 +1100112 VARDECL(int, signx);
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);
Jean-Marc Valin49134382008-03-25 16:07:05 +1100133 ALLOC(signx, N, int);
134
Jean-Marc Valinbd718ba2008-03-25 14:15:41 +1100135 y = _y;
136 ny = _ny;
137 iy = _iy;
138 iny = _iny;
Jean-Marc Valinfe419832008-02-12 15:05:01 +1100139
Jean-Marc Valin41af4212007-11-30 18:35:37 +1100140 for (j=0;j<N;j++)
Jean-Marc Valin0d587d82008-02-14 21:29:50 +1100141 {
Jean-Marc Valin49134382008-03-25 16:07:05 +1100142 if (X[j]>0)
143 signx[j]=1;
144 else
145 signx[j]=-1;
146 }
147
148 for (j=0;j<N;j++)
149 {
Jean-Marc Valinf675adc2008-02-28 12:15:17 +1100150 Rpp = MAC16_16(Rpp, P[j],P[j]);
151 Rxp = MAC16_16(Rxp, X[j],P[j]);
Jean-Marc Valin0d587d82008-02-14 21:29:50 +1100152 }
Jean-Marc Valinf5b05872008-03-21 10:46:17 +1100153 Rpp = ROUND16(Rpp, NORM_SHIFT);
154 Rxp = ROUND16(Rxp, NORM_SHIFT);
Jean-Marc Valinbd718ba2008-03-25 14:15:41 +1100155
Jean-Marc Valin4ff068e2008-03-15 23:34:39 +1100156 celt_assert2(Rpp<=NORM_SCALING, "Rpp should never have a norm greater than unity");
Jean-Marc Valinb60340f2008-02-26 15:41:51 +1100157
Jean-Marc Valin0d587d82008-02-14 21:29:50 +1100158 for (i=0;i<N;i++)
Jean-Marc Valinbd718ba2008-03-25 14:15:41 +1100159 y[i] = 0;
Jean-Marc Valin0d587d82008-02-14 21:29:50 +1100160 for (i=0;i<N;i++)
Jean-Marc Valinbd718ba2008-03-25 14:15:41 +1100161 iy[i] = 0;
162 xy = yy = yp = 0;
Jean-Marc Valin0d587d82008-02-14 21:29:50 +1100163
Jean-Marc Valin846d4e22008-02-12 13:48:48 +1100164 pulsesLeft = K;
165 while (pulsesLeft > 0)
Jean-Marc Valin41af4212007-11-30 18:35:37 +1100166 {
Jean-Marc Valin846d4e22008-02-12 13:48:48 +1100167 int pulsesAtOnce=1;
Jean-Marc Valin0d587d82008-02-14 21:29:50 +1100168
Jean-Marc Valinbd718ba2008-03-25 14:15:41 +1100169 /* Decide on how many pulses to find at once */
Jean-Marc Valincab576e2008-02-12 17:21:14 +1100170 pulsesAtOnce = pulsesLeft/N;
171 if (pulsesAtOnce<1)
172 pulsesAtOnce = 1;
Jean-Marc Valina85657b2008-02-20 11:59:30 +1100173 /*printf ("%d %d %d/%d %d\n", Lupdate, pulsesAtOnce, pulsesLeft, K, N);*/
Jean-Marc Valin846d4e22008-02-12 13:48:48 +1100174
Jean-Marc Valinbd718ba2008-03-25 14:15:41 +1100175 nbest.score = -VERY_LARGE32;
Jean-Marc Valin41af4212007-11-30 18:35:37 +1100176
Jean-Marc Valinbd718ba2008-03-25 14:15:41 +1100177 for (j=0;j<N;j++)
Jean-Marc Valin41af4212007-11-30 18:35:37 +1100178 {
Jean-Marc Valinbd718ba2008-03-25 14:15:41 +1100179 int sign;
180 /*fprintf (stderr, "%d/%d %d/%d %d/%d\n", i, K, m, L2, j, N);*/
181 celt_word32_t Rxy, Ryy, Ryp;
182 celt_word32_t score;
183 celt_word32_t g;
184 celt_word16_t s;
185
186 /* Select sign based on X[j] alone */
Jean-Marc Valin49134382008-03-25 16:07:05 +1100187 sign = signx[j];
Jean-Marc Valinbd718ba2008-03-25 14:15:41 +1100188 s = SHL16(sign*pulsesAtOnce, yshift);
189
190 /* Updating the sums of the new pulse(s) */
191 Rxy = xy + MULT16_16(s,X[j]);
192 Ryy = yy + 2*MULT16_16(s,y[j]) + MULT16_16(s,s);
193 Ryp = yp + MULT16_16(s, P[j]);
194
195 if (pulsesLeft>1)
Jean-Marc Valin41af4212007-11-30 18:35:37 +1100196 {
Jean-Marc Valinbd718ba2008-03-25 14:15:41 +1100197 score = MULT32_32_Q31(MULT16_16(ROUND16(Rxy,14),ABS16(ROUND16(Rxy,14))), celt_rcp(SHR32(Ryy,12)));
198 } else
199 {
200 /* Compute the gain such that ||p + g*y|| = 1 */
201 g = MULT16_32_Q15(
202 celt_sqrt(MULT16_16(ROUND16(Ryp,14),ROUND16(Ryp,14)) + Ryy -
203 MULT16_16(ROUND16(Ryy,14),Rpp))
204 - ROUND16(Ryp,14),
205 celt_rcp(SHR32(Ryy,12)));
206 /* Knowing that gain, what's the error: (x-g*y)^2
207 (result is negated and we discard x^2 because it's constant) */
208 /* score = 2.f*g*Rxy - 1.f*g*g*Ryy*NORM_SCALING_1;*/
209 score = 2*MULT16_32_Q14(ROUND16(Rxy,14),g)
210 - MULT16_32_Q14(EXTRACT16(MULT16_32_Q14(ROUND16(Ryy,14),g)),g);
Jean-Marc Valin41af4212007-11-30 18:35:37 +1100211 }
Jean-Marc Valinbd718ba2008-03-25 14:15:41 +1100212
213 if (score>nbest.score)
214 {
215 nbest.score = score;
216 nbest.pos = j;
Jean-Marc Valinbd718ba2008-03-25 14:15:41 +1100217 nbest.sign = sign;
218 nbest.xy = Rxy;
219 nbest.yy = Ryy;
220 nbest.yp = Ryp;
221 }
Jean-Marc Valin41af4212007-11-30 18:35:37 +1100222 }
Jean-Marc Valinbd718ba2008-03-25 14:15:41 +1100223
Jean-Marc Valin49134382008-03-25 16:07:05 +1100224 celt_assert2(nbest.score > -VERY_LARGE32, "Could not find any match in VQ codebook. Something got corrupted somewhere.");
Jean-Marc Valinbd718ba2008-03-25 14:15:41 +1100225
Jean-Marc Valin0d587d82008-02-14 21:29:50 +1100226 /* Only now that we've made the final choice, update ny/iny and others */
Jean-Marc Valin41af4212007-11-30 18:35:37 +1100227 {
Jean-Marc Valin3b277dc2008-02-14 16:46:50 +1100228 int n;
229 int is;
Jean-Marc Valin8b158f52008-02-28 14:44:19 +1100230 celt_norm_t s;
Jean-Marc Valinbd718ba2008-03-25 14:15:41 +1100231 is = nbest.sign*pulsesAtOnce;
Jean-Marc Valinf675adc2008-02-28 12:15:17 +1100232 s = SHL16(is, yshift);
Jean-Marc Valin3b277dc2008-02-14 16:46:50 +1100233 for (n=0;n<N;n++)
Jean-Marc Valinbd718ba2008-03-25 14:15:41 +1100234 ny[n] = y[n];
235 ny[nbest.pos] += s;
Jean-Marc Valin0d587d82008-02-14 21:29:50 +1100236
Jean-Marc Valin3b277dc2008-02-14 16:46:50 +1100237 for (n=0;n<N;n++)
Jean-Marc Valinbd718ba2008-03-25 14:15:41 +1100238 iny[n] = iy[n];
239 iny[nbest.pos] += is;
Jean-Marc Valin0d587d82008-02-14 21:29:50 +1100240
Jean-Marc Valinbd718ba2008-03-25 14:15:41 +1100241 xy = nbest.xy;
242 yy = nbest.yy;
243 yp = nbest.yp;
Jean-Marc Valin3b277dc2008-02-14 16:46:50 +1100244 }
Jean-Marc Valin0d587d82008-02-14 21:29:50 +1100245 /* Swap ny/iny with y/iy */
Jean-Marc Valin3b277dc2008-02-14 16:46:50 +1100246 {
Jean-Marc Valin8b158f52008-02-28 14:44:19 +1100247 celt_norm_t *tmp_ny;
Jean-Marc Valinfe419832008-02-12 15:05:01 +1100248 int *tmp_iny;
249
Jean-Marc Valinbd718ba2008-03-25 14:15:41 +1100250 tmp_ny = ny;
251 ny = y;
252 y = tmp_ny;
253 tmp_iny = iny;
254 iny = iy;
255 iy = tmp_iny;
Jean-Marc Valin41af4212007-11-30 18:35:37 +1100256 }
Jean-Marc Valin846d4e22008-02-12 13:48:48 +1100257 pulsesLeft -= pulsesAtOnce;
Jean-Marc Valin41af4212007-11-30 18:35:37 +1100258 }
259
Jean-Marc Valinbd718ba2008-03-25 14:15:41 +1100260 encode_pulses(iy, N, K, enc);
Jean-Marc Valin5fa59952008-02-14 13:50:44 +1100261
Jean-Marc Valina4833ff2008-01-10 15:34:00 +1100262 /* Recompute the gain in one pass to reduce the encoder-decoder mismatch
Jean-Marc Valinbd718ba2008-03-25 14:15:41 +1100263 due to the recursive computation used in quantisation. */
264 mix_pitch_and_residual(iy, X, N, K, P);
Jean-Marc Valin8600f692008-02-29 15:14:12 +1100265 RESTORE_STACK;
Jean-Marc Valin41af4212007-11-30 18:35:37 +1100266}
267
Jean-Marc Valinbd718ba2008-03-25 14:15:41 +1100268
Jean-Marc Valin879fbfd2008-02-20 17:17:13 +1100269/** Decode pulse vector and combine the result with the pitch vector to produce
270 the final normalised signal in the current band. */
Jean-Marc Valinbd718ba2008-03-25 14:15:41 +1100271void 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 +1100272{
Jean-Marc Valin31b79d12008-03-12 17:17:23 +1100273 VARDECL(int, iy);
Jean-Marc Valin8600f692008-02-29 15:14:12 +1100274 SAVE_STACK;
Jean-Marc Valin9a0bba12008-02-20 14:08:50 +1100275 ALLOC(iy, N, int);
Jean-Marc Valin5fa59952008-02-14 13:50:44 +1100276 decode_pulses(iy, N, K, dec);
Jean-Marc Valinbd718ba2008-03-25 14:15:41 +1100277 mix_pitch_and_residual(iy, X, N, K, P);
Jean-Marc Valin8600f692008-02-29 15:14:12 +1100278 RESTORE_STACK;
Jean-Marc Valin0d227d82007-12-31 16:12:12 +1100279}
280
Jean-Marc Valin9455d1b2008-03-07 17:17:37 +1100281#ifdef FIXED_POINT
282static const celt_word16_t pg[11] = {32767, 24576, 21299, 19661, 19661, 19661, 18022, 18022, 16384, 16384, 16384};
283#else
Jean-Marc Valin3e650972008-03-07 17:38:58 +1100284static 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 +1100285#endif
Jean-Marc Valin0d227d82007-12-31 16:12:12 +1100286
Jean-Marc Valin208ae6e2008-03-25 15:25:08 +1100287#define MAX_INTRA 32
288#define LOG_MAX_INTRA 5
289
Jean-Marc Valin5f09ea52008-02-26 16:43:04 +1100290void 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 +1100291{
292 int i,j;
293 int best=0;
Jean-Marc Valin877b1972008-02-29 16:40:39 +1100294 celt_word32_t best_score=0;
295 celt_word16_t s = 1;
Jean-Marc Valin0aa39032007-12-07 15:09:58 +1100296 int sign;
Jean-Marc Valin877b1972008-02-29 16:40:39 +1100297 celt_word32_t E;
Jean-Marc Valin9455d1b2008-03-07 17:17:37 +1100298 celt_word16_t pred_gain;
Jean-Marc Valin8f0f4b92008-02-11 13:52:44 +1100299 int max_pos = N0-N/B;
Jean-Marc Valin208ae6e2008-03-25 15:25:08 +1100300 if (max_pos > MAX_INTRA)
301 max_pos = MAX_INTRA;
Jean-Marc Valin8f0f4b92008-02-11 13:52:44 +1100302
303 for (i=0;i<max_pos*B;i+=B)
Jean-Marc Valin4841a0a2007-12-03 13:54:30 +1100304 {
Jean-Marc Valin877b1972008-02-29 16:40:39 +1100305 celt_word32_t xy=0, yy=0;
Jean-Marc Valin03892c12008-03-07 17:25:47 +1100306 celt_word32_t score;
Jean-Marc Valin208ae6e2008-03-25 15:25:08 +1100307 /* If this doesn't generate a double-MAC on supported architectures,
308 complain to your compilor vendor */
Jean-Marc Valin4841a0a2007-12-03 13:54:30 +1100309 for (j=0;j<N;j++)
310 {
Jean-Marc Valin877b1972008-02-29 16:40:39 +1100311 xy = MAC16_16(xy, x[j], Y[i+N-j-1]);
312 yy = MAC16_16(yy, Y[i+N-j-1], Y[i+N-j-1]);
Jean-Marc Valin4841a0a2007-12-03 13:54:30 +1100313 }
Jean-Marc Valin208ae6e2008-03-25 15:25:08 +1100314 /* If you're really desperate for speed, just use xy as the score */
Jean-Marc Valin22823832008-03-22 21:17:45 +1100315 score = celt_div(MULT16_16(ROUND16(xy,14),ROUND16(xy,14)), ROUND16(yy,14));
Jean-Marc Valin4841a0a2007-12-03 13:54:30 +1100316 if (score > best_score)
317 {
318 best_score = score;
319 best = i;
Jean-Marc Valin208ae6e2008-03-25 15:25:08 +1100320 /* Store xy as the sign. We'll normalise it to +/- 1 later. */
321 s = ROUND16(xy,14);
Jean-Marc Valin4841a0a2007-12-03 13:54:30 +1100322 }
323 }
Jean-Marc Valin0aa39032007-12-07 15:09:58 +1100324 if (s<0)
Jean-Marc Valin208ae6e2008-03-25 15:25:08 +1100325 {
326 s = -1;
Jean-Marc Valin0aa39032007-12-07 15:09:58 +1100327 sign = 1;
Jean-Marc Valin208ae6e2008-03-25 15:25:08 +1100328 } else {
329 s = 1;
Jean-Marc Valin0aa39032007-12-07 15:09:58 +1100330 sign = 0;
Jean-Marc Valin208ae6e2008-03-25 15:25:08 +1100331 }
Jean-Marc Valina85657b2008-02-20 11:59:30 +1100332 /*printf ("%d %d ", sign, best);*/
Jean-Marc Valin208ae6e2008-03-25 15:25:08 +1100333 ec_enc_bits(enc,sign,1);
334 if (max_pos == MAX_INTRA)
335 ec_enc_bits(enc,best/B,LOG_MAX_INTRA);
336 else
337 ec_enc_uint(enc,best/B,max_pos);
338
Jean-Marc Valina85657b2008-02-20 11:59:30 +1100339 /*printf ("%d %f\n", best, best_score);*/
Jean-Marc Valin0d227d82007-12-31 16:12:12 +1100340
Jean-Marc Valin0d227d82007-12-31 16:12:12 +1100341 if (K>10)
342 pred_gain = pg[10];
343 else
344 pred_gain = pg[K];
Jean-Marc Valin03892c12008-03-07 17:25:47 +1100345 E = EPSILON;
Jean-Marc Valin0d227d82007-12-31 16:12:12 +1100346 for (j=0;j<N;j++)
Jean-Marc Valin4841a0a2007-12-03 13:54:30 +1100347 {
Jean-Marc Valind501f612008-02-21 12:16:57 +1100348 P[j] = s*Y[best+N-j-1];
Jean-Marc Valin877b1972008-02-29 16:40:39 +1100349 E = MAC16_16(E, P[j],P[j]);
Jean-Marc Valin4841a0a2007-12-03 13:54:30 +1100350 }
Jean-Marc Valin9455d1b2008-03-07 17:17:37 +1100351 /*pred_gain = pred_gain/sqrt(E);*/
Jean-Marc Valin23e82b22008-03-24 08:15:40 +1100352 pred_gain = MULT16_16_Q15(pred_gain,celt_rcp(SHL32(celt_sqrt(E),9)));
Jean-Marc Valin0d227d82007-12-31 16:12:12 +1100353 for (j=0;j<N;j++)
Jean-Marc Valin9455d1b2008-03-07 17:17:37 +1100354 P[j] = PSHR32(MULT16_16(pred_gain, P[j]),8);
Jean-Marc Valin0d227d82007-12-31 16:12:12 +1100355 if (K>0)
356 {
357 for (j=0;j<N;j++)
358 x[j] -= P[j];
359 } else {
360 for (j=0;j<N;j++)
361 x[j] = P[j];
362 }
Jean-Marc Valina85657b2008-02-20 11:59:30 +1100363 /*printf ("quant ");*/
364 /*for (j=0;j<N;j++) printf ("%f ", P[j]);*/
Jean-Marc Valin0d227d82007-12-31 16:12:12 +1100365
Jean-Marc Valin4841a0a2007-12-03 13:54:30 +1100366}
Jean-Marc Valinfc08d0a2007-12-07 13:26:15 +1100367
Jean-Marc Valin18ddc022008-02-22 14:24:50 +1100368void 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 +1100369{
Jean-Marc Valin11f01722007-12-09 01:19:36 +1100370 int j;
Jean-Marc Valin0aa39032007-12-07 15:09:58 +1100371 int sign;
Jean-Marc Valin877b1972008-02-29 16:40:39 +1100372 celt_word16_t s;
Jean-Marc Valin6e9058a2007-12-07 14:59:06 +1100373 int best;
Jean-Marc Valin877b1972008-02-29 16:40:39 +1100374 celt_word32_t E;
Jean-Marc Valin9455d1b2008-03-07 17:17:37 +1100375 celt_word16_t pred_gain;
Jean-Marc Valin8f0f4b92008-02-11 13:52:44 +1100376 int max_pos = N0-N/B;
Jean-Marc Valin208ae6e2008-03-25 15:25:08 +1100377 if (max_pos > MAX_INTRA)
378 max_pos = MAX_INTRA;
Jean-Marc Valin8f0f4b92008-02-11 13:52:44 +1100379
Jean-Marc Valin208ae6e2008-03-25 15:25:08 +1100380 sign = ec_dec_bits(dec, 1);
Jean-Marc Valin0aa39032007-12-07 15:09:58 +1100381 if (sign == 0)
Jean-Marc Valin6e9058a2007-12-07 14:59:06 +1100382 s = 1;
383 else
384 s = -1;
385
Jean-Marc Valin208ae6e2008-03-25 15:25:08 +1100386 if (max_pos == MAX_INTRA)
387 best = B*ec_dec_bits(dec, LOG_MAX_INTRA);
388 else
389 best = B*ec_dec_uint(dec, max_pos);
Jean-Marc Valina85657b2008-02-20 11:59:30 +1100390 /*printf ("%d %d ", sign, best);*/
Jean-Marc Valin6e9058a2007-12-07 14:59:06 +1100391
Jean-Marc Valin0d227d82007-12-31 16:12:12 +1100392 if (K>10)
393 pred_gain = pg[10];
394 else
395 pred_gain = pg[K];
Jean-Marc Valin9455d1b2008-03-07 17:17:37 +1100396 E = EPSILON;
Jean-Marc Valin0d227d82007-12-31 16:12:12 +1100397 for (j=0;j<N;j++)
398 {
Jean-Marc Valind501f612008-02-21 12:16:57 +1100399 P[j] = s*Y[best+N-j-1];
Jean-Marc Valin877b1972008-02-29 16:40:39 +1100400 E = MAC16_16(E, P[j],P[j]);
Jean-Marc Valin0d227d82007-12-31 16:12:12 +1100401 }
Jean-Marc Valin9455d1b2008-03-07 17:17:37 +1100402 /*pred_gain = pred_gain/sqrt(E);*/
Jean-Marc Valin23e82b22008-03-24 08:15:40 +1100403 pred_gain = MULT16_16_Q15(pred_gain,celt_rcp(SHL32(celt_sqrt(E),9)));
Jean-Marc Valin0d227d82007-12-31 16:12:12 +1100404 for (j=0;j<N;j++)
Jean-Marc Valin9455d1b2008-03-07 17:17:37 +1100405 P[j] = PSHR32(MULT16_16(pred_gain, P[j]),8);
Jean-Marc Valin6e9058a2007-12-07 14:59:06 +1100406 if (K==0)
407 {
Jean-Marc Valin6e9058a2007-12-07 14:59:06 +1100408 for (j=0;j<N;j++)
Jean-Marc Valin0d227d82007-12-31 16:12:12 +1100409 x[j] = P[j];
Jean-Marc Valin6e9058a2007-12-07 14:59:06 +1100410 }
411}
Jean-Marc Valin0e20ca02008-02-11 15:33:53 +1100412
Jean-Marc Valin18ddc022008-02-22 14:24:50 +1100413void 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 +1100414{
Jean-Marc Valin0df0eb42008-02-13 16:00:10 +1100415 int i, j;
Jean-Marc Valin877b1972008-02-29 16:40:39 +1100416 celt_word32_t E;
Jean-Marc Valinec9b6df2008-03-07 17:05:47 +1100417 celt_word16_t g;
Jean-Marc Valin0e20ca02008-02-11 15:33:53 +1100418
Jean-Marc Valinec9b6df2008-03-07 17:05:47 +1100419 E = EPSILON;
Jean-Marc Valina536f772008-03-22 09:01:50 +1100420 if (N0 >= (Nmax>>1))
Jean-Marc Valin0e20ca02008-02-11 15:33:53 +1100421 {
Jean-Marc Valin0df0eb42008-02-13 16:00:10 +1100422 for (i=0;i<B;i++)
423 {
424 for (j=0;j<N/B;j++)
425 {
426 P[j*B+i] = Y[(Nmax-N0-j-1)*B+i];
Jean-Marc Valin877b1972008-02-29 16:40:39 +1100427 E += P[j*B+i]*P[j*B+i];
Jean-Marc Valin0df0eb42008-02-13 16:00:10 +1100428 }
429 }
430 } else {
431 for (j=0;j<N;j++)
432 {
433 P[j] = Y[j];
Jean-Marc Valin877b1972008-02-29 16:40:39 +1100434 E = MAC16_16(E, P[j],P[j]);
Jean-Marc Valin0df0eb42008-02-13 16:00:10 +1100435 }
Jean-Marc Valin0e20ca02008-02-11 15:33:53 +1100436 }
Jean-Marc Valin23e82b22008-03-24 08:15:40 +1100437 g = celt_rcp(SHL32(celt_sqrt(E),9));
Jean-Marc Valin0e20ca02008-02-11 15:33:53 +1100438 for (j=0;j<N;j++)
Jean-Marc Valinec9b6df2008-03-07 17:05:47 +1100439 P[j] = PSHR32(MULT16_16(g, P[j]),8);
Jean-Marc Valin0e20ca02008-02-11 15:33:53 +1100440 for (j=0;j<N;j++)
441 x[j] = P[j];
442}
443