blob: 2c9f4ef8d323e8aad8e1c8d7c9d9c9447ca0397e [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 Copyright (c) 2008 Gregory Maxwell
4 Written by Jean-Marc Valin and Gregory Maxwell */
Jean-Marc Valin8ebd3452007-11-29 20:17:32 +11005/*
6 Redistribution and use in source and binary forms, with or without
7 modification, are permitted provided that the following conditions
8 are met:
9
10 - Redistributions of source code must retain the above copyright
11 notice, this list of conditions and the following disclaimer.
12
13 - Redistributions in binary form must reproduce the above copyright
14 notice, this list of conditions and the following disclaimer in the
15 documentation and/or other materials provided with the distribution.
16
17 - Neither the name of the Xiph.org Foundation nor the names of its
18 contributors may be used to endorse or promote products derived from
19 this software without specific prior written permission.
20
21 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22 ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23 LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
24 A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR
25 CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
26 EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
27 PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
28 PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
29 LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
30 NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
31 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32*/
33
Jean-Marc Valin02fa9132008-02-20 12:09:29 +110034#ifdef HAVE_CONFIG_H
35#include "config.h"
36#endif
37
Jean-Marc Valin8600f692008-02-29 15:14:12 +110038#define CELT_C
39
Jean-Marc Valin8ebd3452007-11-29 20:17:32 +110040#include "os_support.h"
Jean-Marc Valinf02ba112007-11-30 01:10:42 +110041#include "mdct.h"
42#include <math.h>
Jean-Marc Valin013c31d2007-11-30 11:36:46 +110043#include "celt.h"
Jean-Marc Valin14191b32007-11-30 12:15:49 +110044#include "pitch.h"
Jean-Marc Valin7351e282008-02-08 15:09:45 +110045#include "kiss_fftr.h"
Jean-Marc Valin991c0f02007-11-30 16:07:46 +110046#include "bands.h"
Jean-Marc Valinecb36a32007-12-05 01:31:49 +110047#include "modes.h"
Jean-Marc Valin6238bc02008-01-28 22:28:54 +110048#include "entcode.h"
Jean-Marc Valin98d2a492007-12-07 22:46:47 +110049#include "quant_bands.h"
Jean-Marc Valin46014ca2007-12-14 13:47:04 +110050#include "psy.h"
Jean-Marc Valin4fbd18d2008-01-17 14:07:55 +110051#include "rate.h"
Jean-Marc Valinc7e0b762008-03-16 07:55:29 +110052#include "stack_alloc.h"
Jean-Marc Valine4aeb472008-06-29 12:06:05 +100053#include "mathops.h"
Jean-Marc Valind9b95652008-08-31 23:34:47 -040054#include "float_cast.h"
Jean-Marc Valinb6f90612008-10-05 22:39:13 -040055#include <stdarg.h>
Jean-Marc Valin013c31d2007-11-30 11:36:46 +110056
Jean-Marc Valin234969c2009-10-17 22:12:42 -040057static const celt_word16 preemph = QCONST16(0.8f,15);
Jean-Marc Valin07586892008-03-03 17:19:17 +110058
Jean-Marc Valin528f4b82008-06-29 03:46:39 +100059#ifdef FIXED_POINT
Jean-Marc Valin234969c2009-10-17 22:12:42 -040060static const celt_word16 transientWindow[16] = {
Jean-Marc Valin528f4b82008-06-29 03:46:39 +100061 279, 1106, 2454, 4276, 6510, 9081, 11900, 14872,
62 17896, 20868, 23687, 26258, 28492, 30314, 31662, 32489};
63#else
64static const float transientWindow[16] = {
Jean-Marc Valin56522ad2009-06-05 17:17:25 -040065 0.0085135, 0.0337639, 0.0748914, 0.1304955,
66 0.1986827, 0.2771308, 0.3631685, 0.4538658,
67 0.5461342, 0.6368315, 0.7228692, 0.8013173,
68 0.8695045, 0.9251086, 0.9662361, 0.9914865};
Jean-Marc Valin528f4b82008-06-29 03:46:39 +100069#endif
70
Gregory Maxwell17169992009-06-04 15:15:34 -040071#define ENCODERVALID 0x4c434554
72#define ENCODERPARTIAL 0x5445434c
73#define ENCODERFREED 0x4c004500
Jean-Marc Valinc9943942008-08-30 00:55:07 -040074
Jean-Marc Valin276de722008-02-20 17:45:51 +110075/** Encoder state
76 @brief Encoder state
77 */
Jean-Marc Valin269d40a2007-12-07 11:29:45 +110078struct CELTEncoder {
Jean-Marc Valin30f7f812009-10-17 14:35:13 -040079 celt_uint32 marker;
Jean-Marc Valin276de722008-02-20 17:45:51 +110080 const CELTMode *mode; /**< Mode used by the encoder */
Jean-Marc Valin8ebd3452007-11-29 20:17:32 +110081 int frame_size;
82 int block_size;
Jean-Marc Valina5431bf2008-01-03 20:53:01 +110083 int overlap;
Jean-Marc Valinffa13472007-12-10 16:54:17 +110084 int channels;
85
Gregory Maxwell2dd3d322009-06-05 14:05:51 -040086 int pitch_enabled; /* Complexity level is allowed to use pitch */
87 int pitch_permitted; /* Use of the LTP is permitted by the user */
88 int pitch_available; /* Amount of pitch buffer available */
89 int force_intra;
Jean-Marc Valin74f4e9f2009-05-02 09:57:50 -040090 int delayedIntra;
Jean-Marc Valin234969c2009-10-17 22:12:42 -040091 celt_word16 tonal_average;
Jean-Marc Valin527db5c2009-06-02 07:56:19 -040092 int fold_decision;
Jean-Marc Valin234969c2009-10-17 22:12:42 -040093 celt_word16 gain_prod;
Jean-Marc Valin527db5c2009-06-02 07:56:19 -040094
Jean-Marc Valinbd5d54a2009-10-20 00:25:31 -040095 /* VBR-related parameters */
96 celt_int32 vbr_reservoir;
97 celt_int32 vbr_drift;
98 celt_int32 vbr_offset;
99 celt_int32 vbr_count;
100
101 celt_int32 vbr_rate; /* Target number of 16th bits per frame */
Jean-Marc Valin234969c2009-10-17 22:12:42 -0400102 celt_word16 * restrict preemph_memE;
103 celt_sig * restrict preemph_memD;
Jean-Marc Valin81b38c22008-02-29 21:08:49 +1100104
Jean-Marc Valin234969c2009-10-17 22:12:42 -0400105 celt_sig *in_mem;
106 celt_sig *out_mem;
Jean-Marc Valin991c0f02007-11-30 16:07:46 +1100107
Jean-Marc Valin234969c2009-10-17 22:12:42 -0400108 celt_word16 *oldBandE;
Jean-Marc Valinc6ca4992008-06-01 23:19:16 +1000109#ifdef EXP_PSY
Jean-Marc Valin234969c2009-10-17 22:12:42 -0400110 celt_word16 *psy_mem;
Jean-Marc Valinc6ca4992008-06-01 23:19:16 +1000111 struct PsyDecay psy;
112#endif
Jean-Marc Valin8ebd3452007-11-29 20:17:32 +1100113};
114
Jean-Marc Valine12017e2009-10-03 13:57:31 -0400115static int check_encoder(const CELTEncoder *st)
Gregory Maxwell17169992009-06-04 15:15:34 -0400116{
117 if (st==NULL)
118 {
119 celt_warning("NULL passed as an encoder structure");
120 return CELT_INVALID_STATE;
121 }
122 if (st->marker == ENCODERVALID)
123 return CELT_OK;
124 if (st->marker == ENCODERFREED)
125 celt_warning("Referencing an encoder that has already been freed");
126 else
127 celt_warning("This is not a valid CELT encoder structure");
128 return CELT_INVALID_STATE;
129}
130
Jean-Marc Valin80ed1472009-10-15 21:45:32 -0400131CELTEncoder *celt_encoder_create(const CELTMode *mode, int channels, int *error)
Jean-Marc Valin8ebd3452007-11-29 20:17:32 +1100132{
Jean-Marc Valinb886ddc2008-03-25 14:38:55 +1100133 int N, C;
Jean-Marc Valin02fa9132008-02-20 12:09:29 +1100134 CELTEncoder *st;
Jean-Marc Valin44ffd5a2008-02-22 00:39:25 +1100135
136 if (check_mode(mode) != CELT_OK)
Jean-Marc Valinece94a02009-10-16 07:30:14 -0400137 {
138 if (error)
139 *error = CELT_INVALID_MODE;
Jean-Marc Valin44ffd5a2008-02-22 00:39:25 +1100140 return NULL;
Jean-Marc Valinece94a02009-10-16 07:30:14 -0400141 }
Jean-Marc Valinbd5d54a2009-10-20 00:25:31 -0400142#ifdef DISABLE_STEREO
143 if (channels > 1)
144 {
145 celt_warning("Stereo support was disable from this build");
146 if (error)
147 *error = CELT_BAD_ARG;
148 return NULL;
149 }
150#endif
151
Jean-Marc Valin80ed1472009-10-15 21:45:32 -0400152 if (channels < 0 || channels > 2)
153 {
154 celt_warning("Only mono and stereo supported");
155 if (error)
156 *error = CELT_BAD_ARG;
157 return NULL;
158 }
Jean-Marc Valin44ffd5a2008-02-22 00:39:25 +1100159
Jean-Marc Valin73e51b32007-12-05 17:48:24 +1100160 N = mode->mdctSize;
Jean-Marc Valin80ed1472009-10-15 21:45:32 -0400161 C = channels;
Jean-Marc Valin02fa9132008-02-20 12:09:29 +1100162 st = celt_alloc(sizeof(CELTEncoder));
Jean-Marc Valin8ebd3452007-11-29 20:17:32 +1100163
Jean-Marc Valinece94a02009-10-16 07:30:14 -0400164 if (st==NULL)
165 {
166 if (error)
167 *error = CELT_ALLOC_FAIL;
Jean-Marc Valin80ed1472009-10-15 21:45:32 -0400168 return NULL;
Jean-Marc Valinece94a02009-10-16 07:30:14 -0400169 }
Gregory Maxwell17169992009-06-04 15:15:34 -0400170 st->marker = ENCODERPARTIAL;
Jean-Marc Valin73e51b32007-12-05 17:48:24 +1100171 st->mode = mode;
Jean-Marc Valinb886ddc2008-03-25 14:38:55 +1100172 st->frame_size = N;
Jean-Marc Valin73e51b32007-12-05 17:48:24 +1100173 st->block_size = N;
Jean-Marc Valina5431bf2008-01-03 20:53:01 +1100174 st->overlap = mode->overlap;
Jean-Marc Valin80ed1472009-10-15 21:45:32 -0400175 st->channels = channels;
Jean-Marc Valina5431bf2008-01-03 20:53:01 +1100176
Jean-Marc Valinbd5d54a2009-10-20 00:25:31 -0400177 st->vbr_rate = 0;
Jean-Marc Valinc9943942008-08-30 00:55:07 -0400178 st->pitch_enabled = 1;
Gregory Maxwell2dd3d322009-06-05 14:05:51 -0400179 st->pitch_permitted = 1;
Gregory Maxwell98046ca2008-12-13 20:42:03 -0500180 st->pitch_available = 1;
Gregory Maxwell2dd3d322009-06-05 14:05:51 -0400181 st->force_intra = 0;
Gregory Maxwell8842fde2009-05-04 15:58:40 -0400182 st->delayedIntra = 1;
Jean-Marc Valin527db5c2009-06-02 07:56:19 -0400183 st->tonal_average = QCONST16(1.,8);
184 st->fold_decision = 1;
Jean-Marc Valina76a0b22008-01-17 22:43:05 +1100185
Jean-Marc Valin234969c2009-10-17 22:12:42 -0400186 st->in_mem = celt_alloc(st->overlap*C*sizeof(celt_sig));
187 st->out_mem = celt_alloc((MAX_PERIOD+st->overlap)*C*sizeof(celt_sig));
Jean-Marc Valin81b38c22008-02-29 21:08:49 +1100188
Jean-Marc Valin234969c2009-10-17 22:12:42 -0400189 st->oldBandE = (celt_word16*)celt_alloc(C*mode->nbEBands*sizeof(celt_word16));
Jean-Marc Valinfa248732007-12-06 07:51:27 +1100190
Jean-Marc Valin234969c2009-10-17 22:12:42 -0400191 st->preemph_memE = (celt_word16*)celt_alloc(C*sizeof(celt_word16));
192 st->preemph_memD = (celt_sig*)celt_alloc(C*sizeof(celt_sig));
Jean-Marc Valinffa13472007-12-10 16:54:17 +1100193
Jean-Marc Valinc6ca4992008-06-01 23:19:16 +1000194#ifdef EXP_PSY
Jean-Marc Valin234969c2009-10-17 22:12:42 -0400195 st->psy_mem = celt_alloc(MAX_PERIOD*sizeof(celt_word16));
Jean-Marc Valinc6ca4992008-06-01 23:19:16 +1000196 psydecay_init(&st->psy, MAX_PERIOD/2, st->mode->Fs);
197#endif
198
Gregory Maxwell17169992009-06-04 15:15:34 -0400199 if ((st->in_mem!=NULL) && (st->out_mem!=NULL) && (st->oldBandE!=NULL)
200#ifdef EXP_PSY
201 && (st->psy_mem!=NULL)
202#endif
203 && (st->preemph_memE!=NULL) && (st->preemph_memD!=NULL))
204 {
Jean-Marc Valinece94a02009-10-16 07:30:14 -0400205 if (error)
206 *error = CELT_OK;
Gregory Maxwell17169992009-06-04 15:15:34 -0400207 st->marker = ENCODERVALID;
208 return st;
209 }
210 /* If the setup fails for some reason deallocate it. */
211 celt_encoder_destroy(st);
Jean-Marc Valinece94a02009-10-16 07:30:14 -0400212 if (error)
213 *error = CELT_ALLOC_FAIL;
Gregory Maxwell17169992009-06-04 15:15:34 -0400214 return NULL;
Jean-Marc Valin8ebd3452007-11-29 20:17:32 +1100215}
216
Peter Kirk19f9dc92008-06-06 14:38:38 +0200217void celt_encoder_destroy(CELTEncoder *st)
Jean-Marc Valin14191b32007-11-30 12:15:49 +1100218{
219 if (st == NULL)
220 {
221 celt_warning("NULL passed to celt_encoder_destroy");
222 return;
223 }
Jean-Marc Valin44ffd5a2008-02-22 00:39:25 +1100224
Gregory Maxwell17169992009-06-04 15:15:34 -0400225 if (st->marker == ENCODERFREED)
226 {
Gregory Maxwell17169992009-06-04 15:15:34 -0400227 celt_warning("Freeing an encoder which has already been freed");
Gregory Maxwelldc67fa92009-06-04 17:17:35 -0400228 return;
Gregory Maxwell17169992009-06-04 15:15:34 -0400229 }
230
231 if (st->marker != ENCODERVALID && st->marker != ENCODERPARTIAL)
232 {
233 celt_warning("This is not a valid CELT encoder structure");
234 return;
235 }
236 /*Check_mode is non-fatal here because we can still free
237 the encoder memory even if the mode is bad, although calling
238 the free functions in this order is a violation of the API.*/
239 check_mode(st->mode);
240
Jean-Marc Valin14191b32007-11-30 12:15:49 +1100241 celt_free(st->in_mem);
Jean-Marc Valin14191b32007-11-30 12:15:49 +1100242 celt_free(st->out_mem);
Jean-Marc Valin991c0f02007-11-30 16:07:46 +1100243
Jean-Marc Valinc245a222007-12-06 19:14:20 +1100244 celt_free(st->oldBandE);
Jean-Marc Valin7351e282008-02-08 15:09:45 +1100245
246 celt_free(st->preemph_memE);
247 celt_free(st->preemph_memD);
248
Jean-Marc Valinc6ca4992008-06-01 23:19:16 +1000249#ifdef EXP_PSY
250 celt_free (st->psy_mem);
251 psydecay_clear(&st->psy);
252#endif
Gregory Maxwell17169992009-06-04 15:15:34 -0400253 st->marker = ENCODERFREED;
Jean-Marc Valinc6ca4992008-06-01 23:19:16 +1000254
Jean-Marc Valin14191b32007-11-30 12:15:49 +1100255 celt_free(st);
256}
257
Jean-Marc Valin30f7f812009-10-17 14:35:13 -0400258static inline celt_int16 FLOAT2INT16(float x)
Jean-Marc Valin42074382008-02-27 11:08:53 +1100259{
Gregory Maxwell0ac2b2f2009-05-21 23:08:46 -0400260 x = x*CELT_SIG_SCALE;
Gregory Maxwell5f2a74b2008-08-11 23:50:07 -0400261 x = MAX32(x, -32768);
262 x = MIN32(x, 32767);
Jean-Marc Valin30f7f812009-10-17 14:35:13 -0400263 return (celt_int16)float2int(x);
Gregory Maxwell5f2a74b2008-08-11 23:50:07 -0400264}
265
Jean-Marc Valin234969c2009-10-17 22:12:42 -0400266static inline celt_word16 SIG2WORD16(celt_sig x)
Gregory Maxwell5f2a74b2008-08-11 23:50:07 -0400267{
268#ifdef FIXED_POINT
Jean-Marc Valin42074382008-02-27 11:08:53 +1100269 x = PSHR32(x, SIG_SHIFT);
Jean-Marc Valinabdfc382008-04-18 15:57:18 +1000270 x = MAX32(x, -32768);
271 x = MIN32(x, 32767);
Jean-Marc Valin42074382008-02-27 11:08:53 +1100272 return EXTRACT16(x);
273#else
Jean-Marc Valin234969c2009-10-17 22:12:42 -0400274 return (celt_word16)x;
Jean-Marc Valin42074382008-02-27 11:08:53 +1100275#endif
276}
277
Jean-Marc Valin234969c2009-10-17 22:12:42 -0400278static int transient_analysis(celt_word32 *in, int len, int C, int *transient_time, int *transient_shift)
Jean-Marc Valin9375aa42008-06-27 07:57:35 +1000279{
280 int c, i, n;
Jean-Marc Valin234969c2009-10-17 22:12:42 -0400281 celt_word32 ratio;
282 VARDECL(celt_word32, begin);
Jean-Marc Valin0ceccb22008-07-03 20:41:06 -0400283 SAVE_STACK;
Jean-Marc Valin234969c2009-10-17 22:12:42 -0400284 ALLOC(begin, len, celt_word32);
Jean-Marc Valin9375aa42008-06-27 07:57:35 +1000285 for (i=0;i<len;i++)
Jean-Marc Valin5c3bc672008-08-28 23:34:24 -0400286 begin[i] = ABS32(SHR32(in[C*i],SIG_SHIFT));
Jean-Marc Valin9375aa42008-06-27 07:57:35 +1000287 for (c=1;c<C;c++)
288 {
289 for (i=0;i<len;i++)
Jean-Marc Valin5c3bc672008-08-28 23:34:24 -0400290 begin[i] = MAX32(begin[i], ABS32(SHR32(in[C*i+c],SIG_SHIFT)));
Jean-Marc Valin9375aa42008-06-27 07:57:35 +1000291 }
Jean-Marc Valin9375aa42008-06-27 07:57:35 +1000292 for (i=1;i<len;i++)
Jean-Marc Valinbd7de0a2008-07-06 10:57:26 -0400293 begin[i] = MAX32(begin[i-1],begin[i]);
Jean-Marc Valin9375aa42008-06-27 07:57:35 +1000294 n = -1;
295 for (i=8;i<len-8;i++)
296 {
Jean-Marc Valinbd7de0a2008-07-06 10:57:26 -0400297 if (begin[i] < MULT16_32_Q15(QCONST16(.2f,15),begin[len-1]))
298 n=i;
Jean-Marc Valin9375aa42008-06-27 07:57:35 +1000299 }
Jean-Marc Valin9375aa42008-06-27 07:57:35 +1000300 if (n<32)
301 {
302 n = -1;
303 ratio = 0;
Jean-Marc Valinbd7de0a2008-07-06 10:57:26 -0400304 } else {
305 ratio = DIV32(begin[len-1],1+begin[n-16]);
Jean-Marc Valin9375aa42008-06-27 07:57:35 +1000306 }
Jean-Marc Valinf4578192008-07-04 16:47:28 -0400307 if (ratio < 0)
308 ratio = 0;
309 if (ratio > 1000)
310 ratio = 1000;
Jean-Marc Valinbd7de0a2008-07-06 10:57:26 -0400311 ratio *= ratio;
Jean-Marc Valinaa936252009-05-29 22:14:20 -0400312
313 if (ratio > 2048)
Jean-Marc Valinbd7de0a2008-07-06 10:57:26 -0400314 *transient_shift = 3;
Jean-Marc Valinaa936252009-05-29 22:14:20 -0400315 else
316 *transient_shift = 0;
317
Jean-Marc Valinbd7de0a2008-07-06 10:57:26 -0400318 *transient_time = n;
319
Jean-Marc Valin0ceccb22008-07-03 20:41:06 -0400320 RESTORE_STACK;
Jean-Marc Valinbd7de0a2008-07-06 10:57:26 -0400321 return ratio > 20;
Jean-Marc Valin9375aa42008-06-27 07:57:35 +1000322}
323
Jean-Marc Valin56522ad2009-06-05 17:17:25 -0400324/** Apply window and compute the MDCT for all sub-frames and
325 all channels in a frame */
Jean-Marc Valin234969c2009-10-17 22:12:42 -0400326static void compute_mdcts(const CELTMode *mode, int shortBlocks, celt_sig * restrict in, celt_sig * restrict out, int _C)
Jean-Marc Valinda721882007-11-30 15:17:42 +1100327{
Jean-Marc Valinbf2398b2009-10-15 07:28:19 -0400328 const int C = CHANNELS(_C);
Jean-Marc Valin9d1decd2008-06-17 13:28:13 +1000329 if (C==1 && !shortBlocks)
Jean-Marc Valinda721882007-11-30 15:17:42 +1100330 {
Jean-Marc Valin9d1decd2008-06-17 13:28:13 +1000331 const mdct_lookup *lookup = MDCT(mode);
332 const int overlap = OVERLAP(mode);
333 mdct_forward(lookup, in, out, mode->window, overlap);
Jean-Marc Valinaa4f58b2009-10-03 09:27:59 -0400334 } else {
Jean-Marc Valin9d1decd2008-06-17 13:28:13 +1000335 const mdct_lookup *lookup = MDCT(mode);
336 const int overlap = OVERLAP(mode);
Jean-Marc Valinaa4f58b2009-10-03 09:27:59 -0400337 int N = FRAMESIZE(mode);
338 int B = 1;
Jean-Marc Valin9d1decd2008-06-17 13:28:13 +1000339 int b, c;
Jean-Marc Valin234969c2009-10-17 22:12:42 -0400340 VARDECL(celt_word32, x);
341 VARDECL(celt_word32, tmp);
Jean-Marc Valin9d1decd2008-06-17 13:28:13 +1000342 SAVE_STACK;
Jean-Marc Valinaa4f58b2009-10-03 09:27:59 -0400343 if (shortBlocks)
344 {
345 lookup = &mode->shortMdct;
346 N = mode->shortMdctSize;
347 B = mode->nbShortMdcts;
348 }
Jean-Marc Valin234969c2009-10-17 22:12:42 -0400349 ALLOC(x, N+overlap, celt_word32);
350 ALLOC(tmp, N, celt_word32);
Jean-Marc Valin9d1decd2008-06-17 13:28:13 +1000351 for (c=0;c<C;c++)
352 {
Jean-Marc Valin9d1decd2008-06-17 13:28:13 +1000353 for (b=0;b<B;b++)
354 {
355 int j;
356 for (j=0;j<N+overlap;j++)
357 x[j] = in[C*(b*N+j)+c];
358 mdct_forward(lookup, x, tmp, mode->window, overlap);
359 /* Interleaving the sub-frames */
360 for (j=0;j<N;j++)
Jean-Marc Valin08a82ff2009-06-14 14:05:19 -0400361 out[(j*B+b)+c*N*B] = tmp[j];
Jean-Marc Valin9d1decd2008-06-17 13:28:13 +1000362 }
363 }
364 RESTORE_STACK;
Jean-Marc Valinda721882007-11-30 15:17:42 +1100365 }
Jean-Marc Valinda721882007-11-30 15:17:42 +1100366}
367
Jean-Marc Valin56522ad2009-06-05 17:17:25 -0400368/** Compute the IMDCT and apply window for all sub-frames and
369 all channels in a frame */
Jean-Marc Valin234969c2009-10-17 22:12:42 -0400370static void compute_inv_mdcts(const CELTMode *mode, int shortBlocks, celt_sig *X, int transient_time, int transient_shift, celt_sig * restrict out_mem, int _C)
Jean-Marc Valin1677aa92007-12-08 01:13:34 +1100371{
Jean-Marc Valinb886ddc2008-03-25 14:38:55 +1100372 int c, N4;
Jean-Marc Valinbf2398b2009-10-15 07:28:19 -0400373 const int C = CHANNELS(_C);
Jean-Marc Valinb18ec0b2008-04-11 04:07:52 +1000374 const int N = FRAMESIZE(mode);
375 const int overlap = OVERLAP(mode);
Jean-Marc Valina536f772008-03-22 09:01:50 +1100376 N4 = (N-overlap)>>1;
Jean-Marc Valinffa13472007-12-10 16:54:17 +1100377 for (c=0;c<C;c++)
Jean-Marc Valin1677aa92007-12-08 01:13:34 +1100378 {
Jean-Marc Valinb886ddc2008-03-25 14:38:55 +1100379 int j;
Jean-Marc Valin528f4b82008-06-29 03:46:39 +1000380 if (transient_shift==0 && C==1 && !shortBlocks) {
Jean-Marc Valin9d1decd2008-06-17 13:28:13 +1000381 const mdct_lookup *lookup = MDCT(mode);
382 mdct_backward(lookup, X, out_mem+C*(MAX_PERIOD-N-N4), mode->window, overlap);
Jean-Marc Valin9d1decd2008-06-17 13:28:13 +1000383 } else {
Jean-Marc Valin234969c2009-10-17 22:12:42 -0400384 VARDECL(celt_word32, x);
385 VARDECL(celt_word32, tmp);
Jean-Marc Valinde678582009-10-03 10:36:27 -0400386 int b;
387 int N2 = N;
388 int B = 1;
389 int n4offset=0;
390 const mdct_lookup *lookup = MDCT(mode);
Jean-Marc Valin9d1decd2008-06-17 13:28:13 +1000391 SAVE_STACK;
Jean-Marc Valinde678582009-10-03 10:36:27 -0400392
Jean-Marc Valin234969c2009-10-17 22:12:42 -0400393 ALLOC(x, 2*N, celt_word32);
394 ALLOC(tmp, N, celt_word32);
Jean-Marc Valinde678582009-10-03 10:36:27 -0400395
396 if (shortBlocks)
397 {
398 lookup = &mode->shortMdct;
399 N2 = mode->shortMdctSize;
400 B = mode->nbShortMdcts;
401 n4offset = N4;
402 }
Jean-Marc Valin9d1decd2008-06-17 13:28:13 +1000403 /* Prevents problems from the imdct doing the overlap-add */
Gregory Maxwell23e654f2008-09-27 16:20:03 -0400404 CELT_MEMSET(x+N4, 0, N2);
Jean-Marc Valinde678582009-10-03 10:36:27 -0400405
Jean-Marc Valin9d1decd2008-06-17 13:28:13 +1000406 for (b=0;b<B;b++)
407 {
408 /* De-interleaving the sub-frames */
409 for (j=0;j<N2;j++)
Jean-Marc Valin08a82ff2009-06-14 14:05:19 -0400410 tmp[j] = X[(j*B+b)+c*N2*B];
Jean-Marc Valinde678582009-10-03 10:36:27 -0400411 mdct_backward(lookup, tmp, x+n4offset+N2*b, mode->window, overlap);
Jean-Marc Valin9d1decd2008-06-17 13:28:13 +1000412 }
Jean-Marc Valinde678582009-10-03 10:36:27 -0400413
Jean-Marc Valin528f4b82008-06-29 03:46:39 +1000414 if (transient_shift > 0)
Jean-Marc Valin12b22482008-06-16 14:13:05 +1000415 {
Jean-Marc Valin528f4b82008-06-29 03:46:39 +1000416#ifdef FIXED_POINT
Jean-Marc Valin12b22482008-06-16 14:13:05 +1000417 for (j=0;j<16;j++)
Jean-Marc Valin528f4b82008-06-29 03:46:39 +1000418 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 +1000419 for (j=transient_time;j<N+overlap;j++)
Jean-Marc Valin528f4b82008-06-29 03:46:39 +1000420 x[N4+j] = SHL32(x[N4+j], transient_shift);
421#else
422 for (j=0;j<16;j++)
Jean-Marc Valine4aeb472008-06-29 12:06:05 +1000423 x[N4+transient_time+j-16] *= 1+transientWindow[j]*((1<<transient_shift)-1);
Jean-Marc Valin528f4b82008-06-29 03:46:39 +1000424 for (j=transient_time;j<N+overlap;j++)
425 x[N4+j] *= 1<<transient_shift;
426#endif
Jean-Marc Valin12b22482008-06-16 14:13:05 +1000427 }
Jean-Marc Valin56522ad2009-06-05 17:17:25 -0400428 /* The first and last part would need to be set to zero
429 if we actually wanted to use them. */
Jean-Marc Valin8ddd7f42008-04-22 13:37:16 +1000430 for (j=0;j<overlap;j++)
431 out_mem[C*(MAX_PERIOD-N)+C*j+c] += x[j+N4];
432 for (j=0;j<overlap;j++)
433 out_mem[C*(MAX_PERIOD)+C*(overlap-j-1)+c] = x[2*N-j-N4-1];
434 for (j=0;j<2*N4;j++)
435 out_mem[C*(MAX_PERIOD-N)+C*(j+overlap)+c] = x[j+N4+overlap];
436 RESTORE_STACK;
437 }
Jean-Marc Valin1677aa92007-12-08 01:13:34 +1100438 }
439}
440
Jean-Marc Valin05ed03e2009-04-29 07:44:13 -0400441#define FLAG_NONE 0
Jean-Marc Valin5a700972009-08-08 13:23:03 -0400442#define FLAG_INTRA (1U<<13)
443#define FLAG_PITCH (1U<<12)
444#define FLAG_SHORT (1U<<11)
445#define FLAG_FOLD (1U<<10)
Jean-Marc Valin05ed03e2009-04-29 07:44:13 -0400446#define FLAG_MASK (FLAG_INTRA|FLAG_PITCH|FLAG_SHORT|FLAG_FOLD)
447
Jean-Marc Valine12017e2009-10-03 13:57:31 -0400448static const int flaglist[8] = {
Jean-Marc Valina8be38a2009-04-29 22:16:26 -0400449 0 /*00 */ | FLAG_FOLD,
450 1 /*01 */ | FLAG_PITCH|FLAG_FOLD,
451 8 /*1000*/ | FLAG_NONE,
452 9 /*1001*/ | FLAG_SHORT|FLAG_FOLD,
453 10 /*1010*/ | FLAG_PITCH,
454 11 /*1011*/ | FLAG_INTRA,
455 6 /*110 */ | FLAG_INTRA|FLAG_FOLD,
456 7 /*111 */ | FLAG_INTRA|FLAG_SHORT|FLAG_FOLD
Jean-Marc Valin05ed03e2009-04-29 07:44:13 -0400457};
458
Jean-Marc Valine12017e2009-10-03 13:57:31 -0400459static void encode_flags(ec_enc *enc, int intra_ener, int has_pitch, int shortBlocks, int has_fold)
Jean-Marc Valin05ed03e2009-04-29 07:44:13 -0400460{
461 int i;
462 int flags=FLAG_NONE;
463 int flag_bits;
464 flags |= intra_ener ? FLAG_INTRA : 0;
465 flags |= has_pitch ? FLAG_PITCH : 0;
466 flags |= shortBlocks ? FLAG_SHORT : 0;
467 flags |= has_fold ? FLAG_FOLD : 0;
468 for (i=0;i<8;i++)
469 if (flags == (flaglist[i]&FLAG_MASK))
470 break;
471 celt_assert(i<8);
472 flag_bits = flaglist[i]&0xf;
473 /*printf ("enc %d: %d %d %d %d\n", flag_bits, intra_ener, has_pitch, shortBlocks, has_fold);*/
474 if (i<2)
Jean-Marc Valinc08be442009-06-17 23:23:46 -0400475 ec_enc_uint(enc, flag_bits, 4);
Jean-Marc Valin05ed03e2009-04-29 07:44:13 -0400476 else if (i<6)
Jean-Marc Valinc08be442009-06-17 23:23:46 -0400477 ec_enc_uint(enc, flag_bits, 16);
Jean-Marc Valin05ed03e2009-04-29 07:44:13 -0400478 else
Jean-Marc Valinc08be442009-06-17 23:23:46 -0400479 ec_enc_uint(enc, flag_bits, 8);
Jean-Marc Valin05ed03e2009-04-29 07:44:13 -0400480}
481
Jean-Marc Valine12017e2009-10-03 13:57:31 -0400482static void decode_flags(ec_dec *dec, int *intra_ener, int *has_pitch, int *shortBlocks, int *has_fold)
Jean-Marc Valin05ed03e2009-04-29 07:44:13 -0400483{
484 int i;
485 int flag_bits;
Jean-Marc Valinc08be442009-06-17 23:23:46 -0400486 flag_bits = ec_dec_uint(dec, 4);
Jean-Marc Valin05ed03e2009-04-29 07:44:13 -0400487 /*printf ("(%d) ", flag_bits);*/
488 if (flag_bits==2)
Jean-Marc Valinc08be442009-06-17 23:23:46 -0400489 flag_bits = (flag_bits<<2) | ec_dec_uint(dec, 4);
Jean-Marc Valin05ed03e2009-04-29 07:44:13 -0400490 else if (flag_bits==3)
Jean-Marc Valinc08be442009-06-17 23:23:46 -0400491 flag_bits = (flag_bits<<1) | ec_dec_uint(dec, 2);
Jean-Marc Valin05ed03e2009-04-29 07:44:13 -0400492 for (i=0;i<8;i++)
493 if (flag_bits == (flaglist[i]&0xf))
494 break;
495 celt_assert(i<8);
496 *intra_ener = (flaglist[i]&FLAG_INTRA) != 0;
497 *has_pitch = (flaglist[i]&FLAG_PITCH) != 0;
498 *shortBlocks = (flaglist[i]&FLAG_SHORT) != 0;
499 *has_fold = (flaglist[i]&FLAG_FOLD ) != 0;
500 /*printf ("dec %d: %d %d %d %d\n", flag_bits, *intra_ener, *has_pitch, *shortBlocks, *has_fold);*/
501}
502
Jean-Marc Valin234969c2009-10-17 22:12:42 -0400503static void deemphasis(celt_sig *in, celt_word16 *pcm, int N, int _C, celt_word16 coef, celt_sig *mem)
Jean-Marc Valine12017e2009-10-03 13:57:31 -0400504{
Jean-Marc Valinbf2398b2009-10-15 07:28:19 -0400505 const int C = CHANNELS(_C);
Jean-Marc Valine12017e2009-10-03 13:57:31 -0400506 int c;
507 for (c=0;c<C;c++)
508 {
509 int j;
510 for (j=0;j<N;j++)
511 {
Jean-Marc Valin234969c2009-10-17 22:12:42 -0400512 celt_sig tmp = MAC16_32_Q15(in[C*(MAX_PERIOD-N)+C*j+c],
Jean-Marc Valine12017e2009-10-03 13:57:31 -0400513 coef,mem[c]);
514 mem[c] = tmp;
515 pcm[C*j+c] = SCALEOUT(SIG2WORD16(tmp));
516 }
517 }
518
519}
520
Jean-Marc Valin234969c2009-10-17 22:12:42 -0400521static void mdct_shape(const CELTMode *mode, celt_norm *X, int start, int end, int N, int nbShortMdcts, int mdct_weight_shift, int _C)
Jean-Marc Valin88619552009-10-04 21:35:36 -0400522{
523 int m, i, c;
Jean-Marc Valinbf2398b2009-10-15 07:28:19 -0400524 const int C = CHANNELS(_C);
Jean-Marc Valin88619552009-10-04 21:35:36 -0400525 for (c=0;c<C;c++)
526 for (m=start;m<end;m++)
527 for (i=m+c*N;i<(c+1)*N;i+=nbShortMdcts)
528#ifdef FIXED_POINT
529 X[i] = SHR16(X[i], mdct_weight_shift);
530#else
531 X[i] = (1.f/(1<<mdct_weight_shift))*X[i];
532#endif
Jean-Marc Valinbf2398b2009-10-15 07:28:19 -0400533 renormalise_bands(mode, X, C);
Jean-Marc Valin88619552009-10-04 21:35:36 -0400534}
535
536
Gregory Maxwell5f2a74b2008-08-11 23:50:07 -0400537#ifdef FIXED_POINT
Jean-Marc Valin30f7f812009-10-17 14:35:13 -0400538int celt_encode(CELTEncoder * restrict st, const celt_int16 * pcm, celt_int16 * optional_synthesis, unsigned char *compressed, int nbCompressedBytes)
Jean-Marc Valin8ebd3452007-11-29 20:17:32 +1100539{
Gregory Maxwell5f2a74b2008-08-11 23:50:07 -0400540#else
Jean-Marc Valin234969c2009-10-17 22:12:42 -0400541int celt_encode_float(CELTEncoder * restrict st, const celt_sig * pcm, celt_sig * optional_synthesis, unsigned char *compressed, int nbCompressedBytes)
Gregory Maxwell5f2a74b2008-08-11 23:50:07 -0400542{
543#endif
Jean-Marc Valin88619552009-10-04 21:35:36 -0400544 int i, c, N, NN, N4;
Jean-Marc Valin7e8a4872008-02-11 16:55:34 +1100545 int has_pitch;
Jean-Marc Valin0bb05bc2008-02-20 13:43:40 +1100546 int pitch_index;
Jean-Marc Valinc890b582008-08-01 22:26:49 -0400547 int bits;
Jean-Marc Valinbc799912008-11-07 22:53:13 -0500548 int has_fold=1;
Gregory Maxwell888d8ce2009-05-21 04:21:53 -0400549 unsigned coarse_needed;
Jean-Marc Valin8679a802008-10-18 07:44:35 -0400550 ec_byte_buffer buf;
551 ec_enc enc;
Jean-Marc Valin234969c2009-10-17 22:12:42 -0400552 VARDECL(celt_sig, in);
553 VARDECL(celt_sig, freq);
554 VARDECL(celt_sig, pitch_freq);
555 VARDECL(celt_norm, X);
556 VARDECL(celt_ener, bandE);
557 VARDECL(celt_word16, bandLogE);
Jean-Marc Valin6775de32008-08-02 08:14:42 -0400558 VARDECL(int, fine_quant);
Jean-Marc Valin234969c2009-10-17 22:12:42 -0400559 VARDECL(celt_word16, error);
Jean-Marc Valin6775de32008-08-02 08:14:42 -0400560 VARDECL(int, pulses);
561 VARDECL(int, offsets);
Jean-Marc Valin52cb5fb2009-06-10 08:08:55 -0400562 VARDECL(int, fine_priority);
Jean-Marc Valin18a3b792009-05-01 19:58:55 -0400563 int intra_ener = 0;
Jean-Marc Valin9d1decd2008-06-17 13:28:13 +1000564 int shortBlocks=0;
Jean-Marc Valin12b22482008-06-16 14:13:05 +1000565 int transient_time;
Jean-Marc Valin528f4b82008-06-29 03:46:39 +1000566 int transient_shift;
Jean-Marc Valin80ed1472009-10-15 21:45:32 -0400567 const int C = CHANNELS(st->channels);
Jean-Marc Valinaa936252009-05-29 22:14:20 -0400568 int mdct_weight_shift = 0;
569 int mdct_weight_pos=0;
Jean-Marc Valinab220aa2009-09-15 22:38:40 -0400570 int gain_id=0;
Jean-Marc Valin92ae3702009-09-16 07:57:17 -0400571 int norm_rate;
Jean-Marc Valin8600f692008-02-29 15:14:12 +1100572 SAVE_STACK;
Jean-Marc Valin44ffd5a2008-02-22 00:39:25 +1100573
Gregory Maxwell17169992009-06-04 15:15:34 -0400574 if (check_encoder(st) != CELT_OK)
575 return CELT_INVALID_STATE;
576
Jean-Marc Valin44ffd5a2008-02-22 00:39:25 +1100577 if (check_mode(st->mode) != CELT_OK)
578 return CELT_INVALID_MODE;
579
Gregory Maxwell0719f6f2009-07-09 17:07:24 -0400580 if (nbCompressedBytes<0 || pcm==NULL)
Gregory Maxwell520eeae2009-02-09 01:33:21 -0500581 return CELT_BAD_ARG;
582
Jean-Marc Valin56522ad2009-06-05 17:17:25 -0400583 /* The memset is important for now in case the encoder doesn't
584 fill up all the bytes */
Jean-Marc Valin8679a802008-10-18 07:44:35 -0400585 CELT_MEMSET(compressed, 0, nbCompressedBytes);
586 ec_byte_writeinit_buffer(&buf, compressed, nbCompressedBytes);
587 ec_enc_init(&enc,&buf);
588
Jean-Marc Valinf02ba112007-11-30 01:10:42 +1100589 N = st->block_size;
Jean-Marc Valina536f772008-03-22 09:01:50 +1100590 N4 = (N-st->overlap)>>1;
Jean-Marc Valin234969c2009-10-17 22:12:42 -0400591 ALLOC(in, 2*C*N-2*C*N4, celt_sig);
Jean-Marc Valina5431bf2008-01-03 20:53:01 +1100592
Jean-Marc Valinbdb58832008-04-20 17:42:10 +1000593 CELT_COPY(in, st->in_mem, C*st->overlap);
Jean-Marc Valinffa13472007-12-10 16:54:17 +1100594 for (c=0;c<C;c++)
Jean-Marc Valin6f7e83d2007-12-01 00:36:41 +1100595 {
Jean-Marc Valin234969c2009-10-17 22:12:42 -0400596 const celt_word16 * restrict pcmp = pcm+c;
597 celt_sig * restrict inp = in+C*st->overlap+c;
Jean-Marc Valinb886ddc2008-03-25 14:38:55 +1100598 for (i=0;i<N;i++)
Jean-Marc Valinffa13472007-12-10 16:54:17 +1100599 {
Jean-Marc Valin62290062008-04-20 22:16:02 +1000600 /* Apply pre-emphasis */
Jean-Marc Valin234969c2009-10-17 22:12:42 -0400601 celt_sig tmp = SCALEIN(SHL32(EXTEND32(*pcmp), SIG_SHIFT));
Jean-Marc Valin5c3bc672008-08-28 23:34:24 -0400602 *inp = SUB32(tmp, SHR32(MULT16_16(preemph,st->preemph_memE[c]),3));
Gregory Maxwell5f2a74b2008-08-11 23:50:07 -0400603 st->preemph_memE[c] = SCALEIN(*pcmp);
Jean-Marc Valin62290062008-04-20 22:16:02 +1000604 inp += C;
605 pcmp += C;
Jean-Marc Valinffa13472007-12-10 16:54:17 +1100606 }
Jean-Marc Valin6f7e83d2007-12-01 00:36:41 +1100607 }
Jean-Marc Valinbdb58832008-04-20 17:42:10 +1000608 CELT_COPY(st->in_mem, in+C*(2*N-2*N4-st->overlap), C*st->overlap);
Jean-Marc Valin2014ca32009-06-18 23:33:04 -0400609
Jean-Marc Valin37ab9c62008-11-08 09:14:38 -0500610 /* Transient handling */
Jean-Marc Valin2014ca32009-06-18 23:33:04 -0400611 transient_time = -1;
612 transient_shift = 0;
613 shortBlocks = 0;
614
615 if (st->mode->nbShortMdcts > 1 && transient_analysis(in, N+st->overlap, C, &transient_time, &transient_shift))
Jean-Marc Valin9375aa42008-06-27 07:57:35 +1000616 {
Jean-Marc Valin7028d622008-07-10 23:06:58 -0400617#ifndef FIXED_POINT
Jean-Marc Valin2014ca32009-06-18 23:33:04 -0400618 float gain_1;
Jean-Marc Valin528f4b82008-06-29 03:46:39 +1000619#endif
Jean-Marc Valin2014ca32009-06-18 23:33:04 -0400620 /* Apply the inverse shaping window */
621 if (transient_shift)
622 {
Jean-Marc Valin7028d622008-07-10 23:06:58 -0400623#ifdef FIXED_POINT
Jean-Marc Valin2014ca32009-06-18 23:33:04 -0400624 for (c=0;c<C;c++)
625 for (i=0;i<16;i++)
626 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]);
627 for (c=0;c<C;c++)
628 for (i=transient_time;i<N+st->overlap;i++)
629 in[C*i+c] = SHR32(in[C*i+c], transient_shift);
Jean-Marc Valin7028d622008-07-10 23:06:58 -0400630#else
Jean-Marc Valin2014ca32009-06-18 23:33:04 -0400631 for (c=0;c<C;c++)
632 for (i=0;i<16;i++)
633 in[C*(transient_time+i-16)+c] /= 1+transientWindow[i]*((1<<transient_shift)-1);
634 gain_1 = 1./(1<<transient_shift);
635 for (c=0;c<C;c++)
636 for (i=transient_time;i<N+st->overlap;i++)
637 in[C*i+c] *= gain_1;
Jean-Marc Valin7028d622008-07-10 23:06:58 -0400638#endif
Jean-Marc Valin528f4b82008-06-29 03:46:39 +1000639 }
Jean-Marc Valin2014ca32009-06-18 23:33:04 -0400640 shortBlocks = 1;
641 has_fold = 1;
Jean-Marc Valin12b22482008-06-16 14:13:05 +1000642 }
Jean-Marc Valinc5f2a9d2008-10-26 22:00:26 -0400643
Jean-Marc Valin234969c2009-10-17 22:12:42 -0400644 ALLOC(freq, C*N, celt_sig); /**< Interleaved signal MDCTs */
645 ALLOC(bandE,st->mode->nbEBands*C, celt_ener);
646 ALLOC(bandLogE,st->mode->nbEBands*C, celt_word16);
Jean-Marc Valin32ec58c2009-05-01 21:28:58 -0400647 /* Compute MDCTs */
Jean-Marc Valinbf2398b2009-10-15 07:28:19 -0400648 compute_mdcts(st->mode, shortBlocks, in, freq, C);
Jean-Marc Valin08a82ff2009-06-14 14:05:19 -0400649
Jean-Marc Valinaa936252009-05-29 22:14:20 -0400650
Jean-Marc Valin30f7f812009-10-17 14:35:13 -0400651 norm_rate = (nbCompressedBytes-5)*8*(celt_uint32)st->mode->Fs/(C*N)>>10;
Jean-Marc Valinddb181b2008-03-03 14:53:47 +1100652 /* Pitch analysis: we do it early to save on the peak stack space */
Jean-Marc Valin56522ad2009-06-05 17:17:25 -0400653 /* Don't use pitch if there isn't enough data available yet,
654 or if we're using shortBlocks */
Jean-Marc Valine6d832a2009-07-08 22:21:31 -0400655 has_pitch = st->pitch_enabled && st->pitch_permitted && (N <= 512)
Jean-Marc Valin92ae3702009-09-16 07:57:17 -0400656 && (st->pitch_available >= MAX_PERIOD) && (!shortBlocks)
657 && norm_rate < 50;
Gregory Maxwell98046ca2008-12-13 20:42:03 -0500658 if (has_pitch)
Jean-Marc Valinc5f2a9d2008-10-26 22:00:26 -0400659 {
Jean-Marc Valinbf2398b2009-10-15 07:28:19 -0400660 find_spectral_pitch(st->mode, st->mode->fft, &st->mode->psy, in, st->out_mem, st->mode->window, NULL, 2*N-2*N4, MAX_PERIOD-(2*N-2*N4), &pitch_index, C);
Jean-Marc Valinc5f2a9d2008-10-26 22:00:26 -0400661 }
Jean-Marc Valin37ab9c62008-11-08 09:14:38 -0500662
Jean-Marc Valin56522ad2009-06-05 17:17:25 -0400663 /* Deferred allocation after find_spectral_pitch() to reduce
664 the peak memory usage */
Jean-Marc Valin234969c2009-10-17 22:12:42 -0400665 ALLOC(X, C*N, celt_norm); /**< Interleaved normalised MDCTs */
Jean-Marc Valin8d4ac152008-02-29 17:24:02 +1100666
Jean-Marc Valin234969c2009-10-17 22:12:42 -0400667 ALLOC(pitch_freq, C*N, celt_sig); /**< Interleaved signal MDCTs */
Jean-Marc Valin4c77ea92009-09-14 22:50:41 -0400668 if (has_pitch)
669 {
Jean-Marc Valin92ae3702009-09-16 07:57:17 -0400670
Jean-Marc Valinbf2398b2009-10-15 07:28:19 -0400671 compute_mdcts(st->mode, 0, st->out_mem+pitch_index*C, pitch_freq, C);
Jean-Marc Valind35d6772009-10-16 23:16:47 -0400672 has_pitch = compute_pitch_gain(st->mode, freq, pitch_freq, norm_rate, &gain_id, C, &st->gain_prod);
Jean-Marc Valin4c77ea92009-09-14 22:50:41 -0400673 }
674
675 if (has_pitch)
Jean-Marc Valinbf2398b2009-10-15 07:28:19 -0400676 apply_pitch(st->mode, freq, pitch_freq, gain_id, 1, C);
Jean-Marc Valin6c245242007-12-29 23:27:42 +1100677
Jean-Marc Valinbf2398b2009-10-15 07:28:19 -0400678 compute_band_energies(st->mode, freq, bandE, C);
Jean-Marc Valin4c77ea92009-09-14 22:50:41 -0400679 for (i=0;i<st->mode->nbEBands*C;i++)
680 bandLogE[i] = amp2Log(bandE[i]);
Jean-Marc Valinbd5d54a2009-10-20 00:25:31 -0400681
Jean-Marc Valin8ebd3452007-11-29 20:17:32 +1100682 /* Band normalisation */
Jean-Marc Valinbf2398b2009-10-15 07:28:19 -0400683 normalise_bands(st->mode, freq, X, bandE, C);
684 if (!shortBlocks && !folding_decision(st->mode, X, &st->tonal_average, &st->fold_decision, C))
Jean-Marc Valin527db5c2009-06-02 07:56:19 -0400685 has_fold = 0;
Jean-Marc Valin26c9e142007-12-31 21:27:54 +1100686
Jean-Marc Valin4c77ea92009-09-14 22:50:41 -0400687 /* Don't use intra energy when we're operating at low bit-rate */
688 intra_ener = st->force_intra || (!has_pitch && st->delayedIntra && nbCompressedBytes > st->mode->nbEBands);
689 if (shortBlocks || intra_decision(bandLogE, st->oldBandE, st->mode->nbEBands))
690 st->delayedIntra = 1;
691 else
692 st->delayedIntra = 0;
693
Jean-Marc Valin88619552009-10-04 21:35:36 -0400694 NN = st->mode->eBands[st->mode->nbEBands];
695 if (shortBlocks && !transient_shift)
696 {
Jean-Marc Valin234969c2009-10-17 22:12:42 -0400697 celt_word32 sum[8]={1,1,1,1,1,1,1,1};
Jean-Marc Valin88619552009-10-04 21:35:36 -0400698 int m;
699 for (c=0;c<C;c++)
700 {
701 m=0;
702 do {
Jean-Marc Valin234969c2009-10-17 22:12:42 -0400703 celt_word32 tmp=0;
Jean-Marc Valin88619552009-10-04 21:35:36 -0400704 for (i=m+c*N;i<c*N+NN;i+=st->mode->nbShortMdcts)
705 tmp += ABS32(X[i]);
706 sum[m++] += tmp;
707 } while (m<st->mode->nbShortMdcts);
708 }
709 m=0;
710#ifdef FIXED_POINT
711 do {
712 if (SHR32(sum[m+1],3) > sum[m])
713 {
714 mdct_weight_shift=2;
715 mdct_weight_pos = m;
716 } else if (SHR32(sum[m+1],1) > sum[m] && mdct_weight_shift < 2)
717 {
718 mdct_weight_shift=1;
719 mdct_weight_pos = m;
720 }
721 m++;
722 } while (m<st->mode->nbShortMdcts-1);
723#else
724 do {
725 if (sum[m+1] > 8*sum[m])
726 {
727 mdct_weight_shift=2;
728 mdct_weight_pos = m;
729 } else if (sum[m+1] > 2*sum[m] && mdct_weight_shift < 2)
730 {
731 mdct_weight_shift=1;
732 mdct_weight_pos = m;
733 }
734 m++;
735 } while (m<st->mode->nbShortMdcts-1);
736#endif
737 if (mdct_weight_shift)
738 {
Jean-Marc Valinbf2398b2009-10-15 07:28:19 -0400739 mdct_shape(st->mode, X, mdct_weight_pos+1, st->mode->nbShortMdcts, N, st->mode->nbShortMdcts, mdct_weight_shift, C);
740 renormalise_bands(st->mode, X, C);
Jean-Marc Valin88619552009-10-04 21:35:36 -0400741 }
742 }
743
Jean-Marc Valin4c77ea92009-09-14 22:50:41 -0400744
Jean-Marc Valin18a3b792009-05-01 19:58:55 -0400745 encode_flags(&enc, intra_ener, has_pitch, shortBlocks, has_fold);
Jean-Marc Valin05ed03e2009-04-29 07:44:13 -0400746 if (has_pitch)
747 {
Gregory Maxwellabe40f02008-12-13 01:31:32 -0500748 ec_enc_uint(&enc, pitch_index, MAX_PERIOD-(2*N-2*N4));
Jean-Marc Valin4c77ea92009-09-14 22:50:41 -0400749 ec_enc_uint(&enc, gain_id, 16);
Jean-Marc Valin96870d92007-12-05 21:14:22 +1100750 }
Jean-Marc Valin05ed03e2009-04-29 07:44:13 -0400751 if (shortBlocks)
752 {
Jean-Marc Valin05ed03e2009-04-29 07:44:13 -0400753 if (transient_shift)
Jean-Marc Valinaa936252009-05-29 22:14:20 -0400754 {
Jean-Marc Valine6108642009-08-01 23:05:47 +0200755 ec_enc_uint(&enc, transient_shift, 4);
Jean-Marc Valin05ed03e2009-04-29 07:44:13 -0400756 ec_enc_uint(&enc, transient_time, N+st->overlap);
Jean-Marc Valinaa936252009-05-29 22:14:20 -0400757 } else {
Jean-Marc Valine6108642009-08-01 23:05:47 +0200758 ec_enc_uint(&enc, mdct_weight_shift, 4);
Jean-Marc Valinaa936252009-05-29 22:14:20 -0400759 if (mdct_weight_shift && st->mode->nbShortMdcts!=2)
760 ec_enc_uint(&enc, mdct_weight_pos, st->mode->nbShortMdcts-1);
761 }
Jean-Marc Valin05ed03e2009-04-29 07:44:13 -0400762 }
Jean-Marc Valinc890b582008-08-01 22:26:49 -0400763
Jean-Marc Valin6775de32008-08-02 08:14:42 -0400764 ALLOC(fine_quant, st->mode->nbEBands, int);
Jean-Marc Valin8dff9232008-08-13 22:07:20 -0400765 ALLOC(pulses, st->mode->nbEBands, int);
Jean-Marc Valin37ab9c62008-11-08 09:14:38 -0500766
767 /* Bit allocation */
Jean-Marc Valin234969c2009-10-17 22:12:42 -0400768 ALLOC(error, C*st->mode->nbEBands, celt_word16);
Jean-Marc Valinbf2398b2009-10-15 07:28:19 -0400769 coarse_needed = quant_coarse_energy(st->mode, bandLogE, st->oldBandE, nbCompressedBytes*8/3, intra_ener, st->mode->prob, error, &enc, C);
Gregory Maxwell888d8ce2009-05-21 04:21:53 -0400770 coarse_needed = ((coarse_needed*3-1)>>3)+1;
771
772 /* Variable bitrate */
Jean-Marc Valinbd5d54a2009-10-20 00:25:31 -0400773 if (st->vbr_rate>0)
Gregory Maxwell888d8ce2009-05-21 04:21:53 -0400774 {
Jean-Marc Valinbd5d54a2009-10-20 00:25:31 -0400775 celt_word16 alpha;
776 celt_int32 delta, vbr_bound;
Gregory Maxwell888d8ce2009-05-21 04:21:53 -0400777 /* The target rate in 16th bits per frame */
Jean-Marc Valinbd5d54a2009-10-20 00:25:31 -0400778 celt_int32 target=st->vbr_rate;
Jean-Marc Valin6775de32008-08-02 08:14:42 -0400779
Jean-Marc Valin56522ad2009-06-05 17:17:25 -0400780 /* Shortblocks get a large boost in bitrate, but since they
781 are uncommon long blocks are not greatly effected */
Gregory Maxwell888d8ce2009-05-21 04:21:53 -0400782 if (shortBlocks)
783 target*=2;
784 else if (st->mode->nbShortMdcts > 1)
Jean-Marc Valinbd5d54a2009-10-20 00:25:31 -0400785 target-=(target+14)/28;
Gregory Maxwell888d8ce2009-05-21 04:21:53 -0400786
Jean-Marc Valin56522ad2009-06-05 17:17:25 -0400787 /* The average energy is removed from the target and the actual
788 energy added*/
Jean-Marc Valinbd5d54a2009-10-20 00:25:31 -0400789 target=target+st->vbr_offset-588+ec_enc_tell(&enc, BITRES);
Gregory Maxwell888d8ce2009-05-21 04:21:53 -0400790
791 /* In VBR mode the frame size must not be reduced so much that it would result in the coarse energy busting its budget */
792 target=IMAX(coarse_needed,(target+64)/128);
793 nbCompressedBytes=IMIN(nbCompressedBytes,target);
Jean-Marc Valinbd5d54a2009-10-20 00:25:31 -0400794
795 /* Make the adaptation coef (alpha) higher at the beginning */
796 if (st->vbr_count < 990)
797 {
798 st->vbr_count++;
799 alpha = celt_rcp(SHL32(EXTEND32(st->vbr_count+10),16));
800 /*printf ("%d %d\n", st->vbr_count+10, alpha);*/
801 } else
802 alpha = QCONST16(.001f,15);
803
804 /* By how much did we "miss" the target on that frame */
805 delta = (8<<BITRES)*(celt_int32)nbCompressedBytes - st->vbr_rate;
806 /* How many bits have we used in excess of what we're allowed */
807 st->vbr_reservoir += delta;
808 /*printf ("%d\n", st->vbr_reservoir);*/
809
810 /* Compute the offset we need to apply in order to reach the target */
811 st->vbr_drift += MULT16_32_Q15(alpha,delta-st->vbr_offset-st->vbr_drift);
812 st->vbr_offset = -st->vbr_drift;
813 /*printf ("%d\n", st->vbr_drift);*/
814
815 /* We could use any multiple of vbr_rate as bound (depending on the delay) */
816 vbr_bound = st->vbr_rate;
817 if (st->vbr_reservoir > vbr_bound)
818 {
819 /* Busted the reservoir -- reduce the rate */
820 int adjust = 1+(st->vbr_reservoir-vbr_bound-1)/(8<<BITRES);
821 nbCompressedBytes -= adjust;
822 st->vbr_reservoir -= adjust*(8<<BITRES);
823 st->vbr_offset -= 8<<BITRES;
824 /*printf ("-%d\n", adjust);*/
825 } else if (st->vbr_reservoir < 0)
826 {
827 /* We're under the min value -- increase rate */
828 int adjust = 1-(st->vbr_reservoir-1)/(8<<BITRES);
829 st->vbr_reservoir += adjust*(8<<BITRES);
830 nbCompressedBytes += adjust;
831 st->vbr_offset += 8<<BITRES;
832 /*printf ("+%d\n", adjust);*/
833 }
834
835 /* This moves the raw bits to take into account the new compressed size */
Jean-Marc Valine6108642009-08-01 23:05:47 +0200836 ec_byte_shrink(&buf, nbCompressedBytes);
Gregory Maxwell888d8ce2009-05-21 04:21:53 -0400837 }
838
Jean-Marc Valin6775de32008-08-02 08:14:42 -0400839 ALLOC(offsets, st->mode->nbEBands, int);
Jean-Marc Valin52cb5fb2009-06-10 08:08:55 -0400840 ALLOC(fine_priority, st->mode->nbEBands, int);
Jean-Marc Valincb7a2a32008-02-11 16:44:48 +1100841
Jean-Marc Valin6775de32008-08-02 08:14:42 -0400842 for (i=0;i<st->mode->nbEBands;i++)
843 offsets[i] = 0;
Jean-Marc Valin8679a802008-10-18 07:44:35 -0400844 bits = nbCompressedBytes*8 - ec_enc_tell(&enc, 0) - 1;
Jean-Marc Valinbf2398b2009-10-15 07:28:19 -0400845 compute_allocation(st->mode, offsets, bits, pulses, fine_quant, fine_priority, C);
Jean-Marc Valin37ab9c62008-11-08 09:14:38 -0500846
Jean-Marc Valinbf2398b2009-10-15 07:28:19 -0400847 quant_fine_energy(st->mode, bandE, st->oldBandE, error, fine_quant, &enc, C);
Jean-Marc Valin6775de32008-08-02 08:14:42 -0400848
Jean-Marc Valin8ebd3452007-11-29 20:17:32 +1100849 /* Residual quantisation */
Jean-Marc Valinca53b7c2009-03-26 20:23:14 -0400850 if (C==1)
Jean-Marc Valina9947c42009-10-08 23:10:45 -0400851 quant_bands(st->mode, X, bandE, pulses, shortBlocks, has_fold, nbCompressedBytes*8, 1, &enc);
Jean-Marc Valin73532032009-06-02 20:07:25 -0400852#ifndef DISABLE_STEREO
Jean-Marc Valinca53b7c2009-03-26 20:23:14 -0400853 else
Jean-Marc Valind5e54362009-09-30 20:50:41 -0400854 quant_bands_stereo(st->mode, X, bandE, pulses, shortBlocks, has_fold, nbCompressedBytes*8, &enc);
Jean-Marc Valin73532032009-06-02 20:07:25 -0400855#endif
Jean-Marc Valin39710532009-06-09 00:10:32 -0400856
Jean-Marc Valinbf2398b2009-10-15 07:28:19 -0400857 quant_energy_finalise(st->mode, bandE, st->oldBandE, error, fine_quant, fine_priority, nbCompressedBytes*8-ec_enc_tell(&enc, 0), &enc, C);
Jean-Marc Valin39710532009-06-09 00:10:32 -0400858
Jean-Marc Valin37ab9c62008-11-08 09:14:38 -0500859 /* Re-synthesis of the coded audio if required */
Gregory Maxwell98046ca2008-12-13 20:42:03 -0500860 if (st->pitch_available>0 || optional_synthesis!=NULL)
Jean-Marc Valin18ddc022008-02-22 14:24:50 +1100861 {
Gregory Maxwell98046ca2008-12-13 20:42:03 -0500862 if (st->pitch_available>0 && st->pitch_available<MAX_PERIOD)
863 st->pitch_available+=st->frame_size;
864
Jean-Marc Valinaa936252009-05-29 22:14:20 -0400865 if (mdct_weight_shift)
866 {
Jean-Marc Valinbf2398b2009-10-15 07:28:19 -0400867 mdct_shape(st->mode, X, 0, mdct_weight_pos+1, N, st->mode->nbShortMdcts, mdct_weight_shift, C);
Jean-Marc Valinaa936252009-05-29 22:14:20 -0400868 }
Jean-Marc Valin88619552009-10-04 21:35:36 -0400869
870 /* Synthesis */
Jean-Marc Valinbf2398b2009-10-15 07:28:19 -0400871 denormalise_bands(st->mode, X, freq, bandE, C);
Jean-Marc Valin88619552009-10-04 21:35:36 -0400872
873 CELT_MOVE(st->out_mem, st->out_mem+C*N, C*(MAX_PERIOD+st->overlap-N));
874
Jean-Marc Valin4c77ea92009-09-14 22:50:41 -0400875 if (has_pitch)
Jean-Marc Valinbf2398b2009-10-15 07:28:19 -0400876 apply_pitch(st->mode, freq, pitch_freq, gain_id, 0, C);
Jean-Marc Valin4c77ea92009-09-14 22:50:41 -0400877
Jean-Marc Valinbf2398b2009-10-15 07:28:19 -0400878 compute_inv_mdcts(st->mode, shortBlocks, freq, transient_time, transient_shift, st->out_mem, C);
Jean-Marc Valine12017e2009-10-03 13:57:31 -0400879
Jean-Marc Valin56522ad2009-06-05 17:17:25 -0400880 /* De-emphasis and put everything back at the right place
881 in the synthesis history */
Gregory Maxwell82595312008-09-30 18:20:14 -0400882 if (optional_synthesis != NULL) {
Jean-Marc Valine12017e2009-10-03 13:57:31 -0400883 deemphasis(st->out_mem, optional_synthesis, N, C, preemph, st->preemph_memD);
884
Jean-Marc Valin6f7e83d2007-12-01 00:36:41 +1100885 }
Jean-Marc Valind9b95652008-08-31 23:34:47 -0400886 }
Gregory Maxwell54547f12009-02-16 18:56:44 -0500887
Jean-Marc Valin8679a802008-10-18 07:44:35 -0400888 ec_enc_done(&enc);
Jean-Marc Valinc871c8d2009-06-09 00:57:00 -0400889
Jean-Marc Valin8600f692008-02-29 15:14:12 +1100890 RESTORE_STACK;
Jean-Marc Valina76a0b22008-01-17 22:43:05 +1100891 return nbCompressedBytes;
Jean-Marc Valin8ebd3452007-11-29 20:17:32 +1100892}
893
Gregory Maxwell5f2a74b2008-08-11 23:50:07 -0400894#ifdef FIXED_POINT
895#ifndef DISABLE_FLOAT_API
Gregory Maxwell82595312008-09-30 18:20:14 -0400896int celt_encode_float(CELTEncoder * restrict st, const float * pcm, float * optional_synthesis, unsigned char *compressed, int nbCompressedBytes)
Gregory Maxwell5f2a74b2008-08-11 23:50:07 -0400897{
Gregory Maxwell17169992009-06-04 15:15:34 -0400898 int j, ret, C, N;
Jean-Marc Valin30f7f812009-10-17 14:35:13 -0400899 VARDECL(celt_int16, in);
Jean-Marc Valincb8780c2009-07-20 23:40:35 -0400900 SAVE_STACK;
Gregory Maxwell17169992009-06-04 15:15:34 -0400901
902 if (check_encoder(st) != CELT_OK)
903 return CELT_INVALID_STATE;
904
905 if (check_mode(st->mode) != CELT_OK)
906 return CELT_INVALID_MODE;
907
Gregory Maxwell0719f6f2009-07-09 17:07:24 -0400908 if (pcm==NULL)
909 return CELT_BAD_ARG;
910
Jean-Marc Valin80ed1472009-10-15 21:45:32 -0400911 C = CHANNELS(st->channels);
Gregory Maxwell17169992009-06-04 15:15:34 -0400912 N = st->block_size;
Jean-Marc Valin30f7f812009-10-17 14:35:13 -0400913 ALLOC(in, C*N, celt_int16);
Gregory Maxwell5f2a74b2008-08-11 23:50:07 -0400914
915 for (j=0;j<C*N;j++)
916 in[j] = FLOAT2INT16(pcm[j]);
917
Gregory Maxwell82595312008-09-30 18:20:14 -0400918 if (optional_synthesis != NULL) {
919 ret=celt_encode(st,in,in,compressed,nbCompressedBytes);
Gregory Maxwellb0a73a02008-12-12 16:54:25 -0500920 for (j=0;j<C*N;j++)
Gregory Maxwell82595312008-09-30 18:20:14 -0400921 optional_synthesis[j]=in[j]*(1/32768.);
922 } else {
923 ret=celt_encode(st,in,NULL,compressed,nbCompressedBytes);
924 }
Wessel Lubberhuizen33ba6cc2008-10-03 07:09:29 -0400925 RESTORE_STACK;
Gregory Maxwell5f2a74b2008-08-11 23:50:07 -0400926 return ret;
927
928}
929#endif /*DISABLE_FLOAT_API*/
930#else
Jean-Marc Valin30f7f812009-10-17 14:35:13 -0400931int celt_encode(CELTEncoder * restrict st, const celt_int16 * pcm, celt_int16 * optional_synthesis, unsigned char *compressed, int nbCompressedBytes)
Gregory Maxwell5f2a74b2008-08-11 23:50:07 -0400932{
Gregory Maxwell17169992009-06-04 15:15:34 -0400933 int j, ret, C, N;
Jean-Marc Valin234969c2009-10-17 22:12:42 -0400934 VARDECL(celt_sig, in);
Jean-Marc Valincb8780c2009-07-20 23:40:35 -0400935 SAVE_STACK;
Gregory Maxwell17169992009-06-04 15:15:34 -0400936
937 if (check_encoder(st) != CELT_OK)
938 return CELT_INVALID_STATE;
939
940 if (check_mode(st->mode) != CELT_OK)
941 return CELT_INVALID_MODE;
942
Gregory Maxwell0719f6f2009-07-09 17:07:24 -0400943 if (pcm==NULL)
944 return CELT_BAD_ARG;
945
Jean-Marc Valin80ed1472009-10-15 21:45:32 -0400946 C=CHANNELS(st->channels);
Gregory Maxwell17169992009-06-04 15:15:34 -0400947 N=st->block_size;
Jean-Marc Valin234969c2009-10-17 22:12:42 -0400948 ALLOC(in, C*N, celt_sig);
Gregory Maxwell5f2a74b2008-08-11 23:50:07 -0400949 for (j=0;j<C*N;j++) {
950 in[j] = SCALEOUT(pcm[j]);
951 }
Gregory Maxwell5f2a74b2008-08-11 23:50:07 -0400952
Gregory Maxwell82595312008-09-30 18:20:14 -0400953 if (optional_synthesis != NULL) {
954 ret = celt_encode_float(st,in,in,compressed,nbCompressedBytes);
955 for (j=0;j<C*N;j++)
956 optional_synthesis[j] = FLOAT2INT16(in[j]);
957 } else {
958 ret = celt_encode_float(st,in,NULL,compressed,nbCompressedBytes);
959 }
Wessel Lubberhuizen33ba6cc2008-10-03 07:09:29 -0400960 RESTORE_STACK;
Gregory Maxwell5f2a74b2008-08-11 23:50:07 -0400961 return ret;
962}
963#endif
Jean-Marc Valin6e9058a2007-12-07 14:59:06 +1100964
Jean-Marc Valinb6f90612008-10-05 22:39:13 -0400965int celt_encoder_ctl(CELTEncoder * restrict st, int request, ...)
Jean-Marc Valinc18fb1d2008-09-30 07:36:54 -0400966{
Jean-Marc Valinb6f90612008-10-05 22:39:13 -0400967 va_list ap;
Gregory Maxwell17169992009-06-04 15:15:34 -0400968
969 if (check_encoder(st) != CELT_OK)
970 return CELT_INVALID_STATE;
971
Jean-Marc Valinb6f90612008-10-05 22:39:13 -0400972 va_start(ap, request);
Gregory Maxwell17169992009-06-04 15:15:34 -0400973 if ((request!=CELT_GET_MODE_REQUEST) && (check_mode(st->mode) != CELT_OK))
974 goto bad_mode;
Jean-Marc Valinc18fb1d2008-09-30 07:36:54 -0400975 switch (request)
976 {
Gregory Maxwellf3b44ef2009-06-03 13:37:45 -0400977 case CELT_GET_MODE_REQUEST:
978 {
979 const CELTMode ** value = va_arg(ap, const CELTMode**);
980 if (value==0)
981 goto bad_arg;
982 *value=st->mode;
983 }
984 break;
Jean-Marc Valinb6f90612008-10-05 22:39:13 -0400985 case CELT_SET_COMPLEXITY_REQUEST:
Jean-Marc Valinc18fb1d2008-09-30 07:36:54 -0400986 {
Jean-Marc Valin30f7f812009-10-17 14:35:13 -0400987 int value = va_arg(ap, celt_int32);
Jean-Marc Valinb6f90612008-10-05 22:39:13 -0400988 if (value<0 || value>10)
989 goto bad_arg;
Gregory Maxwell98046ca2008-12-13 20:42:03 -0500990 if (value<=2) {
991 st->pitch_enabled = 0;
992 st->pitch_available = 0;
993 } else {
994 st->pitch_enabled = 1;
995 if (st->pitch_available<1)
996 st->pitch_available = 1;
997 }
998 }
999 break;
Gregory Maxwell2dd3d322009-06-05 14:05:51 -04001000 case CELT_SET_PREDICTION_REQUEST:
Gregory Maxwell98046ca2008-12-13 20:42:03 -05001001 {
Jean-Marc Valin30f7f812009-10-17 14:35:13 -04001002 int value = va_arg(ap, celt_int32);
Gregory Maxwell2dd3d322009-06-05 14:05:51 -04001003 if (value<0 || value>2)
Gregory Maxwell98046ca2008-12-13 20:42:03 -05001004 goto bad_arg;
1005 if (value==0)
Gregory Maxwell2dd3d322009-06-05 14:05:51 -04001006 {
1007 st->force_intra = 1;
1008 st->pitch_permitted = 0;
Gregory Maxwella80958b2009-06-29 12:48:57 -04001009 } else if (value==1) {
Gregory Maxwell2dd3d322009-06-05 14:05:51 -04001010 st->force_intra = 0;
1011 st->pitch_permitted = 0;
1012 } else {
1013 st->force_intra = 0;
1014 st->pitch_permitted = 1;
1015 }
Jean-Marc Valinc18fb1d2008-09-30 07:36:54 -04001016 }
1017 break;
Gregory Maxwell888d8ce2009-05-21 04:21:53 -04001018 case CELT_SET_VBR_RATE_REQUEST:
1019 {
Jean-Marc Valin30f7f812009-10-17 14:35:13 -04001020 celt_int32 value = va_arg(ap, celt_int32);
Gregory Maxwell888d8ce2009-05-21 04:21:53 -04001021 if (value<0)
1022 goto bad_arg;
1023 if (value>3072000)
1024 value = 3072000;
Jean-Marc Valinbd5d54a2009-10-20 00:25:31 -04001025 st->vbr_rate = ((st->mode->Fs<<3)+(st->block_size>>1))/st->block_size;
1026 st->vbr_rate = ((value<<7)+(st->vbr_rate>>1))/st->vbr_rate;
Gregory Maxwell888d8ce2009-05-21 04:21:53 -04001027 }
1028 break;
John Ridges454d1d02009-05-21 22:38:39 -04001029 case CELT_RESET_STATE:
1030 {
1031 const CELTMode *mode = st->mode;
Jean-Marc Valin80ed1472009-10-15 21:45:32 -04001032 int C = st->channels;
John Ridges454d1d02009-05-21 22:38:39 -04001033
1034 if (st->pitch_available > 0) st->pitch_available = 1;
1035
1036 CELT_MEMSET(st->in_mem, 0, st->overlap*C);
1037 CELT_MEMSET(st->out_mem, 0, (MAX_PERIOD+st->overlap)*C);
1038
1039 CELT_MEMSET(st->oldBandE, 0, C*mode->nbEBands);
1040
1041 CELT_MEMSET(st->preemph_memE, 0, C);
1042 CELT_MEMSET(st->preemph_memD, 0, C);
1043 st->delayedIntra = 1;
1044 }
1045 break;
Jean-Marc Valinc18fb1d2008-09-30 07:36:54 -04001046 default:
Jean-Marc Valinb6f90612008-10-05 22:39:13 -04001047 goto bad_request;
Jean-Marc Valinc18fb1d2008-09-30 07:36:54 -04001048 }
Jean-Marc Valinb6f90612008-10-05 22:39:13 -04001049 va_end(ap);
Jean-Marc Valinc18fb1d2008-09-30 07:36:54 -04001050 return CELT_OK;
Gregory Maxwell17169992009-06-04 15:15:34 -04001051bad_mode:
1052 va_end(ap);
1053 return CELT_INVALID_MODE;
Jean-Marc Valinb6f90612008-10-05 22:39:13 -04001054bad_arg:
1055 va_end(ap);
1056 return CELT_BAD_ARG;
1057bad_request:
1058 va_end(ap);
1059 return CELT_UNIMPLEMENTED;
Jean-Marc Valinc18fb1d2008-09-30 07:36:54 -04001060}
1061
Jean-Marc Valin56522ad2009-06-05 17:17:25 -04001062/**********************************************************************/
1063/* */
1064/* DECODER */
1065/* */
1066/**********************************************************************/
Jean-Marc Valineafbdd52009-04-27 19:35:09 -04001067#ifdef NEW_PLC
1068#define DECODE_BUFFER_SIZE 2048
1069#else
1070#define DECODE_BUFFER_SIZE MAX_PERIOD
1071#endif
Jean-Marc Valin269d40a2007-12-07 11:29:45 +11001072
Gregory Maxwell17169992009-06-04 15:15:34 -04001073#define DECODERVALID 0x4c434454
1074#define DECODERPARTIAL 0x5444434c
1075#define DECODERFREED 0x4c004400
1076
Jean-Marc Valin276de722008-02-20 17:45:51 +11001077/** Decoder state
1078 @brief Decoder state
1079 */
Jean-Marc Valin269d40a2007-12-07 11:29:45 +11001080struct CELTDecoder {
Jean-Marc Valin30f7f812009-10-17 14:35:13 -04001081 celt_uint32 marker;
Jean-Marc Valin269d40a2007-12-07 11:29:45 +11001082 const CELTMode *mode;
1083 int frame_size;
1084 int block_size;
Jean-Marc Valina5431bf2008-01-03 20:53:01 +11001085 int overlap;
Jean-Marc Valin80ed1472009-10-15 21:45:32 -04001086 int channels;
Jean-Marc Valina5431bf2008-01-03 20:53:01 +11001087
Jean-Marc Valin269d40a2007-12-07 11:29:45 +11001088 ec_byte_buffer buf;
1089 ec_enc enc;
1090
Jean-Marc Valin234969c2009-10-17 22:12:42 -04001091 celt_sig * restrict preemph_memD;
Jean-Marc Valin81b38c22008-02-29 21:08:49 +11001092
Jean-Marc Valin234969c2009-10-17 22:12:42 -04001093 celt_sig *out_mem;
1094 celt_sig *decode_mem;
Jean-Marc Valin269d40a2007-12-07 11:29:45 +11001095
Jean-Marc Valin234969c2009-10-17 22:12:42 -04001096 celt_word16 *oldBandE;
Jean-Marc Valinfb83fb42007-12-08 00:56:04 +11001097
1098 int last_pitch_index;
Jean-Marc Valin0f0da992009-08-12 21:34:01 -04001099 int loss_count;
Jean-Marc Valin269d40a2007-12-07 11:29:45 +11001100};
1101
Gregory Maxwell17169992009-06-04 15:15:34 -04001102int check_decoder(const CELTDecoder *st)
1103{
1104 if (st==NULL)
1105 {
1106 celt_warning("NULL passed a decoder structure");
1107 return CELT_INVALID_STATE;
1108 }
1109 if (st->marker == DECODERVALID)
1110 return CELT_OK;
1111 if (st->marker == DECODERFREED)
1112 celt_warning("Referencing a decoder that has already been freed");
1113 else
1114 celt_warning("This is not a valid CELT decoder structure");
1115 return CELT_INVALID_STATE;
1116}
1117
Jean-Marc Valin80ed1472009-10-15 21:45:32 -04001118CELTDecoder *celt_decoder_create(const CELTMode *mode, int channels, int *error)
Jean-Marc Valin269d40a2007-12-07 11:29:45 +11001119{
Jean-Marc Valinb886ddc2008-03-25 14:38:55 +11001120 int N, C;
Jean-Marc Valin0bb05bc2008-02-20 13:43:40 +11001121 CELTDecoder *st;
Jean-Marc Valin44ffd5a2008-02-22 00:39:25 +11001122
1123 if (check_mode(mode) != CELT_OK)
Jean-Marc Valinece94a02009-10-16 07:30:14 -04001124 {
1125 if (error)
1126 *error = CELT_INVALID_MODE;
Jean-Marc Valin44ffd5a2008-02-22 00:39:25 +11001127 return NULL;
Jean-Marc Valinece94a02009-10-16 07:30:14 -04001128 }
Jean-Marc Valinbd5d54a2009-10-20 00:25:31 -04001129#ifdef DISABLE_STEREO
1130 if (channels > 1)
1131 {
1132 celt_warning("Stereo support was disable from this build");
1133 if (error)
1134 *error = CELT_BAD_ARG;
1135 return NULL;
1136 }
1137#endif
1138
Jean-Marc Valin80ed1472009-10-15 21:45:32 -04001139 if (channels < 0 || channels > 2)
1140 {
1141 celt_warning("Only mono and stereo supported");
1142 if (error)
1143 *error = CELT_BAD_ARG;
1144 return NULL;
1145 }
Jean-Marc Valin44ffd5a2008-02-22 00:39:25 +11001146
Jean-Marc Valin269d40a2007-12-07 11:29:45 +11001147 N = mode->mdctSize;
Jean-Marc Valin80ed1472009-10-15 21:45:32 -04001148 C = CHANNELS(channels);
Jean-Marc Valin0bb05bc2008-02-20 13:43:40 +11001149 st = celt_alloc(sizeof(CELTDecoder));
Gregory Maxwell17169992009-06-04 15:15:34 -04001150
1151 if (st==NULL)
Jean-Marc Valinece94a02009-10-16 07:30:14 -04001152 {
1153 if (error)
1154 *error = CELT_ALLOC_FAIL;
Gregory Maxwell17169992009-06-04 15:15:34 -04001155 return NULL;
Jean-Marc Valinece94a02009-10-16 07:30:14 -04001156 }
1157
Gregory Maxwell17169992009-06-04 15:15:34 -04001158 st->marker = DECODERPARTIAL;
Jean-Marc Valin269d40a2007-12-07 11:29:45 +11001159 st->mode = mode;
Jean-Marc Valinb886ddc2008-03-25 14:38:55 +11001160 st->frame_size = N;
Jean-Marc Valin269d40a2007-12-07 11:29:45 +11001161 st->block_size = N;
Jean-Marc Valina5431bf2008-01-03 20:53:01 +11001162 st->overlap = mode->overlap;
Jean-Marc Valin80ed1472009-10-15 21:45:32 -04001163 st->channels = channels;
Jean-Marc Valina5431bf2008-01-03 20:53:01 +11001164
Jean-Marc Valin234969c2009-10-17 22:12:42 -04001165 st->decode_mem = celt_alloc((DECODE_BUFFER_SIZE+st->overlap)*C*sizeof(celt_sig));
Jean-Marc Valineafbdd52009-04-27 19:35:09 -04001166 st->out_mem = st->decode_mem+DECODE_BUFFER_SIZE-MAX_PERIOD;
Jean-Marc Valin269d40a2007-12-07 11:29:45 +11001167
Jean-Marc Valin234969c2009-10-17 22:12:42 -04001168 st->oldBandE = (celt_word16*)celt_alloc(C*mode->nbEBands*sizeof(celt_word16));
Gregory Maxwell17169992009-06-04 15:15:34 -04001169
Jean-Marc Valin234969c2009-10-17 22:12:42 -04001170 st->preemph_memD = (celt_sig*)celt_alloc(C*sizeof(celt_sig));
Jean-Marc Valinffa13472007-12-10 16:54:17 +11001171
Jean-Marc Valin0f0da992009-08-12 21:34:01 -04001172 st->loss_count = 0;
Gregory Maxwell17169992009-06-04 15:15:34 -04001173
1174 if ((st->decode_mem!=NULL) && (st->out_mem!=NULL) && (st->oldBandE!=NULL) &&
1175 (st->preemph_memD!=NULL))
1176 {
Jean-Marc Valinece94a02009-10-16 07:30:14 -04001177 if (error)
1178 *error = CELT_OK;
Gregory Maxwell17169992009-06-04 15:15:34 -04001179 st->marker = DECODERVALID;
1180 return st;
1181 }
1182 /* If the setup fails for some reason deallocate it. */
1183 celt_decoder_destroy(st);
Jean-Marc Valinece94a02009-10-16 07:30:14 -04001184 if (error)
1185 *error = CELT_ALLOC_FAIL;
Gregory Maxwell17169992009-06-04 15:15:34 -04001186 return NULL;
Jean-Marc Valin269d40a2007-12-07 11:29:45 +11001187}
1188
Peter Kirk19f9dc92008-06-06 14:38:38 +02001189void celt_decoder_destroy(CELTDecoder *st)
Jean-Marc Valin269d40a2007-12-07 11:29:45 +11001190{
1191 if (st == NULL)
1192 {
Gregory Maxwell17169992009-06-04 15:15:34 -04001193 celt_warning("NULL passed to celt_decoder_destroy");
Jean-Marc Valin269d40a2007-12-07 11:29:45 +11001194 return;
1195 }
Gregory Maxwell17169992009-06-04 15:15:34 -04001196
1197 if (st->marker == DECODERFREED)
1198 {
1199 celt_warning("Freeing a decoder which has already been freed");
Jean-Marc Valin44ffd5a2008-02-22 00:39:25 +11001200 return;
Gregory Maxwell17169992009-06-04 15:15:34 -04001201 }
1202
1203 if (st->marker != DECODERVALID && st->marker != DECODERPARTIAL)
1204 {
1205 celt_warning("This is not a valid CELT decoder structure");
1206 return;
1207 }
1208
1209 /*Check_mode is non-fatal here because we can still free
1210 the encoder memory even if the mode is bad, although calling
1211 the free functions in this order is a violation of the API.*/
1212 check_mode(st->mode);
1213
Jean-Marc Valineafbdd52009-04-27 19:35:09 -04001214 celt_free(st->decode_mem);
Jean-Marc Valin269d40a2007-12-07 11:29:45 +11001215 celt_free(st->oldBandE);
Jean-Marc Valin7351e282008-02-08 15:09:45 +11001216 celt_free(st->preemph_memD);
Gregory Maxwell17169992009-06-04 15:15:34 -04001217
1218 st->marker = DECODERFREED;
1219
Jean-Marc Valin269d40a2007-12-07 11:29:45 +11001220 celt_free(st);
1221}
1222
Jean-Marc Valin56522ad2009-06-05 17:17:25 -04001223/** Handles lost packets by just copying past data with the same
1224 offset as the last
Jean-Marc Valind501f612008-02-21 12:16:57 +11001225 pitch period */
Jean-Marc Valineafbdd52009-04-27 19:35:09 -04001226#ifdef NEW_PLC
1227#include "plc.c"
1228#else
Jean-Marc Valin234969c2009-10-17 22:12:42 -04001229static void celt_decode_lost(CELTDecoder * restrict st, celt_word16 * restrict pcm)
Jean-Marc Valinfb83fb42007-12-08 00:56:04 +11001230{
Jean-Marc Valin05e56c42008-04-10 09:13:05 +10001231 int c, N;
Jean-Marc Valin0bb05bc2008-02-20 13:43:40 +11001232 int pitch_index;
Jean-Marc Valin234969c2009-10-17 22:12:42 -04001233 celt_word16 fade = Q15ONE;
Jean-Marc Valin24c9cda2008-05-02 10:34:07 +10001234 int i, len;
Jean-Marc Valin234969c2009-10-17 22:12:42 -04001235 VARDECL(celt_sig, freq);
Jean-Marc Valin80ed1472009-10-15 21:45:32 -04001236 const int C = CHANNELS(st->channels);
Jean-Marc Valin24c9cda2008-05-02 10:34:07 +10001237 int offset;
Jean-Marc Valin8600f692008-02-29 15:14:12 +11001238 SAVE_STACK;
Jean-Marc Valinfb83fb42007-12-08 00:56:04 +11001239 N = st->block_size;
Jean-Marc Valin234969c2009-10-17 22:12:42 -04001240 ALLOC(freq,C*N, celt_sig); /**< Interleaved signal MDCTs */
Jean-Marc Valinfb83fb42007-12-08 00:56:04 +11001241
Jean-Marc Valin24c9cda2008-05-02 10:34:07 +10001242 len = N+st->mode->overlap;
Jean-Marc Valinfb83fb42007-12-08 00:56:04 +11001243
Jean-Marc Valin0f0da992009-08-12 21:34:01 -04001244 if (st->loss_count == 0)
1245 {
Jean-Marc Valinbf2398b2009-10-15 07:28:19 -04001246 find_spectral_pitch(st->mode, st->mode->fft, &st->mode->psy, st->out_mem+MAX_PERIOD-len, st->out_mem, st->mode->window, NULL, len, MAX_PERIOD-len-100, &pitch_index, C);
Jean-Marc Valin0f0da992009-08-12 21:34:01 -04001247 pitch_index = MAX_PERIOD-len-pitch_index;
1248 st->last_pitch_index = pitch_index;
1249 } else {
1250 pitch_index = st->last_pitch_index;
1251 if (st->loss_count < 5)
1252 fade = QCONST16(.8f,15);
1253 else
1254 fade = 0;
1255 }
Jean-Marc Valinfb83fb42007-12-08 00:56:04 +11001256
Jean-Marc Valin24c9cda2008-05-02 10:34:07 +10001257 offset = MAX_PERIOD-pitch_index;
1258 while (offset+len >= MAX_PERIOD)
1259 offset -= pitch_index;
Jean-Marc Valinbf2398b2009-10-15 07:28:19 -04001260 compute_mdcts(st->mode, 0, st->out_mem+offset*C, freq, C);
Jean-Marc Valin08a82ff2009-06-14 14:05:19 -04001261 for (i=0;i<C*N;i++)
Jean-Marc Valin0f0da992009-08-12 21:34:01 -04001262 freq[i] = ADD32(VERY_SMALL, MULT16_32_Q15(fade,freq[i]));
1263
Jean-Marc Valin24c9cda2008-05-02 10:34:07 +10001264 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 +11001265 /* Compute inverse MDCTs */
Jean-Marc Valinbf2398b2009-10-15 07:28:19 -04001266 compute_inv_mdcts(st->mode, 0, freq, -1, 0, st->out_mem, C);
Jean-Marc Valin1677aa92007-12-08 01:13:34 +11001267
Jean-Marc Valinffa13472007-12-10 16:54:17 +11001268 for (c=0;c<C;c++)
Jean-Marc Valinfb83fb42007-12-08 00:56:04 +11001269 {
Jean-Marc Valinb886ddc2008-03-25 14:38:55 +11001270 int j;
1271 for (j=0;j<N;j++)
Jean-Marc Valinfb83fb42007-12-08 00:56:04 +11001272 {
Jean-Marc Valin234969c2009-10-17 22:12:42 -04001273 celt_sig tmp = MAC16_32_Q15(st->out_mem[C*(MAX_PERIOD-N)+C*j+c],
Jean-Marc Valin1dab60c2008-09-16 13:29:37 -04001274 preemph,st->preemph_memD[c]);
Jean-Marc Valinb886ddc2008-03-25 14:38:55 +11001275 st->preemph_memD[c] = tmp;
Gregory Maxwell5f2a74b2008-08-11 23:50:07 -04001276 pcm[C*j+c] = SCALEOUT(SIG2WORD16(tmp));
Jean-Marc Valinfb83fb42007-12-08 00:56:04 +11001277 }
1278 }
Jean-Marc Valin0f0da992009-08-12 21:34:01 -04001279
1280 st->loss_count++;
1281
Jean-Marc Valin8600f692008-02-29 15:14:12 +11001282 RESTORE_STACK;
Jean-Marc Valinfb83fb42007-12-08 00:56:04 +11001283}
Jean-Marc Valineafbdd52009-04-27 19:35:09 -04001284#endif
Jean-Marc Valinfb83fb42007-12-08 00:56:04 +11001285
Gregory Maxwell5f2a74b2008-08-11 23:50:07 -04001286#ifdef FIXED_POINT
Jean-Marc Valin30f7f812009-10-17 14:35:13 -04001287int celt_decode(CELTDecoder * restrict st, const unsigned char *data, int len, celt_int16 * restrict pcm)
Jean-Marc Valin269d40a2007-12-07 11:29:45 +11001288{
Gregory Maxwell5f2a74b2008-08-11 23:50:07 -04001289#else
Jean-Marc Valin234969c2009-10-17 22:12:42 -04001290int celt_decode_float(CELTDecoder * restrict st, const unsigned char *data, int len, celt_sig * restrict pcm)
Gregory Maxwell5f2a74b2008-08-11 23:50:07 -04001291{
1292#endif
Jean-Marc Valin88619552009-10-04 21:35:36 -04001293 int i, N, N4;
Jean-Marc Valinc9943942008-08-30 00:55:07 -04001294 int has_pitch, has_fold;
Jean-Marc Valin0bb05bc2008-02-20 13:43:40 +11001295 int pitch_index;
Jean-Marc Valinc890b582008-08-01 22:26:49 -04001296 int bits;
Jean-Marc Valin0bb05bc2008-02-20 13:43:40 +11001297 ec_dec dec;
1298 ec_byte_buffer buf;
Jean-Marc Valin234969c2009-10-17 22:12:42 -04001299 VARDECL(celt_sig, freq);
1300 VARDECL(celt_sig, pitch_freq);
1301 VARDECL(celt_norm, X);
1302 VARDECL(celt_ener, bandE);
Jean-Marc Valin6775de32008-08-02 08:14:42 -04001303 VARDECL(int, fine_quant);
1304 VARDECL(int, pulses);
1305 VARDECL(int, offsets);
Jean-Marc Valin52cb5fb2009-06-10 08:08:55 -04001306 VARDECL(int, fine_priority);
Jean-Marc Valinc890b582008-08-01 22:26:49 -04001307
Jean-Marc Valin9d1decd2008-06-17 13:28:13 +10001308 int shortBlocks;
Jean-Marc Valin05ed03e2009-04-29 07:44:13 -04001309 int intra_ener;
Jean-Marc Valin12b22482008-06-16 14:13:05 +10001310 int transient_time;
Jean-Marc Valin528f4b82008-06-29 03:46:39 +10001311 int transient_shift;
Jean-Marc Valinaa936252009-05-29 22:14:20 -04001312 int mdct_weight_shift=0;
Jean-Marc Valin80ed1472009-10-15 21:45:32 -04001313 const int C = CHANNELS(st->channels);
Jean-Marc Valinaa936252009-05-29 22:14:20 -04001314 int mdct_weight_pos=0;
Jean-Marc Valinab220aa2009-09-15 22:38:40 -04001315 int gain_id=0;
Jean-Marc Valin8600f692008-02-29 15:14:12 +11001316 SAVE_STACK;
Jean-Marc Valin44ffd5a2008-02-22 00:39:25 +11001317
Gregory Maxwell17169992009-06-04 15:15:34 -04001318 if (check_decoder(st) != CELT_OK)
1319 return CELT_INVALID_STATE;
1320
Jean-Marc Valin44ffd5a2008-02-22 00:39:25 +11001321 if (check_mode(st->mode) != CELT_OK)
1322 return CELT_INVALID_MODE;
1323
Gregory Maxwell0719f6f2009-07-09 17:07:24 -04001324 if (pcm==NULL)
1325 return CELT_BAD_ARG;
1326
Jean-Marc Valin269d40a2007-12-07 11:29:45 +11001327 N = st->block_size;
Jean-Marc Valina536f772008-03-22 09:01:50 +11001328 N4 = (N-st->overlap)>>1;
Jean-Marc Valin01417232008-03-03 13:59:55 +11001329
Jean-Marc Valin234969c2009-10-17 22:12:42 -04001330 ALLOC(freq, C*N, celt_sig); /**< Interleaved signal MDCTs */
1331 ALLOC(X, C*N, celt_norm); /**< Interleaved normalised MDCTs */
1332 ALLOC(bandE, st->mode->nbEBands*C, celt_ener);
Jean-Marc Valin70c8ffd2007-12-07 14:20:01 +11001333
Jean-Marc Valinfb83fb42007-12-08 00:56:04 +11001334 if (data == NULL)
1335 {
1336 celt_decode_lost(st, pcm);
Jean-Marc Valin8600f692008-02-29 15:14:12 +11001337 RESTORE_STACK;
Jean-Marc Valinfb83fb42007-12-08 00:56:04 +11001338 return 0;
Jean-Marc Valin0f0da992009-08-12 21:34:01 -04001339 } else {
1340 st->loss_count = 0;
Jean-Marc Valinfb83fb42007-12-08 00:56:04 +11001341 }
Gregory Maxwell520eeae2009-02-09 01:33:21 -05001342 if (len<0) {
1343 RESTORE_STACK;
1344 return CELT_BAD_ARG;
1345 }
Jean-Marc Valinfb83fb42007-12-08 00:56:04 +11001346
Jean-Marc Valin05ed03e2009-04-29 07:44:13 -04001347 ec_byte_readinit(&buf,(unsigned char*)data,len);
Jean-Marc Valin70c8ffd2007-12-07 14:20:01 +11001348 ec_dec_init(&dec,&buf);
1349
Jean-Marc Valin05ed03e2009-04-29 07:44:13 -04001350 decode_flags(&dec, &intra_ener, &has_pitch, &shortBlocks, &has_fold);
Gregory Maxwell0527f372008-09-23 19:28:35 -04001351 if (shortBlocks)
1352 {
Jean-Marc Valine6108642009-08-01 23:05:47 +02001353 transient_shift = ec_dec_uint(&dec, 4);
Jean-Marc Valinaa936252009-05-29 22:14:20 -04001354 if (transient_shift == 3)
1355 {
Gregory Maxwell0527f372008-09-23 19:28:35 -04001356 transient_time = ec_dec_uint(&dec, N+st->mode->overlap);
Jean-Marc Valinaa936252009-05-29 22:14:20 -04001357 } else {
1358 mdct_weight_shift = transient_shift;
1359 if (mdct_weight_shift && st->mode->nbShortMdcts>2)
1360 mdct_weight_pos = ec_dec_uint(&dec, st->mode->nbShortMdcts-1);
1361 transient_shift = 0;
Gregory Maxwell0527f372008-09-23 19:28:35 -04001362 transient_time = 0;
Jean-Marc Valinaa936252009-05-29 22:14:20 -04001363 }
Gregory Maxwell0527f372008-09-23 19:28:35 -04001364 } else {
Jean-Marc Valin12b22482008-06-16 14:13:05 +10001365 transient_time = -1;
Jean-Marc Valin528f4b82008-06-29 03:46:39 +10001366 transient_shift = 0;
Jean-Marc Valin12b22482008-06-16 14:13:05 +10001367 }
Jean-Marc Valincb7a2a32008-02-11 16:44:48 +11001368
Jean-Marc Valin7e8a4872008-02-11 16:55:34 +11001369 if (has_pitch)
1370 {
Jean-Marc Valinb886ddc2008-03-25 14:38:55 +11001371 pitch_index = ec_dec_uint(&dec, MAX_PERIOD-(2*N-2*N4));
Jean-Marc Valin4c77ea92009-09-14 22:50:41 -04001372 gain_id = ec_dec_uint(&dec, 16);
Jean-Marc Valin7e8a4872008-02-11 16:55:34 +11001373 } else {
Jean-Marc Valin7e8a4872008-02-11 16:55:34 +11001374 pitch_index = 0;
1375 }
Jean-Marc Valin827f9312008-05-06 23:21:55 +10001376
Jean-Marc Valin6775de32008-08-02 08:14:42 -04001377 ALLOC(fine_quant, st->mode->nbEBands, int);
Jean-Marc Valin827f9312008-05-06 23:21:55 +10001378 /* Get band energies */
Jean-Marc Valinbf2398b2009-10-15 07:28:19 -04001379 unquant_coarse_energy(st->mode, bandE, st->oldBandE, len*8/3, intra_ener, st->mode->prob, &dec, C);
Jean-Marc Valin6775de32008-08-02 08:14:42 -04001380
1381 ALLOC(pulses, st->mode->nbEBands, int);
1382 ALLOC(offsets, st->mode->nbEBands, int);
Jean-Marc Valin52cb5fb2009-06-10 08:08:55 -04001383 ALLOC(fine_priority, st->mode->nbEBands, int);
Jean-Marc Valin6775de32008-08-02 08:14:42 -04001384
1385 for (i=0;i<st->mode->nbEBands;i++)
1386 offsets[i] = 0;
1387
1388 bits = len*8 - ec_dec_tell(&dec, 0) - 1;
Jean-Marc Valinbf2398b2009-10-15 07:28:19 -04001389 compute_allocation(st->mode, offsets, bits, pulses, fine_quant, fine_priority, C);
Jean-Marc Valin6775de32008-08-02 08:14:42 -04001390 /*bits = ec_dec_tell(&dec, 0);
1391 compute_fine_allocation(st->mode, fine_quant, (20*C+len*8/5-(ec_dec_tell(&dec, 0)-bits))/C);*/
1392
Jean-Marc Valinbf2398b2009-10-15 07:28:19 -04001393 unquant_fine_energy(st->mode, bandE, st->oldBandE, fine_quant, &dec, C);
Jean-Marc Valin827f9312008-05-06 23:21:55 +10001394
Jean-Marc Valin234969c2009-10-17 22:12:42 -04001395 ALLOC(pitch_freq, C*N, celt_sig); /**< Interleaved signal MDCTs */
Jean-Marc Valinc9943942008-08-30 00:55:07 -04001396 if (has_pitch)
Jean-Marc Valin269d40a2007-12-07 11:29:45 +11001397 {
Jean-Marc Valinc9943942008-08-30 00:55:07 -04001398 /* Pitch MDCT */
Jean-Marc Valinbf2398b2009-10-15 07:28:19 -04001399 compute_mdcts(st->mode, 0, st->out_mem+pitch_index*C, pitch_freq, C);
Jean-Marc Valin269d40a2007-12-07 11:29:45 +11001400 }
1401
Jean-Marc Valin70c8ffd2007-12-07 14:20:01 +11001402 /* Decode fixed codebook and merge with pitch */
Jean-Marc Valinca53b7c2009-03-26 20:23:14 -04001403 if (C==1)
Jean-Marc Valina9947c42009-10-08 23:10:45 -04001404 quant_bands(st->mode, X, bandE, pulses, shortBlocks, has_fold, len*8, 0, &dec);
Jean-Marc Valin73532032009-06-02 20:07:25 -04001405#ifndef DISABLE_STEREO
Jean-Marc Valinca53b7c2009-03-26 20:23:14 -04001406 else
Jean-Marc Valind5e54362009-09-30 20:50:41 -04001407 unquant_bands_stereo(st->mode, X, bandE, pulses, shortBlocks, has_fold, len*8, &dec);
Jean-Marc Valin73532032009-06-02 20:07:25 -04001408#endif
Jean-Marc Valinbf2398b2009-10-15 07:28:19 -04001409 unquant_energy_finalise(st->mode, bandE, st->oldBandE, fine_quant, fine_priority, len*8-ec_dec_tell(&dec, 0), &dec, C);
Jean-Marc Valin39710532009-06-09 00:10:32 -04001410
Jean-Marc Valin88619552009-10-04 21:35:36 -04001411 if (mdct_weight_shift)
1412 {
Jean-Marc Valinbf2398b2009-10-15 07:28:19 -04001413 mdct_shape(st->mode, X, 0, mdct_weight_pos+1, N, st->mode->nbShortMdcts, mdct_weight_shift, C);
Jean-Marc Valin88619552009-10-04 21:35:36 -04001414 }
1415
Jean-Marc Valina4833ff2008-01-10 15:34:00 +11001416 /* Synthesis */
Jean-Marc Valinbf2398b2009-10-15 07:28:19 -04001417 denormalise_bands(st->mode, X, freq, bandE, C);
Jean-Marc Valina4833ff2008-01-10 15:34:00 +11001418
1419
Jean-Marc Valineafbdd52009-04-27 19:35:09 -04001420 CELT_MOVE(st->decode_mem, st->decode_mem+C*N, C*(DECODE_BUFFER_SIZE+st->overlap-N));
Jean-Marc Valin88619552009-10-04 21:35:36 -04001421
Jean-Marc Valin4c77ea92009-09-14 22:50:41 -04001422 if (has_pitch)
Jean-Marc Valinbf2398b2009-10-15 07:28:19 -04001423 apply_pitch(st->mode, freq, pitch_freq, gain_id, 0, C);
Jean-Marc Valin4c77ea92009-09-14 22:50:41 -04001424
Jean-Marc Valin269d40a2007-12-07 11:29:45 +11001425 /* Compute inverse MDCTs */
Jean-Marc Valinbf2398b2009-10-15 07:28:19 -04001426 compute_inv_mdcts(st->mode, shortBlocks, freq, transient_time, transient_shift, st->out_mem, C);
Jean-Marc Valinffa13472007-12-10 16:54:17 +11001427
Jean-Marc Valine12017e2009-10-03 13:57:31 -04001428 deemphasis(st->out_mem, pcm, N, C, preemph, st->preemph_memD);
Jean-Marc Valin388f1d62008-01-18 16:28:11 +11001429
Jean-Marc Valin8600f692008-02-29 15:14:12 +11001430 RESTORE_STACK;
Jean-Marc Valinfb83fb42007-12-08 00:56:04 +11001431 return 0;
Jean-Marc Valin269d40a2007-12-07 11:29:45 +11001432}
1433
Gregory Maxwell5f2a74b2008-08-11 23:50:07 -04001434#ifdef FIXED_POINT
1435#ifndef DISABLE_FLOAT_API
Jean-Marc Valin6db6cbd2009-04-11 22:01:20 -04001436int celt_decode_float(CELTDecoder * restrict st, const unsigned char *data, int len, float * restrict pcm)
Gregory Maxwell5f2a74b2008-08-11 23:50:07 -04001437{
Gregory Maxwell17169992009-06-04 15:15:34 -04001438 int j, ret, C, N;
Jean-Marc Valin30f7f812009-10-17 14:35:13 -04001439 VARDECL(celt_int16, out);
Jean-Marc Valincb8780c2009-07-20 23:40:35 -04001440 SAVE_STACK;
Gregory Maxwell17169992009-06-04 15:15:34 -04001441
1442 if (check_decoder(st) != CELT_OK)
1443 return CELT_INVALID_STATE;
1444
1445 if (check_mode(st->mode) != CELT_OK)
1446 return CELT_INVALID_MODE;
1447
Gregory Maxwell0719f6f2009-07-09 17:07:24 -04001448 if (pcm==NULL)
1449 return CELT_BAD_ARG;
1450
Jean-Marc Valin80ed1472009-10-15 21:45:32 -04001451 C = CHANNELS(st->channels);
Gregory Maxwell17169992009-06-04 15:15:34 -04001452 N = st->block_size;
Gregory Maxwell0719f6f2009-07-09 17:07:24 -04001453
Jean-Marc Valin30f7f812009-10-17 14:35:13 -04001454 ALLOC(out, C*N, celt_int16);
Gregory Maxwell5f2a74b2008-08-11 23:50:07 -04001455 ret=celt_decode(st, data, len, out);
Gregory Maxwell5f2a74b2008-08-11 23:50:07 -04001456 for (j=0;j<C*N;j++)
Gregory Maxwell0719f6f2009-07-09 17:07:24 -04001457 pcm[j]=out[j]*(1/32768.);
1458
Wessel Lubberhuizen33ba6cc2008-10-03 07:09:29 -04001459 RESTORE_STACK;
Gregory Maxwell5f2a74b2008-08-11 23:50:07 -04001460 return ret;
1461}
1462#endif /*DISABLE_FLOAT_API*/
1463#else
Jean-Marc Valin30f7f812009-10-17 14:35:13 -04001464int celt_decode(CELTDecoder * restrict st, const unsigned char *data, int len, celt_int16 * restrict pcm)
Gregory Maxwell5f2a74b2008-08-11 23:50:07 -04001465{
Gregory Maxwell17169992009-06-04 15:15:34 -04001466 int j, ret, C, N;
Jean-Marc Valin234969c2009-10-17 22:12:42 -04001467 VARDECL(celt_sig, out);
Jean-Marc Valincb8780c2009-07-20 23:40:35 -04001468 SAVE_STACK;
Gregory Maxwell17169992009-06-04 15:15:34 -04001469
1470 if (check_decoder(st) != CELT_OK)
1471 return CELT_INVALID_STATE;
1472
1473 if (check_mode(st->mode) != CELT_OK)
1474 return CELT_INVALID_MODE;
1475
Gregory Maxwell0719f6f2009-07-09 17:07:24 -04001476 if (pcm==NULL)
1477 return CELT_BAD_ARG;
1478
Jean-Marc Valin80ed1472009-10-15 21:45:32 -04001479 C = CHANNELS(st->channels);
Gregory Maxwell17169992009-06-04 15:15:34 -04001480 N = st->block_size;
Jean-Marc Valin234969c2009-10-17 22:12:42 -04001481 ALLOC(out, C*N, celt_sig);
Gregory Maxwell5f2a74b2008-08-11 23:50:07 -04001482
1483 ret=celt_decode_float(st, data, len, out);
1484
1485 for (j=0;j<C*N;j++)
Gregory Maxwell0719f6f2009-07-09 17:07:24 -04001486 pcm[j] = FLOAT2INT16 (out[j]);
1487
Wessel Lubberhuizen33ba6cc2008-10-03 07:09:29 -04001488 RESTORE_STACK;
Gregory Maxwell5f2a74b2008-08-11 23:50:07 -04001489 return ret;
1490}
1491#endif
John Ridges454d1d02009-05-21 22:38:39 -04001492
1493int celt_decoder_ctl(CELTDecoder * restrict st, int request, ...)
1494{
1495 va_list ap;
Gregory Maxwell17169992009-06-04 15:15:34 -04001496
1497 if (check_decoder(st) != CELT_OK)
1498 return CELT_INVALID_STATE;
1499
John Ridges454d1d02009-05-21 22:38:39 -04001500 va_start(ap, request);
Gregory Maxwell17169992009-06-04 15:15:34 -04001501 if ((request!=CELT_GET_MODE_REQUEST) && (check_mode(st->mode) != CELT_OK))
1502 goto bad_mode;
John Ridges454d1d02009-05-21 22:38:39 -04001503 switch (request)
1504 {
Gregory Maxwellf3b44ef2009-06-03 13:37:45 -04001505 case CELT_GET_MODE_REQUEST:
1506 {
1507 const CELTMode ** value = va_arg(ap, const CELTMode**);
1508 if (value==0)
1509 goto bad_arg;
1510 *value=st->mode;
1511 }
1512 break;
John Ridges454d1d02009-05-21 22:38:39 -04001513 case CELT_RESET_STATE:
1514 {
1515 const CELTMode *mode = st->mode;
Jean-Marc Valin80ed1472009-10-15 21:45:32 -04001516 int C = st->channels;
John Ridges454d1d02009-05-21 22:38:39 -04001517
1518 CELT_MEMSET(st->decode_mem, 0, (DECODE_BUFFER_SIZE+st->overlap)*C);
1519 CELT_MEMSET(st->oldBandE, 0, C*mode->nbEBands);
1520
1521 CELT_MEMSET(st->preemph_memD, 0, C);
1522
Jean-Marc Valin0f0da992009-08-12 21:34:01 -04001523 st->loss_count = 0;
John Ridges454d1d02009-05-21 22:38:39 -04001524 }
1525 break;
1526 default:
1527 goto bad_request;
1528 }
1529 va_end(ap);
1530 return CELT_OK;
Gregory Maxwell17169992009-06-04 15:15:34 -04001531bad_mode:
1532 va_end(ap);
1533 return CELT_INVALID_MODE;
John Ridges454d1d02009-05-21 22:38:39 -04001534bad_arg:
1535 va_end(ap);
1536 return CELT_BAD_ARG;
John Ridges454d1d02009-05-21 22:38:39 -04001537bad_request:
1538 va_end(ap);
1539 return CELT_UNIMPLEMENTED;
1540}
Jean-Marc Valinece94a02009-10-16 07:30:14 -04001541
1542const char *celt_strerror(int error)
1543{
1544 static const char *error_strings[8] = {
1545 "success",
1546 "invalid argument",
1547 "invalid mode",
1548 "internal error",
1549 "corrupted stream",
1550 "request not implemented",
1551 "invalid state",
1552 "memory allocation failed"
1553 };
1554 if (error > 0 || error < -7)
1555 return "unknown error";
1556 else
1557 return error_strings[-error];
1558}
1559