blob: 90c484db37dc87add0fb5d37f368249a8eb568b2 [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 Valin991c0f02007-11-30 16:07:46 +110045#include "bands.h"
Jean-Marc Valinecb36a32007-12-05 01:31:49 +110046#include "modes.h"
Jean-Marc Valin6238bc02008-01-28 22:28:54 +110047#include "entcode.h"
Jean-Marc Valin98d2a492007-12-07 22:46:47 +110048#include "quant_bands.h"
Jean-Marc Valin4fbd18d2008-01-17 14:07:55 +110049#include "rate.h"
Jean-Marc Valinc7e0b762008-03-16 07:55:29 +110050#include "stack_alloc.h"
Jean-Marc Valine4aeb472008-06-29 12:06:05 +100051#include "mathops.h"
Jean-Marc Valind9b95652008-08-31 23:34:47 -040052#include "float_cast.h"
Jean-Marc Valinb6f90612008-10-05 22:39:13 -040053#include <stdarg.h>
Jean-Marc Valin013c31d2007-11-30 11:36:46 +110054
Jean-Marc Valin5a0fae52009-12-14 21:19:37 -050055#define LPC_ORDER 24
Jean-Marc Valin303b3b62009-12-30 22:40:24 -050056/* #define NEW_PLC */
Jean-Marc Valind69c1cb2009-12-28 00:34:29 -050057#if !defined(FIXED_POINT) || defined(NEW_PLC)
58#include "plc.c"
59#endif
Jean-Marc Valin5a0fae52009-12-14 21:19:37 -050060
Jean-Marc Valin234969c2009-10-17 22:12:42 -040061static const celt_word16 preemph = QCONST16(0.8f,15);
Jean-Marc Valin07586892008-03-03 17:19:17 +110062
Jean-Marc Valin528f4b82008-06-29 03:46:39 +100063#ifdef FIXED_POINT
Jean-Marc Valin234969c2009-10-17 22:12:42 -040064static const celt_word16 transientWindow[16] = {
Jean-Marc Valin528f4b82008-06-29 03:46:39 +100065 279, 1106, 2454, 4276, 6510, 9081, 11900, 14872,
66 17896, 20868, 23687, 26258, 28492, 30314, 31662, 32489};
67#else
68static const float transientWindow[16] = {
Jean-Marc Valin56522ad2009-06-05 17:17:25 -040069 0.0085135, 0.0337639, 0.0748914, 0.1304955,
70 0.1986827, 0.2771308, 0.3631685, 0.4538658,
71 0.5461342, 0.6368315, 0.7228692, 0.8013173,
72 0.8695045, 0.9251086, 0.9662361, 0.9914865};
Jean-Marc Valin528f4b82008-06-29 03:46:39 +100073#endif
74
Gregory Maxwell17169992009-06-04 15:15:34 -040075#define ENCODERVALID 0x4c434554
76#define ENCODERPARTIAL 0x5445434c
77#define ENCODERFREED 0x4c004500
Jean-Marc Valinc9943942008-08-30 00:55:07 -040078
Jean-Marc Valin276de722008-02-20 17:45:51 +110079/** Encoder state
80 @brief Encoder state
81 */
Jean-Marc Valin269d40a2007-12-07 11:29:45 +110082struct CELTEncoder {
Jean-Marc Valin30f7f812009-10-17 14:35:13 -040083 celt_uint32 marker;
Jean-Marc Valin276de722008-02-20 17:45:51 +110084 const CELTMode *mode; /**< Mode used by the encoder */
Jean-Marc Valin8ebd3452007-11-29 20:17:32 +110085 int frame_size;
86 int block_size;
Jean-Marc Valina5431bf2008-01-03 20:53:01 +110087 int overlap;
Jean-Marc Valinffa13472007-12-10 16:54:17 +110088 int channels;
89
Gregory Maxwell2dd3d322009-06-05 14:05:51 -040090 int pitch_enabled; /* Complexity level is allowed to use pitch */
91 int pitch_permitted; /* Use of the LTP is permitted by the user */
92 int pitch_available; /* Amount of pitch buffer available */
93 int force_intra;
Jean-Marc Valin74f4e9f2009-05-02 09:57:50 -040094 int delayedIntra;
Jean-Marc Valin234969c2009-10-17 22:12:42 -040095 celt_word16 tonal_average;
Jean-Marc Valin527db5c2009-06-02 07:56:19 -040096 int fold_decision;
Jean-Marc Valin234969c2009-10-17 22:12:42 -040097 celt_word16 gain_prod;
Jean-Marc Valin9c30de52010-04-19 13:32:15 -040098 celt_word32 frame_max;
Jean-Marc Valin527db5c2009-06-02 07:56:19 -040099
Jean-Marc Valinbd5d54a2009-10-20 00:25:31 -0400100 /* VBR-related parameters */
101 celt_int32 vbr_reservoir;
102 celt_int32 vbr_drift;
103 celt_int32 vbr_offset;
104 celt_int32 vbr_count;
105
106 celt_int32 vbr_rate; /* Target number of 16th bits per frame */
Jean-Marc Valin234969c2009-10-17 22:12:42 -0400107 celt_word16 * restrict preemph_memE;
108 celt_sig * restrict preemph_memD;
Jean-Marc Valin81b38c22008-02-29 21:08:49 +1100109
Jean-Marc Valin234969c2009-10-17 22:12:42 -0400110 celt_sig *in_mem;
111 celt_sig *out_mem;
Jean-Marc Valin294863b2009-11-08 22:29:54 +0900112 celt_word16 *pitch_buf;
113 celt_sig xmem;
Jean-Marc Valin991c0f02007-11-30 16:07:46 +1100114
Jean-Marc Valin234969c2009-10-17 22:12:42 -0400115 celt_word16 *oldBandE;
Jean-Marc Valin8ebd3452007-11-29 20:17:32 +1100116};
117
Jean-Marc Valine12017e2009-10-03 13:57:31 -0400118static int check_encoder(const CELTEncoder *st)
Gregory Maxwell17169992009-06-04 15:15:34 -0400119{
120 if (st==NULL)
121 {
122 celt_warning("NULL passed as an encoder structure");
123 return CELT_INVALID_STATE;
124 }
125 if (st->marker == ENCODERVALID)
126 return CELT_OK;
127 if (st->marker == ENCODERFREED)
128 celt_warning("Referencing an encoder that has already been freed");
129 else
130 celt_warning("This is not a valid CELT encoder structure");
131 return CELT_INVALID_STATE;
132}
133
Jean-Marc Valin80ed1472009-10-15 21:45:32 -0400134CELTEncoder *celt_encoder_create(const CELTMode *mode, int channels, int *error)
Jean-Marc Valin8ebd3452007-11-29 20:17:32 +1100135{
Jean-Marc Valinb886ddc2008-03-25 14:38:55 +1100136 int N, C;
Jean-Marc Valin02fa9132008-02-20 12:09:29 +1100137 CELTEncoder *st;
Jean-Marc Valin44ffd5a2008-02-22 00:39:25 +1100138
139 if (check_mode(mode) != CELT_OK)
Jean-Marc Valinece94a02009-10-16 07:30:14 -0400140 {
141 if (error)
142 *error = CELT_INVALID_MODE;
Jean-Marc Valin44ffd5a2008-02-22 00:39:25 +1100143 return NULL;
Jean-Marc Valinece94a02009-10-16 07:30:14 -0400144 }
Jean-Marc Valinbd5d54a2009-10-20 00:25:31 -0400145#ifdef DISABLE_STEREO
146 if (channels > 1)
147 {
148 celt_warning("Stereo support was disable from this build");
149 if (error)
150 *error = CELT_BAD_ARG;
151 return NULL;
152 }
153#endif
154
Jean-Marc Valin80ed1472009-10-15 21:45:32 -0400155 if (channels < 0 || channels > 2)
156 {
157 celt_warning("Only mono and stereo supported");
158 if (error)
159 *error = CELT_BAD_ARG;
160 return NULL;
161 }
Jean-Marc Valin44ffd5a2008-02-22 00:39:25 +1100162
Jean-Marc Valin73e51b32007-12-05 17:48:24 +1100163 N = mode->mdctSize;
Jean-Marc Valin80ed1472009-10-15 21:45:32 -0400164 C = channels;
Jean-Marc Valin02fa9132008-02-20 12:09:29 +1100165 st = celt_alloc(sizeof(CELTEncoder));
Jean-Marc Valin8ebd3452007-11-29 20:17:32 +1100166
Jean-Marc Valinece94a02009-10-16 07:30:14 -0400167 if (st==NULL)
168 {
169 if (error)
170 *error = CELT_ALLOC_FAIL;
Jean-Marc Valin80ed1472009-10-15 21:45:32 -0400171 return NULL;
Jean-Marc Valinece94a02009-10-16 07:30:14 -0400172 }
Gregory Maxwell17169992009-06-04 15:15:34 -0400173 st->marker = ENCODERPARTIAL;
Jean-Marc Valin73e51b32007-12-05 17:48:24 +1100174 st->mode = mode;
Jean-Marc Valinb886ddc2008-03-25 14:38:55 +1100175 st->frame_size = N;
Jean-Marc Valin73e51b32007-12-05 17:48:24 +1100176 st->block_size = N;
Jean-Marc Valina5431bf2008-01-03 20:53:01 +1100177 st->overlap = mode->overlap;
Jean-Marc Valin80ed1472009-10-15 21:45:32 -0400178 st->channels = channels;
Jean-Marc Valina5431bf2008-01-03 20:53:01 +1100179
Jean-Marc Valinbd5d54a2009-10-20 00:25:31 -0400180 st->vbr_rate = 0;
Jean-Marc Valinc9943942008-08-30 00:55:07 -0400181 st->pitch_enabled = 1;
Gregory Maxwell2dd3d322009-06-05 14:05:51 -0400182 st->pitch_permitted = 1;
Gregory Maxwell98046ca2008-12-13 20:42:03 -0500183 st->pitch_available = 1;
Gregory Maxwell2dd3d322009-06-05 14:05:51 -0400184 st->force_intra = 0;
Gregory Maxwell8842fde2009-05-04 15:58:40 -0400185 st->delayedIntra = 1;
Jean-Marc Valin628c0252010-04-16 20:57:56 -0400186 st->tonal_average = QCONST16(1.f,8);
Jean-Marc Valin527db5c2009-06-02 07:56:19 -0400187 st->fold_decision = 1;
Jean-Marc Valina76a0b22008-01-17 22:43:05 +1100188
Jean-Marc Valin234969c2009-10-17 22:12:42 -0400189 st->in_mem = celt_alloc(st->overlap*C*sizeof(celt_sig));
190 st->out_mem = celt_alloc((MAX_PERIOD+st->overlap)*C*sizeof(celt_sig));
Jean-Marc Valine465c142009-11-26 00:39:36 -0500191 st->pitch_buf = celt_alloc(((MAX_PERIOD>>1)+2)*sizeof(celt_word16));
Jean-Marc Valin81b38c22008-02-29 21:08:49 +1100192
Jean-Marc Valin234969c2009-10-17 22:12:42 -0400193 st->oldBandE = (celt_word16*)celt_alloc(C*mode->nbEBands*sizeof(celt_word16));
Jean-Marc Valinfa248732007-12-06 07:51:27 +1100194
Jean-Marc Valin234969c2009-10-17 22:12:42 -0400195 st->preemph_memE = (celt_word16*)celt_alloc(C*sizeof(celt_word16));
196 st->preemph_memD = (celt_sig*)celt_alloc(C*sizeof(celt_sig));
Jean-Marc Valinffa13472007-12-10 16:54:17 +1100197
Gregory Maxwell17169992009-06-04 15:15:34 -0400198 if ((st->in_mem!=NULL) && (st->out_mem!=NULL) && (st->oldBandE!=NULL)
Gregory Maxwell17169992009-06-04 15:15:34 -0400199 && (st->preemph_memE!=NULL) && (st->preemph_memD!=NULL))
200 {
Jean-Marc Valinece94a02009-10-16 07:30:14 -0400201 if (error)
202 *error = CELT_OK;
Gregory Maxwell17169992009-06-04 15:15:34 -0400203 st->marker = ENCODERVALID;
204 return st;
205 }
206 /* If the setup fails for some reason deallocate it. */
207 celt_encoder_destroy(st);
Jean-Marc Valinece94a02009-10-16 07:30:14 -0400208 if (error)
209 *error = CELT_ALLOC_FAIL;
Gregory Maxwell17169992009-06-04 15:15:34 -0400210 return NULL;
Jean-Marc Valin8ebd3452007-11-29 20:17:32 +1100211}
212
Peter Kirk19f9dc92008-06-06 14:38:38 +0200213void celt_encoder_destroy(CELTEncoder *st)
Jean-Marc Valin14191b32007-11-30 12:15:49 +1100214{
215 if (st == NULL)
216 {
217 celt_warning("NULL passed to celt_encoder_destroy");
218 return;
219 }
Jean-Marc Valin44ffd5a2008-02-22 00:39:25 +1100220
Gregory Maxwell17169992009-06-04 15:15:34 -0400221 if (st->marker == ENCODERFREED)
222 {
Gregory Maxwell17169992009-06-04 15:15:34 -0400223 celt_warning("Freeing an encoder which has already been freed");
Gregory Maxwelldc67fa92009-06-04 17:17:35 -0400224 return;
Gregory Maxwell17169992009-06-04 15:15:34 -0400225 }
226
227 if (st->marker != ENCODERVALID && st->marker != ENCODERPARTIAL)
228 {
229 celt_warning("This is not a valid CELT encoder structure");
230 return;
231 }
232 /*Check_mode is non-fatal here because we can still free
233 the encoder memory even if the mode is bad, although calling
234 the free functions in this order is a violation of the API.*/
235 check_mode(st->mode);
236
Jean-Marc Valin14191b32007-11-30 12:15:49 +1100237 celt_free(st->in_mem);
Jean-Marc Valin14191b32007-11-30 12:15:49 +1100238 celt_free(st->out_mem);
Jean-Marc Valin1ccfd3c2009-12-02 21:07:11 -0500239 celt_free(st->pitch_buf);
Jean-Marc Valinc245a222007-12-06 19:14:20 +1100240 celt_free(st->oldBandE);
Jean-Marc Valin7351e282008-02-08 15:09:45 +1100241
242 celt_free(st->preemph_memE);
243 celt_free(st->preemph_memD);
Jean-Marc Valine05e7e22009-11-21 23:41:26 -0500244
Gregory Maxwell17169992009-06-04 15:15:34 -0400245 st->marker = ENCODERFREED;
Jean-Marc Valinc6ca4992008-06-01 23:19:16 +1000246
Jean-Marc Valin14191b32007-11-30 12:15:49 +1100247 celt_free(st);
248}
249
Jean-Marc Valin30f7f812009-10-17 14:35:13 -0400250static inline celt_int16 FLOAT2INT16(float x)
Jean-Marc Valin42074382008-02-27 11:08:53 +1100251{
Gregory Maxwell0ac2b2f2009-05-21 23:08:46 -0400252 x = x*CELT_SIG_SCALE;
Gregory Maxwell5f2a74b2008-08-11 23:50:07 -0400253 x = MAX32(x, -32768);
254 x = MIN32(x, 32767);
Jean-Marc Valin30f7f812009-10-17 14:35:13 -0400255 return (celt_int16)float2int(x);
Gregory Maxwell5f2a74b2008-08-11 23:50:07 -0400256}
257
Jean-Marc Valin234969c2009-10-17 22:12:42 -0400258static inline celt_word16 SIG2WORD16(celt_sig x)
Gregory Maxwell5f2a74b2008-08-11 23:50:07 -0400259{
260#ifdef FIXED_POINT
Jean-Marc Valin42074382008-02-27 11:08:53 +1100261 x = PSHR32(x, SIG_SHIFT);
Jean-Marc Valinabdfc382008-04-18 15:57:18 +1000262 x = MAX32(x, -32768);
263 x = MIN32(x, 32767);
Jean-Marc Valin42074382008-02-27 11:08:53 +1100264 return EXTRACT16(x);
265#else
Jean-Marc Valin234969c2009-10-17 22:12:42 -0400266 return (celt_word16)x;
Jean-Marc Valin42074382008-02-27 11:08:53 +1100267#endif
268}
269
Jean-Marc Valin9c30de52010-04-19 13:32:15 -0400270static int transient_analysis(const celt_word32 * restrict in, int len, int C,
271 int *transient_time, int *transient_shift,
272 celt_word32 *frame_max)
Jean-Marc Valin9375aa42008-06-27 07:57:35 +1000273{
Jean-Marc Valin9c30de52010-04-19 13:32:15 -0400274 int i, n;
Jean-Marc Valin234969c2009-10-17 22:12:42 -0400275 celt_word32 ratio;
Jean-Marc Valin9c30de52010-04-19 13:32:15 -0400276 celt_word32 threshold;
Jean-Marc Valin234969c2009-10-17 22:12:42 -0400277 VARDECL(celt_word32, begin);
Jean-Marc Valin0ceccb22008-07-03 20:41:06 -0400278 SAVE_STACK;
Jean-Marc Valin9c30de52010-04-19 13:32:15 -0400279 ALLOC(begin, len+1, celt_word32);
280 begin[0] = 0;
281 if (C==1)
Jean-Marc Valin9375aa42008-06-27 07:57:35 +1000282 {
283 for (i=0;i<len;i++)
Jean-Marc Valin9c30de52010-04-19 13:32:15 -0400284 begin[i+1] = MAX32(begin[i], ABS32(in[i]));
285 } else {
286 for (i=0;i<len;i++)
287 begin[i+1] = MAX32(begin[i], MAX32(ABS32(in[C*i]),
288 ABS32(in[C*i+1])));
Jean-Marc Valin9375aa42008-06-27 07:57:35 +1000289 }
Jean-Marc Valin9375aa42008-06-27 07:57:35 +1000290 n = -1;
Jean-Marc Valin9c30de52010-04-19 13:32:15 -0400291
292 threshold = MULT16_32_Q15(QCONST16(.2f,15),begin[len]);
293 /* If the following condition isn't met, there's just no way
294 we'll have a transient*/
295 if (*frame_max < threshold)
Jean-Marc Valin9375aa42008-06-27 07:57:35 +1000296 {
Jean-Marc Valin9c30de52010-04-19 13:32:15 -0400297 /* It's likely we have a transient, now find it */
298 for (i=8;i<len-8;i++)
299 {
300 if (begin[i+1] < threshold)
301 n=i;
302 }
Jean-Marc Valin9375aa42008-06-27 07:57:35 +1000303 }
Jean-Marc Valin9375aa42008-06-27 07:57:35 +1000304 if (n<32)
305 {
306 n = -1;
307 ratio = 0;
Jean-Marc Valinbd7de0a2008-07-06 10:57:26 -0400308 } else {
Jean-Marc Valin9c30de52010-04-19 13:32:15 -0400309 ratio = DIV32(begin[len],1+MAX32(*frame_max, begin[n-16]));
Jean-Marc Valin9375aa42008-06-27 07:57:35 +1000310 }
Jean-Marc Valinf4578192008-07-04 16:47:28 -0400311 if (ratio < 0)
312 ratio = 0;
313 if (ratio > 1000)
314 ratio = 1000;
Jean-Marc Valinbd7de0a2008-07-06 10:57:26 -0400315 ratio *= ratio;
Jean-Marc Valin9c30de52010-04-19 13:32:15 -0400316
Jean-Marc Valinaa936252009-05-29 22:14:20 -0400317 if (ratio > 2048)
Jean-Marc Valinbd7de0a2008-07-06 10:57:26 -0400318 *transient_shift = 3;
Jean-Marc Valinaa936252009-05-29 22:14:20 -0400319 else
320 *transient_shift = 0;
321
Jean-Marc Valinbd7de0a2008-07-06 10:57:26 -0400322 *transient_time = n;
Jean-Marc Valin9c30de52010-04-19 13:32:15 -0400323 *frame_max = begin[len];
324
Jean-Marc Valin0ceccb22008-07-03 20:41:06 -0400325 RESTORE_STACK;
Jean-Marc Valinbd7de0a2008-07-06 10:57:26 -0400326 return ratio > 20;
Jean-Marc Valin9375aa42008-06-27 07:57:35 +1000327}
328
Jean-Marc Valin56522ad2009-06-05 17:17:25 -0400329/** Apply window and compute the MDCT for all sub-frames and
330 all channels in a frame */
Jean-Marc Valin234969c2009-10-17 22:12:42 -0400331static 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 +1100332{
Jean-Marc Valinbf2398b2009-10-15 07:28:19 -0400333 const int C = CHANNELS(_C);
Jean-Marc Valin9d1decd2008-06-17 13:28:13 +1000334 if (C==1 && !shortBlocks)
Jean-Marc Valinda721882007-11-30 15:17:42 +1100335 {
Jean-Marc Valin9d1decd2008-06-17 13:28:13 +1000336 const mdct_lookup *lookup = MDCT(mode);
337 const int overlap = OVERLAP(mode);
Jean-Marc Valin6d584ac2009-11-21 21:57:44 -0500338 clt_mdct_forward(lookup, in, out, mode->window, overlap);
Jean-Marc Valinaa4f58b2009-10-03 09:27:59 -0400339 } else {
Jean-Marc Valin9d1decd2008-06-17 13:28:13 +1000340 const mdct_lookup *lookup = MDCT(mode);
341 const int overlap = OVERLAP(mode);
Jean-Marc Valinaa4f58b2009-10-03 09:27:59 -0400342 int N = FRAMESIZE(mode);
343 int B = 1;
Jean-Marc Valin9d1decd2008-06-17 13:28:13 +1000344 int b, c;
Jean-Marc Valin234969c2009-10-17 22:12:42 -0400345 VARDECL(celt_word32, x);
346 VARDECL(celt_word32, tmp);
Jean-Marc Valin9d1decd2008-06-17 13:28:13 +1000347 SAVE_STACK;
Jean-Marc Valinaa4f58b2009-10-03 09:27:59 -0400348 if (shortBlocks)
349 {
350 lookup = &mode->shortMdct;
351 N = mode->shortMdctSize;
352 B = mode->nbShortMdcts;
353 }
Jean-Marc Valin234969c2009-10-17 22:12:42 -0400354 ALLOC(x, N+overlap, celt_word32);
355 ALLOC(tmp, N, celt_word32);
Jean-Marc Valin9d1decd2008-06-17 13:28:13 +1000356 for (c=0;c<C;c++)
357 {
Jean-Marc Valin9d1decd2008-06-17 13:28:13 +1000358 for (b=0;b<B;b++)
359 {
360 int j;
361 for (j=0;j<N+overlap;j++)
362 x[j] = in[C*(b*N+j)+c];
Jean-Marc Valin6d584ac2009-11-21 21:57:44 -0500363 clt_mdct_forward(lookup, x, tmp, mode->window, overlap);
Jean-Marc Valin9d1decd2008-06-17 13:28:13 +1000364 /* Interleaving the sub-frames */
365 for (j=0;j<N;j++)
Jean-Marc Valin08a82ff2009-06-14 14:05:19 -0400366 out[(j*B+b)+c*N*B] = tmp[j];
Jean-Marc Valin9d1decd2008-06-17 13:28:13 +1000367 }
368 }
369 RESTORE_STACK;
Jean-Marc Valinda721882007-11-30 15:17:42 +1100370 }
Jean-Marc Valinda721882007-11-30 15:17:42 +1100371}
372
Jean-Marc Valin56522ad2009-06-05 17:17:25 -0400373/** Compute the IMDCT and apply window for all sub-frames and
374 all channels in a frame */
Jean-Marc Valin234969c2009-10-17 22:12:42 -0400375static 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 +1100376{
Jean-Marc Valinb886ddc2008-03-25 14:38:55 +1100377 int c, N4;
Jean-Marc Valinbf2398b2009-10-15 07:28:19 -0400378 const int C = CHANNELS(_C);
Jean-Marc Valinb18ec0b2008-04-11 04:07:52 +1000379 const int N = FRAMESIZE(mode);
380 const int overlap = OVERLAP(mode);
Jean-Marc Valina536f772008-03-22 09:01:50 +1100381 N4 = (N-overlap)>>1;
Jean-Marc Valinffa13472007-12-10 16:54:17 +1100382 for (c=0;c<C;c++)
Jean-Marc Valin1677aa92007-12-08 01:13:34 +1100383 {
Jean-Marc Valinb886ddc2008-03-25 14:38:55 +1100384 int j;
Jean-Marc Valin528f4b82008-06-29 03:46:39 +1000385 if (transient_shift==0 && C==1 && !shortBlocks) {
Jean-Marc Valin9d1decd2008-06-17 13:28:13 +1000386 const mdct_lookup *lookup = MDCT(mode);
Jean-Marc Valin6d584ac2009-11-21 21:57:44 -0500387 clt_mdct_backward(lookup, X, out_mem+C*(MAX_PERIOD-N-N4), mode->window, overlap);
Jean-Marc Valin9d1decd2008-06-17 13:28:13 +1000388 } else {
Jean-Marc Valin234969c2009-10-17 22:12:42 -0400389 VARDECL(celt_word32, x);
390 VARDECL(celt_word32, tmp);
Jean-Marc Valinde678582009-10-03 10:36:27 -0400391 int b;
392 int N2 = N;
393 int B = 1;
394 int n4offset=0;
395 const mdct_lookup *lookup = MDCT(mode);
Jean-Marc Valin9d1decd2008-06-17 13:28:13 +1000396 SAVE_STACK;
Jean-Marc Valinde678582009-10-03 10:36:27 -0400397
Jean-Marc Valin234969c2009-10-17 22:12:42 -0400398 ALLOC(x, 2*N, celt_word32);
399 ALLOC(tmp, N, celt_word32);
Jean-Marc Valinde678582009-10-03 10:36:27 -0400400
401 if (shortBlocks)
402 {
403 lookup = &mode->shortMdct;
404 N2 = mode->shortMdctSize;
405 B = mode->nbShortMdcts;
406 n4offset = N4;
407 }
Jean-Marc Valin9d1decd2008-06-17 13:28:13 +1000408 /* Prevents problems from the imdct doing the overlap-add */
Gregory Maxwell23e654f2008-09-27 16:20:03 -0400409 CELT_MEMSET(x+N4, 0, N2);
Jean-Marc Valinde678582009-10-03 10:36:27 -0400410
Jean-Marc Valin9d1decd2008-06-17 13:28:13 +1000411 for (b=0;b<B;b++)
412 {
413 /* De-interleaving the sub-frames */
414 for (j=0;j<N2;j++)
Jean-Marc Valin08a82ff2009-06-14 14:05:19 -0400415 tmp[j] = X[(j*B+b)+c*N2*B];
Jean-Marc Valin6d584ac2009-11-21 21:57:44 -0500416 clt_mdct_backward(lookup, tmp, x+n4offset+N2*b, mode->window, overlap);
Jean-Marc Valin9d1decd2008-06-17 13:28:13 +1000417 }
Jean-Marc Valinde678582009-10-03 10:36:27 -0400418
Jean-Marc Valin528f4b82008-06-29 03:46:39 +1000419 if (transient_shift > 0)
Jean-Marc Valin12b22482008-06-16 14:13:05 +1000420 {
Jean-Marc Valin528f4b82008-06-29 03:46:39 +1000421#ifdef FIXED_POINT
Jean-Marc Valin12b22482008-06-16 14:13:05 +1000422 for (j=0;j<16;j++)
Jean-Marc Valin528f4b82008-06-29 03:46:39 +1000423 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 +1000424 for (j=transient_time;j<N+overlap;j++)
Jean-Marc Valin528f4b82008-06-29 03:46:39 +1000425 x[N4+j] = SHL32(x[N4+j], transient_shift);
426#else
427 for (j=0;j<16;j++)
Jean-Marc Valine4aeb472008-06-29 12:06:05 +1000428 x[N4+transient_time+j-16] *= 1+transientWindow[j]*((1<<transient_shift)-1);
Jean-Marc Valin528f4b82008-06-29 03:46:39 +1000429 for (j=transient_time;j<N+overlap;j++)
430 x[N4+j] *= 1<<transient_shift;
431#endif
Jean-Marc Valin12b22482008-06-16 14:13:05 +1000432 }
Jean-Marc Valin56522ad2009-06-05 17:17:25 -0400433 /* The first and last part would need to be set to zero
434 if we actually wanted to use them. */
Jean-Marc Valin8ddd7f42008-04-22 13:37:16 +1000435 for (j=0;j<overlap;j++)
436 out_mem[C*(MAX_PERIOD-N)+C*j+c] += x[j+N4];
437 for (j=0;j<overlap;j++)
438 out_mem[C*(MAX_PERIOD)+C*(overlap-j-1)+c] = x[2*N-j-N4-1];
439 for (j=0;j<2*N4;j++)
440 out_mem[C*(MAX_PERIOD-N)+C*(j+overlap)+c] = x[j+N4+overlap];
441 RESTORE_STACK;
442 }
Jean-Marc Valin1677aa92007-12-08 01:13:34 +1100443 }
444}
445
Jean-Marc Valin05ed03e2009-04-29 07:44:13 -0400446#define FLAG_NONE 0
Jean-Marc Valin5a700972009-08-08 13:23:03 -0400447#define FLAG_INTRA (1U<<13)
448#define FLAG_PITCH (1U<<12)
449#define FLAG_SHORT (1U<<11)
450#define FLAG_FOLD (1U<<10)
Jean-Marc Valin05ed03e2009-04-29 07:44:13 -0400451#define FLAG_MASK (FLAG_INTRA|FLAG_PITCH|FLAG_SHORT|FLAG_FOLD)
452
Jean-Marc Valine12017e2009-10-03 13:57:31 -0400453static const int flaglist[8] = {
Jean-Marc Valina8be38a2009-04-29 22:16:26 -0400454 0 /*00 */ | FLAG_FOLD,
455 1 /*01 */ | FLAG_PITCH|FLAG_FOLD,
456 8 /*1000*/ | FLAG_NONE,
457 9 /*1001*/ | FLAG_SHORT|FLAG_FOLD,
458 10 /*1010*/ | FLAG_PITCH,
459 11 /*1011*/ | FLAG_INTRA,
460 6 /*110 */ | FLAG_INTRA|FLAG_FOLD,
461 7 /*111 */ | FLAG_INTRA|FLAG_SHORT|FLAG_FOLD
Jean-Marc Valin05ed03e2009-04-29 07:44:13 -0400462};
463
Jean-Marc Valine12017e2009-10-03 13:57:31 -0400464static 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 -0400465{
466 int i;
467 int flags=FLAG_NONE;
468 int flag_bits;
469 flags |= intra_ener ? FLAG_INTRA : 0;
470 flags |= has_pitch ? FLAG_PITCH : 0;
471 flags |= shortBlocks ? FLAG_SHORT : 0;
472 flags |= has_fold ? FLAG_FOLD : 0;
473 for (i=0;i<8;i++)
474 if (flags == (flaglist[i]&FLAG_MASK))
475 break;
476 celt_assert(i<8);
477 flag_bits = flaglist[i]&0xf;
478 /*printf ("enc %d: %d %d %d %d\n", flag_bits, intra_ener, has_pitch, shortBlocks, has_fold);*/
479 if (i<2)
Jean-Marc Valinc08be442009-06-17 23:23:46 -0400480 ec_enc_uint(enc, flag_bits, 4);
Jean-Marc Valin05ed03e2009-04-29 07:44:13 -0400481 else if (i<6)
Jean-Marc Valinc08be442009-06-17 23:23:46 -0400482 ec_enc_uint(enc, flag_bits, 16);
Jean-Marc Valin05ed03e2009-04-29 07:44:13 -0400483 else
Jean-Marc Valinc08be442009-06-17 23:23:46 -0400484 ec_enc_uint(enc, flag_bits, 8);
Jean-Marc Valin05ed03e2009-04-29 07:44:13 -0400485}
486
Jean-Marc Valine12017e2009-10-03 13:57:31 -0400487static 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 -0400488{
489 int i;
490 int flag_bits;
Jean-Marc Valinc08be442009-06-17 23:23:46 -0400491 flag_bits = ec_dec_uint(dec, 4);
Jean-Marc Valin05ed03e2009-04-29 07:44:13 -0400492 /*printf ("(%d) ", flag_bits);*/
493 if (flag_bits==2)
Jean-Marc Valinc08be442009-06-17 23:23:46 -0400494 flag_bits = (flag_bits<<2) | ec_dec_uint(dec, 4);
Jean-Marc Valin05ed03e2009-04-29 07:44:13 -0400495 else if (flag_bits==3)
Jean-Marc Valinc08be442009-06-17 23:23:46 -0400496 flag_bits = (flag_bits<<1) | ec_dec_uint(dec, 2);
Jean-Marc Valin05ed03e2009-04-29 07:44:13 -0400497 for (i=0;i<8;i++)
498 if (flag_bits == (flaglist[i]&0xf))
499 break;
500 celt_assert(i<8);
501 *intra_ener = (flaglist[i]&FLAG_INTRA) != 0;
502 *has_pitch = (flaglist[i]&FLAG_PITCH) != 0;
503 *shortBlocks = (flaglist[i]&FLAG_SHORT) != 0;
504 *has_fold = (flaglist[i]&FLAG_FOLD ) != 0;
505 /*printf ("dec %d: %d %d %d %d\n", flag_bits, *intra_ener, *has_pitch, *shortBlocks, *has_fold);*/
506}
507
Jean-Marc Valin64209a32010-04-05 09:26:22 -0400508void 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 -0400509{
Jean-Marc Valinbf2398b2009-10-15 07:28:19 -0400510 const int C = CHANNELS(_C);
Jean-Marc Valine12017e2009-10-03 13:57:31 -0400511 int c;
512 for (c=0;c<C;c++)
513 {
514 int j;
Jean-Marc Valin64209a32010-04-05 09:26:22 -0400515 celt_sig * restrict x;
516 celt_word16 * restrict y;
517 celt_sig m = mem[c];
518 x = &in[C*(MAX_PERIOD-N)+c];
519 y = pcm+c;
Jean-Marc Valine12017e2009-10-03 13:57:31 -0400520 for (j=0;j<N;j++)
521 {
Jean-Marc Valin64209a32010-04-05 09:26:22 -0400522 celt_sig tmp = MAC16_32_Q15(*x, coef,m);
523 m = tmp;
524 *y = SCALEOUT(SIG2WORD16(tmp));
525 x+=C;
526 y+=C;
Jean-Marc Valine12017e2009-10-03 13:57:31 -0400527 }
Jean-Marc Valin64209a32010-04-05 09:26:22 -0400528 mem[c] = m;
Jean-Marc Valine12017e2009-10-03 13:57:31 -0400529 }
Jean-Marc Valine12017e2009-10-03 13:57:31 -0400530}
531
Jean-Marc Valin234969c2009-10-17 22:12:42 -0400532static 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 -0400533{
534 int m, i, c;
Jean-Marc Valinbf2398b2009-10-15 07:28:19 -0400535 const int C = CHANNELS(_C);
Jean-Marc Valin88619552009-10-04 21:35:36 -0400536 for (c=0;c<C;c++)
537 for (m=start;m<end;m++)
538 for (i=m+c*N;i<(c+1)*N;i+=nbShortMdcts)
539#ifdef FIXED_POINT
540 X[i] = SHR16(X[i], mdct_weight_shift);
541#else
542 X[i] = (1.f/(1<<mdct_weight_shift))*X[i];
543#endif
Jean-Marc Valinbf2398b2009-10-15 07:28:19 -0400544 renormalise_bands(mode, X, C);
Jean-Marc Valin88619552009-10-04 21:35:36 -0400545}
546
547
Gregory Maxwell5f2a74b2008-08-11 23:50:07 -0400548#ifdef FIXED_POINT
Jean-Marc Valin30f7f812009-10-17 14:35:13 -0400549int 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 +1100550{
Gregory Maxwell5f2a74b2008-08-11 23:50:07 -0400551#else
Jean-Marc Valin234969c2009-10-17 22:12:42 -0400552int 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 -0400553{
554#endif
Jean-Marc Valin88619552009-10-04 21:35:36 -0400555 int i, c, N, NN, N4;
Jean-Marc Valin7e8a4872008-02-11 16:55:34 +1100556 int has_pitch;
Jean-Marc Valin0bb05bc2008-02-20 13:43:40 +1100557 int pitch_index;
Jean-Marc Valinc890b582008-08-01 22:26:49 -0400558 int bits;
Jean-Marc Valinbc799912008-11-07 22:53:13 -0500559 int has_fold=1;
Jean-Marc Valinab4dcc52009-10-21 07:08:27 -0400560 int coarse_needed;
Jean-Marc Valin8679a802008-10-18 07:44:35 -0400561 ec_byte_buffer buf;
562 ec_enc enc;
Jean-Marc Valin234969c2009-10-17 22:12:42 -0400563 VARDECL(celt_sig, in);
564 VARDECL(celt_sig, freq);
565 VARDECL(celt_sig, pitch_freq);
566 VARDECL(celt_norm, X);
567 VARDECL(celt_ener, bandE);
568 VARDECL(celt_word16, bandLogE);
Jean-Marc Valin6775de32008-08-02 08:14:42 -0400569 VARDECL(int, fine_quant);
Jean-Marc Valin234969c2009-10-17 22:12:42 -0400570 VARDECL(celt_word16, error);
Jean-Marc Valin6775de32008-08-02 08:14:42 -0400571 VARDECL(int, pulses);
572 VARDECL(int, offsets);
Jean-Marc Valin52cb5fb2009-06-10 08:08:55 -0400573 VARDECL(int, fine_priority);
Jean-Marc Valin18a3b792009-05-01 19:58:55 -0400574 int intra_ener = 0;
Jean-Marc Valin9d1decd2008-06-17 13:28:13 +1000575 int shortBlocks=0;
Jean-Marc Valin12b22482008-06-16 14:13:05 +1000576 int transient_time;
Jean-Marc Valin528f4b82008-06-29 03:46:39 +1000577 int transient_shift;
Jean-Marc Valinb8ba70c2010-04-18 22:10:24 -0400578 int resynth;
Jean-Marc Valin80ed1472009-10-15 21:45:32 -0400579 const int C = CHANNELS(st->channels);
Jean-Marc Valinaa936252009-05-29 22:14:20 -0400580 int mdct_weight_shift = 0;
581 int mdct_weight_pos=0;
Jean-Marc Valinab220aa2009-09-15 22:38:40 -0400582 int gain_id=0;
Jean-Marc Valin92ae3702009-09-16 07:57:17 -0400583 int norm_rate;
Jean-Marc Valin3a0bc3d2010-02-21 15:10:22 -0500584 int start=0;
Jean-Marc Valin8600f692008-02-29 15:14:12 +1100585 SAVE_STACK;
Jean-Marc Valin44ffd5a2008-02-22 00:39:25 +1100586
Gregory Maxwell17169992009-06-04 15:15:34 -0400587 if (check_encoder(st) != CELT_OK)
588 return CELT_INVALID_STATE;
589
Jean-Marc Valin44ffd5a2008-02-22 00:39:25 +1100590 if (check_mode(st->mode) != CELT_OK)
591 return CELT_INVALID_MODE;
592
Gregory Maxwell0719f6f2009-07-09 17:07:24 -0400593 if (nbCompressedBytes<0 || pcm==NULL)
Gregory Maxwell520eeae2009-02-09 01:33:21 -0500594 return CELT_BAD_ARG;
595
Jean-Marc Valin56522ad2009-06-05 17:17:25 -0400596 /* The memset is important for now in case the encoder doesn't
597 fill up all the bytes */
Jean-Marc Valin8679a802008-10-18 07:44:35 -0400598 CELT_MEMSET(compressed, 0, nbCompressedBytes);
599 ec_byte_writeinit_buffer(&buf, compressed, nbCompressedBytes);
600 ec_enc_init(&enc,&buf);
601
Jean-Marc Valinf02ba112007-11-30 01:10:42 +1100602 N = st->block_size;
Jean-Marc Valina536f772008-03-22 09:01:50 +1100603 N4 = (N-st->overlap)>>1;
Jean-Marc Valin234969c2009-10-17 22:12:42 -0400604 ALLOC(in, 2*C*N-2*C*N4, celt_sig);
Jean-Marc Valina5431bf2008-01-03 20:53:01 +1100605
Jean-Marc Valinbdb58832008-04-20 17:42:10 +1000606 CELT_COPY(in, st->in_mem, C*st->overlap);
Jean-Marc Valinffa13472007-12-10 16:54:17 +1100607 for (c=0;c<C;c++)
Jean-Marc Valin6f7e83d2007-12-01 00:36:41 +1100608 {
Jean-Marc Valin234969c2009-10-17 22:12:42 -0400609 const celt_word16 * restrict pcmp = pcm+c;
610 celt_sig * restrict inp = in+C*st->overlap+c;
Jean-Marc Valinb886ddc2008-03-25 14:38:55 +1100611 for (i=0;i<N;i++)
Jean-Marc Valinffa13472007-12-10 16:54:17 +1100612 {
Jean-Marc Valin62290062008-04-20 22:16:02 +1000613 /* Apply pre-emphasis */
Jean-Marc Valin234969c2009-10-17 22:12:42 -0400614 celt_sig tmp = SCALEIN(SHL32(EXTEND32(*pcmp), SIG_SHIFT));
Jean-Marc Valin5c3bc672008-08-28 23:34:24 -0400615 *inp = SUB32(tmp, SHR32(MULT16_16(preemph,st->preemph_memE[c]),3));
Gregory Maxwell5f2a74b2008-08-11 23:50:07 -0400616 st->preemph_memE[c] = SCALEIN(*pcmp);
Jean-Marc Valin62290062008-04-20 22:16:02 +1000617 inp += C;
618 pcmp += C;
Jean-Marc Valinffa13472007-12-10 16:54:17 +1100619 }
Jean-Marc Valin6f7e83d2007-12-01 00:36:41 +1100620 }
Jean-Marc Valinbdb58832008-04-20 17:42:10 +1000621 CELT_COPY(st->in_mem, in+C*(2*N-2*N4-st->overlap), C*st->overlap);
Jean-Marc Valin2014ca32009-06-18 23:33:04 -0400622
Jean-Marc Valin37ab9c62008-11-08 09:14:38 -0500623 /* Transient handling */
Jean-Marc Valin2014ca32009-06-18 23:33:04 -0400624 transient_time = -1;
625 transient_shift = 0;
626 shortBlocks = 0;
627
Jean-Marc Valinb8ba70c2010-04-18 22:10:24 -0400628 resynth = st->pitch_available>0 || optional_synthesis!=NULL;
629
Jean-Marc Valin9c30de52010-04-19 13:32:15 -0400630 if (st->mode->nbShortMdcts > 1 && transient_analysis(in, N+st->overlap, C, &transient_time, &transient_shift, &st->frame_max))
Jean-Marc Valin9375aa42008-06-27 07:57:35 +1000631 {
Jean-Marc Valin7028d622008-07-10 23:06:58 -0400632#ifndef FIXED_POINT
Jean-Marc Valin2014ca32009-06-18 23:33:04 -0400633 float gain_1;
Jean-Marc Valin528f4b82008-06-29 03:46:39 +1000634#endif
Jean-Marc Valin2014ca32009-06-18 23:33:04 -0400635 /* Apply the inverse shaping window */
636 if (transient_shift)
637 {
Jean-Marc Valin7028d622008-07-10 23:06:58 -0400638#ifdef FIXED_POINT
Jean-Marc Valin2014ca32009-06-18 23:33:04 -0400639 for (c=0;c<C;c++)
640 for (i=0;i<16;i++)
641 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]);
642 for (c=0;c<C;c++)
643 for (i=transient_time;i<N+st->overlap;i++)
644 in[C*i+c] = SHR32(in[C*i+c], transient_shift);
Jean-Marc Valin7028d622008-07-10 23:06:58 -0400645#else
Jean-Marc Valin2014ca32009-06-18 23:33:04 -0400646 for (c=0;c<C;c++)
647 for (i=0;i<16;i++)
648 in[C*(transient_time+i-16)+c] /= 1+transientWindow[i]*((1<<transient_shift)-1);
649 gain_1 = 1./(1<<transient_shift);
650 for (c=0;c<C;c++)
651 for (i=transient_time;i<N+st->overlap;i++)
652 in[C*i+c] *= gain_1;
Jean-Marc Valin7028d622008-07-10 23:06:58 -0400653#endif
Jean-Marc Valin528f4b82008-06-29 03:46:39 +1000654 }
Jean-Marc Valin2014ca32009-06-18 23:33:04 -0400655 shortBlocks = 1;
656 has_fold = 1;
Jean-Marc Valin12b22482008-06-16 14:13:05 +1000657 }
Jean-Marc Valinc5f2a9d2008-10-26 22:00:26 -0400658
Jean-Marc Valin234969c2009-10-17 22:12:42 -0400659 ALLOC(freq, C*N, celt_sig); /**< Interleaved signal MDCTs */
660 ALLOC(bandE,st->mode->nbEBands*C, celt_ener);
661 ALLOC(bandLogE,st->mode->nbEBands*C, celt_word16);
Jean-Marc Valin32ec58c2009-05-01 21:28:58 -0400662 /* Compute MDCTs */
Jean-Marc Valinbf2398b2009-10-15 07:28:19 -0400663 compute_mdcts(st->mode, shortBlocks, in, freq, C);
Jean-Marc Valin08a82ff2009-06-14 14:05:19 -0400664
Jean-Marc Valinaa936252009-05-29 22:14:20 -0400665
Jean-Marc Valin30f7f812009-10-17 14:35:13 -0400666 norm_rate = (nbCompressedBytes-5)*8*(celt_uint32)st->mode->Fs/(C*N)>>10;
Jean-Marc Valinddb181b2008-03-03 14:53:47 +1100667 /* Pitch analysis: we do it early to save on the peak stack space */
Jean-Marc Valin56522ad2009-06-05 17:17:25 -0400668 /* Don't use pitch if there isn't enough data available yet,
669 or if we're using shortBlocks */
Jean-Marc Valine6d832a2009-07-08 22:21:31 -0400670 has_pitch = st->pitch_enabled && st->pitch_permitted && (N <= 512)
Jean-Marc Valin92ae3702009-09-16 07:57:17 -0400671 && (st->pitch_available >= MAX_PERIOD) && (!shortBlocks)
672 && norm_rate < 50;
Gregory Maxwell98046ca2008-12-13 20:42:03 -0500673 if (has_pitch)
Jean-Marc Valinc5f2a9d2008-10-26 22:00:26 -0400674 {
Jean-Marc Valine465c142009-11-26 00:39:36 -0500675 VARDECL(celt_word16, x_lp);
Jean-Marc Valind5f99302009-12-16 22:42:32 -0500676 SAVE_STACK;
Jean-Marc Valine465c142009-11-26 00:39:36 -0500677 ALLOC(x_lp, (2*N-2*N4)>>1, celt_word16);
678 pitch_downsample(in, x_lp, 2*N-2*N4, N, C, &st->xmem, &st->pitch_buf[MAX_PERIOD>>1]);
679 pitch_search(st->mode, x_lp, st->pitch_buf, 2*N-2*N4, MAX_PERIOD-(2*N-2*N4), &pitch_index, &st->xmem);
Jean-Marc Valind5f99302009-12-16 22:42:32 -0500680 RESTORE_STACK;
Jean-Marc Valinc5f2a9d2008-10-26 22:00:26 -0400681 }
Jean-Marc Valin37ab9c62008-11-08 09:14:38 -0500682
Jean-Marc Valin56522ad2009-06-05 17:17:25 -0400683 /* Deferred allocation after find_spectral_pitch() to reduce
684 the peak memory usage */
Jean-Marc Valin234969c2009-10-17 22:12:42 -0400685 ALLOC(X, C*N, celt_norm); /**< Interleaved normalised MDCTs */
Jean-Marc Valin8d4ac152008-02-29 17:24:02 +1100686
Jean-Marc Valin234969c2009-10-17 22:12:42 -0400687 ALLOC(pitch_freq, C*N, celt_sig); /**< Interleaved signal MDCTs */
Jean-Marc Valin4c77ea92009-09-14 22:50:41 -0400688 if (has_pitch)
689 {
Jean-Marc Valinbf2398b2009-10-15 07:28:19 -0400690 compute_mdcts(st->mode, 0, st->out_mem+pitch_index*C, pitch_freq, C);
Jean-Marc Valind35d6772009-10-16 23:16:47 -0400691 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 -0400692 }
693
694 if (has_pitch)
Jean-Marc Valinbf2398b2009-10-15 07:28:19 -0400695 apply_pitch(st->mode, freq, pitch_freq, gain_id, 1, C);
Jean-Marc Valin6c245242007-12-29 23:27:42 +1100696
Jean-Marc Valinbf2398b2009-10-15 07:28:19 -0400697 compute_band_energies(st->mode, freq, bandE, C);
Jean-Marc Valin4c77ea92009-09-14 22:50:41 -0400698 for (i=0;i<st->mode->nbEBands*C;i++)
699 bandLogE[i] = amp2Log(bandE[i]);
Jean-Marc Valinbd5d54a2009-10-20 00:25:31 -0400700
Jean-Marc Valin8ebd3452007-11-29 20:17:32 +1100701 /* Band normalisation */
Jean-Marc Valinbf2398b2009-10-15 07:28:19 -0400702 normalise_bands(st->mode, freq, X, bandE, C);
703 if (!shortBlocks && !folding_decision(st->mode, X, &st->tonal_average, &st->fold_decision, C))
Jean-Marc Valin527db5c2009-06-02 07:56:19 -0400704 has_fold = 0;
Jean-Marc Valin26c9e142007-12-31 21:27:54 +1100705
Jean-Marc Valin4c77ea92009-09-14 22:50:41 -0400706 /* Don't use intra energy when we're operating at low bit-rate */
707 intra_ener = st->force_intra || (!has_pitch && st->delayedIntra && nbCompressedBytes > st->mode->nbEBands);
708 if (shortBlocks || intra_decision(bandLogE, st->oldBandE, st->mode->nbEBands))
709 st->delayedIntra = 1;
710 else
711 st->delayedIntra = 0;
712
Jean-Marc Valin88619552009-10-04 21:35:36 -0400713 NN = st->mode->eBands[st->mode->nbEBands];
714 if (shortBlocks && !transient_shift)
715 {
Jean-Marc Valin234969c2009-10-17 22:12:42 -0400716 celt_word32 sum[8]={1,1,1,1,1,1,1,1};
Jean-Marc Valin88619552009-10-04 21:35:36 -0400717 int m;
718 for (c=0;c<C;c++)
719 {
720 m=0;
721 do {
Jean-Marc Valin234969c2009-10-17 22:12:42 -0400722 celt_word32 tmp=0;
Jean-Marc Valin88619552009-10-04 21:35:36 -0400723 for (i=m+c*N;i<c*N+NN;i+=st->mode->nbShortMdcts)
724 tmp += ABS32(X[i]);
725 sum[m++] += tmp;
726 } while (m<st->mode->nbShortMdcts);
727 }
728 m=0;
729#ifdef FIXED_POINT
730 do {
731 if (SHR32(sum[m+1],3) > sum[m])
732 {
733 mdct_weight_shift=2;
734 mdct_weight_pos = m;
735 } else if (SHR32(sum[m+1],1) > sum[m] && mdct_weight_shift < 2)
736 {
737 mdct_weight_shift=1;
738 mdct_weight_pos = m;
739 }
740 m++;
741 } while (m<st->mode->nbShortMdcts-1);
742#else
743 do {
744 if (sum[m+1] > 8*sum[m])
745 {
746 mdct_weight_shift=2;
747 mdct_weight_pos = m;
748 } else if (sum[m+1] > 2*sum[m] && mdct_weight_shift < 2)
749 {
750 mdct_weight_shift=1;
751 mdct_weight_pos = m;
752 }
753 m++;
754 } while (m<st->mode->nbShortMdcts-1);
755#endif
756 if (mdct_weight_shift)
757 {
Jean-Marc Valinbf2398b2009-10-15 07:28:19 -0400758 mdct_shape(st->mode, X, mdct_weight_pos+1, st->mode->nbShortMdcts, N, st->mode->nbShortMdcts, mdct_weight_shift, C);
759 renormalise_bands(st->mode, X, C);
Jean-Marc Valin88619552009-10-04 21:35:36 -0400760 }
761 }
762
Jean-Marc Valin4c77ea92009-09-14 22:50:41 -0400763
Jean-Marc Valin18a3b792009-05-01 19:58:55 -0400764 encode_flags(&enc, intra_ener, has_pitch, shortBlocks, has_fold);
Jean-Marc Valin05ed03e2009-04-29 07:44:13 -0400765 if (has_pitch)
766 {
Gregory Maxwellabe40f02008-12-13 01:31:32 -0500767 ec_enc_uint(&enc, pitch_index, MAX_PERIOD-(2*N-2*N4));
Jean-Marc Valin4c77ea92009-09-14 22:50:41 -0400768 ec_enc_uint(&enc, gain_id, 16);
Jean-Marc Valin96870d92007-12-05 21:14:22 +1100769 }
Jean-Marc Valin05ed03e2009-04-29 07:44:13 -0400770 if (shortBlocks)
771 {
Jean-Marc Valin05ed03e2009-04-29 07:44:13 -0400772 if (transient_shift)
Jean-Marc Valinaa936252009-05-29 22:14:20 -0400773 {
Jean-Marc Valine6108642009-08-01 23:05:47 +0200774 ec_enc_uint(&enc, transient_shift, 4);
Jean-Marc Valin05ed03e2009-04-29 07:44:13 -0400775 ec_enc_uint(&enc, transient_time, N+st->overlap);
Jean-Marc Valinaa936252009-05-29 22:14:20 -0400776 } else {
Jean-Marc Valine6108642009-08-01 23:05:47 +0200777 ec_enc_uint(&enc, mdct_weight_shift, 4);
Jean-Marc Valinaa936252009-05-29 22:14:20 -0400778 if (mdct_weight_shift && st->mode->nbShortMdcts!=2)
779 ec_enc_uint(&enc, mdct_weight_pos, st->mode->nbShortMdcts-1);
780 }
Jean-Marc Valin05ed03e2009-04-29 07:44:13 -0400781 }
Jean-Marc Valinc890b582008-08-01 22:26:49 -0400782
Jean-Marc Valin6775de32008-08-02 08:14:42 -0400783 ALLOC(fine_quant, st->mode->nbEBands, int);
Jean-Marc Valin8dff9232008-08-13 22:07:20 -0400784 ALLOC(pulses, st->mode->nbEBands, int);
Jean-Marc Valin37ab9c62008-11-08 09:14:38 -0500785
Jean-Marc Valin25767d12009-10-21 23:24:18 -0400786 /* Computes the max bit-rate allowed in VBR more to avoid busting the budget */
787 if (st->vbr_rate>0)
788 {
789 celt_int32 vbr_bound, max_allowed;
790
791 vbr_bound = st->vbr_rate;
Jean-Marc Valin7a047ea2009-10-22 00:23:56 -0400792 max_allowed = (st->vbr_rate + vbr_bound - st->vbr_reservoir)>>(BITRES+3);
793 if (max_allowed < 4)
794 max_allowed = 4;
Jean-Marc Valin25767d12009-10-21 23:24:18 -0400795 if (max_allowed < nbCompressedBytes)
796 nbCompressedBytes = max_allowed;
797 }
798
Jean-Marc Valin37ab9c62008-11-08 09:14:38 -0500799 /* Bit allocation */
Jean-Marc Valin234969c2009-10-17 22:12:42 -0400800 ALLOC(error, C*st->mode->nbEBands, celt_word16);
Jean-Marc Valin3a0bc3d2010-02-21 15:10:22 -0500801 coarse_needed = quant_coarse_energy(st->mode, start, bandLogE, st->oldBandE, nbCompressedBytes*4-8, intra_ener, st->mode->prob, error, &enc, C);
Gregory Maxwell888d8ce2009-05-21 04:21:53 -0400802 coarse_needed = ((coarse_needed*3-1)>>3)+1;
Jean-Marc Valin25767d12009-10-21 23:24:18 -0400803 if (coarse_needed > nbCompressedBytes)
804 coarse_needed = nbCompressedBytes;
Gregory Maxwell888d8ce2009-05-21 04:21:53 -0400805 /* Variable bitrate */
Jean-Marc Valinbd5d54a2009-10-20 00:25:31 -0400806 if (st->vbr_rate>0)
Gregory Maxwell888d8ce2009-05-21 04:21:53 -0400807 {
Jean-Marc Valinbd5d54a2009-10-20 00:25:31 -0400808 celt_word16 alpha;
Jean-Marc Valin25767d12009-10-21 23:24:18 -0400809 celt_int32 delta;
Gregory Maxwell888d8ce2009-05-21 04:21:53 -0400810 /* The target rate in 16th bits per frame */
Jean-Marc Valinbd5d54a2009-10-20 00:25:31 -0400811 celt_int32 target=st->vbr_rate;
Jean-Marc Valin6775de32008-08-02 08:14:42 -0400812
Jean-Marc Valin56522ad2009-06-05 17:17:25 -0400813 /* Shortblocks get a large boost in bitrate, but since they
814 are uncommon long blocks are not greatly effected */
Gregory Maxwell888d8ce2009-05-21 04:21:53 -0400815 if (shortBlocks)
816 target*=2;
817 else if (st->mode->nbShortMdcts > 1)
Jean-Marc Valinbd5d54a2009-10-20 00:25:31 -0400818 target-=(target+14)/28;
Gregory Maxwell888d8ce2009-05-21 04:21:53 -0400819
Jean-Marc Valin56522ad2009-06-05 17:17:25 -0400820 /* The average energy is removed from the target and the actual
821 energy added*/
Jean-Marc Valinbd5d54a2009-10-20 00:25:31 -0400822 target=target+st->vbr_offset-588+ec_enc_tell(&enc, BITRES);
Gregory Maxwell888d8ce2009-05-21 04:21:53 -0400823
824 /* In VBR mode the frame size must not be reduced so much that it would result in the coarse energy busting its budget */
825 target=IMAX(coarse_needed,(target+64)/128);
Jean-Marc Valin45f11102009-10-22 00:12:31 -0400826 target=IMIN(nbCompressedBytes,target);
Jean-Marc Valinbd5d54a2009-10-20 00:25:31 -0400827 /* Make the adaptation coef (alpha) higher at the beginning */
828 if (st->vbr_count < 990)
829 {
830 st->vbr_count++;
831 alpha = celt_rcp(SHL32(EXTEND32(st->vbr_count+10),16));
832 /*printf ("%d %d\n", st->vbr_count+10, alpha);*/
833 } else
834 alpha = QCONST16(.001f,15);
835
836 /* By how much did we "miss" the target on that frame */
Jean-Marc Valin45f11102009-10-22 00:12:31 -0400837 delta = (8<<BITRES)*(celt_int32)target - st->vbr_rate;
Jean-Marc Valinbd5d54a2009-10-20 00:25:31 -0400838 /* How many bits have we used in excess of what we're allowed */
839 st->vbr_reservoir += delta;
840 /*printf ("%d\n", st->vbr_reservoir);*/
841
842 /* Compute the offset we need to apply in order to reach the target */
843 st->vbr_drift += MULT16_32_Q15(alpha,delta-st->vbr_offset-st->vbr_drift);
844 st->vbr_offset = -st->vbr_drift;
845 /*printf ("%d\n", st->vbr_drift);*/
846
847 /* We could use any multiple of vbr_rate as bound (depending on the delay) */
Jean-Marc Valin25767d12009-10-21 23:24:18 -0400848 if (st->vbr_reservoir < 0)
Jean-Marc Valinbd5d54a2009-10-20 00:25:31 -0400849 {
850 /* We're under the min value -- increase rate */
851 int adjust = 1-(st->vbr_reservoir-1)/(8<<BITRES);
852 st->vbr_reservoir += adjust*(8<<BITRES);
Jean-Marc Valin45f11102009-10-22 00:12:31 -0400853 target += adjust;
Jean-Marc Valinbd5d54a2009-10-20 00:25:31 -0400854 /*printf ("+%d\n", adjust);*/
855 }
Jean-Marc Valin45f11102009-10-22 00:12:31 -0400856 if (target < nbCompressedBytes)
857 nbCompressedBytes = target;
Jean-Marc Valinbd5d54a2009-10-20 00:25:31 -0400858 /* This moves the raw bits to take into account the new compressed size */
Jean-Marc Valine6108642009-08-01 23:05:47 +0200859 ec_byte_shrink(&buf, nbCompressedBytes);
Gregory Maxwell888d8ce2009-05-21 04:21:53 -0400860 }
861
Jean-Marc Valin6775de32008-08-02 08:14:42 -0400862 ALLOC(offsets, st->mode->nbEBands, int);
Jean-Marc Valin52cb5fb2009-06-10 08:08:55 -0400863 ALLOC(fine_priority, st->mode->nbEBands, int);
Jean-Marc Valincb7a2a32008-02-11 16:44:48 +1100864
Jean-Marc Valin6775de32008-08-02 08:14:42 -0400865 for (i=0;i<st->mode->nbEBands;i++)
866 offsets[i] = 0;
Jean-Marc Valin8679a802008-10-18 07:44:35 -0400867 bits = nbCompressedBytes*8 - ec_enc_tell(&enc, 0) - 1;
Jean-Marc Valin3a0bc3d2010-02-21 15:10:22 -0500868 compute_allocation(st->mode, start, offsets, bits, pulses, fine_quant, fine_priority, C);
Jean-Marc Valin37ab9c62008-11-08 09:14:38 -0500869
Jean-Marc Valin3a0bc3d2010-02-21 15:10:22 -0500870 quant_fine_energy(st->mode, start, bandE, st->oldBandE, error, fine_quant, &enc, C);
Jean-Marc Valin6775de32008-08-02 08:14:42 -0400871
Jean-Marc Valin8ebd3452007-11-29 20:17:32 +1100872 /* Residual quantisation */
Jean-Marc Valinca53b7c2009-03-26 20:23:14 -0400873 if (C==1)
Jean-Marc Valinb8ba70c2010-04-18 22:10:24 -0400874 quant_bands(st->mode, start, X, bandE, pulses, shortBlocks, has_fold, resynth, nbCompressedBytes*8, 1, &enc);
Jean-Marc Valin73532032009-06-02 20:07:25 -0400875#ifndef DISABLE_STEREO
Jean-Marc Valinca53b7c2009-03-26 20:23:14 -0400876 else
Jean-Marc Valinb8ba70c2010-04-18 22:10:24 -0400877 quant_bands_stereo(st->mode, start, X, bandE, pulses, shortBlocks, has_fold, resynth, nbCompressedBytes*8, &enc);
Jean-Marc Valin73532032009-06-02 20:07:25 -0400878#endif
Jean-Marc Valin39710532009-06-09 00:10:32 -0400879
Jean-Marc Valin3a0bc3d2010-02-21 15:10:22 -0500880 quant_energy_finalise(st->mode, start, 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 -0400881
Jean-Marc Valin37ab9c62008-11-08 09:14:38 -0500882 /* Re-synthesis of the coded audio if required */
Jean-Marc Valinb8ba70c2010-04-18 22:10:24 -0400883 if (resynth)
Jean-Marc Valin18ddc022008-02-22 14:24:50 +1100884 {
Gregory Maxwell98046ca2008-12-13 20:42:03 -0500885 if (st->pitch_available>0 && st->pitch_available<MAX_PERIOD)
886 st->pitch_available+=st->frame_size;
887
Jean-Marc Valinaa936252009-05-29 22:14:20 -0400888 if (mdct_weight_shift)
889 {
Jean-Marc Valinbf2398b2009-10-15 07:28:19 -0400890 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 -0400891 }
Jean-Marc Valin88619552009-10-04 21:35:36 -0400892
893 /* Synthesis */
Jean-Marc Valinbf2398b2009-10-15 07:28:19 -0400894 denormalise_bands(st->mode, X, freq, bandE, C);
Jean-Marc Valin88619552009-10-04 21:35:36 -0400895
896 CELT_MOVE(st->out_mem, st->out_mem+C*N, C*(MAX_PERIOD+st->overlap-N));
897
Jean-Marc Valin4c77ea92009-09-14 22:50:41 -0400898 if (has_pitch)
Jean-Marc Valinbf2398b2009-10-15 07:28:19 -0400899 apply_pitch(st->mode, freq, pitch_freq, gain_id, 0, C);
Jean-Marc Valin4c77ea92009-09-14 22:50:41 -0400900
Jean-Marc Valinbf2398b2009-10-15 07:28:19 -0400901 compute_inv_mdcts(st->mode, shortBlocks, freq, transient_time, transient_shift, st->out_mem, C);
Jean-Marc Valine12017e2009-10-03 13:57:31 -0400902
Jean-Marc Valin56522ad2009-06-05 17:17:25 -0400903 /* De-emphasis and put everything back at the right place
904 in the synthesis history */
Gregory Maxwell82595312008-09-30 18:20:14 -0400905 if (optional_synthesis != NULL) {
Jean-Marc Valine12017e2009-10-03 13:57:31 -0400906 deemphasis(st->out_mem, optional_synthesis, N, C, preemph, st->preemph_memD);
907
Jean-Marc Valin6f7e83d2007-12-01 00:36:41 +1100908 }
Jean-Marc Valind9b95652008-08-31 23:34:47 -0400909 }
Gregory Maxwell54547f12009-02-16 18:56:44 -0500910
Jean-Marc Valin8679a802008-10-18 07:44:35 -0400911 ec_enc_done(&enc);
Jean-Marc Valinc871c8d2009-06-09 00:57:00 -0400912
Jean-Marc Valin8600f692008-02-29 15:14:12 +1100913 RESTORE_STACK;
Jean-Marc Valina76a0b22008-01-17 22:43:05 +1100914 return nbCompressedBytes;
Jean-Marc Valin8ebd3452007-11-29 20:17:32 +1100915}
916
Gregory Maxwell5f2a74b2008-08-11 23:50:07 -0400917#ifdef FIXED_POINT
918#ifndef DISABLE_FLOAT_API
Gregory Maxwell82595312008-09-30 18:20:14 -0400919int celt_encode_float(CELTEncoder * restrict st, const float * pcm, float * optional_synthesis, unsigned char *compressed, int nbCompressedBytes)
Gregory Maxwell5f2a74b2008-08-11 23:50:07 -0400920{
Gregory Maxwell17169992009-06-04 15:15:34 -0400921 int j, ret, C, N;
Jean-Marc Valin30f7f812009-10-17 14:35:13 -0400922 VARDECL(celt_int16, in);
Jean-Marc Valincb8780c2009-07-20 23:40:35 -0400923 SAVE_STACK;
Gregory Maxwell17169992009-06-04 15:15:34 -0400924
925 if (check_encoder(st) != CELT_OK)
926 return CELT_INVALID_STATE;
927
928 if (check_mode(st->mode) != CELT_OK)
929 return CELT_INVALID_MODE;
930
Gregory Maxwell0719f6f2009-07-09 17:07:24 -0400931 if (pcm==NULL)
932 return CELT_BAD_ARG;
933
Jean-Marc Valin80ed1472009-10-15 21:45:32 -0400934 C = CHANNELS(st->channels);
Gregory Maxwell17169992009-06-04 15:15:34 -0400935 N = st->block_size;
Jean-Marc Valin30f7f812009-10-17 14:35:13 -0400936 ALLOC(in, C*N, celt_int16);
Gregory Maxwell5f2a74b2008-08-11 23:50:07 -0400937
938 for (j=0;j<C*N;j++)
939 in[j] = FLOAT2INT16(pcm[j]);
940
Gregory Maxwell82595312008-09-30 18:20:14 -0400941 if (optional_synthesis != NULL) {
942 ret=celt_encode(st,in,in,compressed,nbCompressedBytes);
Gregory Maxwellb0a73a02008-12-12 16:54:25 -0500943 for (j=0;j<C*N;j++)
Gregory Maxwell82595312008-09-30 18:20:14 -0400944 optional_synthesis[j]=in[j]*(1/32768.);
945 } else {
946 ret=celt_encode(st,in,NULL,compressed,nbCompressedBytes);
947 }
Wessel Lubberhuizen33ba6cc2008-10-03 07:09:29 -0400948 RESTORE_STACK;
Gregory Maxwell5f2a74b2008-08-11 23:50:07 -0400949 return ret;
950
951}
952#endif /*DISABLE_FLOAT_API*/
953#else
Jean-Marc Valin30f7f812009-10-17 14:35:13 -0400954int 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 -0400955{
Gregory Maxwell17169992009-06-04 15:15:34 -0400956 int j, ret, C, N;
Jean-Marc Valin234969c2009-10-17 22:12:42 -0400957 VARDECL(celt_sig, in);
Jean-Marc Valincb8780c2009-07-20 23:40:35 -0400958 SAVE_STACK;
Gregory Maxwell17169992009-06-04 15:15:34 -0400959
960 if (check_encoder(st) != CELT_OK)
961 return CELT_INVALID_STATE;
962
963 if (check_mode(st->mode) != CELT_OK)
964 return CELT_INVALID_MODE;
965
Gregory Maxwell0719f6f2009-07-09 17:07:24 -0400966 if (pcm==NULL)
967 return CELT_BAD_ARG;
968
Jean-Marc Valin80ed1472009-10-15 21:45:32 -0400969 C=CHANNELS(st->channels);
Gregory Maxwell17169992009-06-04 15:15:34 -0400970 N=st->block_size;
Jean-Marc Valin234969c2009-10-17 22:12:42 -0400971 ALLOC(in, C*N, celt_sig);
Gregory Maxwell5f2a74b2008-08-11 23:50:07 -0400972 for (j=0;j<C*N;j++) {
973 in[j] = SCALEOUT(pcm[j]);
974 }
Gregory Maxwell5f2a74b2008-08-11 23:50:07 -0400975
Gregory Maxwell82595312008-09-30 18:20:14 -0400976 if (optional_synthesis != NULL) {
977 ret = celt_encode_float(st,in,in,compressed,nbCompressedBytes);
978 for (j=0;j<C*N;j++)
979 optional_synthesis[j] = FLOAT2INT16(in[j]);
980 } else {
981 ret = celt_encode_float(st,in,NULL,compressed,nbCompressedBytes);
982 }
Wessel Lubberhuizen33ba6cc2008-10-03 07:09:29 -0400983 RESTORE_STACK;
Gregory Maxwell5f2a74b2008-08-11 23:50:07 -0400984 return ret;
985}
986#endif
Jean-Marc Valin6e9058a2007-12-07 14:59:06 +1100987
Jean-Marc Valinb6f90612008-10-05 22:39:13 -0400988int celt_encoder_ctl(CELTEncoder * restrict st, int request, ...)
Jean-Marc Valinc18fb1d2008-09-30 07:36:54 -0400989{
Jean-Marc Valinb6f90612008-10-05 22:39:13 -0400990 va_list ap;
Gregory Maxwell17169992009-06-04 15:15:34 -0400991
992 if (check_encoder(st) != CELT_OK)
993 return CELT_INVALID_STATE;
994
Jean-Marc Valinb6f90612008-10-05 22:39:13 -0400995 va_start(ap, request);
Gregory Maxwell17169992009-06-04 15:15:34 -0400996 if ((request!=CELT_GET_MODE_REQUEST) && (check_mode(st->mode) != CELT_OK))
997 goto bad_mode;
Jean-Marc Valinc18fb1d2008-09-30 07:36:54 -0400998 switch (request)
999 {
Gregory Maxwellf3b44ef2009-06-03 13:37:45 -04001000 case CELT_GET_MODE_REQUEST:
1001 {
1002 const CELTMode ** value = va_arg(ap, const CELTMode**);
1003 if (value==0)
1004 goto bad_arg;
1005 *value=st->mode;
1006 }
1007 break;
Jean-Marc Valinb6f90612008-10-05 22:39:13 -04001008 case CELT_SET_COMPLEXITY_REQUEST:
Jean-Marc Valinc18fb1d2008-09-30 07:36:54 -04001009 {
Jean-Marc Valin30f7f812009-10-17 14:35:13 -04001010 int value = va_arg(ap, celt_int32);
Jean-Marc Valinb6f90612008-10-05 22:39:13 -04001011 if (value<0 || value>10)
1012 goto bad_arg;
Gregory Maxwell98046ca2008-12-13 20:42:03 -05001013 if (value<=2) {
1014 st->pitch_enabled = 0;
1015 st->pitch_available = 0;
1016 } else {
1017 st->pitch_enabled = 1;
1018 if (st->pitch_available<1)
1019 st->pitch_available = 1;
1020 }
1021 }
1022 break;
Gregory Maxwell2dd3d322009-06-05 14:05:51 -04001023 case CELT_SET_PREDICTION_REQUEST:
Gregory Maxwell98046ca2008-12-13 20:42:03 -05001024 {
Jean-Marc Valin30f7f812009-10-17 14:35:13 -04001025 int value = va_arg(ap, celt_int32);
Gregory Maxwell2dd3d322009-06-05 14:05:51 -04001026 if (value<0 || value>2)
Gregory Maxwell98046ca2008-12-13 20:42:03 -05001027 goto bad_arg;
1028 if (value==0)
Gregory Maxwell2dd3d322009-06-05 14:05:51 -04001029 {
1030 st->force_intra = 1;
1031 st->pitch_permitted = 0;
Gregory Maxwella80958b2009-06-29 12:48:57 -04001032 } else if (value==1) {
Gregory Maxwell2dd3d322009-06-05 14:05:51 -04001033 st->force_intra = 0;
1034 st->pitch_permitted = 0;
1035 } else {
1036 st->force_intra = 0;
1037 st->pitch_permitted = 1;
1038 }
Jean-Marc Valinc18fb1d2008-09-30 07:36:54 -04001039 }
1040 break;
Gregory Maxwell888d8ce2009-05-21 04:21:53 -04001041 case CELT_SET_VBR_RATE_REQUEST:
1042 {
Jean-Marc Valin30f7f812009-10-17 14:35:13 -04001043 celt_int32 value = va_arg(ap, celt_int32);
Gregory Maxwell888d8ce2009-05-21 04:21:53 -04001044 if (value<0)
1045 goto bad_arg;
1046 if (value>3072000)
1047 value = 3072000;
Jean-Marc Valinbd5d54a2009-10-20 00:25:31 -04001048 st->vbr_rate = ((st->mode->Fs<<3)+(st->block_size>>1))/st->block_size;
1049 st->vbr_rate = ((value<<7)+(st->vbr_rate>>1))/st->vbr_rate;
Gregory Maxwell888d8ce2009-05-21 04:21:53 -04001050 }
1051 break;
John Ridges454d1d02009-05-21 22:38:39 -04001052 case CELT_RESET_STATE:
1053 {
1054 const CELTMode *mode = st->mode;
Jean-Marc Valin80ed1472009-10-15 21:45:32 -04001055 int C = st->channels;
John Ridges454d1d02009-05-21 22:38:39 -04001056
1057 if (st->pitch_available > 0) st->pitch_available = 1;
1058
1059 CELT_MEMSET(st->in_mem, 0, st->overlap*C);
1060 CELT_MEMSET(st->out_mem, 0, (MAX_PERIOD+st->overlap)*C);
1061
1062 CELT_MEMSET(st->oldBandE, 0, C*mode->nbEBands);
1063
1064 CELT_MEMSET(st->preemph_memE, 0, C);
1065 CELT_MEMSET(st->preemph_memD, 0, C);
1066 st->delayedIntra = 1;
John Ridges5378bf82010-02-12 07:08:01 -05001067
1068 st->fold_decision = 1;
Jean-Marc Valin628c0252010-04-16 20:57:56 -04001069 st->tonal_average = QCONST16(1.f,8);
John Ridges5378bf82010-02-12 07:08:01 -05001070 st->gain_prod = 0;
1071 st->vbr_reservoir = 0;
1072 st->vbr_drift = 0;
1073 st->vbr_offset = 0;
1074 st->vbr_count = 0;
1075 st->xmem = 0;
Jean-Marc Valin9c30de52010-04-19 13:32:15 -04001076 st->frame_max = 0;
John Ridges5378bf82010-02-12 07:08:01 -05001077 CELT_MEMSET(st->pitch_buf, 0, (MAX_PERIOD>>1)+2);
John Ridges454d1d02009-05-21 22:38:39 -04001078 }
1079 break;
Jean-Marc Valinc18fb1d2008-09-30 07:36:54 -04001080 default:
Jean-Marc Valinb6f90612008-10-05 22:39:13 -04001081 goto bad_request;
Jean-Marc Valinc18fb1d2008-09-30 07:36:54 -04001082 }
Jean-Marc Valinb6f90612008-10-05 22:39:13 -04001083 va_end(ap);
Jean-Marc Valinc18fb1d2008-09-30 07:36:54 -04001084 return CELT_OK;
Gregory Maxwell17169992009-06-04 15:15:34 -04001085bad_mode:
1086 va_end(ap);
1087 return CELT_INVALID_MODE;
Jean-Marc Valinb6f90612008-10-05 22:39:13 -04001088bad_arg:
1089 va_end(ap);
1090 return CELT_BAD_ARG;
1091bad_request:
1092 va_end(ap);
1093 return CELT_UNIMPLEMENTED;
Jean-Marc Valinc18fb1d2008-09-30 07:36:54 -04001094}
1095
Jean-Marc Valin56522ad2009-06-05 17:17:25 -04001096/**********************************************************************/
1097/* */
1098/* DECODER */
1099/* */
1100/**********************************************************************/
Jean-Marc Valineafbdd52009-04-27 19:35:09 -04001101#ifdef NEW_PLC
1102#define DECODE_BUFFER_SIZE 2048
1103#else
1104#define DECODE_BUFFER_SIZE MAX_PERIOD
1105#endif
Jean-Marc Valin269d40a2007-12-07 11:29:45 +11001106
Gregory Maxwell17169992009-06-04 15:15:34 -04001107#define DECODERVALID 0x4c434454
1108#define DECODERPARTIAL 0x5444434c
1109#define DECODERFREED 0x4c004400
1110
Jean-Marc Valin276de722008-02-20 17:45:51 +11001111/** Decoder state
1112 @brief Decoder state
1113 */
Jean-Marc Valin269d40a2007-12-07 11:29:45 +11001114struct CELTDecoder {
Jean-Marc Valin30f7f812009-10-17 14:35:13 -04001115 celt_uint32 marker;
Jean-Marc Valin269d40a2007-12-07 11:29:45 +11001116 const CELTMode *mode;
1117 int frame_size;
1118 int block_size;
Jean-Marc Valina5431bf2008-01-03 20:53:01 +11001119 int overlap;
Jean-Marc Valin80ed1472009-10-15 21:45:32 -04001120 int channels;
Jean-Marc Valina5431bf2008-01-03 20:53:01 +11001121
Jean-Marc Valin269d40a2007-12-07 11:29:45 +11001122 ec_byte_buffer buf;
1123 ec_enc enc;
1124
Jean-Marc Valin234969c2009-10-17 22:12:42 -04001125 celt_sig * restrict preemph_memD;
Jean-Marc Valin81b38c22008-02-29 21:08:49 +11001126
Jean-Marc Valin234969c2009-10-17 22:12:42 -04001127 celt_sig *out_mem;
1128 celt_sig *decode_mem;
Jean-Marc Valin269d40a2007-12-07 11:29:45 +11001129
Jean-Marc Valin234969c2009-10-17 22:12:42 -04001130 celt_word16 *oldBandE;
Jean-Marc Valinfb83fb42007-12-08 00:56:04 +11001131
Jean-Marc Valind69c1cb2009-12-28 00:34:29 -05001132#ifdef NEW_PLC
Jean-Marc Valin74128be2010-01-01 09:33:17 -05001133 celt_word16 *lpc;
Jean-Marc Valin5a0fae52009-12-14 21:19:37 -05001134#endif
1135
Jean-Marc Valinfb83fb42007-12-08 00:56:04 +11001136 int last_pitch_index;
Jean-Marc Valin0f0da992009-08-12 21:34:01 -04001137 int loss_count;
Jean-Marc Valin269d40a2007-12-07 11:29:45 +11001138};
1139
Gregory Maxwell17169992009-06-04 15:15:34 -04001140int check_decoder(const CELTDecoder *st)
1141{
1142 if (st==NULL)
1143 {
1144 celt_warning("NULL passed a decoder structure");
1145 return CELT_INVALID_STATE;
1146 }
1147 if (st->marker == DECODERVALID)
1148 return CELT_OK;
1149 if (st->marker == DECODERFREED)
1150 celt_warning("Referencing a decoder that has already been freed");
1151 else
1152 celt_warning("This is not a valid CELT decoder structure");
1153 return CELT_INVALID_STATE;
1154}
1155
Jean-Marc Valin80ed1472009-10-15 21:45:32 -04001156CELTDecoder *celt_decoder_create(const CELTMode *mode, int channels, int *error)
Jean-Marc Valin269d40a2007-12-07 11:29:45 +11001157{
Jean-Marc Valinb886ddc2008-03-25 14:38:55 +11001158 int N, C;
Jean-Marc Valin0bb05bc2008-02-20 13:43:40 +11001159 CELTDecoder *st;
Jean-Marc Valin44ffd5a2008-02-22 00:39:25 +11001160
1161 if (check_mode(mode) != CELT_OK)
Jean-Marc Valinece94a02009-10-16 07:30:14 -04001162 {
1163 if (error)
1164 *error = CELT_INVALID_MODE;
Jean-Marc Valin44ffd5a2008-02-22 00:39:25 +11001165 return NULL;
Jean-Marc Valinece94a02009-10-16 07:30:14 -04001166 }
Jean-Marc Valinbd5d54a2009-10-20 00:25:31 -04001167#ifdef DISABLE_STEREO
1168 if (channels > 1)
1169 {
1170 celt_warning("Stereo support was disable from this build");
1171 if (error)
1172 *error = CELT_BAD_ARG;
1173 return NULL;
1174 }
1175#endif
1176
Jean-Marc Valin80ed1472009-10-15 21:45:32 -04001177 if (channels < 0 || channels > 2)
1178 {
1179 celt_warning("Only mono and stereo supported");
1180 if (error)
1181 *error = CELT_BAD_ARG;
1182 return NULL;
1183 }
Jean-Marc Valin44ffd5a2008-02-22 00:39:25 +11001184
Jean-Marc Valin269d40a2007-12-07 11:29:45 +11001185 N = mode->mdctSize;
Jean-Marc Valin80ed1472009-10-15 21:45:32 -04001186 C = CHANNELS(channels);
Jean-Marc Valin0bb05bc2008-02-20 13:43:40 +11001187 st = celt_alloc(sizeof(CELTDecoder));
Gregory Maxwell17169992009-06-04 15:15:34 -04001188
1189 if (st==NULL)
Jean-Marc Valinece94a02009-10-16 07:30:14 -04001190 {
1191 if (error)
1192 *error = CELT_ALLOC_FAIL;
Gregory Maxwell17169992009-06-04 15:15:34 -04001193 return NULL;
Jean-Marc Valinece94a02009-10-16 07:30:14 -04001194 }
1195
Gregory Maxwell17169992009-06-04 15:15:34 -04001196 st->marker = DECODERPARTIAL;
Jean-Marc Valin269d40a2007-12-07 11:29:45 +11001197 st->mode = mode;
Jean-Marc Valinb886ddc2008-03-25 14:38:55 +11001198 st->frame_size = N;
Jean-Marc Valin269d40a2007-12-07 11:29:45 +11001199 st->block_size = N;
Jean-Marc Valina5431bf2008-01-03 20:53:01 +11001200 st->overlap = mode->overlap;
Jean-Marc Valin80ed1472009-10-15 21:45:32 -04001201 st->channels = channels;
Jean-Marc Valina5431bf2008-01-03 20:53:01 +11001202
Jean-Marc Valin234969c2009-10-17 22:12:42 -04001203 st->decode_mem = celt_alloc((DECODE_BUFFER_SIZE+st->overlap)*C*sizeof(celt_sig));
Jean-Marc Valineafbdd52009-04-27 19:35:09 -04001204 st->out_mem = st->decode_mem+DECODE_BUFFER_SIZE-MAX_PERIOD;
Jean-Marc Valin269d40a2007-12-07 11:29:45 +11001205
Jean-Marc Valin234969c2009-10-17 22:12:42 -04001206 st->oldBandE = (celt_word16*)celt_alloc(C*mode->nbEBands*sizeof(celt_word16));
Gregory Maxwell17169992009-06-04 15:15:34 -04001207
Jean-Marc Valin234969c2009-10-17 22:12:42 -04001208 st->preemph_memD = (celt_sig*)celt_alloc(C*sizeof(celt_sig));
Jean-Marc Valinffa13472007-12-10 16:54:17 +11001209
Jean-Marc Valind69c1cb2009-12-28 00:34:29 -05001210#ifdef NEW_PLC
Jean-Marc Valin74128be2010-01-01 09:33:17 -05001211 st->lpc = (celt_word16*)celt_alloc(C*LPC_ORDER*sizeof(celt_word16));
Jean-Marc Valin5a0fae52009-12-14 21:19:37 -05001212#endif
1213
Jean-Marc Valin0f0da992009-08-12 21:34:01 -04001214 st->loss_count = 0;
Gregory Maxwell17169992009-06-04 15:15:34 -04001215
1216 if ((st->decode_mem!=NULL) && (st->out_mem!=NULL) && (st->oldBandE!=NULL) &&
Jean-Marc Valind69c1cb2009-12-28 00:34:29 -05001217#ifdef NEW_PLC
Jean-Marc Valin5a0fae52009-12-14 21:19:37 -05001218 (st->lpc!=NULL) &&
1219#endif
Gregory Maxwell17169992009-06-04 15:15:34 -04001220 (st->preemph_memD!=NULL))
1221 {
Jean-Marc Valinece94a02009-10-16 07:30:14 -04001222 if (error)
1223 *error = CELT_OK;
Gregory Maxwell17169992009-06-04 15:15:34 -04001224 st->marker = DECODERVALID;
1225 return st;
1226 }
1227 /* If the setup fails for some reason deallocate it. */
1228 celt_decoder_destroy(st);
Jean-Marc Valinece94a02009-10-16 07:30:14 -04001229 if (error)
1230 *error = CELT_ALLOC_FAIL;
Gregory Maxwell17169992009-06-04 15:15:34 -04001231 return NULL;
Jean-Marc Valin269d40a2007-12-07 11:29:45 +11001232}
1233
Peter Kirk19f9dc92008-06-06 14:38:38 +02001234void celt_decoder_destroy(CELTDecoder *st)
Jean-Marc Valin269d40a2007-12-07 11:29:45 +11001235{
1236 if (st == NULL)
1237 {
Gregory Maxwell17169992009-06-04 15:15:34 -04001238 celt_warning("NULL passed to celt_decoder_destroy");
Jean-Marc Valin269d40a2007-12-07 11:29:45 +11001239 return;
1240 }
Gregory Maxwell17169992009-06-04 15:15:34 -04001241
1242 if (st->marker == DECODERFREED)
1243 {
1244 celt_warning("Freeing a decoder which has already been freed");
Jean-Marc Valin44ffd5a2008-02-22 00:39:25 +11001245 return;
Gregory Maxwell17169992009-06-04 15:15:34 -04001246 }
1247
1248 if (st->marker != DECODERVALID && st->marker != DECODERPARTIAL)
1249 {
1250 celt_warning("This is not a valid CELT decoder structure");
1251 return;
1252 }
1253
1254 /*Check_mode is non-fatal here because we can still free
1255 the encoder memory even if the mode is bad, although calling
1256 the free functions in this order is a violation of the API.*/
1257 check_mode(st->mode);
1258
Jean-Marc Valineafbdd52009-04-27 19:35:09 -04001259 celt_free(st->decode_mem);
Jean-Marc Valin269d40a2007-12-07 11:29:45 +11001260 celt_free(st->oldBandE);
Jean-Marc Valin7351e282008-02-08 15:09:45 +11001261 celt_free(st->preemph_memD);
Jean-Marc Valin5a0fae52009-12-14 21:19:37 -05001262
Jean-Marc Valind69c1cb2009-12-28 00:34:29 -05001263#ifdef NEW_PLC
Jean-Marc Valin5a0fae52009-12-14 21:19:37 -05001264 celt_free(st->lpc);
1265#endif
Gregory Maxwell17169992009-06-04 15:15:34 -04001266
1267 st->marker = DECODERFREED;
1268
Jean-Marc Valin269d40a2007-12-07 11:29:45 +11001269 celt_free(st);
1270}
1271
Jean-Marc Valin234969c2009-10-17 22:12:42 -04001272static void celt_decode_lost(CELTDecoder * restrict st, celt_word16 * restrict pcm)
Jean-Marc Valinfb83fb42007-12-08 00:56:04 +11001273{
Jean-Marc Valin05e56c42008-04-10 09:13:05 +10001274 int c, N;
Jean-Marc Valin0bb05bc2008-02-20 13:43:40 +11001275 int pitch_index;
Jean-Marc Valine14fe902009-12-11 00:07:31 -05001276 int overlap = st->mode->overlap;
Jean-Marc Valin234969c2009-10-17 22:12:42 -04001277 celt_word16 fade = Q15ONE;
Jean-Marc Valin24c9cda2008-05-02 10:34:07 +10001278 int i, len;
Jean-Marc Valin234969c2009-10-17 22:12:42 -04001279 VARDECL(celt_sig, freq);
Jean-Marc Valin80ed1472009-10-15 21:45:32 -04001280 const int C = CHANNELS(st->channels);
Jean-Marc Valin24c9cda2008-05-02 10:34:07 +10001281 int offset;
Jean-Marc Valin8600f692008-02-29 15:14:12 +11001282 SAVE_STACK;
Jean-Marc Valinfb83fb42007-12-08 00:56:04 +11001283 N = st->block_size;
Jean-Marc Valinfb83fb42007-12-08 00:56:04 +11001284
Jean-Marc Valin24c9cda2008-05-02 10:34:07 +10001285 len = N+st->mode->overlap;
Jean-Marc Valinfb83fb42007-12-08 00:56:04 +11001286
Jean-Marc Valin0f0da992009-08-12 21:34:01 -04001287 if (st->loss_count == 0)
1288 {
Jean-Marc Valin7a7c42a2009-11-25 20:38:52 -05001289 celt_word16 pitch_buf[MAX_PERIOD>>1];
Jean-Marc Valin294863b2009-11-08 22:29:54 +09001290 celt_word32 tmp=0;
Jean-Marc Valine465c142009-11-26 00:39:36 -05001291 celt_word32 mem0[2]={0,0};
1292 celt_word16 mem1[2]={0,0};
Jean-Marc Valine14fe902009-12-11 00:07:31 -05001293 pitch_downsample(st->out_mem, pitch_buf, MAX_PERIOD, MAX_PERIOD,
1294 C, mem0, mem1);
1295 pitch_search(st->mode, pitch_buf+((MAX_PERIOD-len)>>1), pitch_buf, len,
1296 MAX_PERIOD-len-100, &pitch_index, &tmp);
Jean-Marc Valin0f0da992009-08-12 21:34:01 -04001297 pitch_index = MAX_PERIOD-len-pitch_index;
1298 st->last_pitch_index = pitch_index;
1299 } else {
1300 pitch_index = st->last_pitch_index;
1301 if (st->loss_count < 5)
1302 fade = QCONST16(.8f,15);
1303 else
1304 fade = 0;
1305 }
Jean-Marc Valinfb83fb42007-12-08 00:56:04 +11001306
Jean-Marc Valind69c1cb2009-12-28 00:34:29 -05001307#ifndef NEW_PLC
Jean-Marc Valind5f99302009-12-16 22:42:32 -05001308 offset = MAX_PERIOD-pitch_index;
Jean-Marc Valine14fe902009-12-11 00:07:31 -05001309 ALLOC(freq,C*N, celt_sig); /**< Interleaved signal MDCTs */
Jean-Marc Valin24c9cda2008-05-02 10:34:07 +10001310 while (offset+len >= MAX_PERIOD)
1311 offset -= pitch_index;
Jean-Marc Valinbf2398b2009-10-15 07:28:19 -04001312 compute_mdcts(st->mode, 0, st->out_mem+offset*C, freq, C);
Jean-Marc Valin08a82ff2009-06-14 14:05:19 -04001313 for (i=0;i<C*N;i++)
Jean-Marc Valin0f0da992009-08-12 21:34:01 -04001314 freq[i] = ADD32(VERY_SMALL, MULT16_32_Q15(fade,freq[i]));
1315
Jean-Marc Valin24c9cda2008-05-02 10:34:07 +10001316 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 +11001317 /* Compute inverse MDCTs */
Jean-Marc Valinbf2398b2009-10-15 07:28:19 -04001318 compute_inv_mdcts(st->mode, 0, freq, -1, 0, st->out_mem, C);
Jean-Marc Valine14fe902009-12-11 00:07:31 -05001319#else
1320 for (c=0;c<C;c++)
1321 {
Jean-Marc Valind69c1cb2009-12-28 00:34:29 -05001322 celt_word32 e[MAX_PERIOD];
Jean-Marc Valin303b3b62009-12-30 22:40:24 -05001323 celt_word16 exc[MAX_PERIOD];
Jean-Marc Valine14fe902009-12-11 00:07:31 -05001324 float ac[LPC_ORDER+1];
Jean-Marc Valine14fe902009-12-11 00:07:31 -05001325 float decay = 1;
Jean-Marc Valinaec0ee42009-12-21 00:06:12 -05001326 float S1=0;
Jean-Marc Valin74128be2010-01-01 09:33:17 -05001327 celt_word16 mem[LPC_ORDER]={0};
Jean-Marc Valine14fe902009-12-11 00:07:31 -05001328
Jean-Marc Valind5f99302009-12-16 22:42:32 -05001329 offset = MAX_PERIOD-pitch_index;
Jean-Marc Valine14fe902009-12-11 00:07:31 -05001330 for (i=0;i<MAX_PERIOD;i++)
Jean-Marc Valin74128be2010-01-01 09:33:17 -05001331 exc[i] = ROUND16(st->out_mem[i*C+c], SIG_SHIFT);
Jean-Marc Valin5a0fae52009-12-14 21:19:37 -05001332
1333 if (st->loss_count == 0)
1334 {
1335 _celt_autocorr(exc, ac, st->mode->window, st->mode->overlap,
1336 LPC_ORDER, MAX_PERIOD);
1337
1338 /* Noise floor -50 dB */
1339 ac[0] *= 1.00001;
1340 /* Lag windowing */
1341 for (i=1;i<=LPC_ORDER;i++)
1342 {
1343 /*ac[i] *= exp(-.5*(2*M_PI*.002*i)*(2*M_PI*.002*i));*/
1344 ac[i] -= ac[i]*(.008*i)*(.008*i);
1345 }
1346
Jean-Marc Valin74128be2010-01-01 09:33:17 -05001347 _celt_lpc(st->lpc+c*LPC_ORDER, ac, LPC_ORDER);
Jean-Marc Valin5a0fae52009-12-14 21:19:37 -05001348 }
Jean-Marc Valin74128be2010-01-01 09:33:17 -05001349 fir(exc, st->lpc+c*LPC_ORDER, exc, MAX_PERIOD, LPC_ORDER, mem);
1350 /*for (i=0;i<MAX_PERIOD;i++)printf("%d ", exc[i]); printf("\n");*/
Jean-Marc Valine14fe902009-12-11 00:07:31 -05001351 /* Check if the waveform is decaying (and if so how fast) */
1352 {
1353 float E1=0, E2=0;
1354 int period;
1355 if (pitch_index <= MAX_PERIOD/2)
1356 period = pitch_index;
1357 else
1358 period = MAX_PERIOD/2;
1359 for (i=0;i<period;i++)
1360 {
1361 E1 += exc[MAX_PERIOD-period+i]*exc[MAX_PERIOD-period+i];
1362 E2 += exc[MAX_PERIOD-2*period+i]*exc[MAX_PERIOD-2*period+i];
1363 }
1364 decay = sqrt((E1+1)/(E2+1));
1365 if (decay > 1)
1366 decay = 1;
1367 }
1368
1369 /* Copy excitation, taking decay into account */
1370 for (i=0;i<len+st->mode->overlap;i++)
1371 {
1372 if (offset+i >= MAX_PERIOD)
1373 {
1374 offset -= pitch_index;
1375 decay *= decay;
1376 }
Jean-Marc Valin303b3b62009-12-30 22:40:24 -05001377 e[i] = decay*SHL32(EXTEND32(exc[offset+i]), SIG_SHIFT);
Jean-Marc Valind69c1cb2009-12-28 00:34:29 -05001378 S1 += st->out_mem[offset+i]*1.*st->out_mem[offset+i];
Jean-Marc Valin5a0fae52009-12-14 21:19:37 -05001379 }
1380
Jean-Marc Valin74128be2010-01-01 09:33:17 -05001381 iir(e, st->lpc+c*LPC_ORDER, e, len+st->mode->overlap, LPC_ORDER, mem);
Jean-Marc Valin5a0fae52009-12-14 21:19:37 -05001382
1383 {
Jean-Marc Valin07fed1b2009-12-28 07:59:42 -05001384 float S2=0;
Jean-Marc Valin5a0fae52009-12-14 21:19:37 -05001385 for (i=0;i<len+overlap;i++)
Jean-Marc Valind69c1cb2009-12-28 00:34:29 -05001386 S2 += e[i]*1.*e[i];
Jean-Marc Valin07fed1b2009-12-28 07:59:42 -05001387 /* This checks for an "explosion" in the synthesis (including NaNs) */
1388 if (!(S1 > 0.2f*S2))
1389 {
1390 for (i=0;i<len+overlap;i++)
1391 e[i] = 0;
1392 } else if (S1 < S2)
1393 {
1394 float ratio = sqrt((S1+1)/(S2+1));
Jean-Marc Valin5a0fae52009-12-14 21:19:37 -05001395 for (i=0;i<len+overlap;i++)
1396 e[i] *= ratio;
Jean-Marc Valin07fed1b2009-12-28 07:59:42 -05001397 }
Jean-Marc Valine14fe902009-12-11 00:07:31 -05001398 }
1399
1400 for (i=0;i<MAX_PERIOD+st->mode->overlap-N;i++)
1401 st->out_mem[C*i+c] = st->out_mem[C*(N+i)+c];
1402
Jean-Marc Valine14fe902009-12-11 00:07:31 -05001403 /* Apply TDAC to the concealed audio so that it blends with the
1404 previous and next frames */
1405 for (i=0;i<overlap/2;i++)
1406 {
Jean-Marc Valind69c1cb2009-12-28 00:34:29 -05001407 celt_word32 tmp1, tmp2;
1408 tmp1 = MULT16_32_Q15(st->mode->window[i ], e[i ]) -
1409 MULT16_32_Q15(st->mode->window[overlap-i-1], e[overlap-i-1]);
1410 tmp2 = MULT16_32_Q15(st->mode->window[i], e[N+overlap-1-i]) +
1411 MULT16_32_Q15(st->mode->window[overlap-i-1], e[N+i ]);
1412 tmp1 = MULT16_32_Q15(fade, tmp1);
1413 tmp2 = MULT16_32_Q15(fade, tmp2);
1414 st->out_mem[C*(MAX_PERIOD+i)+c] = MULT16_32_Q15(st->mode->window[overlap-i-1], tmp2);
1415 st->out_mem[C*(MAX_PERIOD+overlap-i-1)+c] = MULT16_32_Q15(st->mode->window[i], tmp2);
1416 st->out_mem[C*(MAX_PERIOD-N+i)+c] += MULT16_32_Q15(st->mode->window[i], tmp1);
1417 st->out_mem[C*(MAX_PERIOD-N+overlap-i-1)+c] -= MULT16_32_Q15(st->mode->window[overlap-i-1], tmp1);
Jean-Marc Valine14fe902009-12-11 00:07:31 -05001418 }
1419 for (i=0;i<N-overlap;i++)
Jean-Marc Valind69c1cb2009-12-28 00:34:29 -05001420 st->out_mem[C*(MAX_PERIOD-N+overlap+i)+c] = MULT16_32_Q15(fade, e[overlap+i]);
Jean-Marc Valine14fe902009-12-11 00:07:31 -05001421 }
1422#endif
Jean-Marc Valin1677aa92007-12-08 01:13:34 +11001423
Jean-Marc Valin5a0fae52009-12-14 21:19:37 -05001424 deemphasis(st->out_mem, pcm, N, C, preemph, st->preemph_memD);
Jean-Marc Valin0f0da992009-08-12 21:34:01 -04001425
1426 st->loss_count++;
1427
Jean-Marc Valin8600f692008-02-29 15:14:12 +11001428 RESTORE_STACK;
Jean-Marc Valinfb83fb42007-12-08 00:56:04 +11001429}
1430
Gregory Maxwell5f2a74b2008-08-11 23:50:07 -04001431#ifdef FIXED_POINT
Jean-Marc Valin30f7f812009-10-17 14:35:13 -04001432int celt_decode(CELTDecoder * restrict st, const unsigned char *data, int len, celt_int16 * restrict pcm)
Jean-Marc Valin269d40a2007-12-07 11:29:45 +11001433{
Gregory Maxwell5f2a74b2008-08-11 23:50:07 -04001434#else
Jean-Marc Valin234969c2009-10-17 22:12:42 -04001435int celt_decode_float(CELTDecoder * restrict st, const unsigned char *data, int len, celt_sig * restrict pcm)
Gregory Maxwell5f2a74b2008-08-11 23:50:07 -04001436{
1437#endif
Jean-Marc Valin88619552009-10-04 21:35:36 -04001438 int i, N, N4;
Jean-Marc Valinc9943942008-08-30 00:55:07 -04001439 int has_pitch, has_fold;
Jean-Marc Valin0bb05bc2008-02-20 13:43:40 +11001440 int pitch_index;
Jean-Marc Valinc890b582008-08-01 22:26:49 -04001441 int bits;
Jean-Marc Valin0bb05bc2008-02-20 13:43:40 +11001442 ec_dec dec;
1443 ec_byte_buffer buf;
Jean-Marc Valin234969c2009-10-17 22:12:42 -04001444 VARDECL(celt_sig, freq);
1445 VARDECL(celt_sig, pitch_freq);
1446 VARDECL(celt_norm, X);
1447 VARDECL(celt_ener, bandE);
Jean-Marc Valin6775de32008-08-02 08:14:42 -04001448 VARDECL(int, fine_quant);
1449 VARDECL(int, pulses);
1450 VARDECL(int, offsets);
Jean-Marc Valin52cb5fb2009-06-10 08:08:55 -04001451 VARDECL(int, fine_priority);
Jean-Marc Valinc890b582008-08-01 22:26:49 -04001452
Jean-Marc Valin9d1decd2008-06-17 13:28:13 +10001453 int shortBlocks;
Jean-Marc Valin05ed03e2009-04-29 07:44:13 -04001454 int intra_ener;
Jean-Marc Valin12b22482008-06-16 14:13:05 +10001455 int transient_time;
Jean-Marc Valin528f4b82008-06-29 03:46:39 +10001456 int transient_shift;
Jean-Marc Valinaa936252009-05-29 22:14:20 -04001457 int mdct_weight_shift=0;
Jean-Marc Valin80ed1472009-10-15 21:45:32 -04001458 const int C = CHANNELS(st->channels);
Jean-Marc Valinaa936252009-05-29 22:14:20 -04001459 int mdct_weight_pos=0;
Jean-Marc Valinab220aa2009-09-15 22:38:40 -04001460 int gain_id=0;
Jean-Marc Valin3a0bc3d2010-02-21 15:10:22 -05001461 int start=0;
Jean-Marc Valin8600f692008-02-29 15:14:12 +11001462 SAVE_STACK;
Jean-Marc Valin44ffd5a2008-02-22 00:39:25 +11001463
Gregory Maxwell17169992009-06-04 15:15:34 -04001464 if (check_decoder(st) != CELT_OK)
1465 return CELT_INVALID_STATE;
1466
Jean-Marc Valin44ffd5a2008-02-22 00:39:25 +11001467 if (check_mode(st->mode) != CELT_OK)
1468 return CELT_INVALID_MODE;
1469
Gregory Maxwell0719f6f2009-07-09 17:07:24 -04001470 if (pcm==NULL)
1471 return CELT_BAD_ARG;
1472
Jean-Marc Valin269d40a2007-12-07 11:29:45 +11001473 N = st->block_size;
Jean-Marc Valina536f772008-03-22 09:01:50 +11001474 N4 = (N-st->overlap)>>1;
Jean-Marc Valin01417232008-03-03 13:59:55 +11001475
Jean-Marc Valin234969c2009-10-17 22:12:42 -04001476 ALLOC(freq, C*N, celt_sig); /**< Interleaved signal MDCTs */
1477 ALLOC(X, C*N, celt_norm); /**< Interleaved normalised MDCTs */
1478 ALLOC(bandE, st->mode->nbEBands*C, celt_ener);
Jean-Marc Valin70c8ffd2007-12-07 14:20:01 +11001479
Jean-Marc Valinfb83fb42007-12-08 00:56:04 +11001480 if (data == NULL)
1481 {
1482 celt_decode_lost(st, pcm);
Jean-Marc Valin8600f692008-02-29 15:14:12 +11001483 RESTORE_STACK;
Jean-Marc Valinfb83fb42007-12-08 00:56:04 +11001484 return 0;
1485 }
Gregory Maxwell520eeae2009-02-09 01:33:21 -05001486 if (len<0) {
1487 RESTORE_STACK;
1488 return CELT_BAD_ARG;
1489 }
Jean-Marc Valinfb83fb42007-12-08 00:56:04 +11001490
Jean-Marc Valin05ed03e2009-04-29 07:44:13 -04001491 ec_byte_readinit(&buf,(unsigned char*)data,len);
Jean-Marc Valin70c8ffd2007-12-07 14:20:01 +11001492 ec_dec_init(&dec,&buf);
1493
Jean-Marc Valin05ed03e2009-04-29 07:44:13 -04001494 decode_flags(&dec, &intra_ener, &has_pitch, &shortBlocks, &has_fold);
Gregory Maxwell0527f372008-09-23 19:28:35 -04001495 if (shortBlocks)
1496 {
Jean-Marc Valine6108642009-08-01 23:05:47 +02001497 transient_shift = ec_dec_uint(&dec, 4);
Jean-Marc Valinaa936252009-05-29 22:14:20 -04001498 if (transient_shift == 3)
1499 {
Gregory Maxwell0527f372008-09-23 19:28:35 -04001500 transient_time = ec_dec_uint(&dec, N+st->mode->overlap);
Jean-Marc Valinaa936252009-05-29 22:14:20 -04001501 } else {
1502 mdct_weight_shift = transient_shift;
1503 if (mdct_weight_shift && st->mode->nbShortMdcts>2)
1504 mdct_weight_pos = ec_dec_uint(&dec, st->mode->nbShortMdcts-1);
1505 transient_shift = 0;
Gregory Maxwell0527f372008-09-23 19:28:35 -04001506 transient_time = 0;
Jean-Marc Valinaa936252009-05-29 22:14:20 -04001507 }
Gregory Maxwell0527f372008-09-23 19:28:35 -04001508 } else {
Jean-Marc Valin12b22482008-06-16 14:13:05 +10001509 transient_time = -1;
Jean-Marc Valin528f4b82008-06-29 03:46:39 +10001510 transient_shift = 0;
Jean-Marc Valin12b22482008-06-16 14:13:05 +10001511 }
Jean-Marc Valincb7a2a32008-02-11 16:44:48 +11001512
Jean-Marc Valin7e8a4872008-02-11 16:55:34 +11001513 if (has_pitch)
1514 {
Jean-Marc Valinb886ddc2008-03-25 14:38:55 +11001515 pitch_index = ec_dec_uint(&dec, MAX_PERIOD-(2*N-2*N4));
Jean-Marc Valin4c77ea92009-09-14 22:50:41 -04001516 gain_id = ec_dec_uint(&dec, 16);
Jean-Marc Valin7e8a4872008-02-11 16:55:34 +11001517 } else {
Jean-Marc Valin7e8a4872008-02-11 16:55:34 +11001518 pitch_index = 0;
1519 }
Jean-Marc Valin827f9312008-05-06 23:21:55 +10001520
Jean-Marc Valin6775de32008-08-02 08:14:42 -04001521 ALLOC(fine_quant, st->mode->nbEBands, int);
Jean-Marc Valin827f9312008-05-06 23:21:55 +10001522 /* Get band energies */
Jean-Marc Valin3a0bc3d2010-02-21 15:10:22 -05001523 unquant_coarse_energy(st->mode, start, bandE, st->oldBandE, len*4-8, intra_ener, st->mode->prob, &dec, C);
Jean-Marc Valin6775de32008-08-02 08:14:42 -04001524
1525 ALLOC(pulses, st->mode->nbEBands, int);
1526 ALLOC(offsets, st->mode->nbEBands, int);
Jean-Marc Valin52cb5fb2009-06-10 08:08:55 -04001527 ALLOC(fine_priority, st->mode->nbEBands, int);
Jean-Marc Valin6775de32008-08-02 08:14:42 -04001528
1529 for (i=0;i<st->mode->nbEBands;i++)
1530 offsets[i] = 0;
1531
1532 bits = len*8 - ec_dec_tell(&dec, 0) - 1;
Jean-Marc Valin3a0bc3d2010-02-21 15:10:22 -05001533 compute_allocation(st->mode, start, offsets, bits, pulses, fine_quant, fine_priority, C);
Jean-Marc Valin6775de32008-08-02 08:14:42 -04001534 /*bits = ec_dec_tell(&dec, 0);
1535 compute_fine_allocation(st->mode, fine_quant, (20*C+len*8/5-(ec_dec_tell(&dec, 0)-bits))/C);*/
1536
Jean-Marc Valin3a0bc3d2010-02-21 15:10:22 -05001537 unquant_fine_energy(st->mode, start, bandE, st->oldBandE, fine_quant, &dec, C);
Jean-Marc Valin827f9312008-05-06 23:21:55 +10001538
Jean-Marc Valin234969c2009-10-17 22:12:42 -04001539 ALLOC(pitch_freq, C*N, celt_sig); /**< Interleaved signal MDCTs */
Jean-Marc Valinc9943942008-08-30 00:55:07 -04001540 if (has_pitch)
Jean-Marc Valin269d40a2007-12-07 11:29:45 +11001541 {
Jean-Marc Valinc9943942008-08-30 00:55:07 -04001542 /* Pitch MDCT */
Jean-Marc Valinbf2398b2009-10-15 07:28:19 -04001543 compute_mdcts(st->mode, 0, st->out_mem+pitch_index*C, pitch_freq, C);
Jean-Marc Valin269d40a2007-12-07 11:29:45 +11001544 }
1545
Jean-Marc Valin70c8ffd2007-12-07 14:20:01 +11001546 /* Decode fixed codebook and merge with pitch */
Jean-Marc Valinca53b7c2009-03-26 20:23:14 -04001547 if (C==1)
Jean-Marc Valinb8ba70c2010-04-18 22:10:24 -04001548 quant_bands(st->mode, start, X, bandE, pulses, shortBlocks, has_fold, 1, len*8, 0, &dec);
Jean-Marc Valin73532032009-06-02 20:07:25 -04001549#ifndef DISABLE_STEREO
Jean-Marc Valinca53b7c2009-03-26 20:23:14 -04001550 else
Jean-Marc Valin3a0bc3d2010-02-21 15:10:22 -05001551 unquant_bands_stereo(st->mode, start, X, bandE, pulses, shortBlocks, has_fold, len*8, &dec);
Jean-Marc Valin73532032009-06-02 20:07:25 -04001552#endif
Jean-Marc Valin3a0bc3d2010-02-21 15:10:22 -05001553 unquant_energy_finalise(st->mode, start, bandE, st->oldBandE, fine_quant, fine_priority, len*8-ec_dec_tell(&dec, 0), &dec, C);
Jean-Marc Valin39710532009-06-09 00:10:32 -04001554
Jean-Marc Valin88619552009-10-04 21:35:36 -04001555 if (mdct_weight_shift)
1556 {
Jean-Marc Valinbf2398b2009-10-15 07:28:19 -04001557 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 -04001558 }
1559
Jean-Marc Valina4833ff2008-01-10 15:34:00 +11001560 /* Synthesis */
Jean-Marc Valinbf2398b2009-10-15 07:28:19 -04001561 denormalise_bands(st->mode, X, freq, bandE, C);
Jean-Marc Valina4833ff2008-01-10 15:34:00 +11001562
1563
Jean-Marc Valineafbdd52009-04-27 19:35:09 -04001564 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 -04001565
Jean-Marc Valin4c77ea92009-09-14 22:50:41 -04001566 if (has_pitch)
Jean-Marc Valinbf2398b2009-10-15 07:28:19 -04001567 apply_pitch(st->mode, freq, pitch_freq, gain_id, 0, C);
Jean-Marc Valin4c77ea92009-09-14 22:50:41 -04001568
Jean-Marc Valin3a0bc3d2010-02-21 15:10:22 -05001569 for (i=0;i<st->mode->eBands[start];i++)
1570 freq[i] = 0;
1571
Jean-Marc Valin269d40a2007-12-07 11:29:45 +11001572 /* Compute inverse MDCTs */
Jean-Marc Valinbf2398b2009-10-15 07:28:19 -04001573 compute_inv_mdcts(st->mode, shortBlocks, freq, transient_time, transient_shift, st->out_mem, C);
Jean-Marc Valinffa13472007-12-10 16:54:17 +11001574
Jean-Marc Valine12017e2009-10-03 13:57:31 -04001575 deemphasis(st->out_mem, pcm, N, C, preemph, st->preemph_memD);
Jean-Marc Valine14fe902009-12-11 00:07:31 -05001576 st->loss_count = 0;
Jean-Marc Valin8600f692008-02-29 15:14:12 +11001577 RESTORE_STACK;
Jean-Marc Valinfb83fb42007-12-08 00:56:04 +11001578 return 0;
Jean-Marc Valin269d40a2007-12-07 11:29:45 +11001579}
1580
Gregory Maxwell5f2a74b2008-08-11 23:50:07 -04001581#ifdef FIXED_POINT
1582#ifndef DISABLE_FLOAT_API
Jean-Marc Valin6db6cbd2009-04-11 22:01:20 -04001583int celt_decode_float(CELTDecoder * restrict st, const unsigned char *data, int len, float * restrict pcm)
Gregory Maxwell5f2a74b2008-08-11 23:50:07 -04001584{
Gregory Maxwell17169992009-06-04 15:15:34 -04001585 int j, ret, C, N;
Jean-Marc Valin30f7f812009-10-17 14:35:13 -04001586 VARDECL(celt_int16, out);
Jean-Marc Valincb8780c2009-07-20 23:40:35 -04001587 SAVE_STACK;
Gregory Maxwell17169992009-06-04 15:15:34 -04001588
1589 if (check_decoder(st) != CELT_OK)
1590 return CELT_INVALID_STATE;
1591
1592 if (check_mode(st->mode) != CELT_OK)
1593 return CELT_INVALID_MODE;
1594
Gregory Maxwell0719f6f2009-07-09 17:07:24 -04001595 if (pcm==NULL)
1596 return CELT_BAD_ARG;
1597
Jean-Marc Valin80ed1472009-10-15 21:45:32 -04001598 C = CHANNELS(st->channels);
Gregory Maxwell17169992009-06-04 15:15:34 -04001599 N = st->block_size;
Gregory Maxwell0719f6f2009-07-09 17:07:24 -04001600
Jean-Marc Valin30f7f812009-10-17 14:35:13 -04001601 ALLOC(out, C*N, celt_int16);
Gregory Maxwell5f2a74b2008-08-11 23:50:07 -04001602 ret=celt_decode(st, data, len, out);
Gregory Maxwell5f2a74b2008-08-11 23:50:07 -04001603 for (j=0;j<C*N;j++)
Gregory Maxwell0719f6f2009-07-09 17:07:24 -04001604 pcm[j]=out[j]*(1/32768.);
1605
Wessel Lubberhuizen33ba6cc2008-10-03 07:09:29 -04001606 RESTORE_STACK;
Gregory Maxwell5f2a74b2008-08-11 23:50:07 -04001607 return ret;
1608}
1609#endif /*DISABLE_FLOAT_API*/
1610#else
Jean-Marc Valin30f7f812009-10-17 14:35:13 -04001611int celt_decode(CELTDecoder * restrict st, const unsigned char *data, int len, celt_int16 * restrict pcm)
Gregory Maxwell5f2a74b2008-08-11 23:50:07 -04001612{
Gregory Maxwell17169992009-06-04 15:15:34 -04001613 int j, ret, C, N;
Jean-Marc Valin234969c2009-10-17 22:12:42 -04001614 VARDECL(celt_sig, out);
Jean-Marc Valincb8780c2009-07-20 23:40:35 -04001615 SAVE_STACK;
Gregory Maxwell17169992009-06-04 15:15:34 -04001616
1617 if (check_decoder(st) != CELT_OK)
1618 return CELT_INVALID_STATE;
1619
1620 if (check_mode(st->mode) != CELT_OK)
1621 return CELT_INVALID_MODE;
1622
Gregory Maxwell0719f6f2009-07-09 17:07:24 -04001623 if (pcm==NULL)
1624 return CELT_BAD_ARG;
1625
Jean-Marc Valin80ed1472009-10-15 21:45:32 -04001626 C = CHANNELS(st->channels);
Gregory Maxwell17169992009-06-04 15:15:34 -04001627 N = st->block_size;
Jean-Marc Valin234969c2009-10-17 22:12:42 -04001628 ALLOC(out, C*N, celt_sig);
Gregory Maxwell5f2a74b2008-08-11 23:50:07 -04001629
1630 ret=celt_decode_float(st, data, len, out);
1631
1632 for (j=0;j<C*N;j++)
Gregory Maxwell0719f6f2009-07-09 17:07:24 -04001633 pcm[j] = FLOAT2INT16 (out[j]);
1634
Wessel Lubberhuizen33ba6cc2008-10-03 07:09:29 -04001635 RESTORE_STACK;
Gregory Maxwell5f2a74b2008-08-11 23:50:07 -04001636 return ret;
1637}
1638#endif
John Ridges454d1d02009-05-21 22:38:39 -04001639
1640int celt_decoder_ctl(CELTDecoder * restrict st, int request, ...)
1641{
1642 va_list ap;
Gregory Maxwell17169992009-06-04 15:15:34 -04001643
1644 if (check_decoder(st) != CELT_OK)
1645 return CELT_INVALID_STATE;
1646
John Ridges454d1d02009-05-21 22:38:39 -04001647 va_start(ap, request);
Gregory Maxwell17169992009-06-04 15:15:34 -04001648 if ((request!=CELT_GET_MODE_REQUEST) && (check_mode(st->mode) != CELT_OK))
1649 goto bad_mode;
John Ridges454d1d02009-05-21 22:38:39 -04001650 switch (request)
1651 {
Gregory Maxwellf3b44ef2009-06-03 13:37:45 -04001652 case CELT_GET_MODE_REQUEST:
1653 {
1654 const CELTMode ** value = va_arg(ap, const CELTMode**);
1655 if (value==0)
1656 goto bad_arg;
1657 *value=st->mode;
1658 }
1659 break;
John Ridges454d1d02009-05-21 22:38:39 -04001660 case CELT_RESET_STATE:
1661 {
1662 const CELTMode *mode = st->mode;
Jean-Marc Valin80ed1472009-10-15 21:45:32 -04001663 int C = st->channels;
John Ridges454d1d02009-05-21 22:38:39 -04001664
1665 CELT_MEMSET(st->decode_mem, 0, (DECODE_BUFFER_SIZE+st->overlap)*C);
1666 CELT_MEMSET(st->oldBandE, 0, C*mode->nbEBands);
1667
1668 CELT_MEMSET(st->preemph_memD, 0, C);
1669
Jean-Marc Valin0f0da992009-08-12 21:34:01 -04001670 st->loss_count = 0;
John Ridges5378bf82010-02-12 07:08:01 -05001671
1672#ifdef NEW_PLC
1673 CELT_MEMSET(st->lpc, 0, C*LPC_ORDER);
1674#endif
John Ridges454d1d02009-05-21 22:38:39 -04001675 }
1676 break;
1677 default:
1678 goto bad_request;
1679 }
1680 va_end(ap);
1681 return CELT_OK;
Gregory Maxwell17169992009-06-04 15:15:34 -04001682bad_mode:
1683 va_end(ap);
1684 return CELT_INVALID_MODE;
John Ridges454d1d02009-05-21 22:38:39 -04001685bad_arg:
1686 va_end(ap);
1687 return CELT_BAD_ARG;
John Ridges454d1d02009-05-21 22:38:39 -04001688bad_request:
1689 va_end(ap);
1690 return CELT_UNIMPLEMENTED;
1691}
Jean-Marc Valinece94a02009-10-16 07:30:14 -04001692
1693const char *celt_strerror(int error)
1694{
1695 static const char *error_strings[8] = {
1696 "success",
1697 "invalid argument",
1698 "invalid mode",
1699 "internal error",
1700 "corrupted stream",
1701 "request not implemented",
1702 "invalid state",
1703 "memory allocation failed"
1704 };
1705 if (error > 0 || error < -7)
1706 return "unknown error";
1707 else
1708 return error_strings[-error];
1709}
1710