blob: ffb4e518f181187e95c8924496ab441b69828b7c [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 Valin234969c2009-10-17 22:12:42 -040048static void exp_rotation(celt_norm *X, int len, int dir, int stride, int K)
Jean-Marc Valina7750b92009-08-29 22:52:03 +010049{
50 int i, k, iter;
Jean-Marc Valin234969c2009-10-17 22:12:42 -040051 celt_word16 c, s;
52 celt_word16 gain, theta;
53 celt_norm *Xptr;
54 gain = celt_div((celt_word32)MULT16_16(Q15_ONE,len),(celt_word32)(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 {
Jean-Marc Valin234969c2009-10-17 22:12:42 -040075 celt_norm x1, x2;
Jean-Marc Valina7750b92009-08-29 22:52:03 +010076 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 {
Jean-Marc Valin234969c2009-10-17 22:12:42 -040084 celt_norm x1, x2;
Jean-Marc Valina7750b92009-08-29 22:52:03 +010085 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 Valin234969c2009-10-17 22:12:42 -0400103static void normalise_residual(int * restrict iy, celt_norm * restrict X, int N, int K, celt_word32 Ryy)
Jean-Marc Valind4018c32008-02-27 10:09:48 +1100104{
105 int i;
Timothy Terriberry8c7bb4c2009-10-31 10:19:06 -0700106#ifdef FIXED_POINT
107 int k;
108#endif
109 celt_word32 t;
110 celt_word16 g;
Jean-Marc Valinf6dc1eb2009-10-06 20:08:49 -0400111
Timothy Terriberry8c7bb4c2009-10-31 10:19:06 -0700112#ifdef FIXED_POINT
113 k = celt_ilog2(Ryy)>>1;
114#endif
115 t = VSHR32(Ryy, (k-7)<<1);
116 g = celt_rsqrt_norm(t);
Jean-Marc Valind4018c32008-02-27 10:09:48 +1100117
Jean-Marc Valin6ea8bae2008-04-15 08:01:33 +1000118 i=0;
Jean-Marc Valinf6dc1eb2009-10-06 20:08:49 -0400119 do
Timothy Terriberry8c7bb4c2009-10-31 10:19:06 -0700120 X[i] = EXTRACT16(PSHR32(MULT16_16(g, iy[i]), k+1));
Jean-Marc Valin6ea8bae2008-04-15 08:01:33 +1000121 while (++i < N);
Jean-Marc Valind4018c32008-02-27 10:09:48 +1100122}
123
Jean-Marc Valin234969c2009-10-17 22:12:42 -0400124void alg_quant(celt_norm *X, int N, int K, int spread, ec_enc *enc)
Jean-Marc Valin41af4212007-11-30 18:35:37 +1100125{
Jean-Marc Valin234969c2009-10-17 22:12:42 -0400126 VARDECL(celt_norm, y);
Jean-Marc Valin44c63352008-03-25 21:28:40 +1100127 VARDECL(int, iy);
Jean-Marc Valin234969c2009-10-17 22:12:42 -0400128 VARDECL(celt_word16, signx);
Jean-Marc Valin6ea8bae2008-04-15 08:01:33 +1000129 int j, is;
Jean-Marc Valin234969c2009-10-17 22:12:42 -0400130 celt_word16 s;
Jean-Marc Valin846d4e22008-02-12 13:48:48 +1100131 int pulsesLeft;
Jean-Marc Valin234969c2009-10-17 22:12:42 -0400132 celt_word32 sum;
133 celt_word32 xy, yy;
Jean-Marc Valinf9584772008-03-27 12:22:44 +1100134 int N_1; /* Inverse of N, in Q14 format (even for float) */
Jean-Marc Valinf675adc2008-02-28 12:15:17 +1100135#ifdef FIXED_POINT
Jean-Marc Valind748cd52008-03-01 07:27:03 +1100136 int yshift;
137#endif
138 SAVE_STACK;
139
Jean-Marc Valin164a2292009-07-22 07:48:35 -0400140 K = get_pulses(K);
Jean-Marc Valind748cd52008-03-01 07:27:03 +1100141#ifdef FIXED_POINT
Jean-Marc Valin98c86c72008-03-27 08:40:45 +1100142 yshift = 13-celt_ilog2(K);
Jean-Marc Valinf675adc2008-02-28 12:15:17 +1100143#endif
Jean-Marc Valin9d8d9b32008-02-27 16:17:39 +1100144
Jean-Marc Valin234969c2009-10-17 22:12:42 -0400145 ALLOC(y, N, celt_norm);
Jean-Marc Valin44c63352008-03-25 21:28:40 +1100146 ALLOC(iy, N, int);
Jean-Marc Valin234969c2009-10-17 22:12:42 -0400147 ALLOC(signx, N, celt_word16);
Jean-Marc Valin124d1cd2008-03-28 00:33:04 +1100148 N_1 = 512/N;
Jean-Marc Valina7750b92009-08-29 22:52:03 +0100149
150 if (spread)
151 exp_rotation(X, N, 1, spread, K);
Jean-Marc Valin3d152a52008-04-15 07:46:48 +1000152
153 sum = 0;
Jean-Marc Valindff9b7e2008-04-21 11:43:51 +1000154 j=0; do {
Jean-Marc Valin49134382008-03-25 16:07:05 +1100155 if (X[j]>0)
156 signx[j]=1;
Jean-Marc Valin6cde5dd2008-12-04 21:21:41 -0500157 else {
Jean-Marc Valin49134382008-03-25 16:07:05 +1100158 signx[j]=-1;
Jean-Marc Valin6cde5dd2008-12-04 21:21:41 -0500159 X[j]=-X[j];
Jean-Marc Valin6cde5dd2008-12-04 21:21:41 -0500160 }
Jean-Marc Valin3d152a52008-04-15 07:46:48 +1000161 iy[j] = 0;
162 y[j] = 0;
Jean-Marc Valindff9b7e2008-04-21 11:43:51 +1000163 } while (++j<N);
Jean-Marc Valinbd718ba2008-03-25 14:15:41 +1100164
Jean-Marc Valin095c1782009-09-17 22:38:34 -0400165 xy = yy = 0;
Jean-Marc Valin0d587d82008-02-14 21:29:50 +1100166
Jean-Marc Valin846d4e22008-02-12 13:48:48 +1100167 pulsesLeft = K;
Jean-Marc Valin8256ed42008-12-12 20:50:56 -0500168
169 /* Do a pre-search by projecting on the pyramid */
Jean-Marc Valina733f082008-12-04 22:52:26 -0500170 if (K > (N>>1))
171 {
Jean-Marc Valin234969c2009-10-17 22:12:42 -0400172 celt_word16 rcp;
Jean-Marc Valina733f082008-12-04 22:52:26 -0500173 j=0; do {
174 sum += X[j];
175 } while (++j<N);
Jean-Marc Valin6d454d82009-06-30 10:31:00 -0400176
177#ifdef FIXED_POINT
178 if (sum <= K)
179#else
180 if (sum <= EPSILON)
181#endif
Jean-Marc Valin8256ed42008-12-12 20:50:56 -0500182 {
Jean-Marc Valinda1156a2009-07-01 01:27:48 -0400183 X[0] = QCONST16(1.f,14);
Jean-Marc Valin6d454d82009-06-30 10:31:00 -0400184 j=1; do
185 X[j]=0;
186 while (++j<N);
Jean-Marc Valinda1156a2009-07-01 01:27:48 -0400187 sum = QCONST16(1.f,14);
Jean-Marc Valin8256ed42008-12-12 20:50:56 -0500188 }
189 /* Do we have sufficient accuracy here? */
190 rcp = EXTRACT16(MULT16_32_Q16(K-1, celt_rcp(sum)));
Jean-Marc Valina733f082008-12-04 22:52:26 -0500191 j=0; do {
Jean-Marc Valin09dc5a12008-12-05 00:28:28 -0500192#ifdef FIXED_POINT
Jean-Marc Valin137241d2008-12-06 23:44:55 -0500193 /* It's really important to round *towards zero* here */
Jean-Marc Valin8256ed42008-12-12 20:50:56 -0500194 iy[j] = MULT16_16_Q15(X[j],rcp);
Jean-Marc Valin09dc5a12008-12-05 00:28:28 -0500195#else
Jean-Marc Valin8256ed42008-12-12 20:50:56 -0500196 iy[j] = floor(rcp*X[j]);
Jean-Marc Valin09dc5a12008-12-05 00:28:28 -0500197#endif
Jean-Marc Valinc7635b42008-12-04 23:26:32 -0500198 y[j] = SHL16(iy[j],yshift);
199 yy = MAC16_16(yy, y[j],y[j]);
200 xy = MAC16_16(xy, X[j],y[j]);
Jean-Marc Valin09dc5a12008-12-05 00:28:28 -0500201 y[j] *= 2;
Jean-Marc Valina733f082008-12-04 22:52:26 -0500202 pulsesLeft -= iy[j];
203 } while (++j<N);
204 }
Jean-Marc Valin137241d2008-12-06 23:44:55 -0500205 celt_assert2(pulsesLeft>=1, "Allocated too many pulses in the quick pass");
Jean-Marc Valin8256ed42008-12-12 20:50:56 -0500206
Jean-Marc Valin095c1782009-09-17 22:38:34 -0400207 while (pulsesLeft > 0)
Jean-Marc Valin41af4212007-11-30 18:35:37 +1100208 {
Jean-Marc Valin846d4e22008-02-12 13:48:48 +1100209 int pulsesAtOnce=1;
Jean-Marc Valin35a1f882008-03-26 10:34:23 +1100210 int best_id;
Jean-Marc Valin234969c2009-10-17 22:12:42 -0400211 celt_word16 magnitude;
212 celt_word32 best_num = -VERY_LARGE16;
213 celt_word16 best_den = 0;
Jean-Marc Valin0bc5f7f2008-04-20 17:16:18 +1000214#ifdef FIXED_POINT
215 int rshift;
216#endif
Jean-Marc Valinbd718ba2008-03-25 14:15:41 +1100217 /* Decide on how many pulses to find at once */
Jean-Marc Valin124d1cd2008-03-28 00:33:04 +1100218 pulsesAtOnce = (pulsesLeft*N_1)>>9; /* pulsesLeft/N */
Jean-Marc Valincab576e2008-02-12 17:21:14 +1100219 if (pulsesAtOnce<1)
220 pulsesAtOnce = 1;
Jean-Marc Valin0bc5f7f2008-04-20 17:16:18 +1000221#ifdef FIXED_POINT
222 rshift = yshift+1+celt_ilog2(K-pulsesLeft+pulsesAtOnce);
223#endif
Jean-Marc Valined317c92008-04-15 17:31:23 +1000224 magnitude = SHL16(pulsesAtOnce, yshift);
Jean-Marc Valin846d4e22008-02-12 13:48:48 +1100225
Jean-Marc Valin35a1f882008-03-26 10:34:23 +1100226 best_id = 0;
Jean-Marc Valined317c92008-04-15 17:31:23 +1000227 /* The squared magnitude term gets added anyway, so we might as well
228 add it outside the loop */
Jean-Marc Valin1dab60c2008-09-16 13:29:37 -0400229 yy = MAC16_16(yy, magnitude,magnitude);
Jean-Marc Valin44c63352008-03-25 21:28:40 +1100230 /* Choose between fast and accurate strategy depending on where we are in the search */
Jean-Marc Valined317c92008-04-15 17:31:23 +1000231 /* This should ensure that anything we can process will have a better score */
Jean-Marc Valin7bb339d2008-09-21 21:11:39 -0400232 j=0;
233 do {
Jean-Marc Valin234969c2009-10-17 22:12:42 -0400234 celt_word16 Rxy, Ryy;
Jean-Marc Valin7bb339d2008-09-21 21:11:39 -0400235 /* Select sign based on X[j] alone */
Jean-Marc Valin6cde5dd2008-12-04 21:21:41 -0500236 s = magnitude;
Jean-Marc Valin7bb339d2008-09-21 21:11:39 -0400237 /* Temporary sums of the new pulse(s) */
238 Rxy = EXTRACT16(SHR32(MAC16_16(xy, s,X[j]),rshift));
239 /* We're multiplying y[j] by two so we don't have to do it here */
240 Ryy = EXTRACT16(SHR32(MAC16_16(yy, s,y[j]),rshift));
Jean-Marc Valin35a1f882008-03-26 10:34:23 +1100241
Jean-Marc Valined317c92008-04-15 17:31:23 +1000242 /* Approximate score: we maximise Rxy/sqrt(Ryy) (we're guaranteed that
Jean-Marc Valin7bb339d2008-09-21 21:11:39 -0400243 Rxy is positive because the sign is pre-computed) */
244 Rxy = MULT16_16_Q15(Rxy,Rxy);
Jean-Marc Valin35a1f882008-03-26 10:34:23 +1100245 /* The idea is to check for num/den >= best_num/best_den, but that way
Jean-Marc Valin7bb339d2008-09-21 21:11:39 -0400246 we can do it without any division */
247 /* OPT: Make sure to use conditional moves here */
248 if (MULT16_16(best_den, Rxy) > MULT16_16(Ryy, best_num))
249 {
250 best_den = Ryy;
251 best_num = Rxy;
252 best_id = j;
253 }
254 } while (++j<N);
Jean-Marc Valin44c63352008-03-25 21:28:40 +1100255
Jean-Marc Valin35a1f882008-03-26 10:34:23 +1100256 j = best_id;
Jean-Marc Valin6cde5dd2008-12-04 21:21:41 -0500257 is = pulsesAtOnce;
Jean-Marc Valin44c63352008-03-25 21:28:40 +1100258 s = SHL16(is, yshift);
Jean-Marc Valinbd718ba2008-03-25 14:15:41 +1100259
Jean-Marc Valin44c63352008-03-25 21:28:40 +1100260 /* Updating the sums of the new pulse(s) */
261 xy = xy + MULT16_16(s,X[j]);
Jean-Marc Valined317c92008-04-15 17:31:23 +1000262 /* We're multiplying y[j] by two so we don't have to do it here */
263 yy = yy + MULT16_16(s,y[j]);
Jean-Marc Valinbd718ba2008-03-25 14:15:41 +1100264
Jean-Marc Valin44c63352008-03-25 21:28:40 +1100265 /* Only now that we've made the final choice, update y/iy */
Jean-Marc Valined317c92008-04-15 17:31:23 +1000266 /* Multiplying y[j] by 2 so we don't have to do it everywhere else */
267 y[j] += 2*s;
Jean-Marc Valin44c63352008-03-25 21:28:40 +1100268 iy[j] += is;
Jean-Marc Valin846d4e22008-02-12 13:48:48 +1100269 pulsesLeft -= pulsesAtOnce;
Jean-Marc Valin41af4212007-11-30 18:35:37 +1100270 }
Jean-Marc Valin6cde5dd2008-12-04 21:21:41 -0500271 j=0;
272 do {
Jean-Marc Valin6cde5dd2008-12-04 21:21:41 -0500273 X[j] = MULT16_16(signx[j],X[j]);
274 if (signx[j] < 0)
275 iy[j] = -iy[j];
276 } while (++j<N);
Jean-Marc Valinbd718ba2008-03-25 14:15:41 +1100277 encode_pulses(iy, N, K, enc);
Jean-Marc Valin5fa59952008-02-14 13:50:44 +1100278
Jean-Marc Valina4833ff2008-01-10 15:34:00 +1100279 /* Recompute the gain in one pass to reduce the encoder-decoder mismatch
Jean-Marc Valinbd718ba2008-03-25 14:15:41 +1100280 due to the recursive computation used in quantisation. */
Jean-Marc Valinf7a1e162009-10-07 06:56:03 -0400281 normalise_residual(iy, X, N, K, EXTRACT16(SHR32(yy,2*yshift)));
Jean-Marc Valina7750b92009-08-29 22:52:03 +0100282 if (spread)
283 exp_rotation(X, N, -1, spread, K);
Jean-Marc Valin8600f692008-02-29 15:14:12 +1100284 RESTORE_STACK;
Jean-Marc Valin41af4212007-11-30 18:35:37 +1100285}
286
Jean-Marc Valinbd718ba2008-03-25 14:15:41 +1100287
Jean-Marc Valin879fbfd2008-02-20 17:17:13 +1100288/** Decode pulse vector and combine the result with the pitch vector to produce
289 the final normalised signal in the current band. */
Jean-Marc Valin234969c2009-10-17 22:12:42 -0400290void alg_unquant(celt_norm *X, int N, int K, int spread, ec_dec *dec)
Jean-Marc Valin0d227d82007-12-31 16:12:12 +1100291{
Jean-Marc Valinf6dc1eb2009-10-06 20:08:49 -0400292 int i;
Jean-Marc Valin234969c2009-10-17 22:12:42 -0400293 celt_word32 Ryy;
Jean-Marc Valin31b79d12008-03-12 17:17:23 +1100294 VARDECL(int, iy);
Jean-Marc Valin8600f692008-02-29 15:14:12 +1100295 SAVE_STACK;
Jean-Marc Valin164a2292009-07-22 07:48:35 -0400296 K = get_pulses(K);
Jean-Marc Valin9a0bba12008-02-20 14:08:50 +1100297 ALLOC(iy, N, int);
Jean-Marc Valin5fa59952008-02-14 13:50:44 +1100298 decode_pulses(iy, N, K, dec);
Jean-Marc Valinf6dc1eb2009-10-06 20:08:49 -0400299 Ryy = 0;
300 i=0;
301 do {
302 Ryy = MAC16_16(Ryy, iy[i], iy[i]);
303 } while (++i < N);
Jean-Marc Valinf7a1e162009-10-07 06:56:03 -0400304 normalise_residual(iy, X, N, K, Ryy);
Jean-Marc Valina7750b92009-08-29 22:52:03 +0100305 if (spread)
306 exp_rotation(X, N, -1, spread, K);
Jean-Marc Valin8600f692008-02-29 15:14:12 +1100307 RESTORE_STACK;
Jean-Marc Valin0d227d82007-12-31 16:12:12 +1100308}
309
Jean-Marc Valin234969c2009-10-17 22:12:42 -0400310celt_word16 renormalise_vector(celt_norm *X, celt_word16 value, int N, int stride)
Jean-Marc Valin6361ad82008-07-20 23:14:31 -0400311{
312 int i;
Jean-Marc Valin234969c2009-10-17 22:12:42 -0400313 celt_word32 E = EPSILON;
314 celt_word16 rE;
315 celt_word16 g;
316 celt_norm *xptr = X;
Jean-Marc Valin6361ad82008-07-20 23:14:31 -0400317 for (i=0;i<N;i++)
318 {
319 E = MAC16_16(E, *xptr, *xptr);
320 xptr += stride;
321 }
322
Jean-Marc Valinca53b7c2009-03-26 20:23:14 -0400323 rE = celt_sqrt(E);
Jean-Marc Valincd29b022009-07-01 09:59:21 -0400324#ifdef FIXED_POINT
325 if (rE <= 128)
326 g = Q15ONE;
327 else
328#endif
329 g = MULT16_16_Q15(value,celt_rcp(SHL32(rE,9)));
Jean-Marc Valin6361ad82008-07-20 23:14:31 -0400330 xptr = X;
331 for (i=0;i<N;i++)
332 {
333 *xptr = PSHR32(MULT16_16(g, *xptr),8);
334 xptr += stride;
335 }
Jean-Marc Valinca53b7c2009-03-26 20:23:14 -0400336 return rE;
Jean-Marc Valin6361ad82008-07-20 23:14:31 -0400337}
338
Jean-Marc Valin3a0bc3d2010-02-21 15:10:22 -0500339static void fold(const CELTMode *m, int start, int N, const celt_norm * restrict Y, celt_norm * restrict P, int N0, int B)
Jean-Marc Valin4841a0a2007-12-03 13:54:30 +1100340{
Jean-Marc Valindf38f2b2008-07-20 20:36:54 -0400341 int j;
Jean-Marc Valind5e54362009-09-30 20:50:41 -0400342 int id = N0 % B;
Jean-Marc Valin3a0bc3d2010-02-21 15:10:22 -0500343 while (id < m->eBands[start])
344 id += B;
Jean-Marc Valindf38f2b2008-07-20 20:36:54 -0400345 /* Here, we assume that id will never be greater than N0, i.e. that
Jean-Marc Valin5eef2642008-08-06 23:06:31 -0400346 no band is wider than N0. In the unlikely case it happens, we set
347 everything to zero */
Jean-Marc Valin4e5b7bc2009-07-03 15:09:07 -0400348 /*{
349 int offset = (N0*C - (id+C*N))/2;
350 if (offset > C*N0/16)
351 offset = C*N0/16;
352 offset -= offset % (C*B);
353 if (offset < 0)
354 offset = 0;
355 //printf ("%d\n", offset);
356 id += offset;
357 }*/
Jean-Marc Valind5e54362009-09-30 20:50:41 -0400358 if (id+N>N0)
359 for (j=0;j<N;j++)
Jean-Marc Valin5eef2642008-08-06 23:06:31 -0400360 P[j] = 0;
361 else
Jean-Marc Valind5e54362009-09-30 20:50:41 -0400362 for (j=0;j<N;j++)
Jean-Marc Valin5eef2642008-08-06 23:06:31 -0400363 P[j] = Y[id++];
Jean-Marc Valin2c733062008-07-17 16:22:23 -0400364}
365
Jean-Marc Valin3a0bc3d2010-02-21 15:10:22 -0500366void intra_fold(const CELTMode *m, int start, int N, const celt_norm * restrict Y, celt_norm * restrict P, int N0, int B)
Jean-Marc Valin2c733062008-07-17 16:22:23 -0400367{
Jean-Marc Valin3a0bc3d2010-02-21 15:10:22 -0500368 fold(m, start, N, Y, P, N0, B);
Jean-Marc Valind5e54362009-09-30 20:50:41 -0400369 renormalise_vector(P, Q15ONE, N, 1);
Jean-Marc Valin0e20ca02008-02-11 15:33:53 +1100370}
371