blob: c7ece7da68b432a2fe495c87cb5e7f6db1054c71 [file] [log] [blame]
Jean-Marc Valin8b2ff0d2009-10-17 21:40:10 -04001/* Copyright (c) 2007-2008 CSIRO
2 Copyright (c) 2007-2009 Xiph.Org Foundation
3 Written by Jean-Marc Valin */
Jean-Marc Valin41af4212007-11-30 18:35:37 +11004/*
5 Redistribution and use in source and binary forms, with or without
6 modification, are permitted provided that the following conditions
7 are met:
8
9 - Redistributions of source code must retain the above copyright
10 notice, this list of conditions and the following disclaimer.
11
12 - Redistributions in binary form must reproduce the above copyright
13 notice, this list of conditions and the following disclaimer in the
14 documentation and/or other materials provided with the distribution.
15
16 - Neither the name of the Xiph.org Foundation nor the names of its
17 contributors may be used to endorse or promote products derived from
18 this software without specific prior written permission.
19
20 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22 LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
23 A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR
24 CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
25 EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
26 PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
27 PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
28 LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
29 NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
30 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31*/
32
Jean-Marc Valin02fa9132008-02-20 12:09:29 +110033#ifdef HAVE_CONFIG_H
34#include "config.h"
35#endif
36
Jean-Marc Valin3ca9b1d2008-02-27 23:50:31 +110037#include "mathops.h"
Jean-Marc Valin29ccab82007-12-06 15:39:38 +110038#include "cwrs.h"
Jean-Marc Valin9cace642007-12-06 17:44:09 +110039#include "vq.h"
Jean-Marc Valin9a0bba12008-02-20 14:08:50 +110040#include "arch.h"
Jean-Marc Valinb60340f2008-02-26 15:41:51 +110041#include "os_support.h"
Jean-Marc Valin164a2292009-07-22 07:48:35 -040042#include "rate.h"
Jean-Marc Valin41af4212007-11-30 18:35:37 +110043
Jean-Marc Valind5e54362009-09-30 20:50:41 -040044#ifndef M_PI
45#define M_PI 3.141592653
46#endif
47
Jean-Marc Valina7750b92009-08-29 22:52:03 +010048static void exp_rotation(celt_norm_t *X, int len, int dir, int stride, int K)
49{
50 int i, k, iter;
51 celt_word16_t c, s;
52 celt_word16_t gain, theta;
53 celt_norm_t *Xptr;
Jean-Marc Valin75732de2009-09-29 22:35:32 -040054 gain = celt_div((celt_word32_t)MULT16_16(Q15_ONE,len),(celt_word32_t)(3+len+6*K));
Jean-Marc Valina7750b92009-08-29 22:52:03 +010055 /* FIXME: Make that HALF16 instead of HALF32 */
56 theta = SUB16(Q15ONE, HALF32(MULT16_16_Q15(gain,gain)));
57 /*if (len==30)
58 {
59 for (i=0;i<len;i++)
60 X[i] = 0;
61 X[14] = 1;
62}*/
63 c = celt_cos_norm(EXTEND32(theta));
64 s = dir*celt_cos_norm(EXTEND32(SUB16(Q15ONE,theta))); /* sin(theta) */
Jean-Marc Valin75732de2009-09-29 22:35:32 -040065 if (len > 8*stride)
66 stride *= len/(8*stride);
Jean-Marc Valina7750b92009-08-29 22:52:03 +010067 iter = 1;
68 for (k=0;k<iter;k++)
69 {
70 /* We could use MULT16_16_P15 instead of MULT16_16_Q15 for more accuracy,
71 but at this point, I really don't think it's necessary */
72 Xptr = X;
73 for (i=0;i<len-stride;i++)
74 {
75 celt_norm_t x1, x2;
76 x1 = Xptr[0];
77 x2 = Xptr[stride];
78 Xptr[stride] = MULT16_16_Q15(c,x2) + MULT16_16_Q15(s,x1);
79 *Xptr++ = MULT16_16_Q15(c,x1) - MULT16_16_Q15(s,x2);
80 }
81 Xptr = &X[len-2*stride-1];
82 for (i=len-2*stride-1;i>=0;i--)
83 {
84 celt_norm_t x1, x2;
85 x1 = Xptr[0];
86 x2 = Xptr[stride];
87 Xptr[stride] = MULT16_16_Q15(c,x2) + MULT16_16_Q15(s,x1);
88 *Xptr-- = MULT16_16_Q15(c,x1) - MULT16_16_Q15(s,x2);
89 }
90 }
91 /*if (len==30)
92 {
93 for (i=0;i<len;i++)
94 printf ("%f ", X[i]);
95 printf ("\n");
96 exit(0);
97}*/
98}
99
100
Jean-Marc Valin35a1f882008-03-26 10:34:23 +1100101/** Takes the pitch vector and the decoded residual vector, computes the gain
102 that will give ||p+g*y||=1 and mixes the residual with the pitch. */
Jean-Marc Valinf7a1e162009-10-07 06:56:03 -0400103static void normalise_residual(int * restrict iy, celt_norm_t * restrict X, int N, int K, celt_word32_t Ryy)
Jean-Marc Valind4018c32008-02-27 10:09:48 +1100104{
105 int i;
Jean-Marc Valina847b772008-02-27 17:46:49 +1100106 celt_word32_t g;
Jean-Marc Valinf6dc1eb2009-10-06 20:08:49 -0400107
108 g = celt_rsqrt(Ryy);
Jean-Marc Valind4018c32008-02-27 10:09:48 +1100109
Jean-Marc Valin6ea8bae2008-04-15 08:01:33 +1000110 i=0;
Jean-Marc Valinf6dc1eb2009-10-06 20:08:49 -0400111 do
Jean-Marc Valinf7a1e162009-10-07 06:56:03 -0400112 X[i] = SHR16(MULT16_16_16(g, iy[i]),1);
Jean-Marc Valin6ea8bae2008-04-15 08:01:33 +1000113 while (++i < N);
Jean-Marc Valind4018c32008-02-27 10:09:48 +1100114}
115
Jean-Marc Valin095c1782009-09-17 22:38:34 -0400116void alg_quant(celt_norm_t *X, int N, int K, int spread, ec_enc *enc)
Jean-Marc Valin41af4212007-11-30 18:35:37 +1100117{
Jean-Marc Valin44c63352008-03-25 21:28:40 +1100118 VARDECL(celt_norm_t, y);
119 VARDECL(int, iy);
Jean-Marc Valin1dab60c2008-09-16 13:29:37 -0400120 VARDECL(celt_word16_t, signx);
Jean-Marc Valin6ea8bae2008-04-15 08:01:33 +1000121 int j, is;
Jean-Marc Valin44c63352008-03-25 21:28:40 +1100122 celt_word16_t s;
Jean-Marc Valin846d4e22008-02-12 13:48:48 +1100123 int pulsesLeft;
Jean-Marc Valin44c63352008-03-25 21:28:40 +1100124 celt_word32_t sum;
Jean-Marc Valin095c1782009-09-17 22:38:34 -0400125 celt_word32_t xy, yy;
Jean-Marc Valinf9584772008-03-27 12:22:44 +1100126 int N_1; /* Inverse of N, in Q14 format (even for float) */
Jean-Marc Valinf675adc2008-02-28 12:15:17 +1100127#ifdef FIXED_POINT
Jean-Marc Valind748cd52008-03-01 07:27:03 +1100128 int yshift;
129#endif
130 SAVE_STACK;
131
Jean-Marc Valin164a2292009-07-22 07:48:35 -0400132 K = get_pulses(K);
Jean-Marc Valind748cd52008-03-01 07:27:03 +1100133#ifdef FIXED_POINT
Jean-Marc Valin98c86c72008-03-27 08:40:45 +1100134 yshift = 13-celt_ilog2(K);
Jean-Marc Valinf675adc2008-02-28 12:15:17 +1100135#endif
Jean-Marc Valin9d8d9b32008-02-27 16:17:39 +1100136
Jean-Marc Valin44c63352008-03-25 21:28:40 +1100137 ALLOC(y, N, celt_norm_t);
138 ALLOC(iy, N, int);
Jean-Marc Valin1dab60c2008-09-16 13:29:37 -0400139 ALLOC(signx, N, celt_word16_t);
Jean-Marc Valin124d1cd2008-03-28 00:33:04 +1100140 N_1 = 512/N;
Jean-Marc Valina7750b92009-08-29 22:52:03 +0100141
142 if (spread)
143 exp_rotation(X, N, 1, spread, K);
Jean-Marc Valin3d152a52008-04-15 07:46:48 +1000144
145 sum = 0;
Jean-Marc Valindff9b7e2008-04-21 11:43:51 +1000146 j=0; do {
Jean-Marc Valin49134382008-03-25 16:07:05 +1100147 if (X[j]>0)
148 signx[j]=1;
Jean-Marc Valin6cde5dd2008-12-04 21:21:41 -0500149 else {
Jean-Marc Valin49134382008-03-25 16:07:05 +1100150 signx[j]=-1;
Jean-Marc Valin6cde5dd2008-12-04 21:21:41 -0500151 X[j]=-X[j];
Jean-Marc Valin6cde5dd2008-12-04 21:21:41 -0500152 }
Jean-Marc Valin3d152a52008-04-15 07:46:48 +1000153 iy[j] = 0;
154 y[j] = 0;
Jean-Marc Valindff9b7e2008-04-21 11:43:51 +1000155 } while (++j<N);
Jean-Marc Valinbd718ba2008-03-25 14:15:41 +1100156
Jean-Marc Valin095c1782009-09-17 22:38:34 -0400157 xy = yy = 0;
Jean-Marc Valin0d587d82008-02-14 21:29:50 +1100158
Jean-Marc Valin846d4e22008-02-12 13:48:48 +1100159 pulsesLeft = K;
Jean-Marc Valin8256ed42008-12-12 20:50:56 -0500160
161 /* Do a pre-search by projecting on the pyramid */
Jean-Marc Valina733f082008-12-04 22:52:26 -0500162 if (K > (N>>1))
163 {
Jean-Marc Valin8256ed42008-12-12 20:50:56 -0500164 celt_word16_t rcp;
Gregory Maxwell61832f12008-12-22 18:15:42 -0500165 sum=0;
Jean-Marc Valina733f082008-12-04 22:52:26 -0500166 j=0; do {
167 sum += X[j];
168 } while (++j<N);
Jean-Marc Valin6d454d82009-06-30 10:31:00 -0400169
170#ifdef FIXED_POINT
171 if (sum <= K)
172#else
173 if (sum <= EPSILON)
174#endif
Jean-Marc Valin8256ed42008-12-12 20:50:56 -0500175 {
Jean-Marc Valinda1156a2009-07-01 01:27:48 -0400176 X[0] = QCONST16(1.f,14);
Jean-Marc Valin6d454d82009-06-30 10:31:00 -0400177 j=1; do
178 X[j]=0;
179 while (++j<N);
Jean-Marc Valinda1156a2009-07-01 01:27:48 -0400180 sum = QCONST16(1.f,14);
Jean-Marc Valin8256ed42008-12-12 20:50:56 -0500181 }
182 /* Do we have sufficient accuracy here? */
183 rcp = EXTRACT16(MULT16_32_Q16(K-1, celt_rcp(sum)));
Jean-Marc Valina733f082008-12-04 22:52:26 -0500184 j=0; do {
Jean-Marc Valin09dc5a12008-12-05 00:28:28 -0500185#ifdef FIXED_POINT
Jean-Marc Valin137241d2008-12-06 23:44:55 -0500186 /* It's really important to round *towards zero* here */
Jean-Marc Valin8256ed42008-12-12 20:50:56 -0500187 iy[j] = MULT16_16_Q15(X[j],rcp);
Jean-Marc Valin09dc5a12008-12-05 00:28:28 -0500188#else
Jean-Marc Valin8256ed42008-12-12 20:50:56 -0500189 iy[j] = floor(rcp*X[j]);
Jean-Marc Valin09dc5a12008-12-05 00:28:28 -0500190#endif
Jean-Marc Valinc7635b42008-12-04 23:26:32 -0500191 y[j] = SHL16(iy[j],yshift);
192 yy = MAC16_16(yy, y[j],y[j]);
193 xy = MAC16_16(xy, X[j],y[j]);
Jean-Marc Valin09dc5a12008-12-05 00:28:28 -0500194 y[j] *= 2;
Jean-Marc Valina733f082008-12-04 22:52:26 -0500195 pulsesLeft -= iy[j];
196 } while (++j<N);
197 }
Jean-Marc Valin137241d2008-12-06 23:44:55 -0500198 celt_assert2(pulsesLeft>=1, "Allocated too many pulses in the quick pass");
Jean-Marc Valin8256ed42008-12-12 20:50:56 -0500199
Jean-Marc Valin095c1782009-09-17 22:38:34 -0400200 while (pulsesLeft > 0)
Jean-Marc Valin41af4212007-11-30 18:35:37 +1100201 {
Jean-Marc Valin846d4e22008-02-12 13:48:48 +1100202 int pulsesAtOnce=1;
Jean-Marc Valin35a1f882008-03-26 10:34:23 +1100203 int best_id;
Jean-Marc Valined317c92008-04-15 17:31:23 +1000204 celt_word16_t magnitude;
Jean-Marc Valin7bb339d2008-09-21 21:11:39 -0400205 celt_word32_t best_num = -VERY_LARGE16;
206 celt_word16_t best_den = 0;
Jean-Marc Valin0bc5f7f2008-04-20 17:16:18 +1000207#ifdef FIXED_POINT
208 int rshift;
209#endif
Jean-Marc Valinbd718ba2008-03-25 14:15:41 +1100210 /* Decide on how many pulses to find at once */
Jean-Marc Valin124d1cd2008-03-28 00:33:04 +1100211 pulsesAtOnce = (pulsesLeft*N_1)>>9; /* pulsesLeft/N */
Jean-Marc Valincab576e2008-02-12 17:21:14 +1100212 if (pulsesAtOnce<1)
213 pulsesAtOnce = 1;
Jean-Marc Valin0bc5f7f2008-04-20 17:16:18 +1000214#ifdef FIXED_POINT
215 rshift = yshift+1+celt_ilog2(K-pulsesLeft+pulsesAtOnce);
216#endif
Jean-Marc Valined317c92008-04-15 17:31:23 +1000217 magnitude = SHL16(pulsesAtOnce, yshift);
Jean-Marc Valin846d4e22008-02-12 13:48:48 +1100218
Jean-Marc Valin35a1f882008-03-26 10:34:23 +1100219 best_id = 0;
Jean-Marc Valined317c92008-04-15 17:31:23 +1000220 /* The squared magnitude term gets added anyway, so we might as well
221 add it outside the loop */
Jean-Marc Valin1dab60c2008-09-16 13:29:37 -0400222 yy = MAC16_16(yy, magnitude,magnitude);
Jean-Marc Valin44c63352008-03-25 21:28:40 +1100223 /* Choose between fast and accurate strategy depending on where we are in the search */
Jean-Marc Valined317c92008-04-15 17:31:23 +1000224 /* This should ensure that anything we can process will have a better score */
Jean-Marc Valin7bb339d2008-09-21 21:11:39 -0400225 j=0;
226 do {
227 celt_word16_t Rxy, Ryy;
228 /* Select sign based on X[j] alone */
Jean-Marc Valin6cde5dd2008-12-04 21:21:41 -0500229 s = magnitude;
Jean-Marc Valin7bb339d2008-09-21 21:11:39 -0400230 /* Temporary sums of the new pulse(s) */
231 Rxy = EXTRACT16(SHR32(MAC16_16(xy, s,X[j]),rshift));
232 /* We're multiplying y[j] by two so we don't have to do it here */
233 Ryy = EXTRACT16(SHR32(MAC16_16(yy, s,y[j]),rshift));
Jean-Marc Valin35a1f882008-03-26 10:34:23 +1100234
Jean-Marc Valined317c92008-04-15 17:31:23 +1000235 /* Approximate score: we maximise Rxy/sqrt(Ryy) (we're guaranteed that
Jean-Marc Valin7bb339d2008-09-21 21:11:39 -0400236 Rxy is positive because the sign is pre-computed) */
237 Rxy = MULT16_16_Q15(Rxy,Rxy);
Jean-Marc Valin35a1f882008-03-26 10:34:23 +1100238 /* The idea is to check for num/den >= best_num/best_den, but that way
Jean-Marc Valin7bb339d2008-09-21 21:11:39 -0400239 we can do it without any division */
240 /* OPT: Make sure to use conditional moves here */
241 if (MULT16_16(best_den, Rxy) > MULT16_16(Ryy, best_num))
242 {
243 best_den = Ryy;
244 best_num = Rxy;
245 best_id = j;
246 }
247 } while (++j<N);
Jean-Marc Valin44c63352008-03-25 21:28:40 +1100248
Jean-Marc Valin35a1f882008-03-26 10:34:23 +1100249 j = best_id;
Jean-Marc Valin6cde5dd2008-12-04 21:21:41 -0500250 is = pulsesAtOnce;
Jean-Marc Valin44c63352008-03-25 21:28:40 +1100251 s = SHL16(is, yshift);
Jean-Marc Valinbd718ba2008-03-25 14:15:41 +1100252
Jean-Marc Valin44c63352008-03-25 21:28:40 +1100253 /* Updating the sums of the new pulse(s) */
254 xy = xy + MULT16_16(s,X[j]);
Jean-Marc Valined317c92008-04-15 17:31:23 +1000255 /* We're multiplying y[j] by two so we don't have to do it here */
256 yy = yy + MULT16_16(s,y[j]);
Jean-Marc Valinbd718ba2008-03-25 14:15:41 +1100257
Jean-Marc Valin44c63352008-03-25 21:28:40 +1100258 /* Only now that we've made the final choice, update y/iy */
Jean-Marc Valined317c92008-04-15 17:31:23 +1000259 /* Multiplying y[j] by 2 so we don't have to do it everywhere else */
260 y[j] += 2*s;
Jean-Marc Valin44c63352008-03-25 21:28:40 +1100261 iy[j] += is;
Jean-Marc Valin846d4e22008-02-12 13:48:48 +1100262 pulsesLeft -= pulsesAtOnce;
Jean-Marc Valin41af4212007-11-30 18:35:37 +1100263 }
Jean-Marc Valin6cde5dd2008-12-04 21:21:41 -0500264 j=0;
265 do {
Jean-Marc Valin6cde5dd2008-12-04 21:21:41 -0500266 X[j] = MULT16_16(signx[j],X[j]);
267 if (signx[j] < 0)
268 iy[j] = -iy[j];
269 } while (++j<N);
Jean-Marc Valinbd718ba2008-03-25 14:15:41 +1100270 encode_pulses(iy, N, K, enc);
Jean-Marc Valin5fa59952008-02-14 13:50:44 +1100271
Jean-Marc Valina4833ff2008-01-10 15:34:00 +1100272 /* Recompute the gain in one pass to reduce the encoder-decoder mismatch
Jean-Marc Valinbd718ba2008-03-25 14:15:41 +1100273 due to the recursive computation used in quantisation. */
Jean-Marc Valinf7a1e162009-10-07 06:56:03 -0400274 normalise_residual(iy, X, N, K, EXTRACT16(SHR32(yy,2*yshift)));
Jean-Marc Valina7750b92009-08-29 22:52:03 +0100275 if (spread)
276 exp_rotation(X, N, -1, spread, K);
Jean-Marc Valin8600f692008-02-29 15:14:12 +1100277 RESTORE_STACK;
Jean-Marc Valin41af4212007-11-30 18:35:37 +1100278}
279
Jean-Marc Valinbd718ba2008-03-25 14:15:41 +1100280
Jean-Marc Valin879fbfd2008-02-20 17:17:13 +1100281/** Decode pulse vector and combine the result with the pitch vector to produce
282 the final normalised signal in the current band. */
Jean-Marc Valin095c1782009-09-17 22:38:34 -0400283void alg_unquant(celt_norm_t *X, int N, int K, int spread, ec_dec *dec)
Jean-Marc Valin0d227d82007-12-31 16:12:12 +1100284{
Jean-Marc Valinf6dc1eb2009-10-06 20:08:49 -0400285 int i;
286 celt_word32_t Ryy;
Jean-Marc Valin31b79d12008-03-12 17:17:23 +1100287 VARDECL(int, iy);
Jean-Marc Valin8600f692008-02-29 15:14:12 +1100288 SAVE_STACK;
Jean-Marc Valin164a2292009-07-22 07:48:35 -0400289 K = get_pulses(K);
Jean-Marc Valin9a0bba12008-02-20 14:08:50 +1100290 ALLOC(iy, N, int);
Jean-Marc Valin5fa59952008-02-14 13:50:44 +1100291 decode_pulses(iy, N, K, dec);
Jean-Marc Valinf6dc1eb2009-10-06 20:08:49 -0400292 Ryy = 0;
293 i=0;
294 do {
295 Ryy = MAC16_16(Ryy, iy[i], iy[i]);
296 } while (++i < N);
Jean-Marc Valinf7a1e162009-10-07 06:56:03 -0400297 normalise_residual(iy, X, N, K, Ryy);
Jean-Marc Valina7750b92009-08-29 22:52:03 +0100298 if (spread)
299 exp_rotation(X, N, -1, spread, K);
Jean-Marc Valin8600f692008-02-29 15:14:12 +1100300 RESTORE_STACK;
Jean-Marc Valin0d227d82007-12-31 16:12:12 +1100301}
302
Jean-Marc Valinca53b7c2009-03-26 20:23:14 -0400303celt_word16_t renormalise_vector(celt_norm_t *X, celt_word16_t value, int N, int stride)
Jean-Marc Valin6361ad82008-07-20 23:14:31 -0400304{
305 int i;
306 celt_word32_t E = EPSILON;
Jean-Marc Valinca53b7c2009-03-26 20:23:14 -0400307 celt_word16_t rE;
Jean-Marc Valin6361ad82008-07-20 23:14:31 -0400308 celt_word16_t g;
309 celt_norm_t *xptr = X;
310 for (i=0;i<N;i++)
311 {
312 E = MAC16_16(E, *xptr, *xptr);
313 xptr += stride;
314 }
315
Jean-Marc Valinca53b7c2009-03-26 20:23:14 -0400316 rE = celt_sqrt(E);
Jean-Marc Valincd29b022009-07-01 09:59:21 -0400317#ifdef FIXED_POINT
318 if (rE <= 128)
319 g = Q15ONE;
320 else
321#endif
322 g = MULT16_16_Q15(value,celt_rcp(SHL32(rE,9)));
Jean-Marc Valin6361ad82008-07-20 23:14:31 -0400323 xptr = X;
324 for (i=0;i<N;i++)
325 {
326 *xptr = PSHR32(MULT16_16(g, *xptr),8);
327 xptr += stride;
328 }
Jean-Marc Valinca53b7c2009-03-26 20:23:14 -0400329 return rE;
Jean-Marc Valin6361ad82008-07-20 23:14:31 -0400330}
331
Jean-Marc Valind5e54362009-09-30 20:50:41 -0400332static void fold(const CELTMode *m, int N, const celt_norm_t * restrict Y, celt_norm_t * restrict P, int N0, int B)
Jean-Marc Valin4841a0a2007-12-03 13:54:30 +1100333{
Jean-Marc Valindf38f2b2008-07-20 20:36:54 -0400334 int j;
Jean-Marc Valind5e54362009-09-30 20:50:41 -0400335 int id = N0 % B;
Jean-Marc Valindf38f2b2008-07-20 20:36:54 -0400336 /* Here, we assume that id will never be greater than N0, i.e. that
Jean-Marc Valin5eef2642008-08-06 23:06:31 -0400337 no band is wider than N0. In the unlikely case it happens, we set
338 everything to zero */
Jean-Marc Valin4e5b7bc2009-07-03 15:09:07 -0400339 /*{
340 int offset = (N0*C - (id+C*N))/2;
341 if (offset > C*N0/16)
342 offset = C*N0/16;
343 offset -= offset % (C*B);
344 if (offset < 0)
345 offset = 0;
346 //printf ("%d\n", offset);
347 id += offset;
348 }*/
Jean-Marc Valind5e54362009-09-30 20:50:41 -0400349 if (id+N>N0)
350 for (j=0;j<N;j++)
Jean-Marc Valin5eef2642008-08-06 23:06:31 -0400351 P[j] = 0;
352 else
Jean-Marc Valind5e54362009-09-30 20:50:41 -0400353 for (j=0;j<N;j++)
Jean-Marc Valin5eef2642008-08-06 23:06:31 -0400354 P[j] = Y[id++];
Jean-Marc Valin2c733062008-07-17 16:22:23 -0400355}
356
Jean-Marc Valind5e54362009-09-30 20:50:41 -0400357void intra_fold(const CELTMode *m, int N, const celt_norm_t * restrict Y, celt_norm_t * restrict P, int N0, int B)
Jean-Marc Valin2c733062008-07-17 16:22:23 -0400358{
Jean-Marc Valin6361ad82008-07-20 23:14:31 -0400359 fold(m, N, Y, P, N0, B);
Jean-Marc Valind5e54362009-09-30 20:50:41 -0400360 renormalise_vector(P, Q15ONE, N, 1);
Jean-Marc Valin0e20ca02008-02-11 15:33:53 +1100361}
362