michael@0: /* Copyright (c) 2007-2008 CSIRO michael@0: Copyright (c) 2007-2010 Xiph.Org Foundation michael@0: Copyright (c) 2008 Gregory Maxwell michael@0: Written by Jean-Marc Valin and Gregory Maxwell */ michael@0: /* michael@0: Redistribution and use in source and binary forms, with or without michael@0: modification, are permitted provided that the following conditions michael@0: are met: michael@0: michael@0: - Redistributions of source code must retain the above copyright michael@0: notice, this list of conditions and the following disclaimer. michael@0: michael@0: - Redistributions in binary form must reproduce the above copyright michael@0: notice, this list of conditions and the following disclaimer in the michael@0: documentation and/or other materials provided with the distribution. michael@0: michael@0: THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS michael@0: ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT michael@0: LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR michael@0: A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER michael@0: OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, michael@0: EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, michael@0: PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR michael@0: PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF michael@0: LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING michael@0: NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS michael@0: SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. michael@0: */ michael@0: michael@0: #ifdef HAVE_CONFIG_H michael@0: #include "config.h" michael@0: #endif michael@0: michael@0: #define CELT_DECODER_C michael@0: michael@0: #include "cpu_support.h" michael@0: #include "os_support.h" michael@0: #include "mdct.h" michael@0: #include michael@0: #include "celt.h" michael@0: #include "pitch.h" michael@0: #include "bands.h" michael@0: #include "modes.h" michael@0: #include "entcode.h" michael@0: #include "quant_bands.h" michael@0: #include "rate.h" michael@0: #include "stack_alloc.h" michael@0: #include "mathops.h" michael@0: #include "float_cast.h" michael@0: #include michael@0: #include "celt_lpc.h" michael@0: #include "vq.h" michael@0: michael@0: /**********************************************************************/ michael@0: /* */ michael@0: /* DECODER */ michael@0: /* */ michael@0: /**********************************************************************/ michael@0: #define DECODE_BUFFER_SIZE 2048 michael@0: michael@0: /** Decoder state michael@0: @brief Decoder state michael@0: */ michael@0: struct OpusCustomDecoder { michael@0: const OpusCustomMode *mode; michael@0: int overlap; michael@0: int channels; michael@0: int stream_channels; michael@0: michael@0: int downsample; michael@0: int start, end; michael@0: int signalling; michael@0: int arch; michael@0: michael@0: /* Everything beyond this point gets cleared on a reset */ michael@0: #define DECODER_RESET_START rng michael@0: michael@0: opus_uint32 rng; michael@0: int error; michael@0: int last_pitch_index; michael@0: int loss_count; michael@0: int postfilter_period; michael@0: int postfilter_period_old; michael@0: opus_val16 postfilter_gain; michael@0: opus_val16 postfilter_gain_old; michael@0: int postfilter_tapset; michael@0: int postfilter_tapset_old; michael@0: michael@0: celt_sig preemph_memD[2]; michael@0: michael@0: celt_sig _decode_mem[1]; /* Size = channels*(DECODE_BUFFER_SIZE+mode->overlap) */ michael@0: /* opus_val16 lpc[], Size = channels*LPC_ORDER */ michael@0: /* opus_val16 oldEBands[], Size = 2*mode->nbEBands */ michael@0: /* opus_val16 oldLogE[], Size = 2*mode->nbEBands */ michael@0: /* opus_val16 oldLogE2[], Size = 2*mode->nbEBands */ michael@0: /* opus_val16 backgroundLogE[], Size = 2*mode->nbEBands */ michael@0: }; michael@0: michael@0: int celt_decoder_get_size(int channels) michael@0: { michael@0: const CELTMode *mode = opus_custom_mode_create(48000, 960, NULL); michael@0: return opus_custom_decoder_get_size(mode, channels); michael@0: } michael@0: michael@0: OPUS_CUSTOM_NOSTATIC int opus_custom_decoder_get_size(const CELTMode *mode, int channels) michael@0: { michael@0: int size = sizeof(struct CELTDecoder) michael@0: + (channels*(DECODE_BUFFER_SIZE+mode->overlap)-1)*sizeof(celt_sig) michael@0: + channels*LPC_ORDER*sizeof(opus_val16) michael@0: + 4*2*mode->nbEBands*sizeof(opus_val16); michael@0: return size; michael@0: } michael@0: michael@0: #ifdef CUSTOM_MODES michael@0: CELTDecoder *opus_custom_decoder_create(const CELTMode *mode, int channels, int *error) michael@0: { michael@0: int ret; michael@0: CELTDecoder *st = (CELTDecoder *)opus_alloc(opus_custom_decoder_get_size(mode, channels)); michael@0: ret = opus_custom_decoder_init(st, mode, channels); michael@0: if (ret != OPUS_OK) michael@0: { michael@0: opus_custom_decoder_destroy(st); michael@0: st = NULL; michael@0: } michael@0: if (error) michael@0: *error = ret; michael@0: return st; michael@0: } michael@0: #endif /* CUSTOM_MODES */ michael@0: michael@0: int celt_decoder_init(CELTDecoder *st, opus_int32 sampling_rate, int channels) michael@0: { michael@0: int ret; michael@0: ret = opus_custom_decoder_init(st, opus_custom_mode_create(48000, 960, NULL), channels); michael@0: if (ret != OPUS_OK) michael@0: return ret; michael@0: st->downsample = resampling_factor(sampling_rate); michael@0: if (st->downsample==0) michael@0: return OPUS_BAD_ARG; michael@0: else michael@0: return OPUS_OK; michael@0: } michael@0: michael@0: OPUS_CUSTOM_NOSTATIC int opus_custom_decoder_init(CELTDecoder *st, const CELTMode *mode, int channels) michael@0: { michael@0: if (channels < 0 || channels > 2) michael@0: return OPUS_BAD_ARG; michael@0: michael@0: if (st==NULL) michael@0: return OPUS_ALLOC_FAIL; michael@0: michael@0: OPUS_CLEAR((char*)st, opus_custom_decoder_get_size(mode, channels)); michael@0: michael@0: st->mode = mode; michael@0: st->overlap = mode->overlap; michael@0: st->stream_channels = st->channels = channels; michael@0: michael@0: st->downsample = 1; michael@0: st->start = 0; michael@0: st->end = st->mode->effEBands; michael@0: st->signalling = 1; michael@0: st->arch = opus_select_arch(); michael@0: michael@0: st->loss_count = 0; michael@0: michael@0: opus_custom_decoder_ctl(st, OPUS_RESET_STATE); michael@0: michael@0: return OPUS_OK; michael@0: } michael@0: michael@0: #ifdef CUSTOM_MODES michael@0: void opus_custom_decoder_destroy(CELTDecoder *st) michael@0: { michael@0: opus_free(st); michael@0: } michael@0: #endif /* CUSTOM_MODES */ michael@0: michael@0: static OPUS_INLINE opus_val16 SIG2WORD16(celt_sig x) michael@0: { michael@0: #ifdef FIXED_POINT michael@0: x = PSHR32(x, SIG_SHIFT); michael@0: x = MAX32(x, -32768); michael@0: x = MIN32(x, 32767); michael@0: return EXTRACT16(x); michael@0: #else michael@0: return (opus_val16)x; michael@0: #endif michael@0: } michael@0: michael@0: #ifndef RESYNTH michael@0: static michael@0: #endif michael@0: void deemphasis(celt_sig *in[], opus_val16 *pcm, int N, int C, int downsample, const opus_val16 *coef, celt_sig *mem, celt_sig * OPUS_RESTRICT scratch) michael@0: { michael@0: int c; michael@0: int Nd; michael@0: int apply_downsampling=0; michael@0: opus_val16 coef0; michael@0: michael@0: coef0 = coef[0]; michael@0: Nd = N/downsample; michael@0: c=0; do { michael@0: int j; michael@0: celt_sig * OPUS_RESTRICT x; michael@0: opus_val16 * OPUS_RESTRICT y; michael@0: celt_sig m = mem[c]; michael@0: x =in[c]; michael@0: y = pcm+c; michael@0: #ifdef CUSTOM_MODES michael@0: if (coef[1] != 0) michael@0: { michael@0: opus_val16 coef1 = coef[1]; michael@0: opus_val16 coef3 = coef[3]; michael@0: for (j=0;j1) michael@0: { michael@0: /* Shortcut for the standard (non-custom modes) case */ michael@0: for (j=0;jshortMdctSize; michael@0: shift = mode->maxLM; michael@0: } else { michael@0: B = 1; michael@0: N = mode->shortMdctSize<maxLM-LM; michael@0: } michael@0: c=0; do { michael@0: /* IMDCT on the interleaved the sub-frames, overlap-add is performed by the IMDCT */ michael@0: for (b=0;bmdct, &X[b+c*N*B], out_mem[c]+N*b, mode->window, overlap, shift, B); michael@0: } while (++cstorage*8; michael@0: tell = ec_tell(dec); michael@0: logp = isTransient ? 2 : 4; michael@0: tf_select_rsv = LM>0 && tell+logp+1<=budget; michael@0: budget -= tf_select_rsv; michael@0: tf_changed = curr = 0; michael@0: for (i=start;ichannels; michael@0: celt_sig *decode_mem[2]; michael@0: celt_sig *out_syn[2]; michael@0: opus_val16 *lpc; michael@0: opus_val16 *oldBandE, *oldLogE, *oldLogE2, *backgroundLogE; michael@0: const OpusCustomMode *mode; michael@0: int nbEBands; michael@0: int overlap; michael@0: int start; michael@0: int downsample; michael@0: int loss_count; michael@0: int noise_based; michael@0: const opus_int16 *eBands; michael@0: VARDECL(celt_sig, scratch); michael@0: SAVE_STACK; michael@0: michael@0: mode = st->mode; michael@0: nbEBands = mode->nbEBands; michael@0: overlap = mode->overlap; michael@0: eBands = mode->eBands; michael@0: michael@0: c=0; do { michael@0: decode_mem[c] = st->_decode_mem + c*(DECODE_BUFFER_SIZE+overlap); michael@0: out_syn[c] = decode_mem[c]+DECODE_BUFFER_SIZE-N; michael@0: } while (++c_decode_mem+(DECODE_BUFFER_SIZE+overlap)*C); michael@0: oldBandE = lpc+C*LPC_ORDER; michael@0: oldLogE = oldBandE + 2*nbEBands; michael@0: oldLogE2 = oldLogE + 2*nbEBands; michael@0: backgroundLogE = oldLogE2 + 2*nbEBands; michael@0: michael@0: loss_count = st->loss_count; michael@0: start = st->start; michael@0: downsample = st->downsample; michael@0: noise_based = loss_count >= 5 || start != 0; michael@0: ALLOC(scratch, noise_based?N*C:N, celt_sig); michael@0: if (noise_based) michael@0: { michael@0: /* Noise-based PLC/CNG */ michael@0: celt_sig *freq; michael@0: VARDECL(celt_norm, X); michael@0: opus_uint32 seed; michael@0: opus_val16 *plcLogE; michael@0: int end; michael@0: int effEnd; michael@0: michael@0: end = st->end; michael@0: effEnd = IMAX(start, IMIN(end, mode->effEBands)); michael@0: michael@0: /* Share the interleaved signal MDCT coefficient buffer with the michael@0: deemphasis scratch buffer. */ michael@0: freq = scratch; michael@0: ALLOC(X, C*N, celt_norm); /**< Interleaved normalised MDCTs */ michael@0: michael@0: if (loss_count >= 5) michael@0: plcLogE = backgroundLogE; michael@0: else { michael@0: /* Energy decay */ michael@0: opus_val16 decay = loss_count==0 ? michael@0: QCONST16(1.5f, DB_SHIFT) : QCONST16(.5f, DB_SHIFT); michael@0: c=0; do michael@0: { michael@0: for (i=start;irng; michael@0: for (c=0;c>20); michael@0: } michael@0: renormalise_vector(X+boffs, blen, Q15ONE); michael@0: } michael@0: } michael@0: st->rng = seed; michael@0: michael@0: denormalise_bands(mode, X, freq, plcLogE, start, effEnd, C, 1<>1)); michael@0: } while (++c>1, opus_val16 ); michael@0: pitch_downsample(decode_mem, lp_pitch_buf, michael@0: DECODE_BUFFER_SIZE, C, st->arch); michael@0: pitch_search(lp_pitch_buf+(PLC_PITCH_LAG_MAX>>1), lp_pitch_buf, michael@0: DECODE_BUFFER_SIZE-PLC_PITCH_LAG_MAX, michael@0: PLC_PITCH_LAG_MAX-PLC_PITCH_LAG_MIN, &pitch_index, st->arch); michael@0: pitch_index = PLC_PITCH_LAG_MAX-pitch_index; michael@0: st->last_pitch_index = pitch_index; michael@0: } else { michael@0: pitch_index = st->last_pitch_index; michael@0: fade = QCONST16(.8f,15); michael@0: } michael@0: michael@0: ALLOC(etmp, overlap, opus_val32); michael@0: ALLOC(exc, MAX_PERIOD, opus_val16); michael@0: window = mode->window; michael@0: c=0; do { michael@0: opus_val16 decay; michael@0: opus_val16 attenuation; michael@0: opus_val32 S1=0; michael@0: celt_sig *buf; michael@0: int extrapolation_offset; michael@0: int extrapolation_len; michael@0: int exc_length; michael@0: int j; michael@0: michael@0: buf = decode_mem[c]; michael@0: for (i=0;iarch); michael@0: /* Add a noise floor of -40 dB. */ michael@0: #ifdef FIXED_POINT michael@0: ac[0] += SHR32(ac[0],13); michael@0: #else michael@0: ac[0] *= 1.0001f; michael@0: #endif michael@0: /* Use lag windowing to stabilize the Levinson-Durbin recursion. */ michael@0: for (i=1;i<=LPC_ORDER;i++) michael@0: { michael@0: /*ac[i] *= exp(-.5*(2*M_PI*.002*i)*(2*M_PI*.002*i));*/ michael@0: #ifdef FIXED_POINT michael@0: ac[i] -= MULT16_32_Q15(2*i*i, ac[i]); michael@0: #else michael@0: ac[i] -= ac[i]*(0.008f*0.008f)*i*i; michael@0: #endif michael@0: } michael@0: _celt_lpc(lpc+c*LPC_ORDER, ac, LPC_ORDER); michael@0: } michael@0: /* We want the excitation for 2 pitch periods in order to look for a michael@0: decaying signal, but we can't get more than MAX_PERIOD. */ michael@0: exc_length = IMIN(2*pitch_index, MAX_PERIOD); michael@0: /* Initialize the LPC history with the samples just before the start michael@0: of the region for which we're computing the excitation. */ michael@0: { michael@0: opus_val16 lpc_mem[LPC_ORDER]; michael@0: for (i=0;i>1; michael@0: for (i=0;i= pitch_index) { michael@0: j -= pitch_index; michael@0: attenuation = MULT16_16_Q15(attenuation, decay); michael@0: } michael@0: buf[DECODE_BUFFER_SIZE-N+i] = michael@0: SHL32(EXTEND32(MULT16_16_Q15(attenuation, michael@0: exc[extrapolation_offset+j])), SIG_SHIFT); michael@0: /* Compute the energy of the previously decoded signal whose michael@0: excitation we're copying. */ michael@0: tmp = ROUND16( michael@0: buf[DECODE_BUFFER_SIZE-MAX_PERIOD-N+extrapolation_offset+j], michael@0: SIG_SHIFT); michael@0: S1 += SHR32(MULT16_16(tmp, tmp), 8); michael@0: } michael@0: michael@0: { michael@0: opus_val16 lpc_mem[LPC_ORDER]; michael@0: /* Copy the last decoded samples (prior to the overlap region) to michael@0: synthesis filter memory so we can have a continuous signal. */ michael@0: for (i=0;i SHR32(S2,2))) michael@0: #else michael@0: /* The float test is written this way to catch NaNs in the output michael@0: of the IIR filter at the same time. */ michael@0: if (!(S1 > 0.2f*S2)) michael@0: #endif michael@0: { michael@0: for (i=0;ipostfilter_period, st->postfilter_period, overlap, michael@0: -st->postfilter_gain, -st->postfilter_gain, michael@0: st->postfilter_tapset, st->postfilter_tapset, NULL, 0); michael@0: michael@0: /* Simulate TDAC on the concealed audio so that it blends with the michael@0: MDCT of the next frame. */ michael@0: for (i=0;ipreemph, st->preemph_memD, scratch); michael@0: michael@0: st->loss_count = loss_count+1; michael@0: michael@0: RESTORE_STACK; michael@0: } michael@0: michael@0: int celt_decode_with_ec(CELTDecoder * OPUS_RESTRICT st, const unsigned char *data, int len, opus_val16 * OPUS_RESTRICT pcm, int frame_size, ec_dec *dec) michael@0: { michael@0: int c, i, N; michael@0: int spread_decision; michael@0: opus_int32 bits; michael@0: ec_dec _dec; michael@0: VARDECL(celt_sig, freq); michael@0: VARDECL(celt_norm, X); michael@0: VARDECL(int, fine_quant); michael@0: VARDECL(int, pulses); michael@0: VARDECL(int, cap); michael@0: VARDECL(int, offsets); michael@0: VARDECL(int, fine_priority); michael@0: VARDECL(int, tf_res); michael@0: VARDECL(unsigned char, collapse_masks); michael@0: celt_sig *decode_mem[2]; michael@0: celt_sig *out_syn[2]; michael@0: opus_val16 *lpc; michael@0: opus_val16 *oldBandE, *oldLogE, *oldLogE2, *backgroundLogE; michael@0: michael@0: int shortBlocks; michael@0: int isTransient; michael@0: int intra_ener; michael@0: const int CC = st->channels; michael@0: int LM, M; michael@0: int effEnd; michael@0: int codedBands; michael@0: int alloc_trim; michael@0: int postfilter_pitch; michael@0: opus_val16 postfilter_gain; michael@0: int intensity=0; michael@0: int dual_stereo=0; michael@0: opus_int32 total_bits; michael@0: opus_int32 balance; michael@0: opus_int32 tell; michael@0: int dynalloc_logp; michael@0: int postfilter_tapset; michael@0: int anti_collapse_rsv; michael@0: int anti_collapse_on=0; michael@0: int silence; michael@0: int C = st->stream_channels; michael@0: const OpusCustomMode *mode; michael@0: int nbEBands; michael@0: int overlap; michael@0: const opus_int16 *eBands; michael@0: ALLOC_STACK; michael@0: michael@0: mode = st->mode; michael@0: nbEBands = mode->nbEBands; michael@0: overlap = mode->overlap; michael@0: eBands = mode->eBands; michael@0: frame_size *= st->downsample; michael@0: michael@0: c=0; do { michael@0: decode_mem[c] = st->_decode_mem + c*(DECODE_BUFFER_SIZE+overlap); michael@0: } while (++c_decode_mem+(DECODE_BUFFER_SIZE+overlap)*CC); michael@0: oldBandE = lpc+CC*LPC_ORDER; michael@0: oldLogE = oldBandE + 2*nbEBands; michael@0: oldLogE2 = oldLogE + 2*nbEBands; michael@0: backgroundLogE = oldLogE2 + 2*nbEBands; michael@0: michael@0: #ifdef CUSTOM_MODES michael@0: if (st->signalling && data!=NULL) michael@0: { michael@0: int data0=data[0]; michael@0: /* Convert "standard mode" to Opus header */ michael@0: if (mode->Fs==48000 && mode->shortMdctSize==120) michael@0: { michael@0: data0 = fromOpus(data0); michael@0: if (data0<0) michael@0: return OPUS_INVALID_PACKET; michael@0: } michael@0: st->end = IMAX(1, mode->effEBands-2*(data0>>5)); michael@0: LM = (data0>>3)&0x3; michael@0: C = 1 + ((data0>>2)&0x1); michael@0: data++; michael@0: len--; michael@0: if (LM>mode->maxLM) michael@0: return OPUS_INVALID_PACKET; michael@0: if (frame_size < mode->shortMdctSize<shortMdctSize<maxLM;LM++) michael@0: if (mode->shortMdctSize<mode->maxLM) michael@0: return OPUS_BAD_ARG; michael@0: } michael@0: M=1<1275 || pcm==NULL) michael@0: return OPUS_BAD_ARG; michael@0: michael@0: N = M*mode->shortMdctSize; michael@0: michael@0: effEnd = st->end; michael@0: if (effEnd > mode->effEBands) michael@0: effEnd = mode->effEBands; michael@0: michael@0: if (data == NULL || len<=1) michael@0: { michael@0: celt_decode_lost(st, pcm, N, LM); michael@0: RESTORE_STACK; michael@0: return frame_size/st->downsample; michael@0: } michael@0: michael@0: if (dec == NULL) michael@0: { michael@0: ec_dec_init(&_dec,(unsigned char*)data,len); michael@0: dec = &_dec; michael@0: } michael@0: michael@0: if (C==1) michael@0: { michael@0: for (i=0;i= total_bits) michael@0: silence = 1; michael@0: else if (tell==1) michael@0: silence = ec_dec_bit_logp(dec, 15); michael@0: else michael@0: silence = 0; michael@0: if (silence) michael@0: { michael@0: /* Pretend we've read all the remaining bits */ michael@0: tell = len*8; michael@0: dec->nbits_total+=tell-ec_tell(dec); michael@0: } michael@0: michael@0: postfilter_gain = 0; michael@0: postfilter_pitch = 0; michael@0: postfilter_tapset = 0; michael@0: if (st->start==0 && tell+16 <= total_bits) michael@0: { michael@0: if(ec_dec_bit_logp(dec, 1)) michael@0: { michael@0: int qg, octave; michael@0: octave = ec_dec_uint(dec, 6); michael@0: postfilter_pitch = (16< 0 && tell+3 <= total_bits) michael@0: { michael@0: isTransient = ec_dec_bit_logp(dec, 3); michael@0: tell = ec_tell(dec); michael@0: } michael@0: else michael@0: isTransient = 0; michael@0: michael@0: if (isTransient) michael@0: shortBlocks = M; michael@0: else michael@0: shortBlocks = 0; michael@0: michael@0: /* Decode the global flags (first symbols in the stream) */ michael@0: intra_ener = tell+3<=total_bits ? ec_dec_bit_logp(dec, 3) : 0; michael@0: /* Get band energies */ michael@0: unquant_coarse_energy(mode, st->start, st->end, oldBandE, michael@0: intra_ener, dec, C, LM); michael@0: michael@0: ALLOC(tf_res, nbEBands, int); michael@0: tf_decode(st->start, st->end, isTransient, tf_res, LM, dec); michael@0: michael@0: tell = ec_tell(dec); michael@0: spread_decision = SPREAD_NORMAL; michael@0: if (tell+4 <= total_bits) michael@0: spread_decision = ec_dec_icdf(dec, spread_icdf, 5); michael@0: michael@0: ALLOC(cap, nbEBands, int); michael@0: michael@0: init_caps(mode,cap,LM,C); michael@0: michael@0: ALLOC(offsets, nbEBands, int); michael@0: michael@0: dynalloc_logp = 6; michael@0: total_bits<<=BITRES; michael@0: tell = ec_tell_frac(dec); michael@0: for (i=st->start;iend;i++) michael@0: { michael@0: int width, quanta; michael@0: int dynalloc_loop_logp; michael@0: int boost; michael@0: width = C*(eBands[i+1]-eBands[i])<0) michael@0: dynalloc_logp = IMAX(2, dynalloc_logp-1); michael@0: } michael@0: michael@0: ALLOC(fine_quant, nbEBands, int); michael@0: alloc_trim = tell+(6<=2&&bits>=((LM+2)<start, st->end, offsets, cap, michael@0: alloc_trim, &intensity, &dual_stereo, bits, &balance, pulses, michael@0: fine_quant, fine_priority, C, LM, dec, 0, 0, 0); michael@0: michael@0: unquant_fine_energy(mode, st->start, st->end, oldBandE, fine_quant, dec, C); michael@0: michael@0: /* Decode fixed codebook */ michael@0: ALLOC(collapse_masks, C*nbEBands, unsigned char); michael@0: ALLOC(X, C*N, celt_norm); /**< Interleaved normalised MDCTs */ michael@0: michael@0: quant_all_bands(0, mode, st->start, st->end, X, C==2 ? X+N : NULL, collapse_masks, michael@0: NULL, pulses, shortBlocks, spread_decision, dual_stereo, intensity, tf_res, michael@0: len*(8<rng); michael@0: michael@0: if (anti_collapse_rsv > 0) michael@0: { michael@0: anti_collapse_on = ec_dec_bits(dec, 1); michael@0: } michael@0: michael@0: unquant_energy_finalise(mode, st->start, st->end, oldBandE, michael@0: fine_quant, fine_priority, len*8-ec_tell(dec), dec, C); michael@0: michael@0: if (anti_collapse_on) michael@0: anti_collapse(mode, X, collapse_masks, LM, C, N, michael@0: st->start, st->end, oldBandE, oldLogE, oldLogE2, pulses, st->rng); michael@0: michael@0: ALLOC(freq, IMAX(CC,C)*N, celt_sig); /**< Interleaved signal MDCTs */ michael@0: michael@0: if (silence) michael@0: { michael@0: for (i=0;istart, effEnd, C, M); michael@0: } michael@0: c=0; do { michael@0: OPUS_MOVE(decode_mem[c], decode_mem[c]+N, DECODE_BUFFER_SIZE-N+overlap/2); michael@0: } while (++cdownsample!=1) michael@0: bound = IMIN(bound, N/st->downsample); michael@0: for (i=bound;ipostfilter_period=IMAX(st->postfilter_period, COMBFILTER_MINPERIOD); michael@0: st->postfilter_period_old=IMAX(st->postfilter_period_old, COMBFILTER_MINPERIOD); michael@0: comb_filter(out_syn[c], out_syn[c], st->postfilter_period_old, st->postfilter_period, mode->shortMdctSize, michael@0: st->postfilter_gain_old, st->postfilter_gain, st->postfilter_tapset_old, st->postfilter_tapset, michael@0: mode->window, overlap); michael@0: if (LM!=0) michael@0: comb_filter(out_syn[c]+mode->shortMdctSize, out_syn[c]+mode->shortMdctSize, st->postfilter_period, postfilter_pitch, N-mode->shortMdctSize, michael@0: st->postfilter_gain, postfilter_gain, st->postfilter_tapset, postfilter_tapset, michael@0: mode->window, overlap); michael@0: michael@0: } while (++cpostfilter_period_old = st->postfilter_period; michael@0: st->postfilter_gain_old = st->postfilter_gain; michael@0: st->postfilter_tapset_old = st->postfilter_tapset; michael@0: st->postfilter_period = postfilter_pitch; michael@0: st->postfilter_gain = postfilter_gain; michael@0: st->postfilter_tapset = postfilter_tapset; michael@0: if (LM!=0) michael@0: { michael@0: st->postfilter_period_old = st->postfilter_period; michael@0: st->postfilter_gain_old = st->postfilter_gain; michael@0: st->postfilter_tapset_old = st->postfilter_tapset; michael@0: } michael@0: michael@0: if (C==1) { michael@0: for (i=0;istart;i++) michael@0: { michael@0: oldBandE[c*nbEBands+i]=0; michael@0: oldLogE[c*nbEBands+i]=oldLogE2[c*nbEBands+i]=-QCONST16(28.f,DB_SHIFT); michael@0: } michael@0: for (i=st->end;irng = dec->rng; michael@0: michael@0: /* We reuse freq[] as scratch space for the de-emphasis */ michael@0: deemphasis(out_syn, pcm, N, CC, st->downsample, mode->preemph, st->preemph_memD, freq); michael@0: st->loss_count = 0; michael@0: RESTORE_STACK; michael@0: if (ec_tell(dec) > 8*len) michael@0: return OPUS_INTERNAL_ERROR; michael@0: if(ec_get_error(dec)) michael@0: st->error = 1; michael@0: return frame_size/st->downsample; michael@0: } michael@0: michael@0: michael@0: #ifdef CUSTOM_MODES michael@0: michael@0: #ifdef FIXED_POINT michael@0: int opus_custom_decode(CELTDecoder * OPUS_RESTRICT st, const unsigned char *data, int len, opus_int16 * OPUS_RESTRICT pcm, int frame_size) michael@0: { michael@0: return celt_decode_with_ec(st, data, len, pcm, frame_size, NULL); michael@0: } michael@0: michael@0: #ifndef DISABLE_FLOAT_API michael@0: int opus_custom_decode_float(CELTDecoder * OPUS_RESTRICT st, const unsigned char *data, int len, float * OPUS_RESTRICT pcm, int frame_size) michael@0: { michael@0: int j, ret, C, N; michael@0: VARDECL(opus_int16, out); michael@0: ALLOC_STACK; michael@0: michael@0: if (pcm==NULL) michael@0: return OPUS_BAD_ARG; michael@0: michael@0: C = st->channels; michael@0: N = frame_size; michael@0: michael@0: ALLOC(out, C*N, opus_int16); michael@0: ret=celt_decode_with_ec(st, data, len, out, frame_size, NULL); michael@0: if (ret>0) michael@0: for (j=0;jchannels; michael@0: N = frame_size; michael@0: ALLOC(out, C*N, celt_sig); michael@0: michael@0: ret=celt_decode_with_ec(st, data, len, out, frame_size, NULL); michael@0: michael@0: if (ret>0) michael@0: for (j=0;j=st->mode->nbEBands) michael@0: goto bad_arg; michael@0: st->start = value; michael@0: } michael@0: break; michael@0: case CELT_SET_END_BAND_REQUEST: michael@0: { michael@0: opus_int32 value = va_arg(ap, opus_int32); michael@0: if (value<1 || value>st->mode->nbEBands) michael@0: goto bad_arg; michael@0: st->end = value; michael@0: } michael@0: break; michael@0: case CELT_SET_CHANNELS_REQUEST: michael@0: { michael@0: opus_int32 value = va_arg(ap, opus_int32); michael@0: if (value<1 || value>2) michael@0: goto bad_arg; michael@0: st->stream_channels = value; michael@0: } michael@0: break; michael@0: case CELT_GET_AND_CLEAR_ERROR_REQUEST: michael@0: { michael@0: opus_int32 *value = va_arg(ap, opus_int32*); michael@0: if (value==NULL) michael@0: goto bad_arg; michael@0: *value=st->error; michael@0: st->error = 0; michael@0: } michael@0: break; michael@0: case OPUS_GET_LOOKAHEAD_REQUEST: michael@0: { michael@0: opus_int32 *value = va_arg(ap, opus_int32*); michael@0: if (value==NULL) michael@0: goto bad_arg; michael@0: *value = st->overlap/st->downsample; michael@0: } michael@0: break; michael@0: case OPUS_RESET_STATE: michael@0: { michael@0: int i; michael@0: opus_val16 *lpc, *oldBandE, *oldLogE, *oldLogE2; michael@0: lpc = (opus_val16*)(st->_decode_mem+(DECODE_BUFFER_SIZE+st->overlap)*st->channels); michael@0: oldBandE = lpc+st->channels*LPC_ORDER; michael@0: oldLogE = oldBandE + 2*st->mode->nbEBands; michael@0: oldLogE2 = oldLogE + 2*st->mode->nbEBands; michael@0: OPUS_CLEAR((char*)&st->DECODER_RESET_START, michael@0: opus_custom_decoder_get_size(st->mode, st->channels)- michael@0: ((char*)&st->DECODER_RESET_START - (char*)st)); michael@0: for (i=0;i<2*st->mode->nbEBands;i++) michael@0: oldLogE[i]=oldLogE2[i]=-QCONST16(28.f,DB_SHIFT); michael@0: } michael@0: break; michael@0: case OPUS_GET_PITCH_REQUEST: michael@0: { michael@0: opus_int32 *value = va_arg(ap, opus_int32*); michael@0: if (value==NULL) michael@0: goto bad_arg; michael@0: *value = st->postfilter_period; michael@0: } michael@0: break; michael@0: case CELT_GET_MODE_REQUEST: michael@0: { michael@0: const CELTMode ** value = va_arg(ap, const CELTMode**); michael@0: if (value==0) michael@0: goto bad_arg; michael@0: *value=st->mode; michael@0: } michael@0: break; michael@0: case CELT_SET_SIGNALLING_REQUEST: michael@0: { michael@0: opus_int32 value = va_arg(ap, opus_int32); michael@0: st->signalling = value; michael@0: } michael@0: break; michael@0: case OPUS_GET_FINAL_RANGE_REQUEST: michael@0: { michael@0: opus_uint32 * value = va_arg(ap, opus_uint32 *); michael@0: if (value==0) michael@0: goto bad_arg; michael@0: *value=st->rng; michael@0: } michael@0: break; michael@0: default: michael@0: goto bad_request; michael@0: } michael@0: va_end(ap); michael@0: return OPUS_OK; michael@0: bad_arg: michael@0: va_end(ap); michael@0: return OPUS_BAD_ARG; michael@0: bad_request: michael@0: va_end(ap); michael@0: return OPUS_UNIMPLEMENTED; michael@0: }