blob: 58e7b75a93de895825c40ca3faecf9ad2c797c56 [file] [log] [blame]
Jean-Marc Valin69062102012-11-08 09:42:27 -05001/* Copyright (c) 2007-2008 CSIRO
2 Copyright (c) 2007-2010 Xiph.Org Foundation
3 Copyright (c) 2008 Gregory Maxwell
4 Written by Jean-Marc Valin and Gregory Maxwell */
5/*
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 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18 ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19 LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
20 A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
21 OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
22 EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
23 PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
24 PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
25 LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
26 NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
27 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28*/
29
30#ifdef HAVE_CONFIG_H
31#include "config.h"
32#endif
33
Jean-Marc Valin1ecb7ea2012-11-08 11:25:20 -050034#define CELT_DECODER_C
Jean-Marc Valin69062102012-11-08 09:42:27 -050035
Aurélien Zanellicd4c8242013-05-31 15:07:00 +020036#include "cpu_support.h"
Jean-Marc Valin69062102012-11-08 09:42:27 -050037#include "os_support.h"
38#include "mdct.h"
39#include <math.h>
40#include "celt.h"
41#include "pitch.h"
42#include "bands.h"
43#include "modes.h"
44#include "entcode.h"
45#include "quant_bands.h"
46#include "rate.h"
47#include "stack_alloc.h"
48#include "mathops.h"
49#include "float_cast.h"
50#include <stdarg.h>
51#include "celt_lpc.h"
52#include "vq.h"
53
Jean-Marc Valin9134e962014-01-07 17:50:46 -050054#if defined(SMALL_FOOTPRINT) && defined(FIXED_POINT)
55#define NORM_ALIASING_HACK
56#endif
Jean-Marc Valin69062102012-11-08 09:42:27 -050057/**********************************************************************/
58/* */
59/* DECODER */
60/* */
61/**********************************************************************/
62#define DECODE_BUFFER_SIZE 2048
63
64/** Decoder state
65 @brief Decoder state
66 */
67struct OpusCustomDecoder {
68 const OpusCustomMode *mode;
69 int overlap;
70 int channels;
71 int stream_channels;
72
73 int downsample;
74 int start, end;
75 int signalling;
Jean-Marc Valin18a380a2016-04-20 13:27:06 -040076 int disable_inv;
Aurélien Zanellicd4c8242013-05-31 15:07:00 +020077 int arch;
Jean-Marc Valin69062102012-11-08 09:42:27 -050078
79 /* Everything beyond this point gets cleared on a reset */
80#define DECODER_RESET_START rng
81
82 opus_uint32 rng;
83 int error;
84 int last_pitch_index;
85 int loss_count;
Felicia Lim787eee22016-04-06 11:23:21 +020086 int skip_plc;
Jean-Marc Valin69062102012-11-08 09:42:27 -050087 int postfilter_period;
88 int postfilter_period_old;
89 opus_val16 postfilter_gain;
90 opus_val16 postfilter_gain_old;
91 int postfilter_tapset;
92 int postfilter_tapset_old;
93
94 celt_sig preemph_memD[2];
95
96 celt_sig _decode_mem[1]; /* Size = channels*(DECODE_BUFFER_SIZE+mode->overlap) */
97 /* opus_val16 lpc[], Size = channels*LPC_ORDER */
98 /* opus_val16 oldEBands[], Size = 2*mode->nbEBands */
99 /* opus_val16 oldLogE[], Size = 2*mode->nbEBands */
100 /* opus_val16 oldLogE2[], Size = 2*mode->nbEBands */
101 /* opus_val16 backgroundLogE[], Size = 2*mode->nbEBands */
102};
103
104int celt_decoder_get_size(int channels)
105{
106 const CELTMode *mode = opus_custom_mode_create(48000, 960, NULL);
107 return opus_custom_decoder_get_size(mode, channels);
108}
109
110OPUS_CUSTOM_NOSTATIC int opus_custom_decoder_get_size(const CELTMode *mode, int channels)
111{
112 int size = sizeof(struct CELTDecoder)
113 + (channels*(DECODE_BUFFER_SIZE+mode->overlap)-1)*sizeof(celt_sig)
114 + channels*LPC_ORDER*sizeof(opus_val16)
115 + 4*2*mode->nbEBands*sizeof(opus_val16);
116 return size;
117}
118
119#ifdef CUSTOM_MODES
120CELTDecoder *opus_custom_decoder_create(const CELTMode *mode, int channels, int *error)
121{
122 int ret;
123 CELTDecoder *st = (CELTDecoder *)opus_alloc(opus_custom_decoder_get_size(mode, channels));
124 ret = opus_custom_decoder_init(st, mode, channels);
125 if (ret != OPUS_OK)
126 {
127 opus_custom_decoder_destroy(st);
128 st = NULL;
129 }
130 if (error)
131 *error = ret;
132 return st;
133}
134#endif /* CUSTOM_MODES */
135
136int celt_decoder_init(CELTDecoder *st, opus_int32 sampling_rate, int channels)
137{
138 int ret;
139 ret = opus_custom_decoder_init(st, opus_custom_mode_create(48000, 960, NULL), channels);
140 if (ret != OPUS_OK)
141 return ret;
142 st->downsample = resampling_factor(sampling_rate);
143 if (st->downsample==0)
144 return OPUS_BAD_ARG;
145 else
146 return OPUS_OK;
147}
148
149OPUS_CUSTOM_NOSTATIC int opus_custom_decoder_init(CELTDecoder *st, const CELTMode *mode, int channels)
150{
151 if (channels < 0 || channels > 2)
152 return OPUS_BAD_ARG;
153
154 if (st==NULL)
155 return OPUS_ALLOC_FAIL;
156
157 OPUS_CLEAR((char*)st, opus_custom_decoder_get_size(mode, channels));
158
159 st->mode = mode;
160 st->overlap = mode->overlap;
161 st->stream_channels = st->channels = channels;
162
163 st->downsample = 1;
164 st->start = 0;
165 st->end = st->mode->effEBands;
166 st->signalling = 1;
Jean-Marc Valin18a380a2016-04-20 13:27:06 -0400167#ifdef ENABLE_UPDATE_DRAFT
168 st->disable_inv = channels == 1;
169#else
170 st->disable_inv = 0;
171#endif
Aurélien Zanellicd4c8242013-05-31 15:07:00 +0200172 st->arch = opus_select_arch();
Jean-Marc Valin69062102012-11-08 09:42:27 -0500173
Jean-Marc Valin69062102012-11-08 09:42:27 -0500174 opus_custom_decoder_ctl(st, OPUS_RESET_STATE);
175
176 return OPUS_OK;
177}
178
179#ifdef CUSTOM_MODES
180void opus_custom_decoder_destroy(CELTDecoder *st)
181{
182 opus_free(st);
183}
184#endif /* CUSTOM_MODES */
185
Jean-Marc Valin11dba8d2016-08-14 17:56:45 -0400186#ifndef CUSTOM_MODES
187/* Special case for stereo with no downsampling and no accumulation. This is
188 quite common and we can make it faster by processing both channels in the
189 same loop, reducing overhead due to the dependency loop in the IIR filter. */
190static void deemphasis_stereo_simple(celt_sig *in[], opus_val16 *pcm, int N, const opus_val16 coef0,
191 celt_sig *mem)
192{
193 celt_sig * OPUS_RESTRICT x0;
194 celt_sig * OPUS_RESTRICT x1;
195 celt_sig m0, m1;
196 int j;
197 x0=in[0];
198 x1=in[1];
199 m0 = mem[0];
200 m1 = mem[1];
201 for (j=0;j<N;j++)
202 {
203 celt_sig tmp0, tmp1;
204 /* Add VERY_SMALL to x[] first to reduce dependency chain. */
205 tmp0 = x0[j] + VERY_SMALL + m0;
206 tmp1 = x1[j] + VERY_SMALL + m1;
207 m0 = MULT16_32_Q15(coef0, tmp0);
208 m1 = MULT16_32_Q15(coef0, tmp1);
209 pcm[2*j ] = SCALEOUT(SIG2WORD16(tmp0));
210 pcm[2*j+1] = SCALEOUT(SIG2WORD16(tmp1));
211 }
212 mem[0] = m0;
213 mem[1] = m1;
214}
215#endif
Jean-Marc Valin69062102012-11-08 09:42:27 -0500216
217#ifndef RESYNTH
218static
219#endif
Jean-Marc Valinbdc7b932014-01-06 08:58:38 -0500220void deemphasis(celt_sig *in[], opus_val16 *pcm, int N, int C, int downsample, const opus_val16 *coef,
Jean-Marc Valin4d07b132014-01-06 17:43:20 -0500221 celt_sig *mem, int accum)
Jean-Marc Valin69062102012-11-08 09:42:27 -0500222{
223 int c;
224 int Nd;
Jean-Marc Valin2fe47002013-05-26 18:50:13 -0400225 int apply_downsampling=0;
Jean-Marc Valine368e622013-01-03 14:28:28 -0500226 opus_val16 coef0;
Jean-Marc Valinbdc7b932014-01-06 08:58:38 -0500227 VARDECL(celt_sig, scratch);
228 SAVE_STACK;
Jean-Marc Valin11dba8d2016-08-14 17:56:45 -0400229#ifndef CUSTOM_MODES
230 /* Short version for common case. */
231 if (downsample == 1 && C == 2 && !accum)
232 {
233 deemphasis_stereo_simple(in, pcm, N, coef[0], mem);
234 return;
235 }
236#endif
Jean-Marc Valin4d07b132014-01-06 17:43:20 -0500237#ifndef FIXED_POINT
238 (void)accum;
239 celt_assert(accum==0);
240#endif
Jean-Marc Valinbdc7b932014-01-06 08:58:38 -0500241 ALLOC(scratch, N, celt_sig);
Jean-Marc Valin69062102012-11-08 09:42:27 -0500242 coef0 = coef[0];
Jean-Marc Valin69062102012-11-08 09:42:27 -0500243 Nd = N/downsample;
244 c=0; do {
245 int j;
246 celt_sig * OPUS_RESTRICT x;
247 opus_val16 * OPUS_RESTRICT y;
248 celt_sig m = mem[c];
249 x =in[c];
250 y = pcm+c;
Jean-Marc Valine368e622013-01-03 14:28:28 -0500251#ifdef CUSTOM_MODES
252 if (coef[1] != 0)
Jean-Marc Valin69062102012-11-08 09:42:27 -0500253 {
Jean-Marc Valine368e622013-01-03 14:28:28 -0500254 opus_val16 coef1 = coef[1];
255 opus_val16 coef3 = coef[3];
256 for (j=0;j<N;j++)
257 {
Jean-Marc Valin96408b62013-12-02 20:02:37 -0500258 celt_sig tmp = x[j] + m + VERY_SMALL;
Jean-Marc Valine368e622013-01-03 14:28:28 -0500259 m = MULT16_32_Q15(coef0, tmp)
260 - MULT16_32_Q15(coef1, x[j]);
261 tmp = SHL32(MULT16_32_Q15(coef3, tmp), 2);
262 scratch[j] = tmp;
263 }
Jean-Marc Valin2fe47002013-05-26 18:50:13 -0400264 apply_downsampling=1;
Jean-Marc Valine368e622013-01-03 14:28:28 -0500265 } else
Jean-Marc Valinebdfbfb2013-01-09 11:13:00 -0500266#endif
Jean-Marc Valin2fe47002013-05-26 18:50:13 -0400267 if (downsample>1)
Jean-Marc Valine368e622013-01-03 14:28:28 -0500268 {
269 /* Shortcut for the standard (non-custom modes) case */
Jean-Marc Valin69062102012-11-08 09:42:27 -0500270 for (j=0;j<N;j++)
271 {
Jean-Marc Valin9f7e5022016-08-12 23:49:35 -0400272 celt_sig tmp = x[j] + VERY_SMALL + m;
Jean-Marc Valin69062102012-11-08 09:42:27 -0500273 m = MULT16_32_Q15(coef0, tmp);
274 scratch[j] = tmp;
275 }
Jean-Marc Valin2fe47002013-05-26 18:50:13 -0400276 apply_downsampling=1;
277 } else {
278 /* Shortcut for the standard (non-custom modes) case */
Jean-Marc Valin4d07b132014-01-06 17:43:20 -0500279#ifdef FIXED_POINT
280 if (accum)
Jean-Marc Valin2fe47002013-05-26 18:50:13 -0400281 {
Jean-Marc Valin4d07b132014-01-06 17:43:20 -0500282 for (j=0;j<N;j++)
283 {
284 celt_sig tmp = x[j] + m + VERY_SMALL;
285 m = MULT16_32_Q15(coef0, tmp);
286 y[j*C] = SAT16(ADD32(y[j*C], SCALEOUT(SIG2WORD16(tmp))));
287 }
288 } else
289#endif
290 {
291 for (j=0;j<N;j++)
292 {
Jean-Marc Valin9f7e5022016-08-12 23:49:35 -0400293 celt_sig tmp = x[j] + VERY_SMALL + m;
Jean-Marc Valin4d07b132014-01-06 17:43:20 -0500294 m = MULT16_32_Q15(coef0, tmp);
295 y[j*C] = SCALEOUT(SIG2WORD16(tmp));
296 }
Jean-Marc Valin2fe47002013-05-26 18:50:13 -0400297 }
Jean-Marc Valin69062102012-11-08 09:42:27 -0500298 }
299 mem[c] = m;
300
Jean-Marc Valin2fe47002013-05-26 18:50:13 -0400301 if (apply_downsampling)
302 {
303 /* Perform down-sampling */
Jean-Marc Valin4d07b132014-01-06 17:43:20 -0500304#ifdef FIXED_POINT
305 if (accum)
306 {
307 for (j=0;j<Nd;j++)
308 y[j*C] = SAT16(ADD32(y[j*C], SCALEOUT(SIG2WORD16(scratch[j*downsample]))));
309 } else
310#endif
311 {
312 for (j=0;j<Nd;j++)
313 y[j*C] = SCALEOUT(SIG2WORD16(scratch[j*downsample]));
314 }
Jean-Marc Valin2fe47002013-05-26 18:50:13 -0400315 }
Jean-Marc Valin69062102012-11-08 09:42:27 -0500316 } while (++c<C);
Jean-Marc Valinbdc7b932014-01-06 08:58:38 -0500317 RESTORE_STACK;
Jean-Marc Valin69062102012-11-08 09:42:27 -0500318}
319
Jean-Marc Valinbdc7b932014-01-06 08:58:38 -0500320#ifndef RESYNTH
321static
322#endif
323void celt_synthesis(const CELTMode *mode, celt_norm *X, celt_sig * out_syn[],
Viswanath Puttagunta19c54062015-05-15 12:42:20 -0500324 opus_val16 *oldBandE, int start, int effEnd, int C, int CC,
325 int isTransient, int LM, int downsample,
326 int silence, int arch)
Jean-Marc Valinbdc7b932014-01-06 08:58:38 -0500327{
328 int c, i;
Jean-Marc Valin14ca4ed2014-01-06 09:31:09 -0500329 int M;
330 int b;
331 int B;
332 int N, NB;
333 int shift;
Jean-Marc Valinbdc7b932014-01-06 08:58:38 -0500334 int nbEBands;
Jean-Marc Valinbdc7b932014-01-06 08:58:38 -0500335 int overlap;
336 VARDECL(celt_sig, freq);
337 SAVE_STACK;
338
339 overlap = mode->overlap;
340 nbEBands = mode->nbEBands;
341 N = mode->shortMdctSize<<LM;
342 ALLOC(freq, N, celt_sig); /**< Interleaved signal MDCTs */
343 M = 1<<LM;
Jean-Marc Valin14ca4ed2014-01-06 09:31:09 -0500344
345 if (isTransient)
346 {
347 B = M;
348 NB = mode->shortMdctSize;
349 shift = mode->maxLM;
350 } else {
351 B = 1;
352 NB = mode->shortMdctSize<<LM;
353 shift = mode->maxLM-LM;
354 }
Jean-Marc Valinbdc7b932014-01-06 08:58:38 -0500355
356 if (CC==2&&C==1)
357 {
358 /* Copying a mono streams to two channels */
359 celt_sig *freq2;
360 denormalise_bands(mode, X, freq, oldBandE, start, effEnd, M,
361 downsample, silence);
362 /* Store a temporary copy in the output buffer because the IMDCT destroys its input. */
363 freq2 = out_syn[1]+overlap/2;
364 OPUS_COPY(freq2, freq, N);
Jean-Marc Valin14ca4ed2014-01-06 09:31:09 -0500365 for (b=0;b<B;b++)
Viswanath Puttagunta19c54062015-05-15 12:42:20 -0500366 clt_mdct_backward(&mode->mdct, &freq2[b], out_syn[0]+NB*b, mode->window, overlap, shift, B, arch);
Jean-Marc Valin14ca4ed2014-01-06 09:31:09 -0500367 for (b=0;b<B;b++)
Viswanath Puttagunta19c54062015-05-15 12:42:20 -0500368 clt_mdct_backward(&mode->mdct, &freq[b], out_syn[1]+NB*b, mode->window, overlap, shift, B, arch);
Jean-Marc Valinbdc7b932014-01-06 08:58:38 -0500369 } else if (CC==1&&C==2)
370 {
371 /* Downmixing a stereo stream to mono */
372 celt_sig *freq2;
373 freq2 = out_syn[0]+overlap/2;
374 denormalise_bands(mode, X, freq, oldBandE, start, effEnd, M,
375 downsample, silence);
376 /* Use the output buffer as temp array before downmixing. */
377 denormalise_bands(mode, X+N, freq2, oldBandE+nbEBands, start, effEnd, M,
378 downsample, silence);
379 for (i=0;i<N;i++)
Jean-Marc Valinae332182016-07-22 14:44:24 -0400380 freq[i] = ADD32(HALF32(freq[i]), HALF32(freq2[i]));
Jean-Marc Valin14ca4ed2014-01-06 09:31:09 -0500381 for (b=0;b<B;b++)
Viswanath Puttagunta19c54062015-05-15 12:42:20 -0500382 clt_mdct_backward(&mode->mdct, &freq[b], out_syn[0]+NB*b, mode->window, overlap, shift, B, arch);
Jean-Marc Valinbdc7b932014-01-06 08:58:38 -0500383 } else {
384 /* Normal case (mono or stereo) */
385 c=0; do {
386 denormalise_bands(mode, X+c*N, freq, oldBandE+c*nbEBands, start, effEnd, M,
387 downsample, silence);
Jean-Marc Valin14ca4ed2014-01-06 09:31:09 -0500388 for (b=0;b<B;b++)
Viswanath Puttagunta19c54062015-05-15 12:42:20 -0500389 clt_mdct_backward(&mode->mdct, &freq[b], out_syn[c]+NB*b, mode->window, overlap, shift, B, arch);
Jean-Marc Valinbdc7b932014-01-06 08:58:38 -0500390 } while (++c<CC);
391 }
Jean-Marc Valin1a37d4e2016-07-24 17:40:44 -0400392 /* Saturate IMDCT output so that we can't overflow in the pitch postfilter
393 or in the */
394 c=0; do {
395 for (i=0;i<N;i++)
396 out_syn[c][i] = SATURATE(out_syn[c][i], SIG_SAT);
397 } while (++c<CC);
Jean-Marc Valinbdc7b932014-01-06 08:58:38 -0500398 RESTORE_STACK;
Jean-Marc Valin69062102012-11-08 09:42:27 -0500399}
400
401static void tf_decode(int start, int end, int isTransient, int *tf_res, int LM, ec_dec *dec)
402{
403 int i, curr, tf_select;
404 int tf_select_rsv;
405 int tf_changed;
406 int logp;
407 opus_uint32 budget;
408 opus_uint32 tell;
409
410 budget = dec->storage*8;
411 tell = ec_tell(dec);
412 logp = isTransient ? 2 : 4;
413 tf_select_rsv = LM>0 && tell+logp+1<=budget;
414 budget -= tf_select_rsv;
415 tf_changed = curr = 0;
416 for (i=start;i<end;i++)
417 {
418 if (tell+logp<=budget)
419 {
420 curr ^= ec_dec_bit_logp(dec, logp);
421 tell = ec_tell(dec);
422 tf_changed |= curr;
423 }
424 tf_res[i] = curr;
425 logp = isTransient ? 4 : 5;
426 }
427 tf_select = 0;
428 if (tf_select_rsv &&
429 tf_select_table[LM][4*isTransient+0+tf_changed] !=
430 tf_select_table[LM][4*isTransient+2+tf_changed])
431 {
432 tf_select = ec_dec_bit_logp(dec, 1);
433 }
434 for (i=start;i<end;i++)
435 {
436 tf_res[i] = tf_select_table[LM][4*isTransient+2*tf_select+tf_res[i]];
437 }
438}
439
Timothy B. Terriberry8eb9bb72012-12-07 14:07:22 -0800440/* The maximum pitch lag to allow in the pitch-based PLC. It's possible to save
441 CPU time in the PLC pitch search by making this smaller than MAX_PERIOD. The
442 current value corresponds to a pitch of 66.67 Hz. */
443#define PLC_PITCH_LAG_MAX (720)
444/* The minimum pitch lag to allow in the pitch-based PLC. This corresponds to a
445 pitch of 480 Hz. */
446#define PLC_PITCH_LAG_MIN (100)
Jean-Marc Valin69062102012-11-08 09:42:27 -0500447
Jean-Marc Valinb63e7112014-01-07 15:02:43 -0500448static int celt_plc_pitch_search(celt_sig *decode_mem[2], int C, int arch)
449{
450 int pitch_index;
Jean-Marc Valinb63e7112014-01-07 15:02:43 -0500451 VARDECL( opus_val16, lp_pitch_buf );
Jean-Marc Valine17ca252014-01-07 15:27:02 -0500452 SAVE_STACK;
Jean-Marc Valinb63e7112014-01-07 15:02:43 -0500453 ALLOC( lp_pitch_buf, DECODE_BUFFER_SIZE>>1, opus_val16 );
454 pitch_downsample(decode_mem, lp_pitch_buf,
455 DECODE_BUFFER_SIZE, C, arch);
456 pitch_search(lp_pitch_buf+(PLC_PITCH_LAG_MAX>>1), lp_pitch_buf,
457 DECODE_BUFFER_SIZE-PLC_PITCH_LAG_MAX,
458 PLC_PITCH_LAG_MAX-PLC_PITCH_LAG_MIN, &pitch_index, arch);
459 pitch_index = PLC_PITCH_LAG_MAX-pitch_index;
460 RESTORE_STACK;
461 return pitch_index;
462}
463
Jean-Marc Valin9d1b6fe2014-01-07 04:32:41 -0500464static void celt_decode_lost(CELTDecoder * OPUS_RESTRICT st, int N, int LM)
Jean-Marc Valin69062102012-11-08 09:42:27 -0500465{
466 int c;
Timothy B. Terriberry8eb9bb72012-12-07 14:07:22 -0800467 int i;
Jean-Marc Valin69062102012-11-08 09:42:27 -0500468 const int C = st->channels;
Jean-Marc Valin69062102012-11-08 09:42:27 -0500469 celt_sig *decode_mem[2];
Timothy B. Terriberry8eb9bb72012-12-07 14:07:22 -0800470 celt_sig *out_syn[2];
Jean-Marc Valin69062102012-11-08 09:42:27 -0500471 opus_val16 *lpc;
Jean-Marc Valin69062102012-11-08 09:42:27 -0500472 opus_val16 *oldBandE, *oldLogE, *oldLogE2, *backgroundLogE;
473 const OpusCustomMode *mode;
474 int nbEBands;
475 int overlap;
Timothy B. Terriberry8eb9bb72012-12-07 14:07:22 -0800476 int start;
Timothy B. Terriberry8eb9bb72012-12-07 14:07:22 -0800477 int loss_count;
478 int noise_based;
Jean-Marc Valin69062102012-11-08 09:42:27 -0500479 const opus_int16 *eBands;
Jean-Marc Valin69062102012-11-08 09:42:27 -0500480 SAVE_STACK;
481
482 mode = st->mode;
483 nbEBands = mode->nbEBands;
484 overlap = mode->overlap;
485 eBands = mode->eBands;
486
487 c=0; do {
Timothy B. Terriberry8eb9bb72012-12-07 14:07:22 -0800488 decode_mem[c] = st->_decode_mem + c*(DECODE_BUFFER_SIZE+overlap);
489 out_syn[c] = decode_mem[c]+DECODE_BUFFER_SIZE-N;
Jean-Marc Valin69062102012-11-08 09:42:27 -0500490 } while (++c<C);
Timothy B. Terriberry8eb9bb72012-12-07 14:07:22 -0800491 lpc = (opus_val16*)(st->_decode_mem+(DECODE_BUFFER_SIZE+overlap)*C);
Jean-Marc Valin69062102012-11-08 09:42:27 -0500492 oldBandE = lpc+C*LPC_ORDER;
493 oldLogE = oldBandE + 2*nbEBands;
494 oldLogE2 = oldLogE + 2*nbEBands;
495 backgroundLogE = oldLogE2 + 2*nbEBands;
496
Timothy B. Terriberry8eb9bb72012-12-07 14:07:22 -0800497 loss_count = st->loss_count;
498 start = st->start;
Felicia Lim787eee22016-04-06 11:23:21 +0200499 noise_based = loss_count >= 5 || start != 0 || st->skip_plc;
Timothy B. Terriberry8eb9bb72012-12-07 14:07:22 -0800500 if (noise_based)
Jean-Marc Valin69062102012-11-08 09:42:27 -0500501 {
502 /* Noise-based PLC/CNG */
Jean-Marc Valin9134e962014-01-07 17:50:46 -0500503#ifdef NORM_ALIASING_HACK
Jean-Marc Valin5f807c12014-01-07 04:48:42 -0500504 celt_norm *X;
505#else
Jean-Marc Valin69062102012-11-08 09:42:27 -0500506 VARDECL(celt_norm, X);
Jean-Marc Valin5f807c12014-01-07 04:48:42 -0500507#endif
Jean-Marc Valin69062102012-11-08 09:42:27 -0500508 opus_uint32 seed;
Timothy B. Terriberry8eb9bb72012-12-07 14:07:22 -0800509 int end;
Jean-Marc Valin69062102012-11-08 09:42:27 -0500510 int effEnd;
Jean-Marc Valin1970d5b2015-12-03 13:32:10 -0500511 opus_val16 decay;
Timothy B. Terriberry8eb9bb72012-12-07 14:07:22 -0800512 end = st->end;
513 effEnd = IMAX(start, IMIN(end, mode->effEBands));
Jean-Marc Valin69062102012-11-08 09:42:27 -0500514
Jean-Marc Valin9134e962014-01-07 17:50:46 -0500515#ifdef NORM_ALIASING_HACK
Jean-Marc Valin5f807c12014-01-07 04:48:42 -0500516 /* This is an ugly hack that breaks aliasing rules and would be easily broken,
517 but it saves almost 4kB of stack. */
518 X = (celt_norm*)(out_syn[C-1]+overlap/2);
519#else
Jean-Marc Valin69062102012-11-08 09:42:27 -0500520 ALLOC(X, C*N, celt_norm); /**< Interleaved normalised MDCTs */
Jean-Marc Valin5f807c12014-01-07 04:48:42 -0500521#endif
Jean-Marc Valin69062102012-11-08 09:42:27 -0500522
Jean-Marc Valin1970d5b2015-12-03 13:32:10 -0500523 /* Energy decay */
524 decay = loss_count==0 ? QCONST16(1.5f, DB_SHIFT) : QCONST16(.5f, DB_SHIFT);
525 c=0; do
526 {
527 for (i=start;i<end;i++)
528 oldBandE[c*nbEBands+i] = MAX16(backgroundLogE[c*nbEBands+i], oldBandE[c*nbEBands+i] - decay);
529 } while (++c<C);
Jean-Marc Valin69062102012-11-08 09:42:27 -0500530 seed = st->rng;
531 for (c=0;c<C;c++)
532 {
Timothy B. Terriberry8eb9bb72012-12-07 14:07:22 -0800533 for (i=start;i<effEnd;i++)
Jean-Marc Valin69062102012-11-08 09:42:27 -0500534 {
535 int j;
536 int boffs;
537 int blen;
538 boffs = N*c+(eBands[i]<<LM);
539 blen = (eBands[i+1]-eBands[i])<<LM;
540 for (j=0;j<blen;j++)
541 {
542 seed = celt_lcg_rand(seed);
543 X[boffs+j] = (celt_norm)((opus_int32)seed>>20);
544 }
xiangmingzhuc95c9a02014-04-30 15:48:07 +0800545 renormalise_vector(X+boffs, blen, Q15ONE, st->arch);
Jean-Marc Valin69062102012-11-08 09:42:27 -0500546 }
547 }
548 st->rng = seed;
549
Jean-Marc Valin69062102012-11-08 09:42:27 -0500550 c=0; do {
Timothy B. Terriberry8eb9bb72012-12-07 14:07:22 -0800551 OPUS_MOVE(decode_mem[c], decode_mem[c]+N,
552 DECODE_BUFFER_SIZE-N+(overlap>>1));
Jean-Marc Valin69062102012-11-08 09:42:27 -0500553 } while (++c<C);
Jean-Marc Valinbdc7b932014-01-06 08:58:38 -0500554
Jean-Marc Valin1970d5b2015-12-03 13:32:10 -0500555 celt_synthesis(mode, X, out_syn, oldBandE, start, effEnd, C, C, 0, LM, st->downsample, 0, st->arch);
Jean-Marc Valin69062102012-11-08 09:42:27 -0500556 } else {
557 /* Pitch-based PLC */
Timothy B. Terriberry8eb9bb72012-12-07 14:07:22 -0800558 const opus_val16 *window;
559 opus_val16 fade = Q15ONE;
560 int pitch_index;
Jean-Marc Valine0491e72012-11-29 16:49:46 -0500561 VARDECL(opus_val32, etmp);
Timothy B. Terriberryc152d602013-05-08 10:32:37 -0700562 VARDECL(opus_val16, exc);
Jean-Marc Valin69062102012-11-08 09:42:27 -0500563
Timothy B. Terriberry8eb9bb72012-12-07 14:07:22 -0800564 if (loss_count == 0)
Jean-Marc Valin69062102012-11-08 09:42:27 -0500565 {
Jean-Marc Valinb63e7112014-01-07 15:02:43 -0500566 st->last_pitch_index = pitch_index = celt_plc_pitch_search(decode_mem, C, st->arch);
Jean-Marc Valin69062102012-11-08 09:42:27 -0500567 } else {
568 pitch_index = st->last_pitch_index;
569 fade = QCONST16(.8f,15);
570 }
571
Jean-Marc Valine0491e72012-11-29 16:49:46 -0500572 ALLOC(etmp, overlap, opus_val32);
Timothy B. Terriberryc152d602013-05-08 10:32:37 -0700573 ALLOC(exc, MAX_PERIOD, opus_val16);
Timothy B. Terriberry8eb9bb72012-12-07 14:07:22 -0800574 window = mode->window;
Jean-Marc Valin69062102012-11-08 09:42:27 -0500575 c=0; do {
Jean-Marc Valine0491e72012-11-29 16:49:46 -0500576 opus_val16 decay;
577 opus_val16 attenuation;
Jean-Marc Valin69062102012-11-08 09:42:27 -0500578 opus_val32 S1=0;
Timothy B. Terriberry8eb9bb72012-12-07 14:07:22 -0800579 celt_sig *buf;
580 int extrapolation_offset;
581 int extrapolation_len;
582 int exc_length;
583 int j;
Jean-Marc Valine0491e72012-11-29 16:49:46 -0500584
Timothy B. Terriberry8eb9bb72012-12-07 14:07:22 -0800585 buf = decode_mem[c];
586 for (i=0;i<MAX_PERIOD;i++) {
587 exc[i] = ROUND16(buf[DECODE_BUFFER_SIZE-MAX_PERIOD+i], SIG_SHIFT);
588 }
Jean-Marc Valin69062102012-11-08 09:42:27 -0500589
Timothy B. Terriberry8eb9bb72012-12-07 14:07:22 -0800590 if (loss_count == 0)
Jean-Marc Valin69062102012-11-08 09:42:27 -0500591 {
Timothy B. Terriberryc152d602013-05-08 10:32:37 -0700592 opus_val32 ac[LPC_ORDER+1];
Timothy B. Terriberry8eb9bb72012-12-07 14:07:22 -0800593 /* Compute LPC coefficients for the last MAX_PERIOD samples before
594 the first loss so we can work in the excitation-filter domain. */
Timothy B. Terriberry39386e02013-11-18 13:30:13 -0500595 _celt_autocorr(exc, ac, window, overlap,
596 LPC_ORDER, MAX_PERIOD, st->arch);
Timothy B. Terriberry8eb9bb72012-12-07 14:07:22 -0800597 /* Add a noise floor of -40 dB. */
Jean-Marc Valin69062102012-11-08 09:42:27 -0500598#ifdef FIXED_POINT
599 ac[0] += SHR32(ac[0],13);
600#else
601 ac[0] *= 1.0001f;
602#endif
Timothy B. Terriberry8eb9bb72012-12-07 14:07:22 -0800603 /* Use lag windowing to stabilize the Levinson-Durbin recursion. */
Jean-Marc Valin69062102012-11-08 09:42:27 -0500604 for (i=1;i<=LPC_ORDER;i++)
605 {
606 /*ac[i] *= exp(-.5*(2*M_PI*.002*i)*(2*M_PI*.002*i));*/
607#ifdef FIXED_POINT
608 ac[i] -= MULT16_32_Q15(2*i*i, ac[i]);
609#else
Timothy B. Terriberry8eb9bb72012-12-07 14:07:22 -0800610 ac[i] -= ac[i]*(0.008f*0.008f)*i*i;
Jean-Marc Valin69062102012-11-08 09:42:27 -0500611#endif
612 }
Jean-Marc Valin69062102012-11-08 09:42:27 -0500613 _celt_lpc(lpc+c*LPC_ORDER, ac, LPC_ORDER);
Jean-Marc Valinee44ff82016-07-25 10:23:07 -0400614#ifdef FIXED_POINT
615 /* For fixed-point, apply bandwidth expansion until we can guarantee that
616 no overflow can happen in the IIR filter. This means:
617 32768*sum(abs(filter)) < 2^31 */
618 while (1) {
619 opus_val16 tmp=Q15ONE;
620 opus_val32 sum=QCONST16(1., SIG_SHIFT);
621 for (i=0;i<LPC_ORDER;i++)
622 sum += ABS16(lpc[c*LPC_ORDER+i]);
623 if (sum < 65535) break;
624 for (i=0;i<LPC_ORDER;i++)
625 {
626 tmp = MULT16_16_Q15(QCONST16(.99f,15), tmp);
627 lpc[c*LPC_ORDER+i] = MULT16_16_Q15(lpc[c*LPC_ORDER+i], tmp);
628 }
629 }
630#endif
Jean-Marc Valin69062102012-11-08 09:42:27 -0500631 }
Timothy B. Terriberry8eb9bb72012-12-07 14:07:22 -0800632 /* We want the excitation for 2 pitch periods in order to look for a
633 decaying signal, but we can't get more than MAX_PERIOD. */
634 exc_length = IMIN(2*pitch_index, MAX_PERIOD);
635 /* Initialize the LPC history with the samples just before the start
636 of the region for which we're computing the excitation. */
Timothy B. Terriberry8eb9bb72012-12-07 14:07:22 -0800637 {
Timothy B. Terriberryc152d602013-05-08 10:32:37 -0700638 opus_val16 lpc_mem[LPC_ORDER];
639 for (i=0;i<LPC_ORDER;i++)
640 {
641 lpc_mem[i] =
642 ROUND16(buf[DECODE_BUFFER_SIZE-exc_length-1-i], SIG_SHIFT);
643 }
644 /* Compute the excitation for exc_length samples before the loss. */
645 celt_fir(exc+MAX_PERIOD-exc_length, lpc+c*LPC_ORDER,
xiangmingzhuc95c9a02014-04-30 15:48:07 +0800646 exc+MAX_PERIOD-exc_length, exc_length, LPC_ORDER, lpc_mem, st->arch);
Timothy B. Terriberry8eb9bb72012-12-07 14:07:22 -0800647 }
Jean-Marc Valin0094c882012-11-29 17:59:50 -0500648
Timothy B. Terriberry8eb9bb72012-12-07 14:07:22 -0800649 /* Check if the waveform is decaying, and if so how fast.
Jean-Marc Valin0094c882012-11-29 17:59:50 -0500650 We do this to avoid adding energy when concealing in a segment
Timothy B. Terriberry8eb9bb72012-12-07 14:07:22 -0800651 with decaying energy. */
Jean-Marc Valin69062102012-11-08 09:42:27 -0500652 {
653 opus_val32 E1=1, E2=1;
Timothy B. Terriberry8eb9bb72012-12-07 14:07:22 -0800654 int decay_length;
Jean-Marc Valinefdd3142013-05-18 02:14:24 -0400655#ifdef FIXED_POINT
656 int shift = IMAX(0,2*celt_zlog2(celt_maxabs16(&exc[MAX_PERIOD-exc_length], exc_length))-20);
657#endif
Timothy B. Terriberry8eb9bb72012-12-07 14:07:22 -0800658 decay_length = exc_length>>1;
659 for (i=0;i<decay_length;i++)
Jean-Marc Valin69062102012-11-08 09:42:27 -0500660 {
Timothy B. Terriberry8eb9bb72012-12-07 14:07:22 -0800661 opus_val16 e;
662 e = exc[MAX_PERIOD-decay_length+i];
Jean-Marc Valinefdd3142013-05-18 02:14:24 -0400663 E1 += SHR32(MULT16_16(e, e), shift);
Timothy B. Terriberry8eb9bb72012-12-07 14:07:22 -0800664 e = exc[MAX_PERIOD-2*decay_length+i];
Jean-Marc Valinefdd3142013-05-18 02:14:24 -0400665 E2 += SHR32(MULT16_16(e, e), shift);
Jean-Marc Valin69062102012-11-08 09:42:27 -0500666 }
Timothy B. Terriberry8eb9bb72012-12-07 14:07:22 -0800667 E1 = MIN32(E1, E2);
668 decay = celt_sqrt(frac_div32(SHR32(E1, 1), E2));
Jean-Marc Valin69062102012-11-08 09:42:27 -0500669 }
670
Timothy B. Terriberry8eb9bb72012-12-07 14:07:22 -0800671 /* Move the decoder memory one frame to the left to give us room to
672 add the data for the new frame. We ignore the overlap that extends
673 past the end of the buffer, because we aren't going to use it. */
674 OPUS_MOVE(buf, buf+N, DECODE_BUFFER_SIZE-N);
Jean-Marc Valine0491e72012-11-29 16:49:46 -0500675
Timothy B. Terriberry8eb9bb72012-12-07 14:07:22 -0800676 /* Extrapolate from the end of the excitation with a period of
677 "pitch_index", scaling down each period by an additional factor of
678 "decay". */
679 extrapolation_offset = MAX_PERIOD-pitch_index;
680 /* We need to extrapolate enough samples to cover a complete MDCT
681 window (including overlap/2 samples on both sides). */
682 extrapolation_len = N+overlap;
683 /* We also apply fading if this is not the first loss. */
684 attenuation = MULT16_16_Q15(fade, decay);
685 for (i=j=0;i<extrapolation_len;i++,j++)
Jean-Marc Valin69062102012-11-08 09:42:27 -0500686 {
687 opus_val16 tmp;
Timothy B. Terriberry8eb9bb72012-12-07 14:07:22 -0800688 if (j >= pitch_index) {
689 j -= pitch_index;
Jean-Marc Valine0491e72012-11-29 16:49:46 -0500690 attenuation = MULT16_16_Q15(attenuation, decay);
Jean-Marc Valin69062102012-11-08 09:42:27 -0500691 }
Timothy B. Terriberry8eb9bb72012-12-07 14:07:22 -0800692 buf[DECODE_BUFFER_SIZE-N+i] =
693 SHL32(EXTEND32(MULT16_16_Q15(attenuation,
694 exc[extrapolation_offset+j])), SIG_SHIFT);
Jean-Marc Valin027a2022012-12-01 22:00:53 -0500695 /* Compute the energy of the previously decoded signal whose
Timothy B. Terriberry8eb9bb72012-12-07 14:07:22 -0800696 excitation we're copying. */
697 tmp = ROUND16(
698 buf[DECODE_BUFFER_SIZE-MAX_PERIOD-N+extrapolation_offset+j],
699 SIG_SHIFT);
Jean-Marc Valin52ded422016-07-24 17:48:40 -0400700 S1 += SHR32(MULT16_16(tmp, tmp), 10);
Jean-Marc Valin69062102012-11-08 09:42:27 -0500701 }
Timothy B. Terriberryc152d602013-05-08 10:32:37 -0700702 {
703 opus_val16 lpc_mem[LPC_ORDER];
704 /* Copy the last decoded samples (prior to the overlap region) to
705 synthesis filter memory so we can have a continuous signal. */
706 for (i=0;i<LPC_ORDER;i++)
707 lpc_mem[i] = ROUND16(buf[DECODE_BUFFER_SIZE-N-1-i], SIG_SHIFT);
708 /* Apply the synthesis filter to convert the excitation back into
709 the signal domain. */
710 celt_iir(buf+DECODE_BUFFER_SIZE-N, lpc+c*LPC_ORDER,
711 buf+DECODE_BUFFER_SIZE-N, extrapolation_len, LPC_ORDER,
xiangmingzhuc95c9a02014-04-30 15:48:07 +0800712 lpc_mem, st->arch);
Jean-Marc Valin646fcc32016-07-22 11:47:01 -0400713#ifdef FIXED_POINT
714 for (i=0; i < extrapolation_len; i++)
715 buf[DECODE_BUFFER_SIZE-N+i] = SATURATE(buf[DECODE_BUFFER_SIZE-N+i], SIG_SAT);
716#endif
Timothy B. Terriberryc152d602013-05-08 10:32:37 -0700717 }
Jean-Marc Valin69062102012-11-08 09:42:27 -0500718
Jean-Marc Valin0094c882012-11-29 17:59:50 -0500719 /* Check if the synthesis energy is higher than expected, which can
Timothy B. Terriberry8eb9bb72012-12-07 14:07:22 -0800720 happen with the signal changes during our window. If so,
721 attenuate. */
Jean-Marc Valin69062102012-11-08 09:42:27 -0500722 {
723 opus_val32 S2=0;
Timothy B. Terriberry8eb9bb72012-12-07 14:07:22 -0800724 for (i=0;i<extrapolation_len;i++)
Jean-Marc Valin69062102012-11-08 09:42:27 -0500725 {
Timothy B. Terriberry8eb9bb72012-12-07 14:07:22 -0800726 opus_val16 tmp = ROUND16(buf[DECODE_BUFFER_SIZE-N+i], SIG_SHIFT);
Jean-Marc Valin52ded422016-07-24 17:48:40 -0400727 S2 += SHR32(MULT16_16(tmp, tmp), 10);
Jean-Marc Valin69062102012-11-08 09:42:27 -0500728 }
Timothy B. Terriberry8eb9bb72012-12-07 14:07:22 -0800729 /* This checks for an "explosion" in the synthesis. */
Jean-Marc Valin69062102012-11-08 09:42:27 -0500730#ifdef FIXED_POINT
731 if (!(S1 > SHR32(S2,2)))
732#else
Timothy B. Terriberry8eb9bb72012-12-07 14:07:22 -0800733 /* The float test is written this way to catch NaNs in the output
734 of the IIR filter at the same time. */
Jean-Marc Valine0491e72012-11-29 16:49:46 -0500735 if (!(S1 > 0.2f*S2))
Jean-Marc Valin69062102012-11-08 09:42:27 -0500736#endif
Jean-Marc Valine0491e72012-11-29 16:49:46 -0500737 {
Timothy B. Terriberry8eb9bb72012-12-07 14:07:22 -0800738 for (i=0;i<extrapolation_len;i++)
739 buf[DECODE_BUFFER_SIZE-N+i] = 0;
Jean-Marc Valine0491e72012-11-29 16:49:46 -0500740 } else if (S1 < S2)
741 {
742 opus_val16 ratio = celt_sqrt(frac_div32(SHR32(S1,1)+1,S2+1));
743 for (i=0;i<overlap;i++)
Jean-Marc Valin69062102012-11-08 09:42:27 -0500744 {
Timothy B. Terriberry8eb9bb72012-12-07 14:07:22 -0800745 opus_val16 tmp_g = Q15ONE
746 - MULT16_16_Q15(window[i], Q15ONE-ratio);
747 buf[DECODE_BUFFER_SIZE-N+i] =
748 MULT16_32_Q15(tmp_g, buf[DECODE_BUFFER_SIZE-N+i]);
Jean-Marc Valin69062102012-11-08 09:42:27 -0500749 }
Timothy B. Terriberry8eb9bb72012-12-07 14:07:22 -0800750 for (i=overlap;i<extrapolation_len;i++)
751 {
752 buf[DECODE_BUFFER_SIZE-N+i] =
753 MULT16_32_Q15(ratio, buf[DECODE_BUFFER_SIZE-N+i]);
754 }
Jean-Marc Valine0491e72012-11-29 16:49:46 -0500755 }
Jean-Marc Valin69062102012-11-08 09:42:27 -0500756 }
757
Timothy B. Terriberry8eb9bb72012-12-07 14:07:22 -0800758 /* Apply the pre-filter to the MDCT overlap for the next frame because
759 the post-filter will be re-applied in the decoder after the MDCT
760 overlap. */
761 comb_filter(etmp, buf+DECODE_BUFFER_SIZE,
762 st->postfilter_period, st->postfilter_period, overlap,
763 -st->postfilter_gain, -st->postfilter_gain,
Jonathan Lennox43120f02015-08-03 17:04:27 -0400764 st->postfilter_tapset, st->postfilter_tapset, NULL, 0, st->arch);
Jean-Marc Valin69062102012-11-08 09:42:27 -0500765
Jean-Marc Valin0094c882012-11-29 17:59:50 -0500766 /* Simulate TDAC on the concealed audio so that it blends with the
Timothy B. Terriberry8eb9bb72012-12-07 14:07:22 -0800767 MDCT of the next frame. */
Jean-Marc Valin69062102012-11-08 09:42:27 -0500768 for (i=0;i<overlap/2;i++)
769 {
Timothy B. Terriberry8eb9bb72012-12-07 14:07:22 -0800770 buf[DECODE_BUFFER_SIZE+i] =
771 MULT16_32_Q15(window[i], etmp[overlap-1-i])
772 + MULT16_32_Q15(window[overlap-i-1], etmp[i]);
Jean-Marc Valin69062102012-11-08 09:42:27 -0500773 }
Jean-Marc Valin69062102012-11-08 09:42:27 -0500774 } while (++c<C);
775 }
776
Timothy B. Terriberry8eb9bb72012-12-07 14:07:22 -0800777 st->loss_count = loss_count+1;
Jean-Marc Valin69062102012-11-08 09:42:27 -0500778
779 RESTORE_STACK;
780}
781
Jean-Marc Valin4d07b132014-01-06 17:43:20 -0500782int celt_decode_with_ec(CELTDecoder * OPUS_RESTRICT st, const unsigned char *data,
783 int len, opus_val16 * OPUS_RESTRICT pcm, int frame_size, ec_dec *dec, int accum)
Jean-Marc Valin69062102012-11-08 09:42:27 -0500784{
785 int c, i, N;
786 int spread_decision;
787 opus_int32 bits;
788 ec_dec _dec;
Jean-Marc Valin9134e962014-01-07 17:50:46 -0500789#ifdef NORM_ALIASING_HACK
Jean-Marc Valin32454dc2014-01-06 09:11:52 -0500790 celt_norm *X;
791#else
Jean-Marc Valin69062102012-11-08 09:42:27 -0500792 VARDECL(celt_norm, X);
Jean-Marc Valin32454dc2014-01-06 09:11:52 -0500793#endif
Jean-Marc Valin69062102012-11-08 09:42:27 -0500794 VARDECL(int, fine_quant);
795 VARDECL(int, pulses);
796 VARDECL(int, cap);
797 VARDECL(int, offsets);
798 VARDECL(int, fine_priority);
799 VARDECL(int, tf_res);
800 VARDECL(unsigned char, collapse_masks);
Jean-Marc Valin69062102012-11-08 09:42:27 -0500801 celt_sig *decode_mem[2];
802 celt_sig *out_syn[2];
803 opus_val16 *lpc;
804 opus_val16 *oldBandE, *oldLogE, *oldLogE2, *backgroundLogE;
805
806 int shortBlocks;
807 int isTransient;
808 int intra_ener;
809 const int CC = st->channels;
810 int LM, M;
Jean-Marc Valin91f80102013-12-10 18:38:44 -0500811 int start;
812 int end;
Jean-Marc Valin69062102012-11-08 09:42:27 -0500813 int effEnd;
814 int codedBands;
815 int alloc_trim;
816 int postfilter_pitch;
817 opus_val16 postfilter_gain;
818 int intensity=0;
819 int dual_stereo=0;
820 opus_int32 total_bits;
821 opus_int32 balance;
822 opus_int32 tell;
823 int dynalloc_logp;
824 int postfilter_tapset;
825 int anti_collapse_rsv;
826 int anti_collapse_on=0;
827 int silence;
828 int C = st->stream_channels;
829 const OpusCustomMode *mode;
830 int nbEBands;
831 int overlap;
832 const opus_int16 *eBands;
833 ALLOC_STACK;
834
835 mode = st->mode;
836 nbEBands = mode->nbEBands;
837 overlap = mode->overlap;
838 eBands = mode->eBands;
Jean-Marc Valin91f80102013-12-10 18:38:44 -0500839 start = st->start;
840 end = st->end;
Jean-Marc Valin69062102012-11-08 09:42:27 -0500841 frame_size *= st->downsample;
842
Jean-Marc Valin69062102012-11-08 09:42:27 -0500843 lpc = (opus_val16*)(st->_decode_mem+(DECODE_BUFFER_SIZE+overlap)*CC);
844 oldBandE = lpc+CC*LPC_ORDER;
845 oldLogE = oldBandE + 2*nbEBands;
846 oldLogE2 = oldLogE + 2*nbEBands;
847 backgroundLogE = oldLogE2 + 2*nbEBands;
848
849#ifdef CUSTOM_MODES
850 if (st->signalling && data!=NULL)
851 {
852 int data0=data[0];
853 /* Convert "standard mode" to Opus header */
854 if (mode->Fs==48000 && mode->shortMdctSize==120)
855 {
856 data0 = fromOpus(data0);
857 if (data0<0)
858 return OPUS_INVALID_PACKET;
859 }
Jean-Marc Valin91f80102013-12-10 18:38:44 -0500860 st->end = end = IMAX(1, mode->effEBands-2*(data0>>5));
Jean-Marc Valin69062102012-11-08 09:42:27 -0500861 LM = (data0>>3)&0x3;
862 C = 1 + ((data0>>2)&0x1);
863 data++;
864 len--;
865 if (LM>mode->maxLM)
866 return OPUS_INVALID_PACKET;
867 if (frame_size < mode->shortMdctSize<<LM)
868 return OPUS_BUFFER_TOO_SMALL;
869 else
870 frame_size = mode->shortMdctSize<<LM;
871 } else {
872#else
873 {
874#endif
875 for (LM=0;LM<=mode->maxLM;LM++)
876 if (mode->shortMdctSize<<LM==frame_size)
877 break;
878 if (LM>mode->maxLM)
879 return OPUS_BAD_ARG;
880 }
881 M=1<<LM;
882
883 if (len<0 || len>1275 || pcm==NULL)
884 return OPUS_BAD_ARG;
885
886 N = M*mode->shortMdctSize;
Jean-Marc Valin9d1b6fe2014-01-07 04:32:41 -0500887 c=0; do {
888 decode_mem[c] = st->_decode_mem + c*(DECODE_BUFFER_SIZE+overlap);
889 out_syn[c] = decode_mem[c]+DECODE_BUFFER_SIZE-N;
890 } while (++c<CC);
Jean-Marc Valin69062102012-11-08 09:42:27 -0500891
Jean-Marc Valin91f80102013-12-10 18:38:44 -0500892 effEnd = end;
Jean-Marc Valin69062102012-11-08 09:42:27 -0500893 if (effEnd > mode->effEBands)
894 effEnd = mode->effEBands;
895
896 if (data == NULL || len<=1)
897 {
Jean-Marc Valin9d1b6fe2014-01-07 04:32:41 -0500898 celt_decode_lost(st, N, LM);
899 deemphasis(out_syn, pcm, N, CC, st->downsample, mode->preemph, st->preemph_memD, accum);
Jean-Marc Valin69062102012-11-08 09:42:27 -0500900 RESTORE_STACK;
901 return frame_size/st->downsample;
902 }
903
Felicia Lim787eee22016-04-06 11:23:21 +0200904 /* Check if there are at least two packets received consecutively before
905 * turning on the pitch-based PLC */
906 st->skip_plc = st->loss_count != 0;
907
Jean-Marc Valin69062102012-11-08 09:42:27 -0500908 if (dec == NULL)
909 {
910 ec_dec_init(&_dec,(unsigned char*)data,len);
911 dec = &_dec;
912 }
913
914 if (C==1)
915 {
916 for (i=0;i<nbEBands;i++)
917 oldBandE[i]=MAX16(oldBandE[i],oldBandE[nbEBands+i]);
918 }
919
920 total_bits = len*8;
921 tell = ec_tell(dec);
922
923 if (tell >= total_bits)
924 silence = 1;
925 else if (tell==1)
926 silence = ec_dec_bit_logp(dec, 15);
927 else
928 silence = 0;
929 if (silence)
930 {
931 /* Pretend we've read all the remaining bits */
932 tell = len*8;
933 dec->nbits_total+=tell-ec_tell(dec);
934 }
935
936 postfilter_gain = 0;
937 postfilter_pitch = 0;
938 postfilter_tapset = 0;
Jean-Marc Valin91f80102013-12-10 18:38:44 -0500939 if (start==0 && tell+16 <= total_bits)
Jean-Marc Valin69062102012-11-08 09:42:27 -0500940 {
941 if(ec_dec_bit_logp(dec, 1))
942 {
943 int qg, octave;
944 octave = ec_dec_uint(dec, 6);
945 postfilter_pitch = (16<<octave)+ec_dec_bits(dec, 4+octave)-1;
946 qg = ec_dec_bits(dec, 3);
947 if (ec_tell(dec)+2<=total_bits)
948 postfilter_tapset = ec_dec_icdf(dec, tapset_icdf, 2);
949 postfilter_gain = QCONST16(.09375f,15)*(qg+1);
950 }
951 tell = ec_tell(dec);
952 }
953
954 if (LM > 0 && tell+3 <= total_bits)
955 {
956 isTransient = ec_dec_bit_logp(dec, 3);
957 tell = ec_tell(dec);
958 }
959 else
960 isTransient = 0;
961
962 if (isTransient)
963 shortBlocks = M;
964 else
965 shortBlocks = 0;
966
967 /* Decode the global flags (first symbols in the stream) */
968 intra_ener = tell+3<=total_bits ? ec_dec_bit_logp(dec, 3) : 0;
969 /* Get band energies */
Jean-Marc Valin91f80102013-12-10 18:38:44 -0500970 unquant_coarse_energy(mode, start, end, oldBandE,
Jean-Marc Valin69062102012-11-08 09:42:27 -0500971 intra_ener, dec, C, LM);
972
973 ALLOC(tf_res, nbEBands, int);
Jean-Marc Valin91f80102013-12-10 18:38:44 -0500974 tf_decode(start, end, isTransient, tf_res, LM, dec);
Jean-Marc Valin69062102012-11-08 09:42:27 -0500975
976 tell = ec_tell(dec);
977 spread_decision = SPREAD_NORMAL;
978 if (tell+4 <= total_bits)
979 spread_decision = ec_dec_icdf(dec, spread_icdf, 5);
980
981 ALLOC(cap, nbEBands, int);
982
983 init_caps(mode,cap,LM,C);
984
985 ALLOC(offsets, nbEBands, int);
986
987 dynalloc_logp = 6;
988 total_bits<<=BITRES;
989 tell = ec_tell_frac(dec);
Jean-Marc Valin91f80102013-12-10 18:38:44 -0500990 for (i=start;i<end;i++)
Jean-Marc Valin69062102012-11-08 09:42:27 -0500991 {
992 int width, quanta;
993 int dynalloc_loop_logp;
994 int boost;
995 width = C*(eBands[i+1]-eBands[i])<<LM;
996 /* quanta is 6 bits, but no more than 1 bit/sample
997 and no less than 1/8 bit/sample */
998 quanta = IMIN(width<<BITRES, IMAX(6<<BITRES, width));
999 dynalloc_loop_logp = dynalloc_logp;
1000 boost = 0;
1001 while (tell+(dynalloc_loop_logp<<BITRES) < total_bits && boost < cap[i])
1002 {
1003 int flag;
1004 flag = ec_dec_bit_logp(dec, dynalloc_loop_logp);
1005 tell = ec_tell_frac(dec);
1006 if (!flag)
1007 break;
1008 boost += quanta;
1009 total_bits -= quanta;
1010 dynalloc_loop_logp = 1;
1011 }
1012 offsets[i] = boost;
1013 /* Making dynalloc more likely */
1014 if (boost>0)
1015 dynalloc_logp = IMAX(2, dynalloc_logp-1);
1016 }
1017
1018 ALLOC(fine_quant, nbEBands, int);
1019 alloc_trim = tell+(6<<BITRES) <= total_bits ?
1020 ec_dec_icdf(dec, trim_icdf, 7) : 5;
1021
1022 bits = (((opus_int32)len*8)<<BITRES) - ec_tell_frac(dec) - 1;
1023 anti_collapse_rsv = isTransient&&LM>=2&&bits>=((LM+2)<<BITRES) ? (1<<BITRES) : 0;
1024 bits -= anti_collapse_rsv;
1025
1026 ALLOC(pulses, nbEBands, int);
1027 ALLOC(fine_priority, nbEBands, int);
1028
Jean-Marc Valin91f80102013-12-10 18:38:44 -05001029 codedBands = compute_allocation(mode, start, end, offsets, cap,
Jean-Marc Valin69062102012-11-08 09:42:27 -05001030 alloc_trim, &intensity, &dual_stereo, bits, &balance, pulses,
Jean-Marc Valin5fb50ad2012-12-21 01:23:26 -05001031 fine_quant, fine_priority, C, LM, dec, 0, 0, 0);
Jean-Marc Valin69062102012-11-08 09:42:27 -05001032
Jean-Marc Valin91f80102013-12-10 18:38:44 -05001033 unquant_fine_energy(mode, start, end, oldBandE, fine_quant, dec, C);
Jean-Marc Valin69062102012-11-08 09:42:27 -05001034
Jean-Marc Valin32454dc2014-01-06 09:11:52 -05001035 c=0; do {
1036 OPUS_MOVE(decode_mem[c], decode_mem[c]+N, DECODE_BUFFER_SIZE-N+overlap/2);
Jean-Marc Valin32454dc2014-01-06 09:11:52 -05001037 } while (++c<CC);
1038
Jean-Marc Valin69062102012-11-08 09:42:27 -05001039 /* Decode fixed codebook */
1040 ALLOC(collapse_masks, C*nbEBands, unsigned char);
Jean-Marc Valin32454dc2014-01-06 09:11:52 -05001041
Jean-Marc Valin9134e962014-01-07 17:50:46 -05001042#ifdef NORM_ALIASING_HACK
Jean-Marc Valin32454dc2014-01-06 09:11:52 -05001043 /* This is an ugly hack that breaks aliasing rules and would be easily broken,
1044 but it saves almost 4kB of stack. */
1045 X = (celt_norm*)(out_syn[CC-1]+overlap/2);
1046#else
Jean-Marc Valin69062102012-11-08 09:42:27 -05001047 ALLOC(X, C*N, celt_norm); /**< Interleaved normalised MDCTs */
Jean-Marc Valin32454dc2014-01-06 09:11:52 -05001048#endif
Jean-Marc Valin69062102012-11-08 09:42:27 -05001049
Jean-Marc Valin91f80102013-12-10 18:38:44 -05001050 quant_all_bands(0, mode, start, end, X, C==2 ? X+N : NULL, collapse_masks,
Jean-Marc Valin69062102012-11-08 09:42:27 -05001051 NULL, pulses, shortBlocks, spread_decision, dual_stereo, intensity, tf_res,
Jean-Marc Valin18a380a2016-04-20 13:27:06 -04001052 len*(8<<BITRES)-anti_collapse_rsv, balance, dec, LM, codedBands, &st->rng, 0,
1053 st->arch, st->disable_inv);
Jean-Marc Valin69062102012-11-08 09:42:27 -05001054
1055 if (anti_collapse_rsv > 0)
1056 {
1057 anti_collapse_on = ec_dec_bits(dec, 1);
1058 }
1059
Jean-Marc Valin91f80102013-12-10 18:38:44 -05001060 unquant_energy_finalise(mode, start, end, oldBandE,
Jean-Marc Valin69062102012-11-08 09:42:27 -05001061 fine_quant, fine_priority, len*8-ec_tell(dec), dec, C);
1062
1063 if (anti_collapse_on)
1064 anti_collapse(mode, X, collapse_masks, LM, C, N,
xiangmingzhuc95c9a02014-04-30 15:48:07 +08001065 start, end, oldBandE, oldLogE, oldLogE2, pulses, st->rng, st->arch);
Jean-Marc Valin69062102012-11-08 09:42:27 -05001066
Jean-Marc Valin69062102012-11-08 09:42:27 -05001067 if (silence)
1068 {
1069 for (i=0;i<C*nbEBands;i++)
Jean-Marc Valin69062102012-11-08 09:42:27 -05001070 oldBandE[i] = -QCONST16(28.f,DB_SHIFT);
Jean-Marc Valin69062102012-11-08 09:42:27 -05001071 }
Jean-Marc Valin4a6744a2014-01-05 21:40:02 -05001072
Viswanath Puttagunta19c54062015-05-15 12:42:20 -05001073 celt_synthesis(mode, X, out_syn, oldBandE, start, effEnd,
1074 C, CC, isTransient, LM, st->downsample, silence, st->arch);
Jean-Marc Valin69062102012-11-08 09:42:27 -05001075
1076 c=0; do {
1077 st->postfilter_period=IMAX(st->postfilter_period, COMBFILTER_MINPERIOD);
1078 st->postfilter_period_old=IMAX(st->postfilter_period_old, COMBFILTER_MINPERIOD);
1079 comb_filter(out_syn[c], out_syn[c], st->postfilter_period_old, st->postfilter_period, mode->shortMdctSize,
1080 st->postfilter_gain_old, st->postfilter_gain, st->postfilter_tapset_old, st->postfilter_tapset,
Jonathan Lennox43120f02015-08-03 17:04:27 -04001081 mode->window, overlap, st->arch);
Jean-Marc Valin69062102012-11-08 09:42:27 -05001082 if (LM!=0)
1083 comb_filter(out_syn[c]+mode->shortMdctSize, out_syn[c]+mode->shortMdctSize, st->postfilter_period, postfilter_pitch, N-mode->shortMdctSize,
1084 st->postfilter_gain, postfilter_gain, st->postfilter_tapset, postfilter_tapset,
Jonathan Lennox43120f02015-08-03 17:04:27 -04001085 mode->window, overlap, st->arch);
Jean-Marc Valin69062102012-11-08 09:42:27 -05001086
1087 } while (++c<CC);
1088 st->postfilter_period_old = st->postfilter_period;
1089 st->postfilter_gain_old = st->postfilter_gain;
1090 st->postfilter_tapset_old = st->postfilter_tapset;
1091 st->postfilter_period = postfilter_pitch;
1092 st->postfilter_gain = postfilter_gain;
1093 st->postfilter_tapset = postfilter_tapset;
1094 if (LM!=0)
1095 {
1096 st->postfilter_period_old = st->postfilter_period;
1097 st->postfilter_gain_old = st->postfilter_gain;
1098 st->postfilter_tapset_old = st->postfilter_tapset;
1099 }
1100
Jean-Marc Valind5553e82013-12-10 02:32:26 -05001101 if (C==1)
1102 OPUS_COPY(&oldBandE[nbEBands], oldBandE, nbEBands);
Jean-Marc Valin69062102012-11-08 09:42:27 -05001103
1104 /* In case start or end were to change */
1105 if (!isTransient)
1106 {
Jean-Marc Valincfaf1472015-12-04 16:11:39 -05001107 opus_val16 max_background_increase;
Jean-Marc Valind5553e82013-12-10 02:32:26 -05001108 OPUS_COPY(oldLogE2, oldLogE, 2*nbEBands);
1109 OPUS_COPY(oldLogE, oldBandE, 2*nbEBands);
Jean-Marc Valincfaf1472015-12-04 16:11:39 -05001110 /* In normal circumstances, we only allow the noise floor to increase by
1111 up to 2.4 dB/second, but when we're in DTX, we allow up to 6 dB
1112 increase for each update.*/
1113 if (st->loss_count < 10)
1114 max_background_increase = M*QCONST16(0.001f,DB_SHIFT);
1115 else
1116 max_background_increase = QCONST16(1.f,DB_SHIFT);
Jean-Marc Valin69062102012-11-08 09:42:27 -05001117 for (i=0;i<2*nbEBands;i++)
Jean-Marc Valincfaf1472015-12-04 16:11:39 -05001118 backgroundLogE[i] = MIN16(backgroundLogE[i] + max_background_increase, oldBandE[i]);
Jean-Marc Valin69062102012-11-08 09:42:27 -05001119 } else {
1120 for (i=0;i<2*nbEBands;i++)
1121 oldLogE[i] = MIN16(oldLogE[i], oldBandE[i]);
1122 }
1123 c=0; do
1124 {
Jean-Marc Valin91f80102013-12-10 18:38:44 -05001125 for (i=0;i<start;i++)
Jean-Marc Valin69062102012-11-08 09:42:27 -05001126 {
1127 oldBandE[c*nbEBands+i]=0;
1128 oldLogE[c*nbEBands+i]=oldLogE2[c*nbEBands+i]=-QCONST16(28.f,DB_SHIFT);
1129 }
Jean-Marc Valin91f80102013-12-10 18:38:44 -05001130 for (i=end;i<nbEBands;i++)
Jean-Marc Valin69062102012-11-08 09:42:27 -05001131 {
1132 oldBandE[c*nbEBands+i]=0;
1133 oldLogE[c*nbEBands+i]=oldLogE2[c*nbEBands+i]=-QCONST16(28.f,DB_SHIFT);
1134 }
1135 } while (++c<2);
1136 st->rng = dec->rng;
1137
Jean-Marc Valin4d07b132014-01-06 17:43:20 -05001138 deemphasis(out_syn, pcm, N, CC, st->downsample, mode->preemph, st->preemph_memD, accum);
Jean-Marc Valin69062102012-11-08 09:42:27 -05001139 st->loss_count = 0;
1140 RESTORE_STACK;
1141 if (ec_tell(dec) > 8*len)
1142 return OPUS_INTERNAL_ERROR;
1143 if(ec_get_error(dec))
1144 st->error = 1;
1145 return frame_size/st->downsample;
1146}
1147
1148
1149#ifdef CUSTOM_MODES
1150
1151#ifdef FIXED_POINT
1152int opus_custom_decode(CELTDecoder * OPUS_RESTRICT st, const unsigned char *data, int len, opus_int16 * OPUS_RESTRICT pcm, int frame_size)
1153{
Jean-Marc Valin4d07b132014-01-06 17:43:20 -05001154 return celt_decode_with_ec(st, data, len, pcm, frame_size, NULL, 0);
Jean-Marc Valin69062102012-11-08 09:42:27 -05001155}
1156
1157#ifndef DISABLE_FLOAT_API
1158int opus_custom_decode_float(CELTDecoder * OPUS_RESTRICT st, const unsigned char *data, int len, float * OPUS_RESTRICT pcm, int frame_size)
1159{
1160 int j, ret, C, N;
1161 VARDECL(opus_int16, out);
1162 ALLOC_STACK;
1163
1164 if (pcm==NULL)
1165 return OPUS_BAD_ARG;
1166
1167 C = st->channels;
1168 N = frame_size;
1169
1170 ALLOC(out, C*N, opus_int16);
Jean-Marc Valin4d07b132014-01-06 17:43:20 -05001171 ret=celt_decode_with_ec(st, data, len, out, frame_size, NULL, 0);
Jean-Marc Valin69062102012-11-08 09:42:27 -05001172 if (ret>0)
1173 for (j=0;j<C*ret;j++)
1174 pcm[j]=out[j]*(1.f/32768.f);
1175
1176 RESTORE_STACK;
1177 return ret;
1178}
1179#endif /* DISABLE_FLOAT_API */
1180
1181#else
1182
1183int opus_custom_decode_float(CELTDecoder * OPUS_RESTRICT st, const unsigned char *data, int len, float * OPUS_RESTRICT pcm, int frame_size)
1184{
Jean-Marc Valin4d07b132014-01-06 17:43:20 -05001185 return celt_decode_with_ec(st, data, len, pcm, frame_size, NULL, 0);
Jean-Marc Valin69062102012-11-08 09:42:27 -05001186}
1187
1188int opus_custom_decode(CELTDecoder * OPUS_RESTRICT st, const unsigned char *data, int len, opus_int16 * OPUS_RESTRICT pcm, int frame_size)
1189{
1190 int j, ret, C, N;
1191 VARDECL(celt_sig, out);
1192 ALLOC_STACK;
1193
1194 if (pcm==NULL)
1195 return OPUS_BAD_ARG;
1196
1197 C = st->channels;
1198 N = frame_size;
1199 ALLOC(out, C*N, celt_sig);
1200
Jean-Marc Valin4d07b132014-01-06 17:43:20 -05001201 ret=celt_decode_with_ec(st, data, len, out, frame_size, NULL, 0);
Jean-Marc Valin69062102012-11-08 09:42:27 -05001202
1203 if (ret>0)
1204 for (j=0;j<C*ret;j++)
1205 pcm[j] = FLOAT2INT16 (out[j]);
1206
1207 RESTORE_STACK;
1208 return ret;
1209}
1210
1211#endif
1212#endif /* CUSTOM_MODES */
1213
1214int opus_custom_decoder_ctl(CELTDecoder * OPUS_RESTRICT st, int request, ...)
1215{
1216 va_list ap;
1217
1218 va_start(ap, request);
1219 switch (request)
1220 {
1221 case CELT_SET_START_BAND_REQUEST:
1222 {
1223 opus_int32 value = va_arg(ap, opus_int32);
1224 if (value<0 || value>=st->mode->nbEBands)
1225 goto bad_arg;
1226 st->start = value;
1227 }
1228 break;
1229 case CELT_SET_END_BAND_REQUEST:
1230 {
1231 opus_int32 value = va_arg(ap, opus_int32);
1232 if (value<1 || value>st->mode->nbEBands)
1233 goto bad_arg;
1234 st->end = value;
1235 }
1236 break;
1237 case CELT_SET_CHANNELS_REQUEST:
1238 {
1239 opus_int32 value = va_arg(ap, opus_int32);
1240 if (value<1 || value>2)
1241 goto bad_arg;
1242 st->stream_channels = value;
1243 }
1244 break;
1245 case CELT_GET_AND_CLEAR_ERROR_REQUEST:
1246 {
1247 opus_int32 *value = va_arg(ap, opus_int32*);
1248 if (value==NULL)
1249 goto bad_arg;
1250 *value=st->error;
1251 st->error = 0;
1252 }
1253 break;
1254 case OPUS_GET_LOOKAHEAD_REQUEST:
1255 {
1256 opus_int32 *value = va_arg(ap, opus_int32*);
1257 if (value==NULL)
1258 goto bad_arg;
1259 *value = st->overlap/st->downsample;
1260 }
1261 break;
1262 case OPUS_RESET_STATE:
1263 {
1264 int i;
1265 opus_val16 *lpc, *oldBandE, *oldLogE, *oldLogE2;
1266 lpc = (opus_val16*)(st->_decode_mem+(DECODE_BUFFER_SIZE+st->overlap)*st->channels);
1267 oldBandE = lpc+st->channels*LPC_ORDER;
1268 oldLogE = oldBandE + 2*st->mode->nbEBands;
1269 oldLogE2 = oldLogE + 2*st->mode->nbEBands;
1270 OPUS_CLEAR((char*)&st->DECODER_RESET_START,
1271 opus_custom_decoder_get_size(st->mode, st->channels)-
1272 ((char*)&st->DECODER_RESET_START - (char*)st));
1273 for (i=0;i<2*st->mode->nbEBands;i++)
1274 oldLogE[i]=oldLogE2[i]=-QCONST16(28.f,DB_SHIFT);
Felicia Lim787eee22016-04-06 11:23:21 +02001275 st->skip_plc = 1;
Jean-Marc Valin69062102012-11-08 09:42:27 -05001276 }
1277 break;
1278 case OPUS_GET_PITCH_REQUEST:
1279 {
1280 opus_int32 *value = va_arg(ap, opus_int32*);
1281 if (value==NULL)
1282 goto bad_arg;
1283 *value = st->postfilter_period;
1284 }
1285 break;
Jean-Marc Valin69062102012-11-08 09:42:27 -05001286 case CELT_GET_MODE_REQUEST:
1287 {
1288 const CELTMode ** value = va_arg(ap, const CELTMode**);
1289 if (value==0)
1290 goto bad_arg;
1291 *value=st->mode;
1292 }
1293 break;
1294 case CELT_SET_SIGNALLING_REQUEST:
1295 {
1296 opus_int32 value = va_arg(ap, opus_int32);
1297 st->signalling = value;
1298 }
1299 break;
1300 case OPUS_GET_FINAL_RANGE_REQUEST:
1301 {
1302 opus_uint32 * value = va_arg(ap, opus_uint32 *);
1303 if (value==0)
1304 goto bad_arg;
1305 *value=st->rng;
1306 }
1307 break;
Jean-Marc Valin18a380a2016-04-20 13:27:06 -04001308 case OPUS_SET_PHASE_INVERSION_DISABLED_REQUEST:
1309 {
1310 opus_int32 value = va_arg(ap, opus_int32);
1311 if(value<0 || value>1)
1312 {
1313 goto bad_arg;
1314 }
1315 st->disable_inv = value;
1316 }
1317 break;
1318 case OPUS_GET_PHASE_INVERSION_DISABLED_REQUEST:
1319 {
1320 opus_int32 *value = va_arg(ap, opus_int32*);
1321 if (!value)
1322 {
1323 goto bad_arg;
1324 }
1325 *value = st->disable_inv;
1326 }
1327 break;
Jean-Marc Valin69062102012-11-08 09:42:27 -05001328 default:
1329 goto bad_request;
1330 }
1331 va_end(ap);
1332 return OPUS_OK;
1333bad_arg:
1334 va_end(ap);
1335 return OPUS_BAD_ARG;
1336bad_request:
1337 va_end(ap);
1338 return OPUS_UNIMPLEMENTED;
1339}