blob: 91b20b73d9f22a6e37c45a8bafb9e45184412e39 [file] [log] [blame]
Jean-Marc Valin8b2ff0d2009-10-17 21:40:10 -04001/* Copyright (c) 2007-2008 CSIRO
2 Copyright (c) 2007-2009 Xiph.Org Foundation
3 Copyright (c) 2008 Gregory Maxwell
4 Written by Jean-Marc Valin and Gregory Maxwell */
Jean-Marc Valin8ebd3452007-11-29 20:17:32 +11005/*
6 Redistribution and use in source and binary forms, with or without
7 modification, are permitted provided that the following conditions
8 are met:
9
10 - Redistributions of source code must retain the above copyright
11 notice, this list of conditions and the following disclaimer.
12
13 - Redistributions in binary form must reproduce the above copyright
14 notice, this list of conditions and the following disclaimer in the
15 documentation and/or other materials provided with the distribution.
16
17 - Neither the name of the Xiph.org Foundation nor the names of its
18 contributors may be used to endorse or promote products derived from
19 this software without specific prior written permission.
20
21 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22 ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23 LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
24 A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR
25 CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
26 EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
27 PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
28 PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
29 LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
30 NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
31 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32*/
33
Jean-Marc Valin02fa9132008-02-20 12:09:29 +110034#ifdef HAVE_CONFIG_H
35#include "config.h"
36#endif
37
Jean-Marc Valin8600f692008-02-29 15:14:12 +110038#define CELT_C
39
Jean-Marc Valin8ebd3452007-11-29 20:17:32 +110040#include "os_support.h"
Jean-Marc Valinf02ba112007-11-30 01:10:42 +110041#include "mdct.h"
42#include <math.h>
Jean-Marc Valin013c31d2007-11-30 11:36:46 +110043#include "celt.h"
Jean-Marc Valin14191b32007-11-30 12:15:49 +110044#include "pitch.h"
Jean-Marc Valin7351e282008-02-08 15:09:45 +110045#include "kiss_fftr.h"
Jean-Marc Valin991c0f02007-11-30 16:07:46 +110046#include "bands.h"
Jean-Marc Valinecb36a32007-12-05 01:31:49 +110047#include "modes.h"
Jean-Marc Valin6238bc02008-01-28 22:28:54 +110048#include "entcode.h"
Jean-Marc Valin98d2a492007-12-07 22:46:47 +110049#include "quant_bands.h"
Jean-Marc Valin46014ca2007-12-14 13:47:04 +110050#include "psy.h"
Jean-Marc Valin4fbd18d2008-01-17 14:07:55 +110051#include "rate.h"
Jean-Marc Valinc7e0b762008-03-16 07:55:29 +110052#include "stack_alloc.h"
Jean-Marc Valine4aeb472008-06-29 12:06:05 +100053#include "mathops.h"
Jean-Marc Valind9b95652008-08-31 23:34:47 -040054#include "float_cast.h"
Jean-Marc Valinb6f90612008-10-05 22:39:13 -040055#include <stdarg.h>
Jean-Marc Valin013c31d2007-11-30 11:36:46 +110056
Jean-Marc Valin07586892008-03-03 17:19:17 +110057static const celt_word16_t preemph = QCONST16(0.8f,15);
58
Jean-Marc Valin528f4b82008-06-29 03:46:39 +100059#ifdef FIXED_POINT
60static const celt_word16_t transientWindow[16] = {
61 279, 1106, 2454, 4276, 6510, 9081, 11900, 14872,
62 17896, 20868, 23687, 26258, 28492, 30314, 31662, 32489};
63#else
64static const float transientWindow[16] = {
Jean-Marc Valin56522ad2009-06-05 17:17:25 -040065 0.0085135, 0.0337639, 0.0748914, 0.1304955,
66 0.1986827, 0.2771308, 0.3631685, 0.4538658,
67 0.5461342, 0.6368315, 0.7228692, 0.8013173,
68 0.8695045, 0.9251086, 0.9662361, 0.9914865};
Jean-Marc Valin528f4b82008-06-29 03:46:39 +100069#endif
70
Gregory Maxwell17169992009-06-04 15:15:34 -040071#define ENCODERVALID 0x4c434554
72#define ENCODERPARTIAL 0x5445434c
73#define ENCODERFREED 0x4c004500
Jean-Marc Valinc9943942008-08-30 00:55:07 -040074
Jean-Marc Valin276de722008-02-20 17:45:51 +110075/** Encoder state
76 @brief Encoder state
77 */
Jean-Marc Valin269d40a2007-12-07 11:29:45 +110078struct CELTEncoder {
Jean-Marc Valin30f7f812009-10-17 14:35:13 -040079 celt_uint32 marker;
Jean-Marc Valin276de722008-02-20 17:45:51 +110080 const CELTMode *mode; /**< Mode used by the encoder */
Jean-Marc Valin8ebd3452007-11-29 20:17:32 +110081 int frame_size;
82 int block_size;
Jean-Marc Valina5431bf2008-01-03 20:53:01 +110083 int overlap;
Jean-Marc Valinffa13472007-12-10 16:54:17 +110084 int channels;
85
Gregory Maxwell2dd3d322009-06-05 14:05:51 -040086 int pitch_enabled; /* Complexity level is allowed to use pitch */
87 int pitch_permitted; /* Use of the LTP is permitted by the user */
88 int pitch_available; /* Amount of pitch buffer available */
89 int force_intra;
Jean-Marc Valin74f4e9f2009-05-02 09:57:50 -040090 int delayedIntra;
Jean-Marc Valin527db5c2009-06-02 07:56:19 -040091 celt_word16_t tonal_average;
92 int fold_decision;
Jean-Marc Valind35d6772009-10-16 23:16:47 -040093 celt_word16_t gain_prod;
Jean-Marc Valin527db5c2009-06-02 07:56:19 -040094
Gregory Maxwell888d8ce2009-05-21 04:21:53 -040095 int VBR_rate; /* Target number of 16th bits per frame */
Jean-Marc Valin56522ad2009-06-05 17:17:25 -040096 celt_word16_t * restrict preemph_memE;
Jean-Marc Valin65fb92e2008-04-19 22:24:53 +100097 celt_sig_t * restrict preemph_memD;
Jean-Marc Valin81b38c22008-02-29 21:08:49 +110098
Jean-Marc Valin18ddc022008-02-22 14:24:50 +110099 celt_sig_t *in_mem;
Jean-Marc Valin18ddc022008-02-22 14:24:50 +1100100 celt_sig_t *out_mem;
Jean-Marc Valin991c0f02007-11-30 16:07:46 +1100101
Jean-Marc Valin5d561832008-02-27 11:59:05 +1100102 celt_word16_t *oldBandE;
Jean-Marc Valinc6ca4992008-06-01 23:19:16 +1000103#ifdef EXP_PSY
104 celt_word16_t *psy_mem;
105 struct PsyDecay psy;
106#endif
Jean-Marc Valin8ebd3452007-11-29 20:17:32 +1100107};
108
Jean-Marc Valine12017e2009-10-03 13:57:31 -0400109static int check_encoder(const CELTEncoder *st)
Gregory Maxwell17169992009-06-04 15:15:34 -0400110{
111 if (st==NULL)
112 {
113 celt_warning("NULL passed as an encoder structure");
114 return CELT_INVALID_STATE;
115 }
116 if (st->marker == ENCODERVALID)
117 return CELT_OK;
118 if (st->marker == ENCODERFREED)
119 celt_warning("Referencing an encoder that has already been freed");
120 else
121 celt_warning("This is not a valid CELT encoder structure");
122 return CELT_INVALID_STATE;
123}
124
Jean-Marc Valin80ed1472009-10-15 21:45:32 -0400125CELTEncoder *celt_encoder_create(const CELTMode *mode, int channels, int *error)
Jean-Marc Valin8ebd3452007-11-29 20:17:32 +1100126{
Jean-Marc Valinb886ddc2008-03-25 14:38:55 +1100127 int N, C;
Jean-Marc Valin02fa9132008-02-20 12:09:29 +1100128 CELTEncoder *st;
Jean-Marc Valin44ffd5a2008-02-22 00:39:25 +1100129
130 if (check_mode(mode) != CELT_OK)
Jean-Marc Valinece94a02009-10-16 07:30:14 -0400131 {
132 if (error)
133 *error = CELT_INVALID_MODE;
Jean-Marc Valin44ffd5a2008-02-22 00:39:25 +1100134 return NULL;
Jean-Marc Valinece94a02009-10-16 07:30:14 -0400135 }
Jean-Marc Valin80ed1472009-10-15 21:45:32 -0400136 if (channels < 0 || channels > 2)
137 {
138 celt_warning("Only mono and stereo supported");
139 if (error)
140 *error = CELT_BAD_ARG;
141 return NULL;
142 }
Jean-Marc Valin44ffd5a2008-02-22 00:39:25 +1100143
Jean-Marc Valin73e51b32007-12-05 17:48:24 +1100144 N = mode->mdctSize;
Jean-Marc Valin80ed1472009-10-15 21:45:32 -0400145 C = channels;
Jean-Marc Valin02fa9132008-02-20 12:09:29 +1100146 st = celt_alloc(sizeof(CELTEncoder));
Jean-Marc Valin8ebd3452007-11-29 20:17:32 +1100147
Jean-Marc Valinece94a02009-10-16 07:30:14 -0400148 if (st==NULL)
149 {
150 if (error)
151 *error = CELT_ALLOC_FAIL;
Jean-Marc Valin80ed1472009-10-15 21:45:32 -0400152 return NULL;
Jean-Marc Valinece94a02009-10-16 07:30:14 -0400153 }
Gregory Maxwell17169992009-06-04 15:15:34 -0400154 st->marker = ENCODERPARTIAL;
Jean-Marc Valin73e51b32007-12-05 17:48:24 +1100155 st->mode = mode;
Jean-Marc Valinb886ddc2008-03-25 14:38:55 +1100156 st->frame_size = N;
Jean-Marc Valin73e51b32007-12-05 17:48:24 +1100157 st->block_size = N;
Jean-Marc Valina5431bf2008-01-03 20:53:01 +1100158 st->overlap = mode->overlap;
Jean-Marc Valin80ed1472009-10-15 21:45:32 -0400159 st->channels = channels;
Jean-Marc Valina5431bf2008-01-03 20:53:01 +1100160
Gregory Maxwell888d8ce2009-05-21 04:21:53 -0400161 st->VBR_rate = 0;
Jean-Marc Valinc9943942008-08-30 00:55:07 -0400162 st->pitch_enabled = 1;
Gregory Maxwell2dd3d322009-06-05 14:05:51 -0400163 st->pitch_permitted = 1;
Gregory Maxwell98046ca2008-12-13 20:42:03 -0500164 st->pitch_available = 1;
Gregory Maxwell2dd3d322009-06-05 14:05:51 -0400165 st->force_intra = 0;
Gregory Maxwell8842fde2009-05-04 15:58:40 -0400166 st->delayedIntra = 1;
Jean-Marc Valin527db5c2009-06-02 07:56:19 -0400167 st->tonal_average = QCONST16(1.,8);
168 st->fold_decision = 1;
Jean-Marc Valina76a0b22008-01-17 22:43:05 +1100169
Jean-Marc Valin7aa9d8c2008-04-21 00:04:23 +1000170 st->in_mem = celt_alloc(st->overlap*C*sizeof(celt_sig_t));
Jean-Marc Valin8ddd7f42008-04-22 13:37:16 +1000171 st->out_mem = celt_alloc((MAX_PERIOD+st->overlap)*C*sizeof(celt_sig_t));
Jean-Marc Valin81b38c22008-02-29 21:08:49 +1100172
Jean-Marc Valin5d561832008-02-27 11:59:05 +1100173 st->oldBandE = (celt_word16_t*)celt_alloc(C*mode->nbEBands*sizeof(celt_word16_t));
Jean-Marc Valinfa248732007-12-06 07:51:27 +1100174
Gregory Maxwell5f2a74b2008-08-11 23:50:07 -0400175 st->preemph_memE = (celt_word16_t*)celt_alloc(C*sizeof(celt_word16_t));
176 st->preemph_memD = (celt_sig_t*)celt_alloc(C*sizeof(celt_sig_t));
Jean-Marc Valinffa13472007-12-10 16:54:17 +1100177
Jean-Marc Valinc6ca4992008-06-01 23:19:16 +1000178#ifdef EXP_PSY
179 st->psy_mem = celt_alloc(MAX_PERIOD*sizeof(celt_word16_t));
180 psydecay_init(&st->psy, MAX_PERIOD/2, st->mode->Fs);
181#endif
182
Gregory Maxwell17169992009-06-04 15:15:34 -0400183 if ((st->in_mem!=NULL) && (st->out_mem!=NULL) && (st->oldBandE!=NULL)
184#ifdef EXP_PSY
185 && (st->psy_mem!=NULL)
186#endif
187 && (st->preemph_memE!=NULL) && (st->preemph_memD!=NULL))
188 {
Jean-Marc Valinece94a02009-10-16 07:30:14 -0400189 if (error)
190 *error = CELT_OK;
Gregory Maxwell17169992009-06-04 15:15:34 -0400191 st->marker = ENCODERVALID;
192 return st;
193 }
194 /* If the setup fails for some reason deallocate it. */
195 celt_encoder_destroy(st);
Jean-Marc Valinece94a02009-10-16 07:30:14 -0400196 if (error)
197 *error = CELT_ALLOC_FAIL;
Gregory Maxwell17169992009-06-04 15:15:34 -0400198 return NULL;
Jean-Marc Valin8ebd3452007-11-29 20:17:32 +1100199}
200
Peter Kirk19f9dc92008-06-06 14:38:38 +0200201void celt_encoder_destroy(CELTEncoder *st)
Jean-Marc Valin14191b32007-11-30 12:15:49 +1100202{
203 if (st == NULL)
204 {
205 celt_warning("NULL passed to celt_encoder_destroy");
206 return;
207 }
Jean-Marc Valin44ffd5a2008-02-22 00:39:25 +1100208
Gregory Maxwell17169992009-06-04 15:15:34 -0400209 if (st->marker == ENCODERFREED)
210 {
Gregory Maxwell17169992009-06-04 15:15:34 -0400211 celt_warning("Freeing an encoder which has already been freed");
Gregory Maxwelldc67fa92009-06-04 17:17:35 -0400212 return;
Gregory Maxwell17169992009-06-04 15:15:34 -0400213 }
214
215 if (st->marker != ENCODERVALID && st->marker != ENCODERPARTIAL)
216 {
217 celt_warning("This is not a valid CELT encoder structure");
218 return;
219 }
220 /*Check_mode is non-fatal here because we can still free
221 the encoder memory even if the mode is bad, although calling
222 the free functions in this order is a violation of the API.*/
223 check_mode(st->mode);
224
Jean-Marc Valin14191b32007-11-30 12:15:49 +1100225 celt_free(st->in_mem);
Jean-Marc Valin14191b32007-11-30 12:15:49 +1100226 celt_free(st->out_mem);
Jean-Marc Valin991c0f02007-11-30 16:07:46 +1100227
Jean-Marc Valinc245a222007-12-06 19:14:20 +1100228 celt_free(st->oldBandE);
Jean-Marc Valin7351e282008-02-08 15:09:45 +1100229
230 celt_free(st->preemph_memE);
231 celt_free(st->preemph_memD);
232
Jean-Marc Valinc6ca4992008-06-01 23:19:16 +1000233#ifdef EXP_PSY
234 celt_free (st->psy_mem);
235 psydecay_clear(&st->psy);
236#endif
Gregory Maxwell17169992009-06-04 15:15:34 -0400237 st->marker = ENCODERFREED;
Jean-Marc Valinc6ca4992008-06-01 23:19:16 +1000238
Jean-Marc Valin14191b32007-11-30 12:15:49 +1100239 celt_free(st);
240}
241
Jean-Marc Valin30f7f812009-10-17 14:35:13 -0400242static inline celt_int16 FLOAT2INT16(float x)
Jean-Marc Valin42074382008-02-27 11:08:53 +1100243{
Gregory Maxwell0ac2b2f2009-05-21 23:08:46 -0400244 x = x*CELT_SIG_SCALE;
Gregory Maxwell5f2a74b2008-08-11 23:50:07 -0400245 x = MAX32(x, -32768);
246 x = MIN32(x, 32767);
Jean-Marc Valin30f7f812009-10-17 14:35:13 -0400247 return (celt_int16)float2int(x);
Gregory Maxwell5f2a74b2008-08-11 23:50:07 -0400248}
249
250static inline celt_word16_t SIG2WORD16(celt_sig_t x)
251{
252#ifdef FIXED_POINT
Jean-Marc Valin42074382008-02-27 11:08:53 +1100253 x = PSHR32(x, SIG_SHIFT);
Jean-Marc Valinabdfc382008-04-18 15:57:18 +1000254 x = MAX32(x, -32768);
255 x = MIN32(x, 32767);
Jean-Marc Valin42074382008-02-27 11:08:53 +1100256 return EXTRACT16(x);
257#else
Gregory Maxwell5f2a74b2008-08-11 23:50:07 -0400258 return (celt_word16_t)x;
Jean-Marc Valin42074382008-02-27 11:08:53 +1100259#endif
260}
261
Jean-Marc Valinbd7de0a2008-07-06 10:57:26 -0400262static int transient_analysis(celt_word32_t *in, int len, int C, int *transient_time, int *transient_shift)
Jean-Marc Valin9375aa42008-06-27 07:57:35 +1000263{
264 int c, i, n;
Jean-Marc Valin0ceccb22008-07-03 20:41:06 -0400265 celt_word32_t ratio;
Jean-Marc Valin0ceccb22008-07-03 20:41:06 -0400266 VARDECL(celt_word32_t, begin);
267 SAVE_STACK;
268 ALLOC(begin, len, celt_word32_t);
Jean-Marc Valin9375aa42008-06-27 07:57:35 +1000269 for (i=0;i<len;i++)
Jean-Marc Valin5c3bc672008-08-28 23:34:24 -0400270 begin[i] = ABS32(SHR32(in[C*i],SIG_SHIFT));
Jean-Marc Valin9375aa42008-06-27 07:57:35 +1000271 for (c=1;c<C;c++)
272 {
273 for (i=0;i<len;i++)
Jean-Marc Valin5c3bc672008-08-28 23:34:24 -0400274 begin[i] = MAX32(begin[i], ABS32(SHR32(in[C*i+c],SIG_SHIFT)));
Jean-Marc Valin9375aa42008-06-27 07:57:35 +1000275 }
Jean-Marc Valin9375aa42008-06-27 07:57:35 +1000276 for (i=1;i<len;i++)
Jean-Marc Valinbd7de0a2008-07-06 10:57:26 -0400277 begin[i] = MAX32(begin[i-1],begin[i]);
Jean-Marc Valin9375aa42008-06-27 07:57:35 +1000278 n = -1;
279 for (i=8;i<len-8;i++)
280 {
Jean-Marc Valinbd7de0a2008-07-06 10:57:26 -0400281 if (begin[i] < MULT16_32_Q15(QCONST16(.2f,15),begin[len-1]))
282 n=i;
Jean-Marc Valin9375aa42008-06-27 07:57:35 +1000283 }
Jean-Marc Valin9375aa42008-06-27 07:57:35 +1000284 if (n<32)
285 {
286 n = -1;
287 ratio = 0;
Jean-Marc Valinbd7de0a2008-07-06 10:57:26 -0400288 } else {
289 ratio = DIV32(begin[len-1],1+begin[n-16]);
Jean-Marc Valin9375aa42008-06-27 07:57:35 +1000290 }
Jean-Marc Valinf4578192008-07-04 16:47:28 -0400291 if (ratio < 0)
292 ratio = 0;
293 if (ratio > 1000)
294 ratio = 1000;
Jean-Marc Valinbd7de0a2008-07-06 10:57:26 -0400295 ratio *= ratio;
Jean-Marc Valinaa936252009-05-29 22:14:20 -0400296
297 if (ratio > 2048)
Jean-Marc Valinbd7de0a2008-07-06 10:57:26 -0400298 *transient_shift = 3;
Jean-Marc Valinaa936252009-05-29 22:14:20 -0400299 else
300 *transient_shift = 0;
301
Jean-Marc Valinbd7de0a2008-07-06 10:57:26 -0400302 *transient_time = n;
303
Jean-Marc Valin0ceccb22008-07-03 20:41:06 -0400304 RESTORE_STACK;
Jean-Marc Valinbd7de0a2008-07-06 10:57:26 -0400305 return ratio > 20;
Jean-Marc Valin9375aa42008-06-27 07:57:35 +1000306}
307
Jean-Marc Valin56522ad2009-06-05 17:17:25 -0400308/** Apply window and compute the MDCT for all sub-frames and
309 all channels in a frame */
Jean-Marc Valinbf2398b2009-10-15 07:28:19 -0400310static void compute_mdcts(const CELTMode *mode, int shortBlocks, celt_sig_t * restrict in, celt_sig_t * restrict out, int _C)
Jean-Marc Valinda721882007-11-30 15:17:42 +1100311{
Jean-Marc Valinbf2398b2009-10-15 07:28:19 -0400312 const int C = CHANNELS(_C);
Jean-Marc Valin9d1decd2008-06-17 13:28:13 +1000313 if (C==1 && !shortBlocks)
Jean-Marc Valinda721882007-11-30 15:17:42 +1100314 {
Jean-Marc Valin9d1decd2008-06-17 13:28:13 +1000315 const mdct_lookup *lookup = MDCT(mode);
316 const int overlap = OVERLAP(mode);
317 mdct_forward(lookup, in, out, mode->window, overlap);
Jean-Marc Valinaa4f58b2009-10-03 09:27:59 -0400318 } else {
Jean-Marc Valin9d1decd2008-06-17 13:28:13 +1000319 const mdct_lookup *lookup = MDCT(mode);
320 const int overlap = OVERLAP(mode);
Jean-Marc Valinaa4f58b2009-10-03 09:27:59 -0400321 int N = FRAMESIZE(mode);
322 int B = 1;
Jean-Marc Valin9d1decd2008-06-17 13:28:13 +1000323 int b, c;
324 VARDECL(celt_word32_t, x);
325 VARDECL(celt_word32_t, tmp);
326 SAVE_STACK;
Jean-Marc Valinaa4f58b2009-10-03 09:27:59 -0400327 if (shortBlocks)
328 {
329 lookup = &mode->shortMdct;
330 N = mode->shortMdctSize;
331 B = mode->nbShortMdcts;
332 }
Jean-Marc Valin9d1decd2008-06-17 13:28:13 +1000333 ALLOC(x, N+overlap, celt_word32_t);
334 ALLOC(tmp, N, celt_word32_t);
335 for (c=0;c<C;c++)
336 {
Jean-Marc Valin9d1decd2008-06-17 13:28:13 +1000337 for (b=0;b<B;b++)
338 {
339 int j;
340 for (j=0;j<N+overlap;j++)
341 x[j] = in[C*(b*N+j)+c];
342 mdct_forward(lookup, x, tmp, mode->window, overlap);
343 /* Interleaving the sub-frames */
344 for (j=0;j<N;j++)
Jean-Marc Valin08a82ff2009-06-14 14:05:19 -0400345 out[(j*B+b)+c*N*B] = tmp[j];
Jean-Marc Valin9d1decd2008-06-17 13:28:13 +1000346 }
347 }
348 RESTORE_STACK;
Jean-Marc Valinda721882007-11-30 15:17:42 +1100349 }
Jean-Marc Valinda721882007-11-30 15:17:42 +1100350}
351
Jean-Marc Valin56522ad2009-06-05 17:17:25 -0400352/** Compute the IMDCT and apply window for all sub-frames and
353 all channels in a frame */
Jean-Marc Valinbf2398b2009-10-15 07:28:19 -0400354static void compute_inv_mdcts(const CELTMode *mode, int shortBlocks, celt_sig_t *X, int transient_time, int transient_shift, celt_sig_t * restrict out_mem, int _C)
Jean-Marc Valin1677aa92007-12-08 01:13:34 +1100355{
Jean-Marc Valinb886ddc2008-03-25 14:38:55 +1100356 int c, N4;
Jean-Marc Valinbf2398b2009-10-15 07:28:19 -0400357 const int C = CHANNELS(_C);
Jean-Marc Valinb18ec0b2008-04-11 04:07:52 +1000358 const int N = FRAMESIZE(mode);
359 const int overlap = OVERLAP(mode);
Jean-Marc Valina536f772008-03-22 09:01:50 +1100360 N4 = (N-overlap)>>1;
Jean-Marc Valinffa13472007-12-10 16:54:17 +1100361 for (c=0;c<C;c++)
Jean-Marc Valin1677aa92007-12-08 01:13:34 +1100362 {
Jean-Marc Valinb886ddc2008-03-25 14:38:55 +1100363 int j;
Jean-Marc Valin528f4b82008-06-29 03:46:39 +1000364 if (transient_shift==0 && C==1 && !shortBlocks) {
Jean-Marc Valin9d1decd2008-06-17 13:28:13 +1000365 const mdct_lookup *lookup = MDCT(mode);
366 mdct_backward(lookup, X, out_mem+C*(MAX_PERIOD-N-N4), mode->window, overlap);
Jean-Marc Valin9d1decd2008-06-17 13:28:13 +1000367 } else {
Jean-Marc Valin9d1decd2008-06-17 13:28:13 +1000368 VARDECL(celt_word32_t, x);
369 VARDECL(celt_word32_t, tmp);
Jean-Marc Valinde678582009-10-03 10:36:27 -0400370 int b;
371 int N2 = N;
372 int B = 1;
373 int n4offset=0;
374 const mdct_lookup *lookup = MDCT(mode);
Jean-Marc Valin9d1decd2008-06-17 13:28:13 +1000375 SAVE_STACK;
Jean-Marc Valinde678582009-10-03 10:36:27 -0400376
Jean-Marc Valin9d1decd2008-06-17 13:28:13 +1000377 ALLOC(x, 2*N, celt_word32_t);
378 ALLOC(tmp, N, celt_word32_t);
Jean-Marc Valinde678582009-10-03 10:36:27 -0400379
380 if (shortBlocks)
381 {
382 lookup = &mode->shortMdct;
383 N2 = mode->shortMdctSize;
384 B = mode->nbShortMdcts;
385 n4offset = N4;
386 }
Jean-Marc Valin9d1decd2008-06-17 13:28:13 +1000387 /* Prevents problems from the imdct doing the overlap-add */
Gregory Maxwell23e654f2008-09-27 16:20:03 -0400388 CELT_MEMSET(x+N4, 0, N2);
Jean-Marc Valinde678582009-10-03 10:36:27 -0400389
Jean-Marc Valin9d1decd2008-06-17 13:28:13 +1000390 for (b=0;b<B;b++)
391 {
392 /* De-interleaving the sub-frames */
393 for (j=0;j<N2;j++)
Jean-Marc Valin08a82ff2009-06-14 14:05:19 -0400394 tmp[j] = X[(j*B+b)+c*N2*B];
Jean-Marc Valinde678582009-10-03 10:36:27 -0400395 mdct_backward(lookup, tmp, x+n4offset+N2*b, mode->window, overlap);
Jean-Marc Valin9d1decd2008-06-17 13:28:13 +1000396 }
Jean-Marc Valinde678582009-10-03 10:36:27 -0400397
Jean-Marc Valin528f4b82008-06-29 03:46:39 +1000398 if (transient_shift > 0)
Jean-Marc Valin12b22482008-06-16 14:13:05 +1000399 {
Jean-Marc Valin528f4b82008-06-29 03:46:39 +1000400#ifdef FIXED_POINT
Jean-Marc Valin12b22482008-06-16 14:13:05 +1000401 for (j=0;j<16;j++)
Jean-Marc Valin528f4b82008-06-29 03:46:39 +1000402 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 +1000403 for (j=transient_time;j<N+overlap;j++)
Jean-Marc Valin528f4b82008-06-29 03:46:39 +1000404 x[N4+j] = SHL32(x[N4+j], transient_shift);
405#else
406 for (j=0;j<16;j++)
Jean-Marc Valine4aeb472008-06-29 12:06:05 +1000407 x[N4+transient_time+j-16] *= 1+transientWindow[j]*((1<<transient_shift)-1);
Jean-Marc Valin528f4b82008-06-29 03:46:39 +1000408 for (j=transient_time;j<N+overlap;j++)
409 x[N4+j] *= 1<<transient_shift;
410#endif
Jean-Marc Valin12b22482008-06-16 14:13:05 +1000411 }
Jean-Marc Valin56522ad2009-06-05 17:17:25 -0400412 /* The first and last part would need to be set to zero
413 if we actually wanted to use them. */
Jean-Marc Valin8ddd7f42008-04-22 13:37:16 +1000414 for (j=0;j<overlap;j++)
415 out_mem[C*(MAX_PERIOD-N)+C*j+c] += x[j+N4];
416 for (j=0;j<overlap;j++)
417 out_mem[C*(MAX_PERIOD)+C*(overlap-j-1)+c] = x[2*N-j-N4-1];
418 for (j=0;j<2*N4;j++)
419 out_mem[C*(MAX_PERIOD-N)+C*(j+overlap)+c] = x[j+N4+overlap];
420 RESTORE_STACK;
421 }
Jean-Marc Valin1677aa92007-12-08 01:13:34 +1100422 }
423}
424
Jean-Marc Valin05ed03e2009-04-29 07:44:13 -0400425#define FLAG_NONE 0
Jean-Marc Valin5a700972009-08-08 13:23:03 -0400426#define FLAG_INTRA (1U<<13)
427#define FLAG_PITCH (1U<<12)
428#define FLAG_SHORT (1U<<11)
429#define FLAG_FOLD (1U<<10)
Jean-Marc Valin05ed03e2009-04-29 07:44:13 -0400430#define FLAG_MASK (FLAG_INTRA|FLAG_PITCH|FLAG_SHORT|FLAG_FOLD)
431
Jean-Marc Valine12017e2009-10-03 13:57:31 -0400432static const int flaglist[8] = {
Jean-Marc Valina8be38a2009-04-29 22:16:26 -0400433 0 /*00 */ | FLAG_FOLD,
434 1 /*01 */ | FLAG_PITCH|FLAG_FOLD,
435 8 /*1000*/ | FLAG_NONE,
436 9 /*1001*/ | FLAG_SHORT|FLAG_FOLD,
437 10 /*1010*/ | FLAG_PITCH,
438 11 /*1011*/ | FLAG_INTRA,
439 6 /*110 */ | FLAG_INTRA|FLAG_FOLD,
440 7 /*111 */ | FLAG_INTRA|FLAG_SHORT|FLAG_FOLD
Jean-Marc Valin05ed03e2009-04-29 07:44:13 -0400441};
442
Jean-Marc Valine12017e2009-10-03 13:57:31 -0400443static 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 -0400444{
445 int i;
446 int flags=FLAG_NONE;
447 int flag_bits;
448 flags |= intra_ener ? FLAG_INTRA : 0;
449 flags |= has_pitch ? FLAG_PITCH : 0;
450 flags |= shortBlocks ? FLAG_SHORT : 0;
451 flags |= has_fold ? FLAG_FOLD : 0;
452 for (i=0;i<8;i++)
453 if (flags == (flaglist[i]&FLAG_MASK))
454 break;
455 celt_assert(i<8);
456 flag_bits = flaglist[i]&0xf;
457 /*printf ("enc %d: %d %d %d %d\n", flag_bits, intra_ener, has_pitch, shortBlocks, has_fold);*/
458 if (i<2)
Jean-Marc Valinc08be442009-06-17 23:23:46 -0400459 ec_enc_uint(enc, flag_bits, 4);
Jean-Marc Valin05ed03e2009-04-29 07:44:13 -0400460 else if (i<6)
Jean-Marc Valinc08be442009-06-17 23:23:46 -0400461 ec_enc_uint(enc, flag_bits, 16);
Jean-Marc Valin05ed03e2009-04-29 07:44:13 -0400462 else
Jean-Marc Valinc08be442009-06-17 23:23:46 -0400463 ec_enc_uint(enc, flag_bits, 8);
Jean-Marc Valin05ed03e2009-04-29 07:44:13 -0400464}
465
Jean-Marc Valine12017e2009-10-03 13:57:31 -0400466static 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 -0400467{
468 int i;
469 int flag_bits;
Jean-Marc Valinc08be442009-06-17 23:23:46 -0400470 flag_bits = ec_dec_uint(dec, 4);
Jean-Marc Valin05ed03e2009-04-29 07:44:13 -0400471 /*printf ("(%d) ", flag_bits);*/
472 if (flag_bits==2)
Jean-Marc Valinc08be442009-06-17 23:23:46 -0400473 flag_bits = (flag_bits<<2) | ec_dec_uint(dec, 4);
Jean-Marc Valin05ed03e2009-04-29 07:44:13 -0400474 else if (flag_bits==3)
Jean-Marc Valinc08be442009-06-17 23:23:46 -0400475 flag_bits = (flag_bits<<1) | ec_dec_uint(dec, 2);
Jean-Marc Valin05ed03e2009-04-29 07:44:13 -0400476 for (i=0;i<8;i++)
477 if (flag_bits == (flaglist[i]&0xf))
478 break;
479 celt_assert(i<8);
480 *intra_ener = (flaglist[i]&FLAG_INTRA) != 0;
481 *has_pitch = (flaglist[i]&FLAG_PITCH) != 0;
482 *shortBlocks = (flaglist[i]&FLAG_SHORT) != 0;
483 *has_fold = (flaglist[i]&FLAG_FOLD ) != 0;
484 /*printf ("dec %d: %d %d %d %d\n", flag_bits, *intra_ener, *has_pitch, *shortBlocks, *has_fold);*/
485}
486
Jean-Marc Valinbf2398b2009-10-15 07:28:19 -0400487static void deemphasis(celt_sig_t *in, celt_word16_t *pcm, int N, int _C, celt_word16_t coef, celt_sig_t *mem)
Jean-Marc Valine12017e2009-10-03 13:57:31 -0400488{
Jean-Marc Valinbf2398b2009-10-15 07:28:19 -0400489 const int C = CHANNELS(_C);
Jean-Marc Valine12017e2009-10-03 13:57:31 -0400490 int c;
491 for (c=0;c<C;c++)
492 {
493 int j;
494 for (j=0;j<N;j++)
495 {
496 celt_sig_t tmp = MAC16_32_Q15(in[C*(MAX_PERIOD-N)+C*j+c],
497 coef,mem[c]);
498 mem[c] = tmp;
499 pcm[C*j+c] = SCALEOUT(SIG2WORD16(tmp));
500 }
501 }
502
503}
504
Jean-Marc Valinbf2398b2009-10-15 07:28:19 -0400505static void mdct_shape(const CELTMode *mode, celt_norm_t *X, int start, int end, int N, int nbShortMdcts, int mdct_weight_shift, int _C)
Jean-Marc Valin88619552009-10-04 21:35:36 -0400506{
507 int m, i, c;
Jean-Marc Valinbf2398b2009-10-15 07:28:19 -0400508 const int C = CHANNELS(_C);
Jean-Marc Valin88619552009-10-04 21:35:36 -0400509 for (c=0;c<C;c++)
510 for (m=start;m<end;m++)
511 for (i=m+c*N;i<(c+1)*N;i+=nbShortMdcts)
512#ifdef FIXED_POINT
513 X[i] = SHR16(X[i], mdct_weight_shift);
514#else
515 X[i] = (1.f/(1<<mdct_weight_shift))*X[i];
516#endif
Jean-Marc Valinbf2398b2009-10-15 07:28:19 -0400517 renormalise_bands(mode, X, C);
Jean-Marc Valin88619552009-10-04 21:35:36 -0400518}
519
520
Gregory Maxwell5f2a74b2008-08-11 23:50:07 -0400521#ifdef FIXED_POINT
Jean-Marc Valin30f7f812009-10-17 14:35:13 -0400522int 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 +1100523{
Gregory Maxwell5f2a74b2008-08-11 23:50:07 -0400524#else
Gregory Maxwell82595312008-09-30 18:20:14 -0400525int celt_encode_float(CELTEncoder * restrict st, const celt_sig_t * pcm, celt_sig_t * optional_synthesis, unsigned char *compressed, int nbCompressedBytes)
Gregory Maxwell5f2a74b2008-08-11 23:50:07 -0400526{
527#endif
Jean-Marc Valin88619552009-10-04 21:35:36 -0400528 int i, c, N, NN, N4;
Jean-Marc Valin7e8a4872008-02-11 16:55:34 +1100529 int has_pitch;
Jean-Marc Valin0bb05bc2008-02-20 13:43:40 +1100530 int pitch_index;
Jean-Marc Valinc890b582008-08-01 22:26:49 -0400531 int bits;
Jean-Marc Valinbc799912008-11-07 22:53:13 -0500532 int has_fold=1;
Gregory Maxwell888d8ce2009-05-21 04:21:53 -0400533 unsigned coarse_needed;
Jean-Marc Valin8679a802008-10-18 07:44:35 -0400534 ec_byte_buffer buf;
535 ec_enc enc;
Jean-Marc Valin31b79d12008-03-12 17:17:23 +1100536 VARDECL(celt_sig_t, in);
537 VARDECL(celt_sig_t, freq);
Jean-Marc Valinab220aa2009-09-15 22:38:40 -0400538 VARDECL(celt_sig_t, pitch_freq);
Jean-Marc Valin31b79d12008-03-12 17:17:23 +1100539 VARDECL(celt_norm_t, X);
Jean-Marc Valin31b79d12008-03-12 17:17:23 +1100540 VARDECL(celt_ener_t, bandE);
Jean-Marc Valin7a567412009-06-13 22:59:43 -0400541 VARDECL(celt_word16_t, bandLogE);
Jean-Marc Valin6775de32008-08-02 08:14:42 -0400542 VARDECL(int, fine_quant);
Jean-Marc Valinc890b582008-08-01 22:26:49 -0400543 VARDECL(celt_word16_t, error);
Jean-Marc Valin6775de32008-08-02 08:14:42 -0400544 VARDECL(int, pulses);
545 VARDECL(int, offsets);
Jean-Marc Valin52cb5fb2009-06-10 08:08:55 -0400546 VARDECL(int, fine_priority);
Jean-Marc Valin18a3b792009-05-01 19:58:55 -0400547 int intra_ener = 0;
Jean-Marc Valin9d1decd2008-06-17 13:28:13 +1000548 int shortBlocks=0;
Jean-Marc Valin12b22482008-06-16 14:13:05 +1000549 int transient_time;
Jean-Marc Valin528f4b82008-06-29 03:46:39 +1000550 int transient_shift;
Jean-Marc Valin80ed1472009-10-15 21:45:32 -0400551 const int C = CHANNELS(st->channels);
Jean-Marc Valinaa936252009-05-29 22:14:20 -0400552 int mdct_weight_shift = 0;
553 int mdct_weight_pos=0;
Jean-Marc Valinab220aa2009-09-15 22:38:40 -0400554 int gain_id=0;
Jean-Marc Valin92ae3702009-09-16 07:57:17 -0400555 int norm_rate;
Jean-Marc Valin8600f692008-02-29 15:14:12 +1100556 SAVE_STACK;
Jean-Marc Valin44ffd5a2008-02-22 00:39:25 +1100557
Gregory Maxwell17169992009-06-04 15:15:34 -0400558 if (check_encoder(st) != CELT_OK)
559 return CELT_INVALID_STATE;
560
Jean-Marc Valin44ffd5a2008-02-22 00:39:25 +1100561 if (check_mode(st->mode) != CELT_OK)
562 return CELT_INVALID_MODE;
563
Gregory Maxwell0719f6f2009-07-09 17:07:24 -0400564 if (nbCompressedBytes<0 || pcm==NULL)
Gregory Maxwell520eeae2009-02-09 01:33:21 -0500565 return CELT_BAD_ARG;
566
Jean-Marc Valin56522ad2009-06-05 17:17:25 -0400567 /* The memset is important for now in case the encoder doesn't
568 fill up all the bytes */
Jean-Marc Valin8679a802008-10-18 07:44:35 -0400569 CELT_MEMSET(compressed, 0, nbCompressedBytes);
570 ec_byte_writeinit_buffer(&buf, compressed, nbCompressedBytes);
571 ec_enc_init(&enc,&buf);
572
Jean-Marc Valinf02ba112007-11-30 01:10:42 +1100573 N = st->block_size;
Jean-Marc Valina536f772008-03-22 09:01:50 +1100574 N4 = (N-st->overlap)>>1;
Jean-Marc Valinbdb58832008-04-20 17:42:10 +1000575 ALLOC(in, 2*C*N-2*C*N4, celt_sig_t);
Jean-Marc Valina5431bf2008-01-03 20:53:01 +1100576
Jean-Marc Valinbdb58832008-04-20 17:42:10 +1000577 CELT_COPY(in, st->in_mem, C*st->overlap);
Jean-Marc Valinffa13472007-12-10 16:54:17 +1100578 for (c=0;c<C;c++)
Jean-Marc Valin6f7e83d2007-12-01 00:36:41 +1100579 {
Gregory Maxwell5f2a74b2008-08-11 23:50:07 -0400580 const celt_word16_t * restrict pcmp = pcm+c;
Jean-Marc Valin62290062008-04-20 22:16:02 +1000581 celt_sig_t * restrict inp = in+C*st->overlap+c;
Jean-Marc Valinb886ddc2008-03-25 14:38:55 +1100582 for (i=0;i<N;i++)
Jean-Marc Valinffa13472007-12-10 16:54:17 +1100583 {
Jean-Marc Valin62290062008-04-20 22:16:02 +1000584 /* Apply pre-emphasis */
Gregory Maxwell5f2a74b2008-08-11 23:50:07 -0400585 celt_sig_t tmp = SCALEIN(SHL32(EXTEND32(*pcmp), SIG_SHIFT));
Jean-Marc Valin5c3bc672008-08-28 23:34:24 -0400586 *inp = SUB32(tmp, SHR32(MULT16_16(preemph,st->preemph_memE[c]),3));
Gregory Maxwell5f2a74b2008-08-11 23:50:07 -0400587 st->preemph_memE[c] = SCALEIN(*pcmp);
Jean-Marc Valin62290062008-04-20 22:16:02 +1000588 inp += C;
589 pcmp += C;
Jean-Marc Valinffa13472007-12-10 16:54:17 +1100590 }
Jean-Marc Valin6f7e83d2007-12-01 00:36:41 +1100591 }
Jean-Marc Valinbdb58832008-04-20 17:42:10 +1000592 CELT_COPY(st->in_mem, in+C*(2*N-2*N4-st->overlap), C*st->overlap);
Jean-Marc Valin2014ca32009-06-18 23:33:04 -0400593
Jean-Marc Valin37ab9c62008-11-08 09:14:38 -0500594 /* Transient handling */
Jean-Marc Valin2014ca32009-06-18 23:33:04 -0400595 transient_time = -1;
596 transient_shift = 0;
597 shortBlocks = 0;
598
599 if (st->mode->nbShortMdcts > 1 && transient_analysis(in, N+st->overlap, C, &transient_time, &transient_shift))
Jean-Marc Valin9375aa42008-06-27 07:57:35 +1000600 {
Jean-Marc Valin7028d622008-07-10 23:06:58 -0400601#ifndef FIXED_POINT
Jean-Marc Valin2014ca32009-06-18 23:33:04 -0400602 float gain_1;
Jean-Marc Valin528f4b82008-06-29 03:46:39 +1000603#endif
Jean-Marc Valin2014ca32009-06-18 23:33:04 -0400604 /* Apply the inverse shaping window */
605 if (transient_shift)
606 {
Jean-Marc Valin7028d622008-07-10 23:06:58 -0400607#ifdef FIXED_POINT
Jean-Marc Valin2014ca32009-06-18 23:33:04 -0400608 for (c=0;c<C;c++)
609 for (i=0;i<16;i++)
610 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]);
611 for (c=0;c<C;c++)
612 for (i=transient_time;i<N+st->overlap;i++)
613 in[C*i+c] = SHR32(in[C*i+c], transient_shift);
Jean-Marc Valin7028d622008-07-10 23:06:58 -0400614#else
Jean-Marc Valin2014ca32009-06-18 23:33:04 -0400615 for (c=0;c<C;c++)
616 for (i=0;i<16;i++)
617 in[C*(transient_time+i-16)+c] /= 1+transientWindow[i]*((1<<transient_shift)-1);
618 gain_1 = 1./(1<<transient_shift);
619 for (c=0;c<C;c++)
620 for (i=transient_time;i<N+st->overlap;i++)
621 in[C*i+c] *= gain_1;
Jean-Marc Valin7028d622008-07-10 23:06:58 -0400622#endif
Jean-Marc Valin528f4b82008-06-29 03:46:39 +1000623 }
Jean-Marc Valin2014ca32009-06-18 23:33:04 -0400624 shortBlocks = 1;
625 has_fold = 1;
Jean-Marc Valin12b22482008-06-16 14:13:05 +1000626 }
Jean-Marc Valinc5f2a9d2008-10-26 22:00:26 -0400627
Jean-Marc Valin32ec58c2009-05-01 21:28:58 -0400628 ALLOC(freq, C*N, celt_sig_t); /**< Interleaved signal MDCTs */
629 ALLOC(bandE,st->mode->nbEBands*C, celt_ener_t);
Jean-Marc Valin7a567412009-06-13 22:59:43 -0400630 ALLOC(bandLogE,st->mode->nbEBands*C, celt_word16_t);
Jean-Marc Valin32ec58c2009-05-01 21:28:58 -0400631 /* Compute MDCTs */
Jean-Marc Valinbf2398b2009-10-15 07:28:19 -0400632 compute_mdcts(st->mode, shortBlocks, in, freq, C);
Jean-Marc Valin08a82ff2009-06-14 14:05:19 -0400633
Jean-Marc Valinaa936252009-05-29 22:14:20 -0400634
Jean-Marc Valin30f7f812009-10-17 14:35:13 -0400635 norm_rate = (nbCompressedBytes-5)*8*(celt_uint32)st->mode->Fs/(C*N)>>10;
Jean-Marc Valinddb181b2008-03-03 14:53:47 +1100636 /* Pitch analysis: we do it early to save on the peak stack space */
Jean-Marc Valin56522ad2009-06-05 17:17:25 -0400637 /* Don't use pitch if there isn't enough data available yet,
638 or if we're using shortBlocks */
Jean-Marc Valine6d832a2009-07-08 22:21:31 -0400639 has_pitch = st->pitch_enabled && st->pitch_permitted && (N <= 512)
Jean-Marc Valin92ae3702009-09-16 07:57:17 -0400640 && (st->pitch_available >= MAX_PERIOD) && (!shortBlocks)
641 && norm_rate < 50;
Gregory Maxwell98046ca2008-12-13 20:42:03 -0500642 if (has_pitch)
Jean-Marc Valinc5f2a9d2008-10-26 22:00:26 -0400643 {
Jean-Marc Valinbf2398b2009-10-15 07:28:19 -0400644 find_spectral_pitch(st->mode, st->mode->fft, &st->mode->psy, in, st->out_mem, st->mode->window, NULL, 2*N-2*N4, MAX_PERIOD-(2*N-2*N4), &pitch_index, C);
Jean-Marc Valinc5f2a9d2008-10-26 22:00:26 -0400645 }
Jean-Marc Valin37ab9c62008-11-08 09:14:38 -0500646
Jean-Marc Valin56522ad2009-06-05 17:17:25 -0400647 /* Deferred allocation after find_spectral_pitch() to reduce
648 the peak memory usage */
Jean-Marc Valinb886ddc2008-03-25 14:38:55 +1100649 ALLOC(X, C*N, celt_norm_t); /**< Interleaved normalised MDCTs */
Jean-Marc Valin8d4ac152008-02-29 17:24:02 +1100650
Jean-Marc Valinab220aa2009-09-15 22:38:40 -0400651 ALLOC(pitch_freq, C*N, celt_sig_t); /**< Interleaved signal MDCTs */
Jean-Marc Valin4c77ea92009-09-14 22:50:41 -0400652 if (has_pitch)
653 {
Jean-Marc Valin92ae3702009-09-16 07:57:17 -0400654
Jean-Marc Valinbf2398b2009-10-15 07:28:19 -0400655 compute_mdcts(st->mode, 0, st->out_mem+pitch_index*C, pitch_freq, C);
Jean-Marc Valind35d6772009-10-16 23:16:47 -0400656 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 -0400657 }
658
659 if (has_pitch)
Jean-Marc Valinbf2398b2009-10-15 07:28:19 -0400660 apply_pitch(st->mode, freq, pitch_freq, gain_id, 1, C);
Jean-Marc Valin6c245242007-12-29 23:27:42 +1100661
Jean-Marc Valinbf2398b2009-10-15 07:28:19 -0400662 compute_band_energies(st->mode, freq, bandE, C);
Jean-Marc Valin4c77ea92009-09-14 22:50:41 -0400663 for (i=0;i<st->mode->nbEBands*C;i++)
664 bandLogE[i] = amp2Log(bandE[i]);
665
Jean-Marc Valin8ebd3452007-11-29 20:17:32 +1100666 /* Band normalisation */
Jean-Marc Valinbf2398b2009-10-15 07:28:19 -0400667 normalise_bands(st->mode, freq, X, bandE, C);
668 if (!shortBlocks && !folding_decision(st->mode, X, &st->tonal_average, &st->fold_decision, C))
Jean-Marc Valin527db5c2009-06-02 07:56:19 -0400669 has_fold = 0;
Jean-Marc Valin26c9e142007-12-31 21:27:54 +1100670
Jean-Marc Valin4c77ea92009-09-14 22:50:41 -0400671 /* Don't use intra energy when we're operating at low bit-rate */
672 intra_ener = st->force_intra || (!has_pitch && st->delayedIntra && nbCompressedBytes > st->mode->nbEBands);
673 if (shortBlocks || intra_decision(bandLogE, st->oldBandE, st->mode->nbEBands))
674 st->delayedIntra = 1;
675 else
676 st->delayedIntra = 0;
677
Jean-Marc Valin88619552009-10-04 21:35:36 -0400678 NN = st->mode->eBands[st->mode->nbEBands];
679 if (shortBlocks && !transient_shift)
680 {
681 celt_word32_t sum[8]={1,1,1,1,1,1,1,1};
682 int m;
683 for (c=0;c<C;c++)
684 {
685 m=0;
686 do {
687 celt_word32_t tmp=0;
688 for (i=m+c*N;i<c*N+NN;i+=st->mode->nbShortMdcts)
689 tmp += ABS32(X[i]);
690 sum[m++] += tmp;
691 } while (m<st->mode->nbShortMdcts);
692 }
693 m=0;
694#ifdef FIXED_POINT
695 do {
696 if (SHR32(sum[m+1],3) > sum[m])
697 {
698 mdct_weight_shift=2;
699 mdct_weight_pos = m;
700 } else if (SHR32(sum[m+1],1) > sum[m] && mdct_weight_shift < 2)
701 {
702 mdct_weight_shift=1;
703 mdct_weight_pos = m;
704 }
705 m++;
706 } while (m<st->mode->nbShortMdcts-1);
707#else
708 do {
709 if (sum[m+1] > 8*sum[m])
710 {
711 mdct_weight_shift=2;
712 mdct_weight_pos = m;
713 } else if (sum[m+1] > 2*sum[m] && mdct_weight_shift < 2)
714 {
715 mdct_weight_shift=1;
716 mdct_weight_pos = m;
717 }
718 m++;
719 } while (m<st->mode->nbShortMdcts-1);
720#endif
721 if (mdct_weight_shift)
722 {
Jean-Marc Valinbf2398b2009-10-15 07:28:19 -0400723 mdct_shape(st->mode, X, mdct_weight_pos+1, st->mode->nbShortMdcts, N, st->mode->nbShortMdcts, mdct_weight_shift, C);
724 renormalise_bands(st->mode, X, C);
Jean-Marc Valin88619552009-10-04 21:35:36 -0400725 }
726 }
727
Jean-Marc Valin4c77ea92009-09-14 22:50:41 -0400728
Jean-Marc Valin18a3b792009-05-01 19:58:55 -0400729 encode_flags(&enc, intra_ener, has_pitch, shortBlocks, has_fold);
Jean-Marc Valin05ed03e2009-04-29 07:44:13 -0400730 if (has_pitch)
731 {
Gregory Maxwellabe40f02008-12-13 01:31:32 -0500732 ec_enc_uint(&enc, pitch_index, MAX_PERIOD-(2*N-2*N4));
Jean-Marc Valin4c77ea92009-09-14 22:50:41 -0400733 ec_enc_uint(&enc, gain_id, 16);
Jean-Marc Valin96870d92007-12-05 21:14:22 +1100734 }
Jean-Marc Valin05ed03e2009-04-29 07:44:13 -0400735 if (shortBlocks)
736 {
Jean-Marc Valin05ed03e2009-04-29 07:44:13 -0400737 if (transient_shift)
Jean-Marc Valinaa936252009-05-29 22:14:20 -0400738 {
Jean-Marc Valine6108642009-08-01 23:05:47 +0200739 ec_enc_uint(&enc, transient_shift, 4);
Jean-Marc Valin05ed03e2009-04-29 07:44:13 -0400740 ec_enc_uint(&enc, transient_time, N+st->overlap);
Jean-Marc Valinaa936252009-05-29 22:14:20 -0400741 } else {
Jean-Marc Valine6108642009-08-01 23:05:47 +0200742 ec_enc_uint(&enc, mdct_weight_shift, 4);
Jean-Marc Valinaa936252009-05-29 22:14:20 -0400743 if (mdct_weight_shift && st->mode->nbShortMdcts!=2)
744 ec_enc_uint(&enc, mdct_weight_pos, st->mode->nbShortMdcts-1);
745 }
Jean-Marc Valin05ed03e2009-04-29 07:44:13 -0400746 }
Jean-Marc Valinc890b582008-08-01 22:26:49 -0400747
Jean-Marc Valin6775de32008-08-02 08:14:42 -0400748 ALLOC(fine_quant, st->mode->nbEBands, int);
Jean-Marc Valin8dff9232008-08-13 22:07:20 -0400749 ALLOC(pulses, st->mode->nbEBands, int);
Jean-Marc Valin37ab9c62008-11-08 09:14:38 -0500750
751 /* Bit allocation */
Jean-Marc Valinc890b582008-08-01 22:26:49 -0400752 ALLOC(error, C*st->mode->nbEBands, celt_word16_t);
Jean-Marc Valinbf2398b2009-10-15 07:28:19 -0400753 coarse_needed = quant_coarse_energy(st->mode, bandLogE, st->oldBandE, nbCompressedBytes*8/3, intra_ener, st->mode->prob, error, &enc, C);
Gregory Maxwell888d8ce2009-05-21 04:21:53 -0400754 coarse_needed = ((coarse_needed*3-1)>>3)+1;
755
756 /* Variable bitrate */
757 if (st->VBR_rate>0)
758 {
759 /* The target rate in 16th bits per frame */
760 int target=st->VBR_rate;
Jean-Marc Valin6775de32008-08-02 08:14:42 -0400761
Jean-Marc Valin56522ad2009-06-05 17:17:25 -0400762 /* Shortblocks get a large boost in bitrate, but since they
763 are uncommon long blocks are not greatly effected */
Gregory Maxwell888d8ce2009-05-21 04:21:53 -0400764 if (shortBlocks)
765 target*=2;
766 else if (st->mode->nbShortMdcts > 1)
767 target-=(target+14)/28;
768
Jean-Marc Valin56522ad2009-06-05 17:17:25 -0400769 /* The average energy is removed from the target and the actual
770 energy added*/
Jean-Marc Valin91f07dc2009-07-25 20:42:24 -0400771 target=target-588+ec_enc_tell(&enc, BITRES);
Gregory Maxwell888d8ce2009-05-21 04:21:53 -0400772
773 /* In VBR mode the frame size must not be reduced so much that it would result in the coarse energy busting its budget */
774 target=IMAX(coarse_needed,(target+64)/128);
775 nbCompressedBytes=IMIN(nbCompressedBytes,target);
Jean-Marc Valine6108642009-08-01 23:05:47 +0200776 ec_byte_shrink(&buf, nbCompressedBytes);
Gregory Maxwell888d8ce2009-05-21 04:21:53 -0400777 }
778
Jean-Marc Valin6775de32008-08-02 08:14:42 -0400779 ALLOC(offsets, st->mode->nbEBands, int);
Jean-Marc Valin52cb5fb2009-06-10 08:08:55 -0400780 ALLOC(fine_priority, st->mode->nbEBands, int);
Jean-Marc Valincb7a2a32008-02-11 16:44:48 +1100781
Jean-Marc Valin6775de32008-08-02 08:14:42 -0400782 for (i=0;i<st->mode->nbEBands;i++)
783 offsets[i] = 0;
Jean-Marc Valin8679a802008-10-18 07:44:35 -0400784 bits = nbCompressedBytes*8 - ec_enc_tell(&enc, 0) - 1;
Jean-Marc Valinbf2398b2009-10-15 07:28:19 -0400785 compute_allocation(st->mode, offsets, bits, pulses, fine_quant, fine_priority, C);
Jean-Marc Valin37ab9c62008-11-08 09:14:38 -0500786
Jean-Marc Valinbf2398b2009-10-15 07:28:19 -0400787 quant_fine_energy(st->mode, bandE, st->oldBandE, error, fine_quant, &enc, C);
Jean-Marc Valin6775de32008-08-02 08:14:42 -0400788
Jean-Marc Valin8ebd3452007-11-29 20:17:32 +1100789 /* Residual quantisation */
Jean-Marc Valinca53b7c2009-03-26 20:23:14 -0400790 if (C==1)
Jean-Marc Valina9947c42009-10-08 23:10:45 -0400791 quant_bands(st->mode, X, bandE, pulses, shortBlocks, has_fold, nbCompressedBytes*8, 1, &enc);
Jean-Marc Valin73532032009-06-02 20:07:25 -0400792#ifndef DISABLE_STEREO
Jean-Marc Valinca53b7c2009-03-26 20:23:14 -0400793 else
Jean-Marc Valind5e54362009-09-30 20:50:41 -0400794 quant_bands_stereo(st->mode, X, bandE, pulses, shortBlocks, has_fold, nbCompressedBytes*8, &enc);
Jean-Marc Valin73532032009-06-02 20:07:25 -0400795#endif
Jean-Marc Valin39710532009-06-09 00:10:32 -0400796
Jean-Marc Valinbf2398b2009-10-15 07:28:19 -0400797 quant_energy_finalise(st->mode, bandE, st->oldBandE, error, fine_quant, fine_priority, nbCompressedBytes*8-ec_enc_tell(&enc, 0), &enc, C);
Jean-Marc Valin39710532009-06-09 00:10:32 -0400798
Jean-Marc Valin37ab9c62008-11-08 09:14:38 -0500799 /* Re-synthesis of the coded audio if required */
Gregory Maxwell98046ca2008-12-13 20:42:03 -0500800 if (st->pitch_available>0 || optional_synthesis!=NULL)
Jean-Marc Valin18ddc022008-02-22 14:24:50 +1100801 {
Gregory Maxwell98046ca2008-12-13 20:42:03 -0500802 if (st->pitch_available>0 && st->pitch_available<MAX_PERIOD)
803 st->pitch_available+=st->frame_size;
804
Jean-Marc Valinaa936252009-05-29 22:14:20 -0400805 if (mdct_weight_shift)
806 {
Jean-Marc Valinbf2398b2009-10-15 07:28:19 -0400807 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 -0400808 }
Jean-Marc Valin88619552009-10-04 21:35:36 -0400809
810 /* Synthesis */
Jean-Marc Valinbf2398b2009-10-15 07:28:19 -0400811 denormalise_bands(st->mode, X, freq, bandE, C);
Jean-Marc Valin88619552009-10-04 21:35:36 -0400812
813 CELT_MOVE(st->out_mem, st->out_mem+C*N, C*(MAX_PERIOD+st->overlap-N));
814
Jean-Marc Valin4c77ea92009-09-14 22:50:41 -0400815 if (has_pitch)
Jean-Marc Valinbf2398b2009-10-15 07:28:19 -0400816 apply_pitch(st->mode, freq, pitch_freq, gain_id, 0, C);
Jean-Marc Valin4c77ea92009-09-14 22:50:41 -0400817
Jean-Marc Valinbf2398b2009-10-15 07:28:19 -0400818 compute_inv_mdcts(st->mode, shortBlocks, freq, transient_time, transient_shift, st->out_mem, C);
Jean-Marc Valine12017e2009-10-03 13:57:31 -0400819
Jean-Marc Valin56522ad2009-06-05 17:17:25 -0400820 /* De-emphasis and put everything back at the right place
821 in the synthesis history */
Gregory Maxwell82595312008-09-30 18:20:14 -0400822 if (optional_synthesis != NULL) {
Jean-Marc Valine12017e2009-10-03 13:57:31 -0400823 deemphasis(st->out_mem, optional_synthesis, N, C, preemph, st->preemph_memD);
824
Jean-Marc Valin6f7e83d2007-12-01 00:36:41 +1100825 }
Jean-Marc Valind9b95652008-08-31 23:34:47 -0400826 }
Gregory Maxwell54547f12009-02-16 18:56:44 -0500827
Jean-Marc Valin8679a802008-10-18 07:44:35 -0400828 ec_enc_done(&enc);
Jean-Marc Valinc871c8d2009-06-09 00:57:00 -0400829
Jean-Marc Valin8600f692008-02-29 15:14:12 +1100830 RESTORE_STACK;
Jean-Marc Valina76a0b22008-01-17 22:43:05 +1100831 return nbCompressedBytes;
Jean-Marc Valin8ebd3452007-11-29 20:17:32 +1100832}
833
Gregory Maxwell5f2a74b2008-08-11 23:50:07 -0400834#ifdef FIXED_POINT
835#ifndef DISABLE_FLOAT_API
Gregory Maxwell82595312008-09-30 18:20:14 -0400836int celt_encode_float(CELTEncoder * restrict st, const float * pcm, float * optional_synthesis, unsigned char *compressed, int nbCompressedBytes)
Gregory Maxwell5f2a74b2008-08-11 23:50:07 -0400837{
Gregory Maxwell17169992009-06-04 15:15:34 -0400838 int j, ret, C, N;
Jean-Marc Valin30f7f812009-10-17 14:35:13 -0400839 VARDECL(celt_int16, in);
Jean-Marc Valincb8780c2009-07-20 23:40:35 -0400840 SAVE_STACK;
Gregory Maxwell17169992009-06-04 15:15:34 -0400841
842 if (check_encoder(st) != CELT_OK)
843 return CELT_INVALID_STATE;
844
845 if (check_mode(st->mode) != CELT_OK)
846 return CELT_INVALID_MODE;
847
Gregory Maxwell0719f6f2009-07-09 17:07:24 -0400848 if (pcm==NULL)
849 return CELT_BAD_ARG;
850
Jean-Marc Valin80ed1472009-10-15 21:45:32 -0400851 C = CHANNELS(st->channels);
Gregory Maxwell17169992009-06-04 15:15:34 -0400852 N = st->block_size;
Jean-Marc Valin30f7f812009-10-17 14:35:13 -0400853 ALLOC(in, C*N, celt_int16);
Gregory Maxwell5f2a74b2008-08-11 23:50:07 -0400854
855 for (j=0;j<C*N;j++)
856 in[j] = FLOAT2INT16(pcm[j]);
857
Gregory Maxwell82595312008-09-30 18:20:14 -0400858 if (optional_synthesis != NULL) {
859 ret=celt_encode(st,in,in,compressed,nbCompressedBytes);
Gregory Maxwellb0a73a02008-12-12 16:54:25 -0500860 for (j=0;j<C*N;j++)
Gregory Maxwell82595312008-09-30 18:20:14 -0400861 optional_synthesis[j]=in[j]*(1/32768.);
862 } else {
863 ret=celt_encode(st,in,NULL,compressed,nbCompressedBytes);
864 }
Wessel Lubberhuizen33ba6cc2008-10-03 07:09:29 -0400865 RESTORE_STACK;
Gregory Maxwell5f2a74b2008-08-11 23:50:07 -0400866 return ret;
867
868}
869#endif /*DISABLE_FLOAT_API*/
870#else
Jean-Marc Valin30f7f812009-10-17 14:35:13 -0400871int 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 -0400872{
Gregory Maxwell17169992009-06-04 15:15:34 -0400873 int j, ret, C, N;
Gregory Maxwell5f2a74b2008-08-11 23:50:07 -0400874 VARDECL(celt_sig_t, in);
Jean-Marc Valincb8780c2009-07-20 23:40:35 -0400875 SAVE_STACK;
Gregory Maxwell17169992009-06-04 15:15:34 -0400876
877 if (check_encoder(st) != CELT_OK)
878 return CELT_INVALID_STATE;
879
880 if (check_mode(st->mode) != CELT_OK)
881 return CELT_INVALID_MODE;
882
Gregory Maxwell0719f6f2009-07-09 17:07:24 -0400883 if (pcm==NULL)
884 return CELT_BAD_ARG;
885
Jean-Marc Valin80ed1472009-10-15 21:45:32 -0400886 C=CHANNELS(st->channels);
Gregory Maxwell17169992009-06-04 15:15:34 -0400887 N=st->block_size;
Gregory Maxwell5f2a74b2008-08-11 23:50:07 -0400888 ALLOC(in, C*N, celt_sig_t);
889 for (j=0;j<C*N;j++) {
890 in[j] = SCALEOUT(pcm[j]);
891 }
Gregory Maxwell5f2a74b2008-08-11 23:50:07 -0400892
Gregory Maxwell82595312008-09-30 18:20:14 -0400893 if (optional_synthesis != NULL) {
894 ret = celt_encode_float(st,in,in,compressed,nbCompressedBytes);
895 for (j=0;j<C*N;j++)
896 optional_synthesis[j] = FLOAT2INT16(in[j]);
897 } else {
898 ret = celt_encode_float(st,in,NULL,compressed,nbCompressedBytes);
899 }
Wessel Lubberhuizen33ba6cc2008-10-03 07:09:29 -0400900 RESTORE_STACK;
Gregory Maxwell5f2a74b2008-08-11 23:50:07 -0400901 return ret;
902}
903#endif
Jean-Marc Valin6e9058a2007-12-07 14:59:06 +1100904
Jean-Marc Valinb6f90612008-10-05 22:39:13 -0400905int celt_encoder_ctl(CELTEncoder * restrict st, int request, ...)
Jean-Marc Valinc18fb1d2008-09-30 07:36:54 -0400906{
Jean-Marc Valinb6f90612008-10-05 22:39:13 -0400907 va_list ap;
Gregory Maxwell17169992009-06-04 15:15:34 -0400908
909 if (check_encoder(st) != CELT_OK)
910 return CELT_INVALID_STATE;
911
Jean-Marc Valinb6f90612008-10-05 22:39:13 -0400912 va_start(ap, request);
Gregory Maxwell17169992009-06-04 15:15:34 -0400913 if ((request!=CELT_GET_MODE_REQUEST) && (check_mode(st->mode) != CELT_OK))
914 goto bad_mode;
Jean-Marc Valinc18fb1d2008-09-30 07:36:54 -0400915 switch (request)
916 {
Gregory Maxwellf3b44ef2009-06-03 13:37:45 -0400917 case CELT_GET_MODE_REQUEST:
918 {
919 const CELTMode ** value = va_arg(ap, const CELTMode**);
920 if (value==0)
921 goto bad_arg;
922 *value=st->mode;
923 }
924 break;
Jean-Marc Valinb6f90612008-10-05 22:39:13 -0400925 case CELT_SET_COMPLEXITY_REQUEST:
Jean-Marc Valinc18fb1d2008-09-30 07:36:54 -0400926 {
Jean-Marc Valin30f7f812009-10-17 14:35:13 -0400927 int value = va_arg(ap, celt_int32);
Jean-Marc Valinb6f90612008-10-05 22:39:13 -0400928 if (value<0 || value>10)
929 goto bad_arg;
Gregory Maxwell98046ca2008-12-13 20:42:03 -0500930 if (value<=2) {
931 st->pitch_enabled = 0;
932 st->pitch_available = 0;
933 } else {
934 st->pitch_enabled = 1;
935 if (st->pitch_available<1)
936 st->pitch_available = 1;
937 }
938 }
939 break;
Gregory Maxwell2dd3d322009-06-05 14:05:51 -0400940 case CELT_SET_PREDICTION_REQUEST:
Gregory Maxwell98046ca2008-12-13 20:42:03 -0500941 {
Jean-Marc Valin30f7f812009-10-17 14:35:13 -0400942 int value = va_arg(ap, celt_int32);
Gregory Maxwell2dd3d322009-06-05 14:05:51 -0400943 if (value<0 || value>2)
Gregory Maxwell98046ca2008-12-13 20:42:03 -0500944 goto bad_arg;
945 if (value==0)
Gregory Maxwell2dd3d322009-06-05 14:05:51 -0400946 {
947 st->force_intra = 1;
948 st->pitch_permitted = 0;
Gregory Maxwella80958b2009-06-29 12:48:57 -0400949 } else if (value==1) {
Gregory Maxwell2dd3d322009-06-05 14:05:51 -0400950 st->force_intra = 0;
951 st->pitch_permitted = 0;
952 } else {
953 st->force_intra = 0;
954 st->pitch_permitted = 1;
955 }
Jean-Marc Valinc18fb1d2008-09-30 07:36:54 -0400956 }
957 break;
Gregory Maxwell888d8ce2009-05-21 04:21:53 -0400958 case CELT_SET_VBR_RATE_REQUEST:
959 {
Jean-Marc Valin30f7f812009-10-17 14:35:13 -0400960 celt_int32 value = va_arg(ap, celt_int32);
Gregory Maxwell888d8ce2009-05-21 04:21:53 -0400961 if (value<0)
962 goto bad_arg;
963 if (value>3072000)
964 value = 3072000;
965 st->VBR_rate = ((st->mode->Fs<<3)+(st->block_size>>1))/st->block_size;
966 st->VBR_rate = ((value<<7)+(st->VBR_rate>>1))/st->VBR_rate;
967 }
968 break;
John Ridges454d1d02009-05-21 22:38:39 -0400969 case CELT_RESET_STATE:
970 {
971 const CELTMode *mode = st->mode;
Jean-Marc Valin80ed1472009-10-15 21:45:32 -0400972 int C = st->channels;
John Ridges454d1d02009-05-21 22:38:39 -0400973
974 if (st->pitch_available > 0) st->pitch_available = 1;
975
976 CELT_MEMSET(st->in_mem, 0, st->overlap*C);
977 CELT_MEMSET(st->out_mem, 0, (MAX_PERIOD+st->overlap)*C);
978
979 CELT_MEMSET(st->oldBandE, 0, C*mode->nbEBands);
980
981 CELT_MEMSET(st->preemph_memE, 0, C);
982 CELT_MEMSET(st->preemph_memD, 0, C);
983 st->delayedIntra = 1;
984 }
985 break;
Jean-Marc Valinc18fb1d2008-09-30 07:36:54 -0400986 default:
Jean-Marc Valinb6f90612008-10-05 22:39:13 -0400987 goto bad_request;
Jean-Marc Valinc18fb1d2008-09-30 07:36:54 -0400988 }
Jean-Marc Valinb6f90612008-10-05 22:39:13 -0400989 va_end(ap);
Jean-Marc Valinc18fb1d2008-09-30 07:36:54 -0400990 return CELT_OK;
Gregory Maxwell17169992009-06-04 15:15:34 -0400991bad_mode:
992 va_end(ap);
993 return CELT_INVALID_MODE;
Jean-Marc Valinb6f90612008-10-05 22:39:13 -0400994bad_arg:
995 va_end(ap);
996 return CELT_BAD_ARG;
997bad_request:
998 va_end(ap);
999 return CELT_UNIMPLEMENTED;
Jean-Marc Valinc18fb1d2008-09-30 07:36:54 -04001000}
1001
Jean-Marc Valin56522ad2009-06-05 17:17:25 -04001002/**********************************************************************/
1003/* */
1004/* DECODER */
1005/* */
1006/**********************************************************************/
Jean-Marc Valineafbdd52009-04-27 19:35:09 -04001007#ifdef NEW_PLC
1008#define DECODE_BUFFER_SIZE 2048
1009#else
1010#define DECODE_BUFFER_SIZE MAX_PERIOD
1011#endif
Jean-Marc Valin269d40a2007-12-07 11:29:45 +11001012
Gregory Maxwell17169992009-06-04 15:15:34 -04001013#define DECODERVALID 0x4c434454
1014#define DECODERPARTIAL 0x5444434c
1015#define DECODERFREED 0x4c004400
1016
Jean-Marc Valin276de722008-02-20 17:45:51 +11001017/** Decoder state
1018 @brief Decoder state
1019 */
Jean-Marc Valin269d40a2007-12-07 11:29:45 +11001020struct CELTDecoder {
Jean-Marc Valin30f7f812009-10-17 14:35:13 -04001021 celt_uint32 marker;
Jean-Marc Valin269d40a2007-12-07 11:29:45 +11001022 const CELTMode *mode;
1023 int frame_size;
1024 int block_size;
Jean-Marc Valina5431bf2008-01-03 20:53:01 +11001025 int overlap;
Jean-Marc Valin80ed1472009-10-15 21:45:32 -04001026 int channels;
Jean-Marc Valina5431bf2008-01-03 20:53:01 +11001027
Jean-Marc Valin269d40a2007-12-07 11:29:45 +11001028 ec_byte_buffer buf;
1029 ec_enc enc;
1030
Jean-Marc Valin65fb92e2008-04-19 22:24:53 +10001031 celt_sig_t * restrict preemph_memD;
Jean-Marc Valin81b38c22008-02-29 21:08:49 +11001032
Jean-Marc Valin18ddc022008-02-22 14:24:50 +11001033 celt_sig_t *out_mem;
Jean-Marc Valineafbdd52009-04-27 19:35:09 -04001034 celt_sig_t *decode_mem;
Jean-Marc Valin269d40a2007-12-07 11:29:45 +11001035
Jean-Marc Valin5d561832008-02-27 11:59:05 +11001036 celt_word16_t *oldBandE;
Jean-Marc Valinfb83fb42007-12-08 00:56:04 +11001037
1038 int last_pitch_index;
Jean-Marc Valin0f0da992009-08-12 21:34:01 -04001039 int loss_count;
Jean-Marc Valin269d40a2007-12-07 11:29:45 +11001040};
1041
Gregory Maxwell17169992009-06-04 15:15:34 -04001042int check_decoder(const CELTDecoder *st)
1043{
1044 if (st==NULL)
1045 {
1046 celt_warning("NULL passed a decoder structure");
1047 return CELT_INVALID_STATE;
1048 }
1049 if (st->marker == DECODERVALID)
1050 return CELT_OK;
1051 if (st->marker == DECODERFREED)
1052 celt_warning("Referencing a decoder that has already been freed");
1053 else
1054 celt_warning("This is not a valid CELT decoder structure");
1055 return CELT_INVALID_STATE;
1056}
1057
Jean-Marc Valin80ed1472009-10-15 21:45:32 -04001058CELTDecoder *celt_decoder_create(const CELTMode *mode, int channels, int *error)
Jean-Marc Valin269d40a2007-12-07 11:29:45 +11001059{
Jean-Marc Valinb886ddc2008-03-25 14:38:55 +11001060 int N, C;
Jean-Marc Valin0bb05bc2008-02-20 13:43:40 +11001061 CELTDecoder *st;
Jean-Marc Valin44ffd5a2008-02-22 00:39:25 +11001062
1063 if (check_mode(mode) != CELT_OK)
Jean-Marc Valinece94a02009-10-16 07:30:14 -04001064 {
1065 if (error)
1066 *error = CELT_INVALID_MODE;
Jean-Marc Valin44ffd5a2008-02-22 00:39:25 +11001067 return NULL;
Jean-Marc Valinece94a02009-10-16 07:30:14 -04001068 }
Jean-Marc Valin80ed1472009-10-15 21:45:32 -04001069 if (channels < 0 || channels > 2)
1070 {
1071 celt_warning("Only mono and stereo supported");
1072 if (error)
1073 *error = CELT_BAD_ARG;
1074 return NULL;
1075 }
Jean-Marc Valin44ffd5a2008-02-22 00:39:25 +11001076
Jean-Marc Valin269d40a2007-12-07 11:29:45 +11001077 N = mode->mdctSize;
Jean-Marc Valin80ed1472009-10-15 21:45:32 -04001078 C = CHANNELS(channels);
Jean-Marc Valin0bb05bc2008-02-20 13:43:40 +11001079 st = celt_alloc(sizeof(CELTDecoder));
Gregory Maxwell17169992009-06-04 15:15:34 -04001080
1081 if (st==NULL)
Jean-Marc Valinece94a02009-10-16 07:30:14 -04001082 {
1083 if (error)
1084 *error = CELT_ALLOC_FAIL;
Gregory Maxwell17169992009-06-04 15:15:34 -04001085 return NULL;
Jean-Marc Valinece94a02009-10-16 07:30:14 -04001086 }
1087
Gregory Maxwell17169992009-06-04 15:15:34 -04001088 st->marker = DECODERPARTIAL;
Jean-Marc Valin269d40a2007-12-07 11:29:45 +11001089 st->mode = mode;
Jean-Marc Valinb886ddc2008-03-25 14:38:55 +11001090 st->frame_size = N;
Jean-Marc Valin269d40a2007-12-07 11:29:45 +11001091 st->block_size = N;
Jean-Marc Valina5431bf2008-01-03 20:53:01 +11001092 st->overlap = mode->overlap;
Jean-Marc Valin80ed1472009-10-15 21:45:32 -04001093 st->channels = channels;
Jean-Marc Valina5431bf2008-01-03 20:53:01 +11001094
Jean-Marc Valineafbdd52009-04-27 19:35:09 -04001095 st->decode_mem = celt_alloc((DECODE_BUFFER_SIZE+st->overlap)*C*sizeof(celt_sig_t));
1096 st->out_mem = st->decode_mem+DECODE_BUFFER_SIZE-MAX_PERIOD;
Jean-Marc Valin269d40a2007-12-07 11:29:45 +11001097
Jean-Marc Valin5d561832008-02-27 11:59:05 +11001098 st->oldBandE = (celt_word16_t*)celt_alloc(C*mode->nbEBands*sizeof(celt_word16_t));
Gregory Maxwell17169992009-06-04 15:15:34 -04001099
Gregory Maxwell5f2a74b2008-08-11 23:50:07 -04001100 st->preemph_memD = (celt_sig_t*)celt_alloc(C*sizeof(celt_sig_t));
Jean-Marc Valinffa13472007-12-10 16:54:17 +11001101
Jean-Marc Valin0f0da992009-08-12 21:34:01 -04001102 st->loss_count = 0;
Gregory Maxwell17169992009-06-04 15:15:34 -04001103
1104 if ((st->decode_mem!=NULL) && (st->out_mem!=NULL) && (st->oldBandE!=NULL) &&
1105 (st->preemph_memD!=NULL))
1106 {
Jean-Marc Valinece94a02009-10-16 07:30:14 -04001107 if (error)
1108 *error = CELT_OK;
Gregory Maxwell17169992009-06-04 15:15:34 -04001109 st->marker = DECODERVALID;
1110 return st;
1111 }
1112 /* If the setup fails for some reason deallocate it. */
1113 celt_decoder_destroy(st);
Jean-Marc Valinece94a02009-10-16 07:30:14 -04001114 if (error)
1115 *error = CELT_ALLOC_FAIL;
Gregory Maxwell17169992009-06-04 15:15:34 -04001116 return NULL;
Jean-Marc Valin269d40a2007-12-07 11:29:45 +11001117}
1118
Peter Kirk19f9dc92008-06-06 14:38:38 +02001119void celt_decoder_destroy(CELTDecoder *st)
Jean-Marc Valin269d40a2007-12-07 11:29:45 +11001120{
1121 if (st == NULL)
1122 {
Gregory Maxwell17169992009-06-04 15:15:34 -04001123 celt_warning("NULL passed to celt_decoder_destroy");
Jean-Marc Valin269d40a2007-12-07 11:29:45 +11001124 return;
1125 }
Gregory Maxwell17169992009-06-04 15:15:34 -04001126
1127 if (st->marker == DECODERFREED)
1128 {
1129 celt_warning("Freeing a decoder which has already been freed");
Jean-Marc Valin44ffd5a2008-02-22 00:39:25 +11001130 return;
Gregory Maxwell17169992009-06-04 15:15:34 -04001131 }
1132
1133 if (st->marker != DECODERVALID && st->marker != DECODERPARTIAL)
1134 {
1135 celt_warning("This is not a valid CELT decoder structure");
1136 return;
1137 }
1138
1139 /*Check_mode is non-fatal here because we can still free
1140 the encoder memory even if the mode is bad, although calling
1141 the free functions in this order is a violation of the API.*/
1142 check_mode(st->mode);
1143
Jean-Marc Valineafbdd52009-04-27 19:35:09 -04001144 celt_free(st->decode_mem);
Jean-Marc Valin269d40a2007-12-07 11:29:45 +11001145 celt_free(st->oldBandE);
Jean-Marc Valin7351e282008-02-08 15:09:45 +11001146 celt_free(st->preemph_memD);
Gregory Maxwell17169992009-06-04 15:15:34 -04001147
1148 st->marker = DECODERFREED;
1149
Jean-Marc Valin269d40a2007-12-07 11:29:45 +11001150 celt_free(st);
1151}
1152
Jean-Marc Valin56522ad2009-06-05 17:17:25 -04001153/** Handles lost packets by just copying past data with the same
1154 offset as the last
Jean-Marc Valind501f612008-02-21 12:16:57 +11001155 pitch period */
Jean-Marc Valineafbdd52009-04-27 19:35:09 -04001156#ifdef NEW_PLC
1157#include "plc.c"
1158#else
Gregory Maxwell5f2a74b2008-08-11 23:50:07 -04001159static void celt_decode_lost(CELTDecoder * restrict st, celt_word16_t * restrict pcm)
Jean-Marc Valinfb83fb42007-12-08 00:56:04 +11001160{
Jean-Marc Valin05e56c42008-04-10 09:13:05 +10001161 int c, N;
Jean-Marc Valin0bb05bc2008-02-20 13:43:40 +11001162 int pitch_index;
Jean-Marc Valin0f0da992009-08-12 21:34:01 -04001163 celt_word16_t fade = Q15ONE;
Jean-Marc Valin24c9cda2008-05-02 10:34:07 +10001164 int i, len;
Jean-Marc Valin31b79d12008-03-12 17:17:23 +11001165 VARDECL(celt_sig_t, freq);
Jean-Marc Valin80ed1472009-10-15 21:45:32 -04001166 const int C = CHANNELS(st->channels);
Jean-Marc Valin24c9cda2008-05-02 10:34:07 +10001167 int offset;
Jean-Marc Valin8600f692008-02-29 15:14:12 +11001168 SAVE_STACK;
Jean-Marc Valinfb83fb42007-12-08 00:56:04 +11001169 N = st->block_size;
Jean-Marc Valin56522ad2009-06-05 17:17:25 -04001170 ALLOC(freq,C*N, celt_sig_t); /**< Interleaved signal MDCTs */
Jean-Marc Valinfb83fb42007-12-08 00:56:04 +11001171
Jean-Marc Valin24c9cda2008-05-02 10:34:07 +10001172 len = N+st->mode->overlap;
Jean-Marc Valinfb83fb42007-12-08 00:56:04 +11001173
Jean-Marc Valin0f0da992009-08-12 21:34:01 -04001174 if (st->loss_count == 0)
1175 {
Jean-Marc Valinbf2398b2009-10-15 07:28:19 -04001176 find_spectral_pitch(st->mode, st->mode->fft, &st->mode->psy, st->out_mem+MAX_PERIOD-len, st->out_mem, st->mode->window, NULL, len, MAX_PERIOD-len-100, &pitch_index, C);
Jean-Marc Valin0f0da992009-08-12 21:34:01 -04001177 pitch_index = MAX_PERIOD-len-pitch_index;
1178 st->last_pitch_index = pitch_index;
1179 } else {
1180 pitch_index = st->last_pitch_index;
1181 if (st->loss_count < 5)
1182 fade = QCONST16(.8f,15);
1183 else
1184 fade = 0;
1185 }
Jean-Marc Valinfb83fb42007-12-08 00:56:04 +11001186
Jean-Marc Valin24c9cda2008-05-02 10:34:07 +10001187 offset = MAX_PERIOD-pitch_index;
1188 while (offset+len >= MAX_PERIOD)
1189 offset -= pitch_index;
Jean-Marc Valinbf2398b2009-10-15 07:28:19 -04001190 compute_mdcts(st->mode, 0, st->out_mem+offset*C, freq, C);
Jean-Marc Valin08a82ff2009-06-14 14:05:19 -04001191 for (i=0;i<C*N;i++)
Jean-Marc Valin0f0da992009-08-12 21:34:01 -04001192 freq[i] = ADD32(VERY_SMALL, MULT16_32_Q15(fade,freq[i]));
1193
Jean-Marc Valin24c9cda2008-05-02 10:34:07 +10001194 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 +11001195 /* Compute inverse MDCTs */
Jean-Marc Valinbf2398b2009-10-15 07:28:19 -04001196 compute_inv_mdcts(st->mode, 0, freq, -1, 0, st->out_mem, C);
Jean-Marc Valin1677aa92007-12-08 01:13:34 +11001197
Jean-Marc Valinffa13472007-12-10 16:54:17 +11001198 for (c=0;c<C;c++)
Jean-Marc Valinfb83fb42007-12-08 00:56:04 +11001199 {
Jean-Marc Valinb886ddc2008-03-25 14:38:55 +11001200 int j;
1201 for (j=0;j<N;j++)
Jean-Marc Valinfb83fb42007-12-08 00:56:04 +11001202 {
Jean-Marc Valin1dab60c2008-09-16 13:29:37 -04001203 celt_sig_t tmp = MAC16_32_Q15(st->out_mem[C*(MAX_PERIOD-N)+C*j+c],
1204 preemph,st->preemph_memD[c]);
Jean-Marc Valinb886ddc2008-03-25 14:38:55 +11001205 st->preemph_memD[c] = tmp;
Gregory Maxwell5f2a74b2008-08-11 23:50:07 -04001206 pcm[C*j+c] = SCALEOUT(SIG2WORD16(tmp));
Jean-Marc Valinfb83fb42007-12-08 00:56:04 +11001207 }
1208 }
Jean-Marc Valin0f0da992009-08-12 21:34:01 -04001209
1210 st->loss_count++;
1211
Jean-Marc Valin8600f692008-02-29 15:14:12 +11001212 RESTORE_STACK;
Jean-Marc Valinfb83fb42007-12-08 00:56:04 +11001213}
Jean-Marc Valineafbdd52009-04-27 19:35:09 -04001214#endif
Jean-Marc Valinfb83fb42007-12-08 00:56:04 +11001215
Gregory Maxwell5f2a74b2008-08-11 23:50:07 -04001216#ifdef FIXED_POINT
Jean-Marc Valin30f7f812009-10-17 14:35:13 -04001217int celt_decode(CELTDecoder * restrict st, const unsigned char *data, int len, celt_int16 * restrict pcm)
Jean-Marc Valin269d40a2007-12-07 11:29:45 +11001218{
Gregory Maxwell5f2a74b2008-08-11 23:50:07 -04001219#else
Jean-Marc Valin6db6cbd2009-04-11 22:01:20 -04001220int celt_decode_float(CELTDecoder * restrict st, const unsigned char *data, int len, celt_sig_t * restrict pcm)
Gregory Maxwell5f2a74b2008-08-11 23:50:07 -04001221{
1222#endif
Jean-Marc Valin88619552009-10-04 21:35:36 -04001223 int i, N, N4;
Jean-Marc Valinc9943942008-08-30 00:55:07 -04001224 int has_pitch, has_fold;
Jean-Marc Valin0bb05bc2008-02-20 13:43:40 +11001225 int pitch_index;
Jean-Marc Valinc890b582008-08-01 22:26:49 -04001226 int bits;
Jean-Marc Valin0bb05bc2008-02-20 13:43:40 +11001227 ec_dec dec;
1228 ec_byte_buffer buf;
Jean-Marc Valin31b79d12008-03-12 17:17:23 +11001229 VARDECL(celt_sig_t, freq);
Jean-Marc Valinab220aa2009-09-15 22:38:40 -04001230 VARDECL(celt_sig_t, pitch_freq);
Jean-Marc Valin31b79d12008-03-12 17:17:23 +11001231 VARDECL(celt_norm_t, X);
Jean-Marc Valin31b79d12008-03-12 17:17:23 +11001232 VARDECL(celt_ener_t, bandE);
Jean-Marc Valin6775de32008-08-02 08:14:42 -04001233 VARDECL(int, fine_quant);
1234 VARDECL(int, pulses);
1235 VARDECL(int, offsets);
Jean-Marc Valin52cb5fb2009-06-10 08:08:55 -04001236 VARDECL(int, fine_priority);
Jean-Marc Valinc890b582008-08-01 22:26:49 -04001237
Jean-Marc Valin9d1decd2008-06-17 13:28:13 +10001238 int shortBlocks;
Jean-Marc Valin05ed03e2009-04-29 07:44:13 -04001239 int intra_ener;
Jean-Marc Valin12b22482008-06-16 14:13:05 +10001240 int transient_time;
Jean-Marc Valin528f4b82008-06-29 03:46:39 +10001241 int transient_shift;
Jean-Marc Valinaa936252009-05-29 22:14:20 -04001242 int mdct_weight_shift=0;
Jean-Marc Valin80ed1472009-10-15 21:45:32 -04001243 const int C = CHANNELS(st->channels);
Jean-Marc Valinaa936252009-05-29 22:14:20 -04001244 int mdct_weight_pos=0;
Jean-Marc Valinab220aa2009-09-15 22:38:40 -04001245 int gain_id=0;
Jean-Marc Valin8600f692008-02-29 15:14:12 +11001246 SAVE_STACK;
Jean-Marc Valin44ffd5a2008-02-22 00:39:25 +11001247
Gregory Maxwell17169992009-06-04 15:15:34 -04001248 if (check_decoder(st) != CELT_OK)
1249 return CELT_INVALID_STATE;
1250
Jean-Marc Valin44ffd5a2008-02-22 00:39:25 +11001251 if (check_mode(st->mode) != CELT_OK)
1252 return CELT_INVALID_MODE;
1253
Gregory Maxwell0719f6f2009-07-09 17:07:24 -04001254 if (pcm==NULL)
1255 return CELT_BAD_ARG;
1256
Jean-Marc Valin269d40a2007-12-07 11:29:45 +11001257 N = st->block_size;
Jean-Marc Valina536f772008-03-22 09:01:50 +11001258 N4 = (N-st->overlap)>>1;
Jean-Marc Valin01417232008-03-03 13:59:55 +11001259
Jean-Marc Valinb886ddc2008-03-25 14:38:55 +11001260 ALLOC(freq, C*N, celt_sig_t); /**< Interleaved signal MDCTs */
Jean-Marc Valin56522ad2009-06-05 17:17:25 -04001261 ALLOC(X, C*N, celt_norm_t); /**< Interleaved normalised MDCTs */
Jean-Marc Valine901fe32008-02-26 14:46:26 +11001262 ALLOC(bandE, st->mode->nbEBands*C, celt_ener_t);
Jean-Marc Valin70c8ffd2007-12-07 14:20:01 +11001263
Jean-Marc Valinfb83fb42007-12-08 00:56:04 +11001264 if (data == NULL)
1265 {
1266 celt_decode_lost(st, pcm);
Jean-Marc Valin8600f692008-02-29 15:14:12 +11001267 RESTORE_STACK;
Jean-Marc Valinfb83fb42007-12-08 00:56:04 +11001268 return 0;
Jean-Marc Valin0f0da992009-08-12 21:34:01 -04001269 } else {
1270 st->loss_count = 0;
Jean-Marc Valinfb83fb42007-12-08 00:56:04 +11001271 }
Gregory Maxwell520eeae2009-02-09 01:33:21 -05001272 if (len<0) {
1273 RESTORE_STACK;
1274 return CELT_BAD_ARG;
1275 }
Jean-Marc Valinfb83fb42007-12-08 00:56:04 +11001276
Jean-Marc Valin05ed03e2009-04-29 07:44:13 -04001277 ec_byte_readinit(&buf,(unsigned char*)data,len);
Jean-Marc Valin70c8ffd2007-12-07 14:20:01 +11001278 ec_dec_init(&dec,&buf);
1279
Jean-Marc Valin05ed03e2009-04-29 07:44:13 -04001280 decode_flags(&dec, &intra_ener, &has_pitch, &shortBlocks, &has_fold);
Gregory Maxwell0527f372008-09-23 19:28:35 -04001281 if (shortBlocks)
1282 {
Jean-Marc Valine6108642009-08-01 23:05:47 +02001283 transient_shift = ec_dec_uint(&dec, 4);
Jean-Marc Valinaa936252009-05-29 22:14:20 -04001284 if (transient_shift == 3)
1285 {
Gregory Maxwell0527f372008-09-23 19:28:35 -04001286 transient_time = ec_dec_uint(&dec, N+st->mode->overlap);
Jean-Marc Valinaa936252009-05-29 22:14:20 -04001287 } else {
1288 mdct_weight_shift = transient_shift;
1289 if (mdct_weight_shift && st->mode->nbShortMdcts>2)
1290 mdct_weight_pos = ec_dec_uint(&dec, st->mode->nbShortMdcts-1);
1291 transient_shift = 0;
Gregory Maxwell0527f372008-09-23 19:28:35 -04001292 transient_time = 0;
Jean-Marc Valinaa936252009-05-29 22:14:20 -04001293 }
Gregory Maxwell0527f372008-09-23 19:28:35 -04001294 } else {
Jean-Marc Valin12b22482008-06-16 14:13:05 +10001295 transient_time = -1;
Jean-Marc Valin528f4b82008-06-29 03:46:39 +10001296 transient_shift = 0;
Jean-Marc Valin12b22482008-06-16 14:13:05 +10001297 }
Jean-Marc Valincb7a2a32008-02-11 16:44:48 +11001298
Jean-Marc Valin7e8a4872008-02-11 16:55:34 +11001299 if (has_pitch)
1300 {
Jean-Marc Valinb886ddc2008-03-25 14:38:55 +11001301 pitch_index = ec_dec_uint(&dec, MAX_PERIOD-(2*N-2*N4));
Jean-Marc Valin4c77ea92009-09-14 22:50:41 -04001302 gain_id = ec_dec_uint(&dec, 16);
Jean-Marc Valin7e8a4872008-02-11 16:55:34 +11001303 } else {
Jean-Marc Valin7e8a4872008-02-11 16:55:34 +11001304 pitch_index = 0;
1305 }
Jean-Marc Valin827f9312008-05-06 23:21:55 +10001306
Jean-Marc Valin6775de32008-08-02 08:14:42 -04001307 ALLOC(fine_quant, st->mode->nbEBands, int);
Jean-Marc Valin827f9312008-05-06 23:21:55 +10001308 /* Get band energies */
Jean-Marc Valinbf2398b2009-10-15 07:28:19 -04001309 unquant_coarse_energy(st->mode, bandE, st->oldBandE, len*8/3, intra_ener, st->mode->prob, &dec, C);
Jean-Marc Valin6775de32008-08-02 08:14:42 -04001310
1311 ALLOC(pulses, st->mode->nbEBands, int);
1312 ALLOC(offsets, st->mode->nbEBands, int);
Jean-Marc Valin52cb5fb2009-06-10 08:08:55 -04001313 ALLOC(fine_priority, st->mode->nbEBands, int);
Jean-Marc Valin6775de32008-08-02 08:14:42 -04001314
1315 for (i=0;i<st->mode->nbEBands;i++)
1316 offsets[i] = 0;
1317
1318 bits = len*8 - ec_dec_tell(&dec, 0) - 1;
Jean-Marc Valinbf2398b2009-10-15 07:28:19 -04001319 compute_allocation(st->mode, offsets, bits, pulses, fine_quant, fine_priority, C);
Jean-Marc Valin6775de32008-08-02 08:14:42 -04001320 /*bits = ec_dec_tell(&dec, 0);
1321 compute_fine_allocation(st->mode, fine_quant, (20*C+len*8/5-(ec_dec_tell(&dec, 0)-bits))/C);*/
1322
Jean-Marc Valinbf2398b2009-10-15 07:28:19 -04001323 unquant_fine_energy(st->mode, bandE, st->oldBandE, fine_quant, &dec, C);
Jean-Marc Valin827f9312008-05-06 23:21:55 +10001324
Jean-Marc Valinab220aa2009-09-15 22:38:40 -04001325 ALLOC(pitch_freq, C*N, celt_sig_t); /**< Interleaved signal MDCTs */
Jean-Marc Valinc9943942008-08-30 00:55:07 -04001326 if (has_pitch)
Jean-Marc Valin269d40a2007-12-07 11:29:45 +11001327 {
Jean-Marc Valinc9943942008-08-30 00:55:07 -04001328 /* Pitch MDCT */
Jean-Marc Valinbf2398b2009-10-15 07:28:19 -04001329 compute_mdcts(st->mode, 0, st->out_mem+pitch_index*C, pitch_freq, C);
Jean-Marc Valin269d40a2007-12-07 11:29:45 +11001330 }
1331
Jean-Marc Valin70c8ffd2007-12-07 14:20:01 +11001332 /* Decode fixed codebook and merge with pitch */
Jean-Marc Valinca53b7c2009-03-26 20:23:14 -04001333 if (C==1)
Jean-Marc Valina9947c42009-10-08 23:10:45 -04001334 quant_bands(st->mode, X, bandE, pulses, shortBlocks, has_fold, len*8, 0, &dec);
Jean-Marc Valin73532032009-06-02 20:07:25 -04001335#ifndef DISABLE_STEREO
Jean-Marc Valinca53b7c2009-03-26 20:23:14 -04001336 else
Jean-Marc Valind5e54362009-09-30 20:50:41 -04001337 unquant_bands_stereo(st->mode, X, bandE, pulses, shortBlocks, has_fold, len*8, &dec);
Jean-Marc Valin73532032009-06-02 20:07:25 -04001338#endif
Jean-Marc Valinbf2398b2009-10-15 07:28:19 -04001339 unquant_energy_finalise(st->mode, bandE, st->oldBandE, fine_quant, fine_priority, len*8-ec_dec_tell(&dec, 0), &dec, C);
Jean-Marc Valin39710532009-06-09 00:10:32 -04001340
Jean-Marc Valin88619552009-10-04 21:35:36 -04001341 if (mdct_weight_shift)
1342 {
Jean-Marc Valinbf2398b2009-10-15 07:28:19 -04001343 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 -04001344 }
1345
Jean-Marc Valina4833ff2008-01-10 15:34:00 +11001346 /* Synthesis */
Jean-Marc Valinbf2398b2009-10-15 07:28:19 -04001347 denormalise_bands(st->mode, X, freq, bandE, C);
Jean-Marc Valina4833ff2008-01-10 15:34:00 +11001348
1349
Jean-Marc Valineafbdd52009-04-27 19:35:09 -04001350 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 -04001351
Jean-Marc Valin4c77ea92009-09-14 22:50:41 -04001352 if (has_pitch)
Jean-Marc Valinbf2398b2009-10-15 07:28:19 -04001353 apply_pitch(st->mode, freq, pitch_freq, gain_id, 0, C);
Jean-Marc Valin4c77ea92009-09-14 22:50:41 -04001354
Jean-Marc Valin269d40a2007-12-07 11:29:45 +11001355 /* Compute inverse MDCTs */
Jean-Marc Valinbf2398b2009-10-15 07:28:19 -04001356 compute_inv_mdcts(st->mode, shortBlocks, freq, transient_time, transient_shift, st->out_mem, C);
Jean-Marc Valinffa13472007-12-10 16:54:17 +11001357
Jean-Marc Valine12017e2009-10-03 13:57:31 -04001358 deemphasis(st->out_mem, pcm, N, C, preemph, st->preemph_memD);
Jean-Marc Valin388f1d62008-01-18 16:28:11 +11001359
Jean-Marc Valin8600f692008-02-29 15:14:12 +11001360 RESTORE_STACK;
Jean-Marc Valinfb83fb42007-12-08 00:56:04 +11001361 return 0;
Jean-Marc Valin269d40a2007-12-07 11:29:45 +11001362}
1363
Gregory Maxwell5f2a74b2008-08-11 23:50:07 -04001364#ifdef FIXED_POINT
1365#ifndef DISABLE_FLOAT_API
Jean-Marc Valin6db6cbd2009-04-11 22:01:20 -04001366int celt_decode_float(CELTDecoder * restrict st, const unsigned char *data, int len, float * restrict pcm)
Gregory Maxwell5f2a74b2008-08-11 23:50:07 -04001367{
Gregory Maxwell17169992009-06-04 15:15:34 -04001368 int j, ret, C, N;
Jean-Marc Valin30f7f812009-10-17 14:35:13 -04001369 VARDECL(celt_int16, out);
Jean-Marc Valincb8780c2009-07-20 23:40:35 -04001370 SAVE_STACK;
Gregory Maxwell17169992009-06-04 15:15:34 -04001371
1372 if (check_decoder(st) != CELT_OK)
1373 return CELT_INVALID_STATE;
1374
1375 if (check_mode(st->mode) != CELT_OK)
1376 return CELT_INVALID_MODE;
1377
Gregory Maxwell0719f6f2009-07-09 17:07:24 -04001378 if (pcm==NULL)
1379 return CELT_BAD_ARG;
1380
Jean-Marc Valin80ed1472009-10-15 21:45:32 -04001381 C = CHANNELS(st->channels);
Gregory Maxwell17169992009-06-04 15:15:34 -04001382 N = st->block_size;
Gregory Maxwell0719f6f2009-07-09 17:07:24 -04001383
Jean-Marc Valin30f7f812009-10-17 14:35:13 -04001384 ALLOC(out, C*N, celt_int16);
Gregory Maxwell5f2a74b2008-08-11 23:50:07 -04001385 ret=celt_decode(st, data, len, out);
Gregory Maxwell5f2a74b2008-08-11 23:50:07 -04001386 for (j=0;j<C*N;j++)
Gregory Maxwell0719f6f2009-07-09 17:07:24 -04001387 pcm[j]=out[j]*(1/32768.);
1388
Wessel Lubberhuizen33ba6cc2008-10-03 07:09:29 -04001389 RESTORE_STACK;
Gregory Maxwell5f2a74b2008-08-11 23:50:07 -04001390 return ret;
1391}
1392#endif /*DISABLE_FLOAT_API*/
1393#else
Jean-Marc Valin30f7f812009-10-17 14:35:13 -04001394int celt_decode(CELTDecoder * restrict st, const unsigned char *data, int len, celt_int16 * restrict pcm)
Gregory Maxwell5f2a74b2008-08-11 23:50:07 -04001395{
Gregory Maxwell17169992009-06-04 15:15:34 -04001396 int j, ret, C, N;
Gregory Maxwell5f2a74b2008-08-11 23:50:07 -04001397 VARDECL(celt_sig_t, out);
Jean-Marc Valincb8780c2009-07-20 23:40:35 -04001398 SAVE_STACK;
Gregory Maxwell17169992009-06-04 15:15:34 -04001399
1400 if (check_decoder(st) != CELT_OK)
1401 return CELT_INVALID_STATE;
1402
1403 if (check_mode(st->mode) != CELT_OK)
1404 return CELT_INVALID_MODE;
1405
Gregory Maxwell0719f6f2009-07-09 17:07:24 -04001406 if (pcm==NULL)
1407 return CELT_BAD_ARG;
1408
Jean-Marc Valin80ed1472009-10-15 21:45:32 -04001409 C = CHANNELS(st->channels);
Gregory Maxwell17169992009-06-04 15:15:34 -04001410 N = st->block_size;
Gregory Maxwell5f2a74b2008-08-11 23:50:07 -04001411 ALLOC(out, C*N, celt_sig_t);
1412
1413 ret=celt_decode_float(st, data, len, out);
1414
1415 for (j=0;j<C*N;j++)
Gregory Maxwell0719f6f2009-07-09 17:07:24 -04001416 pcm[j] = FLOAT2INT16 (out[j]);
1417
Wessel Lubberhuizen33ba6cc2008-10-03 07:09:29 -04001418 RESTORE_STACK;
Gregory Maxwell5f2a74b2008-08-11 23:50:07 -04001419 return ret;
1420}
1421#endif
John Ridges454d1d02009-05-21 22:38:39 -04001422
1423int celt_decoder_ctl(CELTDecoder * restrict st, int request, ...)
1424{
1425 va_list ap;
Gregory Maxwell17169992009-06-04 15:15:34 -04001426
1427 if (check_decoder(st) != CELT_OK)
1428 return CELT_INVALID_STATE;
1429
John Ridges454d1d02009-05-21 22:38:39 -04001430 va_start(ap, request);
Gregory Maxwell17169992009-06-04 15:15:34 -04001431 if ((request!=CELT_GET_MODE_REQUEST) && (check_mode(st->mode) != CELT_OK))
1432 goto bad_mode;
John Ridges454d1d02009-05-21 22:38:39 -04001433 switch (request)
1434 {
Gregory Maxwellf3b44ef2009-06-03 13:37:45 -04001435 case CELT_GET_MODE_REQUEST:
1436 {
1437 const CELTMode ** value = va_arg(ap, const CELTMode**);
1438 if (value==0)
1439 goto bad_arg;
1440 *value=st->mode;
1441 }
1442 break;
John Ridges454d1d02009-05-21 22:38:39 -04001443 case CELT_RESET_STATE:
1444 {
1445 const CELTMode *mode = st->mode;
Jean-Marc Valin80ed1472009-10-15 21:45:32 -04001446 int C = st->channels;
John Ridges454d1d02009-05-21 22:38:39 -04001447
1448 CELT_MEMSET(st->decode_mem, 0, (DECODE_BUFFER_SIZE+st->overlap)*C);
1449 CELT_MEMSET(st->oldBandE, 0, C*mode->nbEBands);
1450
1451 CELT_MEMSET(st->preemph_memD, 0, C);
1452
Jean-Marc Valin0f0da992009-08-12 21:34:01 -04001453 st->loss_count = 0;
John Ridges454d1d02009-05-21 22:38:39 -04001454 }
1455 break;
1456 default:
1457 goto bad_request;
1458 }
1459 va_end(ap);
1460 return CELT_OK;
Gregory Maxwell17169992009-06-04 15:15:34 -04001461bad_mode:
1462 va_end(ap);
1463 return CELT_INVALID_MODE;
John Ridges454d1d02009-05-21 22:38:39 -04001464bad_arg:
1465 va_end(ap);
1466 return CELT_BAD_ARG;
John Ridges454d1d02009-05-21 22:38:39 -04001467bad_request:
1468 va_end(ap);
1469 return CELT_UNIMPLEMENTED;
1470}
Jean-Marc Valinece94a02009-10-16 07:30:14 -04001471
1472const char *celt_strerror(int error)
1473{
1474 static const char *error_strings[8] = {
1475 "success",
1476 "invalid argument",
1477 "invalid mode",
1478 "internal error",
1479 "corrupted stream",
1480 "request not implemented",
1481 "invalid state",
1482 "memory allocation failed"
1483 };
1484 if (error > 0 || error < -7)
1485 return "unknown error";
1486 else
1487 return error_strings[-error];
1488}
1489