Chris@69: /* Copyright (c) 2007-2008 CSIRO Chris@69: Copyright (c) 2007-2010 Xiph.Org Foundation Chris@69: Copyright (c) 2008 Gregory Maxwell Chris@69: Written by Jean-Marc Valin and Gregory Maxwell */ Chris@69: /* Chris@69: Redistribution and use in source and binary forms, with or without Chris@69: modification, are permitted provided that the following conditions Chris@69: are met: Chris@69: Chris@69: - Redistributions of source code must retain the above copyright Chris@69: notice, this list of conditions and the following disclaimer. Chris@69: Chris@69: - Redistributions in binary form must reproduce the above copyright Chris@69: notice, this list of conditions and the following disclaimer in the Chris@69: documentation and/or other materials provided with the distribution. Chris@69: Chris@69: THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS Chris@69: ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT Chris@69: LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR Chris@69: A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER Chris@69: OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, Chris@69: EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, Chris@69: PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR Chris@69: PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF Chris@69: LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING Chris@69: NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS Chris@69: SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. Chris@69: */ Chris@69: Chris@69: #ifdef HAVE_CONFIG_H Chris@69: #include "config.h" Chris@69: #endif Chris@69: Chris@69: #define CELT_ENCODER_C Chris@69: Chris@69: #include "cpu_support.h" Chris@69: #include "os_support.h" Chris@69: #include "mdct.h" Chris@69: #include Chris@69: #include "celt.h" Chris@69: #include "pitch.h" Chris@69: #include "bands.h" Chris@69: #include "modes.h" Chris@69: #include "entcode.h" Chris@69: #include "quant_bands.h" Chris@69: #include "rate.h" Chris@69: #include "stack_alloc.h" Chris@69: #include "mathops.h" Chris@69: #include "float_cast.h" Chris@69: #include Chris@69: #include "celt_lpc.h" Chris@69: #include "vq.h" Chris@69: Chris@69: Chris@69: /** Encoder state Chris@69: @brief Encoder state Chris@69: */ Chris@69: struct OpusCustomEncoder { Chris@69: const OpusCustomMode *mode; /**< Mode used by the encoder */ Chris@69: int channels; Chris@69: int stream_channels; Chris@69: Chris@69: int force_intra; Chris@69: int clip; Chris@69: int disable_pf; Chris@69: int complexity; Chris@69: int upsample; Chris@69: int start, end; Chris@69: Chris@69: opus_int32 bitrate; Chris@69: int vbr; Chris@69: int signalling; Chris@69: int constrained_vbr; /* If zero, VBR can do whatever it likes with the rate */ Chris@69: int loss_rate; Chris@69: int lsb_depth; Chris@69: int lfe; Chris@69: int disable_inv; Chris@69: int arch; Chris@69: Chris@69: /* Everything beyond this point gets cleared on a reset */ Chris@69: #define ENCODER_RESET_START rng Chris@69: Chris@69: opus_uint32 rng; Chris@69: int spread_decision; Chris@69: opus_val32 delayedIntra; Chris@69: int tonal_average; Chris@69: int lastCodedBands; Chris@69: int hf_average; Chris@69: int tapset_decision; Chris@69: Chris@69: int prefilter_period; Chris@69: opus_val16 prefilter_gain; Chris@69: int prefilter_tapset; Chris@69: #ifdef RESYNTH Chris@69: int prefilter_period_old; Chris@69: opus_val16 prefilter_gain_old; Chris@69: int prefilter_tapset_old; Chris@69: #endif Chris@69: int consec_transient; Chris@69: AnalysisInfo analysis; Chris@69: SILKInfo silk_info; Chris@69: Chris@69: opus_val32 preemph_memE[2]; Chris@69: opus_val32 preemph_memD[2]; Chris@69: Chris@69: /* VBR-related parameters */ Chris@69: opus_int32 vbr_reservoir; Chris@69: opus_int32 vbr_drift; Chris@69: opus_int32 vbr_offset; Chris@69: opus_int32 vbr_count; Chris@69: opus_val32 overlap_max; Chris@69: opus_val16 stereo_saving; Chris@69: int intensity; Chris@69: opus_val16 *energy_mask; Chris@69: opus_val16 spec_avg; Chris@69: Chris@69: #ifdef RESYNTH Chris@69: /* +MAX_PERIOD/2 to make space for overlap */ Chris@69: celt_sig syn_mem[2][2*MAX_PERIOD+MAX_PERIOD/2]; Chris@69: #endif Chris@69: Chris@69: celt_sig in_mem[1]; /* Size = channels*mode->overlap */ Chris@69: /* celt_sig prefilter_mem[], Size = channels*COMBFILTER_MAXPERIOD */ Chris@69: /* opus_val16 oldBandE[], Size = channels*mode->nbEBands */ Chris@69: /* opus_val16 oldLogE[], Size = channels*mode->nbEBands */ Chris@69: /* opus_val16 oldLogE2[], Size = channels*mode->nbEBands */ Chris@69: /* opus_val16 energyError[], Size = channels*mode->nbEBands */ Chris@69: }; Chris@69: Chris@69: int celt_encoder_get_size(int channels) Chris@69: { Chris@69: CELTMode *mode = opus_custom_mode_create(48000, 960, NULL); Chris@69: return opus_custom_encoder_get_size(mode, channels); Chris@69: } Chris@69: Chris@69: OPUS_CUSTOM_NOSTATIC int opus_custom_encoder_get_size(const CELTMode *mode, int channels) Chris@69: { Chris@69: int size = sizeof(struct CELTEncoder) Chris@69: + (channels*mode->overlap-1)*sizeof(celt_sig) /* celt_sig in_mem[channels*mode->overlap]; */ Chris@69: + channels*COMBFILTER_MAXPERIOD*sizeof(celt_sig) /* celt_sig prefilter_mem[channels*COMBFILTER_MAXPERIOD]; */ Chris@69: + 4*channels*mode->nbEBands*sizeof(opus_val16); /* opus_val16 oldBandE[channels*mode->nbEBands]; */ Chris@69: /* opus_val16 oldLogE[channels*mode->nbEBands]; */ Chris@69: /* opus_val16 oldLogE2[channels*mode->nbEBands]; */ Chris@69: /* opus_val16 energyError[channels*mode->nbEBands]; */ Chris@69: return size; Chris@69: } Chris@69: Chris@69: #ifdef CUSTOM_MODES Chris@69: CELTEncoder *opus_custom_encoder_create(const CELTMode *mode, int channels, int *error) Chris@69: { Chris@69: int ret; Chris@69: CELTEncoder *st = (CELTEncoder *)opus_alloc(opus_custom_encoder_get_size(mode, channels)); Chris@69: /* init will handle the NULL case */ Chris@69: ret = opus_custom_encoder_init(st, mode, channels); Chris@69: if (ret != OPUS_OK) Chris@69: { Chris@69: opus_custom_encoder_destroy(st); Chris@69: st = NULL; Chris@69: } Chris@69: if (error) Chris@69: *error = ret; Chris@69: return st; Chris@69: } Chris@69: #endif /* CUSTOM_MODES */ Chris@69: Chris@69: static int opus_custom_encoder_init_arch(CELTEncoder *st, const CELTMode *mode, Chris@69: int channels, int arch) Chris@69: { Chris@69: if (channels < 0 || channels > 2) Chris@69: return OPUS_BAD_ARG; Chris@69: Chris@69: if (st==NULL || mode==NULL) Chris@69: return OPUS_ALLOC_FAIL; Chris@69: Chris@69: OPUS_CLEAR((char*)st, opus_custom_encoder_get_size(mode, channels)); Chris@69: Chris@69: st->mode = mode; Chris@69: st->stream_channels = st->channels = channels; Chris@69: Chris@69: st->upsample = 1; Chris@69: st->start = 0; Chris@69: st->end = st->mode->effEBands; Chris@69: st->signalling = 1; Chris@69: st->arch = arch; Chris@69: Chris@69: st->constrained_vbr = 1; Chris@69: st->clip = 1; Chris@69: Chris@69: st->bitrate = OPUS_BITRATE_MAX; Chris@69: st->vbr = 0; Chris@69: st->force_intra = 0; Chris@69: st->complexity = 5; Chris@69: st->lsb_depth=24; Chris@69: Chris@69: opus_custom_encoder_ctl(st, OPUS_RESET_STATE); Chris@69: Chris@69: return OPUS_OK; Chris@69: } Chris@69: Chris@69: #ifdef CUSTOM_MODES Chris@69: int opus_custom_encoder_init(CELTEncoder *st, const CELTMode *mode, int channels) Chris@69: { Chris@69: return opus_custom_encoder_init_arch(st, mode, channels, opus_select_arch()); Chris@69: } Chris@69: #endif Chris@69: Chris@69: int celt_encoder_init(CELTEncoder *st, opus_int32 sampling_rate, int channels, Chris@69: int arch) Chris@69: { Chris@69: int ret; Chris@69: ret = opus_custom_encoder_init_arch(st, Chris@69: opus_custom_mode_create(48000, 960, NULL), channels, arch); Chris@69: if (ret != OPUS_OK) Chris@69: return ret; Chris@69: st->upsample = resampling_factor(sampling_rate); Chris@69: return OPUS_OK; Chris@69: } Chris@69: Chris@69: #ifdef CUSTOM_MODES Chris@69: void opus_custom_encoder_destroy(CELTEncoder *st) Chris@69: { Chris@69: opus_free(st); Chris@69: } Chris@69: #endif /* CUSTOM_MODES */ Chris@69: Chris@69: Chris@69: static int transient_analysis(const opus_val32 * OPUS_RESTRICT in, int len, int C, Chris@69: opus_val16 *tf_estimate, int *tf_chan, int allow_weak_transients, Chris@69: int *weak_transient) Chris@69: { Chris@69: int i; Chris@69: VARDECL(opus_val16, tmp); Chris@69: opus_val32 mem0,mem1; Chris@69: int is_transient = 0; Chris@69: opus_int32 mask_metric = 0; Chris@69: int c; Chris@69: opus_val16 tf_max; Chris@69: int len2; Chris@69: /* Forward masking: 6.7 dB/ms. */ Chris@69: #ifdef FIXED_POINT Chris@69: int forward_shift = 4; Chris@69: #else Chris@69: opus_val16 forward_decay = QCONST16(.0625f,15); Chris@69: #endif Chris@69: /* Table of 6*64/x, trained on real data to minimize the average error */ Chris@69: static const unsigned char inv_table[128] = { Chris@69: 255,255,156,110, 86, 70, 59, 51, 45, 40, 37, 33, 31, 28, 26, 25, Chris@69: 23, 22, 21, 20, 19, 18, 17, 16, 16, 15, 15, 14, 13, 13, 12, 12, Chris@69: 12, 12, 11, 11, 11, 10, 10, 10, 9, 9, 9, 9, 9, 9, 8, 8, Chris@69: 8, 8, 8, 7, 7, 7, 7, 7, 7, 6, 6, 6, 6, 6, 6, 6, Chris@69: 6, 6, 6, 6, 6, 6, 6, 6, 6, 5, 5, 5, 5, 5, 5, 5, Chris@69: 5, 5, 5, 5, 5, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, Chris@69: 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 3, 3, Chris@69: 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, Chris@69: }; Chris@69: SAVE_STACK; Chris@69: ALLOC(tmp, len, opus_val16); Chris@69: Chris@69: *weak_transient = 0; Chris@69: /* For lower bitrates, let's be more conservative and have a forward masking Chris@69: decay of 3.3 dB/ms. This avoids having to code transients at very low Chris@69: bitrate (mostly for hybrid), which can result in unstable energy and/or Chris@69: partial collapse. */ Chris@69: if (allow_weak_transients) Chris@69: { Chris@69: #ifdef FIXED_POINT Chris@69: forward_shift = 5; Chris@69: #else Chris@69: forward_decay = QCONST16(.03125f,15); Chris@69: #endif Chris@69: } Chris@69: len2=len/2; Chris@69: for (c=0;c=0;i--) Chris@69: { Chris@69: /* Backward masking: 13.9 dB/ms. */ Chris@69: #ifdef FIXED_POINT Chris@69: /* FIXME: Use PSHR16() instead */ Chris@69: tmp[i] = mem0 + PSHR32(tmp[i]-mem0,3); Chris@69: #else Chris@69: tmp[i] = mem0 + MULT16_16_P15(QCONST16(0.125f,15),tmp[i]-mem0); Chris@69: #endif Chris@69: mem0 = tmp[i]; Chris@69: maxE = MAX16(maxE, mem0); Chris@69: } Chris@69: /*for (i=0;i>1))); Chris@69: #else Chris@69: mean = celt_sqrt(mean * maxE*.5*len2); Chris@69: #endif Chris@69: /* Inverse of the mean energy in Q15+6 */ Chris@69: norm = SHL32(EXTEND32(len2),6+14)/ADD32(EPSILON,SHR32(mean,1)); Chris@69: /* Compute harmonic mean discarding the unreliable boundaries Chris@69: The data is smooth, so we only take 1/4th of the samples */ Chris@69: unmask=0; Chris@69: /* We should never see NaNs here. If we find any, then something really bad happened and we better abort Chris@69: before it does any damage later on. If these asserts are disabled (no hardening), then the table Chris@69: lookup a few lines below (id = ...) is likely to crash dur to an out-of-bounds read. DO NOT FIX Chris@69: that crash on NaN since it could result in a worse issue later on. */ Chris@69: celt_assert(!celt_isnan(tmp[0])); Chris@69: celt_assert(!celt_isnan(norm)); Chris@69: for (i=12;imask_metric) Chris@69: { Chris@69: *tf_chan = c; Chris@69: mask_metric = unmask; Chris@69: } Chris@69: } Chris@69: is_transient = mask_metric>200; Chris@69: /* For low bitrates, define "weak transients" that need to be Chris@69: handled differently to avoid partial collapse. */ Chris@69: if (allow_weak_transients && is_transient && mask_metric<600) { Chris@69: is_transient = 0; Chris@69: *weak_transient = 1; Chris@69: } Chris@69: /* Arbitrary metric for VBR boost */ Chris@69: tf_max = MAX16(0,celt_sqrt(27*mask_metric)-42); Chris@69: /* *tf_estimate = 1 + MIN16(1, sqrt(MAX16(0, tf_max-30))/20); */ Chris@69: *tf_estimate = celt_sqrt(MAX32(0, SHL32(MULT16_16(QCONST16(0.0069,14),MIN16(163,tf_max)),14)-QCONST32(0.139,28))); Chris@69: /*printf("%d %f\n", tf_max, mask_metric);*/ Chris@69: RESTORE_STACK; Chris@69: #ifdef FUZZING Chris@69: is_transient = rand()&0x1; Chris@69: #endif Chris@69: /*printf("%d %f %d\n", is_transient, (float)*tf_estimate, tf_max);*/ Chris@69: return is_transient; Chris@69: } Chris@69: Chris@69: /* Looks for sudden increases of energy to decide whether we need to patch Chris@69: the transient decision */ Chris@69: static int patch_transient_decision(opus_val16 *newE, opus_val16 *oldE, int nbEBands, Chris@69: int start, int end, int C) Chris@69: { Chris@69: int i, c; Chris@69: opus_val32 mean_diff=0; Chris@69: opus_val16 spread_old[26]; Chris@69: /* Apply an aggressive (-6 dB/Bark) spreading function to the old frame to Chris@69: avoid false detection caused by irrelevant bands */ Chris@69: if (C==1) Chris@69: { Chris@69: spread_old[start] = oldE[start]; Chris@69: for (i=start+1;i=start;i--) Chris@69: spread_old[i] = MAX16(spread_old[i], spread_old[i+1]-QCONST16(1.0f, DB_SHIFT)); Chris@69: /* Compute mean increase */ Chris@69: c=0; do { Chris@69: for (i=IMAX(2,start);i QCONST16(1.f, DB_SHIFT); Chris@69: } Chris@69: Chris@69: /** Apply window and compute the MDCT for all sub-frames and Chris@69: all channels in a frame */ Chris@69: static void compute_mdcts(const CELTMode *mode, int shortBlocks, celt_sig * OPUS_RESTRICT in, Chris@69: celt_sig * OPUS_RESTRICT out, int C, int CC, int LM, int upsample, Chris@69: int arch) Chris@69: { Chris@69: const int overlap = mode->overlap; Chris@69: int N; Chris@69: int B; Chris@69: int shift; Chris@69: int i, b, c; Chris@69: if (shortBlocks) Chris@69: { Chris@69: B = shortBlocks; Chris@69: N = mode->shortMdctSize; Chris@69: shift = mode->maxLM; Chris@69: } else { Chris@69: B = 1; Chris@69: N = mode->shortMdctSize<maxLM-LM; Chris@69: } Chris@69: c=0; do { Chris@69: for (b=0;bmdct, in+c*(B*N+overlap)+b*N, Chris@69: &out[b+c*N*B], mode->window, overlap, shift, B, Chris@69: arch); Chris@69: } Chris@69: } while (++ceBands[len]-m->eBands[len-1])<eBands[len]-m->eBands[len-1])<eBands[i+1]-m->eBands[i])<eBands[i+1]-m->eBands[i])==1; Chris@69: OPUS_COPY(tmp, &X[tf_chan*N0 + (m->eBands[i]<eBands[i]<>LM, 1<>k, 1<=0;i--) Chris@69: { Chris@69: if (tf_res[i+1] == 1) Chris@69: tf_res[i] = path1[i+1]; Chris@69: else Chris@69: tf_res[i] = path0[i+1]; Chris@69: } Chris@69: /*printf("%d %f\n", *tf_sum, tf_estimate);*/ Chris@69: RESTORE_STACK; Chris@69: #ifdef FUZZING Chris@69: tf_select = rand()&0x1; Chris@69: tf_res[0] = rand()&0x1; Chris@69: for (i=1;istorage*8; Chris@69: tell = ec_tell(enc); Chris@69: logp = isTransient ? 2 : 4; Chris@69: /* Reserve space to code the tf_select decision. */ Chris@69: tf_select_rsv = LM>0 && tell+logp+1 <= budget; Chris@69: budget -= tf_select_rsv; Chris@69: curr = tf_changed = 0; Chris@69: for (i=start;i> 10; Chris@69: trim = QCONST16(4.f, 8) + QCONST16(1.f/16.f, 8)*frac; Chris@69: } Chris@69: if (C==2) Chris@69: { Chris@69: opus_val16 sum = 0; /* Q10 */ Chris@69: opus_val16 minXC; /* Q10 */ Chris@69: /* Compute inter-channel correlation for low frequencies */ Chris@69: for (i=0;i<8;i++) Chris@69: { Chris@69: opus_val32 partial; Chris@69: partial = celt_inner_prod(&X[m->eBands[i]<eBands[i]<eBands[i+1]-m->eBands[i])<eBands[i]<eBands[i]<eBands[i+1]-m->eBands[i])<nbEBands]*(opus_int32)(2+2*i-end); Chris@69: } Chris@69: } while (++cvalid) Chris@69: { Chris@69: trim -= MAX16(-QCONST16(2.f, 8), MIN16(QCONST16(2.f, 8), Chris@69: (opus_val16)(QCONST16(2.f, 8)*(analysis->tonality_slope+.05f)))); Chris@69: } Chris@69: #else Chris@69: (void)analysis; Chris@69: #endif Chris@69: Chris@69: #ifdef FIXED_POINT Chris@69: trim_index = PSHR32(trim, 8); Chris@69: #else Chris@69: trim_index = (int)floor(.5f+trim); Chris@69: #endif Chris@69: trim_index = IMAX(0, IMIN(10, trim_index)); Chris@69: /*printf("%d\n", trim_index);*/ Chris@69: #ifdef FUZZING Chris@69: trim_index = rand()%11; Chris@69: #endif Chris@69: return trim_index; Chris@69: } Chris@69: Chris@69: static int stereo_analysis(const CELTMode *m, const celt_norm *X, Chris@69: int LM, int N0) Chris@69: { Chris@69: int i; Chris@69: int thetas; Chris@69: opus_val32 sumLR = EPSILON, sumMS = EPSILON; Chris@69: Chris@69: /* Use the L1 norm to model the entropy of the L/R signal vs the M/S signal */ Chris@69: for (i=0;i<13;i++) Chris@69: { Chris@69: int j; Chris@69: for (j=m->eBands[i]<eBands[i+1]<eBands[13]<<(LM+1))+thetas, sumMS) Chris@69: > MULT16_32_Q15(m->eBands[13]<<(LM+1), sumLR); Chris@69: } Chris@69: Chris@69: #define MSWAP(a,b) do {opus_val16 tmp = a;a=b;b=tmp;} while(0) Chris@69: static opus_val16 median_of_5(const opus_val16 *x) Chris@69: { Chris@69: opus_val16 t0, t1, t2, t3, t4; Chris@69: t2 = x[2]; Chris@69: if (x[0] > x[1]) Chris@69: { Chris@69: t0 = x[1]; Chris@69: t1 = x[0]; Chris@69: } else { Chris@69: t0 = x[0]; Chris@69: t1 = x[1]; Chris@69: } Chris@69: if (x[3] > x[4]) Chris@69: { Chris@69: t3 = x[4]; Chris@69: t4 = x[3]; Chris@69: } else { Chris@69: t3 = x[3]; Chris@69: t4 = x[4]; Chris@69: } Chris@69: if (t0 > t3) Chris@69: { Chris@69: MSWAP(t0, t3); Chris@69: MSWAP(t1, t4); Chris@69: } Chris@69: if (t2 > t1) Chris@69: { Chris@69: if (t1 < t3) Chris@69: return MIN16(t2, t3); Chris@69: else Chris@69: return MIN16(t4, t1); Chris@69: } else { Chris@69: if (t2 < t3) Chris@69: return MIN16(t1, t3); Chris@69: else Chris@69: return MIN16(t2, t4); Chris@69: } Chris@69: } Chris@69: Chris@69: static opus_val16 median_of_3(const opus_val16 *x) Chris@69: { Chris@69: opus_val16 t0, t1, t2; Chris@69: if (x[0] > x[1]) Chris@69: { Chris@69: t0 = x[1]; Chris@69: t1 = x[0]; Chris@69: } else { Chris@69: t0 = x[0]; Chris@69: t1 = x[1]; Chris@69: } Chris@69: t2 = x[2]; Chris@69: if (t1 < t2) Chris@69: return t1; Chris@69: else if (t0 < t2) Chris@69: return t2; Chris@69: else Chris@69: return t0; Chris@69: } Chris@69: Chris@69: static opus_val16 dynalloc_analysis(const opus_val16 *bandLogE, const opus_val16 *bandLogE2, Chris@69: int nbEBands, int start, int end, int C, int *offsets, int lsb_depth, const opus_int16 *logN, Chris@69: int isTransient, int vbr, int constrained_vbr, const opus_int16 *eBands, int LM, Chris@69: int effectiveBytes, opus_int32 *tot_boost_, int lfe, opus_val16 *surround_dynalloc, Chris@69: AnalysisInfo *analysis, int *importance, int *spread_weight) Chris@69: { Chris@69: int i, c; Chris@69: opus_int32 tot_boost=0; Chris@69: opus_val16 maxDepth; Chris@69: VARDECL(opus_val16, follower); Chris@69: VARDECL(opus_val16, noise_floor); Chris@69: SAVE_STACK; Chris@69: ALLOC(follower, C*nbEBands, opus_val16); Chris@69: ALLOC(noise_floor, C*nbEBands, opus_val16); Chris@69: OPUS_CLEAR(offsets, nbEBands); Chris@69: /* Dynamic allocation code */ Chris@69: maxDepth=-QCONST16(31.9f, DB_SHIFT); Chris@69: for (i=0;i=0;i--) Chris@69: mask[i] = MAX16(mask[i], mask[i+1] - QCONST16(3.f, DB_SHIFT)); Chris@69: for (i=0;i> shift; Chris@69: } Chris@69: /*for (i=0;i 50 && LM>=1 && !lfe) Chris@69: { Chris@69: int last=0; Chris@69: c=0;do Chris@69: { Chris@69: opus_val16 offset; Chris@69: opus_val16 tmp; Chris@69: opus_val16 *f; Chris@69: f = &follower[c*nbEBands]; Chris@69: f[0] = bandLogE2[c*nbEBands]; Chris@69: for (i=1;i bandLogE2[c*nbEBands+i-1]+QCONST16(.5f,DB_SHIFT)) Chris@69: last=i; Chris@69: f[i] = MIN16(f[i-1]+QCONST16(1.5f,DB_SHIFT), bandLogE2[c*nbEBands+i]); Chris@69: } Chris@69: for (i=last-1;i>=0;i--) Chris@69: f[i] = MIN16(f[i], MIN16(f[i+1]+QCONST16(2.f,DB_SHIFT), bandLogE2[c*nbEBands+i])); Chris@69: Chris@69: /* Combine with a median filter to avoid dynalloc triggering unnecessarily. Chris@69: The "offset" value controls how conservative we are -- a higher offset Chris@69: reduces the impact of the median filter and makes dynalloc use more bits. */ Chris@69: offset = QCONST16(1.f, DB_SHIFT); Chris@69: for (i=2;i=12) Chris@69: follower[i] = HALF16(follower[i]); Chris@69: } Chris@69: #ifdef DISABLE_FLOAT_API Chris@69: (void)analysis; Chris@69: #else Chris@69: if (analysis->valid) Chris@69: { Chris@69: for (i=start;ileak_boost[i]; Chris@69: } Chris@69: #endif Chris@69: for (i=start;i 48) { Chris@69: boost = (int)SHR32(EXTEND32(follower[i])*8,DB_SHIFT); Chris@69: boost_bits = (boost*width<>BITRES>>3 > 2*effectiveBytes/3) Chris@69: { Chris@69: opus_int32 cap = ((2*effectiveBytes/3)<mode; Chris@69: overlap = mode->overlap; Chris@69: ALLOC(_pre, CC*(N+COMBFILTER_MAXPERIOD), celt_sig); Chris@69: Chris@69: pre[0] = _pre; Chris@69: pre[1] = _pre + (N+COMBFILTER_MAXPERIOD); Chris@69: Chris@69: Chris@69: c=0; do { Chris@69: OPUS_COPY(pre[c], prefilter_mem+c*COMBFILTER_MAXPERIOD, COMBFILTER_MAXPERIOD); Chris@69: OPUS_COPY(pre[c]+COMBFILTER_MAXPERIOD, in+c*(N+overlap)+overlap, N); Chris@69: } while (++c>1, opus_val16); Chris@69: Chris@69: pitch_downsample(pre, pitch_buf, COMBFILTER_MAXPERIOD+N, CC, st->arch); Chris@69: /* Don't search for the fir last 1.5 octave of the range because Chris@69: there's too many false-positives due to short-term correlation */ Chris@69: pitch_search(pitch_buf+(COMBFILTER_MAXPERIOD>>1), pitch_buf, N, Chris@69: COMBFILTER_MAXPERIOD-3*COMBFILTER_MINPERIOD, &pitch_index, Chris@69: st->arch); Chris@69: pitch_index = COMBFILTER_MAXPERIOD-pitch_index; Chris@69: Chris@69: gain1 = remove_doubling(pitch_buf, COMBFILTER_MAXPERIOD, COMBFILTER_MINPERIOD, Chris@69: N, &pitch_index, st->prefilter_period, st->prefilter_gain, st->arch); Chris@69: if (pitch_index > COMBFILTER_MAXPERIOD-2) Chris@69: pitch_index = COMBFILTER_MAXPERIOD-2; Chris@69: gain1 = MULT16_16_Q15(QCONST16(.7f,15),gain1); Chris@69: /*printf("%d %d %f %f\n", pitch_change, pitch_index, gain1, st->analysis.tonality);*/ Chris@69: if (st->loss_rate>2) Chris@69: gain1 = HALF32(gain1); Chris@69: if (st->loss_rate>4) Chris@69: gain1 = HALF32(gain1); Chris@69: if (st->loss_rate>8) Chris@69: gain1 = 0; Chris@69: } else { Chris@69: gain1 = 0; Chris@69: pitch_index = COMBFILTER_MINPERIOD; Chris@69: } Chris@69: #ifndef DISABLE_FLOAT_API Chris@69: if (analysis->valid) Chris@69: gain1 = (opus_val16)(gain1 * analysis->max_pitch_ratio); Chris@69: #else Chris@69: (void)analysis; Chris@69: #endif Chris@69: /* Gain threshold for enabling the prefilter/postfilter */ Chris@69: pf_threshold = QCONST16(.2f,15); Chris@69: Chris@69: /* Adjusting the threshold based on rate and continuity */ Chris@69: if (abs(pitch_index-st->prefilter_period)*10>pitch_index) Chris@69: pf_threshold += QCONST16(.2f,15); Chris@69: if (nbAvailableBytes<25) Chris@69: pf_threshold += QCONST16(.1f,15); Chris@69: if (nbAvailableBytes<35) Chris@69: pf_threshold += QCONST16(.1f,15); Chris@69: if (st->prefilter_gain > QCONST16(.4f,15)) Chris@69: pf_threshold -= QCONST16(.1f,15); Chris@69: if (st->prefilter_gain > QCONST16(.55f,15)) Chris@69: pf_threshold -= QCONST16(.1f,15); Chris@69: Chris@69: /* Hard threshold at 0.2 */ Chris@69: pf_threshold = MAX16(pf_threshold, QCONST16(.2f,15)); Chris@69: if (gain1prefilter_gain)prefilter_gain; Chris@69: Chris@69: #ifdef FIXED_POINT Chris@69: qg = ((gain1+1536)>>10)/3-1; Chris@69: #else Chris@69: qg = (int)floor(.5f+gain1*32/3)-1; Chris@69: #endif Chris@69: qg = IMAX(0, IMIN(7, qg)); Chris@69: gain1 = QCONST16(0.09375f,15)*(qg+1); Chris@69: pf_on = 1; Chris@69: } Chris@69: /*printf("%d %f\n", pitch_index, gain1);*/ Chris@69: Chris@69: c=0; do { Chris@69: int offset = mode->shortMdctSize-overlap; Chris@69: st->prefilter_period=IMAX(st->prefilter_period, COMBFILTER_MINPERIOD); Chris@69: OPUS_COPY(in+c*(N+overlap), st->in_mem+c*(overlap), overlap); Chris@69: if (offset) Chris@69: comb_filter(in+c*(N+overlap)+overlap, pre[c]+COMBFILTER_MAXPERIOD, Chris@69: st->prefilter_period, st->prefilter_period, offset, -st->prefilter_gain, -st->prefilter_gain, Chris@69: st->prefilter_tapset, st->prefilter_tapset, NULL, 0, st->arch); Chris@69: Chris@69: comb_filter(in+c*(N+overlap)+overlap+offset, pre[c]+COMBFILTER_MAXPERIOD+offset, Chris@69: st->prefilter_period, pitch_index, N-offset, -st->prefilter_gain, -gain1, Chris@69: st->prefilter_tapset, prefilter_tapset, mode->window, overlap, st->arch); Chris@69: OPUS_COPY(st->in_mem+c*(overlap), in+c*(N+overlap)+N, overlap); Chris@69: Chris@69: if (N>COMBFILTER_MAXPERIOD) Chris@69: { Chris@69: OPUS_COPY(prefilter_mem+c*COMBFILTER_MAXPERIOD, pre[c]+N, COMBFILTER_MAXPERIOD); Chris@69: } else { Chris@69: OPUS_MOVE(prefilter_mem+c*COMBFILTER_MAXPERIOD, prefilter_mem+c*COMBFILTER_MAXPERIOD+N, COMBFILTER_MAXPERIOD-N); Chris@69: OPUS_COPY(prefilter_mem+c*COMBFILTER_MAXPERIOD+COMBFILTER_MAXPERIOD-N, pre[c]+COMBFILTER_MAXPERIOD, N); Chris@69: } Chris@69: } while (++cnbEBands; Chris@69: eBands = mode->eBands; Chris@69: Chris@69: coded_bands = lastCodedBands ? lastCodedBands : nbEBands; Chris@69: coded_bins = eBands[coded_bands]<analysis.activity, st->analysis.tonality, tf_estimate, st->stereo_saving, tot_boost, coded_bands);*/ Chris@69: #ifndef DISABLE_FLOAT_API Chris@69: if (analysis->valid && analysis->activity<.4) Chris@69: target -= (opus_int32)((coded_bins<activity)); Chris@69: #endif Chris@69: /* Stereo savings */ Chris@69: if (C==2) Chris@69: { Chris@69: int coded_stereo_bands; Chris@69: int coded_stereo_dof; Chris@69: opus_val16 max_frac; Chris@69: coded_stereo_bands = IMIN(intensity, coded_bands); Chris@69: coded_stereo_dof = (eBands[coded_stereo_bands]<valid && !lfe) Chris@69: { Chris@69: opus_int32 tonal_target; Chris@69: float tonal; Chris@69: Chris@69: /* Tonality boost (compensating for the average). */ Chris@69: tonal = MAX16(0.f,analysis->tonality-.15f)-0.12f; Chris@69: tonal_target = target + (opus_int32)((coded_bins<tonality, tonal);*/ Chris@69: target = tonal_target; Chris@69: } Chris@69: #else Chris@69: (void)analysis; Chris@69: (void)pitch_change; Chris@69: #endif Chris@69: Chris@69: if (has_surround_mask&&!lfe) Chris@69: { Chris@69: opus_int32 surround_target = target + (opus_int32)SHR32(MULT16_16(surround_masking,coded_bins<end, st->intensity, surround_target, target, st->bitrate);*/ Chris@69: target = IMAX(target/4, surround_target); Chris@69: } Chris@69: Chris@69: { Chris@69: opus_int32 floor_depth; Chris@69: int bins; Chris@69: bins = eBands[nbEBands-2]<>2); Chris@69: target = IMIN(target, floor_depth); Chris@69: /*printf("%f %d\n", maxDepth, floor_depth);*/ Chris@69: } Chris@69: Chris@69: /* Make VBR less aggressive for constrained VBR because we can't keep a higher bitrate Chris@69: for long. Needs tuning. */ Chris@69: if ((!has_surround_mask||lfe) && constrained_vbr) Chris@69: { Chris@69: target = base_target + (opus_int32)MULT16_32_Q15(QCONST16(0.67f, 15), target-base_target); Chris@69: } Chris@69: Chris@69: if (!has_surround_mask && tf_estimate < QCONST16(.2f, 14)) Chris@69: { Chris@69: opus_val16 amount; Chris@69: opus_val16 tvbr_factor; Chris@69: amount = MULT16_16_Q15(QCONST16(.0000031f, 30), IMAX(0, IMIN(32000, 96000-bitrate))); Chris@69: tvbr_factor = SHR32(MULT16_16(temporal_vbr, amount), DB_SHIFT); Chris@69: target += (opus_int32)MULT16_32_Q15(tvbr_factor, target); Chris@69: } Chris@69: Chris@69: /* Don't allow more than doubling the rate */ Chris@69: target = IMIN(2*base_target, target); Chris@69: Chris@69: return target; Chris@69: } Chris@69: Chris@69: int celt_encode_with_ec(CELTEncoder * OPUS_RESTRICT st, const opus_val16 * pcm, int frame_size, unsigned char *compressed, int nbCompressedBytes, ec_enc *enc) Chris@69: { Chris@69: int i, c, N; Chris@69: opus_int32 bits; Chris@69: ec_enc _enc; Chris@69: VARDECL(celt_sig, in); Chris@69: VARDECL(celt_sig, freq); Chris@69: VARDECL(celt_norm, X); Chris@69: VARDECL(celt_ener, bandE); Chris@69: VARDECL(opus_val16, bandLogE); Chris@69: VARDECL(opus_val16, bandLogE2); Chris@69: VARDECL(int, fine_quant); Chris@69: VARDECL(opus_val16, error); Chris@69: VARDECL(int, pulses); Chris@69: VARDECL(int, cap); Chris@69: VARDECL(int, offsets); Chris@69: VARDECL(int, importance); Chris@69: VARDECL(int, spread_weight); Chris@69: VARDECL(int, fine_priority); Chris@69: VARDECL(int, tf_res); Chris@69: VARDECL(unsigned char, collapse_masks); Chris@69: celt_sig *prefilter_mem; Chris@69: opus_val16 *oldBandE, *oldLogE, *oldLogE2, *energyError; Chris@69: int shortBlocks=0; Chris@69: int isTransient=0; Chris@69: const int CC = st->channels; Chris@69: const int C = st->stream_channels; Chris@69: int LM, M; Chris@69: int tf_select; Chris@69: int nbFilledBytes, nbAvailableBytes; Chris@69: int start; Chris@69: int end; Chris@69: int effEnd; Chris@69: int codedBands; Chris@69: int alloc_trim; Chris@69: int pitch_index=COMBFILTER_MINPERIOD; Chris@69: opus_val16 gain1 = 0; Chris@69: int dual_stereo=0; Chris@69: int effectiveBytes; Chris@69: int dynalloc_logp; Chris@69: opus_int32 vbr_rate; Chris@69: opus_int32 total_bits; Chris@69: opus_int32 total_boost; Chris@69: opus_int32 balance; Chris@69: opus_int32 tell; Chris@69: opus_int32 tell0_frac; Chris@69: int prefilter_tapset=0; Chris@69: int pf_on; Chris@69: int anti_collapse_rsv; Chris@69: int anti_collapse_on=0; Chris@69: int silence=0; Chris@69: int tf_chan = 0; Chris@69: opus_val16 tf_estimate; Chris@69: int pitch_change=0; Chris@69: opus_int32 tot_boost; Chris@69: opus_val32 sample_max; Chris@69: opus_val16 maxDepth; Chris@69: const OpusCustomMode *mode; Chris@69: int nbEBands; Chris@69: int overlap; Chris@69: const opus_int16 *eBands; Chris@69: int secondMdct; Chris@69: int signalBandwidth; Chris@69: int transient_got_disabled=0; Chris@69: opus_val16 surround_masking=0; Chris@69: opus_val16 temporal_vbr=0; Chris@69: opus_val16 surround_trim = 0; Chris@69: opus_int32 equiv_rate; Chris@69: int hybrid; Chris@69: int weak_transient = 0; Chris@69: int enable_tf_analysis; Chris@69: VARDECL(opus_val16, surround_dynalloc); Chris@69: ALLOC_STACK; Chris@69: Chris@69: mode = st->mode; Chris@69: nbEBands = mode->nbEBands; Chris@69: overlap = mode->overlap; Chris@69: eBands = mode->eBands; Chris@69: start = st->start; Chris@69: end = st->end; Chris@69: hybrid = start != 0; Chris@69: tf_estimate = 0; Chris@69: if (nbCompressedBytes<2 || pcm==NULL) Chris@69: { Chris@69: RESTORE_STACK; Chris@69: return OPUS_BAD_ARG; Chris@69: } Chris@69: Chris@69: frame_size *= st->upsample; Chris@69: for (LM=0;LM<=mode->maxLM;LM++) Chris@69: if (mode->shortMdctSize<mode->maxLM) Chris@69: { Chris@69: RESTORE_STACK; Chris@69: return OPUS_BAD_ARG; Chris@69: } Chris@69: M=1<shortMdctSize; Chris@69: Chris@69: prefilter_mem = st->in_mem+CC*(overlap); Chris@69: oldBandE = (opus_val16*)(st->in_mem+CC*(overlap+COMBFILTER_MAXPERIOD)); Chris@69: oldLogE = oldBandE + CC*nbEBands; Chris@69: oldLogE2 = oldLogE + CC*nbEBands; Chris@69: energyError = oldLogE2 + CC*nbEBands; Chris@69: Chris@69: if (enc==NULL) Chris@69: { Chris@69: tell0_frac=tell=1; Chris@69: nbFilledBytes=0; Chris@69: } else { Chris@69: tell0_frac=ec_tell_frac(enc); Chris@69: tell=ec_tell(enc); Chris@69: nbFilledBytes=(tell+4)>>3; Chris@69: } Chris@69: Chris@69: #ifdef CUSTOM_MODES Chris@69: if (st->signalling && enc==NULL) Chris@69: { Chris@69: int tmp = (mode->effEBands-end)>>1; Chris@69: end = st->end = IMAX(1, mode->effEBands-tmp); Chris@69: compressed[0] = tmp<<5; Chris@69: compressed[0] |= LM<<3; Chris@69: compressed[0] |= (C==2)<<2; Chris@69: /* Convert "standard mode" to Opus header */ Chris@69: if (mode->Fs==48000 && mode->shortMdctSize==120) Chris@69: { Chris@69: int c0 = toOpus(compressed[0]); Chris@69: if (c0<0) Chris@69: { Chris@69: RESTORE_STACK; Chris@69: return OPUS_BAD_ARG; Chris@69: } Chris@69: compressed[0] = c0; Chris@69: } Chris@69: compressed++; Chris@69: nbCompressedBytes--; Chris@69: } Chris@69: #else Chris@69: celt_assert(st->signalling==0); Chris@69: #endif Chris@69: Chris@69: /* Can't produce more than 1275 output bytes */ Chris@69: nbCompressedBytes = IMIN(nbCompressedBytes,1275); Chris@69: nbAvailableBytes = nbCompressedBytes - nbFilledBytes; Chris@69: Chris@69: if (st->vbr && st->bitrate!=OPUS_BITRATE_MAX) Chris@69: { Chris@69: opus_int32 den=mode->Fs>>BITRES; Chris@69: vbr_rate=(st->bitrate*frame_size+(den>>1))/den; Chris@69: #ifdef CUSTOM_MODES Chris@69: if (st->signalling) Chris@69: vbr_rate -= 8<>(3+BITRES); Chris@69: } else { Chris@69: opus_int32 tmp; Chris@69: vbr_rate = 0; Chris@69: tmp = st->bitrate*frame_size; Chris@69: if (tell>1) Chris@69: tmp += tell; Chris@69: if (st->bitrate!=OPUS_BITRATE_MAX) Chris@69: nbCompressedBytes = IMAX(2, IMIN(nbCompressedBytes, Chris@69: (tmp+4*mode->Fs)/(8*mode->Fs)-!!st->signalling)); Chris@69: effectiveBytes = nbCompressedBytes - nbFilledBytes; Chris@69: } Chris@69: equiv_rate = ((opus_int32)nbCompressedBytes*8*50 >> (3-LM)) - (40*C+20)*((400>>LM) - 50); Chris@69: if (st->bitrate != OPUS_BITRATE_MAX) Chris@69: equiv_rate = IMIN(equiv_rate, st->bitrate - (40*C+20)*((400>>LM) - 50)); Chris@69: Chris@69: if (enc==NULL) Chris@69: { Chris@69: ec_enc_init(&_enc, compressed, nbCompressedBytes); Chris@69: enc = &_enc; Chris@69: } Chris@69: Chris@69: if (vbr_rate>0) Chris@69: { Chris@69: /* Computes the max bit-rate allowed in VBR mode to avoid violating the Chris@69: target rate and buffering. Chris@69: We must do this up front so that bust-prevention logic triggers Chris@69: correctly if we don't have enough bits. */ Chris@69: if (st->constrained_vbr) Chris@69: { Chris@69: opus_int32 vbr_bound; Chris@69: opus_int32 max_allowed; Chris@69: /* We could use any multiple of vbr_rate as bound (depending on the Chris@69: delay). Chris@69: This is clamped to ensure we use at least two bytes if the encoder Chris@69: was entirely empty, but to allow 0 in hybrid mode. */ Chris@69: vbr_bound = vbr_rate; Chris@69: max_allowed = IMIN(IMAX(tell==1?2:0, Chris@69: (vbr_rate+vbr_bound-st->vbr_reservoir)>>(BITRES+3)), Chris@69: nbAvailableBytes); Chris@69: if(max_allowed < nbAvailableBytes) Chris@69: { Chris@69: nbCompressedBytes = nbFilledBytes+max_allowed; Chris@69: nbAvailableBytes = max_allowed; Chris@69: ec_enc_shrink(enc, nbCompressedBytes); Chris@69: } Chris@69: } Chris@69: } Chris@69: total_bits = nbCompressedBytes*8; Chris@69: Chris@69: effEnd = end; Chris@69: if (effEnd > mode->effEBands) Chris@69: effEnd = mode->effEBands; Chris@69: Chris@69: ALLOC(in, CC*(N+overlap), celt_sig); Chris@69: Chris@69: sample_max=MAX32(st->overlap_max, celt_maxabs16(pcm, C*(N-overlap)/st->upsample)); Chris@69: st->overlap_max=celt_maxabs16(pcm+C*(N-overlap)/st->upsample, C*overlap/st->upsample); Chris@69: sample_max=MAX32(sample_max, st->overlap_max); Chris@69: #ifdef FIXED_POINT Chris@69: silence = (sample_max==0); Chris@69: #else Chris@69: silence = (sample_max <= (opus_val16)1/(1<lsb_depth)); Chris@69: #endif Chris@69: #ifdef FUZZING Chris@69: if ((rand()&0x3F)==0) Chris@69: silence = 1; Chris@69: #endif Chris@69: if (tell==1) Chris@69: ec_enc_bit_logp(enc, silence, 15); Chris@69: else Chris@69: silence=0; Chris@69: if (silence) Chris@69: { Chris@69: /*In VBR mode there is no need to send more than the minimum. */ Chris@69: if (vbr_rate>0) Chris@69: { Chris@69: effectiveBytes=nbCompressedBytes=IMIN(nbCompressedBytes, nbFilledBytes+2); Chris@69: total_bits=nbCompressedBytes*8; Chris@69: nbAvailableBytes=2; Chris@69: ec_enc_shrink(enc, nbCompressedBytes); Chris@69: } Chris@69: /* Pretend we've filled all the remaining bits with zeros Chris@69: (that's what the initialiser did anyway) */ Chris@69: tell = nbCompressedBytes*8; Chris@69: enc->nbits_total+=tell-ec_tell(enc); Chris@69: } Chris@69: c=0; do { Chris@69: int need_clip=0; Chris@69: #ifndef FIXED_POINT Chris@69: need_clip = st->clip && sample_max>65536.f; Chris@69: #endif Chris@69: celt_preemphasis(pcm+c, in+c*(N+overlap)+overlap, N, CC, st->upsample, Chris@69: mode->preemph, st->preemph_memE+c, need_clip); Chris@69: } while (++clfe&&nbAvailableBytes>3) || nbAvailableBytes>12*C) && !hybrid && !silence && !st->disable_pf Chris@69: && st->complexity >= 5; Chris@69: Chris@69: prefilter_tapset = st->tapset_decision; Chris@69: pf_on = run_prefilter(st, in, prefilter_mem, CC, N, prefilter_tapset, &pitch_index, &gain1, &qg, enabled, nbAvailableBytes, &st->analysis); Chris@69: if ((gain1 > QCONST16(.4f,15) || st->prefilter_gain > QCONST16(.4f,15)) && (!st->analysis.valid || st->analysis.tonality > .3) Chris@69: && (pitch_index > 1.26*st->prefilter_period || pitch_index < .79*st->prefilter_period)) Chris@69: pitch_change = 1; Chris@69: if (pf_on==0) Chris@69: { Chris@69: if(!hybrid && tell+16<=total_bits) Chris@69: ec_enc_bit_logp(enc, 0, 1); Chris@69: } else { Chris@69: /*This block is not gated by a total bits check only because Chris@69: of the nbAvailableBytes check above.*/ Chris@69: int octave; Chris@69: ec_enc_bit_logp(enc, 1, 1); Chris@69: pitch_index += 1; Chris@69: octave = EC_ILOG(pitch_index)-5; Chris@69: ec_enc_uint(enc, octave, 6); Chris@69: ec_enc_bits(enc, pitch_index-(16<complexity >= 1 && !st->lfe) Chris@69: { Chris@69: /* Reduces the likelihood of energy instability on fricatives at low bitrate Chris@69: in hybrid mode. It seems like we still want to have real transients on vowels Chris@69: though (small SILK quantization offset value). */ Chris@69: int allow_weak_transients = hybrid && effectiveBytes<15 && st->silk_info.signalType != 2; Chris@69: isTransient = transient_analysis(in, N+overlap, CC, Chris@69: &tf_estimate, &tf_chan, allow_weak_transients, &weak_transient); Chris@69: } Chris@69: if (LM>0 && ec_tell(enc)+3<=total_bits) Chris@69: { Chris@69: if (isTransient) Chris@69: shortBlocks = M; Chris@69: } else { Chris@69: isTransient = 0; Chris@69: transient_got_disabled=1; Chris@69: } Chris@69: Chris@69: ALLOC(freq, CC*N, celt_sig); /**< Interleaved signal MDCTs */ Chris@69: ALLOC(bandE,nbEBands*CC, celt_ener); Chris@69: ALLOC(bandLogE,nbEBands*CC, opus_val16); Chris@69: Chris@69: secondMdct = shortBlocks && st->complexity>=8; Chris@69: ALLOC(bandLogE2, C*nbEBands, opus_val16); Chris@69: if (secondMdct) Chris@69: { Chris@69: compute_mdcts(mode, 0, in, freq, C, CC, LM, st->upsample, st->arch); Chris@69: compute_band_energies(mode, freq, bandE, effEnd, C, LM, st->arch); Chris@69: amp2Log2(mode, effEnd, end, bandE, bandLogE2, C); Chris@69: for (i=0;iupsample, st->arch); Chris@69: /* This should catch any NaN in the CELT input. Since we're not supposed to see any (they're filtered Chris@69: at the Opus layer), just abort. */ Chris@69: celt_assert(!celt_isnan(freq[0]) && (C==1 || !celt_isnan(freq[N]))); Chris@69: if (CC==2&&C==1) Chris@69: tf_chan = 0; Chris@69: compute_band_energies(mode, freq, bandE, effEnd, C, LM, st->arch); Chris@69: Chris@69: if (st->lfe) Chris@69: { Chris@69: for (i=2;ienergy_mask&&!st->lfe) Chris@69: { Chris@69: int mask_end; Chris@69: int midband; Chris@69: int count_dynalloc; Chris@69: opus_val32 mask_avg=0; Chris@69: opus_val32 diff=0; Chris@69: int count=0; Chris@69: mask_end = IMAX(2,st->lastCodedBands); Chris@69: for (c=0;cenergy_mask[nbEBands*c+i], Chris@69: QCONST16(.25f, DB_SHIFT)), -QCONST16(2.0f, DB_SHIFT)); Chris@69: if (mask > 0) Chris@69: mask = HALF16(mask); Chris@69: mask_avg += MULT16_16(mask, eBands[i+1]-eBands[i]); Chris@69: count += eBands[i+1]-eBands[i]; Chris@69: diff += MULT16_16(mask, 1+2*i-mask_end); Chris@69: } Chris@69: } Chris@69: celt_assert(count>0); Chris@69: mask_avg = DIV32_16(mask_avg,count); Chris@69: mask_avg += QCONST16(.2f, DB_SHIFT); Chris@69: diff = diff*6/(C*(mask_end-1)*(mask_end+1)*mask_end); Chris@69: /* Again, being conservative */ Chris@69: diff = HALF32(diff); Chris@69: diff = MAX32(MIN32(diff, QCONST32(.031f, DB_SHIFT)), -QCONST32(.031f, DB_SHIFT)); Chris@69: /* Find the band that's in the middle of the coded spectrum */ Chris@69: for (midband=0;eBands[midband+1] < eBands[mask_end]/2;midband++); Chris@69: count_dynalloc=0; Chris@69: for(i=0;ienergy_mask[i], st->energy_mask[nbEBands+i]); Chris@69: else Chris@69: unmask = st->energy_mask[i]; Chris@69: unmask = MIN16(unmask, QCONST16(.0f, DB_SHIFT)); Chris@69: unmask -= lin; Chris@69: if (unmask > QCONST16(.25f, DB_SHIFT)) Chris@69: { Chris@69: surround_dynalloc[i] = unmask - QCONST16(.25f, DB_SHIFT); Chris@69: count_dynalloc++; Chris@69: } Chris@69: } Chris@69: if (count_dynalloc>=3) Chris@69: { Chris@69: /* If we need dynalloc in many bands, it's probably because our Chris@69: initial masking rate was too low. */ Chris@69: mask_avg += QCONST16(.25f, DB_SHIFT); Chris@69: if (mask_avg>0) Chris@69: { Chris@69: /* Something went really wrong in the original calculations, Chris@69: disabling masking. */ Chris@69: mask_avg = 0; Chris@69: diff = 0; Chris@69: OPUS_CLEAR(surround_dynalloc, mask_end); Chris@69: } else { Chris@69: for(i=0;ilfe) Chris@69: { Chris@69: opus_val16 follow=-QCONST16(10.0f,DB_SHIFT); Chris@69: opus_val32 frame_avg=0; Chris@69: opus_val16 offset = shortBlocks?HALF16(SHL16(LM, DB_SHIFT)):0; Chris@69: for(i=start;ispec_avg); Chris@69: temporal_vbr = MIN16(QCONST16(3.f, DB_SHIFT), MAX16(-QCONST16(1.5f, DB_SHIFT), temporal_vbr)); Chris@69: st->spec_avg += MULT16_16_Q15(QCONST16(.02f, 15), temporal_vbr); Chris@69: } Chris@69: /*for (i=0;i<21;i++) Chris@69: printf("%f ", bandLogE[i]); Chris@69: printf("\n");*/ Chris@69: Chris@69: if (!secondMdct) Chris@69: { Chris@69: OPUS_COPY(bandLogE2, bandLogE, C*nbEBands); Chris@69: } Chris@69: Chris@69: /* Last chance to catch any transient we might have missed in the Chris@69: time-domain analysis */ Chris@69: if (LM>0 && ec_tell(enc)+3<=total_bits && !isTransient && st->complexity>=5 && !st->lfe && !hybrid) Chris@69: { Chris@69: if (patch_transient_decision(bandLogE, oldBandE, nbEBands, start, end, C)) Chris@69: { Chris@69: isTransient = 1; Chris@69: shortBlocks = M; Chris@69: compute_mdcts(mode, shortBlocks, in, freq, C, CC, LM, st->upsample, st->arch); Chris@69: compute_band_energies(mode, freq, bandE, effEnd, C, LM, st->arch); Chris@69: amp2Log2(mode, effEnd, end, bandE, bandLogE, C); Chris@69: /* Compensate for the scaling of short vs long mdcts */ Chris@69: for (i=0;i0 && ec_tell(enc)+3<=total_bits) Chris@69: ec_enc_bit_logp(enc, isTransient, 3); Chris@69: Chris@69: ALLOC(X, C*N, celt_norm); /**< Interleaved normalised MDCTs */ Chris@69: Chris@69: /* Band normalisation */ Chris@69: normalise_bands(mode, freq, X, bandE, effEnd, C, M); Chris@69: Chris@69: enable_tf_analysis = effectiveBytes>=15*C && !hybrid && st->complexity>=2 && !st->lfe; Chris@69: Chris@69: ALLOC(offsets, nbEBands, int); Chris@69: ALLOC(importance, nbEBands, int); Chris@69: ALLOC(spread_weight, nbEBands, int); Chris@69: Chris@69: maxDepth = dynalloc_analysis(bandLogE, bandLogE2, nbEBands, start, end, C, offsets, Chris@69: st->lsb_depth, mode->logN, isTransient, st->vbr, st->constrained_vbr, Chris@69: eBands, LM, effectiveBytes, &tot_boost, st->lfe, surround_dynalloc, &st->analysis, importance, spread_weight); Chris@69: Chris@69: ALLOC(tf_res, nbEBands, int); Chris@69: /* Disable variable tf resolution for hybrid and at very low bitrate */ Chris@69: if (enable_tf_analysis) Chris@69: { Chris@69: int lambda; Chris@69: lambda = IMAX(80, 20480/effectiveBytes + 2); Chris@69: tf_select = tf_analysis(mode, effEnd, isTransient, tf_res, lambda, X, N, LM, tf_estimate, tf_chan, importance); Chris@69: for (i=effEnd;isilk_info.signalType != 2) Chris@69: { Chris@69: /* For low bitrate hybrid, we force temporal resolution to 5 ms rather than 2.5 ms. */ Chris@69: for (i=0;iforce_intra, Chris@69: &st->delayedIntra, st->complexity >= 4, st->loss_rate, st->lfe); Chris@69: Chris@69: tf_encode(start, end, isTransient, tf_res, LM, tf_select, enc); Chris@69: Chris@69: if (ec_tell(enc)+4<=total_bits) Chris@69: { Chris@69: if (st->lfe) Chris@69: { Chris@69: st->tapset_decision = 0; Chris@69: st->spread_decision = SPREAD_NORMAL; Chris@69: } else if (hybrid) Chris@69: { Chris@69: if (st->complexity == 0) Chris@69: st->spread_decision = SPREAD_NONE; Chris@69: else if (isTransient) Chris@69: st->spread_decision = SPREAD_NORMAL; Chris@69: else Chris@69: st->spread_decision = SPREAD_AGGRESSIVE; Chris@69: } else if (shortBlocks || st->complexity < 3 || nbAvailableBytes < 10*C) Chris@69: { Chris@69: if (st->complexity == 0) Chris@69: st->spread_decision = SPREAD_NONE; Chris@69: else Chris@69: st->spread_decision = SPREAD_NORMAL; Chris@69: } else { Chris@69: /* Disable new spreading+tapset estimator until we can show it works Chris@69: better than the old one. So far it seems like spreading_decision() Chris@69: works best. */ Chris@69: #if 0 Chris@69: if (st->analysis.valid) Chris@69: { Chris@69: static const opus_val16 spread_thresholds[3] = {-QCONST16(.6f, 15), -QCONST16(.2f, 15), -QCONST16(.07f, 15)}; Chris@69: static const opus_val16 spread_histeresis[3] = {QCONST16(.15f, 15), QCONST16(.07f, 15), QCONST16(.02f, 15)}; Chris@69: static const opus_val16 tapset_thresholds[2] = {QCONST16(.0f, 15), QCONST16(.15f, 15)}; Chris@69: static const opus_val16 tapset_histeresis[2] = {QCONST16(.1f, 15), QCONST16(.05f, 15)}; Chris@69: st->spread_decision = hysteresis_decision(-st->analysis.tonality, spread_thresholds, spread_histeresis, 3, st->spread_decision); Chris@69: st->tapset_decision = hysteresis_decision(st->analysis.tonality_slope, tapset_thresholds, tapset_histeresis, 2, st->tapset_decision); Chris@69: } else Chris@69: #endif Chris@69: { Chris@69: st->spread_decision = spreading_decision(mode, X, Chris@69: &st->tonal_average, st->spread_decision, &st->hf_average, Chris@69: &st->tapset_decision, pf_on&&!shortBlocks, effEnd, C, M, spread_weight); Chris@69: } Chris@69: /*printf("%d %d\n", st->tapset_decision, st->spread_decision);*/ Chris@69: /*printf("%f %d %f %d\n\n", st->analysis.tonality, st->spread_decision, st->analysis.tonality_slope, st->tapset_decision);*/ Chris@69: } Chris@69: ec_enc_icdf(enc, st->spread_decision, spread_icdf, 5); Chris@69: } Chris@69: Chris@69: /* For LFE, everything interesting is in the first band */ Chris@69: if (st->lfe) Chris@69: offsets[0] = IMIN(8, effectiveBytes/3); Chris@69: ALLOC(cap, nbEBands, int); Chris@69: init_caps(mode,cap,LM,C); Chris@69: Chris@69: dynalloc_logp = 6; Chris@69: total_bits<<=BITRES; Chris@69: total_boost = 0; Chris@69: tell = ec_tell_frac(enc); Chris@69: for (i=start;iintensity = hysteresis_decision((opus_val16)(equiv_rate/1000), Chris@69: intensity_thresholds, intensity_histeresis, 21, st->intensity); Chris@69: st->intensity = IMIN(end,IMAX(start, st->intensity)); Chris@69: } Chris@69: Chris@69: alloc_trim = 5; Chris@69: if (tell+(6< 0 || st->lfe) Chris@69: { Chris@69: st->stereo_saving = 0; Chris@69: alloc_trim = 5; Chris@69: } else { Chris@69: alloc_trim = alloc_trim_analysis(mode, X, bandLogE, Chris@69: end, LM, C, N, &st->analysis, &st->stereo_saving, tf_estimate, Chris@69: st->intensity, surround_trim, equiv_rate, st->arch); Chris@69: } Chris@69: ec_enc_icdf(enc, alloc_trim, trim_icdf, 7); Chris@69: tell = ec_tell_frac(enc); Chris@69: } Chris@69: Chris@69: /* Variable bitrate */ Chris@69: if (vbr_rate>0) Chris@69: { Chris@69: opus_val16 alpha; Chris@69: opus_int32 delta; Chris@69: /* The target rate in 8th bits per frame */ Chris@69: opus_int32 target, base_target; Chris@69: opus_int32 min_allowed; Chris@69: int lm_diff = mode->maxLM - LM; Chris@69: Chris@69: /* Don't attempt to use more than 510 kb/s, even for frames smaller than 20 ms. Chris@69: The CELT allocator will just not be able to use more than that anyway. */ Chris@69: nbCompressedBytes = IMIN(nbCompressedBytes,1275>>(3-LM)); Chris@69: if (!hybrid) Chris@69: { Chris@69: base_target = vbr_rate - ((40*C+20)<constrained_vbr) Chris@69: base_target += (st->vbr_offset>>lm_diff); Chris@69: Chris@69: if (!hybrid) Chris@69: { Chris@69: target = compute_vbr(mode, &st->analysis, base_target, LM, equiv_rate, Chris@69: st->lastCodedBands, C, st->intensity, st->constrained_vbr, Chris@69: st->stereo_saving, tot_boost, tf_estimate, pitch_change, maxDepth, Chris@69: st->lfe, st->energy_mask!=NULL, surround_masking, Chris@69: temporal_vbr); Chris@69: } else { Chris@69: target = base_target; Chris@69: /* Tonal frames (offset<100) need more bits than noisy (offset>100) ones. */ Chris@69: if (st->silk_info.offset < 100) target += 12 << BITRES >> (3-LM); Chris@69: if (st->silk_info.offset > 100) target -= 18 << BITRES >> (3-LM); Chris@69: /* Boosting bitrate on transients and vowels with significant temporal Chris@69: spikes. */ Chris@69: target += (opus_int32)MULT16_16_Q14(tf_estimate-QCONST16(.25f,14), (50< QCONST16(.7f,14)) Chris@69: target = IMAX(target, 50<>(BITRES+3)) + 2; Chris@69: /* Take into account the 37 bits we need to have left in the packet to Chris@69: signal a redundant frame in hybrid mode. Creating a shorter packet would Chris@69: create an entropy coder desync. */ Chris@69: if (hybrid) Chris@69: min_allowed = IMAX(min_allowed, (tell0_frac+(37<>(BITRES+3)); Chris@69: Chris@69: nbAvailableBytes = (target+(1<<(BITRES+2)))>>(BITRES+3); Chris@69: nbAvailableBytes = IMAX(min_allowed,nbAvailableBytes); Chris@69: nbAvailableBytes = IMIN(nbCompressedBytes,nbAvailableBytes); Chris@69: Chris@69: /* By how much did we "miss" the target on that frame */ Chris@69: delta = target - vbr_rate; Chris@69: Chris@69: target=nbAvailableBytes<<(BITRES+3); Chris@69: Chris@69: /*If the frame is silent we don't adjust our drift, otherwise Chris@69: the encoder will shoot to very high rates after hitting a Chris@69: span of silence, but we do allow the bitres to refill. Chris@69: This means that we'll undershoot our target in CVBR/VBR modes Chris@69: on files with lots of silence. */ Chris@69: if(silence) Chris@69: { Chris@69: nbAvailableBytes = 2; Chris@69: target = 2*8<vbr_count < 970) Chris@69: { Chris@69: st->vbr_count++; Chris@69: alpha = celt_rcp(SHL32(EXTEND32(st->vbr_count+20),16)); Chris@69: } else Chris@69: alpha = QCONST16(.001f,15); Chris@69: /* How many bits have we used in excess of what we're allowed */ Chris@69: if (st->constrained_vbr) Chris@69: st->vbr_reservoir += target - vbr_rate; Chris@69: /*printf ("%d\n", st->vbr_reservoir);*/ Chris@69: Chris@69: /* Compute the offset we need to apply in order to reach the target */ Chris@69: if (st->constrained_vbr) Chris@69: { Chris@69: st->vbr_drift += (opus_int32)MULT16_32_Q15(alpha,(delta*(1<vbr_offset-st->vbr_drift); Chris@69: st->vbr_offset = -st->vbr_drift; Chris@69: } Chris@69: /*printf ("%d\n", st->vbr_drift);*/ Chris@69: Chris@69: if (st->constrained_vbr && st->vbr_reservoir < 0) Chris@69: { Chris@69: /* We're under the min value -- increase rate */ Chris@69: int adjust = (-st->vbr_reservoir)/(8<vbr_reservoir = 0; Chris@69: /*printf ("+%d\n", adjust);*/ Chris@69: } Chris@69: nbCompressedBytes = IMIN(nbCompressedBytes,nbAvailableBytes); Chris@69: /*printf("%d\n", nbCompressedBytes*50*8);*/ Chris@69: /* This moves the raw bits to take into account the new compressed size */ Chris@69: ec_enc_shrink(enc, nbCompressedBytes); Chris@69: } Chris@69: Chris@69: /* Bit allocation */ Chris@69: ALLOC(fine_quant, nbEBands, int); Chris@69: ALLOC(pulses, nbEBands, int); Chris@69: ALLOC(fine_priority, nbEBands, int); Chris@69: Chris@69: /* bits = packet size - where we are - safety*/ Chris@69: bits = (((opus_int32)nbCompressedBytes*8)<=2&&bits>=((LM+2)<analysis.valid) Chris@69: { Chris@69: int min_bandwidth; Chris@69: if (equiv_rate < (opus_int32)32000*C) Chris@69: min_bandwidth = 13; Chris@69: else if (equiv_rate < (opus_int32)48000*C) Chris@69: min_bandwidth = 16; Chris@69: else if (equiv_rate < (opus_int32)60000*C) Chris@69: min_bandwidth = 18; Chris@69: else if (equiv_rate < (opus_int32)80000*C) Chris@69: min_bandwidth = 19; Chris@69: else Chris@69: min_bandwidth = 20; Chris@69: signalBandwidth = IMAX(st->analysis.bandwidth, min_bandwidth); Chris@69: } Chris@69: #endif Chris@69: if (st->lfe) Chris@69: signalBandwidth = 1; Chris@69: codedBands = clt_compute_allocation(mode, start, end, offsets, cap, Chris@69: alloc_trim, &st->intensity, &dual_stereo, bits, &balance, pulses, Chris@69: fine_quant, fine_priority, C, LM, enc, 1, st->lastCodedBands, signalBandwidth); Chris@69: if (st->lastCodedBands) Chris@69: st->lastCodedBands = IMIN(st->lastCodedBands+1,IMAX(st->lastCodedBands-1,codedBands)); Chris@69: else Chris@69: st->lastCodedBands = codedBands; Chris@69: Chris@69: quant_fine_energy(mode, start, end, oldBandE, error, fine_quant, enc, C); Chris@69: Chris@69: /* Residual quantisation */ Chris@69: ALLOC(collapse_masks, C*nbEBands, unsigned char); Chris@69: quant_all_bands(1, mode, start, end, X, C==2 ? X+N : NULL, collapse_masks, Chris@69: bandE, pulses, shortBlocks, st->spread_decision, Chris@69: dual_stereo, st->intensity, tf_res, nbCompressedBytes*(8<rng, st->complexity, st->arch, st->disable_inv); Chris@69: Chris@69: if (anti_collapse_rsv > 0) Chris@69: { Chris@69: anti_collapse_on = st->consec_transient<2; Chris@69: #ifdef FUZZING Chris@69: anti_collapse_on = rand()&0x1; Chris@69: #endif Chris@69: ec_enc_bits(enc, anti_collapse_on, 1); Chris@69: } Chris@69: quant_energy_finalise(mode, start, end, oldBandE, error, fine_quant, fine_priority, nbCompressedBytes*8-ec_tell(enc), enc, C); Chris@69: OPUS_CLEAR(energyError, nbEBands*CC); Chris@69: c=0; Chris@69: do { Chris@69: for (i=start;irng); Chris@69: } Chris@69: Chris@69: c=0; do { Chris@69: OPUS_MOVE(st->syn_mem[c], st->syn_mem[c]+N, 2*MAX_PERIOD-N+overlap/2); Chris@69: } while (++csyn_mem[c]+2*MAX_PERIOD-N; Chris@69: } while (++cupsample, silence, st->arch); Chris@69: Chris@69: c=0; do { Chris@69: st->prefilter_period=IMAX(st->prefilter_period, COMBFILTER_MINPERIOD); Chris@69: st->prefilter_period_old=IMAX(st->prefilter_period_old, COMBFILTER_MINPERIOD); Chris@69: comb_filter(out_mem[c], out_mem[c], st->prefilter_period_old, st->prefilter_period, mode->shortMdctSize, Chris@69: st->prefilter_gain_old, st->prefilter_gain, st->prefilter_tapset_old, st->prefilter_tapset, Chris@69: mode->window, overlap); Chris@69: if (LM!=0) Chris@69: comb_filter(out_mem[c]+mode->shortMdctSize, out_mem[c]+mode->shortMdctSize, st->prefilter_period, pitch_index, N-mode->shortMdctSize, Chris@69: st->prefilter_gain, gain1, st->prefilter_tapset, prefilter_tapset, Chris@69: mode->window, overlap); Chris@69: } while (++cupsample, mode->preemph, st->preemph_memD); Chris@69: st->prefilter_period_old = st->prefilter_period; Chris@69: st->prefilter_gain_old = st->prefilter_gain; Chris@69: st->prefilter_tapset_old = st->prefilter_tapset; Chris@69: } Chris@69: #endif Chris@69: Chris@69: st->prefilter_period = pitch_index; Chris@69: st->prefilter_gain = gain1; Chris@69: st->prefilter_tapset = prefilter_tapset; Chris@69: #ifdef RESYNTH Chris@69: if (LM!=0) Chris@69: { Chris@69: st->prefilter_period_old = st->prefilter_period; Chris@69: st->prefilter_gain_old = st->prefilter_gain; Chris@69: st->prefilter_tapset_old = st->prefilter_tapset; Chris@69: } Chris@69: #endif Chris@69: Chris@69: if (CC==2&&C==1) { Chris@69: OPUS_COPY(&oldBandE[nbEBands], oldBandE, nbEBands); Chris@69: } Chris@69: Chris@69: if (!isTransient) Chris@69: { Chris@69: OPUS_COPY(oldLogE2, oldLogE, CC*nbEBands); Chris@69: OPUS_COPY(oldLogE, oldBandE, CC*nbEBands); Chris@69: } else { Chris@69: for (i=0;iconsec_transient++; Chris@69: else Chris@69: st->consec_transient=0; Chris@69: st->rng = enc->rng; Chris@69: Chris@69: /* If there's any room left (can only happen for very high rates), Chris@69: it's already filled with zeros */ Chris@69: ec_enc_done(enc); Chris@69: Chris@69: #ifdef CUSTOM_MODES Chris@69: if (st->signalling) Chris@69: nbCompressedBytes++; Chris@69: #endif Chris@69: Chris@69: RESTORE_STACK; Chris@69: if (ec_get_error(enc)) Chris@69: return OPUS_INTERNAL_ERROR; Chris@69: else Chris@69: return nbCompressedBytes; Chris@69: } Chris@69: Chris@69: Chris@69: #ifdef CUSTOM_MODES Chris@69: Chris@69: #ifdef FIXED_POINT Chris@69: int opus_custom_encode(CELTEncoder * OPUS_RESTRICT st, const opus_int16 * pcm, int frame_size, unsigned char *compressed, int nbCompressedBytes) Chris@69: { Chris@69: return celt_encode_with_ec(st, pcm, frame_size, compressed, nbCompressedBytes, NULL); Chris@69: } Chris@69: Chris@69: #ifndef DISABLE_FLOAT_API Chris@69: int opus_custom_encode_float(CELTEncoder * OPUS_RESTRICT st, const float * pcm, int frame_size, unsigned char *compressed, int nbCompressedBytes) Chris@69: { Chris@69: int j, ret, C, N; Chris@69: VARDECL(opus_int16, in); Chris@69: ALLOC_STACK; Chris@69: Chris@69: if (pcm==NULL) Chris@69: return OPUS_BAD_ARG; Chris@69: Chris@69: C = st->channels; Chris@69: N = frame_size; Chris@69: ALLOC(in, C*N, opus_int16); Chris@69: Chris@69: for (j=0;jchannels; Chris@69: N=frame_size; Chris@69: ALLOC(in, C*N, celt_sig); Chris@69: for (j=0;j10) Chris@69: goto bad_arg; Chris@69: st->complexity = value; Chris@69: } Chris@69: break; Chris@69: case CELT_SET_START_BAND_REQUEST: Chris@69: { Chris@69: opus_int32 value = va_arg(ap, opus_int32); Chris@69: if (value<0 || value>=st->mode->nbEBands) Chris@69: goto bad_arg; Chris@69: st->start = value; Chris@69: } Chris@69: break; Chris@69: case CELT_SET_END_BAND_REQUEST: Chris@69: { Chris@69: opus_int32 value = va_arg(ap, opus_int32); Chris@69: if (value<1 || value>st->mode->nbEBands) Chris@69: goto bad_arg; Chris@69: st->end = value; Chris@69: } Chris@69: break; Chris@69: case CELT_SET_PREDICTION_REQUEST: Chris@69: { Chris@69: int value = va_arg(ap, opus_int32); Chris@69: if (value<0 || value>2) Chris@69: goto bad_arg; Chris@69: st->disable_pf = value<=1; Chris@69: st->force_intra = value==0; Chris@69: } Chris@69: break; Chris@69: case OPUS_SET_PACKET_LOSS_PERC_REQUEST: Chris@69: { Chris@69: int value = va_arg(ap, opus_int32); Chris@69: if (value<0 || value>100) Chris@69: goto bad_arg; Chris@69: st->loss_rate = value; Chris@69: } Chris@69: break; Chris@69: case OPUS_SET_VBR_CONSTRAINT_REQUEST: Chris@69: { Chris@69: opus_int32 value = va_arg(ap, opus_int32); Chris@69: st->constrained_vbr = value; Chris@69: } Chris@69: break; Chris@69: case OPUS_SET_VBR_REQUEST: Chris@69: { Chris@69: opus_int32 value = va_arg(ap, opus_int32); Chris@69: st->vbr = value; Chris@69: } Chris@69: break; Chris@69: case OPUS_SET_BITRATE_REQUEST: Chris@69: { Chris@69: opus_int32 value = va_arg(ap, opus_int32); Chris@69: if (value<=500 && value!=OPUS_BITRATE_MAX) Chris@69: goto bad_arg; Chris@69: value = IMIN(value, 260000*st->channels); Chris@69: st->bitrate = value; Chris@69: } Chris@69: break; Chris@69: case CELT_SET_CHANNELS_REQUEST: Chris@69: { Chris@69: opus_int32 value = va_arg(ap, opus_int32); Chris@69: if (value<1 || value>2) Chris@69: goto bad_arg; Chris@69: st->stream_channels = value; Chris@69: } Chris@69: break; Chris@69: case OPUS_SET_LSB_DEPTH_REQUEST: Chris@69: { Chris@69: opus_int32 value = va_arg(ap, opus_int32); Chris@69: if (value<8 || value>24) Chris@69: goto bad_arg; Chris@69: st->lsb_depth=value; Chris@69: } Chris@69: break; Chris@69: case OPUS_GET_LSB_DEPTH_REQUEST: Chris@69: { Chris@69: opus_int32 *value = va_arg(ap, opus_int32*); Chris@69: *value=st->lsb_depth; Chris@69: } Chris@69: break; Chris@69: case OPUS_SET_PHASE_INVERSION_DISABLED_REQUEST: Chris@69: { Chris@69: opus_int32 value = va_arg(ap, opus_int32); Chris@69: if(value<0 || value>1) Chris@69: { Chris@69: goto bad_arg; Chris@69: } Chris@69: st->disable_inv = value; Chris@69: } Chris@69: break; Chris@69: case OPUS_GET_PHASE_INVERSION_DISABLED_REQUEST: Chris@69: { Chris@69: opus_int32 *value = va_arg(ap, opus_int32*); Chris@69: if (!value) Chris@69: { Chris@69: goto bad_arg; Chris@69: } Chris@69: *value = st->disable_inv; Chris@69: } Chris@69: break; Chris@69: case OPUS_RESET_STATE: Chris@69: { Chris@69: int i; Chris@69: opus_val16 *oldBandE, *oldLogE, *oldLogE2; Chris@69: oldBandE = (opus_val16*)(st->in_mem+st->channels*(st->mode->overlap+COMBFILTER_MAXPERIOD)); Chris@69: oldLogE = oldBandE + st->channels*st->mode->nbEBands; Chris@69: oldLogE2 = oldLogE + st->channels*st->mode->nbEBands; Chris@69: OPUS_CLEAR((char*)&st->ENCODER_RESET_START, Chris@69: opus_custom_encoder_get_size(st->mode, st->channels)- Chris@69: ((char*)&st->ENCODER_RESET_START - (char*)st)); Chris@69: for (i=0;ichannels*st->mode->nbEBands;i++) Chris@69: oldLogE[i]=oldLogE2[i]=-QCONST16(28.f,DB_SHIFT); Chris@69: st->vbr_offset = 0; Chris@69: st->delayedIntra = 1; Chris@69: st->spread_decision = SPREAD_NORMAL; Chris@69: st->tonal_average = 256; Chris@69: st->hf_average = 0; Chris@69: st->tapset_decision = 0; Chris@69: } Chris@69: break; Chris@69: #ifdef CUSTOM_MODES Chris@69: case CELT_SET_INPUT_CLIPPING_REQUEST: Chris@69: { Chris@69: opus_int32 value = va_arg(ap, opus_int32); Chris@69: st->clip = value; Chris@69: } Chris@69: break; Chris@69: #endif Chris@69: case CELT_SET_SIGNALLING_REQUEST: Chris@69: { Chris@69: opus_int32 value = va_arg(ap, opus_int32); Chris@69: st->signalling = value; Chris@69: } Chris@69: break; Chris@69: case CELT_SET_ANALYSIS_REQUEST: Chris@69: { Chris@69: AnalysisInfo *info = va_arg(ap, AnalysisInfo *); Chris@69: if (info) Chris@69: OPUS_COPY(&st->analysis, info, 1); Chris@69: } Chris@69: break; Chris@69: case CELT_SET_SILK_INFO_REQUEST: Chris@69: { Chris@69: SILKInfo *info = va_arg(ap, SILKInfo *); Chris@69: if (info) Chris@69: OPUS_COPY(&st->silk_info, info, 1); Chris@69: } Chris@69: break; Chris@69: case CELT_GET_MODE_REQUEST: Chris@69: { Chris@69: const CELTMode ** value = va_arg(ap, const CELTMode**); Chris@69: if (value==0) Chris@69: goto bad_arg; Chris@69: *value=st->mode; Chris@69: } Chris@69: break; Chris@69: case OPUS_GET_FINAL_RANGE_REQUEST: Chris@69: { Chris@69: opus_uint32 * value = va_arg(ap, opus_uint32 *); Chris@69: if (value==0) Chris@69: goto bad_arg; Chris@69: *value=st->rng; Chris@69: } Chris@69: break; Chris@69: case OPUS_SET_LFE_REQUEST: Chris@69: { Chris@69: opus_int32 value = va_arg(ap, opus_int32); Chris@69: st->lfe = value; Chris@69: } Chris@69: break; Chris@69: case OPUS_SET_ENERGY_MASK_REQUEST: Chris@69: { Chris@69: opus_val16 *value = va_arg(ap, opus_val16*); Chris@69: st->energy_mask = value; Chris@69: } Chris@69: break; Chris@69: default: Chris@69: goto bad_request; Chris@69: } Chris@69: va_end(ap); Chris@69: return OPUS_OK; Chris@69: bad_arg: Chris@69: va_end(ap); Chris@69: return OPUS_BAD_ARG; Chris@69: bad_request: Chris@69: va_end(ap); Chris@69: return OPUS_UNIMPLEMENTED; Chris@69: }