blob: 9f73620f1c2475982a0fe2817013cb1f2ec4295e [file] [log] [blame]
Jean-Marc Valin069c3de2008-03-04 20:38:00 +11001/* (C) 2007-2008 Jean-Marc Valin, CSIRO
Jean-Marc Valin8ebd3452007-11-29 20:17:32 +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 Valin8600f692008-02-29 15:14:12 +110036#define CELT_C
37
Jean-Marc Valin8ebd3452007-11-29 20:17:32 +110038#include "os_support.h"
Jean-Marc Valinf02ba112007-11-30 01:10:42 +110039#include "mdct.h"
40#include <math.h>
Jean-Marc Valin013c31d2007-11-30 11:36:46 +110041#include "celt.h"
Jean-Marc Valin14191b32007-11-30 12:15:49 +110042#include "pitch.h"
Jean-Marc Valin7351e282008-02-08 15:09:45 +110043#include "kiss_fftr.h"
Jean-Marc Valin991c0f02007-11-30 16:07:46 +110044#include "bands.h"
Jean-Marc Valinecb36a32007-12-05 01:31:49 +110045#include "modes.h"
Jean-Marc Valin6238bc02008-01-28 22:28:54 +110046#include "entcode.h"
Jean-Marc Valin98d2a492007-12-07 22:46:47 +110047#include "quant_pitch.h"
48#include "quant_bands.h"
Jean-Marc Valin46014ca2007-12-14 13:47:04 +110049#include "psy.h"
Jean-Marc Valin4fbd18d2008-01-17 14:07:55 +110050#include "rate.h"
Jean-Marc Valinc7e0b762008-03-16 07:55:29 +110051#include "stack_alloc.h"
Jean-Marc Valine4aeb472008-06-29 12:06:05 +100052#include "mathops.h"
Jean-Marc Valin013c31d2007-11-30 11:36:46 +110053
Jean-Marc Valin07586892008-03-03 17:19:17 +110054static const celt_word16_t preemph = QCONST16(0.8f,15);
55
Jean-Marc Valin528f4b82008-06-29 03:46:39 +100056#ifdef FIXED_POINT
57static const celt_word16_t transientWindow[16] = {
58 279, 1106, 2454, 4276, 6510, 9081, 11900, 14872,
59 17896, 20868, 23687, 26258, 28492, 30314, 31662, 32489};
60#else
61static const float transientWindow[16] = {
62 0.0085135, 0.0337639, 0.0748914, 0.1304955, 0.1986827, 0.2771308, 0.3631685, 0.4538658,
63 0.5461342, 0.6368315, 0.7228692, 0.8013173, 0.8695045, 0.9251086, 0.9662361, 0.9914865};
64#endif
65
Jean-Marc Valin276de722008-02-20 17:45:51 +110066/** Encoder state
67 @brief Encoder state
68 */
Jean-Marc Valin269d40a2007-12-07 11:29:45 +110069struct CELTEncoder {
Jean-Marc Valin276de722008-02-20 17:45:51 +110070 const CELTMode *mode; /**< Mode used by the encoder */
Jean-Marc Valin8ebd3452007-11-29 20:17:32 +110071 int frame_size;
72 int block_size;
Jean-Marc Valina5431bf2008-01-03 20:53:01 +110073 int overlap;
Jean-Marc Valinffa13472007-12-10 16:54:17 +110074 int channels;
75
Jean-Marc Valinbc5cedf2007-12-06 15:18:25 +110076 ec_byte_buffer buf;
77 ec_enc enc;
78
Jean-Marc Valin65fb92e2008-04-19 22:24:53 +100079 celt_word16_t * restrict preemph_memE; /* Input is 16-bit, so why bother with 32 */
80 celt_sig_t * restrict preemph_memD;
Jean-Marc Valin81b38c22008-02-29 21:08:49 +110081
Jean-Marc Valin18ddc022008-02-22 14:24:50 +110082 celt_sig_t *in_mem;
Jean-Marc Valin18ddc022008-02-22 14:24:50 +110083 celt_sig_t *out_mem;
Jean-Marc Valin991c0f02007-11-30 16:07:46 +110084
Jean-Marc Valin5d561832008-02-27 11:59:05 +110085 celt_word16_t *oldBandE;
Jean-Marc Valinc6ca4992008-06-01 23:19:16 +100086#ifdef EXP_PSY
87 celt_word16_t *psy_mem;
88 struct PsyDecay psy;
89#endif
Jean-Marc Valin8ebd3452007-11-29 20:17:32 +110090};
91
Peter Kirk19f9dc92008-06-06 14:38:38 +020092CELTEncoder *celt_encoder_create(const CELTMode *mode)
Jean-Marc Valin8ebd3452007-11-29 20:17:32 +110093{
Jean-Marc Valinb886ddc2008-03-25 14:38:55 +110094 int N, C;
Jean-Marc Valin02fa9132008-02-20 12:09:29 +110095 CELTEncoder *st;
Jean-Marc Valin44ffd5a2008-02-22 00:39:25 +110096
97 if (check_mode(mode) != CELT_OK)
98 return NULL;
99
Jean-Marc Valin73e51b32007-12-05 17:48:24 +1100100 N = mode->mdctSize;
Jean-Marc Valinffa13472007-12-10 16:54:17 +1100101 C = mode->nbChannels;
Jean-Marc Valin02fa9132008-02-20 12:09:29 +1100102 st = celt_alloc(sizeof(CELTEncoder));
Jean-Marc Valin8ebd3452007-11-29 20:17:32 +1100103
Jean-Marc Valin73e51b32007-12-05 17:48:24 +1100104 st->mode = mode;
Jean-Marc Valinb886ddc2008-03-25 14:38:55 +1100105 st->frame_size = N;
Jean-Marc Valin73e51b32007-12-05 17:48:24 +1100106 st->block_size = N;
Jean-Marc Valina5431bf2008-01-03 20:53:01 +1100107 st->overlap = mode->overlap;
Jean-Marc Valina5431bf2008-01-03 20:53:01 +1100108
Jean-Marc Valinbc5cedf2007-12-06 15:18:25 +1100109 ec_byte_writeinit(&st->buf);
Jean-Marc Valin671bf402007-12-07 15:36:39 +1100110 ec_enc_init(&st->enc,&st->buf);
Jean-Marc Valina76a0b22008-01-17 22:43:05 +1100111
Jean-Marc Valin7aa9d8c2008-04-21 00:04:23 +1000112 st->in_mem = celt_alloc(st->overlap*C*sizeof(celt_sig_t));
Jean-Marc Valin8ddd7f42008-04-22 13:37:16 +1000113 st->out_mem = celt_alloc((MAX_PERIOD+st->overlap)*C*sizeof(celt_sig_t));
Jean-Marc Valin81b38c22008-02-29 21:08:49 +1100114
Jean-Marc Valin5d561832008-02-27 11:59:05 +1100115 st->oldBandE = (celt_word16_t*)celt_alloc(C*mode->nbEBands*sizeof(celt_word16_t));
Jean-Marc Valinfa248732007-12-06 07:51:27 +1100116
Gregory Maxwell5f2a74b2008-08-11 23:50:07 -0400117 st->preemph_memE = (celt_word16_t*)celt_alloc(C*sizeof(celt_word16_t));
118 st->preemph_memD = (celt_sig_t*)celt_alloc(C*sizeof(celt_sig_t));
Jean-Marc Valinffa13472007-12-10 16:54:17 +1100119
Jean-Marc Valinc6ca4992008-06-01 23:19:16 +1000120#ifdef EXP_PSY
121 st->psy_mem = celt_alloc(MAX_PERIOD*sizeof(celt_word16_t));
122 psydecay_init(&st->psy, MAX_PERIOD/2, st->mode->Fs);
123#endif
124
Jean-Marc Valinf02ba112007-11-30 01:10:42 +1100125 return st;
Jean-Marc Valin8ebd3452007-11-29 20:17:32 +1100126}
127
Peter Kirk19f9dc92008-06-06 14:38:38 +0200128void celt_encoder_destroy(CELTEncoder *st)
Jean-Marc Valin14191b32007-11-30 12:15:49 +1100129{
130 if (st == NULL)
131 {
132 celt_warning("NULL passed to celt_encoder_destroy");
133 return;
134 }
Jean-Marc Valin44ffd5a2008-02-22 00:39:25 +1100135 if (check_mode(st->mode) != CELT_OK)
136 return;
137
Jean-Marc Valinc245a222007-12-06 19:14:20 +1100138 ec_byte_writeclear(&st->buf);
139
Jean-Marc Valin14191b32007-11-30 12:15:49 +1100140 celt_free(st->in_mem);
Jean-Marc Valin14191b32007-11-30 12:15:49 +1100141 celt_free(st->out_mem);
Jean-Marc Valin991c0f02007-11-30 16:07:46 +1100142
Jean-Marc Valinc245a222007-12-06 19:14:20 +1100143 celt_free(st->oldBandE);
Jean-Marc Valin7351e282008-02-08 15:09:45 +1100144
145 celt_free(st->preemph_memE);
146 celt_free(st->preemph_memD);
147
Jean-Marc Valinc6ca4992008-06-01 23:19:16 +1000148#ifdef EXP_PSY
149 celt_free (st->psy_mem);
150 psydecay_clear(&st->psy);
151#endif
152
Jean-Marc Valin14191b32007-11-30 12:15:49 +1100153 celt_free(st);
154}
155
Gregory Maxwell5f2a74b2008-08-11 23:50:07 -0400156static inline celt_int16_t FLOAT2INT16(float x)
Jean-Marc Valin42074382008-02-27 11:08:53 +1100157{
Gregory Maxwell5f2a74b2008-08-11 23:50:07 -0400158 x = x*32768.;
159 x = MAX32(x, -32768);
160 x = MIN32(x, 32767);
161 return (celt_int16_t)floor(.5+x);
162}
163
164static inline celt_word16_t SIG2WORD16(celt_sig_t x)
165{
166#ifdef FIXED_POINT
Jean-Marc Valin42074382008-02-27 11:08:53 +1100167 x = PSHR32(x, SIG_SHIFT);
Jean-Marc Valinabdfc382008-04-18 15:57:18 +1000168 x = MAX32(x, -32768);
169 x = MIN32(x, 32767);
Jean-Marc Valin42074382008-02-27 11:08:53 +1100170 return EXTRACT16(x);
171#else
Gregory Maxwell5f2a74b2008-08-11 23:50:07 -0400172 return (celt_word16_t)x;
Jean-Marc Valin42074382008-02-27 11:08:53 +1100173#endif
174}
175
Jean-Marc Valinbd7de0a2008-07-06 10:57:26 -0400176static int transient_analysis(celt_word32_t *in, int len, int C, int *transient_time, int *transient_shift)
Jean-Marc Valin9375aa42008-06-27 07:57:35 +1000177{
178 int c, i, n;
Jean-Marc Valin0ceccb22008-07-03 20:41:06 -0400179 celt_word32_t ratio;
180 /* FIXME: Remove the floats here */
Jean-Marc Valin0ceccb22008-07-03 20:41:06 -0400181 VARDECL(celt_word32_t, begin);
182 SAVE_STACK;
183 ALLOC(begin, len, celt_word32_t);
Jean-Marc Valin9375aa42008-06-27 07:57:35 +1000184 for (i=0;i<len;i++)
Jean-Marc Valin0ceccb22008-07-03 20:41:06 -0400185 begin[i] = EXTEND32(ABS16(SHR32(in[C*i],SIG_SHIFT)));
Jean-Marc Valin9375aa42008-06-27 07:57:35 +1000186 for (c=1;c<C;c++)
187 {
188 for (i=0;i<len;i++)
Jean-Marc Valinbd7de0a2008-07-06 10:57:26 -0400189 begin[i] = MAX32(begin[i], EXTEND32(ABS16(SHR32(in[C*i+c],SIG_SHIFT))));
Jean-Marc Valin9375aa42008-06-27 07:57:35 +1000190 }
Jean-Marc Valin9375aa42008-06-27 07:57:35 +1000191 for (i=1;i<len;i++)
Jean-Marc Valinbd7de0a2008-07-06 10:57:26 -0400192 begin[i] = MAX32(begin[i-1],begin[i]);
Jean-Marc Valin9375aa42008-06-27 07:57:35 +1000193 n = -1;
194 for (i=8;i<len-8;i++)
195 {
Jean-Marc Valinbd7de0a2008-07-06 10:57:26 -0400196 if (begin[i] < MULT16_32_Q15(QCONST16(.2f,15),begin[len-1]))
197 n=i;
Jean-Marc Valin9375aa42008-06-27 07:57:35 +1000198 }
Jean-Marc Valin9375aa42008-06-27 07:57:35 +1000199 if (n<32)
200 {
201 n = -1;
202 ratio = 0;
Jean-Marc Valinbd7de0a2008-07-06 10:57:26 -0400203 } else {
204 ratio = DIV32(begin[len-1],1+begin[n-16]);
Jean-Marc Valin9375aa42008-06-27 07:57:35 +1000205 }
Jean-Marc Valinbd7de0a2008-07-06 10:57:26 -0400206 /*printf ("%d %f\n", n, ratio*ratio);*/
Jean-Marc Valinf4578192008-07-04 16:47:28 -0400207 if (ratio < 0)
208 ratio = 0;
209 if (ratio > 1000)
210 ratio = 1000;
Jean-Marc Valinbd7de0a2008-07-06 10:57:26 -0400211 ratio *= ratio;
212 if (ratio < 50)
213 *transient_shift = 0;
214 else if (ratio < 256)
215 *transient_shift = 1;
216 else if (ratio < 4096)
217 *transient_shift = 2;
218 else
219 *transient_shift = 3;
220 *transient_time = n;
221
Jean-Marc Valin0ceccb22008-07-03 20:41:06 -0400222 RESTORE_STACK;
Jean-Marc Valinbd7de0a2008-07-06 10:57:26 -0400223 return ratio > 20;
Jean-Marc Valin9375aa42008-06-27 07:57:35 +1000224}
225
Jean-Marc Valind501f612008-02-21 12:16:57 +1100226/** Apply window and compute the MDCT for all sub-frames and all channels in a frame */
Jean-Marc Valin9d1decd2008-06-17 13:28:13 +1000227static void compute_mdcts(const CELTMode *mode, int shortBlocks, celt_sig_t * restrict in, celt_sig_t * restrict out)
Jean-Marc Valinda721882007-11-30 15:17:42 +1100228{
Jean-Marc Valin30e1b4d2008-04-22 00:10:52 +1000229 const int C = CHANNELS(mode);
Jean-Marc Valin9d1decd2008-06-17 13:28:13 +1000230 if (C==1 && !shortBlocks)
Jean-Marc Valinda721882007-11-30 15:17:42 +1100231 {
Jean-Marc Valin9d1decd2008-06-17 13:28:13 +1000232 const mdct_lookup *lookup = MDCT(mode);
233 const int overlap = OVERLAP(mode);
234 mdct_forward(lookup, in, out, mode->window, overlap);
235 } else if (!shortBlocks) {
236 const mdct_lookup *lookup = MDCT(mode);
237 const int overlap = OVERLAP(mode);
238 const int N = FRAMESIZE(mode);
Jean-Marc Valinef0d5f12008-04-22 09:49:22 +1000239 int c;
Jean-Marc Valin30e1b4d2008-04-22 00:10:52 +1000240 VARDECL(celt_word32_t, x);
241 VARDECL(celt_word32_t, tmp);
242 SAVE_STACK;
Jean-Marc Valinef0d5f12008-04-22 09:49:22 +1000243 ALLOC(x, N+overlap, celt_word32_t);
Jean-Marc Valin30e1b4d2008-04-22 00:10:52 +1000244 ALLOC(tmp, N, celt_word32_t);
245 for (c=0;c<C;c++)
Jean-Marc Valinffa13472007-12-10 16:54:17 +1100246 {
Jean-Marc Valin30e1b4d2008-04-22 00:10:52 +1000247 int j;
Jean-Marc Valinef0d5f12008-04-22 09:49:22 +1000248 for (j=0;j<N+overlap;j++)
249 x[j] = in[C*j+c];
Jean-Marc Valin9d1decd2008-06-17 13:28:13 +1000250 mdct_forward(lookup, x, tmp, mode->window, overlap);
Jean-Marc Valin1a3ed792008-04-20 20:39:53 +1000251 /* Interleaving the sub-frames */
252 for (j=0;j<N;j++)
253 out[C*j+c] = tmp[j];
254 }
Jean-Marc Valin30e1b4d2008-04-22 00:10:52 +1000255 RESTORE_STACK;
Jean-Marc Valin9d1decd2008-06-17 13:28:13 +1000256 } else {
257 const mdct_lookup *lookup = &mode->shortMdct;
258 const int overlap = mode->shortMdctSize;
259 const int N = mode->shortMdctSize;
260 int b, c;
261 VARDECL(celt_word32_t, x);
262 VARDECL(celt_word32_t, tmp);
263 SAVE_STACK;
264 ALLOC(x, N+overlap, celt_word32_t);
265 ALLOC(tmp, N, celt_word32_t);
266 for (c=0;c<C;c++)
267 {
268 int B = mode->nbShortMdcts;
269 for (b=0;b<B;b++)
270 {
271 int j;
272 for (j=0;j<N+overlap;j++)
273 x[j] = in[C*(b*N+j)+c];
274 mdct_forward(lookup, x, tmp, mode->window, overlap);
275 /* Interleaving the sub-frames */
276 for (j=0;j<N;j++)
277 out[C*(j*B+b)+c] = tmp[j];
278 }
279 }
280 RESTORE_STACK;
Jean-Marc Valinda721882007-11-30 15:17:42 +1100281 }
Jean-Marc Valinda721882007-11-30 15:17:42 +1100282}
283
Jean-Marc Valind501f612008-02-21 12:16:57 +1100284/** Compute the IMDCT and apply window for all sub-frames and all channels in a frame */
Jean-Marc Valin528f4b82008-06-29 03:46:39 +1000285static void compute_inv_mdcts(const CELTMode *mode, int shortBlocks, celt_sig_t *X, int transient_time, int transient_shift, celt_sig_t * restrict out_mem)
Jean-Marc Valin1677aa92007-12-08 01:13:34 +1100286{
Jean-Marc Valinb886ddc2008-03-25 14:38:55 +1100287 int c, N4;
Jean-Marc Valin05e56c42008-04-10 09:13:05 +1000288 const int C = CHANNELS(mode);
Jean-Marc Valinb18ec0b2008-04-11 04:07:52 +1000289 const int N = FRAMESIZE(mode);
290 const int overlap = OVERLAP(mode);
Jean-Marc Valina536f772008-03-22 09:01:50 +1100291 N4 = (N-overlap)>>1;
Jean-Marc Valinffa13472007-12-10 16:54:17 +1100292 for (c=0;c<C;c++)
Jean-Marc Valin1677aa92007-12-08 01:13:34 +1100293 {
Jean-Marc Valinb886ddc2008-03-25 14:38:55 +1100294 int j;
Jean-Marc Valin528f4b82008-06-29 03:46:39 +1000295 if (transient_shift==0 && C==1 && !shortBlocks) {
Jean-Marc Valin9d1decd2008-06-17 13:28:13 +1000296 const mdct_lookup *lookup = MDCT(mode);
297 mdct_backward(lookup, X, out_mem+C*(MAX_PERIOD-N-N4), mode->window, overlap);
298 } else if (!shortBlocks) {
299 const mdct_lookup *lookup = MDCT(mode);
Jean-Marc Valin8ddd7f42008-04-22 13:37:16 +1000300 VARDECL(celt_word32_t, x);
301 VARDECL(celt_word32_t, tmp);
302 SAVE_STACK;
303 ALLOC(x, 2*N, celt_word32_t);
304 ALLOC(tmp, N, celt_word32_t);
Jean-Marc Valin1a3ed792008-04-20 20:39:53 +1000305 /* De-interleaving the sub-frames */
306 for (j=0;j<N;j++)
307 tmp[j] = X[C*j+c];
Jean-Marc Valin8ddd7f42008-04-22 13:37:16 +1000308 /* Prevents problems from the imdct doing the overlap-add */
309 CELT_MEMSET(x+N4, 0, overlap);
Jean-Marc Valin9d1decd2008-06-17 13:28:13 +1000310 mdct_backward(lookup, tmp, x, mode->window, overlap);
Jean-Marc Valin0ceccb22008-07-03 20:41:06 -0400311 celt_assert(transient_shift == 0);
Jean-Marc Valin9d1decd2008-06-17 13:28:13 +1000312 /* The first and last part would need to be set to zero if we actually
Jean-Marc Valine4aeb472008-06-29 12:06:05 +1000313 wanted to use them. */
Jean-Marc Valin9d1decd2008-06-17 13:28:13 +1000314 for (j=0;j<overlap;j++)
315 out_mem[C*(MAX_PERIOD-N)+C*j+c] += x[j+N4];
316 for (j=0;j<overlap;j++)
317 out_mem[C*(MAX_PERIOD)+C*(overlap-j-1)+c] = x[2*N-j-N4-1];
318 for (j=0;j<2*N4;j++)
319 out_mem[C*(MAX_PERIOD-N)+C*(j+overlap)+c] = x[j+N4+overlap];
320 RESTORE_STACK;
321 } else {
322 int b;
323 const int N2 = mode->shortMdctSize;
324 const int B = mode->nbShortMdcts;
325 const mdct_lookup *lookup = &mode->shortMdct;
326 VARDECL(celt_word32_t, x);
327 VARDECL(celt_word32_t, tmp);
328 SAVE_STACK;
329 ALLOC(x, 2*N, celt_word32_t);
330 ALLOC(tmp, N, celt_word32_t);
331 /* Prevents problems from the imdct doing the overlap-add */
332 CELT_MEMSET(x+N4, 0, overlap);
333 for (b=0;b<B;b++)
334 {
335 /* De-interleaving the sub-frames */
336 for (j=0;j<N2;j++)
337 tmp[j] = X[C*(j*B+b)+c];
338 mdct_backward(lookup, tmp, x+N4+N2*b, mode->window, overlap);
339 }
Jean-Marc Valin528f4b82008-06-29 03:46:39 +1000340 if (transient_shift > 0)
Jean-Marc Valin12b22482008-06-16 14:13:05 +1000341 {
Jean-Marc Valin528f4b82008-06-29 03:46:39 +1000342#ifdef FIXED_POINT
Jean-Marc Valin12b22482008-06-16 14:13:05 +1000343 for (j=0;j<16;j++)
Jean-Marc Valin528f4b82008-06-29 03:46:39 +1000344 x[N4+transient_time+j-16] = MULT16_32_Q15(SHR16(Q15_ONE-transientWindow[j],transient_shift)+transientWindow[j], SHL32(x[N4+transient_time+j-16],transient_shift));
Jean-Marc Valin12b22482008-06-16 14:13:05 +1000345 for (j=transient_time;j<N+overlap;j++)
Jean-Marc Valin528f4b82008-06-29 03:46:39 +1000346 x[N4+j] = SHL32(x[N4+j], transient_shift);
347#else
348 for (j=0;j<16;j++)
Jean-Marc Valine4aeb472008-06-29 12:06:05 +1000349 x[N4+transient_time+j-16] *= 1+transientWindow[j]*((1<<transient_shift)-1);
Jean-Marc Valin528f4b82008-06-29 03:46:39 +1000350 for (j=transient_time;j<N+overlap;j++)
351 x[N4+j] *= 1<<transient_shift;
352#endif
Jean-Marc Valin12b22482008-06-16 14:13:05 +1000353 }
Jean-Marc Valinf28062f2008-03-03 13:24:01 +1100354 /* The first and last part would need to be set to zero if we actually
Jean-Marc Valin8ddd7f42008-04-22 13:37:16 +1000355 wanted to use them. */
356 for (j=0;j<overlap;j++)
357 out_mem[C*(MAX_PERIOD-N)+C*j+c] += x[j+N4];
358 for (j=0;j<overlap;j++)
359 out_mem[C*(MAX_PERIOD)+C*(overlap-j-1)+c] = x[2*N-j-N4-1];
360 for (j=0;j<2*N4;j++)
361 out_mem[C*(MAX_PERIOD-N)+C*(j+overlap)+c] = x[j+N4+overlap];
362 RESTORE_STACK;
363 }
Jean-Marc Valin1677aa92007-12-08 01:13:34 +1100364 }
365}
366
Gregory Maxwell5f2a74b2008-08-11 23:50:07 -0400367#ifdef FIXED_POINT
Peter Kirk19f9dc92008-06-06 14:38:38 +0200368int celt_encode(CELTEncoder * restrict st, celt_int16_t * restrict pcm, unsigned char *compressed, int nbCompressedBytes)
Jean-Marc Valin8ebd3452007-11-29 20:17:32 +1100369{
Gregory Maxwell5f2a74b2008-08-11 23:50:07 -0400370#else
371int celt_encode_float(CELTEncoder * restrict st, celt_sig_t * restrict pcm, unsigned char *compressed, int nbCompressedBytes)
372{
373#endif
Jean-Marc Valin05e56c42008-04-10 09:13:05 +1000374 int i, c, N, N4;
Jean-Marc Valin7e8a4872008-02-11 16:55:34 +1100375 int has_pitch;
Jean-Marc Valin0bb05bc2008-02-20 13:43:40 +1100376 int pitch_index;
Jean-Marc Valinc890b582008-08-01 22:26:49 -0400377 int bits;
Jean-Marc Valine40a19c2008-02-27 12:09:50 +1100378 celt_word32_t curr_power, pitch_power;
Jean-Marc Valin31b79d12008-03-12 17:17:23 +1100379 VARDECL(celt_sig_t, in);
380 VARDECL(celt_sig_t, freq);
381 VARDECL(celt_norm_t, X);
382 VARDECL(celt_norm_t, P);
383 VARDECL(celt_ener_t, bandE);
384 VARDECL(celt_pgain_t, gains);
Jean-Marc Valin7bd2b9e2008-05-23 14:23:22 +1000385 VARDECL(int, stereo_mode);
Jean-Marc Valin6775de32008-08-02 08:14:42 -0400386 VARDECL(int, fine_quant);
Jean-Marc Valinc890b582008-08-01 22:26:49 -0400387 VARDECL(celt_word16_t, error);
Jean-Marc Valin6775de32008-08-02 08:14:42 -0400388 VARDECL(int, pulses);
389 VARDECL(int, offsets);
Jean-Marc Valinc6ca4992008-06-01 23:19:16 +1000390#ifdef EXP_PSY
391 VARDECL(celt_word32_t, mask);
392#endif
Jean-Marc Valin9d1decd2008-06-17 13:28:13 +1000393 int shortBlocks=0;
Jean-Marc Valin12b22482008-06-16 14:13:05 +1000394 int transient_time;
Jean-Marc Valin528f4b82008-06-29 03:46:39 +1000395 int transient_shift;
Jean-Marc Valin05e56c42008-04-10 09:13:05 +1000396 const int C = CHANNELS(st->mode);
Jean-Marc Valin8600f692008-02-29 15:14:12 +1100397 SAVE_STACK;
Jean-Marc Valin44ffd5a2008-02-22 00:39:25 +1100398
399 if (check_mode(st->mode) != CELT_OK)
400 return CELT_INVALID_MODE;
401
Jean-Marc Valinf02ba112007-11-30 01:10:42 +1100402 N = st->block_size;
Jean-Marc Valina536f772008-03-22 09:01:50 +1100403 N4 = (N-st->overlap)>>1;
Jean-Marc Valinbdb58832008-04-20 17:42:10 +1000404 ALLOC(in, 2*C*N-2*C*N4, celt_sig_t);
Jean-Marc Valina5431bf2008-01-03 20:53:01 +1100405
Jean-Marc Valinbdb58832008-04-20 17:42:10 +1000406 CELT_COPY(in, st->in_mem, C*st->overlap);
Jean-Marc Valinffa13472007-12-10 16:54:17 +1100407 for (c=0;c<C;c++)
Jean-Marc Valin6f7e83d2007-12-01 00:36:41 +1100408 {
Gregory Maxwell5f2a74b2008-08-11 23:50:07 -0400409 const celt_word16_t * restrict pcmp = pcm+c;
Jean-Marc Valin62290062008-04-20 22:16:02 +1000410 celt_sig_t * restrict inp = in+C*st->overlap+c;
Jean-Marc Valinb886ddc2008-03-25 14:38:55 +1100411 for (i=0;i<N;i++)
Jean-Marc Valinffa13472007-12-10 16:54:17 +1100412 {
Jean-Marc Valin62290062008-04-20 22:16:02 +1000413 /* Apply pre-emphasis */
Gregory Maxwell5f2a74b2008-08-11 23:50:07 -0400414 celt_sig_t tmp = SCALEIN(SHL32(EXTEND32(*pcmp), SIG_SHIFT));
Jean-Marc Valin62290062008-04-20 22:16:02 +1000415 *inp = SUB32(tmp, SHR32(MULT16_16(preemph,st->preemph_memE[c]),1));
Gregory Maxwell5f2a74b2008-08-11 23:50:07 -0400416 st->preemph_memE[c] = SCALEIN(*pcmp);
Jean-Marc Valin62290062008-04-20 22:16:02 +1000417 inp += C;
418 pcmp += C;
Jean-Marc Valinffa13472007-12-10 16:54:17 +1100419 }
Jean-Marc Valin6f7e83d2007-12-01 00:36:41 +1100420 }
Jean-Marc Valinbdb58832008-04-20 17:42:10 +1000421 CELT_COPY(st->in_mem, in+C*(2*N-2*N4-st->overlap), C*st->overlap);
Jean-Marc Valin9375aa42008-06-27 07:57:35 +1000422
Jean-Marc Valin7028d622008-07-10 23:06:58 -0400423 if (st->mode->nbShortMdcts > 1)
Jean-Marc Valin9375aa42008-06-27 07:57:35 +1000424 {
Jean-Marc Valin7028d622008-07-10 23:06:58 -0400425 if (transient_analysis(in, N+st->overlap, C, &transient_time, &transient_shift))
Jean-Marc Valin528f4b82008-06-29 03:46:39 +1000426 {
Jean-Marc Valin7028d622008-07-10 23:06:58 -0400427#ifndef FIXED_POINT
428 float gain_1;
Jean-Marc Valin528f4b82008-06-29 03:46:39 +1000429#endif
Jean-Marc Valin7028d622008-07-10 23:06:58 -0400430 ec_enc_bits(&st->enc, 1, 1);
431 ec_enc_bits(&st->enc, transient_shift, 2);
432 if (transient_shift)
433 ec_enc_uint(&st->enc, transient_time, N+st->overlap);
434 if (transient_shift)
435 {
436#ifdef FIXED_POINT
437 for (c=0;c<C;c++)
438 for (i=0;i<16;i++)
439 in[C*(transient_time+i-16)+c] = MULT16_32_Q15(EXTRACT16(SHR32(celt_rcp(Q15ONE+MULT16_16(transientWindow[i],((1<<transient_shift)-1))),1)), in[C*(transient_time+i-16)+c]);
440 for (c=0;c<C;c++)
441 for (i=transient_time;i<N+st->overlap;i++)
442 in[C*i+c] = SHR32(in[C*i+c], transient_shift);
443#else
444 for (c=0;c<C;c++)
445 for (i=0;i<16;i++)
446 in[C*(transient_time+i-16)+c] /= 1+transientWindow[i]*((1<<transient_shift)-1);
447 gain_1 = 1./(1<<transient_shift);
448 for (c=0;c<C;c++)
449 for (i=transient_time;i<N+st->overlap;i++)
450 in[C*i+c] *= gain_1;
451#endif
452 }
453 shortBlocks = 1;
454 } else {
455 ec_enc_bits(&st->enc, 0, 1);
456 transient_time = -1;
457 transient_shift = 0;
458 shortBlocks = 0;
Jean-Marc Valin528f4b82008-06-29 03:46:39 +1000459 }
Jean-Marc Valin9375aa42008-06-27 07:57:35 +1000460 } else {
Jean-Marc Valin9375aa42008-06-27 07:57:35 +1000461 transient_time = -1;
Jean-Marc Valin528f4b82008-06-29 03:46:39 +1000462 transient_shift = 0;
Jean-Marc Valin9375aa42008-06-27 07:57:35 +1000463 shortBlocks = 0;
Jean-Marc Valin12b22482008-06-16 14:13:05 +1000464 }
Jean-Marc Valinddb181b2008-03-03 14:53:47 +1100465 /* Pitch analysis: we do it early to save on the peak stack space */
Jean-Marc Valin9d1decd2008-06-17 13:28:13 +1000466 if (!shortBlocks)
Jean-Marc Valin12b22482008-06-16 14:13:05 +1000467 find_spectral_pitch(st->mode, st->mode->fft, &st->mode->psy, in, st->out_mem, st->mode->window, 2*N-2*N4, MAX_PERIOD-(2*N-2*N4), &pitch_index);
Jean-Marc Valinddb181b2008-03-03 14:53:47 +1100468
Jean-Marc Valinb886ddc2008-03-25 14:38:55 +1100469 ALLOC(freq, C*N, celt_sig_t); /**< Interleaved signal MDCTs */
Jean-Marc Valinddb181b2008-03-03 14:53:47 +1100470
Jean-Marc Valina85657b2008-02-20 11:59:30 +1100471 /*for (i=0;i<(B+1)*C*N;i++) printf ("%f(%d) ", in[i], i); printf ("\n");*/
Jean-Marc Valinf02ba112007-11-30 01:10:42 +1100472 /* Compute MDCTs */
Jean-Marc Valin9d1decd2008-06-17 13:28:13 +1000473 compute_mdcts(st->mode, shortBlocks, in, freq);
Jean-Marc Valinb21b2a42008-01-07 23:04:43 +1100474
Jean-Marc Valinc6ca4992008-06-01 23:19:16 +1000475#ifdef EXP_PSY
476 CELT_MOVE(st->psy_mem, st->out_mem+N, MAX_PERIOD+st->overlap-N);
477 for (i=0;i<N;i++)
478 st->psy_mem[MAX_PERIOD+st->overlap-N+i] = in[C*(st->overlap+i)];
479 for (c=1;c<C;c++)
480 for (i=0;i<N;i++)
481 st->psy_mem[MAX_PERIOD+st->overlap-N+i] += in[C*(st->overlap+i)+c];
482
483 ALLOC(mask, N, celt_sig_t);
484 compute_mdct_masking(&st->psy, freq, st->psy_mem, mask, C*N);
Jean-Marc Valinb21b2a42008-01-07 23:04:43 +1100485
486 /* Invert and stretch the mask to length of X
487 For some reason, I get better results by using the sqrt instead,
488 although there's no valid reason to. Must investigate further */
Jean-Marc Valinc6ca4992008-06-01 23:19:16 +1000489 for (i=0;i<C*N;i++)
Jean-Marc Valinb21b2a42008-01-07 23:04:43 +1100490 mask[i] = 1/(.1+mask[i]);
Jean-Marc Valinb7ed44b2008-02-11 11:15:33 +1100491#endif
Jean-Marc Valin4bf5fd82007-11-30 15:01:48 +1100492
Jean-Marc Valin8d4ac152008-02-29 17:24:02 +1100493 /* Deferred allocation after find_spectral_pitch() to reduce the peak memory usage */
Jean-Marc Valinb886ddc2008-03-25 14:38:55 +1100494 ALLOC(X, C*N, celt_norm_t); /**< Interleaved normalised MDCTs */
495 ALLOC(P, C*N, celt_norm_t); /**< Interleaved normalised pitch MDCTs*/
Jean-Marc Valinddb181b2008-03-03 14:53:47 +1100496 ALLOC(bandE,st->mode->nbEBands*C, celt_ener_t);
497 ALLOC(gains,st->mode->nbPBands, celt_pgain_t);
Jean-Marc Valin8d4ac152008-02-29 17:24:02 +1100498
Jean-Marc Valina85657b2008-02-20 11:59:30 +1100499 /*printf ("%f %f\n", curr_power, pitch_power);*/
Jean-Marc Valin4bf5fd82007-11-30 15:01:48 +1100500 /*int j;
501 for (j=0;j<B*N;j++)
502 printf ("%f ", X[j]);
503 for (j=0;j<B*N;j++)
504 printf ("%f ", P[j]);
505 printf ("\n");*/
Jean-Marc Valin6c245242007-12-29 23:27:42 +1100506
Jean-Marc Valin8ebd3452007-11-29 20:17:32 +1100507 /* Band normalisation */
Jean-Marc Valincefc5ca2008-03-07 14:53:17 +1100508 compute_band_energies(st->mode, freq, bandE);
Jean-Marc Valin18ddc022008-02-22 14:24:50 +1100509 normalise_bands(st->mode, freq, X, bandE);
Jean-Marc Valina85657b2008-02-20 11:59:30 +1100510 /*for (i=0;i<st->mode->nbEBands;i++)printf("%f ", bandE[i]);printf("\n");*/
511 /*for (i=0;i<N*B*C;i++)printf("%f ", X[i]);printf("\n");*/
Jean-Marc Valin26c9e142007-12-31 21:27:54 +1100512
Jean-Marc Valin18ddc022008-02-22 14:24:50 +1100513 /* Compute MDCTs of the pitch part */
Jean-Marc Valin9d1decd2008-06-17 13:28:13 +1000514 if (!shortBlocks)
515 compute_mdcts(st->mode, 0, st->out_mem+pitch_index*C, freq);
Jean-Marc Valin18ddc022008-02-22 14:24:50 +1100516
Jean-Marc Valin96870d92007-12-05 21:14:22 +1100517 {
Jean-Marc Valin05686a52008-02-11 17:54:28 +1100518 /* Normalise the pitch vector as well (discard the energies) */
Jean-Marc Valin31b79d12008-03-12 17:17:23 +1100519 VARDECL(celt_ener_t, bandEp);
Jean-Marc Valine901fe32008-02-26 14:46:26 +1100520 ALLOC(bandEp, st->mode->nbEBands*st->mode->nbChannels, celt_ener_t);
Jean-Marc Valincefc5ca2008-03-07 14:53:17 +1100521 compute_band_energies(st->mode, freq, bandEp);
Jean-Marc Valin18ddc022008-02-22 14:24:50 +1100522 normalise_bands(st->mode, freq, P, bandEp);
Jean-Marc Valinbd2828f2008-03-26 08:10:27 +1100523 pitch_power = bandEp[0]+bandEp[1]+bandEp[2];
524 }
525 curr_power = bandE[0]+bandE[1]+bandE[2];
526 /* Check if we can safely use the pitch (i.e. effective gain isn't too high) */
Jean-Marc Valin9d1decd2008-06-17 13:28:13 +1000527 if (!shortBlocks && (MULT16_32_Q15(QCONST16(.1f, 15),curr_power) + QCONST32(10.f,ENER_SHIFT) < pitch_power))
Jean-Marc Valinbd2828f2008-03-26 08:10:27 +1100528 {
Jean-Marc Valin05686a52008-02-11 17:54:28 +1100529 /* Simulates intensity stereo */
Jean-Marc Valina85657b2008-02-20 11:59:30 +1100530 /*for (i=30;i<N*B;i++)
531 X[i*C+1] = P[i*C+1] = 0;*/
Jean-Marc Valin05686a52008-02-11 17:54:28 +1100532
533 /* Pitch prediction */
Jean-Marc Valin5e171492008-02-28 00:07:23 +1100534 compute_pitch_gain(st->mode, X, P, gains);
Jean-Marc Valin05686a52008-02-11 17:54:28 +1100535 has_pitch = quant_pitch(gains, st->mode->nbPBands, &st->enc);
536 if (has_pitch)
Jean-Marc Valinb886ddc2008-03-25 14:38:55 +1100537 ec_enc_uint(&st->enc, pitch_index, MAX_PERIOD-(2*N-2*N4));
Jean-Marc Valin05686a52008-02-11 17:54:28 +1100538 } else {
539 /* No pitch, so we just pretend we found a gain of zero */
540 for (i=0;i<st->mode->nbPBands;i++)
541 gains[i] = 0;
Jean-Marc Valin2146e642008-04-21 15:08:57 +1000542 ec_enc_bits(&st->enc, 0, 7);
Jean-Marc Valinb886ddc2008-03-25 14:38:55 +1100543 for (i=0;i<C*N;i++)
Jean-Marc Valin05686a52008-02-11 17:54:28 +1100544 P[i] = 0;
Jean-Marc Valin96870d92007-12-05 21:14:22 +1100545 }
Jean-Marc Valinc890b582008-08-01 22:26:49 -0400546
Jean-Marc Valin6775de32008-08-02 08:14:42 -0400547 ALLOC(fine_quant, st->mode->nbEBands, int);
Jean-Marc Valinc890b582008-08-01 22:26:49 -0400548 ALLOC(error, C*st->mode->nbEBands, celt_word16_t);
Jean-Marc Valin9c709062008-08-03 22:07:06 -0400549 quant_coarse_energy(st->mode, bandE, st->oldBandE, nbCompressedBytes*8/3, st->mode->prob, error, &st->enc);
Jean-Marc Valin6775de32008-08-02 08:14:42 -0400550
551 ALLOC(pulses, st->mode->nbEBands, int);
552 ALLOC(offsets, st->mode->nbEBands, int);
Jean-Marc Valin7bd2b9e2008-05-23 14:23:22 +1000553 ALLOC(stereo_mode, st->mode->nbEBands, int);
Jean-Marc Valinbf2d6482008-05-23 16:57:34 +1000554 stereo_decision(st->mode, X, stereo_mode, st->mode->nbEBands);
Jean-Marc Valincb7a2a32008-02-11 16:44:48 +1100555
Jean-Marc Valin6775de32008-08-02 08:14:42 -0400556 for (i=0;i<st->mode->nbEBands;i++)
557 offsets[i] = 0;
558 bits = nbCompressedBytes*8 - ec_enc_tell(&st->enc, 0) - 1;
559 compute_allocation(st->mode, offsets, stereo_mode, bits, pulses, fine_quant);
560 /*for (i=0;i<st->mode->nbEBands;i++)
561 printf("%d ", fine_quant[i]);
562 for (i=0;i<st->mode->nbEBands;i++)
563 printf("%d ", pulses[i]);
564 printf ("\n");*/
565 /*bits = ec_enc_tell(&st->enc, 0);
566 compute_fine_allocation(st->mode, fine_quant, (20*C+nbCompressedBytes*8/5-(ec_enc_tell(&st->enc, 0)-bits))/C);*/
567 quant_fine_energy(st->mode, bandE, st->oldBandE, error, fine_quant, &st->enc);
568
Jean-Marc Valin5e171492008-02-28 00:07:23 +1100569 pitch_quant_bands(st->mode, P, gains);
Jean-Marc Valin6e9058a2007-12-07 14:59:06 +1100570
Jean-Marc Valina85657b2008-02-20 11:59:30 +1100571 /*for (i=0;i<B*N;i++) printf("%f ",P[i]);printf("\n");*/
Jean-Marc Valin8ebd3452007-11-29 20:17:32 +1100572
573 /* Residual quantisation */
Jean-Marc Valin6775de32008-08-02 08:14:42 -0400574 quant_bands(st->mode, X, P, NULL, bandE, stereo_mode, pulses, shortBlocks, &st->enc);
Jean-Marc Valinfdca84b2008-01-09 10:44:18 +1100575
Jean-Marc Valinbf940452007-12-10 17:10:29 +1100576 if (C==2)
Jean-Marc Valin18ddc022008-02-22 14:24:50 +1100577 {
Jean-Marc Valin18ddc022008-02-22 14:24:50 +1100578 renormalise_bands(st->mode, X);
579 }
Jean-Marc Valinfdca84b2008-01-09 10:44:18 +1100580 /* Synthesis */
Jean-Marc Valin18ddc022008-02-22 14:24:50 +1100581 denormalise_bands(st->mode, X, freq, bandE);
Jean-Marc Valinfdca84b2008-01-09 10:44:18 +1100582
583
Jean-Marc Valin8ddd7f42008-04-22 13:37:16 +1000584 CELT_MOVE(st->out_mem, st->out_mem+C*N, C*(MAX_PERIOD+st->overlap-N));
Jean-Marc Valin26c9e142007-12-31 21:27:54 +1100585
Jean-Marc Valin528f4b82008-06-29 03:46:39 +1000586 compute_inv_mdcts(st->mode, shortBlocks, freq, transient_time, transient_shift, st->out_mem);
Jean-Marc Valin26c9e142007-12-31 21:27:54 +1100587 /* De-emphasis and put everything back at the right place in the synthesis history */
Jean-Marc Valinef100272008-04-24 08:29:25 +1000588#ifndef SHORTCUTS
Jean-Marc Valinffa13472007-12-10 16:54:17 +1100589 for (c=0;c<C;c++)
Jean-Marc Valinf02ba112007-11-30 01:10:42 +1100590 {
Jean-Marc Valinb886ddc2008-03-25 14:38:55 +1100591 int j;
592 for (j=0;j<N;j++)
Jean-Marc Valin6f7e83d2007-12-01 00:36:41 +1100593 {
Gregory Maxwell5f2a74b2008-08-11 23:50:07 -0400594 celt_sig_t tmp = ADD32(st->out_mem[C*(MAX_PERIOD-N)+C*j+c],
595 MULT16_32_Q15(preemph,st->preemph_memD[c]));
Jean-Marc Valinb886ddc2008-03-25 14:38:55 +1100596 st->preemph_memD[c] = tmp;
Gregory Maxwell5f2a74b2008-08-11 23:50:07 -0400597 pcm[C*j+c] = SCALEOUT(SIG2WORD16(tmp));
Jean-Marc Valin6f7e83d2007-12-01 00:36:41 +1100598 }
Jean-Marc Valinf02ba112007-11-30 01:10:42 +1100599 }
Jean-Marc Valinef100272008-04-24 08:29:25 +1000600#endif
Jean-Marc Valin6361ad82008-07-20 23:14:31 -0400601 /*if (ec_enc_tell(&st->enc, 0) < nbCompressedBytes*8 - 7)
602 celt_warning_int ("many unused bits: ", nbCompressedBytes*8-ec_enc_tell(&st->enc, 0));*/
Jean-Marc Valina85657b2008-02-20 11:59:30 +1100603 /*printf ("%d\n", ec_enc_tell(&st->enc, 0)-8*nbCompressedBytes);*/
Jean-Marc Valin94d4ea92008-01-27 17:34:35 +1100604 /* Finishing the stream with a 0101... pattern so that the decoder can check is everything's right */
605 {
606 int val = 0;
607 while (ec_enc_tell(&st->enc, 0) < nbCompressedBytes*8)
608 {
609 ec_enc_uint(&st->enc, val, 2);
610 val = 1-val;
611 }
612 }
Jean-Marc Valinb35536a2008-01-17 16:57:18 +1100613 ec_enc_done(&st->enc);
Jean-Marc Valina76a0b22008-01-17 22:43:05 +1100614 {
615 unsigned char *data;
616 int nbBytes = ec_byte_bytes(&st->buf);
Jean-Marc Valinb3756702008-02-08 11:50:17 +1100617 if (nbBytes > nbCompressedBytes)
Jean-Marc Valin388f1d62008-01-18 16:28:11 +1100618 {
Jean-Marc Valinb3756702008-02-08 11:50:17 +1100619 celt_warning_int ("got too many bytes:", nbBytes);
Jean-Marc Valin8600f692008-02-29 15:14:12 +1100620 RESTORE_STACK;
Jean-Marc Valin388f1d62008-01-18 16:28:11 +1100621 return CELT_INTERNAL_ERROR;
622 }
Jean-Marc Valina85657b2008-02-20 11:59:30 +1100623 /*printf ("%d\n", *nbBytes);*/
Jean-Marc Valina76a0b22008-01-17 22:43:05 +1100624 data = ec_byte_get_buffer(&st->buf);
625 for (i=0;i<nbBytes;i++)
626 compressed[i] = data[i];
Jean-Marc Valinb3756702008-02-08 11:50:17 +1100627 for (;i<nbCompressedBytes;i++)
628 compressed[i] = 0;
Jean-Marc Valin388f1d62008-01-18 16:28:11 +1100629 }
Jean-Marc Valinb35536a2008-01-17 16:57:18 +1100630 /* Reset the packing for the next encoding */
631 ec_byte_reset(&st->buf);
632 ec_enc_init(&st->enc,&st->buf);
633
Jean-Marc Valin8600f692008-02-29 15:14:12 +1100634 RESTORE_STACK;
Jean-Marc Valina76a0b22008-01-17 22:43:05 +1100635 return nbCompressedBytes;
Jean-Marc Valin8ebd3452007-11-29 20:17:32 +1100636}
637
Gregory Maxwell5f2a74b2008-08-11 23:50:07 -0400638#ifdef FIXED_POINT
639#ifndef DISABLE_FLOAT_API
640int celt_encode_float(CELTEncoder * restrict st, float * restrict pcm, unsigned char *compressed, int nbCompressedBytes)
641{
642 int j, ret;
643 const int C = CHANNELS(st->mode);
644 const int N = st->block_size;
645 ALLOC(in, C*N, celt_int16_t);
646
647 for (j=0;j<C*N;j++)
648 in[j] = FLOAT2INT16(pcm[j]);
649
650 ret=celt_encode(st,in,compressed,nbCompressedBytes);
651#ifndef SHORTCUTS
652 /*Converts backwards for inplace operation*/
653 for (j=0;j=C*N;j++)
654 pcm[j]=in[j]*(1/32768.);
655#endif
656 return ret;
657
658}
659#endif /*DISABLE_FLOAT_API*/
660#else
661int celt_encode(CELTEncoder * restrict st, celt_int16_t * restrict pcm, unsigned char *compressed, int nbCompressedBytes)
662{
663 int j, ret;
664 VARDECL(celt_sig_t, in);
665 const int C = CHANNELS(st->mode);
666 const int N = st->block_size;
667
668 ALLOC(in, C*N, celt_sig_t);
669 for (j=0;j<C*N;j++) {
670 in[j] = SCALEOUT(pcm[j]);
671 }
672 ret = celt_encode_float(st,in,compressed,nbCompressedBytes);
673#ifndef SHORTCUTS
674 for (j=0;j<C*N;j++)
675 pcm[j] = FLOAT2INT16(in[j]);
676
677#endif
678 return ret;
679}
680#endif
Jean-Marc Valin6e9058a2007-12-07 14:59:06 +1100681
Jean-Marc Valin269d40a2007-12-07 11:29:45 +1100682/****************************************************************************/
Jean-Marc Valin671bf402007-12-07 15:36:39 +1100683/* */
684/* DECODER */
685/* */
Jean-Marc Valin269d40a2007-12-07 11:29:45 +1100686/****************************************************************************/
687
688
Jean-Marc Valin276de722008-02-20 17:45:51 +1100689/** Decoder state
690 @brief Decoder state
691 */
Jean-Marc Valin269d40a2007-12-07 11:29:45 +1100692struct CELTDecoder {
693 const CELTMode *mode;
694 int frame_size;
695 int block_size;
Jean-Marc Valina5431bf2008-01-03 20:53:01 +1100696 int overlap;
697
Jean-Marc Valin269d40a2007-12-07 11:29:45 +1100698 ec_byte_buffer buf;
699 ec_enc enc;
700
Jean-Marc Valin65fb92e2008-04-19 22:24:53 +1000701 celt_sig_t * restrict preemph_memD;
Jean-Marc Valin81b38c22008-02-29 21:08:49 +1100702
Jean-Marc Valin18ddc022008-02-22 14:24:50 +1100703 celt_sig_t *out_mem;
Jean-Marc Valin269d40a2007-12-07 11:29:45 +1100704
Jean-Marc Valin5d561832008-02-27 11:59:05 +1100705 celt_word16_t *oldBandE;
Jean-Marc Valinfb83fb42007-12-08 00:56:04 +1100706
707 int last_pitch_index;
Jean-Marc Valin269d40a2007-12-07 11:29:45 +1100708};
709
Peter Kirk19f9dc92008-06-06 14:38:38 +0200710CELTDecoder *celt_decoder_create(const CELTMode *mode)
Jean-Marc Valin269d40a2007-12-07 11:29:45 +1100711{
Jean-Marc Valinb886ddc2008-03-25 14:38:55 +1100712 int N, C;
Jean-Marc Valin0bb05bc2008-02-20 13:43:40 +1100713 CELTDecoder *st;
Jean-Marc Valin44ffd5a2008-02-22 00:39:25 +1100714
715 if (check_mode(mode) != CELT_OK)
716 return NULL;
717
Jean-Marc Valin269d40a2007-12-07 11:29:45 +1100718 N = mode->mdctSize;
Jean-Marc Valin05e56c42008-04-10 09:13:05 +1000719 C = CHANNELS(mode);
Jean-Marc Valin0bb05bc2008-02-20 13:43:40 +1100720 st = celt_alloc(sizeof(CELTDecoder));
Jean-Marc Valin269d40a2007-12-07 11:29:45 +1100721
722 st->mode = mode;
Jean-Marc Valinb886ddc2008-03-25 14:38:55 +1100723 st->frame_size = N;
Jean-Marc Valin269d40a2007-12-07 11:29:45 +1100724 st->block_size = N;
Jean-Marc Valina5431bf2008-01-03 20:53:01 +1100725 st->overlap = mode->overlap;
726
Jean-Marc Valin8ddd7f42008-04-22 13:37:16 +1000727 st->out_mem = celt_alloc((MAX_PERIOD+st->overlap)*C*sizeof(celt_sig_t));
Jean-Marc Valin269d40a2007-12-07 11:29:45 +1100728
Jean-Marc Valin5d561832008-02-27 11:59:05 +1100729 st->oldBandE = (celt_word16_t*)celt_alloc(C*mode->nbEBands*sizeof(celt_word16_t));
Jean-Marc Valin269d40a2007-12-07 11:29:45 +1100730
Gregory Maxwell5f2a74b2008-08-11 23:50:07 -0400731 st->preemph_memD = (celt_sig_t*)celt_alloc(C*sizeof(celt_sig_t));
Jean-Marc Valinffa13472007-12-10 16:54:17 +1100732
Jean-Marc Valinfb83fb42007-12-08 00:56:04 +1100733 st->last_pitch_index = 0;
Jean-Marc Valin269d40a2007-12-07 11:29:45 +1100734 return st;
735}
736
Peter Kirk19f9dc92008-06-06 14:38:38 +0200737void celt_decoder_destroy(CELTDecoder *st)
Jean-Marc Valin269d40a2007-12-07 11:29:45 +1100738{
739 if (st == NULL)
740 {
741 celt_warning("NULL passed to celt_encoder_destroy");
742 return;
743 }
Jean-Marc Valin44ffd5a2008-02-22 00:39:25 +1100744 if (check_mode(st->mode) != CELT_OK)
745 return;
Jean-Marc Valin269d40a2007-12-07 11:29:45 +1100746
Jean-Marc Valin269d40a2007-12-07 11:29:45 +1100747
Jean-Marc Valin269d40a2007-12-07 11:29:45 +1100748 celt_free(st->out_mem);
749
750 celt_free(st->oldBandE);
Jean-Marc Valin7351e282008-02-08 15:09:45 +1100751
752 celt_free(st->preemph_memD);
753
Jean-Marc Valin269d40a2007-12-07 11:29:45 +1100754 celt_free(st);
755}
756
Jean-Marc Valind501f612008-02-21 12:16:57 +1100757/** Handles lost packets by just copying past data with the same offset as the last
758 pitch period */
Gregory Maxwell5f2a74b2008-08-11 23:50:07 -0400759static void celt_decode_lost(CELTDecoder * restrict st, celt_word16_t * restrict pcm)
Jean-Marc Valinfb83fb42007-12-08 00:56:04 +1100760{
Jean-Marc Valin05e56c42008-04-10 09:13:05 +1000761 int c, N;
Jean-Marc Valin0bb05bc2008-02-20 13:43:40 +1100762 int pitch_index;
Jean-Marc Valin24c9cda2008-05-02 10:34:07 +1000763 int i, len;
Jean-Marc Valin31b79d12008-03-12 17:17:23 +1100764 VARDECL(celt_sig_t, freq);
Jean-Marc Valin05e56c42008-04-10 09:13:05 +1000765 const int C = CHANNELS(st->mode);
Jean-Marc Valin24c9cda2008-05-02 10:34:07 +1000766 int offset;
Jean-Marc Valin8600f692008-02-29 15:14:12 +1100767 SAVE_STACK;
Jean-Marc Valinfb83fb42007-12-08 00:56:04 +1100768 N = st->block_size;
Jean-Marc Valinb886ddc2008-03-25 14:38:55 +1100769 ALLOC(freq,C*N, celt_sig_t); /**< Interleaved signal MDCTs */
Jean-Marc Valinfb83fb42007-12-08 00:56:04 +1100770
Jean-Marc Valin24c9cda2008-05-02 10:34:07 +1000771 len = N+st->mode->overlap;
772#if 0
Jean-Marc Valinfb83fb42007-12-08 00:56:04 +1100773 pitch_index = st->last_pitch_index;
774
Jean-Marc Valin1677aa92007-12-08 01:13:34 +1100775 /* Use the pitch MDCT as the "guessed" signal */
Jean-Marc Valinb18ec0b2008-04-11 04:07:52 +1000776 compute_mdcts(st->mode, st->mode->window, st->out_mem+pitch_index*C, freq);
Jean-Marc Valinfb83fb42007-12-08 00:56:04 +1100777
Jean-Marc Valin24c9cda2008-05-02 10:34:07 +1000778#else
779 find_spectral_pitch(st->mode, st->mode->fft, &st->mode->psy, st->out_mem+MAX_PERIOD-len, st->out_mem, st->mode->window, len, MAX_PERIOD-len-100, &pitch_index);
780 pitch_index = MAX_PERIOD-len-pitch_index;
781 offset = MAX_PERIOD-pitch_index;
782 while (offset+len >= MAX_PERIOD)
783 offset -= pitch_index;
Jean-Marc Valin9d1decd2008-06-17 13:28:13 +1000784 compute_mdcts(st->mode, 0, st->out_mem+offset*C, freq);
Jean-Marc Valin24c9cda2008-05-02 10:34:07 +1000785 for (i=0;i<N;i++)
786 freq[i] = MULT16_32_Q15(QCONST16(.9f,15),freq[i]);
787#endif
788
789
790
791 CELT_MOVE(st->out_mem, st->out_mem+C*N, C*(MAX_PERIOD+st->mode->overlap-N));
Jean-Marc Valinfb83fb42007-12-08 00:56:04 +1100792 /* Compute inverse MDCTs */
Jean-Marc Valin9d1decd2008-06-17 13:28:13 +1000793 compute_inv_mdcts(st->mode, 0, freq, -1, 1, st->out_mem);
Jean-Marc Valin1677aa92007-12-08 01:13:34 +1100794
Jean-Marc Valinffa13472007-12-10 16:54:17 +1100795 for (c=0;c<C;c++)
Jean-Marc Valinfb83fb42007-12-08 00:56:04 +1100796 {
Jean-Marc Valinb886ddc2008-03-25 14:38:55 +1100797 int j;
798 for (j=0;j<N;j++)
Jean-Marc Valinfb83fb42007-12-08 00:56:04 +1100799 {
Jean-Marc Valinb886ddc2008-03-25 14:38:55 +1100800 celt_sig_t tmp = ADD32(st->out_mem[C*(MAX_PERIOD-N)+C*j+c],
801 MULT16_32_Q15(preemph,st->preemph_memD[c]));
802 st->preemph_memD[c] = tmp;
Gregory Maxwell5f2a74b2008-08-11 23:50:07 -0400803 pcm[C*j+c] = SCALEOUT(SIG2WORD16(tmp));
Jean-Marc Valinfb83fb42007-12-08 00:56:04 +1100804 }
805 }
Jean-Marc Valin8600f692008-02-29 15:14:12 +1100806 RESTORE_STACK;
Jean-Marc Valinfb83fb42007-12-08 00:56:04 +1100807}
808
Gregory Maxwell5f2a74b2008-08-11 23:50:07 -0400809#ifdef FIXED_POINT
Peter Kirk19f9dc92008-06-06 14:38:38 +0200810int celt_decode(CELTDecoder * restrict st, unsigned char *data, int len, celt_int16_t * restrict pcm)
Jean-Marc Valin269d40a2007-12-07 11:29:45 +1100811{
Gregory Maxwell5f2a74b2008-08-11 23:50:07 -0400812#else
813int celt_decode_float(CELTDecoder * restrict st, unsigned char *data, int len, celt_sig_t * restrict pcm)
814{
815#endif
Jean-Marc Valin6775de32008-08-02 08:14:42 -0400816 int i, c, N, N4;
Jean-Marc Valin7e8a4872008-02-11 16:55:34 +1100817 int has_pitch;
Jean-Marc Valin0bb05bc2008-02-20 13:43:40 +1100818 int pitch_index;
Jean-Marc Valinc890b582008-08-01 22:26:49 -0400819 int bits;
Jean-Marc Valin0bb05bc2008-02-20 13:43:40 +1100820 ec_dec dec;
821 ec_byte_buffer buf;
Jean-Marc Valin31b79d12008-03-12 17:17:23 +1100822 VARDECL(celt_sig_t, freq);
823 VARDECL(celt_norm_t, X);
824 VARDECL(celt_norm_t, P);
825 VARDECL(celt_ener_t, bandE);
826 VARDECL(celt_pgain_t, gains);
Jean-Marc Valin7bd2b9e2008-05-23 14:23:22 +1000827 VARDECL(int, stereo_mode);
Jean-Marc Valin6775de32008-08-02 08:14:42 -0400828 VARDECL(int, fine_quant);
829 VARDECL(int, pulses);
830 VARDECL(int, offsets);
Jean-Marc Valinc890b582008-08-01 22:26:49 -0400831
Jean-Marc Valin9d1decd2008-06-17 13:28:13 +1000832 int shortBlocks;
Jean-Marc Valin12b22482008-06-16 14:13:05 +1000833 int transient_time;
Jean-Marc Valin528f4b82008-06-29 03:46:39 +1000834 int transient_shift;
Jean-Marc Valin05e56c42008-04-10 09:13:05 +1000835 const int C = CHANNELS(st->mode);
Jean-Marc Valin8600f692008-02-29 15:14:12 +1100836 SAVE_STACK;
Jean-Marc Valin44ffd5a2008-02-22 00:39:25 +1100837
838 if (check_mode(st->mode) != CELT_OK)
839 return CELT_INVALID_MODE;
840
Jean-Marc Valin269d40a2007-12-07 11:29:45 +1100841 N = st->block_size;
Jean-Marc Valina536f772008-03-22 09:01:50 +1100842 N4 = (N-st->overlap)>>1;
Jean-Marc Valin01417232008-03-03 13:59:55 +1100843
Jean-Marc Valinb886ddc2008-03-25 14:38:55 +1100844 ALLOC(freq, C*N, celt_sig_t); /**< Interleaved signal MDCTs */
845 ALLOC(X, C*N, celt_norm_t); /**< Interleaved normalised MDCTs */
846 ALLOC(P, C*N, celt_norm_t); /**< Interleaved normalised pitch MDCTs*/
Jean-Marc Valine901fe32008-02-26 14:46:26 +1100847 ALLOC(bandE, st->mode->nbEBands*C, celt_ener_t);
Jean-Marc Valin017d4452008-02-26 16:19:03 +1100848 ALLOC(gains, st->mode->nbPBands, celt_pgain_t);
Jean-Marc Valin70c8ffd2007-12-07 14:20:01 +1100849
Jean-Marc Valin44ffd5a2008-02-22 00:39:25 +1100850 if (check_mode(st->mode) != CELT_OK)
Jean-Marc Valin8600f692008-02-29 15:14:12 +1100851 {
852 RESTORE_STACK;
Jean-Marc Valin44ffd5a2008-02-22 00:39:25 +1100853 return CELT_INVALID_MODE;
Jean-Marc Valin8600f692008-02-29 15:14:12 +1100854 }
Jean-Marc Valinfb83fb42007-12-08 00:56:04 +1100855 if (data == NULL)
856 {
857 celt_decode_lost(st, pcm);
Jean-Marc Valin8600f692008-02-29 15:14:12 +1100858 RESTORE_STACK;
Jean-Marc Valinfb83fb42007-12-08 00:56:04 +1100859 return 0;
860 }
861
Jean-Marc Valin70c8ffd2007-12-07 14:20:01 +1100862 ec_byte_readinit(&buf,data,len);
863 ec_dec_init(&dec,&buf);
864
Jean-Marc Valin7028d622008-07-10 23:06:58 -0400865 if (st->mode->nbShortMdcts > 1)
Jean-Marc Valin12b22482008-06-16 14:13:05 +1000866 {
Jean-Marc Valin7028d622008-07-10 23:06:58 -0400867 shortBlocks = ec_dec_bits(&dec, 1);
868 if (shortBlocks)
869 {
870 transient_shift = ec_dec_bits(&dec, 2);
871 if (transient_shift)
872 transient_time = ec_dec_uint(&dec, N+st->mode->overlap);
873 else
874 transient_time = 0;
875 } else {
876 transient_time = -1;
877 transient_shift = 0;
878 }
Jean-Marc Valin12b22482008-06-16 14:13:05 +1000879 } else {
Jean-Marc Valin7028d622008-07-10 23:06:58 -0400880 shortBlocks = 0;
Jean-Marc Valin12b22482008-06-16 14:13:05 +1000881 transient_time = -1;
Jean-Marc Valin528f4b82008-06-29 03:46:39 +1000882 transient_shift = 0;
Jean-Marc Valin12b22482008-06-16 14:13:05 +1000883 }
Jean-Marc Valincb7a2a32008-02-11 16:44:48 +1100884 /* Get the pitch gains */
Jean-Marc Valin7e8a4872008-02-11 16:55:34 +1100885 has_pitch = unquant_pitch(gains, st->mode->nbPBands, &dec);
Jean-Marc Valincb7a2a32008-02-11 16:44:48 +1100886
Jean-Marc Valin70c8ffd2007-12-07 14:20:01 +1100887 /* Get the pitch index */
Jean-Marc Valin7e8a4872008-02-11 16:55:34 +1100888 if (has_pitch)
889 {
Jean-Marc Valinb886ddc2008-03-25 14:38:55 +1100890 pitch_index = ec_dec_uint(&dec, MAX_PERIOD-(2*N-2*N4));
Jean-Marc Valin7e8a4872008-02-11 16:55:34 +1100891 st->last_pitch_index = pitch_index;
892 } else {
893 /* FIXME: We could be more intelligent here and just not compute the MDCT */
894 pitch_index = 0;
895 }
Jean-Marc Valin827f9312008-05-06 23:21:55 +1000896
Jean-Marc Valin6775de32008-08-02 08:14:42 -0400897 ALLOC(fine_quant, st->mode->nbEBands, int);
Jean-Marc Valin827f9312008-05-06 23:21:55 +1000898 /* Get band energies */
Jean-Marc Valin9c709062008-08-03 22:07:06 -0400899 unquant_coarse_energy(st->mode, bandE, st->oldBandE, len*8/3, st->mode->prob, &dec);
Jean-Marc Valin6775de32008-08-02 08:14:42 -0400900
901 ALLOC(pulses, st->mode->nbEBands, int);
902 ALLOC(offsets, st->mode->nbEBands, int);
903 ALLOC(stereo_mode, st->mode->nbEBands, int);
904 stereo_decision(st->mode, X, stereo_mode, st->mode->nbEBands);
905
906 for (i=0;i<st->mode->nbEBands;i++)
907 offsets[i] = 0;
908
909 bits = len*8 - ec_dec_tell(&dec, 0) - 1;
910 compute_allocation(st->mode, offsets, stereo_mode, bits, pulses, fine_quant);
911 /*bits = ec_dec_tell(&dec, 0);
912 compute_fine_allocation(st->mode, fine_quant, (20*C+len*8/5-(ec_dec_tell(&dec, 0)-bits))/C);*/
913
Jean-Marc Valinc890b582008-08-01 22:26:49 -0400914 unquant_fine_energy(st->mode, bandE, st->oldBandE, fine_quant, &dec);
Jean-Marc Valin827f9312008-05-06 23:21:55 +1000915
Jean-Marc Valin70c8ffd2007-12-07 14:20:01 +1100916 /* Pitch MDCT */
Jean-Marc Valin9d1decd2008-06-17 13:28:13 +1000917 compute_mdcts(st->mode, 0, st->out_mem+pitch_index*C, freq);
Jean-Marc Valin269d40a2007-12-07 11:29:45 +1100918
Jean-Marc Valin269d40a2007-12-07 11:29:45 +1100919 {
Jean-Marc Valin31b79d12008-03-12 17:17:23 +1100920 VARDECL(celt_ener_t, bandEp);
Jean-Marc Valine901fe32008-02-26 14:46:26 +1100921 ALLOC(bandEp, st->mode->nbEBands*C, celt_ener_t);
Jean-Marc Valincefc5ca2008-03-07 14:53:17 +1100922 compute_band_energies(st->mode, freq, bandEp);
Jean-Marc Valin18ddc022008-02-22 14:24:50 +1100923 normalise_bands(st->mode, freq, P, bandEp);
Jean-Marc Valin269d40a2007-12-07 11:29:45 +1100924 }
925
926 /* Apply pitch gains */
Jean-Marc Valin5e171492008-02-28 00:07:23 +1100927 pitch_quant_bands(st->mode, P, gains);
Jean-Marc Valin70c8ffd2007-12-07 14:20:01 +1100928
929 /* Decode fixed codebook and merge with pitch */
Jean-Marc Valin6775de32008-08-02 08:14:42 -0400930 unquant_bands(st->mode, X, P, bandE, stereo_mode, pulses, shortBlocks, &dec);
Jean-Marc Valin70c8ffd2007-12-07 14:20:01 +1100931
Jean-Marc Valinbf940452007-12-10 17:10:29 +1100932 if (C==2)
Jean-Marc Valin18ddc022008-02-22 14:24:50 +1100933 {
Jean-Marc Valin18ddc022008-02-22 14:24:50 +1100934 renormalise_bands(st->mode, X);
935 }
Jean-Marc Valina4833ff2008-01-10 15:34:00 +1100936 /* Synthesis */
Jean-Marc Valin18ddc022008-02-22 14:24:50 +1100937 denormalise_bands(st->mode, X, freq, bandE);
Jean-Marc Valina4833ff2008-01-10 15:34:00 +1100938
939
Jean-Marc Valin8ddd7f42008-04-22 13:37:16 +1000940 CELT_MOVE(st->out_mem, st->out_mem+C*N, C*(MAX_PERIOD+st->overlap-N));
Jean-Marc Valin269d40a2007-12-07 11:29:45 +1100941 /* Compute inverse MDCTs */
Jean-Marc Valin528f4b82008-06-29 03:46:39 +1000942 compute_inv_mdcts(st->mode, shortBlocks, freq, transient_time, transient_shift, st->out_mem);
Jean-Marc Valinffa13472007-12-10 16:54:17 +1100943
944 for (c=0;c<C;c++)
Jean-Marc Valin269d40a2007-12-07 11:29:45 +1100945 {
Jean-Marc Valinb886ddc2008-03-25 14:38:55 +1100946 int j;
947 for (j=0;j<N;j++)
Jean-Marc Valin269d40a2007-12-07 11:29:45 +1100948 {
Gregory Maxwell5f2a74b2008-08-11 23:50:07 -0400949 celt_sig_t tmp = ADD32(st->out_mem[C*(MAX_PERIOD-N)+C*j+c],
950 MULT16_32_Q15(preemph,st->preemph_memD[c]));
Jean-Marc Valinb886ddc2008-03-25 14:38:55 +1100951 st->preemph_memD[c] = tmp;
Gregory Maxwell5f2a74b2008-08-11 23:50:07 -0400952 pcm[C*j+c] = SCALEOUT(SIG2WORD16(tmp));
Jean-Marc Valin269d40a2007-12-07 11:29:45 +1100953 }
954 }
Jean-Marc Valin388f1d62008-01-18 16:28:11 +1100955
Jean-Marc Valin94d4ea92008-01-27 17:34:35 +1100956 {
Jean-Marc Valin5e171492008-02-28 00:07:23 +1100957 unsigned int val = 0;
Jean-Marc Valin94d4ea92008-01-27 17:34:35 +1100958 while (ec_dec_tell(&dec, 0) < len*8)
959 {
960 if (ec_dec_uint(&dec, 2) != val)
961 {
962 celt_warning("decode error");
Jean-Marc Valin8600f692008-02-29 15:14:12 +1100963 RESTORE_STACK;
Jean-Marc Valin94d4ea92008-01-27 17:34:35 +1100964 return CELT_CORRUPTED_DATA;
965 }
966 val = 1-val;
967 }
968 }
969
Jean-Marc Valin8600f692008-02-29 15:14:12 +1100970 RESTORE_STACK;
Jean-Marc Valinfb83fb42007-12-08 00:56:04 +1100971 return 0;
Jean-Marc Valina85657b2008-02-20 11:59:30 +1100972 /*printf ("\n");*/
Jean-Marc Valin269d40a2007-12-07 11:29:45 +1100973}
974
Gregory Maxwell5f2a74b2008-08-11 23:50:07 -0400975#ifdef FIXED_POINT
976#ifndef DISABLE_FLOAT_API
977int celt_decode_float(CELTDecoder * restrict st, unsigned char *data, int len, float * restrict pcm)
978{
979 int j, ret;
980 const int C = CHANNELS(st->mode);
981 const int N = st->block_size;
982 ALLOC(out, C*N, celt_int16_t);
983
984 ret=celt_decode(st, data, len, out);
985
986 for (j=0;j<C*N;j++)
987 pcm[j]=out[j]*(1/32768.);
988
989 return ret;
990}
991#endif /*DISABLE_FLOAT_API*/
992#else
993int celt_decode(CELTDecoder * restrict st, unsigned char *data, int len, celt_int16_t * restrict pcm)
994{
995 int j, ret;
996 VARDECL(celt_sig_t, out);
997 const int C = CHANNELS(st->mode);
998 const int N = st->block_size;
999
1000 ALLOC(out, C*N, celt_sig_t);
1001
1002 ret=celt_decode_float(st, data, len, out);
1003
1004 for (j=0;j<C*N;j++)
1005 pcm[j] = FLOAT2INT16 (out[j]);
1006
1007 return ret;
1008}
1009#endif