annotate src/opus-1.3/celt/celt_decoder.c @ 73:02caadb7509e

Rebuild with --disable-stack-protector for mingw32
author Chris Cannam
date Fri, 25 Jan 2019 14:31:07 +0000
parents 7aeed7906520
children
rev   line source
Chris@69 1 /* Copyright (c) 2007-2008 CSIRO
Chris@69 2 Copyright (c) 2007-2010 Xiph.Org Foundation
Chris@69 3 Copyright (c) 2008 Gregory Maxwell
Chris@69 4 Written by Jean-Marc Valin and Gregory Maxwell */
Chris@69 5 /*
Chris@69 6 Redistribution and use in source and binary forms, with or without
Chris@69 7 modification, are permitted provided that the following conditions
Chris@69 8 are met:
Chris@69 9
Chris@69 10 - Redistributions of source code must retain the above copyright
Chris@69 11 notice, this list of conditions and the following disclaimer.
Chris@69 12
Chris@69 13 - Redistributions in binary form must reproduce the above copyright
Chris@69 14 notice, this list of conditions and the following disclaimer in the
Chris@69 15 documentation and/or other materials provided with the distribution.
Chris@69 16
Chris@69 17 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
Chris@69 18 ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
Chris@69 19 LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
Chris@69 20 A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
Chris@69 21 OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
Chris@69 22 EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
Chris@69 23 PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
Chris@69 24 PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
Chris@69 25 LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
Chris@69 26 NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
Chris@69 27 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Chris@69 28 */
Chris@69 29
Chris@69 30 #ifdef HAVE_CONFIG_H
Chris@69 31 #include "config.h"
Chris@69 32 #endif
Chris@69 33
Chris@69 34 #define CELT_DECODER_C
Chris@69 35
Chris@69 36 #include "cpu_support.h"
Chris@69 37 #include "os_support.h"
Chris@69 38 #include "mdct.h"
Chris@69 39 #include <math.h>
Chris@69 40 #include "celt.h"
Chris@69 41 #include "pitch.h"
Chris@69 42 #include "bands.h"
Chris@69 43 #include "modes.h"
Chris@69 44 #include "entcode.h"
Chris@69 45 #include "quant_bands.h"
Chris@69 46 #include "rate.h"
Chris@69 47 #include "stack_alloc.h"
Chris@69 48 #include "mathops.h"
Chris@69 49 #include "float_cast.h"
Chris@69 50 #include <stdarg.h>
Chris@69 51 #include "celt_lpc.h"
Chris@69 52 #include "vq.h"
Chris@69 53
Chris@69 54 /* The maximum pitch lag to allow in the pitch-based PLC. It's possible to save
Chris@69 55 CPU time in the PLC pitch search by making this smaller than MAX_PERIOD. The
Chris@69 56 current value corresponds to a pitch of 66.67 Hz. */
Chris@69 57 #define PLC_PITCH_LAG_MAX (720)
Chris@69 58 /* The minimum pitch lag to allow in the pitch-based PLC. This corresponds to a
Chris@69 59 pitch of 480 Hz. */
Chris@69 60 #define PLC_PITCH_LAG_MIN (100)
Chris@69 61
Chris@69 62 #if defined(SMALL_FOOTPRINT) && defined(FIXED_POINT)
Chris@69 63 #define NORM_ALIASING_HACK
Chris@69 64 #endif
Chris@69 65 /**********************************************************************/
Chris@69 66 /* */
Chris@69 67 /* DECODER */
Chris@69 68 /* */
Chris@69 69 /**********************************************************************/
Chris@69 70 #define DECODE_BUFFER_SIZE 2048
Chris@69 71
Chris@69 72 /** Decoder state
Chris@69 73 @brief Decoder state
Chris@69 74 */
Chris@69 75 struct OpusCustomDecoder {
Chris@69 76 const OpusCustomMode *mode;
Chris@69 77 int overlap;
Chris@69 78 int channels;
Chris@69 79 int stream_channels;
Chris@69 80
Chris@69 81 int downsample;
Chris@69 82 int start, end;
Chris@69 83 int signalling;
Chris@69 84 int disable_inv;
Chris@69 85 int arch;
Chris@69 86
Chris@69 87 /* Everything beyond this point gets cleared on a reset */
Chris@69 88 #define DECODER_RESET_START rng
Chris@69 89
Chris@69 90 opus_uint32 rng;
Chris@69 91 int error;
Chris@69 92 int last_pitch_index;
Chris@69 93 int loss_count;
Chris@69 94 int skip_plc;
Chris@69 95 int postfilter_period;
Chris@69 96 int postfilter_period_old;
Chris@69 97 opus_val16 postfilter_gain;
Chris@69 98 opus_val16 postfilter_gain_old;
Chris@69 99 int postfilter_tapset;
Chris@69 100 int postfilter_tapset_old;
Chris@69 101
Chris@69 102 celt_sig preemph_memD[2];
Chris@69 103
Chris@69 104 celt_sig _decode_mem[1]; /* Size = channels*(DECODE_BUFFER_SIZE+mode->overlap) */
Chris@69 105 /* opus_val16 lpc[], Size = channels*LPC_ORDER */
Chris@69 106 /* opus_val16 oldEBands[], Size = 2*mode->nbEBands */
Chris@69 107 /* opus_val16 oldLogE[], Size = 2*mode->nbEBands */
Chris@69 108 /* opus_val16 oldLogE2[], Size = 2*mode->nbEBands */
Chris@69 109 /* opus_val16 backgroundLogE[], Size = 2*mode->nbEBands */
Chris@69 110 };
Chris@69 111
Chris@69 112 #if defined(ENABLE_HARDENING) || defined(ENABLE_ASSERTIONS)
Chris@69 113 /* Make basic checks on the CELT state to ensure we don't end
Chris@69 114 up writing all over memory. */
Chris@69 115 void validate_celt_decoder(CELTDecoder *st)
Chris@69 116 {
Chris@69 117 #ifndef CUSTOM_MODES
Chris@69 118 celt_assert(st->mode == opus_custom_mode_create(48000, 960, NULL));
Chris@69 119 celt_assert(st->overlap == 120);
Chris@69 120 #endif
Chris@69 121 celt_assert(st->channels == 1 || st->channels == 2);
Chris@69 122 celt_assert(st->stream_channels == 1 || st->stream_channels == 2);
Chris@69 123 celt_assert(st->downsample > 0);
Chris@69 124 celt_assert(st->start == 0 || st->start == 17);
Chris@69 125 celt_assert(st->start < st->end);
Chris@69 126 celt_assert(st->end <= 21);
Chris@69 127 #ifdef OPUS_ARCHMASK
Chris@69 128 celt_assert(st->arch >= 0);
Chris@69 129 celt_assert(st->arch <= OPUS_ARCHMASK);
Chris@69 130 #endif
Chris@69 131 celt_assert(st->last_pitch_index <= PLC_PITCH_LAG_MAX);
Chris@69 132 celt_assert(st->last_pitch_index >= PLC_PITCH_LAG_MIN || st->last_pitch_index == 0);
Chris@69 133 celt_assert(st->postfilter_period < MAX_PERIOD);
Chris@69 134 celt_assert(st->postfilter_period >= COMBFILTER_MINPERIOD || st->postfilter_period == 0);
Chris@69 135 celt_assert(st->postfilter_period_old < MAX_PERIOD);
Chris@69 136 celt_assert(st->postfilter_period_old >= COMBFILTER_MINPERIOD || st->postfilter_period_old == 0);
Chris@69 137 celt_assert(st->postfilter_tapset <= 2);
Chris@69 138 celt_assert(st->postfilter_tapset >= 0);
Chris@69 139 celt_assert(st->postfilter_tapset_old <= 2);
Chris@69 140 celt_assert(st->postfilter_tapset_old >= 0);
Chris@69 141 }
Chris@69 142 #endif
Chris@69 143
Chris@69 144 int celt_decoder_get_size(int channels)
Chris@69 145 {
Chris@69 146 const CELTMode *mode = opus_custom_mode_create(48000, 960, NULL);
Chris@69 147 return opus_custom_decoder_get_size(mode, channels);
Chris@69 148 }
Chris@69 149
Chris@69 150 OPUS_CUSTOM_NOSTATIC int opus_custom_decoder_get_size(const CELTMode *mode, int channels)
Chris@69 151 {
Chris@69 152 int size = sizeof(struct CELTDecoder)
Chris@69 153 + (channels*(DECODE_BUFFER_SIZE+mode->overlap)-1)*sizeof(celt_sig)
Chris@69 154 + channels*LPC_ORDER*sizeof(opus_val16)
Chris@69 155 + 4*2*mode->nbEBands*sizeof(opus_val16);
Chris@69 156 return size;
Chris@69 157 }
Chris@69 158
Chris@69 159 #ifdef CUSTOM_MODES
Chris@69 160 CELTDecoder *opus_custom_decoder_create(const CELTMode *mode, int channels, int *error)
Chris@69 161 {
Chris@69 162 int ret;
Chris@69 163 CELTDecoder *st = (CELTDecoder *)opus_alloc(opus_custom_decoder_get_size(mode, channels));
Chris@69 164 ret = opus_custom_decoder_init(st, mode, channels);
Chris@69 165 if (ret != OPUS_OK)
Chris@69 166 {
Chris@69 167 opus_custom_decoder_destroy(st);
Chris@69 168 st = NULL;
Chris@69 169 }
Chris@69 170 if (error)
Chris@69 171 *error = ret;
Chris@69 172 return st;
Chris@69 173 }
Chris@69 174 #endif /* CUSTOM_MODES */
Chris@69 175
Chris@69 176 int celt_decoder_init(CELTDecoder *st, opus_int32 sampling_rate, int channels)
Chris@69 177 {
Chris@69 178 int ret;
Chris@69 179 ret = opus_custom_decoder_init(st, opus_custom_mode_create(48000, 960, NULL), channels);
Chris@69 180 if (ret != OPUS_OK)
Chris@69 181 return ret;
Chris@69 182 st->downsample = resampling_factor(sampling_rate);
Chris@69 183 if (st->downsample==0)
Chris@69 184 return OPUS_BAD_ARG;
Chris@69 185 else
Chris@69 186 return OPUS_OK;
Chris@69 187 }
Chris@69 188
Chris@69 189 OPUS_CUSTOM_NOSTATIC int opus_custom_decoder_init(CELTDecoder *st, const CELTMode *mode, int channels)
Chris@69 190 {
Chris@69 191 if (channels < 0 || channels > 2)
Chris@69 192 return OPUS_BAD_ARG;
Chris@69 193
Chris@69 194 if (st==NULL)
Chris@69 195 return OPUS_ALLOC_FAIL;
Chris@69 196
Chris@69 197 OPUS_CLEAR((char*)st, opus_custom_decoder_get_size(mode, channels));
Chris@69 198
Chris@69 199 st->mode = mode;
Chris@69 200 st->overlap = mode->overlap;
Chris@69 201 st->stream_channels = st->channels = channels;
Chris@69 202
Chris@69 203 st->downsample = 1;
Chris@69 204 st->start = 0;
Chris@69 205 st->end = st->mode->effEBands;
Chris@69 206 st->signalling = 1;
Chris@69 207 #ifndef DISABLE_UPDATE_DRAFT
Chris@69 208 st->disable_inv = channels == 1;
Chris@69 209 #else
Chris@69 210 st->disable_inv = 0;
Chris@69 211 #endif
Chris@69 212 st->arch = opus_select_arch();
Chris@69 213
Chris@69 214 opus_custom_decoder_ctl(st, OPUS_RESET_STATE);
Chris@69 215
Chris@69 216 return OPUS_OK;
Chris@69 217 }
Chris@69 218
Chris@69 219 #ifdef CUSTOM_MODES
Chris@69 220 void opus_custom_decoder_destroy(CELTDecoder *st)
Chris@69 221 {
Chris@69 222 opus_free(st);
Chris@69 223 }
Chris@69 224 #endif /* CUSTOM_MODES */
Chris@69 225
Chris@69 226 #ifndef CUSTOM_MODES
Chris@69 227 /* Special case for stereo with no downsampling and no accumulation. This is
Chris@69 228 quite common and we can make it faster by processing both channels in the
Chris@69 229 same loop, reducing overhead due to the dependency loop in the IIR filter. */
Chris@69 230 static void deemphasis_stereo_simple(celt_sig *in[], opus_val16 *pcm, int N, const opus_val16 coef0,
Chris@69 231 celt_sig *mem)
Chris@69 232 {
Chris@69 233 celt_sig * OPUS_RESTRICT x0;
Chris@69 234 celt_sig * OPUS_RESTRICT x1;
Chris@69 235 celt_sig m0, m1;
Chris@69 236 int j;
Chris@69 237 x0=in[0];
Chris@69 238 x1=in[1];
Chris@69 239 m0 = mem[0];
Chris@69 240 m1 = mem[1];
Chris@69 241 for (j=0;j<N;j++)
Chris@69 242 {
Chris@69 243 celt_sig tmp0, tmp1;
Chris@69 244 /* Add VERY_SMALL to x[] first to reduce dependency chain. */
Chris@69 245 tmp0 = x0[j] + VERY_SMALL + m0;
Chris@69 246 tmp1 = x1[j] + VERY_SMALL + m1;
Chris@69 247 m0 = MULT16_32_Q15(coef0, tmp0);
Chris@69 248 m1 = MULT16_32_Q15(coef0, tmp1);
Chris@69 249 pcm[2*j ] = SCALEOUT(SIG2WORD16(tmp0));
Chris@69 250 pcm[2*j+1] = SCALEOUT(SIG2WORD16(tmp1));
Chris@69 251 }
Chris@69 252 mem[0] = m0;
Chris@69 253 mem[1] = m1;
Chris@69 254 }
Chris@69 255 #endif
Chris@69 256
Chris@69 257 #ifndef RESYNTH
Chris@69 258 static
Chris@69 259 #endif
Chris@69 260 void deemphasis(celt_sig *in[], opus_val16 *pcm, int N, int C, int downsample, const opus_val16 *coef,
Chris@69 261 celt_sig *mem, int accum)
Chris@69 262 {
Chris@69 263 int c;
Chris@69 264 int Nd;
Chris@69 265 int apply_downsampling=0;
Chris@69 266 opus_val16 coef0;
Chris@69 267 VARDECL(celt_sig, scratch);
Chris@69 268 SAVE_STACK;
Chris@69 269 #ifndef CUSTOM_MODES
Chris@69 270 /* Short version for common case. */
Chris@69 271 if (downsample == 1 && C == 2 && !accum)
Chris@69 272 {
Chris@69 273 deemphasis_stereo_simple(in, pcm, N, coef[0], mem);
Chris@69 274 return;
Chris@69 275 }
Chris@69 276 #endif
Chris@69 277 #ifndef FIXED_POINT
Chris@69 278 (void)accum;
Chris@69 279 celt_assert(accum==0);
Chris@69 280 #endif
Chris@69 281 ALLOC(scratch, N, celt_sig);
Chris@69 282 coef0 = coef[0];
Chris@69 283 Nd = N/downsample;
Chris@69 284 c=0; do {
Chris@69 285 int j;
Chris@69 286 celt_sig * OPUS_RESTRICT x;
Chris@69 287 opus_val16 * OPUS_RESTRICT y;
Chris@69 288 celt_sig m = mem[c];
Chris@69 289 x =in[c];
Chris@69 290 y = pcm+c;
Chris@69 291 #ifdef CUSTOM_MODES
Chris@69 292 if (coef[1] != 0)
Chris@69 293 {
Chris@69 294 opus_val16 coef1 = coef[1];
Chris@69 295 opus_val16 coef3 = coef[3];
Chris@69 296 for (j=0;j<N;j++)
Chris@69 297 {
Chris@69 298 celt_sig tmp = x[j] + m + VERY_SMALL;
Chris@69 299 m = MULT16_32_Q15(coef0, tmp)
Chris@69 300 - MULT16_32_Q15(coef1, x[j]);
Chris@69 301 tmp = SHL32(MULT16_32_Q15(coef3, tmp), 2);
Chris@69 302 scratch[j] = tmp;
Chris@69 303 }
Chris@69 304 apply_downsampling=1;
Chris@69 305 } else
Chris@69 306 #endif
Chris@69 307 if (downsample>1)
Chris@69 308 {
Chris@69 309 /* Shortcut for the standard (non-custom modes) case */
Chris@69 310 for (j=0;j<N;j++)
Chris@69 311 {
Chris@69 312 celt_sig tmp = x[j] + VERY_SMALL + m;
Chris@69 313 m = MULT16_32_Q15(coef0, tmp);
Chris@69 314 scratch[j] = tmp;
Chris@69 315 }
Chris@69 316 apply_downsampling=1;
Chris@69 317 } else {
Chris@69 318 /* Shortcut for the standard (non-custom modes) case */
Chris@69 319 #ifdef FIXED_POINT
Chris@69 320 if (accum)
Chris@69 321 {
Chris@69 322 for (j=0;j<N;j++)
Chris@69 323 {
Chris@69 324 celt_sig tmp = x[j] + m + VERY_SMALL;
Chris@69 325 m = MULT16_32_Q15(coef0, tmp);
Chris@69 326 y[j*C] = SAT16(ADD32(y[j*C], SCALEOUT(SIG2WORD16(tmp))));
Chris@69 327 }
Chris@69 328 } else
Chris@69 329 #endif
Chris@69 330 {
Chris@69 331 for (j=0;j<N;j++)
Chris@69 332 {
Chris@69 333 celt_sig tmp = x[j] + VERY_SMALL + m;
Chris@69 334 m = MULT16_32_Q15(coef0, tmp);
Chris@69 335 y[j*C] = SCALEOUT(SIG2WORD16(tmp));
Chris@69 336 }
Chris@69 337 }
Chris@69 338 }
Chris@69 339 mem[c] = m;
Chris@69 340
Chris@69 341 if (apply_downsampling)
Chris@69 342 {
Chris@69 343 /* Perform down-sampling */
Chris@69 344 #ifdef FIXED_POINT
Chris@69 345 if (accum)
Chris@69 346 {
Chris@69 347 for (j=0;j<Nd;j++)
Chris@69 348 y[j*C] = SAT16(ADD32(y[j*C], SCALEOUT(SIG2WORD16(scratch[j*downsample]))));
Chris@69 349 } else
Chris@69 350 #endif
Chris@69 351 {
Chris@69 352 for (j=0;j<Nd;j++)
Chris@69 353 y[j*C] = SCALEOUT(SIG2WORD16(scratch[j*downsample]));
Chris@69 354 }
Chris@69 355 }
Chris@69 356 } while (++c<C);
Chris@69 357 RESTORE_STACK;
Chris@69 358 }
Chris@69 359
Chris@69 360 #ifndef RESYNTH
Chris@69 361 static
Chris@69 362 #endif
Chris@69 363 void celt_synthesis(const CELTMode *mode, celt_norm *X, celt_sig * out_syn[],
Chris@69 364 opus_val16 *oldBandE, int start, int effEnd, int C, int CC,
Chris@69 365 int isTransient, int LM, int downsample,
Chris@69 366 int silence, int arch)
Chris@69 367 {
Chris@69 368 int c, i;
Chris@69 369 int M;
Chris@69 370 int b;
Chris@69 371 int B;
Chris@69 372 int N, NB;
Chris@69 373 int shift;
Chris@69 374 int nbEBands;
Chris@69 375 int overlap;
Chris@69 376 VARDECL(celt_sig, freq);
Chris@69 377 SAVE_STACK;
Chris@69 378
Chris@69 379 overlap = mode->overlap;
Chris@69 380 nbEBands = mode->nbEBands;
Chris@69 381 N = mode->shortMdctSize<<LM;
Chris@69 382 ALLOC(freq, N, celt_sig); /**< Interleaved signal MDCTs */
Chris@69 383 M = 1<<LM;
Chris@69 384
Chris@69 385 if (isTransient)
Chris@69 386 {
Chris@69 387 B = M;
Chris@69 388 NB = mode->shortMdctSize;
Chris@69 389 shift = mode->maxLM;
Chris@69 390 } else {
Chris@69 391 B = 1;
Chris@69 392 NB = mode->shortMdctSize<<LM;
Chris@69 393 shift = mode->maxLM-LM;
Chris@69 394 }
Chris@69 395
Chris@69 396 if (CC==2&&C==1)
Chris@69 397 {
Chris@69 398 /* Copying a mono streams to two channels */
Chris@69 399 celt_sig *freq2;
Chris@69 400 denormalise_bands(mode, X, freq, oldBandE, start, effEnd, M,
Chris@69 401 downsample, silence);
Chris@69 402 /* Store a temporary copy in the output buffer because the IMDCT destroys its input. */
Chris@69 403 freq2 = out_syn[1]+overlap/2;
Chris@69 404 OPUS_COPY(freq2, freq, N);
Chris@69 405 for (b=0;b<B;b++)
Chris@69 406 clt_mdct_backward(&mode->mdct, &freq2[b], out_syn[0]+NB*b, mode->window, overlap, shift, B, arch);
Chris@69 407 for (b=0;b<B;b++)
Chris@69 408 clt_mdct_backward(&mode->mdct, &freq[b], out_syn[1]+NB*b, mode->window, overlap, shift, B, arch);
Chris@69 409 } else if (CC==1&&C==2)
Chris@69 410 {
Chris@69 411 /* Downmixing a stereo stream to mono */
Chris@69 412 celt_sig *freq2;
Chris@69 413 freq2 = out_syn[0]+overlap/2;
Chris@69 414 denormalise_bands(mode, X, freq, oldBandE, start, effEnd, M,
Chris@69 415 downsample, silence);
Chris@69 416 /* Use the output buffer as temp array before downmixing. */
Chris@69 417 denormalise_bands(mode, X+N, freq2, oldBandE+nbEBands, start, effEnd, M,
Chris@69 418 downsample, silence);
Chris@69 419 for (i=0;i<N;i++)
Chris@69 420 freq[i] = ADD32(HALF32(freq[i]), HALF32(freq2[i]));
Chris@69 421 for (b=0;b<B;b++)
Chris@69 422 clt_mdct_backward(&mode->mdct, &freq[b], out_syn[0]+NB*b, mode->window, overlap, shift, B, arch);
Chris@69 423 } else {
Chris@69 424 /* Normal case (mono or stereo) */
Chris@69 425 c=0; do {
Chris@69 426 denormalise_bands(mode, X+c*N, freq, oldBandE+c*nbEBands, start, effEnd, M,
Chris@69 427 downsample, silence);
Chris@69 428 for (b=0;b<B;b++)
Chris@69 429 clt_mdct_backward(&mode->mdct, &freq[b], out_syn[c]+NB*b, mode->window, overlap, shift, B, arch);
Chris@69 430 } while (++c<CC);
Chris@69 431 }
Chris@69 432 /* Saturate IMDCT output so that we can't overflow in the pitch postfilter
Chris@69 433 or in the */
Chris@69 434 c=0; do {
Chris@69 435 for (i=0;i<N;i++)
Chris@69 436 out_syn[c][i] = SATURATE(out_syn[c][i], SIG_SAT);
Chris@69 437 } while (++c<CC);
Chris@69 438 RESTORE_STACK;
Chris@69 439 }
Chris@69 440
Chris@69 441 static void tf_decode(int start, int end, int isTransient, int *tf_res, int LM, ec_dec *dec)
Chris@69 442 {
Chris@69 443 int i, curr, tf_select;
Chris@69 444 int tf_select_rsv;
Chris@69 445 int tf_changed;
Chris@69 446 int logp;
Chris@69 447 opus_uint32 budget;
Chris@69 448 opus_uint32 tell;
Chris@69 449
Chris@69 450 budget = dec->storage*8;
Chris@69 451 tell = ec_tell(dec);
Chris@69 452 logp = isTransient ? 2 : 4;
Chris@69 453 tf_select_rsv = LM>0 && tell+logp+1<=budget;
Chris@69 454 budget -= tf_select_rsv;
Chris@69 455 tf_changed = curr = 0;
Chris@69 456 for (i=start;i<end;i++)
Chris@69 457 {
Chris@69 458 if (tell+logp<=budget)
Chris@69 459 {
Chris@69 460 curr ^= ec_dec_bit_logp(dec, logp);
Chris@69 461 tell = ec_tell(dec);
Chris@69 462 tf_changed |= curr;
Chris@69 463 }
Chris@69 464 tf_res[i] = curr;
Chris@69 465 logp = isTransient ? 4 : 5;
Chris@69 466 }
Chris@69 467 tf_select = 0;
Chris@69 468 if (tf_select_rsv &&
Chris@69 469 tf_select_table[LM][4*isTransient+0+tf_changed] !=
Chris@69 470 tf_select_table[LM][4*isTransient+2+tf_changed])
Chris@69 471 {
Chris@69 472 tf_select = ec_dec_bit_logp(dec, 1);
Chris@69 473 }
Chris@69 474 for (i=start;i<end;i++)
Chris@69 475 {
Chris@69 476 tf_res[i] = tf_select_table[LM][4*isTransient+2*tf_select+tf_res[i]];
Chris@69 477 }
Chris@69 478 }
Chris@69 479
Chris@69 480 static int celt_plc_pitch_search(celt_sig *decode_mem[2], int C, int arch)
Chris@69 481 {
Chris@69 482 int pitch_index;
Chris@69 483 VARDECL( opus_val16, lp_pitch_buf );
Chris@69 484 SAVE_STACK;
Chris@69 485 ALLOC( lp_pitch_buf, DECODE_BUFFER_SIZE>>1, opus_val16 );
Chris@69 486 pitch_downsample(decode_mem, lp_pitch_buf,
Chris@69 487 DECODE_BUFFER_SIZE, C, arch);
Chris@69 488 pitch_search(lp_pitch_buf+(PLC_PITCH_LAG_MAX>>1), lp_pitch_buf,
Chris@69 489 DECODE_BUFFER_SIZE-PLC_PITCH_LAG_MAX,
Chris@69 490 PLC_PITCH_LAG_MAX-PLC_PITCH_LAG_MIN, &pitch_index, arch);
Chris@69 491 pitch_index = PLC_PITCH_LAG_MAX-pitch_index;
Chris@69 492 RESTORE_STACK;
Chris@69 493 return pitch_index;
Chris@69 494 }
Chris@69 495
Chris@69 496 static void celt_decode_lost(CELTDecoder * OPUS_RESTRICT st, int N, int LM)
Chris@69 497 {
Chris@69 498 int c;
Chris@69 499 int i;
Chris@69 500 const int C = st->channels;
Chris@69 501 celt_sig *decode_mem[2];
Chris@69 502 celt_sig *out_syn[2];
Chris@69 503 opus_val16 *lpc;
Chris@69 504 opus_val16 *oldBandE, *oldLogE, *oldLogE2, *backgroundLogE;
Chris@69 505 const OpusCustomMode *mode;
Chris@69 506 int nbEBands;
Chris@69 507 int overlap;
Chris@69 508 int start;
Chris@69 509 int loss_count;
Chris@69 510 int noise_based;
Chris@69 511 const opus_int16 *eBands;
Chris@69 512 SAVE_STACK;
Chris@69 513
Chris@69 514 mode = st->mode;
Chris@69 515 nbEBands = mode->nbEBands;
Chris@69 516 overlap = mode->overlap;
Chris@69 517 eBands = mode->eBands;
Chris@69 518
Chris@69 519 c=0; do {
Chris@69 520 decode_mem[c] = st->_decode_mem + c*(DECODE_BUFFER_SIZE+overlap);
Chris@69 521 out_syn[c] = decode_mem[c]+DECODE_BUFFER_SIZE-N;
Chris@69 522 } while (++c<C);
Chris@69 523 lpc = (opus_val16*)(st->_decode_mem+(DECODE_BUFFER_SIZE+overlap)*C);
Chris@69 524 oldBandE = lpc+C*LPC_ORDER;
Chris@69 525 oldLogE = oldBandE + 2*nbEBands;
Chris@69 526 oldLogE2 = oldLogE + 2*nbEBands;
Chris@69 527 backgroundLogE = oldLogE2 + 2*nbEBands;
Chris@69 528
Chris@69 529 loss_count = st->loss_count;
Chris@69 530 start = st->start;
Chris@69 531 noise_based = loss_count >= 5 || start != 0 || st->skip_plc;
Chris@69 532 if (noise_based)
Chris@69 533 {
Chris@69 534 /* Noise-based PLC/CNG */
Chris@69 535 #ifdef NORM_ALIASING_HACK
Chris@69 536 celt_norm *X;
Chris@69 537 #else
Chris@69 538 VARDECL(celt_norm, X);
Chris@69 539 #endif
Chris@69 540 opus_uint32 seed;
Chris@69 541 int end;
Chris@69 542 int effEnd;
Chris@69 543 opus_val16 decay;
Chris@69 544 end = st->end;
Chris@69 545 effEnd = IMAX(start, IMIN(end, mode->effEBands));
Chris@69 546
Chris@69 547 #ifdef NORM_ALIASING_HACK
Chris@69 548 /* This is an ugly hack that breaks aliasing rules and would be easily broken,
Chris@69 549 but it saves almost 4kB of stack. */
Chris@69 550 X = (celt_norm*)(out_syn[C-1]+overlap/2);
Chris@69 551 #else
Chris@69 552 ALLOC(X, C*N, celt_norm); /**< Interleaved normalised MDCTs */
Chris@69 553 #endif
Chris@69 554
Chris@69 555 /* Energy decay */
Chris@69 556 decay = loss_count==0 ? QCONST16(1.5f, DB_SHIFT) : QCONST16(.5f, DB_SHIFT);
Chris@69 557 c=0; do
Chris@69 558 {
Chris@69 559 for (i=start;i<end;i++)
Chris@69 560 oldBandE[c*nbEBands+i] = MAX16(backgroundLogE[c*nbEBands+i], oldBandE[c*nbEBands+i] - decay);
Chris@69 561 } while (++c<C);
Chris@69 562 seed = st->rng;
Chris@69 563 for (c=0;c<C;c++)
Chris@69 564 {
Chris@69 565 for (i=start;i<effEnd;i++)
Chris@69 566 {
Chris@69 567 int j;
Chris@69 568 int boffs;
Chris@69 569 int blen;
Chris@69 570 boffs = N*c+(eBands[i]<<LM);
Chris@69 571 blen = (eBands[i+1]-eBands[i])<<LM;
Chris@69 572 for (j=0;j<blen;j++)
Chris@69 573 {
Chris@69 574 seed = celt_lcg_rand(seed);
Chris@69 575 X[boffs+j] = (celt_norm)((opus_int32)seed>>20);
Chris@69 576 }
Chris@69 577 renormalise_vector(X+boffs, blen, Q15ONE, st->arch);
Chris@69 578 }
Chris@69 579 }
Chris@69 580 st->rng = seed;
Chris@69 581
Chris@69 582 c=0; do {
Chris@69 583 OPUS_MOVE(decode_mem[c], decode_mem[c]+N,
Chris@69 584 DECODE_BUFFER_SIZE-N+(overlap>>1));
Chris@69 585 } while (++c<C);
Chris@69 586
Chris@69 587 celt_synthesis(mode, X, out_syn, oldBandE, start, effEnd, C, C, 0, LM, st->downsample, 0, st->arch);
Chris@69 588 } else {
Chris@69 589 int exc_length;
Chris@69 590 /* Pitch-based PLC */
Chris@69 591 const opus_val16 *window;
Chris@69 592 opus_val16 *exc;
Chris@69 593 opus_val16 fade = Q15ONE;
Chris@69 594 int pitch_index;
Chris@69 595 VARDECL(opus_val32, etmp);
Chris@69 596 VARDECL(opus_val16, _exc);
Chris@69 597 VARDECL(opus_val16, fir_tmp);
Chris@69 598
Chris@69 599 if (loss_count == 0)
Chris@69 600 {
Chris@69 601 st->last_pitch_index = pitch_index = celt_plc_pitch_search(decode_mem, C, st->arch);
Chris@69 602 } else {
Chris@69 603 pitch_index = st->last_pitch_index;
Chris@69 604 fade = QCONST16(.8f,15);
Chris@69 605 }
Chris@69 606
Chris@69 607 /* We want the excitation for 2 pitch periods in order to look for a
Chris@69 608 decaying signal, but we can't get more than MAX_PERIOD. */
Chris@69 609 exc_length = IMIN(2*pitch_index, MAX_PERIOD);
Chris@69 610
Chris@69 611 ALLOC(etmp, overlap, opus_val32);
Chris@69 612 ALLOC(_exc, MAX_PERIOD+LPC_ORDER, opus_val16);
Chris@69 613 ALLOC(fir_tmp, exc_length, opus_val16);
Chris@69 614 exc = _exc+LPC_ORDER;
Chris@69 615 window = mode->window;
Chris@69 616 c=0; do {
Chris@69 617 opus_val16 decay;
Chris@69 618 opus_val16 attenuation;
Chris@69 619 opus_val32 S1=0;
Chris@69 620 celt_sig *buf;
Chris@69 621 int extrapolation_offset;
Chris@69 622 int extrapolation_len;
Chris@69 623 int j;
Chris@69 624
Chris@69 625 buf = decode_mem[c];
Chris@69 626 for (i=0;i<MAX_PERIOD+LPC_ORDER;i++)
Chris@69 627 exc[i-LPC_ORDER] = ROUND16(buf[DECODE_BUFFER_SIZE-MAX_PERIOD-LPC_ORDER+i], SIG_SHIFT);
Chris@69 628
Chris@69 629 if (loss_count == 0)
Chris@69 630 {
Chris@69 631 opus_val32 ac[LPC_ORDER+1];
Chris@69 632 /* Compute LPC coefficients for the last MAX_PERIOD samples before
Chris@69 633 the first loss so we can work in the excitation-filter domain. */
Chris@69 634 _celt_autocorr(exc, ac, window, overlap,
Chris@69 635 LPC_ORDER, MAX_PERIOD, st->arch);
Chris@69 636 /* Add a noise floor of -40 dB. */
Chris@69 637 #ifdef FIXED_POINT
Chris@69 638 ac[0] += SHR32(ac[0],13);
Chris@69 639 #else
Chris@69 640 ac[0] *= 1.0001f;
Chris@69 641 #endif
Chris@69 642 /* Use lag windowing to stabilize the Levinson-Durbin recursion. */
Chris@69 643 for (i=1;i<=LPC_ORDER;i++)
Chris@69 644 {
Chris@69 645 /*ac[i] *= exp(-.5*(2*M_PI*.002*i)*(2*M_PI*.002*i));*/
Chris@69 646 #ifdef FIXED_POINT
Chris@69 647 ac[i] -= MULT16_32_Q15(2*i*i, ac[i]);
Chris@69 648 #else
Chris@69 649 ac[i] -= ac[i]*(0.008f*0.008f)*i*i;
Chris@69 650 #endif
Chris@69 651 }
Chris@69 652 _celt_lpc(lpc+c*LPC_ORDER, ac, LPC_ORDER);
Chris@69 653 #ifdef FIXED_POINT
Chris@69 654 /* For fixed-point, apply bandwidth expansion until we can guarantee that
Chris@69 655 no overflow can happen in the IIR filter. This means:
Chris@69 656 32768*sum(abs(filter)) < 2^31 */
Chris@69 657 while (1) {
Chris@69 658 opus_val16 tmp=Q15ONE;
Chris@69 659 opus_val32 sum=QCONST16(1., SIG_SHIFT);
Chris@69 660 for (i=0;i<LPC_ORDER;i++)
Chris@69 661 sum += ABS16(lpc[c*LPC_ORDER+i]);
Chris@69 662 if (sum < 65535) break;
Chris@69 663 for (i=0;i<LPC_ORDER;i++)
Chris@69 664 {
Chris@69 665 tmp = MULT16_16_Q15(QCONST16(.99f,15), tmp);
Chris@69 666 lpc[c*LPC_ORDER+i] = MULT16_16_Q15(lpc[c*LPC_ORDER+i], tmp);
Chris@69 667 }
Chris@69 668 }
Chris@69 669 #endif
Chris@69 670 }
Chris@69 671 /* Initialize the LPC history with the samples just before the start
Chris@69 672 of the region for which we're computing the excitation. */
Chris@69 673 {
Chris@69 674 /* Compute the excitation for exc_length samples before the loss. We need the copy
Chris@69 675 because celt_fir() cannot filter in-place. */
Chris@69 676 celt_fir(exc+MAX_PERIOD-exc_length, lpc+c*LPC_ORDER,
Chris@69 677 fir_tmp, exc_length, LPC_ORDER, st->arch);
Chris@69 678 OPUS_COPY(exc+MAX_PERIOD-exc_length, fir_tmp, exc_length);
Chris@69 679 }
Chris@69 680
Chris@69 681 /* Check if the waveform is decaying, and if so how fast.
Chris@69 682 We do this to avoid adding energy when concealing in a segment
Chris@69 683 with decaying energy. */
Chris@69 684 {
Chris@69 685 opus_val32 E1=1, E2=1;
Chris@69 686 int decay_length;
Chris@69 687 #ifdef FIXED_POINT
Chris@69 688 int shift = IMAX(0,2*celt_zlog2(celt_maxabs16(&exc[MAX_PERIOD-exc_length], exc_length))-20);
Chris@69 689 #endif
Chris@69 690 decay_length = exc_length>>1;
Chris@69 691 for (i=0;i<decay_length;i++)
Chris@69 692 {
Chris@69 693 opus_val16 e;
Chris@69 694 e = exc[MAX_PERIOD-decay_length+i];
Chris@69 695 E1 += SHR32(MULT16_16(e, e), shift);
Chris@69 696 e = exc[MAX_PERIOD-2*decay_length+i];
Chris@69 697 E2 += SHR32(MULT16_16(e, e), shift);
Chris@69 698 }
Chris@69 699 E1 = MIN32(E1, E2);
Chris@69 700 decay = celt_sqrt(frac_div32(SHR32(E1, 1), E2));
Chris@69 701 }
Chris@69 702
Chris@69 703 /* Move the decoder memory one frame to the left to give us room to
Chris@69 704 add the data for the new frame. We ignore the overlap that extends
Chris@69 705 past the end of the buffer, because we aren't going to use it. */
Chris@69 706 OPUS_MOVE(buf, buf+N, DECODE_BUFFER_SIZE-N);
Chris@69 707
Chris@69 708 /* Extrapolate from the end of the excitation with a period of
Chris@69 709 "pitch_index", scaling down each period by an additional factor of
Chris@69 710 "decay". */
Chris@69 711 extrapolation_offset = MAX_PERIOD-pitch_index;
Chris@69 712 /* We need to extrapolate enough samples to cover a complete MDCT
Chris@69 713 window (including overlap/2 samples on both sides). */
Chris@69 714 extrapolation_len = N+overlap;
Chris@69 715 /* We also apply fading if this is not the first loss. */
Chris@69 716 attenuation = MULT16_16_Q15(fade, decay);
Chris@69 717 for (i=j=0;i<extrapolation_len;i++,j++)
Chris@69 718 {
Chris@69 719 opus_val16 tmp;
Chris@69 720 if (j >= pitch_index) {
Chris@69 721 j -= pitch_index;
Chris@69 722 attenuation = MULT16_16_Q15(attenuation, decay);
Chris@69 723 }
Chris@69 724 buf[DECODE_BUFFER_SIZE-N+i] =
Chris@69 725 SHL32(EXTEND32(MULT16_16_Q15(attenuation,
Chris@69 726 exc[extrapolation_offset+j])), SIG_SHIFT);
Chris@69 727 /* Compute the energy of the previously decoded signal whose
Chris@69 728 excitation we're copying. */
Chris@69 729 tmp = ROUND16(
Chris@69 730 buf[DECODE_BUFFER_SIZE-MAX_PERIOD-N+extrapolation_offset+j],
Chris@69 731 SIG_SHIFT);
Chris@69 732 S1 += SHR32(MULT16_16(tmp, tmp), 10);
Chris@69 733 }
Chris@69 734 {
Chris@69 735 opus_val16 lpc_mem[LPC_ORDER];
Chris@69 736 /* Copy the last decoded samples (prior to the overlap region) to
Chris@69 737 synthesis filter memory so we can have a continuous signal. */
Chris@69 738 for (i=0;i<LPC_ORDER;i++)
Chris@69 739 lpc_mem[i] = ROUND16(buf[DECODE_BUFFER_SIZE-N-1-i], SIG_SHIFT);
Chris@69 740 /* Apply the synthesis filter to convert the excitation back into
Chris@69 741 the signal domain. */
Chris@69 742 celt_iir(buf+DECODE_BUFFER_SIZE-N, lpc+c*LPC_ORDER,
Chris@69 743 buf+DECODE_BUFFER_SIZE-N, extrapolation_len, LPC_ORDER,
Chris@69 744 lpc_mem, st->arch);
Chris@69 745 #ifdef FIXED_POINT
Chris@69 746 for (i=0; i < extrapolation_len; i++)
Chris@69 747 buf[DECODE_BUFFER_SIZE-N+i] = SATURATE(buf[DECODE_BUFFER_SIZE-N+i], SIG_SAT);
Chris@69 748 #endif
Chris@69 749 }
Chris@69 750
Chris@69 751 /* Check if the synthesis energy is higher than expected, which can
Chris@69 752 happen with the signal changes during our window. If so,
Chris@69 753 attenuate. */
Chris@69 754 {
Chris@69 755 opus_val32 S2=0;
Chris@69 756 for (i=0;i<extrapolation_len;i++)
Chris@69 757 {
Chris@69 758 opus_val16 tmp = ROUND16(buf[DECODE_BUFFER_SIZE-N+i], SIG_SHIFT);
Chris@69 759 S2 += SHR32(MULT16_16(tmp, tmp), 10);
Chris@69 760 }
Chris@69 761 /* This checks for an "explosion" in the synthesis. */
Chris@69 762 #ifdef FIXED_POINT
Chris@69 763 if (!(S1 > SHR32(S2,2)))
Chris@69 764 #else
Chris@69 765 /* The float test is written this way to catch NaNs in the output
Chris@69 766 of the IIR filter at the same time. */
Chris@69 767 if (!(S1 > 0.2f*S2))
Chris@69 768 #endif
Chris@69 769 {
Chris@69 770 for (i=0;i<extrapolation_len;i++)
Chris@69 771 buf[DECODE_BUFFER_SIZE-N+i] = 0;
Chris@69 772 } else if (S1 < S2)
Chris@69 773 {
Chris@69 774 opus_val16 ratio = celt_sqrt(frac_div32(SHR32(S1,1)+1,S2+1));
Chris@69 775 for (i=0;i<overlap;i++)
Chris@69 776 {
Chris@69 777 opus_val16 tmp_g = Q15ONE
Chris@69 778 - MULT16_16_Q15(window[i], Q15ONE-ratio);
Chris@69 779 buf[DECODE_BUFFER_SIZE-N+i] =
Chris@69 780 MULT16_32_Q15(tmp_g, buf[DECODE_BUFFER_SIZE-N+i]);
Chris@69 781 }
Chris@69 782 for (i=overlap;i<extrapolation_len;i++)
Chris@69 783 {
Chris@69 784 buf[DECODE_BUFFER_SIZE-N+i] =
Chris@69 785 MULT16_32_Q15(ratio, buf[DECODE_BUFFER_SIZE-N+i]);
Chris@69 786 }
Chris@69 787 }
Chris@69 788 }
Chris@69 789
Chris@69 790 /* Apply the pre-filter to the MDCT overlap for the next frame because
Chris@69 791 the post-filter will be re-applied in the decoder after the MDCT
Chris@69 792 overlap. */
Chris@69 793 comb_filter(etmp, buf+DECODE_BUFFER_SIZE,
Chris@69 794 st->postfilter_period, st->postfilter_period, overlap,
Chris@69 795 -st->postfilter_gain, -st->postfilter_gain,
Chris@69 796 st->postfilter_tapset, st->postfilter_tapset, NULL, 0, st->arch);
Chris@69 797
Chris@69 798 /* Simulate TDAC on the concealed audio so that it blends with the
Chris@69 799 MDCT of the next frame. */
Chris@69 800 for (i=0;i<overlap/2;i++)
Chris@69 801 {
Chris@69 802 buf[DECODE_BUFFER_SIZE+i] =
Chris@69 803 MULT16_32_Q15(window[i], etmp[overlap-1-i])
Chris@69 804 + MULT16_32_Q15(window[overlap-i-1], etmp[i]);
Chris@69 805 }
Chris@69 806 } while (++c<C);
Chris@69 807 }
Chris@69 808
Chris@69 809 st->loss_count = loss_count+1;
Chris@69 810
Chris@69 811 RESTORE_STACK;
Chris@69 812 }
Chris@69 813
Chris@69 814 int celt_decode_with_ec(CELTDecoder * OPUS_RESTRICT st, const unsigned char *data,
Chris@69 815 int len, opus_val16 * OPUS_RESTRICT pcm, int frame_size, ec_dec *dec, int accum)
Chris@69 816 {
Chris@69 817 int c, i, N;
Chris@69 818 int spread_decision;
Chris@69 819 opus_int32 bits;
Chris@69 820 ec_dec _dec;
Chris@69 821 #ifdef NORM_ALIASING_HACK
Chris@69 822 celt_norm *X;
Chris@69 823 #else
Chris@69 824 VARDECL(celt_norm, X);
Chris@69 825 #endif
Chris@69 826 VARDECL(int, fine_quant);
Chris@69 827 VARDECL(int, pulses);
Chris@69 828 VARDECL(int, cap);
Chris@69 829 VARDECL(int, offsets);
Chris@69 830 VARDECL(int, fine_priority);
Chris@69 831 VARDECL(int, tf_res);
Chris@69 832 VARDECL(unsigned char, collapse_masks);
Chris@69 833 celt_sig *decode_mem[2];
Chris@69 834 celt_sig *out_syn[2];
Chris@69 835 opus_val16 *lpc;
Chris@69 836 opus_val16 *oldBandE, *oldLogE, *oldLogE2, *backgroundLogE;
Chris@69 837
Chris@69 838 int shortBlocks;
Chris@69 839 int isTransient;
Chris@69 840 int intra_ener;
Chris@69 841 const int CC = st->channels;
Chris@69 842 int LM, M;
Chris@69 843 int start;
Chris@69 844 int end;
Chris@69 845 int effEnd;
Chris@69 846 int codedBands;
Chris@69 847 int alloc_trim;
Chris@69 848 int postfilter_pitch;
Chris@69 849 opus_val16 postfilter_gain;
Chris@69 850 int intensity=0;
Chris@69 851 int dual_stereo=0;
Chris@69 852 opus_int32 total_bits;
Chris@69 853 opus_int32 balance;
Chris@69 854 opus_int32 tell;
Chris@69 855 int dynalloc_logp;
Chris@69 856 int postfilter_tapset;
Chris@69 857 int anti_collapse_rsv;
Chris@69 858 int anti_collapse_on=0;
Chris@69 859 int silence;
Chris@69 860 int C = st->stream_channels;
Chris@69 861 const OpusCustomMode *mode;
Chris@69 862 int nbEBands;
Chris@69 863 int overlap;
Chris@69 864 const opus_int16 *eBands;
Chris@69 865 ALLOC_STACK;
Chris@69 866
Chris@69 867 VALIDATE_CELT_DECODER(st);
Chris@69 868 mode = st->mode;
Chris@69 869 nbEBands = mode->nbEBands;
Chris@69 870 overlap = mode->overlap;
Chris@69 871 eBands = mode->eBands;
Chris@69 872 start = st->start;
Chris@69 873 end = st->end;
Chris@69 874 frame_size *= st->downsample;
Chris@69 875
Chris@69 876 lpc = (opus_val16*)(st->_decode_mem+(DECODE_BUFFER_SIZE+overlap)*CC);
Chris@69 877 oldBandE = lpc+CC*LPC_ORDER;
Chris@69 878 oldLogE = oldBandE + 2*nbEBands;
Chris@69 879 oldLogE2 = oldLogE + 2*nbEBands;
Chris@69 880 backgroundLogE = oldLogE2 + 2*nbEBands;
Chris@69 881
Chris@69 882 #ifdef CUSTOM_MODES
Chris@69 883 if (st->signalling && data!=NULL)
Chris@69 884 {
Chris@69 885 int data0=data[0];
Chris@69 886 /* Convert "standard mode" to Opus header */
Chris@69 887 if (mode->Fs==48000 && mode->shortMdctSize==120)
Chris@69 888 {
Chris@69 889 data0 = fromOpus(data0);
Chris@69 890 if (data0<0)
Chris@69 891 return OPUS_INVALID_PACKET;
Chris@69 892 }
Chris@69 893 st->end = end = IMAX(1, mode->effEBands-2*(data0>>5));
Chris@69 894 LM = (data0>>3)&0x3;
Chris@69 895 C = 1 + ((data0>>2)&0x1);
Chris@69 896 data++;
Chris@69 897 len--;
Chris@69 898 if (LM>mode->maxLM)
Chris@69 899 return OPUS_INVALID_PACKET;
Chris@69 900 if (frame_size < mode->shortMdctSize<<LM)
Chris@69 901 return OPUS_BUFFER_TOO_SMALL;
Chris@69 902 else
Chris@69 903 frame_size = mode->shortMdctSize<<LM;
Chris@69 904 } else {
Chris@69 905 #else
Chris@69 906 {
Chris@69 907 #endif
Chris@69 908 for (LM=0;LM<=mode->maxLM;LM++)
Chris@69 909 if (mode->shortMdctSize<<LM==frame_size)
Chris@69 910 break;
Chris@69 911 if (LM>mode->maxLM)
Chris@69 912 return OPUS_BAD_ARG;
Chris@69 913 }
Chris@69 914 M=1<<LM;
Chris@69 915
Chris@69 916 if (len<0 || len>1275 || pcm==NULL)
Chris@69 917 return OPUS_BAD_ARG;
Chris@69 918
Chris@69 919 N = M*mode->shortMdctSize;
Chris@69 920 c=0; do {
Chris@69 921 decode_mem[c] = st->_decode_mem + c*(DECODE_BUFFER_SIZE+overlap);
Chris@69 922 out_syn[c] = decode_mem[c]+DECODE_BUFFER_SIZE-N;
Chris@69 923 } while (++c<CC);
Chris@69 924
Chris@69 925 effEnd = end;
Chris@69 926 if (effEnd > mode->effEBands)
Chris@69 927 effEnd = mode->effEBands;
Chris@69 928
Chris@69 929 if (data == NULL || len<=1)
Chris@69 930 {
Chris@69 931 celt_decode_lost(st, N, LM);
Chris@69 932 deemphasis(out_syn, pcm, N, CC, st->downsample, mode->preemph, st->preemph_memD, accum);
Chris@69 933 RESTORE_STACK;
Chris@69 934 return frame_size/st->downsample;
Chris@69 935 }
Chris@69 936
Chris@69 937 /* Check if there are at least two packets received consecutively before
Chris@69 938 * turning on the pitch-based PLC */
Chris@69 939 st->skip_plc = st->loss_count != 0;
Chris@69 940
Chris@69 941 if (dec == NULL)
Chris@69 942 {
Chris@69 943 ec_dec_init(&_dec,(unsigned char*)data,len);
Chris@69 944 dec = &_dec;
Chris@69 945 }
Chris@69 946
Chris@69 947 if (C==1)
Chris@69 948 {
Chris@69 949 for (i=0;i<nbEBands;i++)
Chris@69 950 oldBandE[i]=MAX16(oldBandE[i],oldBandE[nbEBands+i]);
Chris@69 951 }
Chris@69 952
Chris@69 953 total_bits = len*8;
Chris@69 954 tell = ec_tell(dec);
Chris@69 955
Chris@69 956 if (tell >= total_bits)
Chris@69 957 silence = 1;
Chris@69 958 else if (tell==1)
Chris@69 959 silence = ec_dec_bit_logp(dec, 15);
Chris@69 960 else
Chris@69 961 silence = 0;
Chris@69 962 if (silence)
Chris@69 963 {
Chris@69 964 /* Pretend we've read all the remaining bits */
Chris@69 965 tell = len*8;
Chris@69 966 dec->nbits_total+=tell-ec_tell(dec);
Chris@69 967 }
Chris@69 968
Chris@69 969 postfilter_gain = 0;
Chris@69 970 postfilter_pitch = 0;
Chris@69 971 postfilter_tapset = 0;
Chris@69 972 if (start==0 && tell+16 <= total_bits)
Chris@69 973 {
Chris@69 974 if(ec_dec_bit_logp(dec, 1))
Chris@69 975 {
Chris@69 976 int qg, octave;
Chris@69 977 octave = ec_dec_uint(dec, 6);
Chris@69 978 postfilter_pitch = (16<<octave)+ec_dec_bits(dec, 4+octave)-1;
Chris@69 979 qg = ec_dec_bits(dec, 3);
Chris@69 980 if (ec_tell(dec)+2<=total_bits)
Chris@69 981 postfilter_tapset = ec_dec_icdf(dec, tapset_icdf, 2);
Chris@69 982 postfilter_gain = QCONST16(.09375f,15)*(qg+1);
Chris@69 983 }
Chris@69 984 tell = ec_tell(dec);
Chris@69 985 }
Chris@69 986
Chris@69 987 if (LM > 0 && tell+3 <= total_bits)
Chris@69 988 {
Chris@69 989 isTransient = ec_dec_bit_logp(dec, 3);
Chris@69 990 tell = ec_tell(dec);
Chris@69 991 }
Chris@69 992 else
Chris@69 993 isTransient = 0;
Chris@69 994
Chris@69 995 if (isTransient)
Chris@69 996 shortBlocks = M;
Chris@69 997 else
Chris@69 998 shortBlocks = 0;
Chris@69 999
Chris@69 1000 /* Decode the global flags (first symbols in the stream) */
Chris@69 1001 intra_ener = tell+3<=total_bits ? ec_dec_bit_logp(dec, 3) : 0;
Chris@69 1002 /* Get band energies */
Chris@69 1003 unquant_coarse_energy(mode, start, end, oldBandE,
Chris@69 1004 intra_ener, dec, C, LM);
Chris@69 1005
Chris@69 1006 ALLOC(tf_res, nbEBands, int);
Chris@69 1007 tf_decode(start, end, isTransient, tf_res, LM, dec);
Chris@69 1008
Chris@69 1009 tell = ec_tell(dec);
Chris@69 1010 spread_decision = SPREAD_NORMAL;
Chris@69 1011 if (tell+4 <= total_bits)
Chris@69 1012 spread_decision = ec_dec_icdf(dec, spread_icdf, 5);
Chris@69 1013
Chris@69 1014 ALLOC(cap, nbEBands, int);
Chris@69 1015
Chris@69 1016 init_caps(mode,cap,LM,C);
Chris@69 1017
Chris@69 1018 ALLOC(offsets, nbEBands, int);
Chris@69 1019
Chris@69 1020 dynalloc_logp = 6;
Chris@69 1021 total_bits<<=BITRES;
Chris@69 1022 tell = ec_tell_frac(dec);
Chris@69 1023 for (i=start;i<end;i++)
Chris@69 1024 {
Chris@69 1025 int width, quanta;
Chris@69 1026 int dynalloc_loop_logp;
Chris@69 1027 int boost;
Chris@69 1028 width = C*(eBands[i+1]-eBands[i])<<LM;
Chris@69 1029 /* quanta is 6 bits, but no more than 1 bit/sample
Chris@69 1030 and no less than 1/8 bit/sample */
Chris@69 1031 quanta = IMIN(width<<BITRES, IMAX(6<<BITRES, width));
Chris@69 1032 dynalloc_loop_logp = dynalloc_logp;
Chris@69 1033 boost = 0;
Chris@69 1034 while (tell+(dynalloc_loop_logp<<BITRES) < total_bits && boost < cap[i])
Chris@69 1035 {
Chris@69 1036 int flag;
Chris@69 1037 flag = ec_dec_bit_logp(dec, dynalloc_loop_logp);
Chris@69 1038 tell = ec_tell_frac(dec);
Chris@69 1039 if (!flag)
Chris@69 1040 break;
Chris@69 1041 boost += quanta;
Chris@69 1042 total_bits -= quanta;
Chris@69 1043 dynalloc_loop_logp = 1;
Chris@69 1044 }
Chris@69 1045 offsets[i] = boost;
Chris@69 1046 /* Making dynalloc more likely */
Chris@69 1047 if (boost>0)
Chris@69 1048 dynalloc_logp = IMAX(2, dynalloc_logp-1);
Chris@69 1049 }
Chris@69 1050
Chris@69 1051 ALLOC(fine_quant, nbEBands, int);
Chris@69 1052 alloc_trim = tell+(6<<BITRES) <= total_bits ?
Chris@69 1053 ec_dec_icdf(dec, trim_icdf, 7) : 5;
Chris@69 1054
Chris@69 1055 bits = (((opus_int32)len*8)<<BITRES) - ec_tell_frac(dec) - 1;
Chris@69 1056 anti_collapse_rsv = isTransient&&LM>=2&&bits>=((LM+2)<<BITRES) ? (1<<BITRES) : 0;
Chris@69 1057 bits -= anti_collapse_rsv;
Chris@69 1058
Chris@69 1059 ALLOC(pulses, nbEBands, int);
Chris@69 1060 ALLOC(fine_priority, nbEBands, int);
Chris@69 1061
Chris@69 1062 codedBands = clt_compute_allocation(mode, start, end, offsets, cap,
Chris@69 1063 alloc_trim, &intensity, &dual_stereo, bits, &balance, pulses,
Chris@69 1064 fine_quant, fine_priority, C, LM, dec, 0, 0, 0);
Chris@69 1065
Chris@69 1066 unquant_fine_energy(mode, start, end, oldBandE, fine_quant, dec, C);
Chris@69 1067
Chris@69 1068 c=0; do {
Chris@69 1069 OPUS_MOVE(decode_mem[c], decode_mem[c]+N, DECODE_BUFFER_SIZE-N+overlap/2);
Chris@69 1070 } while (++c<CC);
Chris@69 1071
Chris@69 1072 /* Decode fixed codebook */
Chris@69 1073 ALLOC(collapse_masks, C*nbEBands, unsigned char);
Chris@69 1074
Chris@69 1075 #ifdef NORM_ALIASING_HACK
Chris@69 1076 /* This is an ugly hack that breaks aliasing rules and would be easily broken,
Chris@69 1077 but it saves almost 4kB of stack. */
Chris@69 1078 X = (celt_norm*)(out_syn[CC-1]+overlap/2);
Chris@69 1079 #else
Chris@69 1080 ALLOC(X, C*N, celt_norm); /**< Interleaved normalised MDCTs */
Chris@69 1081 #endif
Chris@69 1082
Chris@69 1083 quant_all_bands(0, mode, start, end, X, C==2 ? X+N : NULL, collapse_masks,
Chris@69 1084 NULL, pulses, shortBlocks, spread_decision, dual_stereo, intensity, tf_res,
Chris@69 1085 len*(8<<BITRES)-anti_collapse_rsv, balance, dec, LM, codedBands, &st->rng, 0,
Chris@69 1086 st->arch, st->disable_inv);
Chris@69 1087
Chris@69 1088 if (anti_collapse_rsv > 0)
Chris@69 1089 {
Chris@69 1090 anti_collapse_on = ec_dec_bits(dec, 1);
Chris@69 1091 }
Chris@69 1092
Chris@69 1093 unquant_energy_finalise(mode, start, end, oldBandE,
Chris@69 1094 fine_quant, fine_priority, len*8-ec_tell(dec), dec, C);
Chris@69 1095
Chris@69 1096 if (anti_collapse_on)
Chris@69 1097 anti_collapse(mode, X, collapse_masks, LM, C, N,
Chris@69 1098 start, end, oldBandE, oldLogE, oldLogE2, pulses, st->rng, st->arch);
Chris@69 1099
Chris@69 1100 if (silence)
Chris@69 1101 {
Chris@69 1102 for (i=0;i<C*nbEBands;i++)
Chris@69 1103 oldBandE[i] = -QCONST16(28.f,DB_SHIFT);
Chris@69 1104 }
Chris@69 1105
Chris@69 1106 celt_synthesis(mode, X, out_syn, oldBandE, start, effEnd,
Chris@69 1107 C, CC, isTransient, LM, st->downsample, silence, st->arch);
Chris@69 1108
Chris@69 1109 c=0; do {
Chris@69 1110 st->postfilter_period=IMAX(st->postfilter_period, COMBFILTER_MINPERIOD);
Chris@69 1111 st->postfilter_period_old=IMAX(st->postfilter_period_old, COMBFILTER_MINPERIOD);
Chris@69 1112 comb_filter(out_syn[c], out_syn[c], st->postfilter_period_old, st->postfilter_period, mode->shortMdctSize,
Chris@69 1113 st->postfilter_gain_old, st->postfilter_gain, st->postfilter_tapset_old, st->postfilter_tapset,
Chris@69 1114 mode->window, overlap, st->arch);
Chris@69 1115 if (LM!=0)
Chris@69 1116 comb_filter(out_syn[c]+mode->shortMdctSize, out_syn[c]+mode->shortMdctSize, st->postfilter_period, postfilter_pitch, N-mode->shortMdctSize,
Chris@69 1117 st->postfilter_gain, postfilter_gain, st->postfilter_tapset, postfilter_tapset,
Chris@69 1118 mode->window, overlap, st->arch);
Chris@69 1119
Chris@69 1120 } while (++c<CC);
Chris@69 1121 st->postfilter_period_old = st->postfilter_period;
Chris@69 1122 st->postfilter_gain_old = st->postfilter_gain;
Chris@69 1123 st->postfilter_tapset_old = st->postfilter_tapset;
Chris@69 1124 st->postfilter_period = postfilter_pitch;
Chris@69 1125 st->postfilter_gain = postfilter_gain;
Chris@69 1126 st->postfilter_tapset = postfilter_tapset;
Chris@69 1127 if (LM!=0)
Chris@69 1128 {
Chris@69 1129 st->postfilter_period_old = st->postfilter_period;
Chris@69 1130 st->postfilter_gain_old = st->postfilter_gain;
Chris@69 1131 st->postfilter_tapset_old = st->postfilter_tapset;
Chris@69 1132 }
Chris@69 1133
Chris@69 1134 if (C==1)
Chris@69 1135 OPUS_COPY(&oldBandE[nbEBands], oldBandE, nbEBands);
Chris@69 1136
Chris@69 1137 /* In case start or end were to change */
Chris@69 1138 if (!isTransient)
Chris@69 1139 {
Chris@69 1140 opus_val16 max_background_increase;
Chris@69 1141 OPUS_COPY(oldLogE2, oldLogE, 2*nbEBands);
Chris@69 1142 OPUS_COPY(oldLogE, oldBandE, 2*nbEBands);
Chris@69 1143 /* In normal circumstances, we only allow the noise floor to increase by
Chris@69 1144 up to 2.4 dB/second, but when we're in DTX, we allow up to 6 dB
Chris@69 1145 increase for each update.*/
Chris@69 1146 if (st->loss_count < 10)
Chris@69 1147 max_background_increase = M*QCONST16(0.001f,DB_SHIFT);
Chris@69 1148 else
Chris@69 1149 max_background_increase = QCONST16(1.f,DB_SHIFT);
Chris@69 1150 for (i=0;i<2*nbEBands;i++)
Chris@69 1151 backgroundLogE[i] = MIN16(backgroundLogE[i] + max_background_increase, oldBandE[i]);
Chris@69 1152 } else {
Chris@69 1153 for (i=0;i<2*nbEBands;i++)
Chris@69 1154 oldLogE[i] = MIN16(oldLogE[i], oldBandE[i]);
Chris@69 1155 }
Chris@69 1156 c=0; do
Chris@69 1157 {
Chris@69 1158 for (i=0;i<start;i++)
Chris@69 1159 {
Chris@69 1160 oldBandE[c*nbEBands+i]=0;
Chris@69 1161 oldLogE[c*nbEBands+i]=oldLogE2[c*nbEBands+i]=-QCONST16(28.f,DB_SHIFT);
Chris@69 1162 }
Chris@69 1163 for (i=end;i<nbEBands;i++)
Chris@69 1164 {
Chris@69 1165 oldBandE[c*nbEBands+i]=0;
Chris@69 1166 oldLogE[c*nbEBands+i]=oldLogE2[c*nbEBands+i]=-QCONST16(28.f,DB_SHIFT);
Chris@69 1167 }
Chris@69 1168 } while (++c<2);
Chris@69 1169 st->rng = dec->rng;
Chris@69 1170
Chris@69 1171 deemphasis(out_syn, pcm, N, CC, st->downsample, mode->preemph, st->preemph_memD, accum);
Chris@69 1172 st->loss_count = 0;
Chris@69 1173 RESTORE_STACK;
Chris@69 1174 if (ec_tell(dec) > 8*len)
Chris@69 1175 return OPUS_INTERNAL_ERROR;
Chris@69 1176 if(ec_get_error(dec))
Chris@69 1177 st->error = 1;
Chris@69 1178 return frame_size/st->downsample;
Chris@69 1179 }
Chris@69 1180
Chris@69 1181
Chris@69 1182 #ifdef CUSTOM_MODES
Chris@69 1183
Chris@69 1184 #ifdef FIXED_POINT
Chris@69 1185 int opus_custom_decode(CELTDecoder * OPUS_RESTRICT st, const unsigned char *data, int len, opus_int16 * OPUS_RESTRICT pcm, int frame_size)
Chris@69 1186 {
Chris@69 1187 return celt_decode_with_ec(st, data, len, pcm, frame_size, NULL, 0);
Chris@69 1188 }
Chris@69 1189
Chris@69 1190 #ifndef DISABLE_FLOAT_API
Chris@69 1191 int opus_custom_decode_float(CELTDecoder * OPUS_RESTRICT st, const unsigned char *data, int len, float * OPUS_RESTRICT pcm, int frame_size)
Chris@69 1192 {
Chris@69 1193 int j, ret, C, N;
Chris@69 1194 VARDECL(opus_int16, out);
Chris@69 1195 ALLOC_STACK;
Chris@69 1196
Chris@69 1197 if (pcm==NULL)
Chris@69 1198 return OPUS_BAD_ARG;
Chris@69 1199
Chris@69 1200 C = st->channels;
Chris@69 1201 N = frame_size;
Chris@69 1202
Chris@69 1203 ALLOC(out, C*N, opus_int16);
Chris@69 1204 ret=celt_decode_with_ec(st, data, len, out, frame_size, NULL, 0);
Chris@69 1205 if (ret>0)
Chris@69 1206 for (j=0;j<C*ret;j++)
Chris@69 1207 pcm[j]=out[j]*(1.f/32768.f);
Chris@69 1208
Chris@69 1209 RESTORE_STACK;
Chris@69 1210 return ret;
Chris@69 1211 }
Chris@69 1212 #endif /* DISABLE_FLOAT_API */
Chris@69 1213
Chris@69 1214 #else
Chris@69 1215
Chris@69 1216 int opus_custom_decode_float(CELTDecoder * OPUS_RESTRICT st, const unsigned char *data, int len, float * OPUS_RESTRICT pcm, int frame_size)
Chris@69 1217 {
Chris@69 1218 return celt_decode_with_ec(st, data, len, pcm, frame_size, NULL, 0);
Chris@69 1219 }
Chris@69 1220
Chris@69 1221 int opus_custom_decode(CELTDecoder * OPUS_RESTRICT st, const unsigned char *data, int len, opus_int16 * OPUS_RESTRICT pcm, int frame_size)
Chris@69 1222 {
Chris@69 1223 int j, ret, C, N;
Chris@69 1224 VARDECL(celt_sig, out);
Chris@69 1225 ALLOC_STACK;
Chris@69 1226
Chris@69 1227 if (pcm==NULL)
Chris@69 1228 return OPUS_BAD_ARG;
Chris@69 1229
Chris@69 1230 C = st->channels;
Chris@69 1231 N = frame_size;
Chris@69 1232 ALLOC(out, C*N, celt_sig);
Chris@69 1233
Chris@69 1234 ret=celt_decode_with_ec(st, data, len, out, frame_size, NULL, 0);
Chris@69 1235
Chris@69 1236 if (ret>0)
Chris@69 1237 for (j=0;j<C*ret;j++)
Chris@69 1238 pcm[j] = FLOAT2INT16 (out[j]);
Chris@69 1239
Chris@69 1240 RESTORE_STACK;
Chris@69 1241 return ret;
Chris@69 1242 }
Chris@69 1243
Chris@69 1244 #endif
Chris@69 1245 #endif /* CUSTOM_MODES */
Chris@69 1246
Chris@69 1247 int opus_custom_decoder_ctl(CELTDecoder * OPUS_RESTRICT st, int request, ...)
Chris@69 1248 {
Chris@69 1249 va_list ap;
Chris@69 1250
Chris@69 1251 va_start(ap, request);
Chris@69 1252 switch (request)
Chris@69 1253 {
Chris@69 1254 case CELT_SET_START_BAND_REQUEST:
Chris@69 1255 {
Chris@69 1256 opus_int32 value = va_arg(ap, opus_int32);
Chris@69 1257 if (value<0 || value>=st->mode->nbEBands)
Chris@69 1258 goto bad_arg;
Chris@69 1259 st->start = value;
Chris@69 1260 }
Chris@69 1261 break;
Chris@69 1262 case CELT_SET_END_BAND_REQUEST:
Chris@69 1263 {
Chris@69 1264 opus_int32 value = va_arg(ap, opus_int32);
Chris@69 1265 if (value<1 || value>st->mode->nbEBands)
Chris@69 1266 goto bad_arg;
Chris@69 1267 st->end = value;
Chris@69 1268 }
Chris@69 1269 break;
Chris@69 1270 case CELT_SET_CHANNELS_REQUEST:
Chris@69 1271 {
Chris@69 1272 opus_int32 value = va_arg(ap, opus_int32);
Chris@69 1273 if (value<1 || value>2)
Chris@69 1274 goto bad_arg;
Chris@69 1275 st->stream_channels = value;
Chris@69 1276 }
Chris@69 1277 break;
Chris@69 1278 case CELT_GET_AND_CLEAR_ERROR_REQUEST:
Chris@69 1279 {
Chris@69 1280 opus_int32 *value = va_arg(ap, opus_int32*);
Chris@69 1281 if (value==NULL)
Chris@69 1282 goto bad_arg;
Chris@69 1283 *value=st->error;
Chris@69 1284 st->error = 0;
Chris@69 1285 }
Chris@69 1286 break;
Chris@69 1287 case OPUS_GET_LOOKAHEAD_REQUEST:
Chris@69 1288 {
Chris@69 1289 opus_int32 *value = va_arg(ap, opus_int32*);
Chris@69 1290 if (value==NULL)
Chris@69 1291 goto bad_arg;
Chris@69 1292 *value = st->overlap/st->downsample;
Chris@69 1293 }
Chris@69 1294 break;
Chris@69 1295 case OPUS_RESET_STATE:
Chris@69 1296 {
Chris@69 1297 int i;
Chris@69 1298 opus_val16 *lpc, *oldBandE, *oldLogE, *oldLogE2;
Chris@69 1299 lpc = (opus_val16*)(st->_decode_mem+(DECODE_BUFFER_SIZE+st->overlap)*st->channels);
Chris@69 1300 oldBandE = lpc+st->channels*LPC_ORDER;
Chris@69 1301 oldLogE = oldBandE + 2*st->mode->nbEBands;
Chris@69 1302 oldLogE2 = oldLogE + 2*st->mode->nbEBands;
Chris@69 1303 OPUS_CLEAR((char*)&st->DECODER_RESET_START,
Chris@69 1304 opus_custom_decoder_get_size(st->mode, st->channels)-
Chris@69 1305 ((char*)&st->DECODER_RESET_START - (char*)st));
Chris@69 1306 for (i=0;i<2*st->mode->nbEBands;i++)
Chris@69 1307 oldLogE[i]=oldLogE2[i]=-QCONST16(28.f,DB_SHIFT);
Chris@69 1308 st->skip_plc = 1;
Chris@69 1309 }
Chris@69 1310 break;
Chris@69 1311 case OPUS_GET_PITCH_REQUEST:
Chris@69 1312 {
Chris@69 1313 opus_int32 *value = va_arg(ap, opus_int32*);
Chris@69 1314 if (value==NULL)
Chris@69 1315 goto bad_arg;
Chris@69 1316 *value = st->postfilter_period;
Chris@69 1317 }
Chris@69 1318 break;
Chris@69 1319 case CELT_GET_MODE_REQUEST:
Chris@69 1320 {
Chris@69 1321 const CELTMode ** value = va_arg(ap, const CELTMode**);
Chris@69 1322 if (value==0)
Chris@69 1323 goto bad_arg;
Chris@69 1324 *value=st->mode;
Chris@69 1325 }
Chris@69 1326 break;
Chris@69 1327 case CELT_SET_SIGNALLING_REQUEST:
Chris@69 1328 {
Chris@69 1329 opus_int32 value = va_arg(ap, opus_int32);
Chris@69 1330 st->signalling = value;
Chris@69 1331 }
Chris@69 1332 break;
Chris@69 1333 case OPUS_GET_FINAL_RANGE_REQUEST:
Chris@69 1334 {
Chris@69 1335 opus_uint32 * value = va_arg(ap, opus_uint32 *);
Chris@69 1336 if (value==0)
Chris@69 1337 goto bad_arg;
Chris@69 1338 *value=st->rng;
Chris@69 1339 }
Chris@69 1340 break;
Chris@69 1341 case OPUS_SET_PHASE_INVERSION_DISABLED_REQUEST:
Chris@69 1342 {
Chris@69 1343 opus_int32 value = va_arg(ap, opus_int32);
Chris@69 1344 if(value<0 || value>1)
Chris@69 1345 {
Chris@69 1346 goto bad_arg;
Chris@69 1347 }
Chris@69 1348 st->disable_inv = value;
Chris@69 1349 }
Chris@69 1350 break;
Chris@69 1351 case OPUS_GET_PHASE_INVERSION_DISABLED_REQUEST:
Chris@69 1352 {
Chris@69 1353 opus_int32 *value = va_arg(ap, opus_int32*);
Chris@69 1354 if (!value)
Chris@69 1355 {
Chris@69 1356 goto bad_arg;
Chris@69 1357 }
Chris@69 1358 *value = st->disable_inv;
Chris@69 1359 }
Chris@69 1360 break;
Chris@69 1361 default:
Chris@69 1362 goto bad_request;
Chris@69 1363 }
Chris@69 1364 va_end(ap);
Chris@69 1365 return OPUS_OK;
Chris@69 1366 bad_arg:
Chris@69 1367 va_end(ap);
Chris@69 1368 return OPUS_BAD_ARG;
Chris@69 1369 bad_request:
Chris@69 1370 va_end(ap);
Chris@69 1371 return OPUS_UNIMPLEMENTED;
Chris@69 1372 }