blob: 966cd685d67bf0118264b95f4aa00dae230ef4e3 [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
Jean-Marc Valin4b087df2010-11-30 21:08:31 -050056static const int trim_cdf[12] = {0, 2, 4, 9, 19, 41, 87, 109, 119, 124, 126, 128};
57
Jean-Marc Valin35095c62010-11-04 13:24:44 -040058#define COMBFILTER_MAXPERIOD 1024
59#define COMBFILTER_MINPERIOD 16
Jean-Marc Valin6bf04622010-09-30 10:16:22 -040060
Jean-Marc Valin276de722008-02-20 17:45:51 +110061/** Encoder state
62 @brief Encoder state
63 */
Jean-Marc Valin269d40a2007-12-07 11:29:45 +110064struct CELTEncoder {
Jean-Marc Valin276de722008-02-20 17:45:51 +110065 const CELTMode *mode; /**< Mode used by the encoder */
Jean-Marc Valina5431bf2008-01-03 20:53:01 +110066 int overlap;
Jean-Marc Valinffa13472007-12-10 16:54:17 +110067 int channels;
68
Gregory Maxwell2dd3d322009-06-05 14:05:51 -040069 int force_intra;
Jean-Marc Valin1213ba52010-08-31 17:03:13 -040070 int complexity;
Jean-Marc Valinc09807d2010-08-27 17:17:50 -040071 int start, end;
72
Gregory Maxwella9411472010-10-28 03:52:21 -040073 celt_int32 vbr_rate_norm; /* Target number of 8th bits per frame */
Jean-Marc Valin9faf7402010-12-04 10:27:22 -050074 int constrained_vbr; /* If zero, VBR can do whatever it likes with the rate */
Jean-Marc Valinc09807d2010-08-27 17:17:50 -040075
76 /* Everything beyond this point gets cleared on a reset */
77#define ENCODER_RESET_START frame_max
78
79 celt_word32 frame_max;
Timothy B. Terriberry320cf2e2010-12-17 05:52:06 -080080 int spread_decision;
Jean-Marc Valin74f4e9f2009-05-02 09:57:50 -040081 int delayedIntra;
Jean-Marc Valin1d17b9a2010-08-31 14:51:58 -040082 int tonal_average;
Jean-Marc Valindfd6e712010-12-09 23:23:34 -050083 int lastCodedBands;
Jean-Marc Valin527db5c2009-06-02 07:56:19 -040084
Jean-Marc Valin35095c62010-11-04 13:24:44 -040085 int prefilter_period;
86 celt_word16 prefilter_gain;
Jean-Marc Valin70d30ff2010-12-13 13:50:29 -050087#ifdef RESYNTH
88 int prefilter_period_old;
89 celt_word16 prefilter_gain_old;
90#endif
Jean-Marc Valin35095c62010-11-04 13:24:44 -040091
Jean-Marc Valinbd5d54a2009-10-20 00:25:31 -040092 /* VBR-related parameters */
93 celt_int32 vbr_reservoir;
94 celt_int32 vbr_drift;
95 celt_int32 vbr_offset;
96 celt_int32 vbr_count;
97
Jean-Marc Valinac1da4f2010-07-24 11:48:10 -040098 celt_word32 preemph_memE[2];
99 celt_word32 preemph_memD[2];
Jean-Marc Valin81b38c22008-02-29 21:08:49 +1100100
Jean-Marc Valin35095c62010-11-04 13:24:44 -0400101#ifdef RESYNTH
102 celt_sig syn_mem[2][2*MAX_PERIOD];
103#endif
104
Jean-Marc Valinca8b9922010-08-27 16:23:03 -0400105 celt_sig in_mem[1]; /* Size = channels*mode->overlap */
Jean-Marc Valin35095c62010-11-04 13:24:44 -0400106 /* celt_sig prefilter_mem[], Size = channels*COMBFILTER_PERIOD */
Jean-Marc Valinca8b9922010-08-27 16:23:03 -0400107 /* celt_sig overlap_mem[], Size = channels*mode->overlap */
108 /* celt_word16 oldEBands[], Size = channels*mode->nbEBands */
Jean-Marc Valin8ebd3452007-11-29 20:17:32 +1100109};
110
Jean-Marc Valin0d8eaa32010-08-27 14:57:37 -0400111int celt_encoder_get_size(const CELTMode *mode, int channels)
112{
113 int size = sizeof(struct CELTEncoder)
114 + (2*channels*mode->overlap-1)*sizeof(celt_sig)
Jean-Marc Valin35095c62010-11-04 13:24:44 -0400115 + channels*COMBFILTER_MAXPERIOD*sizeof(celt_sig)
Jean-Marc Valin0d8eaa32010-08-27 14:57:37 -0400116 + channels*mode->nbEBands*sizeof(celt_word16);
117 return size;
118}
119
Jean-Marc Valin80ed1472009-10-15 21:45:32 -0400120CELTEncoder *celt_encoder_create(const CELTMode *mode, int channels, int *error)
Jean-Marc Valin8ebd3452007-11-29 20:17:32 +1100121{
Jean-Marc Valin7cfb7302010-08-27 16:54:33 -0400122 return celt_encoder_init(
123 (CELTEncoder *)celt_alloc(celt_encoder_get_size(mode, channels)),
124 mode, channels, error);
125}
Jean-Marc Valin44ffd5a2008-02-22 00:39:25 +1100126
Jean-Marc Valin7cfb7302010-08-27 16:54:33 -0400127CELTEncoder *celt_encoder_init(CELTEncoder *st, const CELTMode *mode, int channels, int *error)
128{
Jean-Marc Valin80ed1472009-10-15 21:45:32 -0400129 if (channels < 0 || channels > 2)
130 {
Jean-Marc Valin80ed1472009-10-15 21:45:32 -0400131 if (error)
132 *error = CELT_BAD_ARG;
133 return NULL;
134 }
Jean-Marc Valin44ffd5a2008-02-22 00:39:25 +1100135
Jean-Marc Valinece94a02009-10-16 07:30:14 -0400136 if (st==NULL)
137 {
138 if (error)
139 *error = CELT_ALLOC_FAIL;
Jean-Marc Valin80ed1472009-10-15 21:45:32 -0400140 return NULL;
Jean-Marc Valinece94a02009-10-16 07:30:14 -0400141 }
Jean-Marc Valin6d3829f2010-08-27 17:52:38 -0400142
143 CELT_MEMSET((char*)st, 0, celt_encoder_get_size(mode, channels));
144
Jean-Marc Valin73e51b32007-12-05 17:48:24 +1100145 st->mode = mode;
Jean-Marc Valina5431bf2008-01-03 20:53:01 +1100146 st->overlap = mode->overlap;
Jean-Marc Valin80ed1472009-10-15 21:45:32 -0400147 st->channels = channels;
Jean-Marc Valina5431bf2008-01-03 20:53:01 +1100148
Jean-Marc Valin5f961462010-05-19 13:38:10 -0400149 st->start = 0;
Jean-Marc Valin8952c452010-07-16 21:48:44 -0400150 st->end = st->mode->effEBands;
Jean-Marc Valin9faf7402010-12-04 10:27:22 -0500151 st->constrained_vbr = 1;
Jean-Marc Valin5f961462010-05-19 13:38:10 -0400152
Jean-Marc Valin8cc945c2010-05-29 08:07:18 -0400153 st->vbr_rate_norm = 0;
Jean-Marc Valin30165bb2010-12-03 14:35:59 -0500154 st->vbr_offset = 0;
Gregory Maxwell2dd3d322009-06-05 14:05:51 -0400155 st->force_intra = 0;
Gregory Maxwell8842fde2009-05-04 15:58:40 -0400156 st->delayedIntra = 1;
Jean-Marc Valin1213ba52010-08-31 17:03:13 -0400157 st->tonal_average = 256;
Timothy B. Terriberry320cf2e2010-12-17 05:52:06 -0800158 st->spread_decision = SPREAD_NORMAL;
Jean-Marc Valin1213ba52010-08-31 17:03:13 -0400159 st->complexity = 5;
Jean-Marc Valina76a0b22008-01-17 22:43:05 +1100160
Jean-Marc Valinece94a02009-10-16 07:30:14 -0400161 if (error)
Jean-Marc Valin0d8eaa32010-08-27 14:57:37 -0400162 *error = CELT_OK;
Jean-Marc Valin0d8eaa32010-08-27 14:57:37 -0400163 return st;
Jean-Marc Valin8ebd3452007-11-29 20:17:32 +1100164}
165
Peter Kirk19f9dc92008-06-06 14:38:38 +0200166void celt_encoder_destroy(CELTEncoder *st)
Jean-Marc Valin14191b32007-11-30 12:15:49 +1100167{
Jean-Marc Valin14191b32007-11-30 12:15:49 +1100168 celt_free(st);
169}
170
Jean-Marc Valin30f7f812009-10-17 14:35:13 -0400171static inline celt_int16 FLOAT2INT16(float x)
Jean-Marc Valin42074382008-02-27 11:08:53 +1100172{
Gregory Maxwell0ac2b2f2009-05-21 23:08:46 -0400173 x = x*CELT_SIG_SCALE;
Gregory Maxwell5f2a74b2008-08-11 23:50:07 -0400174 x = MAX32(x, -32768);
175 x = MIN32(x, 32767);
Jean-Marc Valin30f7f812009-10-17 14:35:13 -0400176 return (celt_int16)float2int(x);
Gregory Maxwell5f2a74b2008-08-11 23:50:07 -0400177}
178
Jean-Marc Valin234969c2009-10-17 22:12:42 -0400179static inline celt_word16 SIG2WORD16(celt_sig x)
Gregory Maxwell5f2a74b2008-08-11 23:50:07 -0400180{
181#ifdef FIXED_POINT
Jean-Marc Valin42074382008-02-27 11:08:53 +1100182 x = PSHR32(x, SIG_SHIFT);
Jean-Marc Valinabdfc382008-04-18 15:57:18 +1000183 x = MAX32(x, -32768);
184 x = MIN32(x, 32767);
Jean-Marc Valin42074382008-02-27 11:08:53 +1100185 return EXTRACT16(x);
186#else
Jean-Marc Valin234969c2009-10-17 22:12:42 -0400187 return (celt_word16)x;
Jean-Marc Valin42074382008-02-27 11:08:53 +1100188#endif
189}
190
Jean-Marc Valin9c30de52010-04-19 13:32:15 -0400191static int transient_analysis(const celt_word32 * restrict in, int len, int C,
Jean-Marc Valinbdb58712010-05-28 18:58:42 -0400192 celt_word32 *frame_max, int overlap)
Jean-Marc Valin9375aa42008-06-27 07:57:35 +1000193{
Jean-Marc Valinfddc5212010-12-09 14:28:26 -0500194 int i;
Jean-Marc Valin2794b632010-10-13 17:32:57 -0400195 VARDECL(celt_word16, tmp);
196 celt_word32 mem0=0,mem1=0;
Jean-Marc Valinfddc5212010-12-09 14:28:26 -0500197 int is_transient = 0;
198 int block;
199 int N;
200 /* FIXME: Make that smaller */
201 celt_word16 bins[50];
Jean-Marc Valin0ceccb22008-07-03 20:41:06 -0400202 SAVE_STACK;
Jean-Marc Valin2794b632010-10-13 17:32:57 -0400203 ALLOC(tmp, len, celt_word16);
Jean-Marc Valin2794b632010-10-13 17:32:57 -0400204
Jean-Marc Valinfddc5212010-12-09 14:28:26 -0500205 block = overlap/2;
206 N=len/block;
Jean-Marc Valin9c30de52010-04-19 13:32:15 -0400207 if (C==1)
Jean-Marc Valin9375aa42008-06-27 07:57:35 +1000208 {
209 for (i=0;i<len;i++)
Jean-Marc Valin2794b632010-10-13 17:32:57 -0400210 tmp[i] = SHR32(in[i],SIG_SHIFT);
Jean-Marc Valin9c30de52010-04-19 13:32:15 -0400211 } else {
212 for (i=0;i<len;i++)
Jean-Marc Valin933dd832010-10-24 00:08:16 -0400213 tmp[i] = SHR32(ADD32(in[i],in[i+len]), SIG_SHIFT+1);
Jean-Marc Valin9375aa42008-06-27 07:57:35 +1000214 }
Jean-Marc Valin2794b632010-10-13 17:32:57 -0400215
216 /* High-pass filter: (1 - 2*z^-1 + z^-2) / (1 - z^-1 + .5*z^-2) */
217 for (i=0;i<len;i++)
218 {
219 celt_word32 x,y;
220 x = tmp[i];
221 y = ADD32(mem0, x);
222#ifdef FIXED_POINT
223 mem0 = mem1 + y - SHL32(x,1);
224 mem1 = x - SHR32(y,1);
225#else
226 mem0 = mem1 + y - 2*x;
Gregory Maxwell60c316b2010-11-04 20:14:19 -0400227 mem1 = x - .5f*y;
Jean-Marc Valin2794b632010-10-13 17:32:57 -0400228#endif
229 tmp[i] = EXTRACT16(SHR(y,2));
230 }
231 /* First few samples are bad because we don't propagate the memory */
Jean-Marc Valinfddc5212010-12-09 14:28:26 -0500232 for (i=0;i<12;i++)
Jean-Marc Valin2794b632010-10-13 17:32:57 -0400233 tmp[i] = 0;
234
Jean-Marc Valinfddc5212010-12-09 14:28:26 -0500235 for (i=0;i<N;i++)
Jean-Marc Valin9375aa42008-06-27 07:57:35 +1000236 {
Jean-Marc Valinfddc5212010-12-09 14:28:26 -0500237 int j;
238 float max_abs=0;
239 for (j=0;j<block;j++)
240 max_abs = MAX32(max_abs, tmp[i*block+j]);
241 bins[i] = max_abs;
Jean-Marc Valin9375aa42008-06-27 07:57:35 +1000242 }
Jean-Marc Valinfddc5212010-12-09 14:28:26 -0500243 for (i=0;i<N;i++)
Jean-Marc Valin4a8c1f12010-10-13 18:03:50 -0400244 {
Jean-Marc Valinfddc5212010-12-09 14:28:26 -0500245 int j;
246 int conseq=0;
247 celt_word16 t1, t2, t3;
248
249 t1 = MULT16_16_Q15(QCONST16(.15f, 15), bins[i]);
250 t2 = MULT16_16_Q15(QCONST16(.4f, 15), bins[i]);
251 t3 = MULT16_16_Q15(QCONST16(.15f, 15), bins[i]);
252 for (j=0;j<i;j++)
253 {
254 if (bins[j] < t1)
255 conseq++;
256 if (bins[j] < t2)
257 conseq++;
258 else
259 conseq = 0;
260 }
261 if (conseq>=3)
262 is_transient=1;
263 conseq = 0;
264 for (j=i+1;j<N;j++)
265 {
266 if (bins[j] < t3)
267 conseq++;
268 else
269 conseq = 0;
270 }
271 if (conseq>=7)
272 is_transient=1;
Jean-Marc Valin4a8c1f12010-10-13 18:03:50 -0400273 }
Jean-Marc Valin0ceccb22008-07-03 20:41:06 -0400274 RESTORE_STACK;
Jean-Marc Valinfddc5212010-12-09 14:28:26 -0500275 return is_transient;
Jean-Marc Valin9375aa42008-06-27 07:57:35 +1000276}
277
Jean-Marc Valin56522ad2009-06-05 17:17:25 -0400278/** Apply window and compute the MDCT for all sub-frames and
279 all channels in a frame */
Jean-Marc Valin017fa852010-05-06 22:11:48 -0400280static 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 +1100281{
Jean-Marc Valinbf2398b2009-10-15 07:28:19 -0400282 const int C = CHANNELS(_C);
Jean-Marc Valin9d1decd2008-06-17 13:28:13 +1000283 if (C==1 && !shortBlocks)
Jean-Marc Valinda721882007-11-30 15:17:42 +1100284 {
Jean-Marc Valin9d1decd2008-06-17 13:28:13 +1000285 const int overlap = OVERLAP(mode);
Jean-Marc Valin72513f32010-07-07 21:26:38 -0400286 clt_mdct_forward(&mode->mdct, in, out, mode->window, overlap, mode->maxLM-LM);
Jean-Marc Valinaa4f58b2009-10-03 09:27:59 -0400287 } else {
Jean-Marc Valin9d1decd2008-06-17 13:28:13 +1000288 const int overlap = OVERLAP(mode);
Jean-Marc Valince4dd362010-05-07 07:45:18 -0400289 int N = mode->shortMdctSize<<LM;
Jean-Marc Valinaa4f58b2009-10-03 09:27:59 -0400290 int B = 1;
Jean-Marc Valin9d1decd2008-06-17 13:28:13 +1000291 int b, c;
Jean-Marc Valin234969c2009-10-17 22:12:42 -0400292 VARDECL(celt_word32, tmp);
Jean-Marc Valin9d1decd2008-06-17 13:28:13 +1000293 SAVE_STACK;
Jean-Marc Valinaa4f58b2009-10-03 09:27:59 -0400294 if (shortBlocks)
295 {
Jean-Marc Valin72513f32010-07-07 21:26:38 -0400296 /*lookup = &mode->mdct[0];*/
Jean-Marc Valinaa4f58b2009-10-03 09:27:59 -0400297 N = mode->shortMdctSize;
Jean-Marc Valin3b918ba2010-05-05 00:02:26 -0400298 B = shortBlocks;
Jean-Marc Valinaa4f58b2009-10-03 09:27:59 -0400299 }
Jean-Marc Valin234969c2009-10-17 22:12:42 -0400300 ALLOC(tmp, N, celt_word32);
Gregory Maxwell9743bf32010-11-04 20:45:09 -0400301 c=0; do {
Jean-Marc Valin9d1decd2008-06-17 13:28:13 +1000302 for (b=0;b<B;b++)
303 {
304 int j;
Jean-Marc Valineedb4222010-10-24 00:22:45 -0400305 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 +1000306 /* Interleaving the sub-frames */
307 for (j=0;j<N;j++)
Jean-Marc Valin08a82ff2009-06-14 14:05:19 -0400308 out[(j*B+b)+c*N*B] = tmp[j];
Jean-Marc Valin9d1decd2008-06-17 13:28:13 +1000309 }
Gregory Maxwell9743bf32010-11-04 20:45:09 -0400310 } while (++c<C);
Jean-Marc Valin9d1decd2008-06-17 13:28:13 +1000311 RESTORE_STACK;
Jean-Marc Valinda721882007-11-30 15:17:42 +1100312 }
Jean-Marc Valinda721882007-11-30 15:17:42 +1100313}
314
Jean-Marc Valin56522ad2009-06-05 17:17:25 -0400315/** Compute the IMDCT and apply window for all sub-frames and
316 all channels in a frame */
Jean-Marc Valine0ce2cf2010-08-26 23:58:08 -0400317static void compute_inv_mdcts(const CELTMode *mode, int shortBlocks, celt_sig *X,
Jean-Marc Valin7a08ddd2010-10-18 14:55:42 -0400318 celt_sig * restrict out_mem[],
Jean-Marc Valine0ce2cf2010-08-26 23:58:08 -0400319 celt_sig * restrict overlap_mem[], int _C, int LM)
Jean-Marc Valin1677aa92007-12-08 01:13:34 +1100320{
Jean-Marc Valin0695a5f2010-08-27 11:33:18 -0400321 int c;
Jean-Marc Valinbf2398b2009-10-15 07:28:19 -0400322 const int C = CHANNELS(_C);
Jean-Marc Valince4dd362010-05-07 07:45:18 -0400323 const int N = mode->shortMdctSize<<LM;
Jean-Marc Valinb18ec0b2008-04-11 04:07:52 +1000324 const int overlap = OVERLAP(mode);
Gregory Maxwell9743bf32010-11-04 20:45:09 -0400325 c=0; do {
Jean-Marc Valinb886ddc2008-03-25 14:38:55 +1100326 int j;
Jean-Marc Valin234969c2009-10-17 22:12:42 -0400327 VARDECL(celt_word32, x);
328 VARDECL(celt_word32, tmp);
Jean-Marc Valinde678582009-10-03 10:36:27 -0400329 int b;
330 int N2 = N;
331 int B = 1;
Jean-Marc Valin9d1decd2008-06-17 13:28:13 +1000332 SAVE_STACK;
Jean-Marc Valinde678582009-10-03 10:36:27 -0400333
Jean-Marc Valinf67b4472010-08-27 01:32:40 -0400334 ALLOC(x, N+overlap, celt_word32);
Jean-Marc Valin234969c2009-10-17 22:12:42 -0400335 ALLOC(tmp, N, celt_word32);
Jean-Marc Valinde678582009-10-03 10:36:27 -0400336
337 if (shortBlocks)
338 {
Jean-Marc Valinde678582009-10-03 10:36:27 -0400339 N2 = mode->shortMdctSize;
Jean-Marc Valin3b918ba2010-05-05 00:02:26 -0400340 B = shortBlocks;
Jean-Marc Valinde678582009-10-03 10:36:27 -0400341 }
Jean-Marc Valin9d1decd2008-06-17 13:28:13 +1000342 /* Prevents problems from the imdct doing the overlap-add */
Jean-Marc Valinf67b4472010-08-27 01:32:40 -0400343 CELT_MEMSET(x, 0, overlap);
Jean-Marc Valinde678582009-10-03 10:36:27 -0400344
Jean-Marc Valin9d1decd2008-06-17 13:28:13 +1000345 for (b=0;b<B;b++)
346 {
347 /* De-interleaving the sub-frames */
348 for (j=0;j<N2;j++)
Jean-Marc Valin08a82ff2009-06-14 14:05:19 -0400349 tmp[j] = X[(j*B+b)+c*N2*B];
Jean-Marc Valinf67b4472010-08-27 01:32:40 -0400350 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 +1000351 }
Jean-Marc Valinde678582009-10-03 10:36:27 -0400352
Jean-Marc Valin8ddd7f42008-04-22 13:37:16 +1000353 for (j=0;j<overlap;j++)
Jean-Marc Valinf67b4472010-08-27 01:32:40 -0400354 out_mem[c][j] = x[j] + overlap_mem[c][j];
Jean-Marc Valine0ce2cf2010-08-26 23:58:08 -0400355 for (;j<N;j++)
Jean-Marc Valinf67b4472010-08-27 01:32:40 -0400356 out_mem[c][j] = x[j];
Jean-Marc Valine0ce2cf2010-08-26 23:58:08 -0400357 for (j=0;j<overlap;j++)
Jean-Marc Valinf67b4472010-08-27 01:32:40 -0400358 overlap_mem[c][j] = x[N+j];
Jean-Marc Valin8ddd7f42008-04-22 13:37:16 +1000359 RESTORE_STACK;
Gregory Maxwell9743bf32010-11-04 20:45:09 -0400360 } while (++c<C);
Jean-Marc Valin1677aa92007-12-08 01:13:34 +1100361}
362
Jean-Marc Valin903dbf72010-08-26 20:06:49 -0400363static 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 -0400364{
Jean-Marc Valinbf2398b2009-10-15 07:28:19 -0400365 const int C = CHANNELS(_C);
Jean-Marc Valine12017e2009-10-03 13:57:31 -0400366 int c;
Gregory Maxwell9743bf32010-11-04 20:45:09 -0400367 c=0; do {
Jean-Marc Valine12017e2009-10-03 13:57:31 -0400368 int j;
Jean-Marc Valin64209a32010-04-05 09:26:22 -0400369 celt_sig * restrict x;
370 celt_word16 * restrict y;
371 celt_sig m = mem[c];
Jean-Marc Valinf67b4472010-08-27 01:32:40 -0400372 x =in[c];
Jean-Marc Valin64209a32010-04-05 09:26:22 -0400373 y = pcm+c;
Jean-Marc Valine12017e2009-10-03 13:57:31 -0400374 for (j=0;j<N;j++)
375 {
Jean-Marc Valinaf1fce92010-07-16 11:05:06 -0400376 celt_sig tmp = *x + m;
377 m = MULT16_32_Q15(coef[0], tmp)
378 - MULT16_32_Q15(coef[1], *x);
Jean-Marc Valin223b69d2010-07-16 11:47:50 -0400379 tmp = SHL32(MULT16_32_Q15(coef[3], tmp), 2);
Jean-Marc Valin64209a32010-04-05 09:26:22 -0400380 *y = SCALEOUT(SIG2WORD16(tmp));
Jean-Marc Valin903dbf72010-08-26 20:06:49 -0400381 x++;
Jean-Marc Valin64209a32010-04-05 09:26:22 -0400382 y+=C;
Jean-Marc Valine12017e2009-10-03 13:57:31 -0400383 }
Jean-Marc Valin64209a32010-04-05 09:26:22 -0400384 mem[c] = m;
Gregory Maxwell9743bf32010-11-04 20:45:09 -0400385 } while (++c<C);
Jean-Marc Valine12017e2009-10-03 13:57:31 -0400386}
387
Jean-Marc Valin35095c62010-11-04 13:24:44 -0400388#ifdef ENABLE_POSTFILTER
389/* FIXME: Handle the case where T = maxperiod */
390static void comb_filter(celt_word32 *y, celt_word32 *x, int T0, int T1, int N,
391 int C, celt_word16 g0, celt_word16 g1, const celt_word16 *window, int overlap)
392{
393 int i;
394 /* printf ("%d %d %f %f\n", T0, T1, g0, g1); */
395 celt_word16 g00, g01, g02, g10, g11, g12;
396 celt_word16 t0, t1, t2;
397 /* zeros at theta = +/- 5*pi/6 */
398 t0 = QCONST16(.26795f, 15);
399 t1 = QCONST16(.46410f, 15);
400 t2 = QCONST16(.26795f, 15);
401 g00 = MULT16_16_Q15(g0, t0);
402 g01 = MULT16_16_Q15(g0, t1);
403 g02 = MULT16_16_Q15(g0, t2);
404 g10 = MULT16_16_Q15(g1, t0);
405 g11 = MULT16_16_Q15(g1, t1);
406 g12 = MULT16_16_Q15(g1, t2);
407 for (i=0;i<overlap;i++)
408 {
409 celt_word16 f;
410 f = MULT16_16_Q15(window[i],window[i]);
411 y[i] = x[i]
412 + MULT16_32_Q15(MULT16_16_Q15((Q15ONE-f),g01),x[i-T0])
413 + MULT16_32_Q15(MULT16_16_Q15((Q15ONE-f),g00),x[i-T0-1])
414 + MULT16_32_Q15(MULT16_16_Q15((Q15ONE-f),g02),x[i-T0+1])
415 + MULT16_32_Q15(MULT16_16_Q15(f,g11),x[i-T1])
416 + MULT16_32_Q15(MULT16_16_Q15(f,g10),x[i-T1-1])
417 + MULT16_32_Q15(MULT16_16_Q15(f,g12),x[i-T1+1]);
418
419 }
420 for (i=overlap;i<N;i++)
421 y[i] = x[i]
422 + MULT16_32_Q15(g11,x[i-T1])
423 + MULT16_32_Q15(g10,x[i-T1-1])
424 + MULT16_32_Q15(g12,x[i-T1+1]);
425}
426#endif /* ENABLE_POSTFILTER */
427
Jean-Marc Valina8160dd2010-10-12 14:55:16 -0400428static const signed char tf_select_table[4][8] = {
Jean-Marc Valin890a9c02010-06-13 08:06:28 -0400429 {0, -1, 0, -1, 0,-1, 0,-1},
430 {0, -1, 0, -2, 1, 0, 1 -1},
431 {0, -2, 0, -3, 2, 0, 1 -1},
432 {0, -2, 0, -3, 2, 0, 1 -1},
433};
434
Jean-Marc Valinc5792de2010-10-19 14:24:50 -0400435static celt_word32 l1_metric(const celt_norm *tmp, int N, int LM, int width)
Jean-Marc Valin8200b2d2010-10-15 02:18:47 -0400436{
437 int i, j;
438 static const celt_word16 sqrtM_1[4] = {Q15ONE, QCONST16(0.70711f,15), QCONST16(0.5f,15), QCONST16(0.35355f,15)};
439 celt_word32 L1;
440 celt_word16 bias;
441 L1=0;
442 for (i=0;i<1<<LM;i++)
443 {
444 celt_word32 L2 = 0;
445 for (j=0;j<N>>LM;j++)
446 L2 = MAC16_16(L2, tmp[(j<<LM)+i], tmp[(j<<LM)+i]);
447 L1 += celt_sqrt(L2);
448 }
449 L1 = MULT16_32_Q15(sqrtM_1[LM], L1);
Jean-Marc Valin54fb7e52010-10-15 11:26:32 -0400450 if (width==1)
451 bias = QCONST16(.12f,15)*LM;
452 else if (width==2)
453 bias = QCONST16(.05f,15)*LM;
454 else
455 bias = QCONST16(.02f,15)*LM;
Jean-Marc Valin8200b2d2010-10-15 02:18:47 -0400456 L1 = MAC16_32_Q15(L1, bias, L1);
457 return L1;
458}
459
Jean-Marc Valin0f8fc0b2010-10-12 23:25:58 -0400460static int tf_analysis(const CELTMode *m, celt_word16 *bandLogE, celt_word16 *oldBandE,
Jean-Marc Valinccd5a612010-10-13 01:11:55 -0400461 int len, int C, int isTransient, int *tf_res, int nbCompressedBytes, celt_norm *X,
462 int N0, int LM, int *tf_sum)
Jean-Marc Valin163b76e2010-05-27 23:56:53 -0400463{
Jean-Marc Valin0a571ef2010-06-05 23:12:19 -0400464 int i;
Jean-Marc Valin0f8fc0b2010-10-12 23:25:58 -0400465 VARDECL(int, metric);
466 int cost0;
467 int cost1;
Jean-Marc Valin9d420c52010-05-28 17:26:27 -0400468 VARDECL(int, path0);
469 VARDECL(int, path1);
Jean-Marc Valin0f8fc0b2010-10-12 23:25:58 -0400470 VARDECL(celt_norm, tmp);
471 int lambda;
Jean-Marc Valin890a9c02010-06-13 08:06:28 -0400472 int tf_select=0;
Jean-Marc Valin163b76e2010-05-27 23:56:53 -0400473 SAVE_STACK;
474
Jean-Marc Valin6bf3b0a2010-07-19 14:32:40 -0400475 /* FIXME: Should check number of bytes *left* */
476 if (nbCompressedBytes<15*C)
477 {
Jean-Marc Valina3a066c2010-11-04 15:15:54 -0400478 *tf_sum = 0;
Jean-Marc Valin6bf3b0a2010-07-19 14:32:40 -0400479 for (i=0;i<len;i++)
Jean-Marc Valinc5792de2010-10-19 14:24:50 -0400480 tf_res[i] = isTransient;
Jean-Marc Valin6bf3b0a2010-07-19 14:32:40 -0400481 return 0;
482 }
Jean-Marc Valin73319772010-05-28 21:12:39 -0400483 if (nbCompressedBytes<40)
Jean-Marc Valin54fb7e52010-10-15 11:26:32 -0400484 lambda = 12;
Jean-Marc Valin73319772010-05-28 21:12:39 -0400485 else if (nbCompressedBytes<60)
Jean-Marc Valin54fb7e52010-10-15 11:26:32 -0400486 lambda = 6;
Jean-Marc Valin73319772010-05-28 21:12:39 -0400487 else if (nbCompressedBytes<100)
Jean-Marc Valin54fb7e52010-10-15 11:26:32 -0400488 lambda = 4;
Jean-Marc Valin73319772010-05-28 21:12:39 -0400489 else
Jean-Marc Valin54fb7e52010-10-15 11:26:32 -0400490 lambda = 3;
Jean-Marc Valin73319772010-05-28 21:12:39 -0400491
Jean-Marc Valin0f8fc0b2010-10-12 23:25:58 -0400492 ALLOC(metric, len, int);
493 ALLOC(tmp, (m->eBands[len]-m->eBands[len-1])<<LM, celt_norm);
Jean-Marc Valin9d420c52010-05-28 17:26:27 -0400494 ALLOC(path0, len, int);
495 ALLOC(path1, len, int);
Jean-Marc Valin0f8fc0b2010-10-12 23:25:58 -0400496
Jean-Marc Valinccd5a612010-10-13 01:11:55 -0400497 *tf_sum = 0;
Jean-Marc Valin163b76e2010-05-27 23:56:53 -0400498 for (i=0;i<len;i++)
Jean-Marc Valin890a9c02010-06-13 08:06:28 -0400499 {
Jean-Marc Valin0f8fc0b2010-10-12 23:25:58 -0400500 int j, k, N;
501 celt_word32 L1, best_L1;
502 int best_level=0;
503 N = (m->eBands[i+1]-m->eBands[i])<<LM;
504 for (j=0;j<N;j++)
505 tmp[j] = X[j+(m->eBands[i]<<LM)];
Jean-Marc Valin8200b2d2010-10-15 02:18:47 -0400506 /* FIXME: Do something with the right channel */
Jean-Marc Valina3a066c2010-11-04 15:15:54 -0400507 if (C==2)
Jean-Marc Valin0f8fc0b2010-10-12 23:25:58 -0400508 for (j=0;j<N;j++)
Jean-Marc Valina3a066c2010-11-04 15:15:54 -0400509 tmp[j] = ADD16(tmp[j],X[N0+j+(m->eBands[i]<<LM)]);
Jean-Marc Valin8200b2d2010-10-15 02:18:47 -0400510 L1 = l1_metric(tmp, N, isTransient ? LM : 0, N>>LM);
Jean-Marc Valin0f8fc0b2010-10-12 23:25:58 -0400511 best_L1 = L1;
512 /*printf ("%f ", L1);*/
513 for (k=0;k<LM;k++)
Jean-Marc Valin890a9c02010-06-13 08:06:28 -0400514 {
Jean-Marc Valin8200b2d2010-10-15 02:18:47 -0400515 int B;
516
517 if (isTransient)
518 B = (LM-k-1);
519 else
520 B = k+1;
521
Jean-Marc Valin0f8fc0b2010-10-12 23:25:58 -0400522 if (isTransient)
523 haar1(tmp, N>>(LM-k), 1<<(LM-k));
524 else
525 haar1(tmp, N>>k, 1<<k);
526
Jean-Marc Valin8200b2d2010-10-15 02:18:47 -0400527 L1 = l1_metric(tmp, N, B, N>>LM);
Jean-Marc Valin0f8fc0b2010-10-12 23:25:58 -0400528
Jean-Marc Valin0f8fc0b2010-10-12 23:25:58 -0400529 if (L1 < best_L1)
530 {
531 best_L1 = L1;
532 best_level = k+1;
533 }
Jean-Marc Valin890a9c02010-06-13 08:06:28 -0400534 }
Jean-Marc Valin0f8fc0b2010-10-12 23:25:58 -0400535 /*printf ("%d ", isTransient ? LM-best_level : best_level);*/
536 if (isTransient)
537 metric[i] = best_level;
538 else
539 metric[i] = -best_level;
Jean-Marc Valinccd5a612010-10-13 01:11:55 -0400540 *tf_sum += metric[i];
Jean-Marc Valin890a9c02010-06-13 08:06:28 -0400541 }
Jean-Marc Valin0f8fc0b2010-10-12 23:25:58 -0400542 /*printf("\n");*/
543 /* FIXME: Figure out how to set this */
Jean-Marc Valin8200b2d2010-10-15 02:18:47 -0400544 tf_select = 0;
Jean-Marc Valin0f8fc0b2010-10-12 23:25:58 -0400545
Jean-Marc Valin88232612010-05-28 18:01:02 -0400546 cost0 = 0;
Jean-Marc Valinc5792de2010-10-19 14:24:50 -0400547 cost1 = isTransient ? 0 : lambda;
Jean-Marc Valin9d420c52010-05-28 17:26:27 -0400548 /* Viterbi forward pass */
549 for (i=1;i<len;i++)
Jean-Marc Valin163b76e2010-05-27 23:56:53 -0400550 {
Jean-Marc Valin0f8fc0b2010-10-12 23:25:58 -0400551 int curr0, curr1;
552 int from0, from1;
Jean-Marc Valin581fdba2010-05-28 06:56:23 -0400553
Jean-Marc Valin88232612010-05-28 18:01:02 -0400554 from0 = cost0;
555 from1 = cost1 + lambda;
Jean-Marc Valin9d420c52010-05-28 17:26:27 -0400556 if (from0 < from1)
557 {
Jean-Marc Valin88232612010-05-28 18:01:02 -0400558 curr0 = from0;
Jean-Marc Valin9d420c52010-05-28 17:26:27 -0400559 path0[i]= 0;
560 } else {
Jean-Marc Valin88232612010-05-28 18:01:02 -0400561 curr0 = from1;
Jean-Marc Valin9d420c52010-05-28 17:26:27 -0400562 path0[i]= 1;
563 }
564
Jean-Marc Valin88232612010-05-28 18:01:02 -0400565 from0 = cost0 + lambda;
566 from1 = cost1;
Jean-Marc Valin9d420c52010-05-28 17:26:27 -0400567 if (from0 < from1)
568 {
Jean-Marc Valin88232612010-05-28 18:01:02 -0400569 curr1 = from0;
Jean-Marc Valin9d420c52010-05-28 17:26:27 -0400570 path1[i]= 0;
571 } else {
Jean-Marc Valin88232612010-05-28 18:01:02 -0400572 curr1 = from1;
Jean-Marc Valin9d420c52010-05-28 17:26:27 -0400573 path1[i]= 1;
574 }
Jean-Marc Valin0f8fc0b2010-10-12 23:25:58 -0400575 cost0 = curr0 + abs(metric[i]-tf_select_table[LM][4*isTransient+2*tf_select+0]);
576 cost1 = curr1 + abs(metric[i]-tf_select_table[LM][4*isTransient+2*tf_select+1]);
Jean-Marc Valin9d420c52010-05-28 17:26:27 -0400577 }
Jean-Marc Valin88232612010-05-28 18:01:02 -0400578 tf_res[len-1] = cost0 < cost1 ? 0 : 1;
Jean-Marc Valin9d420c52010-05-28 17:26:27 -0400579 /* Viterbi backward pass to check the decisions */
580 for (i=len-2;i>=0;i--)
581 {
582 if (tf_res[i+1] == 1)
583 tf_res[i] = path1[i+1];
584 else
585 tf_res[i] = path0[i+1];
586 }
Jean-Marc Valin71ae6d42010-06-27 21:55:08 -0400587 RESTORE_STACK;
Jean-Marc Valin890a9c02010-06-13 08:06:28 -0400588 return tf_select;
Jean-Marc Valin0a571ef2010-06-05 23:12:19 -0400589}
590
Jean-Marc Valine5e9aa72010-12-02 16:09:51 -0500591static 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 -0400592{
593 int curr, i;
Jean-Marc Valina8160dd2010-10-12 14:55:16 -0400594 ec_enc_bit_prob(enc, tf_res[start], isTransient ? 16384 : 4096);
595 curr = tf_res[start];
596 for (i=start+1;i<end;i++)
Jean-Marc Valin163b76e2010-05-27 23:56:53 -0400597 {
Jean-Marc Valina8160dd2010-10-12 14:55:16 -0400598 ec_enc_bit_prob(enc, tf_res[i] ^ curr, isTransient ? 4096 : 2048);
599 curr = tf_res[i];
Jean-Marc Valin163b76e2010-05-27 23:56:53 -0400600 }
Jean-Marc Valin6cbfbc32010-12-14 11:53:39 -0500601 if (LM!=0)
602 ec_enc_bits(enc, tf_select, 1);
Jean-Marc Valin2ed5e672010-07-13 16:50:11 -0400603 for (i=start;i<end;i++)
Jean-Marc Valin890a9c02010-06-13 08:06:28 -0400604 tf_res[i] = tf_select_table[LM][4*isTransient+2*tf_select+tf_res[i]];
Jean-Marc Valin0f8fc0b2010-10-12 23:25:58 -0400605 /*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 -0400606}
607
Jean-Marc Valine5e9aa72010-12-02 16:09:51 -0500608static 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 -0400609{
Jean-Marc Valin890a9c02010-06-13 08:06:28 -0400610 int i, curr, tf_select;
Jean-Marc Valina8160dd2010-10-12 14:55:16 -0400611 tf_res[start] = ec_dec_bit_prob(dec, isTransient ? 16384 : 4096);
612 curr = tf_res[start];
613 for (i=start+1;i<end;i++)
Jean-Marc Valin163b76e2010-05-27 23:56:53 -0400614 {
Jean-Marc Valina8160dd2010-10-12 14:55:16 -0400615 tf_res[i] = ec_dec_bit_prob(dec, isTransient ? 4096 : 2048) ^ curr;
616 curr = tf_res[i];
Jean-Marc Valin163b76e2010-05-27 23:56:53 -0400617 }
Jean-Marc Valin6cbfbc32010-12-14 11:53:39 -0500618 if (LM!=0)
619 tf_select = ec_dec_bits(dec, 1);
620 else
621 tf_select = 0;
Jean-Marc Valin2ed5e672010-07-13 16:50:11 -0400622 for (i=start;i<end;i++)
Jean-Marc Valin890a9c02010-06-13 08:06:28 -0400623 tf_res[i] = tf_select_table[LM][4*isTransient+2*tf_select+tf_res[i]];
Jean-Marc Valin163b76e2010-05-27 23:56:53 -0400624}
625
Jean-Marc Valinc5792de2010-10-19 14:24:50 -0400626static int alloc_trim_analysis(const CELTMode *m, const celt_norm *X,
627 const celt_word16 *bandLogE, int nbEBands, int LM, int C, int N0)
628{
629 int i;
Jean-Marc Valin546dfa12010-12-10 17:18:17 -0500630 celt_word32 diff=0;
631 int c;
Jean-Marc Valin4b087df2010-11-30 21:08:31 -0500632 int trim_index = 5;
Jean-Marc Valinc5792de2010-10-19 14:24:50 -0400633 if (C==2)
634 {
635 celt_word16 sum = 0; /* Q10 */
636 /* Compute inter-channel correlation for low frequencies */
637 for (i=0;i<8;i++)
638 {
639 int j;
640 celt_word32 partial = 0;
641 for (j=m->eBands[i]<<LM;j<m->eBands[i+1]<<LM;j++)
642 partial = MAC16_16(partial, X[j], X[N0+j]);
643 sum = ADD16(sum, EXTRACT16(SHR32(partial, 18)));
644 }
645 sum = MULT16_16_Q15(QCONST16(1.f/8, 15), sum);
646 /*printf ("%f\n", sum);*/
Gregory Maxwell60c316b2010-11-04 20:14:19 -0400647 if (sum > QCONST16(.995f,10))
Jean-Marc Valin4b087df2010-11-30 21:08:31 -0500648 trim_index-=4;
Gregory Maxwell60c316b2010-11-04 20:14:19 -0400649 else if (sum > QCONST16(.92f,10))
Jean-Marc Valin4b087df2010-11-30 21:08:31 -0500650 trim_index-=3;
651 else if (sum > QCONST16(.85f,10))
Jean-Marc Valinc5792de2010-10-19 14:24:50 -0400652 trim_index-=2;
Gregory Maxwell60c316b2010-11-04 20:14:19 -0400653 else if (sum > QCONST16(.8f,10))
Jean-Marc Valinc40addc2010-10-22 14:57:07 -0400654 trim_index-=1;
Jean-Marc Valinc5792de2010-10-19 14:24:50 -0400655 }
Jean-Marc Valin546dfa12010-12-10 17:18:17 -0500656
657 /* Estimate spectral tilt */
Gregory Maxwell9743bf32010-11-04 20:45:09 -0400658 c=0; do {
Jean-Marc Valinc5792de2010-10-19 14:24:50 -0400659 for (i=0;i<nbEBands-1;i++)
660 {
Jean-Marc Valin546dfa12010-12-10 17:18:17 -0500661 diff += bandLogE[i+c*nbEBands]*(celt_int32)(2+2*i-nbEBands);
Jean-Marc Valinc5792de2010-10-19 14:24:50 -0400662 }
Gregory Maxwell9743bf32010-11-04 20:45:09 -0400663 } while (++c<0);
Jean-Marc Valinc5792de2010-10-19 14:24:50 -0400664 diff /= C*(nbEBands-1);
665 /*printf("%f\n", diff);*/
Jean-Marc Valin546dfa12010-12-10 17:18:17 -0500666 if (diff > QCONST16(2.f, DB_SHIFT))
Jean-Marc Valinc5792de2010-10-19 14:24:50 -0400667 trim_index--;
Jean-Marc Valin546dfa12010-12-10 17:18:17 -0500668 if (diff > QCONST16(8.f, DB_SHIFT))
Jean-Marc Valinc5792de2010-10-19 14:24:50 -0400669 trim_index--;
Jean-Marc Valin546dfa12010-12-10 17:18:17 -0500670 if (diff < -QCONST16(4.f, DB_SHIFT))
Jean-Marc Valin90377572010-10-22 15:12:01 -0400671 trim_index++;
Jean-Marc Valin546dfa12010-12-10 17:18:17 -0500672 if (diff < -QCONST16(10.f, DB_SHIFT))
673 trim_index++;
674
Jean-Marc Valinc5792de2010-10-19 14:24:50 -0400675 if (trim_index<0)
676 trim_index = 0;
Jean-Marc Valin546dfa12010-12-10 17:18:17 -0500677 if (trim_index>10)
678 trim_index = 10;
Jean-Marc Valinc5792de2010-10-19 14:24:50 -0400679 return trim_index;
680}
681
Jean-Marc Valine65978f2010-12-02 13:46:48 -0500682static int stereo_analysis(const CELTMode *m, const celt_norm *X,
683 int nbEBands, int LM, int C, int N0)
684{
685 int i;
686 int thetas;
687 celt_word32 sumLR = EPSILON, sumMS = EPSILON;
688
689 /* Use the L1 norm to model the entropy of the L/R signal vs the M/S signal */
690 for (i=0;i<13;i++)
691 {
692 int j;
693 for (j=m->eBands[i]<<LM;j<m->eBands[i+1]<<LM;j++)
694 {
695 celt_word16 L, R, M, S;
696 L = X[j];
697 R = X[N0+j];
698 M = L+R;
699 S = L-R;
700 sumLR += EXTEND32(ABS16(L)) + EXTEND32(ABS16(R));
701 sumMS += EXTEND32(ABS16(M)) + EXTEND32(ABS16(S));
702 }
703 }
704 sumMS = MULT16_32_Q15(QCONST16(0.707107f, 15), sumMS);
705 thetas = 13;
706 /* We don't need thetas for lower bands with LM<=1 */
707 if (LM<=1)
708 thetas -= 8;
709 return MULT16_32_Q15((m->eBands[13]<<(LM+1))+thetas, sumMS)
710 > MULT16_32_Q15(m->eBands[13]<<(LM+1), sumLR);
711}
712
Gregory Maxwell5f2a74b2008-08-11 23:50:07 -0400713#ifdef FIXED_POINT
Jean-Marc Valin35095c62010-11-04 13:24:44 -0400714int 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 +1100715{
Gregory Maxwell5f2a74b2008-08-11 23:50:07 -0400716#else
Jean-Marc Valin35095c62010-11-04 13:24:44 -0400717int 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 -0400718{
719#endif
Jean-Marc Valin7a08ddd2010-10-18 14:55:42 -0400720 int i, c, N;
Jean-Marc Valinc890b582008-08-01 22:26:49 -0400721 int bits;
Jean-Marc Valin8679a802008-10-18 07:44:35 -0400722 ec_byte_buffer buf;
Jean-Marc Valin4794f2e2010-05-19 11:56:57 -0400723 ec_enc _enc;
Jean-Marc Valin234969c2009-10-17 22:12:42 -0400724 VARDECL(celt_sig, in);
725 VARDECL(celt_sig, freq);
Jean-Marc Valin234969c2009-10-17 22:12:42 -0400726 VARDECL(celt_norm, X);
727 VARDECL(celt_ener, bandE);
728 VARDECL(celt_word16, bandLogE);
Jean-Marc Valin6775de32008-08-02 08:14:42 -0400729 VARDECL(int, fine_quant);
Jean-Marc Valin234969c2009-10-17 22:12:42 -0400730 VARDECL(celt_word16, error);
Jean-Marc Valin6775de32008-08-02 08:14:42 -0400731 VARDECL(int, pulses);
732 VARDECL(int, offsets);
Jean-Marc Valin52cb5fb2009-06-10 08:08:55 -0400733 VARDECL(int, fine_priority);
Jean-Marc Valin163b76e2010-05-27 23:56:53 -0400734 VARDECL(int, tf_res);
Jean-Marc Valin0d8eaa32010-08-27 14:57:37 -0400735 celt_sig *_overlap_mem;
Jean-Marc Valin35095c62010-11-04 13:24:44 -0400736 celt_sig *prefilter_mem;
Jean-Marc Valin0d8eaa32010-08-27 14:57:37 -0400737 celt_word16 *oldBandE;
Jean-Marc Valin9d1decd2008-06-17 13:28:13 +1000738 int shortBlocks=0;
Jean-Marc Valin3b918ba2010-05-05 00:02:26 -0400739 int isTransient=0;
Jean-Marc Valinb8ba70c2010-04-18 22:10:24 -0400740 int resynth;
Jean-Marc Valin80ed1472009-10-15 21:45:32 -0400741 const int C = CHANNELS(st->channels);
Jean-Marc Valin017fa852010-05-06 22:11:48 -0400742 int LM, M;
Jean-Marc Valin890a9c02010-06-13 08:06:28 -0400743 int tf_select;
Jean-Marc Valin6b95d8f2010-06-21 21:39:44 -0400744 int nbFilledBytes, nbAvailableBytes;
Jean-Marc Valin85f41b22010-07-16 18:12:45 -0400745 int effEnd;
Jean-Marc Valinb801da52010-09-28 14:56:20 -0400746 int codedBands;
Jean-Marc Valinccd5a612010-10-13 01:11:55 -0400747 int tf_sum;
Jean-Marc Valinf1fea662010-10-09 22:58:52 -0400748 int alloc_trim;
Jean-Marc Valin6cbfbc32010-12-14 11:53:39 -0500749 int pitch_index=COMBFILTER_MINPERIOD;
Jean-Marc Valin35095c62010-11-04 13:24:44 -0400750 celt_word16 gain1 = 0;
Jean-Marc Valin4f177e82010-11-26 10:32:03 -0500751 int intensity=0;
Jean-Marc Valine65978f2010-12-02 13:46:48 -0500752 int dual_stereo=0;
Jean-Marc Valine5e9aa72010-12-02 16:09:51 -0500753 int effectiveBytes;
Jean-Marc Valin8600f692008-02-29 15:14:12 +1100754 SAVE_STACK;
Jean-Marc Valin44ffd5a2008-02-22 00:39:25 +1100755
Gregory Maxwell0719f6f2009-07-09 17:07:24 -0400756 if (nbCompressedBytes<0 || pcm==NULL)
Jean-Marc Valin017fa852010-05-06 22:11:48 -0400757 return CELT_BAD_ARG;
Gregory Maxwell520eeae2009-02-09 01:33:21 -0500758
Jean-Marc Valin017fa852010-05-06 22:11:48 -0400759 for (LM=0;LM<4;LM++)
760 if (st->mode->shortMdctSize<<LM==frame_size)
761 break;
762 if (LM>=MAX_CONFIG_SIZES)
763 return CELT_BAD_ARG;
764 M=1<<LM;
Jean-Marc Valin8679a802008-10-18 07:44:35 -0400765
Jean-Marc Valin35095c62010-11-04 13:24:44 -0400766 prefilter_mem = st->in_mem+C*(st->overlap);
767 _overlap_mem = prefilter_mem+C*COMBFILTER_MAXPERIOD;
768 /*_overlap_mem = st->in_mem+C*(st->overlap);*/
769 oldBandE = (celt_word16*)(st->in_mem+C*(2*st->overlap+COMBFILTER_MAXPERIOD));
Jean-Marc Valin0d8eaa32010-08-27 14:57:37 -0400770
Jean-Marc Valin4794f2e2010-05-19 11:56:57 -0400771 if (enc==NULL)
772 {
773 ec_byte_writeinit_buffer(&buf, compressed, nbCompressedBytes);
774 ec_enc_init(&_enc,&buf);
775 enc = &_enc;
Jean-Marc Valin6b95d8f2010-06-21 21:39:44 -0400776 nbFilledBytes=0;
777 } else {
Jean-Marc Valinbdcaaf72010-07-05 13:52:41 -0400778 nbFilledBytes=(ec_enc_tell(enc, 0)+4)>>3;
Jean-Marc Valin4794f2e2010-05-19 11:56:57 -0400779 }
Jean-Marc Valin6b95d8f2010-06-21 21:39:44 -0400780 nbAvailableBytes = nbCompressedBytes - nbFilledBytes;
781
Jean-Marc Valine5e9aa72010-12-02 16:09:51 -0500782 if (st->vbr_rate_norm>0)
783 effectiveBytes = st->vbr_rate_norm>>BITRES<<LM>>3;
784 else
785 effectiveBytes = nbCompressedBytes;
786
Jean-Marc Valin85f41b22010-07-16 18:12:45 -0400787 effEnd = st->end;
788 if (effEnd > st->mode->effEBands)
789 effEnd = st->mode->effEBands;
790
Jean-Marc Valin04752672010-05-05 07:21:21 -0400791 N = M*st->mode->shortMdctSize;
Jean-Marc Valin0695a5f2010-08-27 11:33:18 -0400792 ALLOC(in, C*(N+st->overlap), celt_sig);
Jean-Marc Valina5431bf2008-01-03 20:53:01 +1100793
Jean-Marc Valin35095c62010-11-04 13:24:44 -0400794 /* Find pitch period and gain */
Jean-Marc Valin6f7e83d2007-12-01 00:36:41 +1100795 {
Jean-Marc Valin35095c62010-11-04 13:24:44 -0400796 VARDECL(celt_sig, _pre);
797 celt_sig *pre[2];
798 SAVE_STACK;
799 c = 0;
800 ALLOC(_pre, C*(N+COMBFILTER_MAXPERIOD), celt_sig);
801
802 pre[0] = _pre;
803 pre[1] = _pre + (N+COMBFILTER_MAXPERIOD);
804
Gregory Maxwell9743bf32010-11-04 20:45:09 -0400805 c=0; do {
Jean-Marc Valin35095c62010-11-04 13:24:44 -0400806 const celt_word16 * restrict pcmp = pcm+c;
807 celt_sig * restrict inp = in+c*(N+st->overlap)+st->overlap;
808
809 for (i=0;i<N;i++)
810 {
811 /* Apply pre-emphasis */
812 celt_sig tmp = MULT16_16(st->mode->preemph[2], SCALEIN(*pcmp));
813 *inp = tmp + st->preemph_memE[c];
814 st->preemph_memE[c] = MULT16_32_Q15(st->mode->preemph[1], *inp)
815 - MULT16_32_Q15(st->mode->preemph[0], tmp);
816 inp++;
817 pcmp+=C;
818 }
819 CELT_COPY(pre[c], prefilter_mem+c*COMBFILTER_MAXPERIOD, COMBFILTER_MAXPERIOD);
820 CELT_COPY(pre[c]+COMBFILTER_MAXPERIOD, in+c*(N+st->overlap)+st->overlap, N);
Gregory Maxwell9743bf32010-11-04 20:45:09 -0400821 } while (++c<C);
Jean-Marc Valin35095c62010-11-04 13:24:44 -0400822
823#ifdef ENABLE_POSTFILTER
Jean-Marc Valincd84e3d2010-12-16 22:29:35 -0500824 if (nbAvailableBytes>12*C)
Jean-Marc Valin35095c62010-11-04 13:24:44 -0400825 {
826 VARDECL(celt_word16, pitch_buf);
827 ALLOC(pitch_buf, (COMBFILTER_MAXPERIOD+N)>>1, celt_word16);
828 celt_word32 tmp=0;
829 celt_word32 mem0[2]={0,0};
830 celt_word16 mem1[2]={0,0};
831
832 pitch_downsample(pre, pitch_buf, COMBFILTER_MAXPERIOD+N, COMBFILTER_MAXPERIOD+N,
833 C, mem0, mem1);
834 pitch_search(st->mode, pitch_buf+(COMBFILTER_MAXPERIOD>>1), pitch_buf, N,
835 COMBFILTER_MAXPERIOD-COMBFILTER_MINPERIOD, &pitch_index, &tmp, 1<<LM);
836 pitch_index = COMBFILTER_MAXPERIOD-pitch_index;
837
838 gain1 = remove_doubling(pitch_buf, COMBFILTER_MAXPERIOD, COMBFILTER_MINPERIOD,
839 N, &pitch_index, st->prefilter_period, st->prefilter_gain);
Jean-Marc Valin6cbfbc32010-12-14 11:53:39 -0500840 if (pitch_index > COMBFILTER_MAXPERIOD)
841 pitch_index = COMBFILTER_MAXPERIOD;
842 gain1 = MULT16_16_Q15(QCONST16(.7f,15),gain1);
843 if (gain1 > QCONST16(.6f,15))
844 gain1 = QCONST16(.6f,15);
845 if (ABS16(gain1-st->prefilter_gain)<QCONST16(.1,15))
846 gain1=st->prefilter_gain;
847 } else {
848 gain1 = 0;
Jean-Marc Valin35095c62010-11-04 13:24:44 -0400849 }
Jean-Marc Valin6cbfbc32010-12-14 11:53:39 -0500850 if (gain1<QCONST16(.2f,15) || (nbAvailableBytes<30 && gain1<QCONST16(.4f,15)))
Jean-Marc Valin35095c62010-11-04 13:24:44 -0400851 {
852 ec_enc_bit_prob(enc, 0, 32768);
853 gain1 = 0;
854 } else {
855 int qg;
856 int octave;
857#ifdef FIXED_POINT
858 qg = ((gain1+2048)>>12)-2;
859#else
860 qg = floor(.5+gain1*8)-2;
861#endif
862 ec_enc_bit_prob(enc, 1, 32768);
863 octave = EC_ILOG(pitch_index)-5;
864 ec_enc_uint(enc, octave, 6);
865 ec_enc_bits(enc, pitch_index-(16<<octave), 4+octave);
866 ec_enc_bits(enc, qg, 2);
867 gain1 = QCONST16(.125f,15)*(qg+2);
868 }
869 /*printf("%d %f\n", pitch_index, gain1);*/
870#else /* ENABLE_POSTFILTER */
871 ec_enc_bit_prob(enc, 0, 32768);
872#endif /* ENABLE_POSTFILTER */
873
Gregory Maxwell9743bf32010-11-04 20:45:09 -0400874 c=0; do {
Jean-Marc Valin70d30ff2010-12-13 13:50:29 -0500875 st->prefilter_period=IMAX(st->prefilter_period, COMBFILTER_MINPERIOD);
Jean-Marc Valin35095c62010-11-04 13:24:44 -0400876 CELT_COPY(in+c*(N+st->overlap), st->in_mem+c*(st->overlap), st->overlap);
877#ifdef ENABLE_POSTFILTER
878 comb_filter(in+c*(N+st->overlap)+st->overlap, pre[c]+COMBFILTER_MAXPERIOD,
879 st->prefilter_period, pitch_index, N, C, -st->prefilter_gain, -gain1, st->mode->window, st->mode->overlap);
880#endif /* ENABLE_POSTFILTER */
881 CELT_COPY(st->in_mem+c*(st->overlap), in+c*(N+st->overlap)+N, st->overlap);
882
883#ifdef ENABLE_POSTFILTER
884 if (N>COMBFILTER_MAXPERIOD)
885 {
886 CELT_MOVE(prefilter_mem+c*COMBFILTER_MAXPERIOD, pre[c]+N, COMBFILTER_MAXPERIOD);
887 } else {
888 CELT_MOVE(prefilter_mem+c*COMBFILTER_MAXPERIOD, prefilter_mem+c*COMBFILTER_MAXPERIOD+N, COMBFILTER_MAXPERIOD-N);
889 CELT_MOVE(prefilter_mem+c*COMBFILTER_MAXPERIOD+COMBFILTER_MAXPERIOD-N, pre[c]+COMBFILTER_MAXPERIOD, N);
890 }
891#endif /* ENABLE_POSTFILTER */
Gregory Maxwell9743bf32010-11-04 20:45:09 -0400892 } while (++c<C);
Jean-Marc Valin35095c62010-11-04 13:24:44 -0400893
894 RESTORE_STACK;
Jean-Marc Valin6f7e83d2007-12-01 00:36:41 +1100895 }
Jean-Marc Valin2014ca32009-06-18 23:33:04 -0400896
Jean-Marc Valin35095c62010-11-04 13:24:44 -0400897#ifdef RESYNTH
898 resynth = 1;
899#else
900 resynth = 0;
901#endif
Jean-Marc Valinb8ba70c2010-04-18 22:10:24 -0400902
Jean-Marc Valinf9fdbff2010-09-05 21:02:38 -0400903 if (st->complexity > 1 && LM>0)
Jean-Marc Valin1213ba52010-08-31 17:03:13 -0400904 {
905 isTransient = M > 1 &&
Jean-Marc Valin7a08ddd2010-10-18 14:55:42 -0400906 transient_analysis(in, N+st->overlap, C, &st->frame_max, st->overlap);
Jean-Marc Valin1213ba52010-08-31 17:03:13 -0400907 } else {
908 isTransient = 0;
909 }
Jean-Marc Valinc5f2a9d2008-10-26 22:00:26 -0400910
Jean-Marc Valin3b918ba2010-05-05 00:02:26 -0400911 if (isTransient)
912 shortBlocks = M;
913 else
914 shortBlocks = 0;
915
Jean-Marc Valin234969c2009-10-17 22:12:42 -0400916 ALLOC(freq, C*N, celt_sig); /**< Interleaved signal MDCTs */
917 ALLOC(bandE,st->mode->nbEBands*C, celt_ener);
918 ALLOC(bandLogE,st->mode->nbEBands*C, celt_word16);
Jean-Marc Valin32ec58c2009-05-01 21:28:58 -0400919 /* Compute MDCTs */
Jean-Marc Valin017fa852010-05-06 22:11:48 -0400920 compute_mdcts(st->mode, shortBlocks, in, freq, C, LM);
Jean-Marc Valin08a82ff2009-06-14 14:05:19 -0400921
Jean-Marc Valin234969c2009-10-17 22:12:42 -0400922 ALLOC(X, C*N, celt_norm); /**< Interleaved normalised MDCTs */
Jean-Marc Valin8d4ac152008-02-29 17:24:02 +1100923
Jean-Marc Valin85f41b22010-07-16 18:12:45 -0400924 compute_band_energies(st->mode, freq, bandE, effEnd, C, M);
Jean-Marc Valin504fb3c2010-08-06 15:56:22 -0400925
926 amp2Log2(st->mode, effEnd, st->end, bandE, bandLogE, C);
Jean-Marc Valinbd5d54a2009-10-20 00:25:31 -0400927
Jean-Marc Valin8ebd3452007-11-29 20:17:32 +1100928 /* Band normalisation */
Jean-Marc Valin85f41b22010-07-16 18:12:45 -0400929 normalise_bands(st->mode, freq, X, bandE, effEnd, C, M);
Jean-Marc Valin4c77ea92009-09-14 22:50:41 -0400930
Jean-Marc Valin8200b2d2010-10-15 02:18:47 -0400931 ALLOC(tf_res, st->mode->nbEBands, int);
932 /* Needs to be before coarse energy quantization because otherwise the energy gets modified */
Jean-Marc Valine5e9aa72010-12-02 16:09:51 -0500933 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 -0400934 for (i=effEnd;i<st->end;i++)
935 tf_res[i] = tf_res[effEnd-1];
936
Jean-Marc Valin9099bc32010-08-07 21:50:01 -0400937 ALLOC(error, C*st->mode->nbEBands, celt_word16);
Jean-Marc Valin5e7f02d2010-08-08 09:48:22 -0400938 quant_coarse_energy(st->mode, st->start, st->end, effEnd, bandLogE,
Timothy B. Terriberryef2e6502010-11-09 01:43:18 -0800939 oldBandE, nbCompressedBytes*8, error, enc,
940 C, LM, nbAvailableBytes, st->force_intra,
Jean-Marc Valin1b36d6c2010-08-31 17:21:52 -0400941 &st->delayedIntra, st->complexity >= 4);
Jean-Marc Valin9099bc32010-08-07 21:50:01 -0400942
Jean-Marc Valinf9fdbff2010-09-05 21:02:38 -0400943 if (LM > 0)
944 ec_enc_bit_prob(enc, shortBlocks!=0, 8192);
Jean-Marc Valin4c77ea92009-09-14 22:50:41 -0400945
Jean-Marc Valine5e9aa72010-12-02 16:09:51 -0500946 tf_encode(st->start, st->end, isTransient, tf_res, LM, tf_select, enc);
Jean-Marc Valinbe04f5a2010-08-07 21:42:03 -0400947
Jean-Marc Valin5c803912010-12-16 14:11:48 -0500948 if (shortBlocks || st->complexity < 3 || nbAvailableBytes < 10*C)
Jean-Marc Valin1d17b9a2010-08-31 14:51:58 -0400949 {
Jean-Marc Valin1213ba52010-08-31 17:03:13 -0400950 if (st->complexity == 0)
951 {
Timothy B. Terriberry320cf2e2010-12-17 05:52:06 -0800952 st->spread_decision = SPREAD_NONE;
Jean-Marc Valin1213ba52010-08-31 17:03:13 -0400953 } else {
Timothy B. Terriberry320cf2e2010-12-17 05:52:06 -0800954 st->spread_decision = SPREAD_NORMAL;
Jean-Marc Valin1213ba52010-08-31 17:03:13 -0400955 }
Jean-Marc Valin1d17b9a2010-08-31 14:51:58 -0400956 } else {
Timothy B. Terriberry320cf2e2010-12-17 05:52:06 -0800957 st->spread_decision = spreading_decision(st->mode, X, &st->tonal_average, st->spread_decision, effEnd, C, M);
Jean-Marc Valin1d17b9a2010-08-31 14:51:58 -0400958 }
Timothy B. Terriberry320cf2e2010-12-17 05:52:06 -0800959 /* Probs: NONE: 21.875%, LIGHT: 6.25%, NORMAL: 65.625%, AGGRESSIVE: 6.25% */
960 ec_enc_bit_prob(enc, st->spread_decision>>1, 18432);
961 ec_enc_bit_prob(enc, st->spread_decision&1,
962 (st->spread_decision>>1) ? 5699 : 14564);
Jean-Marc Valin9099bc32010-08-07 21:50:01 -0400963
Jean-Marc Valinf1fea662010-10-09 22:58:52 -0400964 ALLOC(offsets, st->mode->nbEBands, int);
965
966 for (i=0;i<st->mode->nbEBands;i++)
967 offsets[i] = 0;
968 /* Dynamic allocation code */
969 /* Make sure that dynamic allocation can't make us bust the budget */
Jean-Marc Valine5e9aa72010-12-02 16:09:51 -0500970 if (effectiveBytes > 50 && LM>=1)
Jean-Marc Valinf1fea662010-10-09 22:58:52 -0400971 {
972 int t1, t2;
973 if (LM <= 1)
974 {
975 t1 = 3;
976 t2 = 5;
977 } else {
978 t1 = 2;
979 t2 = 4;
980 }
981 for (i=1;i<st->mode->nbEBands-1;i++)
982 {
Jean-Marc Valina3a066c2010-11-04 15:15:54 -0400983 celt_word32 d2;
984 d2 = 2*bandLogE[i]-bandLogE[i-1]-bandLogE[i+1];
985 if (C==2)
986 d2 = HALF32(d2 + 2*bandLogE[i+st->mode->nbEBands]-
987 bandLogE[i-1+st->mode->nbEBands]-bandLogE[i+1+st->mode->nbEBands]);
988 if (d2 > SHL16(t1,DB_SHIFT))
Jean-Marc Valinf1fea662010-10-09 22:58:52 -0400989 offsets[i] += 1;
Jean-Marc Valina3a066c2010-11-04 15:15:54 -0400990 if (d2 > SHL16(t2,DB_SHIFT))
Jean-Marc Valinf1fea662010-10-09 22:58:52 -0400991 offsets[i] += 1;
992 }
993 }
994 for (i=0;i<st->mode->nbEBands;i++)
995 {
996 int j;
997 ec_enc_bit_prob(enc, offsets[i]!=0, 1024);
998 if (offsets[i]!=0)
999 {
1000 for (j=0;j<offsets[i]-1;j++)
1001 ec_enc_bit_prob(enc, 1, 32768);
1002 ec_enc_bit_prob(enc, 0, 32768);
1003 }
1004 offsets[i] *= (6<<BITRES);
1005 }
Jean-Marc Valinc40addc2010-10-22 14:57:07 -04001006 alloc_trim = alloc_trim_analysis(st->mode, X, bandLogE, st->mode->nbEBands, LM, C, N);
1007 ec_encode_bin(enc, trim_cdf[alloc_trim], trim_cdf[alloc_trim+1], 7);
Jean-Marc Valinf1fea662010-10-09 22:58:52 -04001008
Gregory Maxwell888d8ce2009-05-21 04:21:53 -04001009 /* Variable bitrate */
Jean-Marc Valinbe04f5a2010-08-07 21:42:03 -04001010 if (st->vbr_rate_norm>0)
Gregory Maxwell888d8ce2009-05-21 04:21:53 -04001011 {
Jean-Marc Valinbd5d54a2009-10-20 00:25:31 -04001012 celt_word16 alpha;
Jean-Marc Valina4badac2010-12-03 15:20:11 -05001013 celt_int32 delta, tell;
Gregory Maxwella9411472010-10-28 03:52:21 -04001014 /* The target rate in 8th bits per frame */
Jean-Marc Valinbe04f5a2010-08-07 21:42:03 -04001015 celt_int32 vbr_rate;
1016 celt_int32 target;
Jean-Marc Valina4badac2010-12-03 15:20:11 -05001017 celt_int32 vbr_bound, max_allowed, min_allowed;
Jean-Marc Valinbe04f5a2010-08-07 21:42:03 -04001018
Gregory Maxwellfac6c982010-10-28 15:00:37 -04001019 target = vbr_rate = M*st->vbr_rate_norm;
Jean-Marc Valinbe04f5a2010-08-07 21:42:03 -04001020
Jean-Marc Valin30165bb2010-12-03 14:35:59 -05001021 target = target + st->vbr_offset - ((40*C+20)<<BITRES);
1022
Gregory Maxwellfac6c982010-10-28 15:00:37 -04001023 /* Shortblocks get a large boost in bitrate, but since they
Jean-Marc Valinccd5a612010-10-13 01:11:55 -04001024 are uncommon long blocks are not greatly affected */
1025 if (shortBlocks || tf_sum < -2*(st->end-st->start))
Jean-Marc Valin30165bb2010-12-03 14:35:59 -05001026 target = 7*target/4;
Jean-Marc Valinccd5a612010-10-13 01:11:55 -04001027 else if (tf_sum < -(st->end-st->start))
1028 target = 3*target/2;
Jean-Marc Valin3b918ba2010-05-05 00:02:26 -04001029 else if (M > 1)
Jean-Marc Valinccd5a612010-10-13 01:11:55 -04001030 target-=(target+14)/28;
Gregory Maxwell888d8ce2009-05-21 04:21:53 -04001031
Jean-Marc Valina4badac2010-12-03 15:20:11 -05001032 tell = ec_enc_tell(enc, BITRES);
1033
Gregory Maxwella9411472010-10-28 03:52:21 -04001034 /* The current offset is removed from the target and the space used
1035 so far is added*/
Jean-Marc Valina4badac2010-12-03 15:20:11 -05001036 target=target+tell;
Jean-Marc Valin30165bb2010-12-03 14:35:59 -05001037 /* By how much did we "miss" the target on that frame */
1038 delta = target - vbr_rate;
Gregory Maxwell888d8ce2009-05-21 04:21:53 -04001039
Gregory Maxwellfac6c982010-10-28 15:00:37 -04001040 /* Computes the max bit-rate allowed in VBR more to avoid violating the target rate and buffering */
1041 vbr_bound = vbr_rate;
Jean-Marc Valin9faf7402010-12-04 10:27:22 -05001042 if (st->constrained_vbr)
1043 max_allowed = IMIN(vbr_rate+vbr_bound-st->vbr_reservoir>>(BITRES+3),nbAvailableBytes);
1044 else
1045 max_allowed = nbAvailableBytes;
Jean-Marc Valina4badac2010-12-03 15:20:11 -05001046 min_allowed = (tell>>(BITRES+3)) + 2 - nbFilledBytes;
Gregory Maxwellfac6c982010-10-28 15:00:37 -04001047
1048 /* In VBR mode the frame size must not be reduced so much that it would result in the encoder running out of bits */
1049 nbAvailableBytes = target+(1<<(BITRES+2))>>(BITRES+3);
Jean-Marc Valina4badac2010-12-03 15:20:11 -05001050 nbAvailableBytes=IMAX(min_allowed,IMIN(max_allowed,nbAvailableBytes));
Gregory Maxwellfac6c982010-10-28 15:00:37 -04001051 target=nbAvailableBytes<<(BITRES+3);
1052
Gregory Maxwella9411472010-10-28 03:52:21 -04001053 if (st->vbr_count < 970)
Jean-Marc Valinbd5d54a2009-10-20 00:25:31 -04001054 {
1055 st->vbr_count++;
Gregory Maxwella9411472010-10-28 03:52:21 -04001056 alpha = celt_rcp(SHL32(EXTEND32(st->vbr_count+20),16));
Jean-Marc Valinbd5d54a2009-10-20 00:25:31 -04001057 } else
1058 alpha = QCONST16(.001f,15);
Jean-Marc Valinbd5d54a2009-10-20 00:25:31 -04001059 /* How many bits have we used in excess of what we're allowed */
Jean-Marc Valin9faf7402010-12-04 10:27:22 -05001060 if (st->constrained_vbr)
1061 st->vbr_reservoir += target - vbr_rate;
Jean-Marc Valinbd5d54a2009-10-20 00:25:31 -04001062 /*printf ("%d\n", st->vbr_reservoir);*/
1063
1064 /* Compute the offset we need to apply in order to reach the target */
Jean-Marc Valin736efd62010-08-31 11:52:45 -04001065 st->vbr_drift += (celt_int32)MULT16_32_Q15(alpha,delta-st->vbr_offset-st->vbr_drift);
Jean-Marc Valinbd5d54a2009-10-20 00:25:31 -04001066 st->vbr_offset = -st->vbr_drift;
1067 /*printf ("%d\n", st->vbr_drift);*/
1068
1069 /* We could use any multiple of vbr_rate as bound (depending on the delay) */
Jean-Marc Valin9faf7402010-12-04 10:27:22 -05001070 if (st->constrained_vbr && st->vbr_reservoir < 0)
Jean-Marc Valinbd5d54a2009-10-20 00:25:31 -04001071 {
1072 /* We're under the min value -- increase rate */
Gregory Maxwellfac6c982010-10-28 15:00:37 -04001073 int adjust = (-st->vbr_reservoir)/(8<<BITRES);
1074 nbAvailableBytes += adjust;
1075 st->vbr_reservoir = 0;
Jean-Marc Valinbd5d54a2009-10-20 00:25:31 -04001076 /*printf ("+%d\n", adjust);*/
1077 }
Gregory Maxwellfac6c982010-10-28 15:00:37 -04001078 nbCompressedBytes = IMIN(nbCompressedBytes,nbAvailableBytes+nbFilledBytes);
Jean-Marc Valin6b95d8f2010-06-21 21:39:44 -04001079
Jean-Marc Valinbd5d54a2009-10-20 00:25:31 -04001080 /* This moves the raw bits to take into account the new compressed size */
Jean-Marc Valine6108642009-08-01 23:05:47 +02001081 ec_byte_shrink(&buf, nbCompressedBytes);
Gregory Maxwell888d8ce2009-05-21 04:21:53 -04001082 }
1083
Jean-Marc Valin4f177e82010-11-26 10:32:03 -05001084 if (C==2)
1085 {
Jean-Marc Valincd84e3d2010-12-16 22:29:35 -05001086 /* Always use MS for 2.5 ms frames until we can do a better analysis */
1087 if (LM==0)
1088 dual_stereo = 0;
1089 else
1090 dual_stereo = stereo_analysis(st->mode, X, st->mode->nbEBands, LM, C, N);
Jean-Marc Valine65978f2010-12-02 13:46:48 -05001091 ec_enc_bit_prob(enc, dual_stereo, 32768);
1092 }
1093 if (C==2)
1094 {
Jean-Marc Valin4f177e82010-11-26 10:32:03 -05001095 int effectiveRate;
1096
Jean-Marc Valin4f177e82010-11-26 10:32:03 -05001097 /* Account for coarse energy */
Jean-Marc Valine5e9aa72010-12-02 16:09:51 -05001098 effectiveRate = (8*effectiveBytes - 80)>>LM;
1099
Jean-Marc Valin4f177e82010-11-26 10:32:03 -05001100 /* effectiveRate in kb/s */
1101 effectiveRate = 2*effectiveRate/5;
1102 if (effectiveRate<35)
Jean-Marc Valin6cbfbc32010-12-14 11:53:39 -05001103 intensity = 8;
Jean-Marc Valin4f177e82010-11-26 10:32:03 -05001104 else if (effectiveRate<50)
1105 intensity = 12;
1106 else if (effectiveRate<68)
1107 intensity = 16;
1108 else if (effectiveRate<84)
1109 intensity = 18;
1110 else if (effectiveRate<102)
1111 intensity = 19;
1112 else if (effectiveRate<130)
1113 intensity = 20;
1114 else
1115 intensity = 100;
1116 intensity = IMIN(st->end,IMAX(st->start, intensity));
1117 ec_enc_uint(enc, intensity, 1+st->end-st->start);
1118 }
1119
Jean-Marc Valinbe04f5a2010-08-07 21:42:03 -04001120 /* Bit allocation */
1121 ALLOC(fine_quant, st->mode->nbEBands, int);
1122 ALLOC(pulses, st->mode->nbEBands, int);
Jean-Marc Valin52cb5fb2009-06-10 08:08:55 -04001123 ALLOC(fine_priority, st->mode->nbEBands, int);
Jean-Marc Valincb7a2a32008-02-11 16:44:48 +11001124
Timothy B. Terriberry76ea41e2010-12-16 14:39:58 -08001125 /* bits = packet size - where we are - safety */
1126 bits = (nbCompressedBytes*8<<BITRES) - ec_enc_tell(enc, BITRES) - 1;
Jean-Marc Valindfd6e712010-12-09 23:23:34 -05001127 codedBands = compute_allocation(st->mode, st->start, st->end, offsets,
Timothy B. Terriberryb2f59002010-12-15 05:12:43 -08001128 alloc_trim, bits, pulses, fine_quant, fine_priority, C, LM, enc, 1, st->lastCodedBands);
Jean-Marc Valindfd6e712010-12-09 23:23:34 -05001129 st->lastCodedBands = codedBands;
Jean-Marc Valin37ab9c62008-11-08 09:14:38 -05001130
Jean-Marc Valin0d8eaa32010-08-27 14:57:37 -04001131 quant_fine_energy(st->mode, st->start, st->end, bandE, oldBandE, error, fine_quant, enc, C);
Jean-Marc Valin6775de32008-08-02 08:14:42 -04001132
Jean-Marc Valin7b5a0862010-07-29 15:01:24 +02001133#ifdef MEASURE_NORM_MSE
Jean-Marc Valin44092242010-07-29 18:32:54 +02001134 float X0[3000];
1135 float bandE0[60];
Gregory Maxwell9743bf32010-11-04 20:45:09 -04001136 c=0; do
Jean-Marc Valin44092242010-07-29 18:32:54 +02001137 for (i=0;i<N;i++)
1138 X0[i+c*N] = X[i+c*N];
Gregory Maxwell9743bf32010-11-04 20:45:09 -04001139 while (++c<C);
Jean-Marc Valin44092242010-07-29 18:32:54 +02001140 for (i=0;i<C*st->mode->nbEBands;i++)
Jean-Marc Valin7b5a0862010-07-29 15:01:24 +02001141 bandE0[i] = bandE[i];
1142#endif
1143
Jean-Marc Valin8ebd3452007-11-29 20:17:32 +11001144 /* Residual quantisation */
Jean-Marc Valin4f177e82010-11-26 10:32:03 -05001145 quant_all_bands(1, st->mode, st->start, st->end, X, C==2 ? X+N : NULL,
Timothy B. Terriberry320cf2e2010-12-17 05:52:06 -08001146 bandE, pulses, shortBlocks, st->spread_decision, dual_stereo, intensity, tf_res, resynth,
Jean-Marc Valin4f177e82010-11-26 10:32:03 -05001147 nbCompressedBytes*8, enc, LM, codedBands);
Jean-Marc Valin39710532009-06-09 00:10:32 -04001148
Jean-Marc Valin0d8eaa32010-08-27 14:57:37 -04001149 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 -04001150
Jean-Marc Valin35095c62010-11-04 13:24:44 -04001151#ifdef RESYNTH
Jean-Marc Valin37ab9c62008-11-08 09:14:38 -05001152 /* Re-synthesis of the coded audio if required */
Jean-Marc Valinb8ba70c2010-04-18 22:10:24 -04001153 if (resynth)
Jean-Marc Valin18ddc022008-02-22 14:24:50 +11001154 {
Jean-Marc Valine0ce2cf2010-08-26 23:58:08 -04001155 celt_sig *out_mem[2];
Jean-Marc Valin0d8eaa32010-08-27 14:57:37 -04001156 celt_sig *overlap_mem[2];
Jean-Marc Valine0ce2cf2010-08-26 23:58:08 -04001157
Jean-Marc Valin0d8eaa32010-08-27 14:57:37 -04001158 log2Amp(st->mode, st->start, st->end, bandE, oldBandE, C);
Jean-Marc Valinbc272de2010-08-02 09:41:31 -04001159
1160#ifdef MEASURE_NORM_MSE
1161 measure_norm_mse(st->mode, X, X0, bandE, bandE0, M, N, C);
1162#endif
1163
Jean-Marc Valin88619552009-10-04 21:35:36 -04001164 /* Synthesis */
Jean-Marc Valin85f41b22010-07-16 18:12:45 -04001165 denormalise_bands(st->mode, X, freq, bandE, effEnd, C, M);
Jean-Marc Valin88619552009-10-04 21:35:36 -04001166
Jean-Marc Valin35095c62010-11-04 13:24:44 -04001167 CELT_MOVE(st->syn_mem[0], st->syn_mem[0]+N, MAX_PERIOD);
1168 if (C==2)
1169 CELT_MOVE(st->syn_mem[1], st->syn_mem[1]+N, MAX_PERIOD);
1170
Gregory Maxwell9743bf32010-11-04 20:45:09 -04001171 c=0; do
Jean-Marc Valin3b0df0d2010-07-16 15:55:30 -04001172 for (i=0;i<M*st->mode->eBands[st->start];i++)
1173 freq[c*N+i] = 0;
Gregory Maxwell9743bf32010-11-04 20:45:09 -04001174 while (++c<C);
1175 c=0; do
Jean-Marc Valin3b0df0d2010-07-16 15:55:30 -04001176 for (i=M*st->mode->eBands[st->end];i<N;i++)
1177 freq[c*N+i] = 0;
Gregory Maxwell9743bf32010-11-04 20:45:09 -04001178 while (++c<C);
Jean-Marc Valin3b0df0d2010-07-16 15:55:30 -04001179
Jean-Marc Valin35095c62010-11-04 13:24:44 -04001180 out_mem[0] = st->syn_mem[0]+MAX_PERIOD;
1181 if (C==2)
1182 out_mem[1] = st->syn_mem[1]+MAX_PERIOD;
Jean-Marc Valin0d8eaa32010-08-27 14:57:37 -04001183
Gregory Maxwell9743bf32010-11-04 20:45:09 -04001184 c=0; do
Jean-Marc Valin0d8eaa32010-08-27 14:57:37 -04001185 overlap_mem[c] = _overlap_mem + c*st->overlap;
Gregory Maxwell9743bf32010-11-04 20:45:09 -04001186 while (++c<C);
Jean-Marc Valine0ce2cf2010-08-26 23:58:08 -04001187
Jean-Marc Valin7a08ddd2010-10-18 14:55:42 -04001188 compute_inv_mdcts(st->mode, shortBlocks, freq, out_mem, overlap_mem, C, LM);
Jean-Marc Valine12017e2009-10-03 13:57:31 -04001189
Jean-Marc Valin35095c62010-11-04 13:24:44 -04001190#ifdef ENABLE_POSTFILTER
Gregory Maxwell9743bf32010-11-04 20:45:09 -04001191 c=0; do {
Jean-Marc Valin70d30ff2010-12-13 13:50:29 -05001192 st->prefilter_period=IMAX(st->prefilter_period, COMBFILTER_MINPERIOD);
1193 st->prefilter_period_old=IMAX(st->prefilter_period_old, COMBFILTER_MINPERIOD);
1194 if (LM!=0)
1195 {
1196 comb_filter(out_mem[c], out_mem[c], st->prefilter_period, st->prefilter_period, st->overlap, C,
1197 st->prefilter_gain, st->prefilter_gain, NULL, 0);
1198 comb_filter(out_mem[c]+st->overlap, out_mem[c]+st->overlap, st->prefilter_period, pitch_index, N-st->overlap, C,
1199 st->prefilter_gain, gain1, st->mode->window, st->mode->overlap);
1200 } else {
1201 comb_filter(out_mem[c], out_mem[c], st->prefilter_period_old, st->prefilter_period, N, C,
1202 st->prefilter_gain_old, st->prefilter_gain, st->mode->window, st->mode->overlap);
1203 }
Gregory Maxwell9743bf32010-11-04 20:45:09 -04001204 } while (++c<C);
Jean-Marc Valin35095c62010-11-04 13:24:44 -04001205#endif /* ENABLE_POSTFILTER */
1206
1207 deemphasis(out_mem, (celt_word16*)pcm, N, C, st->mode->preemph, st->preemph_memD);
Jean-Marc Valin70d30ff2010-12-13 13:50:29 -05001208 st->prefilter_period_old = st->prefilter_period;
1209 st->prefilter_gain_old = st->prefilter_gain;
Jean-Marc Valind9b95652008-08-31 23:34:47 -04001210 }
Jean-Marc Valin35095c62010-11-04 13:24:44 -04001211#endif
1212
1213 st->prefilter_period = pitch_index;
1214 st->prefilter_gain = gain1;
Gregory Maxwell54547f12009-02-16 18:56:44 -05001215
Jean-Marc Valin30d51252010-06-21 17:55:28 -04001216 /* If there's any room left (can only happen for very high rates),
1217 fill it with zeros */
Jean-Marc Valin5d774e02010-08-04 17:17:18 -04001218 while (ec_enc_tell(enc,0) + 8 <= nbCompressedBytes*8)
Jean-Marc Valin30d51252010-06-21 17:55:28 -04001219 ec_enc_bits(enc, 0, 8);
Jean-Marc Valin4794f2e2010-05-19 11:56:57 -04001220 ec_enc_done(enc);
Jean-Marc Valinc871c8d2009-06-09 00:57:00 -04001221
Jean-Marc Valin8600f692008-02-29 15:14:12 +11001222 RESTORE_STACK;
Jean-Marc Valinb1e017f2010-07-18 21:20:35 -04001223 if (ec_enc_get_error(enc))
Jean-Marc Valin9d785af2010-07-18 09:42:05 -04001224 return CELT_CORRUPTED_DATA;
1225 else
1226 return nbCompressedBytes;
Jean-Marc Valin8ebd3452007-11-29 20:17:32 +11001227}
1228
Gregory Maxwell5f2a74b2008-08-11 23:50:07 -04001229#ifdef FIXED_POINT
1230#ifndef DISABLE_FLOAT_API
Jean-Marc Valin35095c62010-11-04 13:24:44 -04001231int 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 -04001232{
Jean-Marc Valin017fa852010-05-06 22:11:48 -04001233 int j, ret, C, N, LM, M;
Jean-Marc Valin30f7f812009-10-17 14:35:13 -04001234 VARDECL(celt_int16, in);
Jean-Marc Valincb8780c2009-07-20 23:40:35 -04001235 SAVE_STACK;
Gregory Maxwell17169992009-06-04 15:15:34 -04001236
Gregory Maxwell0719f6f2009-07-09 17:07:24 -04001237 if (pcm==NULL)
1238 return CELT_BAD_ARG;
1239
Jean-Marc Valin017fa852010-05-06 22:11:48 -04001240 for (LM=0;LM<4;LM++)
1241 if (st->mode->shortMdctSize<<LM==frame_size)
1242 break;
1243 if (LM>=MAX_CONFIG_SIZES)
1244 return CELT_BAD_ARG;
1245 M=1<<LM;
1246
Jean-Marc Valin80ed1472009-10-15 21:45:32 -04001247 C = CHANNELS(st->channels);
Jean-Marc Valin017fa852010-05-06 22:11:48 -04001248 N = M*st->mode->shortMdctSize;
Jean-Marc Valin30f7f812009-10-17 14:35:13 -04001249 ALLOC(in, C*N, celt_int16);
Gregory Maxwell5f2a74b2008-08-11 23:50:07 -04001250
1251 for (j=0;j<C*N;j++)
1252 in[j] = FLOAT2INT16(pcm[j]);
1253
Jean-Marc Valin35095c62010-11-04 13:24:44 -04001254 ret=celt_encode_with_ec(st,in,frame_size,compressed,nbCompressedBytes, enc);
1255#ifdef RESYNTH
1256 for (j=0;j<C*N;j++)
1257 ((float*)pcm)[j]=in[j]*(1.f/32768.f);
1258#endif
Wessel Lubberhuizen33ba6cc2008-10-03 07:09:29 -04001259 RESTORE_STACK;
Gregory Maxwell5f2a74b2008-08-11 23:50:07 -04001260 return ret;
1261
1262}
1263#endif /*DISABLE_FLOAT_API*/
1264#else
Jean-Marc Valin35095c62010-11-04 13:24:44 -04001265int 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 -04001266{
Jean-Marc Valin017fa852010-05-06 22:11:48 -04001267 int j, ret, C, N, LM, M;
Jean-Marc Valin234969c2009-10-17 22:12:42 -04001268 VARDECL(celt_sig, in);
Jean-Marc Valincb8780c2009-07-20 23:40:35 -04001269 SAVE_STACK;
Gregory Maxwell17169992009-06-04 15:15:34 -04001270
Gregory Maxwell0719f6f2009-07-09 17:07:24 -04001271 if (pcm==NULL)
1272 return CELT_BAD_ARG;
1273
Jean-Marc Valin017fa852010-05-06 22:11:48 -04001274 for (LM=0;LM<4;LM++)
1275 if (st->mode->shortMdctSize<<LM==frame_size)
1276 break;
1277 if (LM>=MAX_CONFIG_SIZES)
1278 return CELT_BAD_ARG;
1279 M=1<<LM;
1280
Jean-Marc Valin80ed1472009-10-15 21:45:32 -04001281 C=CHANNELS(st->channels);
Jean-Marc Valin04752672010-05-05 07:21:21 -04001282 N=M*st->mode->shortMdctSize;
Jean-Marc Valin234969c2009-10-17 22:12:42 -04001283 ALLOC(in, C*N, celt_sig);
Gregory Maxwell5f2a74b2008-08-11 23:50:07 -04001284 for (j=0;j<C*N;j++) {
1285 in[j] = SCALEOUT(pcm[j]);
1286 }
Gregory Maxwell5f2a74b2008-08-11 23:50:07 -04001287
Jean-Marc Valin35095c62010-11-04 13:24:44 -04001288 ret = celt_encode_with_ec_float(st,in,frame_size,compressed,nbCompressedBytes, enc);
1289#ifdef RESYNTH
1290 for (j=0;j<C*N;j++)
1291 ((celt_int16*)pcm)[j] = FLOAT2INT16(in[j]);
1292#endif
Wessel Lubberhuizen33ba6cc2008-10-03 07:09:29 -04001293 RESTORE_STACK;
Gregory Maxwell5f2a74b2008-08-11 23:50:07 -04001294 return ret;
1295}
1296#endif
Jean-Marc Valin6e9058a2007-12-07 14:59:06 +11001297
Jean-Marc Valind56c6102010-05-07 20:30:22 -04001298int celt_encode(CELTEncoder * restrict st, const celt_int16 * pcm, int frame_size, unsigned char *compressed, int nbCompressedBytes)
1299{
Jean-Marc Valin35095c62010-11-04 13:24:44 -04001300 return celt_encode_with_ec(st, pcm, frame_size, compressed, nbCompressedBytes, NULL);
Jean-Marc Valind56c6102010-05-07 20:30:22 -04001301}
1302
Jean-Marc Valin4424b5a2010-07-06 19:37:23 -04001303#ifndef DISABLE_FLOAT_API
Jean-Marc Valind56c6102010-05-07 20:30:22 -04001304int celt_encode_float(CELTEncoder * restrict st, const float * pcm, int frame_size, unsigned char *compressed, int nbCompressedBytes)
1305{
Jean-Marc Valin35095c62010-11-04 13:24:44 -04001306 return celt_encode_with_ec_float(st, pcm, frame_size, compressed, nbCompressedBytes, NULL);
Jean-Marc Valind56c6102010-05-07 20:30:22 -04001307}
Jean-Marc Valin4424b5a2010-07-06 19:37:23 -04001308#endif /* DISABLE_FLOAT_API */
Jean-Marc Valind56c6102010-05-07 20:30:22 -04001309
Jean-Marc Valinb6f90612008-10-05 22:39:13 -04001310int celt_encoder_ctl(CELTEncoder * restrict st, int request, ...)
Jean-Marc Valinc18fb1d2008-09-30 07:36:54 -04001311{
Jean-Marc Valinb6f90612008-10-05 22:39:13 -04001312 va_list ap;
Gregory Maxwell17169992009-06-04 15:15:34 -04001313
Jean-Marc Valinb6f90612008-10-05 22:39:13 -04001314 va_start(ap, request);
Jean-Marc Valinc18fb1d2008-09-30 07:36:54 -04001315 switch (request)
1316 {
Gregory Maxwellf3b44ef2009-06-03 13:37:45 -04001317 case CELT_GET_MODE_REQUEST:
1318 {
1319 const CELTMode ** value = va_arg(ap, const CELTMode**);
1320 if (value==0)
1321 goto bad_arg;
1322 *value=st->mode;
1323 }
1324 break;
Jean-Marc Valinb6f90612008-10-05 22:39:13 -04001325 case CELT_SET_COMPLEXITY_REQUEST:
Jean-Marc Valinc18fb1d2008-09-30 07:36:54 -04001326 {
Jean-Marc Valin30f7f812009-10-17 14:35:13 -04001327 int value = va_arg(ap, celt_int32);
Jean-Marc Valinb6f90612008-10-05 22:39:13 -04001328 if (value<0 || value>10)
1329 goto bad_arg;
Jean-Marc Valin1213ba52010-08-31 17:03:13 -04001330 st->complexity = value;
Gregory Maxwell98046ca2008-12-13 20:42:03 -05001331 }
1332 break;
Jean-Marc Valin5f961462010-05-19 13:38:10 -04001333 case CELT_SET_START_BAND_REQUEST:
1334 {
1335 celt_int32 value = va_arg(ap, celt_int32);
1336 if (value<0 || value>=st->mode->nbEBands)
1337 goto bad_arg;
1338 st->start = value;
1339 }
1340 break;
Jean-Marc Valin525d7cf2010-07-13 14:14:16 -04001341 case CELT_SET_END_BAND_REQUEST:
1342 {
1343 celt_int32 value = va_arg(ap, celt_int32);
1344 if (value<0 || value>=st->mode->nbEBands)
1345 goto bad_arg;
1346 st->end = value;
1347 }
1348 break;
Gregory Maxwell2dd3d322009-06-05 14:05:51 -04001349 case CELT_SET_PREDICTION_REQUEST:
Gregory Maxwell98046ca2008-12-13 20:42:03 -05001350 {
Jean-Marc Valin30f7f812009-10-17 14:35:13 -04001351 int value = va_arg(ap, celt_int32);
Gregory Maxwell2dd3d322009-06-05 14:05:51 -04001352 if (value<0 || value>2)
Gregory Maxwell98046ca2008-12-13 20:42:03 -05001353 goto bad_arg;
1354 if (value==0)
Gregory Maxwell2dd3d322009-06-05 14:05:51 -04001355 {
1356 st->force_intra = 1;
Gregory Maxwella80958b2009-06-29 12:48:57 -04001357 } else if (value==1) {
Gregory Maxwell2dd3d322009-06-05 14:05:51 -04001358 st->force_intra = 0;
Gregory Maxwell2dd3d322009-06-05 14:05:51 -04001359 } else {
1360 st->force_intra = 0;
Gregory Maxwell2dd3d322009-06-05 14:05:51 -04001361 }
Jean-Marc Valinc18fb1d2008-09-30 07:36:54 -04001362 }
1363 break;
Jean-Marc Valin79b34eb2010-12-05 17:22:06 -05001364 case CELT_SET_VBR_CONSTRAINT_REQUEST:
1365 {
1366 celt_int32 value = va_arg(ap, celt_int32);
1367 st->constrained_vbr = value;
1368 }
1369 break;
Gregory Maxwell888d8ce2009-05-21 04:21:53 -04001370 case CELT_SET_VBR_RATE_REQUEST:
1371 {
Jean-Marc Valin30f7f812009-10-17 14:35:13 -04001372 celt_int32 value = va_arg(ap, celt_int32);
Jean-Marc Valin8cc945c2010-05-29 08:07:18 -04001373 int frame_rate;
1374 int N = st->mode->shortMdctSize;
Gregory Maxwell888d8ce2009-05-21 04:21:53 -04001375 if (value<0)
1376 goto bad_arg;
1377 if (value>3072000)
1378 value = 3072000;
Jean-Marc Valin8cc945c2010-05-29 08:07:18 -04001379 frame_rate = ((st->mode->Fs<<3)+(N>>1))/N;
1380 st->vbr_rate_norm = ((value<<(BITRES+3))+(frame_rate>>1))/frame_rate;
Gregory Maxwell888d8ce2009-05-21 04:21:53 -04001381 }
1382 break;
John Ridges454d1d02009-05-21 22:38:39 -04001383 case CELT_RESET_STATE:
1384 {
Jean-Marc Valinc09807d2010-08-27 17:17:50 -04001385 CELT_MEMSET((char*)&st->ENCODER_RESET_START, 0,
1386 celt_encoder_get_size(st->mode, st->channels)-
1387 ((char*)&st->ENCODER_RESET_START - (char*)st));
Jean-Marc Valin30165bb2010-12-03 14:35:59 -05001388 st->vbr_offset = 0;
John Ridges454d1d02009-05-21 22:38:39 -04001389 st->delayedIntra = 1;
Timothy B. Terriberry320cf2e2010-12-17 05:52:06 -08001390 st->spread_decision = SPREAD_NORMAL;
Jean-Marc Valin628c0252010-04-16 20:57:56 -04001391 st->tonal_average = QCONST16(1.f,8);
John Ridges454d1d02009-05-21 22:38:39 -04001392 }
1393 break;
Jean-Marc Valinc18fb1d2008-09-30 07:36:54 -04001394 default:
Jean-Marc Valinb6f90612008-10-05 22:39:13 -04001395 goto bad_request;
Jean-Marc Valinc18fb1d2008-09-30 07:36:54 -04001396 }
Jean-Marc Valinb6f90612008-10-05 22:39:13 -04001397 va_end(ap);
Jean-Marc Valinc18fb1d2008-09-30 07:36:54 -04001398 return CELT_OK;
Jean-Marc Valinb6f90612008-10-05 22:39:13 -04001399bad_arg:
1400 va_end(ap);
1401 return CELT_BAD_ARG;
1402bad_request:
1403 va_end(ap);
1404 return CELT_UNIMPLEMENTED;
Jean-Marc Valinc18fb1d2008-09-30 07:36:54 -04001405}
1406
Jean-Marc Valin56522ad2009-06-05 17:17:25 -04001407/**********************************************************************/
1408/* */
1409/* DECODER */
1410/* */
1411/**********************************************************************/
Jean-Marc Valineafbdd52009-04-27 19:35:09 -04001412#define DECODE_BUFFER_SIZE 2048
Jean-Marc Valin269d40a2007-12-07 11:29:45 +11001413
Jean-Marc Valin276de722008-02-20 17:45:51 +11001414/** Decoder state
1415 @brief Decoder state
1416 */
Jean-Marc Valin269d40a2007-12-07 11:29:45 +11001417struct CELTDecoder {
1418 const CELTMode *mode;
Jean-Marc Valina5431bf2008-01-03 20:53:01 +11001419 int overlap;
Jean-Marc Valin80ed1472009-10-15 21:45:32 -04001420 int channels;
Jean-Marc Valina5431bf2008-01-03 20:53:01 +11001421
Jean-Marc Valin5f961462010-05-19 13:38:10 -04001422 int start, end;
Jean-Marc Valinc09807d2010-08-27 17:17:50 -04001423
1424 /* Everything beyond this point gets cleared on a reset */
1425#define DECODER_RESET_START last_pitch_index
1426
Jean-Marc Valinfb83fb42007-12-08 00:56:04 +11001427 int last_pitch_index;
Jean-Marc Valin0f0da992009-08-12 21:34:01 -04001428 int loss_count;
Jean-Marc Valin35095c62010-11-04 13:24:44 -04001429 int postfilter_period;
Jean-Marc Valin70d30ff2010-12-13 13:50:29 -05001430 int postfilter_period_old;
Jean-Marc Valin35095c62010-11-04 13:24:44 -04001431 celt_word16 postfilter_gain;
Jean-Marc Valin70d30ff2010-12-13 13:50:29 -05001432 celt_word16 postfilter_gain_old;
Jean-Marc Valin02a35272010-08-27 16:00:01 -04001433
1434 celt_sig preemph_memD[2];
1435
Jean-Marc Valinca8b9922010-08-27 16:23:03 -04001436 celt_sig _decode_mem[1]; /* Size = channels*(DECODE_BUFFER_SIZE+mode->overlap) */
1437 /* celt_word16 lpc[], Size = channels*LPC_ORDER */
1438 /* celt_word16 oldEBands[], Size = channels*mode->nbEBands */
Jean-Marc Valin269d40a2007-12-07 11:29:45 +11001439};
1440
Jean-Marc Valin02a35272010-08-27 16:00:01 -04001441int celt_decoder_get_size(const CELTMode *mode, int channels)
1442{
1443 int size = sizeof(struct CELTDecoder)
1444 + (channels*(DECODE_BUFFER_SIZE+mode->overlap)-1)*sizeof(celt_sig)
1445 + channels*LPC_ORDER*sizeof(celt_word16)
1446 + channels*mode->nbEBands*sizeof(celt_word16);
1447 return size;
1448}
1449
Jean-Marc Valin80ed1472009-10-15 21:45:32 -04001450CELTDecoder *celt_decoder_create(const CELTMode *mode, int channels, int *error)
Jean-Marc Valin269d40a2007-12-07 11:29:45 +11001451{
Jean-Marc Valin7cfb7302010-08-27 16:54:33 -04001452 return celt_decoder_init(
1453 (CELTDecoder *)celt_alloc(celt_decoder_get_size(mode, channels)),
1454 mode, channels, error);
1455}
Jean-Marc Valin44ffd5a2008-02-22 00:39:25 +11001456
Jean-Marc Valin7cfb7302010-08-27 16:54:33 -04001457CELTDecoder *celt_decoder_init(CELTDecoder *st, const CELTMode *mode, int channels, int *error)
1458{
Jean-Marc Valin80ed1472009-10-15 21:45:32 -04001459 if (channels < 0 || channels > 2)
1460 {
Jean-Marc Valin80ed1472009-10-15 21:45:32 -04001461 if (error)
1462 *error = CELT_BAD_ARG;
1463 return NULL;
1464 }
Jean-Marc Valin44ffd5a2008-02-22 00:39:25 +11001465
Gregory Maxwell17169992009-06-04 15:15:34 -04001466 if (st==NULL)
Jean-Marc Valinece94a02009-10-16 07:30:14 -04001467 {
1468 if (error)
1469 *error = CELT_ALLOC_FAIL;
Gregory Maxwell17169992009-06-04 15:15:34 -04001470 return NULL;
Jean-Marc Valinece94a02009-10-16 07:30:14 -04001471 }
1472
Jean-Marc Valin6d3829f2010-08-27 17:52:38 -04001473 CELT_MEMSET((char*)st, 0, celt_decoder_get_size(mode, channels));
1474
Jean-Marc Valin269d40a2007-12-07 11:29:45 +11001475 st->mode = mode;
Jean-Marc Valina5431bf2008-01-03 20:53:01 +11001476 st->overlap = mode->overlap;
Jean-Marc Valin80ed1472009-10-15 21:45:32 -04001477 st->channels = channels;
Jean-Marc Valina5431bf2008-01-03 20:53:01 +11001478
Jean-Marc Valin5f961462010-05-19 13:38:10 -04001479 st->start = 0;
Jean-Marc Valin8952c452010-07-16 21:48:44 -04001480 st->end = st->mode->effEBands;
Jean-Marc Valin5f961462010-05-19 13:38:10 -04001481
Jean-Marc Valin0f0da992009-08-12 21:34:01 -04001482 st->loss_count = 0;
Gregory Maxwell17169992009-06-04 15:15:34 -04001483
Jean-Marc Valin02a35272010-08-27 16:00:01 -04001484 if (error)
1485 *error = CELT_OK;
Jean-Marc Valin02a35272010-08-27 16:00:01 -04001486 return st;
Jean-Marc Valin269d40a2007-12-07 11:29:45 +11001487}
1488
Peter Kirk19f9dc92008-06-06 14:38:38 +02001489void celt_decoder_destroy(CELTDecoder *st)
Jean-Marc Valin269d40a2007-12-07 11:29:45 +11001490{
Jean-Marc Valin269d40a2007-12-07 11:29:45 +11001491 celt_free(st);
1492}
1493
Jean-Marc Valin017fa852010-05-06 22:11:48 -04001494static void celt_decode_lost(CELTDecoder * restrict st, celt_word16 * restrict pcm, int N, int LM)
Jean-Marc Valinfb83fb42007-12-08 00:56:04 +11001495{
Jean-Marc Valin04752672010-05-05 07:21:21 -04001496 int c;
Jean-Marc Valin0bb05bc2008-02-20 13:43:40 +11001497 int pitch_index;
Jean-Marc Valine14fe902009-12-11 00:07:31 -05001498 int overlap = st->mode->overlap;
Jean-Marc Valin234969c2009-10-17 22:12:42 -04001499 celt_word16 fade = Q15ONE;
Jean-Marc Valin24c9cda2008-05-02 10:34:07 +10001500 int i, len;
Jean-Marc Valin80ed1472009-10-15 21:45:32 -04001501 const int C = CHANNELS(st->channels);
Jean-Marc Valin24c9cda2008-05-02 10:34:07 +10001502 int offset;
Jean-Marc Valin6d131082010-08-27 15:15:32 -04001503 celt_sig *out_mem[2];
1504 celt_sig *decode_mem[2];
1505 celt_sig *overlap_mem[2];
Jean-Marc Valin02a35272010-08-27 16:00:01 -04001506 celt_word16 *lpc;
Jean-Marc Valin8600f692008-02-29 15:14:12 +11001507 SAVE_STACK;
Jean-Marc Valinfb83fb42007-12-08 00:56:04 +11001508
Gregory Maxwell9743bf32010-11-04 20:45:09 -04001509 c=0; do {
Jean-Marc Valin6d131082010-08-27 15:15:32 -04001510 decode_mem[c] = st->_decode_mem + c*(DECODE_BUFFER_SIZE+st->overlap);
1511 out_mem[c] = decode_mem[c]+DECODE_BUFFER_SIZE-MAX_PERIOD;
1512 overlap_mem[c] = decode_mem[c]+DECODE_BUFFER_SIZE;
Gregory Maxwell9743bf32010-11-04 20:45:09 -04001513 } while (++c<C);
Jean-Marc Valin02a35272010-08-27 16:00:01 -04001514 lpc = (celt_word16*)(st->_decode_mem+(DECODE_BUFFER_SIZE+st->overlap)*C);
Jean-Marc Valin6d131082010-08-27 15:15:32 -04001515
Jean-Marc Valin24c9cda2008-05-02 10:34:07 +10001516 len = N+st->mode->overlap;
Jean-Marc Valinfb83fb42007-12-08 00:56:04 +11001517
Jean-Marc Valin0f0da992009-08-12 21:34:01 -04001518 if (st->loss_count == 0)
1519 {
Jean-Marc Valin7a7c42a2009-11-25 20:38:52 -05001520 celt_word16 pitch_buf[MAX_PERIOD>>1];
Jean-Marc Valin294863b2009-11-08 22:29:54 +09001521 celt_word32 tmp=0;
Jean-Marc Valine465c142009-11-26 00:39:36 -05001522 celt_word32 mem0[2]={0,0};
1523 celt_word16 mem1[2]={0,0};
Jean-Marc Valin6202c742010-06-01 00:30:37 -04001524 int len2 = len;
1525 /* FIXME: This is a kludge */
1526 if (len2>MAX_PERIOD>>1)
1527 len2 = MAX_PERIOD>>1;
Jean-Marc Valin6d131082010-08-27 15:15:32 -04001528 pitch_downsample(out_mem, pitch_buf, MAX_PERIOD, MAX_PERIOD,
Jean-Marc Valine14fe902009-12-11 00:07:31 -05001529 C, mem0, mem1);
Jean-Marc Valin6202c742010-06-01 00:30:37 -04001530 pitch_search(st->mode, pitch_buf+((MAX_PERIOD-len2)>>1), pitch_buf, len2,
1531 MAX_PERIOD-len2-100, &pitch_index, &tmp, 1<<LM);
1532 pitch_index = MAX_PERIOD-len2-pitch_index;
Jean-Marc Valin0f0da992009-08-12 21:34:01 -04001533 st->last_pitch_index = pitch_index;
1534 } else {
1535 pitch_index = st->last_pitch_index;
1536 if (st->loss_count < 5)
1537 fade = QCONST16(.8f,15);
1538 else
1539 fade = 0;
1540 }
Jean-Marc Valinfb83fb42007-12-08 00:56:04 +11001541
Gregory Maxwell9743bf32010-11-04 20:45:09 -04001542 c=0; do {
Jean-Marc Valin6202c742010-06-01 00:30:37 -04001543 /* FIXME: This is more memory than necessary */
1544 celt_word32 e[2*MAX_PERIOD];
1545 celt_word16 exc[2*MAX_PERIOD];
Jean-Marc Valin456eab22010-06-16 22:38:57 -04001546 celt_word32 ac[LPC_ORDER+1];
Jean-Marc Valin7b7f0712010-06-17 20:10:02 -04001547 celt_word16 decay = 1;
1548 celt_word32 S1=0;
Jean-Marc Valin74128be2010-01-01 09:33:17 -05001549 celt_word16 mem[LPC_ORDER]={0};
Jean-Marc Valine14fe902009-12-11 00:07:31 -05001550
Jean-Marc Valind5f99302009-12-16 22:42:32 -05001551 offset = MAX_PERIOD-pitch_index;
Jean-Marc Valine14fe902009-12-11 00:07:31 -05001552 for (i=0;i<MAX_PERIOD;i++)
Jean-Marc Valin6d131082010-08-27 15:15:32 -04001553 exc[i] = ROUND16(out_mem[c][i], SIG_SHIFT);
Jean-Marc Valin5a0fae52009-12-14 21:19:37 -05001554
1555 if (st->loss_count == 0)
1556 {
1557 _celt_autocorr(exc, ac, st->mode->window, st->mode->overlap,
1558 LPC_ORDER, MAX_PERIOD);
1559
Jean-Marc Valin456eab22010-06-16 22:38:57 -04001560 /* Noise floor -40 dB */
Jean-Marc Valin7b7f0712010-06-17 20:10:02 -04001561#ifdef FIXED_POINT
1562 ac[0] += SHR32(ac[0],13);
1563#else
Jean-Marc Valinae01e112010-08-03 21:43:41 -04001564 ac[0] *= 1.0001f;
Jean-Marc Valin7b7f0712010-06-17 20:10:02 -04001565#endif
Jean-Marc Valin5a0fae52009-12-14 21:19:37 -05001566 /* Lag windowing */
1567 for (i=1;i<=LPC_ORDER;i++)
1568 {
1569 /*ac[i] *= exp(-.5*(2*M_PI*.002*i)*(2*M_PI*.002*i));*/
Jean-Marc Valin7b7f0712010-06-17 20:10:02 -04001570#ifdef FIXED_POINT
1571 ac[i] -= MULT16_32_Q15(2*i*i, ac[i]);
1572#else
Jean-Marc Valinae01e112010-08-03 21:43:41 -04001573 ac[i] -= ac[i]*(.008f*i)*(.008f*i);
Jean-Marc Valin7b7f0712010-06-17 20:10:02 -04001574#endif
Jean-Marc Valin5a0fae52009-12-14 21:19:37 -05001575 }
1576
Jean-Marc Valin02a35272010-08-27 16:00:01 -04001577 _celt_lpc(lpc+c*LPC_ORDER, ac, LPC_ORDER);
Jean-Marc Valin5a0fae52009-12-14 21:19:37 -05001578 }
Jean-Marc Valinbc4a0022010-11-06 18:11:06 -04001579 for (i=0;i<LPC_ORDER;i++)
Jean-Marc Valine53c4bc2010-11-06 21:41:40 -04001580 mem[i] = ROUND16(out_mem[c][MAX_PERIOD-1-i], SIG_SHIFT);
Jean-Marc Valin02a35272010-08-27 16:00:01 -04001581 fir(exc, lpc+c*LPC_ORDER, exc, MAX_PERIOD, LPC_ORDER, mem);
Jean-Marc Valin74128be2010-01-01 09:33:17 -05001582 /*for (i=0;i<MAX_PERIOD;i++)printf("%d ", exc[i]); printf("\n");*/
Jean-Marc Valine14fe902009-12-11 00:07:31 -05001583 /* Check if the waveform is decaying (and if so how fast) */
1584 {
Jean-Marc Valin7b7f0712010-06-17 20:10:02 -04001585 celt_word32 E1=1, E2=1;
Jean-Marc Valine14fe902009-12-11 00:07:31 -05001586 int period;
1587 if (pitch_index <= MAX_PERIOD/2)
1588 period = pitch_index;
1589 else
1590 period = MAX_PERIOD/2;
1591 for (i=0;i<period;i++)
1592 {
Jean-Marc Valin7b7f0712010-06-17 20:10:02 -04001593 E1 += SHR32(MULT16_16(exc[MAX_PERIOD-period+i],exc[MAX_PERIOD-period+i]),8);
1594 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 -05001595 }
Jean-Marc Valin7b7f0712010-06-17 20:10:02 -04001596 if (E1 > E2)
1597 E1 = E2;
1598 decay = celt_sqrt(frac_div32(SHR(E1,1),E2));
Jean-Marc Valine14fe902009-12-11 00:07:31 -05001599 }
1600
1601 /* Copy excitation, taking decay into account */
1602 for (i=0;i<len+st->mode->overlap;i++)
1603 {
Jean-Marc Valin1ad93cf2010-11-06 22:02:32 -04001604 celt_word16 tmp;
Jean-Marc Valine14fe902009-12-11 00:07:31 -05001605 if (offset+i >= MAX_PERIOD)
1606 {
1607 offset -= pitch_index;
Jean-Marc Valin7b7f0712010-06-17 20:10:02 -04001608 decay = MULT16_16_Q15(decay, decay);
Jean-Marc Valine14fe902009-12-11 00:07:31 -05001609 }
Jean-Marc Valin7b7f0712010-06-17 20:10:02 -04001610 e[i] = SHL32(EXTEND32(MULT16_16_Q15(decay, exc[offset+i])), SIG_SHIFT);
Jean-Marc Valin1ad93cf2010-11-06 22:02:32 -04001611 tmp = ROUND16(out_mem[c][offset+i],SIG_SHIFT);
1612 S1 += SHR32(MULT16_16(tmp,tmp),8);
Jean-Marc Valin5a0fae52009-12-14 21:19:37 -05001613 }
Jean-Marc Valinbc2c4542010-10-28 14:27:05 -04001614 for (i=0;i<LPC_ORDER;i++)
Jean-Marc Valine53c4bc2010-11-06 21:41:40 -04001615 mem[i] = ROUND16(out_mem[c][MAX_PERIOD-1-i], SIG_SHIFT);
Jean-Marc Valinbc2c4542010-10-28 14:27:05 -04001616 for (i=0;i<len+st->mode->overlap;i++)
1617 e[i] = MULT16_32_Q15(fade, e[i]);
Jean-Marc Valin02a35272010-08-27 16:00:01 -04001618 iir(e, lpc+c*LPC_ORDER, e, len+st->mode->overlap, LPC_ORDER, mem);
Jean-Marc Valin5a0fae52009-12-14 21:19:37 -05001619
1620 {
Jean-Marc Valin7b7f0712010-06-17 20:10:02 -04001621 celt_word32 S2=0;
Jean-Marc Valin5a0fae52009-12-14 21:19:37 -05001622 for (i=0;i<len+overlap;i++)
Jean-Marc Valin1ad93cf2010-11-06 22:02:32 -04001623 {
1624 celt_word16 tmp = ROUND16(e[i],SIG_SHIFT);
1625 S2 += SHR32(MULT16_16(tmp,tmp),8);
1626 }
Jean-Marc Valinfeca0952010-06-17 20:25:51 -04001627 /* This checks for an "explosion" in the synthesis */
1628#ifdef FIXED_POINT
1629 if (!(S1 > SHR32(S2,2)))
1630#else
1631 /* Float test is written this way to catch NaNs at the same time */
Jean-Marc Valin07fed1b2009-12-28 07:59:42 -05001632 if (!(S1 > 0.2f*S2))
Jean-Marc Valinfeca0952010-06-17 20:25:51 -04001633#endif
Jean-Marc Valin07fed1b2009-12-28 07:59:42 -05001634 {
1635 for (i=0;i<len+overlap;i++)
1636 e[i] = 0;
1637 } else if (S1 < S2)
1638 {
Jean-Marc Valin12996402010-08-04 09:13:24 -04001639 celt_word16 ratio = celt_sqrt(frac_div32(SHR32(S1,1)+1,S2+1));
Jean-Marc Valin5a0fae52009-12-14 21:19:37 -05001640 for (i=0;i<len+overlap;i++)
Jean-Marc Valin1ad93cf2010-11-06 22:02:32 -04001641 e[i] = MULT16_32_Q15(ratio, e[i]);
Jean-Marc Valin07fed1b2009-12-28 07:59:42 -05001642 }
Jean-Marc Valine14fe902009-12-11 00:07:31 -05001643 }
1644
Jean-Marc Valin35095c62010-11-04 13:24:44 -04001645#ifdef ENABLE_POSTFILTER
1646 /* Apply post-filter to the MDCT overlap of the previous frame */
1647 comb_filter(out_mem[c]+MAX_PERIOD, out_mem[c]+MAX_PERIOD, st->postfilter_period, st->postfilter_period, st->overlap, C,
1648 st->postfilter_gain, st->postfilter_gain, NULL, 0);
1649#endif /* ENABLE_POSTFILTER */
1650
Jean-Marc Valine14fe902009-12-11 00:07:31 -05001651 for (i=0;i<MAX_PERIOD+st->mode->overlap-N;i++)
Jean-Marc Valin6d131082010-08-27 15:15:32 -04001652 out_mem[c][i] = out_mem[c][N+i];
Jean-Marc Valine14fe902009-12-11 00:07:31 -05001653
Jean-Marc Valine14fe902009-12-11 00:07:31 -05001654 /* Apply TDAC to the concealed audio so that it blends with the
1655 previous and next frames */
1656 for (i=0;i<overlap/2;i++)
1657 {
Jean-Marc Valind7231dd2010-11-06 20:30:17 -04001658 celt_word32 tmp;
1659 tmp = MULT16_32_Q15(st->mode->window[i], e[N+overlap-1-i]) +
1660 MULT16_32_Q15(st->mode->window[overlap-i-1], e[N+i ]);
1661 out_mem[c][MAX_PERIOD+i] = MULT16_32_Q15(st->mode->window[overlap-i-1], tmp);
1662 out_mem[c][MAX_PERIOD+overlap-i-1] = MULT16_32_Q15(st->mode->window[i], tmp);
Jean-Marc Valine14fe902009-12-11 00:07:31 -05001663 }
Jean-Marc Valinbc4a0022010-11-06 18:11:06 -04001664 for (i=0;i<N;i++)
1665 out_mem[c][MAX_PERIOD-N+i] = e[i];
Jean-Marc Valin35095c62010-11-04 13:24:44 -04001666
1667#ifdef ENABLE_POSTFILTER
1668 /* Apply pre-filter to the MDCT overlap for the next frame (post-filter will be applied then) */
1669 comb_filter(e, out_mem[c]+MAX_PERIOD, st->postfilter_period, st->postfilter_period, st->overlap, C,
1670 -st->postfilter_gain, -st->postfilter_gain, NULL, 0);
1671#endif /* ENABLE_POSTFILTER */
1672 for (i=0;i<overlap;i++)
1673 out_mem[c][MAX_PERIOD+i] = e[i];
Gregory Maxwell9743bf32010-11-04 20:45:09 -04001674 } while (++c<C);
Jean-Marc Valin1677aa92007-12-08 01:13:34 +11001675
Jean-Marc Valinbc2c4542010-10-28 14:27:05 -04001676 {
1677 celt_word32 *out_syn[2];
1678 out_syn[0] = out_mem[0]+MAX_PERIOD-N;
1679 if (C==2)
1680 out_syn[1] = out_mem[1]+MAX_PERIOD-N;
1681 deemphasis(out_syn, pcm, N, C, st->mode->preemph, st->preemph_memD);
1682 }
Jean-Marc Valin0f0da992009-08-12 21:34:01 -04001683
1684 st->loss_count++;
1685
Jean-Marc Valin8600f692008-02-29 15:14:12 +11001686 RESTORE_STACK;
Jean-Marc Valinfb83fb42007-12-08 00:56:04 +11001687}
1688
Gregory Maxwell5f2a74b2008-08-11 23:50:07 -04001689#ifdef FIXED_POINT
Jean-Marc Valinf5e2e322010-05-19 12:05:02 -04001690int 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 +11001691{
Gregory Maxwell5f2a74b2008-08-11 23:50:07 -04001692#else
Jean-Marc Valinf5e2e322010-05-19 12:05:02 -04001693int 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 -04001694{
1695#endif
Jean-Marc Valin0695a5f2010-08-27 11:33:18 -04001696 int c, i, N;
Timothy B. Terriberry320cf2e2010-12-17 05:52:06 -08001697 int spread_decision;
Jean-Marc Valinc890b582008-08-01 22:26:49 -04001698 int bits;
Jean-Marc Valinf5e2e322010-05-19 12:05:02 -04001699 ec_dec _dec;
Jean-Marc Valin0bb05bc2008-02-20 13:43:40 +11001700 ec_byte_buffer buf;
Jean-Marc Valin234969c2009-10-17 22:12:42 -04001701 VARDECL(celt_sig, freq);
Jean-Marc Valin234969c2009-10-17 22:12:42 -04001702 VARDECL(celt_norm, X);
1703 VARDECL(celt_ener, bandE);
Jean-Marc Valin6775de32008-08-02 08:14:42 -04001704 VARDECL(int, fine_quant);
1705 VARDECL(int, pulses);
1706 VARDECL(int, offsets);
Jean-Marc Valin52cb5fb2009-06-10 08:08:55 -04001707 VARDECL(int, fine_priority);
Jean-Marc Valin163b76e2010-05-27 23:56:53 -04001708 VARDECL(int, tf_res);
Jean-Marc Valin6d131082010-08-27 15:15:32 -04001709 celt_sig *out_mem[2];
1710 celt_sig *decode_mem[2];
1711 celt_sig *overlap_mem[2];
Jean-Marc Valinf67b4472010-08-27 01:32:40 -04001712 celt_sig *out_syn[2];
Jean-Marc Valin02a35272010-08-27 16:00:01 -04001713 celt_word16 *lpc;
1714 celt_word16 *oldBandE;
Jean-Marc Valinc890b582008-08-01 22:26:49 -04001715
Jean-Marc Valin9d1decd2008-06-17 13:28:13 +10001716 int shortBlocks;
Jean-Marc Valin3b918ba2010-05-05 00:02:26 -04001717 int isTransient;
Jean-Marc Valin05ed03e2009-04-29 07:44:13 -04001718 int intra_ener;
Jean-Marc Valin80ed1472009-10-15 21:45:32 -04001719 const int C = CHANNELS(st->channels);
Jean-Marc Valin017fa852010-05-06 22:11:48 -04001720 int LM, M;
Jean-Marc Valin6b95d8f2010-06-21 21:39:44 -04001721 int nbFilledBytes, nbAvailableBytes;
Jean-Marc Valin85f41b22010-07-16 18:12:45 -04001722 int effEnd;
Jean-Marc Valinb801da52010-09-28 14:56:20 -04001723 int codedBands;
Jean-Marc Valinf1fea662010-10-09 22:58:52 -04001724 int alloc_trim;
Jean-Marc Valin35095c62010-11-04 13:24:44 -04001725 int postfilter_pitch;
1726 celt_word16 postfilter_gain;
Jean-Marc Valin4f177e82010-11-26 10:32:03 -05001727 int intensity=0;
Jean-Marc Valine65978f2010-12-02 13:46:48 -05001728 int dual_stereo=0;
Jean-Marc Valin8600f692008-02-29 15:14:12 +11001729 SAVE_STACK;
Jean-Marc Valin44ffd5a2008-02-22 00:39:25 +11001730
Gregory Maxwell0719f6f2009-07-09 17:07:24 -04001731 if (pcm==NULL)
1732 return CELT_BAD_ARG;
1733
Jean-Marc Valin017fa852010-05-06 22:11:48 -04001734 for (LM=0;LM<4;LM++)
1735 if (st->mode->shortMdctSize<<LM==frame_size)
1736 break;
1737 if (LM>=MAX_CONFIG_SIZES)
1738 return CELT_BAD_ARG;
1739 M=1<<LM;
1740
Gregory Maxwell9743bf32010-11-04 20:45:09 -04001741 c=0; do {
Jean-Marc Valin6d131082010-08-27 15:15:32 -04001742 decode_mem[c] = st->_decode_mem + c*(DECODE_BUFFER_SIZE+st->overlap);
1743 out_mem[c] = decode_mem[c]+DECODE_BUFFER_SIZE-MAX_PERIOD;
1744 overlap_mem[c] = decode_mem[c]+DECODE_BUFFER_SIZE;
Gregory Maxwell9743bf32010-11-04 20:45:09 -04001745 } while (++c<C);
Jean-Marc Valin02a35272010-08-27 16:00:01 -04001746 lpc = (celt_word16*)(st->_decode_mem+(DECODE_BUFFER_SIZE+st->overlap)*C);
1747 oldBandE = lpc+C*LPC_ORDER;
Jean-Marc Valin6d131082010-08-27 15:15:32 -04001748
Jean-Marc Valin04752672010-05-05 07:21:21 -04001749 N = M*st->mode->shortMdctSize;
Jean-Marc Valin01417232008-03-03 13:59:55 +11001750
Jean-Marc Valin85f41b22010-07-16 18:12:45 -04001751 effEnd = st->end;
1752 if (effEnd > st->mode->effEBands)
1753 effEnd = st->mode->effEBands;
1754
Jean-Marc Valin234969c2009-10-17 22:12:42 -04001755 ALLOC(freq, C*N, celt_sig); /**< Interleaved signal MDCTs */
1756 ALLOC(X, C*N, celt_norm); /**< Interleaved normalised MDCTs */
1757 ALLOC(bandE, st->mode->nbEBands*C, celt_ener);
Gregory Maxwell9743bf32010-11-04 20:45:09 -04001758 c=0; do
Jean-Marc Valin5f961462010-05-19 13:38:10 -04001759 for (i=0;i<M*st->mode->eBands[st->start];i++)
1760 X[c*N+i] = 0;
Gregory Maxwell9743bf32010-11-04 20:45:09 -04001761 while (++c<C);
1762 c=0; do
Jean-Marc Valin85f41b22010-07-16 18:12:45 -04001763 for (i=M*st->mode->eBands[effEnd];i<N;i++)
Jean-Marc Valin525d7cf2010-07-13 14:14:16 -04001764 X[c*N+i] = 0;
Gregory Maxwell9743bf32010-11-04 20:45:09 -04001765 while (++c<C);
Jean-Marc Valin5f961462010-05-19 13:38:10 -04001766
Jean-Marc Valinfb83fb42007-12-08 00:56:04 +11001767 if (data == NULL)
1768 {
Jean-Marc Valin017fa852010-05-06 22:11:48 -04001769 celt_decode_lost(st, pcm, N, LM);
Jean-Marc Valin8600f692008-02-29 15:14:12 +11001770 RESTORE_STACK;
Jean-Marc Valinb1e017f2010-07-18 21:20:35 -04001771 return CELT_OK;
Jean-Marc Valinfb83fb42007-12-08 00:56:04 +11001772 }
Gregory Maxwell520eeae2009-02-09 01:33:21 -05001773 if (len<0) {
1774 RESTORE_STACK;
1775 return CELT_BAD_ARG;
1776 }
Jean-Marc Valinfb83fb42007-12-08 00:56:04 +11001777
Jean-Marc Valinf5e2e322010-05-19 12:05:02 -04001778 if (dec == NULL)
1779 {
1780 ec_byte_readinit(&buf,(unsigned char*)data,len);
1781 ec_dec_init(&_dec,&buf);
1782 dec = &_dec;
Jean-Marc Valin6b95d8f2010-06-21 21:39:44 -04001783 nbFilledBytes = 0;
1784 } else {
Jean-Marc Valinbdcaaf72010-07-05 13:52:41 -04001785 nbFilledBytes = (ec_dec_tell(dec, 0)+4)>>3;
Jean-Marc Valinf5e2e322010-05-19 12:05:02 -04001786 }
Jean-Marc Valin6b95d8f2010-06-21 21:39:44 -04001787 nbAvailableBytes = len-nbFilledBytes;
1788
Jean-Marc Valin35095c62010-11-04 13:24:44 -04001789 if (ec_dec_bit_prob(dec, 32768))
1790 {
1791#ifdef ENABLE_POSTFILTER
1792 int qg, octave;
1793 octave = ec_dec_uint(dec, 6);
1794 postfilter_pitch = (16<<octave)+ec_dec_bits(dec, 4+octave);
1795 qg = ec_dec_bits(dec, 2);
1796 postfilter_gain = QCONST16(.125f,15)*(qg+2);
1797#else /* ENABLE_POSTFILTER */
1798 RESTORE_STACK;
1799 return CELT_CORRUPTED_DATA;
1800#endif /* ENABLE_POSTFILTER */
1801
1802 } else {
1803 postfilter_gain = 0;
1804 postfilter_pitch = 0;
1805 }
1806
Jean-Marc Valin017001a2010-08-05 15:42:50 -04001807 /* Decode the global flags (first symbols in the stream) */
1808 intra_ener = ec_dec_bit_prob(dec, 8192);
Jean-Marc Valin9099bc32010-08-07 21:50:01 -04001809 /* Get band energies */
Jean-Marc Valin02a35272010-08-27 16:00:01 -04001810 unquant_coarse_energy(st->mode, st->start, st->end, bandE, oldBandE,
Timothy B. Terriberryef2e6502010-11-09 01:43:18 -08001811 intra_ener, dec, C, LM);
Jean-Marc Valin9099bc32010-08-07 21:50:01 -04001812
Jean-Marc Valinf9fdbff2010-09-05 21:02:38 -04001813 if (LM > 0)
1814 isTransient = ec_dec_bit_prob(dec, 8192);
1815 else
1816 isTransient = 0;
Jean-Marc Valin017001a2010-08-05 15:42:50 -04001817
Jean-Marc Valin3b918ba2010-05-05 00:02:26 -04001818 if (isTransient)
1819 shortBlocks = M;
1820 else
1821 shortBlocks = 0;
1822
Jean-Marc Valin0a571ef2010-06-05 23:12:19 -04001823 ALLOC(tf_res, st->mode->nbEBands, int);
Jean-Marc Valine5e9aa72010-12-02 16:09:51 -05001824 tf_decode(st->start, st->end, C, isTransient, tf_res, LM, dec);
Jean-Marc Valin0a571ef2010-06-05 23:12:19 -04001825
Timothy B. Terriberry320cf2e2010-12-17 05:52:06 -08001826 spread_decision = ec_dec_bit_prob(dec, 18432)<<1;
1827 spread_decision |= ec_dec_bit_prob(dec, (spread_decision>>1) ? 5699 : 14564);
Jean-Marc Valin9099bc32010-08-07 21:50:01 -04001828
Jean-Marc Valin6775de32008-08-02 08:14:42 -04001829 ALLOC(pulses, st->mode->nbEBands, int);
1830 ALLOC(offsets, st->mode->nbEBands, int);
Jean-Marc Valin52cb5fb2009-06-10 08:08:55 -04001831 ALLOC(fine_priority, st->mode->nbEBands, int);
Jean-Marc Valin6775de32008-08-02 08:14:42 -04001832
1833 for (i=0;i<st->mode->nbEBands;i++)
1834 offsets[i] = 0;
Jean-Marc Valind74c8512010-09-29 17:39:54 -04001835 for (i=0;i<st->mode->nbEBands;i++)
1836 {
1837 if (ec_dec_bit_prob(dec, 1024))
1838 {
1839 while (ec_dec_bit_prob(dec, 32768))
1840 offsets[i]++;
1841 offsets[i]++;
1842 offsets[i] *= (6<<BITRES);
1843 }
1844 }
Jean-Marc Valin6775de32008-08-02 08:14:42 -04001845
Jean-Marc Valin9099bc32010-08-07 21:50:01 -04001846 ALLOC(fine_quant, st->mode->nbEBands, int);
Jean-Marc Valin6bf04622010-09-30 10:16:22 -04001847 {
Jean-Marc Valinf1fea662010-10-09 22:58:52 -04001848 int fl;
Jean-Marc Valinc40addc2010-10-22 14:57:07 -04001849 alloc_trim = 0;
Jean-Marc Valin6bf04622010-09-30 10:16:22 -04001850 fl = ec_decode_bin(dec, 7);
Jean-Marc Valinc40addc2010-10-22 14:57:07 -04001851 while (trim_cdf[alloc_trim+1] <= fl)
1852 alloc_trim++;
1853 ec_dec_update(dec, trim_cdf[alloc_trim], trim_cdf[alloc_trim+1], 128);
Jean-Marc Valin6bf04622010-09-30 10:16:22 -04001854 }
Jean-Marc Valinf1fea662010-10-09 22:58:52 -04001855
Jean-Marc Valin4f177e82010-11-26 10:32:03 -05001856 if (C==2)
Jean-Marc Valine65978f2010-12-02 13:46:48 -05001857 {
1858 dual_stereo = ec_dec_bit_prob(dec, 32768);
Jean-Marc Valin4f177e82010-11-26 10:32:03 -05001859 intensity = ec_dec_uint(dec, 1+st->end-st->start);
Jean-Marc Valine65978f2010-12-02 13:46:48 -05001860 }
Jean-Marc Valin4f177e82010-11-26 10:32:03 -05001861
Timothy B. Terriberry76ea41e2010-12-16 14:39:58 -08001862 bits = (len*8<<BITRES) - ec_dec_tell(dec, BITRES) - 1;
Jean-Marc Valindfd6e712010-12-09 23:23:34 -05001863 codedBands = compute_allocation(st->mode, st->start, st->end, offsets,
Timothy B. Terriberryb2f59002010-12-15 05:12:43 -08001864 alloc_trim, bits, pulses, fine_quant, fine_priority, C, LM, dec, 0, 0);
Jean-Marc Valin6775de32008-08-02 08:14:42 -04001865
Jean-Marc Valin02a35272010-08-27 16:00:01 -04001866 unquant_fine_energy(st->mode, st->start, st->end, bandE, oldBandE, fine_quant, dec, C);
Jean-Marc Valin827f9312008-05-06 23:21:55 +10001867
Jean-Marc Valin8cbea172010-08-05 15:22:57 -04001868 /* Decode fixed codebook */
Jean-Marc Valin4f177e82010-11-26 10:32:03 -05001869 quant_all_bands(0, st->mode, st->start, st->end, X, C==2 ? X+N : NULL,
Timothy B. Terriberry320cf2e2010-12-17 05:52:06 -08001870 NULL, pulses, shortBlocks, spread_decision, dual_stereo, intensity, tf_res, 1,
Jean-Marc Valin4f177e82010-11-26 10:32:03 -05001871 len*8, dec, LM, codedBands);
Jean-Marc Valin746b2a82010-05-14 22:12:33 -04001872
Jean-Marc Valin02a35272010-08-27 16:00:01 -04001873 unquant_energy_finalise(st->mode, st->start, st->end, bandE, oldBandE,
1874 fine_quant, fine_priority, len*8-ec_dec_tell(dec, 0), dec, C);
Jean-Marc Valin30d51252010-06-21 17:55:28 -04001875
Jean-Marc Valin02a35272010-08-27 16:00:01 -04001876 log2Amp(st->mode, st->start, st->end, bandE, oldBandE, C);
Jean-Marc Valinbc272de2010-08-02 09:41:31 -04001877
Jean-Marc Valina4833ff2008-01-10 15:34:00 +11001878 /* Synthesis */
Jean-Marc Valin85f41b22010-07-16 18:12:45 -04001879 denormalise_bands(st->mode, X, freq, bandE, effEnd, C, M);
Jean-Marc Valina4833ff2008-01-10 15:34:00 +11001880
Jean-Marc Valin6d131082010-08-27 15:15:32 -04001881 CELT_MOVE(decode_mem[0], decode_mem[0]+N, DECODE_BUFFER_SIZE-N);
Jean-Marc Valin903dbf72010-08-26 20:06:49 -04001882 if (C==2)
Jean-Marc Valin6d131082010-08-27 15:15:32 -04001883 CELT_MOVE(decode_mem[1], decode_mem[1]+N, DECODE_BUFFER_SIZE-N);
Jean-Marc Valin88619552009-10-04 21:35:36 -04001884
Gregory Maxwell9743bf32010-11-04 20:45:09 -04001885 c=0; do
Jean-Marc Valin5f961462010-05-19 13:38:10 -04001886 for (i=0;i<M*st->mode->eBands[st->start];i++)
1887 freq[c*N+i] = 0;
Gregory Maxwell9743bf32010-11-04 20:45:09 -04001888 while (++c<C);
1889 c=0; do
Jean-Marc Valin85f41b22010-07-16 18:12:45 -04001890 for (i=M*st->mode->eBands[effEnd];i<N;i++)
Jean-Marc Valin525d7cf2010-07-13 14:14:16 -04001891 freq[c*N+i] = 0;
Gregory Maxwell9743bf32010-11-04 20:45:09 -04001892 while (++c<C);
Jean-Marc Valin3a0bc3d2010-02-21 15:10:22 -05001893
Jean-Marc Valin6d131082010-08-27 15:15:32 -04001894 out_syn[0] = out_mem[0]+MAX_PERIOD-N;
Jean-Marc Valinf67b4472010-08-27 01:32:40 -04001895 if (C==2)
Jean-Marc Valin6d131082010-08-27 15:15:32 -04001896 out_syn[1] = out_mem[1]+MAX_PERIOD-N;
Jean-Marc Valinf67b4472010-08-27 01:32:40 -04001897
Jean-Marc Valin269d40a2007-12-07 11:29:45 +11001898 /* Compute inverse MDCTs */
Jean-Marc Valin7a08ddd2010-10-18 14:55:42 -04001899 compute_inv_mdcts(st->mode, shortBlocks, freq, out_syn, overlap_mem, C, LM);
Jean-Marc Valinffa13472007-12-10 16:54:17 +11001900
Jean-Marc Valin35095c62010-11-04 13:24:44 -04001901#ifdef ENABLE_POSTFILTER
Gregory Maxwell9743bf32010-11-04 20:45:09 -04001902 c=0; do {
Jean-Marc Valin70d30ff2010-12-13 13:50:29 -05001903 st->postfilter_period=IMAX(st->postfilter_period, COMBFILTER_MINPERIOD);
1904 st->postfilter_period_old=IMAX(st->postfilter_period_old, COMBFILTER_MINPERIOD);
1905 if (LM!=0)
1906 {
1907 comb_filter(out_syn[c], out_syn[c], st->postfilter_period, st->postfilter_period, st->overlap, C,
1908 st->postfilter_gain, st->postfilter_gain, NULL, 0);
1909 comb_filter(out_syn[c]+st->overlap, out_syn[c]+st->overlap, st->postfilter_period, postfilter_pitch, N-st->overlap, C,
1910 st->postfilter_gain, postfilter_gain, st->mode->window, st->mode->overlap);
1911 } else {
1912 comb_filter(out_syn[c], out_syn[c], st->postfilter_period_old, st->postfilter_period, N-st->overlap, C,
1913 st->postfilter_gain_old, st->postfilter_gain, st->mode->window, st->mode->overlap);
1914 }
Gregory Maxwell9743bf32010-11-04 20:45:09 -04001915 } while (++c<C);
Jean-Marc Valin70d30ff2010-12-13 13:50:29 -05001916 st->postfilter_period_old = st->postfilter_period;
1917 st->postfilter_gain_old = st->postfilter_gain;
Jean-Marc Valin35095c62010-11-04 13:24:44 -04001918 st->postfilter_period = postfilter_pitch;
1919 st->postfilter_gain = postfilter_gain;
1920#endif /* ENABLE_POSTFILTER */
1921
Jean-Marc Valinf67b4472010-08-27 01:32:40 -04001922 deemphasis(out_syn, pcm, N, C, st->mode->preemph, st->preemph_memD);
Jean-Marc Valine14fe902009-12-11 00:07:31 -05001923 st->loss_count = 0;
Jean-Marc Valin8600f692008-02-29 15:14:12 +11001924 RESTORE_STACK;
Jean-Marc Valinb1e017f2010-07-18 21:20:35 -04001925 if (ec_dec_get_error(dec))
1926 return CELT_CORRUPTED_DATA;
1927 else
1928 return CELT_OK;
Jean-Marc Valin269d40a2007-12-07 11:29:45 +11001929}
1930
Gregory Maxwell5f2a74b2008-08-11 23:50:07 -04001931#ifdef FIXED_POINT
1932#ifndef DISABLE_FLOAT_API
Jean-Marc Valinf5e2e322010-05-19 12:05:02 -04001933int 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 -04001934{
Jean-Marc Valin017fa852010-05-06 22:11:48 -04001935 int j, ret, C, N, LM, M;
Jean-Marc Valin30f7f812009-10-17 14:35:13 -04001936 VARDECL(celt_int16, out);
Jean-Marc Valincb8780c2009-07-20 23:40:35 -04001937 SAVE_STACK;
Gregory Maxwell17169992009-06-04 15:15:34 -04001938
Gregory Maxwell0719f6f2009-07-09 17:07:24 -04001939 if (pcm==NULL)
1940 return CELT_BAD_ARG;
1941
Jean-Marc Valin017fa852010-05-06 22:11:48 -04001942 for (LM=0;LM<4;LM++)
1943 if (st->mode->shortMdctSize<<LM==frame_size)
1944 break;
1945 if (LM>=MAX_CONFIG_SIZES)
1946 return CELT_BAD_ARG;
1947 M=1<<LM;
1948
Jean-Marc Valin80ed1472009-10-15 21:45:32 -04001949 C = CHANNELS(st->channels);
Jean-Marc Valin017fa852010-05-06 22:11:48 -04001950 N = M*st->mode->shortMdctSize;
Gregory Maxwell0719f6f2009-07-09 17:07:24 -04001951
Jean-Marc Valin30f7f812009-10-17 14:35:13 -04001952 ALLOC(out, C*N, celt_int16);
Jean-Marc Valinf5e2e322010-05-19 12:05:02 -04001953 ret=celt_decode_with_ec(st, data, len, out, frame_size, dec);
Jean-Marc Valinb1e017f2010-07-18 21:20:35 -04001954 if (ret==0)
1955 for (j=0;j<C*N;j++)
Jean-Marc Valinae01e112010-08-03 21:43:41 -04001956 pcm[j]=out[j]*(1.f/32768.f);
Gregory Maxwell0719f6f2009-07-09 17:07:24 -04001957
Wessel Lubberhuizen33ba6cc2008-10-03 07:09:29 -04001958 RESTORE_STACK;
Gregory Maxwell5f2a74b2008-08-11 23:50:07 -04001959 return ret;
1960}
1961#endif /*DISABLE_FLOAT_API*/
1962#else
Jean-Marc Valinf5e2e322010-05-19 12:05:02 -04001963int 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 -04001964{
Jean-Marc Valin017fa852010-05-06 22:11:48 -04001965 int j, ret, C, N, LM, M;
Jean-Marc Valin234969c2009-10-17 22:12:42 -04001966 VARDECL(celt_sig, out);
Jean-Marc Valincb8780c2009-07-20 23:40:35 -04001967 SAVE_STACK;
Gregory Maxwell17169992009-06-04 15:15:34 -04001968
Gregory Maxwell0719f6f2009-07-09 17:07:24 -04001969 if (pcm==NULL)
1970 return CELT_BAD_ARG;
1971
Jean-Marc Valin017fa852010-05-06 22:11:48 -04001972 for (LM=0;LM<4;LM++)
1973 if (st->mode->shortMdctSize<<LM==frame_size)
1974 break;
1975 if (LM>=MAX_CONFIG_SIZES)
1976 return CELT_BAD_ARG;
1977 M=1<<LM;
1978
Jean-Marc Valin80ed1472009-10-15 21:45:32 -04001979 C = CHANNELS(st->channels);
Jean-Marc Valin017fa852010-05-06 22:11:48 -04001980 N = M*st->mode->shortMdctSize;
Jean-Marc Valin234969c2009-10-17 22:12:42 -04001981 ALLOC(out, C*N, celt_sig);
Gregory Maxwell5f2a74b2008-08-11 23:50:07 -04001982
Jean-Marc Valinf5e2e322010-05-19 12:05:02 -04001983 ret=celt_decode_with_ec_float(st, data, len, out, frame_size, dec);
Gregory Maxwell5f2a74b2008-08-11 23:50:07 -04001984
Jean-Marc Valinb1e017f2010-07-18 21:20:35 -04001985 if (ret==0)
1986 for (j=0;j<C*N;j++)
1987 pcm[j] = FLOAT2INT16 (out[j]);
Gregory Maxwell0719f6f2009-07-09 17:07:24 -04001988
Wessel Lubberhuizen33ba6cc2008-10-03 07:09:29 -04001989 RESTORE_STACK;
Gregory Maxwell5f2a74b2008-08-11 23:50:07 -04001990 return ret;
1991}
1992#endif
John Ridges454d1d02009-05-21 22:38:39 -04001993
Jean-Marc Valinf5e2e322010-05-19 12:05:02 -04001994int celt_decode(CELTDecoder * restrict st, const unsigned char *data, int len, celt_int16 * restrict pcm, int frame_size)
1995{
1996 return celt_decode_with_ec(st, data, len, pcm, frame_size, NULL);
1997}
1998
Jean-Marc Valin4424b5a2010-07-06 19:37:23 -04001999#ifndef DISABLE_FLOAT_API
Jean-Marc Valinf5e2e322010-05-19 12:05:02 -04002000int celt_decode_float(CELTDecoder * restrict st, const unsigned char *data, int len, float * restrict pcm, int frame_size)
2001{
2002 return celt_decode_with_ec_float(st, data, len, pcm, frame_size, NULL);
2003}
Jean-Marc Valin4424b5a2010-07-06 19:37:23 -04002004#endif /* DISABLE_FLOAT_API */
Jean-Marc Valinf5e2e322010-05-19 12:05:02 -04002005
John Ridges454d1d02009-05-21 22:38:39 -04002006int celt_decoder_ctl(CELTDecoder * restrict st, int request, ...)
2007{
2008 va_list ap;
Gregory Maxwell17169992009-06-04 15:15:34 -04002009
John Ridges454d1d02009-05-21 22:38:39 -04002010 va_start(ap, request);
2011 switch (request)
2012 {
Gregory Maxwellf3b44ef2009-06-03 13:37:45 -04002013 case CELT_GET_MODE_REQUEST:
2014 {
2015 const CELTMode ** value = va_arg(ap, const CELTMode**);
2016 if (value==0)
2017 goto bad_arg;
2018 *value=st->mode;
2019 }
2020 break;
Jean-Marc Valin5f961462010-05-19 13:38:10 -04002021 case CELT_SET_START_BAND_REQUEST:
2022 {
2023 celt_int32 value = va_arg(ap, celt_int32);
2024 if (value<0 || value>=st->mode->nbEBands)
2025 goto bad_arg;
2026 st->start = value;
2027 }
2028 break;
Jean-Marc Valin525d7cf2010-07-13 14:14:16 -04002029 case CELT_SET_END_BAND_REQUEST:
2030 {
2031 celt_int32 value = va_arg(ap, celt_int32);
2032 if (value<0 || value>=st->mode->nbEBands)
2033 goto bad_arg;
2034 st->end = value;
2035 }
2036 break;
John Ridges454d1d02009-05-21 22:38:39 -04002037 case CELT_RESET_STATE:
2038 {
Jean-Marc Valinc09807d2010-08-27 17:17:50 -04002039 CELT_MEMSET((char*)&st->DECODER_RESET_START, 0,
2040 celt_decoder_get_size(st->mode, st->channels)-
2041 ((char*)&st->DECODER_RESET_START - (char*)st));
John Ridges454d1d02009-05-21 22:38:39 -04002042 }
2043 break;
2044 default:
2045 goto bad_request;
2046 }
2047 va_end(ap);
2048 return CELT_OK;
John Ridges454d1d02009-05-21 22:38:39 -04002049bad_arg:
2050 va_end(ap);
2051 return CELT_BAD_ARG;
John Ridges454d1d02009-05-21 22:38:39 -04002052bad_request:
2053 va_end(ap);
2054 return CELT_UNIMPLEMENTED;
2055}
Jean-Marc Valinece94a02009-10-16 07:30:14 -04002056
2057const char *celt_strerror(int error)
2058{
2059 static const char *error_strings[8] = {
2060 "success",
2061 "invalid argument",
2062 "invalid mode",
2063 "internal error",
2064 "corrupted stream",
2065 "request not implemented",
2066 "invalid state",
2067 "memory allocation failed"
2068 };
2069 if (error > 0 || error < -7)
2070 return "unknown error";
2071 else
2072 return error_strings[-error];
2073}
2074