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