annotate src/opus-1.3/celt/celt_decoder.c @ 83:ae30d91d2ffe

Replace these with versions built using an older toolset (so as to avoid ABI compatibilities when linking on Ubuntu 14.04 for packaging purposes)
author Chris Cannam
date Fri, 07 Feb 2020 11:51:13 +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 }