blob: bcec7d7587a89ecee1d443df71d87529bd22c843 [file] [log] [blame]
Jean-Marc Valin8b2ff0d2009-10-17 21:40:10 -04001/* Copyright (c) 2007-2008 CSIRO
Jean-Marc Valin190b7822010-08-27 15:03:20 -04002 Copyright (c) 2007-2010 Xiph.Org Foundation
Jean-Marc Valin8b2ff0d2009-10-17 21:40:10 -04003 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 Valin6c3788c2010-06-20 22:48:50 -040054#include "plc.h"
Jean-Marc Valin5a0fae52009-12-14 21:19:37 -050055
Timothy B. Terriberry845dfa12011-01-02 16:53:28 -080056static const unsigned char trim_icdf[11] = {126, 124, 119, 109, 87, 41, 19, 9, 4, 2, 0};
57/* Probs: NONE: 21.875%, LIGHT: 6.25%, NORMAL: 65.625%, AGGRESSIVE: 6.25% */
58static const unsigned char spread_icdf[4] = {25, 23, 2, 0};
Jean-Marc Valin4b087df2010-11-30 21:08:31 -050059
Jean-Marc Valin35095c62010-11-04 13:24:44 -040060#define COMBFILTER_MAXPERIOD 1024
61#define COMBFILTER_MINPERIOD 16
Jean-Marc Valin6bf04622010-09-30 10:16:22 -040062
Jean-Marc Valin276de722008-02-20 17:45:51 +110063/** Encoder state
64 @brief Encoder state
65 */
Jean-Marc Valin269d40a2007-12-07 11:29:45 +110066struct CELTEncoder {
Jean-Marc Valin276de722008-02-20 17:45:51 +110067 const CELTMode *mode; /**< Mode used by the encoder */
Jean-Marc Valina5431bf2008-01-03 20:53:01 +110068 int overlap;
Jean-Marc Valinffa13472007-12-10 16:54:17 +110069 int channels;
70
Gregory Maxwell2dd3d322009-06-05 14:05:51 -040071 int force_intra;
Jean-Marc Valin1213ba52010-08-31 17:03:13 -040072 int complexity;
Jean-Marc Valinc09807d2010-08-27 17:17:50 -040073 int start, end;
74
Gregory Maxwella9411472010-10-28 03:52:21 -040075 celt_int32 vbr_rate_norm; /* Target number of 8th bits per frame */
Jean-Marc Valin9faf7402010-12-04 10:27:22 -050076 int constrained_vbr; /* If zero, VBR can do whatever it likes with the rate */
Jean-Marc Valinc09807d2010-08-27 17:17:50 -040077
78 /* Everything beyond this point gets cleared on a reset */
79#define ENCODER_RESET_START frame_max
80
81 celt_word32 frame_max;
Timothy B. Terriberry320cf2e2010-12-17 05:52:06 -080082 int spread_decision;
Jean-Marc Valin74f4e9f2009-05-02 09:57:50 -040083 int delayedIntra;
Jean-Marc Valin1d17b9a2010-08-31 14:51:58 -040084 int tonal_average;
Jean-Marc Valindfd6e712010-12-09 23:23:34 -050085 int lastCodedBands;
Jean-Marc Valin8d367022011-01-17 16:37:51 -050086 int hf_average;
87 int tapset_decision;
Jean-Marc Valin527db5c2009-06-02 07:56:19 -040088
Jean-Marc Valin35095c62010-11-04 13:24:44 -040089 int prefilter_period;
90 celt_word16 prefilter_gain;
Jean-Marc Valindfa847a2011-01-17 11:37:08 -050091 int prefilter_tapset;
Jean-Marc Valin70d30ff2010-12-13 13:50:29 -050092#ifdef RESYNTH
93 int prefilter_period_old;
94 celt_word16 prefilter_gain_old;
Jean-Marc Valindfa847a2011-01-17 11:37:08 -050095 int prefilter_tapset_old;
Jean-Marc Valin70d30ff2010-12-13 13:50:29 -050096#endif
Jean-Marc Valin35095c62010-11-04 13:24:44 -040097
Jean-Marc Valinbd5d54a2009-10-20 00:25:31 -040098 /* VBR-related parameters */
99 celt_int32 vbr_reservoir;
100 celt_int32 vbr_drift;
101 celt_int32 vbr_offset;
102 celt_int32 vbr_count;
103
Jean-Marc Valinac1da4f2010-07-24 11:48:10 -0400104 celt_word32 preemph_memE[2];
105 celt_word32 preemph_memD[2];
Jean-Marc Valin81b38c22008-02-29 21:08:49 +1100106
Jean-Marc Valin35095c62010-11-04 13:24:44 -0400107#ifdef RESYNTH
108 celt_sig syn_mem[2][2*MAX_PERIOD];
109#endif
110
Jean-Marc Valinca8b9922010-08-27 16:23:03 -0400111 celt_sig in_mem[1]; /* Size = channels*mode->overlap */
Jean-Marc Valin35095c62010-11-04 13:24:44 -0400112 /* celt_sig prefilter_mem[], Size = channels*COMBFILTER_PERIOD */
Jean-Marc Valinca8b9922010-08-27 16:23:03 -0400113 /* celt_sig overlap_mem[], Size = channels*mode->overlap */
114 /* celt_word16 oldEBands[], Size = channels*mode->nbEBands */
Jean-Marc Valin8ebd3452007-11-29 20:17:32 +1100115};
116
Jean-Marc Valin0d8eaa32010-08-27 14:57:37 -0400117int celt_encoder_get_size(const CELTMode *mode, int channels)
118{
119 int size = sizeof(struct CELTEncoder)
120 + (2*channels*mode->overlap-1)*sizeof(celt_sig)
Jean-Marc Valin35095c62010-11-04 13:24:44 -0400121 + channels*COMBFILTER_MAXPERIOD*sizeof(celt_sig)
Jean-Marc Valin0d8eaa32010-08-27 14:57:37 -0400122 + channels*mode->nbEBands*sizeof(celt_word16);
123 return size;
124}
125
Jean-Marc Valin80ed1472009-10-15 21:45:32 -0400126CELTEncoder *celt_encoder_create(const CELTMode *mode, int channels, int *error)
Jean-Marc Valin8ebd3452007-11-29 20:17:32 +1100127{
Jean-Marc Valin7cfb7302010-08-27 16:54:33 -0400128 return celt_encoder_init(
129 (CELTEncoder *)celt_alloc(celt_encoder_get_size(mode, channels)),
130 mode, channels, error);
131}
Jean-Marc Valin44ffd5a2008-02-22 00:39:25 +1100132
Jean-Marc Valin7cfb7302010-08-27 16:54:33 -0400133CELTEncoder *celt_encoder_init(CELTEncoder *st, const CELTMode *mode, int channels, int *error)
134{
Jean-Marc Valin80ed1472009-10-15 21:45:32 -0400135 if (channels < 0 || channels > 2)
136 {
Jean-Marc Valin80ed1472009-10-15 21:45:32 -0400137 if (error)
138 *error = CELT_BAD_ARG;
139 return NULL;
140 }
Jean-Marc Valin44ffd5a2008-02-22 00:39:25 +1100141
Jean-Marc Valinece94a02009-10-16 07:30:14 -0400142 if (st==NULL)
143 {
144 if (error)
145 *error = CELT_ALLOC_FAIL;
Jean-Marc Valin80ed1472009-10-15 21:45:32 -0400146 return NULL;
Jean-Marc Valinece94a02009-10-16 07:30:14 -0400147 }
Jean-Marc Valin6d3829f2010-08-27 17:52:38 -0400148
149 CELT_MEMSET((char*)st, 0, celt_encoder_get_size(mode, channels));
150
Jean-Marc Valin73e51b32007-12-05 17:48:24 +1100151 st->mode = mode;
Jean-Marc Valina5431bf2008-01-03 20:53:01 +1100152 st->overlap = mode->overlap;
Jean-Marc Valin80ed1472009-10-15 21:45:32 -0400153 st->channels = channels;
Jean-Marc Valina5431bf2008-01-03 20:53:01 +1100154
Jean-Marc Valin5f961462010-05-19 13:38:10 -0400155 st->start = 0;
Jean-Marc Valin8952c452010-07-16 21:48:44 -0400156 st->end = st->mode->effEBands;
Jean-Marc Valin9faf7402010-12-04 10:27:22 -0500157 st->constrained_vbr = 1;
Jean-Marc Valin5f961462010-05-19 13:38:10 -0400158
Jean-Marc Valin8cc945c2010-05-29 08:07:18 -0400159 st->vbr_rate_norm = 0;
Jean-Marc Valin30165bb2010-12-03 14:35:59 -0500160 st->vbr_offset = 0;
Gregory Maxwell2dd3d322009-06-05 14:05:51 -0400161 st->force_intra = 0;
Gregory Maxwell8842fde2009-05-04 15:58:40 -0400162 st->delayedIntra = 1;
Jean-Marc Valin1213ba52010-08-31 17:03:13 -0400163 st->tonal_average = 256;
Timothy B. Terriberry320cf2e2010-12-17 05:52:06 -0800164 st->spread_decision = SPREAD_NORMAL;
Jean-Marc Valin8d367022011-01-17 16:37:51 -0500165 st->hf_average = 0;
166 st->tapset_decision = 0;
Jean-Marc Valin1213ba52010-08-31 17:03:13 -0400167 st->complexity = 5;
Jean-Marc Valina76a0b22008-01-17 22:43:05 +1100168
Jean-Marc Valinece94a02009-10-16 07:30:14 -0400169 if (error)
Jean-Marc Valin0d8eaa32010-08-27 14:57:37 -0400170 *error = CELT_OK;
Jean-Marc Valin0d8eaa32010-08-27 14:57:37 -0400171 return st;
Jean-Marc Valin8ebd3452007-11-29 20:17:32 +1100172}
173
Peter Kirk19f9dc92008-06-06 14:38:38 +0200174void celt_encoder_destroy(CELTEncoder *st)
Jean-Marc Valin14191b32007-11-30 12:15:49 +1100175{
Jean-Marc Valin14191b32007-11-30 12:15:49 +1100176 celt_free(st);
177}
178
Jean-Marc Valin30f7f812009-10-17 14:35:13 -0400179static inline celt_int16 FLOAT2INT16(float x)
Jean-Marc Valin42074382008-02-27 11:08:53 +1100180{
Gregory Maxwell0ac2b2f2009-05-21 23:08:46 -0400181 x = x*CELT_SIG_SCALE;
Gregory Maxwell5f2a74b2008-08-11 23:50:07 -0400182 x = MAX32(x, -32768);
183 x = MIN32(x, 32767);
Jean-Marc Valin30f7f812009-10-17 14:35:13 -0400184 return (celt_int16)float2int(x);
Gregory Maxwell5f2a74b2008-08-11 23:50:07 -0400185}
186
Jean-Marc Valin234969c2009-10-17 22:12:42 -0400187static inline celt_word16 SIG2WORD16(celt_sig x)
Gregory Maxwell5f2a74b2008-08-11 23:50:07 -0400188{
189#ifdef FIXED_POINT
Jean-Marc Valin42074382008-02-27 11:08:53 +1100190 x = PSHR32(x, SIG_SHIFT);
Jean-Marc Valinabdfc382008-04-18 15:57:18 +1000191 x = MAX32(x, -32768);
192 x = MIN32(x, 32767);
Jean-Marc Valin42074382008-02-27 11:08:53 +1100193 return EXTRACT16(x);
194#else
Jean-Marc Valin234969c2009-10-17 22:12:42 -0400195 return (celt_word16)x;
Jean-Marc Valin42074382008-02-27 11:08:53 +1100196#endif
197}
198
Jean-Marc Valin9c30de52010-04-19 13:32:15 -0400199static int transient_analysis(const celt_word32 * restrict in, int len, int C,
Jean-Marc Valinbdb58712010-05-28 18:58:42 -0400200 celt_word32 *frame_max, int overlap)
Jean-Marc Valin9375aa42008-06-27 07:57:35 +1000201{
Jean-Marc Valinfddc5212010-12-09 14:28:26 -0500202 int i;
Jean-Marc Valin2794b632010-10-13 17:32:57 -0400203 VARDECL(celt_word16, tmp);
204 celt_word32 mem0=0,mem1=0;
Jean-Marc Valinfddc5212010-12-09 14:28:26 -0500205 int is_transient = 0;
206 int block;
207 int N;
208 /* FIXME: Make that smaller */
209 celt_word16 bins[50];
Jean-Marc Valin0ceccb22008-07-03 20:41:06 -0400210 SAVE_STACK;
Jean-Marc Valin2794b632010-10-13 17:32:57 -0400211 ALLOC(tmp, len, celt_word16);
Jean-Marc Valin2794b632010-10-13 17:32:57 -0400212
Jean-Marc Valinfddc5212010-12-09 14:28:26 -0500213 block = overlap/2;
214 N=len/block;
Jean-Marc Valin9c30de52010-04-19 13:32:15 -0400215 if (C==1)
Jean-Marc Valin9375aa42008-06-27 07:57:35 +1000216 {
217 for (i=0;i<len;i++)
Jean-Marc Valin2794b632010-10-13 17:32:57 -0400218 tmp[i] = SHR32(in[i],SIG_SHIFT);
Jean-Marc Valin9c30de52010-04-19 13:32:15 -0400219 } else {
220 for (i=0;i<len;i++)
Jean-Marc Valin933dd832010-10-24 00:08:16 -0400221 tmp[i] = SHR32(ADD32(in[i],in[i+len]), SIG_SHIFT+1);
Jean-Marc Valin9375aa42008-06-27 07:57:35 +1000222 }
Jean-Marc Valin2794b632010-10-13 17:32:57 -0400223
224 /* High-pass filter: (1 - 2*z^-1 + z^-2) / (1 - z^-1 + .5*z^-2) */
225 for (i=0;i<len;i++)
226 {
227 celt_word32 x,y;
228 x = tmp[i];
229 y = ADD32(mem0, x);
230#ifdef FIXED_POINT
231 mem0 = mem1 + y - SHL32(x,1);
232 mem1 = x - SHR32(y,1);
233#else
234 mem0 = mem1 + y - 2*x;
Gregory Maxwell60c316b2010-11-04 20:14:19 -0400235 mem1 = x - .5f*y;
Jean-Marc Valin2794b632010-10-13 17:32:57 -0400236#endif
237 tmp[i] = EXTRACT16(SHR(y,2));
238 }
239 /* First few samples are bad because we don't propagate the memory */
Jean-Marc Valinfddc5212010-12-09 14:28:26 -0500240 for (i=0;i<12;i++)
Jean-Marc Valin2794b632010-10-13 17:32:57 -0400241 tmp[i] = 0;
242
Jean-Marc Valinfddc5212010-12-09 14:28:26 -0500243 for (i=0;i<N;i++)
Jean-Marc Valin9375aa42008-06-27 07:57:35 +1000244 {
Jean-Marc Valinfddc5212010-12-09 14:28:26 -0500245 int j;
246 float max_abs=0;
247 for (j=0;j<block;j++)
248 max_abs = MAX32(max_abs, tmp[i*block+j]);
249 bins[i] = max_abs;
Jean-Marc Valin9375aa42008-06-27 07:57:35 +1000250 }
Jean-Marc Valinfddc5212010-12-09 14:28:26 -0500251 for (i=0;i<N;i++)
Jean-Marc Valin4a8c1f12010-10-13 18:03:50 -0400252 {
Jean-Marc Valinfddc5212010-12-09 14:28:26 -0500253 int j;
254 int conseq=0;
255 celt_word16 t1, t2, t3;
256
257 t1 = MULT16_16_Q15(QCONST16(.15f, 15), bins[i]);
258 t2 = MULT16_16_Q15(QCONST16(.4f, 15), bins[i]);
259 t3 = MULT16_16_Q15(QCONST16(.15f, 15), bins[i]);
260 for (j=0;j<i;j++)
261 {
262 if (bins[j] < t1)
263 conseq++;
264 if (bins[j] < t2)
265 conseq++;
266 else
267 conseq = 0;
268 }
269 if (conseq>=3)
270 is_transient=1;
271 conseq = 0;
272 for (j=i+1;j<N;j++)
273 {
274 if (bins[j] < t3)
275 conseq++;
276 else
277 conseq = 0;
278 }
279 if (conseq>=7)
280 is_transient=1;
Jean-Marc Valin4a8c1f12010-10-13 18:03:50 -0400281 }
Jean-Marc Valin0ceccb22008-07-03 20:41:06 -0400282 RESTORE_STACK;
Jean-Marc Valinfddc5212010-12-09 14:28:26 -0500283 return is_transient;
Jean-Marc Valin9375aa42008-06-27 07:57:35 +1000284}
285
Jean-Marc Valin56522ad2009-06-05 17:17:25 -0400286/** Apply window and compute the MDCT for all sub-frames and
287 all channels in a frame */
Jean-Marc Valin017fa852010-05-06 22:11:48 -0400288static 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 +1100289{
Jean-Marc Valinbf2398b2009-10-15 07:28:19 -0400290 const int C = CHANNELS(_C);
Jean-Marc Valin9d1decd2008-06-17 13:28:13 +1000291 if (C==1 && !shortBlocks)
Jean-Marc Valinda721882007-11-30 15:17:42 +1100292 {
Jean-Marc Valin9d1decd2008-06-17 13:28:13 +1000293 const int overlap = OVERLAP(mode);
Jean-Marc Valin72513f32010-07-07 21:26:38 -0400294 clt_mdct_forward(&mode->mdct, in, out, mode->window, overlap, mode->maxLM-LM);
Jean-Marc Valinaa4f58b2009-10-03 09:27:59 -0400295 } else {
Jean-Marc Valin9d1decd2008-06-17 13:28:13 +1000296 const int overlap = OVERLAP(mode);
Jean-Marc Valince4dd362010-05-07 07:45:18 -0400297 int N = mode->shortMdctSize<<LM;
Jean-Marc Valinaa4f58b2009-10-03 09:27:59 -0400298 int B = 1;
Jean-Marc Valin9d1decd2008-06-17 13:28:13 +1000299 int b, c;
Jean-Marc Valin234969c2009-10-17 22:12:42 -0400300 VARDECL(celt_word32, tmp);
Jean-Marc Valin9d1decd2008-06-17 13:28:13 +1000301 SAVE_STACK;
Jean-Marc Valinaa4f58b2009-10-03 09:27:59 -0400302 if (shortBlocks)
303 {
Jean-Marc Valin72513f32010-07-07 21:26:38 -0400304 /*lookup = &mode->mdct[0];*/
Jean-Marc Valinaa4f58b2009-10-03 09:27:59 -0400305 N = mode->shortMdctSize;
Jean-Marc Valin3b918ba2010-05-05 00:02:26 -0400306 B = shortBlocks;
Jean-Marc Valinaa4f58b2009-10-03 09:27:59 -0400307 }
Jean-Marc Valin234969c2009-10-17 22:12:42 -0400308 ALLOC(tmp, N, celt_word32);
Gregory Maxwell9743bf32010-11-04 20:45:09 -0400309 c=0; do {
Jean-Marc Valin9d1decd2008-06-17 13:28:13 +1000310 for (b=0;b<B;b++)
311 {
312 int j;
Jean-Marc Valineedb4222010-10-24 00:22:45 -0400313 clt_mdct_forward(&mode->mdct, in+c*(B*N+overlap)+b*N, tmp, mode->window, overlap, shortBlocks ? mode->maxLM : mode->maxLM-LM);
Jean-Marc Valin9d1decd2008-06-17 13:28:13 +1000314 /* Interleaving the sub-frames */
315 for (j=0;j<N;j++)
Jean-Marc Valin08a82ff2009-06-14 14:05:19 -0400316 out[(j*B+b)+c*N*B] = tmp[j];
Jean-Marc Valin9d1decd2008-06-17 13:28:13 +1000317 }
Gregory Maxwell9743bf32010-11-04 20:45:09 -0400318 } while (++c<C);
Jean-Marc Valin9d1decd2008-06-17 13:28:13 +1000319 RESTORE_STACK;
Jean-Marc Valinda721882007-11-30 15:17:42 +1100320 }
Jean-Marc Valinda721882007-11-30 15:17:42 +1100321}
322
Jean-Marc Valin56522ad2009-06-05 17:17:25 -0400323/** Compute the IMDCT and apply window for all sub-frames and
324 all channels in a frame */
Jean-Marc Valine0ce2cf2010-08-26 23:58:08 -0400325static void compute_inv_mdcts(const CELTMode *mode, int shortBlocks, celt_sig *X,
Jean-Marc Valin7a08ddd2010-10-18 14:55:42 -0400326 celt_sig * restrict out_mem[],
Jean-Marc Valine0ce2cf2010-08-26 23:58:08 -0400327 celt_sig * restrict overlap_mem[], int _C, int LM)
Jean-Marc Valin1677aa92007-12-08 01:13:34 +1100328{
Jean-Marc Valin0695a5f2010-08-27 11:33:18 -0400329 int c;
Jean-Marc Valinbf2398b2009-10-15 07:28:19 -0400330 const int C = CHANNELS(_C);
Jean-Marc Valince4dd362010-05-07 07:45:18 -0400331 const int N = mode->shortMdctSize<<LM;
Jean-Marc Valinb18ec0b2008-04-11 04:07:52 +1000332 const int overlap = OVERLAP(mode);
Gregory Maxwell9743bf32010-11-04 20:45:09 -0400333 c=0; do {
Jean-Marc Valinb886ddc2008-03-25 14:38:55 +1100334 int j;
Jean-Marc Valin234969c2009-10-17 22:12:42 -0400335 VARDECL(celt_word32, x);
336 VARDECL(celt_word32, tmp);
Jean-Marc Valinde678582009-10-03 10:36:27 -0400337 int b;
338 int N2 = N;
339 int B = 1;
Jean-Marc Valin9d1decd2008-06-17 13:28:13 +1000340 SAVE_STACK;
Jean-Marc Valinde678582009-10-03 10:36:27 -0400341
Jean-Marc Valinf67b4472010-08-27 01:32:40 -0400342 ALLOC(x, N+overlap, celt_word32);
Jean-Marc Valin234969c2009-10-17 22:12:42 -0400343 ALLOC(tmp, N, celt_word32);
Jean-Marc Valinde678582009-10-03 10:36:27 -0400344
345 if (shortBlocks)
346 {
Jean-Marc Valinde678582009-10-03 10:36:27 -0400347 N2 = mode->shortMdctSize;
Jean-Marc Valin3b918ba2010-05-05 00:02:26 -0400348 B = shortBlocks;
Jean-Marc Valinde678582009-10-03 10:36:27 -0400349 }
Jean-Marc Valin9d1decd2008-06-17 13:28:13 +1000350 /* Prevents problems from the imdct doing the overlap-add */
Jean-Marc Valinf67b4472010-08-27 01:32:40 -0400351 CELT_MEMSET(x, 0, overlap);
Jean-Marc Valinde678582009-10-03 10:36:27 -0400352
Jean-Marc Valin9d1decd2008-06-17 13:28:13 +1000353 for (b=0;b<B;b++)
354 {
355 /* De-interleaving the sub-frames */
356 for (j=0;j<N2;j++)
Jean-Marc Valin08a82ff2009-06-14 14:05:19 -0400357 tmp[j] = X[(j*B+b)+c*N2*B];
Jean-Marc Valinf67b4472010-08-27 01:32:40 -0400358 clt_mdct_backward(&mode->mdct, tmp, x+N2*b, mode->window, overlap, shortBlocks ? mode->maxLM : mode->maxLM-LM);
Jean-Marc Valin9d1decd2008-06-17 13:28:13 +1000359 }
Jean-Marc Valinde678582009-10-03 10:36:27 -0400360
Jean-Marc Valin8ddd7f42008-04-22 13:37:16 +1000361 for (j=0;j<overlap;j++)
Jean-Marc Valinf67b4472010-08-27 01:32:40 -0400362 out_mem[c][j] = x[j] + overlap_mem[c][j];
Jean-Marc Valine0ce2cf2010-08-26 23:58:08 -0400363 for (;j<N;j++)
Jean-Marc Valinf67b4472010-08-27 01:32:40 -0400364 out_mem[c][j] = x[j];
Jean-Marc Valine0ce2cf2010-08-26 23:58:08 -0400365 for (j=0;j<overlap;j++)
Jean-Marc Valinf67b4472010-08-27 01:32:40 -0400366 overlap_mem[c][j] = x[N+j];
Jean-Marc Valin8ddd7f42008-04-22 13:37:16 +1000367 RESTORE_STACK;
Gregory Maxwell9743bf32010-11-04 20:45:09 -0400368 } while (++c<C);
Jean-Marc Valin1677aa92007-12-08 01:13:34 +1100369}
370
Jean-Marc Valin903dbf72010-08-26 20:06:49 -0400371static void deemphasis(celt_sig *in[], celt_word16 *pcm, int N, int _C, const celt_word16 *coef, celt_sig *mem)
Jean-Marc Valine12017e2009-10-03 13:57:31 -0400372{
Jean-Marc Valinbf2398b2009-10-15 07:28:19 -0400373 const int C = CHANNELS(_C);
Jean-Marc Valine12017e2009-10-03 13:57:31 -0400374 int c;
Gregory Maxwell9743bf32010-11-04 20:45:09 -0400375 c=0; do {
Jean-Marc Valine12017e2009-10-03 13:57:31 -0400376 int j;
Jean-Marc Valin64209a32010-04-05 09:26:22 -0400377 celt_sig * restrict x;
378 celt_word16 * restrict y;
379 celt_sig m = mem[c];
Jean-Marc Valinf67b4472010-08-27 01:32:40 -0400380 x =in[c];
Jean-Marc Valin64209a32010-04-05 09:26:22 -0400381 y = pcm+c;
Jean-Marc Valine12017e2009-10-03 13:57:31 -0400382 for (j=0;j<N;j++)
383 {
Jean-Marc Valinaf1fce92010-07-16 11:05:06 -0400384 celt_sig tmp = *x + m;
385 m = MULT16_32_Q15(coef[0], tmp)
386 - MULT16_32_Q15(coef[1], *x);
Jean-Marc Valin223b69d2010-07-16 11:47:50 -0400387 tmp = SHL32(MULT16_32_Q15(coef[3], tmp), 2);
Jean-Marc Valin64209a32010-04-05 09:26:22 -0400388 *y = SCALEOUT(SIG2WORD16(tmp));
Jean-Marc Valin903dbf72010-08-26 20:06:49 -0400389 x++;
Jean-Marc Valin64209a32010-04-05 09:26:22 -0400390 y+=C;
Jean-Marc Valine12017e2009-10-03 13:57:31 -0400391 }
Jean-Marc Valin64209a32010-04-05 09:26:22 -0400392 mem[c] = m;
Gregory Maxwell9743bf32010-11-04 20:45:09 -0400393 } while (++c<C);
Jean-Marc Valine12017e2009-10-03 13:57:31 -0400394}
395
Jean-Marc Valin35095c62010-11-04 13:24:44 -0400396#ifdef ENABLE_POSTFILTER
Jean-Marc Valin35095c62010-11-04 13:24:44 -0400397static void comb_filter(celt_word32 *y, celt_word32 *x, int T0, int T1, int N,
Jean-Marc Valindfa847a2011-01-17 11:37:08 -0500398 int C, celt_word16 g0, celt_word16 g1, int tapset0, int tapset1,
399 const celt_word16 *window, int overlap)
Jean-Marc Valin35095c62010-11-04 13:24:44 -0400400{
401 int i;
402 /* printf ("%d %d %f %f\n", T0, T1, g0, g1); */
403 celt_word16 g00, g01, g02, g10, g11, g12;
Jean-Marc Valindfa847a2011-01-17 11:37:08 -0500404 static const celt_word16 gains[3][3] = {
405 {QCONST16(0.30690f, 15), QCONST16(0.21701f, 15), QCONST16(0.12954f, 15)},
406 {QCONST16(0.46410f, 15), QCONST16(0.26795f, 15), QCONST16(0.f, 15)},
407 {QCONST16(0.8f, 15), QCONST16(0.1f, 15), QCONST16(0.f, 15)}};
408 g00 = MULT16_16_Q15(g0, gains[tapset0][0]);
409 g01 = MULT16_16_Q15(g0, gains[tapset0][1]);
410 g02 = MULT16_16_Q15(g0, gains[tapset0][2]);
411 g10 = MULT16_16_Q15(g1, gains[tapset1][0]);
412 g11 = MULT16_16_Q15(g1, gains[tapset1][1]);
413 g12 = MULT16_16_Q15(g1, gains[tapset1][2]);
Jean-Marc Valin35095c62010-11-04 13:24:44 -0400414 for (i=0;i<overlap;i++)
415 {
416 celt_word16 f;
417 f = MULT16_16_Q15(window[i],window[i]);
418 y[i] = x[i]
Jean-Marc Valindfa847a2011-01-17 11:37:08 -0500419 + MULT16_32_Q15(MULT16_16_Q15((Q15ONE-f),g00),x[i-T0])
420 + MULT16_32_Q15(MULT16_16_Q15((Q15ONE-f),g01),x[i-T0-1])
421 + MULT16_32_Q15(MULT16_16_Q15((Q15ONE-f),g01),x[i-T0+1])
422 + MULT16_32_Q15(MULT16_16_Q15((Q15ONE-f),g02),x[i-T0-2])
423 + MULT16_32_Q15(MULT16_16_Q15((Q15ONE-f),g02),x[i-T0+2])
424 + MULT16_32_Q15(MULT16_16_Q15(f,g10),x[i-T1])
425 + MULT16_32_Q15(MULT16_16_Q15(f,g11),x[i-T1-1])
426 + MULT16_32_Q15(MULT16_16_Q15(f,g11),x[i-T1+1])
427 + MULT16_32_Q15(MULT16_16_Q15(f,g12),x[i-T1-2])
428 + MULT16_32_Q15(MULT16_16_Q15(f,g12),x[i-T1+2]);
Jean-Marc Valin35095c62010-11-04 13:24:44 -0400429
430 }
431 for (i=overlap;i<N;i++)
432 y[i] = x[i]
Jean-Marc Valindfa847a2011-01-17 11:37:08 -0500433 + MULT16_32_Q15(g10,x[i-T1])
434 + MULT16_32_Q15(g11,x[i-T1-1])
435 + MULT16_32_Q15(g11,x[i-T1+1])
436 + MULT16_32_Q15(g12,x[i-T1-2])
437 + MULT16_32_Q15(g12,x[i-T1+2]);
Jean-Marc Valin35095c62010-11-04 13:24:44 -0400438}
439#endif /* ENABLE_POSTFILTER */
440
Jean-Marc Valina8160dd2010-10-12 14:55:16 -0400441static const signed char tf_select_table[4][8] = {
Jean-Marc Valin890a9c02010-06-13 08:06:28 -0400442 {0, -1, 0, -1, 0,-1, 0,-1},
Jean-Marc Valin41a15e62010-12-27 16:33:38 -0500443 {0, -1, 0, -2, 1, 0, 1,-1},
444 {0, -2, 0, -3, 2, 0, 1,-1},
Jean-Marc Valin2b134012011-01-12 16:13:46 -0500445 {0, -2, 0, -3, 3, 0, 1,-1},
Jean-Marc Valin890a9c02010-06-13 08:06:28 -0400446};
447
Jean-Marc Valinc5792de2010-10-19 14:24:50 -0400448static celt_word32 l1_metric(const celt_norm *tmp, int N, int LM, int width)
Jean-Marc Valin8200b2d2010-10-15 02:18:47 -0400449{
450 int i, j;
Timothy B. Terriberry051e0442011-01-08 22:11:46 -0800451 static const celt_word16 sqrtM_1[4] = {Q15ONE, QCONST16(.70710678f,15), QCONST16(0.5f,15), QCONST16(0.35355339f,15)};
Jean-Marc Valin8200b2d2010-10-15 02:18:47 -0400452 celt_word32 L1;
453 celt_word16 bias;
454 L1=0;
455 for (i=0;i<1<<LM;i++)
456 {
457 celt_word32 L2 = 0;
458 for (j=0;j<N>>LM;j++)
459 L2 = MAC16_16(L2, tmp[(j<<LM)+i], tmp[(j<<LM)+i]);
460 L1 += celt_sqrt(L2);
461 }
462 L1 = MULT16_32_Q15(sqrtM_1[LM], L1);
Jean-Marc Valin54fb7e52010-10-15 11:26:32 -0400463 if (width==1)
464 bias = QCONST16(.12f,15)*LM;
465 else if (width==2)
466 bias = QCONST16(.05f,15)*LM;
467 else
468 bias = QCONST16(.02f,15)*LM;
Jean-Marc Valin8200b2d2010-10-15 02:18:47 -0400469 L1 = MAC16_32_Q15(L1, bias, L1);
470 return L1;
471}
472
Jean-Marc Valin0f8fc0b2010-10-12 23:25:58 -0400473static int tf_analysis(const CELTMode *m, celt_word16 *bandLogE, celt_word16 *oldBandE,
Jean-Marc Valinccd5a612010-10-13 01:11:55 -0400474 int len, int C, int isTransient, int *tf_res, int nbCompressedBytes, celt_norm *X,
475 int N0, int LM, int *tf_sum)
Jean-Marc Valin163b76e2010-05-27 23:56:53 -0400476{
Jean-Marc Valin0a571ef2010-06-05 23:12:19 -0400477 int i;
Jean-Marc Valin0f8fc0b2010-10-12 23:25:58 -0400478 VARDECL(int, metric);
479 int cost0;
480 int cost1;
Jean-Marc Valin9d420c52010-05-28 17:26:27 -0400481 VARDECL(int, path0);
482 VARDECL(int, path1);
Jean-Marc Valin0f8fc0b2010-10-12 23:25:58 -0400483 VARDECL(celt_norm, tmp);
484 int lambda;
Jean-Marc Valin890a9c02010-06-13 08:06:28 -0400485 int tf_select=0;
Jean-Marc Valin163b76e2010-05-27 23:56:53 -0400486 SAVE_STACK;
487
Jean-Marc Valin6bf3b0a2010-07-19 14:32:40 -0400488 if (nbCompressedBytes<15*C)
489 {
Jean-Marc Valina3a066c2010-11-04 15:15:54 -0400490 *tf_sum = 0;
Jean-Marc Valin6bf3b0a2010-07-19 14:32:40 -0400491 for (i=0;i<len;i++)
Jean-Marc Valinc5792de2010-10-19 14:24:50 -0400492 tf_res[i] = isTransient;
Jean-Marc Valin6bf3b0a2010-07-19 14:32:40 -0400493 return 0;
494 }
Jean-Marc Valin73319772010-05-28 21:12:39 -0400495 if (nbCompressedBytes<40)
Jean-Marc Valin54fb7e52010-10-15 11:26:32 -0400496 lambda = 12;
Jean-Marc Valin73319772010-05-28 21:12:39 -0400497 else if (nbCompressedBytes<60)
Jean-Marc Valin54fb7e52010-10-15 11:26:32 -0400498 lambda = 6;
Jean-Marc Valin73319772010-05-28 21:12:39 -0400499 else if (nbCompressedBytes<100)
Jean-Marc Valin54fb7e52010-10-15 11:26:32 -0400500 lambda = 4;
Jean-Marc Valin73319772010-05-28 21:12:39 -0400501 else
Jean-Marc Valin54fb7e52010-10-15 11:26:32 -0400502 lambda = 3;
Jean-Marc Valin73319772010-05-28 21:12:39 -0400503
Jean-Marc Valin0f8fc0b2010-10-12 23:25:58 -0400504 ALLOC(metric, len, int);
505 ALLOC(tmp, (m->eBands[len]-m->eBands[len-1])<<LM, celt_norm);
Jean-Marc Valin9d420c52010-05-28 17:26:27 -0400506 ALLOC(path0, len, int);
507 ALLOC(path1, len, int);
Jean-Marc Valin0f8fc0b2010-10-12 23:25:58 -0400508
Jean-Marc Valinccd5a612010-10-13 01:11:55 -0400509 *tf_sum = 0;
Jean-Marc Valin163b76e2010-05-27 23:56:53 -0400510 for (i=0;i<len;i++)
Jean-Marc Valin890a9c02010-06-13 08:06:28 -0400511 {
Jean-Marc Valin0f8fc0b2010-10-12 23:25:58 -0400512 int j, k, N;
513 celt_word32 L1, best_L1;
514 int best_level=0;
515 N = (m->eBands[i+1]-m->eBands[i])<<LM;
516 for (j=0;j<N;j++)
517 tmp[j] = X[j+(m->eBands[i]<<LM)];
Jean-Marc Valin20e4c6a2010-12-21 22:27:08 -0500518 /* Just add the right channel if we're in stereo */
Jean-Marc Valina3a066c2010-11-04 15:15:54 -0400519 if (C==2)
Jean-Marc Valin0f8fc0b2010-10-12 23:25:58 -0400520 for (j=0;j<N;j++)
Jean-Marc Valina3a066c2010-11-04 15:15:54 -0400521 tmp[j] = ADD16(tmp[j],X[N0+j+(m->eBands[i]<<LM)]);
Jean-Marc Valin8200b2d2010-10-15 02:18:47 -0400522 L1 = l1_metric(tmp, N, isTransient ? LM : 0, N>>LM);
Jean-Marc Valin0f8fc0b2010-10-12 23:25:58 -0400523 best_L1 = L1;
524 /*printf ("%f ", L1);*/
525 for (k=0;k<LM;k++)
Jean-Marc Valin890a9c02010-06-13 08:06:28 -0400526 {
Jean-Marc Valin8200b2d2010-10-15 02:18:47 -0400527 int B;
528
529 if (isTransient)
530 B = (LM-k-1);
531 else
532 B = k+1;
533
Jean-Marc Valin0f8fc0b2010-10-12 23:25:58 -0400534 if (isTransient)
535 haar1(tmp, N>>(LM-k), 1<<(LM-k));
536 else
537 haar1(tmp, N>>k, 1<<k);
538
Jean-Marc Valin8200b2d2010-10-15 02:18:47 -0400539 L1 = l1_metric(tmp, N, B, N>>LM);
Jean-Marc Valin0f8fc0b2010-10-12 23:25:58 -0400540
Jean-Marc Valin0f8fc0b2010-10-12 23:25:58 -0400541 if (L1 < best_L1)
542 {
543 best_L1 = L1;
544 best_level = k+1;
545 }
Jean-Marc Valin890a9c02010-06-13 08:06:28 -0400546 }
Jean-Marc Valin0f8fc0b2010-10-12 23:25:58 -0400547 /*printf ("%d ", isTransient ? LM-best_level : best_level);*/
548 if (isTransient)
549 metric[i] = best_level;
550 else
551 metric[i] = -best_level;
Jean-Marc Valinccd5a612010-10-13 01:11:55 -0400552 *tf_sum += metric[i];
Jean-Marc Valin890a9c02010-06-13 08:06:28 -0400553 }
Jean-Marc Valin0f8fc0b2010-10-12 23:25:58 -0400554 /*printf("\n");*/
555 /* FIXME: Figure out how to set this */
Jean-Marc Valin8200b2d2010-10-15 02:18:47 -0400556 tf_select = 0;
Jean-Marc Valin0f8fc0b2010-10-12 23:25:58 -0400557
Jean-Marc Valin88232612010-05-28 18:01:02 -0400558 cost0 = 0;
Jean-Marc Valinc5792de2010-10-19 14:24:50 -0400559 cost1 = isTransient ? 0 : lambda;
Jean-Marc Valin9d420c52010-05-28 17:26:27 -0400560 /* Viterbi forward pass */
561 for (i=1;i<len;i++)
Jean-Marc Valin163b76e2010-05-27 23:56:53 -0400562 {
Jean-Marc Valin0f8fc0b2010-10-12 23:25:58 -0400563 int curr0, curr1;
564 int from0, from1;
Jean-Marc Valin581fdba2010-05-28 06:56:23 -0400565
Jean-Marc Valin88232612010-05-28 18:01:02 -0400566 from0 = cost0;
567 from1 = cost1 + lambda;
Jean-Marc Valin9d420c52010-05-28 17:26:27 -0400568 if (from0 < from1)
569 {
Jean-Marc Valin88232612010-05-28 18:01:02 -0400570 curr0 = from0;
Jean-Marc Valin9d420c52010-05-28 17:26:27 -0400571 path0[i]= 0;
572 } else {
Jean-Marc Valin88232612010-05-28 18:01:02 -0400573 curr0 = from1;
Jean-Marc Valin9d420c52010-05-28 17:26:27 -0400574 path0[i]= 1;
575 }
576
Jean-Marc Valin88232612010-05-28 18:01:02 -0400577 from0 = cost0 + lambda;
578 from1 = cost1;
Jean-Marc Valin9d420c52010-05-28 17:26:27 -0400579 if (from0 < from1)
580 {
Jean-Marc Valin88232612010-05-28 18:01:02 -0400581 curr1 = from0;
Jean-Marc Valin9d420c52010-05-28 17:26:27 -0400582 path1[i]= 0;
583 } else {
Jean-Marc Valin88232612010-05-28 18:01:02 -0400584 curr1 = from1;
Jean-Marc Valin9d420c52010-05-28 17:26:27 -0400585 path1[i]= 1;
586 }
Jean-Marc Valin0f8fc0b2010-10-12 23:25:58 -0400587 cost0 = curr0 + abs(metric[i]-tf_select_table[LM][4*isTransient+2*tf_select+0]);
588 cost1 = curr1 + abs(metric[i]-tf_select_table[LM][4*isTransient+2*tf_select+1]);
Jean-Marc Valin9d420c52010-05-28 17:26:27 -0400589 }
Jean-Marc Valin88232612010-05-28 18:01:02 -0400590 tf_res[len-1] = cost0 < cost1 ? 0 : 1;
Jean-Marc Valin9d420c52010-05-28 17:26:27 -0400591 /* Viterbi backward pass to check the decisions */
592 for (i=len-2;i>=0;i--)
593 {
594 if (tf_res[i+1] == 1)
595 tf_res[i] = path1[i+1];
596 else
597 tf_res[i] = path0[i+1];
598 }
Jean-Marc Valin71ae6d42010-06-27 21:55:08 -0400599 RESTORE_STACK;
Jean-Marc Valin890a9c02010-06-13 08:06:28 -0400600 return tf_select;
Jean-Marc Valin0a571ef2010-06-05 23:12:19 -0400601}
602
Jean-Marc Valine5e9aa72010-12-02 16:09:51 -0500603static void tf_encode(int start, int end, int isTransient, int *tf_res, int LM, int tf_select, ec_enc *enc)
Jean-Marc Valin0a571ef2010-06-05 23:12:19 -0400604{
605 int curr, i;
Timothy B. Terriberry76469c62011-01-07 09:18:34 -0800606 int tf_select_rsv;
607 int tf_changed;
608 int logp;
609 ec_uint32 budget;
610 ec_uint32 tell;
611 budget = enc->buf->storage*8;
612 tell = ec_enc_tell(enc, 0);
613 logp = isTransient ? 2 : 4;
614 /* Reserve space to code the tf_select decision. */
615 tf_select_rsv = LM>0 && tell+logp+1 <= budget;
616 budget -= tf_select_rsv;
617 curr = tf_changed = 0;
618 for (i=start;i<end;i++)
Jean-Marc Valin163b76e2010-05-27 23:56:53 -0400619 {
Timothy B. Terriberry76469c62011-01-07 09:18:34 -0800620 if (tell+logp<=budget)
621 {
622 ec_enc_bit_logp(enc, tf_res[i] ^ curr, logp);
623 tell = ec_enc_tell(enc, 0);
624 curr = tf_res[i];
625 tf_changed |= curr;
626 }
627 else
628 tf_res[i] = curr;
629 logp = isTransient ? 4 : 5;
Jean-Marc Valin163b76e2010-05-27 23:56:53 -0400630 }
Timothy B. Terriberry76469c62011-01-07 09:18:34 -0800631 /* Only code tf_select if it would actually make a difference. */
632 if (tf_select_rsv &&
633 tf_select_table[LM][4*isTransient+0+tf_changed]!=
634 tf_select_table[LM][4*isTransient+2+tf_changed])
635 ec_enc_bit_logp(enc, tf_select, 1);
636 else
637 tf_select = 0;
Jean-Marc Valin2ed5e672010-07-13 16:50:11 -0400638 for (i=start;i<end;i++)
Jean-Marc Valin890a9c02010-06-13 08:06:28 -0400639 tf_res[i] = tf_select_table[LM][4*isTransient+2*tf_select+tf_res[i]];
Jean-Marc Valin0f8fc0b2010-10-12 23:25:58 -0400640 /*printf("%d %d ", isTransient, tf_select); for(i=0;i<end;i++)printf("%d ", tf_res[i]);printf("\n");*/
Jean-Marc Valin163b76e2010-05-27 23:56:53 -0400641}
642
Jean-Marc Valine5e9aa72010-12-02 16:09:51 -0500643static void tf_decode(int start, int end, int C, int isTransient, int *tf_res, int LM, ec_dec *dec)
Jean-Marc Valin163b76e2010-05-27 23:56:53 -0400644{
Jean-Marc Valin890a9c02010-06-13 08:06:28 -0400645 int i, curr, tf_select;
Timothy B. Terriberry76469c62011-01-07 09:18:34 -0800646 int tf_select_rsv;
647 int tf_changed;
648 int logp;
649 ec_uint32 budget;
650 ec_uint32 tell;
651
652 budget = dec->buf->storage*8;
653 tell = ec_dec_tell(dec, 0);
654 logp = isTransient ? 2 : 4;
655 tf_select_rsv = LM>0 && tell+logp+1<=budget;
656 budget -= tf_select_rsv;
657 tf_changed = curr = 0;
658 for (i=start;i<end;i++)
Timothy B. Terriberry509ad202010-12-27 18:20:20 -0800659 {
Timothy B. Terriberry76469c62011-01-07 09:18:34 -0800660 if (tell+logp<=budget)
661 {
662 curr ^= ec_dec_bit_logp(dec, logp);
663 tell = ec_dec_tell(dec, 0);
664 tf_changed |= curr;
665 }
666 tf_res[i] = curr;
667 logp = isTransient ? 4 : 5;
668 }
669 tf_select = 0;
670 if (tf_select_rsv &&
671 tf_select_table[LM][4*isTransient+0+tf_changed] !=
672 tf_select_table[LM][4*isTransient+2+tf_changed])
673 {
674 tf_select = ec_dec_bit_logp(dec, 1);
675 }
676 for (i=start;i<end;i++)
677 {
678 tf_res[i] = tf_select_table[LM][4*isTransient+2*tf_select+tf_res[i]];
Timothy B. Terriberry509ad202010-12-27 18:20:20 -0800679 }
Jean-Marc Valin163b76e2010-05-27 23:56:53 -0400680}
681
Jean-Marc Valinc5792de2010-10-19 14:24:50 -0400682static int alloc_trim_analysis(const CELTMode *m, const celt_norm *X,
683 const celt_word16 *bandLogE, int nbEBands, int LM, int C, int N0)
684{
685 int i;
Jean-Marc Valin546dfa12010-12-10 17:18:17 -0500686 celt_word32 diff=0;
687 int c;
Jean-Marc Valin4b087df2010-11-30 21:08:31 -0500688 int trim_index = 5;
Jean-Marc Valinc5792de2010-10-19 14:24:50 -0400689 if (C==2)
690 {
691 celt_word16 sum = 0; /* Q10 */
692 /* Compute inter-channel correlation for low frequencies */
693 for (i=0;i<8;i++)
694 {
695 int j;
696 celt_word32 partial = 0;
697 for (j=m->eBands[i]<<LM;j<m->eBands[i+1]<<LM;j++)
698 partial = MAC16_16(partial, X[j], X[N0+j]);
699 sum = ADD16(sum, EXTRACT16(SHR32(partial, 18)));
700 }
701 sum = MULT16_16_Q15(QCONST16(1.f/8, 15), sum);
702 /*printf ("%f\n", sum);*/
Gregory Maxwell60c316b2010-11-04 20:14:19 -0400703 if (sum > QCONST16(.995f,10))
Jean-Marc Valin4b087df2010-11-30 21:08:31 -0500704 trim_index-=4;
Gregory Maxwell60c316b2010-11-04 20:14:19 -0400705 else if (sum > QCONST16(.92f,10))
Jean-Marc Valin4b087df2010-11-30 21:08:31 -0500706 trim_index-=3;
707 else if (sum > QCONST16(.85f,10))
Jean-Marc Valinc5792de2010-10-19 14:24:50 -0400708 trim_index-=2;
Gregory Maxwell60c316b2010-11-04 20:14:19 -0400709 else if (sum > QCONST16(.8f,10))
Jean-Marc Valinc40addc2010-10-22 14:57:07 -0400710 trim_index-=1;
Jean-Marc Valinc5792de2010-10-19 14:24:50 -0400711 }
Jean-Marc Valin546dfa12010-12-10 17:18:17 -0500712
713 /* Estimate spectral tilt */
Gregory Maxwell9743bf32010-11-04 20:45:09 -0400714 c=0; do {
Jean-Marc Valinc5792de2010-10-19 14:24:50 -0400715 for (i=0;i<nbEBands-1;i++)
716 {
Jean-Marc Valin546dfa12010-12-10 17:18:17 -0500717 diff += bandLogE[i+c*nbEBands]*(celt_int32)(2+2*i-nbEBands);
Jean-Marc Valinc5792de2010-10-19 14:24:50 -0400718 }
Gregory Maxwell9743bf32010-11-04 20:45:09 -0400719 } while (++c<0);
Jean-Marc Valinc5792de2010-10-19 14:24:50 -0400720 diff /= C*(nbEBands-1);
721 /*printf("%f\n", diff);*/
Jean-Marc Valin546dfa12010-12-10 17:18:17 -0500722 if (diff > QCONST16(2.f, DB_SHIFT))
Jean-Marc Valinc5792de2010-10-19 14:24:50 -0400723 trim_index--;
Jean-Marc Valin546dfa12010-12-10 17:18:17 -0500724 if (diff > QCONST16(8.f, DB_SHIFT))
Jean-Marc Valinc5792de2010-10-19 14:24:50 -0400725 trim_index--;
Jean-Marc Valin546dfa12010-12-10 17:18:17 -0500726 if (diff < -QCONST16(4.f, DB_SHIFT))
Jean-Marc Valin90377572010-10-22 15:12:01 -0400727 trim_index++;
Jean-Marc Valin546dfa12010-12-10 17:18:17 -0500728 if (diff < -QCONST16(10.f, DB_SHIFT))
729 trim_index++;
730
Jean-Marc Valinc5792de2010-10-19 14:24:50 -0400731 if (trim_index<0)
732 trim_index = 0;
Jean-Marc Valin546dfa12010-12-10 17:18:17 -0500733 if (trim_index>10)
734 trim_index = 10;
Jean-Marc Valinc5792de2010-10-19 14:24:50 -0400735 return trim_index;
736}
737
Jean-Marc Valine65978f2010-12-02 13:46:48 -0500738static int stereo_analysis(const CELTMode *m, const celt_norm *X,
739 int nbEBands, int LM, int C, int N0)
740{
741 int i;
742 int thetas;
743 celt_word32 sumLR = EPSILON, sumMS = EPSILON;
744
745 /* Use the L1 norm to model the entropy of the L/R signal vs the M/S signal */
746 for (i=0;i<13;i++)
747 {
748 int j;
749 for (j=m->eBands[i]<<LM;j<m->eBands[i+1]<<LM;j++)
750 {
751 celt_word16 L, R, M, S;
752 L = X[j];
753 R = X[N0+j];
754 M = L+R;
755 S = L-R;
756 sumLR += EXTEND32(ABS16(L)) + EXTEND32(ABS16(R));
757 sumMS += EXTEND32(ABS16(M)) + EXTEND32(ABS16(S));
758 }
759 }
760 sumMS = MULT16_32_Q15(QCONST16(0.707107f, 15), sumMS);
761 thetas = 13;
762 /* We don't need thetas for lower bands with LM<=1 */
763 if (LM<=1)
764 thetas -= 8;
765 return MULT16_32_Q15((m->eBands[13]<<(LM+1))+thetas, sumMS)
766 > MULT16_32_Q15(m->eBands[13]<<(LM+1), sumLR);
767}
768
Gregory Maxwell5f2a74b2008-08-11 23:50:07 -0400769#ifdef FIXED_POINT
Jean-Marc Valin35095c62010-11-04 13:24:44 -0400770int celt_encode_with_ec(CELTEncoder * restrict st, const celt_int16 * pcm, int frame_size, unsigned char *compressed, int nbCompressedBytes, ec_enc *enc)
Jean-Marc Valin8ebd3452007-11-29 20:17:32 +1100771{
Gregory Maxwell5f2a74b2008-08-11 23:50:07 -0400772#else
Jean-Marc Valin35095c62010-11-04 13:24:44 -0400773int celt_encode_with_ec_float(CELTEncoder * restrict st, const celt_sig * pcm, int frame_size, unsigned char *compressed, int nbCompressedBytes, ec_enc *enc)
Gregory Maxwell5f2a74b2008-08-11 23:50:07 -0400774{
775#endif
Jean-Marc Valin7a08ddd2010-10-18 14:55:42 -0400776 int i, c, N;
Jean-Marc Valinc890b582008-08-01 22:26:49 -0400777 int bits;
Jean-Marc Valin8679a802008-10-18 07:44:35 -0400778 ec_byte_buffer buf;
Jean-Marc Valin4794f2e2010-05-19 11:56:57 -0400779 ec_enc _enc;
Jean-Marc Valin234969c2009-10-17 22:12:42 -0400780 VARDECL(celt_sig, in);
781 VARDECL(celt_sig, freq);
Jean-Marc Valin234969c2009-10-17 22:12:42 -0400782 VARDECL(celt_norm, X);
783 VARDECL(celt_ener, bandE);
784 VARDECL(celt_word16, bandLogE);
Jean-Marc Valin6775de32008-08-02 08:14:42 -0400785 VARDECL(int, fine_quant);
Jean-Marc Valin234969c2009-10-17 22:12:42 -0400786 VARDECL(celt_word16, error);
Jean-Marc Valin6775de32008-08-02 08:14:42 -0400787 VARDECL(int, pulses);
788 VARDECL(int, offsets);
Jean-Marc Valin52cb5fb2009-06-10 08:08:55 -0400789 VARDECL(int, fine_priority);
Jean-Marc Valin163b76e2010-05-27 23:56:53 -0400790 VARDECL(int, tf_res);
Jean-Marc Valin0d8eaa32010-08-27 14:57:37 -0400791 celt_sig *_overlap_mem;
Jean-Marc Valin35095c62010-11-04 13:24:44 -0400792 celt_sig *prefilter_mem;
Jean-Marc Valin0d8eaa32010-08-27 14:57:37 -0400793 celt_word16 *oldBandE;
Jean-Marc Valin9d1decd2008-06-17 13:28:13 +1000794 int shortBlocks=0;
Jean-Marc Valin3b918ba2010-05-05 00:02:26 -0400795 int isTransient=0;
Jean-Marc Valinb8ba70c2010-04-18 22:10:24 -0400796 int resynth;
Jean-Marc Valin80ed1472009-10-15 21:45:32 -0400797 const int C = CHANNELS(st->channels);
Jean-Marc Valin017fa852010-05-06 22:11:48 -0400798 int LM, M;
Jean-Marc Valin890a9c02010-06-13 08:06:28 -0400799 int tf_select;
Jean-Marc Valin6b95d8f2010-06-21 21:39:44 -0400800 int nbFilledBytes, nbAvailableBytes;
Jean-Marc Valin85f41b22010-07-16 18:12:45 -0400801 int effEnd;
Jean-Marc Valinb801da52010-09-28 14:56:20 -0400802 int codedBands;
Jean-Marc Valinccd5a612010-10-13 01:11:55 -0400803 int tf_sum;
Jean-Marc Valinf1fea662010-10-09 22:58:52 -0400804 int alloc_trim;
Jean-Marc Valin6cbfbc32010-12-14 11:53:39 -0500805 int pitch_index=COMBFILTER_MINPERIOD;
Jean-Marc Valin35095c62010-11-04 13:24:44 -0400806 celt_word16 gain1 = 0;
Jean-Marc Valin4f177e82010-11-26 10:32:03 -0500807 int intensity=0;
Jean-Marc Valine65978f2010-12-02 13:46:48 -0500808 int dual_stereo=0;
Jean-Marc Valine5e9aa72010-12-02 16:09:51 -0500809 int effectiveBytes;
Jean-Marc Valin6ba0b352010-12-20 11:40:30 -0500810 celt_word16 pf_threshold;
Timothy B. Terriberry76469c62011-01-07 09:18:34 -0800811 int dynalloc_logp;
812 celt_int32 vbr_rate;
813 celt_int32 total_bits;
814 celt_int32 total_boost;
815 celt_int32 tell;
Jean-Marc Valin8d367022011-01-17 16:37:51 -0500816 int prefilter_tapset=0;
817 int pf_on;
Jean-Marc Valin8600f692008-02-29 15:14:12 +1100818 SAVE_STACK;
Jean-Marc Valin44ffd5a2008-02-22 00:39:25 +1100819
Gregory Maxwell0719f6f2009-07-09 17:07:24 -0400820 if (nbCompressedBytes<0 || pcm==NULL)
Jean-Marc Valin017fa852010-05-06 22:11:48 -0400821 return CELT_BAD_ARG;
Gregory Maxwell520eeae2009-02-09 01:33:21 -0500822
Jean-Marc Valin017fa852010-05-06 22:11:48 -0400823 for (LM=0;LM<4;LM++)
824 if (st->mode->shortMdctSize<<LM==frame_size)
825 break;
826 if (LM>=MAX_CONFIG_SIZES)
827 return CELT_BAD_ARG;
828 M=1<<LM;
Jean-Marc Valin8679a802008-10-18 07:44:35 -0400829
Jean-Marc Valin35095c62010-11-04 13:24:44 -0400830 prefilter_mem = st->in_mem+C*(st->overlap);
831 _overlap_mem = prefilter_mem+C*COMBFILTER_MAXPERIOD;
832 /*_overlap_mem = st->in_mem+C*(st->overlap);*/
833 oldBandE = (celt_word16*)(st->in_mem+C*(2*st->overlap+COMBFILTER_MAXPERIOD));
Jean-Marc Valin0d8eaa32010-08-27 14:57:37 -0400834
Jean-Marc Valin4794f2e2010-05-19 11:56:57 -0400835 if (enc==NULL)
836 {
837 ec_byte_writeinit_buffer(&buf, compressed, nbCompressedBytes);
838 ec_enc_init(&_enc,&buf);
839 enc = &_enc;
Timothy B. Terriberry76469c62011-01-07 09:18:34 -0800840 tell=1;
Jean-Marc Valin6b95d8f2010-06-21 21:39:44 -0400841 nbFilledBytes=0;
842 } else {
Timothy B. Terriberry76469c62011-01-07 09:18:34 -0800843 tell=ec_enc_tell(enc, 0);
844 nbFilledBytes=(tell+4)>>3;
Jean-Marc Valin4794f2e2010-05-19 11:56:57 -0400845 }
Jean-Marc Valin6b95d8f2010-06-21 21:39:44 -0400846 nbAvailableBytes = nbCompressedBytes - nbFilledBytes;
847
Timothy B. Terriberry76469c62011-01-07 09:18:34 -0800848 vbr_rate = st->vbr_rate_norm<<LM;
849 if (vbr_rate>0)
850 {
Jean-Marc Valine5e9aa72010-12-02 16:09:51 -0500851 effectiveBytes = st->vbr_rate_norm>>BITRES<<LM>>3;
Timothy B. Terriberry76469c62011-01-07 09:18:34 -0800852 /* Computes the max bit-rate allowed in VBR mode to avoid violating the
853 target rate and buffering.
854 We must do this up front so that bust-prevention logic triggers
855 correctly if we don't have enough bits. */
856 if (st->constrained_vbr)
857 {
858 celt_int32 vbr_bound;
859 celt_int32 max_allowed;
860 /* We could use any multiple of vbr_rate as bound (depending on the
861 delay).
862 This is clamped to ensure we use at least one byte if the encoder
863 was entirely empty, but to allow 0 in hybrid mode. */
864 vbr_bound = vbr_rate;
865 max_allowed = IMIN(IMAX((tell+7>>3)-nbFilledBytes,
866 vbr_rate+vbr_bound-st->vbr_reservoir>>(BITRES+3)),
867 nbAvailableBytes);
868 if(max_allowed < nbAvailableBytes)
869 {
870 nbCompressedBytes = nbFilledBytes+max_allowed;
871 nbAvailableBytes = max_allowed;
872 ec_byte_shrink(&buf, nbCompressedBytes);
873 }
874 }
875 } else
Jean-Marc Valine5e9aa72010-12-02 16:09:51 -0500876 effectiveBytes = nbCompressedBytes;
Timothy B. Terriberry76469c62011-01-07 09:18:34 -0800877 total_bits = nbCompressedBytes*8;
Jean-Marc Valine5e9aa72010-12-02 16:09:51 -0500878
Jean-Marc Valin85f41b22010-07-16 18:12:45 -0400879 effEnd = st->end;
880 if (effEnd > st->mode->effEBands)
881 effEnd = st->mode->effEBands;
882
Jean-Marc Valin04752672010-05-05 07:21:21 -0400883 N = M*st->mode->shortMdctSize;
Jean-Marc Valin0695a5f2010-08-27 11:33:18 -0400884 ALLOC(in, C*(N+st->overlap), celt_sig);
Jean-Marc Valina5431bf2008-01-03 20:53:01 +1100885
Jean-Marc Valin35095c62010-11-04 13:24:44 -0400886 /* Find pitch period and gain */
Jean-Marc Valin6f7e83d2007-12-01 00:36:41 +1100887 {
Jean-Marc Valin35095c62010-11-04 13:24:44 -0400888 VARDECL(celt_sig, _pre);
889 celt_sig *pre[2];
890 SAVE_STACK;
891 c = 0;
892 ALLOC(_pre, C*(N+COMBFILTER_MAXPERIOD), celt_sig);
893
894 pre[0] = _pre;
895 pre[1] = _pre + (N+COMBFILTER_MAXPERIOD);
896
Gregory Maxwell9743bf32010-11-04 20:45:09 -0400897 c=0; do {
Jean-Marc Valin35095c62010-11-04 13:24:44 -0400898 const celt_word16 * restrict pcmp = pcm+c;
899 celt_sig * restrict inp = in+c*(N+st->overlap)+st->overlap;
900
901 for (i=0;i<N;i++)
902 {
903 /* Apply pre-emphasis */
904 celt_sig tmp = MULT16_16(st->mode->preemph[2], SCALEIN(*pcmp));
905 *inp = tmp + st->preemph_memE[c];
906 st->preemph_memE[c] = MULT16_32_Q15(st->mode->preemph[1], *inp)
907 - MULT16_32_Q15(st->mode->preemph[0], tmp);
908 inp++;
909 pcmp+=C;
910 }
911 CELT_COPY(pre[c], prefilter_mem+c*COMBFILTER_MAXPERIOD, COMBFILTER_MAXPERIOD);
912 CELT_COPY(pre[c]+COMBFILTER_MAXPERIOD, in+c*(N+st->overlap)+st->overlap, N);
Gregory Maxwell9743bf32010-11-04 20:45:09 -0400913 } while (++c<C);
Jean-Marc Valin35095c62010-11-04 13:24:44 -0400914
915#ifdef ENABLE_POSTFILTER
Jean-Marc Valin7365c7d2010-12-21 16:30:01 -0500916 if (nbAvailableBytes>12*C && st->start==0)
Jean-Marc Valin35095c62010-11-04 13:24:44 -0400917 {
918 VARDECL(celt_word16, pitch_buf);
919 ALLOC(pitch_buf, (COMBFILTER_MAXPERIOD+N)>>1, celt_word16);
920 celt_word32 tmp=0;
921 celt_word32 mem0[2]={0,0};
922 celt_word16 mem1[2]={0,0};
923
924 pitch_downsample(pre, pitch_buf, COMBFILTER_MAXPERIOD+N, COMBFILTER_MAXPERIOD+N,
925 C, mem0, mem1);
926 pitch_search(st->mode, pitch_buf+(COMBFILTER_MAXPERIOD>>1), pitch_buf, N,
927 COMBFILTER_MAXPERIOD-COMBFILTER_MINPERIOD, &pitch_index, &tmp, 1<<LM);
928 pitch_index = COMBFILTER_MAXPERIOD-pitch_index;
929
930 gain1 = remove_doubling(pitch_buf, COMBFILTER_MAXPERIOD, COMBFILTER_MINPERIOD,
931 N, &pitch_index, st->prefilter_period, st->prefilter_gain);
Jean-Marc Valindfa847a2011-01-17 11:37:08 -0500932 if (pitch_index > COMBFILTER_MAXPERIOD-2)
933 pitch_index = COMBFILTER_MAXPERIOD-2;
Jean-Marc Valin6cbfbc32010-12-14 11:53:39 -0500934 gain1 = MULT16_16_Q15(QCONST16(.7f,15),gain1);
Jean-Marc Valin8d367022011-01-17 16:37:51 -0500935 prefilter_tapset = st->tapset_decision;
Jean-Marc Valin6cbfbc32010-12-14 11:53:39 -0500936 } else {
937 gain1 = 0;
Jean-Marc Valin35095c62010-11-04 13:24:44 -0400938 }
Jean-Marc Valin6ba0b352010-12-20 11:40:30 -0500939
940 /* Gain threshold for enabling the prefilter/postfilter */
941 pf_threshold = QCONST16(.2f,15);
942
943 /* Adjusting the threshold based on rate and continuity */
944 if (abs(pitch_index-st->prefilter_period)*10>pitch_index)
945 pf_threshold += QCONST16(.2f,15);
946 if (nbAvailableBytes<25)
947 pf_threshold += QCONST16(.1f,15);
948 if (nbAvailableBytes<35)
949 pf_threshold += QCONST16(.1f,15);
950 if (st->prefilter_gain > QCONST16(.4f,15))
951 pf_threshold -= QCONST16(.1f,15);
952 if (st->prefilter_gain > QCONST16(.55f,15))
953 pf_threshold -= QCONST16(.1f,15);
954
955 /* Hard threshold at 0.2 */
956 pf_threshold = MAX16(pf_threshold, QCONST16(.2f,15));
957 if (gain1<pf_threshold)
Jean-Marc Valin35095c62010-11-04 13:24:44 -0400958 {
Timothy B. Terriberry76469c62011-01-07 09:18:34 -0800959 if(tell+15<=total_bits)
960 ec_enc_bit_logp(enc, 0, 1);
Jean-Marc Valin35095c62010-11-04 13:24:44 -0400961 gain1 = 0;
Jean-Marc Valin8d367022011-01-17 16:37:51 -0500962 pf_on = 0;
Jean-Marc Valin35095c62010-11-04 13:24:44 -0400963 } else {
964 int qg;
965 int octave;
Jean-Marc Valin6ba0b352010-12-20 11:40:30 -0500966
967 if (gain1 > QCONST16(.6f,15))
968 gain1 = QCONST16(.6f,15);
969 if (ABS16(gain1-st->prefilter_gain)<QCONST16(.1,15))
970 gain1=st->prefilter_gain;
971
Jean-Marc Valin35095c62010-11-04 13:24:44 -0400972#ifdef FIXED_POINT
973 qg = ((gain1+2048)>>12)-2;
974#else
975 qg = floor(.5+gain1*8)-2;
976#endif
Timothy B. Terriberrye86fb262010-12-17 14:50:19 -0800977 ec_enc_bit_logp(enc, 1, 1);
Jean-Marc Valindfa847a2011-01-17 11:37:08 -0500978 pitch_index += 1;
Jean-Marc Valin35095c62010-11-04 13:24:44 -0400979 octave = EC_ILOG(pitch_index)-5;
980 ec_enc_uint(enc, octave, 6);
981 ec_enc_bits(enc, pitch_index-(16<<octave), 4+octave);
Jean-Marc Valindfa847a2011-01-17 11:37:08 -0500982 pitch_index -= 1;
Jean-Marc Valin35095c62010-11-04 13:24:44 -0400983 ec_enc_bits(enc, qg, 2);
984 gain1 = QCONST16(.125f,15)*(qg+2);
Jean-Marc Valindfa847a2011-01-17 11:37:08 -0500985 ec_enc_bits(enc, prefilter_tapset!=0, 1);
986 if (prefilter_tapset!=0)
987 ec_enc_bits(enc, prefilter_tapset>1, 1);
Jean-Marc Valin8d367022011-01-17 16:37:51 -0500988 pf_on = 1;
Jean-Marc Valin35095c62010-11-04 13:24:44 -0400989 }
990 /*printf("%d %f\n", pitch_index, gain1);*/
991#else /* ENABLE_POSTFILTER */
Jean-Marc Valin8d367022011-01-17 16:37:51 -0500992 if(tell+17<=total_bits)
Timothy B. Terriberry76469c62011-01-07 09:18:34 -0800993 ec_enc_bit_logp(enc, 0, 1);
Jean-Marc Valin8d367022011-01-17 16:37:51 -0500994 pf_on = 0;
Jean-Marc Valin35095c62010-11-04 13:24:44 -0400995#endif /* ENABLE_POSTFILTER */
996
Gregory Maxwell9743bf32010-11-04 20:45:09 -0400997 c=0; do {
Jean-Marc Valin70d30ff2010-12-13 13:50:29 -0500998 st->prefilter_period=IMAX(st->prefilter_period, COMBFILTER_MINPERIOD);
Jean-Marc Valin35095c62010-11-04 13:24:44 -0400999 CELT_COPY(in+c*(N+st->overlap), st->in_mem+c*(st->overlap), st->overlap);
1000#ifdef ENABLE_POSTFILTER
1001 comb_filter(in+c*(N+st->overlap)+st->overlap, pre[c]+COMBFILTER_MAXPERIOD,
Jean-Marc Valindfa847a2011-01-17 11:37:08 -05001002 st->prefilter_period, pitch_index, N, C, -st->prefilter_gain, -gain1,
1003 st->prefilter_tapset, prefilter_tapset, st->mode->window, st->mode->overlap);
Jean-Marc Valin35095c62010-11-04 13:24:44 -04001004#endif /* ENABLE_POSTFILTER */
1005 CELT_COPY(st->in_mem+c*(st->overlap), in+c*(N+st->overlap)+N, st->overlap);
1006
1007#ifdef ENABLE_POSTFILTER
1008 if (N>COMBFILTER_MAXPERIOD)
1009 {
1010 CELT_MOVE(prefilter_mem+c*COMBFILTER_MAXPERIOD, pre[c]+N, COMBFILTER_MAXPERIOD);
1011 } else {
1012 CELT_MOVE(prefilter_mem+c*COMBFILTER_MAXPERIOD, prefilter_mem+c*COMBFILTER_MAXPERIOD+N, COMBFILTER_MAXPERIOD-N);
1013 CELT_MOVE(prefilter_mem+c*COMBFILTER_MAXPERIOD+COMBFILTER_MAXPERIOD-N, pre[c]+COMBFILTER_MAXPERIOD, N);
1014 }
1015#endif /* ENABLE_POSTFILTER */
Gregory Maxwell9743bf32010-11-04 20:45:09 -04001016 } while (++c<C);
Jean-Marc Valin35095c62010-11-04 13:24:44 -04001017
1018 RESTORE_STACK;
Jean-Marc Valin6f7e83d2007-12-01 00:36:41 +11001019 }
Jean-Marc Valin2014ca32009-06-18 23:33:04 -04001020
Jean-Marc Valin35095c62010-11-04 13:24:44 -04001021#ifdef RESYNTH
1022 resynth = 1;
1023#else
1024 resynth = 0;
1025#endif
Jean-Marc Valinb8ba70c2010-04-18 22:10:24 -04001026
Timothy B. Terriberry76469c62011-01-07 09:18:34 -08001027 isTransient = 0;
1028 shortBlocks = 0;
1029 if (LM>0 && ec_enc_tell(enc, 0)+3<=total_bits)
Jean-Marc Valin1213ba52010-08-31 17:03:13 -04001030 {
Timothy B. Terriberry76469c62011-01-07 09:18:34 -08001031 if (st->complexity > 1)
1032 {
1033 isTransient = transient_analysis(in, N+st->overlap, C,
1034 &st->frame_max, st->overlap);
1035 if (isTransient)
1036 shortBlocks = M;
1037 }
1038 ec_enc_bit_logp(enc, isTransient, 3);
Jean-Marc Valin1213ba52010-08-31 17:03:13 -04001039 }
Jean-Marc Valinc5f2a9d2008-10-26 22:00:26 -04001040
Jean-Marc Valin234969c2009-10-17 22:12:42 -04001041 ALLOC(freq, C*N, celt_sig); /**< Interleaved signal MDCTs */
1042 ALLOC(bandE,st->mode->nbEBands*C, celt_ener);
1043 ALLOC(bandLogE,st->mode->nbEBands*C, celt_word16);
Jean-Marc Valin32ec58c2009-05-01 21:28:58 -04001044 /* Compute MDCTs */
Jean-Marc Valin017fa852010-05-06 22:11:48 -04001045 compute_mdcts(st->mode, shortBlocks, in, freq, C, LM);
Jean-Marc Valin08a82ff2009-06-14 14:05:19 -04001046
Jean-Marc Valin234969c2009-10-17 22:12:42 -04001047 ALLOC(X, C*N, celt_norm); /**< Interleaved normalised MDCTs */
Jean-Marc Valin8d4ac152008-02-29 17:24:02 +11001048
Jean-Marc Valin85f41b22010-07-16 18:12:45 -04001049 compute_band_energies(st->mode, freq, bandE, effEnd, C, M);
Jean-Marc Valin504fb3c2010-08-06 15:56:22 -04001050
1051 amp2Log2(st->mode, effEnd, st->end, bandE, bandLogE, C);
Jean-Marc Valinbd5d54a2009-10-20 00:25:31 -04001052
Jean-Marc Valin8ebd3452007-11-29 20:17:32 +11001053 /* Band normalisation */
Jean-Marc Valin85f41b22010-07-16 18:12:45 -04001054 normalise_bands(st->mode, freq, X, bandE, effEnd, C, M);
Jean-Marc Valin4c77ea92009-09-14 22:50:41 -04001055
Jean-Marc Valin8200b2d2010-10-15 02:18:47 -04001056 ALLOC(tf_res, st->mode->nbEBands, int);
1057 /* Needs to be before coarse energy quantization because otherwise the energy gets modified */
Jean-Marc Valine5e9aa72010-12-02 16:09:51 -05001058 tf_select = tf_analysis(st->mode, bandLogE, oldBandE, effEnd, C, isTransient, tf_res, effectiveBytes, X, N, LM, &tf_sum);
Jean-Marc Valin8200b2d2010-10-15 02:18:47 -04001059 for (i=effEnd;i<st->end;i++)
1060 tf_res[i] = tf_res[effEnd-1];
1061
Jean-Marc Valin9099bc32010-08-07 21:50:01 -04001062 ALLOC(error, C*st->mode->nbEBands, celt_word16);
Jean-Marc Valin5e7f02d2010-08-08 09:48:22 -04001063 quant_coarse_energy(st->mode, st->start, st->end, effEnd, bandLogE,
Timothy B. Terriberry76469c62011-01-07 09:18:34 -08001064 oldBandE, total_bits, error, enc,
Timothy B. Terriberryef2e6502010-11-09 01:43:18 -08001065 C, LM, nbAvailableBytes, st->force_intra,
Jean-Marc Valin1b36d6c2010-08-31 17:21:52 -04001066 &st->delayedIntra, st->complexity >= 4);
Jean-Marc Valin9099bc32010-08-07 21:50:01 -04001067
Jean-Marc Valine5e9aa72010-12-02 16:09:51 -05001068 tf_encode(st->start, st->end, isTransient, tf_res, LM, tf_select, enc);
Jean-Marc Valinbe04f5a2010-08-07 21:42:03 -04001069
Timothy B. Terriberry76469c62011-01-07 09:18:34 -08001070 st->spread_decision = SPREAD_NORMAL;
1071 if (ec_enc_tell(enc, 0)+4<=total_bits)
Jean-Marc Valin1d17b9a2010-08-31 14:51:58 -04001072 {
Timothy B. Terriberry76469c62011-01-07 09:18:34 -08001073 if (shortBlocks || st->complexity < 3 || nbAvailableBytes < 10*C)
Jean-Marc Valin1213ba52010-08-31 17:03:13 -04001074 {
Timothy B. Terriberry76469c62011-01-07 09:18:34 -08001075 if (st->complexity == 0)
1076 st->spread_decision = SPREAD_NONE;
Jean-Marc Valin1213ba52010-08-31 17:03:13 -04001077 } else {
Timothy B. Terriberry76469c62011-01-07 09:18:34 -08001078 st->spread_decision = spreading_decision(st->mode, X,
Jean-Marc Valin8d367022011-01-17 16:37:51 -05001079 &st->tonal_average, st->spread_decision, &st->hf_average,
1080 &st->tapset_decision, pf_on&&!shortBlocks, effEnd, C, M);
Jean-Marc Valin1213ba52010-08-31 17:03:13 -04001081 }
Timothy B. Terriberry76469c62011-01-07 09:18:34 -08001082 ec_enc_icdf(enc, st->spread_decision, spread_icdf, 5);
Jean-Marc Valin1d17b9a2010-08-31 14:51:58 -04001083 }
Jean-Marc Valin9099bc32010-08-07 21:50:01 -04001084
Jean-Marc Valinf1fea662010-10-09 22:58:52 -04001085 ALLOC(offsets, st->mode->nbEBands, int);
1086
1087 for (i=0;i<st->mode->nbEBands;i++)
1088 offsets[i] = 0;
1089 /* Dynamic allocation code */
1090 /* Make sure that dynamic allocation can't make us bust the budget */
Jean-Marc Valine5e9aa72010-12-02 16:09:51 -05001091 if (effectiveBytes > 50 && LM>=1)
Jean-Marc Valinf1fea662010-10-09 22:58:52 -04001092 {
1093 int t1, t2;
1094 if (LM <= 1)
1095 {
1096 t1 = 3;
1097 t2 = 5;
1098 } else {
1099 t1 = 2;
1100 t2 = 4;
1101 }
1102 for (i=1;i<st->mode->nbEBands-1;i++)
1103 {
Jean-Marc Valina3a066c2010-11-04 15:15:54 -04001104 celt_word32 d2;
1105 d2 = 2*bandLogE[i]-bandLogE[i-1]-bandLogE[i+1];
1106 if (C==2)
1107 d2 = HALF32(d2 + 2*bandLogE[i+st->mode->nbEBands]-
1108 bandLogE[i-1+st->mode->nbEBands]-bandLogE[i+1+st->mode->nbEBands]);
1109 if (d2 > SHL16(t1,DB_SHIFT))
Jean-Marc Valinf1fea662010-10-09 22:58:52 -04001110 offsets[i] += 1;
Jean-Marc Valina3a066c2010-11-04 15:15:54 -04001111 if (d2 > SHL16(t2,DB_SHIFT))
Jean-Marc Valinf1fea662010-10-09 22:58:52 -04001112 offsets[i] += 1;
1113 }
1114 }
Timothy B. Terriberry76469c62011-01-07 09:18:34 -08001115 dynalloc_logp = 6;
1116 total_bits<<=BITRES;
1117 total_boost = 0;
1118 tell = ec_enc_tell(enc, BITRES);
Timothy B. Terriberryd6f61572010-12-30 09:04:16 -08001119 for (i=st->start;i<st->end;i++)
Jean-Marc Valinf1fea662010-10-09 22:58:52 -04001120 {
Timothy B. Terriberry76469c62011-01-07 09:18:34 -08001121 int width, quanta;
1122 int dynalloc_loop_logp;
1123 int boost;
Jean-Marc Valinf1fea662010-10-09 22:58:52 -04001124 int j;
Timothy B. Terriberry76469c62011-01-07 09:18:34 -08001125 width = C*(st->mode->eBands[i+1]-st->mode->eBands[i])<<LM;
1126 /* quanta is 6 bits, but no more than 1 bit/sample
1127 and no less than 1/8 bit/sample */
1128 quanta = IMIN(width<<BITRES, IMAX(6<<BITRES, width));
1129 dynalloc_loop_logp = dynalloc_logp;
1130 boost = 0;
1131 for (j = 0; tell+(dynalloc_loop_logp<<BITRES) < total_bits-total_boost
1132 && boost < (64<<LM)*(C<<BITRES); j++)
Jean-Marc Valinf1fea662010-10-09 22:58:52 -04001133 {
Timothy B. Terriberry76469c62011-01-07 09:18:34 -08001134 int flag;
1135 flag = j<offsets[i];
1136 ec_enc_bit_logp(enc, flag, dynalloc_loop_logp);
1137 tell = ec_enc_tell(enc, BITRES);
1138 if (!flag)
1139 break;
1140 boost += quanta;
1141 total_boost += quanta;
1142 dynalloc_loop_logp = 1;
Jean-Marc Valinf1fea662010-10-09 22:58:52 -04001143 }
Timothy B. Terriberry76469c62011-01-07 09:18:34 -08001144 /* Making dynalloc more likely */
1145 if (j)
1146 dynalloc_logp = IMAX(2, dynalloc_logp-1);
1147 offsets[i] = boost;
Jean-Marc Valinf1fea662010-10-09 22:58:52 -04001148 }
Timothy B. Terriberry76469c62011-01-07 09:18:34 -08001149 alloc_trim = 5;
1150 if (tell+(6<<BITRES) <= total_bits - total_boost)
1151 {
1152 alloc_trim = alloc_trim_analysis(st->mode, X, bandLogE,
1153 st->mode->nbEBands, LM, C, N);
1154 ec_enc_icdf(enc, alloc_trim, trim_icdf, 7);
1155 tell = ec_enc_tell(enc, BITRES);
1156 }
Jean-Marc Valinf1fea662010-10-09 22:58:52 -04001157
Gregory Maxwell888d8ce2009-05-21 04:21:53 -04001158 /* Variable bitrate */
Timothy B. Terriberry76469c62011-01-07 09:18:34 -08001159 if (vbr_rate>0)
Gregory Maxwell888d8ce2009-05-21 04:21:53 -04001160 {
Jean-Marc Valinbd5d54a2009-10-20 00:25:31 -04001161 celt_word16 alpha;
Timothy B. Terriberry76469c62011-01-07 09:18:34 -08001162 celt_int32 delta;
Gregory Maxwella9411472010-10-28 03:52:21 -04001163 /* The target rate in 8th bits per frame */
Jean-Marc Valinbe04f5a2010-08-07 21:42:03 -04001164 celt_int32 target;
Timothy B. Terriberry76469c62011-01-07 09:18:34 -08001165 celt_int32 min_allowed;
Jean-Marc Valinbe04f5a2010-08-07 21:42:03 -04001166
Timothy B. Terriberry76469c62011-01-07 09:18:34 -08001167 target = vbr_rate + st->vbr_offset - ((40*C+20)<<BITRES);
Jean-Marc Valin30165bb2010-12-03 14:35:59 -05001168
Gregory Maxwellfac6c982010-10-28 15:00:37 -04001169 /* Shortblocks get a large boost in bitrate, but since they
Jean-Marc Valinccd5a612010-10-13 01:11:55 -04001170 are uncommon long blocks are not greatly affected */
1171 if (shortBlocks || tf_sum < -2*(st->end-st->start))
Jean-Marc Valin30165bb2010-12-03 14:35:59 -05001172 target = 7*target/4;
Jean-Marc Valinccd5a612010-10-13 01:11:55 -04001173 else if (tf_sum < -(st->end-st->start))
1174 target = 3*target/2;
Jean-Marc Valin3b918ba2010-05-05 00:02:26 -04001175 else if (M > 1)
Jean-Marc Valinccd5a612010-10-13 01:11:55 -04001176 target-=(target+14)/28;
Gregory Maxwell888d8ce2009-05-21 04:21:53 -04001177
Gregory Maxwella9411472010-10-28 03:52:21 -04001178 /* The current offset is removed from the target and the space used
1179 so far is added*/
Jean-Marc Valina4badac2010-12-03 15:20:11 -05001180 target=target+tell;
Jean-Marc Valin30165bb2010-12-03 14:35:59 -05001181 /* By how much did we "miss" the target on that frame */
1182 delta = target - vbr_rate;
Gregory Maxwell888d8ce2009-05-21 04:21:53 -04001183
Timothy B. Terriberry76469c62011-01-07 09:18:34 -08001184 /* In VBR mode the frame size must not be reduced so much that it would
1185 result in the encoder running out of bits.
1186 The margin of 2 bytes ensures that none of the bust-prevention logic
1187 in the decoder will have triggered so far. */
1188 min_allowed = (tell+total_boost+(1<<BITRES+3)-1>>(BITRES+3)) + 2 - nbFilledBytes;
Gregory Maxwellfac6c982010-10-28 15:00:37 -04001189
Gregory Maxwellfac6c982010-10-28 15:00:37 -04001190 nbAvailableBytes = target+(1<<(BITRES+2))>>(BITRES+3);
Gregory Maxwelld85018c2011-01-13 14:38:24 -05001191 nbAvailableBytes = IMAX(min_allowed,nbAvailableBytes);
1192 nbAvailableBytes = IMIN(nbCompressedBytes,nbAvailableBytes+nbFilledBytes) - nbFilledBytes;
Jean-Marc Valin6b565262011-01-12 11:27:03 -05001193
Gregory Maxwellfac6c982010-10-28 15:00:37 -04001194 target=nbAvailableBytes<<(BITRES+3);
1195
Gregory Maxwella9411472010-10-28 03:52:21 -04001196 if (st->vbr_count < 970)
Jean-Marc Valinbd5d54a2009-10-20 00:25:31 -04001197 {
1198 st->vbr_count++;
Gregory Maxwella9411472010-10-28 03:52:21 -04001199 alpha = celt_rcp(SHL32(EXTEND32(st->vbr_count+20),16));
Jean-Marc Valinbd5d54a2009-10-20 00:25:31 -04001200 } else
1201 alpha = QCONST16(.001f,15);
Jean-Marc Valinbd5d54a2009-10-20 00:25:31 -04001202 /* How many bits have we used in excess of what we're allowed */
Jean-Marc Valin9faf7402010-12-04 10:27:22 -05001203 if (st->constrained_vbr)
1204 st->vbr_reservoir += target - vbr_rate;
Jean-Marc Valinbd5d54a2009-10-20 00:25:31 -04001205 /*printf ("%d\n", st->vbr_reservoir);*/
1206
1207 /* Compute the offset we need to apply in order to reach the target */
Jean-Marc Valin736efd62010-08-31 11:52:45 -04001208 st->vbr_drift += (celt_int32)MULT16_32_Q15(alpha,delta-st->vbr_offset-st->vbr_drift);
Jean-Marc Valinbd5d54a2009-10-20 00:25:31 -04001209 st->vbr_offset = -st->vbr_drift;
1210 /*printf ("%d\n", st->vbr_drift);*/
1211
Jean-Marc Valin9faf7402010-12-04 10:27:22 -05001212 if (st->constrained_vbr && st->vbr_reservoir < 0)
Jean-Marc Valinbd5d54a2009-10-20 00:25:31 -04001213 {
1214 /* We're under the min value -- increase rate */
Gregory Maxwellfac6c982010-10-28 15:00:37 -04001215 int adjust = (-st->vbr_reservoir)/(8<<BITRES);
1216 nbAvailableBytes += adjust;
1217 st->vbr_reservoir = 0;
Jean-Marc Valinbd5d54a2009-10-20 00:25:31 -04001218 /*printf ("+%d\n", adjust);*/
1219 }
Gregory Maxwelld85018c2011-01-13 14:38:24 -05001220 nbCompressedBytes = IMIN(nbCompressedBytes,nbAvailableBytes+nbFilledBytes);
Jean-Marc Valin6b95d8f2010-06-21 21:39:44 -04001221
Jean-Marc Valinbd5d54a2009-10-20 00:25:31 -04001222 /* This moves the raw bits to take into account the new compressed size */
Jean-Marc Valine6108642009-08-01 23:05:47 +02001223 ec_byte_shrink(&buf, nbCompressedBytes);
Gregory Maxwell888d8ce2009-05-21 04:21:53 -04001224 }
1225
Jean-Marc Valin4f177e82010-11-26 10:32:03 -05001226 if (C==2)
1227 {
1228 int effectiveRate;
1229
Timothy B. Terriberry76469c62011-01-07 09:18:34 -08001230 /* Always use MS for 2.5 ms frames until we can do a better analysis */
1231 if (LM!=0)
1232 dual_stereo = stereo_analysis(st->mode, X, st->mode->nbEBands, LM, C, N);
1233
Jean-Marc Valin4f177e82010-11-26 10:32:03 -05001234 /* Account for coarse energy */
Jean-Marc Valine5e9aa72010-12-02 16:09:51 -05001235 effectiveRate = (8*effectiveBytes - 80)>>LM;
1236
Jean-Marc Valin4f177e82010-11-26 10:32:03 -05001237 /* effectiveRate in kb/s */
1238 effectiveRate = 2*effectiveRate/5;
1239 if (effectiveRate<35)
Jean-Marc Valin6cbfbc32010-12-14 11:53:39 -05001240 intensity = 8;
Jean-Marc Valin4f177e82010-11-26 10:32:03 -05001241 else if (effectiveRate<50)
1242 intensity = 12;
1243 else if (effectiveRate<68)
1244 intensity = 16;
1245 else if (effectiveRate<84)
1246 intensity = 18;
1247 else if (effectiveRate<102)
1248 intensity = 19;
1249 else if (effectiveRate<130)
1250 intensity = 20;
1251 else
1252 intensity = 100;
1253 intensity = IMIN(st->end,IMAX(st->start, intensity));
Jean-Marc Valin4f177e82010-11-26 10:32:03 -05001254 }
1255
Jean-Marc Valinbe04f5a2010-08-07 21:42:03 -04001256 /* Bit allocation */
1257 ALLOC(fine_quant, st->mode->nbEBands, int);
1258 ALLOC(pulses, st->mode->nbEBands, int);
Jean-Marc Valin52cb5fb2009-06-10 08:08:55 -04001259 ALLOC(fine_priority, st->mode->nbEBands, int);
Jean-Marc Valincb7a2a32008-02-11 16:44:48 +11001260
Timothy B. Terriberry76ea41e2010-12-16 14:39:58 -08001261 /* bits = packet size - where we are - safety */
1262 bits = (nbCompressedBytes*8<<BITRES) - ec_enc_tell(enc, BITRES) - 1;
Jean-Marc Valindfd6e712010-12-09 23:23:34 -05001263 codedBands = compute_allocation(st->mode, st->start, st->end, offsets,
Timothy B. Terriberry76469c62011-01-07 09:18:34 -08001264 alloc_trim, &intensity, &dual_stereo, bits, pulses, fine_quant,
1265 fine_priority, C, LM, enc, 1, st->lastCodedBands);
Jean-Marc Valindfd6e712010-12-09 23:23:34 -05001266 st->lastCodedBands = codedBands;
Jean-Marc Valin37ab9c62008-11-08 09:14:38 -05001267
Jean-Marc Valin0d8eaa32010-08-27 14:57:37 -04001268 quant_fine_energy(st->mode, st->start, st->end, bandE, oldBandE, error, fine_quant, enc, C);
Jean-Marc Valin6775de32008-08-02 08:14:42 -04001269
Jean-Marc Valin7b5a0862010-07-29 15:01:24 +02001270#ifdef MEASURE_NORM_MSE
Jean-Marc Valin44092242010-07-29 18:32:54 +02001271 float X0[3000];
1272 float bandE0[60];
Gregory Maxwell9743bf32010-11-04 20:45:09 -04001273 c=0; do
Jean-Marc Valin44092242010-07-29 18:32:54 +02001274 for (i=0;i<N;i++)
1275 X0[i+c*N] = X[i+c*N];
Gregory Maxwell9743bf32010-11-04 20:45:09 -04001276 while (++c<C);
Jean-Marc Valin44092242010-07-29 18:32:54 +02001277 for (i=0;i<C*st->mode->nbEBands;i++)
Jean-Marc Valin7b5a0862010-07-29 15:01:24 +02001278 bandE0[i] = bandE[i];
1279#endif
1280
Jean-Marc Valin8ebd3452007-11-29 20:17:32 +11001281 /* Residual quantisation */
Jean-Marc Valin4f177e82010-11-26 10:32:03 -05001282 quant_all_bands(1, st->mode, st->start, st->end, X, C==2 ? X+N : NULL,
Timothy B. Terriberry320cf2e2010-12-17 05:52:06 -08001283 bandE, pulses, shortBlocks, st->spread_decision, dual_stereo, intensity, tf_res, resynth,
Jean-Marc Valin4f177e82010-11-26 10:32:03 -05001284 nbCompressedBytes*8, enc, LM, codedBands);
Jean-Marc Valin39710532009-06-09 00:10:32 -04001285
Jean-Marc Valin0d8eaa32010-08-27 14:57:37 -04001286 quant_energy_finalise(st->mode, st->start, st->end, bandE, oldBandE, error, fine_quant, fine_priority, nbCompressedBytes*8-ec_enc_tell(enc, 0), enc, C);
Jean-Marc Valin39710532009-06-09 00:10:32 -04001287
Jean-Marc Valin35095c62010-11-04 13:24:44 -04001288#ifdef RESYNTH
Jean-Marc Valin37ab9c62008-11-08 09:14:38 -05001289 /* Re-synthesis of the coded audio if required */
Jean-Marc Valinb8ba70c2010-04-18 22:10:24 -04001290 if (resynth)
Jean-Marc Valin18ddc022008-02-22 14:24:50 +11001291 {
Jean-Marc Valine0ce2cf2010-08-26 23:58:08 -04001292 celt_sig *out_mem[2];
Jean-Marc Valin0d8eaa32010-08-27 14:57:37 -04001293 celt_sig *overlap_mem[2];
Jean-Marc Valine0ce2cf2010-08-26 23:58:08 -04001294
Jean-Marc Valin0d8eaa32010-08-27 14:57:37 -04001295 log2Amp(st->mode, st->start, st->end, bandE, oldBandE, C);
Jean-Marc Valinbc272de2010-08-02 09:41:31 -04001296
1297#ifdef MEASURE_NORM_MSE
1298 measure_norm_mse(st->mode, X, X0, bandE, bandE0, M, N, C);
1299#endif
1300
Jean-Marc Valin88619552009-10-04 21:35:36 -04001301 /* Synthesis */
Jean-Marc Valin85f41b22010-07-16 18:12:45 -04001302 denormalise_bands(st->mode, X, freq, bandE, effEnd, C, M);
Jean-Marc Valin88619552009-10-04 21:35:36 -04001303
Jean-Marc Valin35095c62010-11-04 13:24:44 -04001304 CELT_MOVE(st->syn_mem[0], st->syn_mem[0]+N, MAX_PERIOD);
1305 if (C==2)
1306 CELT_MOVE(st->syn_mem[1], st->syn_mem[1]+N, MAX_PERIOD);
1307
Gregory Maxwell9743bf32010-11-04 20:45:09 -04001308 c=0; do
Jean-Marc Valin3b0df0d2010-07-16 15:55:30 -04001309 for (i=0;i<M*st->mode->eBands[st->start];i++)
1310 freq[c*N+i] = 0;
Gregory Maxwell9743bf32010-11-04 20:45:09 -04001311 while (++c<C);
1312 c=0; do
Jean-Marc Valin3b0df0d2010-07-16 15:55:30 -04001313 for (i=M*st->mode->eBands[st->end];i<N;i++)
1314 freq[c*N+i] = 0;
Gregory Maxwell9743bf32010-11-04 20:45:09 -04001315 while (++c<C);
Jean-Marc Valin3b0df0d2010-07-16 15:55:30 -04001316
Jean-Marc Valin35095c62010-11-04 13:24:44 -04001317 out_mem[0] = st->syn_mem[0]+MAX_PERIOD;
1318 if (C==2)
1319 out_mem[1] = st->syn_mem[1]+MAX_PERIOD;
Jean-Marc Valin0d8eaa32010-08-27 14:57:37 -04001320
Gregory Maxwell9743bf32010-11-04 20:45:09 -04001321 c=0; do
Jean-Marc Valin0d8eaa32010-08-27 14:57:37 -04001322 overlap_mem[c] = _overlap_mem + c*st->overlap;
Gregory Maxwell9743bf32010-11-04 20:45:09 -04001323 while (++c<C);
Jean-Marc Valine0ce2cf2010-08-26 23:58:08 -04001324
Jean-Marc Valin7a08ddd2010-10-18 14:55:42 -04001325 compute_inv_mdcts(st->mode, shortBlocks, freq, out_mem, overlap_mem, C, LM);
Jean-Marc Valine12017e2009-10-03 13:57:31 -04001326
Jean-Marc Valin35095c62010-11-04 13:24:44 -04001327#ifdef ENABLE_POSTFILTER
Gregory Maxwell9743bf32010-11-04 20:45:09 -04001328 c=0; do {
Jean-Marc Valin70d30ff2010-12-13 13:50:29 -05001329 st->prefilter_period=IMAX(st->prefilter_period, COMBFILTER_MINPERIOD);
1330 st->prefilter_period_old=IMAX(st->prefilter_period_old, COMBFILTER_MINPERIOD);
1331 if (LM!=0)
1332 {
1333 comb_filter(out_mem[c], out_mem[c], st->prefilter_period, st->prefilter_period, st->overlap, C,
Jean-Marc Valindfa847a2011-01-17 11:37:08 -05001334 st->prefilter_gain, st->prefilter_gain, st->prefilter_tapset, st->prefilter_tapset,
1335 NULL, 0);
Jean-Marc Valin70d30ff2010-12-13 13:50:29 -05001336 comb_filter(out_mem[c]+st->overlap, out_mem[c]+st->overlap, st->prefilter_period, pitch_index, N-st->overlap, C,
Jean-Marc Valindfa847a2011-01-17 11:37:08 -05001337 st->prefilter_gain, gain1, st->prefilter_tapset, prefilter_tapset,
1338 st->mode->window, st->mode->overlap);
Jean-Marc Valin70d30ff2010-12-13 13:50:29 -05001339 } else {
1340 comb_filter(out_mem[c], out_mem[c], st->prefilter_period_old, st->prefilter_period, N, C,
Jean-Marc Valindfa847a2011-01-17 11:37:08 -05001341 st->prefilter_gain_old, st->prefilter_gain, st->prefilter_tapset_old, st->prefilter_tapset,
1342 st->mode->window, st->mode->overlap);
Jean-Marc Valin70d30ff2010-12-13 13:50:29 -05001343 }
Gregory Maxwell9743bf32010-11-04 20:45:09 -04001344 } while (++c<C);
Jean-Marc Valin35095c62010-11-04 13:24:44 -04001345#endif /* ENABLE_POSTFILTER */
1346
1347 deemphasis(out_mem, (celt_word16*)pcm, N, C, st->mode->preemph, st->preemph_memD);
Jean-Marc Valin70d30ff2010-12-13 13:50:29 -05001348 st->prefilter_period_old = st->prefilter_period;
1349 st->prefilter_gain_old = st->prefilter_gain;
Jean-Marc Valindfa847a2011-01-17 11:37:08 -05001350 st->prefilter_tapset_old = st->prefilter_tapset;
Jean-Marc Valind9b95652008-08-31 23:34:47 -04001351 }
Jean-Marc Valin35095c62010-11-04 13:24:44 -04001352#endif
1353
1354 st->prefilter_period = pitch_index;
1355 st->prefilter_gain = gain1;
Jean-Marc Valindfa847a2011-01-17 11:37:08 -05001356 st->prefilter_tapset = prefilter_tapset;
Gregory Maxwell54547f12009-02-16 18:56:44 -05001357
Jean-Marc Valin5677e342011-01-13 16:15:53 -05001358 /* In case start or end were to change */
1359 for (i=0;i<st->start;i++)
1360 oldBandE[i]=0;
1361 for (i=st->end;i<st->mode->nbEBands;i++)
1362 oldBandE[i]=0;
1363
Jean-Marc Valin30d51252010-06-21 17:55:28 -04001364 /* If there's any room left (can only happen for very high rates),
1365 fill it with zeros */
Jean-Marc Valin5d774e02010-08-04 17:17:18 -04001366 while (ec_enc_tell(enc,0) + 8 <= nbCompressedBytes*8)
Jean-Marc Valin30d51252010-06-21 17:55:28 -04001367 ec_enc_bits(enc, 0, 8);
Jean-Marc Valin4794f2e2010-05-19 11:56:57 -04001368 ec_enc_done(enc);
Jean-Marc Valinc871c8d2009-06-09 00:57:00 -04001369
Jean-Marc Valin8600f692008-02-29 15:14:12 +11001370 RESTORE_STACK;
Jean-Marc Valinb1e017f2010-07-18 21:20:35 -04001371 if (ec_enc_get_error(enc))
Jean-Marc Valin9d785af2010-07-18 09:42:05 -04001372 return CELT_CORRUPTED_DATA;
1373 else
1374 return nbCompressedBytes;
Jean-Marc Valin8ebd3452007-11-29 20:17:32 +11001375}
1376
Gregory Maxwell5f2a74b2008-08-11 23:50:07 -04001377#ifdef FIXED_POINT
1378#ifndef DISABLE_FLOAT_API
Jean-Marc Valin35095c62010-11-04 13:24:44 -04001379int celt_encode_with_ec_float(CELTEncoder * restrict st, const float * pcm, int frame_size, unsigned char *compressed, int nbCompressedBytes, ec_enc *enc)
Gregory Maxwell5f2a74b2008-08-11 23:50:07 -04001380{
Jean-Marc Valin017fa852010-05-06 22:11:48 -04001381 int j, ret, C, N, LM, M;
Jean-Marc Valin30f7f812009-10-17 14:35:13 -04001382 VARDECL(celt_int16, in);
Jean-Marc Valincb8780c2009-07-20 23:40:35 -04001383 SAVE_STACK;
Gregory Maxwell17169992009-06-04 15:15:34 -04001384
Gregory Maxwell0719f6f2009-07-09 17:07:24 -04001385 if (pcm==NULL)
1386 return CELT_BAD_ARG;
1387
Jean-Marc Valin017fa852010-05-06 22:11:48 -04001388 for (LM=0;LM<4;LM++)
1389 if (st->mode->shortMdctSize<<LM==frame_size)
1390 break;
1391 if (LM>=MAX_CONFIG_SIZES)
1392 return CELT_BAD_ARG;
1393 M=1<<LM;
1394
Jean-Marc Valin80ed1472009-10-15 21:45:32 -04001395 C = CHANNELS(st->channels);
Jean-Marc Valin017fa852010-05-06 22:11:48 -04001396 N = M*st->mode->shortMdctSize;
Jean-Marc Valin30f7f812009-10-17 14:35:13 -04001397 ALLOC(in, C*N, celt_int16);
Gregory Maxwell5f2a74b2008-08-11 23:50:07 -04001398
1399 for (j=0;j<C*N;j++)
1400 in[j] = FLOAT2INT16(pcm[j]);
1401
Jean-Marc Valin35095c62010-11-04 13:24:44 -04001402 ret=celt_encode_with_ec(st,in,frame_size,compressed,nbCompressedBytes, enc);
1403#ifdef RESYNTH
1404 for (j=0;j<C*N;j++)
1405 ((float*)pcm)[j]=in[j]*(1.f/32768.f);
1406#endif
Wessel Lubberhuizen33ba6cc2008-10-03 07:09:29 -04001407 RESTORE_STACK;
Gregory Maxwell5f2a74b2008-08-11 23:50:07 -04001408 return ret;
1409
1410}
1411#endif /*DISABLE_FLOAT_API*/
1412#else
Jean-Marc Valin35095c62010-11-04 13:24:44 -04001413int celt_encode_with_ec(CELTEncoder * restrict st, const celt_int16 * pcm, int frame_size, unsigned char *compressed, int nbCompressedBytes, ec_enc *enc)
Gregory Maxwell5f2a74b2008-08-11 23:50:07 -04001414{
Jean-Marc Valin017fa852010-05-06 22:11:48 -04001415 int j, ret, C, N, LM, M;
Jean-Marc Valin234969c2009-10-17 22:12:42 -04001416 VARDECL(celt_sig, in);
Jean-Marc Valincb8780c2009-07-20 23:40:35 -04001417 SAVE_STACK;
Gregory Maxwell17169992009-06-04 15:15:34 -04001418
Gregory Maxwell0719f6f2009-07-09 17:07:24 -04001419 if (pcm==NULL)
1420 return CELT_BAD_ARG;
1421
Jean-Marc Valin017fa852010-05-06 22:11:48 -04001422 for (LM=0;LM<4;LM++)
1423 if (st->mode->shortMdctSize<<LM==frame_size)
1424 break;
1425 if (LM>=MAX_CONFIG_SIZES)
1426 return CELT_BAD_ARG;
1427 M=1<<LM;
1428
Jean-Marc Valin80ed1472009-10-15 21:45:32 -04001429 C=CHANNELS(st->channels);
Jean-Marc Valin04752672010-05-05 07:21:21 -04001430 N=M*st->mode->shortMdctSize;
Jean-Marc Valin234969c2009-10-17 22:12:42 -04001431 ALLOC(in, C*N, celt_sig);
Gregory Maxwell5f2a74b2008-08-11 23:50:07 -04001432 for (j=0;j<C*N;j++) {
1433 in[j] = SCALEOUT(pcm[j]);
1434 }
Gregory Maxwell5f2a74b2008-08-11 23:50:07 -04001435
Jean-Marc Valin35095c62010-11-04 13:24:44 -04001436 ret = celt_encode_with_ec_float(st,in,frame_size,compressed,nbCompressedBytes, enc);
1437#ifdef RESYNTH
1438 for (j=0;j<C*N;j++)
1439 ((celt_int16*)pcm)[j] = FLOAT2INT16(in[j]);
1440#endif
Wessel Lubberhuizen33ba6cc2008-10-03 07:09:29 -04001441 RESTORE_STACK;
Gregory Maxwell5f2a74b2008-08-11 23:50:07 -04001442 return ret;
1443}
1444#endif
Jean-Marc Valin6e9058a2007-12-07 14:59:06 +11001445
Jean-Marc Valind56c6102010-05-07 20:30:22 -04001446int celt_encode(CELTEncoder * restrict st, const celt_int16 * pcm, int frame_size, unsigned char *compressed, int nbCompressedBytes)
1447{
Jean-Marc Valin35095c62010-11-04 13:24:44 -04001448 return celt_encode_with_ec(st, pcm, frame_size, compressed, nbCompressedBytes, NULL);
Jean-Marc Valind56c6102010-05-07 20:30:22 -04001449}
1450
Jean-Marc Valin4424b5a2010-07-06 19:37:23 -04001451#ifndef DISABLE_FLOAT_API
Jean-Marc Valind56c6102010-05-07 20:30:22 -04001452int celt_encode_float(CELTEncoder * restrict st, const float * pcm, int frame_size, unsigned char *compressed, int nbCompressedBytes)
1453{
Jean-Marc Valin35095c62010-11-04 13:24:44 -04001454 return celt_encode_with_ec_float(st, pcm, frame_size, compressed, nbCompressedBytes, NULL);
Jean-Marc Valind56c6102010-05-07 20:30:22 -04001455}
Jean-Marc Valin4424b5a2010-07-06 19:37:23 -04001456#endif /* DISABLE_FLOAT_API */
Jean-Marc Valind56c6102010-05-07 20:30:22 -04001457
Jean-Marc Valinb6f90612008-10-05 22:39:13 -04001458int celt_encoder_ctl(CELTEncoder * restrict st, int request, ...)
Jean-Marc Valinc18fb1d2008-09-30 07:36:54 -04001459{
Jean-Marc Valinb6f90612008-10-05 22:39:13 -04001460 va_list ap;
Gregory Maxwell17169992009-06-04 15:15:34 -04001461
Jean-Marc Valinb6f90612008-10-05 22:39:13 -04001462 va_start(ap, request);
Jean-Marc Valinc18fb1d2008-09-30 07:36:54 -04001463 switch (request)
1464 {
Gregory Maxwellf3b44ef2009-06-03 13:37:45 -04001465 case CELT_GET_MODE_REQUEST:
1466 {
1467 const CELTMode ** value = va_arg(ap, const CELTMode**);
1468 if (value==0)
1469 goto bad_arg;
1470 *value=st->mode;
1471 }
1472 break;
Jean-Marc Valinb6f90612008-10-05 22:39:13 -04001473 case CELT_SET_COMPLEXITY_REQUEST:
Jean-Marc Valinc18fb1d2008-09-30 07:36:54 -04001474 {
Jean-Marc Valin30f7f812009-10-17 14:35:13 -04001475 int value = va_arg(ap, celt_int32);
Jean-Marc Valinb6f90612008-10-05 22:39:13 -04001476 if (value<0 || value>10)
1477 goto bad_arg;
Jean-Marc Valin1213ba52010-08-31 17:03:13 -04001478 st->complexity = value;
Gregory Maxwell98046ca2008-12-13 20:42:03 -05001479 }
1480 break;
Jean-Marc Valin5f961462010-05-19 13:38:10 -04001481 case CELT_SET_START_BAND_REQUEST:
1482 {
1483 celt_int32 value = va_arg(ap, celt_int32);
1484 if (value<0 || value>=st->mode->nbEBands)
1485 goto bad_arg;
1486 st->start = value;
1487 }
1488 break;
Jean-Marc Valin525d7cf2010-07-13 14:14:16 -04001489 case CELT_SET_END_BAND_REQUEST:
1490 {
1491 celt_int32 value = va_arg(ap, celt_int32);
Timothy B. Terriberry8893e532010-12-30 08:56:49 -08001492 if (value<1 || value>st->mode->nbEBands)
Jean-Marc Valin525d7cf2010-07-13 14:14:16 -04001493 goto bad_arg;
1494 st->end = value;
1495 }
1496 break;
Gregory Maxwell2dd3d322009-06-05 14:05:51 -04001497 case CELT_SET_PREDICTION_REQUEST:
Gregory Maxwell98046ca2008-12-13 20:42:03 -05001498 {
Jean-Marc Valin30f7f812009-10-17 14:35:13 -04001499 int value = va_arg(ap, celt_int32);
Gregory Maxwell2dd3d322009-06-05 14:05:51 -04001500 if (value<0 || value>2)
Gregory Maxwell98046ca2008-12-13 20:42:03 -05001501 goto bad_arg;
1502 if (value==0)
Gregory Maxwell2dd3d322009-06-05 14:05:51 -04001503 {
1504 st->force_intra = 1;
Gregory Maxwella80958b2009-06-29 12:48:57 -04001505 } else if (value==1) {
Gregory Maxwell2dd3d322009-06-05 14:05:51 -04001506 st->force_intra = 0;
Gregory Maxwell2dd3d322009-06-05 14:05:51 -04001507 } else {
1508 st->force_intra = 0;
Gregory Maxwell2dd3d322009-06-05 14:05:51 -04001509 }
Jean-Marc Valinc18fb1d2008-09-30 07:36:54 -04001510 }
1511 break;
Jean-Marc Valin79b34eb2010-12-05 17:22:06 -05001512 case CELT_SET_VBR_CONSTRAINT_REQUEST:
1513 {
1514 celt_int32 value = va_arg(ap, celt_int32);
1515 st->constrained_vbr = value;
1516 }
1517 break;
Gregory Maxwell888d8ce2009-05-21 04:21:53 -04001518 case CELT_SET_VBR_RATE_REQUEST:
1519 {
Jean-Marc Valin30f7f812009-10-17 14:35:13 -04001520 celt_int32 value = va_arg(ap, celt_int32);
Jean-Marc Valin8cc945c2010-05-29 08:07:18 -04001521 int frame_rate;
1522 int N = st->mode->shortMdctSize;
Gregory Maxwell888d8ce2009-05-21 04:21:53 -04001523 if (value<0)
1524 goto bad_arg;
1525 if (value>3072000)
1526 value = 3072000;
Jean-Marc Valin8cc945c2010-05-29 08:07:18 -04001527 frame_rate = ((st->mode->Fs<<3)+(N>>1))/N;
1528 st->vbr_rate_norm = ((value<<(BITRES+3))+(frame_rate>>1))/frame_rate;
Gregory Maxwell888d8ce2009-05-21 04:21:53 -04001529 }
1530 break;
John Ridges454d1d02009-05-21 22:38:39 -04001531 case CELT_RESET_STATE:
1532 {
Jean-Marc Valinc09807d2010-08-27 17:17:50 -04001533 CELT_MEMSET((char*)&st->ENCODER_RESET_START, 0,
1534 celt_encoder_get_size(st->mode, st->channels)-
1535 ((char*)&st->ENCODER_RESET_START - (char*)st));
Jean-Marc Valin30165bb2010-12-03 14:35:59 -05001536 st->vbr_offset = 0;
John Ridges454d1d02009-05-21 22:38:39 -04001537 st->delayedIntra = 1;
Timothy B. Terriberry320cf2e2010-12-17 05:52:06 -08001538 st->spread_decision = SPREAD_NORMAL;
Jean-Marc Valin628c0252010-04-16 20:57:56 -04001539 st->tonal_average = QCONST16(1.f,8);
John Ridges454d1d02009-05-21 22:38:39 -04001540 }
1541 break;
Jean-Marc Valinc18fb1d2008-09-30 07:36:54 -04001542 default:
Jean-Marc Valinb6f90612008-10-05 22:39:13 -04001543 goto bad_request;
Jean-Marc Valinc18fb1d2008-09-30 07:36:54 -04001544 }
Jean-Marc Valinb6f90612008-10-05 22:39:13 -04001545 va_end(ap);
Jean-Marc Valinc18fb1d2008-09-30 07:36:54 -04001546 return CELT_OK;
Jean-Marc Valinb6f90612008-10-05 22:39:13 -04001547bad_arg:
1548 va_end(ap);
1549 return CELT_BAD_ARG;
1550bad_request:
1551 va_end(ap);
1552 return CELT_UNIMPLEMENTED;
Jean-Marc Valinc18fb1d2008-09-30 07:36:54 -04001553}
1554
Jean-Marc Valin56522ad2009-06-05 17:17:25 -04001555/**********************************************************************/
1556/* */
1557/* DECODER */
1558/* */
1559/**********************************************************************/
Jean-Marc Valineafbdd52009-04-27 19:35:09 -04001560#define DECODE_BUFFER_SIZE 2048
Jean-Marc Valin269d40a2007-12-07 11:29:45 +11001561
Jean-Marc Valin276de722008-02-20 17:45:51 +11001562/** Decoder state
1563 @brief Decoder state
1564 */
Jean-Marc Valin269d40a2007-12-07 11:29:45 +11001565struct CELTDecoder {
1566 const CELTMode *mode;
Jean-Marc Valina5431bf2008-01-03 20:53:01 +11001567 int overlap;
Jean-Marc Valin80ed1472009-10-15 21:45:32 -04001568 int channels;
Jean-Marc Valina5431bf2008-01-03 20:53:01 +11001569
Jean-Marc Valin5f961462010-05-19 13:38:10 -04001570 int start, end;
Jean-Marc Valinc09807d2010-08-27 17:17:50 -04001571
1572 /* Everything beyond this point gets cleared on a reset */
1573#define DECODER_RESET_START last_pitch_index
1574
Jean-Marc Valinfb83fb42007-12-08 00:56:04 +11001575 int last_pitch_index;
Jean-Marc Valin0f0da992009-08-12 21:34:01 -04001576 int loss_count;
Jean-Marc Valin35095c62010-11-04 13:24:44 -04001577 int postfilter_period;
Jean-Marc Valin70d30ff2010-12-13 13:50:29 -05001578 int postfilter_period_old;
Jean-Marc Valin35095c62010-11-04 13:24:44 -04001579 celt_word16 postfilter_gain;
Jean-Marc Valin70d30ff2010-12-13 13:50:29 -05001580 celt_word16 postfilter_gain_old;
Jean-Marc Valindfa847a2011-01-17 11:37:08 -05001581 int postfilter_tapset;
1582 int postfilter_tapset_old;
Jean-Marc Valin02a35272010-08-27 16:00:01 -04001583
1584 celt_sig preemph_memD[2];
1585
Jean-Marc Valinca8b9922010-08-27 16:23:03 -04001586 celt_sig _decode_mem[1]; /* Size = channels*(DECODE_BUFFER_SIZE+mode->overlap) */
1587 /* celt_word16 lpc[], Size = channels*LPC_ORDER */
1588 /* celt_word16 oldEBands[], Size = channels*mode->nbEBands */
Jean-Marc Valin269d40a2007-12-07 11:29:45 +11001589};
1590
Jean-Marc Valin02a35272010-08-27 16:00:01 -04001591int celt_decoder_get_size(const CELTMode *mode, int channels)
1592{
1593 int size = sizeof(struct CELTDecoder)
1594 + (channels*(DECODE_BUFFER_SIZE+mode->overlap)-1)*sizeof(celt_sig)
1595 + channels*LPC_ORDER*sizeof(celt_word16)
1596 + channels*mode->nbEBands*sizeof(celt_word16);
1597 return size;
1598}
1599
Jean-Marc Valin80ed1472009-10-15 21:45:32 -04001600CELTDecoder *celt_decoder_create(const CELTMode *mode, int channels, int *error)
Jean-Marc Valin269d40a2007-12-07 11:29:45 +11001601{
Jean-Marc Valin7cfb7302010-08-27 16:54:33 -04001602 return celt_decoder_init(
1603 (CELTDecoder *)celt_alloc(celt_decoder_get_size(mode, channels)),
1604 mode, channels, error);
1605}
Jean-Marc Valin44ffd5a2008-02-22 00:39:25 +11001606
Jean-Marc Valin7cfb7302010-08-27 16:54:33 -04001607CELTDecoder *celt_decoder_init(CELTDecoder *st, const CELTMode *mode, int channels, int *error)
1608{
Jean-Marc Valin80ed1472009-10-15 21:45:32 -04001609 if (channels < 0 || channels > 2)
1610 {
Jean-Marc Valin80ed1472009-10-15 21:45:32 -04001611 if (error)
1612 *error = CELT_BAD_ARG;
1613 return NULL;
1614 }
Jean-Marc Valin44ffd5a2008-02-22 00:39:25 +11001615
Gregory Maxwell17169992009-06-04 15:15:34 -04001616 if (st==NULL)
Jean-Marc Valinece94a02009-10-16 07:30:14 -04001617 {
1618 if (error)
1619 *error = CELT_ALLOC_FAIL;
Gregory Maxwell17169992009-06-04 15:15:34 -04001620 return NULL;
Jean-Marc Valinece94a02009-10-16 07:30:14 -04001621 }
1622
Jean-Marc Valin6d3829f2010-08-27 17:52:38 -04001623 CELT_MEMSET((char*)st, 0, celt_decoder_get_size(mode, channels));
1624
Jean-Marc Valin269d40a2007-12-07 11:29:45 +11001625 st->mode = mode;
Jean-Marc Valina5431bf2008-01-03 20:53:01 +11001626 st->overlap = mode->overlap;
Jean-Marc Valin80ed1472009-10-15 21:45:32 -04001627 st->channels = channels;
Jean-Marc Valina5431bf2008-01-03 20:53:01 +11001628
Jean-Marc Valin5f961462010-05-19 13:38:10 -04001629 st->start = 0;
Jean-Marc Valin8952c452010-07-16 21:48:44 -04001630 st->end = st->mode->effEBands;
Jean-Marc Valin5f961462010-05-19 13:38:10 -04001631
Jean-Marc Valin0f0da992009-08-12 21:34:01 -04001632 st->loss_count = 0;
Gregory Maxwell17169992009-06-04 15:15:34 -04001633
Jean-Marc Valin02a35272010-08-27 16:00:01 -04001634 if (error)
1635 *error = CELT_OK;
Jean-Marc Valin02a35272010-08-27 16:00:01 -04001636 return st;
Jean-Marc Valin269d40a2007-12-07 11:29:45 +11001637}
1638
Peter Kirk19f9dc92008-06-06 14:38:38 +02001639void celt_decoder_destroy(CELTDecoder *st)
Jean-Marc Valin269d40a2007-12-07 11:29:45 +11001640{
Jean-Marc Valin269d40a2007-12-07 11:29:45 +11001641 celt_free(st);
1642}
1643
Jean-Marc Valin017fa852010-05-06 22:11:48 -04001644static void celt_decode_lost(CELTDecoder * restrict st, celt_word16 * restrict pcm, int N, int LM)
Jean-Marc Valinfb83fb42007-12-08 00:56:04 +11001645{
Jean-Marc Valin04752672010-05-05 07:21:21 -04001646 int c;
Jean-Marc Valin0bb05bc2008-02-20 13:43:40 +11001647 int pitch_index;
Jean-Marc Valine14fe902009-12-11 00:07:31 -05001648 int overlap = st->mode->overlap;
Jean-Marc Valin234969c2009-10-17 22:12:42 -04001649 celt_word16 fade = Q15ONE;
Jean-Marc Valin24c9cda2008-05-02 10:34:07 +10001650 int i, len;
Jean-Marc Valin80ed1472009-10-15 21:45:32 -04001651 const int C = CHANNELS(st->channels);
Jean-Marc Valin24c9cda2008-05-02 10:34:07 +10001652 int offset;
Jean-Marc Valin6d131082010-08-27 15:15:32 -04001653 celt_sig *out_mem[2];
1654 celt_sig *decode_mem[2];
1655 celt_sig *overlap_mem[2];
Jean-Marc Valin02a35272010-08-27 16:00:01 -04001656 celt_word16 *lpc;
Jean-Marc Valin8600f692008-02-29 15:14:12 +11001657 SAVE_STACK;
Jean-Marc Valinfb83fb42007-12-08 00:56:04 +11001658
Gregory Maxwell9743bf32010-11-04 20:45:09 -04001659 c=0; do {
Jean-Marc Valin6d131082010-08-27 15:15:32 -04001660 decode_mem[c] = st->_decode_mem + c*(DECODE_BUFFER_SIZE+st->overlap);
1661 out_mem[c] = decode_mem[c]+DECODE_BUFFER_SIZE-MAX_PERIOD;
1662 overlap_mem[c] = decode_mem[c]+DECODE_BUFFER_SIZE;
Gregory Maxwell9743bf32010-11-04 20:45:09 -04001663 } while (++c<C);
Jean-Marc Valin02a35272010-08-27 16:00:01 -04001664 lpc = (celt_word16*)(st->_decode_mem+(DECODE_BUFFER_SIZE+st->overlap)*C);
Jean-Marc Valin6d131082010-08-27 15:15:32 -04001665
Jean-Marc Valin24c9cda2008-05-02 10:34:07 +10001666 len = N+st->mode->overlap;
Jean-Marc Valinfb83fb42007-12-08 00:56:04 +11001667
Jean-Marc Valin0f0da992009-08-12 21:34:01 -04001668 if (st->loss_count == 0)
1669 {
Jean-Marc Valin7a7c42a2009-11-25 20:38:52 -05001670 celt_word16 pitch_buf[MAX_PERIOD>>1];
Jean-Marc Valin294863b2009-11-08 22:29:54 +09001671 celt_word32 tmp=0;
Jean-Marc Valine465c142009-11-26 00:39:36 -05001672 celt_word32 mem0[2]={0,0};
1673 celt_word16 mem1[2]={0,0};
Jean-Marc Valin6202c742010-06-01 00:30:37 -04001674 int len2 = len;
1675 /* FIXME: This is a kludge */
1676 if (len2>MAX_PERIOD>>1)
1677 len2 = MAX_PERIOD>>1;
Jean-Marc Valin6d131082010-08-27 15:15:32 -04001678 pitch_downsample(out_mem, pitch_buf, MAX_PERIOD, MAX_PERIOD,
Jean-Marc Valine14fe902009-12-11 00:07:31 -05001679 C, mem0, mem1);
Jean-Marc Valin6202c742010-06-01 00:30:37 -04001680 pitch_search(st->mode, pitch_buf+((MAX_PERIOD-len2)>>1), pitch_buf, len2,
1681 MAX_PERIOD-len2-100, &pitch_index, &tmp, 1<<LM);
1682 pitch_index = MAX_PERIOD-len2-pitch_index;
Jean-Marc Valin0f0da992009-08-12 21:34:01 -04001683 st->last_pitch_index = pitch_index;
1684 } else {
1685 pitch_index = st->last_pitch_index;
1686 if (st->loss_count < 5)
1687 fade = QCONST16(.8f,15);
1688 else
1689 fade = 0;
1690 }
Jean-Marc Valinfb83fb42007-12-08 00:56:04 +11001691
Gregory Maxwell9743bf32010-11-04 20:45:09 -04001692 c=0; do {
Jean-Marc Valin6202c742010-06-01 00:30:37 -04001693 /* FIXME: This is more memory than necessary */
1694 celt_word32 e[2*MAX_PERIOD];
1695 celt_word16 exc[2*MAX_PERIOD];
Jean-Marc Valin456eab22010-06-16 22:38:57 -04001696 celt_word32 ac[LPC_ORDER+1];
Jean-Marc Valin7b7f0712010-06-17 20:10:02 -04001697 celt_word16 decay = 1;
1698 celt_word32 S1=0;
Jean-Marc Valin74128be2010-01-01 09:33:17 -05001699 celt_word16 mem[LPC_ORDER]={0};
Jean-Marc Valine14fe902009-12-11 00:07:31 -05001700
Jean-Marc Valind5f99302009-12-16 22:42:32 -05001701 offset = MAX_PERIOD-pitch_index;
Jean-Marc Valine14fe902009-12-11 00:07:31 -05001702 for (i=0;i<MAX_PERIOD;i++)
Jean-Marc Valin6d131082010-08-27 15:15:32 -04001703 exc[i] = ROUND16(out_mem[c][i], SIG_SHIFT);
Jean-Marc Valin5a0fae52009-12-14 21:19:37 -05001704
1705 if (st->loss_count == 0)
1706 {
1707 _celt_autocorr(exc, ac, st->mode->window, st->mode->overlap,
1708 LPC_ORDER, MAX_PERIOD);
1709
Jean-Marc Valin456eab22010-06-16 22:38:57 -04001710 /* Noise floor -40 dB */
Jean-Marc Valin7b7f0712010-06-17 20:10:02 -04001711#ifdef FIXED_POINT
1712 ac[0] += SHR32(ac[0],13);
1713#else
Jean-Marc Valinae01e112010-08-03 21:43:41 -04001714 ac[0] *= 1.0001f;
Jean-Marc Valin7b7f0712010-06-17 20:10:02 -04001715#endif
Jean-Marc Valin5a0fae52009-12-14 21:19:37 -05001716 /* Lag windowing */
1717 for (i=1;i<=LPC_ORDER;i++)
1718 {
1719 /*ac[i] *= exp(-.5*(2*M_PI*.002*i)*(2*M_PI*.002*i));*/
Jean-Marc Valin7b7f0712010-06-17 20:10:02 -04001720#ifdef FIXED_POINT
1721 ac[i] -= MULT16_32_Q15(2*i*i, ac[i]);
1722#else
Jean-Marc Valinae01e112010-08-03 21:43:41 -04001723 ac[i] -= ac[i]*(.008f*i)*(.008f*i);
Jean-Marc Valin7b7f0712010-06-17 20:10:02 -04001724#endif
Jean-Marc Valin5a0fae52009-12-14 21:19:37 -05001725 }
1726
Jean-Marc Valin02a35272010-08-27 16:00:01 -04001727 _celt_lpc(lpc+c*LPC_ORDER, ac, LPC_ORDER);
Jean-Marc Valin5a0fae52009-12-14 21:19:37 -05001728 }
Jean-Marc Valinbc4a0022010-11-06 18:11:06 -04001729 for (i=0;i<LPC_ORDER;i++)
Jean-Marc Valine53c4bc2010-11-06 21:41:40 -04001730 mem[i] = ROUND16(out_mem[c][MAX_PERIOD-1-i], SIG_SHIFT);
Jean-Marc Valin02a35272010-08-27 16:00:01 -04001731 fir(exc, lpc+c*LPC_ORDER, exc, MAX_PERIOD, LPC_ORDER, mem);
Jean-Marc Valin74128be2010-01-01 09:33:17 -05001732 /*for (i=0;i<MAX_PERIOD;i++)printf("%d ", exc[i]); printf("\n");*/
Jean-Marc Valine14fe902009-12-11 00:07:31 -05001733 /* Check if the waveform is decaying (and if so how fast) */
1734 {
Jean-Marc Valin7b7f0712010-06-17 20:10:02 -04001735 celt_word32 E1=1, E2=1;
Jean-Marc Valine14fe902009-12-11 00:07:31 -05001736 int period;
1737 if (pitch_index <= MAX_PERIOD/2)
1738 period = pitch_index;
1739 else
1740 period = MAX_PERIOD/2;
1741 for (i=0;i<period;i++)
1742 {
Jean-Marc Valin7b7f0712010-06-17 20:10:02 -04001743 E1 += SHR32(MULT16_16(exc[MAX_PERIOD-period+i],exc[MAX_PERIOD-period+i]),8);
1744 E2 += SHR32(MULT16_16(exc[MAX_PERIOD-2*period+i],exc[MAX_PERIOD-2*period+i]),8);
Jean-Marc Valine14fe902009-12-11 00:07:31 -05001745 }
Jean-Marc Valin7b7f0712010-06-17 20:10:02 -04001746 if (E1 > E2)
1747 E1 = E2;
1748 decay = celt_sqrt(frac_div32(SHR(E1,1),E2));
Jean-Marc Valine14fe902009-12-11 00:07:31 -05001749 }
1750
1751 /* Copy excitation, taking decay into account */
1752 for (i=0;i<len+st->mode->overlap;i++)
1753 {
Jean-Marc Valin1ad93cf2010-11-06 22:02:32 -04001754 celt_word16 tmp;
Jean-Marc Valine14fe902009-12-11 00:07:31 -05001755 if (offset+i >= MAX_PERIOD)
1756 {
1757 offset -= pitch_index;
Jean-Marc Valin7b7f0712010-06-17 20:10:02 -04001758 decay = MULT16_16_Q15(decay, decay);
Jean-Marc Valine14fe902009-12-11 00:07:31 -05001759 }
Jean-Marc Valin7b7f0712010-06-17 20:10:02 -04001760 e[i] = SHL32(EXTEND32(MULT16_16_Q15(decay, exc[offset+i])), SIG_SHIFT);
Jean-Marc Valin1ad93cf2010-11-06 22:02:32 -04001761 tmp = ROUND16(out_mem[c][offset+i],SIG_SHIFT);
1762 S1 += SHR32(MULT16_16(tmp,tmp),8);
Jean-Marc Valin5a0fae52009-12-14 21:19:37 -05001763 }
Jean-Marc Valinbc2c4542010-10-28 14:27:05 -04001764 for (i=0;i<LPC_ORDER;i++)
Jean-Marc Valine53c4bc2010-11-06 21:41:40 -04001765 mem[i] = ROUND16(out_mem[c][MAX_PERIOD-1-i], SIG_SHIFT);
Jean-Marc Valinbc2c4542010-10-28 14:27:05 -04001766 for (i=0;i<len+st->mode->overlap;i++)
1767 e[i] = MULT16_32_Q15(fade, e[i]);
Jean-Marc Valin02a35272010-08-27 16:00:01 -04001768 iir(e, lpc+c*LPC_ORDER, e, len+st->mode->overlap, LPC_ORDER, mem);
Jean-Marc Valin5a0fae52009-12-14 21:19:37 -05001769
1770 {
Jean-Marc Valin7b7f0712010-06-17 20:10:02 -04001771 celt_word32 S2=0;
Jean-Marc Valin5a0fae52009-12-14 21:19:37 -05001772 for (i=0;i<len+overlap;i++)
Jean-Marc Valin1ad93cf2010-11-06 22:02:32 -04001773 {
1774 celt_word16 tmp = ROUND16(e[i],SIG_SHIFT);
1775 S2 += SHR32(MULT16_16(tmp,tmp),8);
1776 }
Jean-Marc Valinfeca0952010-06-17 20:25:51 -04001777 /* This checks for an "explosion" in the synthesis */
1778#ifdef FIXED_POINT
1779 if (!(S1 > SHR32(S2,2)))
1780#else
1781 /* Float test is written this way to catch NaNs at the same time */
Jean-Marc Valin07fed1b2009-12-28 07:59:42 -05001782 if (!(S1 > 0.2f*S2))
Jean-Marc Valinfeca0952010-06-17 20:25:51 -04001783#endif
Jean-Marc Valin07fed1b2009-12-28 07:59:42 -05001784 {
1785 for (i=0;i<len+overlap;i++)
1786 e[i] = 0;
1787 } else if (S1 < S2)
1788 {
Jean-Marc Valin12996402010-08-04 09:13:24 -04001789 celt_word16 ratio = celt_sqrt(frac_div32(SHR32(S1,1)+1,S2+1));
Jean-Marc Valin5a0fae52009-12-14 21:19:37 -05001790 for (i=0;i<len+overlap;i++)
Jean-Marc Valin1ad93cf2010-11-06 22:02:32 -04001791 e[i] = MULT16_32_Q15(ratio, e[i]);
Jean-Marc Valin07fed1b2009-12-28 07:59:42 -05001792 }
Jean-Marc Valine14fe902009-12-11 00:07:31 -05001793 }
1794
Jean-Marc Valin35095c62010-11-04 13:24:44 -04001795#ifdef ENABLE_POSTFILTER
1796 /* Apply post-filter to the MDCT overlap of the previous frame */
1797 comb_filter(out_mem[c]+MAX_PERIOD, out_mem[c]+MAX_PERIOD, st->postfilter_period, st->postfilter_period, st->overlap, C,
Jean-Marc Valindfa847a2011-01-17 11:37:08 -05001798 st->postfilter_gain, st->postfilter_gain, st->postfilter_tapset, st->postfilter_tapset,
1799 NULL, 0);
Jean-Marc Valin35095c62010-11-04 13:24:44 -04001800#endif /* ENABLE_POSTFILTER */
1801
Jean-Marc Valine14fe902009-12-11 00:07:31 -05001802 for (i=0;i<MAX_PERIOD+st->mode->overlap-N;i++)
Jean-Marc Valin6d131082010-08-27 15:15:32 -04001803 out_mem[c][i] = out_mem[c][N+i];
Jean-Marc Valine14fe902009-12-11 00:07:31 -05001804
Jean-Marc Valine14fe902009-12-11 00:07:31 -05001805 /* Apply TDAC to the concealed audio so that it blends with the
1806 previous and next frames */
1807 for (i=0;i<overlap/2;i++)
1808 {
Jean-Marc Valind7231dd2010-11-06 20:30:17 -04001809 celt_word32 tmp;
1810 tmp = MULT16_32_Q15(st->mode->window[i], e[N+overlap-1-i]) +
1811 MULT16_32_Q15(st->mode->window[overlap-i-1], e[N+i ]);
1812 out_mem[c][MAX_PERIOD+i] = MULT16_32_Q15(st->mode->window[overlap-i-1], tmp);
1813 out_mem[c][MAX_PERIOD+overlap-i-1] = MULT16_32_Q15(st->mode->window[i], tmp);
Jean-Marc Valine14fe902009-12-11 00:07:31 -05001814 }
Jean-Marc Valinbc4a0022010-11-06 18:11:06 -04001815 for (i=0;i<N;i++)
1816 out_mem[c][MAX_PERIOD-N+i] = e[i];
Jean-Marc Valin35095c62010-11-04 13:24:44 -04001817
1818#ifdef ENABLE_POSTFILTER
1819 /* Apply pre-filter to the MDCT overlap for the next frame (post-filter will be applied then) */
1820 comb_filter(e, out_mem[c]+MAX_PERIOD, st->postfilter_period, st->postfilter_period, st->overlap, C,
Jean-Marc Valindfa847a2011-01-17 11:37:08 -05001821 -st->postfilter_gain, -st->postfilter_gain, st->postfilter_tapset, st->postfilter_tapset,
1822 NULL, 0);
Jean-Marc Valin35095c62010-11-04 13:24:44 -04001823#endif /* ENABLE_POSTFILTER */
1824 for (i=0;i<overlap;i++)
1825 out_mem[c][MAX_PERIOD+i] = e[i];
Gregory Maxwell9743bf32010-11-04 20:45:09 -04001826 } while (++c<C);
Jean-Marc Valin1677aa92007-12-08 01:13:34 +11001827
Jean-Marc Valinbc2c4542010-10-28 14:27:05 -04001828 {
1829 celt_word32 *out_syn[2];
1830 out_syn[0] = out_mem[0]+MAX_PERIOD-N;
1831 if (C==2)
1832 out_syn[1] = out_mem[1]+MAX_PERIOD-N;
1833 deemphasis(out_syn, pcm, N, C, st->mode->preemph, st->preemph_memD);
1834 }
Jean-Marc Valin0f0da992009-08-12 21:34:01 -04001835
1836 st->loss_count++;
1837
Jean-Marc Valin8600f692008-02-29 15:14:12 +11001838 RESTORE_STACK;
Jean-Marc Valinfb83fb42007-12-08 00:56:04 +11001839}
1840
Gregory Maxwell5f2a74b2008-08-11 23:50:07 -04001841#ifdef FIXED_POINT
Jean-Marc Valinf5e2e322010-05-19 12:05:02 -04001842int 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 +11001843{
Gregory Maxwell5f2a74b2008-08-11 23:50:07 -04001844#else
Jean-Marc Valinf5e2e322010-05-19 12:05:02 -04001845int 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 -04001846{
1847#endif
Jean-Marc Valin0695a5f2010-08-27 11:33:18 -04001848 int c, i, N;
Timothy B. Terriberry320cf2e2010-12-17 05:52:06 -08001849 int spread_decision;
Jean-Marc Valinc890b582008-08-01 22:26:49 -04001850 int bits;
Jean-Marc Valinf5e2e322010-05-19 12:05:02 -04001851 ec_dec _dec;
Jean-Marc Valin0bb05bc2008-02-20 13:43:40 +11001852 ec_byte_buffer buf;
Jean-Marc Valin234969c2009-10-17 22:12:42 -04001853 VARDECL(celt_sig, freq);
Jean-Marc Valin234969c2009-10-17 22:12:42 -04001854 VARDECL(celt_norm, X);
1855 VARDECL(celt_ener, bandE);
Jean-Marc Valin6775de32008-08-02 08:14:42 -04001856 VARDECL(int, fine_quant);
1857 VARDECL(int, pulses);
1858 VARDECL(int, offsets);
Jean-Marc Valin52cb5fb2009-06-10 08:08:55 -04001859 VARDECL(int, fine_priority);
Jean-Marc Valin163b76e2010-05-27 23:56:53 -04001860 VARDECL(int, tf_res);
Jean-Marc Valin6d131082010-08-27 15:15:32 -04001861 celt_sig *out_mem[2];
1862 celt_sig *decode_mem[2];
1863 celt_sig *overlap_mem[2];
Jean-Marc Valinf67b4472010-08-27 01:32:40 -04001864 celt_sig *out_syn[2];
Jean-Marc Valin02a35272010-08-27 16:00:01 -04001865 celt_word16 *lpc;
1866 celt_word16 *oldBandE;
Jean-Marc Valinc890b582008-08-01 22:26:49 -04001867
Jean-Marc Valin9d1decd2008-06-17 13:28:13 +10001868 int shortBlocks;
Jean-Marc Valin3b918ba2010-05-05 00:02:26 -04001869 int isTransient;
Jean-Marc Valin05ed03e2009-04-29 07:44:13 -04001870 int intra_ener;
Jean-Marc Valin80ed1472009-10-15 21:45:32 -04001871 const int C = CHANNELS(st->channels);
Jean-Marc Valin017fa852010-05-06 22:11:48 -04001872 int LM, M;
Jean-Marc Valin85f41b22010-07-16 18:12:45 -04001873 int effEnd;
Jean-Marc Valinb801da52010-09-28 14:56:20 -04001874 int codedBands;
Jean-Marc Valinf1fea662010-10-09 22:58:52 -04001875 int alloc_trim;
Jean-Marc Valin35095c62010-11-04 13:24:44 -04001876 int postfilter_pitch;
1877 celt_word16 postfilter_gain;
Jean-Marc Valin4f177e82010-11-26 10:32:03 -05001878 int intensity=0;
Jean-Marc Valine65978f2010-12-02 13:46:48 -05001879 int dual_stereo=0;
Timothy B. Terriberry76469c62011-01-07 09:18:34 -08001880 celt_int32 total_bits;
1881 celt_int32 tell;
1882 int dynalloc_logp;
Jean-Marc Valindfa847a2011-01-17 11:37:08 -05001883 int postfilter_tapset;
Jean-Marc Valin8600f692008-02-29 15:14:12 +11001884 SAVE_STACK;
Jean-Marc Valin44ffd5a2008-02-22 00:39:25 +11001885
Gregory Maxwell0719f6f2009-07-09 17:07:24 -04001886 if (pcm==NULL)
1887 return CELT_BAD_ARG;
1888
Jean-Marc Valin017fa852010-05-06 22:11:48 -04001889 for (LM=0;LM<4;LM++)
1890 if (st->mode->shortMdctSize<<LM==frame_size)
1891 break;
1892 if (LM>=MAX_CONFIG_SIZES)
1893 return CELT_BAD_ARG;
1894 M=1<<LM;
1895
Gregory Maxwell9743bf32010-11-04 20:45:09 -04001896 c=0; do {
Jean-Marc Valin6d131082010-08-27 15:15:32 -04001897 decode_mem[c] = st->_decode_mem + c*(DECODE_BUFFER_SIZE+st->overlap);
1898 out_mem[c] = decode_mem[c]+DECODE_BUFFER_SIZE-MAX_PERIOD;
1899 overlap_mem[c] = decode_mem[c]+DECODE_BUFFER_SIZE;
Gregory Maxwell9743bf32010-11-04 20:45:09 -04001900 } while (++c<C);
Jean-Marc Valin02a35272010-08-27 16:00:01 -04001901 lpc = (celt_word16*)(st->_decode_mem+(DECODE_BUFFER_SIZE+st->overlap)*C);
1902 oldBandE = lpc+C*LPC_ORDER;
Jean-Marc Valin6d131082010-08-27 15:15:32 -04001903
Jean-Marc Valin04752672010-05-05 07:21:21 -04001904 N = M*st->mode->shortMdctSize;
Jean-Marc Valin01417232008-03-03 13:59:55 +11001905
Jean-Marc Valin85f41b22010-07-16 18:12:45 -04001906 effEnd = st->end;
1907 if (effEnd > st->mode->effEBands)
1908 effEnd = st->mode->effEBands;
1909
Jean-Marc Valin234969c2009-10-17 22:12:42 -04001910 ALLOC(freq, C*N, celt_sig); /**< Interleaved signal MDCTs */
1911 ALLOC(X, C*N, celt_norm); /**< Interleaved normalised MDCTs */
1912 ALLOC(bandE, st->mode->nbEBands*C, celt_ener);
Gregory Maxwell9743bf32010-11-04 20:45:09 -04001913 c=0; do
Jean-Marc Valin5f961462010-05-19 13:38:10 -04001914 for (i=0;i<M*st->mode->eBands[st->start];i++)
1915 X[c*N+i] = 0;
Gregory Maxwell9743bf32010-11-04 20:45:09 -04001916 while (++c<C);
1917 c=0; do
Jean-Marc Valin85f41b22010-07-16 18:12:45 -04001918 for (i=M*st->mode->eBands[effEnd];i<N;i++)
Jean-Marc Valin525d7cf2010-07-13 14:14:16 -04001919 X[c*N+i] = 0;
Gregory Maxwell9743bf32010-11-04 20:45:09 -04001920 while (++c<C);
Jean-Marc Valin5f961462010-05-19 13:38:10 -04001921
Jean-Marc Valinfb83fb42007-12-08 00:56:04 +11001922 if (data == NULL)
1923 {
Jean-Marc Valin017fa852010-05-06 22:11:48 -04001924 celt_decode_lost(st, pcm, N, LM);
Jean-Marc Valin8600f692008-02-29 15:14:12 +11001925 RESTORE_STACK;
Jean-Marc Valinb1e017f2010-07-18 21:20:35 -04001926 return CELT_OK;
Jean-Marc Valinfb83fb42007-12-08 00:56:04 +11001927 }
Gregory Maxwell520eeae2009-02-09 01:33:21 -05001928 if (len<0) {
1929 RESTORE_STACK;
1930 return CELT_BAD_ARG;
1931 }
Jean-Marc Valinfb83fb42007-12-08 00:56:04 +11001932
Jean-Marc Valinf5e2e322010-05-19 12:05:02 -04001933 if (dec == NULL)
1934 {
1935 ec_byte_readinit(&buf,(unsigned char*)data,len);
1936 ec_dec_init(&_dec,&buf);
1937 dec = &_dec;
1938 }
Jean-Marc Valin6b95d8f2010-06-21 21:39:44 -04001939
Timothy B. Terriberry76469c62011-01-07 09:18:34 -08001940 total_bits = len*8;
1941 tell = ec_dec_tell(dec, 0);
1942
1943 postfilter_gain = 0;
1944 postfilter_pitch = 0;
Jean-Marc Valindfa847a2011-01-17 11:37:08 -05001945 postfilter_tapset = 0;
Jean-Marc Valin8d367022011-01-17 16:37:51 -05001946 if (tell+17 <= total_bits)
Jean-Marc Valin35095c62010-11-04 13:24:44 -04001947 {
Timothy B. Terriberry76469c62011-01-07 09:18:34 -08001948 if(ec_dec_bit_logp(dec, 1))
1949 {
Jean-Marc Valin35095c62010-11-04 13:24:44 -04001950#ifdef ENABLE_POSTFILTER
Timothy B. Terriberry76469c62011-01-07 09:18:34 -08001951 int qg, octave;
1952 octave = ec_dec_uint(dec, 6);
Jean-Marc Valindfa847a2011-01-17 11:37:08 -05001953 postfilter_pitch = (16<<octave)+ec_dec_bits(dec, 4+octave)-1;
Timothy B. Terriberry76469c62011-01-07 09:18:34 -08001954 qg = ec_dec_bits(dec, 2);
Jean-Marc Valindfa847a2011-01-17 11:37:08 -05001955 postfilter_tapset = ec_dec_bits(dec, 1);
1956 if (postfilter_tapset)
1957 postfilter_tapset += ec_dec_bits(dec, 1);
Timothy B. Terriberry76469c62011-01-07 09:18:34 -08001958 postfilter_gain = QCONST16(.125f,15)*(qg+2);
1959 tell = ec_dec_tell(dec, 0);
Jean-Marc Valin35095c62010-11-04 13:24:44 -04001960#else /* ENABLE_POSTFILTER */
Timothy B. Terriberry76469c62011-01-07 09:18:34 -08001961 RESTORE_STACK;
1962 return CELT_CORRUPTED_DATA;
Jean-Marc Valin35095c62010-11-04 13:24:44 -04001963#endif /* ENABLE_POSTFILTER */
Timothy B. Terriberry76469c62011-01-07 09:18:34 -08001964 }
1965 tell = ec_dec_tell(dec, 0);
Jean-Marc Valin35095c62010-11-04 13:24:44 -04001966 }
1967
Timothy B. Terriberry76469c62011-01-07 09:18:34 -08001968 if (LM > 0 && tell+3 <= total_bits)
1969 {
Timothy B. Terriberrye86fb262010-12-17 14:50:19 -08001970 isTransient = ec_dec_bit_logp(dec, 3);
Timothy B. Terriberry76469c62011-01-07 09:18:34 -08001971 tell = ec_dec_tell(dec, 0);
1972 }
Jean-Marc Valinf9fdbff2010-09-05 21:02:38 -04001973 else
1974 isTransient = 0;
Jean-Marc Valin017001a2010-08-05 15:42:50 -04001975
Jean-Marc Valin3b918ba2010-05-05 00:02:26 -04001976 if (isTransient)
1977 shortBlocks = M;
1978 else
1979 shortBlocks = 0;
1980
Timothy B. Terriberry76469c62011-01-07 09:18:34 -08001981 /* Decode the global flags (first symbols in the stream) */
1982 intra_ener = tell+3<=total_bits ? ec_dec_bit_logp(dec, 3) : 0;
1983 /* Get band energies */
1984 unquant_coarse_energy(st->mode, st->start, st->end, bandE, oldBandE,
1985 intra_ener, dec, C, LM);
1986
Jean-Marc Valin0a571ef2010-06-05 23:12:19 -04001987 ALLOC(tf_res, st->mode->nbEBands, int);
Jean-Marc Valine5e9aa72010-12-02 16:09:51 -05001988 tf_decode(st->start, st->end, C, isTransient, tf_res, LM, dec);
Jean-Marc Valin0a571ef2010-06-05 23:12:19 -04001989
Timothy B. Terriberry76469c62011-01-07 09:18:34 -08001990 tell = ec_dec_tell(dec, 0);
1991 spread_decision = SPREAD_NORMAL;
1992 if (tell+4 <= total_bits)
1993 spread_decision = ec_dec_icdf(dec, spread_icdf, 5);
Jean-Marc Valin9099bc32010-08-07 21:50:01 -04001994
Jean-Marc Valin6775de32008-08-02 08:14:42 -04001995 ALLOC(pulses, st->mode->nbEBands, int);
1996 ALLOC(offsets, st->mode->nbEBands, int);
Jean-Marc Valin52cb5fb2009-06-10 08:08:55 -04001997 ALLOC(fine_priority, st->mode->nbEBands, int);
Jean-Marc Valin6775de32008-08-02 08:14:42 -04001998
Timothy B. Terriberry76469c62011-01-07 09:18:34 -08001999 dynalloc_logp = 6;
2000 total_bits<<=BITRES;
2001 tell = ec_dec_tell(dec, BITRES);
Timothy B. Terriberryd6f61572010-12-30 09:04:16 -08002002 for (i=st->start;i<st->end;i++)
Jean-Marc Valind74c8512010-09-29 17:39:54 -04002003 {
Timothy B. Terriberry76469c62011-01-07 09:18:34 -08002004 int width, quanta;
2005 int dynalloc_loop_logp;
2006 int boost;
2007 width = C*(st->mode->eBands[i+1]-st->mode->eBands[i])<<LM;
2008 /* quanta is 6 bits, but no more than 1 bit/sample
2009 and no less than 1/8 bit/sample */
2010 quanta = IMIN(width<<BITRES, IMAX(6<<BITRES, width));
2011 dynalloc_loop_logp = dynalloc_logp;
2012 boost = 0;
2013 while (tell+(dynalloc_loop_logp<<BITRES) < total_bits &&
2014 boost < (64<<LM)*(C<<BITRES))
Jean-Marc Valind74c8512010-09-29 17:39:54 -04002015 {
Timothy B. Terriberry76469c62011-01-07 09:18:34 -08002016 int flag;
2017 flag = ec_dec_bit_logp(dec, dynalloc_loop_logp);
2018 tell = ec_dec_tell(dec, BITRES);
2019 if (!flag)
2020 break;
2021 boost += quanta;
2022 total_bits -= quanta;
2023 dynalloc_loop_logp = 1;
Jean-Marc Valind74c8512010-09-29 17:39:54 -04002024 }
Timothy B. Terriberry76469c62011-01-07 09:18:34 -08002025 offsets[i] = boost;
2026 /* Making dynalloc more likely */
2027 if (boost>0)
2028 dynalloc_logp = IMAX(2, dynalloc_logp-1);
Jean-Marc Valind74c8512010-09-29 17:39:54 -04002029 }
Jean-Marc Valin6775de32008-08-02 08:14:42 -04002030
Jean-Marc Valin9099bc32010-08-07 21:50:01 -04002031 ALLOC(fine_quant, st->mode->nbEBands, int);
Timothy B. Terriberry76469c62011-01-07 09:18:34 -08002032 alloc_trim = tell+(6<<BITRES) <= total_bits ?
2033 ec_dec_icdf(dec, trim_icdf, 7) : 5;
Jean-Marc Valin4f177e82010-11-26 10:32:03 -05002034
Timothy B. Terriberry76ea41e2010-12-16 14:39:58 -08002035 bits = (len*8<<BITRES) - ec_dec_tell(dec, BITRES) - 1;
Jean-Marc Valindfd6e712010-12-09 23:23:34 -05002036 codedBands = compute_allocation(st->mode, st->start, st->end, offsets,
Timothy B. Terriberry76469c62011-01-07 09:18:34 -08002037 alloc_trim, &intensity, &dual_stereo, bits, pulses, fine_quant,
2038 fine_priority, C, LM, dec, 0, 0);
Jean-Marc Valin6775de32008-08-02 08:14:42 -04002039
Jean-Marc Valin02a35272010-08-27 16:00:01 -04002040 unquant_fine_energy(st->mode, st->start, st->end, bandE, oldBandE, fine_quant, dec, C);
Jean-Marc Valin827f9312008-05-06 23:21:55 +10002041
Jean-Marc Valin8cbea172010-08-05 15:22:57 -04002042 /* Decode fixed codebook */
Jean-Marc Valin4f177e82010-11-26 10:32:03 -05002043 quant_all_bands(0, st->mode, st->start, st->end, X, C==2 ? X+N : NULL,
Timothy B. Terriberry320cf2e2010-12-17 05:52:06 -08002044 NULL, pulses, shortBlocks, spread_decision, dual_stereo, intensity, tf_res, 1,
Jean-Marc Valin4f177e82010-11-26 10:32:03 -05002045 len*8, dec, LM, codedBands);
Jean-Marc Valin746b2a82010-05-14 22:12:33 -04002046
Jean-Marc Valin02a35272010-08-27 16:00:01 -04002047 unquant_energy_finalise(st->mode, st->start, st->end, bandE, oldBandE,
2048 fine_quant, fine_priority, len*8-ec_dec_tell(dec, 0), dec, C);
Jean-Marc Valin30d51252010-06-21 17:55:28 -04002049
Jean-Marc Valin02a35272010-08-27 16:00:01 -04002050 log2Amp(st->mode, st->start, st->end, bandE, oldBandE, C);
Jean-Marc Valinbc272de2010-08-02 09:41:31 -04002051
Jean-Marc Valina4833ff2008-01-10 15:34:00 +11002052 /* Synthesis */
Jean-Marc Valin85f41b22010-07-16 18:12:45 -04002053 denormalise_bands(st->mode, X, freq, bandE, effEnd, C, M);
Jean-Marc Valina4833ff2008-01-10 15:34:00 +11002054
Jean-Marc Valin6d131082010-08-27 15:15:32 -04002055 CELT_MOVE(decode_mem[0], decode_mem[0]+N, DECODE_BUFFER_SIZE-N);
Jean-Marc Valin903dbf72010-08-26 20:06:49 -04002056 if (C==2)
Jean-Marc Valin6d131082010-08-27 15:15:32 -04002057 CELT_MOVE(decode_mem[1], decode_mem[1]+N, DECODE_BUFFER_SIZE-N);
Jean-Marc Valin88619552009-10-04 21:35:36 -04002058
Gregory Maxwell9743bf32010-11-04 20:45:09 -04002059 c=0; do
Jean-Marc Valin5f961462010-05-19 13:38:10 -04002060 for (i=0;i<M*st->mode->eBands[st->start];i++)
2061 freq[c*N+i] = 0;
Gregory Maxwell9743bf32010-11-04 20:45:09 -04002062 while (++c<C);
2063 c=0; do
Jean-Marc Valin85f41b22010-07-16 18:12:45 -04002064 for (i=M*st->mode->eBands[effEnd];i<N;i++)
Jean-Marc Valin525d7cf2010-07-13 14:14:16 -04002065 freq[c*N+i] = 0;
Gregory Maxwell9743bf32010-11-04 20:45:09 -04002066 while (++c<C);
Jean-Marc Valin3a0bc3d2010-02-21 15:10:22 -05002067
Jean-Marc Valin6d131082010-08-27 15:15:32 -04002068 out_syn[0] = out_mem[0]+MAX_PERIOD-N;
Jean-Marc Valinf67b4472010-08-27 01:32:40 -04002069 if (C==2)
Jean-Marc Valin6d131082010-08-27 15:15:32 -04002070 out_syn[1] = out_mem[1]+MAX_PERIOD-N;
Jean-Marc Valinf67b4472010-08-27 01:32:40 -04002071
Jean-Marc Valin269d40a2007-12-07 11:29:45 +11002072 /* Compute inverse MDCTs */
Jean-Marc Valin7a08ddd2010-10-18 14:55:42 -04002073 compute_inv_mdcts(st->mode, shortBlocks, freq, out_syn, overlap_mem, C, LM);
Jean-Marc Valinffa13472007-12-10 16:54:17 +11002074
Jean-Marc Valin35095c62010-11-04 13:24:44 -04002075#ifdef ENABLE_POSTFILTER
Gregory Maxwell9743bf32010-11-04 20:45:09 -04002076 c=0; do {
Jean-Marc Valin70d30ff2010-12-13 13:50:29 -05002077 st->postfilter_period=IMAX(st->postfilter_period, COMBFILTER_MINPERIOD);
2078 st->postfilter_period_old=IMAX(st->postfilter_period_old, COMBFILTER_MINPERIOD);
2079 if (LM!=0)
2080 {
2081 comb_filter(out_syn[c], out_syn[c], st->postfilter_period, st->postfilter_period, st->overlap, C,
Jean-Marc Valindfa847a2011-01-17 11:37:08 -05002082 st->postfilter_gain, st->postfilter_gain, st->postfilter_tapset, st->postfilter_tapset,
2083 NULL, 0);
Jean-Marc Valin70d30ff2010-12-13 13:50:29 -05002084 comb_filter(out_syn[c]+st->overlap, out_syn[c]+st->overlap, st->postfilter_period, postfilter_pitch, N-st->overlap, C,
Jean-Marc Valindfa847a2011-01-17 11:37:08 -05002085 st->postfilter_gain, postfilter_gain, st->postfilter_tapset, postfilter_tapset,
2086 st->mode->window, st->mode->overlap);
Jean-Marc Valin70d30ff2010-12-13 13:50:29 -05002087 } else {
2088 comb_filter(out_syn[c], out_syn[c], st->postfilter_period_old, st->postfilter_period, N-st->overlap, C,
Jean-Marc Valindfa847a2011-01-17 11:37:08 -05002089 st->postfilter_gain_old, st->postfilter_gain, st->postfilter_tapset_old, st->postfilter_tapset,
2090 st->mode->window, st->mode->overlap);
Jean-Marc Valin70d30ff2010-12-13 13:50:29 -05002091 }
Gregory Maxwell9743bf32010-11-04 20:45:09 -04002092 } while (++c<C);
Jean-Marc Valin70d30ff2010-12-13 13:50:29 -05002093 st->postfilter_period_old = st->postfilter_period;
2094 st->postfilter_gain_old = st->postfilter_gain;
Jean-Marc Valindfa847a2011-01-17 11:37:08 -05002095 st->postfilter_tapset_old = st->postfilter_tapset;
Jean-Marc Valin35095c62010-11-04 13:24:44 -04002096 st->postfilter_period = postfilter_pitch;
2097 st->postfilter_gain = postfilter_gain;
Jean-Marc Valindfa847a2011-01-17 11:37:08 -05002098 st->postfilter_tapset = postfilter_tapset;
Jean-Marc Valin35095c62010-11-04 13:24:44 -04002099#endif /* ENABLE_POSTFILTER */
2100
Jean-Marc Valin5677e342011-01-13 16:15:53 -05002101 /* In case start or end were to change */
2102 for (i=0;i<st->start;i++)
2103 oldBandE[i]=0;
2104 for (i=st->end;i<st->mode->nbEBands;i++)
2105 oldBandE[i]=0;
2106
Jean-Marc Valinf67b4472010-08-27 01:32:40 -04002107 deemphasis(out_syn, pcm, N, C, st->mode->preemph, st->preemph_memD);
Jean-Marc Valine14fe902009-12-11 00:07:31 -05002108 st->loss_count = 0;
Jean-Marc Valin8600f692008-02-29 15:14:12 +11002109 RESTORE_STACK;
Timothy B. Terriberry30df6cf2010-12-21 08:42:26 -08002110 if (ec_dec_tell(dec,0) > 8*len || ec_dec_get_error(dec))
Jean-Marc Valinb1e017f2010-07-18 21:20:35 -04002111 return CELT_CORRUPTED_DATA;
2112 else
2113 return CELT_OK;
Jean-Marc Valin269d40a2007-12-07 11:29:45 +11002114}
2115
Gregory Maxwell5f2a74b2008-08-11 23:50:07 -04002116#ifdef FIXED_POINT
2117#ifndef DISABLE_FLOAT_API
Jean-Marc Valinf5e2e322010-05-19 12:05:02 -04002118int 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 -04002119{
Jean-Marc Valin017fa852010-05-06 22:11:48 -04002120 int j, ret, C, N, LM, M;
Jean-Marc Valin30f7f812009-10-17 14:35:13 -04002121 VARDECL(celt_int16, out);
Jean-Marc Valincb8780c2009-07-20 23:40:35 -04002122 SAVE_STACK;
Gregory Maxwell17169992009-06-04 15:15:34 -04002123
Gregory Maxwell0719f6f2009-07-09 17:07:24 -04002124 if (pcm==NULL)
2125 return CELT_BAD_ARG;
2126
Jean-Marc Valin017fa852010-05-06 22:11:48 -04002127 for (LM=0;LM<4;LM++)
2128 if (st->mode->shortMdctSize<<LM==frame_size)
2129 break;
2130 if (LM>=MAX_CONFIG_SIZES)
2131 return CELT_BAD_ARG;
2132 M=1<<LM;
2133
Jean-Marc Valin80ed1472009-10-15 21:45:32 -04002134 C = CHANNELS(st->channels);
Jean-Marc Valin017fa852010-05-06 22:11:48 -04002135 N = M*st->mode->shortMdctSize;
Gregory Maxwell0719f6f2009-07-09 17:07:24 -04002136
Jean-Marc Valin30f7f812009-10-17 14:35:13 -04002137 ALLOC(out, C*N, celt_int16);
Jean-Marc Valinf5e2e322010-05-19 12:05:02 -04002138 ret=celt_decode_with_ec(st, data, len, out, frame_size, dec);
Jean-Marc Valinb1e017f2010-07-18 21:20:35 -04002139 if (ret==0)
2140 for (j=0;j<C*N;j++)
Jean-Marc Valinae01e112010-08-03 21:43:41 -04002141 pcm[j]=out[j]*(1.f/32768.f);
Gregory Maxwell0719f6f2009-07-09 17:07:24 -04002142
Wessel Lubberhuizen33ba6cc2008-10-03 07:09:29 -04002143 RESTORE_STACK;
Gregory Maxwell5f2a74b2008-08-11 23:50:07 -04002144 return ret;
2145}
2146#endif /*DISABLE_FLOAT_API*/
2147#else
Jean-Marc Valinf5e2e322010-05-19 12:05:02 -04002148int 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 -04002149{
Jean-Marc Valin017fa852010-05-06 22:11:48 -04002150 int j, ret, C, N, LM, M;
Jean-Marc Valin234969c2009-10-17 22:12:42 -04002151 VARDECL(celt_sig, out);
Jean-Marc Valincb8780c2009-07-20 23:40:35 -04002152 SAVE_STACK;
Gregory Maxwell17169992009-06-04 15:15:34 -04002153
Gregory Maxwell0719f6f2009-07-09 17:07:24 -04002154 if (pcm==NULL)
2155 return CELT_BAD_ARG;
2156
Jean-Marc Valin017fa852010-05-06 22:11:48 -04002157 for (LM=0;LM<4;LM++)
2158 if (st->mode->shortMdctSize<<LM==frame_size)
2159 break;
2160 if (LM>=MAX_CONFIG_SIZES)
2161 return CELT_BAD_ARG;
2162 M=1<<LM;
2163
Jean-Marc Valin80ed1472009-10-15 21:45:32 -04002164 C = CHANNELS(st->channels);
Jean-Marc Valin017fa852010-05-06 22:11:48 -04002165 N = M*st->mode->shortMdctSize;
Jean-Marc Valin234969c2009-10-17 22:12:42 -04002166 ALLOC(out, C*N, celt_sig);
Gregory Maxwell5f2a74b2008-08-11 23:50:07 -04002167
Jean-Marc Valinf5e2e322010-05-19 12:05:02 -04002168 ret=celt_decode_with_ec_float(st, data, len, out, frame_size, dec);
Gregory Maxwell5f2a74b2008-08-11 23:50:07 -04002169
Jean-Marc Valinb1e017f2010-07-18 21:20:35 -04002170 if (ret==0)
2171 for (j=0;j<C*N;j++)
2172 pcm[j] = FLOAT2INT16 (out[j]);
Gregory Maxwell0719f6f2009-07-09 17:07:24 -04002173
Wessel Lubberhuizen33ba6cc2008-10-03 07:09:29 -04002174 RESTORE_STACK;
Gregory Maxwell5f2a74b2008-08-11 23:50:07 -04002175 return ret;
2176}
2177#endif
John Ridges454d1d02009-05-21 22:38:39 -04002178
Jean-Marc Valinf5e2e322010-05-19 12:05:02 -04002179int celt_decode(CELTDecoder * restrict st, const unsigned char *data, int len, celt_int16 * restrict pcm, int frame_size)
2180{
2181 return celt_decode_with_ec(st, data, len, pcm, frame_size, NULL);
2182}
2183
Jean-Marc Valin4424b5a2010-07-06 19:37:23 -04002184#ifndef DISABLE_FLOAT_API
Jean-Marc Valinf5e2e322010-05-19 12:05:02 -04002185int celt_decode_float(CELTDecoder * restrict st, const unsigned char *data, int len, float * restrict pcm, int frame_size)
2186{
2187 return celt_decode_with_ec_float(st, data, len, pcm, frame_size, NULL);
2188}
Jean-Marc Valin4424b5a2010-07-06 19:37:23 -04002189#endif /* DISABLE_FLOAT_API */
Jean-Marc Valinf5e2e322010-05-19 12:05:02 -04002190
John Ridges454d1d02009-05-21 22:38:39 -04002191int celt_decoder_ctl(CELTDecoder * restrict st, int request, ...)
2192{
2193 va_list ap;
Gregory Maxwell17169992009-06-04 15:15:34 -04002194
John Ridges454d1d02009-05-21 22:38:39 -04002195 va_start(ap, request);
2196 switch (request)
2197 {
Gregory Maxwellf3b44ef2009-06-03 13:37:45 -04002198 case CELT_GET_MODE_REQUEST:
2199 {
2200 const CELTMode ** value = va_arg(ap, const CELTMode**);
2201 if (value==0)
2202 goto bad_arg;
2203 *value=st->mode;
2204 }
2205 break;
Jean-Marc Valin5f961462010-05-19 13:38:10 -04002206 case CELT_SET_START_BAND_REQUEST:
2207 {
2208 celt_int32 value = va_arg(ap, celt_int32);
2209 if (value<0 || value>=st->mode->nbEBands)
2210 goto bad_arg;
2211 st->start = value;
2212 }
2213 break;
Jean-Marc Valin525d7cf2010-07-13 14:14:16 -04002214 case CELT_SET_END_BAND_REQUEST:
2215 {
2216 celt_int32 value = va_arg(ap, celt_int32);
2217 if (value<0 || value>=st->mode->nbEBands)
2218 goto bad_arg;
2219 st->end = value;
2220 }
2221 break;
John Ridges454d1d02009-05-21 22:38:39 -04002222 case CELT_RESET_STATE:
2223 {
Jean-Marc Valinc09807d2010-08-27 17:17:50 -04002224 CELT_MEMSET((char*)&st->DECODER_RESET_START, 0,
2225 celt_decoder_get_size(st->mode, st->channels)-
2226 ((char*)&st->DECODER_RESET_START - (char*)st));
John Ridges454d1d02009-05-21 22:38:39 -04002227 }
2228 break;
2229 default:
2230 goto bad_request;
2231 }
2232 va_end(ap);
2233 return CELT_OK;
John Ridges454d1d02009-05-21 22:38:39 -04002234bad_arg:
2235 va_end(ap);
2236 return CELT_BAD_ARG;
John Ridges454d1d02009-05-21 22:38:39 -04002237bad_request:
2238 va_end(ap);
2239 return CELT_UNIMPLEMENTED;
2240}
Jean-Marc Valinece94a02009-10-16 07:30:14 -04002241
2242const char *celt_strerror(int error)
2243{
2244 static const char *error_strings[8] = {
2245 "success",
2246 "invalid argument",
2247 "invalid mode",
2248 "internal error",
2249 "corrupted stream",
2250 "request not implemented",
2251 "invalid state",
2252 "memory allocation failed"
2253 };
2254 if (error > 0 || error < -7)
2255 return "unknown error";
2256 else
2257 return error_strings[-error];
2258}
2259