/* Copyright (c) 2007-2008 CSIRO Copyright (c) 2007-2010 Xiph.Org Foundation Copyright (c) 2008 Gregory Maxwell Written by Jean-Marc Valin and Gregory Maxwell */ /* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #define CELT_C #include "os_support.h" #include "mdct.h" #include #include "celt.h" #include "pitch.h" #include "bands.h" #include "modes.h" #include "entcode.h" #include "quant_bands.h" #include "rate.h" #include "stack_alloc.h" #include "mathops.h" #include "float_cast.h" #include #include "celt_lpc.h" #include "vq.h" #ifndef OPUS_VERSION #define OPUS_VERSION "unknown" #endif #ifdef CUSTOM_MODES #define OPUS_CUSTOM_NOSTATIC #else #define OPUS_CUSTOM_NOSTATIC static inline #endif static const unsigned char trim_icdf[11] = {126, 124, 119, 109, 87, 41, 19, 9, 4, 2, 0}; /* Probs: NONE: 21.875%, LIGHT: 6.25%, NORMAL: 65.625%, AGGRESSIVE: 6.25% */ static const unsigned char spread_icdf[4] = {25, 23, 2, 0}; static const unsigned char tapset_icdf[3]={2,1,0}; #ifdef CUSTOM_MODES static const unsigned char toOpusTable[20] = { 0xE0, 0xE8, 0xF0, 0xF8, 0xC0, 0xC8, 0xD0, 0xD8, 0xA0, 0xA8, 0xB0, 0xB8, 0x00, 0x00, 0x00, 0x00, 0x80, 0x88, 0x90, 0x98, }; static const unsigned char fromOpusTable[16] = { 0x80, 0x88, 0x90, 0x98, 0x40, 0x48, 0x50, 0x58, 0x20, 0x28, 0x30, 0x38, 0x00, 0x08, 0x10, 0x18 }; static inline int toOpus(unsigned char c) { int ret=0; if (c<0xA0) ret = toOpusTable[c>>3]; if (ret == 0) return -1; else return ret|(c&0x7); } static inline int fromOpus(unsigned char c) { if (c<0x80) return -1; else return fromOpusTable[(c>>3)-16] | (c&0x7); } #endif /* CUSTOM_MODES */ #define COMBFILTER_MAXPERIOD 1024 #define COMBFILTER_MINPERIOD 15 static int resampling_factor(opus_int32 rate) { int ret; switch (rate) { case 48000: ret = 1; break; case 24000: ret = 2; break; case 16000: ret = 3; break; case 12000: ret = 4; break; case 8000: ret = 6; break; default: #ifndef CUSTOM_MODES celt_assert(0); #endif ret = 0; break; } return ret; } /** Encoder state @brief Encoder state */ struct OpusCustomEncoder { const OpusCustomMode *mode; /**< Mode used by the encoder */ int overlap; int channels; int stream_channels; int force_intra; int clip; int disable_pf; int complexity; int upsample; int start, end; opus_int32 bitrate; int vbr; int signalling; int constrained_vbr; /* If zero, VBR can do whatever it likes with the rate */ int loss_rate; int lsb_depth; /* Everything beyond this point gets cleared on a reset */ #define ENCODER_RESET_START rng opus_uint32 rng; int spread_decision; opus_val32 delayedIntra; int tonal_average; int lastCodedBands; int hf_average; int tapset_decision; int prefilter_period; opus_val16 prefilter_gain; int prefilter_tapset; #ifdef RESYNTH int prefilter_period_old; opus_val16 prefilter_gain_old; int prefilter_tapset_old; #endif int consec_transient; AnalysisInfo analysis; opus_val32 preemph_memE[2]; opus_val32 preemph_memD[2]; /* VBR-related parameters */ opus_int32 vbr_reservoir; opus_int32 vbr_drift; opus_int32 vbr_offset; opus_int32 vbr_count; opus_val16 overlap_max; opus_val16 stereo_saving; int intensity; #ifdef RESYNTH celt_sig syn_mem[2][2*MAX_PERIOD]; #endif celt_sig in_mem[1]; /* Size = channels*mode->overlap */ /* celt_sig prefilter_mem[], Size = channels*COMBFILTER_PERIOD */ /* celt_sig overlap_mem[], Size = channels*mode->overlap */ /* opus_val16 oldEBands[], Size = 2*channels*mode->nbEBands */ }; int celt_encoder_get_size(int channels) { CELTMode *mode = opus_custom_mode_create(48000, 960, NULL); return opus_custom_encoder_get_size(mode, channels); } OPUS_CUSTOM_NOSTATIC int opus_custom_encoder_get_size(const CELTMode *mode, int channels) { int size = sizeof(struct CELTEncoder) + (2*channels*mode->overlap-1)*sizeof(celt_sig) + channels*COMBFILTER_MAXPERIOD*sizeof(celt_sig) + 3*channels*mode->nbEBands*sizeof(opus_val16); return size; } #ifdef CUSTOM_MODES CELTEncoder *opus_custom_encoder_create(const CELTMode *mode, int channels, int *error) { int ret; CELTEncoder *st = (CELTEncoder *)opus_alloc(opus_custom_encoder_get_size(mode, channels)); /* init will handle the NULL case */ ret = opus_custom_encoder_init(st, mode, channels); if (ret != OPUS_OK) { opus_custom_encoder_destroy(st); st = NULL; } if (error) *error = ret; return st; } #endif /* CUSTOM_MODES */ int celt_encoder_init(CELTEncoder *st, opus_int32 sampling_rate, int channels) { int ret; ret = opus_custom_encoder_init(st, opus_custom_mode_create(48000, 960, NULL), channels); if (ret != OPUS_OK) return ret; st->upsample = resampling_factor(sampling_rate); return OPUS_OK; } OPUS_CUSTOM_NOSTATIC int opus_custom_encoder_init(CELTEncoder *st, const CELTMode *mode, int channels) { if (channels < 0 || channels > 2) return OPUS_BAD_ARG; if (st==NULL || mode==NULL) return OPUS_ALLOC_FAIL; OPUS_CLEAR((char*)st, opus_custom_encoder_get_size(mode, channels)); st->mode = mode; st->overlap = mode->overlap; st->stream_channels = st->channels = channels; st->upsample = 1; st->start = 0; st->end = st->mode->effEBands; st->signalling = 1; st->constrained_vbr = 1; st->clip = 1; st->bitrate = OPUS_BITRATE_MAX; st->vbr = 0; st->force_intra = 0; st->complexity = 5; st->lsb_depth=24; opus_custom_encoder_ctl(st, OPUS_RESET_STATE); return OPUS_OK; } #ifdef CUSTOM_MODES void opus_custom_encoder_destroy(CELTEncoder *st) { opus_free(st); } #endif /* CUSTOM_MODES */ static inline opus_val16 SIG2WORD16(celt_sig x) { #ifdef FIXED_POINT x = PSHR32(x, SIG_SHIFT); x = MAX32(x, -32768); x = MIN32(x, 32767); return EXTRACT16(x); #else return (opus_val16)x; #endif } static int transient_analysis(const opus_val32 * restrict in, int len, int C, int overlap, opus_val16 *tf_estimate, int *tf_chan, AnalysisInfo *analysis) { int i; VARDECL(opus_val16, tmp); opus_val32 mem0,mem1; int is_transient = 0; int block; int c, N; opus_val16 maxbin; int tf_max; VARDECL(opus_val16, bins); opus_val16 T1, T2, T3, T4, T5; opus_val16 follower; int metric=0; int fmetric=0, bmetric=0; int count1, count2, count3, count4, count5;; SAVE_STACK; ALLOC(tmp, len, opus_val16); block = overlap/4; N=len/block-1; ALLOC(bins, N, opus_val16); tf_max = 0; for (c=0;c=0;i--) { follower = MAX16(bins[i], MULT16_16_Q15(QCONST16(0.97f, 15), follower)); if (bins[i] < MULT16_16_Q15(T1, follower)) count1++; if (bins[i] < MULT16_16_Q15(T2, follower)) count2++; if (bins[i] < MULT16_16_Q15(T3, follower)) count3++; if (bins[i] < MULT16_16_Q15(T4, follower)) count4++; if (bins[i] < MULT16_16_Q15(T5, follower)) count5++; } bmetric = 5*count1 + 4*count2 + 3*count3 + 2*count4 + count5; metric = fmetric+bmetric; /*if (metric>40)*/ if (metric>20+50*MAX16(analysis->tonality, analysis->noisiness)) is_transient=1; if (metric>tf_max) { *tf_chan = c; tf_max = metric; } } /* *tf_estimate = 1 + MIN16(1, sqrt(MAX16(0, tf_max-30))/20); */ *tf_estimate = QCONST16(1.f, 14) + celt_sqrt(MAX16(0, SHL32(MULT16_16(QCONST16(0.0069,14),IMIN(163,tf_max)),14)-QCONST32(0.139,28))); RESTORE_STACK; #ifdef FUZZING is_transient = rand()&0x1; #endif /*printf("%d %f %f %f %f\n", is_transient, *tf_estimate, tf_max, analysis->tonality, analysis->noisiness);*/ return is_transient; } /** Apply window and compute the MDCT for all sub-frames and all channels in a frame */ static void compute_mdcts(const CELTMode *mode, int shortBlocks, celt_sig * restrict in, celt_sig * restrict out, int C, int LM) { if (C==1 && !shortBlocks) { const int overlap = OVERLAP(mode); clt_mdct_forward(&mode->mdct, in, out, mode->window, overlap, mode->maxLM-LM, 1); } else { const int overlap = OVERLAP(mode); int N = mode->shortMdctSize<shortMdctSize; B = shortBlocks; } c=0; do { for (b=0;bmdct, in+c*(B*N+overlap)+b*N, &out[b+c*N*B], mode->window, overlap, shortBlocks ? mode->maxLM : mode->maxLM-LM, B); } } while (++cshortMdctSize<shortMdctSize; B = shortBlocks; } /* Prevents problems from the imdct doing the overlap-add */ OPUS_CLEAR(x, overlap); for (b=0;bmdct, &X[b+c*N2*B], x+N2*b, mode->window, overlap, shortBlocks ? mode->maxLM : mode->maxLM-LM, B); } for (j=0;jeBands[len]-m->eBands[len-1])<eBands[len]-m->eBands[len-1])<eBands[i+1]-m->eBands[i])<eBands[i+1]-m->eBands[i])==1; for (j=0;jeBands[i]<eBands[i]<>LM, 1<>k, 1<=0;i--) { if (tf_res[i+1] == 1) tf_res[i] = path1[i+1]; else tf_res[i] = path0[i+1]; } /*printf("%d %f\n", *tf_sum, tf_estimate);*/ RESTORE_STACK; #ifdef FUZZING tf_select = rand()&0x1; tf_res[0] = rand()&0x1; for (i=1;istorage*8; tell = ec_tell(enc); logp = isTransient ? 2 : 4; /* Reserve space to code the tf_select decision. */ tf_select_rsv = LM>0 && tell+logp+1 <= budget; budget -= tf_select_rsv; curr = tf_changed = 0; for (i=start;istorage*8; tell = ec_tell(dec); logp = isTransient ? 2 : 4; tf_select_rsv = LM>0 && tell+logp+1<=budget; budget -= tf_select_rsv; tf_changed = curr = 0; for (i=start;inbEBands;i++) { int N; N=(m->eBands[i+1]-m->eBands[i])<cache.caps[m->nbEBands*(2*LM+C-1)+i]+64)*C*N>>2; } } static int alloc_trim_analysis(const CELTMode *m, const celt_norm *X, const opus_val16 *bandLogE, int end, int LM, int C, int N0, AnalysisInfo *analysis, opus_val16 *stereo_saving, opus_val16 tf_estimate, int intensity) { int i; opus_val32 diff=0; int c; int trim_index = 5; opus_val16 trim = QCONST16(5.f, 8); opus_val16 logXC, logXC2; if (C==2) { opus_val16 sum = 0; /* Q10 */ opus_val16 minXC; /* Q10 */ /* Compute inter-channel correlation for low frequencies */ for (i=0;i<8;i++) { int j; opus_val32 partial = 0; for (j=m->eBands[i]<eBands[i+1]<eBands[i]<eBands[i+1]< QCONST16(.995f,10)) trim_index-=4; else if (sum > QCONST16(.92f,10)) trim_index-=3; else if (sum > QCONST16(.85f,10)) trim_index-=2; else if (sum > QCONST16(.8f,10)) trim_index-=1; /* mid-side savings estimations based on the LF average*/ logXC = celt_log2(QCONST32(1.001f, 20)-MULT16_16(sum, sum)); /* mid-side savings estimations based on min correlation */ logXC2 = MAX16(HALF16(logXC), celt_log2(QCONST32(1.001f, 20)-MULT16_16(minXC, minXC))); #ifdef FIXED_POINT /* Compensate for Q20 vs Q14 input and convert output to Q8 */ logXC = PSHR32(logXC-QCONST16(6.f, DB_SHIFT),DB_SHIFT-8); logXC2 = PSHR32(logXC2-QCONST16(6.f, DB_SHIFT),DB_SHIFT-8); #endif trim += MAX16(-QCONST16(4.f, 8), MULT16_16_Q15(QCONST16(.75f,15),logXC)); *stereo_saving = MIN16(*stereo_saving + QCONST16(0.25f, 8), -HALF16(logXC2)); } /* Estimate spectral tilt */ c=0; do { for (i=0;inbEBands]*(opus_int32)(2+2*i-end); } } while (++c QCONST16(2.f, DB_SHIFT)) trim_index--; if (diff > QCONST16(8.f, DB_SHIFT)) trim_index--; if (diff < -QCONST16(4.f, DB_SHIFT)) trim_index++; if (diff < -QCONST16(10.f, DB_SHIFT)) trim_index++; trim -= MAX16(-QCONST16(2.f, 8), MIN16(QCONST16(2.f, 8), SHR16(diff+QCONST16(1.f, DB_SHIFT),DB_SHIFT-8)/6 )); trim -= 2*SHR16(tf_estimate-QCONST16(1.f,14), 14-8); #ifndef FIXED_POINT if (analysis->valid) { trim -= MAX16(-QCONST16(2.f, 8), MIN16(QCONST16(2.f, 8), 2*(analysis->tonality_slope+.05))); } #endif #ifdef FIXED_POINT trim_index = PSHR32(trim, 8); #else trim_index = floor(.5+trim); #endif if (trim_index<0) trim_index = 0; if (trim_index>10) trim_index = 10; /*printf("%d\n", trim_index);*/ #ifdef FUZZING trim_index = rand()%11; #endif return trim_index; } static int stereo_analysis(const CELTMode *m, const celt_norm *X, int LM, int N0) { int i; int thetas; opus_val32 sumLR = EPSILON, sumMS = EPSILON; /* Use the L1 norm to model the entropy of the L/R signal vs the M/S signal */ for (i=0;i<13;i++) { int j; for (j=m->eBands[i]<eBands[i+1]<eBands[13]<<(LM+1))+thetas, sumMS) > MULT16_32_Q15(m->eBands[13]<<(LM+1), sumLR); } int celt_encode_with_ec(CELTEncoder * restrict st, const opus_val16 * pcm, int frame_size, unsigned char *compressed, int nbCompressedBytes, ec_enc *enc) { int i, c, N; opus_int32 bits; ec_enc _enc; VARDECL(celt_sig, in); VARDECL(celt_sig, freq); VARDECL(celt_norm, X); VARDECL(celt_ener, bandE); VARDECL(opus_val16, bandLogE); VARDECL(opus_val16, bandLogE2); VARDECL(int, fine_quant); VARDECL(opus_val16, error); VARDECL(int, pulses); VARDECL(int, cap); VARDECL(int, offsets); VARDECL(int, fine_priority); VARDECL(int, tf_res); VARDECL(unsigned char, collapse_masks); celt_sig *prefilter_mem; opus_val16 *oldBandE, *oldLogE, *oldLogE2; int shortBlocks=0; int isTransient=0; const int CC = st->channels; const int C = st->stream_channels; int LM, M; int tf_select; int nbFilledBytes, nbAvailableBytes; int effEnd; int codedBands; int tf_sum; int alloc_trim; int pitch_index=COMBFILTER_MINPERIOD; opus_val16 gain1 = 0; int dual_stereo=0; int effectiveBytes; opus_val16 pf_threshold; int dynalloc_logp; opus_int32 vbr_rate; opus_int32 total_bits; opus_int32 total_boost; opus_int32 balance; opus_int32 tell; int prefilter_tapset=0; int pf_on; int anti_collapse_rsv; int anti_collapse_on=0; int silence=0; int tf_chan = 0; opus_val16 tf_estimate; int pitch_change=0; opus_int32 tot_boost=0; opus_val16 sample_max; opus_val16 maxDepth; ALLOC_STACK; tf_estimate = QCONST16(1.0f,14); if (nbCompressedBytes<2 || pcm==NULL) return OPUS_BAD_ARG; frame_size *= st->upsample; for (LM=0;LM<=st->mode->maxLM;LM++) if (st->mode->shortMdctSize<st->mode->maxLM) return OPUS_BAD_ARG; M=1<mode->shortMdctSize; prefilter_mem = st->in_mem+CC*(st->overlap); oldBandE = (opus_val16*)(st->in_mem+CC*(2*st->overlap+COMBFILTER_MAXPERIOD)); oldLogE = oldBandE + CC*st->mode->nbEBands; oldLogE2 = oldLogE + CC*st->mode->nbEBands; if (enc==NULL) { tell=1; nbFilledBytes=0; } else { tell=ec_tell(enc); nbFilledBytes=(tell+4)>>3; } #ifdef CUSTOM_MODES if (st->signalling && enc==NULL) { int tmp = (st->mode->effEBands-st->end)>>1; st->end = IMAX(1, st->mode->effEBands-tmp); compressed[0] = tmp<<5; compressed[0] |= LM<<3; compressed[0] |= (C==2)<<2; /* Convert "standard mode" to Opus header */ if (st->mode->Fs==48000 && st->mode->shortMdctSize==120) { int c0 = toOpus(compressed[0]); if (c0<0) return OPUS_BAD_ARG; compressed[0] = c0; } compressed++; nbCompressedBytes--; } #else celt_assert(st->signalling==0); #endif /* Can't produce more than 1275 output bytes */ nbCompressedBytes = IMIN(nbCompressedBytes,1275); nbAvailableBytes = nbCompressedBytes - nbFilledBytes; if (st->vbr && st->bitrate!=OPUS_BITRATE_MAX) { opus_int32 den=st->mode->Fs>>BITRES; vbr_rate=(st->bitrate*frame_size+(den>>1))/den; #ifdef CUSTOM_MODES if (st->signalling) vbr_rate -= 8<>(3+BITRES); } else { opus_int32 tmp; vbr_rate = 0; tmp = st->bitrate*frame_size; if (tell>1) tmp += tell; if (st->bitrate!=OPUS_BITRATE_MAX) nbCompressedBytes = IMAX(2, IMIN(nbCompressedBytes, (tmp+4*st->mode->Fs)/(8*st->mode->Fs)-!!st->signalling)); effectiveBytes = nbCompressedBytes; } if (enc==NULL) { ec_enc_init(&_enc, compressed, nbCompressedBytes); enc = &_enc; } if (vbr_rate>0) { /* Computes the max bit-rate allowed in VBR mode to avoid violating the target rate and buffering. We must do this up front so that bust-prevention logic triggers correctly if we don't have enough bits. */ if (st->constrained_vbr) { opus_int32 vbr_bound; opus_int32 max_allowed; /* We could use any multiple of vbr_rate as bound (depending on the delay). This is clamped to ensure we use at least two bytes if the encoder was entirely empty, but to allow 0 in hybrid mode. */ vbr_bound = vbr_rate; max_allowed = IMIN(IMAX(tell==1?2:0, (vbr_rate+vbr_bound-st->vbr_reservoir)>>(BITRES+3)), nbAvailableBytes); if(max_allowed < nbAvailableBytes) { nbCompressedBytes = nbFilledBytes+max_allowed; nbAvailableBytes = max_allowed; ec_enc_shrink(enc, nbCompressedBytes); } } } total_bits = nbCompressedBytes*8; effEnd = st->end; if (effEnd > st->mode->effEBands) effEnd = st->mode->effEBands; ALLOC(in, CC*(N+st->overlap), celt_sig); sample_max=MAX16(st->overlap_max, celt_maxabs16(pcm, C*(N-st->mode->overlap))); st->overlap_max=celt_maxabs16(pcm+C*(N-st->mode->overlap), C*st->mode->overlap); sample_max=MAX16(sample_max, st->overlap_max); /* Find pitch period and gain */ { VARDECL(celt_sig, _pre); celt_sig *pre[2]; SAVE_STACK; ALLOC(_pre, CC*(N+COMBFILTER_MAXPERIOD), celt_sig); pre[0] = _pre; pre[1] = _pre + (N+COMBFILTER_MAXPERIOD); silence = 1; c=0; do { int count = 0; const opus_val16 * restrict pcmp = pcm+c; celt_sig * restrict inp = in+c*(N+st->overlap)+st->overlap; for (i=0;iclip) x = MAX32(-65536.f, MIN32(65536.f,x)); #endif if (++count==st->upsample) { count=0; pcmp+=CC; } else { x = 0; } /* Apply pre-emphasis */ tmp = MULT16_16(st->mode->preemph[2], x); *inp = tmp + st->preemph_memE[c]; st->preemph_memE[c] = MULT16_32_Q15(st->mode->preemph[1], *inp) - MULT16_32_Q15(st->mode->preemph[0], tmp); inp++; } OPUS_COPY(pre[c], prefilter_mem+c*COMBFILTER_MAXPERIOD, COMBFILTER_MAXPERIOD); OPUS_COPY(pre[c]+COMBFILTER_MAXPERIOD, in+c*(N+st->overlap)+st->overlap, N); } while (++clsb_depth)); #endif #ifdef FUZZING if ((rand()&0x3F)==0) silence = 1; #endif if (tell==1) ec_enc_bit_logp(enc, silence, 15); else silence=0; if (silence) { /*In VBR mode there is no need to send more than the minimum. */ if (vbr_rate>0) { effectiveBytes=nbCompressedBytes=IMIN(nbCompressedBytes, nbFilledBytes+2); total_bits=nbCompressedBytes*8; nbAvailableBytes=2; ec_enc_shrink(enc, nbCompressedBytes); } /* Pretend we've filled all the remaining bits with zeros (that's what the initialiser did anyway) */ tell = nbCompressedBytes*8; enc->nbits_total+=tell-ec_tell(enc); } if (nbAvailableBytes>12*C && st->start==0 && !silence && !st->disable_pf && st->complexity >= 5) { VARDECL(opus_val16, pitch_buf); ALLOC(pitch_buf, (COMBFILTER_MAXPERIOD+N)>>1, opus_val16); pitch_downsample(pre, pitch_buf, COMBFILTER_MAXPERIOD+N, CC); /* Don't search for the fir last 1.5 octave of the range because there's too many false-positives due to short-term correlation */ pitch_search(pitch_buf+(COMBFILTER_MAXPERIOD>>1), pitch_buf, N, COMBFILTER_MAXPERIOD-3*COMBFILTER_MINPERIOD, &pitch_index); pitch_index = COMBFILTER_MAXPERIOD-pitch_index; gain1 = remove_doubling(pitch_buf, COMBFILTER_MAXPERIOD, COMBFILTER_MINPERIOD, N, &pitch_index, st->prefilter_period, st->prefilter_gain); if (pitch_index > COMBFILTER_MAXPERIOD-2) pitch_index = COMBFILTER_MAXPERIOD-2; gain1 = MULT16_16_Q15(QCONST16(.7f,15),gain1); if ((gain1 > QCONST16(.4f,15) || st->prefilter_gain > QCONST16(.4f,15)) && st->analysis.tonality > .3 && (pitch_index > 1.26*st->prefilter_period || pitch_index < .79*st->prefilter_period)) pitch_change = 1; /*printf("%d %d %f %f\n", pitch_change, pitch_index, gain1, st->analysis.tonality);*/ if (st->loss_rate>2) gain1 = HALF32(gain1); if (st->loss_rate>4) gain1 = HALF32(gain1); if (st->loss_rate>8) gain1 = 0; prefilter_tapset = st->tapset_decision; } else { gain1 = 0; } /* Gain threshold for enabling the prefilter/postfilter */ pf_threshold = QCONST16(.2f,15); /* Adjusting the threshold based on rate and continuity */ if (abs(pitch_index-st->prefilter_period)*10>pitch_index) pf_threshold += QCONST16(.2f,15); if (nbAvailableBytes<25) pf_threshold += QCONST16(.1f,15); if (nbAvailableBytes<35) pf_threshold += QCONST16(.1f,15); if (st->prefilter_gain > QCONST16(.4f,15)) pf_threshold -= QCONST16(.1f,15); if (st->prefilter_gain > QCONST16(.55f,15)) pf_threshold -= QCONST16(.1f,15); /* Hard threshold at 0.2 */ pf_threshold = MAX16(pf_threshold, QCONST16(.2f,15)); if (gain1start==0 && tell+16<=total_bits) ec_enc_bit_logp(enc, 0, 1); gain1 = 0; pf_on = 0; } else { /*This block is not gated by a total bits check only because of the nbAvailableBytes check above.*/ int qg; int octave; if (ABS16(gain1-st->prefilter_gain)prefilter_gain; #ifdef FIXED_POINT qg = ((gain1+1536)>>10)/3-1; #else qg = (int)floor(.5f+gain1*32/3)-1; #endif qg = IMAX(0, IMIN(7, qg)); ec_enc_bit_logp(enc, 1, 1); pitch_index += 1; octave = EC_ILOG(pitch_index)-5; ec_enc_uint(enc, octave, 6); ec_enc_bits(enc, pitch_index-(16<mode->shortMdctSize-st->mode->overlap; st->prefilter_period=IMAX(st->prefilter_period, COMBFILTER_MINPERIOD); OPUS_COPY(in+c*(N+st->overlap), st->in_mem+c*(st->overlap), st->overlap); if (offset) comb_filter(in+c*(N+st->overlap)+st->overlap, pre[c]+COMBFILTER_MAXPERIOD, st->prefilter_period, st->prefilter_period, offset, -st->prefilter_gain, -st->prefilter_gain, st->prefilter_tapset, st->prefilter_tapset, NULL, 0); comb_filter(in+c*(N+st->overlap)+st->overlap+offset, pre[c]+COMBFILTER_MAXPERIOD+offset, st->prefilter_period, pitch_index, N-offset, -st->prefilter_gain, -gain1, st->prefilter_tapset, prefilter_tapset, st->mode->window, st->mode->overlap); OPUS_COPY(st->in_mem+c*(st->overlap), in+c*(N+st->overlap)+N, st->overlap); if (N>COMBFILTER_MAXPERIOD) { OPUS_MOVE(prefilter_mem+c*COMBFILTER_MAXPERIOD, pre[c]+N, COMBFILTER_MAXPERIOD); } else { OPUS_MOVE(prefilter_mem+c*COMBFILTER_MAXPERIOD, prefilter_mem+c*COMBFILTER_MAXPERIOD+N, COMBFILTER_MAXPERIOD-N); OPUS_MOVE(prefilter_mem+c*COMBFILTER_MAXPERIOD+COMBFILTER_MAXPERIOD-N, pre[c]+COMBFILTER_MAXPERIOD, N); } } while (++c0 && ec_tell(enc)+3<=total_bits) { if (st->complexity > 1) { isTransient = transient_analysis(in, N+st->overlap, CC, st->overlap, &tf_estimate, &tf_chan, &st->analysis); if (isTransient) shortBlocks = M; } ec_enc_bit_logp(enc, isTransient, 3); } ALLOC(freq, CC*N, celt_sig); /**< Interleaved signal MDCTs */ ALLOC(bandE,st->mode->nbEBands*CC, celt_ener); ALLOC(bandLogE,st->mode->nbEBands*CC, opus_val16); /* Compute MDCTs */ compute_mdcts(st->mode, shortBlocks, in, freq, CC, LM); if (CC==2&&C==1) { for (i=0;iupsample != 1) { c=0; do { int bound = N/st->upsample; for (i=0;iupsample; for (;imode, freq, bandE, effEnd, C, M); amp2Log2(st->mode, effEnd, st->end, bandE, bandLogE, C); /*for (i=0;i<21;i++) printf("%f ", bandLogE[i]); printf("\n");*/ ALLOC(bandLogE2, C*st->mode->nbEBands, opus_val16); if (shortBlocks && st->complexity>=8) { VARDECL(celt_sig, freq2); VARDECL(opus_val32, bandE2); ALLOC(freq2, CC*N, celt_sig); compute_mdcts(st->mode, 0, in, freq2, CC, LM); if (CC==2&&C==1) { for (i=0;iupsample != 1) { c=0; do { int bound = N/st->upsample; for (i=0;iupsample; for (;imode->nbEBands, opus_val32); compute_band_energies(st->mode, freq2, bandE2, effEnd, C, M); amp2Log2(st->mode, effEnd, st->end, bandE2, bandLogE2, C); for (i=0;imode->nbEBands;i++) bandLogE2[i] += HALF16(SHL16(LM, DB_SHIFT)); } else { for (i=0;imode->nbEBands;i++) bandLogE2[i] = bandLogE[i]; } ALLOC(X, C*N, celt_norm); /**< Interleaved normalised MDCTs */ /* Band normalisation */ normalise_bands(st->mode, freq, X, bandE, effEnd, C, M); ALLOC(tf_res, st->mode->nbEBands, int); tf_select = tf_analysis(st->mode, effEnd, C, isTransient, tf_res, effectiveBytes, X, N, LM, &tf_sum, tf_estimate, tf_chan); for (i=effEnd;iend;i++) tf_res[i] = tf_res[effEnd-1]; ALLOC(error, C*st->mode->nbEBands, opus_val16); quant_coarse_energy(st->mode, st->start, st->end, effEnd, bandLogE, oldBandE, total_bits, error, enc, C, LM, nbAvailableBytes, st->force_intra, &st->delayedIntra, st->complexity >= 4, st->loss_rate); tf_encode(st->start, st->end, isTransient, tf_res, LM, tf_select, enc); if (ec_tell(enc)+4<=total_bits) { if (shortBlocks || st->complexity < 3 || nbAvailableBytes < 10*C) { if (st->complexity == 0) st->spread_decision = SPREAD_NONE; } else { if (st->analysis.valid) { static const opus_val16 spread_thresholds[3] = {-QCONST16(.6f, 15), -QCONST16(.2f, 15), -QCONST16(.07f, 15)}; static const opus_val16 spread_histeresis[3] = {QCONST16(.15f, 15), QCONST16(.07f, 15), QCONST16(.02f, 15)}; static const opus_val16 tapset_thresholds[2] = {QCONST16(.0f, 15), QCONST16(.15f, 15)}; static const opus_val16 tapset_histeresis[2] = {QCONST16(.1f, 15), QCONST16(.05f, 15)}; st->spread_decision = hysteresis_decision(-st->analysis.tonality, spread_thresholds, spread_histeresis, 3, st->spread_decision); st->tapset_decision = hysteresis_decision(st->analysis.tonality_slope, tapset_thresholds, tapset_histeresis, 2, st->tapset_decision); } else { st->spread_decision = spreading_decision(st->mode, X, &st->tonal_average, st->spread_decision, &st->hf_average, &st->tapset_decision, pf_on&&!shortBlocks, effEnd, C, M); } /*printf("%d %d\n", st->tapset_decision, st->spread_decision);*/ /*printf("%f %d %f %d\n\n", st->analysis.tonality, st->spread_decision, st->analysis.tonality_slope, st->tapset_decision);*/ } ec_enc_icdf(enc, st->spread_decision, spread_icdf, 5); } ALLOC(cap, st->mode->nbEBands, int); ALLOC(offsets, st->mode->nbEBands, int); init_caps(st->mode,cap,LM,C); for (i=0;imode->nbEBands;i++) offsets[i] = 0; /* Dynamic allocation code */ maxDepth=-QCONST16(32.f, DB_SHIFT); /* Make sure that dynamic allocation can't make us bust the budget */ if (effectiveBytes > 50 && LM>=1) { int last=0; VARDECL(opus_val16, follower); ALLOC(follower, C*st->mode->nbEBands, opus_val16); c=0;do { follower[c*st->mode->nbEBands] = bandLogE2[c*st->mode->nbEBands]; for (i=1;iend;i++) { /* The last band to be at least 3 dB higher than the previous one is the last we'll consider. Otherwise, we run into problems on bandlimited signals. */ if (bandLogE2[c*st->mode->nbEBands+i] > bandLogE2[c*st->mode->nbEBands+i-1]+QCONST16(.5f,DB_SHIFT)) last=i; follower[c*st->mode->nbEBands+i] = MIN16(follower[c*st->mode->nbEBands+i-1]+QCONST16(1.5f,DB_SHIFT), bandLogE2[c*st->mode->nbEBands+i]); } for (i=last-1;i>=0;i--) follower[c*st->mode->nbEBands+i] = MIN16(follower[c*st->mode->nbEBands+i], MIN16(follower[c*st->mode->nbEBands+i+1]+QCONST16(2.f,DB_SHIFT), bandLogE2[c*st->mode->nbEBands+i])); for (i=0;iend;i++) { opus_val16 noise_floor; /* Noise floor must take into account eMeans, the depth, the width of the bands and the preemphasis filter (approx. square of bark band ID) */ noise_floor = MULT16_16(QCONST16(0.0625f, DB_SHIFT),st->mode->logN[i]) +QCONST16(.5f,DB_SHIFT)+SHL16(9-st->lsb_depth,DB_SHIFT)-SHL16(eMeans[i],6) +MULT16_16(QCONST16(.0062,DB_SHIFT),(i+5)*(i+5)); follower[c*st->mode->nbEBands+i] = MAX16(follower[c*st->mode->nbEBands+i], noise_floor); maxDepth = MAX16(maxDepth, bandLogE[c*st->mode->nbEBands+i]-noise_floor); } } while (++cstart;iend;i++) { /* Consider 24 dB "cross-talk" */ follower[st->mode->nbEBands+i] = MAX16(follower[st->mode->nbEBands+i], follower[ i]-QCONST16(4.f,DB_SHIFT)); follower[ i] = MAX16(follower[ i], follower[st->mode->nbEBands+i]-QCONST16(4.f,DB_SHIFT)); follower[i] = HALF16(MAX16(0, bandLogE[i]-follower[i]) + MAX16(0, bandLogE[st->mode->nbEBands+i]-follower[st->mode->nbEBands+i])); } } else { for (i=st->start;iend;i++) { follower[i] = MAX16(0, bandLogE[i]-follower[i]); } } /* For non-transient CBR/CVBR frames, halve the dynalloc contribution */ if ((!st->vbr || st->constrained_vbr)&&!isTransient) { for (i=st->start;iend;i++) follower[i] = HALF16(follower[i]); } for (i=st->start;iend;i++) { int width; int boost; int boost_bits; if (i<8) follower[i] *= 2; if (i>=12) follower[i] = HALF16(follower[i]); follower[i] = MIN16(follower[i], QCONST16(4, DB_SHIFT)); /* FIXME: Adaptively reduce follower at low rate or for cbr/cvbr */ width = C*(st->mode->eBands[i+1]-st->mode->eBands[i])< 48) { boost = SHR32(EXTEND32(follower[i])*8,DB_SHIFT); boost_bits = (boost*width<vbr || (st->constrained_vbr&&!isTransient)) && (tot_boost+boost_bits)>>BITRES>>3 > effectiveBytes/4) { offsets[i] = 0; break; } else { offsets[i] = boost; tot_boost += boost_bits; } } } dynalloc_logp = 6; total_bits<<=BITRES; total_boost = 0; tell = ec_tell_frac(enc); for (i=st->start;iend;i++) { int width, quanta; int dynalloc_loop_logp; int boost; int j; width = C*(st->mode->eBands[i+1]-st->mode->eBands[i])<mode, X, LM, N); /* Account for coarse energy */ effectiveRate = (8*effectiveBytes - 80)>>LM; /* effectiveRate in kb/s */ effectiveRate = 2*effectiveRate/5; st->intensity = hysteresis_decision(effectiveRate, intensity_thresholds, intensity_histeresis, 21, st->intensity); st->intensity = IMIN(st->end,IMAX(st->start, st->intensity)); } alloc_trim = 5; if (tell+(6<mode, X, bandLogE, st->end, LM, C, N, &st->analysis, &st->stereo_saving, tf_estimate, st->intensity); ec_enc_icdf(enc, alloc_trim, trim_icdf, 7); tell = ec_tell_frac(enc); } /* Variable bitrate */ if (vbr_rate>0) { opus_val16 alpha; opus_int32 delta; /* The target rate in 8th bits per frame */ opus_int32 target, base_target; opus_int32 min_allowed; int coded_bins; int coded_bands; int lm_diff = st->mode->maxLM - LM; coded_bands = st->lastCodedBands ? st->lastCodedBands : st->mode->nbEBands; coded_bins = st->mode->eBands[coded_bands]<mode->eBands[IMIN(st->intensity, coded_bands)]<>(3-LM)); target = vbr_rate - ((40*C+20)<constrained_vbr) target += (st->vbr_offset>>lm_diff); /*printf("%f %f %f %f %d %d ", st->analysis.activity, st->analysis.tonality, tf_estimate, st->stereo_saving, tot_boost, coded_bands);*/ #ifndef FIXED_POINT if (st->analysis.valid && st->analysis.activity<.4) target -= (coded_bins<analysis.activity); #endif /* Stereo savings */ if (C==2) { int coded_stereo_bands; int coded_stereo_dof; coded_stereo_bands = IMIN(st->intensity, coded_bands); coded_stereo_dof = (st->mode->eBands[coded_stereo_bands]<stereo_saving,(coded_stereo_dof<analysis.valid) { int tonal_target; float tonal; /* Compensates for the average tonality boost */ target -= MULT16_16_Q15(QCONST16(0.13f,15),coded_bins<analysis.tonality-.2); tonal_target = target + (coded_bins<analysis.tonality, tonal);*/ target = IMAX(tonal_target,target); } #endif { opus_int32 floor_depth; int bins; bins = st->mode->eBands[st->mode->nbEBands-2]<>2); target = IMIN(target, floor_depth); /*printf("%f %d\n", maxDepth, floor_depth);*/ } if (st->constrained_vbr || st->bitrate<64000) { opus_val16 rate_factor; #ifdef FIXED_POINT rate_factor = MAX16(0,(st->bitrate-32000)); #else rate_factor = MAX16(0,(1.f/32768)*(st->bitrate-32000)); #endif if (st->constrained_vbr) rate_factor = MIN16(rate_factor, QCONST16(0.67f, 15)); target = base_target + MULT16_32_Q15(rate_factor, target-base_target); } /* Don't allow more than doubling the rate */ target = IMIN(2*base_target, target); /* The current offset is removed from the target and the space used so far is added*/ target=target+tell; /* In VBR mode the frame size must not be reduced so much that it would result in the encoder running out of bits. The margin of 2 bytes ensures that none of the bust-prevention logic in the decoder will have triggered so far. */ min_allowed = ((tell+total_boost+(1<<(BITRES+3))-1)>>(BITRES+3)) + 2 - nbFilledBytes; nbAvailableBytes = (target+(1<<(BITRES+2)))>>(BITRES+3); nbAvailableBytes = IMAX(min_allowed,nbAvailableBytes); nbAvailableBytes = IMIN(nbCompressedBytes,nbAvailableBytes+nbFilledBytes) - nbFilledBytes; /* By how much did we "miss" the target on that frame */ delta = target - vbr_rate; target=nbAvailableBytes<<(BITRES+3); /*If the frame is silent we don't adjust our drift, otherwise the encoder will shoot to very high rates after hitting a span of silence, but we do allow the bitres to refill. This means that we'll undershoot our target in CVBR/VBR modes on files with lots of silence. */ if(silence) { nbAvailableBytes = 2; target = 2*8<vbr_count < 970) { st->vbr_count++; alpha = celt_rcp(SHL32(EXTEND32(st->vbr_count+20),16)); } else alpha = QCONST16(.001f,15); /* How many bits have we used in excess of what we're allowed */ if (st->constrained_vbr) st->vbr_reservoir += target - vbr_rate; /*printf ("%d\n", st->vbr_reservoir);*/ /* Compute the offset we need to apply in order to reach the target */ if (st->constrained_vbr) { st->vbr_drift += (opus_int32)MULT16_32_Q15(alpha,(delta*(1<vbr_offset-st->vbr_drift); st->vbr_offset = -st->vbr_drift; } /*printf ("%d\n", st->vbr_drift);*/ if (st->constrained_vbr && st->vbr_reservoir < 0) { /* We're under the min value -- increase rate */ int adjust = (-st->vbr_reservoir)/(8<vbr_reservoir = 0; /*printf ("+%d\n", adjust);*/ } nbCompressedBytes = IMIN(nbCompressedBytes,nbAvailableBytes+nbFilledBytes); /*printf("%d\n", nbCompressedBytes*50*8);*/ /* This moves the raw bits to take into account the new compressed size */ ec_enc_shrink(enc, nbCompressedBytes); } /* Bit allocation */ ALLOC(fine_quant, st->mode->nbEBands, int); ALLOC(pulses, st->mode->nbEBands, int); ALLOC(fine_priority, st->mode->nbEBands, int); /* bits = packet size - where we are - safety*/ bits = (((opus_int32)nbCompressedBytes*8)<=2&&bits>=((LM+2)<mode, st->start, st->end, offsets, cap, alloc_trim, &st->intensity, &dual_stereo, bits, &balance, pulses, fine_quant, fine_priority, C, LM, enc, 1, st->lastCodedBands); st->lastCodedBands = codedBands; quant_fine_energy(st->mode, st->start, st->end, oldBandE, error, fine_quant, enc, C); #ifdef MEASURE_NORM_MSE float X0[3000]; float bandE0[60]; c=0; do for (i=0;imode->nbEBands;i++) bandE0[i] = bandE[i]; #endif /* Residual quantisation */ ALLOC(collapse_masks, C*st->mode->nbEBands, unsigned char); quant_all_bands(1, st->mode, st->start, st->end, X, C==2 ? X+N : NULL, collapse_masks, bandE, pulses, shortBlocks, st->spread_decision, dual_stereo, st->intensity, tf_res, nbCompressedBytes*(8<rng); if (anti_collapse_rsv > 0) { anti_collapse_on = st->consec_transient<2; #ifdef FUZZING anti_collapse_on = rand()&0x1; #endif ec_enc_bits(enc, anti_collapse_on, 1); } quant_energy_finalise(st->mode, st->start, st->end, oldBandE, error, fine_quant, fine_priority, nbCompressedBytes*8-ec_tell(enc), enc, C); if (silence) { for (i=0;imode->nbEBands;i++) oldBandE[i] = -QCONST16(28.f,DB_SHIFT); } #ifdef RESYNTH /* Re-synthesis of the coded audio if required */ { celt_sig *out_mem[2]; celt_sig *overlap_mem[2]; log2Amp(st->mode, st->start, st->end, bandE, oldBandE, C); if (silence) { for (i=0;imode->nbEBands;i++) bandE[i] = 0; } #ifdef MEASURE_NORM_MSE measure_norm_mse(st->mode, X, X0, bandE, bandE0, M, N, C); #endif if (anti_collapse_on) { anti_collapse(st->mode, X, collapse_masks, LM, C, N, st->start, st->end, oldBandE, oldLogE, oldLogE2, pulses, st->rng); } /* Synthesis */ denormalise_bands(st->mode, X, freq, bandE, effEnd, C, M); OPUS_MOVE(st->syn_mem[0], st->syn_mem[0]+N, MAX_PERIOD); if (CC==2) OPUS_MOVE(st->syn_mem[1], st->syn_mem[1]+N, MAX_PERIOD); c=0; do for (i=0;imode->eBands[st->start];i++) freq[c*N+i] = 0; while (++cmode->eBands[st->end];isyn_mem[0]+MAX_PERIOD; if (CC==2) out_mem[1] = st->syn_mem[1]+MAX_PERIOD; overlap_mem[0] = prefilter_mem+CC*COMBFILTER_MAXPERIOD; if (CC==2) overlap_mem[1] = overlap_mem[0] + st->overlap; compute_inv_mdcts(st->mode, shortBlocks, freq, out_mem, overlap_mem, CC, LM); c=0; do { st->prefilter_period=IMAX(st->prefilter_period, COMBFILTER_MINPERIOD); st->prefilter_period_old=IMAX(st->prefilter_period_old, COMBFILTER_MINPERIOD); comb_filter(out_mem[c], out_mem[c], st->prefilter_period_old, st->prefilter_period, st->mode->shortMdctSize, st->prefilter_gain_old, st->prefilter_gain, st->prefilter_tapset_old, st->prefilter_tapset, st->mode->window, st->overlap); if (LM!=0) comb_filter(out_mem[c]+st->mode->shortMdctSize, out_mem[c]+st->mode->shortMdctSize, st->prefilter_period, pitch_index, N-st->mode->shortMdctSize, st->prefilter_gain, gain1, st->prefilter_tapset, prefilter_tapset, st->mode->window, st->mode->overlap); } while (++cupsample, st->mode->preemph, st->preemph_memD); st->prefilter_period_old = st->prefilter_period; st->prefilter_gain_old = st->prefilter_gain; st->prefilter_tapset_old = st->prefilter_tapset; } #endif st->prefilter_period = pitch_index; st->prefilter_gain = gain1; st->prefilter_tapset = prefilter_tapset; #ifdef RESYNTH if (LM!=0) { st->prefilter_period_old = st->prefilter_period; st->prefilter_gain_old = st->prefilter_gain; st->prefilter_tapset_old = st->prefilter_tapset; } #endif if (CC==2&&C==1) { for (i=0;imode->nbEBands;i++) oldBandE[st->mode->nbEBands+i]=oldBandE[i]; } if (!isTransient) { for (i=0;imode->nbEBands;i++) oldLogE2[i] = oldLogE[i]; for (i=0;imode->nbEBands;i++) oldLogE[i] = oldBandE[i]; } else { for (i=0;imode->nbEBands;i++) oldLogE[i] = MIN16(oldLogE[i], oldBandE[i]); } /* In case start or end were to change */ c=0; do { for (i=0;istart;i++) { oldBandE[c*st->mode->nbEBands+i]=0; oldLogE[c*st->mode->nbEBands+i]=oldLogE2[c*st->mode->nbEBands+i]=-QCONST16(28.f,DB_SHIFT); } for (i=st->end;imode->nbEBands;i++) { oldBandE[c*st->mode->nbEBands+i]=0; oldLogE[c*st->mode->nbEBands+i]=oldLogE2[c*st->mode->nbEBands+i]=-QCONST16(28.f,DB_SHIFT); } } while (++cconsec_transient++; else st->consec_transient=0; st->rng = enc->rng; /* If there's any room left (can only happen for very high rates), it's already filled with zeros */ ec_enc_done(enc); #ifdef CUSTOM_MODES if (st->signalling) nbCompressedBytes++; #endif RESTORE_STACK; if (ec_get_error(enc)) return OPUS_INTERNAL_ERROR; else return nbCompressedBytes; } #ifdef CUSTOM_MODES #ifdef FIXED_POINT int opus_custom_encode(CELTEncoder * restrict st, const opus_int16 * pcm, int frame_size, unsigned char *compressed, int nbCompressedBytes) { return celt_encode_with_ec(st, pcm, frame_size, compressed, nbCompressedBytes, NULL); } #ifndef DISABLE_FLOAT_API int opus_custom_encode_float(CELTEncoder * restrict st, const float * pcm, int frame_size, unsigned char *compressed, int nbCompressedBytes) { int j, ret, C, N; VARDECL(opus_int16, in); ALLOC_STACK; if (pcm==NULL) return OPUS_BAD_ARG; C = st->channels; N = frame_size; ALLOC(in, C*N, opus_int16); for (j=0;jchannels; N=frame_size; ALLOC(in, C*N, celt_sig); for (j=0;j10) goto bad_arg; st->complexity = value; } break; case CELT_SET_START_BAND_REQUEST: { opus_int32 value = va_arg(ap, opus_int32); if (value<0 || value>=st->mode->nbEBands) goto bad_arg; st->start = value; } break; case CELT_SET_END_BAND_REQUEST: { opus_int32 value = va_arg(ap, opus_int32); if (value<1 || value>st->mode->nbEBands) goto bad_arg; st->end = value; } break; case CELT_SET_PREDICTION_REQUEST: { int value = va_arg(ap, opus_int32); if (value<0 || value>2) goto bad_arg; st->disable_pf = value<=1; st->force_intra = value==0; } break; case OPUS_SET_PACKET_LOSS_PERC_REQUEST: { int value = va_arg(ap, opus_int32); if (value<0 || value>100) goto bad_arg; st->loss_rate = value; } break; case OPUS_SET_VBR_CONSTRAINT_REQUEST: { opus_int32 value = va_arg(ap, opus_int32); st->constrained_vbr = value; } break; case OPUS_SET_VBR_REQUEST: { opus_int32 value = va_arg(ap, opus_int32); st->vbr = value; } break; case OPUS_SET_BITRATE_REQUEST: { opus_int32 value = va_arg(ap, opus_int32); if (value<=500 && value!=OPUS_BITRATE_MAX) goto bad_arg; value = IMIN(value, 260000*st->channels); st->bitrate = value; } break; case CELT_SET_CHANNELS_REQUEST: { opus_int32 value = va_arg(ap, opus_int32); if (value<1 || value>2) goto bad_arg; st->stream_channels = value; } break; case OPUS_SET_LSB_DEPTH_REQUEST: { opus_int32 value = va_arg(ap, opus_int32); if (value<8 || value>24) goto bad_arg; st->lsb_depth=value; } break; case OPUS_GET_LSB_DEPTH_REQUEST: { opus_int32 *value = va_arg(ap, opus_int32*); *value=st->lsb_depth; } break; case OPUS_RESET_STATE: { int i; opus_val16 *oldBandE, *oldLogE, *oldLogE2; oldBandE = (opus_val16*)(st->in_mem+st->channels*(2*st->overlap+COMBFILTER_MAXPERIOD)); oldLogE = oldBandE + st->channels*st->mode->nbEBands; oldLogE2 = oldLogE + st->channels*st->mode->nbEBands; OPUS_CLEAR((char*)&st->ENCODER_RESET_START, opus_custom_encoder_get_size(st->mode, st->channels)- ((char*)&st->ENCODER_RESET_START - (char*)st)); for (i=0;ichannels*st->mode->nbEBands;i++) oldLogE[i]=oldLogE2[i]=-QCONST16(28.f,DB_SHIFT); st->vbr_offset = 0; st->delayedIntra = 1; st->spread_decision = SPREAD_NORMAL; st->tonal_average = 256; st->hf_average = 0; st->tapset_decision = 0; } break; #ifdef CUSTOM_MODES case CELT_SET_INPUT_CLIPPING_REQUEST: { opus_int32 value = va_arg(ap, opus_int32); st->clip = value; } break; #endif case CELT_SET_SIGNALLING_REQUEST: { opus_int32 value = va_arg(ap, opus_int32); st->signalling = value; } break; case CELT_SET_ANALYSIS_REQUEST: { AnalysisInfo *info = va_arg(ap, AnalysisInfo *); if (info) OPUS_COPY(&st->analysis, info, 1); } break; case CELT_GET_MODE_REQUEST: { const CELTMode ** value = va_arg(ap, const CELTMode**); if (value==0) goto bad_arg; *value=st->mode; } break; case OPUS_GET_FINAL_RANGE_REQUEST: { opus_uint32 * value = va_arg(ap, opus_uint32 *); if (value==0) goto bad_arg; *value=st->rng; } break; default: goto bad_request; } va_end(ap); return OPUS_OK; bad_arg: va_end(ap); return OPUS_BAD_ARG; bad_request: va_end(ap); return OPUS_UNIMPLEMENTED; } /**********************************************************************/ /* */ /* DECODER */ /* */ /**********************************************************************/ #define DECODE_BUFFER_SIZE 2048 /** Decoder state @brief Decoder state */ struct OpusCustomDecoder { const OpusCustomMode *mode; int overlap; int channels; int stream_channels; int downsample; int start, end; int signalling; /* Everything beyond this point gets cleared on a reset */ #define DECODER_RESET_START rng opus_uint32 rng; int error; int last_pitch_index; int loss_count; int postfilter_period; int postfilter_period_old; opus_val16 postfilter_gain; opus_val16 postfilter_gain_old; int postfilter_tapset; int postfilter_tapset_old; celt_sig preemph_memD[2]; celt_sig _decode_mem[1]; /* Size = channels*(DECODE_BUFFER_SIZE+mode->overlap) */ /* opus_val16 lpc[], Size = channels*LPC_ORDER */ /* opus_val16 oldEBands[], Size = 2*mode->nbEBands */ /* opus_val16 oldLogE[], Size = 2*mode->nbEBands */ /* opus_val16 oldLogE2[], Size = 2*mode->nbEBands */ /* opus_val16 backgroundLogE[], Size = 2*mode->nbEBands */ }; int celt_decoder_get_size(int channels) { const CELTMode *mode = opus_custom_mode_create(48000, 960, NULL); return opus_custom_decoder_get_size(mode, channels); } OPUS_CUSTOM_NOSTATIC int opus_custom_decoder_get_size(const CELTMode *mode, int channels) { int size = sizeof(struct CELTDecoder) + (channels*(DECODE_BUFFER_SIZE+mode->overlap)-1)*sizeof(celt_sig) + channels*LPC_ORDER*sizeof(opus_val16) + 4*2*mode->nbEBands*sizeof(opus_val16); return size; } #ifdef CUSTOM_MODES CELTDecoder *opus_custom_decoder_create(const CELTMode *mode, int channels, int *error) { int ret; CELTDecoder *st = (CELTDecoder *)opus_alloc(opus_custom_decoder_get_size(mode, channels)); ret = opus_custom_decoder_init(st, mode, channels); if (ret != OPUS_OK) { opus_custom_decoder_destroy(st); st = NULL; } if (error) *error = ret; return st; } #endif /* CUSTOM_MODES */ int celt_decoder_init(CELTDecoder *st, opus_int32 sampling_rate, int channels) { int ret; ret = opus_custom_decoder_init(st, opus_custom_mode_create(48000, 960, NULL), channels); if (ret != OPUS_OK) return ret; st->downsample = resampling_factor(sampling_rate); if (st->downsample==0) return OPUS_BAD_ARG; else return OPUS_OK; } OPUS_CUSTOM_NOSTATIC int opus_custom_decoder_init(CELTDecoder *st, const CELTMode *mode, int channels) { if (channels < 0 || channels > 2) return OPUS_BAD_ARG; if (st==NULL) return OPUS_ALLOC_FAIL; OPUS_CLEAR((char*)st, opus_custom_decoder_get_size(mode, channels)); st->mode = mode; st->overlap = mode->overlap; st->stream_channels = st->channels = channels; st->downsample = 1; st->start = 0; st->end = st->mode->effEBands; st->signalling = 1; st->loss_count = 0; opus_custom_decoder_ctl(st, OPUS_RESET_STATE); return OPUS_OK; } #ifdef CUSTOM_MODES void opus_custom_decoder_destroy(CELTDecoder *st) { opus_free(st); } #endif /* CUSTOM_MODES */ static void celt_decode_lost(CELTDecoder * restrict st, opus_val16 * restrict pcm, int N, int LM) { int c; int pitch_index; int overlap = st->mode->overlap; opus_val16 fade = Q15ONE; int i, len; const int C = st->channels; int offset; celt_sig *out_mem[2]; celt_sig *decode_mem[2]; celt_sig *overlap_mem[2]; opus_val16 *lpc; opus_val32 *out_syn[2]; opus_val16 *oldBandE, *oldLogE, *oldLogE2, *backgroundLogE; SAVE_STACK; c=0; do { decode_mem[c] = st->_decode_mem + c*(DECODE_BUFFER_SIZE+st->overlap); out_mem[c] = decode_mem[c]+DECODE_BUFFER_SIZE-MAX_PERIOD; overlap_mem[c] = decode_mem[c]+DECODE_BUFFER_SIZE; } while (++c_decode_mem+(DECODE_BUFFER_SIZE+st->overlap)*C); oldBandE = lpc+C*LPC_ORDER; oldLogE = oldBandE + 2*st->mode->nbEBands; oldLogE2 = oldLogE + 2*st->mode->nbEBands; backgroundLogE = oldLogE2 + 2*st->mode->nbEBands; out_syn[0] = out_mem[0]+MAX_PERIOD-N; if (C==2) out_syn[1] = out_mem[1]+MAX_PERIOD-N; len = N+st->mode->overlap; if (st->loss_count >= 5 || st->start!=0) { /* Noise-based PLC/CNG */ VARDECL(celt_sig, freq); VARDECL(celt_norm, X); VARDECL(celt_ener, bandE); opus_uint32 seed; int effEnd; effEnd = st->end; if (effEnd > st->mode->effEBands) effEnd = st->mode->effEBands; ALLOC(freq, C*N, celt_sig); /**< Interleaved signal MDCTs */ ALLOC(X, C*N, celt_norm); /**< Interleaved normalised MDCTs */ ALLOC(bandE, st->mode->nbEBands*C, celt_ener); if (st->loss_count >= 5) log2Amp(st->mode, st->start, st->end, bandE, backgroundLogE, C); else { /* Energy decay */ opus_val16 decay = st->loss_count==0 ? QCONST16(1.5f, DB_SHIFT) : QCONST16(.5f, DB_SHIFT); c=0; do { for (i=st->start;iend;i++) oldBandE[c*st->mode->nbEBands+i] -= decay; } while (++cmode, st->start, st->end, bandE, oldBandE, C); } seed = st->rng; for (c=0;cmode->eBands[st->start]<start;imode->effEBands;i++) { int j; int boffs; int blen; boffs = N*c+(st->mode->eBands[i]<mode->eBands[i+1]-st->mode->eBands[i])<>20); } renormalise_vector(X+boffs, blen, Q15ONE); } for (i=(st->mode->eBands[st->end]<rng = seed; denormalise_bands(st->mode, X, freq, bandE, st->mode->effEBands, C, 1<mode->eBands[st->start]<mode->eBands[effEnd]<downsample!=1) bound = IMIN(bound, N/st->downsample); for (i=bound;imode, 0, freq, out_syn, overlap_mem, C, LM); } else { /* Pitch-based PLC */ if (st->loss_count == 0) { opus_val16 pitch_buf[DECODE_BUFFER_SIZE>>1]; /* Corresponds to a min pitch of 67 Hz. It's possible to save CPU in this search by using only part of the decode buffer */ int poffset = 720; pitch_downsample(decode_mem, pitch_buf, DECODE_BUFFER_SIZE, C); /* Max pitch is 100 samples (480 Hz) */ pitch_search(pitch_buf+((poffset)>>1), pitch_buf, DECODE_BUFFER_SIZE-poffset, poffset-100, &pitch_index); pitch_index = poffset-pitch_index; st->last_pitch_index = pitch_index; } else { pitch_index = st->last_pitch_index; fade = QCONST16(.8f,15); } c=0; do { VARDECL(opus_val32, e); opus_val16 exc[MAX_PERIOD]; opus_val32 ac[LPC_ORDER+1]; opus_val16 decay = 1; opus_val32 S1=0; opus_val16 mem[LPC_ORDER]={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; ALLOC(e, MAX_PERIOD+2*st->mode->overlap, opus_val32); offset = MAX_PERIOD-pitch_index; for (i=0;iloss_count == 0) { _celt_autocorr(exc, ac, st->mode->window, st->mode->overlap, LPC_ORDER, MAX_PERIOD); /* Noise floor -40 dB */ #ifdef FIXED_POINT ac[0] += SHR32(ac[0],13); #else ac[0] *= 1.0001f; #endif /* Lag windowing */ for (i=1;i<=LPC_ORDER;i++) { /*ac[i] *= exp(-.5*(2*M_PI*.002*i)*(2*M_PI*.002*i));*/ #ifdef FIXED_POINT ac[i] -= MULT16_32_Q15(2*i*i, ac[i]); #else ac[i] -= ac[i]*(.008f*i)*(.008f*i); #endif } _celt_lpc(lpc+c*LPC_ORDER, ac, LPC_ORDER); } for (i=0;i E2) E1 = E2; decay = celt_sqrt(frac_div32(SHR32(E1,1),E2)); } /* Copy excitation, taking decay into account */ for (i=0;imode->overlap;i++) { opus_val16 tmp; if (offset+i >= MAX_PERIOD) { offset -= pitch_index; decay = MULT16_16_Q15(decay, decay); } e[i] = SHL32(EXTEND32(MULT16_16_Q15(decay, exc[offset+i])), SIG_SHIFT); tmp = ROUND16(out_mem[c][offset+i],SIG_SHIFT); S1 += SHR32(MULT16_16(tmp,tmp),8); } for (i=0;imode->overlap;i++) e[i] = MULT16_32_Q15(fade, e[i]); celt_iir(e, lpc+c*LPC_ORDER, e, len+st->mode->overlap, LPC_ORDER, mem); { opus_val32 S2=0; for (i=0;i SHR32(S2,2))) #else /* Float test is written this way to catch NaNs at the same time */ if (!(S1 > 0.2f*S2)) #endif { for (i=0;ipostfilter_period, st->postfilter_period, st->overlap, st->postfilter_gain, st->postfilter_gain, st->postfilter_tapset, st->postfilter_tapset, NULL, 0); for (i=0;imode->overlap-N;i++) out_mem[c][i] = out_mem[c][N+i]; /* Apply TDAC to the concealed audio so that it blends with the previous and next frames */ for (i=0;imode->window[i], e[N+overlap-1-i]) + MULT16_32_Q15(st->mode->window[overlap-i-1], e[N+i ]); out_mem[c][MAX_PERIOD+i] = MULT16_32_Q15(st->mode->window[overlap-i-1], tmp); out_mem[c][MAX_PERIOD+overlap-i-1] = MULT16_32_Q15(st->mode->window[i], tmp); } for (i=0;ipostfilter_period, st->postfilter_period, st->overlap, -st->postfilter_gain, -st->postfilter_gain, st->postfilter_tapset, st->postfilter_tapset, NULL, 0); for (i=0;idownsample, st->mode->preemph, st->preemph_memD); st->loss_count++; RESTORE_STACK; } int celt_decode_with_ec(CELTDecoder * restrict st, const unsigned char *data, int len, opus_val16 * restrict pcm, int frame_size, ec_dec *dec) { int c, i, N; int spread_decision; opus_int32 bits; ec_dec _dec; VARDECL(celt_sig, freq); VARDECL(celt_norm, X); VARDECL(celt_ener, bandE); VARDECL(int, fine_quant); VARDECL(int, pulses); VARDECL(int, cap); VARDECL(int, offsets); VARDECL(int, fine_priority); VARDECL(int, tf_res); VARDECL(unsigned char, collapse_masks); celt_sig *out_mem[2]; celt_sig *decode_mem[2]; celt_sig *overlap_mem[2]; celt_sig *out_syn[2]; opus_val16 *lpc; opus_val16 *oldBandE, *oldLogE, *oldLogE2, *backgroundLogE; int shortBlocks; int isTransient; int intra_ener; const int CC = st->channels; int LM, M; int effEnd; int codedBands; int alloc_trim; int postfilter_pitch; opus_val16 postfilter_gain; int intensity=0; int dual_stereo=0; opus_int32 total_bits; opus_int32 balance; opus_int32 tell; int dynalloc_logp; int postfilter_tapset; int anti_collapse_rsv; int anti_collapse_on=0; int silence; int C = st->stream_channels; ALLOC_STACK; frame_size *= st->downsample; c=0; do { decode_mem[c] = st->_decode_mem + c*(DECODE_BUFFER_SIZE+st->overlap); out_mem[c] = decode_mem[c]+DECODE_BUFFER_SIZE-MAX_PERIOD; overlap_mem[c] = decode_mem[c]+DECODE_BUFFER_SIZE; } while (++c_decode_mem+(DECODE_BUFFER_SIZE+st->overlap)*CC); oldBandE = lpc+CC*LPC_ORDER; oldLogE = oldBandE + 2*st->mode->nbEBands; oldLogE2 = oldLogE + 2*st->mode->nbEBands; backgroundLogE = oldLogE2 + 2*st->mode->nbEBands; #ifdef CUSTOM_MODES if (st->signalling && data!=NULL) { int data0=data[0]; /* Convert "standard mode" to Opus header */ if (st->mode->Fs==48000 && st->mode->shortMdctSize==120) { data0 = fromOpus(data0); if (data0<0) return OPUS_INVALID_PACKET; } st->end = IMAX(1, st->mode->effEBands-2*(data0>>5)); LM = (data0>>3)&0x3; C = 1 + ((data0>>2)&0x1); data++; len--; if (LM>st->mode->maxLM) return OPUS_INVALID_PACKET; if (frame_size < st->mode->shortMdctSize<mode->shortMdctSize<mode->maxLM;LM++) if (st->mode->shortMdctSize<st->mode->maxLM) return OPUS_BAD_ARG; } M=1<1275 || pcm==NULL) return OPUS_BAD_ARG; N = M*st->mode->shortMdctSize; effEnd = st->end; if (effEnd > st->mode->effEBands) effEnd = st->mode->effEBands; ALLOC(freq, IMAX(CC,C)*N, celt_sig); /**< Interleaved signal MDCTs */ ALLOC(X, C*N, celt_norm); /**< Interleaved normalised MDCTs */ ALLOC(bandE, st->mode->nbEBands*C, celt_ener); c=0; do for (i=0;imode->eBands[st->start];i++) X[c*N+i] = 0; while (++cmode->eBands[effEnd];idownsample; } if (dec == NULL) { ec_dec_init(&_dec,(unsigned char*)data,len); dec = &_dec; } if (C==1) { for (i=0;imode->nbEBands;i++) oldBandE[i]=MAX16(oldBandE[i],oldBandE[st->mode->nbEBands+i]); } total_bits = len*8; tell = ec_tell(dec); if (tell >= total_bits) silence = 1; else if (tell==1) silence = ec_dec_bit_logp(dec, 15); else silence = 0; if (silence) { /* Pretend we've read all the remaining bits */ tell = len*8; dec->nbits_total+=tell-ec_tell(dec); } postfilter_gain = 0; postfilter_pitch = 0; postfilter_tapset = 0; if (st->start==0 && tell+16 <= total_bits) { if(ec_dec_bit_logp(dec, 1)) { int qg, octave; octave = ec_dec_uint(dec, 6); postfilter_pitch = (16< 0 && tell+3 <= total_bits) { isTransient = ec_dec_bit_logp(dec, 3); tell = ec_tell(dec); } else isTransient = 0; if (isTransient) shortBlocks = M; else shortBlocks = 0; /* Decode the global flags (first symbols in the stream) */ intra_ener = tell+3<=total_bits ? ec_dec_bit_logp(dec, 3) : 0; /* Get band energies */ unquant_coarse_energy(st->mode, st->start, st->end, oldBandE, intra_ener, dec, C, LM); ALLOC(tf_res, st->mode->nbEBands, int); tf_decode(st->start, st->end, isTransient, tf_res, LM, dec); tell = ec_tell(dec); spread_decision = SPREAD_NORMAL; if (tell+4 <= total_bits) spread_decision = ec_dec_icdf(dec, spread_icdf, 5); ALLOC(pulses, st->mode->nbEBands, int); ALLOC(cap, st->mode->nbEBands, int); ALLOC(offsets, st->mode->nbEBands, int); ALLOC(fine_priority, st->mode->nbEBands, int); init_caps(st->mode,cap,LM,C); dynalloc_logp = 6; total_bits<<=BITRES; tell = ec_tell_frac(dec); for (i=st->start;iend;i++) { int width, quanta; int dynalloc_loop_logp; int boost; width = C*(st->mode->eBands[i+1]-st->mode->eBands[i])<0) dynalloc_logp = IMAX(2, dynalloc_logp-1); } ALLOC(fine_quant, st->mode->nbEBands, int); alloc_trim = tell+(6<=2&&bits>=((LM+2)<mode, st->start, st->end, offsets, cap, alloc_trim, &intensity, &dual_stereo, bits, &balance, pulses, fine_quant, fine_priority, C, LM, dec, 0, 0); unquant_fine_energy(st->mode, st->start, st->end, oldBandE, fine_quant, dec, C); /* Decode fixed codebook */ ALLOC(collapse_masks, C*st->mode->nbEBands, unsigned char); quant_all_bands(0, st->mode, st->start, st->end, X, C==2 ? X+N : NULL, collapse_masks, NULL, pulses, shortBlocks, spread_decision, dual_stereo, intensity, tf_res, len*(8<rng); if (anti_collapse_rsv > 0) { anti_collapse_on = ec_dec_bits(dec, 1); } unquant_energy_finalise(st->mode, st->start, st->end, oldBandE, fine_quant, fine_priority, len*8-ec_tell(dec), dec, C); if (anti_collapse_on) anti_collapse(st->mode, X, collapse_masks, LM, C, N, st->start, st->end, oldBandE, oldLogE, oldLogE2, pulses, st->rng); log2Amp(st->mode, st->start, st->end, bandE, oldBandE, C); if (silence) { for (i=0;imode->nbEBands;i++) { bandE[i] = 0; oldBandE[i] = -QCONST16(28.f,DB_SHIFT); } } /* Synthesis */ denormalise_bands(st->mode, X, freq, bandE, effEnd, C, M); OPUS_MOVE(decode_mem[0], decode_mem[0]+N, DECODE_BUFFER_SIZE-N); if (CC==2) OPUS_MOVE(decode_mem[1], decode_mem[1]+N, DECODE_BUFFER_SIZE-N); c=0; do for (i=0;imode->eBands[st->start];i++) freq[c*N+i] = 0; while (++cmode->eBands[effEnd]; if (st->downsample!=1) bound = IMIN(bound, N/st->downsample); for (i=bound;imode, shortBlocks, freq, out_syn, overlap_mem, CC, LM); c=0; do { st->postfilter_period=IMAX(st->postfilter_period, COMBFILTER_MINPERIOD); st->postfilter_period_old=IMAX(st->postfilter_period_old, COMBFILTER_MINPERIOD); comb_filter(out_syn[c], out_syn[c], st->postfilter_period_old, st->postfilter_period, st->mode->shortMdctSize, st->postfilter_gain_old, st->postfilter_gain, st->postfilter_tapset_old, st->postfilter_tapset, st->mode->window, st->overlap); if (LM!=0) comb_filter(out_syn[c]+st->mode->shortMdctSize, out_syn[c]+st->mode->shortMdctSize, st->postfilter_period, postfilter_pitch, N-st->mode->shortMdctSize, st->postfilter_gain, postfilter_gain, st->postfilter_tapset, postfilter_tapset, st->mode->window, st->mode->overlap); } while (++cpostfilter_period_old = st->postfilter_period; st->postfilter_gain_old = st->postfilter_gain; st->postfilter_tapset_old = st->postfilter_tapset; st->postfilter_period = postfilter_pitch; st->postfilter_gain = postfilter_gain; st->postfilter_tapset = postfilter_tapset; if (LM!=0) { st->postfilter_period_old = st->postfilter_period; st->postfilter_gain_old = st->postfilter_gain; st->postfilter_tapset_old = st->postfilter_tapset; } if (C==1) { for (i=0;imode->nbEBands;i++) oldBandE[st->mode->nbEBands+i]=oldBandE[i]; } /* In case start or end were to change */ if (!isTransient) { for (i=0;i<2*st->mode->nbEBands;i++) oldLogE2[i] = oldLogE[i]; for (i=0;i<2*st->mode->nbEBands;i++) oldLogE[i] = oldBandE[i]; for (i=0;i<2*st->mode->nbEBands;i++) backgroundLogE[i] = MIN16(backgroundLogE[i] + M*QCONST16(0.001f,DB_SHIFT), oldBandE[i]); } else { for (i=0;i<2*st->mode->nbEBands;i++) oldLogE[i] = MIN16(oldLogE[i], oldBandE[i]); } c=0; do { for (i=0;istart;i++) { oldBandE[c*st->mode->nbEBands+i]=0; oldLogE[c*st->mode->nbEBands+i]=oldLogE2[c*st->mode->nbEBands+i]=-QCONST16(28.f,DB_SHIFT); } for (i=st->end;imode->nbEBands;i++) { oldBandE[c*st->mode->nbEBands+i]=0; oldLogE[c*st->mode->nbEBands+i]=oldLogE2[c*st->mode->nbEBands+i]=-QCONST16(28.f,DB_SHIFT); } } while (++c<2); st->rng = dec->rng; deemphasis(out_syn, pcm, N, CC, st->downsample, st->mode->preemph, st->preemph_memD); st->loss_count = 0; RESTORE_STACK; if (ec_tell(dec) > 8*len) return OPUS_INTERNAL_ERROR; if(ec_get_error(dec)) st->error = 1; return frame_size/st->downsample; } #ifdef CUSTOM_MODES #ifdef FIXED_POINT int opus_custom_decode(CELTDecoder * restrict st, const unsigned char *data, int len, opus_int16 * restrict pcm, int frame_size) { return celt_decode_with_ec(st, data, len, pcm, frame_size, NULL); } #ifndef DISABLE_FLOAT_API int opus_custom_decode_float(CELTDecoder * restrict st, const unsigned char *data, int len, float * restrict pcm, int frame_size) { int j, ret, C, N; VARDECL(opus_int16, out); ALLOC_STACK; if (pcm==NULL) return OPUS_BAD_ARG; C = st->channels; N = frame_size; ALLOC(out, C*N, opus_int16); ret=celt_decode_with_ec(st, data, len, out, frame_size, NULL); if (ret>0) for (j=0;jchannels; N = frame_size; ALLOC(out, C*N, celt_sig); ret=celt_decode_with_ec(st, data, len, out, frame_size, NULL); if (ret>0) for (j=0;j=st->mode->nbEBands) goto bad_arg; st->start = value; } break; case CELT_SET_END_BAND_REQUEST: { opus_int32 value = va_arg(ap, opus_int32); if (value<1 || value>st->mode->nbEBands) goto bad_arg; st->end = value; } break; case CELT_SET_CHANNELS_REQUEST: { opus_int32 value = va_arg(ap, opus_int32); if (value<1 || value>2) goto bad_arg; st->stream_channels = value; } break; case CELT_GET_AND_CLEAR_ERROR_REQUEST: { opus_int32 *value = va_arg(ap, opus_int32*); if (value==NULL) goto bad_arg; *value=st->error; st->error = 0; } break; case OPUS_GET_LOOKAHEAD_REQUEST: { opus_int32 *value = va_arg(ap, opus_int32*); if (value==NULL) goto bad_arg; *value = st->overlap/st->downsample; } break; case OPUS_RESET_STATE: { int i; opus_val16 *lpc, *oldBandE, *oldLogE, *oldLogE2; lpc = (opus_val16*)(st->_decode_mem+(DECODE_BUFFER_SIZE+st->overlap)*st->channels); oldBandE = lpc+st->channels*LPC_ORDER; oldLogE = oldBandE + 2*st->mode->nbEBands; oldLogE2 = oldLogE + 2*st->mode->nbEBands; OPUS_CLEAR((char*)&st->DECODER_RESET_START, opus_custom_decoder_get_size(st->mode, st->channels)- ((char*)&st->DECODER_RESET_START - (char*)st)); for (i=0;i<2*st->mode->nbEBands;i++) oldLogE[i]=oldLogE2[i]=-QCONST16(28.f,DB_SHIFT); } break; case OPUS_GET_PITCH_REQUEST: { opus_int32 *value = va_arg(ap, opus_int32*); if (value==NULL) goto bad_arg; *value = st->postfilter_period; } break; #ifdef OPUS_BUILD case CELT_GET_MODE_REQUEST: { const CELTMode ** value = va_arg(ap, const CELTMode**); if (value==0) goto bad_arg; *value=st->mode; } break; case CELT_SET_SIGNALLING_REQUEST: { opus_int32 value = va_arg(ap, opus_int32); st->signalling = value; } break; case OPUS_GET_FINAL_RANGE_REQUEST: { opus_uint32 * value = va_arg(ap, opus_uint32 *); if (value==0) goto bad_arg; *value=st->rng; } break; #endif default: goto bad_request; } va_end(ap); return OPUS_OK; bad_arg: va_end(ap); return OPUS_BAD_ARG; bad_request: va_end(ap); return OPUS_UNIMPLEMENTED; } const char *opus_strerror(int error) { static const char *error_strings[8] = { "success", "invalid argument", "buffer too small", "internal error", "corrupted stream", "request not implemented", "invalid state", "memory allocation failed" }; if (error > 0 || error < -7) return "unknown error"; else return error_strings[-error]; } const char *opus_get_version_string(void) { return "libopus " OPUS_VERSION "-exp_analysis" #ifdef FIXED_POINT "-fixed" #endif #ifdef FUZZING "-fuzzing" #endif ; }