blob: c2e5e9242644797f7dde87b9fb57c0126eeec4f1 [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 Valin98c86c72008-03-27 08:40:45 +110055 yshift = 13-celt_ilog2(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 Valind4018c32008-02-27 10:09:48 +110065 for (i=0;i<N;i++)
Jean-Marc Valinbd718ba2008-03-25 14:15:41 +110066 y[i] = SHL16(iy[i],yshift);
Jean-Marc Valin95088d42008-03-26 17:57:49 +110067
Jean-Marc Valind4018c32008-02-27 10:09:48 +110068 Ryp = 0;
Jean-Marc Valinb50c5412008-02-27 17:05:43 +110069 Ryy = 0;
Jean-Marc Valindf7ab432008-03-26 18:03:22 +110070 /* If this doesn't generate a dual MAC (on supported archs), fire the compiler guy */
Jean-Marc Valind4018c32008-02-27 10:09:48 +110071 for (i=0;i<N;i++)
Jean-Marc Valindf7ab432008-03-26 18:03:22 +110072 {
73 Ryp = MAC16_16(Ryp, y[i], P[i]);
74 Ryy = MAC16_16(Ryy, y[i], y[i]);
75 }
76
Jean-Marc Valin1ca07222008-02-27 17:23:04 +110077 /* g = (sqrt(Ryp^2 + Ryy - Rpp*Ryy)-Ryp)/Ryy */
Jean-Marc Valin9d5b4a62008-03-13 11:36:45 +110078 g = MULT16_32_Q15(
Jean-Marc Valinf5b05872008-03-21 10:46:17 +110079 celt_sqrt(MULT16_16(ROUND16(Ryp,14),ROUND16(Ryp,14)) + Ryy -
80 MULT16_16(ROUND16(Ryy,14),ROUND16(Rpp,14)))
81 - ROUND16(Ryp,14),
Jean-Marc Valin9d5b4a62008-03-13 11:36:45 +110082 celt_rcp(SHR32(Ryy,9)));
Jean-Marc Valind4018c32008-02-27 10:09:48 +110083
84 for (i=0;i<N;i++)
Jean-Marc Valinf5b05872008-03-21 10:46:17 +110085 X[i] = P[i] + ROUND16(MULT16_16(y[i], g),11);
Jean-Marc Valin8600f692008-02-29 15:14:12 +110086 RESTORE_STACK;
Jean-Marc Valind4018c32008-02-27 10:09:48 +110087}
88
Jean-Marc Valin41af4212007-11-30 18:35:37 +110089
Jean-Marc Valinbd718ba2008-03-25 14:15:41 +110090void 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 +110091{
Jean-Marc Valin44c63352008-03-25 21:28:40 +110092 VARDECL(celt_norm_t, y);
93 VARDECL(int, iy);
Jean-Marc Valin49134382008-03-25 16:07:05 +110094 VARDECL(int, signx);
Jean-Marc Valin44c63352008-03-25 21:28:40 +110095 int i, j, is;
96 celt_word16_t s;
Jean-Marc Valin846d4e22008-02-12 13:48:48 +110097 int pulsesLeft;
Jean-Marc Valin44c63352008-03-25 21:28:40 +110098 celt_word32_t sum;
Jean-Marc Valinbd718ba2008-03-25 14:15:41 +110099 celt_word32_t xy, yy, yp;
Jean-Marc Valin44c63352008-03-25 21:28:40 +1100100 celt_word16_t Rpp;
Jean-Marc Valinf9584772008-03-27 12:22:44 +1100101 int N_1; /* Inverse of N, in Q14 format (even for float) */
Jean-Marc Valinf675adc2008-02-28 12:15:17 +1100102#ifdef FIXED_POINT
Jean-Marc Valind748cd52008-03-01 07:27:03 +1100103 int yshift;
104#endif
105 SAVE_STACK;
106
107#ifdef FIXED_POINT
Jean-Marc Valin98c86c72008-03-27 08:40:45 +1100108 yshift = 13-celt_ilog2(K);
Jean-Marc Valinf675adc2008-02-28 12:15:17 +1100109#endif
Jean-Marc Valin9d8d9b32008-02-27 16:17:39 +1100110
Jean-Marc Valin44c63352008-03-25 21:28:40 +1100111 ALLOC(y, N, celt_norm_t);
112 ALLOC(iy, N, int);
Jean-Marc Valin49134382008-03-25 16:07:05 +1100113 ALLOC(signx, N, int);
Jean-Marc Valin124d1cd2008-03-28 00:33:04 +1100114 N_1 = 512/N;
Jean-Marc Valinf9584772008-03-27 12:22:44 +1100115
Jean-Marc Valin41af4212007-11-30 18:35:37 +1100116 for (j=0;j<N;j++)
Jean-Marc Valin0d587d82008-02-14 21:29:50 +1100117 {
Jean-Marc Valin49134382008-03-25 16:07:05 +1100118 if (X[j]>0)
119 signx[j]=1;
120 else
121 signx[j]=-1;
122 }
123
Jean-Marc Valin44c63352008-03-25 21:28:40 +1100124 sum = 0;
Jean-Marc Valin49134382008-03-25 16:07:05 +1100125 for (j=0;j<N;j++)
126 {
Jean-Marc Valin44c63352008-03-25 21:28:40 +1100127 sum = MAC16_16(sum, P[j],P[j]);
Jean-Marc Valin0d587d82008-02-14 21:29:50 +1100128 }
Jean-Marc Valin44c63352008-03-25 21:28:40 +1100129 Rpp = ROUND16(sum, NORM_SHIFT);
Jean-Marc Valinbd718ba2008-03-25 14:15:41 +1100130
Jean-Marc Valin4ff068e2008-03-15 23:34:39 +1100131 celt_assert2(Rpp<=NORM_SCALING, "Rpp should never have a norm greater than unity");
Jean-Marc Valinb60340f2008-02-26 15:41:51 +1100132
Jean-Marc Valin0d587d82008-02-14 21:29:50 +1100133 for (i=0;i<N;i++)
Jean-Marc Valinbd718ba2008-03-25 14:15:41 +1100134 y[i] = 0;
Jean-Marc Valin0d587d82008-02-14 21:29:50 +1100135 for (i=0;i<N;i++)
Jean-Marc Valinbd718ba2008-03-25 14:15:41 +1100136 iy[i] = 0;
137 xy = yy = yp = 0;
Jean-Marc Valin0d587d82008-02-14 21:29:50 +1100138
Jean-Marc Valin846d4e22008-02-12 13:48:48 +1100139 pulsesLeft = K;
140 while (pulsesLeft > 0)
Jean-Marc Valin41af4212007-11-30 18:35:37 +1100141 {
Jean-Marc Valin846d4e22008-02-12 13:48:48 +1100142 int pulsesAtOnce=1;
Jean-Marc Valin44c63352008-03-25 21:28:40 +1100143 int sign;
144 celt_word32_t Rxy, Ryy, Ryp;
145 celt_word32_t g;
Jean-Marc Valin35a1f882008-03-26 10:34:23 +1100146 celt_word32_t best_num;
147 celt_word16_t best_den;
148 int best_id;
Jean-Marc Valin0d587d82008-02-14 21:29:50 +1100149
Jean-Marc Valinbd718ba2008-03-25 14:15:41 +1100150 /* Decide on how many pulses to find at once */
Jean-Marc Valin124d1cd2008-03-28 00:33:04 +1100151 pulsesAtOnce = (pulsesLeft*N_1)>>9; /* pulsesLeft/N */
Jean-Marc Valincab576e2008-02-12 17:21:14 +1100152 if (pulsesAtOnce<1)
153 pulsesAtOnce = 1;
Jean-Marc Valin846d4e22008-02-12 13:48:48 +1100154
Jean-Marc Valin35a1f882008-03-26 10:34:23 +1100155 /* This should ensure that anything we can process will have a better score */
156 best_num = -SHR32(VERY_LARGE32,4);
157 best_den = 0;
158 best_id = 0;
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 Valinfed97d52008-03-26 21:31:56 +1100162 /* OPT: This loop is very CPU-intensive */
163 j=0;
164 do {
Jean-Marc Valin35a1f882008-03-26 10:34:23 +1100165 celt_word32_t num;
166 celt_word16_t den;
Jean-Marc Valin44c63352008-03-25 21:28:40 +1100167 /* Select sign based on X[j] alone */
168 sign = signx[j];
169 s = SHL16(sign*pulsesAtOnce, yshift);
170 /* Temporary sums of the new pulse(s) */
171 Rxy = xy + MULT16_16(s,X[j]);
172 Ryy = yy + 2*MULT16_16(s,y[j]) + MULT16_16(s,s);
Jean-Marc Valin35a1f882008-03-26 10:34:23 +1100173
174 /* Approximate score: we maximise Rxy/sqrt(Ryy) */
175 num = MULT16_16(ROUND16(Rxy,14),ABS16(ROUND16(Rxy,14)));
176 den = ROUND16(Ryy,14);
177 /* The idea is to check for num/den >= best_num/best_den, but that way
178 we can do it without any division */
Jean-Marc Valinfed97d52008-03-26 21:31:56 +1100179 /* OPT: Make sure to use a conditional move here */
Jean-Marc Valin233e3172008-03-26 15:46:51 +1100180 if (MULT16_32_Q15(best_den, num) > MULT16_32_Q15(den, best_num))
Jean-Marc Valin35a1f882008-03-26 10:34:23 +1100181 {
182 best_den = den;
183 best_num = num;
184 best_id = j;
185 }
Jean-Marc Valinfed97d52008-03-26 21:31:56 +1100186 } while (++j<N); /* Promises we loop at least once */
Jean-Marc Valin44c63352008-03-25 21:28:40 +1100187 } else {
188 for (j=0;j<N;j++)
189 {
Jean-Marc Valin35a1f882008-03-26 10:34:23 +1100190 celt_word32_t num;
Jean-Marc Valin44c63352008-03-25 21:28:40 +1100191 /* Select sign based on X[j] alone */
192 sign = signx[j];
193 s = SHL16(sign*pulsesAtOnce, yshift);
194 /* Temporary sums of the new pulse(s) */
195 Rxy = xy + MULT16_16(s,X[j]);
196 Ryy = yy + 2*MULT16_16(s,y[j]) + MULT16_16(s,s);
197 Ryp = yp + MULT16_16(s, P[j]);
Jean-Marc Valinbd718ba2008-03-25 14:15:41 +1100198
Jean-Marc Valinbd718ba2008-03-25 14:15:41 +1100199 /* Compute the gain such that ||p + g*y|| = 1 */
200 g = MULT16_32_Q15(
201 celt_sqrt(MULT16_16(ROUND16(Ryp,14),ROUND16(Ryp,14)) + Ryy -
202 MULT16_16(ROUND16(Ryy,14),Rpp))
203 - ROUND16(Ryp,14),
204 celt_rcp(SHR32(Ryy,12)));
205 /* Knowing that gain, what's the error: (x-g*y)^2
206 (result is negated and we discard x^2 because it's constant) */
207 /* score = 2.f*g*Rxy - 1.f*g*g*Ryy*NORM_SCALING_1;*/
Jean-Marc Valin35a1f882008-03-26 10:34:23 +1100208 num = 2*MULT16_32_Q14(ROUND16(Rxy,14),g)
209 - MULT16_32_Q14(EXTRACT16(MULT16_32_Q14(ROUND16(Ryy,14),g)),g);
210 if (num >= best_num)
211 {
212 best_num = num;
213 best_id = j;
214 }
Jean-Marc Valin41af4212007-11-30 18:35:37 +1100215 }
Jean-Marc Valin41af4212007-11-30 18:35:37 +1100216 }
Jean-Marc Valin44c63352008-03-25 21:28:40 +1100217
Jean-Marc Valin35a1f882008-03-26 10:34:23 +1100218 j = best_id;
Jean-Marc Valin44c63352008-03-25 21:28:40 +1100219 is = signx[j]*pulsesAtOnce;
220 s = SHL16(is, yshift);
Jean-Marc Valinbd718ba2008-03-25 14:15:41 +1100221
Jean-Marc Valin44c63352008-03-25 21:28:40 +1100222 /* Updating the sums of the new pulse(s) */
223 xy = xy + MULT16_16(s,X[j]);
224 yy = yy + 2*MULT16_16(s,y[j]) + MULT16_16(s,s);
225 yp = yp + MULT16_16(s, P[j]);
Jean-Marc Valinbd718ba2008-03-25 14:15:41 +1100226
Jean-Marc Valin44c63352008-03-25 21:28:40 +1100227 /* Only now that we've made the final choice, update y/iy */
228 y[j] += s;
229 iy[j] += is;
Jean-Marc Valin846d4e22008-02-12 13:48:48 +1100230 pulsesLeft -= pulsesAtOnce;
Jean-Marc Valin41af4212007-11-30 18:35:37 +1100231 }
232
Jean-Marc Valinbd718ba2008-03-25 14:15:41 +1100233 encode_pulses(iy, N, K, enc);
Jean-Marc Valin5fa59952008-02-14 13:50:44 +1100234
Jean-Marc Valina4833ff2008-01-10 15:34:00 +1100235 /* Recompute the gain in one pass to reduce the encoder-decoder mismatch
Jean-Marc Valinbd718ba2008-03-25 14:15:41 +1100236 due to the recursive computation used in quantisation. */
237 mix_pitch_and_residual(iy, X, N, K, P);
Jean-Marc Valin8600f692008-02-29 15:14:12 +1100238 RESTORE_STACK;
Jean-Marc Valin41af4212007-11-30 18:35:37 +1100239}
240
Jean-Marc Valinbd718ba2008-03-25 14:15:41 +1100241
Jean-Marc Valin879fbfd2008-02-20 17:17:13 +1100242/** Decode pulse vector and combine the result with the pitch vector to produce
243 the final normalised signal in the current band. */
Jean-Marc Valinbd718ba2008-03-25 14:15:41 +1100244void 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 +1100245{
Jean-Marc Valin31b79d12008-03-12 17:17:23 +1100246 VARDECL(int, iy);
Jean-Marc Valin8600f692008-02-29 15:14:12 +1100247 SAVE_STACK;
Jean-Marc Valin9a0bba12008-02-20 14:08:50 +1100248 ALLOC(iy, N, int);
Jean-Marc Valin5fa59952008-02-14 13:50:44 +1100249 decode_pulses(iy, N, K, dec);
Jean-Marc Valinbd718ba2008-03-25 14:15:41 +1100250 mix_pitch_and_residual(iy, X, N, K, P);
Jean-Marc Valin8600f692008-02-29 15:14:12 +1100251 RESTORE_STACK;
Jean-Marc Valin0d227d82007-12-31 16:12:12 +1100252}
253
Jean-Marc Valin9455d1b2008-03-07 17:17:37 +1100254#ifdef FIXED_POINT
255static const celt_word16_t pg[11] = {32767, 24576, 21299, 19661, 19661, 19661, 18022, 18022, 16384, 16384, 16384};
256#else
Jean-Marc Valin3e650972008-03-07 17:38:58 +1100257static 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 +1100258#endif
Jean-Marc Valin0d227d82007-12-31 16:12:12 +1100259
Jean-Marc Valin208ae6e2008-03-25 15:25:08 +1100260#define MAX_INTRA 32
261#define LOG_MAX_INTRA 5
262
Jean-Marc Valin5de868c2008-03-25 22:38:58 +1100263void 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 +1100264{
Jean-Marc Valin381b29c2008-04-10 11:00:51 +1000265 int i,j,c;
Jean-Marc Valin4841a0a2007-12-03 13:54:30 +1100266 int best=0;
Jean-Marc Valin89c5fd12008-03-26 12:16:00 +1100267 celt_word32_t best_num=-SHR32(VERY_LARGE32,4);
268 celt_word16_t best_den=0;
Jean-Marc Valin877b1972008-02-29 16:40:39 +1100269 celt_word16_t s = 1;
Jean-Marc Valin0aa39032007-12-07 15:09:58 +1100270 int sign;
Jean-Marc Valin877b1972008-02-29 16:40:39 +1100271 celt_word32_t E;
Jean-Marc Valin9455d1b2008-03-07 17:17:37 +1100272 celt_word16_t pred_gain;
Jean-Marc Valine28f25f2008-03-27 14:18:28 +1100273 int max_pos = N0-N;
Jean-Marc Valin381b29c2008-04-10 11:00:51 +1000274 VARDECL(spx_norm_t, Xr);
275 SAVE_STACK;
276
277 ALLOC(Xr, B*N, celt_norm_t);
278
Jean-Marc Valin208ae6e2008-03-25 15:25:08 +1100279 if (max_pos > MAX_INTRA)
280 max_pos = MAX_INTRA;
Jean-Marc Valin8f0f4b92008-02-11 13:52:44 +1100281
Jean-Marc Valin381b29c2008-04-10 11:00:51 +1000282 for (c=0;c<B;c++)
283 {
284 for (j=0;j<N;j++)
285 {
286 Xr[B*N-B*j-B+c] = x[B*j+c];
287 }
288 }
289
Jean-Marc Valin8f0f4b92008-02-11 13:52:44 +1100290 for (i=0;i<max_pos*B;i+=B)
Jean-Marc Valin4841a0a2007-12-03 13:54:30 +1100291 {
Jean-Marc Valin877b1972008-02-29 16:40:39 +1100292 celt_word32_t xy=0, yy=0;
Jean-Marc Valin89c5fd12008-03-26 12:16:00 +1100293 celt_word32_t num;
294 celt_word16_t den;
Jean-Marc Valinfed97d52008-03-26 21:31:56 +1100295 /* OPT: If this doesn't generate a double-MAC (on supported architectures),
Jean-Marc Valin208ae6e2008-03-25 15:25:08 +1100296 complain to your compilor vendor */
Jean-Marc Valinfed97d52008-03-26 21:31:56 +1100297 j=0;
298 do {
Jean-Marc Valin381b29c2008-04-10 11:00:51 +1000299 xy = MAC16_16(xy, Xr[B*N-j-1], Y[i+B*N-j-1]);
Jean-Marc Valine28f25f2008-03-27 14:18:28 +1100300 yy = MAC16_16(yy, Y[i+B*N-j-1], Y[i+B*N-j-1]);
301 } while (++j<B*N); /* Promises we loop at least once */
Jean-Marc Valin89c5fd12008-03-26 12:16:00 +1100302 /* Using xy^2/yy as the score but without having to do the division */
303 num = MULT16_16(ROUND16(xy,14),ROUND16(xy,14));
304 den = ROUND16(yy,14);
Jean-Marc Valin208ae6e2008-03-25 15:25:08 +1100305 /* If you're really desperate for speed, just use xy as the score */
Jean-Marc Valinfed97d52008-03-26 21:31:56 +1100306 /* OPT: Make sure to use a conditional move here */
Jean-Marc Valin89c5fd12008-03-26 12:16:00 +1100307 if (MULT16_32_Q15(best_den, num) > MULT16_32_Q15(den, best_num))
Jean-Marc Valin4841a0a2007-12-03 13:54:30 +1100308 {
Jean-Marc Valin89c5fd12008-03-26 12:16:00 +1100309 best_num = num;
310 best_den = den;
Jean-Marc Valin4841a0a2007-12-03 13:54:30 +1100311 best = i;
Jean-Marc Valin208ae6e2008-03-25 15:25:08 +1100312 /* Store xy as the sign. We'll normalise it to +/- 1 later. */
313 s = ROUND16(xy,14);
Jean-Marc Valin4841a0a2007-12-03 13:54:30 +1100314 }
315 }
Jean-Marc Valin0aa39032007-12-07 15:09:58 +1100316 if (s<0)
Jean-Marc Valin208ae6e2008-03-25 15:25:08 +1100317 {
318 s = -1;
Jean-Marc Valin0aa39032007-12-07 15:09:58 +1100319 sign = 1;
Jean-Marc Valin208ae6e2008-03-25 15:25:08 +1100320 } else {
321 s = 1;
Jean-Marc Valin0aa39032007-12-07 15:09:58 +1100322 sign = 0;
Jean-Marc Valin208ae6e2008-03-25 15:25:08 +1100323 }
Jean-Marc Valina85657b2008-02-20 11:59:30 +1100324 /*printf ("%d %d ", sign, best);*/
Jean-Marc Valin208ae6e2008-03-25 15:25:08 +1100325 ec_enc_bits(enc,sign,1);
326 if (max_pos == MAX_INTRA)
Jean-Marc Valin15588ad2008-04-10 09:00:12 +1000327 ec_enc_bits(enc,best/B,LOG_MAX_INTRA);
Jean-Marc Valin208ae6e2008-03-25 15:25:08 +1100328 else
Jean-Marc Valin15588ad2008-04-10 09:00:12 +1000329 ec_enc_uint(enc,best/B,max_pos);
Jean-Marc Valin208ae6e2008-03-25 15:25:08 +1100330
Jean-Marc Valina85657b2008-02-20 11:59:30 +1100331 /*printf ("%d %f\n", best, best_score);*/
Jean-Marc Valin0d227d82007-12-31 16:12:12 +1100332
Jean-Marc Valin0d227d82007-12-31 16:12:12 +1100333 if (K>10)
334 pred_gain = pg[10];
335 else
336 pred_gain = pg[K];
Jean-Marc Valin03892c12008-03-07 17:25:47 +1100337 E = EPSILON;
Jean-Marc Valin381b29c2008-04-10 11:00:51 +1000338 for (c=0;c<B;c++)
Jean-Marc Valin4841a0a2007-12-03 13:54:30 +1100339 {
Jean-Marc Valin381b29c2008-04-10 11:00:51 +1000340 for (j=0;j<N;j++)
341 {
342 P[B*j+c] = s*Y[best+B*(N-j-1)+c];
343 E = MAC16_16(E, P[j],P[j]);
344 }
Jean-Marc Valin4841a0a2007-12-03 13:54:30 +1100345 }
Jean-Marc Valin9455d1b2008-03-07 17:17:37 +1100346 /*pred_gain = pred_gain/sqrt(E);*/
Jean-Marc Valin23e82b22008-03-24 08:15:40 +1100347 pred_gain = MULT16_16_Q15(pred_gain,celt_rcp(SHL32(celt_sqrt(E),9)));
Jean-Marc Valine28f25f2008-03-27 14:18:28 +1100348 for (j=0;j<B*N;j++)
Jean-Marc Valin9455d1b2008-03-07 17:17:37 +1100349 P[j] = PSHR32(MULT16_16(pred_gain, P[j]),8);
Jean-Marc Valin0d227d82007-12-31 16:12:12 +1100350 if (K>0)
351 {
Jean-Marc Valine28f25f2008-03-27 14:18:28 +1100352 for (j=0;j<B*N;j++)
Jean-Marc Valin0d227d82007-12-31 16:12:12 +1100353 x[j] -= P[j];
354 } else {
Jean-Marc Valine28f25f2008-03-27 14:18:28 +1100355 for (j=0;j<B*N;j++)
Jean-Marc Valin0d227d82007-12-31 16:12:12 +1100356 x[j] = P[j];
357 }
Jean-Marc Valina85657b2008-02-20 11:59:30 +1100358 /*printf ("quant ");*/
359 /*for (j=0;j<N;j++) printf ("%f ", P[j]);*/
Jean-Marc Valin0d227d82007-12-31 16:12:12 +1100360
Jean-Marc Valin4841a0a2007-12-03 13:54:30 +1100361}
Jean-Marc Valinfc08d0a2007-12-07 13:26:15 +1100362
Jean-Marc Valin5de868c2008-03-25 22:38:58 +1100363void 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 +1100364{
Jean-Marc Valin381b29c2008-04-10 11:00:51 +1000365 int j, c;
Jean-Marc Valin0aa39032007-12-07 15:09:58 +1100366 int sign;
Jean-Marc Valin877b1972008-02-29 16:40:39 +1100367 celt_word16_t s;
Jean-Marc Valin6e9058a2007-12-07 14:59:06 +1100368 int best;
Jean-Marc Valin877b1972008-02-29 16:40:39 +1100369 celt_word32_t E;
Jean-Marc Valin9455d1b2008-03-07 17:17:37 +1100370 celt_word16_t pred_gain;
Jean-Marc Valine28f25f2008-03-27 14:18:28 +1100371 int max_pos = N0-N;
Jean-Marc Valin208ae6e2008-03-25 15:25:08 +1100372 if (max_pos > MAX_INTRA)
373 max_pos = MAX_INTRA;
Jean-Marc Valin8f0f4b92008-02-11 13:52:44 +1100374
Jean-Marc Valin208ae6e2008-03-25 15:25:08 +1100375 sign = ec_dec_bits(dec, 1);
Jean-Marc Valin0aa39032007-12-07 15:09:58 +1100376 if (sign == 0)
Jean-Marc Valin6e9058a2007-12-07 14:59:06 +1100377 s = 1;
378 else
379 s = -1;
380
Jean-Marc Valin208ae6e2008-03-25 15:25:08 +1100381 if (max_pos == MAX_INTRA)
Jean-Marc Valin15588ad2008-04-10 09:00:12 +1000382 best = B*ec_dec_bits(dec, LOG_MAX_INTRA);
Jean-Marc Valin208ae6e2008-03-25 15:25:08 +1100383 else
Jean-Marc Valin15588ad2008-04-10 09:00:12 +1000384 best = B*ec_dec_uint(dec, max_pos);
Jean-Marc Valina85657b2008-02-20 11:59:30 +1100385 /*printf ("%d %d ", sign, best);*/
Jean-Marc Valin6e9058a2007-12-07 14:59:06 +1100386
Jean-Marc Valin0d227d82007-12-31 16:12:12 +1100387 if (K>10)
388 pred_gain = pg[10];
389 else
390 pred_gain = pg[K];
Jean-Marc Valin9455d1b2008-03-07 17:17:37 +1100391 E = EPSILON;
Jean-Marc Valin381b29c2008-04-10 11:00:51 +1000392 for (c=0;c<B;c++)
Jean-Marc Valin0d227d82007-12-31 16:12:12 +1100393 {
Jean-Marc Valin381b29c2008-04-10 11:00:51 +1000394 for (j=0;j<N;j++)
395 {
396 P[B*j+c] = s*Y[best+B*(N-j-1)+c];
397 E = MAC16_16(E, P[j],P[j]);
398 }
Jean-Marc Valin0d227d82007-12-31 16:12:12 +1100399 }
Jean-Marc Valin9455d1b2008-03-07 17:17:37 +1100400 /*pred_gain = pred_gain/sqrt(E);*/
Jean-Marc Valin23e82b22008-03-24 08:15:40 +1100401 pred_gain = MULT16_16_Q15(pred_gain,celt_rcp(SHL32(celt_sqrt(E),9)));
Jean-Marc Valine28f25f2008-03-27 14:18:28 +1100402 for (j=0;j<B*N;j++)
Jean-Marc Valin9455d1b2008-03-07 17:17:37 +1100403 P[j] = PSHR32(MULT16_16(pred_gain, P[j]),8);
Jean-Marc Valin6e9058a2007-12-07 14:59:06 +1100404 if (K==0)
405 {
Jean-Marc Valine28f25f2008-03-27 14:18:28 +1100406 for (j=0;j<B*N;j++)
Jean-Marc Valin0d227d82007-12-31 16:12:12 +1100407 x[j] = P[j];
Jean-Marc Valin6e9058a2007-12-07 14:59:06 +1100408 }
409}
Jean-Marc Valin0e20ca02008-02-11 15:33:53 +1100410
Jean-Marc Valin5de868c2008-03-25 22:38:58 +1100411void 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 +1100412{
Jean-Marc Valin0df0eb42008-02-13 16:00:10 +1100413 int i, j;
Jean-Marc Valin877b1972008-02-29 16:40:39 +1100414 celt_word32_t E;
Jean-Marc Valinec9b6df2008-03-07 17:05:47 +1100415 celt_word16_t g;
Jean-Marc Valin0e20ca02008-02-11 15:33:53 +1100416
Jean-Marc Valinec9b6df2008-03-07 17:05:47 +1100417 E = EPSILON;
Jean-Marc Valina536f772008-03-22 09:01:50 +1100418 if (N0 >= (Nmax>>1))
Jean-Marc Valin0e20ca02008-02-11 15:33:53 +1100419 {
Jean-Marc Valin0df0eb42008-02-13 16:00:10 +1100420 for (i=0;i<B;i++)
421 {
Jean-Marc Valine28f25f2008-03-27 14:18:28 +1100422 for (j=0;j<N;j++)
Jean-Marc Valin0df0eb42008-02-13 16:00:10 +1100423 {
424 P[j*B+i] = Y[(Nmax-N0-j-1)*B+i];
Jean-Marc Valin877b1972008-02-29 16:40:39 +1100425 E += P[j*B+i]*P[j*B+i];
Jean-Marc Valin0df0eb42008-02-13 16:00:10 +1100426 }
427 }
428 } else {
Jean-Marc Valine28f25f2008-03-27 14:18:28 +1100429 for (j=0;j<B*N;j++)
Jean-Marc Valin0df0eb42008-02-13 16:00:10 +1100430 {
431 P[j] = Y[j];
Jean-Marc Valin877b1972008-02-29 16:40:39 +1100432 E = MAC16_16(E, P[j],P[j]);
Jean-Marc Valin0df0eb42008-02-13 16:00:10 +1100433 }
Jean-Marc Valin0e20ca02008-02-11 15:33:53 +1100434 }
Jean-Marc Valin23e82b22008-03-24 08:15:40 +1100435 g = celt_rcp(SHL32(celt_sqrt(E),9));
Jean-Marc Valine28f25f2008-03-27 14:18:28 +1100436 for (j=0;j<B*N;j++)
Jean-Marc Valinec9b6df2008-03-07 17:05:47 +1100437 P[j] = PSHR32(MULT16_16(g, P[j]),8);
Jean-Marc Valine28f25f2008-03-27 14:18:28 +1100438 for (j=0;j<B*N;j++)
Jean-Marc Valin0e20ca02008-02-11 15:33:53 +1100439 x[j] = P[j];
440}
441