blob: 21edb0cae644f2b33d8401f73d3cb531847d19ce [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;
Jean-Marc Valinab4dcc52009-10-21 07:08:27 -0400549 int 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 Valinab4dcc52009-10-21 07:08:27 -0400769 coarse_needed = quant_coarse_energy(st->mode, bandLogE, st->oldBandE, nbCompressedBytes*8-16, 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 /* Make the adaptation coef (alpha) higher at the beginning */
795 if (st->vbr_count < 990)
796 {
797 st->vbr_count++;
798 alpha = celt_rcp(SHL32(EXTEND32(st->vbr_count+10),16));
799 /*printf ("%d %d\n", st->vbr_count+10, alpha);*/
800 } else
801 alpha = QCONST16(.001f,15);
802
803 /* By how much did we "miss" the target on that frame */
804 delta = (8<<BITRES)*(celt_int32)nbCompressedBytes - st->vbr_rate;
805 /* How many bits have we used in excess of what we're allowed */
806 st->vbr_reservoir += delta;
807 /*printf ("%d\n", st->vbr_reservoir);*/
808
809 /* Compute the offset we need to apply in order to reach the target */
810 st->vbr_drift += MULT16_32_Q15(alpha,delta-st->vbr_offset-st->vbr_drift);
811 st->vbr_offset = -st->vbr_drift;
812 /*printf ("%d\n", st->vbr_drift);*/
813
814 /* We could use any multiple of vbr_rate as bound (depending on the delay) */
815 vbr_bound = st->vbr_rate;
816 if (st->vbr_reservoir > vbr_bound)
817 {
818 /* Busted the reservoir -- reduce the rate */
819 int adjust = 1+(st->vbr_reservoir-vbr_bound-1)/(8<<BITRES);
820 nbCompressedBytes -= adjust;
821 st->vbr_reservoir -= adjust*(8<<BITRES);
Jean-Marc Valinbd5d54a2009-10-20 00:25:31 -0400822 /*printf ("-%d\n", adjust);*/
823 } else if (st->vbr_reservoir < 0)
824 {
825 /* We're under the min value -- increase rate */
826 int adjust = 1-(st->vbr_reservoir-1)/(8<<BITRES);
827 st->vbr_reservoir += adjust*(8<<BITRES);
828 nbCompressedBytes += adjust;
Jean-Marc Valinbd5d54a2009-10-20 00:25:31 -0400829 /*printf ("+%d\n", adjust);*/
830 }
831
832 /* This moves the raw bits to take into account the new compressed size */
Jean-Marc Valine6108642009-08-01 23:05:47 +0200833 ec_byte_shrink(&buf, nbCompressedBytes);
Gregory Maxwell888d8ce2009-05-21 04:21:53 -0400834 }
835
Jean-Marc Valin6775de32008-08-02 08:14:42 -0400836 ALLOC(offsets, st->mode->nbEBands, int);
Jean-Marc Valin52cb5fb2009-06-10 08:08:55 -0400837 ALLOC(fine_priority, st->mode->nbEBands, int);
Jean-Marc Valincb7a2a32008-02-11 16:44:48 +1100838
Jean-Marc Valin6775de32008-08-02 08:14:42 -0400839 for (i=0;i<st->mode->nbEBands;i++)
840 offsets[i] = 0;
Jean-Marc Valin8679a802008-10-18 07:44:35 -0400841 bits = nbCompressedBytes*8 - ec_enc_tell(&enc, 0) - 1;
Jean-Marc Valinbf2398b2009-10-15 07:28:19 -0400842 compute_allocation(st->mode, offsets, bits, pulses, fine_quant, fine_priority, C);
Jean-Marc Valin37ab9c62008-11-08 09:14:38 -0500843
Jean-Marc Valinbf2398b2009-10-15 07:28:19 -0400844 quant_fine_energy(st->mode, bandE, st->oldBandE, error, fine_quant, &enc, C);
Jean-Marc Valin6775de32008-08-02 08:14:42 -0400845
Jean-Marc Valin8ebd3452007-11-29 20:17:32 +1100846 /* Residual quantisation */
Jean-Marc Valinca53b7c2009-03-26 20:23:14 -0400847 if (C==1)
Jean-Marc Valina9947c42009-10-08 23:10:45 -0400848 quant_bands(st->mode, X, bandE, pulses, shortBlocks, has_fold, nbCompressedBytes*8, 1, &enc);
Jean-Marc Valin73532032009-06-02 20:07:25 -0400849#ifndef DISABLE_STEREO
Jean-Marc Valinca53b7c2009-03-26 20:23:14 -0400850 else
Jean-Marc Valind5e54362009-09-30 20:50:41 -0400851 quant_bands_stereo(st->mode, X, bandE, pulses, shortBlocks, has_fold, nbCompressedBytes*8, &enc);
Jean-Marc Valin73532032009-06-02 20:07:25 -0400852#endif
Jean-Marc Valin39710532009-06-09 00:10:32 -0400853
Jean-Marc Valinbf2398b2009-10-15 07:28:19 -0400854 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 -0400855
Jean-Marc Valin37ab9c62008-11-08 09:14:38 -0500856 /* Re-synthesis of the coded audio if required */
Gregory Maxwell98046ca2008-12-13 20:42:03 -0500857 if (st->pitch_available>0 || optional_synthesis!=NULL)
Jean-Marc Valin18ddc022008-02-22 14:24:50 +1100858 {
Gregory Maxwell98046ca2008-12-13 20:42:03 -0500859 if (st->pitch_available>0 && st->pitch_available<MAX_PERIOD)
860 st->pitch_available+=st->frame_size;
861
Jean-Marc Valinaa936252009-05-29 22:14:20 -0400862 if (mdct_weight_shift)
863 {
Jean-Marc Valinbf2398b2009-10-15 07:28:19 -0400864 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 -0400865 }
Jean-Marc Valin88619552009-10-04 21:35:36 -0400866
867 /* Synthesis */
Jean-Marc Valinbf2398b2009-10-15 07:28:19 -0400868 denormalise_bands(st->mode, X, freq, bandE, C);
Jean-Marc Valin88619552009-10-04 21:35:36 -0400869
870 CELT_MOVE(st->out_mem, st->out_mem+C*N, C*(MAX_PERIOD+st->overlap-N));
871
Jean-Marc Valin4c77ea92009-09-14 22:50:41 -0400872 if (has_pitch)
Jean-Marc Valinbf2398b2009-10-15 07:28:19 -0400873 apply_pitch(st->mode, freq, pitch_freq, gain_id, 0, C);
Jean-Marc Valin4c77ea92009-09-14 22:50:41 -0400874
Jean-Marc Valinbf2398b2009-10-15 07:28:19 -0400875 compute_inv_mdcts(st->mode, shortBlocks, freq, transient_time, transient_shift, st->out_mem, C);
Jean-Marc Valine12017e2009-10-03 13:57:31 -0400876
Jean-Marc Valin56522ad2009-06-05 17:17:25 -0400877 /* De-emphasis and put everything back at the right place
878 in the synthesis history */
Gregory Maxwell82595312008-09-30 18:20:14 -0400879 if (optional_synthesis != NULL) {
Jean-Marc Valine12017e2009-10-03 13:57:31 -0400880 deemphasis(st->out_mem, optional_synthesis, N, C, preemph, st->preemph_memD);
881
Jean-Marc Valin6f7e83d2007-12-01 00:36:41 +1100882 }
Jean-Marc Valind9b95652008-08-31 23:34:47 -0400883 }
Gregory Maxwell54547f12009-02-16 18:56:44 -0500884
Jean-Marc Valin8679a802008-10-18 07:44:35 -0400885 ec_enc_done(&enc);
Jean-Marc Valinc871c8d2009-06-09 00:57:00 -0400886
Jean-Marc Valin8600f692008-02-29 15:14:12 +1100887 RESTORE_STACK;
Jean-Marc Valina76a0b22008-01-17 22:43:05 +1100888 return nbCompressedBytes;
Jean-Marc Valin8ebd3452007-11-29 20:17:32 +1100889}
890
Gregory Maxwell5f2a74b2008-08-11 23:50:07 -0400891#ifdef FIXED_POINT
892#ifndef DISABLE_FLOAT_API
Gregory Maxwell82595312008-09-30 18:20:14 -0400893int celt_encode_float(CELTEncoder * restrict st, const float * pcm, float * optional_synthesis, unsigned char *compressed, int nbCompressedBytes)
Gregory Maxwell5f2a74b2008-08-11 23:50:07 -0400894{
Gregory Maxwell17169992009-06-04 15:15:34 -0400895 int j, ret, C, N;
Jean-Marc Valin30f7f812009-10-17 14:35:13 -0400896 VARDECL(celt_int16, in);
Jean-Marc Valincb8780c2009-07-20 23:40:35 -0400897 SAVE_STACK;
Gregory Maxwell17169992009-06-04 15:15:34 -0400898
899 if (check_encoder(st) != CELT_OK)
900 return CELT_INVALID_STATE;
901
902 if (check_mode(st->mode) != CELT_OK)
903 return CELT_INVALID_MODE;
904
Gregory Maxwell0719f6f2009-07-09 17:07:24 -0400905 if (pcm==NULL)
906 return CELT_BAD_ARG;
907
Jean-Marc Valin80ed1472009-10-15 21:45:32 -0400908 C = CHANNELS(st->channels);
Gregory Maxwell17169992009-06-04 15:15:34 -0400909 N = st->block_size;
Jean-Marc Valin30f7f812009-10-17 14:35:13 -0400910 ALLOC(in, C*N, celt_int16);
Gregory Maxwell5f2a74b2008-08-11 23:50:07 -0400911
912 for (j=0;j<C*N;j++)
913 in[j] = FLOAT2INT16(pcm[j]);
914
Gregory Maxwell82595312008-09-30 18:20:14 -0400915 if (optional_synthesis != NULL) {
916 ret=celt_encode(st,in,in,compressed,nbCompressedBytes);
Gregory Maxwellb0a73a02008-12-12 16:54:25 -0500917 for (j=0;j<C*N;j++)
Gregory Maxwell82595312008-09-30 18:20:14 -0400918 optional_synthesis[j]=in[j]*(1/32768.);
919 } else {
920 ret=celt_encode(st,in,NULL,compressed,nbCompressedBytes);
921 }
Wessel Lubberhuizen33ba6cc2008-10-03 07:09:29 -0400922 RESTORE_STACK;
Gregory Maxwell5f2a74b2008-08-11 23:50:07 -0400923 return ret;
924
925}
926#endif /*DISABLE_FLOAT_API*/
927#else
Jean-Marc Valin30f7f812009-10-17 14:35:13 -0400928int 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 -0400929{
Gregory Maxwell17169992009-06-04 15:15:34 -0400930 int j, ret, C, N;
Jean-Marc Valin234969c2009-10-17 22:12:42 -0400931 VARDECL(celt_sig, in);
Jean-Marc Valincb8780c2009-07-20 23:40:35 -0400932 SAVE_STACK;
Gregory Maxwell17169992009-06-04 15:15:34 -0400933
934 if (check_encoder(st) != CELT_OK)
935 return CELT_INVALID_STATE;
936
937 if (check_mode(st->mode) != CELT_OK)
938 return CELT_INVALID_MODE;
939
Gregory Maxwell0719f6f2009-07-09 17:07:24 -0400940 if (pcm==NULL)
941 return CELT_BAD_ARG;
942
Jean-Marc Valin80ed1472009-10-15 21:45:32 -0400943 C=CHANNELS(st->channels);
Gregory Maxwell17169992009-06-04 15:15:34 -0400944 N=st->block_size;
Jean-Marc Valin234969c2009-10-17 22:12:42 -0400945 ALLOC(in, C*N, celt_sig);
Gregory Maxwell5f2a74b2008-08-11 23:50:07 -0400946 for (j=0;j<C*N;j++) {
947 in[j] = SCALEOUT(pcm[j]);
948 }
Gregory Maxwell5f2a74b2008-08-11 23:50:07 -0400949
Gregory Maxwell82595312008-09-30 18:20:14 -0400950 if (optional_synthesis != NULL) {
951 ret = celt_encode_float(st,in,in,compressed,nbCompressedBytes);
952 for (j=0;j<C*N;j++)
953 optional_synthesis[j] = FLOAT2INT16(in[j]);
954 } else {
955 ret = celt_encode_float(st,in,NULL,compressed,nbCompressedBytes);
956 }
Wessel Lubberhuizen33ba6cc2008-10-03 07:09:29 -0400957 RESTORE_STACK;
Gregory Maxwell5f2a74b2008-08-11 23:50:07 -0400958 return ret;
959}
960#endif
Jean-Marc Valin6e9058a2007-12-07 14:59:06 +1100961
Jean-Marc Valinb6f90612008-10-05 22:39:13 -0400962int celt_encoder_ctl(CELTEncoder * restrict st, int request, ...)
Jean-Marc Valinc18fb1d2008-09-30 07:36:54 -0400963{
Jean-Marc Valinb6f90612008-10-05 22:39:13 -0400964 va_list ap;
Gregory Maxwell17169992009-06-04 15:15:34 -0400965
966 if (check_encoder(st) != CELT_OK)
967 return CELT_INVALID_STATE;
968
Jean-Marc Valinb6f90612008-10-05 22:39:13 -0400969 va_start(ap, request);
Gregory Maxwell17169992009-06-04 15:15:34 -0400970 if ((request!=CELT_GET_MODE_REQUEST) && (check_mode(st->mode) != CELT_OK))
971 goto bad_mode;
Jean-Marc Valinc18fb1d2008-09-30 07:36:54 -0400972 switch (request)
973 {
Gregory Maxwellf3b44ef2009-06-03 13:37:45 -0400974 case CELT_GET_MODE_REQUEST:
975 {
976 const CELTMode ** value = va_arg(ap, const CELTMode**);
977 if (value==0)
978 goto bad_arg;
979 *value=st->mode;
980 }
981 break;
Jean-Marc Valinb6f90612008-10-05 22:39:13 -0400982 case CELT_SET_COMPLEXITY_REQUEST:
Jean-Marc Valinc18fb1d2008-09-30 07:36:54 -0400983 {
Jean-Marc Valin30f7f812009-10-17 14:35:13 -0400984 int value = va_arg(ap, celt_int32);
Jean-Marc Valinb6f90612008-10-05 22:39:13 -0400985 if (value<0 || value>10)
986 goto bad_arg;
Gregory Maxwell98046ca2008-12-13 20:42:03 -0500987 if (value<=2) {
988 st->pitch_enabled = 0;
989 st->pitch_available = 0;
990 } else {
991 st->pitch_enabled = 1;
992 if (st->pitch_available<1)
993 st->pitch_available = 1;
994 }
995 }
996 break;
Gregory Maxwell2dd3d322009-06-05 14:05:51 -0400997 case CELT_SET_PREDICTION_REQUEST:
Gregory Maxwell98046ca2008-12-13 20:42:03 -0500998 {
Jean-Marc Valin30f7f812009-10-17 14:35:13 -0400999 int value = va_arg(ap, celt_int32);
Gregory Maxwell2dd3d322009-06-05 14:05:51 -04001000 if (value<0 || value>2)
Gregory Maxwell98046ca2008-12-13 20:42:03 -05001001 goto bad_arg;
1002 if (value==0)
Gregory Maxwell2dd3d322009-06-05 14:05:51 -04001003 {
1004 st->force_intra = 1;
1005 st->pitch_permitted = 0;
Gregory Maxwella80958b2009-06-29 12:48:57 -04001006 } else if (value==1) {
Gregory Maxwell2dd3d322009-06-05 14:05:51 -04001007 st->force_intra = 0;
1008 st->pitch_permitted = 0;
1009 } else {
1010 st->force_intra = 0;
1011 st->pitch_permitted = 1;
1012 }
Jean-Marc Valinc18fb1d2008-09-30 07:36:54 -04001013 }
1014 break;
Gregory Maxwell888d8ce2009-05-21 04:21:53 -04001015 case CELT_SET_VBR_RATE_REQUEST:
1016 {
Jean-Marc Valin30f7f812009-10-17 14:35:13 -04001017 celt_int32 value = va_arg(ap, celt_int32);
Gregory Maxwell888d8ce2009-05-21 04:21:53 -04001018 if (value<0)
1019 goto bad_arg;
1020 if (value>3072000)
1021 value = 3072000;
Jean-Marc Valinbd5d54a2009-10-20 00:25:31 -04001022 st->vbr_rate = ((st->mode->Fs<<3)+(st->block_size>>1))/st->block_size;
1023 st->vbr_rate = ((value<<7)+(st->vbr_rate>>1))/st->vbr_rate;
Gregory Maxwell888d8ce2009-05-21 04:21:53 -04001024 }
1025 break;
John Ridges454d1d02009-05-21 22:38:39 -04001026 case CELT_RESET_STATE:
1027 {
1028 const CELTMode *mode = st->mode;
Jean-Marc Valin80ed1472009-10-15 21:45:32 -04001029 int C = st->channels;
John Ridges454d1d02009-05-21 22:38:39 -04001030
1031 if (st->pitch_available > 0) st->pitch_available = 1;
1032
1033 CELT_MEMSET(st->in_mem, 0, st->overlap*C);
1034 CELT_MEMSET(st->out_mem, 0, (MAX_PERIOD+st->overlap)*C);
1035
1036 CELT_MEMSET(st->oldBandE, 0, C*mode->nbEBands);
1037
1038 CELT_MEMSET(st->preemph_memE, 0, C);
1039 CELT_MEMSET(st->preemph_memD, 0, C);
1040 st->delayedIntra = 1;
1041 }
1042 break;
Jean-Marc Valinc18fb1d2008-09-30 07:36:54 -04001043 default:
Jean-Marc Valinb6f90612008-10-05 22:39:13 -04001044 goto bad_request;
Jean-Marc Valinc18fb1d2008-09-30 07:36:54 -04001045 }
Jean-Marc Valinb6f90612008-10-05 22:39:13 -04001046 va_end(ap);
Jean-Marc Valinc18fb1d2008-09-30 07:36:54 -04001047 return CELT_OK;
Gregory Maxwell17169992009-06-04 15:15:34 -04001048bad_mode:
1049 va_end(ap);
1050 return CELT_INVALID_MODE;
Jean-Marc Valinb6f90612008-10-05 22:39:13 -04001051bad_arg:
1052 va_end(ap);
1053 return CELT_BAD_ARG;
1054bad_request:
1055 va_end(ap);
1056 return CELT_UNIMPLEMENTED;
Jean-Marc Valinc18fb1d2008-09-30 07:36:54 -04001057}
1058
Jean-Marc Valin56522ad2009-06-05 17:17:25 -04001059/**********************************************************************/
1060/* */
1061/* DECODER */
1062/* */
1063/**********************************************************************/
Jean-Marc Valineafbdd52009-04-27 19:35:09 -04001064#ifdef NEW_PLC
1065#define DECODE_BUFFER_SIZE 2048
1066#else
1067#define DECODE_BUFFER_SIZE MAX_PERIOD
1068#endif
Jean-Marc Valin269d40a2007-12-07 11:29:45 +11001069
Gregory Maxwell17169992009-06-04 15:15:34 -04001070#define DECODERVALID 0x4c434454
1071#define DECODERPARTIAL 0x5444434c
1072#define DECODERFREED 0x4c004400
1073
Jean-Marc Valin276de722008-02-20 17:45:51 +11001074/** Decoder state
1075 @brief Decoder state
1076 */
Jean-Marc Valin269d40a2007-12-07 11:29:45 +11001077struct CELTDecoder {
Jean-Marc Valin30f7f812009-10-17 14:35:13 -04001078 celt_uint32 marker;
Jean-Marc Valin269d40a2007-12-07 11:29:45 +11001079 const CELTMode *mode;
1080 int frame_size;
1081 int block_size;
Jean-Marc Valina5431bf2008-01-03 20:53:01 +11001082 int overlap;
Jean-Marc Valin80ed1472009-10-15 21:45:32 -04001083 int channels;
Jean-Marc Valina5431bf2008-01-03 20:53:01 +11001084
Jean-Marc Valin269d40a2007-12-07 11:29:45 +11001085 ec_byte_buffer buf;
1086 ec_enc enc;
1087
Jean-Marc Valin234969c2009-10-17 22:12:42 -04001088 celt_sig * restrict preemph_memD;
Jean-Marc Valin81b38c22008-02-29 21:08:49 +11001089
Jean-Marc Valin234969c2009-10-17 22:12:42 -04001090 celt_sig *out_mem;
1091 celt_sig *decode_mem;
Jean-Marc Valin269d40a2007-12-07 11:29:45 +11001092
Jean-Marc Valin234969c2009-10-17 22:12:42 -04001093 celt_word16 *oldBandE;
Jean-Marc Valinfb83fb42007-12-08 00:56:04 +11001094
1095 int last_pitch_index;
Jean-Marc Valin0f0da992009-08-12 21:34:01 -04001096 int loss_count;
Jean-Marc Valin269d40a2007-12-07 11:29:45 +11001097};
1098
Gregory Maxwell17169992009-06-04 15:15:34 -04001099int check_decoder(const CELTDecoder *st)
1100{
1101 if (st==NULL)
1102 {
1103 celt_warning("NULL passed a decoder structure");
1104 return CELT_INVALID_STATE;
1105 }
1106 if (st->marker == DECODERVALID)
1107 return CELT_OK;
1108 if (st->marker == DECODERFREED)
1109 celt_warning("Referencing a decoder that has already been freed");
1110 else
1111 celt_warning("This is not a valid CELT decoder structure");
1112 return CELT_INVALID_STATE;
1113}
1114
Jean-Marc Valin80ed1472009-10-15 21:45:32 -04001115CELTDecoder *celt_decoder_create(const CELTMode *mode, int channels, int *error)
Jean-Marc Valin269d40a2007-12-07 11:29:45 +11001116{
Jean-Marc Valinb886ddc2008-03-25 14:38:55 +11001117 int N, C;
Jean-Marc Valin0bb05bc2008-02-20 13:43:40 +11001118 CELTDecoder *st;
Jean-Marc Valin44ffd5a2008-02-22 00:39:25 +11001119
1120 if (check_mode(mode) != CELT_OK)
Jean-Marc Valinece94a02009-10-16 07:30:14 -04001121 {
1122 if (error)
1123 *error = CELT_INVALID_MODE;
Jean-Marc Valin44ffd5a2008-02-22 00:39:25 +11001124 return NULL;
Jean-Marc Valinece94a02009-10-16 07:30:14 -04001125 }
Jean-Marc Valinbd5d54a2009-10-20 00:25:31 -04001126#ifdef DISABLE_STEREO
1127 if (channels > 1)
1128 {
1129 celt_warning("Stereo support was disable from this build");
1130 if (error)
1131 *error = CELT_BAD_ARG;
1132 return NULL;
1133 }
1134#endif
1135
Jean-Marc Valin80ed1472009-10-15 21:45:32 -04001136 if (channels < 0 || channels > 2)
1137 {
1138 celt_warning("Only mono and stereo supported");
1139 if (error)
1140 *error = CELT_BAD_ARG;
1141 return NULL;
1142 }
Jean-Marc Valin44ffd5a2008-02-22 00:39:25 +11001143
Jean-Marc Valin269d40a2007-12-07 11:29:45 +11001144 N = mode->mdctSize;
Jean-Marc Valin80ed1472009-10-15 21:45:32 -04001145 C = CHANNELS(channels);
Jean-Marc Valin0bb05bc2008-02-20 13:43:40 +11001146 st = celt_alloc(sizeof(CELTDecoder));
Gregory Maxwell17169992009-06-04 15:15:34 -04001147
1148 if (st==NULL)
Jean-Marc Valinece94a02009-10-16 07:30:14 -04001149 {
1150 if (error)
1151 *error = CELT_ALLOC_FAIL;
Gregory Maxwell17169992009-06-04 15:15:34 -04001152 return NULL;
Jean-Marc Valinece94a02009-10-16 07:30:14 -04001153 }
1154
Gregory Maxwell17169992009-06-04 15:15:34 -04001155 st->marker = DECODERPARTIAL;
Jean-Marc Valin269d40a2007-12-07 11:29:45 +11001156 st->mode = mode;
Jean-Marc Valinb886ddc2008-03-25 14:38:55 +11001157 st->frame_size = N;
Jean-Marc Valin269d40a2007-12-07 11:29:45 +11001158 st->block_size = N;
Jean-Marc Valina5431bf2008-01-03 20:53:01 +11001159 st->overlap = mode->overlap;
Jean-Marc Valin80ed1472009-10-15 21:45:32 -04001160 st->channels = channels;
Jean-Marc Valina5431bf2008-01-03 20:53:01 +11001161
Jean-Marc Valin234969c2009-10-17 22:12:42 -04001162 st->decode_mem = celt_alloc((DECODE_BUFFER_SIZE+st->overlap)*C*sizeof(celt_sig));
Jean-Marc Valineafbdd52009-04-27 19:35:09 -04001163 st->out_mem = st->decode_mem+DECODE_BUFFER_SIZE-MAX_PERIOD;
Jean-Marc Valin269d40a2007-12-07 11:29:45 +11001164
Jean-Marc Valin234969c2009-10-17 22:12:42 -04001165 st->oldBandE = (celt_word16*)celt_alloc(C*mode->nbEBands*sizeof(celt_word16));
Gregory Maxwell17169992009-06-04 15:15:34 -04001166
Jean-Marc Valin234969c2009-10-17 22:12:42 -04001167 st->preemph_memD = (celt_sig*)celt_alloc(C*sizeof(celt_sig));
Jean-Marc Valinffa13472007-12-10 16:54:17 +11001168
Jean-Marc Valin0f0da992009-08-12 21:34:01 -04001169 st->loss_count = 0;
Gregory Maxwell17169992009-06-04 15:15:34 -04001170
1171 if ((st->decode_mem!=NULL) && (st->out_mem!=NULL) && (st->oldBandE!=NULL) &&
1172 (st->preemph_memD!=NULL))
1173 {
Jean-Marc Valinece94a02009-10-16 07:30:14 -04001174 if (error)
1175 *error = CELT_OK;
Gregory Maxwell17169992009-06-04 15:15:34 -04001176 st->marker = DECODERVALID;
1177 return st;
1178 }
1179 /* If the setup fails for some reason deallocate it. */
1180 celt_decoder_destroy(st);
Jean-Marc Valinece94a02009-10-16 07:30:14 -04001181 if (error)
1182 *error = CELT_ALLOC_FAIL;
Gregory Maxwell17169992009-06-04 15:15:34 -04001183 return NULL;
Jean-Marc Valin269d40a2007-12-07 11:29:45 +11001184}
1185
Peter Kirk19f9dc92008-06-06 14:38:38 +02001186void celt_decoder_destroy(CELTDecoder *st)
Jean-Marc Valin269d40a2007-12-07 11:29:45 +11001187{
1188 if (st == NULL)
1189 {
Gregory Maxwell17169992009-06-04 15:15:34 -04001190 celt_warning("NULL passed to celt_decoder_destroy");
Jean-Marc Valin269d40a2007-12-07 11:29:45 +11001191 return;
1192 }
Gregory Maxwell17169992009-06-04 15:15:34 -04001193
1194 if (st->marker == DECODERFREED)
1195 {
1196 celt_warning("Freeing a decoder which has already been freed");
Jean-Marc Valin44ffd5a2008-02-22 00:39:25 +11001197 return;
Gregory Maxwell17169992009-06-04 15:15:34 -04001198 }
1199
1200 if (st->marker != DECODERVALID && st->marker != DECODERPARTIAL)
1201 {
1202 celt_warning("This is not a valid CELT decoder structure");
1203 return;
1204 }
1205
1206 /*Check_mode is non-fatal here because we can still free
1207 the encoder memory even if the mode is bad, although calling
1208 the free functions in this order is a violation of the API.*/
1209 check_mode(st->mode);
1210
Jean-Marc Valineafbdd52009-04-27 19:35:09 -04001211 celt_free(st->decode_mem);
Jean-Marc Valin269d40a2007-12-07 11:29:45 +11001212 celt_free(st->oldBandE);
Jean-Marc Valin7351e282008-02-08 15:09:45 +11001213 celt_free(st->preemph_memD);
Gregory Maxwell17169992009-06-04 15:15:34 -04001214
1215 st->marker = DECODERFREED;
1216
Jean-Marc Valin269d40a2007-12-07 11:29:45 +11001217 celt_free(st);
1218}
1219
Jean-Marc Valin56522ad2009-06-05 17:17:25 -04001220/** Handles lost packets by just copying past data with the same
1221 offset as the last
Jean-Marc Valind501f612008-02-21 12:16:57 +11001222 pitch period */
Jean-Marc Valineafbdd52009-04-27 19:35:09 -04001223#ifdef NEW_PLC
1224#include "plc.c"
1225#else
Jean-Marc Valin234969c2009-10-17 22:12:42 -04001226static void celt_decode_lost(CELTDecoder * restrict st, celt_word16 * restrict pcm)
Jean-Marc Valinfb83fb42007-12-08 00:56:04 +11001227{
Jean-Marc Valin05e56c42008-04-10 09:13:05 +10001228 int c, N;
Jean-Marc Valin0bb05bc2008-02-20 13:43:40 +11001229 int pitch_index;
Jean-Marc Valin234969c2009-10-17 22:12:42 -04001230 celt_word16 fade = Q15ONE;
Jean-Marc Valin24c9cda2008-05-02 10:34:07 +10001231 int i, len;
Jean-Marc Valin234969c2009-10-17 22:12:42 -04001232 VARDECL(celt_sig, freq);
Jean-Marc Valin80ed1472009-10-15 21:45:32 -04001233 const int C = CHANNELS(st->channels);
Jean-Marc Valin24c9cda2008-05-02 10:34:07 +10001234 int offset;
Jean-Marc Valin8600f692008-02-29 15:14:12 +11001235 SAVE_STACK;
Jean-Marc Valinfb83fb42007-12-08 00:56:04 +11001236 N = st->block_size;
Jean-Marc Valin234969c2009-10-17 22:12:42 -04001237 ALLOC(freq,C*N, celt_sig); /**< Interleaved signal MDCTs */
Jean-Marc Valinfb83fb42007-12-08 00:56:04 +11001238
Jean-Marc Valin24c9cda2008-05-02 10:34:07 +10001239 len = N+st->mode->overlap;
Jean-Marc Valinfb83fb42007-12-08 00:56:04 +11001240
Jean-Marc Valin0f0da992009-08-12 21:34:01 -04001241 if (st->loss_count == 0)
1242 {
Jean-Marc Valinbf2398b2009-10-15 07:28:19 -04001243 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 -04001244 pitch_index = MAX_PERIOD-len-pitch_index;
1245 st->last_pitch_index = pitch_index;
1246 } else {
1247 pitch_index = st->last_pitch_index;
1248 if (st->loss_count < 5)
1249 fade = QCONST16(.8f,15);
1250 else
1251 fade = 0;
1252 }
Jean-Marc Valinfb83fb42007-12-08 00:56:04 +11001253
Jean-Marc Valin24c9cda2008-05-02 10:34:07 +10001254 offset = MAX_PERIOD-pitch_index;
1255 while (offset+len >= MAX_PERIOD)
1256 offset -= pitch_index;
Jean-Marc Valinbf2398b2009-10-15 07:28:19 -04001257 compute_mdcts(st->mode, 0, st->out_mem+offset*C, freq, C);
Jean-Marc Valin08a82ff2009-06-14 14:05:19 -04001258 for (i=0;i<C*N;i++)
Jean-Marc Valin0f0da992009-08-12 21:34:01 -04001259 freq[i] = ADD32(VERY_SMALL, MULT16_32_Q15(fade,freq[i]));
1260
Jean-Marc Valin24c9cda2008-05-02 10:34:07 +10001261 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 +11001262 /* Compute inverse MDCTs */
Jean-Marc Valinbf2398b2009-10-15 07:28:19 -04001263 compute_inv_mdcts(st->mode, 0, freq, -1, 0, st->out_mem, C);
Jean-Marc Valin1677aa92007-12-08 01:13:34 +11001264
Jean-Marc Valinffa13472007-12-10 16:54:17 +11001265 for (c=0;c<C;c++)
Jean-Marc Valinfb83fb42007-12-08 00:56:04 +11001266 {
Jean-Marc Valinb886ddc2008-03-25 14:38:55 +11001267 int j;
1268 for (j=0;j<N;j++)
Jean-Marc Valinfb83fb42007-12-08 00:56:04 +11001269 {
Jean-Marc Valin234969c2009-10-17 22:12:42 -04001270 celt_sig tmp = MAC16_32_Q15(st->out_mem[C*(MAX_PERIOD-N)+C*j+c],
Jean-Marc Valin1dab60c2008-09-16 13:29:37 -04001271 preemph,st->preemph_memD[c]);
Jean-Marc Valinb886ddc2008-03-25 14:38:55 +11001272 st->preemph_memD[c] = tmp;
Gregory Maxwell5f2a74b2008-08-11 23:50:07 -04001273 pcm[C*j+c] = SCALEOUT(SIG2WORD16(tmp));
Jean-Marc Valinfb83fb42007-12-08 00:56:04 +11001274 }
1275 }
Jean-Marc Valin0f0da992009-08-12 21:34:01 -04001276
1277 st->loss_count++;
1278
Jean-Marc Valin8600f692008-02-29 15:14:12 +11001279 RESTORE_STACK;
Jean-Marc Valinfb83fb42007-12-08 00:56:04 +11001280}
Jean-Marc Valineafbdd52009-04-27 19:35:09 -04001281#endif
Jean-Marc Valinfb83fb42007-12-08 00:56:04 +11001282
Gregory Maxwell5f2a74b2008-08-11 23:50:07 -04001283#ifdef FIXED_POINT
Jean-Marc Valin30f7f812009-10-17 14:35:13 -04001284int celt_decode(CELTDecoder * restrict st, const unsigned char *data, int len, celt_int16 * restrict pcm)
Jean-Marc Valin269d40a2007-12-07 11:29:45 +11001285{
Gregory Maxwell5f2a74b2008-08-11 23:50:07 -04001286#else
Jean-Marc Valin234969c2009-10-17 22:12:42 -04001287int celt_decode_float(CELTDecoder * restrict st, const unsigned char *data, int len, celt_sig * restrict pcm)
Gregory Maxwell5f2a74b2008-08-11 23:50:07 -04001288{
1289#endif
Jean-Marc Valin88619552009-10-04 21:35:36 -04001290 int i, N, N4;
Jean-Marc Valinc9943942008-08-30 00:55:07 -04001291 int has_pitch, has_fold;
Jean-Marc Valin0bb05bc2008-02-20 13:43:40 +11001292 int pitch_index;
Jean-Marc Valinc890b582008-08-01 22:26:49 -04001293 int bits;
Jean-Marc Valin0bb05bc2008-02-20 13:43:40 +11001294 ec_dec dec;
1295 ec_byte_buffer buf;
Jean-Marc Valin234969c2009-10-17 22:12:42 -04001296 VARDECL(celt_sig, freq);
1297 VARDECL(celt_sig, pitch_freq);
1298 VARDECL(celt_norm, X);
1299 VARDECL(celt_ener, bandE);
Jean-Marc Valin6775de32008-08-02 08:14:42 -04001300 VARDECL(int, fine_quant);
1301 VARDECL(int, pulses);
1302 VARDECL(int, offsets);
Jean-Marc Valin52cb5fb2009-06-10 08:08:55 -04001303 VARDECL(int, fine_priority);
Jean-Marc Valinc890b582008-08-01 22:26:49 -04001304
Jean-Marc Valin9d1decd2008-06-17 13:28:13 +10001305 int shortBlocks;
Jean-Marc Valin05ed03e2009-04-29 07:44:13 -04001306 int intra_ener;
Jean-Marc Valin12b22482008-06-16 14:13:05 +10001307 int transient_time;
Jean-Marc Valin528f4b82008-06-29 03:46:39 +10001308 int transient_shift;
Jean-Marc Valinaa936252009-05-29 22:14:20 -04001309 int mdct_weight_shift=0;
Jean-Marc Valin80ed1472009-10-15 21:45:32 -04001310 const int C = CHANNELS(st->channels);
Jean-Marc Valinaa936252009-05-29 22:14:20 -04001311 int mdct_weight_pos=0;
Jean-Marc Valinab220aa2009-09-15 22:38:40 -04001312 int gain_id=0;
Jean-Marc Valin8600f692008-02-29 15:14:12 +11001313 SAVE_STACK;
Jean-Marc Valin44ffd5a2008-02-22 00:39:25 +11001314
Gregory Maxwell17169992009-06-04 15:15:34 -04001315 if (check_decoder(st) != CELT_OK)
1316 return CELT_INVALID_STATE;
1317
Jean-Marc Valin44ffd5a2008-02-22 00:39:25 +11001318 if (check_mode(st->mode) != CELT_OK)
1319 return CELT_INVALID_MODE;
1320
Gregory Maxwell0719f6f2009-07-09 17:07:24 -04001321 if (pcm==NULL)
1322 return CELT_BAD_ARG;
1323
Jean-Marc Valin269d40a2007-12-07 11:29:45 +11001324 N = st->block_size;
Jean-Marc Valina536f772008-03-22 09:01:50 +11001325 N4 = (N-st->overlap)>>1;
Jean-Marc Valin01417232008-03-03 13:59:55 +11001326
Jean-Marc Valin234969c2009-10-17 22:12:42 -04001327 ALLOC(freq, C*N, celt_sig); /**< Interleaved signal MDCTs */
1328 ALLOC(X, C*N, celt_norm); /**< Interleaved normalised MDCTs */
1329 ALLOC(bandE, st->mode->nbEBands*C, celt_ener);
Jean-Marc Valin70c8ffd2007-12-07 14:20:01 +11001330
Jean-Marc Valinfb83fb42007-12-08 00:56:04 +11001331 if (data == NULL)
1332 {
1333 celt_decode_lost(st, pcm);
Jean-Marc Valin8600f692008-02-29 15:14:12 +11001334 RESTORE_STACK;
Jean-Marc Valinfb83fb42007-12-08 00:56:04 +11001335 return 0;
Jean-Marc Valin0f0da992009-08-12 21:34:01 -04001336 } else {
1337 st->loss_count = 0;
Jean-Marc Valinfb83fb42007-12-08 00:56:04 +11001338 }
Gregory Maxwell520eeae2009-02-09 01:33:21 -05001339 if (len<0) {
1340 RESTORE_STACK;
1341 return CELT_BAD_ARG;
1342 }
Jean-Marc Valinfb83fb42007-12-08 00:56:04 +11001343
Jean-Marc Valin05ed03e2009-04-29 07:44:13 -04001344 ec_byte_readinit(&buf,(unsigned char*)data,len);
Jean-Marc Valin70c8ffd2007-12-07 14:20:01 +11001345 ec_dec_init(&dec,&buf);
1346
Jean-Marc Valin05ed03e2009-04-29 07:44:13 -04001347 decode_flags(&dec, &intra_ener, &has_pitch, &shortBlocks, &has_fold);
Gregory Maxwell0527f372008-09-23 19:28:35 -04001348 if (shortBlocks)
1349 {
Jean-Marc Valine6108642009-08-01 23:05:47 +02001350 transient_shift = ec_dec_uint(&dec, 4);
Jean-Marc Valinaa936252009-05-29 22:14:20 -04001351 if (transient_shift == 3)
1352 {
Gregory Maxwell0527f372008-09-23 19:28:35 -04001353 transient_time = ec_dec_uint(&dec, N+st->mode->overlap);
Jean-Marc Valinaa936252009-05-29 22:14:20 -04001354 } else {
1355 mdct_weight_shift = transient_shift;
1356 if (mdct_weight_shift && st->mode->nbShortMdcts>2)
1357 mdct_weight_pos = ec_dec_uint(&dec, st->mode->nbShortMdcts-1);
1358 transient_shift = 0;
Gregory Maxwell0527f372008-09-23 19:28:35 -04001359 transient_time = 0;
Jean-Marc Valinaa936252009-05-29 22:14:20 -04001360 }
Gregory Maxwell0527f372008-09-23 19:28:35 -04001361 } else {
Jean-Marc Valin12b22482008-06-16 14:13:05 +10001362 transient_time = -1;
Jean-Marc Valin528f4b82008-06-29 03:46:39 +10001363 transient_shift = 0;
Jean-Marc Valin12b22482008-06-16 14:13:05 +10001364 }
Jean-Marc Valincb7a2a32008-02-11 16:44:48 +11001365
Jean-Marc Valin7e8a4872008-02-11 16:55:34 +11001366 if (has_pitch)
1367 {
Jean-Marc Valinb886ddc2008-03-25 14:38:55 +11001368 pitch_index = ec_dec_uint(&dec, MAX_PERIOD-(2*N-2*N4));
Jean-Marc Valin4c77ea92009-09-14 22:50:41 -04001369 gain_id = ec_dec_uint(&dec, 16);
Jean-Marc Valin7e8a4872008-02-11 16:55:34 +11001370 } else {
Jean-Marc Valin7e8a4872008-02-11 16:55:34 +11001371 pitch_index = 0;
1372 }
Jean-Marc Valin827f9312008-05-06 23:21:55 +10001373
Jean-Marc Valin6775de32008-08-02 08:14:42 -04001374 ALLOC(fine_quant, st->mode->nbEBands, int);
Jean-Marc Valin827f9312008-05-06 23:21:55 +10001375 /* Get band energies */
Jean-Marc Valinab4dcc52009-10-21 07:08:27 -04001376 unquant_coarse_energy(st->mode, bandE, st->oldBandE, len*8-16, intra_ener, st->mode->prob, &dec, C);
Jean-Marc Valin6775de32008-08-02 08:14:42 -04001377
1378 ALLOC(pulses, st->mode->nbEBands, int);
1379 ALLOC(offsets, st->mode->nbEBands, int);
Jean-Marc Valin52cb5fb2009-06-10 08:08:55 -04001380 ALLOC(fine_priority, st->mode->nbEBands, int);
Jean-Marc Valin6775de32008-08-02 08:14:42 -04001381
1382 for (i=0;i<st->mode->nbEBands;i++)
1383 offsets[i] = 0;
1384
1385 bits = len*8 - ec_dec_tell(&dec, 0) - 1;
Jean-Marc Valinbf2398b2009-10-15 07:28:19 -04001386 compute_allocation(st->mode, offsets, bits, pulses, fine_quant, fine_priority, C);
Jean-Marc Valin6775de32008-08-02 08:14:42 -04001387 /*bits = ec_dec_tell(&dec, 0);
1388 compute_fine_allocation(st->mode, fine_quant, (20*C+len*8/5-(ec_dec_tell(&dec, 0)-bits))/C);*/
1389
Jean-Marc Valinbf2398b2009-10-15 07:28:19 -04001390 unquant_fine_energy(st->mode, bandE, st->oldBandE, fine_quant, &dec, C);
Jean-Marc Valin827f9312008-05-06 23:21:55 +10001391
Jean-Marc Valin234969c2009-10-17 22:12:42 -04001392 ALLOC(pitch_freq, C*N, celt_sig); /**< Interleaved signal MDCTs */
Jean-Marc Valinc9943942008-08-30 00:55:07 -04001393 if (has_pitch)
Jean-Marc Valin269d40a2007-12-07 11:29:45 +11001394 {
Jean-Marc Valinc9943942008-08-30 00:55:07 -04001395 /* Pitch MDCT */
Jean-Marc Valinbf2398b2009-10-15 07:28:19 -04001396 compute_mdcts(st->mode, 0, st->out_mem+pitch_index*C, pitch_freq, C);
Jean-Marc Valin269d40a2007-12-07 11:29:45 +11001397 }
1398
Jean-Marc Valin70c8ffd2007-12-07 14:20:01 +11001399 /* Decode fixed codebook and merge with pitch */
Jean-Marc Valinca53b7c2009-03-26 20:23:14 -04001400 if (C==1)
Jean-Marc Valina9947c42009-10-08 23:10:45 -04001401 quant_bands(st->mode, X, bandE, pulses, shortBlocks, has_fold, len*8, 0, &dec);
Jean-Marc Valin73532032009-06-02 20:07:25 -04001402#ifndef DISABLE_STEREO
Jean-Marc Valinca53b7c2009-03-26 20:23:14 -04001403 else
Jean-Marc Valind5e54362009-09-30 20:50:41 -04001404 unquant_bands_stereo(st->mode, X, bandE, pulses, shortBlocks, has_fold, len*8, &dec);
Jean-Marc Valin73532032009-06-02 20:07:25 -04001405#endif
Jean-Marc Valinbf2398b2009-10-15 07:28:19 -04001406 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 -04001407
Jean-Marc Valin88619552009-10-04 21:35:36 -04001408 if (mdct_weight_shift)
1409 {
Jean-Marc Valinbf2398b2009-10-15 07:28:19 -04001410 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 -04001411 }
1412
Jean-Marc Valina4833ff2008-01-10 15:34:00 +11001413 /* Synthesis */
Jean-Marc Valinbf2398b2009-10-15 07:28:19 -04001414 denormalise_bands(st->mode, X, freq, bandE, C);
Jean-Marc Valina4833ff2008-01-10 15:34:00 +11001415
1416
Jean-Marc Valineafbdd52009-04-27 19:35:09 -04001417 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 -04001418
Jean-Marc Valin4c77ea92009-09-14 22:50:41 -04001419 if (has_pitch)
Jean-Marc Valinbf2398b2009-10-15 07:28:19 -04001420 apply_pitch(st->mode, freq, pitch_freq, gain_id, 0, C);
Jean-Marc Valin4c77ea92009-09-14 22:50:41 -04001421
Jean-Marc Valin269d40a2007-12-07 11:29:45 +11001422 /* Compute inverse MDCTs */
Jean-Marc Valinbf2398b2009-10-15 07:28:19 -04001423 compute_inv_mdcts(st->mode, shortBlocks, freq, transient_time, transient_shift, st->out_mem, C);
Jean-Marc Valinffa13472007-12-10 16:54:17 +11001424
Jean-Marc Valine12017e2009-10-03 13:57:31 -04001425 deemphasis(st->out_mem, pcm, N, C, preemph, st->preemph_memD);
Jean-Marc Valin388f1d62008-01-18 16:28:11 +11001426
Jean-Marc Valin8600f692008-02-29 15:14:12 +11001427 RESTORE_STACK;
Jean-Marc Valinfb83fb42007-12-08 00:56:04 +11001428 return 0;
Jean-Marc Valin269d40a2007-12-07 11:29:45 +11001429}
1430
Gregory Maxwell5f2a74b2008-08-11 23:50:07 -04001431#ifdef FIXED_POINT
1432#ifndef DISABLE_FLOAT_API
Jean-Marc Valin6db6cbd2009-04-11 22:01:20 -04001433int celt_decode_float(CELTDecoder * restrict st, const unsigned char *data, int len, float * restrict pcm)
Gregory Maxwell5f2a74b2008-08-11 23:50:07 -04001434{
Gregory Maxwell17169992009-06-04 15:15:34 -04001435 int j, ret, C, N;
Jean-Marc Valin30f7f812009-10-17 14:35:13 -04001436 VARDECL(celt_int16, out);
Jean-Marc Valincb8780c2009-07-20 23:40:35 -04001437 SAVE_STACK;
Gregory Maxwell17169992009-06-04 15:15:34 -04001438
1439 if (check_decoder(st) != CELT_OK)
1440 return CELT_INVALID_STATE;
1441
1442 if (check_mode(st->mode) != CELT_OK)
1443 return CELT_INVALID_MODE;
1444
Gregory Maxwell0719f6f2009-07-09 17:07:24 -04001445 if (pcm==NULL)
1446 return CELT_BAD_ARG;
1447
Jean-Marc Valin80ed1472009-10-15 21:45:32 -04001448 C = CHANNELS(st->channels);
Gregory Maxwell17169992009-06-04 15:15:34 -04001449 N = st->block_size;
Gregory Maxwell0719f6f2009-07-09 17:07:24 -04001450
Jean-Marc Valin30f7f812009-10-17 14:35:13 -04001451 ALLOC(out, C*N, celt_int16);
Gregory Maxwell5f2a74b2008-08-11 23:50:07 -04001452 ret=celt_decode(st, data, len, out);
Gregory Maxwell5f2a74b2008-08-11 23:50:07 -04001453 for (j=0;j<C*N;j++)
Gregory Maxwell0719f6f2009-07-09 17:07:24 -04001454 pcm[j]=out[j]*(1/32768.);
1455
Wessel Lubberhuizen33ba6cc2008-10-03 07:09:29 -04001456 RESTORE_STACK;
Gregory Maxwell5f2a74b2008-08-11 23:50:07 -04001457 return ret;
1458}
1459#endif /*DISABLE_FLOAT_API*/
1460#else
Jean-Marc Valin30f7f812009-10-17 14:35:13 -04001461int celt_decode(CELTDecoder * restrict st, const unsigned char *data, int len, celt_int16 * restrict pcm)
Gregory Maxwell5f2a74b2008-08-11 23:50:07 -04001462{
Gregory Maxwell17169992009-06-04 15:15:34 -04001463 int j, ret, C, N;
Jean-Marc Valin234969c2009-10-17 22:12:42 -04001464 VARDECL(celt_sig, out);
Jean-Marc Valincb8780c2009-07-20 23:40:35 -04001465 SAVE_STACK;
Gregory Maxwell17169992009-06-04 15:15:34 -04001466
1467 if (check_decoder(st) != CELT_OK)
1468 return CELT_INVALID_STATE;
1469
1470 if (check_mode(st->mode) != CELT_OK)
1471 return CELT_INVALID_MODE;
1472
Gregory Maxwell0719f6f2009-07-09 17:07:24 -04001473 if (pcm==NULL)
1474 return CELT_BAD_ARG;
1475
Jean-Marc Valin80ed1472009-10-15 21:45:32 -04001476 C = CHANNELS(st->channels);
Gregory Maxwell17169992009-06-04 15:15:34 -04001477 N = st->block_size;
Jean-Marc Valin234969c2009-10-17 22:12:42 -04001478 ALLOC(out, C*N, celt_sig);
Gregory Maxwell5f2a74b2008-08-11 23:50:07 -04001479
1480 ret=celt_decode_float(st, data, len, out);
1481
1482 for (j=0;j<C*N;j++)
Gregory Maxwell0719f6f2009-07-09 17:07:24 -04001483 pcm[j] = FLOAT2INT16 (out[j]);
1484
Wessel Lubberhuizen33ba6cc2008-10-03 07:09:29 -04001485 RESTORE_STACK;
Gregory Maxwell5f2a74b2008-08-11 23:50:07 -04001486 return ret;
1487}
1488#endif
John Ridges454d1d02009-05-21 22:38:39 -04001489
1490int celt_decoder_ctl(CELTDecoder * restrict st, int request, ...)
1491{
1492 va_list ap;
Gregory Maxwell17169992009-06-04 15:15:34 -04001493
1494 if (check_decoder(st) != CELT_OK)
1495 return CELT_INVALID_STATE;
1496
John Ridges454d1d02009-05-21 22:38:39 -04001497 va_start(ap, request);
Gregory Maxwell17169992009-06-04 15:15:34 -04001498 if ((request!=CELT_GET_MODE_REQUEST) && (check_mode(st->mode) != CELT_OK))
1499 goto bad_mode;
John Ridges454d1d02009-05-21 22:38:39 -04001500 switch (request)
1501 {
Gregory Maxwellf3b44ef2009-06-03 13:37:45 -04001502 case CELT_GET_MODE_REQUEST:
1503 {
1504 const CELTMode ** value = va_arg(ap, const CELTMode**);
1505 if (value==0)
1506 goto bad_arg;
1507 *value=st->mode;
1508 }
1509 break;
John Ridges454d1d02009-05-21 22:38:39 -04001510 case CELT_RESET_STATE:
1511 {
1512 const CELTMode *mode = st->mode;
Jean-Marc Valin80ed1472009-10-15 21:45:32 -04001513 int C = st->channels;
John Ridges454d1d02009-05-21 22:38:39 -04001514
1515 CELT_MEMSET(st->decode_mem, 0, (DECODE_BUFFER_SIZE+st->overlap)*C);
1516 CELT_MEMSET(st->oldBandE, 0, C*mode->nbEBands);
1517
1518 CELT_MEMSET(st->preemph_memD, 0, C);
1519
Jean-Marc Valin0f0da992009-08-12 21:34:01 -04001520 st->loss_count = 0;
John Ridges454d1d02009-05-21 22:38:39 -04001521 }
1522 break;
1523 default:
1524 goto bad_request;
1525 }
1526 va_end(ap);
1527 return CELT_OK;
Gregory Maxwell17169992009-06-04 15:15:34 -04001528bad_mode:
1529 va_end(ap);
1530 return CELT_INVALID_MODE;
John Ridges454d1d02009-05-21 22:38:39 -04001531bad_arg:
1532 va_end(ap);
1533 return CELT_BAD_ARG;
John Ridges454d1d02009-05-21 22:38:39 -04001534bad_request:
1535 va_end(ap);
1536 return CELT_UNIMPLEMENTED;
1537}
Jean-Marc Valinece94a02009-10-16 07:30:14 -04001538
1539const char *celt_strerror(int error)
1540{
1541 static const char *error_strings[8] = {
1542 "success",
1543 "invalid argument",
1544 "invalid mode",
1545 "internal error",
1546 "corrupted stream",
1547 "request not implemented",
1548 "invalid state",
1549 "memory allocation failed"
1550 };
1551 if (error > 0 || error < -7)
1552 return "unknown error";
1553 else
1554 return error_strings[-error];
1555}
1556