blob: ddf7fa5c5c03bdb43a1ec6ece144032d14691ad3 [file] [log] [blame]
Jean-Marc Valin35a1f882008-03-26 10:34:23 +11001/* (C) 2007-2008 Jean-Marc Valin, CSIRO
Jean-Marc Valin41af4212007-11-30 18:35:37 +11002*/
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 Valin35a1f882008-03-26 10:34:23 +110042/** Takes the pitch vector and the decoded residual vector, computes the gain
43 that will give ||p+g*y||=1 and mixes the residual with the pitch. */
Jean-Marc Valin5de868c2008-03-25 22:38:58 +110044static 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 +110045{
46 int i;
Jean-Marc Valinb50c5412008-02-27 17:05:43 +110047 celt_word32_t Ryp, Ryy, Rpp;
Jean-Marc Valina847b772008-02-27 17:46:49 +110048 celt_word32_t g;
Jean-Marc Valin31b79d12008-03-12 17:17:23 +110049 VARDECL(celt_norm_t, y);
Jean-Marc Valind9de5932008-03-05 08:11:57 +110050#ifdef FIXED_POINT
51 int yshift;
52#endif
Jean-Marc Valin8600f692008-02-29 15:14:12 +110053 SAVE_STACK;
Jean-Marc Valind17edd32008-02-27 16:52:30 +110054#ifdef FIXED_POINT
Jean-Marc Valind9de5932008-03-05 08:11:57 +110055 yshift = 14-EC_ILOG(K);
Jean-Marc Valind17edd32008-02-27 16:52:30 +110056#endif
57 ALLOC(y, N, celt_norm_t);
Jean-Marc Valind4018c32008-02-27 10:09:48 +110058
59 /*for (i=0;i<N;i++)
60 printf ("%d ", iy[i]);*/
Jean-Marc Valinb50c5412008-02-27 17:05:43 +110061 Rpp = 0;
Jean-Marc Valind4018c32008-02-27 10:09:48 +110062 for (i=0;i<N;i++)
Jean-Marc Valinb50c5412008-02-27 17:05:43 +110063 Rpp = MAC16_16(Rpp,P[i],P[i]);
Jean-Marc Valind4018c32008-02-27 10:09:48 +110064
Jean-Marc Valinb50c5412008-02-27 17:05:43 +110065 Ryp = 0;
Jean-Marc Valind4018c32008-02-27 10:09:48 +110066 for (i=0;i<N;i++)
Jean-Marc Valinb50c5412008-02-27 17:05:43 +110067 Ryp = MAC16_16(Ryp,SHL16(iy[i],yshift),P[i]);
Jean-Marc Valind4018c32008-02-27 10:09:48 +110068
Jean-Marc Valind17edd32008-02-27 16:52:30 +110069 /* Remove part of the pitch component to compute the real residual from
Jean-Marc Valinbd718ba2008-03-25 14:15:41 +110070 the encoded (int) one */
Jean-Marc Valind4018c32008-02-27 10:09:48 +110071 for (i=0;i<N;i++)
Jean-Marc Valinbd718ba2008-03-25 14:15:41 +110072 y[i] = SHL16(iy[i],yshift);
Jean-Marc Valind4018c32008-02-27 10:09:48 +110073
74 /* Recompute after the projection (I think it's right) */
75 Ryp = 0;
76 for (i=0;i<N;i++)
Jean-Marc Valinb50c5412008-02-27 17:05:43 +110077 Ryp = MAC16_16(Ryp,y[i],P[i]);
Jean-Marc Valind4018c32008-02-27 10:09:48 +110078
Jean-Marc Valinb50c5412008-02-27 17:05:43 +110079 Ryy = 0;
Jean-Marc Valind4018c32008-02-27 10:09:48 +110080 for (i=0;i<N;i++)
Jean-Marc Valinb50c5412008-02-27 17:05:43 +110081 Ryy = MAC16_16(Ryy, y[i],y[i]);
Jean-Marc Valind4018c32008-02-27 10:09:48 +110082
Jean-Marc Valin1ca07222008-02-27 17:23:04 +110083 /* g = (sqrt(Ryp^2 + Ryy - Rpp*Ryy)-Ryp)/Ryy */
Jean-Marc Valin9d5b4a62008-03-13 11:36:45 +110084 g = MULT16_32_Q15(
Jean-Marc Valinf5b05872008-03-21 10:46:17 +110085 celt_sqrt(MULT16_16(ROUND16(Ryp,14),ROUND16(Ryp,14)) + Ryy -
86 MULT16_16(ROUND16(Ryy,14),ROUND16(Rpp,14)))
87 - ROUND16(Ryp,14),
Jean-Marc Valin9d5b4a62008-03-13 11:36:45 +110088 celt_rcp(SHR32(Ryy,9)));
Jean-Marc Valind4018c32008-02-27 10:09:48 +110089
90 for (i=0;i<N;i++)
Jean-Marc Valinf5b05872008-03-21 10:46:17 +110091 X[i] = P[i] + ROUND16(MULT16_16(y[i], g),11);
Jean-Marc Valin8600f692008-02-29 15:14:12 +110092 RESTORE_STACK;
Jean-Marc Valind4018c32008-02-27 10:09:48 +110093}
94
Jean-Marc Valin41af4212007-11-30 18:35:37 +110095
Jean-Marc Valinbd718ba2008-03-25 14:15:41 +110096void 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 +110097{
Jean-Marc Valin44c63352008-03-25 21:28:40 +110098 VARDECL(celt_norm_t, y);
99 VARDECL(int, iy);
Jean-Marc Valin49134382008-03-25 16:07:05 +1100100 VARDECL(int, signx);
Jean-Marc Valin44c63352008-03-25 21:28:40 +1100101 int i, j, is;
102 celt_word16_t s;
Jean-Marc Valin846d4e22008-02-12 13:48:48 +1100103 int pulsesLeft;
Jean-Marc Valin44c63352008-03-25 21:28:40 +1100104 celt_word32_t sum;
Jean-Marc Valinbd718ba2008-03-25 14:15:41 +1100105 celt_word32_t xy, yy, yp;
Jean-Marc Valin44c63352008-03-25 21:28:40 +1100106 celt_word16_t Rpp;
Jean-Marc Valinf675adc2008-02-28 12:15:17 +1100107#ifdef FIXED_POINT
Jean-Marc Valind748cd52008-03-01 07:27:03 +1100108 int yshift;
109#endif
110 SAVE_STACK;
111
112#ifdef FIXED_POINT
113 yshift = 14-EC_ILOG(K);
Jean-Marc Valinf675adc2008-02-28 12:15:17 +1100114#endif
Jean-Marc Valin9d8d9b32008-02-27 16:17:39 +1100115
Jean-Marc Valin44c63352008-03-25 21:28:40 +1100116 ALLOC(y, N, celt_norm_t);
117 ALLOC(iy, N, int);
Jean-Marc Valin49134382008-03-25 16:07:05 +1100118 ALLOC(signx, N, int);
119
Jean-Marc Valin41af4212007-11-30 18:35:37 +1100120 for (j=0;j<N;j++)
Jean-Marc Valin0d587d82008-02-14 21:29:50 +1100121 {
Jean-Marc Valin49134382008-03-25 16:07:05 +1100122 if (X[j]>0)
123 signx[j]=1;
124 else
125 signx[j]=-1;
126 }
127
Jean-Marc Valin44c63352008-03-25 21:28:40 +1100128 sum = 0;
Jean-Marc Valin49134382008-03-25 16:07:05 +1100129 for (j=0;j<N;j++)
130 {
Jean-Marc Valin44c63352008-03-25 21:28:40 +1100131 sum = MAC16_16(sum, P[j],P[j]);
Jean-Marc Valin0d587d82008-02-14 21:29:50 +1100132 }
Jean-Marc Valin44c63352008-03-25 21:28:40 +1100133 Rpp = ROUND16(sum, NORM_SHIFT);
Jean-Marc Valinbd718ba2008-03-25 14:15:41 +1100134
Jean-Marc Valin4ff068e2008-03-15 23:34:39 +1100135 celt_assert2(Rpp<=NORM_SCALING, "Rpp should never have a norm greater than unity");
Jean-Marc Valinb60340f2008-02-26 15:41:51 +1100136
Jean-Marc Valin0d587d82008-02-14 21:29:50 +1100137 for (i=0;i<N;i++)
Jean-Marc Valinbd718ba2008-03-25 14:15:41 +1100138 y[i] = 0;
Jean-Marc Valin0d587d82008-02-14 21:29:50 +1100139 for (i=0;i<N;i++)
Jean-Marc Valinbd718ba2008-03-25 14:15:41 +1100140 iy[i] = 0;
141 xy = yy = yp = 0;
Jean-Marc Valin0d587d82008-02-14 21:29:50 +1100142
Jean-Marc Valin846d4e22008-02-12 13:48:48 +1100143 pulsesLeft = K;
144 while (pulsesLeft > 0)
Jean-Marc Valin41af4212007-11-30 18:35:37 +1100145 {
Jean-Marc Valin846d4e22008-02-12 13:48:48 +1100146 int pulsesAtOnce=1;
Jean-Marc Valin44c63352008-03-25 21:28:40 +1100147 int sign;
148 celt_word32_t Rxy, Ryy, Ryp;
149 celt_word32_t g;
Jean-Marc Valin35a1f882008-03-26 10:34:23 +1100150 celt_word32_t best_num;
151 celt_word16_t best_den;
152 int best_id;
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 Valin35a1f882008-03-26 10:34:23 +1100159 /* This should ensure that anything we can process will have a better score */
160 best_num = -SHR32(VERY_LARGE32,4);
161 best_den = 0;
162 best_id = 0;
Jean-Marc Valin44c63352008-03-25 21:28:40 +1100163 /* Choose between fast and accurate strategy depending on where we are in the search */
164 if (pulsesLeft>1)
Jean-Marc Valin41af4212007-11-30 18:35:37 +1100165 {
Jean-Marc Valin44c63352008-03-25 21:28:40 +1100166 for (j=0;j<N;j++)
167 {
Jean-Marc Valin35a1f882008-03-26 10:34:23 +1100168 celt_word32_t num;
169 celt_word16_t den;
Jean-Marc Valin44c63352008-03-25 21:28:40 +1100170 /* Select sign based on X[j] alone */
171 sign = signx[j];
172 s = SHL16(sign*pulsesAtOnce, yshift);
173 /* Temporary sums of the new pulse(s) */
174 Rxy = xy + MULT16_16(s,X[j]);
175 Ryy = yy + 2*MULT16_16(s,y[j]) + MULT16_16(s,s);
Jean-Marc Valin35a1f882008-03-26 10:34:23 +1100176
177 /* Approximate score: we maximise Rxy/sqrt(Ryy) */
178 num = MULT16_16(ROUND16(Rxy,14),ABS16(ROUND16(Rxy,14)));
179 den = ROUND16(Ryy,14);
180 /* The idea is to check for num/den >= best_num/best_den, but that way
181 we can do it without any division */
182 if (MULT16_32_Q15(best_den, num) >= MULT16_32_Q15(den, best_num))
183 {
184 best_den = den;
185 best_num = num;
186 best_id = j;
187 }
Jean-Marc Valin44c63352008-03-25 21:28:40 +1100188 }
189 } else {
190 for (j=0;j<N;j++)
191 {
Jean-Marc Valin35a1f882008-03-26 10:34:23 +1100192 celt_word32_t num;
Jean-Marc Valin44c63352008-03-25 21:28:40 +1100193 /* Select sign based on X[j] alone */
194 sign = signx[j];
195 s = SHL16(sign*pulsesAtOnce, yshift);
196 /* Temporary sums of the new pulse(s) */
197 Rxy = xy + MULT16_16(s,X[j]);
198 Ryy = yy + 2*MULT16_16(s,y[j]) + MULT16_16(s,s);
199 Ryp = yp + MULT16_16(s, P[j]);
Jean-Marc Valinbd718ba2008-03-25 14:15:41 +1100200
Jean-Marc Valinbd718ba2008-03-25 14:15:41 +1100201 /* Compute the gain such that ||p + g*y|| = 1 */
202 g = MULT16_32_Q15(
203 celt_sqrt(MULT16_16(ROUND16(Ryp,14),ROUND16(Ryp,14)) + Ryy -
204 MULT16_16(ROUND16(Ryy,14),Rpp))
205 - ROUND16(Ryp,14),
206 celt_rcp(SHR32(Ryy,12)));
207 /* Knowing that gain, what's the error: (x-g*y)^2
208 (result is negated and we discard x^2 because it's constant) */
209 /* score = 2.f*g*Rxy - 1.f*g*g*Ryy*NORM_SCALING_1;*/
Jean-Marc Valin35a1f882008-03-26 10:34:23 +1100210 num = 2*MULT16_32_Q14(ROUND16(Rxy,14),g)
211 - MULT16_32_Q14(EXTRACT16(MULT16_32_Q14(ROUND16(Ryy,14),g)),g);
212 if (num >= best_num)
213 {
214 best_num = num;
215 best_id = j;
216 }
Jean-Marc Valin41af4212007-11-30 18:35:37 +1100217 }
Jean-Marc Valin41af4212007-11-30 18:35:37 +1100218 }
Jean-Marc Valin44c63352008-03-25 21:28:40 +1100219
Jean-Marc Valin35a1f882008-03-26 10:34:23 +1100220 j = best_id;
Jean-Marc Valin44c63352008-03-25 21:28:40 +1100221 is = signx[j]*pulsesAtOnce;
222 s = SHL16(is, yshift);
Jean-Marc Valinbd718ba2008-03-25 14:15:41 +1100223
Jean-Marc Valin44c63352008-03-25 21:28:40 +1100224 /* Updating the sums of the new pulse(s) */
225 xy = xy + MULT16_16(s,X[j]);
226 yy = yy + 2*MULT16_16(s,y[j]) + MULT16_16(s,s);
227 yp = yp + MULT16_16(s, P[j]);
Jean-Marc Valinbd718ba2008-03-25 14:15:41 +1100228
Jean-Marc Valin44c63352008-03-25 21:28:40 +1100229 /* Only now that we've made the final choice, update y/iy */
230 y[j] += s;
231 iy[j] += is;
Jean-Marc Valin846d4e22008-02-12 13:48:48 +1100232 pulsesLeft -= pulsesAtOnce;
Jean-Marc Valin41af4212007-11-30 18:35:37 +1100233 }
234
Jean-Marc Valinbd718ba2008-03-25 14:15:41 +1100235 encode_pulses(iy, N, K, enc);
Jean-Marc Valin5fa59952008-02-14 13:50:44 +1100236
Jean-Marc Valina4833ff2008-01-10 15:34:00 +1100237 /* Recompute the gain in one pass to reduce the encoder-decoder mismatch
Jean-Marc Valinbd718ba2008-03-25 14:15:41 +1100238 due to the recursive computation used in quantisation. */
239 mix_pitch_and_residual(iy, X, N, K, P);
Jean-Marc Valin8600f692008-02-29 15:14:12 +1100240 RESTORE_STACK;
Jean-Marc Valin41af4212007-11-30 18:35:37 +1100241}
242
Jean-Marc Valinbd718ba2008-03-25 14:15:41 +1100243
Jean-Marc Valin879fbfd2008-02-20 17:17:13 +1100244/** Decode pulse vector and combine the result with the pitch vector to produce
245 the final normalised signal in the current band. */
Jean-Marc Valinbd718ba2008-03-25 14:15:41 +1100246void 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 +1100247{
Jean-Marc Valin31b79d12008-03-12 17:17:23 +1100248 VARDECL(int, iy);
Jean-Marc Valin8600f692008-02-29 15:14:12 +1100249 SAVE_STACK;
Jean-Marc Valin9a0bba12008-02-20 14:08:50 +1100250 ALLOC(iy, N, int);
Jean-Marc Valin5fa59952008-02-14 13:50:44 +1100251 decode_pulses(iy, N, K, dec);
Jean-Marc Valinbd718ba2008-03-25 14:15:41 +1100252 mix_pitch_and_residual(iy, X, N, K, P);
Jean-Marc Valin8600f692008-02-29 15:14:12 +1100253 RESTORE_STACK;
Jean-Marc Valin0d227d82007-12-31 16:12:12 +1100254}
255
Jean-Marc Valin9455d1b2008-03-07 17:17:37 +1100256#ifdef FIXED_POINT
257static const celt_word16_t pg[11] = {32767, 24576, 21299, 19661, 19661, 19661, 18022, 18022, 16384, 16384, 16384};
258#else
Jean-Marc Valin3e650972008-03-07 17:38:58 +1100259static 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 +1100260#endif
Jean-Marc Valin0d227d82007-12-31 16:12:12 +1100261
Jean-Marc Valin208ae6e2008-03-25 15:25:08 +1100262#define MAX_INTRA 32
263#define LOG_MAX_INTRA 5
264
Jean-Marc Valin5de868c2008-03-25 22:38:58 +1100265void 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 +1100266{
267 int i,j;
268 int best=0;
Jean-Marc Valin89c5fd12008-03-26 12:16:00 +1100269 celt_word32_t best_num=-SHR32(VERY_LARGE32,4);
270 celt_word16_t best_den=0;
Jean-Marc Valin877b1972008-02-29 16:40:39 +1100271 celt_word16_t s = 1;
Jean-Marc Valin0aa39032007-12-07 15:09:58 +1100272 int sign;
Jean-Marc Valin877b1972008-02-29 16:40:39 +1100273 celt_word32_t E;
Jean-Marc Valin9455d1b2008-03-07 17:17:37 +1100274 celt_word16_t pred_gain;
Jean-Marc Valin8f0f4b92008-02-11 13:52:44 +1100275 int max_pos = N0-N/B;
Jean-Marc Valin208ae6e2008-03-25 15:25:08 +1100276 if (max_pos > MAX_INTRA)
277 max_pos = MAX_INTRA;
Jean-Marc Valin8f0f4b92008-02-11 13:52:44 +1100278
279 for (i=0;i<max_pos*B;i+=B)
Jean-Marc Valin4841a0a2007-12-03 13:54:30 +1100280 {
Jean-Marc Valin877b1972008-02-29 16:40:39 +1100281 celt_word32_t xy=0, yy=0;
Jean-Marc Valin89c5fd12008-03-26 12:16:00 +1100282 celt_word32_t num;
283 celt_word16_t den;
Jean-Marc Valin208ae6e2008-03-25 15:25:08 +1100284 /* If this doesn't generate a double-MAC on supported architectures,
285 complain to your compilor vendor */
Jean-Marc Valin4841a0a2007-12-03 13:54:30 +1100286 for (j=0;j<N;j++)
287 {
Jean-Marc Valin877b1972008-02-29 16:40:39 +1100288 xy = MAC16_16(xy, x[j], Y[i+N-j-1]);
289 yy = MAC16_16(yy, Y[i+N-j-1], Y[i+N-j-1]);
Jean-Marc Valin4841a0a2007-12-03 13:54:30 +1100290 }
Jean-Marc Valin89c5fd12008-03-26 12:16:00 +1100291 /* Using xy^2/yy as the score but without having to do the division */
292 num = MULT16_16(ROUND16(xy,14),ROUND16(xy,14));
293 den = ROUND16(yy,14);
Jean-Marc Valin208ae6e2008-03-25 15:25:08 +1100294 /* If you're really desperate for speed, just use xy as the score */
Jean-Marc Valin89c5fd12008-03-26 12:16:00 +1100295 if (MULT16_32_Q15(best_den, num) > MULT16_32_Q15(den, best_num))
Jean-Marc Valin4841a0a2007-12-03 13:54:30 +1100296 {
Jean-Marc Valin89c5fd12008-03-26 12:16:00 +1100297 best_num = num;
298 best_den = den;
Jean-Marc Valin4841a0a2007-12-03 13:54:30 +1100299 best = i;
Jean-Marc Valin208ae6e2008-03-25 15:25:08 +1100300 /* Store xy as the sign. We'll normalise it to +/- 1 later. */
301 s = ROUND16(xy,14);
Jean-Marc Valin4841a0a2007-12-03 13:54:30 +1100302 }
303 }
Jean-Marc Valin0aa39032007-12-07 15:09:58 +1100304 if (s<0)
Jean-Marc Valin208ae6e2008-03-25 15:25:08 +1100305 {
306 s = -1;
Jean-Marc Valin0aa39032007-12-07 15:09:58 +1100307 sign = 1;
Jean-Marc Valin208ae6e2008-03-25 15:25:08 +1100308 } else {
309 s = 1;
Jean-Marc Valin0aa39032007-12-07 15:09:58 +1100310 sign = 0;
Jean-Marc Valin208ae6e2008-03-25 15:25:08 +1100311 }
Jean-Marc Valina85657b2008-02-20 11:59:30 +1100312 /*printf ("%d %d ", sign, best);*/
Jean-Marc Valin208ae6e2008-03-25 15:25:08 +1100313 ec_enc_bits(enc,sign,1);
314 if (max_pos == MAX_INTRA)
315 ec_enc_bits(enc,best/B,LOG_MAX_INTRA);
316 else
317 ec_enc_uint(enc,best/B,max_pos);
318
Jean-Marc Valina85657b2008-02-20 11:59:30 +1100319 /*printf ("%d %f\n", best, best_score);*/
Jean-Marc Valin0d227d82007-12-31 16:12:12 +1100320
Jean-Marc Valin0d227d82007-12-31 16:12:12 +1100321 if (K>10)
322 pred_gain = pg[10];
323 else
324 pred_gain = pg[K];
Jean-Marc Valin03892c12008-03-07 17:25:47 +1100325 E = EPSILON;
Jean-Marc Valin0d227d82007-12-31 16:12:12 +1100326 for (j=0;j<N;j++)
Jean-Marc Valin4841a0a2007-12-03 13:54:30 +1100327 {
Jean-Marc Valind501f612008-02-21 12:16:57 +1100328 P[j] = s*Y[best+N-j-1];
Jean-Marc Valin877b1972008-02-29 16:40:39 +1100329 E = MAC16_16(E, P[j],P[j]);
Jean-Marc Valin4841a0a2007-12-03 13:54:30 +1100330 }
Jean-Marc Valin9455d1b2008-03-07 17:17:37 +1100331 /*pred_gain = pred_gain/sqrt(E);*/
Jean-Marc Valin23e82b22008-03-24 08:15:40 +1100332 pred_gain = MULT16_16_Q15(pred_gain,celt_rcp(SHL32(celt_sqrt(E),9)));
Jean-Marc Valin0d227d82007-12-31 16:12:12 +1100333 for (j=0;j<N;j++)
Jean-Marc Valin9455d1b2008-03-07 17:17:37 +1100334 P[j] = PSHR32(MULT16_16(pred_gain, P[j]),8);
Jean-Marc Valin0d227d82007-12-31 16:12:12 +1100335 if (K>0)
336 {
337 for (j=0;j<N;j++)
338 x[j] -= P[j];
339 } else {
340 for (j=0;j<N;j++)
341 x[j] = P[j];
342 }
Jean-Marc Valina85657b2008-02-20 11:59:30 +1100343 /*printf ("quant ");*/
344 /*for (j=0;j<N;j++) printf ("%f ", P[j]);*/
Jean-Marc Valin0d227d82007-12-31 16:12:12 +1100345
Jean-Marc Valin4841a0a2007-12-03 13:54:30 +1100346}
Jean-Marc Valinfc08d0a2007-12-07 13:26:15 +1100347
Jean-Marc Valin5de868c2008-03-25 22:38:58 +1100348void 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 +1100349{
Jean-Marc Valin11f01722007-12-09 01:19:36 +1100350 int j;
Jean-Marc Valin0aa39032007-12-07 15:09:58 +1100351 int sign;
Jean-Marc Valin877b1972008-02-29 16:40:39 +1100352 celt_word16_t s;
Jean-Marc Valin6e9058a2007-12-07 14:59:06 +1100353 int best;
Jean-Marc Valin877b1972008-02-29 16:40:39 +1100354 celt_word32_t E;
Jean-Marc Valin9455d1b2008-03-07 17:17:37 +1100355 celt_word16_t pred_gain;
Jean-Marc Valin8f0f4b92008-02-11 13:52:44 +1100356 int max_pos = N0-N/B;
Jean-Marc Valin208ae6e2008-03-25 15:25:08 +1100357 if (max_pos > MAX_INTRA)
358 max_pos = MAX_INTRA;
Jean-Marc Valin8f0f4b92008-02-11 13:52:44 +1100359
Jean-Marc Valin208ae6e2008-03-25 15:25:08 +1100360 sign = ec_dec_bits(dec, 1);
Jean-Marc Valin0aa39032007-12-07 15:09:58 +1100361 if (sign == 0)
Jean-Marc Valin6e9058a2007-12-07 14:59:06 +1100362 s = 1;
363 else
364 s = -1;
365
Jean-Marc Valin208ae6e2008-03-25 15:25:08 +1100366 if (max_pos == MAX_INTRA)
367 best = B*ec_dec_bits(dec, LOG_MAX_INTRA);
368 else
369 best = B*ec_dec_uint(dec, max_pos);
Jean-Marc Valina85657b2008-02-20 11:59:30 +1100370 /*printf ("%d %d ", sign, best);*/
Jean-Marc Valin6e9058a2007-12-07 14:59:06 +1100371
Jean-Marc Valin0d227d82007-12-31 16:12:12 +1100372 if (K>10)
373 pred_gain = pg[10];
374 else
375 pred_gain = pg[K];
Jean-Marc Valin9455d1b2008-03-07 17:17:37 +1100376 E = EPSILON;
Jean-Marc Valin0d227d82007-12-31 16:12:12 +1100377 for (j=0;j<N;j++)
378 {
Jean-Marc Valind501f612008-02-21 12:16:57 +1100379 P[j] = s*Y[best+N-j-1];
Jean-Marc Valin877b1972008-02-29 16:40:39 +1100380 E = MAC16_16(E, P[j],P[j]);
Jean-Marc Valin0d227d82007-12-31 16:12:12 +1100381 }
Jean-Marc Valin9455d1b2008-03-07 17:17:37 +1100382 /*pred_gain = pred_gain/sqrt(E);*/
Jean-Marc Valin23e82b22008-03-24 08:15:40 +1100383 pred_gain = MULT16_16_Q15(pred_gain,celt_rcp(SHL32(celt_sqrt(E),9)));
Jean-Marc Valin0d227d82007-12-31 16:12:12 +1100384 for (j=0;j<N;j++)
Jean-Marc Valin9455d1b2008-03-07 17:17:37 +1100385 P[j] = PSHR32(MULT16_16(pred_gain, P[j]),8);
Jean-Marc Valin6e9058a2007-12-07 14:59:06 +1100386 if (K==0)
387 {
Jean-Marc Valin6e9058a2007-12-07 14:59:06 +1100388 for (j=0;j<N;j++)
Jean-Marc Valin0d227d82007-12-31 16:12:12 +1100389 x[j] = P[j];
Jean-Marc Valin6e9058a2007-12-07 14:59:06 +1100390 }
391}
Jean-Marc Valin0e20ca02008-02-11 15:33:53 +1100392
Jean-Marc Valin5de868c2008-03-25 22:38:58 +1100393void 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 +1100394{
Jean-Marc Valin0df0eb42008-02-13 16:00:10 +1100395 int i, j;
Jean-Marc Valin877b1972008-02-29 16:40:39 +1100396 celt_word32_t E;
Jean-Marc Valinec9b6df2008-03-07 17:05:47 +1100397 celt_word16_t g;
Jean-Marc Valin0e20ca02008-02-11 15:33:53 +1100398
Jean-Marc Valinec9b6df2008-03-07 17:05:47 +1100399 E = EPSILON;
Jean-Marc Valina536f772008-03-22 09:01:50 +1100400 if (N0 >= (Nmax>>1))
Jean-Marc Valin0e20ca02008-02-11 15:33:53 +1100401 {
Jean-Marc Valin0df0eb42008-02-13 16:00:10 +1100402 for (i=0;i<B;i++)
403 {
404 for (j=0;j<N/B;j++)
405 {
406 P[j*B+i] = Y[(Nmax-N0-j-1)*B+i];
Jean-Marc Valin877b1972008-02-29 16:40:39 +1100407 E += P[j*B+i]*P[j*B+i];
Jean-Marc Valin0df0eb42008-02-13 16:00:10 +1100408 }
409 }
410 } else {
411 for (j=0;j<N;j++)
412 {
413 P[j] = Y[j];
Jean-Marc Valin877b1972008-02-29 16:40:39 +1100414 E = MAC16_16(E, P[j],P[j]);
Jean-Marc Valin0df0eb42008-02-13 16:00:10 +1100415 }
Jean-Marc Valin0e20ca02008-02-11 15:33:53 +1100416 }
Jean-Marc Valin23e82b22008-03-24 08:15:40 +1100417 g = celt_rcp(SHL32(celt_sqrt(E),9));
Jean-Marc Valin0e20ca02008-02-11 15:33:53 +1100418 for (j=0;j<N;j++)
Jean-Marc Valinec9b6df2008-03-07 17:05:47 +1100419 P[j] = PSHR32(MULT16_16(g, P[j]),8);
Jean-Marc Valin0e20ca02008-02-11 15:33:53 +1100420 for (j=0;j<N;j++)
421 x[j] = P[j];
422}
423