blob: acac0c06e2cd22a80b09da267adf5195caf9100e [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 Valin0a571ef2010-06-05 23:12:19 -0400539static void tf_analysis(celt_word16 *bandLogE, celt_word16 *oldBandE, int len, int C, int isTransient, int *tf_res, int nbCompressedBytes)
Jean-Marc Valin163b76e2010-05-27 23:56:53 -0400540{
Jean-Marc Valin0a571ef2010-06-05 23:12:19 -0400541 int i;
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 }
Jean-Marc Valin0a571ef2010-06-05 23:12:19 -0400617 RESTORE_STACK
618}
619
620static void tf_encode(int len, int isTransient, int *tf_res, ec_enc *enc)
621{
622 int curr, i;
Timothy B. Terriberry43e94062010-05-29 23:02:33 -0400623 ec_enc_bit_prob(enc, tf_res[0], isTransient ? 16384 : 4096);
Jean-Marc Valin581fdba2010-05-28 06:56:23 -0400624 curr = tf_res[0];
625 for (i=1;i<len;i++)
Jean-Marc Valin163b76e2010-05-27 23:56:53 -0400626 {
Timothy B. Terriberry43e94062010-05-29 23:02:33 -0400627 ec_enc_bit_prob(enc, tf_res[i] ^ curr, 4096);
Jean-Marc Valin163b76e2010-05-27 23:56:53 -0400628 curr = tf_res[i];
629 }
Jean-Marc Valin163b76e2010-05-27 23:56:53 -0400630}
631
632static void tf_decode(int len, int C, int isTransient, int *tf_res, ec_dec *dec)
633{
634 int i, curr;
Jean-Marc Valin581fdba2010-05-28 06:56:23 -0400635
Timothy B. Terriberry43e94062010-05-29 23:02:33 -0400636 tf_res[0] = ec_dec_bit_prob(dec, isTransient ? 16384 : 4096);
Jean-Marc Valin581fdba2010-05-28 06:56:23 -0400637 curr = tf_res[0];
638 for (i=1;i<len;i++)
Jean-Marc Valin163b76e2010-05-27 23:56:53 -0400639 {
Timothy B. Terriberry43e94062010-05-29 23:02:33 -0400640 tf_res[i] = ec_dec_bit_prob(dec, 4096) ^ curr;
Jean-Marc Valin163b76e2010-05-27 23:56:53 -0400641 curr = tf_res[i];
642 }
Jean-Marc Valin163b76e2010-05-27 23:56:53 -0400643}
644
Gregory Maxwell5f2a74b2008-08-11 23:50:07 -0400645#ifdef FIXED_POINT
Jean-Marc Valin4794f2e2010-05-19 11:56:57 -0400646int 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 +1100647{
Gregory Maxwell5f2a74b2008-08-11 23:50:07 -0400648#else
Jean-Marc Valin4794f2e2010-05-19 11:56:57 -0400649int 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 -0400650{
651#endif
Jean-Marc Valin88619552009-10-04 21:35:36 -0400652 int i, c, N, NN, N4;
Jean-Marc Valin7e8a4872008-02-11 16:55:34 +1100653 int has_pitch;
Jean-Marc Valin0bb05bc2008-02-20 13:43:40 +1100654 int pitch_index;
Jean-Marc Valinc890b582008-08-01 22:26:49 -0400655 int bits;
Jean-Marc Valinbc799912008-11-07 22:53:13 -0500656 int has_fold=1;
Jean-Marc Valinab4dcc52009-10-21 07:08:27 -0400657 int coarse_needed;
Jean-Marc Valin8679a802008-10-18 07:44:35 -0400658 ec_byte_buffer buf;
Jean-Marc Valin4794f2e2010-05-19 11:56:57 -0400659 ec_enc _enc;
Jean-Marc Valin234969c2009-10-17 22:12:42 -0400660 VARDECL(celt_sig, in);
661 VARDECL(celt_sig, freq);
662 VARDECL(celt_sig, pitch_freq);
663 VARDECL(celt_norm, X);
664 VARDECL(celt_ener, bandE);
665 VARDECL(celt_word16, bandLogE);
Jean-Marc Valin6775de32008-08-02 08:14:42 -0400666 VARDECL(int, fine_quant);
Jean-Marc Valin234969c2009-10-17 22:12:42 -0400667 VARDECL(celt_word16, error);
Jean-Marc Valin6775de32008-08-02 08:14:42 -0400668 VARDECL(int, pulses);
669 VARDECL(int, offsets);
Jean-Marc Valin52cb5fb2009-06-10 08:08:55 -0400670 VARDECL(int, fine_priority);
Jean-Marc Valin163b76e2010-05-27 23:56:53 -0400671 VARDECL(int, tf_res);
Jean-Marc Valin18a3b792009-05-01 19:58:55 -0400672 int intra_ener = 0;
Jean-Marc Valin9d1decd2008-06-17 13:28:13 +1000673 int shortBlocks=0;
Jean-Marc Valin3b918ba2010-05-05 00:02:26 -0400674 int isTransient=0;
Jean-Marc Valin12b22482008-06-16 14:13:05 +1000675 int transient_time;
Jean-Marc Valin528f4b82008-06-29 03:46:39 +1000676 int transient_shift;
Jean-Marc Valinb8ba70c2010-04-18 22:10:24 -0400677 int resynth;
Jean-Marc Valin80ed1472009-10-15 21:45:32 -0400678 const int C = CHANNELS(st->channels);
Jean-Marc Valinaa936252009-05-29 22:14:20 -0400679 int mdct_weight_shift = 0;
680 int mdct_weight_pos=0;
Jean-Marc Valinab220aa2009-09-15 22:38:40 -0400681 int gain_id=0;
Jean-Marc Valin92ae3702009-09-16 07:57:17 -0400682 int norm_rate;
Jean-Marc Valin017fa852010-05-06 22:11:48 -0400683 int LM, M;
Jean-Marc Valin8cc945c2010-05-29 08:07:18 -0400684 celt_int32 vbr_rate=0;
Jean-Marc Valin8600f692008-02-29 15:14:12 +1100685 SAVE_STACK;
Jean-Marc Valin44ffd5a2008-02-22 00:39:25 +1100686
Gregory Maxwell17169992009-06-04 15:15:34 -0400687 if (check_encoder(st) != CELT_OK)
688 return CELT_INVALID_STATE;
689
Jean-Marc Valin44ffd5a2008-02-22 00:39:25 +1100690 if (check_mode(st->mode) != CELT_OK)
691 return CELT_INVALID_MODE;
692
Gregory Maxwell0719f6f2009-07-09 17:07:24 -0400693 if (nbCompressedBytes<0 || pcm==NULL)
Jean-Marc Valin017fa852010-05-06 22:11:48 -0400694 return CELT_BAD_ARG;
Gregory Maxwell520eeae2009-02-09 01:33:21 -0500695
Jean-Marc Valin017fa852010-05-06 22:11:48 -0400696 for (LM=0;LM<4;LM++)
697 if (st->mode->shortMdctSize<<LM==frame_size)
698 break;
699 if (LM>=MAX_CONFIG_SIZES)
700 return CELT_BAD_ARG;
701 M=1<<LM;
Jean-Marc Valin56522ad2009-06-05 17:17:25 -0400702 /* The memset is important for now in case the encoder doesn't
703 fill up all the bytes */
Jean-Marc Valin8679a802008-10-18 07:44:35 -0400704 CELT_MEMSET(compressed, 0, nbCompressedBytes);
Jean-Marc Valin8679a802008-10-18 07:44:35 -0400705
Jean-Marc Valin4794f2e2010-05-19 11:56:57 -0400706 if (enc==NULL)
707 {
708 ec_byte_writeinit_buffer(&buf, compressed, nbCompressedBytes);
709 ec_enc_init(&_enc,&buf);
710 enc = &_enc;
711 }
Jean-Marc Valin04752672010-05-05 07:21:21 -0400712 N = M*st->mode->shortMdctSize;
Jean-Marc Valina536f772008-03-22 09:01:50 +1100713 N4 = (N-st->overlap)>>1;
Jean-Marc Valin234969c2009-10-17 22:12:42 -0400714 ALLOC(in, 2*C*N-2*C*N4, celt_sig);
Jean-Marc Valina5431bf2008-01-03 20:53:01 +1100715
Jean-Marc Valinbdb58832008-04-20 17:42:10 +1000716 CELT_COPY(in, st->in_mem, C*st->overlap);
Jean-Marc Valinffa13472007-12-10 16:54:17 +1100717 for (c=0;c<C;c++)
Jean-Marc Valin6f7e83d2007-12-01 00:36:41 +1100718 {
Jean-Marc Valin234969c2009-10-17 22:12:42 -0400719 const celt_word16 * restrict pcmp = pcm+c;
720 celt_sig * restrict inp = in+C*st->overlap+c;
Jean-Marc Valinb886ddc2008-03-25 14:38:55 +1100721 for (i=0;i<N;i++)
Jean-Marc Valinffa13472007-12-10 16:54:17 +1100722 {
Jean-Marc Valin62290062008-04-20 22:16:02 +1000723 /* Apply pre-emphasis */
Jean-Marc Valin234969c2009-10-17 22:12:42 -0400724 celt_sig tmp = SCALEIN(SHL32(EXTEND32(*pcmp), SIG_SHIFT));
Jean-Marc Valin5c3bc672008-08-28 23:34:24 -0400725 *inp = SUB32(tmp, SHR32(MULT16_16(preemph,st->preemph_memE[c]),3));
Gregory Maxwell5f2a74b2008-08-11 23:50:07 -0400726 st->preemph_memE[c] = SCALEIN(*pcmp);
Jean-Marc Valin62290062008-04-20 22:16:02 +1000727 inp += C;
728 pcmp += C;
Jean-Marc Valinffa13472007-12-10 16:54:17 +1100729 }
Jean-Marc Valin6f7e83d2007-12-01 00:36:41 +1100730 }
Jean-Marc Valinbdb58832008-04-20 17:42:10 +1000731 CELT_COPY(st->in_mem, in+C*(2*N-2*N4-st->overlap), C*st->overlap);
Jean-Marc Valin2014ca32009-06-18 23:33:04 -0400732
Jean-Marc Valin37ab9c62008-11-08 09:14:38 -0500733 /* Transient handling */
Jean-Marc Valin2014ca32009-06-18 23:33:04 -0400734 transient_time = -1;
735 transient_shift = 0;
Jean-Marc Valin3b918ba2010-05-05 00:02:26 -0400736 isTransient = 0;
Jean-Marc Valin2014ca32009-06-18 23:33:04 -0400737
Jean-Marc Valind56c6102010-05-07 20:30:22 -0400738 resynth = st->pitch_available>0 || optional_resynthesis!=NULL;
Jean-Marc Valinb8ba70c2010-04-18 22:10:24 -0400739
Jean-Marc Valinbdb58712010-05-28 18:58:42 -0400740 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 +1000741 {
Jean-Marc Valin7028d622008-07-10 23:06:58 -0400742#ifndef FIXED_POINT
Jean-Marc Valin2014ca32009-06-18 23:33:04 -0400743 float gain_1;
Jean-Marc Valin528f4b82008-06-29 03:46:39 +1000744#endif
Jean-Marc Valin2014ca32009-06-18 23:33:04 -0400745 /* Apply the inverse shaping window */
746 if (transient_shift)
747 {
Jean-Marc Valin7028d622008-07-10 23:06:58 -0400748#ifdef FIXED_POINT
Jean-Marc Valin2014ca32009-06-18 23:33:04 -0400749 for (c=0;c<C;c++)
750 for (i=0;i<16;i++)
751 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]);
752 for (c=0;c<C;c++)
753 for (i=transient_time;i<N+st->overlap;i++)
754 in[C*i+c] = SHR32(in[C*i+c], transient_shift);
Jean-Marc Valin7028d622008-07-10 23:06:58 -0400755#else
Jean-Marc Valin2014ca32009-06-18 23:33:04 -0400756 for (c=0;c<C;c++)
757 for (i=0;i<16;i++)
758 in[C*(transient_time+i-16)+c] /= 1+transientWindow[i]*((1<<transient_shift)-1);
759 gain_1 = 1./(1<<transient_shift);
760 for (c=0;c<C;c++)
761 for (i=transient_time;i<N+st->overlap;i++)
762 in[C*i+c] *= gain_1;
Jean-Marc Valin7028d622008-07-10 23:06:58 -0400763#endif
Jean-Marc Valin528f4b82008-06-29 03:46:39 +1000764 }
Jean-Marc Valin3b918ba2010-05-05 00:02:26 -0400765 isTransient = 1;
Jean-Marc Valin2014ca32009-06-18 23:33:04 -0400766 has_fold = 1;
Jean-Marc Valin12b22482008-06-16 14:13:05 +1000767 }
Jean-Marc Valinc5f2a9d2008-10-26 22:00:26 -0400768
Jean-Marc Valin3b918ba2010-05-05 00:02:26 -0400769 if (isTransient)
770 shortBlocks = M;
771 else
772 shortBlocks = 0;
773
Jean-Marc Valin234969c2009-10-17 22:12:42 -0400774 ALLOC(freq, C*N, celt_sig); /**< Interleaved signal MDCTs */
775 ALLOC(bandE,st->mode->nbEBands*C, celt_ener);
776 ALLOC(bandLogE,st->mode->nbEBands*C, celt_word16);
Jean-Marc Valin32ec58c2009-05-01 21:28:58 -0400777 /* Compute MDCTs */
Jean-Marc Valin017fa852010-05-06 22:11:48 -0400778 compute_mdcts(st->mode, shortBlocks, in, freq, C, LM);
Jean-Marc Valin08a82ff2009-06-14 14:05:19 -0400779
Jean-Marc Valinaa936252009-05-29 22:14:20 -0400780
Jean-Marc Valin30f7f812009-10-17 14:35:13 -0400781 norm_rate = (nbCompressedBytes-5)*8*(celt_uint32)st->mode->Fs/(C*N)>>10;
Jean-Marc Valinddb181b2008-03-03 14:53:47 +1100782 /* Pitch analysis: we do it early to save on the peak stack space */
Jean-Marc Valin56522ad2009-06-05 17:17:25 -0400783 /* Don't use pitch if there isn't enough data available yet,
784 or if we're using shortBlocks */
Jean-Marc Valine6d832a2009-07-08 22:21:31 -0400785 has_pitch = st->pitch_enabled && st->pitch_permitted && (N <= 512)
Jean-Marc Valin92ae3702009-09-16 07:57:17 -0400786 && (st->pitch_available >= MAX_PERIOD) && (!shortBlocks)
787 && norm_rate < 50;
Gregory Maxwell98046ca2008-12-13 20:42:03 -0500788 if (has_pitch)
Jean-Marc Valinc5f2a9d2008-10-26 22:00:26 -0400789 {
Jean-Marc Valine465c142009-11-26 00:39:36 -0500790 VARDECL(celt_word16, x_lp);
Jean-Marc Valind5f99302009-12-16 22:42:32 -0500791 SAVE_STACK;
Jean-Marc Valine465c142009-11-26 00:39:36 -0500792 ALLOC(x_lp, (2*N-2*N4)>>1, celt_word16);
793 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 -0400794 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 -0500795 RESTORE_STACK;
Jean-Marc Valinc5f2a9d2008-10-26 22:00:26 -0400796 }
Jean-Marc Valin37ab9c62008-11-08 09:14:38 -0500797
Jean-Marc Valin56522ad2009-06-05 17:17:25 -0400798 /* Deferred allocation after find_spectral_pitch() to reduce
799 the peak memory usage */
Jean-Marc Valin234969c2009-10-17 22:12:42 -0400800 ALLOC(X, C*N, celt_norm); /**< Interleaved normalised MDCTs */
Jean-Marc Valin8d4ac152008-02-29 17:24:02 +1100801
Jean-Marc Valin234969c2009-10-17 22:12:42 -0400802 ALLOC(pitch_freq, C*N, celt_sig); /**< Interleaved signal MDCTs */
Jean-Marc Valin4c77ea92009-09-14 22:50:41 -0400803 if (has_pitch)
804 {
Jean-Marc Valin017fa852010-05-06 22:11:48 -0400805 compute_mdcts(st->mode, 0, st->out_mem+pitch_index*C, pitch_freq, C, LM);
Jean-Marc Valince4dd362010-05-07 07:45:18 -0400806 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 -0400807 }
808
809 if (has_pitch)
Jean-Marc Valince4dd362010-05-07 07:45:18 -0400810 apply_pitch(st->mode, freq, pitch_freq, gain_id, 1, C, M);
Jean-Marc Valin6c245242007-12-29 23:27:42 +1100811
Jean-Marc Valin65ee67a2010-04-26 07:08:44 -0400812 compute_band_energies(st->mode, freq, bandE, C, M);
Jean-Marc Valin4c77ea92009-09-14 22:50:41 -0400813 for (i=0;i<st->mode->nbEBands*C;i++)
814 bandLogE[i] = amp2Log(bandE[i]);
Jean-Marc Valinbd5d54a2009-10-20 00:25:31 -0400815
Jean-Marc Valin8ebd3452007-11-29 20:17:32 +1100816 /* Band normalisation */
Jean-Marc Valin65ee67a2010-04-26 07:08:44 -0400817 normalise_bands(st->mode, freq, X, bandE, C, M);
818 if (!shortBlocks && !folding_decision(st->mode, X, &st->tonal_average, &st->fold_decision, C, M))
Jean-Marc Valin527db5c2009-06-02 07:56:19 -0400819 has_fold = 0;
Jean-Marc Valin26c9e142007-12-31 21:27:54 +1100820
Jean-Marc Valin4c77ea92009-09-14 22:50:41 -0400821 /* Don't use intra energy when we're operating at low bit-rate */
822 intra_ener = st->force_intra || (!has_pitch && st->delayedIntra && nbCompressedBytes > st->mode->nbEBands);
823 if (shortBlocks || intra_decision(bandLogE, st->oldBandE, st->mode->nbEBands))
824 st->delayedIntra = 1;
825 else
826 st->delayedIntra = 0;
827
Jean-Marc Valin65ee67a2010-04-26 07:08:44 -0400828 NN = M*st->mode->eBands[st->mode->nbEBands];
Jean-Marc Valin9f89cab2010-05-21 14:18:38 -0400829 if (shortBlocks && !transient_shift)
Jean-Marc Valin88619552009-10-04 21:35:36 -0400830 {
Jean-Marc Valin234969c2009-10-17 22:12:42 -0400831 celt_word32 sum[8]={1,1,1,1,1,1,1,1};
Jean-Marc Valin88619552009-10-04 21:35:36 -0400832 int m;
833 for (c=0;c<C;c++)
834 {
835 m=0;
836 do {
Jean-Marc Valin234969c2009-10-17 22:12:42 -0400837 celt_word32 tmp=0;
Jean-Marc Valin3b918ba2010-05-05 00:02:26 -0400838 for (i=m+c*N;i<c*N+NN;i+=M)
Jean-Marc Valin88619552009-10-04 21:35:36 -0400839 tmp += ABS32(X[i]);
840 sum[m++] += tmp;
Jean-Marc Valin3b918ba2010-05-05 00:02:26 -0400841 } while (m<M);
Jean-Marc Valin88619552009-10-04 21:35:36 -0400842 }
843 m=0;
844#ifdef FIXED_POINT
845 do {
846 if (SHR32(sum[m+1],3) > sum[m])
847 {
848 mdct_weight_shift=2;
849 mdct_weight_pos = m;
850 } else if (SHR32(sum[m+1],1) > sum[m] && mdct_weight_shift < 2)
851 {
852 mdct_weight_shift=1;
853 mdct_weight_pos = m;
854 }
855 m++;
Jean-Marc Valin3b918ba2010-05-05 00:02:26 -0400856 } while (m<M-1);
Jean-Marc Valin88619552009-10-04 21:35:36 -0400857#else
858 do {
859 if (sum[m+1] > 8*sum[m])
860 {
861 mdct_weight_shift=2;
862 mdct_weight_pos = m;
863 } else if (sum[m+1] > 2*sum[m] && mdct_weight_shift < 2)
864 {
865 mdct_weight_shift=1;
866 mdct_weight_pos = m;
867 }
868 m++;
Jean-Marc Valin3b918ba2010-05-05 00:02:26 -0400869 } while (m<M-1);
Jean-Marc Valin88619552009-10-04 21:35:36 -0400870#endif
871 if (mdct_weight_shift)
Jean-Marc Valin3b918ba2010-05-05 00:02:26 -0400872 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 -0400873 }
874
Jean-Marc Valin4c77ea92009-09-14 22:50:41 -0400875
Jean-Marc Valin4794f2e2010-05-19 11:56:57 -0400876 encode_flags(enc, intra_ener, has_pitch, shortBlocks, has_fold);
Jean-Marc Valin05ed03e2009-04-29 07:44:13 -0400877 if (has_pitch)
878 {
Jean-Marc Valin4794f2e2010-05-19 11:56:57 -0400879 ec_enc_uint(enc, pitch_index, MAX_PERIOD-(2*N-2*N4));
880 ec_enc_uint(enc, gain_id, 16);
Jean-Marc Valin96870d92007-12-05 21:14:22 +1100881 }
Jean-Marc Valin05ed03e2009-04-29 07:44:13 -0400882 if (shortBlocks)
883 {
Jean-Marc Valin05ed03e2009-04-29 07:44:13 -0400884 if (transient_shift)
Jean-Marc Valinaa936252009-05-29 22:14:20 -0400885 {
Jean-Marc Valin4794f2e2010-05-19 11:56:57 -0400886 ec_enc_uint(enc, transient_shift, 4);
887 ec_enc_uint(enc, transient_time, N+st->overlap);
Jean-Marc Valinaa936252009-05-29 22:14:20 -0400888 } else {
Jean-Marc Valin4794f2e2010-05-19 11:56:57 -0400889 ec_enc_uint(enc, mdct_weight_shift, 4);
Jean-Marc Valin3b918ba2010-05-05 00:02:26 -0400890 if (mdct_weight_shift && M!=2)
Jean-Marc Valin4794f2e2010-05-19 11:56:57 -0400891 ec_enc_uint(enc, mdct_weight_pos, M-1);
Jean-Marc Valinaa936252009-05-29 22:14:20 -0400892 }
Jean-Marc Valin05ed03e2009-04-29 07:44:13 -0400893 }
Jean-Marc Valinc890b582008-08-01 22:26:49 -0400894
Jean-Marc Valin6775de32008-08-02 08:14:42 -0400895 ALLOC(fine_quant, st->mode->nbEBands, int);
Jean-Marc Valin8dff9232008-08-13 22:07:20 -0400896 ALLOC(pulses, st->mode->nbEBands, int);
Jean-Marc Valin37ab9c62008-11-08 09:14:38 -0500897
Jean-Marc Valin8cc945c2010-05-29 08:07:18 -0400898 vbr_rate = M*st->vbr_rate_norm;
Jean-Marc Valin25767d12009-10-21 23:24:18 -0400899 /* Computes the max bit-rate allowed in VBR more to avoid busting the budget */
Jean-Marc Valin8cc945c2010-05-29 08:07:18 -0400900 if (st->vbr_rate_norm>0)
Jean-Marc Valin25767d12009-10-21 23:24:18 -0400901 {
902 celt_int32 vbr_bound, max_allowed;
903
Jean-Marc Valin8cc945c2010-05-29 08:07:18 -0400904 vbr_bound = vbr_rate;
905 max_allowed = (vbr_rate + vbr_bound - st->vbr_reservoir)>>(BITRES+3);
Jean-Marc Valin7a047ea2009-10-22 00:23:56 -0400906 if (max_allowed < 4)
907 max_allowed = 4;
Jean-Marc Valin25767d12009-10-21 23:24:18 -0400908 if (max_allowed < nbCompressedBytes)
909 nbCompressedBytes = max_allowed;
910 }
911
Jean-Marc Valin163b76e2010-05-27 23:56:53 -0400912 ALLOC(tf_res, st->mode->nbEBands, int);
Jean-Marc Valin0a571ef2010-06-05 23:12:19 -0400913 tf_analysis(bandLogE, st->oldBandE, st->mode->nbEBands, C, isTransient, tf_res, nbCompressedBytes);
Jean-Marc Valin163b76e2010-05-27 23:56:53 -0400914
Jean-Marc Valin37ab9c62008-11-08 09:14:38 -0500915 /* Bit allocation */
Jean-Marc Valin234969c2009-10-17 22:12:42 -0400916 ALLOC(error, C*st->mode->nbEBands, celt_word16);
Jean-Marc Valin5f961462010-05-19 13:38:10 -0400917 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 -0400918 coarse_needed = ((coarse_needed*3-1)>>3)+1;
Jean-Marc Valin25767d12009-10-21 23:24:18 -0400919 if (coarse_needed > nbCompressedBytes)
920 coarse_needed = nbCompressedBytes;
Gregory Maxwell888d8ce2009-05-21 04:21:53 -0400921 /* Variable bitrate */
Jean-Marc Valin8cc945c2010-05-29 08:07:18 -0400922 if (vbr_rate>0)
Gregory Maxwell888d8ce2009-05-21 04:21:53 -0400923 {
Jean-Marc Valinbd5d54a2009-10-20 00:25:31 -0400924 celt_word16 alpha;
Jean-Marc Valin25767d12009-10-21 23:24:18 -0400925 celt_int32 delta;
Gregory Maxwell888d8ce2009-05-21 04:21:53 -0400926 /* The target rate in 16th bits per frame */
Jean-Marc Valin8cc945c2010-05-29 08:07:18 -0400927 celt_int32 target=vbr_rate;
Jean-Marc Valin6775de32008-08-02 08:14:42 -0400928
Jean-Marc Valin56522ad2009-06-05 17:17:25 -0400929 /* Shortblocks get a large boost in bitrate, but since they
930 are uncommon long blocks are not greatly effected */
Gregory Maxwell888d8ce2009-05-21 04:21:53 -0400931 if (shortBlocks)
932 target*=2;
Jean-Marc Valin3b918ba2010-05-05 00:02:26 -0400933 else if (M > 1)
Jean-Marc Valinbd5d54a2009-10-20 00:25:31 -0400934 target-=(target+14)/28;
Gregory Maxwell888d8ce2009-05-21 04:21:53 -0400935
Jean-Marc Valin56522ad2009-06-05 17:17:25 -0400936 /* The average energy is removed from the target and the actual
937 energy added*/
Jean-Marc Valin4794f2e2010-05-19 11:56:57 -0400938 target=target+st->vbr_offset-588+ec_enc_tell(enc, BITRES);
Gregory Maxwell888d8ce2009-05-21 04:21:53 -0400939
940 /* In VBR mode the frame size must not be reduced so much that it would result in the coarse energy busting its budget */
941 target=IMAX(coarse_needed,(target+64)/128);
Jean-Marc Valin45f11102009-10-22 00:12:31 -0400942 target=IMIN(nbCompressedBytes,target);
Jean-Marc Valinbd5d54a2009-10-20 00:25:31 -0400943 /* Make the adaptation coef (alpha) higher at the beginning */
944 if (st->vbr_count < 990)
945 {
946 st->vbr_count++;
947 alpha = celt_rcp(SHL32(EXTEND32(st->vbr_count+10),16));
948 /*printf ("%d %d\n", st->vbr_count+10, alpha);*/
949 } else
950 alpha = QCONST16(.001f,15);
951
952 /* By how much did we "miss" the target on that frame */
Jean-Marc Valin8cc945c2010-05-29 08:07:18 -0400953 delta = (8<<BITRES)*(celt_int32)target - vbr_rate;
Jean-Marc Valinbd5d54a2009-10-20 00:25:31 -0400954 /* How many bits have we used in excess of what we're allowed */
955 st->vbr_reservoir += delta;
956 /*printf ("%d\n", st->vbr_reservoir);*/
957
958 /* Compute the offset we need to apply in order to reach the target */
959 st->vbr_drift += MULT16_32_Q15(alpha,delta-st->vbr_offset-st->vbr_drift);
960 st->vbr_offset = -st->vbr_drift;
961 /*printf ("%d\n", st->vbr_drift);*/
962
963 /* We could use any multiple of vbr_rate as bound (depending on the delay) */
Jean-Marc Valin25767d12009-10-21 23:24:18 -0400964 if (st->vbr_reservoir < 0)
Jean-Marc Valinbd5d54a2009-10-20 00:25:31 -0400965 {
966 /* We're under the min value -- increase rate */
967 int adjust = 1-(st->vbr_reservoir-1)/(8<<BITRES);
968 st->vbr_reservoir += adjust*(8<<BITRES);
Jean-Marc Valin45f11102009-10-22 00:12:31 -0400969 target += adjust;
Jean-Marc Valinbd5d54a2009-10-20 00:25:31 -0400970 /*printf ("+%d\n", adjust);*/
971 }
Jean-Marc Valin45f11102009-10-22 00:12:31 -0400972 if (target < nbCompressedBytes)
973 nbCompressedBytes = target;
Jean-Marc Valinbd5d54a2009-10-20 00:25:31 -0400974 /* This moves the raw bits to take into account the new compressed size */
Jean-Marc Valine6108642009-08-01 23:05:47 +0200975 ec_byte_shrink(&buf, nbCompressedBytes);
Gregory Maxwell888d8ce2009-05-21 04:21:53 -0400976 }
977
Jean-Marc Valin0a571ef2010-06-05 23:12:19 -0400978 tf_encode(st->mode->nbEBands, isTransient, tf_res, enc);
979
Jean-Marc Valin6775de32008-08-02 08:14:42 -0400980 ALLOC(offsets, st->mode->nbEBands, int);
Jean-Marc Valin52cb5fb2009-06-10 08:08:55 -0400981 ALLOC(fine_priority, st->mode->nbEBands, int);
Jean-Marc Valincb7a2a32008-02-11 16:44:48 +1100982
Jean-Marc Valin6775de32008-08-02 08:14:42 -0400983 for (i=0;i<st->mode->nbEBands;i++)
984 offsets[i] = 0;
Jean-Marc Valin4794f2e2010-05-19 11:56:57 -0400985 bits = nbCompressedBytes*8 - ec_enc_tell(enc, 0) - 1;
Jean-Marc Valin5f961462010-05-19 13:38:10 -0400986 compute_allocation(st->mode, st->start, offsets, bits, pulses, fine_quant, fine_priority, C, M);
Jean-Marc Valin37ab9c62008-11-08 09:14:38 -0500987
Jean-Marc Valin5f961462010-05-19 13:38:10 -0400988 quant_fine_energy(st->mode, st->start, bandE, st->oldBandE, error, fine_quant, enc, C);
Jean-Marc Valin6775de32008-08-02 08:14:42 -0400989
Jean-Marc Valin8ebd3452007-11-29 20:17:32 +1100990 /* Residual quantisation */
Jean-Marc Valin163b76e2010-05-27 23:56:53 -0400991 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 -0400992
Jean-Marc Valin5f961462010-05-19 13:38:10 -0400993 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 -0400994
Jean-Marc Valin37ab9c62008-11-08 09:14:38 -0500995 /* Re-synthesis of the coded audio if required */
Jean-Marc Valinb8ba70c2010-04-18 22:10:24 -0400996 if (resynth)
Jean-Marc Valin18ddc022008-02-22 14:24:50 +1100997 {
Gregory Maxwell98046ca2008-12-13 20:42:03 -0500998 if (st->pitch_available>0 && st->pitch_available<MAX_PERIOD)
Jean-Marc Valin04752672010-05-05 07:21:21 -0400999 st->pitch_available+=N;
Gregory Maxwell98046ca2008-12-13 20:42:03 -05001000
Jean-Marc Valinaa936252009-05-29 22:14:20 -04001001 if (mdct_weight_shift)
1002 {
Jean-Marc Valin3b918ba2010-05-05 00:02:26 -04001003 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 -04001004 }
Jean-Marc Valin88619552009-10-04 21:35:36 -04001005
1006 /* Synthesis */
Jean-Marc Valin65ee67a2010-04-26 07:08:44 -04001007 denormalise_bands(st->mode, X, freq, bandE, C, M);
Jean-Marc Valin88619552009-10-04 21:35:36 -04001008
1009 CELT_MOVE(st->out_mem, st->out_mem+C*N, C*(MAX_PERIOD+st->overlap-N));
1010
Jean-Marc Valin4c77ea92009-09-14 22:50:41 -04001011 if (has_pitch)
Jean-Marc Valince4dd362010-05-07 07:45:18 -04001012 apply_pitch(st->mode, freq, pitch_freq, gain_id, 0, C, M);
Jean-Marc Valin4c77ea92009-09-14 22:50:41 -04001013
Jean-Marc Valin017fa852010-05-06 22:11:48 -04001014 compute_inv_mdcts(st->mode, shortBlocks, freq, transient_time, transient_shift, st->out_mem, C, LM);
Jean-Marc Valine12017e2009-10-03 13:57:31 -04001015
Jean-Marc Valin56522ad2009-06-05 17:17:25 -04001016 /* De-emphasis and put everything back at the right place
1017 in the synthesis history */
Jean-Marc Valind56c6102010-05-07 20:30:22 -04001018 if (optional_resynthesis != NULL) {
1019 deemphasis(st->out_mem, optional_resynthesis, N, C, preemph, st->preemph_memD);
Jean-Marc Valine12017e2009-10-03 13:57:31 -04001020
Jean-Marc Valin6f7e83d2007-12-01 00:36:41 +11001021 }
Jean-Marc Valind9b95652008-08-31 23:34:47 -04001022 }
Gregory Maxwell54547f12009-02-16 18:56:44 -05001023
Jean-Marc Valin4794f2e2010-05-19 11:56:57 -04001024 ec_enc_done(enc);
Jean-Marc Valinc871c8d2009-06-09 00:57:00 -04001025
Jean-Marc Valin8600f692008-02-29 15:14:12 +11001026 RESTORE_STACK;
Jean-Marc Valina76a0b22008-01-17 22:43:05 +11001027 return nbCompressedBytes;
Jean-Marc Valin8ebd3452007-11-29 20:17:32 +11001028}
1029
Gregory Maxwell5f2a74b2008-08-11 23:50:07 -04001030#ifdef FIXED_POINT
1031#ifndef DISABLE_FLOAT_API
Jean-Marc Valin4794f2e2010-05-19 11:56:57 -04001032int 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 -04001033{
Jean-Marc Valin017fa852010-05-06 22:11:48 -04001034 int j, ret, C, N, LM, M;
Jean-Marc Valin30f7f812009-10-17 14:35:13 -04001035 VARDECL(celt_int16, in);
Jean-Marc Valincb8780c2009-07-20 23:40:35 -04001036 SAVE_STACK;
Gregory Maxwell17169992009-06-04 15:15:34 -04001037
1038 if (check_encoder(st) != CELT_OK)
1039 return CELT_INVALID_STATE;
1040
1041 if (check_mode(st->mode) != CELT_OK)
1042 return CELT_INVALID_MODE;
1043
Gregory Maxwell0719f6f2009-07-09 17:07:24 -04001044 if (pcm==NULL)
1045 return CELT_BAD_ARG;
1046
Jean-Marc Valin017fa852010-05-06 22:11:48 -04001047 for (LM=0;LM<4;LM++)
1048 if (st->mode->shortMdctSize<<LM==frame_size)
1049 break;
1050 if (LM>=MAX_CONFIG_SIZES)
1051 return CELT_BAD_ARG;
1052 M=1<<LM;
1053
Jean-Marc Valin80ed1472009-10-15 21:45:32 -04001054 C = CHANNELS(st->channels);
Jean-Marc Valin017fa852010-05-06 22:11:48 -04001055 N = M*st->mode->shortMdctSize;
Jean-Marc Valin30f7f812009-10-17 14:35:13 -04001056 ALLOC(in, C*N, celt_int16);
Gregory Maxwell5f2a74b2008-08-11 23:50:07 -04001057
1058 for (j=0;j<C*N;j++)
1059 in[j] = FLOAT2INT16(pcm[j]);
1060
Jean-Marc Valin4794f2e2010-05-19 11:56:57 -04001061 if (optional_resynthesis != NULL) {
1062 ret=celt_encode_with_ec(st,in,in,frame_size,compressed,nbCompressedBytes, enc);
Gregory Maxwellb0a73a02008-12-12 16:54:25 -05001063 for (j=0;j<C*N;j++)
Jean-Marc Valin4794f2e2010-05-19 11:56:57 -04001064 optional_resynthesis[j]=in[j]*(1/32768.);
Gregory Maxwell82595312008-09-30 18:20:14 -04001065 } else {
Jean-Marc Valin4794f2e2010-05-19 11:56:57 -04001066 ret=celt_encode_with_ec(st,in,NULL,frame_size,compressed,nbCompressedBytes, enc);
Gregory Maxwell82595312008-09-30 18:20:14 -04001067 }
Wessel Lubberhuizen33ba6cc2008-10-03 07:09:29 -04001068 RESTORE_STACK;
Gregory Maxwell5f2a74b2008-08-11 23:50:07 -04001069 return ret;
1070
1071}
1072#endif /*DISABLE_FLOAT_API*/
1073#else
Jean-Marc Valin4794f2e2010-05-19 11:56:57 -04001074int 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 -04001075{
Jean-Marc Valin017fa852010-05-06 22:11:48 -04001076 int j, ret, C, N, LM, M;
Jean-Marc Valin234969c2009-10-17 22:12:42 -04001077 VARDECL(celt_sig, in);
Jean-Marc Valincb8780c2009-07-20 23:40:35 -04001078 SAVE_STACK;
Gregory Maxwell17169992009-06-04 15:15:34 -04001079
1080 if (check_encoder(st) != CELT_OK)
1081 return CELT_INVALID_STATE;
1082
1083 if (check_mode(st->mode) != CELT_OK)
1084 return CELT_INVALID_MODE;
1085
Gregory Maxwell0719f6f2009-07-09 17:07:24 -04001086 if (pcm==NULL)
1087 return CELT_BAD_ARG;
1088
Jean-Marc Valin017fa852010-05-06 22:11:48 -04001089 for (LM=0;LM<4;LM++)
1090 if (st->mode->shortMdctSize<<LM==frame_size)
1091 break;
1092 if (LM>=MAX_CONFIG_SIZES)
1093 return CELT_BAD_ARG;
1094 M=1<<LM;
1095
Jean-Marc Valin80ed1472009-10-15 21:45:32 -04001096 C=CHANNELS(st->channels);
Jean-Marc Valin04752672010-05-05 07:21:21 -04001097 N=M*st->mode->shortMdctSize;
Jean-Marc Valin234969c2009-10-17 22:12:42 -04001098 ALLOC(in, C*N, celt_sig);
Gregory Maxwell5f2a74b2008-08-11 23:50:07 -04001099 for (j=0;j<C*N;j++) {
1100 in[j] = SCALEOUT(pcm[j]);
1101 }
Gregory Maxwell5f2a74b2008-08-11 23:50:07 -04001102
Jean-Marc Valind56c6102010-05-07 20:30:22 -04001103 if (optional_resynthesis != NULL) {
Jean-Marc Valin4794f2e2010-05-19 11:56:57 -04001104 ret = celt_encode_with_ec_float(st,in,in,frame_size,compressed,nbCompressedBytes, enc);
Gregory Maxwell82595312008-09-30 18:20:14 -04001105 for (j=0;j<C*N;j++)
Jean-Marc Valind56c6102010-05-07 20:30:22 -04001106 optional_resynthesis[j] = FLOAT2INT16(in[j]);
Gregory Maxwell82595312008-09-30 18:20:14 -04001107 } else {
Jean-Marc Valin4794f2e2010-05-19 11:56:57 -04001108 ret = celt_encode_with_ec_float(st,in,NULL,frame_size,compressed,nbCompressedBytes, enc);
Gregory Maxwell82595312008-09-30 18:20:14 -04001109 }
Wessel Lubberhuizen33ba6cc2008-10-03 07:09:29 -04001110 RESTORE_STACK;
Gregory Maxwell5f2a74b2008-08-11 23:50:07 -04001111 return ret;
1112}
1113#endif
Jean-Marc Valin6e9058a2007-12-07 14:59:06 +11001114
Jean-Marc Valind56c6102010-05-07 20:30:22 -04001115int celt_encode(CELTEncoder * restrict st, const celt_int16 * pcm, int frame_size, unsigned char *compressed, int nbCompressedBytes)
1116{
Jean-Marc Valin4794f2e2010-05-19 11:56:57 -04001117 return celt_encode_with_ec(st, pcm, NULL, frame_size, compressed, nbCompressedBytes, NULL);
Jean-Marc Valind56c6102010-05-07 20:30:22 -04001118}
1119
1120int celt_encode_float(CELTEncoder * restrict st, const float * pcm, int frame_size, unsigned char *compressed, int nbCompressedBytes)
1121{
Jean-Marc Valin4794f2e2010-05-19 11:56:57 -04001122 return celt_encode_with_ec_float(st, pcm, NULL, frame_size, compressed, nbCompressedBytes, NULL);
Jean-Marc Valind56c6102010-05-07 20:30:22 -04001123}
1124
Jean-Marc Valin4794f2e2010-05-19 11:56:57 -04001125int celt_encode_resynthesis(CELTEncoder * restrict st, const celt_int16 * pcm, celt_int16 * optional_resynthesis, int frame_size, unsigned char *compressed, int nbCompressedBytes)
1126{
1127 return celt_encode_with_ec(st, pcm, optional_resynthesis, frame_size, compressed, nbCompressedBytes, NULL);
1128}
1129
1130int celt_encode_resynthesis_float(CELTEncoder * restrict st, const float * pcm, float * optional_resynthesis, int frame_size, unsigned char *compressed, int nbCompressedBytes)
1131{
1132 return celt_encode_with_ec_float(st, pcm, optional_resynthesis, frame_size, compressed, nbCompressedBytes, NULL);
1133}
1134
1135
Jean-Marc Valinb6f90612008-10-05 22:39:13 -04001136int celt_encoder_ctl(CELTEncoder * restrict st, int request, ...)
Jean-Marc Valinc18fb1d2008-09-30 07:36:54 -04001137{
Jean-Marc Valinb6f90612008-10-05 22:39:13 -04001138 va_list ap;
Gregory Maxwell17169992009-06-04 15:15:34 -04001139
1140 if (check_encoder(st) != CELT_OK)
1141 return CELT_INVALID_STATE;
1142
Jean-Marc Valinb6f90612008-10-05 22:39:13 -04001143 va_start(ap, request);
Gregory Maxwell17169992009-06-04 15:15:34 -04001144 if ((request!=CELT_GET_MODE_REQUEST) && (check_mode(st->mode) != CELT_OK))
1145 goto bad_mode;
Jean-Marc Valinc18fb1d2008-09-30 07:36:54 -04001146 switch (request)
1147 {
Gregory Maxwellf3b44ef2009-06-03 13:37:45 -04001148 case CELT_GET_MODE_REQUEST:
1149 {
1150 const CELTMode ** value = va_arg(ap, const CELTMode**);
1151 if (value==0)
1152 goto bad_arg;
1153 *value=st->mode;
1154 }
1155 break;
Jean-Marc Valinb6f90612008-10-05 22:39:13 -04001156 case CELT_SET_COMPLEXITY_REQUEST:
Jean-Marc Valinc18fb1d2008-09-30 07:36:54 -04001157 {
Jean-Marc Valin30f7f812009-10-17 14:35:13 -04001158 int value = va_arg(ap, celt_int32);
Jean-Marc Valinb6f90612008-10-05 22:39:13 -04001159 if (value<0 || value>10)
1160 goto bad_arg;
Gregory Maxwell98046ca2008-12-13 20:42:03 -05001161 if (value<=2) {
1162 st->pitch_enabled = 0;
1163 st->pitch_available = 0;
1164 } else {
1165 st->pitch_enabled = 1;
1166 if (st->pitch_available<1)
1167 st->pitch_available = 1;
1168 }
1169 }
1170 break;
Jean-Marc Valin5f961462010-05-19 13:38:10 -04001171 case CELT_SET_START_BAND_REQUEST:
1172 {
1173 celt_int32 value = va_arg(ap, celt_int32);
1174 if (value<0 || value>=st->mode->nbEBands)
1175 goto bad_arg;
1176 st->start = value;
1177 }
1178 break;
Gregory Maxwell2dd3d322009-06-05 14:05:51 -04001179 case CELT_SET_PREDICTION_REQUEST:
Gregory Maxwell98046ca2008-12-13 20:42:03 -05001180 {
Jean-Marc Valin30f7f812009-10-17 14:35:13 -04001181 int value = va_arg(ap, celt_int32);
Gregory Maxwell2dd3d322009-06-05 14:05:51 -04001182 if (value<0 || value>2)
Gregory Maxwell98046ca2008-12-13 20:42:03 -05001183 goto bad_arg;
1184 if (value==0)
Gregory Maxwell2dd3d322009-06-05 14:05:51 -04001185 {
1186 st->force_intra = 1;
1187 st->pitch_permitted = 0;
Gregory Maxwella80958b2009-06-29 12:48:57 -04001188 } else if (value==1) {
Gregory Maxwell2dd3d322009-06-05 14:05:51 -04001189 st->force_intra = 0;
1190 st->pitch_permitted = 0;
1191 } else {
1192 st->force_intra = 0;
1193 st->pitch_permitted = 1;
1194 }
Jean-Marc Valinc18fb1d2008-09-30 07:36:54 -04001195 }
1196 break;
Gregory Maxwell888d8ce2009-05-21 04:21:53 -04001197 case CELT_SET_VBR_RATE_REQUEST:
1198 {
Jean-Marc Valin30f7f812009-10-17 14:35:13 -04001199 celt_int32 value = va_arg(ap, celt_int32);
Jean-Marc Valin8cc945c2010-05-29 08:07:18 -04001200 int frame_rate;
1201 int N = st->mode->shortMdctSize;
Gregory Maxwell888d8ce2009-05-21 04:21:53 -04001202 if (value<0)
1203 goto bad_arg;
1204 if (value>3072000)
1205 value = 3072000;
Jean-Marc Valin8cc945c2010-05-29 08:07:18 -04001206 frame_rate = ((st->mode->Fs<<3)+(N>>1))/N;
1207 st->vbr_rate_norm = ((value<<(BITRES+3))+(frame_rate>>1))/frame_rate;
Gregory Maxwell888d8ce2009-05-21 04:21:53 -04001208 }
1209 break;
John Ridges454d1d02009-05-21 22:38:39 -04001210 case CELT_RESET_STATE:
1211 {
1212 const CELTMode *mode = st->mode;
Jean-Marc Valin80ed1472009-10-15 21:45:32 -04001213 int C = st->channels;
John Ridges454d1d02009-05-21 22:38:39 -04001214
1215 if (st->pitch_available > 0) st->pitch_available = 1;
1216
1217 CELT_MEMSET(st->in_mem, 0, st->overlap*C);
1218 CELT_MEMSET(st->out_mem, 0, (MAX_PERIOD+st->overlap)*C);
1219
1220 CELT_MEMSET(st->oldBandE, 0, C*mode->nbEBands);
1221
1222 CELT_MEMSET(st->preemph_memE, 0, C);
1223 CELT_MEMSET(st->preemph_memD, 0, C);
1224 st->delayedIntra = 1;
John Ridges5378bf82010-02-12 07:08:01 -05001225
1226 st->fold_decision = 1;
Jean-Marc Valin628c0252010-04-16 20:57:56 -04001227 st->tonal_average = QCONST16(1.f,8);
John Ridges5378bf82010-02-12 07:08:01 -05001228 st->gain_prod = 0;
1229 st->vbr_reservoir = 0;
1230 st->vbr_drift = 0;
1231 st->vbr_offset = 0;
1232 st->vbr_count = 0;
1233 st->xmem = 0;
Jean-Marc Valin9c30de52010-04-19 13:32:15 -04001234 st->frame_max = 0;
John Ridges5378bf82010-02-12 07:08:01 -05001235 CELT_MEMSET(st->pitch_buf, 0, (MAX_PERIOD>>1)+2);
John Ridges454d1d02009-05-21 22:38:39 -04001236 }
1237 break;
Jean-Marc Valinc18fb1d2008-09-30 07:36:54 -04001238 default:
Jean-Marc Valinb6f90612008-10-05 22:39:13 -04001239 goto bad_request;
Jean-Marc Valinc18fb1d2008-09-30 07:36:54 -04001240 }
Jean-Marc Valinb6f90612008-10-05 22:39:13 -04001241 va_end(ap);
Jean-Marc Valinc18fb1d2008-09-30 07:36:54 -04001242 return CELT_OK;
Gregory Maxwell17169992009-06-04 15:15:34 -04001243bad_mode:
1244 va_end(ap);
1245 return CELT_INVALID_MODE;
Jean-Marc Valinb6f90612008-10-05 22:39:13 -04001246bad_arg:
1247 va_end(ap);
1248 return CELT_BAD_ARG;
1249bad_request:
1250 va_end(ap);
1251 return CELT_UNIMPLEMENTED;
Jean-Marc Valinc18fb1d2008-09-30 07:36:54 -04001252}
1253
Jean-Marc Valin56522ad2009-06-05 17:17:25 -04001254/**********************************************************************/
1255/* */
1256/* DECODER */
1257/* */
1258/**********************************************************************/
Jean-Marc Valineafbdd52009-04-27 19:35:09 -04001259#ifdef NEW_PLC
1260#define DECODE_BUFFER_SIZE 2048
1261#else
1262#define DECODE_BUFFER_SIZE MAX_PERIOD
1263#endif
Jean-Marc Valin269d40a2007-12-07 11:29:45 +11001264
Gregory Maxwell17169992009-06-04 15:15:34 -04001265#define DECODERVALID 0x4c434454
1266#define DECODERPARTIAL 0x5444434c
1267#define DECODERFREED 0x4c004400
1268
Jean-Marc Valin276de722008-02-20 17:45:51 +11001269/** Decoder state
1270 @brief Decoder state
1271 */
Jean-Marc Valin269d40a2007-12-07 11:29:45 +11001272struct CELTDecoder {
Jean-Marc Valin30f7f812009-10-17 14:35:13 -04001273 celt_uint32 marker;
Jean-Marc Valin269d40a2007-12-07 11:29:45 +11001274 const CELTMode *mode;
Jean-Marc Valina5431bf2008-01-03 20:53:01 +11001275 int overlap;
Jean-Marc Valin80ed1472009-10-15 21:45:32 -04001276 int channels;
Jean-Marc Valina5431bf2008-01-03 20:53:01 +11001277
Jean-Marc Valin5f961462010-05-19 13:38:10 -04001278 int start, end;
Jean-Marc Valin269d40a2007-12-07 11:29:45 +11001279 ec_byte_buffer buf;
1280 ec_enc enc;
1281
Jean-Marc Valin234969c2009-10-17 22:12:42 -04001282 celt_sig * restrict preemph_memD;
Jean-Marc Valin81b38c22008-02-29 21:08:49 +11001283
Jean-Marc Valin234969c2009-10-17 22:12:42 -04001284 celt_sig *out_mem;
1285 celt_sig *decode_mem;
Jean-Marc Valin269d40a2007-12-07 11:29:45 +11001286
Jean-Marc Valin234969c2009-10-17 22:12:42 -04001287 celt_word16 *oldBandE;
Jean-Marc Valinfb83fb42007-12-08 00:56:04 +11001288
Jean-Marc Valind69c1cb2009-12-28 00:34:29 -05001289#ifdef NEW_PLC
Jean-Marc Valin74128be2010-01-01 09:33:17 -05001290 celt_word16 *lpc;
Jean-Marc Valin5a0fae52009-12-14 21:19:37 -05001291#endif
1292
Jean-Marc Valinfb83fb42007-12-08 00:56:04 +11001293 int last_pitch_index;
Jean-Marc Valin0f0da992009-08-12 21:34:01 -04001294 int loss_count;
Jean-Marc Valin269d40a2007-12-07 11:29:45 +11001295};
1296
Gregory Maxwell17169992009-06-04 15:15:34 -04001297int check_decoder(const CELTDecoder *st)
1298{
1299 if (st==NULL)
1300 {
1301 celt_warning("NULL passed a decoder structure");
1302 return CELT_INVALID_STATE;
1303 }
1304 if (st->marker == DECODERVALID)
1305 return CELT_OK;
1306 if (st->marker == DECODERFREED)
1307 celt_warning("Referencing a decoder that has already been freed");
1308 else
1309 celt_warning("This is not a valid CELT decoder structure");
1310 return CELT_INVALID_STATE;
1311}
1312
Jean-Marc Valin80ed1472009-10-15 21:45:32 -04001313CELTDecoder *celt_decoder_create(const CELTMode *mode, int channels, int *error)
Jean-Marc Valin269d40a2007-12-07 11:29:45 +11001314{
Jean-Marc Valin04752672010-05-05 07:21:21 -04001315 int C;
Jean-Marc Valin0bb05bc2008-02-20 13:43:40 +11001316 CELTDecoder *st;
Jean-Marc Valin44ffd5a2008-02-22 00:39:25 +11001317
1318 if (check_mode(mode) != CELT_OK)
Jean-Marc Valinece94a02009-10-16 07:30:14 -04001319 {
1320 if (error)
1321 *error = CELT_INVALID_MODE;
Jean-Marc Valin44ffd5a2008-02-22 00:39:25 +11001322 return NULL;
Jean-Marc Valinece94a02009-10-16 07:30:14 -04001323 }
Jean-Marc Valinbd5d54a2009-10-20 00:25:31 -04001324
Jean-Marc Valin80ed1472009-10-15 21:45:32 -04001325 if (channels < 0 || channels > 2)
1326 {
1327 celt_warning("Only mono and stereo supported");
1328 if (error)
1329 *error = CELT_BAD_ARG;
1330 return NULL;
1331 }
Jean-Marc Valin44ffd5a2008-02-22 00:39:25 +11001332
Jean-Marc Valin80ed1472009-10-15 21:45:32 -04001333 C = CHANNELS(channels);
Jean-Marc Valin0bb05bc2008-02-20 13:43:40 +11001334 st = celt_alloc(sizeof(CELTDecoder));
Gregory Maxwell17169992009-06-04 15:15:34 -04001335
1336 if (st==NULL)
Jean-Marc Valinece94a02009-10-16 07:30:14 -04001337 {
1338 if (error)
1339 *error = CELT_ALLOC_FAIL;
Gregory Maxwell17169992009-06-04 15:15:34 -04001340 return NULL;
Jean-Marc Valinece94a02009-10-16 07:30:14 -04001341 }
1342
Gregory Maxwell17169992009-06-04 15:15:34 -04001343 st->marker = DECODERPARTIAL;
Jean-Marc Valin269d40a2007-12-07 11:29:45 +11001344 st->mode = mode;
Jean-Marc Valina5431bf2008-01-03 20:53:01 +11001345 st->overlap = mode->overlap;
Jean-Marc Valin80ed1472009-10-15 21:45:32 -04001346 st->channels = channels;
Jean-Marc Valina5431bf2008-01-03 20:53:01 +11001347
Jean-Marc Valin5f961462010-05-19 13:38:10 -04001348 st->start = 0;
1349 st->end = st->mode->nbEBands;
1350
Jean-Marc Valin234969c2009-10-17 22:12:42 -04001351 st->decode_mem = celt_alloc((DECODE_BUFFER_SIZE+st->overlap)*C*sizeof(celt_sig));
Jean-Marc Valineafbdd52009-04-27 19:35:09 -04001352 st->out_mem = st->decode_mem+DECODE_BUFFER_SIZE-MAX_PERIOD;
Jean-Marc Valin269d40a2007-12-07 11:29:45 +11001353
Jean-Marc Valin234969c2009-10-17 22:12:42 -04001354 st->oldBandE = (celt_word16*)celt_alloc(C*mode->nbEBands*sizeof(celt_word16));
Gregory Maxwell17169992009-06-04 15:15:34 -04001355
Jean-Marc Valin234969c2009-10-17 22:12:42 -04001356 st->preemph_memD = (celt_sig*)celt_alloc(C*sizeof(celt_sig));
Jean-Marc Valinffa13472007-12-10 16:54:17 +11001357
Jean-Marc Valind69c1cb2009-12-28 00:34:29 -05001358#ifdef NEW_PLC
Jean-Marc Valin74128be2010-01-01 09:33:17 -05001359 st->lpc = (celt_word16*)celt_alloc(C*LPC_ORDER*sizeof(celt_word16));
Jean-Marc Valin5a0fae52009-12-14 21:19:37 -05001360#endif
1361
Jean-Marc Valin0f0da992009-08-12 21:34:01 -04001362 st->loss_count = 0;
Gregory Maxwell17169992009-06-04 15:15:34 -04001363
1364 if ((st->decode_mem!=NULL) && (st->out_mem!=NULL) && (st->oldBandE!=NULL) &&
Jean-Marc Valind69c1cb2009-12-28 00:34:29 -05001365#ifdef NEW_PLC
Jean-Marc Valin5a0fae52009-12-14 21:19:37 -05001366 (st->lpc!=NULL) &&
1367#endif
Gregory Maxwell17169992009-06-04 15:15:34 -04001368 (st->preemph_memD!=NULL))
1369 {
Jean-Marc Valinece94a02009-10-16 07:30:14 -04001370 if (error)
1371 *error = CELT_OK;
Gregory Maxwell17169992009-06-04 15:15:34 -04001372 st->marker = DECODERVALID;
1373 return st;
1374 }
1375 /* If the setup fails for some reason deallocate it. */
1376 celt_decoder_destroy(st);
Jean-Marc Valinece94a02009-10-16 07:30:14 -04001377 if (error)
1378 *error = CELT_ALLOC_FAIL;
Gregory Maxwell17169992009-06-04 15:15:34 -04001379 return NULL;
Jean-Marc Valin269d40a2007-12-07 11:29:45 +11001380}
1381
Peter Kirk19f9dc92008-06-06 14:38:38 +02001382void celt_decoder_destroy(CELTDecoder *st)
Jean-Marc Valin269d40a2007-12-07 11:29:45 +11001383{
1384 if (st == NULL)
1385 {
Gregory Maxwell17169992009-06-04 15:15:34 -04001386 celt_warning("NULL passed to celt_decoder_destroy");
Jean-Marc Valin269d40a2007-12-07 11:29:45 +11001387 return;
1388 }
Gregory Maxwell17169992009-06-04 15:15:34 -04001389
1390 if (st->marker == DECODERFREED)
1391 {
1392 celt_warning("Freeing a decoder which has already been freed");
Jean-Marc Valin44ffd5a2008-02-22 00:39:25 +11001393 return;
Gregory Maxwell17169992009-06-04 15:15:34 -04001394 }
1395
1396 if (st->marker != DECODERVALID && st->marker != DECODERPARTIAL)
1397 {
1398 celt_warning("This is not a valid CELT decoder structure");
1399 return;
1400 }
1401
1402 /*Check_mode is non-fatal here because we can still free
1403 the encoder memory even if the mode is bad, although calling
1404 the free functions in this order is a violation of the API.*/
1405 check_mode(st->mode);
1406
Jean-Marc Valineafbdd52009-04-27 19:35:09 -04001407 celt_free(st->decode_mem);
Jean-Marc Valin269d40a2007-12-07 11:29:45 +11001408 celt_free(st->oldBandE);
Jean-Marc Valin7351e282008-02-08 15:09:45 +11001409 celt_free(st->preemph_memD);
Jean-Marc Valin5a0fae52009-12-14 21:19:37 -05001410
Jean-Marc Valind69c1cb2009-12-28 00:34:29 -05001411#ifdef NEW_PLC
Jean-Marc Valin5a0fae52009-12-14 21:19:37 -05001412 celt_free(st->lpc);
1413#endif
Gregory Maxwell17169992009-06-04 15:15:34 -04001414
1415 st->marker = DECODERFREED;
1416
Jean-Marc Valin269d40a2007-12-07 11:29:45 +11001417 celt_free(st);
1418}
1419
Jean-Marc Valin017fa852010-05-06 22:11:48 -04001420static void celt_decode_lost(CELTDecoder * restrict st, celt_word16 * restrict pcm, int N, int LM)
Jean-Marc Valinfb83fb42007-12-08 00:56:04 +11001421{
Jean-Marc Valin04752672010-05-05 07:21:21 -04001422 int c;
Jean-Marc Valin0bb05bc2008-02-20 13:43:40 +11001423 int pitch_index;
Jean-Marc Valine14fe902009-12-11 00:07:31 -05001424 int overlap = st->mode->overlap;
Jean-Marc Valin234969c2009-10-17 22:12:42 -04001425 celt_word16 fade = Q15ONE;
Jean-Marc Valin24c9cda2008-05-02 10:34:07 +10001426 int i, len;
Jean-Marc Valin234969c2009-10-17 22:12:42 -04001427 VARDECL(celt_sig, freq);
Jean-Marc Valin80ed1472009-10-15 21:45:32 -04001428 const int C = CHANNELS(st->channels);
Jean-Marc Valin24c9cda2008-05-02 10:34:07 +10001429 int offset;
Jean-Marc Valin8600f692008-02-29 15:14:12 +11001430 SAVE_STACK;
Jean-Marc Valinfb83fb42007-12-08 00:56:04 +11001431
Jean-Marc Valin24c9cda2008-05-02 10:34:07 +10001432 len = N+st->mode->overlap;
Jean-Marc Valinfb83fb42007-12-08 00:56:04 +11001433
Jean-Marc Valin0f0da992009-08-12 21:34:01 -04001434 if (st->loss_count == 0)
1435 {
Jean-Marc Valin7a7c42a2009-11-25 20:38:52 -05001436 celt_word16 pitch_buf[MAX_PERIOD>>1];
Jean-Marc Valin294863b2009-11-08 22:29:54 +09001437 celt_word32 tmp=0;
Jean-Marc Valine465c142009-11-26 00:39:36 -05001438 celt_word32 mem0[2]={0,0};
1439 celt_word16 mem1[2]={0,0};
Jean-Marc Valin6202c742010-06-01 00:30:37 -04001440 int len2 = len;
1441 /* FIXME: This is a kludge */
1442 if (len2>MAX_PERIOD>>1)
1443 len2 = MAX_PERIOD>>1;
Jean-Marc Valine14fe902009-12-11 00:07:31 -05001444 pitch_downsample(st->out_mem, pitch_buf, MAX_PERIOD, MAX_PERIOD,
1445 C, mem0, mem1);
Jean-Marc Valin6202c742010-06-01 00:30:37 -04001446 pitch_search(st->mode, pitch_buf+((MAX_PERIOD-len2)>>1), pitch_buf, len2,
1447 MAX_PERIOD-len2-100, &pitch_index, &tmp, 1<<LM);
1448 pitch_index = MAX_PERIOD-len2-pitch_index;
Jean-Marc Valin0f0da992009-08-12 21:34:01 -04001449 st->last_pitch_index = pitch_index;
1450 } else {
1451 pitch_index = st->last_pitch_index;
1452 if (st->loss_count < 5)
1453 fade = QCONST16(.8f,15);
1454 else
1455 fade = 0;
1456 }
Jean-Marc Valinfb83fb42007-12-08 00:56:04 +11001457
Jean-Marc Valind69c1cb2009-12-28 00:34:29 -05001458#ifndef NEW_PLC
Jean-Marc Valind5f99302009-12-16 22:42:32 -05001459 offset = MAX_PERIOD-pitch_index;
Jean-Marc Valine14fe902009-12-11 00:07:31 -05001460 ALLOC(freq,C*N, celt_sig); /**< Interleaved signal MDCTs */
Jean-Marc Valin24c9cda2008-05-02 10:34:07 +10001461 while (offset+len >= MAX_PERIOD)
1462 offset -= pitch_index;
Jean-Marc Valin017fa852010-05-06 22:11:48 -04001463 compute_mdcts(st->mode, 0, st->out_mem+offset*C, freq, C, LM);
Jean-Marc Valin08a82ff2009-06-14 14:05:19 -04001464 for (i=0;i<C*N;i++)
Jean-Marc Valin0f0da992009-08-12 21:34:01 -04001465 freq[i] = ADD32(VERY_SMALL, MULT16_32_Q15(fade,freq[i]));
1466
Jean-Marc Valin24c9cda2008-05-02 10:34:07 +10001467 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 +11001468 /* Compute inverse MDCTs */
Jean-Marc Valin017fa852010-05-06 22:11:48 -04001469 compute_inv_mdcts(st->mode, 0, freq, -1, 0, st->out_mem, C, LM);
Jean-Marc Valine14fe902009-12-11 00:07:31 -05001470#else
1471 for (c=0;c<C;c++)
1472 {
Jean-Marc Valin6202c742010-06-01 00:30:37 -04001473 /* FIXME: This is more memory than necessary */
1474 celt_word32 e[2*MAX_PERIOD];
1475 celt_word16 exc[2*MAX_PERIOD];
Jean-Marc Valine14fe902009-12-11 00:07:31 -05001476 float ac[LPC_ORDER+1];
Jean-Marc Valine14fe902009-12-11 00:07:31 -05001477 float decay = 1;
Jean-Marc Valinaec0ee42009-12-21 00:06:12 -05001478 float S1=0;
Jean-Marc Valin74128be2010-01-01 09:33:17 -05001479 celt_word16 mem[LPC_ORDER]={0};
Jean-Marc Valine14fe902009-12-11 00:07:31 -05001480
Jean-Marc Valind5f99302009-12-16 22:42:32 -05001481 offset = MAX_PERIOD-pitch_index;
Jean-Marc Valine14fe902009-12-11 00:07:31 -05001482 for (i=0;i<MAX_PERIOD;i++)
Jean-Marc Valin74128be2010-01-01 09:33:17 -05001483 exc[i] = ROUND16(st->out_mem[i*C+c], SIG_SHIFT);
Jean-Marc Valin5a0fae52009-12-14 21:19:37 -05001484
1485 if (st->loss_count == 0)
1486 {
1487 _celt_autocorr(exc, ac, st->mode->window, st->mode->overlap,
1488 LPC_ORDER, MAX_PERIOD);
1489
1490 /* Noise floor -50 dB */
1491 ac[0] *= 1.00001;
1492 /* Lag windowing */
1493 for (i=1;i<=LPC_ORDER;i++)
1494 {
1495 /*ac[i] *= exp(-.5*(2*M_PI*.002*i)*(2*M_PI*.002*i));*/
1496 ac[i] -= ac[i]*(.008*i)*(.008*i);
1497 }
1498
Jean-Marc Valin74128be2010-01-01 09:33:17 -05001499 _celt_lpc(st->lpc+c*LPC_ORDER, ac, LPC_ORDER);
Jean-Marc Valin5a0fae52009-12-14 21:19:37 -05001500 }
Jean-Marc Valin74128be2010-01-01 09:33:17 -05001501 fir(exc, st->lpc+c*LPC_ORDER, exc, MAX_PERIOD, LPC_ORDER, mem);
1502 /*for (i=0;i<MAX_PERIOD;i++)printf("%d ", exc[i]); printf("\n");*/
Jean-Marc Valine14fe902009-12-11 00:07:31 -05001503 /* Check if the waveform is decaying (and if so how fast) */
1504 {
1505 float E1=0, E2=0;
1506 int period;
1507 if (pitch_index <= MAX_PERIOD/2)
1508 period = pitch_index;
1509 else
1510 period = MAX_PERIOD/2;
1511 for (i=0;i<period;i++)
1512 {
1513 E1 += exc[MAX_PERIOD-period+i]*exc[MAX_PERIOD-period+i];
1514 E2 += exc[MAX_PERIOD-2*period+i]*exc[MAX_PERIOD-2*period+i];
1515 }
1516 decay = sqrt((E1+1)/(E2+1));
1517 if (decay > 1)
1518 decay = 1;
1519 }
1520
1521 /* Copy excitation, taking decay into account */
1522 for (i=0;i<len+st->mode->overlap;i++)
1523 {
1524 if (offset+i >= MAX_PERIOD)
1525 {
1526 offset -= pitch_index;
1527 decay *= decay;
1528 }
Jean-Marc Valin303b3b62009-12-30 22:40:24 -05001529 e[i] = decay*SHL32(EXTEND32(exc[offset+i]), SIG_SHIFT);
Jean-Marc Valind69c1cb2009-12-28 00:34:29 -05001530 S1 += st->out_mem[offset+i]*1.*st->out_mem[offset+i];
Jean-Marc Valin5a0fae52009-12-14 21:19:37 -05001531 }
1532
Jean-Marc Valin74128be2010-01-01 09:33:17 -05001533 iir(e, st->lpc+c*LPC_ORDER, e, len+st->mode->overlap, LPC_ORDER, mem);
Jean-Marc Valin5a0fae52009-12-14 21:19:37 -05001534
1535 {
Jean-Marc Valin07fed1b2009-12-28 07:59:42 -05001536 float S2=0;
Jean-Marc Valin5a0fae52009-12-14 21:19:37 -05001537 for (i=0;i<len+overlap;i++)
Jean-Marc Valind69c1cb2009-12-28 00:34:29 -05001538 S2 += e[i]*1.*e[i];
Jean-Marc Valin07fed1b2009-12-28 07:59:42 -05001539 /* This checks for an "explosion" in the synthesis (including NaNs) */
1540 if (!(S1 > 0.2f*S2))
1541 {
1542 for (i=0;i<len+overlap;i++)
1543 e[i] = 0;
1544 } else if (S1 < S2)
1545 {
1546 float ratio = sqrt((S1+1)/(S2+1));
Jean-Marc Valin5a0fae52009-12-14 21:19:37 -05001547 for (i=0;i<len+overlap;i++)
1548 e[i] *= ratio;
Jean-Marc Valin07fed1b2009-12-28 07:59:42 -05001549 }
Jean-Marc Valine14fe902009-12-11 00:07:31 -05001550 }
1551
1552 for (i=0;i<MAX_PERIOD+st->mode->overlap-N;i++)
1553 st->out_mem[C*i+c] = st->out_mem[C*(N+i)+c];
1554
Jean-Marc Valine14fe902009-12-11 00:07:31 -05001555 /* Apply TDAC to the concealed audio so that it blends with the
1556 previous and next frames */
1557 for (i=0;i<overlap/2;i++)
1558 {
Jean-Marc Valind69c1cb2009-12-28 00:34:29 -05001559 celt_word32 tmp1, tmp2;
1560 tmp1 = MULT16_32_Q15(st->mode->window[i ], e[i ]) -
1561 MULT16_32_Q15(st->mode->window[overlap-i-1], e[overlap-i-1]);
1562 tmp2 = MULT16_32_Q15(st->mode->window[i], e[N+overlap-1-i]) +
1563 MULT16_32_Q15(st->mode->window[overlap-i-1], e[N+i ]);
1564 tmp1 = MULT16_32_Q15(fade, tmp1);
1565 tmp2 = MULT16_32_Q15(fade, tmp2);
1566 st->out_mem[C*(MAX_PERIOD+i)+c] = MULT16_32_Q15(st->mode->window[overlap-i-1], tmp2);
1567 st->out_mem[C*(MAX_PERIOD+overlap-i-1)+c] = MULT16_32_Q15(st->mode->window[i], tmp2);
1568 st->out_mem[C*(MAX_PERIOD-N+i)+c] += MULT16_32_Q15(st->mode->window[i], tmp1);
1569 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 -05001570 }
1571 for (i=0;i<N-overlap;i++)
Jean-Marc Valind69c1cb2009-12-28 00:34:29 -05001572 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 -05001573 }
1574#endif
Jean-Marc Valin1677aa92007-12-08 01:13:34 +11001575
Jean-Marc Valin5a0fae52009-12-14 21:19:37 -05001576 deemphasis(st->out_mem, pcm, N, C, preemph, st->preemph_memD);
Jean-Marc Valin0f0da992009-08-12 21:34:01 -04001577
1578 st->loss_count++;
1579
Jean-Marc Valin8600f692008-02-29 15:14:12 +11001580 RESTORE_STACK;
Jean-Marc Valinfb83fb42007-12-08 00:56:04 +11001581}
1582
Gregory Maxwell5f2a74b2008-08-11 23:50:07 -04001583#ifdef FIXED_POINT
Jean-Marc Valinf5e2e322010-05-19 12:05:02 -04001584int 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 +11001585{
Gregory Maxwell5f2a74b2008-08-11 23:50:07 -04001586#else
Jean-Marc Valinf5e2e322010-05-19 12:05:02 -04001587int 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 -04001588{
1589#endif
Jean-Marc Valin5f961462010-05-19 13:38:10 -04001590 int c, i, N, N4;
Jean-Marc Valinc9943942008-08-30 00:55:07 -04001591 int has_pitch, has_fold;
Jean-Marc Valin0bb05bc2008-02-20 13:43:40 +11001592 int pitch_index;
Jean-Marc Valinc890b582008-08-01 22:26:49 -04001593 int bits;
Jean-Marc Valinf5e2e322010-05-19 12:05:02 -04001594 ec_dec _dec;
Jean-Marc Valin0bb05bc2008-02-20 13:43:40 +11001595 ec_byte_buffer buf;
Jean-Marc Valin234969c2009-10-17 22:12:42 -04001596 VARDECL(celt_sig, freq);
1597 VARDECL(celt_sig, pitch_freq);
1598 VARDECL(celt_norm, X);
1599 VARDECL(celt_ener, bandE);
Jean-Marc Valin6775de32008-08-02 08:14:42 -04001600 VARDECL(int, fine_quant);
1601 VARDECL(int, pulses);
1602 VARDECL(int, offsets);
Jean-Marc Valin52cb5fb2009-06-10 08:08:55 -04001603 VARDECL(int, fine_priority);
Jean-Marc Valin163b76e2010-05-27 23:56:53 -04001604 VARDECL(int, tf_res);
Jean-Marc Valinc890b582008-08-01 22:26:49 -04001605
Jean-Marc Valin9d1decd2008-06-17 13:28:13 +10001606 int shortBlocks;
Jean-Marc Valin3b918ba2010-05-05 00:02:26 -04001607 int isTransient;
Jean-Marc Valin05ed03e2009-04-29 07:44:13 -04001608 int intra_ener;
Jean-Marc Valin12b22482008-06-16 14:13:05 +10001609 int transient_time;
Jean-Marc Valin528f4b82008-06-29 03:46:39 +10001610 int transient_shift;
Jean-Marc Valinaa936252009-05-29 22:14:20 -04001611 int mdct_weight_shift=0;
Jean-Marc Valin80ed1472009-10-15 21:45:32 -04001612 const int C = CHANNELS(st->channels);
Jean-Marc Valinaa936252009-05-29 22:14:20 -04001613 int mdct_weight_pos=0;
Jean-Marc Valinab220aa2009-09-15 22:38:40 -04001614 int gain_id=0;
Jean-Marc Valin017fa852010-05-06 22:11:48 -04001615 int LM, M;
Jean-Marc Valin8600f692008-02-29 15:14:12 +11001616 SAVE_STACK;
Jean-Marc Valin44ffd5a2008-02-22 00:39:25 +11001617
Gregory Maxwell17169992009-06-04 15:15:34 -04001618 if (check_decoder(st) != CELT_OK)
1619 return CELT_INVALID_STATE;
1620
Jean-Marc Valin44ffd5a2008-02-22 00:39:25 +11001621 if (check_mode(st->mode) != CELT_OK)
1622 return CELT_INVALID_MODE;
1623
Gregory Maxwell0719f6f2009-07-09 17:07:24 -04001624 if (pcm==NULL)
1625 return CELT_BAD_ARG;
1626
Jean-Marc Valin017fa852010-05-06 22:11:48 -04001627 for (LM=0;LM<4;LM++)
1628 if (st->mode->shortMdctSize<<LM==frame_size)
1629 break;
1630 if (LM>=MAX_CONFIG_SIZES)
1631 return CELT_BAD_ARG;
1632 M=1<<LM;
1633
Jean-Marc Valin04752672010-05-05 07:21:21 -04001634 N = M*st->mode->shortMdctSize;
Jean-Marc Valina536f772008-03-22 09:01:50 +11001635 N4 = (N-st->overlap)>>1;
Jean-Marc Valin01417232008-03-03 13:59:55 +11001636
Jean-Marc Valin234969c2009-10-17 22:12:42 -04001637 ALLOC(freq, C*N, celt_sig); /**< Interleaved signal MDCTs */
1638 ALLOC(X, C*N, celt_norm); /**< Interleaved normalised MDCTs */
1639 ALLOC(bandE, st->mode->nbEBands*C, celt_ener);
Jean-Marc Valin5f961462010-05-19 13:38:10 -04001640 for (c=0;c<C;c++)
1641 for (i=0;i<M*st->mode->eBands[st->start];i++)
1642 X[c*N+i] = 0;
1643
Jean-Marc Valinfb83fb42007-12-08 00:56:04 +11001644 if (data == NULL)
1645 {
Jean-Marc Valin017fa852010-05-06 22:11:48 -04001646 celt_decode_lost(st, pcm, N, LM);
Jean-Marc Valin8600f692008-02-29 15:14:12 +11001647 RESTORE_STACK;
Jean-Marc Valinfb83fb42007-12-08 00:56:04 +11001648 return 0;
1649 }
Gregory Maxwell520eeae2009-02-09 01:33:21 -05001650 if (len<0) {
1651 RESTORE_STACK;
1652 return CELT_BAD_ARG;
1653 }
Jean-Marc Valinfb83fb42007-12-08 00:56:04 +11001654
Jean-Marc Valinf5e2e322010-05-19 12:05:02 -04001655 if (dec == NULL)
1656 {
1657 ec_byte_readinit(&buf,(unsigned char*)data,len);
1658 ec_dec_init(&_dec,&buf);
1659 dec = &_dec;
1660 }
1661 decode_flags(dec, &intra_ener, &has_pitch, &isTransient, &has_fold);
Jean-Marc Valin3b918ba2010-05-05 00:02:26 -04001662 if (isTransient)
1663 shortBlocks = M;
1664 else
1665 shortBlocks = 0;
1666
1667 if (isTransient)
Gregory Maxwell0527f372008-09-23 19:28:35 -04001668 {
Jean-Marc Valinf5e2e322010-05-19 12:05:02 -04001669 transient_shift = ec_dec_uint(dec, 4);
Jean-Marc Valinaa936252009-05-29 22:14:20 -04001670 if (transient_shift == 3)
1671 {
Jean-Marc Valinf5e2e322010-05-19 12:05:02 -04001672 transient_time = ec_dec_uint(dec, N+st->mode->overlap);
Jean-Marc Valinaa936252009-05-29 22:14:20 -04001673 } else {
1674 mdct_weight_shift = transient_shift;
Jean-Marc Valin3b918ba2010-05-05 00:02:26 -04001675 if (mdct_weight_shift && M>2)
Jean-Marc Valinf5e2e322010-05-19 12:05:02 -04001676 mdct_weight_pos = ec_dec_uint(dec, M-1);
Jean-Marc Valinaa936252009-05-29 22:14:20 -04001677 transient_shift = 0;
Gregory Maxwell0527f372008-09-23 19:28:35 -04001678 transient_time = 0;
Jean-Marc Valinaa936252009-05-29 22:14:20 -04001679 }
Gregory Maxwell0527f372008-09-23 19:28:35 -04001680 } else {
Jean-Marc Valin12b22482008-06-16 14:13:05 +10001681 transient_time = -1;
Jean-Marc Valin528f4b82008-06-29 03:46:39 +10001682 transient_shift = 0;
Jean-Marc Valin12b22482008-06-16 14:13:05 +10001683 }
Jean-Marc Valincb7a2a32008-02-11 16:44:48 +11001684
Jean-Marc Valin7e8a4872008-02-11 16:55:34 +11001685 if (has_pitch)
1686 {
Jean-Marc Valin32589cd2010-05-31 21:56:12 -04001687 int maxpitch = MAX_PERIOD-(2*N-2*N4);
1688 if (maxpitch<0)
1689 {
1690 celt_notify("detected pitch when not allowed, bit corruption suspected");
1691 pitch_index = 0;
1692 has_pitch = 0;
1693 } else {
1694 pitch_index = ec_dec_uint(dec, maxpitch);
1695 gain_id = ec_dec_uint(dec, 16);
1696 }
Jean-Marc Valin7e8a4872008-02-11 16:55:34 +11001697 } else {
Jean-Marc Valin7e8a4872008-02-11 16:55:34 +11001698 pitch_index = 0;
1699 }
Jean-Marc Valin827f9312008-05-06 23:21:55 +10001700
Jean-Marc Valin163b76e2010-05-27 23:56:53 -04001701
Jean-Marc Valin6775de32008-08-02 08:14:42 -04001702 ALLOC(fine_quant, st->mode->nbEBands, int);
Jean-Marc Valin827f9312008-05-06 23:21:55 +10001703 /* Get band energies */
Jean-Marc Valin5f961462010-05-19 13:38:10 -04001704 unquant_coarse_energy(st->mode, st->start, bandE, st->oldBandE, len*4-8, intra_ener, st->mode->prob, dec, C);
Jean-Marc Valin0a571ef2010-06-05 23:12:19 -04001705
1706 ALLOC(tf_res, st->mode->nbEBands, int);
1707 tf_decode(st->mode->nbEBands, C, isTransient, tf_res, dec);
1708
Jean-Marc Valin6775de32008-08-02 08:14:42 -04001709 ALLOC(pulses, st->mode->nbEBands, int);
1710 ALLOC(offsets, st->mode->nbEBands, int);
Jean-Marc Valin52cb5fb2009-06-10 08:08:55 -04001711 ALLOC(fine_priority, st->mode->nbEBands, int);
Jean-Marc Valin6775de32008-08-02 08:14:42 -04001712
1713 for (i=0;i<st->mode->nbEBands;i++)
1714 offsets[i] = 0;
1715
Jean-Marc Valinf5e2e322010-05-19 12:05:02 -04001716 bits = len*8 - ec_dec_tell(dec, 0) - 1;
Jean-Marc Valin5f961462010-05-19 13:38:10 -04001717 compute_allocation(st->mode, st->start, offsets, bits, pulses, fine_quant, fine_priority, C, M);
Jean-Marc Valinf5e2e322010-05-19 12:05:02 -04001718 /*bits = ec_dec_tell(dec, 0);
1719 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 -04001720
Jean-Marc Valin5f961462010-05-19 13:38:10 -04001721 unquant_fine_energy(st->mode, st->start, bandE, st->oldBandE, fine_quant, dec, C);
Jean-Marc Valin827f9312008-05-06 23:21:55 +10001722
Jean-Marc Valin234969c2009-10-17 22:12:42 -04001723 ALLOC(pitch_freq, C*N, celt_sig); /**< Interleaved signal MDCTs */
Jean-Marc Valinc9943942008-08-30 00:55:07 -04001724 if (has_pitch)
Jean-Marc Valin269d40a2007-12-07 11:29:45 +11001725 {
Jean-Marc Valinc9943942008-08-30 00:55:07 -04001726 /* Pitch MDCT */
Jean-Marc Valin017fa852010-05-06 22:11:48 -04001727 compute_mdcts(st->mode, 0, st->out_mem+pitch_index*C, pitch_freq, C, LM);
Jean-Marc Valin269d40a2007-12-07 11:29:45 +11001728 }
1729
Jean-Marc Valin70c8ffd2007-12-07 14:20:01 +11001730 /* Decode fixed codebook and merge with pitch */
Jean-Marc Valin163b76e2010-05-27 23:56:53 -04001731 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 -04001732
Jean-Marc Valin5f961462010-05-19 13:38:10 -04001733 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 -04001734
Jean-Marc Valin88619552009-10-04 21:35:36 -04001735 if (mdct_weight_shift)
1736 {
Jean-Marc Valin3b918ba2010-05-05 00:02:26 -04001737 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 -04001738 }
1739
Jean-Marc Valina4833ff2008-01-10 15:34:00 +11001740 /* Synthesis */
Jean-Marc Valin65ee67a2010-04-26 07:08:44 -04001741 denormalise_bands(st->mode, X, freq, bandE, C, M);
Jean-Marc Valina4833ff2008-01-10 15:34:00 +11001742
1743
Jean-Marc Valineafbdd52009-04-27 19:35:09 -04001744 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 -04001745
Jean-Marc Valin4c77ea92009-09-14 22:50:41 -04001746 if (has_pitch)
Jean-Marc Valince4dd362010-05-07 07:45:18 -04001747 apply_pitch(st->mode, freq, pitch_freq, gain_id, 0, C, M);
Jean-Marc Valin4c77ea92009-09-14 22:50:41 -04001748
Jean-Marc Valin5f961462010-05-19 13:38:10 -04001749 for (c=0;c<C;c++)
1750 for (i=0;i<M*st->mode->eBands[st->start];i++)
1751 freq[c*N+i] = 0;
Jean-Marc Valin3a0bc3d2010-02-21 15:10:22 -05001752
Jean-Marc Valin269d40a2007-12-07 11:29:45 +11001753 /* Compute inverse MDCTs */
Jean-Marc Valin017fa852010-05-06 22:11:48 -04001754 compute_inv_mdcts(st->mode, shortBlocks, freq, transient_time, transient_shift, st->out_mem, C, LM);
Jean-Marc Valinffa13472007-12-10 16:54:17 +11001755
Jean-Marc Valine12017e2009-10-03 13:57:31 -04001756 deemphasis(st->out_mem, pcm, N, C, preemph, st->preemph_memD);
Jean-Marc Valine14fe902009-12-11 00:07:31 -05001757 st->loss_count = 0;
Jean-Marc Valin8600f692008-02-29 15:14:12 +11001758 RESTORE_STACK;
Jean-Marc Valinfb83fb42007-12-08 00:56:04 +11001759 return 0;
Jean-Marc Valin269d40a2007-12-07 11:29:45 +11001760}
1761
Gregory Maxwell5f2a74b2008-08-11 23:50:07 -04001762#ifdef FIXED_POINT
1763#ifndef DISABLE_FLOAT_API
Jean-Marc Valinf5e2e322010-05-19 12:05:02 -04001764int 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 -04001765{
Jean-Marc Valin017fa852010-05-06 22:11:48 -04001766 int j, ret, C, N, LM, M;
Jean-Marc Valin30f7f812009-10-17 14:35:13 -04001767 VARDECL(celt_int16, out);
Jean-Marc Valincb8780c2009-07-20 23:40:35 -04001768 SAVE_STACK;
Gregory Maxwell17169992009-06-04 15:15:34 -04001769
1770 if (check_decoder(st) != CELT_OK)
1771 return CELT_INVALID_STATE;
1772
1773 if (check_mode(st->mode) != CELT_OK)
1774 return CELT_INVALID_MODE;
1775
Gregory Maxwell0719f6f2009-07-09 17:07:24 -04001776 if (pcm==NULL)
1777 return CELT_BAD_ARG;
1778
Jean-Marc Valin017fa852010-05-06 22:11:48 -04001779 for (LM=0;LM<4;LM++)
1780 if (st->mode->shortMdctSize<<LM==frame_size)
1781 break;
1782 if (LM>=MAX_CONFIG_SIZES)
1783 return CELT_BAD_ARG;
1784 M=1<<LM;
1785
Jean-Marc Valin80ed1472009-10-15 21:45:32 -04001786 C = CHANNELS(st->channels);
Jean-Marc Valin017fa852010-05-06 22:11:48 -04001787 N = M*st->mode->shortMdctSize;
Gregory Maxwell0719f6f2009-07-09 17:07:24 -04001788
Jean-Marc Valin30f7f812009-10-17 14:35:13 -04001789 ALLOC(out, C*N, celt_int16);
Jean-Marc Valinf5e2e322010-05-19 12:05:02 -04001790 ret=celt_decode_with_ec(st, data, len, out, frame_size, dec);
Gregory Maxwell5f2a74b2008-08-11 23:50:07 -04001791 for (j=0;j<C*N;j++)
Gregory Maxwell0719f6f2009-07-09 17:07:24 -04001792 pcm[j]=out[j]*(1/32768.);
1793
Wessel Lubberhuizen33ba6cc2008-10-03 07:09:29 -04001794 RESTORE_STACK;
Gregory Maxwell5f2a74b2008-08-11 23:50:07 -04001795 return ret;
1796}
1797#endif /*DISABLE_FLOAT_API*/
1798#else
Jean-Marc Valinf5e2e322010-05-19 12:05:02 -04001799int 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 -04001800{
Jean-Marc Valin017fa852010-05-06 22:11:48 -04001801 int j, ret, C, N, LM, M;
Jean-Marc Valin234969c2009-10-17 22:12:42 -04001802 VARDECL(celt_sig, out);
Jean-Marc Valincb8780c2009-07-20 23:40:35 -04001803 SAVE_STACK;
Gregory Maxwell17169992009-06-04 15:15:34 -04001804
1805 if (check_decoder(st) != CELT_OK)
1806 return CELT_INVALID_STATE;
1807
1808 if (check_mode(st->mode) != CELT_OK)
1809 return CELT_INVALID_MODE;
1810
Gregory Maxwell0719f6f2009-07-09 17:07:24 -04001811 if (pcm==NULL)
1812 return CELT_BAD_ARG;
1813
Jean-Marc Valin017fa852010-05-06 22:11:48 -04001814 for (LM=0;LM<4;LM++)
1815 if (st->mode->shortMdctSize<<LM==frame_size)
1816 break;
1817 if (LM>=MAX_CONFIG_SIZES)
1818 return CELT_BAD_ARG;
1819 M=1<<LM;
1820
Jean-Marc Valin80ed1472009-10-15 21:45:32 -04001821 C = CHANNELS(st->channels);
Jean-Marc Valin017fa852010-05-06 22:11:48 -04001822 N = M*st->mode->shortMdctSize;
Jean-Marc Valin234969c2009-10-17 22:12:42 -04001823 ALLOC(out, C*N, celt_sig);
Gregory Maxwell5f2a74b2008-08-11 23:50:07 -04001824
Jean-Marc Valinf5e2e322010-05-19 12:05:02 -04001825 ret=celt_decode_with_ec_float(st, data, len, out, frame_size, dec);
Gregory Maxwell5f2a74b2008-08-11 23:50:07 -04001826
1827 for (j=0;j<C*N;j++)
Gregory Maxwell0719f6f2009-07-09 17:07:24 -04001828 pcm[j] = FLOAT2INT16 (out[j]);
1829
Wessel Lubberhuizen33ba6cc2008-10-03 07:09:29 -04001830 RESTORE_STACK;
Gregory Maxwell5f2a74b2008-08-11 23:50:07 -04001831 return ret;
1832}
1833#endif
John Ridges454d1d02009-05-21 22:38:39 -04001834
Jean-Marc Valinf5e2e322010-05-19 12:05:02 -04001835int celt_decode(CELTDecoder * restrict st, const unsigned char *data, int len, celt_int16 * restrict pcm, int frame_size)
1836{
1837 return celt_decode_with_ec(st, data, len, pcm, frame_size, NULL);
1838}
1839
1840int celt_decode_float(CELTDecoder * restrict st, const unsigned char *data, int len, float * restrict pcm, int frame_size)
1841{
1842 return celt_decode_with_ec_float(st, data, len, pcm, frame_size, NULL);
1843}
1844
John Ridges454d1d02009-05-21 22:38:39 -04001845int celt_decoder_ctl(CELTDecoder * restrict st, int request, ...)
1846{
1847 va_list ap;
Gregory Maxwell17169992009-06-04 15:15:34 -04001848
1849 if (check_decoder(st) != CELT_OK)
1850 return CELT_INVALID_STATE;
1851
John Ridges454d1d02009-05-21 22:38:39 -04001852 va_start(ap, request);
Gregory Maxwell17169992009-06-04 15:15:34 -04001853 if ((request!=CELT_GET_MODE_REQUEST) && (check_mode(st->mode) != CELT_OK))
1854 goto bad_mode;
John Ridges454d1d02009-05-21 22:38:39 -04001855 switch (request)
1856 {
Gregory Maxwellf3b44ef2009-06-03 13:37:45 -04001857 case CELT_GET_MODE_REQUEST:
1858 {
1859 const CELTMode ** value = va_arg(ap, const CELTMode**);
1860 if (value==0)
1861 goto bad_arg;
1862 *value=st->mode;
1863 }
1864 break;
Jean-Marc Valin5f961462010-05-19 13:38:10 -04001865 case CELT_SET_START_BAND_REQUEST:
1866 {
1867 celt_int32 value = va_arg(ap, celt_int32);
1868 if (value<0 || value>=st->mode->nbEBands)
1869 goto bad_arg;
1870 st->start = value;
1871 }
1872 break;
John Ridges454d1d02009-05-21 22:38:39 -04001873 case CELT_RESET_STATE:
1874 {
1875 const CELTMode *mode = st->mode;
Jean-Marc Valin80ed1472009-10-15 21:45:32 -04001876 int C = st->channels;
John Ridges454d1d02009-05-21 22:38:39 -04001877
1878 CELT_MEMSET(st->decode_mem, 0, (DECODE_BUFFER_SIZE+st->overlap)*C);
1879 CELT_MEMSET(st->oldBandE, 0, C*mode->nbEBands);
1880
1881 CELT_MEMSET(st->preemph_memD, 0, C);
1882
Jean-Marc Valin0f0da992009-08-12 21:34:01 -04001883 st->loss_count = 0;
John Ridges5378bf82010-02-12 07:08:01 -05001884
1885#ifdef NEW_PLC
1886 CELT_MEMSET(st->lpc, 0, C*LPC_ORDER);
1887#endif
John Ridges454d1d02009-05-21 22:38:39 -04001888 }
1889 break;
1890 default:
1891 goto bad_request;
1892 }
1893 va_end(ap);
1894 return CELT_OK;
Gregory Maxwell17169992009-06-04 15:15:34 -04001895bad_mode:
1896 va_end(ap);
1897 return CELT_INVALID_MODE;
John Ridges454d1d02009-05-21 22:38:39 -04001898bad_arg:
1899 va_end(ap);
1900 return CELT_BAD_ARG;
John Ridges454d1d02009-05-21 22:38:39 -04001901bad_request:
1902 va_end(ap);
1903 return CELT_UNIMPLEMENTED;
1904}
Jean-Marc Valinece94a02009-10-16 07:30:14 -04001905
1906const char *celt_strerror(int error)
1907{
1908 static const char *error_strings[8] = {
1909 "success",
1910 "invalid argument",
1911 "invalid mode",
1912 "internal error",
1913 "corrupted stream",
1914 "request not implemented",
1915 "invalid state",
1916 "memory allocation failed"
1917 };
1918 if (error > 0 || error < -7)
1919 return "unknown error";
1920 else
1921 return error_strings[-error];
1922}
1923