blob: dcc059678aff0016bdf0c5ae9c8e42a130c730a8 [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 Valina5431bf2008-01-03 20:53:01 +110085 int overlap;
Jean-Marc Valinffa13472007-12-10 16:54:17 +110086 int channels;
87
Gregory Maxwell2dd3d322009-06-05 14:05:51 -040088 int pitch_enabled; /* Complexity level is allowed to use pitch */
89 int pitch_permitted; /* Use of the LTP is permitted by the user */
90 int pitch_available; /* Amount of pitch buffer available */
91 int force_intra;
Jean-Marc Valin74f4e9f2009-05-02 09:57:50 -040092 int delayedIntra;
Jean-Marc Valin234969c2009-10-17 22:12:42 -040093 celt_word16 tonal_average;
Jean-Marc Valin527db5c2009-06-02 07:56:19 -040094 int fold_decision;
Jean-Marc Valin234969c2009-10-17 22:12:42 -040095 celt_word16 gain_prod;
Jean-Marc Valin9c30de52010-04-19 13:32:15 -040096 celt_word32 frame_max;
Jean-Marc Valin5f961462010-05-19 13:38:10 -040097 int start, end;
Jean-Marc Valin527db5c2009-06-02 07:56:19 -040098
Jean-Marc Valinbd5d54a2009-10-20 00:25:31 -040099 /* VBR-related parameters */
100 celt_int32 vbr_reservoir;
101 celt_int32 vbr_drift;
102 celt_int32 vbr_offset;
103 celt_int32 vbr_count;
104
Jean-Marc Valin8cc945c2010-05-29 08:07:18 -0400105 celt_int32 vbr_rate_norm; /* Target number of 16th bits per frame */
Jean-Marc Valin234969c2009-10-17 22:12:42 -0400106 celt_word16 * restrict preemph_memE;
107 celt_sig * restrict preemph_memD;
Jean-Marc Valin81b38c22008-02-29 21:08:49 +1100108
Jean-Marc Valin234969c2009-10-17 22:12:42 -0400109 celt_sig *in_mem;
110 celt_sig *out_mem;
Jean-Marc Valin294863b2009-11-08 22:29:54 +0900111 celt_word16 *pitch_buf;
112 celt_sig xmem;
Jean-Marc Valin991c0f02007-11-30 16:07:46 +1100113
Jean-Marc Valin234969c2009-10-17 22:12:42 -0400114 celt_word16 *oldBandE;
Jean-Marc Valin8ebd3452007-11-29 20:17:32 +1100115};
116
Jean-Marc Valine12017e2009-10-03 13:57:31 -0400117static int check_encoder(const CELTEncoder *st)
Gregory Maxwell17169992009-06-04 15:15:34 -0400118{
119 if (st==NULL)
120 {
121 celt_warning("NULL passed as an encoder structure");
122 return CELT_INVALID_STATE;
123 }
124 if (st->marker == ENCODERVALID)
125 return CELT_OK;
126 if (st->marker == ENCODERFREED)
127 celt_warning("Referencing an encoder that has already been freed");
128 else
129 celt_warning("This is not a valid CELT encoder structure");
130 return CELT_INVALID_STATE;
131}
132
Jean-Marc Valin80ed1472009-10-15 21:45:32 -0400133CELTEncoder *celt_encoder_create(const CELTMode *mode, int channels, int *error)
Jean-Marc Valin8ebd3452007-11-29 20:17:32 +1100134{
Jean-Marc Valin04752672010-05-05 07:21:21 -0400135 int C;
Jean-Marc Valin02fa9132008-02-20 12:09:29 +1100136 CELTEncoder *st;
Jean-Marc Valin44ffd5a2008-02-22 00:39:25 +1100137
138 if (check_mode(mode) != CELT_OK)
Jean-Marc Valinece94a02009-10-16 07:30:14 -0400139 {
140 if (error)
141 *error = CELT_INVALID_MODE;
Jean-Marc Valin44ffd5a2008-02-22 00:39:25 +1100142 return NULL;
Jean-Marc Valinece94a02009-10-16 07:30:14 -0400143 }
Jean-Marc Valinbd5d54a2009-10-20 00:25:31 -0400144
Jean-Marc Valin80ed1472009-10-15 21:45:32 -0400145 if (channels < 0 || channels > 2)
146 {
147 celt_warning("Only mono and stereo supported");
148 if (error)
149 *error = CELT_BAD_ARG;
150 return NULL;
151 }
Jean-Marc Valin44ffd5a2008-02-22 00:39:25 +1100152
Jean-Marc Valin80ed1472009-10-15 21:45:32 -0400153 C = channels;
Jean-Marc Valin02fa9132008-02-20 12:09:29 +1100154 st = celt_alloc(sizeof(CELTEncoder));
Jean-Marc Valin8ebd3452007-11-29 20:17:32 +1100155
Jean-Marc Valinece94a02009-10-16 07:30:14 -0400156 if (st==NULL)
157 {
158 if (error)
159 *error = CELT_ALLOC_FAIL;
Jean-Marc Valin80ed1472009-10-15 21:45:32 -0400160 return NULL;
Jean-Marc Valinece94a02009-10-16 07:30:14 -0400161 }
Gregory Maxwell17169992009-06-04 15:15:34 -0400162 st->marker = ENCODERPARTIAL;
Jean-Marc Valin73e51b32007-12-05 17:48:24 +1100163 st->mode = mode;
Jean-Marc Valina5431bf2008-01-03 20:53:01 +1100164 st->overlap = mode->overlap;
Jean-Marc Valin80ed1472009-10-15 21:45:32 -0400165 st->channels = channels;
Jean-Marc Valina5431bf2008-01-03 20:53:01 +1100166
Jean-Marc Valin5f961462010-05-19 13:38:10 -0400167 st->start = 0;
168 st->end = st->mode->nbEBands;
169
Jean-Marc Valin8cc945c2010-05-29 08:07:18 -0400170 st->vbr_rate_norm = 0;
Jean-Marc Valinc9943942008-08-30 00:55:07 -0400171 st->pitch_enabled = 1;
Gregory Maxwell2dd3d322009-06-05 14:05:51 -0400172 st->pitch_permitted = 1;
Gregory Maxwell98046ca2008-12-13 20:42:03 -0500173 st->pitch_available = 1;
Gregory Maxwell2dd3d322009-06-05 14:05:51 -0400174 st->force_intra = 0;
Gregory Maxwell8842fde2009-05-04 15:58:40 -0400175 st->delayedIntra = 1;
Jean-Marc Valin628c0252010-04-16 20:57:56 -0400176 st->tonal_average = QCONST16(1.f,8);
Jean-Marc Valin527db5c2009-06-02 07:56:19 -0400177 st->fold_decision = 1;
Jean-Marc Valina76a0b22008-01-17 22:43:05 +1100178
Jean-Marc Valin234969c2009-10-17 22:12:42 -0400179 st->in_mem = celt_alloc(st->overlap*C*sizeof(celt_sig));
180 st->out_mem = celt_alloc((MAX_PERIOD+st->overlap)*C*sizeof(celt_sig));
Jean-Marc Valine465c142009-11-26 00:39:36 -0500181 st->pitch_buf = celt_alloc(((MAX_PERIOD>>1)+2)*sizeof(celt_word16));
Jean-Marc Valin81b38c22008-02-29 21:08:49 +1100182
Jean-Marc Valin234969c2009-10-17 22:12:42 -0400183 st->oldBandE = (celt_word16*)celt_alloc(C*mode->nbEBands*sizeof(celt_word16));
Jean-Marc Valinfa248732007-12-06 07:51:27 +1100184
Jean-Marc Valin234969c2009-10-17 22:12:42 -0400185 st->preemph_memE = (celt_word16*)celt_alloc(C*sizeof(celt_word16));
186 st->preemph_memD = (celt_sig*)celt_alloc(C*sizeof(celt_sig));
Jean-Marc Valinffa13472007-12-10 16:54:17 +1100187
Gregory Maxwell17169992009-06-04 15:15:34 -0400188 if ((st->in_mem!=NULL) && (st->out_mem!=NULL) && (st->oldBandE!=NULL)
Gregory Maxwell17169992009-06-04 15:15:34 -0400189 && (st->preemph_memE!=NULL) && (st->preemph_memD!=NULL))
190 {
Jean-Marc Valinece94a02009-10-16 07:30:14 -0400191 if (error)
192 *error = CELT_OK;
Gregory Maxwell17169992009-06-04 15:15:34 -0400193 st->marker = ENCODERVALID;
194 return st;
195 }
196 /* If the setup fails for some reason deallocate it. */
197 celt_encoder_destroy(st);
Jean-Marc Valinece94a02009-10-16 07:30:14 -0400198 if (error)
199 *error = CELT_ALLOC_FAIL;
Gregory Maxwell17169992009-06-04 15:15:34 -0400200 return NULL;
Jean-Marc Valin8ebd3452007-11-29 20:17:32 +1100201}
202
Peter Kirk19f9dc92008-06-06 14:38:38 +0200203void celt_encoder_destroy(CELTEncoder *st)
Jean-Marc Valin14191b32007-11-30 12:15:49 +1100204{
205 if (st == NULL)
206 {
207 celt_warning("NULL passed to celt_encoder_destroy");
208 return;
209 }
Jean-Marc Valin44ffd5a2008-02-22 00:39:25 +1100210
Gregory Maxwell17169992009-06-04 15:15:34 -0400211 if (st->marker == ENCODERFREED)
212 {
Gregory Maxwell17169992009-06-04 15:15:34 -0400213 celt_warning("Freeing an encoder which has already been freed");
Gregory Maxwelldc67fa92009-06-04 17:17:35 -0400214 return;
Gregory Maxwell17169992009-06-04 15:15:34 -0400215 }
216
217 if (st->marker != ENCODERVALID && st->marker != ENCODERPARTIAL)
218 {
219 celt_warning("This is not a valid CELT encoder structure");
220 return;
221 }
222 /*Check_mode is non-fatal here because we can still free
223 the encoder memory even if the mode is bad, although calling
224 the free functions in this order is a violation of the API.*/
225 check_mode(st->mode);
226
Jean-Marc Valin14191b32007-11-30 12:15:49 +1100227 celt_free(st->in_mem);
Jean-Marc Valin14191b32007-11-30 12:15:49 +1100228 celt_free(st->out_mem);
Jean-Marc Valin1ccfd3c2009-12-02 21:07:11 -0500229 celt_free(st->pitch_buf);
Jean-Marc Valinc245a222007-12-06 19:14:20 +1100230 celt_free(st->oldBandE);
Jean-Marc Valin7351e282008-02-08 15:09:45 +1100231
232 celt_free(st->preemph_memE);
233 celt_free(st->preemph_memD);
Jean-Marc Valine05e7e22009-11-21 23:41:26 -0500234
Gregory Maxwell17169992009-06-04 15:15:34 -0400235 st->marker = ENCODERFREED;
Jean-Marc Valinc6ca4992008-06-01 23:19:16 +1000236
Jean-Marc Valin14191b32007-11-30 12:15:49 +1100237 celt_free(st);
238}
239
Jean-Marc Valin30f7f812009-10-17 14:35:13 -0400240static inline celt_int16 FLOAT2INT16(float x)
Jean-Marc Valin42074382008-02-27 11:08:53 +1100241{
Gregory Maxwell0ac2b2f2009-05-21 23:08:46 -0400242 x = x*CELT_SIG_SCALE;
Gregory Maxwell5f2a74b2008-08-11 23:50:07 -0400243 x = MAX32(x, -32768);
244 x = MIN32(x, 32767);
Jean-Marc Valin30f7f812009-10-17 14:35:13 -0400245 return (celt_int16)float2int(x);
Gregory Maxwell5f2a74b2008-08-11 23:50:07 -0400246}
247
Jean-Marc Valin234969c2009-10-17 22:12:42 -0400248static inline celt_word16 SIG2WORD16(celt_sig x)
Gregory Maxwell5f2a74b2008-08-11 23:50:07 -0400249{
250#ifdef FIXED_POINT
Jean-Marc Valin42074382008-02-27 11:08:53 +1100251 x = PSHR32(x, SIG_SHIFT);
Jean-Marc Valinabdfc382008-04-18 15:57:18 +1000252 x = MAX32(x, -32768);
253 x = MIN32(x, 32767);
Jean-Marc Valin42074382008-02-27 11:08:53 +1100254 return EXTRACT16(x);
255#else
Jean-Marc Valin234969c2009-10-17 22:12:42 -0400256 return (celt_word16)x;
Jean-Marc Valin42074382008-02-27 11:08:53 +1100257#endif
258}
259
Jean-Marc Valin9c30de52010-04-19 13:32:15 -0400260static int transient_analysis(const celt_word32 * restrict in, int len, int C,
261 int *transient_time, int *transient_shift,
Jean-Marc Valinbdb58712010-05-28 18:58:42 -0400262 celt_word32 *frame_max, int overlap)
Jean-Marc Valin9375aa42008-06-27 07:57:35 +1000263{
Jean-Marc Valinbdb58712010-05-28 18:58:42 -0400264 int i, n;
Jean-Marc Valin234969c2009-10-17 22:12:42 -0400265 celt_word32 ratio;
Jean-Marc Valin9c30de52010-04-19 13:32:15 -0400266 celt_word32 threshold;
Jean-Marc Valin234969c2009-10-17 22:12:42 -0400267 VARDECL(celt_word32, begin);
Jean-Marc Valin0ceccb22008-07-03 20:41:06 -0400268 SAVE_STACK;
Jean-Marc Valin9c30de52010-04-19 13:32:15 -0400269 ALLOC(begin, len+1, celt_word32);
270 begin[0] = 0;
271 if (C==1)
Jean-Marc Valin9375aa42008-06-27 07:57:35 +1000272 {
273 for (i=0;i<len;i++)
Jean-Marc Valin9c30de52010-04-19 13:32:15 -0400274 begin[i+1] = MAX32(begin[i], ABS32(in[i]));
275 } else {
276 for (i=0;i<len;i++)
277 begin[i+1] = MAX32(begin[i], MAX32(ABS32(in[C*i]),
278 ABS32(in[C*i+1])));
Jean-Marc Valin9375aa42008-06-27 07:57:35 +1000279 }
Jean-Marc Valin9375aa42008-06-27 07:57:35 +1000280 n = -1;
Jean-Marc Valin9c30de52010-04-19 13:32:15 -0400281
282 threshold = MULT16_32_Q15(QCONST16(.2f,15),begin[len]);
283 /* If the following condition isn't met, there's just no way
284 we'll have a transient*/
285 if (*frame_max < threshold)
Jean-Marc Valin9375aa42008-06-27 07:57:35 +1000286 {
Jean-Marc Valin9c30de52010-04-19 13:32:15 -0400287 /* It's likely we have a transient, now find it */
288 for (i=8;i<len-8;i++)
289 {
290 if (begin[i+1] < threshold)
291 n=i;
292 }
Jean-Marc Valin9375aa42008-06-27 07:57:35 +1000293 }
Jean-Marc Valin9375aa42008-06-27 07:57:35 +1000294 if (n<32)
295 {
296 n = -1;
297 ratio = 0;
Jean-Marc Valinbd7de0a2008-07-06 10:57:26 -0400298 } else {
Jean-Marc Valin9c30de52010-04-19 13:32:15 -0400299 ratio = DIV32(begin[len],1+MAX32(*frame_max, begin[n-16]));
Jean-Marc Valin9375aa42008-06-27 07:57:35 +1000300 }
Jean-Marc Valinf4578192008-07-04 16:47:28 -0400301 if (ratio < 0)
302 ratio = 0;
303 if (ratio > 1000)
304 ratio = 1000;
Jean-Marc Valin9c30de52010-04-19 13:32:15 -0400305
Jean-Marc Valin816f8932010-05-31 21:35:40 -0400306 if (ratio > 45)
Jean-Marc Valinbd7de0a2008-07-06 10:57:26 -0400307 *transient_shift = 3;
Jean-Marc Valinaa936252009-05-29 22:14:20 -0400308 else
309 *transient_shift = 0;
310
Jean-Marc Valinbd7de0a2008-07-06 10:57:26 -0400311 *transient_time = n;
Jean-Marc Valinbdb58712010-05-28 18:58:42 -0400312 *frame_max = begin[len-overlap];
Jean-Marc Valin9c30de52010-04-19 13:32:15 -0400313
Jean-Marc Valin0ceccb22008-07-03 20:41:06 -0400314 RESTORE_STACK;
Jean-Marc Valin816f8932010-05-31 21:35:40 -0400315 return ratio > 4;
Jean-Marc Valin9375aa42008-06-27 07:57:35 +1000316}
317
Jean-Marc Valin56522ad2009-06-05 17:17:25 -0400318/** Apply window and compute the MDCT for all sub-frames and
319 all channels in a frame */
Jean-Marc Valin017fa852010-05-06 22:11:48 -0400320static void compute_mdcts(const CELTMode *mode, int shortBlocks, celt_sig * restrict in, celt_sig * restrict out, int _C, int LM)
Jean-Marc Valinda721882007-11-30 15:17:42 +1100321{
Jean-Marc Valinbf2398b2009-10-15 07:28:19 -0400322 const int C = CHANNELS(_C);
Jean-Marc Valin9d1decd2008-06-17 13:28:13 +1000323 if (C==1 && !shortBlocks)
Jean-Marc Valinda721882007-11-30 15:17:42 +1100324 {
Jean-Marc Valin017fa852010-05-06 22:11:48 -0400325 const mdct_lookup *lookup = &mode->mdct[LM];
Jean-Marc Valin9d1decd2008-06-17 13:28:13 +1000326 const int overlap = OVERLAP(mode);
Jean-Marc Valin6d584ac2009-11-21 21:57:44 -0500327 clt_mdct_forward(lookup, in, out, mode->window, overlap);
Jean-Marc Valinaa4f58b2009-10-03 09:27:59 -0400328 } else {
Jean-Marc Valin017fa852010-05-06 22:11:48 -0400329 const mdct_lookup *lookup = &mode->mdct[LM];
Jean-Marc Valin9d1decd2008-06-17 13:28:13 +1000330 const int overlap = OVERLAP(mode);
Jean-Marc Valince4dd362010-05-07 07:45:18 -0400331 int N = mode->shortMdctSize<<LM;
Jean-Marc Valinaa4f58b2009-10-03 09:27:59 -0400332 int B = 1;
Jean-Marc Valin9d1decd2008-06-17 13:28:13 +1000333 int b, c;
Jean-Marc Valin234969c2009-10-17 22:12:42 -0400334 VARDECL(celt_word32, x);
335 VARDECL(celt_word32, tmp);
Jean-Marc Valin9d1decd2008-06-17 13:28:13 +1000336 SAVE_STACK;
Jean-Marc Valinaa4f58b2009-10-03 09:27:59 -0400337 if (shortBlocks)
338 {
Jean-Marc Valin073d0bc2010-05-05 21:37:53 -0400339 lookup = &mode->mdct[0];
Jean-Marc Valinaa4f58b2009-10-03 09:27:59 -0400340 N = mode->shortMdctSize;
Jean-Marc Valin3b918ba2010-05-05 00:02:26 -0400341 B = shortBlocks;
Jean-Marc Valinaa4f58b2009-10-03 09:27:59 -0400342 }
Jean-Marc Valin234969c2009-10-17 22:12:42 -0400343 ALLOC(x, N+overlap, celt_word32);
344 ALLOC(tmp, N, celt_word32);
Jean-Marc Valin9d1decd2008-06-17 13:28:13 +1000345 for (c=0;c<C;c++)
346 {
Jean-Marc Valin9d1decd2008-06-17 13:28:13 +1000347 for (b=0;b<B;b++)
348 {
349 int j;
350 for (j=0;j<N+overlap;j++)
351 x[j] = in[C*(b*N+j)+c];
Jean-Marc Valin6d584ac2009-11-21 21:57:44 -0500352 clt_mdct_forward(lookup, x, tmp, mode->window, overlap);
Jean-Marc Valin9d1decd2008-06-17 13:28:13 +1000353 /* Interleaving the sub-frames */
354 for (j=0;j<N;j++)
Jean-Marc Valin08a82ff2009-06-14 14:05:19 -0400355 out[(j*B+b)+c*N*B] = tmp[j];
Jean-Marc Valin9d1decd2008-06-17 13:28:13 +1000356 }
357 }
358 RESTORE_STACK;
Jean-Marc Valinda721882007-11-30 15:17:42 +1100359 }
Jean-Marc Valinda721882007-11-30 15:17:42 +1100360}
361
Jean-Marc Valin56522ad2009-06-05 17:17:25 -0400362/** Compute the IMDCT and apply window for all sub-frames and
363 all channels in a frame */
Jean-Marc Valin017fa852010-05-06 22:11:48 -0400364static 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, int LM)
Jean-Marc Valin1677aa92007-12-08 01:13:34 +1100365{
Jean-Marc Valinb886ddc2008-03-25 14:38:55 +1100366 int c, N4;
Jean-Marc Valinbf2398b2009-10-15 07:28:19 -0400367 const int C = CHANNELS(_C);
Jean-Marc Valince4dd362010-05-07 07:45:18 -0400368 const int N = mode->shortMdctSize<<LM;
Jean-Marc Valinb18ec0b2008-04-11 04:07:52 +1000369 const int overlap = OVERLAP(mode);
Jean-Marc Valina536f772008-03-22 09:01:50 +1100370 N4 = (N-overlap)>>1;
Jean-Marc Valinffa13472007-12-10 16:54:17 +1100371 for (c=0;c<C;c++)
Jean-Marc Valin1677aa92007-12-08 01:13:34 +1100372 {
Jean-Marc Valinb886ddc2008-03-25 14:38:55 +1100373 int j;
Jean-Marc Valin528f4b82008-06-29 03:46:39 +1000374 if (transient_shift==0 && C==1 && !shortBlocks) {
Jean-Marc Valin017fa852010-05-06 22:11:48 -0400375 const mdct_lookup *lookup = &mode->mdct[LM];
Jean-Marc Valin6d584ac2009-11-21 21:57:44 -0500376 clt_mdct_backward(lookup, X, out_mem+C*(MAX_PERIOD-N-N4), mode->window, overlap);
Jean-Marc Valin9d1decd2008-06-17 13:28:13 +1000377 } else {
Jean-Marc Valin234969c2009-10-17 22:12:42 -0400378 VARDECL(celt_word32, x);
379 VARDECL(celt_word32, tmp);
Jean-Marc Valinde678582009-10-03 10:36:27 -0400380 int b;
381 int N2 = N;
382 int B = 1;
383 int n4offset=0;
Jean-Marc Valin017fa852010-05-06 22:11:48 -0400384 const mdct_lookup *lookup = &mode->mdct[LM];
Jean-Marc Valin9d1decd2008-06-17 13:28:13 +1000385 SAVE_STACK;
Jean-Marc Valinde678582009-10-03 10:36:27 -0400386
Jean-Marc Valin234969c2009-10-17 22:12:42 -0400387 ALLOC(x, 2*N, celt_word32);
388 ALLOC(tmp, N, celt_word32);
Jean-Marc Valinde678582009-10-03 10:36:27 -0400389
390 if (shortBlocks)
391 {
Jean-Marc Valin073d0bc2010-05-05 21:37:53 -0400392 lookup = &mode->mdct[0];
Jean-Marc Valinde678582009-10-03 10:36:27 -0400393 N2 = mode->shortMdctSize;
Jean-Marc Valin3b918ba2010-05-05 00:02:26 -0400394 B = shortBlocks;
Jean-Marc Valinde678582009-10-03 10:36:27 -0400395 n4offset = N4;
396 }
Jean-Marc Valin9d1decd2008-06-17 13:28:13 +1000397 /* Prevents problems from the imdct doing the overlap-add */
Gregory Maxwell23e654f2008-09-27 16:20:03 -0400398 CELT_MEMSET(x+N4, 0, N2);
Jean-Marc Valinde678582009-10-03 10:36:27 -0400399
Jean-Marc Valin9d1decd2008-06-17 13:28:13 +1000400 for (b=0;b<B;b++)
401 {
402 /* De-interleaving the sub-frames */
403 for (j=0;j<N2;j++)
Jean-Marc Valin08a82ff2009-06-14 14:05:19 -0400404 tmp[j] = X[(j*B+b)+c*N2*B];
Jean-Marc Valin6d584ac2009-11-21 21:57:44 -0500405 clt_mdct_backward(lookup, tmp, x+n4offset+N2*b, mode->window, overlap);
Jean-Marc Valin9d1decd2008-06-17 13:28:13 +1000406 }
Jean-Marc Valinde678582009-10-03 10:36:27 -0400407
Jean-Marc Valin528f4b82008-06-29 03:46:39 +1000408 if (transient_shift > 0)
Jean-Marc Valin12b22482008-06-16 14:13:05 +1000409 {
Jean-Marc Valin528f4b82008-06-29 03:46:39 +1000410#ifdef FIXED_POINT
Jean-Marc Valin12b22482008-06-16 14:13:05 +1000411 for (j=0;j<16;j++)
Jean-Marc Valin528f4b82008-06-29 03:46:39 +1000412 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 +1000413 for (j=transient_time;j<N+overlap;j++)
Jean-Marc Valin528f4b82008-06-29 03:46:39 +1000414 x[N4+j] = SHL32(x[N4+j], transient_shift);
415#else
416 for (j=0;j<16;j++)
Jean-Marc Valine4aeb472008-06-29 12:06:05 +1000417 x[N4+transient_time+j-16] *= 1+transientWindow[j]*((1<<transient_shift)-1);
Jean-Marc Valin528f4b82008-06-29 03:46:39 +1000418 for (j=transient_time;j<N+overlap;j++)
419 x[N4+j] *= 1<<transient_shift;
420#endif
Jean-Marc Valin12b22482008-06-16 14:13:05 +1000421 }
Jean-Marc Valin56522ad2009-06-05 17:17:25 -0400422 /* The first and last part would need to be set to zero
423 if we actually wanted to use them. */
Jean-Marc Valin8ddd7f42008-04-22 13:37:16 +1000424 for (j=0;j<overlap;j++)
425 out_mem[C*(MAX_PERIOD-N)+C*j+c] += x[j+N4];
426 for (j=0;j<overlap;j++)
427 out_mem[C*(MAX_PERIOD)+C*(overlap-j-1)+c] = x[2*N-j-N4-1];
428 for (j=0;j<2*N4;j++)
429 out_mem[C*(MAX_PERIOD-N)+C*(j+overlap)+c] = x[j+N4+overlap];
430 RESTORE_STACK;
431 }
Jean-Marc Valin1677aa92007-12-08 01:13:34 +1100432 }
433}
434
Jean-Marc Valin05ed03e2009-04-29 07:44:13 -0400435#define FLAG_NONE 0
Jean-Marc Valin5a700972009-08-08 13:23:03 -0400436#define FLAG_INTRA (1U<<13)
437#define FLAG_PITCH (1U<<12)
438#define FLAG_SHORT (1U<<11)
439#define FLAG_FOLD (1U<<10)
Jean-Marc Valin05ed03e2009-04-29 07:44:13 -0400440#define FLAG_MASK (FLAG_INTRA|FLAG_PITCH|FLAG_SHORT|FLAG_FOLD)
441
Jean-Marc Valine12017e2009-10-03 13:57:31 -0400442static const int flaglist[8] = {
Jean-Marc Valina8be38a2009-04-29 22:16:26 -0400443 0 /*00 */ | FLAG_FOLD,
444 1 /*01 */ | FLAG_PITCH|FLAG_FOLD,
445 8 /*1000*/ | FLAG_NONE,
446 9 /*1001*/ | FLAG_SHORT|FLAG_FOLD,
447 10 /*1010*/ | FLAG_PITCH,
448 11 /*1011*/ | FLAG_INTRA,
449 6 /*110 */ | FLAG_INTRA|FLAG_FOLD,
450 7 /*111 */ | FLAG_INTRA|FLAG_SHORT|FLAG_FOLD
Jean-Marc Valin05ed03e2009-04-29 07:44:13 -0400451};
452
Jean-Marc Valine12017e2009-10-03 13:57:31 -0400453static 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 -0400454{
455 int i;
456 int flags=FLAG_NONE;
457 int flag_bits;
458 flags |= intra_ener ? FLAG_INTRA : 0;
459 flags |= has_pitch ? FLAG_PITCH : 0;
460 flags |= shortBlocks ? FLAG_SHORT : 0;
461 flags |= has_fold ? FLAG_FOLD : 0;
462 for (i=0;i<8;i++)
463 if (flags == (flaglist[i]&FLAG_MASK))
464 break;
465 celt_assert(i<8);
466 flag_bits = flaglist[i]&0xf;
467 /*printf ("enc %d: %d %d %d %d\n", flag_bits, intra_ener, has_pitch, shortBlocks, has_fold);*/
468 if (i<2)
Jean-Marc Valinc08be442009-06-17 23:23:46 -0400469 ec_enc_uint(enc, flag_bits, 4);
Jean-Marc Valin05ed03e2009-04-29 07:44:13 -0400470 else if (i<6)
Jean-Marc Valinc08be442009-06-17 23:23:46 -0400471 ec_enc_uint(enc, flag_bits, 16);
Jean-Marc Valin05ed03e2009-04-29 07:44:13 -0400472 else
Jean-Marc Valinc08be442009-06-17 23:23:46 -0400473 ec_enc_uint(enc, flag_bits, 8);
Jean-Marc Valin05ed03e2009-04-29 07:44:13 -0400474}
475
Jean-Marc Valine12017e2009-10-03 13:57:31 -0400476static 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 -0400477{
478 int i;
479 int flag_bits;
Jean-Marc Valinc08be442009-06-17 23:23:46 -0400480 flag_bits = ec_dec_uint(dec, 4);
Jean-Marc Valin05ed03e2009-04-29 07:44:13 -0400481 /*printf ("(%d) ", flag_bits);*/
482 if (flag_bits==2)
Jean-Marc Valinc08be442009-06-17 23:23:46 -0400483 flag_bits = (flag_bits<<2) | ec_dec_uint(dec, 4);
Jean-Marc Valin05ed03e2009-04-29 07:44:13 -0400484 else if (flag_bits==3)
Jean-Marc Valinc08be442009-06-17 23:23:46 -0400485 flag_bits = (flag_bits<<1) | ec_dec_uint(dec, 2);
Jean-Marc Valin05ed03e2009-04-29 07:44:13 -0400486 for (i=0;i<8;i++)
487 if (flag_bits == (flaglist[i]&0xf))
488 break;
489 celt_assert(i<8);
490 *intra_ener = (flaglist[i]&FLAG_INTRA) != 0;
491 *has_pitch = (flaglist[i]&FLAG_PITCH) != 0;
492 *shortBlocks = (flaglist[i]&FLAG_SHORT) != 0;
493 *has_fold = (flaglist[i]&FLAG_FOLD ) != 0;
494 /*printf ("dec %d: %d %d %d %d\n", flag_bits, *intra_ener, *has_pitch, *shortBlocks, *has_fold);*/
495}
496
Jean-Marc Valin64209a32010-04-05 09:26:22 -0400497void 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 -0400498{
Jean-Marc Valinbf2398b2009-10-15 07:28:19 -0400499 const int C = CHANNELS(_C);
Jean-Marc Valine12017e2009-10-03 13:57:31 -0400500 int c;
501 for (c=0;c<C;c++)
502 {
503 int j;
Jean-Marc Valin64209a32010-04-05 09:26:22 -0400504 celt_sig * restrict x;
505 celt_word16 * restrict y;
506 celt_sig m = mem[c];
507 x = &in[C*(MAX_PERIOD-N)+c];
508 y = pcm+c;
Jean-Marc Valine12017e2009-10-03 13:57:31 -0400509 for (j=0;j<N;j++)
510 {
Jean-Marc Valin64209a32010-04-05 09:26:22 -0400511 celt_sig tmp = MAC16_32_Q15(*x, coef,m);
512 m = tmp;
513 *y = SCALEOUT(SIG2WORD16(tmp));
514 x+=C;
515 y+=C;
Jean-Marc Valine12017e2009-10-03 13:57:31 -0400516 }
Jean-Marc Valin64209a32010-04-05 09:26:22 -0400517 mem[c] = m;
Jean-Marc Valine12017e2009-10-03 13:57:31 -0400518 }
Jean-Marc Valine12017e2009-10-03 13:57:31 -0400519}
520
Jean-Marc Valind6b79ee2010-04-20 17:31:45 -0400521static void mdct_shape(const CELTMode *mode, celt_norm *X, int start,
Jean-Marc Valin3b918ba2010-05-05 00:02:26 -0400522 int end, int N,
Jean-Marc Valin65ee67a2010-04-26 07:08:44 -0400523 int mdct_weight_shift, int _C, int renorm, int M)
Jean-Marc Valin88619552009-10-04 21:35:36 -0400524{
525 int m, i, c;
Jean-Marc Valinbf2398b2009-10-15 07:28:19 -0400526 const int C = CHANNELS(_C);
Jean-Marc Valin88619552009-10-04 21:35:36 -0400527 for (c=0;c<C;c++)
528 for (m=start;m<end;m++)
Jean-Marc Valin3b918ba2010-05-05 00:02:26 -0400529 for (i=m+c*N;i<(c+1)*N;i+=M)
Jean-Marc Valin88619552009-10-04 21:35:36 -0400530#ifdef FIXED_POINT
531 X[i] = SHR16(X[i], mdct_weight_shift);
532#else
533 X[i] = (1.f/(1<<mdct_weight_shift))*X[i];
534#endif
Jean-Marc Valind6b79ee2010-04-20 17:31:45 -0400535 if (renorm)
Jean-Marc Valin65ee67a2010-04-26 07:08:44 -0400536 renormalise_bands(mode, X, C, M);
Jean-Marc Valin88619552009-10-04 21:35:36 -0400537}
538
Jean-Marc Valin73319772010-05-28 21:12:39 -0400539static void tf_encode(celt_word16 *bandLogE, celt_word16 *oldBandE, int len, int C, int isTransient, int *tf_res, int nbCompressedBytes, ec_enc *enc)
Jean-Marc Valin163b76e2010-05-27 23:56:53 -0400540{
541 int i, curr;
Jean-Marc Valin0ef39c92010-05-28 17:50:34 -0400542 celt_word16 threshold;
Jean-Marc Valin73319772010-05-28 21:12:39 -0400543 VARDECL(celt_word32, metric);
544 celt_word32 cost0;
545 celt_word32 cost1;
Jean-Marc Valin9d420c52010-05-28 17:26:27 -0400546 VARDECL(int, path0);
547 VARDECL(int, path1);
548 /* FIXME: lambda should depend on the bit-rate */
Jean-Marc Valin73319772010-05-28 21:12:39 -0400549 celt_word16 lambda;
Jean-Marc Valin163b76e2010-05-27 23:56:53 -0400550 SAVE_STACK;
551
Jean-Marc Valin73319772010-05-28 21:12:39 -0400552 if (nbCompressedBytes<40)
553 lambda = QCONST16(5.f, DB_SHIFT);
554 else if (nbCompressedBytes<60)
555 lambda = QCONST16(2.f, DB_SHIFT);
556 else if (nbCompressedBytes<100)
557 lambda = QCONST16(1.f, DB_SHIFT);
558 else
559 lambda = QCONST16(.5f, DB_SHIFT);
560
Jean-Marc Valin163b76e2010-05-27 23:56:53 -0400561 ALLOC(metric, len, celt_word16);
Jean-Marc Valin9d420c52010-05-28 17:26:27 -0400562 ALLOC(path0, len, int);
563 ALLOC(path1, len, int);
Jean-Marc Valin163b76e2010-05-27 23:56:53 -0400564 for (i=0;i<len;i++)
Jean-Marc Valin73319772010-05-28 21:12:39 -0400565 metric[i] = SUB16(bandLogE[i], oldBandE[i]);
Jean-Marc Valin163b76e2010-05-27 23:56:53 -0400566 if (C==2)
567 for (i=0;i<len;i++)
Jean-Marc Valin73319772010-05-28 21:12:39 -0400568 metric[i] = HALF32(metric[i]) + HALF32(SUB16(bandLogE[i+len], oldBandE[i+len]));
Jean-Marc Valin163b76e2010-05-27 23:56:53 -0400569
Jean-Marc Valin163b76e2010-05-27 23:56:53 -0400570 if (isTransient)
571 {
Jean-Marc Valin0ef39c92010-05-28 17:50:34 -0400572 threshold = QCONST16(1.f,DB_SHIFT);
Jean-Marc Valin163b76e2010-05-27 23:56:53 -0400573 } else {
Jean-Marc Valin0ef39c92010-05-28 17:50:34 -0400574 threshold = QCONST16(.5f,DB_SHIFT);
Jean-Marc Valin163b76e2010-05-27 23:56:53 -0400575 }
Jean-Marc Valin88232612010-05-28 18:01:02 -0400576 cost0 = 0;
577 cost1 = lambda;
Jean-Marc Valin9d420c52010-05-28 17:26:27 -0400578 /* Viterbi forward pass */
579 for (i=1;i<len;i++)
Jean-Marc Valin163b76e2010-05-27 23:56:53 -0400580 {
Jean-Marc Valin88232612010-05-28 18:01:02 -0400581 celt_word16 curr0, curr1;
Jean-Marc Valin9d420c52010-05-28 17:26:27 -0400582 celt_word16 from0, from1;
Jean-Marc Valin581fdba2010-05-28 06:56:23 -0400583
Jean-Marc Valin88232612010-05-28 18:01:02 -0400584 from0 = cost0;
585 from1 = cost1 + lambda;
Jean-Marc Valin9d420c52010-05-28 17:26:27 -0400586 if (from0 < from1)
587 {
Jean-Marc Valin88232612010-05-28 18:01:02 -0400588 curr0 = from0;
Jean-Marc Valin9d420c52010-05-28 17:26:27 -0400589 path0[i]= 0;
590 } else {
Jean-Marc Valin88232612010-05-28 18:01:02 -0400591 curr0 = from1;
Jean-Marc Valin9d420c52010-05-28 17:26:27 -0400592 path0[i]= 1;
593 }
594
Jean-Marc Valin88232612010-05-28 18:01:02 -0400595 from0 = cost0 + lambda;
596 from1 = cost1;
Jean-Marc Valin9d420c52010-05-28 17:26:27 -0400597 if (from0 < from1)
598 {
Jean-Marc Valin88232612010-05-28 18:01:02 -0400599 curr1 = from0;
Jean-Marc Valin9d420c52010-05-28 17:26:27 -0400600 path1[i]= 0;
601 } else {
Jean-Marc Valin88232612010-05-28 18:01:02 -0400602 curr1 = from1;
Jean-Marc Valin9d420c52010-05-28 17:26:27 -0400603 path1[i]= 1;
604 }
Jean-Marc Valin88232612010-05-28 18:01:02 -0400605 cost0 = curr0 + (metric[i]-threshold);
606 cost1 = curr1;
Jean-Marc Valin9d420c52010-05-28 17:26:27 -0400607 }
Jean-Marc Valin88232612010-05-28 18:01:02 -0400608 tf_res[len-1] = cost0 < cost1 ? 0 : 1;
Jean-Marc Valin9d420c52010-05-28 17:26:27 -0400609 /* Viterbi backward pass to check the decisions */
610 for (i=len-2;i>=0;i--)
611 {
612 if (tf_res[i+1] == 1)
613 tf_res[i] = path1[i+1];
614 else
615 tf_res[i] = path0[i+1];
616 }
Timothy B. Terriberry43e94062010-05-29 23:02:33 -0400617 ec_enc_bit_prob(enc, tf_res[0], isTransient ? 16384 : 4096);
Jean-Marc Valin581fdba2010-05-28 06:56:23 -0400618 curr = tf_res[0];
619 for (i=1;i<len;i++)
Jean-Marc Valin163b76e2010-05-27 23:56:53 -0400620 {
Timothy B. Terriberry43e94062010-05-29 23:02:33 -0400621 ec_enc_bit_prob(enc, tf_res[i] ^ curr, 4096);
Jean-Marc Valin163b76e2010-05-27 23:56:53 -0400622 curr = tf_res[i];
623 }
624 RESTORE_STACK
625}
626
627static void tf_decode(int len, int C, int isTransient, int *tf_res, ec_dec *dec)
628{
629 int i, curr;
Jean-Marc Valin581fdba2010-05-28 06:56:23 -0400630
Timothy B. Terriberry43e94062010-05-29 23:02:33 -0400631 tf_res[0] = ec_dec_bit_prob(dec, isTransient ? 16384 : 4096);
Jean-Marc Valin581fdba2010-05-28 06:56:23 -0400632 curr = tf_res[0];
633 for (i=1;i<len;i++)
Jean-Marc Valin163b76e2010-05-27 23:56:53 -0400634 {
Timothy B. Terriberry43e94062010-05-29 23:02:33 -0400635 tf_res[i] = ec_dec_bit_prob(dec, 4096) ^ curr;
Jean-Marc Valin163b76e2010-05-27 23:56:53 -0400636 curr = tf_res[i];
637 }
Jean-Marc Valin163b76e2010-05-27 23:56:53 -0400638}
639
Gregory Maxwell5f2a74b2008-08-11 23:50:07 -0400640#ifdef FIXED_POINT
Jean-Marc Valin4794f2e2010-05-19 11:56:57 -0400641int celt_encode_with_ec(CELTEncoder * restrict st, const celt_int16 * pcm, celt_int16 * optional_resynthesis, int frame_size, unsigned char *compressed, int nbCompressedBytes, ec_enc *enc)
Jean-Marc Valin8ebd3452007-11-29 20:17:32 +1100642{
Gregory Maxwell5f2a74b2008-08-11 23:50:07 -0400643#else
Jean-Marc Valin4794f2e2010-05-19 11:56:57 -0400644int celt_encode_with_ec_float(CELTEncoder * restrict st, const celt_sig * pcm, celt_sig * optional_resynthesis, int frame_size, unsigned char *compressed, int nbCompressedBytes, ec_enc *enc)
Gregory Maxwell5f2a74b2008-08-11 23:50:07 -0400645{
646#endif
Jean-Marc Valin88619552009-10-04 21:35:36 -0400647 int i, c, N, NN, N4;
Jean-Marc Valin7e8a4872008-02-11 16:55:34 +1100648 int has_pitch;
Jean-Marc Valin0bb05bc2008-02-20 13:43:40 +1100649 int pitch_index;
Jean-Marc Valinc890b582008-08-01 22:26:49 -0400650 int bits;
Jean-Marc Valinbc799912008-11-07 22:53:13 -0500651 int has_fold=1;
Jean-Marc Valinab4dcc52009-10-21 07:08:27 -0400652 int coarse_needed;
Jean-Marc Valin8679a802008-10-18 07:44:35 -0400653 ec_byte_buffer buf;
Jean-Marc Valin4794f2e2010-05-19 11:56:57 -0400654 ec_enc _enc;
Jean-Marc Valin234969c2009-10-17 22:12:42 -0400655 VARDECL(celt_sig, in);
656 VARDECL(celt_sig, freq);
657 VARDECL(celt_sig, pitch_freq);
658 VARDECL(celt_norm, X);
659 VARDECL(celt_ener, bandE);
660 VARDECL(celt_word16, bandLogE);
Jean-Marc Valin6775de32008-08-02 08:14:42 -0400661 VARDECL(int, fine_quant);
Jean-Marc Valin234969c2009-10-17 22:12:42 -0400662 VARDECL(celt_word16, error);
Jean-Marc Valin6775de32008-08-02 08:14:42 -0400663 VARDECL(int, pulses);
664 VARDECL(int, offsets);
Jean-Marc Valin52cb5fb2009-06-10 08:08:55 -0400665 VARDECL(int, fine_priority);
Jean-Marc Valin163b76e2010-05-27 23:56:53 -0400666 VARDECL(int, tf_res);
Jean-Marc Valin18a3b792009-05-01 19:58:55 -0400667 int intra_ener = 0;
Jean-Marc Valin9d1decd2008-06-17 13:28:13 +1000668 int shortBlocks=0;
Jean-Marc Valin3b918ba2010-05-05 00:02:26 -0400669 int isTransient=0;
Jean-Marc Valin12b22482008-06-16 14:13:05 +1000670 int transient_time;
Jean-Marc Valin528f4b82008-06-29 03:46:39 +1000671 int transient_shift;
Jean-Marc Valinb8ba70c2010-04-18 22:10:24 -0400672 int resynth;
Jean-Marc Valin80ed1472009-10-15 21:45:32 -0400673 const int C = CHANNELS(st->channels);
Jean-Marc Valinaa936252009-05-29 22:14:20 -0400674 int mdct_weight_shift = 0;
675 int mdct_weight_pos=0;
Jean-Marc Valinab220aa2009-09-15 22:38:40 -0400676 int gain_id=0;
Jean-Marc Valin92ae3702009-09-16 07:57:17 -0400677 int norm_rate;
Jean-Marc Valin017fa852010-05-06 22:11:48 -0400678 int LM, M;
Jean-Marc Valin8cc945c2010-05-29 08:07:18 -0400679 celt_int32 vbr_rate=0;
Jean-Marc Valin8600f692008-02-29 15:14:12 +1100680 SAVE_STACK;
Jean-Marc Valin44ffd5a2008-02-22 00:39:25 +1100681
Gregory Maxwell17169992009-06-04 15:15:34 -0400682 if (check_encoder(st) != CELT_OK)
683 return CELT_INVALID_STATE;
684
Jean-Marc Valin44ffd5a2008-02-22 00:39:25 +1100685 if (check_mode(st->mode) != CELT_OK)
686 return CELT_INVALID_MODE;
687
Gregory Maxwell0719f6f2009-07-09 17:07:24 -0400688 if (nbCompressedBytes<0 || pcm==NULL)
Jean-Marc Valin017fa852010-05-06 22:11:48 -0400689 return CELT_BAD_ARG;
Gregory Maxwell520eeae2009-02-09 01:33:21 -0500690
Jean-Marc Valin017fa852010-05-06 22:11:48 -0400691 for (LM=0;LM<4;LM++)
692 if (st->mode->shortMdctSize<<LM==frame_size)
693 break;
694 if (LM>=MAX_CONFIG_SIZES)
695 return CELT_BAD_ARG;
696 M=1<<LM;
Jean-Marc Valin56522ad2009-06-05 17:17:25 -0400697 /* The memset is important for now in case the encoder doesn't
698 fill up all the bytes */
Jean-Marc Valin8679a802008-10-18 07:44:35 -0400699 CELT_MEMSET(compressed, 0, nbCompressedBytes);
Jean-Marc Valin8679a802008-10-18 07:44:35 -0400700
Jean-Marc Valin4794f2e2010-05-19 11:56:57 -0400701 if (enc==NULL)
702 {
703 ec_byte_writeinit_buffer(&buf, compressed, nbCompressedBytes);
704 ec_enc_init(&_enc,&buf);
705 enc = &_enc;
706 }
Jean-Marc Valin04752672010-05-05 07:21:21 -0400707 N = M*st->mode->shortMdctSize;
Jean-Marc Valina536f772008-03-22 09:01:50 +1100708 N4 = (N-st->overlap)>>1;
Jean-Marc Valin234969c2009-10-17 22:12:42 -0400709 ALLOC(in, 2*C*N-2*C*N4, celt_sig);
Jean-Marc Valina5431bf2008-01-03 20:53:01 +1100710
Jean-Marc Valinbdb58832008-04-20 17:42:10 +1000711 CELT_COPY(in, st->in_mem, C*st->overlap);
Jean-Marc Valinffa13472007-12-10 16:54:17 +1100712 for (c=0;c<C;c++)
Jean-Marc Valin6f7e83d2007-12-01 00:36:41 +1100713 {
Jean-Marc Valin234969c2009-10-17 22:12:42 -0400714 const celt_word16 * restrict pcmp = pcm+c;
715 celt_sig * restrict inp = in+C*st->overlap+c;
Jean-Marc Valinb886ddc2008-03-25 14:38:55 +1100716 for (i=0;i<N;i++)
Jean-Marc Valinffa13472007-12-10 16:54:17 +1100717 {
Jean-Marc Valin62290062008-04-20 22:16:02 +1000718 /* Apply pre-emphasis */
Jean-Marc Valin234969c2009-10-17 22:12:42 -0400719 celt_sig tmp = SCALEIN(SHL32(EXTEND32(*pcmp), SIG_SHIFT));
Jean-Marc Valin5c3bc672008-08-28 23:34:24 -0400720 *inp = SUB32(tmp, SHR32(MULT16_16(preemph,st->preemph_memE[c]),3));
Gregory Maxwell5f2a74b2008-08-11 23:50:07 -0400721 st->preemph_memE[c] = SCALEIN(*pcmp);
Jean-Marc Valin62290062008-04-20 22:16:02 +1000722 inp += C;
723 pcmp += C;
Jean-Marc Valinffa13472007-12-10 16:54:17 +1100724 }
Jean-Marc Valin6f7e83d2007-12-01 00:36:41 +1100725 }
Jean-Marc Valinbdb58832008-04-20 17:42:10 +1000726 CELT_COPY(st->in_mem, in+C*(2*N-2*N4-st->overlap), C*st->overlap);
Jean-Marc Valin2014ca32009-06-18 23:33:04 -0400727
Jean-Marc Valin37ab9c62008-11-08 09:14:38 -0500728 /* Transient handling */
Jean-Marc Valin2014ca32009-06-18 23:33:04 -0400729 transient_time = -1;
730 transient_shift = 0;
Jean-Marc Valin3b918ba2010-05-05 00:02:26 -0400731 isTransient = 0;
Jean-Marc Valin2014ca32009-06-18 23:33:04 -0400732
Jean-Marc Valind56c6102010-05-07 20:30:22 -0400733 resynth = st->pitch_available>0 || optional_resynthesis!=NULL;
Jean-Marc Valinb8ba70c2010-04-18 22:10:24 -0400734
Jean-Marc Valinbdb58712010-05-28 18:58:42 -0400735 if (M > 1 && transient_analysis(in, N+st->overlap, C, &transient_time, &transient_shift, &st->frame_max, st->overlap))
Jean-Marc Valin9375aa42008-06-27 07:57:35 +1000736 {
Jean-Marc Valin7028d622008-07-10 23:06:58 -0400737#ifndef FIXED_POINT
Jean-Marc Valin2014ca32009-06-18 23:33:04 -0400738 float gain_1;
Jean-Marc Valin528f4b82008-06-29 03:46:39 +1000739#endif
Jean-Marc Valin2014ca32009-06-18 23:33:04 -0400740 /* Apply the inverse shaping window */
741 if (transient_shift)
742 {
Jean-Marc Valin7028d622008-07-10 23:06:58 -0400743#ifdef FIXED_POINT
Jean-Marc Valin2014ca32009-06-18 23:33:04 -0400744 for (c=0;c<C;c++)
745 for (i=0;i<16;i++)
746 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]);
747 for (c=0;c<C;c++)
748 for (i=transient_time;i<N+st->overlap;i++)
749 in[C*i+c] = SHR32(in[C*i+c], transient_shift);
Jean-Marc Valin7028d622008-07-10 23:06:58 -0400750#else
Jean-Marc Valin2014ca32009-06-18 23:33:04 -0400751 for (c=0;c<C;c++)
752 for (i=0;i<16;i++)
753 in[C*(transient_time+i-16)+c] /= 1+transientWindow[i]*((1<<transient_shift)-1);
754 gain_1 = 1./(1<<transient_shift);
755 for (c=0;c<C;c++)
756 for (i=transient_time;i<N+st->overlap;i++)
757 in[C*i+c] *= gain_1;
Jean-Marc Valin7028d622008-07-10 23:06:58 -0400758#endif
Jean-Marc Valin528f4b82008-06-29 03:46:39 +1000759 }
Jean-Marc Valin3b918ba2010-05-05 00:02:26 -0400760 isTransient = 1;
Jean-Marc Valin2014ca32009-06-18 23:33:04 -0400761 has_fold = 1;
Jean-Marc Valin12b22482008-06-16 14:13:05 +1000762 }
Jean-Marc Valinc5f2a9d2008-10-26 22:00:26 -0400763
Jean-Marc Valin3b918ba2010-05-05 00:02:26 -0400764 if (isTransient)
765 shortBlocks = M;
766 else
767 shortBlocks = 0;
768
Jean-Marc Valin234969c2009-10-17 22:12:42 -0400769 ALLOC(freq, C*N, celt_sig); /**< Interleaved signal MDCTs */
770 ALLOC(bandE,st->mode->nbEBands*C, celt_ener);
771 ALLOC(bandLogE,st->mode->nbEBands*C, celt_word16);
Jean-Marc Valin32ec58c2009-05-01 21:28:58 -0400772 /* Compute MDCTs */
Jean-Marc Valin017fa852010-05-06 22:11:48 -0400773 compute_mdcts(st->mode, shortBlocks, in, freq, C, LM);
Jean-Marc Valin08a82ff2009-06-14 14:05:19 -0400774
Jean-Marc Valinaa936252009-05-29 22:14:20 -0400775
Jean-Marc Valin30f7f812009-10-17 14:35:13 -0400776 norm_rate = (nbCompressedBytes-5)*8*(celt_uint32)st->mode->Fs/(C*N)>>10;
Jean-Marc Valinddb181b2008-03-03 14:53:47 +1100777 /* Pitch analysis: we do it early to save on the peak stack space */
Jean-Marc Valin56522ad2009-06-05 17:17:25 -0400778 /* Don't use pitch if there isn't enough data available yet,
779 or if we're using shortBlocks */
Jean-Marc Valine6d832a2009-07-08 22:21:31 -0400780 has_pitch = st->pitch_enabled && st->pitch_permitted && (N <= 512)
Jean-Marc Valin92ae3702009-09-16 07:57:17 -0400781 && (st->pitch_available >= MAX_PERIOD) && (!shortBlocks)
782 && norm_rate < 50;
Gregory Maxwell98046ca2008-12-13 20:42:03 -0500783 if (has_pitch)
Jean-Marc Valinc5f2a9d2008-10-26 22:00:26 -0400784 {
Jean-Marc Valine465c142009-11-26 00:39:36 -0500785 VARDECL(celt_word16, x_lp);
Jean-Marc Valind5f99302009-12-16 22:42:32 -0500786 SAVE_STACK;
Jean-Marc Valine465c142009-11-26 00:39:36 -0500787 ALLOC(x_lp, (2*N-2*N4)>>1, celt_word16);
788 pitch_downsample(in, x_lp, 2*N-2*N4, N, C, &st->xmem, &st->pitch_buf[MAX_PERIOD>>1]);
Jean-Marc Valince4dd362010-05-07 07:45:18 -0400789 pitch_search(st->mode, x_lp, st->pitch_buf, 2*N-2*N4, MAX_PERIOD-(2*N-2*N4), &pitch_index, &st->xmem, M);
Jean-Marc Valind5f99302009-12-16 22:42:32 -0500790 RESTORE_STACK;
Jean-Marc Valinc5f2a9d2008-10-26 22:00:26 -0400791 }
Jean-Marc Valin37ab9c62008-11-08 09:14:38 -0500792
Jean-Marc Valin56522ad2009-06-05 17:17:25 -0400793 /* Deferred allocation after find_spectral_pitch() to reduce
794 the peak memory usage */
Jean-Marc Valin234969c2009-10-17 22:12:42 -0400795 ALLOC(X, C*N, celt_norm); /**< Interleaved normalised MDCTs */
Jean-Marc Valin8d4ac152008-02-29 17:24:02 +1100796
Jean-Marc Valin234969c2009-10-17 22:12:42 -0400797 ALLOC(pitch_freq, C*N, celt_sig); /**< Interleaved signal MDCTs */
Jean-Marc Valin4c77ea92009-09-14 22:50:41 -0400798 if (has_pitch)
799 {
Jean-Marc Valin017fa852010-05-06 22:11:48 -0400800 compute_mdcts(st->mode, 0, st->out_mem+pitch_index*C, pitch_freq, C, LM);
Jean-Marc Valince4dd362010-05-07 07:45:18 -0400801 has_pitch = compute_pitch_gain(st->mode, freq, pitch_freq, norm_rate, &gain_id, C, &st->gain_prod, M);
Jean-Marc Valin4c77ea92009-09-14 22:50:41 -0400802 }
803
804 if (has_pitch)
Jean-Marc Valince4dd362010-05-07 07:45:18 -0400805 apply_pitch(st->mode, freq, pitch_freq, gain_id, 1, C, M);
Jean-Marc Valin6c245242007-12-29 23:27:42 +1100806
Jean-Marc Valin65ee67a2010-04-26 07:08:44 -0400807 compute_band_energies(st->mode, freq, bandE, C, M);
Jean-Marc Valin4c77ea92009-09-14 22:50:41 -0400808 for (i=0;i<st->mode->nbEBands*C;i++)
809 bandLogE[i] = amp2Log(bandE[i]);
Jean-Marc Valinbd5d54a2009-10-20 00:25:31 -0400810
Jean-Marc Valin8ebd3452007-11-29 20:17:32 +1100811 /* Band normalisation */
Jean-Marc Valin65ee67a2010-04-26 07:08:44 -0400812 normalise_bands(st->mode, freq, X, bandE, C, M);
813 if (!shortBlocks && !folding_decision(st->mode, X, &st->tonal_average, &st->fold_decision, C, M))
Jean-Marc Valin527db5c2009-06-02 07:56:19 -0400814 has_fold = 0;
Jean-Marc Valin26c9e142007-12-31 21:27:54 +1100815
Jean-Marc Valin4c77ea92009-09-14 22:50:41 -0400816 /* Don't use intra energy when we're operating at low bit-rate */
817 intra_ener = st->force_intra || (!has_pitch && st->delayedIntra && nbCompressedBytes > st->mode->nbEBands);
818 if (shortBlocks || intra_decision(bandLogE, st->oldBandE, st->mode->nbEBands))
819 st->delayedIntra = 1;
820 else
821 st->delayedIntra = 0;
822
Jean-Marc Valin65ee67a2010-04-26 07:08:44 -0400823 NN = M*st->mode->eBands[st->mode->nbEBands];
Jean-Marc Valin9f89cab2010-05-21 14:18:38 -0400824 if (shortBlocks && !transient_shift)
Jean-Marc Valin88619552009-10-04 21:35:36 -0400825 {
Jean-Marc Valin234969c2009-10-17 22:12:42 -0400826 celt_word32 sum[8]={1,1,1,1,1,1,1,1};
Jean-Marc Valin88619552009-10-04 21:35:36 -0400827 int m;
828 for (c=0;c<C;c++)
829 {
830 m=0;
831 do {
Jean-Marc Valin234969c2009-10-17 22:12:42 -0400832 celt_word32 tmp=0;
Jean-Marc Valin3b918ba2010-05-05 00:02:26 -0400833 for (i=m+c*N;i<c*N+NN;i+=M)
Jean-Marc Valin88619552009-10-04 21:35:36 -0400834 tmp += ABS32(X[i]);
835 sum[m++] += tmp;
Jean-Marc Valin3b918ba2010-05-05 00:02:26 -0400836 } while (m<M);
Jean-Marc Valin88619552009-10-04 21:35:36 -0400837 }
838 m=0;
839#ifdef FIXED_POINT
840 do {
841 if (SHR32(sum[m+1],3) > sum[m])
842 {
843 mdct_weight_shift=2;
844 mdct_weight_pos = m;
845 } else if (SHR32(sum[m+1],1) > sum[m] && mdct_weight_shift < 2)
846 {
847 mdct_weight_shift=1;
848 mdct_weight_pos = m;
849 }
850 m++;
Jean-Marc Valin3b918ba2010-05-05 00:02:26 -0400851 } while (m<M-1);
Jean-Marc Valin88619552009-10-04 21:35:36 -0400852#else
853 do {
854 if (sum[m+1] > 8*sum[m])
855 {
856 mdct_weight_shift=2;
857 mdct_weight_pos = m;
858 } else if (sum[m+1] > 2*sum[m] && mdct_weight_shift < 2)
859 {
860 mdct_weight_shift=1;
861 mdct_weight_pos = m;
862 }
863 m++;
Jean-Marc Valin3b918ba2010-05-05 00:02:26 -0400864 } while (m<M-1);
Jean-Marc Valin88619552009-10-04 21:35:36 -0400865#endif
866 if (mdct_weight_shift)
Jean-Marc Valin3b918ba2010-05-05 00:02:26 -0400867 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 -0400868 }
869
Jean-Marc Valin4c77ea92009-09-14 22:50:41 -0400870
Jean-Marc Valin4794f2e2010-05-19 11:56:57 -0400871 encode_flags(enc, intra_ener, has_pitch, shortBlocks, has_fold);
Jean-Marc Valin05ed03e2009-04-29 07:44:13 -0400872 if (has_pitch)
873 {
Jean-Marc Valin4794f2e2010-05-19 11:56:57 -0400874 ec_enc_uint(enc, pitch_index, MAX_PERIOD-(2*N-2*N4));
875 ec_enc_uint(enc, gain_id, 16);
Jean-Marc Valin96870d92007-12-05 21:14:22 +1100876 }
Jean-Marc Valin05ed03e2009-04-29 07:44:13 -0400877 if (shortBlocks)
878 {
Jean-Marc Valin05ed03e2009-04-29 07:44:13 -0400879 if (transient_shift)
Jean-Marc Valinaa936252009-05-29 22:14:20 -0400880 {
Jean-Marc Valin4794f2e2010-05-19 11:56:57 -0400881 ec_enc_uint(enc, transient_shift, 4);
882 ec_enc_uint(enc, transient_time, N+st->overlap);
Jean-Marc Valinaa936252009-05-29 22:14:20 -0400883 } else {
Jean-Marc Valin4794f2e2010-05-19 11:56:57 -0400884 ec_enc_uint(enc, mdct_weight_shift, 4);
Jean-Marc Valin3b918ba2010-05-05 00:02:26 -0400885 if (mdct_weight_shift && M!=2)
Jean-Marc Valin4794f2e2010-05-19 11:56:57 -0400886 ec_enc_uint(enc, mdct_weight_pos, M-1);
Jean-Marc Valinaa936252009-05-29 22:14:20 -0400887 }
Jean-Marc Valin05ed03e2009-04-29 07:44:13 -0400888 }
Jean-Marc Valinc890b582008-08-01 22:26:49 -0400889
Jean-Marc Valin6775de32008-08-02 08:14:42 -0400890 ALLOC(fine_quant, st->mode->nbEBands, int);
Jean-Marc Valin8dff9232008-08-13 22:07:20 -0400891 ALLOC(pulses, st->mode->nbEBands, int);
Jean-Marc Valin37ab9c62008-11-08 09:14:38 -0500892
Jean-Marc Valin8cc945c2010-05-29 08:07:18 -0400893 vbr_rate = M*st->vbr_rate_norm;
Jean-Marc Valin25767d12009-10-21 23:24:18 -0400894 /* Computes the max bit-rate allowed in VBR more to avoid busting the budget */
Jean-Marc Valin8cc945c2010-05-29 08:07:18 -0400895 if (st->vbr_rate_norm>0)
Jean-Marc Valin25767d12009-10-21 23:24:18 -0400896 {
897 celt_int32 vbr_bound, max_allowed;
898
Jean-Marc Valin8cc945c2010-05-29 08:07:18 -0400899 vbr_bound = vbr_rate;
900 max_allowed = (vbr_rate + vbr_bound - st->vbr_reservoir)>>(BITRES+3);
Jean-Marc Valin7a047ea2009-10-22 00:23:56 -0400901 if (max_allowed < 4)
902 max_allowed = 4;
Jean-Marc Valin25767d12009-10-21 23:24:18 -0400903 if (max_allowed < nbCompressedBytes)
904 nbCompressedBytes = max_allowed;
905 }
906
Jean-Marc Valin163b76e2010-05-27 23:56:53 -0400907 ALLOC(tf_res, st->mode->nbEBands, int);
Jean-Marc Valin73319772010-05-28 21:12:39 -0400908 tf_encode(bandLogE, st->oldBandE, st->mode->nbEBands, C, isTransient, tf_res, nbCompressedBytes, enc);
Jean-Marc Valin163b76e2010-05-27 23:56:53 -0400909
Jean-Marc Valin37ab9c62008-11-08 09:14:38 -0500910 /* Bit allocation */
Jean-Marc Valin234969c2009-10-17 22:12:42 -0400911 ALLOC(error, C*st->mode->nbEBands, celt_word16);
Jean-Marc Valin5f961462010-05-19 13:38:10 -0400912 coarse_needed = quant_coarse_energy(st->mode, st->start, bandLogE, st->oldBandE, nbCompressedBytes*4-8, intra_ener, st->mode->prob, error, enc, C);
Gregory Maxwell888d8ce2009-05-21 04:21:53 -0400913 coarse_needed = ((coarse_needed*3-1)>>3)+1;
Jean-Marc Valin25767d12009-10-21 23:24:18 -0400914 if (coarse_needed > nbCompressedBytes)
915 coarse_needed = nbCompressedBytes;
Gregory Maxwell888d8ce2009-05-21 04:21:53 -0400916 /* Variable bitrate */
Jean-Marc Valin8cc945c2010-05-29 08:07:18 -0400917 if (vbr_rate>0)
Gregory Maxwell888d8ce2009-05-21 04:21:53 -0400918 {
Jean-Marc Valinbd5d54a2009-10-20 00:25:31 -0400919 celt_word16 alpha;
Jean-Marc Valin25767d12009-10-21 23:24:18 -0400920 celt_int32 delta;
Gregory Maxwell888d8ce2009-05-21 04:21:53 -0400921 /* The target rate in 16th bits per frame */
Jean-Marc Valin8cc945c2010-05-29 08:07:18 -0400922 celt_int32 target=vbr_rate;
Jean-Marc Valin6775de32008-08-02 08:14:42 -0400923
Jean-Marc Valin56522ad2009-06-05 17:17:25 -0400924 /* Shortblocks get a large boost in bitrate, but since they
925 are uncommon long blocks are not greatly effected */
Gregory Maxwell888d8ce2009-05-21 04:21:53 -0400926 if (shortBlocks)
927 target*=2;
Jean-Marc Valin3b918ba2010-05-05 00:02:26 -0400928 else if (M > 1)
Jean-Marc Valinbd5d54a2009-10-20 00:25:31 -0400929 target-=(target+14)/28;
Gregory Maxwell888d8ce2009-05-21 04:21:53 -0400930
Jean-Marc Valin56522ad2009-06-05 17:17:25 -0400931 /* The average energy is removed from the target and the actual
932 energy added*/
Jean-Marc Valin4794f2e2010-05-19 11:56:57 -0400933 target=target+st->vbr_offset-588+ec_enc_tell(enc, BITRES);
Gregory Maxwell888d8ce2009-05-21 04:21:53 -0400934
935 /* In VBR mode the frame size must not be reduced so much that it would result in the coarse energy busting its budget */
936 target=IMAX(coarse_needed,(target+64)/128);
Jean-Marc Valin45f11102009-10-22 00:12:31 -0400937 target=IMIN(nbCompressedBytes,target);
Jean-Marc Valinbd5d54a2009-10-20 00:25:31 -0400938 /* Make the adaptation coef (alpha) higher at the beginning */
939 if (st->vbr_count < 990)
940 {
941 st->vbr_count++;
942 alpha = celt_rcp(SHL32(EXTEND32(st->vbr_count+10),16));
943 /*printf ("%d %d\n", st->vbr_count+10, alpha);*/
944 } else
945 alpha = QCONST16(.001f,15);
946
947 /* By how much did we "miss" the target on that frame */
Jean-Marc Valin8cc945c2010-05-29 08:07:18 -0400948 delta = (8<<BITRES)*(celt_int32)target - vbr_rate;
Jean-Marc Valinbd5d54a2009-10-20 00:25:31 -0400949 /* How many bits have we used in excess of what we're allowed */
950 st->vbr_reservoir += delta;
951 /*printf ("%d\n", st->vbr_reservoir);*/
952
953 /* Compute the offset we need to apply in order to reach the target */
954 st->vbr_drift += MULT16_32_Q15(alpha,delta-st->vbr_offset-st->vbr_drift);
955 st->vbr_offset = -st->vbr_drift;
956 /*printf ("%d\n", st->vbr_drift);*/
957
958 /* We could use any multiple of vbr_rate as bound (depending on the delay) */
Jean-Marc Valin25767d12009-10-21 23:24:18 -0400959 if (st->vbr_reservoir < 0)
Jean-Marc Valinbd5d54a2009-10-20 00:25:31 -0400960 {
961 /* We're under the min value -- increase rate */
962 int adjust = 1-(st->vbr_reservoir-1)/(8<<BITRES);
963 st->vbr_reservoir += adjust*(8<<BITRES);
Jean-Marc Valin45f11102009-10-22 00:12:31 -0400964 target += adjust;
Jean-Marc Valinbd5d54a2009-10-20 00:25:31 -0400965 /*printf ("+%d\n", adjust);*/
966 }
Jean-Marc Valin45f11102009-10-22 00:12:31 -0400967 if (target < nbCompressedBytes)
968 nbCompressedBytes = target;
Jean-Marc Valinbd5d54a2009-10-20 00:25:31 -0400969 /* This moves the raw bits to take into account the new compressed size */
Jean-Marc Valine6108642009-08-01 23:05:47 +0200970 ec_byte_shrink(&buf, nbCompressedBytes);
Gregory Maxwell888d8ce2009-05-21 04:21:53 -0400971 }
972
Jean-Marc Valin6775de32008-08-02 08:14:42 -0400973 ALLOC(offsets, st->mode->nbEBands, int);
Jean-Marc Valin52cb5fb2009-06-10 08:08:55 -0400974 ALLOC(fine_priority, st->mode->nbEBands, int);
Jean-Marc Valincb7a2a32008-02-11 16:44:48 +1100975
Jean-Marc Valin6775de32008-08-02 08:14:42 -0400976 for (i=0;i<st->mode->nbEBands;i++)
977 offsets[i] = 0;
Jean-Marc Valin4794f2e2010-05-19 11:56:57 -0400978 bits = nbCompressedBytes*8 - ec_enc_tell(enc, 0) - 1;
Jean-Marc Valin5f961462010-05-19 13:38:10 -0400979 compute_allocation(st->mode, st->start, offsets, bits, pulses, fine_quant, fine_priority, C, M);
Jean-Marc Valin37ab9c62008-11-08 09:14:38 -0500980
Jean-Marc Valin5f961462010-05-19 13:38:10 -0400981 quant_fine_energy(st->mode, st->start, bandE, st->oldBandE, error, fine_quant, enc, C);
Jean-Marc Valin6775de32008-08-02 08:14:42 -0400982
Jean-Marc Valin8ebd3452007-11-29 20:17:32 +1100983 /* Residual quantisation */
Jean-Marc Valin163b76e2010-05-27 23:56:53 -0400984 quant_all_bands(1, st->mode, st->start, X, C==2 ? X+N : NULL, bandE, pulses, shortBlocks, has_fold, tf_res, resynth, nbCompressedBytes*8, enc, LM);
Jean-Marc Valin39710532009-06-09 00:10:32 -0400985
Jean-Marc Valin5f961462010-05-19 13:38:10 -0400986 quant_energy_finalise(st->mode, st->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 -0400987
Jean-Marc Valin37ab9c62008-11-08 09:14:38 -0500988 /* Re-synthesis of the coded audio if required */
Jean-Marc Valinb8ba70c2010-04-18 22:10:24 -0400989 if (resynth)
Jean-Marc Valin18ddc022008-02-22 14:24:50 +1100990 {
Gregory Maxwell98046ca2008-12-13 20:42:03 -0500991 if (st->pitch_available>0 && st->pitch_available<MAX_PERIOD)
Jean-Marc Valin04752672010-05-05 07:21:21 -0400992 st->pitch_available+=N;
Gregory Maxwell98046ca2008-12-13 20:42:03 -0500993
Jean-Marc Valinaa936252009-05-29 22:14:20 -0400994 if (mdct_weight_shift)
995 {
Jean-Marc Valin3b918ba2010-05-05 00:02:26 -0400996 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 -0400997 }
Jean-Marc Valin88619552009-10-04 21:35:36 -0400998
999 /* Synthesis */
Jean-Marc Valin65ee67a2010-04-26 07:08:44 -04001000 denormalise_bands(st->mode, X, freq, bandE, C, M);
Jean-Marc Valin88619552009-10-04 21:35:36 -04001001
1002 CELT_MOVE(st->out_mem, st->out_mem+C*N, C*(MAX_PERIOD+st->overlap-N));
1003
Jean-Marc Valin4c77ea92009-09-14 22:50:41 -04001004 if (has_pitch)
Jean-Marc Valince4dd362010-05-07 07:45:18 -04001005 apply_pitch(st->mode, freq, pitch_freq, gain_id, 0, C, M);
Jean-Marc Valin4c77ea92009-09-14 22:50:41 -04001006
Jean-Marc Valin017fa852010-05-06 22:11:48 -04001007 compute_inv_mdcts(st->mode, shortBlocks, freq, transient_time, transient_shift, st->out_mem, C, LM);
Jean-Marc Valine12017e2009-10-03 13:57:31 -04001008
Jean-Marc Valin56522ad2009-06-05 17:17:25 -04001009 /* De-emphasis and put everything back at the right place
1010 in the synthesis history */
Jean-Marc Valind56c6102010-05-07 20:30:22 -04001011 if (optional_resynthesis != NULL) {
1012 deemphasis(st->out_mem, optional_resynthesis, N, C, preemph, st->preemph_memD);
Jean-Marc Valine12017e2009-10-03 13:57:31 -04001013
Jean-Marc Valin6f7e83d2007-12-01 00:36:41 +11001014 }
Jean-Marc Valind9b95652008-08-31 23:34:47 -04001015 }
Gregory Maxwell54547f12009-02-16 18:56:44 -05001016
Jean-Marc Valin4794f2e2010-05-19 11:56:57 -04001017 ec_enc_done(enc);
Jean-Marc Valinc871c8d2009-06-09 00:57:00 -04001018
Jean-Marc Valin8600f692008-02-29 15:14:12 +11001019 RESTORE_STACK;
Jean-Marc Valina76a0b22008-01-17 22:43:05 +11001020 return nbCompressedBytes;
Jean-Marc Valin8ebd3452007-11-29 20:17:32 +11001021}
1022
Gregory Maxwell5f2a74b2008-08-11 23:50:07 -04001023#ifdef FIXED_POINT
1024#ifndef DISABLE_FLOAT_API
Jean-Marc Valin4794f2e2010-05-19 11:56:57 -04001025int celt_encode_with_ec_float(CELTEncoder * restrict st, const float * pcm, float * optional_resynthesis, int frame_size, unsigned char *compressed, int nbCompressedBytes, ec_enc *enc)
Gregory Maxwell5f2a74b2008-08-11 23:50:07 -04001026{
Jean-Marc Valin017fa852010-05-06 22:11:48 -04001027 int j, ret, C, N, LM, M;
Jean-Marc Valin30f7f812009-10-17 14:35:13 -04001028 VARDECL(celt_int16, in);
Jean-Marc Valincb8780c2009-07-20 23:40:35 -04001029 SAVE_STACK;
Gregory Maxwell17169992009-06-04 15:15:34 -04001030
1031 if (check_encoder(st) != CELT_OK)
1032 return CELT_INVALID_STATE;
1033
1034 if (check_mode(st->mode) != CELT_OK)
1035 return CELT_INVALID_MODE;
1036
Gregory Maxwell0719f6f2009-07-09 17:07:24 -04001037 if (pcm==NULL)
1038 return CELT_BAD_ARG;
1039
Jean-Marc Valin017fa852010-05-06 22:11:48 -04001040 for (LM=0;LM<4;LM++)
1041 if (st->mode->shortMdctSize<<LM==frame_size)
1042 break;
1043 if (LM>=MAX_CONFIG_SIZES)
1044 return CELT_BAD_ARG;
1045 M=1<<LM;
1046
Jean-Marc Valin80ed1472009-10-15 21:45:32 -04001047 C = CHANNELS(st->channels);
Jean-Marc Valin017fa852010-05-06 22:11:48 -04001048 N = M*st->mode->shortMdctSize;
Jean-Marc Valin30f7f812009-10-17 14:35:13 -04001049 ALLOC(in, C*N, celt_int16);
Gregory Maxwell5f2a74b2008-08-11 23:50:07 -04001050
1051 for (j=0;j<C*N;j++)
1052 in[j] = FLOAT2INT16(pcm[j]);
1053
Jean-Marc Valin4794f2e2010-05-19 11:56:57 -04001054 if (optional_resynthesis != NULL) {
1055 ret=celt_encode_with_ec(st,in,in,frame_size,compressed,nbCompressedBytes, enc);
Gregory Maxwellb0a73a02008-12-12 16:54:25 -05001056 for (j=0;j<C*N;j++)
Jean-Marc Valin4794f2e2010-05-19 11:56:57 -04001057 optional_resynthesis[j]=in[j]*(1/32768.);
Gregory Maxwell82595312008-09-30 18:20:14 -04001058 } else {
Jean-Marc Valin4794f2e2010-05-19 11:56:57 -04001059 ret=celt_encode_with_ec(st,in,NULL,frame_size,compressed,nbCompressedBytes, enc);
Gregory Maxwell82595312008-09-30 18:20:14 -04001060 }
Wessel Lubberhuizen33ba6cc2008-10-03 07:09:29 -04001061 RESTORE_STACK;
Gregory Maxwell5f2a74b2008-08-11 23:50:07 -04001062 return ret;
1063
1064}
1065#endif /*DISABLE_FLOAT_API*/
1066#else
Jean-Marc Valin4794f2e2010-05-19 11:56:57 -04001067int celt_encode_with_ec(CELTEncoder * restrict st, const celt_int16 * pcm, celt_int16 * optional_resynthesis, int frame_size, unsigned char *compressed, int nbCompressedBytes, ec_enc *enc)
Gregory Maxwell5f2a74b2008-08-11 23:50:07 -04001068{
Jean-Marc Valin017fa852010-05-06 22:11:48 -04001069 int j, ret, C, N, LM, M;
Jean-Marc Valin234969c2009-10-17 22:12:42 -04001070 VARDECL(celt_sig, in);
Jean-Marc Valincb8780c2009-07-20 23:40:35 -04001071 SAVE_STACK;
Gregory Maxwell17169992009-06-04 15:15:34 -04001072
1073 if (check_encoder(st) != CELT_OK)
1074 return CELT_INVALID_STATE;
1075
1076 if (check_mode(st->mode) != CELT_OK)
1077 return CELT_INVALID_MODE;
1078
Gregory Maxwell0719f6f2009-07-09 17:07:24 -04001079 if (pcm==NULL)
1080 return CELT_BAD_ARG;
1081
Jean-Marc Valin017fa852010-05-06 22:11:48 -04001082 for (LM=0;LM<4;LM++)
1083 if (st->mode->shortMdctSize<<LM==frame_size)
1084 break;
1085 if (LM>=MAX_CONFIG_SIZES)
1086 return CELT_BAD_ARG;
1087 M=1<<LM;
1088
Jean-Marc Valin80ed1472009-10-15 21:45:32 -04001089 C=CHANNELS(st->channels);
Jean-Marc Valin04752672010-05-05 07:21:21 -04001090 N=M*st->mode->shortMdctSize;
Jean-Marc Valin234969c2009-10-17 22:12:42 -04001091 ALLOC(in, C*N, celt_sig);
Gregory Maxwell5f2a74b2008-08-11 23:50:07 -04001092 for (j=0;j<C*N;j++) {
1093 in[j] = SCALEOUT(pcm[j]);
1094 }
Gregory Maxwell5f2a74b2008-08-11 23:50:07 -04001095
Jean-Marc Valind56c6102010-05-07 20:30:22 -04001096 if (optional_resynthesis != NULL) {
Jean-Marc Valin4794f2e2010-05-19 11:56:57 -04001097 ret = celt_encode_with_ec_float(st,in,in,frame_size,compressed,nbCompressedBytes, enc);
Gregory Maxwell82595312008-09-30 18:20:14 -04001098 for (j=0;j<C*N;j++)
Jean-Marc Valind56c6102010-05-07 20:30:22 -04001099 optional_resynthesis[j] = FLOAT2INT16(in[j]);
Gregory Maxwell82595312008-09-30 18:20:14 -04001100 } else {
Jean-Marc Valin4794f2e2010-05-19 11:56:57 -04001101 ret = celt_encode_with_ec_float(st,in,NULL,frame_size,compressed,nbCompressedBytes, enc);
Gregory Maxwell82595312008-09-30 18:20:14 -04001102 }
Wessel Lubberhuizen33ba6cc2008-10-03 07:09:29 -04001103 RESTORE_STACK;
Gregory Maxwell5f2a74b2008-08-11 23:50:07 -04001104 return ret;
1105}
1106#endif
Jean-Marc Valin6e9058a2007-12-07 14:59:06 +11001107
Jean-Marc Valind56c6102010-05-07 20:30:22 -04001108int celt_encode(CELTEncoder * restrict st, const celt_int16 * pcm, int frame_size, unsigned char *compressed, int nbCompressedBytes)
1109{
Jean-Marc Valin4794f2e2010-05-19 11:56:57 -04001110 return celt_encode_with_ec(st, pcm, NULL, frame_size, compressed, nbCompressedBytes, NULL);
Jean-Marc Valind56c6102010-05-07 20:30:22 -04001111}
1112
1113int celt_encode_float(CELTEncoder * restrict st, const float * pcm, int frame_size, unsigned char *compressed, int nbCompressedBytes)
1114{
Jean-Marc Valin4794f2e2010-05-19 11:56:57 -04001115 return celt_encode_with_ec_float(st, pcm, NULL, frame_size, compressed, nbCompressedBytes, NULL);
Jean-Marc Valind56c6102010-05-07 20:30:22 -04001116}
1117
Jean-Marc Valin4794f2e2010-05-19 11:56:57 -04001118int celt_encode_resynthesis(CELTEncoder * restrict st, const celt_int16 * pcm, celt_int16 * optional_resynthesis, int frame_size, unsigned char *compressed, int nbCompressedBytes)
1119{
1120 return celt_encode_with_ec(st, pcm, optional_resynthesis, frame_size, compressed, nbCompressedBytes, NULL);
1121}
1122
1123int celt_encode_resynthesis_float(CELTEncoder * restrict st, const float * pcm, float * optional_resynthesis, int frame_size, unsigned char *compressed, int nbCompressedBytes)
1124{
1125 return celt_encode_with_ec_float(st, pcm, optional_resynthesis, frame_size, compressed, nbCompressedBytes, NULL);
1126}
1127
1128
Jean-Marc Valinb6f90612008-10-05 22:39:13 -04001129int celt_encoder_ctl(CELTEncoder * restrict st, int request, ...)
Jean-Marc Valinc18fb1d2008-09-30 07:36:54 -04001130{
Jean-Marc Valinb6f90612008-10-05 22:39:13 -04001131 va_list ap;
Gregory Maxwell17169992009-06-04 15:15:34 -04001132
1133 if (check_encoder(st) != CELT_OK)
1134 return CELT_INVALID_STATE;
1135
Jean-Marc Valinb6f90612008-10-05 22:39:13 -04001136 va_start(ap, request);
Gregory Maxwell17169992009-06-04 15:15:34 -04001137 if ((request!=CELT_GET_MODE_REQUEST) && (check_mode(st->mode) != CELT_OK))
1138 goto bad_mode;
Jean-Marc Valinc18fb1d2008-09-30 07:36:54 -04001139 switch (request)
1140 {
Gregory Maxwellf3b44ef2009-06-03 13:37:45 -04001141 case CELT_GET_MODE_REQUEST:
1142 {
1143 const CELTMode ** value = va_arg(ap, const CELTMode**);
1144 if (value==0)
1145 goto bad_arg;
1146 *value=st->mode;
1147 }
1148 break;
Jean-Marc Valinb6f90612008-10-05 22:39:13 -04001149 case CELT_SET_COMPLEXITY_REQUEST:
Jean-Marc Valinc18fb1d2008-09-30 07:36:54 -04001150 {
Jean-Marc Valin30f7f812009-10-17 14:35:13 -04001151 int value = va_arg(ap, celt_int32);
Jean-Marc Valinb6f90612008-10-05 22:39:13 -04001152 if (value<0 || value>10)
1153 goto bad_arg;
Gregory Maxwell98046ca2008-12-13 20:42:03 -05001154 if (value<=2) {
1155 st->pitch_enabled = 0;
1156 st->pitch_available = 0;
1157 } else {
1158 st->pitch_enabled = 1;
1159 if (st->pitch_available<1)
1160 st->pitch_available = 1;
1161 }
1162 }
1163 break;
Jean-Marc Valin5f961462010-05-19 13:38:10 -04001164 case CELT_SET_START_BAND_REQUEST:
1165 {
1166 celt_int32 value = va_arg(ap, celt_int32);
1167 if (value<0 || value>=st->mode->nbEBands)
1168 goto bad_arg;
1169 st->start = value;
1170 }
1171 break;
Gregory Maxwell2dd3d322009-06-05 14:05:51 -04001172 case CELT_SET_PREDICTION_REQUEST:
Gregory Maxwell98046ca2008-12-13 20:42:03 -05001173 {
Jean-Marc Valin30f7f812009-10-17 14:35:13 -04001174 int value = va_arg(ap, celt_int32);
Gregory Maxwell2dd3d322009-06-05 14:05:51 -04001175 if (value<0 || value>2)
Gregory Maxwell98046ca2008-12-13 20:42:03 -05001176 goto bad_arg;
1177 if (value==0)
Gregory Maxwell2dd3d322009-06-05 14:05:51 -04001178 {
1179 st->force_intra = 1;
1180 st->pitch_permitted = 0;
Gregory Maxwella80958b2009-06-29 12:48:57 -04001181 } else if (value==1) {
Gregory Maxwell2dd3d322009-06-05 14:05:51 -04001182 st->force_intra = 0;
1183 st->pitch_permitted = 0;
1184 } else {
1185 st->force_intra = 0;
1186 st->pitch_permitted = 1;
1187 }
Jean-Marc Valinc18fb1d2008-09-30 07:36:54 -04001188 }
1189 break;
Gregory Maxwell888d8ce2009-05-21 04:21:53 -04001190 case CELT_SET_VBR_RATE_REQUEST:
1191 {
Jean-Marc Valin30f7f812009-10-17 14:35:13 -04001192 celt_int32 value = va_arg(ap, celt_int32);
Jean-Marc Valin8cc945c2010-05-29 08:07:18 -04001193 int frame_rate;
1194 int N = st->mode->shortMdctSize;
Gregory Maxwell888d8ce2009-05-21 04:21:53 -04001195 if (value<0)
1196 goto bad_arg;
1197 if (value>3072000)
1198 value = 3072000;
Jean-Marc Valin8cc945c2010-05-29 08:07:18 -04001199 frame_rate = ((st->mode->Fs<<3)+(N>>1))/N;
1200 st->vbr_rate_norm = ((value<<(BITRES+3))+(frame_rate>>1))/frame_rate;
Gregory Maxwell888d8ce2009-05-21 04:21:53 -04001201 }
1202 break;
John Ridges454d1d02009-05-21 22:38:39 -04001203 case CELT_RESET_STATE:
1204 {
1205 const CELTMode *mode = st->mode;
Jean-Marc Valin80ed1472009-10-15 21:45:32 -04001206 int C = st->channels;
John Ridges454d1d02009-05-21 22:38:39 -04001207
1208 if (st->pitch_available > 0) st->pitch_available = 1;
1209
1210 CELT_MEMSET(st->in_mem, 0, st->overlap*C);
1211 CELT_MEMSET(st->out_mem, 0, (MAX_PERIOD+st->overlap)*C);
1212
1213 CELT_MEMSET(st->oldBandE, 0, C*mode->nbEBands);
1214
1215 CELT_MEMSET(st->preemph_memE, 0, C);
1216 CELT_MEMSET(st->preemph_memD, 0, C);
1217 st->delayedIntra = 1;
John Ridges5378bf82010-02-12 07:08:01 -05001218
1219 st->fold_decision = 1;
Jean-Marc Valin628c0252010-04-16 20:57:56 -04001220 st->tonal_average = QCONST16(1.f,8);
John Ridges5378bf82010-02-12 07:08:01 -05001221 st->gain_prod = 0;
1222 st->vbr_reservoir = 0;
1223 st->vbr_drift = 0;
1224 st->vbr_offset = 0;
1225 st->vbr_count = 0;
1226 st->xmem = 0;
Jean-Marc Valin9c30de52010-04-19 13:32:15 -04001227 st->frame_max = 0;
John Ridges5378bf82010-02-12 07:08:01 -05001228 CELT_MEMSET(st->pitch_buf, 0, (MAX_PERIOD>>1)+2);
John Ridges454d1d02009-05-21 22:38:39 -04001229 }
1230 break;
Jean-Marc Valinc18fb1d2008-09-30 07:36:54 -04001231 default:
Jean-Marc Valinb6f90612008-10-05 22:39:13 -04001232 goto bad_request;
Jean-Marc Valinc18fb1d2008-09-30 07:36:54 -04001233 }
Jean-Marc Valinb6f90612008-10-05 22:39:13 -04001234 va_end(ap);
Jean-Marc Valinc18fb1d2008-09-30 07:36:54 -04001235 return CELT_OK;
Gregory Maxwell17169992009-06-04 15:15:34 -04001236bad_mode:
1237 va_end(ap);
1238 return CELT_INVALID_MODE;
Jean-Marc Valinb6f90612008-10-05 22:39:13 -04001239bad_arg:
1240 va_end(ap);
1241 return CELT_BAD_ARG;
1242bad_request:
1243 va_end(ap);
1244 return CELT_UNIMPLEMENTED;
Jean-Marc Valinc18fb1d2008-09-30 07:36:54 -04001245}
1246
Jean-Marc Valin56522ad2009-06-05 17:17:25 -04001247/**********************************************************************/
1248/* */
1249/* DECODER */
1250/* */
1251/**********************************************************************/
Jean-Marc Valineafbdd52009-04-27 19:35:09 -04001252#ifdef NEW_PLC
1253#define DECODE_BUFFER_SIZE 2048
1254#else
1255#define DECODE_BUFFER_SIZE MAX_PERIOD
1256#endif
Jean-Marc Valin269d40a2007-12-07 11:29:45 +11001257
Gregory Maxwell17169992009-06-04 15:15:34 -04001258#define DECODERVALID 0x4c434454
1259#define DECODERPARTIAL 0x5444434c
1260#define DECODERFREED 0x4c004400
1261
Jean-Marc Valin276de722008-02-20 17:45:51 +11001262/** Decoder state
1263 @brief Decoder state
1264 */
Jean-Marc Valin269d40a2007-12-07 11:29:45 +11001265struct CELTDecoder {
Jean-Marc Valin30f7f812009-10-17 14:35:13 -04001266 celt_uint32 marker;
Jean-Marc Valin269d40a2007-12-07 11:29:45 +11001267 const CELTMode *mode;
Jean-Marc Valina5431bf2008-01-03 20:53:01 +11001268 int overlap;
Jean-Marc Valin80ed1472009-10-15 21:45:32 -04001269 int channels;
Jean-Marc Valina5431bf2008-01-03 20:53:01 +11001270
Jean-Marc Valin5f961462010-05-19 13:38:10 -04001271 int start, end;
Jean-Marc Valin269d40a2007-12-07 11:29:45 +11001272 ec_byte_buffer buf;
1273 ec_enc enc;
1274
Jean-Marc Valin234969c2009-10-17 22:12:42 -04001275 celt_sig * restrict preemph_memD;
Jean-Marc Valin81b38c22008-02-29 21:08:49 +11001276
Jean-Marc Valin234969c2009-10-17 22:12:42 -04001277 celt_sig *out_mem;
1278 celt_sig *decode_mem;
Jean-Marc Valin269d40a2007-12-07 11:29:45 +11001279
Jean-Marc Valin234969c2009-10-17 22:12:42 -04001280 celt_word16 *oldBandE;
Jean-Marc Valinfb83fb42007-12-08 00:56:04 +11001281
Jean-Marc Valind69c1cb2009-12-28 00:34:29 -05001282#ifdef NEW_PLC
Jean-Marc Valin74128be2010-01-01 09:33:17 -05001283 celt_word16 *lpc;
Jean-Marc Valin5a0fae52009-12-14 21:19:37 -05001284#endif
1285
Jean-Marc Valinfb83fb42007-12-08 00:56:04 +11001286 int last_pitch_index;
Jean-Marc Valin0f0da992009-08-12 21:34:01 -04001287 int loss_count;
Jean-Marc Valin269d40a2007-12-07 11:29:45 +11001288};
1289
Gregory Maxwell17169992009-06-04 15:15:34 -04001290int check_decoder(const CELTDecoder *st)
1291{
1292 if (st==NULL)
1293 {
1294 celt_warning("NULL passed a decoder structure");
1295 return CELT_INVALID_STATE;
1296 }
1297 if (st->marker == DECODERVALID)
1298 return CELT_OK;
1299 if (st->marker == DECODERFREED)
1300 celt_warning("Referencing a decoder that has already been freed");
1301 else
1302 celt_warning("This is not a valid CELT decoder structure");
1303 return CELT_INVALID_STATE;
1304}
1305
Jean-Marc Valin80ed1472009-10-15 21:45:32 -04001306CELTDecoder *celt_decoder_create(const CELTMode *mode, int channels, int *error)
Jean-Marc Valin269d40a2007-12-07 11:29:45 +11001307{
Jean-Marc Valin04752672010-05-05 07:21:21 -04001308 int C;
Jean-Marc Valin0bb05bc2008-02-20 13:43:40 +11001309 CELTDecoder *st;
Jean-Marc Valin44ffd5a2008-02-22 00:39:25 +11001310
1311 if (check_mode(mode) != CELT_OK)
Jean-Marc Valinece94a02009-10-16 07:30:14 -04001312 {
1313 if (error)
1314 *error = CELT_INVALID_MODE;
Jean-Marc Valin44ffd5a2008-02-22 00:39:25 +11001315 return NULL;
Jean-Marc Valinece94a02009-10-16 07:30:14 -04001316 }
Jean-Marc Valinbd5d54a2009-10-20 00:25:31 -04001317
Jean-Marc Valin80ed1472009-10-15 21:45:32 -04001318 if (channels < 0 || channels > 2)
1319 {
1320 celt_warning("Only mono and stereo supported");
1321 if (error)
1322 *error = CELT_BAD_ARG;
1323 return NULL;
1324 }
Jean-Marc Valin44ffd5a2008-02-22 00:39:25 +11001325
Jean-Marc Valin80ed1472009-10-15 21:45:32 -04001326 C = CHANNELS(channels);
Jean-Marc Valin0bb05bc2008-02-20 13:43:40 +11001327 st = celt_alloc(sizeof(CELTDecoder));
Gregory Maxwell17169992009-06-04 15:15:34 -04001328
1329 if (st==NULL)
Jean-Marc Valinece94a02009-10-16 07:30:14 -04001330 {
1331 if (error)
1332 *error = CELT_ALLOC_FAIL;
Gregory Maxwell17169992009-06-04 15:15:34 -04001333 return NULL;
Jean-Marc Valinece94a02009-10-16 07:30:14 -04001334 }
1335
Gregory Maxwell17169992009-06-04 15:15:34 -04001336 st->marker = DECODERPARTIAL;
Jean-Marc Valin269d40a2007-12-07 11:29:45 +11001337 st->mode = mode;
Jean-Marc Valina5431bf2008-01-03 20:53:01 +11001338 st->overlap = mode->overlap;
Jean-Marc Valin80ed1472009-10-15 21:45:32 -04001339 st->channels = channels;
Jean-Marc Valina5431bf2008-01-03 20:53:01 +11001340
Jean-Marc Valin5f961462010-05-19 13:38:10 -04001341 st->start = 0;
1342 st->end = st->mode->nbEBands;
1343
Jean-Marc Valin234969c2009-10-17 22:12:42 -04001344 st->decode_mem = celt_alloc((DECODE_BUFFER_SIZE+st->overlap)*C*sizeof(celt_sig));
Jean-Marc Valineafbdd52009-04-27 19:35:09 -04001345 st->out_mem = st->decode_mem+DECODE_BUFFER_SIZE-MAX_PERIOD;
Jean-Marc Valin269d40a2007-12-07 11:29:45 +11001346
Jean-Marc Valin234969c2009-10-17 22:12:42 -04001347 st->oldBandE = (celt_word16*)celt_alloc(C*mode->nbEBands*sizeof(celt_word16));
Gregory Maxwell17169992009-06-04 15:15:34 -04001348
Jean-Marc Valin234969c2009-10-17 22:12:42 -04001349 st->preemph_memD = (celt_sig*)celt_alloc(C*sizeof(celt_sig));
Jean-Marc Valinffa13472007-12-10 16:54:17 +11001350
Jean-Marc Valind69c1cb2009-12-28 00:34:29 -05001351#ifdef NEW_PLC
Jean-Marc Valin74128be2010-01-01 09:33:17 -05001352 st->lpc = (celt_word16*)celt_alloc(C*LPC_ORDER*sizeof(celt_word16));
Jean-Marc Valin5a0fae52009-12-14 21:19:37 -05001353#endif
1354
Jean-Marc Valin0f0da992009-08-12 21:34:01 -04001355 st->loss_count = 0;
Gregory Maxwell17169992009-06-04 15:15:34 -04001356
1357 if ((st->decode_mem!=NULL) && (st->out_mem!=NULL) && (st->oldBandE!=NULL) &&
Jean-Marc Valind69c1cb2009-12-28 00:34:29 -05001358#ifdef NEW_PLC
Jean-Marc Valin5a0fae52009-12-14 21:19:37 -05001359 (st->lpc!=NULL) &&
1360#endif
Gregory Maxwell17169992009-06-04 15:15:34 -04001361 (st->preemph_memD!=NULL))
1362 {
Jean-Marc Valinece94a02009-10-16 07:30:14 -04001363 if (error)
1364 *error = CELT_OK;
Gregory Maxwell17169992009-06-04 15:15:34 -04001365 st->marker = DECODERVALID;
1366 return st;
1367 }
1368 /* If the setup fails for some reason deallocate it. */
1369 celt_decoder_destroy(st);
Jean-Marc Valinece94a02009-10-16 07:30:14 -04001370 if (error)
1371 *error = CELT_ALLOC_FAIL;
Gregory Maxwell17169992009-06-04 15:15:34 -04001372 return NULL;
Jean-Marc Valin269d40a2007-12-07 11:29:45 +11001373}
1374
Peter Kirk19f9dc92008-06-06 14:38:38 +02001375void celt_decoder_destroy(CELTDecoder *st)
Jean-Marc Valin269d40a2007-12-07 11:29:45 +11001376{
1377 if (st == NULL)
1378 {
Gregory Maxwell17169992009-06-04 15:15:34 -04001379 celt_warning("NULL passed to celt_decoder_destroy");
Jean-Marc Valin269d40a2007-12-07 11:29:45 +11001380 return;
1381 }
Gregory Maxwell17169992009-06-04 15:15:34 -04001382
1383 if (st->marker == DECODERFREED)
1384 {
1385 celt_warning("Freeing a decoder which has already been freed");
Jean-Marc Valin44ffd5a2008-02-22 00:39:25 +11001386 return;
Gregory Maxwell17169992009-06-04 15:15:34 -04001387 }
1388
1389 if (st->marker != DECODERVALID && st->marker != DECODERPARTIAL)
1390 {
1391 celt_warning("This is not a valid CELT decoder structure");
1392 return;
1393 }
1394
1395 /*Check_mode is non-fatal here because we can still free
1396 the encoder memory even if the mode is bad, although calling
1397 the free functions in this order is a violation of the API.*/
1398 check_mode(st->mode);
1399
Jean-Marc Valineafbdd52009-04-27 19:35:09 -04001400 celt_free(st->decode_mem);
Jean-Marc Valin269d40a2007-12-07 11:29:45 +11001401 celt_free(st->oldBandE);
Jean-Marc Valin7351e282008-02-08 15:09:45 +11001402 celt_free(st->preemph_memD);
Jean-Marc Valin5a0fae52009-12-14 21:19:37 -05001403
Jean-Marc Valind69c1cb2009-12-28 00:34:29 -05001404#ifdef NEW_PLC
Jean-Marc Valin5a0fae52009-12-14 21:19:37 -05001405 celt_free(st->lpc);
1406#endif
Gregory Maxwell17169992009-06-04 15:15:34 -04001407
1408 st->marker = DECODERFREED;
1409
Jean-Marc Valin269d40a2007-12-07 11:29:45 +11001410 celt_free(st);
1411}
1412
Jean-Marc Valin017fa852010-05-06 22:11:48 -04001413static void celt_decode_lost(CELTDecoder * restrict st, celt_word16 * restrict pcm, int N, int LM)
Jean-Marc Valinfb83fb42007-12-08 00:56:04 +11001414{
Jean-Marc Valin04752672010-05-05 07:21:21 -04001415 int c;
Jean-Marc Valin0bb05bc2008-02-20 13:43:40 +11001416 int pitch_index;
Jean-Marc Valine14fe902009-12-11 00:07:31 -05001417 int overlap = st->mode->overlap;
Jean-Marc Valin234969c2009-10-17 22:12:42 -04001418 celt_word16 fade = Q15ONE;
Jean-Marc Valin24c9cda2008-05-02 10:34:07 +10001419 int i, len;
Jean-Marc Valin234969c2009-10-17 22:12:42 -04001420 VARDECL(celt_sig, freq);
Jean-Marc Valin80ed1472009-10-15 21:45:32 -04001421 const int C = CHANNELS(st->channels);
Jean-Marc Valin24c9cda2008-05-02 10:34:07 +10001422 int offset;
Jean-Marc Valin8600f692008-02-29 15:14:12 +11001423 SAVE_STACK;
Jean-Marc Valinfb83fb42007-12-08 00:56:04 +11001424
Jean-Marc Valin24c9cda2008-05-02 10:34:07 +10001425 len = N+st->mode->overlap;
Jean-Marc Valinfb83fb42007-12-08 00:56:04 +11001426
Jean-Marc Valin0f0da992009-08-12 21:34:01 -04001427 if (st->loss_count == 0)
1428 {
Jean-Marc Valin7a7c42a2009-11-25 20:38:52 -05001429 celt_word16 pitch_buf[MAX_PERIOD>>1];
Jean-Marc Valin294863b2009-11-08 22:29:54 +09001430 celt_word32 tmp=0;
Jean-Marc Valine465c142009-11-26 00:39:36 -05001431 celt_word32 mem0[2]={0,0};
1432 celt_word16 mem1[2]={0,0};
Jean-Marc Valine14fe902009-12-11 00:07:31 -05001433 pitch_downsample(st->out_mem, pitch_buf, MAX_PERIOD, MAX_PERIOD,
1434 C, mem0, mem1);
1435 pitch_search(st->mode, pitch_buf+((MAX_PERIOD-len)>>1), pitch_buf, len,
Jean-Marc Valince4dd362010-05-07 07:45:18 -04001436 MAX_PERIOD-len-100, &pitch_index, &tmp, 1<<LM);
Jean-Marc Valin0f0da992009-08-12 21:34:01 -04001437 pitch_index = MAX_PERIOD-len-pitch_index;
1438 st->last_pitch_index = pitch_index;
1439 } else {
1440 pitch_index = st->last_pitch_index;
1441 if (st->loss_count < 5)
1442 fade = QCONST16(.8f,15);
1443 else
1444 fade = 0;
1445 }
Jean-Marc Valinfb83fb42007-12-08 00:56:04 +11001446
Jean-Marc Valind69c1cb2009-12-28 00:34:29 -05001447#ifndef NEW_PLC
Jean-Marc Valind5f99302009-12-16 22:42:32 -05001448 offset = MAX_PERIOD-pitch_index;
Jean-Marc Valine14fe902009-12-11 00:07:31 -05001449 ALLOC(freq,C*N, celt_sig); /**< Interleaved signal MDCTs */
Jean-Marc Valin24c9cda2008-05-02 10:34:07 +10001450 while (offset+len >= MAX_PERIOD)
1451 offset -= pitch_index;
Jean-Marc Valin017fa852010-05-06 22:11:48 -04001452 compute_mdcts(st->mode, 0, st->out_mem+offset*C, freq, C, LM);
Jean-Marc Valin08a82ff2009-06-14 14:05:19 -04001453 for (i=0;i<C*N;i++)
Jean-Marc Valin0f0da992009-08-12 21:34:01 -04001454 freq[i] = ADD32(VERY_SMALL, MULT16_32_Q15(fade,freq[i]));
1455
Jean-Marc Valin24c9cda2008-05-02 10:34:07 +10001456 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 +11001457 /* Compute inverse MDCTs */
Jean-Marc Valin017fa852010-05-06 22:11:48 -04001458 compute_inv_mdcts(st->mode, 0, freq, -1, 0, st->out_mem, C, LM);
Jean-Marc Valine14fe902009-12-11 00:07:31 -05001459#else
1460 for (c=0;c<C;c++)
1461 {
Jean-Marc Valind69c1cb2009-12-28 00:34:29 -05001462 celt_word32 e[MAX_PERIOD];
Jean-Marc Valin303b3b62009-12-30 22:40:24 -05001463 celt_word16 exc[MAX_PERIOD];
Jean-Marc Valine14fe902009-12-11 00:07:31 -05001464 float ac[LPC_ORDER+1];
Jean-Marc Valine14fe902009-12-11 00:07:31 -05001465 float decay = 1;
Jean-Marc Valinaec0ee42009-12-21 00:06:12 -05001466 float S1=0;
Jean-Marc Valin74128be2010-01-01 09:33:17 -05001467 celt_word16 mem[LPC_ORDER]={0};
Jean-Marc Valine14fe902009-12-11 00:07:31 -05001468
Jean-Marc Valind5f99302009-12-16 22:42:32 -05001469 offset = MAX_PERIOD-pitch_index;
Jean-Marc Valine14fe902009-12-11 00:07:31 -05001470 for (i=0;i<MAX_PERIOD;i++)
Jean-Marc Valin74128be2010-01-01 09:33:17 -05001471 exc[i] = ROUND16(st->out_mem[i*C+c], SIG_SHIFT);
Jean-Marc Valin5a0fae52009-12-14 21:19:37 -05001472
1473 if (st->loss_count == 0)
1474 {
1475 _celt_autocorr(exc, ac, st->mode->window, st->mode->overlap,
1476 LPC_ORDER, MAX_PERIOD);
1477
1478 /* Noise floor -50 dB */
1479 ac[0] *= 1.00001;
1480 /* Lag windowing */
1481 for (i=1;i<=LPC_ORDER;i++)
1482 {
1483 /*ac[i] *= exp(-.5*(2*M_PI*.002*i)*(2*M_PI*.002*i));*/
1484 ac[i] -= ac[i]*(.008*i)*(.008*i);
1485 }
1486
Jean-Marc Valin74128be2010-01-01 09:33:17 -05001487 _celt_lpc(st->lpc+c*LPC_ORDER, ac, LPC_ORDER);
Jean-Marc Valin5a0fae52009-12-14 21:19:37 -05001488 }
Jean-Marc Valin74128be2010-01-01 09:33:17 -05001489 fir(exc, st->lpc+c*LPC_ORDER, exc, MAX_PERIOD, LPC_ORDER, mem);
1490 /*for (i=0;i<MAX_PERIOD;i++)printf("%d ", exc[i]); printf("\n");*/
Jean-Marc Valine14fe902009-12-11 00:07:31 -05001491 /* Check if the waveform is decaying (and if so how fast) */
1492 {
1493 float E1=0, E2=0;
1494 int period;
1495 if (pitch_index <= MAX_PERIOD/2)
1496 period = pitch_index;
1497 else
1498 period = MAX_PERIOD/2;
1499 for (i=0;i<period;i++)
1500 {
1501 E1 += exc[MAX_PERIOD-period+i]*exc[MAX_PERIOD-period+i];
1502 E2 += exc[MAX_PERIOD-2*period+i]*exc[MAX_PERIOD-2*period+i];
1503 }
1504 decay = sqrt((E1+1)/(E2+1));
1505 if (decay > 1)
1506 decay = 1;
1507 }
1508
1509 /* Copy excitation, taking decay into account */
1510 for (i=0;i<len+st->mode->overlap;i++)
1511 {
1512 if (offset+i >= MAX_PERIOD)
1513 {
1514 offset -= pitch_index;
1515 decay *= decay;
1516 }
Jean-Marc Valin303b3b62009-12-30 22:40:24 -05001517 e[i] = decay*SHL32(EXTEND32(exc[offset+i]), SIG_SHIFT);
Jean-Marc Valind69c1cb2009-12-28 00:34:29 -05001518 S1 += st->out_mem[offset+i]*1.*st->out_mem[offset+i];
Jean-Marc Valin5a0fae52009-12-14 21:19:37 -05001519 }
1520
Jean-Marc Valin74128be2010-01-01 09:33:17 -05001521 iir(e, st->lpc+c*LPC_ORDER, e, len+st->mode->overlap, LPC_ORDER, mem);
Jean-Marc Valin5a0fae52009-12-14 21:19:37 -05001522
1523 {
Jean-Marc Valin07fed1b2009-12-28 07:59:42 -05001524 float S2=0;
Jean-Marc Valin5a0fae52009-12-14 21:19:37 -05001525 for (i=0;i<len+overlap;i++)
Jean-Marc Valind69c1cb2009-12-28 00:34:29 -05001526 S2 += e[i]*1.*e[i];
Jean-Marc Valin07fed1b2009-12-28 07:59:42 -05001527 /* This checks for an "explosion" in the synthesis (including NaNs) */
1528 if (!(S1 > 0.2f*S2))
1529 {
1530 for (i=0;i<len+overlap;i++)
1531 e[i] = 0;
1532 } else if (S1 < S2)
1533 {
1534 float ratio = sqrt((S1+1)/(S2+1));
Jean-Marc Valin5a0fae52009-12-14 21:19:37 -05001535 for (i=0;i<len+overlap;i++)
1536 e[i] *= ratio;
Jean-Marc Valin07fed1b2009-12-28 07:59:42 -05001537 }
Jean-Marc Valine14fe902009-12-11 00:07:31 -05001538 }
1539
1540 for (i=0;i<MAX_PERIOD+st->mode->overlap-N;i++)
1541 st->out_mem[C*i+c] = st->out_mem[C*(N+i)+c];
1542
Jean-Marc Valine14fe902009-12-11 00:07:31 -05001543 /* Apply TDAC to the concealed audio so that it blends with the
1544 previous and next frames */
1545 for (i=0;i<overlap/2;i++)
1546 {
Jean-Marc Valind69c1cb2009-12-28 00:34:29 -05001547 celt_word32 tmp1, tmp2;
1548 tmp1 = MULT16_32_Q15(st->mode->window[i ], e[i ]) -
1549 MULT16_32_Q15(st->mode->window[overlap-i-1], e[overlap-i-1]);
1550 tmp2 = MULT16_32_Q15(st->mode->window[i], e[N+overlap-1-i]) +
1551 MULT16_32_Q15(st->mode->window[overlap-i-1], e[N+i ]);
1552 tmp1 = MULT16_32_Q15(fade, tmp1);
1553 tmp2 = MULT16_32_Q15(fade, tmp2);
1554 st->out_mem[C*(MAX_PERIOD+i)+c] = MULT16_32_Q15(st->mode->window[overlap-i-1], tmp2);
1555 st->out_mem[C*(MAX_PERIOD+overlap-i-1)+c] = MULT16_32_Q15(st->mode->window[i], tmp2);
1556 st->out_mem[C*(MAX_PERIOD-N+i)+c] += MULT16_32_Q15(st->mode->window[i], tmp1);
1557 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 -05001558 }
1559 for (i=0;i<N-overlap;i++)
Jean-Marc Valind69c1cb2009-12-28 00:34:29 -05001560 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 -05001561 }
1562#endif
Jean-Marc Valin1677aa92007-12-08 01:13:34 +11001563
Jean-Marc Valin5a0fae52009-12-14 21:19:37 -05001564 deemphasis(st->out_mem, pcm, N, C, preemph, st->preemph_memD);
Jean-Marc Valin0f0da992009-08-12 21:34:01 -04001565
1566 st->loss_count++;
1567
Jean-Marc Valin8600f692008-02-29 15:14:12 +11001568 RESTORE_STACK;
Jean-Marc Valinfb83fb42007-12-08 00:56:04 +11001569}
1570
Gregory Maxwell5f2a74b2008-08-11 23:50:07 -04001571#ifdef FIXED_POINT
Jean-Marc Valinf5e2e322010-05-19 12:05:02 -04001572int celt_decode_with_ec(CELTDecoder * restrict st, const unsigned char *data, int len, celt_int16 * restrict pcm, int frame_size, ec_dec *dec)
Jean-Marc Valin269d40a2007-12-07 11:29:45 +11001573{
Gregory Maxwell5f2a74b2008-08-11 23:50:07 -04001574#else
Jean-Marc Valinf5e2e322010-05-19 12:05:02 -04001575int celt_decode_with_ec_float(CELTDecoder * restrict st, const unsigned char *data, int len, celt_sig * restrict pcm, int frame_size, ec_dec *dec)
Gregory Maxwell5f2a74b2008-08-11 23:50:07 -04001576{
1577#endif
Jean-Marc Valin5f961462010-05-19 13:38:10 -04001578 int c, i, N, N4;
Jean-Marc Valinc9943942008-08-30 00:55:07 -04001579 int has_pitch, has_fold;
Jean-Marc Valin0bb05bc2008-02-20 13:43:40 +11001580 int pitch_index;
Jean-Marc Valinc890b582008-08-01 22:26:49 -04001581 int bits;
Jean-Marc Valinf5e2e322010-05-19 12:05:02 -04001582 ec_dec _dec;
Jean-Marc Valin0bb05bc2008-02-20 13:43:40 +11001583 ec_byte_buffer buf;
Jean-Marc Valin234969c2009-10-17 22:12:42 -04001584 VARDECL(celt_sig, freq);
1585 VARDECL(celt_sig, pitch_freq);
1586 VARDECL(celt_norm, X);
1587 VARDECL(celt_ener, bandE);
Jean-Marc Valin6775de32008-08-02 08:14:42 -04001588 VARDECL(int, fine_quant);
1589 VARDECL(int, pulses);
1590 VARDECL(int, offsets);
Jean-Marc Valin52cb5fb2009-06-10 08:08:55 -04001591 VARDECL(int, fine_priority);
Jean-Marc Valin163b76e2010-05-27 23:56:53 -04001592 VARDECL(int, tf_res);
Jean-Marc Valinc890b582008-08-01 22:26:49 -04001593
Jean-Marc Valin9d1decd2008-06-17 13:28:13 +10001594 int shortBlocks;
Jean-Marc Valin3b918ba2010-05-05 00:02:26 -04001595 int isTransient;
Jean-Marc Valin05ed03e2009-04-29 07:44:13 -04001596 int intra_ener;
Jean-Marc Valin12b22482008-06-16 14:13:05 +10001597 int transient_time;
Jean-Marc Valin528f4b82008-06-29 03:46:39 +10001598 int transient_shift;
Jean-Marc Valinaa936252009-05-29 22:14:20 -04001599 int mdct_weight_shift=0;
Jean-Marc Valin80ed1472009-10-15 21:45:32 -04001600 const int C = CHANNELS(st->channels);
Jean-Marc Valinaa936252009-05-29 22:14:20 -04001601 int mdct_weight_pos=0;
Jean-Marc Valinab220aa2009-09-15 22:38:40 -04001602 int gain_id=0;
Jean-Marc Valin017fa852010-05-06 22:11:48 -04001603 int LM, M;
Jean-Marc Valin8600f692008-02-29 15:14:12 +11001604 SAVE_STACK;
Jean-Marc Valin44ffd5a2008-02-22 00:39:25 +11001605
Gregory Maxwell17169992009-06-04 15:15:34 -04001606 if (check_decoder(st) != CELT_OK)
1607 return CELT_INVALID_STATE;
1608
Jean-Marc Valin44ffd5a2008-02-22 00:39:25 +11001609 if (check_mode(st->mode) != CELT_OK)
1610 return CELT_INVALID_MODE;
1611
Gregory Maxwell0719f6f2009-07-09 17:07:24 -04001612 if (pcm==NULL)
1613 return CELT_BAD_ARG;
1614
Jean-Marc Valin017fa852010-05-06 22:11:48 -04001615 for (LM=0;LM<4;LM++)
1616 if (st->mode->shortMdctSize<<LM==frame_size)
1617 break;
1618 if (LM>=MAX_CONFIG_SIZES)
1619 return CELT_BAD_ARG;
1620 M=1<<LM;
1621
Jean-Marc Valin04752672010-05-05 07:21:21 -04001622 N = M*st->mode->shortMdctSize;
Jean-Marc Valina536f772008-03-22 09:01:50 +11001623 N4 = (N-st->overlap)>>1;
Jean-Marc Valin01417232008-03-03 13:59:55 +11001624
Jean-Marc Valin234969c2009-10-17 22:12:42 -04001625 ALLOC(freq, C*N, celt_sig); /**< Interleaved signal MDCTs */
1626 ALLOC(X, C*N, celt_norm); /**< Interleaved normalised MDCTs */
1627 ALLOC(bandE, st->mode->nbEBands*C, celt_ener);
Jean-Marc Valin5f961462010-05-19 13:38:10 -04001628 for (c=0;c<C;c++)
1629 for (i=0;i<M*st->mode->eBands[st->start];i++)
1630 X[c*N+i] = 0;
1631
Jean-Marc Valinfb83fb42007-12-08 00:56:04 +11001632 if (data == NULL)
1633 {
Jean-Marc Valin017fa852010-05-06 22:11:48 -04001634 celt_decode_lost(st, pcm, N, LM);
Jean-Marc Valin8600f692008-02-29 15:14:12 +11001635 RESTORE_STACK;
Jean-Marc Valinfb83fb42007-12-08 00:56:04 +11001636 return 0;
1637 }
Gregory Maxwell520eeae2009-02-09 01:33:21 -05001638 if (len<0) {
1639 RESTORE_STACK;
1640 return CELT_BAD_ARG;
1641 }
Jean-Marc Valinfb83fb42007-12-08 00:56:04 +11001642
Jean-Marc Valinf5e2e322010-05-19 12:05:02 -04001643 if (dec == NULL)
1644 {
1645 ec_byte_readinit(&buf,(unsigned char*)data,len);
1646 ec_dec_init(&_dec,&buf);
1647 dec = &_dec;
1648 }
1649 decode_flags(dec, &intra_ener, &has_pitch, &isTransient, &has_fold);
Jean-Marc Valin3b918ba2010-05-05 00:02:26 -04001650 if (isTransient)
1651 shortBlocks = M;
1652 else
1653 shortBlocks = 0;
1654
1655 if (isTransient)
Gregory Maxwell0527f372008-09-23 19:28:35 -04001656 {
Jean-Marc Valinf5e2e322010-05-19 12:05:02 -04001657 transient_shift = ec_dec_uint(dec, 4);
Jean-Marc Valinaa936252009-05-29 22:14:20 -04001658 if (transient_shift == 3)
1659 {
Jean-Marc Valinf5e2e322010-05-19 12:05:02 -04001660 transient_time = ec_dec_uint(dec, N+st->mode->overlap);
Jean-Marc Valinaa936252009-05-29 22:14:20 -04001661 } else {
1662 mdct_weight_shift = transient_shift;
Jean-Marc Valin3b918ba2010-05-05 00:02:26 -04001663 if (mdct_weight_shift && M>2)
Jean-Marc Valinf5e2e322010-05-19 12:05:02 -04001664 mdct_weight_pos = ec_dec_uint(dec, M-1);
Jean-Marc Valinaa936252009-05-29 22:14:20 -04001665 transient_shift = 0;
Gregory Maxwell0527f372008-09-23 19:28:35 -04001666 transient_time = 0;
Jean-Marc Valinaa936252009-05-29 22:14:20 -04001667 }
Gregory Maxwell0527f372008-09-23 19:28:35 -04001668 } else {
Jean-Marc Valin12b22482008-06-16 14:13:05 +10001669 transient_time = -1;
Jean-Marc Valin528f4b82008-06-29 03:46:39 +10001670 transient_shift = 0;
Jean-Marc Valin12b22482008-06-16 14:13:05 +10001671 }
Jean-Marc Valincb7a2a32008-02-11 16:44:48 +11001672
Jean-Marc Valin7e8a4872008-02-11 16:55:34 +11001673 if (has_pitch)
1674 {
Jean-Marc Valinf5e2e322010-05-19 12:05:02 -04001675 pitch_index = ec_dec_uint(dec, MAX_PERIOD-(2*N-2*N4));
1676 gain_id = ec_dec_uint(dec, 16);
Jean-Marc Valin7e8a4872008-02-11 16:55:34 +11001677 } else {
Jean-Marc Valin7e8a4872008-02-11 16:55:34 +11001678 pitch_index = 0;
1679 }
Jean-Marc Valin827f9312008-05-06 23:21:55 +10001680
Jean-Marc Valin163b76e2010-05-27 23:56:53 -04001681 ALLOC(tf_res, st->mode->nbEBands, int);
1682 tf_decode(st->mode->nbEBands, C, isTransient, tf_res, dec);
1683
Jean-Marc Valin6775de32008-08-02 08:14:42 -04001684 ALLOC(fine_quant, st->mode->nbEBands, int);
Jean-Marc Valin827f9312008-05-06 23:21:55 +10001685 /* Get band energies */
Jean-Marc Valin5f961462010-05-19 13:38:10 -04001686 unquant_coarse_energy(st->mode, st->start, bandE, st->oldBandE, len*4-8, intra_ener, st->mode->prob, dec, C);
Jean-Marc Valin6775de32008-08-02 08:14:42 -04001687
1688 ALLOC(pulses, st->mode->nbEBands, int);
1689 ALLOC(offsets, st->mode->nbEBands, int);
Jean-Marc Valin52cb5fb2009-06-10 08:08:55 -04001690 ALLOC(fine_priority, st->mode->nbEBands, int);
Jean-Marc Valin6775de32008-08-02 08:14:42 -04001691
1692 for (i=0;i<st->mode->nbEBands;i++)
1693 offsets[i] = 0;
1694
Jean-Marc Valinf5e2e322010-05-19 12:05:02 -04001695 bits = len*8 - ec_dec_tell(dec, 0) - 1;
Jean-Marc Valin5f961462010-05-19 13:38:10 -04001696 compute_allocation(st->mode, st->start, offsets, bits, pulses, fine_quant, fine_priority, C, M);
Jean-Marc Valinf5e2e322010-05-19 12:05:02 -04001697 /*bits = ec_dec_tell(dec, 0);
1698 compute_fine_allocation(st->mode, fine_quant, (20*C+len*8/5-(ec_dec_tell(dec, 0)-bits))/C);*/
Jean-Marc Valin6775de32008-08-02 08:14:42 -04001699
Jean-Marc Valin5f961462010-05-19 13:38:10 -04001700 unquant_fine_energy(st->mode, st->start, bandE, st->oldBandE, fine_quant, dec, C);
Jean-Marc Valin827f9312008-05-06 23:21:55 +10001701
Jean-Marc Valin234969c2009-10-17 22:12:42 -04001702 ALLOC(pitch_freq, C*N, celt_sig); /**< Interleaved signal MDCTs */
Jean-Marc Valinc9943942008-08-30 00:55:07 -04001703 if (has_pitch)
Jean-Marc Valin269d40a2007-12-07 11:29:45 +11001704 {
Jean-Marc Valinc9943942008-08-30 00:55:07 -04001705 /* Pitch MDCT */
Jean-Marc Valin017fa852010-05-06 22:11:48 -04001706 compute_mdcts(st->mode, 0, st->out_mem+pitch_index*C, pitch_freq, C, LM);
Jean-Marc Valin269d40a2007-12-07 11:29:45 +11001707 }
1708
Jean-Marc Valin70c8ffd2007-12-07 14:20:01 +11001709 /* Decode fixed codebook and merge with pitch */
Jean-Marc Valin163b76e2010-05-27 23:56:53 -04001710 quant_all_bands(0, st->mode, st->start, X, C==2 ? X+N : NULL, NULL, pulses, shortBlocks, has_fold, tf_res, 1, len*8, dec, LM);
Jean-Marc Valin746b2a82010-05-14 22:12:33 -04001711
Jean-Marc Valin5f961462010-05-19 13:38:10 -04001712 unquant_energy_finalise(st->mode, st->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 -04001713
Jean-Marc Valin88619552009-10-04 21:35:36 -04001714 if (mdct_weight_shift)
1715 {
Jean-Marc Valin3b918ba2010-05-05 00:02:26 -04001716 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 -04001717 }
1718
Jean-Marc Valina4833ff2008-01-10 15:34:00 +11001719 /* Synthesis */
Jean-Marc Valin65ee67a2010-04-26 07:08:44 -04001720 denormalise_bands(st->mode, X, freq, bandE, C, M);
Jean-Marc Valina4833ff2008-01-10 15:34:00 +11001721
1722
Jean-Marc Valineafbdd52009-04-27 19:35:09 -04001723 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 -04001724
Jean-Marc Valin4c77ea92009-09-14 22:50:41 -04001725 if (has_pitch)
Jean-Marc Valince4dd362010-05-07 07:45:18 -04001726 apply_pitch(st->mode, freq, pitch_freq, gain_id, 0, C, M);
Jean-Marc Valin4c77ea92009-09-14 22:50:41 -04001727
Jean-Marc Valin5f961462010-05-19 13:38:10 -04001728 for (c=0;c<C;c++)
1729 for (i=0;i<M*st->mode->eBands[st->start];i++)
1730 freq[c*N+i] = 0;
Jean-Marc Valin3a0bc3d2010-02-21 15:10:22 -05001731
Jean-Marc Valin269d40a2007-12-07 11:29:45 +11001732 /* Compute inverse MDCTs */
Jean-Marc Valin017fa852010-05-06 22:11:48 -04001733 compute_inv_mdcts(st->mode, shortBlocks, freq, transient_time, transient_shift, st->out_mem, C, LM);
Jean-Marc Valinffa13472007-12-10 16:54:17 +11001734
Jean-Marc Valine12017e2009-10-03 13:57:31 -04001735 deemphasis(st->out_mem, pcm, N, C, preemph, st->preemph_memD);
Jean-Marc Valine14fe902009-12-11 00:07:31 -05001736 st->loss_count = 0;
Jean-Marc Valin8600f692008-02-29 15:14:12 +11001737 RESTORE_STACK;
Jean-Marc Valinfb83fb42007-12-08 00:56:04 +11001738 return 0;
Jean-Marc Valin269d40a2007-12-07 11:29:45 +11001739}
1740
Gregory Maxwell5f2a74b2008-08-11 23:50:07 -04001741#ifdef FIXED_POINT
1742#ifndef DISABLE_FLOAT_API
Jean-Marc Valinf5e2e322010-05-19 12:05:02 -04001743int celt_decode_with_ec_float(CELTDecoder * restrict st, const unsigned char *data, int len, float * restrict pcm, int frame_size, ec_dec *dec)
Gregory Maxwell5f2a74b2008-08-11 23:50:07 -04001744{
Jean-Marc Valin017fa852010-05-06 22:11:48 -04001745 int j, ret, C, N, LM, M;
Jean-Marc Valin30f7f812009-10-17 14:35:13 -04001746 VARDECL(celt_int16, out);
Jean-Marc Valincb8780c2009-07-20 23:40:35 -04001747 SAVE_STACK;
Gregory Maxwell17169992009-06-04 15:15:34 -04001748
1749 if (check_decoder(st) != CELT_OK)
1750 return CELT_INVALID_STATE;
1751
1752 if (check_mode(st->mode) != CELT_OK)
1753 return CELT_INVALID_MODE;
1754
Gregory Maxwell0719f6f2009-07-09 17:07:24 -04001755 if (pcm==NULL)
1756 return CELT_BAD_ARG;
1757
Jean-Marc Valin017fa852010-05-06 22:11:48 -04001758 for (LM=0;LM<4;LM++)
1759 if (st->mode->shortMdctSize<<LM==frame_size)
1760 break;
1761 if (LM>=MAX_CONFIG_SIZES)
1762 return CELT_BAD_ARG;
1763 M=1<<LM;
1764
Jean-Marc Valin80ed1472009-10-15 21:45:32 -04001765 C = CHANNELS(st->channels);
Jean-Marc Valin017fa852010-05-06 22:11:48 -04001766 N = M*st->mode->shortMdctSize;
Gregory Maxwell0719f6f2009-07-09 17:07:24 -04001767
Jean-Marc Valin30f7f812009-10-17 14:35:13 -04001768 ALLOC(out, C*N, celt_int16);
Jean-Marc Valinf5e2e322010-05-19 12:05:02 -04001769 ret=celt_decode_with_ec(st, data, len, out, frame_size, dec);
Gregory Maxwell5f2a74b2008-08-11 23:50:07 -04001770 for (j=0;j<C*N;j++)
Gregory Maxwell0719f6f2009-07-09 17:07:24 -04001771 pcm[j]=out[j]*(1/32768.);
1772
Wessel Lubberhuizen33ba6cc2008-10-03 07:09:29 -04001773 RESTORE_STACK;
Gregory Maxwell5f2a74b2008-08-11 23:50:07 -04001774 return ret;
1775}
1776#endif /*DISABLE_FLOAT_API*/
1777#else
Jean-Marc Valinf5e2e322010-05-19 12:05:02 -04001778int celt_decode_with_ec(CELTDecoder * restrict st, const unsigned char *data, int len, celt_int16 * restrict pcm, int frame_size, ec_dec *dec)
Gregory Maxwell5f2a74b2008-08-11 23:50:07 -04001779{
Jean-Marc Valin017fa852010-05-06 22:11:48 -04001780 int j, ret, C, N, LM, M;
Jean-Marc Valin234969c2009-10-17 22:12:42 -04001781 VARDECL(celt_sig, out);
Jean-Marc Valincb8780c2009-07-20 23:40:35 -04001782 SAVE_STACK;
Gregory Maxwell17169992009-06-04 15:15:34 -04001783
1784 if (check_decoder(st) != CELT_OK)
1785 return CELT_INVALID_STATE;
1786
1787 if (check_mode(st->mode) != CELT_OK)
1788 return CELT_INVALID_MODE;
1789
Gregory Maxwell0719f6f2009-07-09 17:07:24 -04001790 if (pcm==NULL)
1791 return CELT_BAD_ARG;
1792
Jean-Marc Valin017fa852010-05-06 22:11:48 -04001793 for (LM=0;LM<4;LM++)
1794 if (st->mode->shortMdctSize<<LM==frame_size)
1795 break;
1796 if (LM>=MAX_CONFIG_SIZES)
1797 return CELT_BAD_ARG;
1798 M=1<<LM;
1799
Jean-Marc Valin80ed1472009-10-15 21:45:32 -04001800 C = CHANNELS(st->channels);
Jean-Marc Valin017fa852010-05-06 22:11:48 -04001801 N = M*st->mode->shortMdctSize;
Jean-Marc Valin234969c2009-10-17 22:12:42 -04001802 ALLOC(out, C*N, celt_sig);
Gregory Maxwell5f2a74b2008-08-11 23:50:07 -04001803
Jean-Marc Valinf5e2e322010-05-19 12:05:02 -04001804 ret=celt_decode_with_ec_float(st, data, len, out, frame_size, dec);
Gregory Maxwell5f2a74b2008-08-11 23:50:07 -04001805
1806 for (j=0;j<C*N;j++)
Gregory Maxwell0719f6f2009-07-09 17:07:24 -04001807 pcm[j] = FLOAT2INT16 (out[j]);
1808
Wessel Lubberhuizen33ba6cc2008-10-03 07:09:29 -04001809 RESTORE_STACK;
Gregory Maxwell5f2a74b2008-08-11 23:50:07 -04001810 return ret;
1811}
1812#endif
John Ridges454d1d02009-05-21 22:38:39 -04001813
Jean-Marc Valinf5e2e322010-05-19 12:05:02 -04001814int celt_decode(CELTDecoder * restrict st, const unsigned char *data, int len, celt_int16 * restrict pcm, int frame_size)
1815{
1816 return celt_decode_with_ec(st, data, len, pcm, frame_size, NULL);
1817}
1818
1819int celt_decode_float(CELTDecoder * restrict st, const unsigned char *data, int len, float * restrict pcm, int frame_size)
1820{
1821 return celt_decode_with_ec_float(st, data, len, pcm, frame_size, NULL);
1822}
1823
John Ridges454d1d02009-05-21 22:38:39 -04001824int celt_decoder_ctl(CELTDecoder * restrict st, int request, ...)
1825{
1826 va_list ap;
Gregory Maxwell17169992009-06-04 15:15:34 -04001827
1828 if (check_decoder(st) != CELT_OK)
1829 return CELT_INVALID_STATE;
1830
John Ridges454d1d02009-05-21 22:38:39 -04001831 va_start(ap, request);
Gregory Maxwell17169992009-06-04 15:15:34 -04001832 if ((request!=CELT_GET_MODE_REQUEST) && (check_mode(st->mode) != CELT_OK))
1833 goto bad_mode;
John Ridges454d1d02009-05-21 22:38:39 -04001834 switch (request)
1835 {
Gregory Maxwellf3b44ef2009-06-03 13:37:45 -04001836 case CELT_GET_MODE_REQUEST:
1837 {
1838 const CELTMode ** value = va_arg(ap, const CELTMode**);
1839 if (value==0)
1840 goto bad_arg;
1841 *value=st->mode;
1842 }
1843 break;
Jean-Marc Valin5f961462010-05-19 13:38:10 -04001844 case CELT_SET_START_BAND_REQUEST:
1845 {
1846 celt_int32 value = va_arg(ap, celt_int32);
1847 if (value<0 || value>=st->mode->nbEBands)
1848 goto bad_arg;
1849 st->start = value;
1850 }
1851 break;
John Ridges454d1d02009-05-21 22:38:39 -04001852 case CELT_RESET_STATE:
1853 {
1854 const CELTMode *mode = st->mode;
Jean-Marc Valin80ed1472009-10-15 21:45:32 -04001855 int C = st->channels;
John Ridges454d1d02009-05-21 22:38:39 -04001856
1857 CELT_MEMSET(st->decode_mem, 0, (DECODE_BUFFER_SIZE+st->overlap)*C);
1858 CELT_MEMSET(st->oldBandE, 0, C*mode->nbEBands);
1859
1860 CELT_MEMSET(st->preemph_memD, 0, C);
1861
Jean-Marc Valin0f0da992009-08-12 21:34:01 -04001862 st->loss_count = 0;
John Ridges5378bf82010-02-12 07:08:01 -05001863
1864#ifdef NEW_PLC
1865 CELT_MEMSET(st->lpc, 0, C*LPC_ORDER);
1866#endif
John Ridges454d1d02009-05-21 22:38:39 -04001867 }
1868 break;
1869 default:
1870 goto bad_request;
1871 }
1872 va_end(ap);
1873 return CELT_OK;
Gregory Maxwell17169992009-06-04 15:15:34 -04001874bad_mode:
1875 va_end(ap);
1876 return CELT_INVALID_MODE;
John Ridges454d1d02009-05-21 22:38:39 -04001877bad_arg:
1878 va_end(ap);
1879 return CELT_BAD_ARG;
John Ridges454d1d02009-05-21 22:38:39 -04001880bad_request:
1881 va_end(ap);
1882 return CELT_UNIMPLEMENTED;
1883}
Jean-Marc Valinece94a02009-10-16 07:30:14 -04001884
1885const char *celt_strerror(int error)
1886{
1887 static const char *error_strings[8] = {
1888 "success",
1889 "invalid argument",
1890 "invalid mode",
1891 "internal error",
1892 "corrupted stream",
1893 "request not implemented",
1894 "invalid state",
1895 "memory allocation failed"
1896 };
1897 if (error > 0 || error < -7)
1898 return "unknown error";
1899 else
1900 return error_strings[-error];
1901}
1902