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