blob: 3a6494ef990f7fdecdd6c2cace3e97c29e14422f [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 Valin5de868c2008-03-25 22:38:58 +110045static void mix_pitch_and_residual(int * restrict iy, celt_norm_t * restrict X, int N, int K, const celt_norm_t * restrict 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 Valin41af4212007-11-30 18:35:37 +110096
Jean-Marc Valinbd718ba2008-03-25 14:15:41 +110097void 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 +110098{
Jean-Marc Valin44c63352008-03-25 21:28:40 +110099 VARDECL(celt_norm_t, y);
100 VARDECL(int, iy);
Jean-Marc Valin49134382008-03-25 16:07:05 +1100101 VARDECL(int, signx);
Jean-Marc Valin44c63352008-03-25 21:28:40 +1100102 VARDECL(celt_word32_t, scores);
103 int i, j, is;
104 celt_word16_t s;
Jean-Marc Valin846d4e22008-02-12 13:48:48 +1100105 int pulsesLeft;
Jean-Marc Valin44c63352008-03-25 21:28:40 +1100106 celt_word32_t sum;
Jean-Marc Valinbd718ba2008-03-25 14:15:41 +1100107 celt_word32_t xy, yy, yp;
Jean-Marc Valin44c63352008-03-25 21:28:40 +1100108 celt_word16_t Rpp;
Jean-Marc Valinf675adc2008-02-28 12:15:17 +1100109#ifdef FIXED_POINT
Jean-Marc Valind748cd52008-03-01 07:27:03 +1100110 int yshift;
111#endif
112 SAVE_STACK;
113
114#ifdef FIXED_POINT
115 yshift = 14-EC_ILOG(K);
Jean-Marc Valinf675adc2008-02-28 12:15:17 +1100116#endif
Jean-Marc Valin9d8d9b32008-02-27 16:17:39 +1100117
Jean-Marc Valin44c63352008-03-25 21:28:40 +1100118 ALLOC(y, N, celt_norm_t);
119 ALLOC(iy, N, int);
Jean-Marc Valin49134382008-03-25 16:07:05 +1100120 ALLOC(signx, N, int);
Jean-Marc Valin44c63352008-03-25 21:28:40 +1100121 ALLOC(scores, N, celt_word32_t);
Jean-Marc Valin49134382008-03-25 16:07:05 +1100122
Jean-Marc Valin41af4212007-11-30 18:35:37 +1100123 for (j=0;j<N;j++)
Jean-Marc Valin0d587d82008-02-14 21:29:50 +1100124 {
Jean-Marc Valin49134382008-03-25 16:07:05 +1100125 if (X[j]>0)
126 signx[j]=1;
127 else
128 signx[j]=-1;
129 }
130
Jean-Marc Valin44c63352008-03-25 21:28:40 +1100131 sum = 0;
Jean-Marc Valin49134382008-03-25 16:07:05 +1100132 for (j=0;j<N;j++)
133 {
Jean-Marc Valin44c63352008-03-25 21:28:40 +1100134 sum = MAC16_16(sum, P[j],P[j]);
Jean-Marc Valin0d587d82008-02-14 21:29:50 +1100135 }
Jean-Marc Valin44c63352008-03-25 21:28:40 +1100136 Rpp = ROUND16(sum, NORM_SHIFT);
Jean-Marc Valinbd718ba2008-03-25 14:15:41 +1100137
Jean-Marc Valin4ff068e2008-03-15 23:34:39 +1100138 celt_assert2(Rpp<=NORM_SCALING, "Rpp should never have a norm greater than unity");
Jean-Marc Valinb60340f2008-02-26 15:41:51 +1100139
Jean-Marc Valin0d587d82008-02-14 21:29:50 +1100140 for (i=0;i<N;i++)
Jean-Marc Valinbd718ba2008-03-25 14:15:41 +1100141 y[i] = 0;
Jean-Marc Valin0d587d82008-02-14 21:29:50 +1100142 for (i=0;i<N;i++)
Jean-Marc Valinbd718ba2008-03-25 14:15:41 +1100143 iy[i] = 0;
144 xy = yy = yp = 0;
Jean-Marc Valin0d587d82008-02-14 21:29:50 +1100145
Jean-Marc Valin846d4e22008-02-12 13:48:48 +1100146 pulsesLeft = K;
147 while (pulsesLeft > 0)
Jean-Marc Valin41af4212007-11-30 18:35:37 +1100148 {
Jean-Marc Valin846d4e22008-02-12 13:48:48 +1100149 int pulsesAtOnce=1;
Jean-Marc Valin44c63352008-03-25 21:28:40 +1100150 int sign;
151 celt_word32_t Rxy, Ryy, Ryp;
152 celt_word32_t g;
Jean-Marc Valin0d587d82008-02-14 21:29:50 +1100153
Jean-Marc Valinbd718ba2008-03-25 14:15:41 +1100154 /* Decide on how many pulses to find at once */
Jean-Marc Valincab576e2008-02-12 17:21:14 +1100155 pulsesAtOnce = pulsesLeft/N;
156 if (pulsesAtOnce<1)
157 pulsesAtOnce = 1;
Jean-Marc Valin846d4e22008-02-12 13:48:48 +1100158
Jean-Marc Valin44c63352008-03-25 21:28:40 +1100159 /* Choose between fast and accurate strategy depending on where we are in the search */
160 if (pulsesLeft>1)
Jean-Marc Valin41af4212007-11-30 18:35:37 +1100161 {
Jean-Marc Valin44c63352008-03-25 21:28:40 +1100162 for (j=0;j<N;j++)
163 {
164 /* Select sign based on X[j] alone */
165 sign = signx[j];
166 s = SHL16(sign*pulsesAtOnce, yshift);
167 /* Temporary sums of the new pulse(s) */
168 Rxy = xy + MULT16_16(s,X[j]);
169 Ryy = yy + 2*MULT16_16(s,y[j]) + MULT16_16(s,s);
Jean-Marc Valinbd2828f2008-03-26 08:10:27 +1100170 /* This score is approximate, but good enough for the first pulses */
Jean-Marc Valin44c63352008-03-25 21:28:40 +1100171 scores[j] = MULT32_32_Q31(MULT16_16(ROUND16(Rxy,14),ABS16(ROUND16(Rxy,14))), celt_rcp(SHR32(Ryy,12)));
172 }
173 } else {
174 for (j=0;j<N;j++)
175 {
176 /* Select sign based on X[j] alone */
177 sign = signx[j];
178 s = SHL16(sign*pulsesAtOnce, yshift);
179 /* Temporary sums of the new pulse(s) */
180 Rxy = xy + MULT16_16(s,X[j]);
181 Ryy = yy + 2*MULT16_16(s,y[j]) + MULT16_16(s,s);
182 Ryp = yp + MULT16_16(s, P[j]);
Jean-Marc Valinbd718ba2008-03-25 14:15:41 +1100183
Jean-Marc Valinbd718ba2008-03-25 14:15:41 +1100184 /* Compute the gain such that ||p + g*y|| = 1 */
185 g = MULT16_32_Q15(
186 celt_sqrt(MULT16_16(ROUND16(Ryp,14),ROUND16(Ryp,14)) + Ryy -
187 MULT16_16(ROUND16(Ryy,14),Rpp))
188 - ROUND16(Ryp,14),
189 celt_rcp(SHR32(Ryy,12)));
190 /* Knowing that gain, what's the error: (x-g*y)^2
191 (result is negated and we discard x^2 because it's constant) */
192 /* score = 2.f*g*Rxy - 1.f*g*g*Ryy*NORM_SCALING_1;*/
Jean-Marc Valin44c63352008-03-25 21:28:40 +1100193 scores[j] = 2*MULT16_32_Q14(ROUND16(Rxy,14),g)
Jean-Marc Valinbd718ba2008-03-25 14:15:41 +1100194 - MULT16_32_Q14(EXTRACT16(MULT16_32_Q14(ROUND16(Ryy,14),g)),g);
Jean-Marc Valin41af4212007-11-30 18:35:37 +1100195 }
Jean-Marc Valin41af4212007-11-30 18:35:37 +1100196 }
Jean-Marc Valin44c63352008-03-25 21:28:40 +1100197
198 j = find_max32(scores, N);
199 is = signx[j]*pulsesAtOnce;
200 s = SHL16(is, yshift);
Jean-Marc Valinbd718ba2008-03-25 14:15:41 +1100201
Jean-Marc Valin44c63352008-03-25 21:28:40 +1100202 /* Updating the sums of the new pulse(s) */
203 xy = xy + MULT16_16(s,X[j]);
204 yy = yy + 2*MULT16_16(s,y[j]) + MULT16_16(s,s);
205 yp = yp + MULT16_16(s, P[j]);
Jean-Marc Valinbd718ba2008-03-25 14:15:41 +1100206
Jean-Marc Valin44c63352008-03-25 21:28:40 +1100207 /* Only now that we've made the final choice, update y/iy */
208 y[j] += s;
209 iy[j] += is;
Jean-Marc Valin846d4e22008-02-12 13:48:48 +1100210 pulsesLeft -= pulsesAtOnce;
Jean-Marc Valin41af4212007-11-30 18:35:37 +1100211 }
212
Jean-Marc Valinbd718ba2008-03-25 14:15:41 +1100213 encode_pulses(iy, N, K, enc);
Jean-Marc Valin5fa59952008-02-14 13:50:44 +1100214
Jean-Marc Valina4833ff2008-01-10 15:34:00 +1100215 /* Recompute the gain in one pass to reduce the encoder-decoder mismatch
Jean-Marc Valinbd718ba2008-03-25 14:15:41 +1100216 due to the recursive computation used in quantisation. */
217 mix_pitch_and_residual(iy, X, N, K, P);
Jean-Marc Valin8600f692008-02-29 15:14:12 +1100218 RESTORE_STACK;
Jean-Marc Valin41af4212007-11-30 18:35:37 +1100219}
220
Jean-Marc Valinbd718ba2008-03-25 14:15:41 +1100221
Jean-Marc Valin879fbfd2008-02-20 17:17:13 +1100222/** Decode pulse vector and combine the result with the pitch vector to produce
223 the final normalised signal in the current band. */
Jean-Marc Valinbd718ba2008-03-25 14:15:41 +1100224void 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 +1100225{
Jean-Marc Valin31b79d12008-03-12 17:17:23 +1100226 VARDECL(int, iy);
Jean-Marc Valin8600f692008-02-29 15:14:12 +1100227 SAVE_STACK;
Jean-Marc Valin9a0bba12008-02-20 14:08:50 +1100228 ALLOC(iy, N, int);
Jean-Marc Valin5fa59952008-02-14 13:50:44 +1100229 decode_pulses(iy, N, K, dec);
Jean-Marc Valinbd718ba2008-03-25 14:15:41 +1100230 mix_pitch_and_residual(iy, X, N, K, P);
Jean-Marc Valin8600f692008-02-29 15:14:12 +1100231 RESTORE_STACK;
Jean-Marc Valin0d227d82007-12-31 16:12:12 +1100232}
233
Jean-Marc Valin9455d1b2008-03-07 17:17:37 +1100234#ifdef FIXED_POINT
235static const celt_word16_t pg[11] = {32767, 24576, 21299, 19661, 19661, 19661, 18022, 18022, 16384, 16384, 16384};
236#else
Jean-Marc Valin3e650972008-03-07 17:38:58 +1100237static 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 +1100238#endif
Jean-Marc Valin0d227d82007-12-31 16:12:12 +1100239
Jean-Marc Valin208ae6e2008-03-25 15:25:08 +1100240#define MAX_INTRA 32
241#define LOG_MAX_INTRA 5
242
Jean-Marc Valin5de868c2008-03-25 22:38:58 +1100243void intra_prediction(celt_norm_t *x, celt_mask_t *W, int N, int K, celt_norm_t *Y, celt_norm_t * restrict P, int B, int N0, ec_enc *enc)
Jean-Marc Valin4841a0a2007-12-03 13:54:30 +1100244{
245 int i,j;
246 int best=0;
Jean-Marc Valin877b1972008-02-29 16:40:39 +1100247 celt_word32_t best_score=0;
248 celt_word16_t s = 1;
Jean-Marc Valin0aa39032007-12-07 15:09:58 +1100249 int sign;
Jean-Marc Valin877b1972008-02-29 16:40:39 +1100250 celt_word32_t E;
Jean-Marc Valin9455d1b2008-03-07 17:17:37 +1100251 celt_word16_t pred_gain;
Jean-Marc Valin8f0f4b92008-02-11 13:52:44 +1100252 int max_pos = N0-N/B;
Jean-Marc Valin208ae6e2008-03-25 15:25:08 +1100253 if (max_pos > MAX_INTRA)
254 max_pos = MAX_INTRA;
Jean-Marc Valin8f0f4b92008-02-11 13:52:44 +1100255
256 for (i=0;i<max_pos*B;i+=B)
Jean-Marc Valin4841a0a2007-12-03 13:54:30 +1100257 {
Jean-Marc Valin877b1972008-02-29 16:40:39 +1100258 celt_word32_t xy=0, yy=0;
Jean-Marc Valin03892c12008-03-07 17:25:47 +1100259 celt_word32_t score;
Jean-Marc Valin208ae6e2008-03-25 15:25:08 +1100260 /* If this doesn't generate a double-MAC on supported architectures,
261 complain to your compilor vendor */
Jean-Marc Valin4841a0a2007-12-03 13:54:30 +1100262 for (j=0;j<N;j++)
263 {
Jean-Marc Valin877b1972008-02-29 16:40:39 +1100264 xy = MAC16_16(xy, x[j], Y[i+N-j-1]);
265 yy = MAC16_16(yy, Y[i+N-j-1], Y[i+N-j-1]);
Jean-Marc Valin4841a0a2007-12-03 13:54:30 +1100266 }
Jean-Marc Valin208ae6e2008-03-25 15:25:08 +1100267 /* If you're really desperate for speed, just use xy as the score */
Jean-Marc Valin22823832008-03-22 21:17:45 +1100268 score = celt_div(MULT16_16(ROUND16(xy,14),ROUND16(xy,14)), ROUND16(yy,14));
Jean-Marc Valin4841a0a2007-12-03 13:54:30 +1100269 if (score > best_score)
270 {
271 best_score = score;
272 best = i;
Jean-Marc Valin208ae6e2008-03-25 15:25:08 +1100273 /* Store xy as the sign. We'll normalise it to +/- 1 later. */
274 s = ROUND16(xy,14);
Jean-Marc Valin4841a0a2007-12-03 13:54:30 +1100275 }
276 }
Jean-Marc Valin0aa39032007-12-07 15:09:58 +1100277 if (s<0)
Jean-Marc Valin208ae6e2008-03-25 15:25:08 +1100278 {
279 s = -1;
Jean-Marc Valin0aa39032007-12-07 15:09:58 +1100280 sign = 1;
Jean-Marc Valin208ae6e2008-03-25 15:25:08 +1100281 } else {
282 s = 1;
Jean-Marc Valin0aa39032007-12-07 15:09:58 +1100283 sign = 0;
Jean-Marc Valin208ae6e2008-03-25 15:25:08 +1100284 }
Jean-Marc Valina85657b2008-02-20 11:59:30 +1100285 /*printf ("%d %d ", sign, best);*/
Jean-Marc Valin208ae6e2008-03-25 15:25:08 +1100286 ec_enc_bits(enc,sign,1);
287 if (max_pos == MAX_INTRA)
288 ec_enc_bits(enc,best/B,LOG_MAX_INTRA);
289 else
290 ec_enc_uint(enc,best/B,max_pos);
291
Jean-Marc Valina85657b2008-02-20 11:59:30 +1100292 /*printf ("%d %f\n", best, best_score);*/
Jean-Marc Valin0d227d82007-12-31 16:12:12 +1100293
Jean-Marc Valin0d227d82007-12-31 16:12:12 +1100294 if (K>10)
295 pred_gain = pg[10];
296 else
297 pred_gain = pg[K];
Jean-Marc Valin03892c12008-03-07 17:25:47 +1100298 E = EPSILON;
Jean-Marc Valin0d227d82007-12-31 16:12:12 +1100299 for (j=0;j<N;j++)
Jean-Marc Valin4841a0a2007-12-03 13:54:30 +1100300 {
Jean-Marc Valind501f612008-02-21 12:16:57 +1100301 P[j] = s*Y[best+N-j-1];
Jean-Marc Valin877b1972008-02-29 16:40:39 +1100302 E = MAC16_16(E, P[j],P[j]);
Jean-Marc Valin4841a0a2007-12-03 13:54:30 +1100303 }
Jean-Marc Valin9455d1b2008-03-07 17:17:37 +1100304 /*pred_gain = pred_gain/sqrt(E);*/
Jean-Marc Valin23e82b22008-03-24 08:15:40 +1100305 pred_gain = MULT16_16_Q15(pred_gain,celt_rcp(SHL32(celt_sqrt(E),9)));
Jean-Marc Valin0d227d82007-12-31 16:12:12 +1100306 for (j=0;j<N;j++)
Jean-Marc Valin9455d1b2008-03-07 17:17:37 +1100307 P[j] = PSHR32(MULT16_16(pred_gain, P[j]),8);
Jean-Marc Valin0d227d82007-12-31 16:12:12 +1100308 if (K>0)
309 {
310 for (j=0;j<N;j++)
311 x[j] -= P[j];
312 } else {
313 for (j=0;j<N;j++)
314 x[j] = P[j];
315 }
Jean-Marc Valina85657b2008-02-20 11:59:30 +1100316 /*printf ("quant ");*/
317 /*for (j=0;j<N;j++) printf ("%f ", P[j]);*/
Jean-Marc Valin0d227d82007-12-31 16:12:12 +1100318
Jean-Marc Valin4841a0a2007-12-03 13:54:30 +1100319}
Jean-Marc Valinfc08d0a2007-12-07 13:26:15 +1100320
Jean-Marc Valin5de868c2008-03-25 22:38:58 +1100321void intra_unquant(celt_norm_t *x, int N, int K, celt_norm_t *Y, celt_norm_t * restrict P, int B, int N0, ec_dec *dec)
Jean-Marc Valin6e9058a2007-12-07 14:59:06 +1100322{
Jean-Marc Valin11f01722007-12-09 01:19:36 +1100323 int j;
Jean-Marc Valin0aa39032007-12-07 15:09:58 +1100324 int sign;
Jean-Marc Valin877b1972008-02-29 16:40:39 +1100325 celt_word16_t s;
Jean-Marc Valin6e9058a2007-12-07 14:59:06 +1100326 int best;
Jean-Marc Valin877b1972008-02-29 16:40:39 +1100327 celt_word32_t E;
Jean-Marc Valin9455d1b2008-03-07 17:17:37 +1100328 celt_word16_t pred_gain;
Jean-Marc Valin8f0f4b92008-02-11 13:52:44 +1100329 int max_pos = N0-N/B;
Jean-Marc Valin208ae6e2008-03-25 15:25:08 +1100330 if (max_pos > MAX_INTRA)
331 max_pos = MAX_INTRA;
Jean-Marc Valin8f0f4b92008-02-11 13:52:44 +1100332
Jean-Marc Valin208ae6e2008-03-25 15:25:08 +1100333 sign = ec_dec_bits(dec, 1);
Jean-Marc Valin0aa39032007-12-07 15:09:58 +1100334 if (sign == 0)
Jean-Marc Valin6e9058a2007-12-07 14:59:06 +1100335 s = 1;
336 else
337 s = -1;
338
Jean-Marc Valin208ae6e2008-03-25 15:25:08 +1100339 if (max_pos == MAX_INTRA)
340 best = B*ec_dec_bits(dec, LOG_MAX_INTRA);
341 else
342 best = B*ec_dec_uint(dec, max_pos);
Jean-Marc Valina85657b2008-02-20 11:59:30 +1100343 /*printf ("%d %d ", sign, best);*/
Jean-Marc Valin6e9058a2007-12-07 14:59:06 +1100344
Jean-Marc Valin0d227d82007-12-31 16:12:12 +1100345 if (K>10)
346 pred_gain = pg[10];
347 else
348 pred_gain = pg[K];
Jean-Marc Valin9455d1b2008-03-07 17:17:37 +1100349 E = EPSILON;
Jean-Marc Valin0d227d82007-12-31 16:12:12 +1100350 for (j=0;j<N;j++)
351 {
Jean-Marc Valind501f612008-02-21 12:16:57 +1100352 P[j] = s*Y[best+N-j-1];
Jean-Marc Valin877b1972008-02-29 16:40:39 +1100353 E = MAC16_16(E, P[j],P[j]);
Jean-Marc Valin0d227d82007-12-31 16:12:12 +1100354 }
Jean-Marc Valin9455d1b2008-03-07 17:17:37 +1100355 /*pred_gain = pred_gain/sqrt(E);*/
Jean-Marc Valin23e82b22008-03-24 08:15:40 +1100356 pred_gain = MULT16_16_Q15(pred_gain,celt_rcp(SHL32(celt_sqrt(E),9)));
Jean-Marc Valin0d227d82007-12-31 16:12:12 +1100357 for (j=0;j<N;j++)
Jean-Marc Valin9455d1b2008-03-07 17:17:37 +1100358 P[j] = PSHR32(MULT16_16(pred_gain, P[j]),8);
Jean-Marc Valin6e9058a2007-12-07 14:59:06 +1100359 if (K==0)
360 {
Jean-Marc Valin6e9058a2007-12-07 14:59:06 +1100361 for (j=0;j<N;j++)
Jean-Marc Valin0d227d82007-12-31 16:12:12 +1100362 x[j] = P[j];
Jean-Marc Valin6e9058a2007-12-07 14:59:06 +1100363 }
364}
Jean-Marc Valin0e20ca02008-02-11 15:33:53 +1100365
Jean-Marc Valin5de868c2008-03-25 22:38:58 +1100366void intra_fold(celt_norm_t *x, int N, celt_norm_t *Y, celt_norm_t * restrict P, int B, int N0, int Nmax)
Jean-Marc Valin0e20ca02008-02-11 15:33:53 +1100367{
Jean-Marc Valin0df0eb42008-02-13 16:00:10 +1100368 int i, j;
Jean-Marc Valin877b1972008-02-29 16:40:39 +1100369 celt_word32_t E;
Jean-Marc Valinec9b6df2008-03-07 17:05:47 +1100370 celt_word16_t g;
Jean-Marc Valin0e20ca02008-02-11 15:33:53 +1100371
Jean-Marc Valinec9b6df2008-03-07 17:05:47 +1100372 E = EPSILON;
Jean-Marc Valina536f772008-03-22 09:01:50 +1100373 if (N0 >= (Nmax>>1))
Jean-Marc Valin0e20ca02008-02-11 15:33:53 +1100374 {
Jean-Marc Valin0df0eb42008-02-13 16:00:10 +1100375 for (i=0;i<B;i++)
376 {
377 for (j=0;j<N/B;j++)
378 {
379 P[j*B+i] = Y[(Nmax-N0-j-1)*B+i];
Jean-Marc Valin877b1972008-02-29 16:40:39 +1100380 E += P[j*B+i]*P[j*B+i];
Jean-Marc Valin0df0eb42008-02-13 16:00:10 +1100381 }
382 }
383 } else {
384 for (j=0;j<N;j++)
385 {
386 P[j] = Y[j];
Jean-Marc Valin877b1972008-02-29 16:40:39 +1100387 E = MAC16_16(E, P[j],P[j]);
Jean-Marc Valin0df0eb42008-02-13 16:00:10 +1100388 }
Jean-Marc Valin0e20ca02008-02-11 15:33:53 +1100389 }
Jean-Marc Valin23e82b22008-03-24 08:15:40 +1100390 g = celt_rcp(SHL32(celt_sqrt(E),9));
Jean-Marc Valin0e20ca02008-02-11 15:33:53 +1100391 for (j=0;j<N;j++)
Jean-Marc Valinec9b6df2008-03-07 17:05:47 +1100392 P[j] = PSHR32(MULT16_16(g, P[j]),8);
Jean-Marc Valin0e20ca02008-02-11 15:33:53 +1100393 for (j=0;j<N;j++)
394 x[j] = P[j];
395}
396