blob: 45fc1ec6f93a75a1d25a1a16a7ffb5f68064efde [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;
Jean-Marc Valin3b918ba2010-05-05 00:02:26 -0400352 B = shortBlocks;
Jean-Marc Valinaa4f58b2009-10-03 09:27:59 -0400353 }
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;
Jean-Marc Valin3b918ba2010-05-05 00:02:26 -0400405 B = shortBlocks;
Jean-Marc Valinde678582009-10-03 10:36:27 -0400406 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 Valind6b79ee2010-04-20 17:31:45 -0400532static void mdct_shape(const CELTMode *mode, celt_norm *X, int start,
Jean-Marc Valin3b918ba2010-05-05 00:02:26 -0400533 int end, int N,
Jean-Marc Valin65ee67a2010-04-26 07:08:44 -0400534 int mdct_weight_shift, int _C, int renorm, int M)
Jean-Marc Valin88619552009-10-04 21:35:36 -0400535{
536 int m, i, c;
Jean-Marc Valinbf2398b2009-10-15 07:28:19 -0400537 const int C = CHANNELS(_C);
Jean-Marc Valin88619552009-10-04 21:35:36 -0400538 for (c=0;c<C;c++)
539 for (m=start;m<end;m++)
Jean-Marc Valin3b918ba2010-05-05 00:02:26 -0400540 for (i=m+c*N;i<(c+1)*N;i+=M)
Jean-Marc Valin88619552009-10-04 21:35:36 -0400541#ifdef FIXED_POINT
542 X[i] = SHR16(X[i], mdct_weight_shift);
543#else
544 X[i] = (1.f/(1<<mdct_weight_shift))*X[i];
545#endif
Jean-Marc Valind6b79ee2010-04-20 17:31:45 -0400546 if (renorm)
Jean-Marc Valin65ee67a2010-04-26 07:08:44 -0400547 renormalise_bands(mode, X, C, M);
Jean-Marc Valin88619552009-10-04 21:35:36 -0400548}
549
550
Gregory Maxwell5f2a74b2008-08-11 23:50:07 -0400551#ifdef FIXED_POINT
Jean-Marc Valin30f7f812009-10-17 14:35:13 -0400552int 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 +1100553{
Gregory Maxwell5f2a74b2008-08-11 23:50:07 -0400554#else
Jean-Marc Valin234969c2009-10-17 22:12:42 -0400555int 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 -0400556{
557#endif
Jean-Marc Valin88619552009-10-04 21:35:36 -0400558 int i, c, N, NN, N4;
Jean-Marc Valin7e8a4872008-02-11 16:55:34 +1100559 int has_pitch;
Jean-Marc Valin0bb05bc2008-02-20 13:43:40 +1100560 int pitch_index;
Jean-Marc Valinc890b582008-08-01 22:26:49 -0400561 int bits;
Jean-Marc Valinbc799912008-11-07 22:53:13 -0500562 int has_fold=1;
Jean-Marc Valinab4dcc52009-10-21 07:08:27 -0400563 int coarse_needed;
Jean-Marc Valin8679a802008-10-18 07:44:35 -0400564 ec_byte_buffer buf;
565 ec_enc enc;
Jean-Marc Valin234969c2009-10-17 22:12:42 -0400566 VARDECL(celt_sig, in);
567 VARDECL(celt_sig, freq);
568 VARDECL(celt_sig, pitch_freq);
569 VARDECL(celt_norm, X);
570 VARDECL(celt_ener, bandE);
571 VARDECL(celt_word16, bandLogE);
Jean-Marc Valin6775de32008-08-02 08:14:42 -0400572 VARDECL(int, fine_quant);
Jean-Marc Valin234969c2009-10-17 22:12:42 -0400573 VARDECL(celt_word16, error);
Jean-Marc Valin6775de32008-08-02 08:14:42 -0400574 VARDECL(int, pulses);
575 VARDECL(int, offsets);
Jean-Marc Valin52cb5fb2009-06-10 08:08:55 -0400576 VARDECL(int, fine_priority);
Jean-Marc Valin18a3b792009-05-01 19:58:55 -0400577 int intra_ener = 0;
Jean-Marc Valin9d1decd2008-06-17 13:28:13 +1000578 int shortBlocks=0;
Jean-Marc Valin3b918ba2010-05-05 00:02:26 -0400579 int isTransient=0;
Jean-Marc Valin12b22482008-06-16 14:13:05 +1000580 int transient_time;
Jean-Marc Valin528f4b82008-06-29 03:46:39 +1000581 int transient_shift;
Jean-Marc Valinb8ba70c2010-04-18 22:10:24 -0400582 int resynth;
Jean-Marc Valin80ed1472009-10-15 21:45:32 -0400583 const int C = CHANNELS(st->channels);
Jean-Marc Valinaa936252009-05-29 22:14:20 -0400584 int mdct_weight_shift = 0;
585 int mdct_weight_pos=0;
Jean-Marc Valinab220aa2009-09-15 22:38:40 -0400586 int gain_id=0;
Jean-Marc Valin92ae3702009-09-16 07:57:17 -0400587 int norm_rate;
Jean-Marc Valin3a0bc3d2010-02-21 15:10:22 -0500588 int start=0;
Jean-Marc Valin65ee67a2010-04-26 07:08:44 -0400589 const int M=st->mode->nbShortMdcts;
Jean-Marc Valin8600f692008-02-29 15:14:12 +1100590 SAVE_STACK;
Jean-Marc Valin44ffd5a2008-02-22 00:39:25 +1100591
Gregory Maxwell17169992009-06-04 15:15:34 -0400592 if (check_encoder(st) != CELT_OK)
593 return CELT_INVALID_STATE;
594
Jean-Marc Valin44ffd5a2008-02-22 00:39:25 +1100595 if (check_mode(st->mode) != CELT_OK)
596 return CELT_INVALID_MODE;
597
Gregory Maxwell0719f6f2009-07-09 17:07:24 -0400598 if (nbCompressedBytes<0 || pcm==NULL)
Gregory Maxwell520eeae2009-02-09 01:33:21 -0500599 return CELT_BAD_ARG;
600
Jean-Marc Valin56522ad2009-06-05 17:17:25 -0400601 /* The memset is important for now in case the encoder doesn't
602 fill up all the bytes */
Jean-Marc Valin8679a802008-10-18 07:44:35 -0400603 CELT_MEMSET(compressed, 0, nbCompressedBytes);
604 ec_byte_writeinit_buffer(&buf, compressed, nbCompressedBytes);
605 ec_enc_init(&enc,&buf);
606
Jean-Marc Valinf02ba112007-11-30 01:10:42 +1100607 N = st->block_size;
Jean-Marc Valina536f772008-03-22 09:01:50 +1100608 N4 = (N-st->overlap)>>1;
Jean-Marc Valin234969c2009-10-17 22:12:42 -0400609 ALLOC(in, 2*C*N-2*C*N4, celt_sig);
Jean-Marc Valina5431bf2008-01-03 20:53:01 +1100610
Jean-Marc Valinbdb58832008-04-20 17:42:10 +1000611 CELT_COPY(in, st->in_mem, C*st->overlap);
Jean-Marc Valinffa13472007-12-10 16:54:17 +1100612 for (c=0;c<C;c++)
Jean-Marc Valin6f7e83d2007-12-01 00:36:41 +1100613 {
Jean-Marc Valin234969c2009-10-17 22:12:42 -0400614 const celt_word16 * restrict pcmp = pcm+c;
615 celt_sig * restrict inp = in+C*st->overlap+c;
Jean-Marc Valinb886ddc2008-03-25 14:38:55 +1100616 for (i=0;i<N;i++)
Jean-Marc Valinffa13472007-12-10 16:54:17 +1100617 {
Jean-Marc Valin62290062008-04-20 22:16:02 +1000618 /* Apply pre-emphasis */
Jean-Marc Valin234969c2009-10-17 22:12:42 -0400619 celt_sig tmp = SCALEIN(SHL32(EXTEND32(*pcmp), SIG_SHIFT));
Jean-Marc Valin5c3bc672008-08-28 23:34:24 -0400620 *inp = SUB32(tmp, SHR32(MULT16_16(preemph,st->preemph_memE[c]),3));
Gregory Maxwell5f2a74b2008-08-11 23:50:07 -0400621 st->preemph_memE[c] = SCALEIN(*pcmp);
Jean-Marc Valin62290062008-04-20 22:16:02 +1000622 inp += C;
623 pcmp += C;
Jean-Marc Valinffa13472007-12-10 16:54:17 +1100624 }
Jean-Marc Valin6f7e83d2007-12-01 00:36:41 +1100625 }
Jean-Marc Valinbdb58832008-04-20 17:42:10 +1000626 CELT_COPY(st->in_mem, in+C*(2*N-2*N4-st->overlap), C*st->overlap);
Jean-Marc Valin2014ca32009-06-18 23:33:04 -0400627
Jean-Marc Valin37ab9c62008-11-08 09:14:38 -0500628 /* Transient handling */
Jean-Marc Valin2014ca32009-06-18 23:33:04 -0400629 transient_time = -1;
630 transient_shift = 0;
Jean-Marc Valin3b918ba2010-05-05 00:02:26 -0400631 isTransient = 0;
Jean-Marc Valin2014ca32009-06-18 23:33:04 -0400632
Jean-Marc Valinb8ba70c2010-04-18 22:10:24 -0400633 resynth = st->pitch_available>0 || optional_synthesis!=NULL;
634
Jean-Marc Valin3b918ba2010-05-05 00:02:26 -0400635 if (M > 1 && transient_analysis(in, N+st->overlap, C, &transient_time, &transient_shift, &st->frame_max))
Jean-Marc Valin9375aa42008-06-27 07:57:35 +1000636 {
Jean-Marc Valin7028d622008-07-10 23:06:58 -0400637#ifndef FIXED_POINT
Jean-Marc Valin2014ca32009-06-18 23:33:04 -0400638 float gain_1;
Jean-Marc Valin528f4b82008-06-29 03:46:39 +1000639#endif
Jean-Marc Valin2014ca32009-06-18 23:33:04 -0400640 /* Apply the inverse shaping window */
641 if (transient_shift)
642 {
Jean-Marc Valin7028d622008-07-10 23:06:58 -0400643#ifdef FIXED_POINT
Jean-Marc Valin2014ca32009-06-18 23:33:04 -0400644 for (c=0;c<C;c++)
645 for (i=0;i<16;i++)
646 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]);
647 for (c=0;c<C;c++)
648 for (i=transient_time;i<N+st->overlap;i++)
649 in[C*i+c] = SHR32(in[C*i+c], transient_shift);
Jean-Marc Valin7028d622008-07-10 23:06:58 -0400650#else
Jean-Marc Valin2014ca32009-06-18 23:33:04 -0400651 for (c=0;c<C;c++)
652 for (i=0;i<16;i++)
653 in[C*(transient_time+i-16)+c] /= 1+transientWindow[i]*((1<<transient_shift)-1);
654 gain_1 = 1./(1<<transient_shift);
655 for (c=0;c<C;c++)
656 for (i=transient_time;i<N+st->overlap;i++)
657 in[C*i+c] *= gain_1;
Jean-Marc Valin7028d622008-07-10 23:06:58 -0400658#endif
Jean-Marc Valin528f4b82008-06-29 03:46:39 +1000659 }
Jean-Marc Valin3b918ba2010-05-05 00:02:26 -0400660 isTransient = 1;
Jean-Marc Valin2014ca32009-06-18 23:33:04 -0400661 has_fold = 1;
Jean-Marc Valin12b22482008-06-16 14:13:05 +1000662 }
Jean-Marc Valinc5f2a9d2008-10-26 22:00:26 -0400663
Jean-Marc Valin3b918ba2010-05-05 00:02:26 -0400664 if (isTransient)
665 shortBlocks = M;
666 else
667 shortBlocks = 0;
668
Jean-Marc Valin234969c2009-10-17 22:12:42 -0400669 ALLOC(freq, C*N, celt_sig); /**< Interleaved signal MDCTs */
670 ALLOC(bandE,st->mode->nbEBands*C, celt_ener);
671 ALLOC(bandLogE,st->mode->nbEBands*C, celt_word16);
Jean-Marc Valin32ec58c2009-05-01 21:28:58 -0400672 /* Compute MDCTs */
Jean-Marc Valinbf2398b2009-10-15 07:28:19 -0400673 compute_mdcts(st->mode, shortBlocks, in, freq, C);
Jean-Marc Valin08a82ff2009-06-14 14:05:19 -0400674
Jean-Marc Valinaa936252009-05-29 22:14:20 -0400675
Jean-Marc Valin30f7f812009-10-17 14:35:13 -0400676 norm_rate = (nbCompressedBytes-5)*8*(celt_uint32)st->mode->Fs/(C*N)>>10;
Jean-Marc Valinddb181b2008-03-03 14:53:47 +1100677 /* Pitch analysis: we do it early to save on the peak stack space */
Jean-Marc Valin56522ad2009-06-05 17:17:25 -0400678 /* Don't use pitch if there isn't enough data available yet,
679 or if we're using shortBlocks */
Jean-Marc Valine6d832a2009-07-08 22:21:31 -0400680 has_pitch = st->pitch_enabled && st->pitch_permitted && (N <= 512)
Jean-Marc Valin92ae3702009-09-16 07:57:17 -0400681 && (st->pitch_available >= MAX_PERIOD) && (!shortBlocks)
682 && norm_rate < 50;
Gregory Maxwell98046ca2008-12-13 20:42:03 -0500683 if (has_pitch)
Jean-Marc Valinc5f2a9d2008-10-26 22:00:26 -0400684 {
Jean-Marc Valine465c142009-11-26 00:39:36 -0500685 VARDECL(celt_word16, x_lp);
Jean-Marc Valind5f99302009-12-16 22:42:32 -0500686 SAVE_STACK;
Jean-Marc Valine465c142009-11-26 00:39:36 -0500687 ALLOC(x_lp, (2*N-2*N4)>>1, celt_word16);
688 pitch_downsample(in, x_lp, 2*N-2*N4, N, C, &st->xmem, &st->pitch_buf[MAX_PERIOD>>1]);
689 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 -0500690 RESTORE_STACK;
Jean-Marc Valinc5f2a9d2008-10-26 22:00:26 -0400691 }
Jean-Marc Valin37ab9c62008-11-08 09:14:38 -0500692
Jean-Marc Valin56522ad2009-06-05 17:17:25 -0400693 /* Deferred allocation after find_spectral_pitch() to reduce
694 the peak memory usage */
Jean-Marc Valin234969c2009-10-17 22:12:42 -0400695 ALLOC(X, C*N, celt_norm); /**< Interleaved normalised MDCTs */
Jean-Marc Valin8d4ac152008-02-29 17:24:02 +1100696
Jean-Marc Valin234969c2009-10-17 22:12:42 -0400697 ALLOC(pitch_freq, C*N, celt_sig); /**< Interleaved signal MDCTs */
Jean-Marc Valin4c77ea92009-09-14 22:50:41 -0400698 if (has_pitch)
699 {
Jean-Marc Valinbf2398b2009-10-15 07:28:19 -0400700 compute_mdcts(st->mode, 0, st->out_mem+pitch_index*C, pitch_freq, C);
Jean-Marc Valind35d6772009-10-16 23:16:47 -0400701 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 -0400702 }
703
704 if (has_pitch)
Jean-Marc Valinbf2398b2009-10-15 07:28:19 -0400705 apply_pitch(st->mode, freq, pitch_freq, gain_id, 1, C);
Jean-Marc Valin6c245242007-12-29 23:27:42 +1100706
Jean-Marc Valin65ee67a2010-04-26 07:08:44 -0400707 compute_band_energies(st->mode, freq, bandE, C, M);
Jean-Marc Valin4c77ea92009-09-14 22:50:41 -0400708 for (i=0;i<st->mode->nbEBands*C;i++)
709 bandLogE[i] = amp2Log(bandE[i]);
Jean-Marc Valinbd5d54a2009-10-20 00:25:31 -0400710
Jean-Marc Valin8ebd3452007-11-29 20:17:32 +1100711 /* Band normalisation */
Jean-Marc Valin65ee67a2010-04-26 07:08:44 -0400712 normalise_bands(st->mode, freq, X, bandE, C, M);
713 if (!shortBlocks && !folding_decision(st->mode, X, &st->tonal_average, &st->fold_decision, C, M))
Jean-Marc Valin527db5c2009-06-02 07:56:19 -0400714 has_fold = 0;
Jean-Marc Valin26c9e142007-12-31 21:27:54 +1100715
Jean-Marc Valin4c77ea92009-09-14 22:50:41 -0400716 /* Don't use intra energy when we're operating at low bit-rate */
717 intra_ener = st->force_intra || (!has_pitch && st->delayedIntra && nbCompressedBytes > st->mode->nbEBands);
718 if (shortBlocks || intra_decision(bandLogE, st->oldBandE, st->mode->nbEBands))
719 st->delayedIntra = 1;
720 else
721 st->delayedIntra = 0;
722
Jean-Marc Valin65ee67a2010-04-26 07:08:44 -0400723 NN = M*st->mode->eBands[st->mode->nbEBands];
Jean-Marc Valin88619552009-10-04 21:35:36 -0400724 if (shortBlocks && !transient_shift)
725 {
Jean-Marc Valin234969c2009-10-17 22:12:42 -0400726 celt_word32 sum[8]={1,1,1,1,1,1,1,1};
Jean-Marc Valin88619552009-10-04 21:35:36 -0400727 int m;
728 for (c=0;c<C;c++)
729 {
730 m=0;
731 do {
Jean-Marc Valin234969c2009-10-17 22:12:42 -0400732 celt_word32 tmp=0;
Jean-Marc Valin3b918ba2010-05-05 00:02:26 -0400733 for (i=m+c*N;i<c*N+NN;i+=M)
Jean-Marc Valin88619552009-10-04 21:35:36 -0400734 tmp += ABS32(X[i]);
735 sum[m++] += tmp;
Jean-Marc Valin3b918ba2010-05-05 00:02:26 -0400736 } while (m<M);
Jean-Marc Valin88619552009-10-04 21:35:36 -0400737 }
738 m=0;
739#ifdef FIXED_POINT
740 do {
741 if (SHR32(sum[m+1],3) > sum[m])
742 {
743 mdct_weight_shift=2;
744 mdct_weight_pos = m;
745 } else if (SHR32(sum[m+1],1) > sum[m] && mdct_weight_shift < 2)
746 {
747 mdct_weight_shift=1;
748 mdct_weight_pos = m;
749 }
750 m++;
Jean-Marc Valin3b918ba2010-05-05 00:02:26 -0400751 } while (m<M-1);
Jean-Marc Valin88619552009-10-04 21:35:36 -0400752#else
753 do {
754 if (sum[m+1] > 8*sum[m])
755 {
756 mdct_weight_shift=2;
757 mdct_weight_pos = m;
758 } else if (sum[m+1] > 2*sum[m] && mdct_weight_shift < 2)
759 {
760 mdct_weight_shift=1;
761 mdct_weight_pos = m;
762 }
763 m++;
Jean-Marc Valin3b918ba2010-05-05 00:02:26 -0400764 } while (m<M-1);
Jean-Marc Valin88619552009-10-04 21:35:36 -0400765#endif
766 if (mdct_weight_shift)
Jean-Marc Valin3b918ba2010-05-05 00:02:26 -0400767 mdct_shape(st->mode, X, mdct_weight_pos+1, M, N, mdct_weight_shift, C, 0, M);
Jean-Marc Valin88619552009-10-04 21:35:36 -0400768 }
769
Jean-Marc Valin4c77ea92009-09-14 22:50:41 -0400770
Jean-Marc Valin18a3b792009-05-01 19:58:55 -0400771 encode_flags(&enc, intra_ener, has_pitch, shortBlocks, has_fold);
Jean-Marc Valin05ed03e2009-04-29 07:44:13 -0400772 if (has_pitch)
773 {
Gregory Maxwellabe40f02008-12-13 01:31:32 -0500774 ec_enc_uint(&enc, pitch_index, MAX_PERIOD-(2*N-2*N4));
Jean-Marc Valin4c77ea92009-09-14 22:50:41 -0400775 ec_enc_uint(&enc, gain_id, 16);
Jean-Marc Valin96870d92007-12-05 21:14:22 +1100776 }
Jean-Marc Valin05ed03e2009-04-29 07:44:13 -0400777 if (shortBlocks)
778 {
Jean-Marc Valin05ed03e2009-04-29 07:44:13 -0400779 if (transient_shift)
Jean-Marc Valinaa936252009-05-29 22:14:20 -0400780 {
Jean-Marc Valine6108642009-08-01 23:05:47 +0200781 ec_enc_uint(&enc, transient_shift, 4);
Jean-Marc Valin05ed03e2009-04-29 07:44:13 -0400782 ec_enc_uint(&enc, transient_time, N+st->overlap);
Jean-Marc Valinaa936252009-05-29 22:14:20 -0400783 } else {
Jean-Marc Valine6108642009-08-01 23:05:47 +0200784 ec_enc_uint(&enc, mdct_weight_shift, 4);
Jean-Marc Valin3b918ba2010-05-05 00:02:26 -0400785 if (mdct_weight_shift && M!=2)
786 ec_enc_uint(&enc, mdct_weight_pos, M-1);
Jean-Marc Valinaa936252009-05-29 22:14:20 -0400787 }
Jean-Marc Valin05ed03e2009-04-29 07:44:13 -0400788 }
Jean-Marc Valinc890b582008-08-01 22:26:49 -0400789
Jean-Marc Valin6775de32008-08-02 08:14:42 -0400790 ALLOC(fine_quant, st->mode->nbEBands, int);
Jean-Marc Valin8dff9232008-08-13 22:07:20 -0400791 ALLOC(pulses, st->mode->nbEBands, int);
Jean-Marc Valin37ab9c62008-11-08 09:14:38 -0500792
Jean-Marc Valin25767d12009-10-21 23:24:18 -0400793 /* Computes the max bit-rate allowed in VBR more to avoid busting the budget */
794 if (st->vbr_rate>0)
795 {
796 celt_int32 vbr_bound, max_allowed;
797
798 vbr_bound = st->vbr_rate;
Jean-Marc Valin7a047ea2009-10-22 00:23:56 -0400799 max_allowed = (st->vbr_rate + vbr_bound - st->vbr_reservoir)>>(BITRES+3);
800 if (max_allowed < 4)
801 max_allowed = 4;
Jean-Marc Valin25767d12009-10-21 23:24:18 -0400802 if (max_allowed < nbCompressedBytes)
803 nbCompressedBytes = max_allowed;
804 }
805
Jean-Marc Valin37ab9c62008-11-08 09:14:38 -0500806 /* Bit allocation */
Jean-Marc Valin234969c2009-10-17 22:12:42 -0400807 ALLOC(error, C*st->mode->nbEBands, celt_word16);
Jean-Marc Valin3a0bc3d2010-02-21 15:10:22 -0500808 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 -0400809 coarse_needed = ((coarse_needed*3-1)>>3)+1;
Jean-Marc Valin25767d12009-10-21 23:24:18 -0400810 if (coarse_needed > nbCompressedBytes)
811 coarse_needed = nbCompressedBytes;
Gregory Maxwell888d8ce2009-05-21 04:21:53 -0400812 /* Variable bitrate */
Jean-Marc Valinbd5d54a2009-10-20 00:25:31 -0400813 if (st->vbr_rate>0)
Gregory Maxwell888d8ce2009-05-21 04:21:53 -0400814 {
Jean-Marc Valinbd5d54a2009-10-20 00:25:31 -0400815 celt_word16 alpha;
Jean-Marc Valin25767d12009-10-21 23:24:18 -0400816 celt_int32 delta;
Gregory Maxwell888d8ce2009-05-21 04:21:53 -0400817 /* The target rate in 16th bits per frame */
Jean-Marc Valinbd5d54a2009-10-20 00:25:31 -0400818 celt_int32 target=st->vbr_rate;
Jean-Marc Valin6775de32008-08-02 08:14:42 -0400819
Jean-Marc Valin56522ad2009-06-05 17:17:25 -0400820 /* Shortblocks get a large boost in bitrate, but since they
821 are uncommon long blocks are not greatly effected */
Gregory Maxwell888d8ce2009-05-21 04:21:53 -0400822 if (shortBlocks)
823 target*=2;
Jean-Marc Valin3b918ba2010-05-05 00:02:26 -0400824 else if (M > 1)
Jean-Marc Valinbd5d54a2009-10-20 00:25:31 -0400825 target-=(target+14)/28;
Gregory Maxwell888d8ce2009-05-21 04:21:53 -0400826
Jean-Marc Valin56522ad2009-06-05 17:17:25 -0400827 /* The average energy is removed from the target and the actual
828 energy added*/
Jean-Marc Valinbd5d54a2009-10-20 00:25:31 -0400829 target=target+st->vbr_offset-588+ec_enc_tell(&enc, BITRES);
Gregory Maxwell888d8ce2009-05-21 04:21:53 -0400830
831 /* In VBR mode the frame size must not be reduced so much that it would result in the coarse energy busting its budget */
832 target=IMAX(coarse_needed,(target+64)/128);
Jean-Marc Valin45f11102009-10-22 00:12:31 -0400833 target=IMIN(nbCompressedBytes,target);
Jean-Marc Valinbd5d54a2009-10-20 00:25:31 -0400834 /* Make the adaptation coef (alpha) higher at the beginning */
835 if (st->vbr_count < 990)
836 {
837 st->vbr_count++;
838 alpha = celt_rcp(SHL32(EXTEND32(st->vbr_count+10),16));
839 /*printf ("%d %d\n", st->vbr_count+10, alpha);*/
840 } else
841 alpha = QCONST16(.001f,15);
842
843 /* By how much did we "miss" the target on that frame */
Jean-Marc Valin45f11102009-10-22 00:12:31 -0400844 delta = (8<<BITRES)*(celt_int32)target - st->vbr_rate;
Jean-Marc Valinbd5d54a2009-10-20 00:25:31 -0400845 /* How many bits have we used in excess of what we're allowed */
846 st->vbr_reservoir += delta;
847 /*printf ("%d\n", st->vbr_reservoir);*/
848
849 /* Compute the offset we need to apply in order to reach the target */
850 st->vbr_drift += MULT16_32_Q15(alpha,delta-st->vbr_offset-st->vbr_drift);
851 st->vbr_offset = -st->vbr_drift;
852 /*printf ("%d\n", st->vbr_drift);*/
853
854 /* We could use any multiple of vbr_rate as bound (depending on the delay) */
Jean-Marc Valin25767d12009-10-21 23:24:18 -0400855 if (st->vbr_reservoir < 0)
Jean-Marc Valinbd5d54a2009-10-20 00:25:31 -0400856 {
857 /* We're under the min value -- increase rate */
858 int adjust = 1-(st->vbr_reservoir-1)/(8<<BITRES);
859 st->vbr_reservoir += adjust*(8<<BITRES);
Jean-Marc Valin45f11102009-10-22 00:12:31 -0400860 target += adjust;
Jean-Marc Valinbd5d54a2009-10-20 00:25:31 -0400861 /*printf ("+%d\n", adjust);*/
862 }
Jean-Marc Valin45f11102009-10-22 00:12:31 -0400863 if (target < nbCompressedBytes)
864 nbCompressedBytes = target;
Jean-Marc Valinbd5d54a2009-10-20 00:25:31 -0400865 /* This moves the raw bits to take into account the new compressed size */
Jean-Marc Valine6108642009-08-01 23:05:47 +0200866 ec_byte_shrink(&buf, nbCompressedBytes);
Gregory Maxwell888d8ce2009-05-21 04:21:53 -0400867 }
868
Jean-Marc Valin6775de32008-08-02 08:14:42 -0400869 ALLOC(offsets, st->mode->nbEBands, int);
Jean-Marc Valin52cb5fb2009-06-10 08:08:55 -0400870 ALLOC(fine_priority, st->mode->nbEBands, int);
Jean-Marc Valincb7a2a32008-02-11 16:44:48 +1100871
Jean-Marc Valin6775de32008-08-02 08:14:42 -0400872 for (i=0;i<st->mode->nbEBands;i++)
873 offsets[i] = 0;
Jean-Marc Valin8679a802008-10-18 07:44:35 -0400874 bits = nbCompressedBytes*8 - ec_enc_tell(&enc, 0) - 1;
Jean-Marc Valin65ee67a2010-04-26 07:08:44 -0400875 compute_allocation(st->mode, start, offsets, bits, pulses, fine_quant, fine_priority, C, M);
Jean-Marc Valin37ab9c62008-11-08 09:14:38 -0500876
Jean-Marc Valin3a0bc3d2010-02-21 15:10:22 -0500877 quant_fine_energy(st->mode, start, bandE, st->oldBandE, error, fine_quant, &enc, C);
Jean-Marc Valin6775de32008-08-02 08:14:42 -0400878
Jean-Marc Valin8ebd3452007-11-29 20:17:32 +1100879 /* Residual quantisation */
Jean-Marc Valinca53b7c2009-03-26 20:23:14 -0400880 if (C==1)
Jean-Marc Valin65ee67a2010-04-26 07:08:44 -0400881 quant_bands(st->mode, start, X, bandE, pulses, shortBlocks, has_fold, resynth, nbCompressedBytes*8, 1, &enc, M);
Jean-Marc Valin73532032009-06-02 20:07:25 -0400882#ifndef DISABLE_STEREO
Jean-Marc Valinca53b7c2009-03-26 20:23:14 -0400883 else
Jean-Marc Valin65ee67a2010-04-26 07:08:44 -0400884 quant_bands_stereo(st->mode, start, X, bandE, pulses, shortBlocks, has_fold, resynth, nbCompressedBytes*8, &enc, M);
Jean-Marc Valin73532032009-06-02 20:07:25 -0400885#endif
Jean-Marc Valin39710532009-06-09 00:10:32 -0400886
Jean-Marc Valin3a0bc3d2010-02-21 15:10:22 -0500887 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 -0400888
Jean-Marc Valin37ab9c62008-11-08 09:14:38 -0500889 /* Re-synthesis of the coded audio if required */
Jean-Marc Valinb8ba70c2010-04-18 22:10:24 -0400890 if (resynth)
Jean-Marc Valin18ddc022008-02-22 14:24:50 +1100891 {
Gregory Maxwell98046ca2008-12-13 20:42:03 -0500892 if (st->pitch_available>0 && st->pitch_available<MAX_PERIOD)
893 st->pitch_available+=st->frame_size;
894
Jean-Marc Valinaa936252009-05-29 22:14:20 -0400895 if (mdct_weight_shift)
896 {
Jean-Marc Valin3b918ba2010-05-05 00:02:26 -0400897 mdct_shape(st->mode, X, 0, mdct_weight_pos+1, N, mdct_weight_shift, C, 1, M);
Jean-Marc Valinaa936252009-05-29 22:14:20 -0400898 }
Jean-Marc Valin88619552009-10-04 21:35:36 -0400899
900 /* Synthesis */
Jean-Marc Valin65ee67a2010-04-26 07:08:44 -0400901 denormalise_bands(st->mode, X, freq, bandE, C, M);
Jean-Marc Valin88619552009-10-04 21:35:36 -0400902
903 CELT_MOVE(st->out_mem, st->out_mem+C*N, C*(MAX_PERIOD+st->overlap-N));
904
Jean-Marc Valin4c77ea92009-09-14 22:50:41 -0400905 if (has_pitch)
Jean-Marc Valinbf2398b2009-10-15 07:28:19 -0400906 apply_pitch(st->mode, freq, pitch_freq, gain_id, 0, C);
Jean-Marc Valin4c77ea92009-09-14 22:50:41 -0400907
Jean-Marc Valinbf2398b2009-10-15 07:28:19 -0400908 compute_inv_mdcts(st->mode, shortBlocks, freq, transient_time, transient_shift, st->out_mem, C);
Jean-Marc Valine12017e2009-10-03 13:57:31 -0400909
Jean-Marc Valin56522ad2009-06-05 17:17:25 -0400910 /* De-emphasis and put everything back at the right place
911 in the synthesis history */
Gregory Maxwell82595312008-09-30 18:20:14 -0400912 if (optional_synthesis != NULL) {
Jean-Marc Valine12017e2009-10-03 13:57:31 -0400913 deemphasis(st->out_mem, optional_synthesis, N, C, preemph, st->preemph_memD);
914
Jean-Marc Valin6f7e83d2007-12-01 00:36:41 +1100915 }
Jean-Marc Valind9b95652008-08-31 23:34:47 -0400916 }
Gregory Maxwell54547f12009-02-16 18:56:44 -0500917
Jean-Marc Valin8679a802008-10-18 07:44:35 -0400918 ec_enc_done(&enc);
Jean-Marc Valinc871c8d2009-06-09 00:57:00 -0400919
Jean-Marc Valin8600f692008-02-29 15:14:12 +1100920 RESTORE_STACK;
Jean-Marc Valina76a0b22008-01-17 22:43:05 +1100921 return nbCompressedBytes;
Jean-Marc Valin8ebd3452007-11-29 20:17:32 +1100922}
923
Gregory Maxwell5f2a74b2008-08-11 23:50:07 -0400924#ifdef FIXED_POINT
925#ifndef DISABLE_FLOAT_API
Gregory Maxwell82595312008-09-30 18:20:14 -0400926int celt_encode_float(CELTEncoder * restrict st, const float * pcm, float * optional_synthesis, unsigned char *compressed, int nbCompressedBytes)
Gregory Maxwell5f2a74b2008-08-11 23:50:07 -0400927{
Gregory Maxwell17169992009-06-04 15:15:34 -0400928 int j, ret, C, N;
Jean-Marc Valin30f7f812009-10-17 14:35:13 -0400929 VARDECL(celt_int16, in);
Jean-Marc Valincb8780c2009-07-20 23:40:35 -0400930 SAVE_STACK;
Gregory Maxwell17169992009-06-04 15:15:34 -0400931
932 if (check_encoder(st) != CELT_OK)
933 return CELT_INVALID_STATE;
934
935 if (check_mode(st->mode) != CELT_OK)
936 return CELT_INVALID_MODE;
937
Gregory Maxwell0719f6f2009-07-09 17:07:24 -0400938 if (pcm==NULL)
939 return CELT_BAD_ARG;
940
Jean-Marc Valin80ed1472009-10-15 21:45:32 -0400941 C = CHANNELS(st->channels);
Gregory Maxwell17169992009-06-04 15:15:34 -0400942 N = st->block_size;
Jean-Marc Valin30f7f812009-10-17 14:35:13 -0400943 ALLOC(in, C*N, celt_int16);
Gregory Maxwell5f2a74b2008-08-11 23:50:07 -0400944
945 for (j=0;j<C*N;j++)
946 in[j] = FLOAT2INT16(pcm[j]);
947
Gregory Maxwell82595312008-09-30 18:20:14 -0400948 if (optional_synthesis != NULL) {
949 ret=celt_encode(st,in,in,compressed,nbCompressedBytes);
Gregory Maxwellb0a73a02008-12-12 16:54:25 -0500950 for (j=0;j<C*N;j++)
Gregory Maxwell82595312008-09-30 18:20:14 -0400951 optional_synthesis[j]=in[j]*(1/32768.);
952 } else {
953 ret=celt_encode(st,in,NULL,compressed,nbCompressedBytes);
954 }
Wessel Lubberhuizen33ba6cc2008-10-03 07:09:29 -0400955 RESTORE_STACK;
Gregory Maxwell5f2a74b2008-08-11 23:50:07 -0400956 return ret;
957
958}
959#endif /*DISABLE_FLOAT_API*/
960#else
Jean-Marc Valin30f7f812009-10-17 14:35:13 -0400961int 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 -0400962{
Gregory Maxwell17169992009-06-04 15:15:34 -0400963 int j, ret, C, N;
Jean-Marc Valin234969c2009-10-17 22:12:42 -0400964 VARDECL(celt_sig, in);
Jean-Marc Valincb8780c2009-07-20 23:40:35 -0400965 SAVE_STACK;
Gregory Maxwell17169992009-06-04 15:15:34 -0400966
967 if (check_encoder(st) != CELT_OK)
968 return CELT_INVALID_STATE;
969
970 if (check_mode(st->mode) != CELT_OK)
971 return CELT_INVALID_MODE;
972
Gregory Maxwell0719f6f2009-07-09 17:07:24 -0400973 if (pcm==NULL)
974 return CELT_BAD_ARG;
975
Jean-Marc Valin80ed1472009-10-15 21:45:32 -0400976 C=CHANNELS(st->channels);
Gregory Maxwell17169992009-06-04 15:15:34 -0400977 N=st->block_size;
Jean-Marc Valin234969c2009-10-17 22:12:42 -0400978 ALLOC(in, C*N, celt_sig);
Gregory Maxwell5f2a74b2008-08-11 23:50:07 -0400979 for (j=0;j<C*N;j++) {
980 in[j] = SCALEOUT(pcm[j]);
981 }
Gregory Maxwell5f2a74b2008-08-11 23:50:07 -0400982
Gregory Maxwell82595312008-09-30 18:20:14 -0400983 if (optional_synthesis != NULL) {
984 ret = celt_encode_float(st,in,in,compressed,nbCompressedBytes);
985 for (j=0;j<C*N;j++)
986 optional_synthesis[j] = FLOAT2INT16(in[j]);
987 } else {
988 ret = celt_encode_float(st,in,NULL,compressed,nbCompressedBytes);
989 }
Wessel Lubberhuizen33ba6cc2008-10-03 07:09:29 -0400990 RESTORE_STACK;
Gregory Maxwell5f2a74b2008-08-11 23:50:07 -0400991 return ret;
992}
993#endif
Jean-Marc Valin6e9058a2007-12-07 14:59:06 +1100994
Jean-Marc Valinb6f90612008-10-05 22:39:13 -0400995int celt_encoder_ctl(CELTEncoder * restrict st, int request, ...)
Jean-Marc Valinc18fb1d2008-09-30 07:36:54 -0400996{
Jean-Marc Valinb6f90612008-10-05 22:39:13 -0400997 va_list ap;
Gregory Maxwell17169992009-06-04 15:15:34 -0400998
999 if (check_encoder(st) != CELT_OK)
1000 return CELT_INVALID_STATE;
1001
Jean-Marc Valinb6f90612008-10-05 22:39:13 -04001002 va_start(ap, request);
Gregory Maxwell17169992009-06-04 15:15:34 -04001003 if ((request!=CELT_GET_MODE_REQUEST) && (check_mode(st->mode) != CELT_OK))
1004 goto bad_mode;
Jean-Marc Valinc18fb1d2008-09-30 07:36:54 -04001005 switch (request)
1006 {
Gregory Maxwellf3b44ef2009-06-03 13:37:45 -04001007 case CELT_GET_MODE_REQUEST:
1008 {
1009 const CELTMode ** value = va_arg(ap, const CELTMode**);
1010 if (value==0)
1011 goto bad_arg;
1012 *value=st->mode;
1013 }
1014 break;
Jean-Marc Valinb6f90612008-10-05 22:39:13 -04001015 case CELT_SET_COMPLEXITY_REQUEST:
Jean-Marc Valinc18fb1d2008-09-30 07:36:54 -04001016 {
Jean-Marc Valin30f7f812009-10-17 14:35:13 -04001017 int value = va_arg(ap, celt_int32);
Jean-Marc Valinb6f90612008-10-05 22:39:13 -04001018 if (value<0 || value>10)
1019 goto bad_arg;
Gregory Maxwell98046ca2008-12-13 20:42:03 -05001020 if (value<=2) {
1021 st->pitch_enabled = 0;
1022 st->pitch_available = 0;
1023 } else {
1024 st->pitch_enabled = 1;
1025 if (st->pitch_available<1)
1026 st->pitch_available = 1;
1027 }
1028 }
1029 break;
Gregory Maxwell2dd3d322009-06-05 14:05:51 -04001030 case CELT_SET_PREDICTION_REQUEST:
Gregory Maxwell98046ca2008-12-13 20:42:03 -05001031 {
Jean-Marc Valin30f7f812009-10-17 14:35:13 -04001032 int value = va_arg(ap, celt_int32);
Gregory Maxwell2dd3d322009-06-05 14:05:51 -04001033 if (value<0 || value>2)
Gregory Maxwell98046ca2008-12-13 20:42:03 -05001034 goto bad_arg;
1035 if (value==0)
Gregory Maxwell2dd3d322009-06-05 14:05:51 -04001036 {
1037 st->force_intra = 1;
1038 st->pitch_permitted = 0;
Gregory Maxwella80958b2009-06-29 12:48:57 -04001039 } else if (value==1) {
Gregory Maxwell2dd3d322009-06-05 14:05:51 -04001040 st->force_intra = 0;
1041 st->pitch_permitted = 0;
1042 } else {
1043 st->force_intra = 0;
1044 st->pitch_permitted = 1;
1045 }
Jean-Marc Valinc18fb1d2008-09-30 07:36:54 -04001046 }
1047 break;
Gregory Maxwell888d8ce2009-05-21 04:21:53 -04001048 case CELT_SET_VBR_RATE_REQUEST:
1049 {
Jean-Marc Valin30f7f812009-10-17 14:35:13 -04001050 celt_int32 value = va_arg(ap, celt_int32);
Gregory Maxwell888d8ce2009-05-21 04:21:53 -04001051 if (value<0)
1052 goto bad_arg;
1053 if (value>3072000)
1054 value = 3072000;
Jean-Marc Valinbd5d54a2009-10-20 00:25:31 -04001055 st->vbr_rate = ((st->mode->Fs<<3)+(st->block_size>>1))/st->block_size;
1056 st->vbr_rate = ((value<<7)+(st->vbr_rate>>1))/st->vbr_rate;
Gregory Maxwell888d8ce2009-05-21 04:21:53 -04001057 }
1058 break;
John Ridges454d1d02009-05-21 22:38:39 -04001059 case CELT_RESET_STATE:
1060 {
1061 const CELTMode *mode = st->mode;
Jean-Marc Valin80ed1472009-10-15 21:45:32 -04001062 int C = st->channels;
John Ridges454d1d02009-05-21 22:38:39 -04001063
1064 if (st->pitch_available > 0) st->pitch_available = 1;
1065
1066 CELT_MEMSET(st->in_mem, 0, st->overlap*C);
1067 CELT_MEMSET(st->out_mem, 0, (MAX_PERIOD+st->overlap)*C);
1068
1069 CELT_MEMSET(st->oldBandE, 0, C*mode->nbEBands);
1070
1071 CELT_MEMSET(st->preemph_memE, 0, C);
1072 CELT_MEMSET(st->preemph_memD, 0, C);
1073 st->delayedIntra = 1;
John Ridges5378bf82010-02-12 07:08:01 -05001074
1075 st->fold_decision = 1;
Jean-Marc Valin628c0252010-04-16 20:57:56 -04001076 st->tonal_average = QCONST16(1.f,8);
John Ridges5378bf82010-02-12 07:08:01 -05001077 st->gain_prod = 0;
1078 st->vbr_reservoir = 0;
1079 st->vbr_drift = 0;
1080 st->vbr_offset = 0;
1081 st->vbr_count = 0;
1082 st->xmem = 0;
Jean-Marc Valin9c30de52010-04-19 13:32:15 -04001083 st->frame_max = 0;
John Ridges5378bf82010-02-12 07:08:01 -05001084 CELT_MEMSET(st->pitch_buf, 0, (MAX_PERIOD>>1)+2);
John Ridges454d1d02009-05-21 22:38:39 -04001085 }
1086 break;
Jean-Marc Valinc18fb1d2008-09-30 07:36:54 -04001087 default:
Jean-Marc Valinb6f90612008-10-05 22:39:13 -04001088 goto bad_request;
Jean-Marc Valinc18fb1d2008-09-30 07:36:54 -04001089 }
Jean-Marc Valinb6f90612008-10-05 22:39:13 -04001090 va_end(ap);
Jean-Marc Valinc18fb1d2008-09-30 07:36:54 -04001091 return CELT_OK;
Gregory Maxwell17169992009-06-04 15:15:34 -04001092bad_mode:
1093 va_end(ap);
1094 return CELT_INVALID_MODE;
Jean-Marc Valinb6f90612008-10-05 22:39:13 -04001095bad_arg:
1096 va_end(ap);
1097 return CELT_BAD_ARG;
1098bad_request:
1099 va_end(ap);
1100 return CELT_UNIMPLEMENTED;
Jean-Marc Valinc18fb1d2008-09-30 07:36:54 -04001101}
1102
Jean-Marc Valin56522ad2009-06-05 17:17:25 -04001103/**********************************************************************/
1104/* */
1105/* DECODER */
1106/* */
1107/**********************************************************************/
Jean-Marc Valineafbdd52009-04-27 19:35:09 -04001108#ifdef NEW_PLC
1109#define DECODE_BUFFER_SIZE 2048
1110#else
1111#define DECODE_BUFFER_SIZE MAX_PERIOD
1112#endif
Jean-Marc Valin269d40a2007-12-07 11:29:45 +11001113
Gregory Maxwell17169992009-06-04 15:15:34 -04001114#define DECODERVALID 0x4c434454
1115#define DECODERPARTIAL 0x5444434c
1116#define DECODERFREED 0x4c004400
1117
Jean-Marc Valin276de722008-02-20 17:45:51 +11001118/** Decoder state
1119 @brief Decoder state
1120 */
Jean-Marc Valin269d40a2007-12-07 11:29:45 +11001121struct CELTDecoder {
Jean-Marc Valin30f7f812009-10-17 14:35:13 -04001122 celt_uint32 marker;
Jean-Marc Valin269d40a2007-12-07 11:29:45 +11001123 const CELTMode *mode;
1124 int frame_size;
1125 int block_size;
Jean-Marc Valina5431bf2008-01-03 20:53:01 +11001126 int overlap;
Jean-Marc Valin80ed1472009-10-15 21:45:32 -04001127 int channels;
Jean-Marc Valina5431bf2008-01-03 20:53:01 +11001128
Jean-Marc Valin269d40a2007-12-07 11:29:45 +11001129 ec_byte_buffer buf;
1130 ec_enc enc;
1131
Jean-Marc Valin234969c2009-10-17 22:12:42 -04001132 celt_sig * restrict preemph_memD;
Jean-Marc Valin81b38c22008-02-29 21:08:49 +11001133
Jean-Marc Valin234969c2009-10-17 22:12:42 -04001134 celt_sig *out_mem;
1135 celt_sig *decode_mem;
Jean-Marc Valin269d40a2007-12-07 11:29:45 +11001136
Jean-Marc Valin234969c2009-10-17 22:12:42 -04001137 celt_word16 *oldBandE;
Jean-Marc Valinfb83fb42007-12-08 00:56:04 +11001138
Jean-Marc Valind69c1cb2009-12-28 00:34:29 -05001139#ifdef NEW_PLC
Jean-Marc Valin74128be2010-01-01 09:33:17 -05001140 celt_word16 *lpc;
Jean-Marc Valin5a0fae52009-12-14 21:19:37 -05001141#endif
1142
Jean-Marc Valinfb83fb42007-12-08 00:56:04 +11001143 int last_pitch_index;
Jean-Marc Valin0f0da992009-08-12 21:34:01 -04001144 int loss_count;
Jean-Marc Valin269d40a2007-12-07 11:29:45 +11001145};
1146
Gregory Maxwell17169992009-06-04 15:15:34 -04001147int check_decoder(const CELTDecoder *st)
1148{
1149 if (st==NULL)
1150 {
1151 celt_warning("NULL passed a decoder structure");
1152 return CELT_INVALID_STATE;
1153 }
1154 if (st->marker == DECODERVALID)
1155 return CELT_OK;
1156 if (st->marker == DECODERFREED)
1157 celt_warning("Referencing a decoder that has already been freed");
1158 else
1159 celt_warning("This is not a valid CELT decoder structure");
1160 return CELT_INVALID_STATE;
1161}
1162
Jean-Marc Valin80ed1472009-10-15 21:45:32 -04001163CELTDecoder *celt_decoder_create(const CELTMode *mode, int channels, int *error)
Jean-Marc Valin269d40a2007-12-07 11:29:45 +11001164{
Jean-Marc Valinb886ddc2008-03-25 14:38:55 +11001165 int N, C;
Jean-Marc Valin0bb05bc2008-02-20 13:43:40 +11001166 CELTDecoder *st;
Jean-Marc Valin44ffd5a2008-02-22 00:39:25 +11001167
1168 if (check_mode(mode) != CELT_OK)
Jean-Marc Valinece94a02009-10-16 07:30:14 -04001169 {
1170 if (error)
1171 *error = CELT_INVALID_MODE;
Jean-Marc Valin44ffd5a2008-02-22 00:39:25 +11001172 return NULL;
Jean-Marc Valinece94a02009-10-16 07:30:14 -04001173 }
Jean-Marc Valinbd5d54a2009-10-20 00:25:31 -04001174#ifdef DISABLE_STEREO
1175 if (channels > 1)
1176 {
1177 celt_warning("Stereo support was disable from this build");
1178 if (error)
1179 *error = CELT_BAD_ARG;
1180 return NULL;
1181 }
1182#endif
1183
Jean-Marc Valin80ed1472009-10-15 21:45:32 -04001184 if (channels < 0 || channels > 2)
1185 {
1186 celt_warning("Only mono and stereo supported");
1187 if (error)
1188 *error = CELT_BAD_ARG;
1189 return NULL;
1190 }
Jean-Marc Valin44ffd5a2008-02-22 00:39:25 +11001191
Jean-Marc Valin269d40a2007-12-07 11:29:45 +11001192 N = mode->mdctSize;
Jean-Marc Valin80ed1472009-10-15 21:45:32 -04001193 C = CHANNELS(channels);
Jean-Marc Valin0bb05bc2008-02-20 13:43:40 +11001194 st = celt_alloc(sizeof(CELTDecoder));
Gregory Maxwell17169992009-06-04 15:15:34 -04001195
1196 if (st==NULL)
Jean-Marc Valinece94a02009-10-16 07:30:14 -04001197 {
1198 if (error)
1199 *error = CELT_ALLOC_FAIL;
Gregory Maxwell17169992009-06-04 15:15:34 -04001200 return NULL;
Jean-Marc Valinece94a02009-10-16 07:30:14 -04001201 }
1202
Gregory Maxwell17169992009-06-04 15:15:34 -04001203 st->marker = DECODERPARTIAL;
Jean-Marc Valin269d40a2007-12-07 11:29:45 +11001204 st->mode = mode;
Jean-Marc Valinb886ddc2008-03-25 14:38:55 +11001205 st->frame_size = N;
Jean-Marc Valin269d40a2007-12-07 11:29:45 +11001206 st->block_size = N;
Jean-Marc Valina5431bf2008-01-03 20:53:01 +11001207 st->overlap = mode->overlap;
Jean-Marc Valin80ed1472009-10-15 21:45:32 -04001208 st->channels = channels;
Jean-Marc Valina5431bf2008-01-03 20:53:01 +11001209
Jean-Marc Valin234969c2009-10-17 22:12:42 -04001210 st->decode_mem = celt_alloc((DECODE_BUFFER_SIZE+st->overlap)*C*sizeof(celt_sig));
Jean-Marc Valineafbdd52009-04-27 19:35:09 -04001211 st->out_mem = st->decode_mem+DECODE_BUFFER_SIZE-MAX_PERIOD;
Jean-Marc Valin269d40a2007-12-07 11:29:45 +11001212
Jean-Marc Valin234969c2009-10-17 22:12:42 -04001213 st->oldBandE = (celt_word16*)celt_alloc(C*mode->nbEBands*sizeof(celt_word16));
Gregory Maxwell17169992009-06-04 15:15:34 -04001214
Jean-Marc Valin234969c2009-10-17 22:12:42 -04001215 st->preemph_memD = (celt_sig*)celt_alloc(C*sizeof(celt_sig));
Jean-Marc Valinffa13472007-12-10 16:54:17 +11001216
Jean-Marc Valind69c1cb2009-12-28 00:34:29 -05001217#ifdef NEW_PLC
Jean-Marc Valin74128be2010-01-01 09:33:17 -05001218 st->lpc = (celt_word16*)celt_alloc(C*LPC_ORDER*sizeof(celt_word16));
Jean-Marc Valin5a0fae52009-12-14 21:19:37 -05001219#endif
1220
Jean-Marc Valin0f0da992009-08-12 21:34:01 -04001221 st->loss_count = 0;
Gregory Maxwell17169992009-06-04 15:15:34 -04001222
1223 if ((st->decode_mem!=NULL) && (st->out_mem!=NULL) && (st->oldBandE!=NULL) &&
Jean-Marc Valind69c1cb2009-12-28 00:34:29 -05001224#ifdef NEW_PLC
Jean-Marc Valin5a0fae52009-12-14 21:19:37 -05001225 (st->lpc!=NULL) &&
1226#endif
Gregory Maxwell17169992009-06-04 15:15:34 -04001227 (st->preemph_memD!=NULL))
1228 {
Jean-Marc Valinece94a02009-10-16 07:30:14 -04001229 if (error)
1230 *error = CELT_OK;
Gregory Maxwell17169992009-06-04 15:15:34 -04001231 st->marker = DECODERVALID;
1232 return st;
1233 }
1234 /* If the setup fails for some reason deallocate it. */
1235 celt_decoder_destroy(st);
Jean-Marc Valinece94a02009-10-16 07:30:14 -04001236 if (error)
1237 *error = CELT_ALLOC_FAIL;
Gregory Maxwell17169992009-06-04 15:15:34 -04001238 return NULL;
Jean-Marc Valin269d40a2007-12-07 11:29:45 +11001239}
1240
Peter Kirk19f9dc92008-06-06 14:38:38 +02001241void celt_decoder_destroy(CELTDecoder *st)
Jean-Marc Valin269d40a2007-12-07 11:29:45 +11001242{
1243 if (st == NULL)
1244 {
Gregory Maxwell17169992009-06-04 15:15:34 -04001245 celt_warning("NULL passed to celt_decoder_destroy");
Jean-Marc Valin269d40a2007-12-07 11:29:45 +11001246 return;
1247 }
Gregory Maxwell17169992009-06-04 15:15:34 -04001248
1249 if (st->marker == DECODERFREED)
1250 {
1251 celt_warning("Freeing a decoder which has already been freed");
Jean-Marc Valin44ffd5a2008-02-22 00:39:25 +11001252 return;
Gregory Maxwell17169992009-06-04 15:15:34 -04001253 }
1254
1255 if (st->marker != DECODERVALID && st->marker != DECODERPARTIAL)
1256 {
1257 celt_warning("This is not a valid CELT decoder structure");
1258 return;
1259 }
1260
1261 /*Check_mode is non-fatal here because we can still free
1262 the encoder memory even if the mode is bad, although calling
1263 the free functions in this order is a violation of the API.*/
1264 check_mode(st->mode);
1265
Jean-Marc Valineafbdd52009-04-27 19:35:09 -04001266 celt_free(st->decode_mem);
Jean-Marc Valin269d40a2007-12-07 11:29:45 +11001267 celt_free(st->oldBandE);
Jean-Marc Valin7351e282008-02-08 15:09:45 +11001268 celt_free(st->preemph_memD);
Jean-Marc Valin5a0fae52009-12-14 21:19:37 -05001269
Jean-Marc Valind69c1cb2009-12-28 00:34:29 -05001270#ifdef NEW_PLC
Jean-Marc Valin5a0fae52009-12-14 21:19:37 -05001271 celt_free(st->lpc);
1272#endif
Gregory Maxwell17169992009-06-04 15:15:34 -04001273
1274 st->marker = DECODERFREED;
1275
Jean-Marc Valin269d40a2007-12-07 11:29:45 +11001276 celt_free(st);
1277}
1278
Jean-Marc Valin234969c2009-10-17 22:12:42 -04001279static void celt_decode_lost(CELTDecoder * restrict st, celt_word16 * restrict pcm)
Jean-Marc Valinfb83fb42007-12-08 00:56:04 +11001280{
Jean-Marc Valin05e56c42008-04-10 09:13:05 +10001281 int c, N;
Jean-Marc Valin0bb05bc2008-02-20 13:43:40 +11001282 int pitch_index;
Jean-Marc Valine14fe902009-12-11 00:07:31 -05001283 int overlap = st->mode->overlap;
Jean-Marc Valin234969c2009-10-17 22:12:42 -04001284 celt_word16 fade = Q15ONE;
Jean-Marc Valin24c9cda2008-05-02 10:34:07 +10001285 int i, len;
Jean-Marc Valin234969c2009-10-17 22:12:42 -04001286 VARDECL(celt_sig, freq);
Jean-Marc Valin80ed1472009-10-15 21:45:32 -04001287 const int C = CHANNELS(st->channels);
Jean-Marc Valin24c9cda2008-05-02 10:34:07 +10001288 int offset;
Jean-Marc Valin8600f692008-02-29 15:14:12 +11001289 SAVE_STACK;
Jean-Marc Valinfb83fb42007-12-08 00:56:04 +11001290 N = st->block_size;
Jean-Marc Valinfb83fb42007-12-08 00:56:04 +11001291
Jean-Marc Valin24c9cda2008-05-02 10:34:07 +10001292 len = N+st->mode->overlap;
Jean-Marc Valinfb83fb42007-12-08 00:56:04 +11001293
Jean-Marc Valin0f0da992009-08-12 21:34:01 -04001294 if (st->loss_count == 0)
1295 {
Jean-Marc Valin7a7c42a2009-11-25 20:38:52 -05001296 celt_word16 pitch_buf[MAX_PERIOD>>1];
Jean-Marc Valin294863b2009-11-08 22:29:54 +09001297 celt_word32 tmp=0;
Jean-Marc Valine465c142009-11-26 00:39:36 -05001298 celt_word32 mem0[2]={0,0};
1299 celt_word16 mem1[2]={0,0};
Jean-Marc Valine14fe902009-12-11 00:07:31 -05001300 pitch_downsample(st->out_mem, pitch_buf, MAX_PERIOD, MAX_PERIOD,
1301 C, mem0, mem1);
1302 pitch_search(st->mode, pitch_buf+((MAX_PERIOD-len)>>1), pitch_buf, len,
1303 MAX_PERIOD-len-100, &pitch_index, &tmp);
Jean-Marc Valin0f0da992009-08-12 21:34:01 -04001304 pitch_index = MAX_PERIOD-len-pitch_index;
1305 st->last_pitch_index = pitch_index;
1306 } else {
1307 pitch_index = st->last_pitch_index;
1308 if (st->loss_count < 5)
1309 fade = QCONST16(.8f,15);
1310 else
1311 fade = 0;
1312 }
Jean-Marc Valinfb83fb42007-12-08 00:56:04 +11001313
Jean-Marc Valind69c1cb2009-12-28 00:34:29 -05001314#ifndef NEW_PLC
Jean-Marc Valind5f99302009-12-16 22:42:32 -05001315 offset = MAX_PERIOD-pitch_index;
Jean-Marc Valine14fe902009-12-11 00:07:31 -05001316 ALLOC(freq,C*N, celt_sig); /**< Interleaved signal MDCTs */
Jean-Marc Valin24c9cda2008-05-02 10:34:07 +10001317 while (offset+len >= MAX_PERIOD)
1318 offset -= pitch_index;
Jean-Marc Valinbf2398b2009-10-15 07:28:19 -04001319 compute_mdcts(st->mode, 0, st->out_mem+offset*C, freq, C);
Jean-Marc Valin08a82ff2009-06-14 14:05:19 -04001320 for (i=0;i<C*N;i++)
Jean-Marc Valin0f0da992009-08-12 21:34:01 -04001321 freq[i] = ADD32(VERY_SMALL, MULT16_32_Q15(fade,freq[i]));
1322
Jean-Marc Valin24c9cda2008-05-02 10:34:07 +10001323 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 +11001324 /* Compute inverse MDCTs */
Jean-Marc Valinbf2398b2009-10-15 07:28:19 -04001325 compute_inv_mdcts(st->mode, 0, freq, -1, 0, st->out_mem, C);
Jean-Marc Valine14fe902009-12-11 00:07:31 -05001326#else
1327 for (c=0;c<C;c++)
1328 {
Jean-Marc Valind69c1cb2009-12-28 00:34:29 -05001329 celt_word32 e[MAX_PERIOD];
Jean-Marc Valin303b3b62009-12-30 22:40:24 -05001330 celt_word16 exc[MAX_PERIOD];
Jean-Marc Valine14fe902009-12-11 00:07:31 -05001331 float ac[LPC_ORDER+1];
Jean-Marc Valine14fe902009-12-11 00:07:31 -05001332 float decay = 1;
Jean-Marc Valinaec0ee42009-12-21 00:06:12 -05001333 float S1=0;
Jean-Marc Valin74128be2010-01-01 09:33:17 -05001334 celt_word16 mem[LPC_ORDER]={0};
Jean-Marc Valine14fe902009-12-11 00:07:31 -05001335
Jean-Marc Valind5f99302009-12-16 22:42:32 -05001336 offset = MAX_PERIOD-pitch_index;
Jean-Marc Valine14fe902009-12-11 00:07:31 -05001337 for (i=0;i<MAX_PERIOD;i++)
Jean-Marc Valin74128be2010-01-01 09:33:17 -05001338 exc[i] = ROUND16(st->out_mem[i*C+c], SIG_SHIFT);
Jean-Marc Valin5a0fae52009-12-14 21:19:37 -05001339
1340 if (st->loss_count == 0)
1341 {
1342 _celt_autocorr(exc, ac, st->mode->window, st->mode->overlap,
1343 LPC_ORDER, MAX_PERIOD);
1344
1345 /* Noise floor -50 dB */
1346 ac[0] *= 1.00001;
1347 /* Lag windowing */
1348 for (i=1;i<=LPC_ORDER;i++)
1349 {
1350 /*ac[i] *= exp(-.5*(2*M_PI*.002*i)*(2*M_PI*.002*i));*/
1351 ac[i] -= ac[i]*(.008*i)*(.008*i);
1352 }
1353
Jean-Marc Valin74128be2010-01-01 09:33:17 -05001354 _celt_lpc(st->lpc+c*LPC_ORDER, ac, LPC_ORDER);
Jean-Marc Valin5a0fae52009-12-14 21:19:37 -05001355 }
Jean-Marc Valin74128be2010-01-01 09:33:17 -05001356 fir(exc, st->lpc+c*LPC_ORDER, exc, MAX_PERIOD, LPC_ORDER, mem);
1357 /*for (i=0;i<MAX_PERIOD;i++)printf("%d ", exc[i]); printf("\n");*/
Jean-Marc Valine14fe902009-12-11 00:07:31 -05001358 /* Check if the waveform is decaying (and if so how fast) */
1359 {
1360 float E1=0, E2=0;
1361 int period;
1362 if (pitch_index <= MAX_PERIOD/2)
1363 period = pitch_index;
1364 else
1365 period = MAX_PERIOD/2;
1366 for (i=0;i<period;i++)
1367 {
1368 E1 += exc[MAX_PERIOD-period+i]*exc[MAX_PERIOD-period+i];
1369 E2 += exc[MAX_PERIOD-2*period+i]*exc[MAX_PERIOD-2*period+i];
1370 }
1371 decay = sqrt((E1+1)/(E2+1));
1372 if (decay > 1)
1373 decay = 1;
1374 }
1375
1376 /* Copy excitation, taking decay into account */
1377 for (i=0;i<len+st->mode->overlap;i++)
1378 {
1379 if (offset+i >= MAX_PERIOD)
1380 {
1381 offset -= pitch_index;
1382 decay *= decay;
1383 }
Jean-Marc Valin303b3b62009-12-30 22:40:24 -05001384 e[i] = decay*SHL32(EXTEND32(exc[offset+i]), SIG_SHIFT);
Jean-Marc Valind69c1cb2009-12-28 00:34:29 -05001385 S1 += st->out_mem[offset+i]*1.*st->out_mem[offset+i];
Jean-Marc Valin5a0fae52009-12-14 21:19:37 -05001386 }
1387
Jean-Marc Valin74128be2010-01-01 09:33:17 -05001388 iir(e, st->lpc+c*LPC_ORDER, e, len+st->mode->overlap, LPC_ORDER, mem);
Jean-Marc Valin5a0fae52009-12-14 21:19:37 -05001389
1390 {
Jean-Marc Valin07fed1b2009-12-28 07:59:42 -05001391 float S2=0;
Jean-Marc Valin5a0fae52009-12-14 21:19:37 -05001392 for (i=0;i<len+overlap;i++)
Jean-Marc Valind69c1cb2009-12-28 00:34:29 -05001393 S2 += e[i]*1.*e[i];
Jean-Marc Valin07fed1b2009-12-28 07:59:42 -05001394 /* This checks for an "explosion" in the synthesis (including NaNs) */
1395 if (!(S1 > 0.2f*S2))
1396 {
1397 for (i=0;i<len+overlap;i++)
1398 e[i] = 0;
1399 } else if (S1 < S2)
1400 {
1401 float ratio = sqrt((S1+1)/(S2+1));
Jean-Marc Valin5a0fae52009-12-14 21:19:37 -05001402 for (i=0;i<len+overlap;i++)
1403 e[i] *= ratio;
Jean-Marc Valin07fed1b2009-12-28 07:59:42 -05001404 }
Jean-Marc Valine14fe902009-12-11 00:07:31 -05001405 }
1406
1407 for (i=0;i<MAX_PERIOD+st->mode->overlap-N;i++)
1408 st->out_mem[C*i+c] = st->out_mem[C*(N+i)+c];
1409
Jean-Marc Valine14fe902009-12-11 00:07:31 -05001410 /* Apply TDAC to the concealed audio so that it blends with the
1411 previous and next frames */
1412 for (i=0;i<overlap/2;i++)
1413 {
Jean-Marc Valind69c1cb2009-12-28 00:34:29 -05001414 celt_word32 tmp1, tmp2;
1415 tmp1 = MULT16_32_Q15(st->mode->window[i ], e[i ]) -
1416 MULT16_32_Q15(st->mode->window[overlap-i-1], e[overlap-i-1]);
1417 tmp2 = MULT16_32_Q15(st->mode->window[i], e[N+overlap-1-i]) +
1418 MULT16_32_Q15(st->mode->window[overlap-i-1], e[N+i ]);
1419 tmp1 = MULT16_32_Q15(fade, tmp1);
1420 tmp2 = MULT16_32_Q15(fade, tmp2);
1421 st->out_mem[C*(MAX_PERIOD+i)+c] = MULT16_32_Q15(st->mode->window[overlap-i-1], tmp2);
1422 st->out_mem[C*(MAX_PERIOD+overlap-i-1)+c] = MULT16_32_Q15(st->mode->window[i], tmp2);
1423 st->out_mem[C*(MAX_PERIOD-N+i)+c] += MULT16_32_Q15(st->mode->window[i], tmp1);
1424 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 -05001425 }
1426 for (i=0;i<N-overlap;i++)
Jean-Marc Valind69c1cb2009-12-28 00:34:29 -05001427 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 -05001428 }
1429#endif
Jean-Marc Valin1677aa92007-12-08 01:13:34 +11001430
Jean-Marc Valin5a0fae52009-12-14 21:19:37 -05001431 deemphasis(st->out_mem, pcm, N, C, preemph, st->preemph_memD);
Jean-Marc Valin0f0da992009-08-12 21:34:01 -04001432
1433 st->loss_count++;
1434
Jean-Marc Valin8600f692008-02-29 15:14:12 +11001435 RESTORE_STACK;
Jean-Marc Valinfb83fb42007-12-08 00:56:04 +11001436}
1437
Gregory Maxwell5f2a74b2008-08-11 23:50:07 -04001438#ifdef FIXED_POINT
Jean-Marc Valin30f7f812009-10-17 14:35:13 -04001439int celt_decode(CELTDecoder * restrict st, const unsigned char *data, int len, celt_int16 * restrict pcm)
Jean-Marc Valin269d40a2007-12-07 11:29:45 +11001440{
Gregory Maxwell5f2a74b2008-08-11 23:50:07 -04001441#else
Jean-Marc Valin234969c2009-10-17 22:12:42 -04001442int celt_decode_float(CELTDecoder * restrict st, const unsigned char *data, int len, celt_sig * restrict pcm)
Gregory Maxwell5f2a74b2008-08-11 23:50:07 -04001443{
1444#endif
Jean-Marc Valin88619552009-10-04 21:35:36 -04001445 int i, N, N4;
Jean-Marc Valinc9943942008-08-30 00:55:07 -04001446 int has_pitch, has_fold;
Jean-Marc Valin0bb05bc2008-02-20 13:43:40 +11001447 int pitch_index;
Jean-Marc Valinc890b582008-08-01 22:26:49 -04001448 int bits;
Jean-Marc Valin0bb05bc2008-02-20 13:43:40 +11001449 ec_dec dec;
1450 ec_byte_buffer buf;
Jean-Marc Valin234969c2009-10-17 22:12:42 -04001451 VARDECL(celt_sig, freq);
1452 VARDECL(celt_sig, pitch_freq);
1453 VARDECL(celt_norm, X);
1454 VARDECL(celt_ener, bandE);
Jean-Marc Valin6775de32008-08-02 08:14:42 -04001455 VARDECL(int, fine_quant);
1456 VARDECL(int, pulses);
1457 VARDECL(int, offsets);
Jean-Marc Valin52cb5fb2009-06-10 08:08:55 -04001458 VARDECL(int, fine_priority);
Jean-Marc Valinc890b582008-08-01 22:26:49 -04001459
Jean-Marc Valin9d1decd2008-06-17 13:28:13 +10001460 int shortBlocks;
Jean-Marc Valin3b918ba2010-05-05 00:02:26 -04001461 int isTransient;
Jean-Marc Valin05ed03e2009-04-29 07:44:13 -04001462 int intra_ener;
Jean-Marc Valin12b22482008-06-16 14:13:05 +10001463 int transient_time;
Jean-Marc Valin528f4b82008-06-29 03:46:39 +10001464 int transient_shift;
Jean-Marc Valinaa936252009-05-29 22:14:20 -04001465 int mdct_weight_shift=0;
Jean-Marc Valin80ed1472009-10-15 21:45:32 -04001466 const int C = CHANNELS(st->channels);
Jean-Marc Valinaa936252009-05-29 22:14:20 -04001467 int mdct_weight_pos=0;
Jean-Marc Valinab220aa2009-09-15 22:38:40 -04001468 int gain_id=0;
Jean-Marc Valin3a0bc3d2010-02-21 15:10:22 -05001469 int start=0;
Jean-Marc Valin65ee67a2010-04-26 07:08:44 -04001470 const int M=st->mode->nbShortMdcts;
Jean-Marc Valin8600f692008-02-29 15:14:12 +11001471 SAVE_STACK;
Jean-Marc Valin44ffd5a2008-02-22 00:39:25 +11001472
Gregory Maxwell17169992009-06-04 15:15:34 -04001473 if (check_decoder(st) != CELT_OK)
1474 return CELT_INVALID_STATE;
1475
Jean-Marc Valin44ffd5a2008-02-22 00:39:25 +11001476 if (check_mode(st->mode) != CELT_OK)
1477 return CELT_INVALID_MODE;
1478
Gregory Maxwell0719f6f2009-07-09 17:07:24 -04001479 if (pcm==NULL)
1480 return CELT_BAD_ARG;
1481
Jean-Marc Valin269d40a2007-12-07 11:29:45 +11001482 N = st->block_size;
Jean-Marc Valina536f772008-03-22 09:01:50 +11001483 N4 = (N-st->overlap)>>1;
Jean-Marc Valin01417232008-03-03 13:59:55 +11001484
Jean-Marc Valin234969c2009-10-17 22:12:42 -04001485 ALLOC(freq, C*N, celt_sig); /**< Interleaved signal MDCTs */
1486 ALLOC(X, C*N, celt_norm); /**< Interleaved normalised MDCTs */
1487 ALLOC(bandE, st->mode->nbEBands*C, celt_ener);
Jean-Marc Valin70c8ffd2007-12-07 14:20:01 +11001488
Jean-Marc Valinfb83fb42007-12-08 00:56:04 +11001489 if (data == NULL)
1490 {
1491 celt_decode_lost(st, pcm);
Jean-Marc Valin8600f692008-02-29 15:14:12 +11001492 RESTORE_STACK;
Jean-Marc Valinfb83fb42007-12-08 00:56:04 +11001493 return 0;
1494 }
Gregory Maxwell520eeae2009-02-09 01:33:21 -05001495 if (len<0) {
1496 RESTORE_STACK;
1497 return CELT_BAD_ARG;
1498 }
Jean-Marc Valinfb83fb42007-12-08 00:56:04 +11001499
Jean-Marc Valin05ed03e2009-04-29 07:44:13 -04001500 ec_byte_readinit(&buf,(unsigned char*)data,len);
Jean-Marc Valin70c8ffd2007-12-07 14:20:01 +11001501 ec_dec_init(&dec,&buf);
1502
Jean-Marc Valin3b918ba2010-05-05 00:02:26 -04001503 decode_flags(&dec, &intra_ener, &has_pitch, &isTransient, &has_fold);
1504 if (isTransient)
1505 shortBlocks = M;
1506 else
1507 shortBlocks = 0;
1508
1509 if (isTransient)
Gregory Maxwell0527f372008-09-23 19:28:35 -04001510 {
Jean-Marc Valine6108642009-08-01 23:05:47 +02001511 transient_shift = ec_dec_uint(&dec, 4);
Jean-Marc Valinaa936252009-05-29 22:14:20 -04001512 if (transient_shift == 3)
1513 {
Gregory Maxwell0527f372008-09-23 19:28:35 -04001514 transient_time = ec_dec_uint(&dec, N+st->mode->overlap);
Jean-Marc Valinaa936252009-05-29 22:14:20 -04001515 } else {
1516 mdct_weight_shift = transient_shift;
Jean-Marc Valin3b918ba2010-05-05 00:02:26 -04001517 if (mdct_weight_shift && M>2)
1518 mdct_weight_pos = ec_dec_uint(&dec, M-1);
Jean-Marc Valinaa936252009-05-29 22:14:20 -04001519 transient_shift = 0;
Gregory Maxwell0527f372008-09-23 19:28:35 -04001520 transient_time = 0;
Jean-Marc Valinaa936252009-05-29 22:14:20 -04001521 }
Gregory Maxwell0527f372008-09-23 19:28:35 -04001522 } else {
Jean-Marc Valin12b22482008-06-16 14:13:05 +10001523 transient_time = -1;
Jean-Marc Valin528f4b82008-06-29 03:46:39 +10001524 transient_shift = 0;
Jean-Marc Valin12b22482008-06-16 14:13:05 +10001525 }
Jean-Marc Valincb7a2a32008-02-11 16:44:48 +11001526
Jean-Marc Valin7e8a4872008-02-11 16:55:34 +11001527 if (has_pitch)
1528 {
Jean-Marc Valinb886ddc2008-03-25 14:38:55 +11001529 pitch_index = ec_dec_uint(&dec, MAX_PERIOD-(2*N-2*N4));
Jean-Marc Valin4c77ea92009-09-14 22:50:41 -04001530 gain_id = ec_dec_uint(&dec, 16);
Jean-Marc Valin7e8a4872008-02-11 16:55:34 +11001531 } else {
Jean-Marc Valin7e8a4872008-02-11 16:55:34 +11001532 pitch_index = 0;
1533 }
Jean-Marc Valin827f9312008-05-06 23:21:55 +10001534
Jean-Marc Valin6775de32008-08-02 08:14:42 -04001535 ALLOC(fine_quant, st->mode->nbEBands, int);
Jean-Marc Valin827f9312008-05-06 23:21:55 +10001536 /* Get band energies */
Jean-Marc Valin3a0bc3d2010-02-21 15:10:22 -05001537 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 -04001538
1539 ALLOC(pulses, st->mode->nbEBands, int);
1540 ALLOC(offsets, st->mode->nbEBands, int);
Jean-Marc Valin52cb5fb2009-06-10 08:08:55 -04001541 ALLOC(fine_priority, st->mode->nbEBands, int);
Jean-Marc Valin6775de32008-08-02 08:14:42 -04001542
1543 for (i=0;i<st->mode->nbEBands;i++)
1544 offsets[i] = 0;
1545
1546 bits = len*8 - ec_dec_tell(&dec, 0) - 1;
Jean-Marc Valin65ee67a2010-04-26 07:08:44 -04001547 compute_allocation(st->mode, start, offsets, bits, pulses, fine_quant, fine_priority, C, M);
Jean-Marc Valin6775de32008-08-02 08:14:42 -04001548 /*bits = ec_dec_tell(&dec, 0);
1549 compute_fine_allocation(st->mode, fine_quant, (20*C+len*8/5-(ec_dec_tell(&dec, 0)-bits))/C);*/
1550
Jean-Marc Valin3a0bc3d2010-02-21 15:10:22 -05001551 unquant_fine_energy(st->mode, start, bandE, st->oldBandE, fine_quant, &dec, C);
Jean-Marc Valin827f9312008-05-06 23:21:55 +10001552
Jean-Marc Valin234969c2009-10-17 22:12:42 -04001553 ALLOC(pitch_freq, C*N, celt_sig); /**< Interleaved signal MDCTs */
Jean-Marc Valinc9943942008-08-30 00:55:07 -04001554 if (has_pitch)
Jean-Marc Valin269d40a2007-12-07 11:29:45 +11001555 {
Jean-Marc Valinc9943942008-08-30 00:55:07 -04001556 /* Pitch MDCT */
Jean-Marc Valinbf2398b2009-10-15 07:28:19 -04001557 compute_mdcts(st->mode, 0, st->out_mem+pitch_index*C, pitch_freq, C);
Jean-Marc Valin269d40a2007-12-07 11:29:45 +11001558 }
1559
Jean-Marc Valin70c8ffd2007-12-07 14:20:01 +11001560 /* Decode fixed codebook and merge with pitch */
Jean-Marc Valinca53b7c2009-03-26 20:23:14 -04001561 if (C==1)
Jean-Marc Valin3b918ba2010-05-05 00:02:26 -04001562 quant_bands(st->mode, start, X, bandE, pulses, isTransient, has_fold, 1, len*8, 0, &dec, M);
Jean-Marc Valin73532032009-06-02 20:07:25 -04001563#ifndef DISABLE_STEREO
Jean-Marc Valinca53b7c2009-03-26 20:23:14 -04001564 else
Jean-Marc Valin3b918ba2010-05-05 00:02:26 -04001565 unquant_bands_stereo(st->mode, start, X, bandE, pulses, isTransient, has_fold, len*8, &dec, M);
Jean-Marc Valin73532032009-06-02 20:07:25 -04001566#endif
Jean-Marc Valin3a0bc3d2010-02-21 15:10:22 -05001567 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 -04001568
Jean-Marc Valin88619552009-10-04 21:35:36 -04001569 if (mdct_weight_shift)
1570 {
Jean-Marc Valin3b918ba2010-05-05 00:02:26 -04001571 mdct_shape(st->mode, X, 0, mdct_weight_pos+1, N, mdct_weight_shift, C, 1, M);
Jean-Marc Valin88619552009-10-04 21:35:36 -04001572 }
1573
Jean-Marc Valina4833ff2008-01-10 15:34:00 +11001574 /* Synthesis */
Jean-Marc Valin65ee67a2010-04-26 07:08:44 -04001575 denormalise_bands(st->mode, X, freq, bandE, C, M);
Jean-Marc Valina4833ff2008-01-10 15:34:00 +11001576
1577
Jean-Marc Valineafbdd52009-04-27 19:35:09 -04001578 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 -04001579
Jean-Marc Valin4c77ea92009-09-14 22:50:41 -04001580 if (has_pitch)
Jean-Marc Valinbf2398b2009-10-15 07:28:19 -04001581 apply_pitch(st->mode, freq, pitch_freq, gain_id, 0, C);
Jean-Marc Valin4c77ea92009-09-14 22:50:41 -04001582
Jean-Marc Valin65ee67a2010-04-26 07:08:44 -04001583 for (i=0;i<M*st->mode->eBands[start];i++)
Jean-Marc Valin3a0bc3d2010-02-21 15:10:22 -05001584 freq[i] = 0;
1585
Jean-Marc Valin269d40a2007-12-07 11:29:45 +11001586 /* Compute inverse MDCTs */
Jean-Marc Valinbf2398b2009-10-15 07:28:19 -04001587 compute_inv_mdcts(st->mode, shortBlocks, freq, transient_time, transient_shift, st->out_mem, C);
Jean-Marc Valinffa13472007-12-10 16:54:17 +11001588
Jean-Marc Valine12017e2009-10-03 13:57:31 -04001589 deemphasis(st->out_mem, pcm, N, C, preemph, st->preemph_memD);
Jean-Marc Valine14fe902009-12-11 00:07:31 -05001590 st->loss_count = 0;
Jean-Marc Valin8600f692008-02-29 15:14:12 +11001591 RESTORE_STACK;
Jean-Marc Valinfb83fb42007-12-08 00:56:04 +11001592 return 0;
Jean-Marc Valin269d40a2007-12-07 11:29:45 +11001593}
1594
Gregory Maxwell5f2a74b2008-08-11 23:50:07 -04001595#ifdef FIXED_POINT
1596#ifndef DISABLE_FLOAT_API
Jean-Marc Valin6db6cbd2009-04-11 22:01:20 -04001597int celt_decode_float(CELTDecoder * restrict st, const unsigned char *data, int len, float * restrict pcm)
Gregory Maxwell5f2a74b2008-08-11 23:50:07 -04001598{
Gregory Maxwell17169992009-06-04 15:15:34 -04001599 int j, ret, C, N;
Jean-Marc Valin30f7f812009-10-17 14:35:13 -04001600 VARDECL(celt_int16, out);
Jean-Marc Valincb8780c2009-07-20 23:40:35 -04001601 SAVE_STACK;
Gregory Maxwell17169992009-06-04 15:15:34 -04001602
1603 if (check_decoder(st) != CELT_OK)
1604 return CELT_INVALID_STATE;
1605
1606 if (check_mode(st->mode) != CELT_OK)
1607 return CELT_INVALID_MODE;
1608
Gregory Maxwell0719f6f2009-07-09 17:07:24 -04001609 if (pcm==NULL)
1610 return CELT_BAD_ARG;
1611
Jean-Marc Valin80ed1472009-10-15 21:45:32 -04001612 C = CHANNELS(st->channels);
Gregory Maxwell17169992009-06-04 15:15:34 -04001613 N = st->block_size;
Gregory Maxwell0719f6f2009-07-09 17:07:24 -04001614
Jean-Marc Valin30f7f812009-10-17 14:35:13 -04001615 ALLOC(out, C*N, celt_int16);
Gregory Maxwell5f2a74b2008-08-11 23:50:07 -04001616 ret=celt_decode(st, data, len, out);
Gregory Maxwell5f2a74b2008-08-11 23:50:07 -04001617 for (j=0;j<C*N;j++)
Gregory Maxwell0719f6f2009-07-09 17:07:24 -04001618 pcm[j]=out[j]*(1/32768.);
1619
Wessel Lubberhuizen33ba6cc2008-10-03 07:09:29 -04001620 RESTORE_STACK;
Gregory Maxwell5f2a74b2008-08-11 23:50:07 -04001621 return ret;
1622}
1623#endif /*DISABLE_FLOAT_API*/
1624#else
Jean-Marc Valin30f7f812009-10-17 14:35:13 -04001625int celt_decode(CELTDecoder * restrict st, const unsigned char *data, int len, celt_int16 * restrict pcm)
Gregory Maxwell5f2a74b2008-08-11 23:50:07 -04001626{
Gregory Maxwell17169992009-06-04 15:15:34 -04001627 int j, ret, C, N;
Jean-Marc Valin234969c2009-10-17 22:12:42 -04001628 VARDECL(celt_sig, out);
Jean-Marc Valincb8780c2009-07-20 23:40:35 -04001629 SAVE_STACK;
Gregory Maxwell17169992009-06-04 15:15:34 -04001630
1631 if (check_decoder(st) != CELT_OK)
1632 return CELT_INVALID_STATE;
1633
1634 if (check_mode(st->mode) != CELT_OK)
1635 return CELT_INVALID_MODE;
1636
Gregory Maxwell0719f6f2009-07-09 17:07:24 -04001637 if (pcm==NULL)
1638 return CELT_BAD_ARG;
1639
Jean-Marc Valin80ed1472009-10-15 21:45:32 -04001640 C = CHANNELS(st->channels);
Gregory Maxwell17169992009-06-04 15:15:34 -04001641 N = st->block_size;
Jean-Marc Valin234969c2009-10-17 22:12:42 -04001642 ALLOC(out, C*N, celt_sig);
Gregory Maxwell5f2a74b2008-08-11 23:50:07 -04001643
1644 ret=celt_decode_float(st, data, len, out);
1645
1646 for (j=0;j<C*N;j++)
Gregory Maxwell0719f6f2009-07-09 17:07:24 -04001647 pcm[j] = FLOAT2INT16 (out[j]);
1648
Wessel Lubberhuizen33ba6cc2008-10-03 07:09:29 -04001649 RESTORE_STACK;
Gregory Maxwell5f2a74b2008-08-11 23:50:07 -04001650 return ret;
1651}
1652#endif
John Ridges454d1d02009-05-21 22:38:39 -04001653
1654int celt_decoder_ctl(CELTDecoder * restrict st, int request, ...)
1655{
1656 va_list ap;
Gregory Maxwell17169992009-06-04 15:15:34 -04001657
1658 if (check_decoder(st) != CELT_OK)
1659 return CELT_INVALID_STATE;
1660
John Ridges454d1d02009-05-21 22:38:39 -04001661 va_start(ap, request);
Gregory Maxwell17169992009-06-04 15:15:34 -04001662 if ((request!=CELT_GET_MODE_REQUEST) && (check_mode(st->mode) != CELT_OK))
1663 goto bad_mode;
John Ridges454d1d02009-05-21 22:38:39 -04001664 switch (request)
1665 {
Gregory Maxwellf3b44ef2009-06-03 13:37:45 -04001666 case CELT_GET_MODE_REQUEST:
1667 {
1668 const CELTMode ** value = va_arg(ap, const CELTMode**);
1669 if (value==0)
1670 goto bad_arg;
1671 *value=st->mode;
1672 }
1673 break;
John Ridges454d1d02009-05-21 22:38:39 -04001674 case CELT_RESET_STATE:
1675 {
1676 const CELTMode *mode = st->mode;
Jean-Marc Valin80ed1472009-10-15 21:45:32 -04001677 int C = st->channels;
John Ridges454d1d02009-05-21 22:38:39 -04001678
1679 CELT_MEMSET(st->decode_mem, 0, (DECODE_BUFFER_SIZE+st->overlap)*C);
1680 CELT_MEMSET(st->oldBandE, 0, C*mode->nbEBands);
1681
1682 CELT_MEMSET(st->preemph_memD, 0, C);
1683
Jean-Marc Valin0f0da992009-08-12 21:34:01 -04001684 st->loss_count = 0;
John Ridges5378bf82010-02-12 07:08:01 -05001685
1686#ifdef NEW_PLC
1687 CELT_MEMSET(st->lpc, 0, C*LPC_ORDER);
1688#endif
John Ridges454d1d02009-05-21 22:38:39 -04001689 }
1690 break;
1691 default:
1692 goto bad_request;
1693 }
1694 va_end(ap);
1695 return CELT_OK;
Gregory Maxwell17169992009-06-04 15:15:34 -04001696bad_mode:
1697 va_end(ap);
1698 return CELT_INVALID_MODE;
John Ridges454d1d02009-05-21 22:38:39 -04001699bad_arg:
1700 va_end(ap);
1701 return CELT_BAD_ARG;
John Ridges454d1d02009-05-21 22:38:39 -04001702bad_request:
1703 va_end(ap);
1704 return CELT_UNIMPLEMENTED;
1705}
Jean-Marc Valinece94a02009-10-16 07:30:14 -04001706
1707const char *celt_strerror(int error)
1708{
1709 static const char *error_strings[8] = {
1710 "success",
1711 "invalid argument",
1712 "invalid mode",
1713 "internal error",
1714 "corrupted stream",
1715 "request not implemented",
1716 "invalid state",
1717 "memory allocation failed"
1718 };
1719 if (error > 0 || error < -7)
1720 return "unknown error";
1721 else
1722 return error_strings[-error];
1723}
1724