diff --git a/modules/opus/SCsub b/modules/opus/SCsub index 8af4f16a267..1db5b0987e9 100644 --- a/modules/opus/SCsub +++ b/modules/opus/SCsub @@ -20,9 +20,6 @@ if env['builtin_opus']: "opus_multistream.c", "opus_multistream_encoder.c", "opus_multistream_decoder.c", - "opus_projection_encoder.c", - "opus_projection_decoder.c", - "mapping_matrix.c", "repacketizer.c", "analysis.c", @@ -56,10 +53,9 @@ if env['builtin_opus']: "celt/vq.c", #"celt/arm/arm_celt_map.c", #"celt/arm/armcpu.c", - #"celt/arm/celt_fft_ne10.c", - #"celt/arm/celt_mdct_ne10.c", + #"celt/arm/celt_ne10_fft.c", + #"celt/arm/celt_ne10_mdct.c", #"celt/arm/celt_neon_intr.c", - #"celt/arm/pitch_neon_intr.c", # Sync with silk_sources.mk "silk/CNG.c", @@ -117,7 +113,6 @@ if env['builtin_opus']: "silk/lin2log.c", "silk/log2lin.c", "silk/LPC_analysis_filter.c", - "silk/LPC_fit.c", "silk/LPC_inv_pred_gain.c", "silk/table_LSF_cos.c", "silk/NLSF2A.c", @@ -155,10 +150,12 @@ if env['builtin_opus']: "silk/fixed/find_pitch_lags_FIX.c", "silk/fixed/find_pred_coefs_FIX.c", "silk/fixed/noise_shape_analysis_FIX.c", + "silk/fixed/prefilter_FIX.c", "silk/fixed/process_gains_FIX.c", "silk/fixed/regularize_correlations_FIX.c", "silk/fixed/residual_energy16_FIX.c", "silk/fixed/residual_energy_FIX.c", + "silk/fixed/solve_LS_FIX.c", "silk/fixed/warped_autocorrelation_FIX.c", "silk/fixed/apply_sine_window_FIX.c", "silk/fixed/autocorr_FIX.c", @@ -183,9 +180,11 @@ if env['builtin_opus']: "silk/float/LTP_analysis_filter_FLP.c", "silk/float/LTP_scale_ctrl_FLP.c", "silk/float/noise_shape_analysis_FLP.c", + "silk/float/prefilter_FLP.c", "silk/float/process_gains_FLP.c", "silk/float/regularize_correlations_FLP.c", "silk/float/residual_energy_FLP.c", + "silk/float/solve_LS_FLP.c", "silk/float/warped_autocorrelation_FLP.c", "silk/float/wrappers_FLP.c", "silk/float/autocorrelation_FLP.c", @@ -194,6 +193,7 @@ if env['builtin_opus']: "silk/float/energy_FLP.c", "silk/float/inner_product_FLP.c", "silk/float/k2a_FLP.c", + "silk/float/levinsondurbin_FLP.c", "silk/float/LPC_inv_pred_gain_FLP.c", "silk/float/pitch_analysis_core_FLP.c", "silk/float/scale_copy_vector_FLP.c", diff --git a/thirdparty/README.md b/thirdparty/README.md index 27cfe412381..9571ee49b93 100644 --- a/thirdparty/README.md +++ b/thirdparty/README.md @@ -397,19 +397,17 @@ Files extracted from the upstream source: ## opus - Upstream: https://opus-codec.org -- Version: 1.3.1 (opus) and 0.11 (opusfile) +- Version: 1.1.5 (opus) and 0.8 (opusfile) - License: BSD-3-Clause Files extracted from upstream source: -- Run `opus/configure` and copy/sync changes to `config.h` - (note that this file may have Godot-specific options enabled) - all .c and .h files in src/ (both opus and opusfile) - all .h files in include/ (both opus and opusfile) as opus/ - remove unused `opus_demo.c`, - remove `http.c`, `wincerts.c` and `winerrno.h` (part of unused libopusurl) -- celt/ and silk/ subfolders (minus tests folders) +- celt/ and silk/ subfolders - COPYING diff --git a/thirdparty/opus/analysis.c b/thirdparty/opus/analysis.c index cb46dec582d..663431a436a 100644 --- a/thirdparty/opus/analysis.c +++ b/thirdparty/opus/analysis.c @@ -29,29 +29,20 @@ #include "config.h" #endif -#define ANALYSIS_C - -#include - -#include "mathops.h" #include "kiss_fft.h" #include "celt.h" #include "modes.h" #include "arch.h" #include "quant_bands.h" +#include #include "analysis.h" #include "mlp.h" #include "stack_alloc.h" -#include "float_cast.h" #ifndef M_PI #define M_PI 3.141592653 #endif -#ifndef DISABLE_FLOAT_API - -#define TRANSITION_PENALTY 10 - static const float dct_table[128] = { 0.250000f, 0.250000f, 0.250000f, 0.250000f, 0.250000f, 0.250000f, 0.250000f, 0.250000f, 0.250000f, 0.250000f, 0.250000f, 0.250000f, 0.250000f, 0.250000f, 0.250000f, 0.250000f, @@ -105,118 +96,52 @@ static const float analysis_window[240] = { }; static const int tbands[NB_TBANDS+1] = { - 4, 8, 12, 16, 20, 24, 28, 32, 40, 48, 56, 64, 80, 96, 112, 136, 160, 192, 240 + 2, 4, 6, 8, 10, 12, 14, 16, 20, 24, 28, 32, 40, 48, 56, 68, 80, 96, 120 }; +static const int extra_bands[NB_TOT_BANDS+1] = { + 1, 2, 4, 6, 8, 10, 12, 14, 16, 20, 24, 28, 32, 40, 48, 56, 68, 80, 96, 120, 160, 200 +}; + +/*static const float tweight[NB_TBANDS+1] = { + .3, .4, .5, .6, .7, .8, .9, 1., 1., 1., 1., 1., 1., 1., .8, .7, .6, .5 +};*/ + #define NB_TONAL_SKIP_BANDS 9 -static opus_val32 silk_resampler_down2_hp( - opus_val32 *S, /* I/O State vector [ 2 ] */ - opus_val32 *out, /* O Output signal [ floor(len/2) ] */ - const opus_val32 *in, /* I Input signal [ len ] */ - int inLen /* I Number of input samples */ -) -{ - int k, len2 = inLen/2; - opus_val32 in32, out32, out32_hp, Y, X; - opus_val64 hp_ener = 0; - /* Internal variables and state are in Q10 format */ - for( k = 0; k < len2; k++ ) { - /* Convert to Q10 */ - in32 = in[ 2 * k ]; - - /* All-pass section for even input sample */ - Y = SUB32( in32, S[ 0 ] ); - X = MULT16_32_Q15(QCONST16(0.6074371f, 15), Y); - out32 = ADD32( S[ 0 ], X ); - S[ 0 ] = ADD32( in32, X ); - out32_hp = out32; - /* Convert to Q10 */ - in32 = in[ 2 * k + 1 ]; - - /* All-pass section for odd input sample, and add to output of previous section */ - Y = SUB32( in32, S[ 1 ] ); - X = MULT16_32_Q15(QCONST16(0.15063f, 15), Y); - out32 = ADD32( out32, S[ 1 ] ); - out32 = ADD32( out32, X ); - S[ 1 ] = ADD32( in32, X ); - - Y = SUB32( -in32, S[ 2 ] ); - X = MULT16_32_Q15(QCONST16(0.15063f, 15), Y); - out32_hp = ADD32( out32_hp, S[ 2 ] ); - out32_hp = ADD32( out32_hp, X ); - S[ 2 ] = ADD32( -in32, X ); - - hp_ener += out32_hp*(opus_val64)out32_hp; - /* Add, convert back to int16 and store to output */ - out[ k ] = HALF32(out32); - } -#ifdef FIXED_POINT - /* len2 can be up to 480, so we shift by 8 more to make it fit. */ - hp_ener = hp_ener >> (2*SIG_SHIFT + 8); -#endif - return (opus_val32)hp_ener; +#define cA 0.43157974f +#define cB 0.67848403f +#define cC 0.08595542f +#define cE ((float)M_PI/2) +static OPUS_INLINE float fast_atan2f(float y, float x) { + float x2, y2; + /* Should avoid underflow on the values we'll get */ + if (ABS16(x)+ABS16(y)<1e-9f) + { + x*=1e12f; + y*=1e12f; + } + x2 = x*x; + y2 = y*y; + if(x2-1) - scale /= 2; - for (j=0;jarch = opus_select_arch(); - tonal->Fs = Fs; /* Clear remaining fields. */ tonality_analysis_reset(tonal); } @@ -232,34 +157,15 @@ void tonality_get_info(TonalityAnalysisState *tonal, AnalysisInfo *info_out, int { int pos; int curr_lookahead; - float tonality_max; - float tonality_avg; - int tonality_count; + float psum; int i; - int pos0; - float prob_avg; - float prob_count; - float prob_min, prob_max; - float vad_prob; - int mpos, vpos; - int bandwidth_span; pos = tonal->read_pos; curr_lookahead = tonal->write_pos-tonal->read_pos; if (curr_lookahead<0) curr_lookahead += DETECT_SIZE; - tonal->read_subframe += len/(tonal->Fs/400); - while (tonal->read_subframe>=8) - { - tonal->read_subframe -= 8; - tonal->read_pos++; - } - if (tonal->read_pos>=DETECT_SIZE) - tonal->read_pos-=DETECT_SIZE; - - /* On long frames, look at the second analysis window rather than the first. */ - if (len > tonal->Fs/50 && pos != tonal->write_pos) + if (len > 480 && pos != tonal->write_pos) { pos++; if (pos==DETECT_SIZE) @@ -269,178 +175,33 @@ void tonality_get_info(TonalityAnalysisState *tonal, AnalysisInfo *info_out, int pos--; if (pos<0) pos = DETECT_SIZE-1; - pos0 = pos; OPUS_COPY(info_out, &tonal->info[pos], 1); - if (!info_out->valid) - return; - tonality_max = tonality_avg = info_out->tonality; - tonality_count = 1; - /* Look at the neighbouring frames and pick largest bandwidth found (to be safe). */ - bandwidth_span = 6; - /* If possible, look ahead for a tone to compensate for the delay in the tone detector. */ - for (i=0;i<3;i++) + tonal->read_subframe += len/120; + while (tonal->read_subframe>=4) { - pos++; - if (pos==DETECT_SIZE) - pos = 0; - if (pos == tonal->write_pos) - break; - tonality_max = MAX32(tonality_max, tonal->info[pos].tonality); - tonality_avg += tonal->info[pos].tonality; - tonality_count++; - info_out->bandwidth = IMAX(info_out->bandwidth, tonal->info[pos].bandwidth); - bandwidth_span--; + tonal->read_subframe -= 4; + tonal->read_pos++; } - pos = pos0; - /* Look back in time to see if any has a wider bandwidth than the current frame. */ - for (i=0;iwrite_pos) - break; - info_out->bandwidth = IMAX(info_out->bandwidth, tonal->info[pos].bandwidth); - } - info_out->tonality = MAX32(tonality_avg/tonality_count, tonality_max-.2f); + if (tonal->read_pos>=DETECT_SIZE) + tonal->read_pos-=DETECT_SIZE; - mpos = vpos = pos0; - /* If we have enough look-ahead, compensate for the ~5-frame delay in the music prob and - ~1 frame delay in the VAD prob. */ - if (curr_lookahead > 15) - { - mpos += 5; - if (mpos>=DETECT_SIZE) - mpos -= DETECT_SIZE; - vpos += 1; - if (vpos>=DETECT_SIZE) - vpos -= DETECT_SIZE; - } + /* Compensate for the delay in the features themselves. + FIXME: Need a better estimate the 10 I just made up */ + curr_lookahead = IMAX(curr_lookahead-10, 0); - /* The following calculations attempt to minimize a "badness function" - for the transition. When switching from speech to music, the badness - of switching at frame k is - b_k = S*v_k + \sum_{i=0}^{k-1} v_i*(p_i - T) - where - v_i is the activity probability (VAD) at frame i, - p_i is the music probability at frame i - T is the probability threshold for switching - S is the penalty for switching during active audio rather than silence - the current frame has index i=0 + psum=0; + /* Summing the probability of transition patterns that involve music at + time (DETECT_SIZE-curr_lookahead-1) */ + for (i=0;ipmusic[i]; + for (;ipspeech[i]; + psum = psum*tonal->music_confidence + (1-psum)*tonal->speech_confidence; + /*printf("%f %f %f\n", psum, info_out->music_prob, info_out->tonality);*/ - Rather than apply badness to directly decide when to switch, what we compute - instead is the threshold for which the optimal switching point is now. When - considering whether to switch now (frame 0) or at frame k, we have: - S*v_0 = S*v_k + \sum_{i=0}^{k-1} v_i*(p_i - T) - which gives us: - T = ( \sum_{i=0}^{k-1} v_i*p_i + S*(v_k-v_0) ) / ( \sum_{i=0}^{k-1} v_i ) - We take the min threshold across all positive values of k (up to the maximum - amount of lookahead we have) to give us the threshold for which the current - frame is the optimal switch point. - - The last step is that we need to consider whether we want to switch at all. - For that we use the average of the music probability over the entire window. - If the threshold is higher than that average we're not going to - switch, so we compute a min with the average as well. The result of all these - min operations is music_prob_min, which gives the threshold for switching to music - if we're currently encoding for speech. - - We do the exact opposite to compute music_prob_max which is used for switching - from music to speech. - */ - prob_min = 1.f; - prob_max = 0.f; - vad_prob = tonal->info[vpos].activity_probability; - prob_count = MAX16(.1f, vad_prob); - prob_avg = MAX16(.1f, vad_prob)*tonal->info[mpos].music_prob; - while (1) - { - float pos_vad; - mpos++; - if (mpos==DETECT_SIZE) - mpos = 0; - if (mpos == tonal->write_pos) - break; - vpos++; - if (vpos==DETECT_SIZE) - vpos = 0; - if (vpos == tonal->write_pos) - break; - pos_vad = tonal->info[vpos].activity_probability; - prob_min = MIN16((prob_avg - TRANSITION_PENALTY*(vad_prob - pos_vad))/prob_count, prob_min); - prob_max = MAX16((prob_avg + TRANSITION_PENALTY*(vad_prob - pos_vad))/prob_count, prob_max); - prob_count += MAX16(.1f, pos_vad); - prob_avg += MAX16(.1f, pos_vad)*tonal->info[mpos].music_prob; - } - info_out->music_prob = prob_avg/prob_count; - prob_min = MIN16(prob_avg/prob_count, prob_min); - prob_max = MAX16(prob_avg/prob_count, prob_max); - prob_min = MAX16(prob_min, 0.f); - prob_max = MIN16(prob_max, 1.f); - - /* If we don't have enough look-ahead, do our best to make a decent decision. */ - if (curr_lookahead < 10) - { - float pmin, pmax; - pmin = prob_min; - pmax = prob_max; - pos = pos0; - /* Look for min/max in the past. */ - for (i=0;icount-1, 15);i++) - { - pos--; - if (pos < 0) - pos = DETECT_SIZE-1; - pmin = MIN16(pmin, tonal->info[pos].music_prob); - pmax = MAX16(pmax, tonal->info[pos].music_prob); - } - /* Bias against switching on active audio. */ - pmin = MAX16(0.f, pmin - .1f*vad_prob); - pmax = MIN16(1.f, pmax + .1f*vad_prob); - prob_min += (1.f-.1f*curr_lookahead)*(pmin - prob_min); - prob_max += (1.f-.1f*curr_lookahead)*(pmax - prob_max); - } - info_out->music_prob_min = prob_min; - info_out->music_prob_max = prob_max; - - /* printf("%f %f %f %f %f\n", prob_min, prob_max, prob_avg/prob_count, vad_prob, info_out->music_prob); */ + info_out->music_prob = psum; } -static const float std_feature_bias[9] = { - 5.684947f, 3.475288f, 1.770634f, 1.599784f, 3.773215f, - 2.163313f, 1.260756f, 1.116868f, 1.918795f -}; - -#define LEAKAGE_OFFSET 2.5f -#define LEAKAGE_SLOPE 2.f - -#ifdef FIXED_POINT -/* For fixed-point, the input is +/-2^15 shifted up by SIG_SHIFT, so we need to - compensate for that in the energy. */ -#define SCALE_COMPENS (1.f/((opus_int32)1<<(15+SIG_SHIFT))) -#define SCALE_ENER(e) ((SCALE_COMPENS*SCALE_COMPENS)*(e)) -#else -#define SCALE_ENER(e) (e) -#endif - -#ifdef FIXED_POINT -static int is_digital_silence32(const opus_val32* pcm, int frame_size, int channels, int lsb_depth) -{ - int silence = 0; - opus_val32 sample_max = 0; -#ifdef MLP_TRAINING - return 0; -#endif - sample_max = celt_maxabs32(pcm, frame_size*channels); - - silence = (sample_max == 0); - (void)lsb_depth; - return silence; -} -#else -#define is_digital_silence32(pcm, frame_size, channels, lsb_depth) is_digital_silence(pcm, frame_size, channels, lsb_depth) -#endif - static void tonality_analysis(TonalityAnalysisState *tonal, const CELTMode *celt_mode, const void *x, int len, int offset, int c1, int c2, int C, int lsb_depth, downmix_func downmix) { int i, b; @@ -469,50 +230,24 @@ static void tonality_analysis(TonalityAnalysisState *tonal, const CELTMode *celt float alpha, alphaE, alphaE2; float frame_loudness; float bandwidth_mask; - int is_masked[NB_TBANDS+1]; int bandwidth=0; float maxE = 0; float noise_floor; int remaining; AnalysisInfo *info; - float hp_ener; - float tonality2[240]; - float midE[8]; - float spec_variability=0; - float band_log2[NB_TBANDS+1]; - float leakage_from[NB_TBANDS+1]; - float leakage_to[NB_TBANDS+1]; - float layer_out[MAX_NEURONS]; - float below_max_pitch; - float above_max_pitch; - int is_silence; SAVE_STACK; - if (!tonal->initialized) - { - tonal->mem_fill = 240; - tonal->initialized = 1; - } - alpha = 1.f/IMIN(10, 1+tonal->count); - alphaE = 1.f/IMIN(25, 1+tonal->count); - /* Noise floor related decay for bandwidth detection: -2.2 dB/second */ - alphaE2 = 1.f/IMIN(100, 1+tonal->count); - if (tonal->count <= 1) alphaE2 = 1; - - if (tonal->Fs == 48000) - { - /* len and offset are now at 24 kHz. */ - len/= 2; - offset /= 2; - } else if (tonal->Fs == 16000) { - len = 3*len/2; - offset = 3*offset/2; - } + tonal->last_transition++; + alpha = 1.f/IMIN(20, 1+tonal->count); + alphaE = 1.f/IMIN(50, 1+tonal->count); + alphaE2 = 1.f/IMIN(1000, 1+tonal->count); + if (tonal->count<4) + tonal->music_prob = .5; kfft = celt_mode->mdct.kfft[0]; - tonal->hp_ener_accum += (float)downmix_and_resample(downmix, x, - &tonal->inmem[tonal->mem_fill], tonal->downmix_state, - IMIN(len, ANALYSIS_BUF_SIZE-tonal->mem_fill), offset, c1, c2, C, tonal->Fs); + if (tonal->count==0) + tonal->mem_fill = 240; + downmix(x, &tonal->inmem[tonal->mem_fill], IMIN(len, ANALYSIS_BUF_SIZE-tonal->mem_fill), offset, c1, c2, C); if (tonal->mem_fill+len < ANALYSIS_BUF_SIZE) { tonal->mem_fill += len; @@ -520,13 +255,10 @@ static void tonality_analysis(TonalityAnalysisState *tonal, const CELTMode *celt RESTORE_STACK; return; } - hp_ener = tonal->hp_ener_accum; info = &tonal->info[tonal->write_pos++]; if (tonal->write_pos>=DETECT_SIZE) tonal->write_pos-=DETECT_SIZE; - is_silence = is_digital_silence32(tonal->inmem, ANALYSIS_BUF_SIZE, 1, lsb_depth); - ALLOC(in, 480, kiss_fft_cpx); ALLOC(out, 480, kiss_fft_cpx); ALLOC(tonality, 240, float); @@ -541,20 +273,8 @@ static void tonality_analysis(TonalityAnalysisState *tonal, const CELTMode *celt } OPUS_MOVE(tonal->inmem, tonal->inmem+ANALYSIS_BUF_SIZE-240, 240); remaining = len - (ANALYSIS_BUF_SIZE-tonal->mem_fill); - tonal->hp_ener_accum = (float)downmix_and_resample(downmix, x, - &tonal->inmem[240], tonal->downmix_state, remaining, - offset+ANALYSIS_BUF_SIZE-tonal->mem_fill, c1, c2, C, tonal->Fs); + downmix(x, &tonal->inmem[240], remaining, offset+ANALYSIS_BUF_SIZE-tonal->mem_fill, c1, c2, C); tonal->mem_fill = 240 + remaining; - if (is_silence) - { - /* On silence, copy the previous analysis. */ - int prev_pos = tonal->write_pos-2; - if (prev_pos < 0) - prev_pos += DETECT_SIZE; - OPUS_COPY(info, &tonal->info[prev_pos], 1); - RESTORE_STACK; - return; - } opus_fft(kfft, in, out, tonal->arch); #ifndef FIXED_POINT /* If there's any NaN on the input, the entire output will be NaN, so we only need to check one value. */ @@ -585,31 +305,24 @@ static void tonality_analysis(TonalityAnalysisState *tonal, const CELTMode *celt d_angle2 = angle2 - angle; d2_angle2 = d_angle2 - d_angle; - mod1 = d2_angle - (float)float2int(d2_angle); + mod1 = d2_angle - (float)floor(.5+d2_angle); noisiness[i] = ABS16(mod1); mod1 *= mod1; mod1 *= mod1; - mod2 = d2_angle2 - (float)float2int(d2_angle2); + mod2 = d2_angle2 - (float)floor(.5+d2_angle2); noisiness[i] += ABS16(mod2); mod2 *= mod2; mod2 *= mod2; - avg_mod = .25f*(d2A[i]+mod1+2*mod2); - /* This introduces an extra delay of 2 frames in the detection. */ + avg_mod = .25f*(d2A[i]+2.f*mod1+mod2); tonality[i] = 1.f/(1.f+40.f*16.f*pi4*avg_mod)-.015f; - /* No delay on this detection, but it's less reliable. */ - tonality2[i] = 1.f/(1.f+40.f*16.f*pi4*mod2)-.015f; A[i] = angle2; dA[i] = d_angle2; d2A[i] = mod2; } - for (i=2;ilogE[tonal->E_count][b] = logE[b]; - if (tonal->count==0) - tonal->highE[b] = tonal->lowE[b] = logE[b]; - if (tonal->highE[b] > tonal->lowE[b] + 7.5) + tonal->lowE[b] = MIN32(logE[b], tonal->lowE[b]+.01f); + tonal->highE[b] = MAX32(logE[b], tonal->highE[b]-.1f); + if (tonal->highE[b] < tonal->lowE[b]+1.f) { - if (tonal->highE[b] - logE[b] > logE[b] - tonal->lowE[b]) - tonal->highE[b] -= .01f; - else - tonal->lowE[b] += .01f; + tonal->highE[b]+=.5f; + tonal->lowE[b]-=.5f; } - if (logE[b] > tonal->highE[b]) - { - tonal->highE[b] = logE[b]; - tonal->lowE[b] = MAX32(tonal->highE[b]-15, tonal->lowE[b]); - } else if (logE[b] < tonal->lowE[b]) - { - tonal->lowE[b] = logE[b]; - tonal->highE[b] = MIN32(tonal->lowE[b]+15, tonal->highE[b]); - } - relativeE += (logE[b]-tonal->lowE[b])/(1e-5f + (tonal->highE[b]-tonal->lowE[b])); + relativeE += (logE[b]-tonal->lowE[b])/(1e-15f+tonal->highE[b]-tonal->lowE[b]); L1=L2=0; for (i=0;iprev_band_tonality[b] = band_tonality[b]; } - leakage_from[0] = band_log2[0]; - leakage_to[0] = band_log2[0] - LEAKAGE_OFFSET; - for (b=1;b=0;b--) - { - float leak_slope = LEAKAGE_SLOPE*(tbands[b+1]-tbands[b])/4; - leakage_from[b] = MIN16(leakage_from[b+1]+leak_slope, leakage_from[b]); - leakage_to[b] = MAX16(leakage_to[b+1]-leak_slope, leakage_to[b]); - } - celt_assert(NB_TBANDS+1 <= LEAK_BANDS); - for (b=0;bleak_boost[b] = IMIN(255, (int)floor(.5 + 64.f*boost)); - } - for (;bleak_boost[b] = 0; - - for (i=0;ilogE[i][k] - tonal->logE[j][k]; - dist += tmp*tmp; - } - if (j!=i) - mindist = MIN32(mindist, dist); - } - spec_variability += mindist; - } - spec_variability = (float)sqrt(spec_variability/NB_FRAMES/NB_TBANDS); bandwidth_mask = 0; bandwidth = 0; maxE = 0; noise_floor = 5.7e-4f/(1<<(IMAX(0,lsb_depth-8))); +#ifdef FIXED_POINT + noise_floor *= 1<<(15+SIG_SHIFT); +#endif noise_floor *= noise_floor; - below_max_pitch=0; - above_max_pitch=0; - for (b=0;bmeanE[b] = MAX32((1-alphaE2)*tonal->meanE[b], E); - Em = MAX32(E, tonal->meanE[b]); - /* Consider the band "active" only if all these conditions are met: - 1) less than 90 dB below the peak band (maximal masking possible considering - both the ATH and the loudness-dependent slope of the spreading function) - 2) above the PCM quantization noise floor - We use b+1 because the first CELT band isn't included in tbands[] - */ - if (E*1e9f > maxE && (Em > 3*noise_floor*(band_end-band_start) || E > noise_floor*(band_end-band_start))) - bandwidth = b+1; - /* Check if the band is masked (see below). */ - is_masked[b] = E < (tonal->prev_bandwidth >= b+1 ? .01f : .05f)*bandwidth_mask; - /* Use a simple follower with 13 dB/Bark slope for spreading function. */ + E = MAX32(E, tonal->meanE[b]); + /* Use a simple follower with 13 dB/Bark slope for spreading function */ bandwidth_mask = MAX32(.05f*bandwidth_mask, E); + /* Consider the band "active" only if all these conditions are met: + 1) less than 10 dB below the simple follower + 2) less than 90 dB below the peak band (maximal masking possible considering + both the ATH and the loudness-dependent slope of the spreading function) + 3) above the PCM quantization noise floor + */ + if (E>.1*bandwidth_mask && E*1e9f > maxE && E > noise_floor*(band_end-band_start)) + bandwidth = b; } - /* Special case for the last two bands, for which we don't have spectrum but only - the energy above 12 kHz. The difficulty here is that the high-pass we use - leaks some LF energy, so we need to increase the threshold without accidentally cutting - off the band. */ - if (tonal->Fs == 48000) { - float noise_ratio; - float Em; - float E = hp_ener*(1.f/(60*60)); - noise_ratio = tonal->prev_bandwidth==20 ? 10.f : 30.f; - -#ifdef FIXED_POINT - /* silk_resampler_down2_hp() shifted right by an extra 8 bits. */ - E *= 256.f*(1.f/Q15ONE)*(1.f/Q15ONE); -#endif - above_max_pitch += E; - tonal->meanE[b] = MAX32((1-alphaE2)*tonal->meanE[b], E); - Em = MAX32(E, tonal->meanE[b]); - if (Em > 3*noise_ratio*noise_floor*160 || E > noise_ratio*noise_floor*160) - bandwidth = 20; - /* Check if the band is masked (see below). */ - is_masked[b] = E < (tonal->prev_bandwidth == 20 ? .01f : .05f)*bandwidth_mask; - } - if (above_max_pitch > below_max_pitch) - info->max_pitch_ratio = below_max_pitch/above_max_pitch; - else - info->max_pitch_ratio = 1; - /* In some cases, resampling aliasing can create a small amount of energy in the first band - being cut. So if the last band is masked, we don't include it. */ - if (bandwidth == 20 && is_masked[NB_TBANDS]) - bandwidth-=2; - else if (bandwidth > 0 && bandwidth <= NB_TBANDS && is_masked[bandwidth-1]) - bandwidth--; if (tonal->count<=2) bandwidth = 20; frame_loudness = 20*(float)log10(frame_loudness); - tonal->Etracker = MAX32(tonal->Etracker-.003f, frame_loudness); + tonal->Etracker = MAX32(tonal->Etracker-.03f, frame_loudness); tonal->lowECount *= (1-alphaE); if (frame_loudness < tonal->Etracker-30) tonal->lowECount += alphaE; @@ -863,18 +460,11 @@ static void tonality_analysis(TonalityAnalysisState *tonal, const CELTMode *celt sum += dct_table[i*16+b]*logE[b]; BFCC[i] = sum; } - for (i=0;i<8;i++) - { - float sum=0; - for (b=0;b<16;b++) - sum += dct_table[i*16+b]*.5f*(tonal->highE[b]+tonal->lowE[b]); - midE[i] = sum; - } frame_stationarity /= NB_TBANDS; relativeE /= NB_TBANDS; if (tonal->count<10) - relativeE = .5f; + relativeE = .5; frame_noisiness /= NB_TBANDS; #if 1 info->activity = frame_noisiness + (1-frame_noisiness)*relativeE; @@ -889,7 +479,7 @@ static void tonality_analysis(TonalityAnalysisState *tonal, const CELTMode *celt info->tonality_slope = slope; tonal->E_count = (tonal->E_count+1)%NB_FRAMES; - tonal->count = IMIN(tonal->count+1, ANALYSIS_COUNT_MAX); + tonal->count++; info->tonality = frame_tonality; for (i=0;i<4;i++) @@ -908,8 +498,6 @@ static void tonality_analysis(TonalityAnalysisState *tonal, const CELTMode *celt for (i=0;i<9;i++) tonal->std[i] = (1-alpha)*tonal->std[i] + alpha*features[i]*features[i]; } - for (i=0;i<4;i++) - features[i] = BFCC[i]-midE[i]; for (i=0;i<8;i++) { @@ -919,31 +507,136 @@ static void tonality_analysis(TonalityAnalysisState *tonal, const CELTMode *celt tonal->mem[i] = BFCC[i]; } for (i=0;i<9;i++) - features[11+i] = (float)sqrt(tonal->std[i]) - std_feature_bias[i]; - features[18] = spec_variability - 0.78f; - features[20] = info->tonality - 0.154723f; - features[21] = info->activity - 0.724643f; - features[22] = frame_stationarity - 0.743717f; - features[23] = info->tonality_slope + 0.069216f; - features[24] = tonal->lowECount - 0.067930f; + features[11+i] = (float)sqrt(tonal->std[i]); + features[20] = info->tonality; + features[21] = info->activity; + features[22] = frame_stationarity; + features[23] = info->tonality_slope; + features[24] = tonal->lowECount; - compute_dense(&layer0, layer_out, features); - compute_gru(&layer1, tonal->rnn_state, layer_out); - compute_dense(&layer2, frame_probs, tonal->rnn_state); +#ifndef DISABLE_FLOAT_API + mlp_process(&net, features, frame_probs); + frame_probs[0] = .5f*(frame_probs[0]+1); + /* Curve fitting between the MLP probability and the actual probability */ + frame_probs[0] = .01f + 1.21f*frame_probs[0]*frame_probs[0] - .23f*(float)pow(frame_probs[0], 10); + /* Probability of active audio (as opposed to silence) */ + frame_probs[1] = .5f*frame_probs[1]+.5f; + /* Consider that silence has a 50-50 probability. */ + frame_probs[0] = frame_probs[1]*frame_probs[0] + (1-frame_probs[1])*.5f; - /* Probability of speech or music vs noise */ - info->activity_probability = frame_probs[1]; - info->music_prob = frame_probs[0]; + /*printf("%f %f ", frame_probs[0], frame_probs[1]);*/ + { + /* Probability of state transition */ + float tau; + /* Represents independence of the MLP probabilities, where + beta=1 means fully independent. */ + float beta; + /* Denormalized probability of speech (p0) and music (p1) after update */ + float p0, p1; + /* Probabilities for "all speech" and "all music" */ + float s0, m0; + /* Probability sum for renormalisation */ + float psum; + /* Instantaneous probability of speech and music, with beta pre-applied. */ + float speech0; + float music0; + float p, q; - /*printf("%f %f %f\n", frame_probs[0], frame_probs[1], info->music_prob);*/ -#ifdef MLP_TRAINING - for (i=0;i<25;i++) - printf("%f ", features[i]); - printf("\n"); + /* One transition every 3 minutes of active audio */ + tau = .00005f*frame_probs[1]; + /* Adapt beta based on how "unexpected" the new prob is */ + p = MAX16(.05f,MIN16(.95f,frame_probs[0])); + q = MAX16(.05f,MIN16(.95f,tonal->music_prob)); + beta = .01f+.05f*ABS16(p-q)/(p*(1-q)+q*(1-p)); + /* p0 and p1 are the probabilities of speech and music at this frame + using only information from previous frame and applying the + state transition model */ + p0 = (1-tonal->music_prob)*(1-tau) + tonal->music_prob *tau; + p1 = tonal->music_prob *(1-tau) + (1-tonal->music_prob)*tau; + /* We apply the current probability with exponent beta to work around + the fact that the probability estimates aren't independent. */ + p0 *= (float)pow(1-frame_probs[0], beta); + p1 *= (float)pow(frame_probs[0], beta); + /* Normalise the probabilities to get the Marokv probability of music. */ + tonal->music_prob = p1/(p0+p1); + info->music_prob = tonal->music_prob; + + /* This chunk of code deals with delayed decision. */ + psum=1e-20f; + /* Instantaneous probability of speech and music, with beta pre-applied. */ + speech0 = (float)pow(1-frame_probs[0], beta); + music0 = (float)pow(frame_probs[0], beta); + if (tonal->count==1) + { + tonal->pspeech[0]=.5; + tonal->pmusic [0]=.5; + } + /* Updated probability of having only speech (s0) or only music (m0), + before considering the new observation. */ + s0 = tonal->pspeech[0] + tonal->pspeech[1]; + m0 = tonal->pmusic [0] + tonal->pmusic [1]; + /* Updates s0 and m0 with instantaneous probability. */ + tonal->pspeech[0] = s0*(1-tau)*speech0; + tonal->pmusic [0] = m0*(1-tau)*music0; + /* Propagate the transition probabilities */ + for (i=1;ipspeech[i] = tonal->pspeech[i+1]*speech0; + tonal->pmusic [i] = tonal->pmusic [i+1]*music0; + } + /* Probability that the latest frame is speech, when all the previous ones were music. */ + tonal->pspeech[DETECT_SIZE-1] = m0*tau*speech0; + /* Probability that the latest frame is music, when all the previous ones were speech. */ + tonal->pmusic [DETECT_SIZE-1] = s0*tau*music0; + + /* Renormalise probabilities to 1 */ + for (i=0;ipspeech[i] + tonal->pmusic[i]; + psum = 1.f/psum; + for (i=0;ipspeech[i] *= psum; + tonal->pmusic [i] *= psum; + } + psum = tonal->pmusic[0]; + for (i=1;ipspeech[i]; + + /* Estimate our confidence in the speech/music decisions */ + if (frame_probs[1]>.75) + { + if (tonal->music_prob>.9) + { + float adapt; + adapt = 1.f/(++tonal->music_confidence_count); + tonal->music_confidence_count = IMIN(tonal->music_confidence_count, 500); + tonal->music_confidence += adapt*MAX16(-.2f,frame_probs[0]-tonal->music_confidence); + } + if (tonal->music_prob<.1) + { + float adapt; + adapt = 1.f/(++tonal->speech_confidence_count); + tonal->speech_confidence_count = IMIN(tonal->speech_confidence_count, 500); + tonal->speech_confidence += adapt*MIN16(.2f,frame_probs[0]-tonal->speech_confidence); + } + } else { + if (tonal->music_confidence_count==0) + tonal->music_confidence = .9f; + if (tonal->speech_confidence_count==0) + tonal->speech_confidence = .1f; + } + } + if (tonal->last_music != (tonal->music_prob>.5f)) + tonal->last_transition=0; + tonal->last_music = tonal->music_prob>.5f; +#else + info->music_prob = 0; #endif + /*for (i=0;i<25;i++) + printf("%f ", features[i]); + printf("\n");*/ info->bandwidth = bandwidth; - tonal->prev_bandwidth = bandwidth; /*printf("%d %d\n", info->bandwidth, info->opus_bandwidth);*/ info->noisiness = frame_noisiness; info->valid = 1; @@ -957,25 +650,23 @@ void run_analysis(TonalityAnalysisState *analysis, const CELTMode *celt_mode, co int offset; int pcm_len; - analysis_frame_size -= analysis_frame_size&1; if (analysis_pcm != NULL) { /* Avoid overflow/wrap-around of the analysis buffer */ - analysis_frame_size = IMIN((DETECT_SIZE-5)*Fs/50, analysis_frame_size); + analysis_frame_size = IMIN((DETECT_SIZE-5)*Fs/100, analysis_frame_size); pcm_len = analysis_frame_size - analysis->analysis_offset; offset = analysis->analysis_offset; - while (pcm_len>0) { - tonality_analysis(analysis, celt_mode, analysis_pcm, IMIN(Fs/50, pcm_len), offset, c1, c2, C, lsb_depth, downmix); - offset += Fs/50; - pcm_len -= Fs/50; - } + do { + tonality_analysis(analysis, celt_mode, analysis_pcm, IMIN(480, pcm_len), offset, c1, c2, C, lsb_depth, downmix); + offset += 480; + pcm_len -= 480; + } while (pcm_len>0); analysis->analysis_offset = analysis_frame_size; analysis->analysis_offset -= frame_size; } + analysis_info->valid = 0; tonality_get_info(analysis, analysis_info, frame_size); } - -#endif /* DISABLE_FLOAT_API */ diff --git a/thirdparty/opus/analysis.h b/thirdparty/opus/analysis.h index 0b66555f215..9eae56a5253 100644 --- a/thirdparty/opus/analysis.h +++ b/thirdparty/opus/analysis.h @@ -30,24 +30,16 @@ #include "celt.h" #include "opus_private.h" -#include "mlp.h" #define NB_FRAMES 8 #define NB_TBANDS 18 -#define ANALYSIS_BUF_SIZE 720 /* 30 ms at 24 kHz */ +#define NB_TOT_BANDS 21 +#define ANALYSIS_BUF_SIZE 720 /* 15 ms at 48 kHz */ -/* At that point we can stop counting frames because it no longer matters. */ -#define ANALYSIS_COUNT_MAX 10000 - -#define DETECT_SIZE 100 - -/* Uncomment this to print the MLP features on stdout. */ -/*#define MLP_TRAINING*/ +#define DETECT_SIZE 200 typedef struct { int arch; - int application; - opus_int32 Fs; #define TONALITY_ANALYSIS_RESET_START angle float angle[240]; float d_angle[240]; @@ -56,27 +48,35 @@ typedef struct { int mem_fill; /* number of usable samples in the buffer */ float prev_band_tonality[NB_TBANDS]; float prev_tonality; - int prev_bandwidth; float E[NB_FRAMES][NB_TBANDS]; - float logE[NB_FRAMES][NB_TBANDS]; float lowE[NB_TBANDS]; float highE[NB_TBANDS]; - float meanE[NB_TBANDS+1]; + float meanE[NB_TOT_BANDS]; float mem[32]; float cmean[8]; float std[9]; + float music_prob; float Etracker; float lowECount; int E_count; + int last_music; + int last_transition; int count; + float subframe_mem[3]; int analysis_offset; + /** Probability of having speech for time i to DETECT_SIZE-1 (and music before). + pspeech[0] is the probability that all frames in the window are speech. */ + float pspeech[DETECT_SIZE]; + /** Probability of having music for time i to DETECT_SIZE-1 (and speech before). + pmusic[0] is the probability that all frames in the window are music. */ + float pmusic[DETECT_SIZE]; + float speech_confidence; + float music_confidence; + int speech_confidence_count; + int music_confidence_count; int write_pos; int read_pos; int read_subframe; - float hp_ener_accum; - int initialized; - float rnn_state[MAX_NEURONS]; - opus_val32 downmix_state[3]; AnalysisInfo info[DETECT_SIZE]; } TonalityAnalysisState; @@ -86,7 +86,7 @@ typedef struct { * not be repeated every analysis step. No allocated memory is retained * by the state struct, so no cleanup call is required. */ -void tonality_analysis_init(TonalityAnalysisState *analysis, opus_int32 Fs); +void tonality_analysis_init(TonalityAnalysisState *analysis); /** Reset a TonalityAnalysisState stuct. * diff --git a/thirdparty/opus/celt/_kiss_fft_guts.h b/thirdparty/opus/celt/_kiss_fft_guts.h index 17392b3e909..5e3d58fd664 100644 --- a/thirdparty/opus/celt/_kiss_fft_guts.h +++ b/thirdparty/opus/celt/_kiss_fft_guts.h @@ -58,12 +58,12 @@ # define S_MUL(a,b) MULT16_32_Q15(b, a) # define C_MUL(m,a,b) \ - do{ (m).r = SUB32_ovflw(S_MUL((a).r,(b).r) , S_MUL((a).i,(b).i)); \ - (m).i = ADD32_ovflw(S_MUL((a).r,(b).i) , S_MUL((a).i,(b).r)); }while(0) + do{ (m).r = SUB32(S_MUL((a).r,(b).r) , S_MUL((a).i,(b).i)); \ + (m).i = ADD32(S_MUL((a).r,(b).i) , S_MUL((a).i,(b).r)); }while(0) # define C_MULC(m,a,b) \ - do{ (m).r = ADD32_ovflw(S_MUL((a).r,(b).r) , S_MUL((a).i,(b).i)); \ - (m).i = SUB32_ovflw(S_MUL((a).i,(b).r) , S_MUL((a).r,(b).i)); }while(0) + do{ (m).r = ADD32(S_MUL((a).r,(b).r) , S_MUL((a).i,(b).i)); \ + (m).i = SUB32(S_MUL((a).i,(b).r) , S_MUL((a).r,(b).i)); }while(0) # define C_MULBYSCALAR( c, s ) \ do{ (c).r = S_MUL( (c).r , s ) ;\ @@ -77,17 +77,17 @@ DIVSCALAR( (c).i , div); }while (0) #define C_ADD( res, a,b)\ - do {(res).r=ADD32_ovflw((a).r,(b).r); (res).i=ADD32_ovflw((a).i,(b).i); \ + do {(res).r=ADD32((a).r,(b).r); (res).i=ADD32((a).i,(b).i); \ }while(0) #define C_SUB( res, a,b)\ - do {(res).r=SUB32_ovflw((a).r,(b).r); (res).i=SUB32_ovflw((a).i,(b).i); \ + do {(res).r=SUB32((a).r,(b).r); (res).i=SUB32((a).i,(b).i); \ }while(0) #define C_ADDTO( res , a)\ - do {(res).r = ADD32_ovflw((res).r, (a).r); (res).i = ADD32_ovflw((res).i,(a).i);\ + do {(res).r = ADD32((res).r, (a).r); (res).i = ADD32((res).i,(a).i);\ }while(0) #define C_SUBFROM( res , a)\ - do {(res).r = ADD32_ovflw((res).r,(a).r); (res).i = SUB32_ovflw((res).i,(a).i); \ + do {(res).r = ADD32((res).r,(a).r); (res).i = SUB32((res).i,(a).i); \ }while(0) #if defined(OPUS_ARM_INLINE_ASM) diff --git a/thirdparty/opus/celt/arch.h b/thirdparty/opus/celt/arch.h index 08b07db5982..8ceab5fe10e 100644 --- a/thirdparty/opus/celt/arch.h +++ b/thirdparty/opus/celt/arch.h @@ -46,50 +46,25 @@ # endif # endif -#if OPUS_GNUC_PREREQ(3, 0) -#define opus_likely(x) (__builtin_expect(!!(x), 1)) -#define opus_unlikely(x) (__builtin_expect(!!(x), 0)) -#else -#define opus_likely(x) (!!(x)) -#define opus_unlikely(x) (!!(x)) -#endif - #define CELT_SIG_SCALE 32768.f -#define CELT_FATAL(str) celt_fatal(str, __FILE__, __LINE__); - -#if defined(ENABLE_ASSERTIONS) || defined(ENABLE_HARDENING) -#ifdef __GNUC__ -__attribute__((noreturn)) -#endif -void celt_fatal(const char *str, const char *file, int line); - -#if defined(CELT_C) && !defined(OVERRIDE_celt_fatal) +#define celt_fatal(str) _celt_fatal(str, __FILE__, __LINE__); +#ifdef ENABLE_ASSERTIONS #include #include #ifdef __GNUC__ __attribute__((noreturn)) #endif -void celt_fatal(const char *str, const char *file, int line) +static OPUS_INLINE void _celt_fatal(const char *str, const char *file, int line) { fprintf (stderr, "Fatal (internal) error in %s, line %d: %s\n", file, line, str); abort(); } -#endif - -#define celt_assert(cond) {if (!(cond)) {CELT_FATAL("assertion failed: " #cond);}} -#define celt_assert2(cond, message) {if (!(cond)) {CELT_FATAL("assertion failed: " #cond "\n" message);}} -#define MUST_SUCCEED(call) celt_assert((call) == OPUS_OK) +#define celt_assert(cond) {if (!(cond)) {celt_fatal("assertion failed: " #cond);}} +#define celt_assert2(cond, message) {if (!(cond)) {celt_fatal("assertion failed: " #cond "\n" message);}} #else #define celt_assert(cond) #define celt_assert2(cond, message) -#define MUST_SUCCEED(call) do {if((call) != OPUS_OK) {RESTORE_STACK; return OPUS_INTERNAL_ERROR;} } while (0) -#endif - -#if defined(ENABLE_ASSERTIONS) -#define celt_sig_assert(cond) {if (!(cond)) {CELT_FATAL("signal assertion failed: " #cond);}} -#else -#define celt_sig_assert(cond) #endif #define IMUL32(a,b) ((a)*(b)) @@ -118,20 +93,14 @@ void celt_fatal(const char *str, const char *file, int line) typedef opus_int16 opus_val16; typedef opus_int32 opus_val32; -typedef opus_int64 opus_val64; typedef opus_val32 celt_sig; typedef opus_val16 celt_norm; typedef opus_val32 celt_ener; -#define celt_isnan(x) 0 - #define Q15ONE 32767 #define SIG_SHIFT 12 -/* Safe saturation value for 32-bit signals. Should be less than - 2^31*(1-0.85) to avoid blowing up on DC at deemphasis.*/ -#define SIG_SAT (300000000) #define NORM_SCALING 16384 @@ -160,7 +129,7 @@ static OPUS_INLINE opus_int16 SAT16(opus_int32 x) { #ifdef OPUS_ARM_PRESUME_AARCH64_NEON_INTR #include "arm/fixed_arm64.h" -#elif defined (OPUS_ARM_INLINE_EDSP) +#elif OPUS_ARM_INLINE_EDSP #include "arm/fixed_armv5e.h" #elif defined (OPUS_ARM_INLINE_ASM) #include "arm/fixed_armv4.h" @@ -178,7 +147,6 @@ static OPUS_INLINE opus_int16 SAT16(opus_int32 x) { typedef float opus_val16; typedef float opus_val32; -typedef float opus_val64; typedef float celt_sig; typedef float celt_norm; @@ -218,7 +186,6 @@ static OPUS_INLINE int celt_isnan(float x) #define NEG16(x) (-(x)) #define NEG32(x) (-(x)) -#define NEG32_ovflw(x) (-(x)) #define EXTRACT16(x) (x) #define EXTEND32(x) (x) #define SHR16(a,shift) (a) @@ -235,7 +202,6 @@ static OPUS_INLINE int celt_isnan(float x) #define SATURATE16(x) (x) #define ROUND16(a,shift) (a) -#define SROUND16(a,shift) (a) #define HALF16(x) (.5f*(x)) #define HALF32(x) (.5f*(x)) @@ -243,8 +209,6 @@ static OPUS_INLINE int celt_isnan(float x) #define SUB16(a,b) ((a)-(b)) #define ADD32(a,b) ((a)+(b)) #define SUB32(a,b) ((a)-(b)) -#define ADD32_ovflw(a,b) ((a)+(b)) -#define SUB32_ovflw(a,b) ((a)-(b)) #define MULT16_16_16(a,b) ((a)*(b)) #define MULT16_16(a,b) ((opus_val32)(a)*(opus_val32)(b)) #define MAC16_16(c,a,b) ((c)+(opus_val32)(a)*(opus_val32)(b)) @@ -279,9 +243,9 @@ static OPUS_INLINE int celt_isnan(float x) #ifndef GLOBAL_STACK_SIZE #ifdef FIXED_POINT -#define GLOBAL_STACK_SIZE 120000 +#define GLOBAL_STACK_SIZE 100000 #else -#define GLOBAL_STACK_SIZE 120000 +#define GLOBAL_STACK_SIZE 100000 #endif #endif diff --git a/thirdparty/opus/celt/arm/arm2gnu.pl b/thirdparty/opus/celt/arm/arm2gnu.pl index a2895f7445e..6c922ac819d 100755 --- a/thirdparty/opus/celt/arm/arm2gnu.pl +++ b/thirdparty/opus/celt/arm/arm2gnu.pl @@ -164,11 +164,11 @@ while (<>) { $prefix = ""; if ($proc) { - $prefix = $prefix.sprintf("\t.type\t%s, %%function", $proc) unless ($apple); + $prefix = $prefix.sprintf("\t.type\t%s, %%function; ",$proc) unless ($apple); # Make sure we $prefix isn't empty here (for the $apple case). # We handle mangling the label here, make sure it doesn't match # the label handling below (if $prefix would be empty). - $prefix = $prefix."; "; + $prefix = "; "; push(@proc_stack, $proc); s/^[A-Za-z_\.]\w+/$symprefix$&:/; } diff --git a/thirdparty/opus/celt/arm/arm_celt_map.c b/thirdparty/opus/celt/arm/arm_celt_map.c index ca988b66f55..4d4d069a86f 100644 --- a/thirdparty/opus/celt/arm/arm_celt_map.c +++ b/thirdparty/opus/celt/arm/arm_celt_map.c @@ -35,29 +35,12 @@ #if defined(OPUS_HAVE_RTCD) -# if defined(OPUS_ARM_MAY_HAVE_NEON_INTR) && !defined(OPUS_ARM_PRESUME_NEON_INTR) -opus_val32 (*const CELT_INNER_PROD_IMPL[OPUS_ARCHMASK+1])(const opus_val16 *x, const opus_val16 *y, int N) = { - celt_inner_prod_c, /* ARMv4 */ - celt_inner_prod_c, /* EDSP */ - celt_inner_prod_c, /* Media */ - celt_inner_prod_neon /* NEON */ -}; - -void (*const DUAL_INNER_PROD_IMPL[OPUS_ARCHMASK+1])(const opus_val16 *x, const opus_val16 *y01, const opus_val16 *y02, - int N, opus_val32 *xy1, opus_val32 *xy2) = { - dual_inner_prod_c, /* ARMv4 */ - dual_inner_prod_c, /* EDSP */ - dual_inner_prod_c, /* Media */ - dual_inner_prod_neon /* NEON */ -}; -# endif - # if defined(FIXED_POINT) # if ((defined(OPUS_ARM_MAY_HAVE_NEON) && !defined(OPUS_ARM_PRESUME_NEON)) || \ (defined(OPUS_ARM_MAY_HAVE_MEDIA) && !defined(OPUS_ARM_PRESUME_MEDIA)) || \ (defined(OPUS_ARM_MAY_HAVE_EDSP) && !defined(OPUS_ARM_PRESUME_EDSP))) opus_val32 (*const CELT_PITCH_XCORR_IMPL[OPUS_ARCHMASK+1])(const opus_val16 *, - const opus_val16 *, opus_val32 *, int, int, int) = { + const opus_val16 *, opus_val32 *, int , int) = { celt_pitch_xcorr_c, /* ARMv4 */ MAY_HAVE_EDSP(celt_pitch_xcorr), /* EDSP */ MAY_HAVE_MEDIA(celt_pitch_xcorr), /* Media */ @@ -68,7 +51,7 @@ opus_val32 (*const CELT_PITCH_XCORR_IMPL[OPUS_ARCHMASK+1])(const opus_val16 *, # else /* !FIXED_POINT */ # if defined(OPUS_ARM_MAY_HAVE_NEON_INTR) && !defined(OPUS_ARM_PRESUME_NEON_INTR) void (*const CELT_PITCH_XCORR_IMPL[OPUS_ARCHMASK+1])(const opus_val16 *, - const opus_val16 *, opus_val32 *, int, int, int) = { + const opus_val16 *, opus_val32 *, int, int) = { celt_pitch_xcorr_c, /* ARMv4 */ celt_pitch_xcorr_c, /* EDSP */ celt_pitch_xcorr_c, /* Media */ diff --git a/thirdparty/opus/celt/arm/celt_fft_ne10.c b/thirdparty/opus/celt/arm/celt_ne10_fft.c similarity index 99% rename from thirdparty/opus/celt/arm/celt_fft_ne10.c rename to thirdparty/opus/celt/arm/celt_ne10_fft.c index ea5fd7808b0..42d96a71176 100644 --- a/thirdparty/opus/celt/arm/celt_fft_ne10.c +++ b/thirdparty/opus/celt/arm/celt_ne10_fft.c @@ -1,7 +1,7 @@ /* Copyright (c) 2015 Xiph.Org Foundation Written by Viswanath Puttagunta */ /** - @file celt_fft_ne10.c + @file celt_ne10_fft.c @brief ARM Neon optimizations for fft using NE10 library */ @@ -36,6 +36,7 @@ #endif #endif +#include #include #include "os_support.h" #include "kiss_fft.h" diff --git a/thirdparty/opus/celt/arm/celt_mdct_ne10.c b/thirdparty/opus/celt/arm/celt_ne10_mdct.c similarity index 99% rename from thirdparty/opus/celt/arm/celt_mdct_ne10.c rename to thirdparty/opus/celt/arm/celt_ne10_mdct.c index 3531d02d100..293c3efd7a2 100644 --- a/thirdparty/opus/celt/arm/celt_mdct_ne10.c +++ b/thirdparty/opus/celt/arm/celt_ne10_mdct.c @@ -1,7 +1,7 @@ /* Copyright (c) 2015 Xiph.Org Foundation Written by Viswanath Puttagunta */ /** - @file celt_mdct_ne10.c + @file celt_ne10_mdct.c @brief ARM Neon optimizations for mdct using NE10 library */ diff --git a/thirdparty/opus/celt/arm/celt_neon_intr.c b/thirdparty/opus/celt/arm/celt_neon_intr.c index effda769d07..47bbe3dc22e 100644 --- a/thirdparty/opus/celt/arm/celt_neon_intr.c +++ b/thirdparty/opus/celt/arm/celt_neon_intr.c @@ -191,21 +191,121 @@ static void xcorr_kernel_neon_float(const float32_t *x, const float32_t *y, vst1q_f32(sum, SUMM); } +/* + * Function: xcorr_kernel_neon_float_process1 + * --------------------------------- + * Computes single correlation values and stores in *sum + */ +static void xcorr_kernel_neon_float_process1(const float32_t *x, + const float32_t *y, float32_t *sum, int len) { + float32x4_t XX[4]; + float32x4_t YY[4]; + float32x2_t XX_2; + float32x2_t YY_2; + float32x4_t SUMM; + float32x2_t SUMM_2[2]; + const float32_t *xi = x; + const float32_t *yi = y; + + SUMM = vdupq_n_f32(0); + + /* Work on 16 values per iteration */ + while (len >= 16) { + XX[0] = vld1q_f32(xi); + xi += 4; + XX[1] = vld1q_f32(xi); + xi += 4; + XX[2] = vld1q_f32(xi); + xi += 4; + XX[3] = vld1q_f32(xi); + xi += 4; + + YY[0] = vld1q_f32(yi); + yi += 4; + YY[1] = vld1q_f32(yi); + yi += 4; + YY[2] = vld1q_f32(yi); + yi += 4; + YY[3] = vld1q_f32(yi); + yi += 4; + + SUMM = vmlaq_f32(SUMM, YY[0], XX[0]); + SUMM = vmlaq_f32(SUMM, YY[1], XX[1]); + SUMM = vmlaq_f32(SUMM, YY[2], XX[2]); + SUMM = vmlaq_f32(SUMM, YY[3], XX[3]); + len -= 16; + } + + /* Work on 8 values */ + if (len >= 8) { + XX[0] = vld1q_f32(xi); + xi += 4; + XX[1] = vld1q_f32(xi); + xi += 4; + + YY[0] = vld1q_f32(yi); + yi += 4; + YY[1] = vld1q_f32(yi); + yi += 4; + + SUMM = vmlaq_f32(SUMM, YY[0], XX[0]); + SUMM = vmlaq_f32(SUMM, YY[1], XX[1]); + len -= 8; + } + + /* Work on 4 values */ + if (len >= 4) { + XX[0] = vld1q_f32(xi); + xi += 4; + YY[0] = vld1q_f32(yi); + yi += 4; + SUMM = vmlaq_f32(SUMM, YY[0], XX[0]); + len -= 4; + } + + /* Start accumulating results */ + SUMM_2[0] = vget_low_f32(SUMM); + if (len >= 2) { + /* While at it, consume 2 more values if available */ + XX_2 = vld1_f32(xi); + xi += 2; + YY_2 = vld1_f32(yi); + yi += 2; + SUMM_2[0] = vmla_f32(SUMM_2[0], YY_2, XX_2); + len -= 2; + } + SUMM_2[1] = vget_high_f32(SUMM); + SUMM_2[0] = vadd_f32(SUMM_2[0], SUMM_2[1]); + SUMM_2[0] = vpadd_f32(SUMM_2[0], SUMM_2[0]); + /* Ok, now we have result accumulated in SUMM_2[0].0 */ + + if (len > 0) { + /* Case when you have one value left */ + XX_2 = vld1_dup_f32(xi); + YY_2 = vld1_dup_f32(yi); + SUMM_2[0] = vmla_f32(SUMM_2[0], XX_2, YY_2); + } + + vst1_lane_f32(sum, SUMM_2[0], 0); +} + void celt_pitch_xcorr_float_neon(const opus_val16 *_x, const opus_val16 *_y, - opus_val32 *xcorr, int len, int max_pitch, int arch) { + opus_val32 *xcorr, int len, int max_pitch) { int i; - (void)arch; celt_assert(max_pitch > 0); - celt_sig_assert((((unsigned char *)_x-(unsigned char *)NULL)&3)==0); + celt_assert((((unsigned char *)_x-(unsigned char *)NULL)&3)==0); for (i = 0; i < (max_pitch-3); i += 4) { xcorr_kernel_neon_float((const float32_t *)_x, (const float32_t *)_y+i, (float32_t *)xcorr+i, len); } - /* In case max_pitch isn't a multiple of 4, do non-unrolled version. */ + /* In case max_pitch isn't multiple of 4 + * compute single correlation value per iteration + */ for (; i < max_pitch; i++) { - xcorr[i] = celt_inner_prod_neon(_x, _y+i, len); + xcorr_kernel_neon_float_process1((const float32_t *)_x, + (const float32_t *)_y+i, (float32_t *)xcorr+i, len); } } #endif diff --git a/thirdparty/opus/celt/arm/celt_pitch_xcorr_arm-gnu.S b/thirdparty/opus/celt/arm/celt_pitch_xcorr_arm-gnu.S new file mode 100644 index 00000000000..5b2ee55a10c --- /dev/null +++ b/thirdparty/opus/celt/arm/celt_pitch_xcorr_arm-gnu.S @@ -0,0 +1,551 @@ + .syntax unified +@ Copyright (c) 2007-2008 CSIRO +@ Copyright (c) 2007-2009 Xiph.Org Foundation +@ Copyright (c) 2013 Parrot +@ Written by Aurélien Zanelli +@ +@ Redistribution and use in source and binary forms, with or without +@ modification, are permitted provided that the following conditions +@ are met: +@ +@ - Redistributions of source code must retain the above copyright +@ notice, this list of conditions and the following disclaimer. +@ +@ - Redistributions in binary form must reproduce the above copyright +@ notice, this list of conditions and the following disclaimer in the +@ documentation and/or other materials provided with the distribution. +@ +@ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +@ ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +@ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +@ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER +@ OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +@ EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +@ PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +@ PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +@ LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +@ NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + .text; .p2align 2; .arch armv7-a + .fpu neon + .object_arch armv4t + + .include "celt/arm/armopts-gnu.S" + + .if OPUS_ARM_MAY_HAVE_EDSP + .global celt_pitch_xcorr_edsp + .endif + + .if OPUS_ARM_MAY_HAVE_NEON + .global celt_pitch_xcorr_neon + .endif + + .if OPUS_ARM_MAY_HAVE_NEON + +@ Compute sum[k]=sum(x[j]*y[j+k],j=0...len-1), k=0...3 +; xcorr_kernel_neon: @ PROC +xcorr_kernel_neon_start: + @ input: + @ r3 = int len + @ r4 = opus_val16 *x + @ r5 = opus_val16 *y + @ q0 = opus_val32 sum[4] + @ output: + @ q0 = opus_val32 sum[4] + @ preserved: r0-r3, r6-r11, d2, q4-q7, q9-q15 + @ internal usage: + @ r12 = int j + @ d3 = y_3|y_2|y_1|y_0 + @ q2 = y_B|y_A|y_9|y_8|y_7|y_6|y_5|y_4 + @ q3 = x_7|x_6|x_5|x_4|x_3|x_2|x_1|x_0 + @ q8 = scratch + @ + @ Load y[0...3] + @ This requires len>0 to always be valid (which we assert in the C code). + VLD1.16 {d5}, [r5]! + SUBS r12, r3, #8 + BLE xcorr_kernel_neon_process4 +@ Process 8 samples at a time. +@ This loop loads one y value more than we actually need. Therefore we have to +@ stop as soon as there are 8 or fewer samples left (instead of 7), to avoid +@ reading past the end of the array. +xcorr_kernel_neon_process8: + @ This loop has 19 total instructions (10 cycles to issue, minimum), with + @ - 2 cycles of ARM insrtuctions, + @ - 10 cycles of load/store/byte permute instructions, and + @ - 9 cycles of data processing instructions. + @ On a Cortex A8, we dual-issue the maximum amount (9 cycles) between the + @ latter two categories, meaning the whole loop should run in 10 cycles per + @ iteration, barring cache misses. + @ + @ Load x[0...7] + VLD1.16 {d6, d7}, [r4]! + @ Unlike VMOV, VAND is a data processsing instruction (and doesn't get + @ assembled to VMOV, like VORR would), so it dual-issues with the prior VLD1. + VAND d3, d5, d5 + SUBS r12, r12, #8 + @ Load y[4...11] + VLD1.16 {d4, d5}, [r5]! + VMLAL.S16 q0, d3, d6[0] + VEXT.16 d16, d3, d4, #1 + VMLAL.S16 q0, d4, d7[0] + VEXT.16 d17, d4, d5, #1 + VMLAL.S16 q0, d16, d6[1] + VEXT.16 d16, d3, d4, #2 + VMLAL.S16 q0, d17, d7[1] + VEXT.16 d17, d4, d5, #2 + VMLAL.S16 q0, d16, d6[2] + VEXT.16 d16, d3, d4, #3 + VMLAL.S16 q0, d17, d7[2] + VEXT.16 d17, d4, d5, #3 + VMLAL.S16 q0, d16, d6[3] + VMLAL.S16 q0, d17, d7[3] + BGT xcorr_kernel_neon_process8 +@ Process 4 samples here if we have > 4 left (still reading one extra y value). +xcorr_kernel_neon_process4: + ADDS r12, r12, #4 + BLE xcorr_kernel_neon_process2 + @ Load x[0...3] + VLD1.16 d6, [r4]! + @ Use VAND since it's a data processing instruction again. + VAND d4, d5, d5 + SUB r12, r12, #4 + @ Load y[4...7] + VLD1.16 d5, [r5]! + VMLAL.S16 q0, d4, d6[0] + VEXT.16 d16, d4, d5, #1 + VMLAL.S16 q0, d16, d6[1] + VEXT.16 d16, d4, d5, #2 + VMLAL.S16 q0, d16, d6[2] + VEXT.16 d16, d4, d5, #3 + VMLAL.S16 q0, d16, d6[3] +@ Process 2 samples here if we have > 2 left (still reading one extra y value). +xcorr_kernel_neon_process2: + ADDS r12, r12, #2 + BLE xcorr_kernel_neon_process1 + @ Load x[0...1] + VLD2.16 {d6[],d7[]}, [r4]! + @ Use VAND since it's a data processing instruction again. + VAND d4, d5, d5 + SUB r12, r12, #2 + @ Load y[4...5] + VLD1.32 {d5[]}, [r5]! + VMLAL.S16 q0, d4, d6 + VEXT.16 d16, d4, d5, #1 + @ Replace bottom copy of {y5,y4} in d5 with {y3,y2} from d4, using VSRI + @ instead of VEXT, since it's a data-processing instruction. + VSRI.64 d5, d4, #32 + VMLAL.S16 q0, d16, d7 +@ Process 1 sample using the extra y value we loaded above. +xcorr_kernel_neon_process1: + @ Load next *x + VLD1.16 {d6[]}, [r4]! + ADDS r12, r12, #1 + @ y[0...3] are left in d5 from prior iteration(s) (if any) + VMLAL.S16 q0, d5, d6 + MOVLE pc, lr +@ Now process 1 last sample, not reading ahead. + @ Load last *y + VLD1.16 {d4[]}, [r5]! + VSRI.64 d4, d5, #16 + @ Load last *x + VLD1.16 {d6[]}, [r4]! + VMLAL.S16 q0, d4, d6 + MOV pc, lr + .size xcorr_kernel_neon, .-xcorr_kernel_neon @ ENDP + +@ opus_val32 celt_pitch_xcorr_neon(opus_val16 *_x, opus_val16 *_y, +@ opus_val32 *xcorr, int len, int max_pitch) +; celt_pitch_xcorr_neon: @ PROC + @ input: + @ r0 = opus_val16 *_x + @ r1 = opus_val16 *_y + @ r2 = opus_val32 *xcorr + @ r3 = int len + @ output: + @ r0 = int maxcorr + @ internal usage: + @ r4 = opus_val16 *x (for xcorr_kernel_neon()) + @ r5 = opus_val16 *y (for xcorr_kernel_neon()) + @ r6 = int max_pitch + @ r12 = int j + @ q15 = int maxcorr[4] (q15 is not used by xcorr_kernel_neon()) + STMFD sp!, {r4-r6, lr} + LDR r6, [sp, #16] + VMOV.S32 q15, #1 + @ if (max_pitch < 4) goto celt_pitch_xcorr_neon_process4_done + SUBS r6, r6, #4 + BLT celt_pitch_xcorr_neon_process4_done +celt_pitch_xcorr_neon_process4: + @ xcorr_kernel_neon parameters: + @ r3 = len, r4 = _x, r5 = _y, q0 = {0, 0, 0, 0} + MOV r4, r0 + MOV r5, r1 + VEOR q0, q0, q0 + @ xcorr_kernel_neon only modifies r4, r5, r12, and q0...q3. + @ So we don't save/restore any other registers. + BL xcorr_kernel_neon_start + SUBS r6, r6, #4 + VST1.32 {q0}, [r2]! + @ _y += 4 + ADD r1, r1, #8 + VMAX.S32 q15, q15, q0 + @ if (max_pitch < 4) goto celt_pitch_xcorr_neon_process4_done + BGE celt_pitch_xcorr_neon_process4 +@ We have less than 4 sums left to compute. +celt_pitch_xcorr_neon_process4_done: + ADDS r6, r6, #4 + @ Reduce maxcorr to a single value + VMAX.S32 d30, d30, d31 + VPMAX.S32 d30, d30, d30 + @ if (max_pitch <= 0) goto celt_pitch_xcorr_neon_done + BLE celt_pitch_xcorr_neon_done +@ Now compute each remaining sum one at a time. +celt_pitch_xcorr_neon_process_remaining: + MOV r4, r0 + MOV r5, r1 + VMOV.I32 q0, #0 + SUBS r12, r3, #8 + BLT celt_pitch_xcorr_neon_process_remaining4 +@ Sum terms 8 at a time. +celt_pitch_xcorr_neon_process_remaining_loop8: + @ Load x[0...7] + VLD1.16 {q1}, [r4]! + @ Load y[0...7] + VLD1.16 {q2}, [r5]! + SUBS r12, r12, #8 + VMLAL.S16 q0, d4, d2 + VMLAL.S16 q0, d5, d3 + BGE celt_pitch_xcorr_neon_process_remaining_loop8 +@ Sum terms 4 at a time. +celt_pitch_xcorr_neon_process_remaining4: + ADDS r12, r12, #4 + BLT celt_pitch_xcorr_neon_process_remaining4_done + @ Load x[0...3] + VLD1.16 {d2}, [r4]! + @ Load y[0...3] + VLD1.16 {d3}, [r5]! + SUB r12, r12, #4 + VMLAL.S16 q0, d3, d2 +celt_pitch_xcorr_neon_process_remaining4_done: + @ Reduce the sum to a single value. + VADD.S32 d0, d0, d1 + VPADDL.S32 d0, d0 + ADDS r12, r12, #4 + BLE celt_pitch_xcorr_neon_process_remaining_loop_done +@ Sum terms 1 at a time. +celt_pitch_xcorr_neon_process_remaining_loop1: + VLD1.16 {d2[]}, [r4]! + VLD1.16 {d3[]}, [r5]! + SUBS r12, r12, #1 + VMLAL.S16 q0, d2, d3 + BGT celt_pitch_xcorr_neon_process_remaining_loop1 +celt_pitch_xcorr_neon_process_remaining_loop_done: + VST1.32 {d0[0]}, [r2]! + VMAX.S32 d30, d30, d0 + SUBS r6, r6, #1 + @ _y++ + ADD r1, r1, #2 + @ if (--max_pitch > 0) goto celt_pitch_xcorr_neon_process_remaining + BGT celt_pitch_xcorr_neon_process_remaining +celt_pitch_xcorr_neon_done: + VMOV.32 r0, d30[0] + LDMFD sp!, {r4-r6, pc} + .size celt_pitch_xcorr_neon, .-celt_pitch_xcorr_neon @ ENDP + + .endif + + .if OPUS_ARM_MAY_HAVE_EDSP + +@ This will get used on ARMv7 devices without NEON, so it has been optimized +@ to take advantage of dual-issuing where possible. +; xcorr_kernel_edsp: @ PROC +xcorr_kernel_edsp_start: + @ input: + @ r3 = int len + @ r4 = opus_val16 *_x (must be 32-bit aligned) + @ r5 = opus_val16 *_y (must be 32-bit aligned) + @ r6...r9 = opus_val32 sum[4] + @ output: + @ r6...r9 = opus_val32 sum[4] + @ preserved: r0-r5 + @ internal usage + @ r2 = int j + @ r12,r14 = opus_val16 x[4] + @ r10,r11 = opus_val16 y[4] + STMFD sp!, {r2,r4,r5,lr} + LDR r10, [r5], #4 @ Load y[0...1] + SUBS r2, r3, #4 @ j = len-4 + LDR r11, [r5], #4 @ Load y[2...3] + BLE xcorr_kernel_edsp_process4_done + LDR r12, [r4], #4 @ Load x[0...1] + @ Stall +xcorr_kernel_edsp_process4: + @ The multiplies must issue from pipeline 0, and can't dual-issue with each + @ other. Every other instruction here dual-issues with a multiply, and is + @ thus "free". There should be no stalls in the body of the loop. + SMLABB r6, r12, r10, r6 @ sum[0] = MAC16_16(sum[0],x_0,y_0) + LDR r14, [r4], #4 @ Load x[2...3] + SMLABT r7, r12, r10, r7 @ sum[1] = MAC16_16(sum[1],x_0,y_1) + SUBS r2, r2, #4 @ j-=4 + SMLABB r8, r12, r11, r8 @ sum[2] = MAC16_16(sum[2],x_0,y_2) + SMLABT r9, r12, r11, r9 @ sum[3] = MAC16_16(sum[3],x_0,y_3) + SMLATT r6, r12, r10, r6 @ sum[0] = MAC16_16(sum[0],x_1,y_1) + LDR r10, [r5], #4 @ Load y[4...5] + SMLATB r7, r12, r11, r7 @ sum[1] = MAC16_16(sum[1],x_1,y_2) + SMLATT r8, r12, r11, r8 @ sum[2] = MAC16_16(sum[2],x_1,y_3) + SMLATB r9, r12, r10, r9 @ sum[3] = MAC16_16(sum[3],x_1,y_4) + LDRGT r12, [r4], #4 @ Load x[0...1] + SMLABB r6, r14, r11, r6 @ sum[0] = MAC16_16(sum[0],x_2,y_2) + SMLABT r7, r14, r11, r7 @ sum[1] = MAC16_16(sum[1],x_2,y_3) + SMLABB r8, r14, r10, r8 @ sum[2] = MAC16_16(sum[2],x_2,y_4) + SMLABT r9, r14, r10, r9 @ sum[3] = MAC16_16(sum[3],x_2,y_5) + SMLATT r6, r14, r11, r6 @ sum[0] = MAC16_16(sum[0],x_3,y_3) + LDR r11, [r5], #4 @ Load y[6...7] + SMLATB r7, r14, r10, r7 @ sum[1] = MAC16_16(sum[1],x_3,y_4) + SMLATT r8, r14, r10, r8 @ sum[2] = MAC16_16(sum[2],x_3,y_5) + SMLATB r9, r14, r11, r9 @ sum[3] = MAC16_16(sum[3],x_3,y_6) + BGT xcorr_kernel_edsp_process4 +xcorr_kernel_edsp_process4_done: + ADDS r2, r2, #4 + BLE xcorr_kernel_edsp_done + LDRH r12, [r4], #2 @ r12 = *x++ + SUBS r2, r2, #1 @ j-- + @ Stall + SMLABB r6, r12, r10, r6 @ sum[0] = MAC16_16(sum[0],x,y_0) + LDRHGT r14, [r4], #2 @ r14 = *x++ + SMLABT r7, r12, r10, r7 @ sum[1] = MAC16_16(sum[1],x,y_1) + SMLABB r8, r12, r11, r8 @ sum[2] = MAC16_16(sum[2],x,y_2) + SMLABT r9, r12, r11, r9 @ sum[3] = MAC16_16(sum[3],x,y_3) + BLE xcorr_kernel_edsp_done + SMLABT r6, r14, r10, r6 @ sum[0] = MAC16_16(sum[0],x,y_1) + SUBS r2, r2, #1 @ j-- + SMLABB r7, r14, r11, r7 @ sum[1] = MAC16_16(sum[1],x,y_2) + LDRH r10, [r5], #2 @ r10 = y_4 = *y++ + SMLABT r8, r14, r11, r8 @ sum[2] = MAC16_16(sum[2],x,y_3) + LDRHGT r12, [r4], #2 @ r12 = *x++ + SMLABB r9, r14, r10, r9 @ sum[3] = MAC16_16(sum[3],x,y_4) + BLE xcorr_kernel_edsp_done + SMLABB r6, r12, r11, r6 @ sum[0] = MAC16_16(sum[0],tmp,y_2) + CMP r2, #1 @ j-- + SMLABT r7, r12, r11, r7 @ sum[1] = MAC16_16(sum[1],tmp,y_3) + LDRH r2, [r5], #2 @ r2 = y_5 = *y++ + SMLABB r8, r12, r10, r8 @ sum[2] = MAC16_16(sum[2],tmp,y_4) + LDRHGT r14, [r4] @ r14 = *x + SMLABB r9, r12, r2, r9 @ sum[3] = MAC16_16(sum[3],tmp,y_5) + BLE xcorr_kernel_edsp_done + SMLABT r6, r14, r11, r6 @ sum[0] = MAC16_16(sum[0],tmp,y_3) + LDRH r11, [r5] @ r11 = y_6 = *y + SMLABB r7, r14, r10, r7 @ sum[1] = MAC16_16(sum[1],tmp,y_4) + SMLABB r8, r14, r2, r8 @ sum[2] = MAC16_16(sum[2],tmp,y_5) + SMLABB r9, r14, r11, r9 @ sum[3] = MAC16_16(sum[3],tmp,y_6) +xcorr_kernel_edsp_done: + LDMFD sp!, {r2,r4,r5,pc} + .size xcorr_kernel_edsp, .-xcorr_kernel_edsp @ ENDP + +; celt_pitch_xcorr_edsp: @ PROC + @ input: + @ r0 = opus_val16 *_x (must be 32-bit aligned) + @ r1 = opus_val16 *_y (only needs to be 16-bit aligned) + @ r2 = opus_val32 *xcorr + @ r3 = int len + @ output: + @ r0 = maxcorr + @ internal usage + @ r4 = opus_val16 *x + @ r5 = opus_val16 *y + @ r6 = opus_val32 sum0 + @ r7 = opus_val32 sum1 + @ r8 = opus_val32 sum2 + @ r9 = opus_val32 sum3 + @ r1 = int max_pitch + @ r12 = int j + STMFD sp!, {r4-r11, lr} + MOV r5, r1 + LDR r1, [sp, #36] + MOV r4, r0 + TST r5, #3 + @ maxcorr = 1 + MOV r0, #1 + BEQ celt_pitch_xcorr_edsp_process1u_done +@ Compute one sum at the start to make y 32-bit aligned. + SUBS r12, r3, #4 + @ r14 = sum = 0 + MOV r14, #0 + LDRH r8, [r5], #2 + BLE celt_pitch_xcorr_edsp_process1u_loop4_done + LDR r6, [r4], #4 + MOV r8, r8, LSL #16 +celt_pitch_xcorr_edsp_process1u_loop4: + LDR r9, [r5], #4 + SMLABT r14, r6, r8, r14 @ sum = MAC16_16(sum, x_0, y_0) + LDR r7, [r4], #4 + SMLATB r14, r6, r9, r14 @ sum = MAC16_16(sum, x_1, y_1) + LDR r8, [r5], #4 + SMLABT r14, r7, r9, r14 @ sum = MAC16_16(sum, x_2, y_2) + SUBS r12, r12, #4 @ j-=4 + SMLATB r14, r7, r8, r14 @ sum = MAC16_16(sum, x_3, y_3) + LDRGT r6, [r4], #4 + BGT celt_pitch_xcorr_edsp_process1u_loop4 + MOV r8, r8, LSR #16 +celt_pitch_xcorr_edsp_process1u_loop4_done: + ADDS r12, r12, #4 +celt_pitch_xcorr_edsp_process1u_loop1: + LDRHGE r6, [r4], #2 + @ Stall + SMLABBGE r14, r6, r8, r14 @ sum = MAC16_16(sum, *x, *y) + SUBSGE r12, r12, #1 + LDRHGT r8, [r5], #2 + BGT celt_pitch_xcorr_edsp_process1u_loop1 + @ Restore _x + SUB r4, r4, r3, LSL #1 + @ Restore and advance _y + SUB r5, r5, r3, LSL #1 + @ maxcorr = max(maxcorr, sum) + CMP r0, r14 + ADD r5, r5, #2 + MOVLT r0, r14 + SUBS r1, r1, #1 + @ xcorr[i] = sum + STR r14, [r2], #4 + BLE celt_pitch_xcorr_edsp_done +celt_pitch_xcorr_edsp_process1u_done: + @ if (max_pitch < 4) goto celt_pitch_xcorr_edsp_process2 + SUBS r1, r1, #4 + BLT celt_pitch_xcorr_edsp_process2 +celt_pitch_xcorr_edsp_process4: + @ xcorr_kernel_edsp parameters: + @ r3 = len, r4 = _x, r5 = _y, r6...r9 = sum[4] = {0, 0, 0, 0} + MOV r6, #0 + MOV r7, #0 + MOV r8, #0 + MOV r9, #0 + BL xcorr_kernel_edsp_start @ xcorr_kernel_edsp(_x, _y+i, xcorr+i, len) + @ maxcorr = max(maxcorr, sum0, sum1, sum2, sum3) + CMP r0, r6 + @ _y+=4 + ADD r5, r5, #8 + MOVLT r0, r6 + CMP r0, r7 + MOVLT r0, r7 + CMP r0, r8 + MOVLT r0, r8 + CMP r0, r9 + MOVLT r0, r9 + STMIA r2!, {r6-r9} + SUBS r1, r1, #4 + BGE celt_pitch_xcorr_edsp_process4 +celt_pitch_xcorr_edsp_process2: + ADDS r1, r1, #2 + BLT celt_pitch_xcorr_edsp_process1a + SUBS r12, r3, #4 + @ {r10, r11} = {sum0, sum1} = {0, 0} + MOV r10, #0 + MOV r11, #0 + LDR r8, [r5], #4 + BLE celt_pitch_xcorr_edsp_process2_loop_done + LDR r6, [r4], #4 + LDR r9, [r5], #4 +celt_pitch_xcorr_edsp_process2_loop4: + SMLABB r10, r6, r8, r10 @ sum0 = MAC16_16(sum0, x_0, y_0) + LDR r7, [r4], #4 + SMLABT r11, r6, r8, r11 @ sum1 = MAC16_16(sum1, x_0, y_1) + SUBS r12, r12, #4 @ j-=4 + SMLATT r10, r6, r8, r10 @ sum0 = MAC16_16(sum0, x_1, y_1) + LDR r8, [r5], #4 + SMLATB r11, r6, r9, r11 @ sum1 = MAC16_16(sum1, x_1, y_2) + LDRGT r6, [r4], #4 + SMLABB r10, r7, r9, r10 @ sum0 = MAC16_16(sum0, x_2, y_2) + SMLABT r11, r7, r9, r11 @ sum1 = MAC16_16(sum1, x_2, y_3) + SMLATT r10, r7, r9, r10 @ sum0 = MAC16_16(sum0, x_3, y_3) + LDRGT r9, [r5], #4 + SMLATB r11, r7, r8, r11 @ sum1 = MAC16_16(sum1, x_3, y_4) + BGT celt_pitch_xcorr_edsp_process2_loop4 +celt_pitch_xcorr_edsp_process2_loop_done: + ADDS r12, r12, #2 + BLE celt_pitch_xcorr_edsp_process2_1 + LDR r6, [r4], #4 + @ Stall + SMLABB r10, r6, r8, r10 @ sum0 = MAC16_16(sum0, x_0, y_0) + LDR r9, [r5], #4 + SMLABT r11, r6, r8, r11 @ sum1 = MAC16_16(sum1, x_0, y_1) + SUB r12, r12, #2 + SMLATT r10, r6, r8, r10 @ sum0 = MAC16_16(sum0, x_1, y_1) + MOV r8, r9 + SMLATB r11, r6, r9, r11 @ sum1 = MAC16_16(sum1, x_1, y_2) +celt_pitch_xcorr_edsp_process2_1: + LDRH r6, [r4], #2 + ADDS r12, r12, #1 + @ Stall + SMLABB r10, r6, r8, r10 @ sum0 = MAC16_16(sum0, x_0, y_0) + LDRHGT r7, [r4], #2 + SMLABT r11, r6, r8, r11 @ sum1 = MAC16_16(sum1, x_0, y_1) + BLE celt_pitch_xcorr_edsp_process2_done + LDRH r9, [r5], #2 + SMLABT r10, r7, r8, r10 @ sum0 = MAC16_16(sum0, x_0, y_1) + SMLABB r11, r7, r9, r11 @ sum1 = MAC16_16(sum1, x_0, y_2) +celt_pitch_xcorr_edsp_process2_done: + @ Restore _x + SUB r4, r4, r3, LSL #1 + @ Restore and advance _y + SUB r5, r5, r3, LSL #1 + @ maxcorr = max(maxcorr, sum0) + CMP r0, r10 + ADD r5, r5, #2 + MOVLT r0, r10 + SUB r1, r1, #2 + @ maxcorr = max(maxcorr, sum1) + CMP r0, r11 + @ xcorr[i] = sum + STR r10, [r2], #4 + MOVLT r0, r11 + STR r11, [r2], #4 +celt_pitch_xcorr_edsp_process1a: + ADDS r1, r1, #1 + BLT celt_pitch_xcorr_edsp_done + SUBS r12, r3, #4 + @ r14 = sum = 0 + MOV r14, #0 + BLT celt_pitch_xcorr_edsp_process1a_loop_done + LDR r6, [r4], #4 + LDR r8, [r5], #4 + LDR r7, [r4], #4 + LDR r9, [r5], #4 +celt_pitch_xcorr_edsp_process1a_loop4: + SMLABB r14, r6, r8, r14 @ sum = MAC16_16(sum, x_0, y_0) + SUBS r12, r12, #4 @ j-=4 + SMLATT r14, r6, r8, r14 @ sum = MAC16_16(sum, x_1, y_1) + LDRGE r6, [r4], #4 + SMLABB r14, r7, r9, r14 @ sum = MAC16_16(sum, x_2, y_2) + LDRGE r8, [r5], #4 + SMLATT r14, r7, r9, r14 @ sum = MAC16_16(sum, x_3, y_3) + LDRGE r7, [r4], #4 + LDRGE r9, [r5], #4 + BGE celt_pitch_xcorr_edsp_process1a_loop4 +celt_pitch_xcorr_edsp_process1a_loop_done: + ADDS r12, r12, #2 + LDRGE r6, [r4], #4 + LDRGE r8, [r5], #4 + @ Stall + SMLABBGE r14, r6, r8, r14 @ sum = MAC16_16(sum, x_0, y_0) + SUBGE r12, r12, #2 + SMLATTGE r14, r6, r8, r14 @ sum = MAC16_16(sum, x_1, y_1) + ADDS r12, r12, #1 + LDRHGE r6, [r4], #2 + LDRHGE r8, [r5], #2 + @ Stall + SMLABBGE r14, r6, r8, r14 @ sum = MAC16_16(sum, *x, *y) + @ maxcorr = max(maxcorr, sum) + CMP r0, r14 + @ xcorr[i] = sum + STR r14, [r2], #4 + MOVLT r0, r14 +celt_pitch_xcorr_edsp_done: + LDMFD sp!, {r4-r11, pc} + .size celt_pitch_xcorr_edsp, .-celt_pitch_xcorr_edsp @ ENDP + + .endif + +@ END: + .section .note.GNU-stack,"",%progbits diff --git a/thirdparty/opus/celt/arm/celt_pitch_xcorr_arm.s b/thirdparty/opus/celt/arm/celt_pitch_xcorr_arm.s index 6e873afc371..f96e0a88bbe 100644 --- a/thirdparty/opus/celt/arm/celt_pitch_xcorr_arm.s +++ b/thirdparty/opus/celt/arm/celt_pitch_xcorr_arm.s @@ -153,7 +153,7 @@ xcorr_kernel_neon_process1 ENDP ; opus_val32 celt_pitch_xcorr_neon(opus_val16 *_x, opus_val16 *_y, -; opus_val32 *xcorr, int len, int max_pitch, int arch) +; opus_val32 *xcorr, int len, int max_pitch) celt_pitch_xcorr_neon PROC ; input: ; r0 = opus_val16 *_x @@ -168,8 +168,6 @@ celt_pitch_xcorr_neon PROC ; r6 = int max_pitch ; r12 = int j ; q15 = int maxcorr[4] (q15 is not used by xcorr_kernel_neon()) - ; ignored: - ; int arch STMFD sp!, {r4-r6, lr} LDR r6, [sp, #16] VMOV.S32 q15, #1 @@ -360,8 +358,6 @@ celt_pitch_xcorr_edsp PROC ; r9 = opus_val32 sum3 ; r1 = int max_pitch ; r12 = int j - ; ignored: - ; int arch STMFD sp!, {r4-r11, lr} MOV r5, r1 LDR r1, [sp, #36] diff --git a/thirdparty/opus/celt/arm/fft_arm.h b/thirdparty/opus/celt/arm/fft_arm.h index 0b78175f3a9..0cb55d8e22d 100644 --- a/thirdparty/opus/celt/arm/fft_arm.h +++ b/thirdparty/opus/celt/arm/fft_arm.h @@ -34,6 +34,7 @@ #if !defined(FFT_ARM_H) #define FFT_ARM_H +#include "config.h" #include "kiss_fft.h" #if defined(HAVE_ARM_NE10) diff --git a/thirdparty/opus/celt/arm/fixed_armv4.h b/thirdparty/opus/celt/arm/fixed_armv4.h index d84888a772a..efb3b1896a8 100644 --- a/thirdparty/opus/celt/arm/fixed_armv4.h +++ b/thirdparty/opus/celt/arm/fixed_armv4.h @@ -37,7 +37,7 @@ static OPUS_INLINE opus_val32 MULT16_32_Q16_armv4(opus_val16 a, opus_val32 b) "#MULT16_32_Q16\n\t" "smull %0, %1, %2, %3\n\t" : "=&r"(rd_lo), "=&r"(rd_hi) - : "%r"(b),"r"(SHL32(a,16)) + : "%r"(b),"r"(a<<16) ); return rd_hi; } @@ -54,10 +54,10 @@ static OPUS_INLINE opus_val32 MULT16_32_Q15_armv4(opus_val16 a, opus_val32 b) "#MULT16_32_Q15\n\t" "smull %0, %1, %2, %3\n\t" : "=&r"(rd_lo), "=&r"(rd_hi) - : "%r"(b), "r"(SHL32(a,16)) + : "%r"(b), "r"(a<<16) ); /*We intentionally don't OR in the high bit of rd_lo for speed.*/ - return SHL32(rd_hi,1); + return rd_hi<<1; } #define MULT16_32_Q15(a, b) (MULT16_32_Q15_armv4(a, b)) diff --git a/thirdparty/opus/celt/arm/fixed_armv5e.h b/thirdparty/opus/celt/arm/fixed_armv5e.h index 6bf73cbace3..36a63211013 100644 --- a/thirdparty/opus/celt/arm/fixed_armv5e.h +++ b/thirdparty/opus/celt/arm/fixed_armv5e.h @@ -59,7 +59,7 @@ static OPUS_INLINE opus_val32 MULT16_32_Q15_armv5e(opus_val16 a, opus_val32 b) : "=r"(res) : "r"(b), "r"(a) ); - return SHL32(res,1); + return res<<1; } #define MULT16_32_Q15(a, b) (MULT16_32_Q15_armv5e(a, b)) @@ -76,7 +76,7 @@ static OPUS_INLINE opus_val32 MAC16_32_Q15_armv5e(opus_val32 c, opus_val16 a, "#MAC16_32_Q15\n\t" "smlawb %0, %1, %2, %3;\n" : "=r"(res) - : "r"(SHL32(b,1)), "r"(a), "r"(c) + : "r"(b<<1), "r"(a), "r"(c) ); return res; } diff --git a/thirdparty/opus/celt/arm/mdct_arm.h b/thirdparty/opus/celt/arm/mdct_arm.h index 14200bac4b3..49cbb445760 100644 --- a/thirdparty/opus/celt/arm/mdct_arm.h +++ b/thirdparty/opus/celt/arm/mdct_arm.h @@ -33,6 +33,7 @@ #if !defined(MDCT_ARM_H) #define MDCT_ARM_H +#include "config.h" #include "mdct.h" #if defined(HAVE_ARM_NE10) diff --git a/thirdparty/opus/celt/arm/pitch_arm.h b/thirdparty/opus/celt/arm/pitch_arm.h index bed8b04eac1..14331169eeb 100644 --- a/thirdparty/opus/celt/arm/pitch_arm.h +++ b/thirdparty/opus/celt/arm/pitch_arm.h @@ -30,47 +30,11 @@ # include "armcpu.h" -# if defined(OPUS_ARM_MAY_HAVE_NEON_INTR) -opus_val32 celt_inner_prod_neon(const opus_val16 *x, const opus_val16 *y, int N); -void dual_inner_prod_neon(const opus_val16 *x, const opus_val16 *y01, - const opus_val16 *y02, int N, opus_val32 *xy1, opus_val32 *xy2); - -# if !defined(OPUS_HAVE_RTCD) && defined(OPUS_ARM_PRESUME_NEON) -# define OVERRIDE_CELT_INNER_PROD (1) -# define OVERRIDE_DUAL_INNER_PROD (1) -# define celt_inner_prod(x, y, N, arch) ((void)(arch), PRESUME_NEON(celt_inner_prod)(x, y, N)) -# define dual_inner_prod(x, y01, y02, N, xy1, xy2, arch) ((void)(arch), PRESUME_NEON(dual_inner_prod)(x, y01, y02, N, xy1, xy2)) -# endif -# endif - -# if !defined(OVERRIDE_CELT_INNER_PROD) -# if defined(OPUS_HAVE_RTCD) && (defined(OPUS_ARM_MAY_HAVE_NEON_INTR) && !defined(OPUS_ARM_PRESUME_NEON_INTR)) -extern opus_val32 (*const CELT_INNER_PROD_IMPL[OPUS_ARCHMASK+1])(const opus_val16 *x, const opus_val16 *y, int N); -# define OVERRIDE_CELT_INNER_PROD (1) -# define celt_inner_prod(x, y, N, arch) ((*CELT_INNER_PROD_IMPL[(arch)&OPUS_ARCHMASK])(x, y, N)) -# elif defined(OPUS_ARM_PRESUME_NEON_INTR) -# define OVERRIDE_CELT_INNER_PROD (1) -# define celt_inner_prod(x, y, N, arch) ((void)(arch), celt_inner_prod_neon(x, y, N)) -# endif -# endif - -# if !defined(OVERRIDE_DUAL_INNER_PROD) -# if defined(OPUS_HAVE_RTCD) && (defined(OPUS_ARM_MAY_HAVE_NEON_INTR) && !defined(OPUS_ARM_PRESUME_NEON_INTR)) -extern void (*const DUAL_INNER_PROD_IMPL[OPUS_ARCHMASK+1])(const opus_val16 *x, - const opus_val16 *y01, const opus_val16 *y02, int N, opus_val32 *xy1, opus_val32 *xy2); -# define OVERRIDE_DUAL_INNER_PROD (1) -# define dual_inner_prod(x, y01, y02, N, xy1, xy2, arch) ((*DUAL_INNER_PROD_IMPL[(arch)&OPUS_ARCHMASK])(x, y01, y02, N, xy1, xy2)) -# elif defined(OPUS_ARM_PRESUME_NEON_INTR) -# define OVERRIDE_DUAL_INNER_PROD (1) -# define dual_inner_prod(x, y01, y02, N, xy1, xy2, arch) ((void)(arch), dual_inner_prod_neon(x, y01, y02, N, xy1, xy2)) -# endif -# endif - # if defined(FIXED_POINT) # if defined(OPUS_ARM_MAY_HAVE_NEON) opus_val32 celt_pitch_xcorr_neon(const opus_val16 *_x, const opus_val16 *_y, - opus_val32 *xcorr, int len, int max_pitch, int arch); + opus_val32 *xcorr, int len, int max_pitch); # endif # if defined(OPUS_ARM_MAY_HAVE_MEDIA) @@ -79,7 +43,7 @@ opus_val32 celt_pitch_xcorr_neon(const opus_val16 *_x, const opus_val16 *_y, # if defined(OPUS_ARM_MAY_HAVE_EDSP) opus_val32 celt_pitch_xcorr_edsp(const opus_val16 *_x, const opus_val16 *_y, - opus_val32 *xcorr, int len, int max_pitch, int arch); + opus_val32 *xcorr, int len, int max_pitch); # endif # if defined(OPUS_HAVE_RTCD) && \ @@ -88,17 +52,18 @@ opus_val32 celt_pitch_xcorr_edsp(const opus_val16 *_x, const opus_val16 *_y, (defined(OPUS_ARM_MAY_HAVE_EDSP) && !defined(OPUS_ARM_PRESUME_EDSP))) extern opus_val32 (*const CELT_PITCH_XCORR_IMPL[OPUS_ARCHMASK+1])(const opus_val16 *, - const opus_val16 *, opus_val32 *, int, int, int); + const opus_val16 *, opus_val32 *, int, int); # define OVERRIDE_PITCH_XCORR (1) # define celt_pitch_xcorr(_x, _y, xcorr, len, max_pitch, arch) \ ((*CELT_PITCH_XCORR_IMPL[(arch)&OPUS_ARCHMASK])(_x, _y, \ - xcorr, len, max_pitch, arch)) + xcorr, len, max_pitch)) # elif defined(OPUS_ARM_PRESUME_EDSP) || \ defined(OPUS_ARM_PRESUME_MEDIA) || \ defined(OPUS_ARM_PRESUME_NEON) # define OVERRIDE_PITCH_XCORR (1) -# define celt_pitch_xcorr (PRESUME_NEON(celt_pitch_xcorr)) +# define celt_pitch_xcorr(_x, _y, xcorr, len, max_pitch, arch) \ + ((void)(arch),PRESUME_NEON(celt_pitch_xcorr)(_x, _y, xcorr, len, max_pitch)) # endif @@ -134,24 +99,25 @@ extern void (*const XCORR_KERNEL_IMPL[OPUS_ARCHMASK + 1])( /* Float case */ #if defined(OPUS_ARM_MAY_HAVE_NEON_INTR) void celt_pitch_xcorr_float_neon(const opus_val16 *_x, const opus_val16 *_y, - opus_val32 *xcorr, int len, int max_pitch, int arch); + opus_val32 *xcorr, int len, int max_pitch); #endif # if defined(OPUS_HAVE_RTCD) && \ (defined(OPUS_ARM_MAY_HAVE_NEON_INTR) && !defined(OPUS_ARM_PRESUME_NEON_INTR)) extern void (*const CELT_PITCH_XCORR_IMPL[OPUS_ARCHMASK+1])(const opus_val16 *, - const opus_val16 *, opus_val32 *, int, int, int); + const opus_val16 *, opus_val32 *, int, int); # define OVERRIDE_PITCH_XCORR (1) # define celt_pitch_xcorr(_x, _y, xcorr, len, max_pitch, arch) \ ((*CELT_PITCH_XCORR_IMPL[(arch)&OPUS_ARCHMASK])(_x, _y, \ - xcorr, len, max_pitch, arch)) + xcorr, len, max_pitch)) # elif defined(OPUS_ARM_PRESUME_NEON_INTR) # define OVERRIDE_PITCH_XCORR (1) -# define celt_pitch_xcorr celt_pitch_xcorr_float_neon +# define celt_pitch_xcorr(_x, _y, xcorr, len, max_pitch, arch) \ + ((void)(arch),celt_pitch_xcorr_float_neon(_x, _y, xcorr, len, max_pitch)) # endif diff --git a/thirdparty/opus/celt/arm/pitch_neon_intr.c b/thirdparty/opus/celt/arm/pitch_neon_intr.c deleted file mode 100644 index 1ac38c433a8..00000000000 --- a/thirdparty/opus/celt/arm/pitch_neon_intr.c +++ /dev/null @@ -1,290 +0,0 @@ -/*********************************************************************** -Copyright (c) 2017 Google Inc. -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions -are met: -- Redistributions of source code must retain the above copyright notice, -this list of conditions and the following disclaimer. -- Redistributions in binary form must reproduce the above copyright -notice, this list of conditions and the following disclaimer in the -documentation and/or other materials provided with the distribution. -- Neither the name of Internet Society, IETF or IETF Trust, nor the -names of specific contributors, may be used to endorse or promote -products derived from this software without specific prior written -permission. -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -POSSIBILITY OF SUCH DAMAGE. -***********************************************************************/ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include -#include "pitch.h" - -#ifdef FIXED_POINT - -opus_val32 celt_inner_prod_neon(const opus_val16 *x, const opus_val16 *y, int N) -{ - int i; - opus_val32 xy; - int16x8_t x_s16x8, y_s16x8; - int32x4_t xy_s32x4 = vdupq_n_s32(0); - int64x2_t xy_s64x2; - int64x1_t xy_s64x1; - - for (i = 0; i < N - 7; i += 8) { - x_s16x8 = vld1q_s16(&x[i]); - y_s16x8 = vld1q_s16(&y[i]); - xy_s32x4 = vmlal_s16(xy_s32x4, vget_low_s16 (x_s16x8), vget_low_s16 (y_s16x8)); - xy_s32x4 = vmlal_s16(xy_s32x4, vget_high_s16(x_s16x8), vget_high_s16(y_s16x8)); - } - - if (N - i >= 4) { - const int16x4_t x_s16x4 = vld1_s16(&x[i]); - const int16x4_t y_s16x4 = vld1_s16(&y[i]); - xy_s32x4 = vmlal_s16(xy_s32x4, x_s16x4, y_s16x4); - i += 4; - } - - xy_s64x2 = vpaddlq_s32(xy_s32x4); - xy_s64x1 = vadd_s64(vget_low_s64(xy_s64x2), vget_high_s64(xy_s64x2)); - xy = vget_lane_s32(vreinterpret_s32_s64(xy_s64x1), 0); - - for (; i < N; i++) { - xy = MAC16_16(xy, x[i], y[i]); - } - -#ifdef OPUS_CHECK_ASM - celt_assert(celt_inner_prod_c(x, y, N) == xy); -#endif - - return xy; -} - -void dual_inner_prod_neon(const opus_val16 *x, const opus_val16 *y01, const opus_val16 *y02, - int N, opus_val32 *xy1, opus_val32 *xy2) -{ - int i; - opus_val32 xy01, xy02; - int16x8_t x_s16x8, y01_s16x8, y02_s16x8; - int32x4_t xy01_s32x4 = vdupq_n_s32(0); - int32x4_t xy02_s32x4 = vdupq_n_s32(0); - int64x2_t xy01_s64x2, xy02_s64x2; - int64x1_t xy01_s64x1, xy02_s64x1; - - for (i = 0; i < N - 7; i += 8) { - x_s16x8 = vld1q_s16(&x[i]); - y01_s16x8 = vld1q_s16(&y01[i]); - y02_s16x8 = vld1q_s16(&y02[i]); - xy01_s32x4 = vmlal_s16(xy01_s32x4, vget_low_s16 (x_s16x8), vget_low_s16 (y01_s16x8)); - xy02_s32x4 = vmlal_s16(xy02_s32x4, vget_low_s16 (x_s16x8), vget_low_s16 (y02_s16x8)); - xy01_s32x4 = vmlal_s16(xy01_s32x4, vget_high_s16(x_s16x8), vget_high_s16(y01_s16x8)); - xy02_s32x4 = vmlal_s16(xy02_s32x4, vget_high_s16(x_s16x8), vget_high_s16(y02_s16x8)); - } - - if (N - i >= 4) { - const int16x4_t x_s16x4 = vld1_s16(&x[i]); - const int16x4_t y01_s16x4 = vld1_s16(&y01[i]); - const int16x4_t y02_s16x4 = vld1_s16(&y02[i]); - xy01_s32x4 = vmlal_s16(xy01_s32x4, x_s16x4, y01_s16x4); - xy02_s32x4 = vmlal_s16(xy02_s32x4, x_s16x4, y02_s16x4); - i += 4; - } - - xy01_s64x2 = vpaddlq_s32(xy01_s32x4); - xy02_s64x2 = vpaddlq_s32(xy02_s32x4); - xy01_s64x1 = vadd_s64(vget_low_s64(xy01_s64x2), vget_high_s64(xy01_s64x2)); - xy02_s64x1 = vadd_s64(vget_low_s64(xy02_s64x2), vget_high_s64(xy02_s64x2)); - xy01 = vget_lane_s32(vreinterpret_s32_s64(xy01_s64x1), 0); - xy02 = vget_lane_s32(vreinterpret_s32_s64(xy02_s64x1), 0); - - for (; i < N; i++) { - xy01 = MAC16_16(xy01, x[i], y01[i]); - xy02 = MAC16_16(xy02, x[i], y02[i]); - } - *xy1 = xy01; - *xy2 = xy02; - -#ifdef OPUS_CHECK_ASM - { - opus_val32 xy1_c, xy2_c; - dual_inner_prod_c(x, y01, y02, N, &xy1_c, &xy2_c); - celt_assert(xy1_c == *xy1); - celt_assert(xy2_c == *xy2); - } -#endif -} - -#else /* !FIXED_POINT */ - -/* ========================================================================== */ - -#ifdef OPUS_CHECK_ASM - -/* This part of code simulates floating-point NEON operations. */ - -/* celt_inner_prod_neon_float_c_simulation() simulates the floating-point */ -/* operations of celt_inner_prod_neon(), and both functions should have bit */ -/* exact output. */ -static opus_val32 celt_inner_prod_neon_float_c_simulation(const opus_val16 *x, const opus_val16 *y, int N) -{ - int i; - opus_val32 xy, xy0 = 0, xy1 = 0, xy2 = 0, xy3 = 0; - for (i = 0; i < N - 3; i += 4) { - xy0 = MAC16_16(xy0, x[i + 0], y[i + 0]); - xy1 = MAC16_16(xy1, x[i + 1], y[i + 1]); - xy2 = MAC16_16(xy2, x[i + 2], y[i + 2]); - xy3 = MAC16_16(xy3, x[i + 3], y[i + 3]); - } - xy0 += xy2; - xy1 += xy3; - xy = xy0 + xy1; - for (; i < N; i++) { - xy = MAC16_16(xy, x[i], y[i]); - } - return xy; -} - -/* dual_inner_prod_neon_float_c_simulation() simulates the floating-point */ -/* operations of dual_inner_prod_neon(), and both functions should have bit */ -/* exact output. */ -static void dual_inner_prod_neon_float_c_simulation(const opus_val16 *x, const opus_val16 *y01, const opus_val16 *y02, - int N, opus_val32 *xy1, opus_val32 *xy2) -{ - int i; - opus_val32 xy01, xy02, xy01_0 = 0, xy01_1 = 0, xy01_2 = 0, xy01_3 = 0, xy02_0 = 0, xy02_1 = 0, xy02_2 = 0, xy02_3 = 0; - for (i = 0; i < N - 3; i += 4) { - xy01_0 = MAC16_16(xy01_0, x[i + 0], y01[i + 0]); - xy01_1 = MAC16_16(xy01_1, x[i + 1], y01[i + 1]); - xy01_2 = MAC16_16(xy01_2, x[i + 2], y01[i + 2]); - xy01_3 = MAC16_16(xy01_3, x[i + 3], y01[i + 3]); - xy02_0 = MAC16_16(xy02_0, x[i + 0], y02[i + 0]); - xy02_1 = MAC16_16(xy02_1, x[i + 1], y02[i + 1]); - xy02_2 = MAC16_16(xy02_2, x[i + 2], y02[i + 2]); - xy02_3 = MAC16_16(xy02_3, x[i + 3], y02[i + 3]); - } - xy01_0 += xy01_2; - xy02_0 += xy02_2; - xy01_1 += xy01_3; - xy02_1 += xy02_3; - xy01 = xy01_0 + xy01_1; - xy02 = xy02_0 + xy02_1; - for (; i < N; i++) { - xy01 = MAC16_16(xy01, x[i], y01[i]); - xy02 = MAC16_16(xy02, x[i], y02[i]); - } - *xy1 = xy01; - *xy2 = xy02; -} - -#endif /* OPUS_CHECK_ASM */ - -/* ========================================================================== */ - -opus_val32 celt_inner_prod_neon(const opus_val16 *x, const opus_val16 *y, int N) -{ - int i; - opus_val32 xy; - float32x4_t xy_f32x4 = vdupq_n_f32(0); - float32x2_t xy_f32x2; - - for (i = 0; i < N - 7; i += 8) { - float32x4_t x_f32x4, y_f32x4; - x_f32x4 = vld1q_f32(&x[i]); - y_f32x4 = vld1q_f32(&y[i]); - xy_f32x4 = vmlaq_f32(xy_f32x4, x_f32x4, y_f32x4); - x_f32x4 = vld1q_f32(&x[i + 4]); - y_f32x4 = vld1q_f32(&y[i + 4]); - xy_f32x4 = vmlaq_f32(xy_f32x4, x_f32x4, y_f32x4); - } - - if (N - i >= 4) { - const float32x4_t x_f32x4 = vld1q_f32(&x[i]); - const float32x4_t y_f32x4 = vld1q_f32(&y[i]); - xy_f32x4 = vmlaq_f32(xy_f32x4, x_f32x4, y_f32x4); - i += 4; - } - - xy_f32x2 = vadd_f32(vget_low_f32(xy_f32x4), vget_high_f32(xy_f32x4)); - xy_f32x2 = vpadd_f32(xy_f32x2, xy_f32x2); - xy = vget_lane_f32(xy_f32x2, 0); - - for (; i < N; i++) { - xy = MAC16_16(xy, x[i], y[i]); - } - -#ifdef OPUS_CHECK_ASM - celt_assert(ABS32(celt_inner_prod_neon_float_c_simulation(x, y, N) - xy) <= VERY_SMALL); -#endif - - return xy; -} - -void dual_inner_prod_neon(const opus_val16 *x, const opus_val16 *y01, const opus_val16 *y02, - int N, opus_val32 *xy1, opus_val32 *xy2) -{ - int i; - opus_val32 xy01, xy02; - float32x4_t xy01_f32x4 = vdupq_n_f32(0); - float32x4_t xy02_f32x4 = vdupq_n_f32(0); - float32x2_t xy01_f32x2, xy02_f32x2; - - for (i = 0; i < N - 7; i += 8) { - float32x4_t x_f32x4, y01_f32x4, y02_f32x4; - x_f32x4 = vld1q_f32(&x[i]); - y01_f32x4 = vld1q_f32(&y01[i]); - y02_f32x4 = vld1q_f32(&y02[i]); - xy01_f32x4 = vmlaq_f32(xy01_f32x4, x_f32x4, y01_f32x4); - xy02_f32x4 = vmlaq_f32(xy02_f32x4, x_f32x4, y02_f32x4); - x_f32x4 = vld1q_f32(&x[i + 4]); - y01_f32x4 = vld1q_f32(&y01[i + 4]); - y02_f32x4 = vld1q_f32(&y02[i + 4]); - xy01_f32x4 = vmlaq_f32(xy01_f32x4, x_f32x4, y01_f32x4); - xy02_f32x4 = vmlaq_f32(xy02_f32x4, x_f32x4, y02_f32x4); - } - - if (N - i >= 4) { - const float32x4_t x_f32x4 = vld1q_f32(&x[i]); - const float32x4_t y01_f32x4 = vld1q_f32(&y01[i]); - const float32x4_t y02_f32x4 = vld1q_f32(&y02[i]); - xy01_f32x4 = vmlaq_f32(xy01_f32x4, x_f32x4, y01_f32x4); - xy02_f32x4 = vmlaq_f32(xy02_f32x4, x_f32x4, y02_f32x4); - i += 4; - } - - xy01_f32x2 = vadd_f32(vget_low_f32(xy01_f32x4), vget_high_f32(xy01_f32x4)); - xy02_f32x2 = vadd_f32(vget_low_f32(xy02_f32x4), vget_high_f32(xy02_f32x4)); - xy01_f32x2 = vpadd_f32(xy01_f32x2, xy01_f32x2); - xy02_f32x2 = vpadd_f32(xy02_f32x2, xy02_f32x2); - xy01 = vget_lane_f32(xy01_f32x2, 0); - xy02 = vget_lane_f32(xy02_f32x2, 0); - - for (; i < N; i++) { - xy01 = MAC16_16(xy01, x[i], y01[i]); - xy02 = MAC16_16(xy02, x[i], y02[i]); - } - *xy1 = xy01; - *xy2 = xy02; - -#ifdef OPUS_CHECK_ASM - { - opus_val32 xy1_c, xy2_c; - dual_inner_prod_neon_float_c_simulation(x, y01, y02, N, &xy1_c, &xy2_c); - celt_assert(ABS32(xy1_c - *xy1) <= VERY_SMALL); - celt_assert(ABS32(xy2_c - *xy2) <= VERY_SMALL); - } -#endif -} - -#endif /* FIXED_POINT */ diff --git a/thirdparty/opus/celt/bands.c b/thirdparty/opus/celt/bands.c index 2702963c37a..87eaa6c0311 100644 --- a/thirdparty/opus/celt/bands.c +++ b/thirdparty/opus/celt/bands.c @@ -65,19 +65,19 @@ opus_uint32 celt_lcg_rand(opus_uint32 seed) /* This is a cos() approximation designed to be bit-exact on any platform. Bit exactness with this approximation is important because it has an impact on the bit allocation */ -opus_int16 bitexact_cos(opus_int16 x) +static opus_int16 bitexact_cos(opus_int16 x) { opus_int32 tmp; opus_int16 x2; tmp = (4096+((opus_int32)(x)*(x)))>>13; - celt_sig_assert(tmp<=32767); + celt_assert(tmp<=32767); x2 = tmp; x2 = (32767-x2) + FRAC_MUL16(x2, (-7651 + FRAC_MUL16(x2, (8277 + FRAC_MUL16(-626, x2))))); - celt_sig_assert(x2<=32766); + celt_assert(x2<=32766); return 1+x2; } -int bitexact_log2tan(int isin,int icos) +static int bitexact_log2tan(int isin,int icos) { int lc; int ls; @@ -92,11 +92,10 @@ int bitexact_log2tan(int isin,int icos) #ifdef FIXED_POINT /* Compute the amplitude (sqrt energy) in each of the bands */ -void compute_band_energies(const CELTMode *m, const celt_sig *X, celt_ener *bandE, int end, int C, int LM, int arch) +void compute_band_energies(const CELTMode *m, const celt_sig *X, celt_ener *bandE, int end, int C, int LM) { int i, c, N; const opus_int16 *eBands = m->eBands; - (void)arch; N = m->shortMdctSize<eBands; @@ -165,7 +164,7 @@ void compute_band_energies(const CELTMode *m, const celt_sig *X, celt_ener *band for (i=0;inbEBands] = celt_sqrt(sum); /*printf ("%f ", bandE[i+c*m->nbEBands]);*/ } @@ -225,9 +224,9 @@ void denormalise_bands(const CELTMode *m, const celt_norm * OPUS_RESTRICT X, #endif j=M*eBands[i]; band_end = M*eBands[i+1]; - lg = SATURATE16(ADD32(bandLogE[i], SHL32((opus_val32)eMeans[i],6))); + lg = ADD16(bandLogE[i], SHL16((opus_val16)eMeans[i],6)); #ifndef FIXED_POINT - g = celt_exp2(MIN32(32.f, lg)); + g = celt_exp2(lg); #else /* Handle the integer part of the log energy */ shift = 16-(lg>>DB_SHIFT); @@ -242,12 +241,12 @@ void denormalise_bands(const CELTMode *m, const celt_norm * OPUS_RESTRICT X, /* Handle extreme gains with negative shift. */ if (shift<0) { - /* For shift <= -2 and g > 16384 we'd be likely to overflow, so we're - capping the gain here, which is equivalent to a cap of 18 on lg. - This shouldn't trigger unless the bitstream is already corrupted. */ - if (shift <= -2) + /* For shift < -2 we'd be likely to overflow, so we're capping + the gain here. This shouldn't happen unless the bitstream is + already corrupted. */ + if (shift < -2) { - g = 16384; + g = 32767; shift = -2; } do { @@ -282,7 +281,7 @@ void anti_collapse(const CELTMode *m, celt_norm *X_, unsigned char *collapse_mas N0 = m->eBands[i+1]-m->eBands[i]; /* depth in 1/8 bits */ - celt_sig_assert(pulses[i]>=0); + celt_assert(pulses[i]>=0); depth = celt_udiv(1+pulses[i], (m->eBands[i+1]-m->eBands[i]))>>LM; #ifdef FIXED_POINT @@ -361,30 +360,6 @@ void anti_collapse(const CELTMode *m, celt_norm *X_, unsigned char *collapse_mas } } -/* Compute the weights to use for optimizing normalized distortion across - channels. We use the amplitude to weight square distortion, which means - that we use the square root of the value we would have been using if we - wanted to minimize the MSE in the non-normalized domain. This roughly - corresponds to some quick-and-dirty perceptual experiments I ran to - measure inter-aural masking (there doesn't seem to be any published data - on the topic). */ -static void compute_channel_weights(celt_ener Ex, celt_ener Ey, opus_val16 w[2]) -{ - celt_ener minE; -#ifdef FIXED_POINT - int shift; -#endif - minE = MIN32(Ex, Ey); - /* Adjustment to make the weights a bit more conservative. */ - Ex = ADD32(Ex, minE/3); - Ey = ADD32(Ey, minE/3); -#ifdef FIXED_POINT - shift = celt_ilog2(EPSILON+MAX32(Ex, Ey))-14; -#endif - w[0] = VSHR32(Ex, shift); - w[1] = VSHR32(Ey, shift); -} - static void intensity_stereo(const CELTMode *m, celt_norm * OPUS_RESTRICT X, const celt_norm * OPUS_RESTRICT Y, const celt_ener *bandE, int bandID, int N) { int i = bandID; @@ -478,7 +453,7 @@ static void stereo_merge(celt_norm * OPUS_RESTRICT X, celt_norm * OPUS_RESTRICT /* Decide whether we should spread the pulses in the current frame */ int spreading_decision(const CELTMode *m, const celt_norm *X, int *average, int last_decision, int *hf_average, int *tapset_decision, int update_hf, - int end, int C, int M, const int *spread_weight) + int end, int C, int M) { int i, c, N0; int sum = 0, nbBands=0; @@ -519,8 +494,8 @@ int spreading_decision(const CELTMode *m, const celt_norm *X, int *average, if (i>m->nbEBands-4) hf_sum += celt_udiv(32*(tcount[1]+tcount[0]), N); tmp = (2*tcount[2] >= N) + (2*tcount[1] >= N) + (2*tcount[0] >= N); - sum += tmp*spread_weight[i]; - nbBands+=spread_weight[i]; + sum += tmp*256; + nbBands++; } } while (++c0); /* end has to be non-zero */ celt_assert(sum>=0); - sum = celt_udiv((opus_int32)sum<<8, nbBands); + sum = celt_udiv(sum, nbBands); /* Recursive averaging */ sum = (sum+*average)>>1; *average = sum; @@ -672,7 +647,6 @@ static int compute_qn(int N, int b, int offset, int pulse_cap, int stereo) struct band_ctx { int encode; - int resynth; const CELTMode *m; int i; int intensity; @@ -683,9 +657,6 @@ struct band_ctx { const celt_ener *bandE; opus_uint32 seed; int arch; - int theta_round; - int disable_inv; - int avoid_split_noise; }; struct split_ctx { @@ -743,35 +714,8 @@ static void compute_theta(struct band_ctx *ctx, struct split_ctx *sctx, if (qn!=1) { if (encode) - { - if (!stereo || ctx->theta_round == 0) - { - itheta = (itheta*(opus_int32)qn+8192)>>14; - if (!stereo && ctx->avoid_split_noise && itheta > 0 && itheta < qn) - { - /* Check if the selected value of theta will cause the bit allocation - to inject noise on one side. If so, make sure the energy of that side - is zero. */ - int unquantized = celt_udiv((opus_int32)itheta*16384, qn); - imid = bitexact_cos((opus_int16)unquantized); - iside = bitexact_cos((opus_int16)(16384-unquantized)); - delta = FRAC_MUL16((N-1)<<7,bitexact_log2tan(iside,imid)); - if (delta > *b) - itheta = qn; - else if (delta < -*b) - itheta = 0; - } - } else { - int down; - /* Bias quantization towards itheta=0 and itheta=16384. */ - int bias = itheta > 8192 ? 32767/qn : -32767/qn; - down = IMIN(qn-1, IMAX(0, (itheta*(opus_int32)qn + bias)>>14)); - if (ctx->theta_round < 0) - itheta = down; - else - itheta = down+1; - } - } + itheta = (itheta*(opus_int32)qn+8192)>>14; + /* Entropy coding of the angle. We use a uniform pdf for the time split, a step for stereo, and a triangular one for the rest. */ if (stereo && N>2) @@ -849,7 +793,7 @@ static void compute_theta(struct band_ctx *ctx, struct split_ctx *sctx, } else if (stereo) { if (encode) { - inv = itheta > 8192 && !ctx->disable_inv; + inv = itheta > 8192; if (inv) { int j; @@ -866,9 +810,6 @@ static void compute_theta(struct band_ctx *ctx, struct split_ctx *sctx, inv = ec_dec_bit_logp(ec, 2); } else inv = 0; - /* inv flag override to avoid problems with downmixing. */ - if (ctx->disable_inv) - inv = 0; itheta = 0; } qalloc = ec_tell_frac(ec) - tell; @@ -904,6 +845,11 @@ static void compute_theta(struct band_ctx *ctx, struct split_ctx *sctx, static unsigned quant_band_n1(struct band_ctx *ctx, celt_norm *X, celt_norm *Y, int b, celt_norm *lowband_out) { +#ifdef RESYNTH + int resynth = 1; +#else + int resynth = !ctx->encode; +#endif int c; int stereo; celt_norm *x = X; @@ -928,7 +874,7 @@ static unsigned quant_band_n1(struct band_ctx *ctx, celt_norm *X, celt_norm *Y, ctx->remaining_bits -= 1<resynth) + if (resynth) x[0] = sign ? -NORM_SCALING : NORM_SCALING; x = Y; } while (++c<1+stereo); @@ -953,6 +899,11 @@ static unsigned quant_partition(struct band_ctx *ctx, celt_norm *X, int B0=B; opus_val16 mid=0, side=0; unsigned cm=0; +#ifdef RESYNTH + int resynth = 1; +#else + int resynth = !ctx->encode; +#endif celt_norm *Y=NULL; int encode; const CELTMode *m; @@ -984,7 +935,8 @@ static unsigned quant_partition(struct band_ctx *ctx, celt_norm *X, fill = (fill&1)|(fill<<1); B = (B+1)>>1; - compute_theta(ctx, &sctx, X, Y, N, &b, B, B0, LM, 0, &fill); + compute_theta(ctx, &sctx, X, Y, N, &b, B, B0, + LM, 0, &fill); imid = sctx.imid; iside = sctx.iside; delta = sctx.delta; @@ -1018,20 +970,24 @@ static unsigned quant_partition(struct band_ctx *ctx, celt_norm *X, rebalance = ctx->remaining_bits; if (mbits >= sbits) { - cm = quant_partition(ctx, X, N, mbits, B, lowband, LM, + cm = quant_partition(ctx, X, N, mbits, B, + lowband, LM, MULT16_16_P15(gain,mid), fill); rebalance = mbits - (rebalance-ctx->remaining_bits); if (rebalance > 3<>B)<<(B0>>1); } else { - cm = quant_partition(ctx, Y, N, sbits, B, next_lowband2, LM, + cm = quant_partition(ctx, Y, N, sbits, B, + next_lowband2, LM, MULT16_16_P15(gain,side), fill>>B)<<(B0>>1); rebalance = sbits - (rebalance-ctx->remaining_bits); if (rebalance > 3<resynth, ctx->arch); + cm = alg_quant(X, N, K, spread, B, ec +#ifdef RESYNTH + , gain +#endif + ); } else { cm = alg_unquant(X, N, K, spread, B, ec, gain); } } else { /* If there's no pulse, fill the band anyway */ int j; - if (ctx->resynth) + if (resynth) { unsigned cm_mask; /* B can be as large as 16, so this shift might overflow an int on a @@ -1120,6 +1080,11 @@ static unsigned quant_band(struct band_ctx *ctx, celt_norm *X, int recombine=0; int longBlocks; unsigned cm=0; +#ifdef RESYNTH + int resynth = 1; +#else + int resynth = !ctx->encode; +#endif int k; int encode; int tf_change; @@ -1186,10 +1151,11 @@ static unsigned quant_band(struct band_ctx *ctx, celt_norm *X, deinterleave_hadamard(lowband, N_B>>recombine, B0<resynth) + if (resynth) { /* Undo the sample reorganization going from time order to frequency order */ if (B0>1) @@ -1242,6 +1208,11 @@ static unsigned quant_band_stereo(struct band_ctx *ctx, celt_norm *X, celt_norm int inv = 0; opus_val16 mid=0, side=0; unsigned cm=0; +#ifdef RESYNTH + int resynth = 1; +#else + int resynth = !ctx->encode; +#endif int mbits, sbits, delta; int itheta; int qalloc; @@ -1261,7 +1232,8 @@ static unsigned quant_band_stereo(struct band_ctx *ctx, celt_norm *X, celt_norm orig_fill = fill; - compute_theta(ctx, &sctx, X, Y, N, &b, B, B, LM, 1, &fill); + compute_theta(ctx, &sctx, X, Y, N, &b, B, B, + LM, 1, &fill); inv = sctx.inv; imid = sctx.imid; iside = sctx.iside; @@ -1309,13 +1281,13 @@ static unsigned quant_band_stereo(struct band_ctx *ctx, celt_norm *X, celt_norm sign = 1-2*sign; /* We use orig_fill here because we want to fold the side, but if itheta==16384, we'll have cleared the low bits of fill. */ - cm = quant_band(ctx, x2, N, mbits, B, lowband, LM, lowband_out, Q15ONE, - lowband_scratch, orig_fill); + cm = quant_band(ctx, x2, N, mbits, B, lowband, + LM, lowband_out, Q15ONE, lowband_scratch, orig_fill); /* We don't split N=2 bands, so cm is either 1 or 0 (for a fold-collapse), and there's no need to worry about mixing with the other channel. */ y2[0] = -sign*x2[1]; y2[1] = sign*x2[0]; - if (ctx->resynth) + if (resynth) { celt_norm tmp; X[0] = MULT16_16_Q15(mid, X[0]); @@ -1342,32 +1314,38 @@ static unsigned quant_band_stereo(struct band_ctx *ctx, celt_norm *X, celt_norm { /* In stereo mode, we do not apply a scaling to the mid because we need the normalized mid for folding later. */ - cm = quant_band(ctx, X, N, mbits, B, lowband, LM, lowband_out, Q15ONE, - lowband_scratch, fill); + cm = quant_band(ctx, X, N, mbits, B, + lowband, LM, lowband_out, + Q15ONE, lowband_scratch, fill); rebalance = mbits - (rebalance-ctx->remaining_bits); if (rebalance > 3<>B); + cm |= quant_band(ctx, Y, N, sbits, B, + NULL, LM, NULL, + side, NULL, fill>>B); } else { /* For a stereo split, the high bits of fill are always zero, so no folding will be done to the side. */ - cm = quant_band(ctx, Y, N, sbits, B, NULL, LM, NULL, side, NULL, fill>>B); + cm = quant_band(ctx, Y, N, sbits, B, + NULL, LM, NULL, + side, NULL, fill>>B); rebalance = sbits - (rebalance-ctx->remaining_bits); if (rebalance > 3<resynth) + if (resynth) { if (N!=2) stereo_merge(X, Y, mid, N, ctx->arch); @@ -1381,38 +1359,19 @@ static unsigned quant_band_stereo(struct band_ctx *ctx, celt_norm *X, celt_norm return cm; } -static void special_hybrid_folding(const CELTMode *m, celt_norm *norm, celt_norm *norm2, int start, int M, int dual_stereo) -{ - int n1, n2; - const opus_int16 * OPUS_RESTRICT eBands = m->eBands; - n1 = M*(eBands[start+1]-eBands[start]); - n2 = M*(eBands[start+2]-eBands[start+1]); - /* Duplicate enough of the first band folding data to be able to fold the second band. - Copies no data for CELT-only mode. */ - OPUS_COPY(&norm[n1], &norm[2*n1 - n2], n2-n1); - if (dual_stereo) - OPUS_COPY(&norm2[n1], &norm2[2*n1 - n2], n2-n1); -} void quant_all_bands(int encode, const CELTMode *m, int start, int end, celt_norm *X_, celt_norm *Y_, unsigned char *collapse_masks, const celt_ener *bandE, int *pulses, int shortBlocks, int spread, int dual_stereo, int intensity, int *tf_res, opus_int32 total_bits, opus_int32 balance, ec_ctx *ec, int LM, int codedBands, - opus_uint32 *seed, int complexity, int arch, int disable_inv) + opus_uint32 *seed, int arch) { int i; opus_int32 remaining_bits; const opus_int16 * OPUS_RESTRICT eBands = m->eBands; celt_norm * OPUS_RESTRICT norm, * OPUS_RESTRICT norm2; VARDECL(celt_norm, _norm); - VARDECL(celt_norm, _lowband_scratch); - VARDECL(celt_norm, X_save); - VARDECL(celt_norm, Y_save); - VARDECL(celt_norm, X_save2); - VARDECL(celt_norm, Y_save2); - VARDECL(celt_norm, norm_save2); - int resynth_alloc; celt_norm *lowband_scratch; int B; int M; @@ -1420,11 +1379,10 @@ void quant_all_bands(int encode, const CELTMode *m, int start, int end, int update_lowband = 1; int C = Y_ != NULL ? 2 : 1; int norm_offset; - int theta_rdo = encode && Y_!=NULL && !dual_stereo && complexity>=8; #ifdef RESYNTH int resynth = 1; #else - int resynth = !encode || theta_rdo; + int resynth = !encode; #endif struct band_ctx ctx; SAVE_STACK; @@ -1437,24 +1395,9 @@ void quant_all_bands(int encode, const CELTMode *m, int start, int end, ALLOC(_norm, C*(M*eBands[m->nbEBands-1]-norm_offset), celt_norm); norm = _norm; norm2 = norm + M*eBands[m->nbEBands-1]-norm_offset; - - /* For decoding, we can use the last band as scratch space because we don't need that - scratch space for the last band and we don't care about the data there until we're - decoding the last band. */ - if (encode && resynth) - resynth_alloc = M*(eBands[m->nbEBands]-eBands[m->nbEBands-1]); - else - resynth_alloc = ALLOC_NONE; - ALLOC(_lowband_scratch, resynth_alloc, celt_norm); - if (encode && resynth) - lowband_scratch = _lowband_scratch; - else - lowband_scratch = X_+M*eBands[m->nbEBands-1]; - ALLOC(X_save, resynth_alloc, celt_norm); - ALLOC(Y_save, resynth_alloc, celt_norm); - ALLOC(X_save2, resynth_alloc, celt_norm); - ALLOC(Y_save2, resynth_alloc, celt_norm); - ALLOC(norm_save2, resynth_alloc, celt_norm); + /* We can use the last band as scratch space because we don't need that + scratch space for the last band. */ + lowband_scratch = X_+M*eBands[m->nbEBands-1]; lowband_offset = 0; ctx.bandE = bandE; @@ -1465,11 +1408,6 @@ void quant_all_bands(int encode, const CELTMode *m, int start, int end, ctx.seed = *seed; ctx.spread = spread; ctx.arch = arch; - ctx.disable_inv = disable_inv; - ctx.resynth = resynth; - ctx.theta_round = 0; - /* Avoid injecting noise in the first band on transients. */ - ctx.avoid_split_noise = B > 1; for (i=start;i 0); tell = ec_tell_frac(ec); /* Compute how many bits we want to allocate to this band */ @@ -1508,15 +1445,8 @@ void quant_all_bands(int encode, const CELTMode *m, int start, int end, b = 0; } -#ifndef DISABLE_UPDATE_DRAFT - if (resynth && (M*eBands[i]-N >= M*eBands[start] || i==start+1) && (update_lowband || lowband_offset==0)) - lowband_offset = i; - if (i == start+1) - special_hybrid_folding(m, norm, norm2, start, M, dual_stereo); -#else if (resynth && M*eBands[i]-N >= M*eBands[start] && (update_lowband || lowband_offset==0)) lowband_offset = i; -#endif tf_change = tf_res[i]; ctx.tf_change = tf_change; @@ -1527,7 +1457,7 @@ void quant_all_bands(int encode, const CELTMode *m, int start, int end, Y = norm; lowband_scratch = NULL; } - if (last && !theta_rdo) + if (i==end-1) lowband_scratch = NULL; /* Get a conservative estimate of the collapse_mask's for the bands we're @@ -1542,11 +1472,7 @@ void quant_all_bands(int encode, const CELTMode *m, int start, int end, fold_start = lowband_offset; while(M*eBands[--fold_start] > effective_lowband+norm_offset); fold_end = lowband_offset-1; -#ifndef DISABLE_UPDATE_DRAFT - while(++fold_end < i && M*eBands[fold_end] < effective_lowband+norm_offset+N); -#else while(M*eBands[++fold_end] < effective_lowband+norm_offset+N); -#endif x_cm = y_cm = 0; fold_i = fold_start; do { x_cm |= collapse_masks[fold_i*C+0]; @@ -1579,79 +1505,13 @@ void quant_all_bands(int encode, const CELTMode *m, int start, int end, } else { if (Y!=NULL) { - if (theta_rdo && i < intensity) - { - ec_ctx ec_save, ec_save2; - struct band_ctx ctx_save, ctx_save2; - opus_val32 dist0, dist1; - unsigned cm, cm2; - int nstart_bytes, nend_bytes, save_bytes; - unsigned char *bytes_buf; - unsigned char bytes_save[1275]; - opus_val16 w[2]; - compute_channel_weights(bandE[i], bandE[i+m->nbEBands], w); - /* Make a copy. */ - cm = x_cm|y_cm; - ec_save = *ec; - ctx_save = ctx; - OPUS_COPY(X_save, X, N); - OPUS_COPY(Y_save, Y, N); - /* Encode and round down. */ - ctx.theta_round = -1; - x_cm = quant_band_stereo(&ctx, X, Y, N, b, B, - effective_lowband != -1 ? norm+effective_lowband : NULL, LM, - last?NULL:norm+M*eBands[i]-norm_offset, lowband_scratch, cm); - dist0 = MULT16_32_Q15(w[0], celt_inner_prod(X_save, X, N, arch)) + MULT16_32_Q15(w[1], celt_inner_prod(Y_save, Y, N, arch)); - - /* Save first result. */ - cm2 = x_cm; - ec_save2 = *ec; - ctx_save2 = ctx; - OPUS_COPY(X_save2, X, N); - OPUS_COPY(Y_save2, Y, N); - if (!last) - OPUS_COPY(norm_save2, norm+M*eBands[i]-norm_offset, N); - nstart_bytes = ec_save.offs; - nend_bytes = ec_save.storage; - bytes_buf = ec_save.buf+nstart_bytes; - save_bytes = nend_bytes-nstart_bytes; - OPUS_COPY(bytes_save, bytes_buf, save_bytes); - - /* Restore */ - *ec = ec_save; - ctx = ctx_save; - OPUS_COPY(X, X_save, N); - OPUS_COPY(Y, Y_save, N); -#ifndef DISABLE_UPDATE_DRAFT - if (i == start+1) - special_hybrid_folding(m, norm, norm2, start, M, dual_stereo); -#endif - /* Encode and round up. */ - ctx.theta_round = 1; - x_cm = quant_band_stereo(&ctx, X, Y, N, b, B, - effective_lowband != -1 ? norm+effective_lowband : NULL, LM, - last?NULL:norm+M*eBands[i]-norm_offset, lowband_scratch, cm); - dist1 = MULT16_32_Q15(w[0], celt_inner_prod(X_save, X, N, arch)) + MULT16_32_Q15(w[1], celt_inner_prod(Y_save, Y, N, arch)); - if (dist0 >= dist1) { - x_cm = cm2; - *ec = ec_save2; - ctx = ctx_save2; - OPUS_COPY(X, X_save2, N); - OPUS_COPY(Y, Y_save2, N); - if (!last) - OPUS_COPY(norm+M*eBands[i]-norm_offset, norm_save2, N); - OPUS_COPY(bytes_buf, bytes_save, save_bytes); - } - } else { - ctx.theta_round = 0; - x_cm = quant_band_stereo(&ctx, X, Y, N, b, B, - effective_lowband != -1 ? norm+effective_lowband : NULL, LM, - last?NULL:norm+M*eBands[i]-norm_offset, lowband_scratch, x_cm|y_cm); - } + x_cm = quant_band_stereo(&ctx, X, Y, N, b, B, + effective_lowband != -1 ? norm+effective_lowband : NULL, LM, + last?NULL:norm+M*eBands[i]-norm_offset, lowband_scratch, x_cm|y_cm); } else { x_cm = quant_band(&ctx, X, N, b, B, effective_lowband != -1 ? norm+effective_lowband : NULL, LM, - last?NULL:norm+M*eBands[i]-norm_offset, Q15ONE, lowband_scratch, x_cm|y_cm); + last?NULL:norm+M*eBands[i]-norm_offset, Q15ONE, lowband_scratch, x_cm|y_cm); } y_cm = x_cm; } @@ -1661,9 +1521,6 @@ void quant_all_bands(int encode, const CELTMode *m, int start, int end, /* Update the folding position only as long as we have 1 bit/sample depth. */ update_lowband = b>(N<nbEBands */ }; -#if defined(ENABLE_HARDENING) || defined(ENABLE_ASSERTIONS) -/* Make basic checks on the CELT state to ensure we don't end - up writing all over memory. */ -void validate_celt_decoder(CELTDecoder *st) -{ -#ifndef CUSTOM_MODES - celt_assert(st->mode == opus_custom_mode_create(48000, 960, NULL)); - celt_assert(st->overlap == 120); -#endif - celt_assert(st->channels == 1 || st->channels == 2); - celt_assert(st->stream_channels == 1 || st->stream_channels == 2); - celt_assert(st->downsample > 0); - celt_assert(st->start == 0 || st->start == 17); - celt_assert(st->start < st->end); - celt_assert(st->end <= 21); -#ifdef OPUS_ARCHMASK - celt_assert(st->arch >= 0); - celt_assert(st->arch <= OPUS_ARCHMASK); -#endif - celt_assert(st->last_pitch_index <= PLC_PITCH_LAG_MAX); - celt_assert(st->last_pitch_index >= PLC_PITCH_LAG_MIN || st->last_pitch_index == 0); - celt_assert(st->postfilter_period < MAX_PERIOD); - celt_assert(st->postfilter_period >= COMBFILTER_MINPERIOD || st->postfilter_period == 0); - celt_assert(st->postfilter_period_old < MAX_PERIOD); - celt_assert(st->postfilter_period_old >= COMBFILTER_MINPERIOD || st->postfilter_period_old == 0); - celt_assert(st->postfilter_tapset <= 2); - celt_assert(st->postfilter_tapset >= 0); - celt_assert(st->postfilter_tapset_old <= 2); - celt_assert(st->postfilter_tapset_old >= 0); -} -#endif - int celt_decoder_get_size(int channels) { const CELTMode *mode = opus_custom_mode_create(48000, 960, NULL); @@ -204,11 +163,6 @@ OPUS_CUSTOM_NOSTATIC int opus_custom_decoder_init(CELTDecoder *st, const CELTMod st->start = 0; st->end = st->mode->effEBands; st->signalling = 1; -#ifndef DISABLE_UPDATE_DRAFT - st->disable_inv = channels == 1; -#else - st->disable_inv = 0; -#endif st->arch = opus_select_arch(); opus_custom_decoder_ctl(st, OPUS_RESET_STATE); @@ -223,36 +177,6 @@ void opus_custom_decoder_destroy(CELTDecoder *st) } #endif /* CUSTOM_MODES */ -#ifndef CUSTOM_MODES -/* Special case for stereo with no downsampling and no accumulation. This is - quite common and we can make it faster by processing both channels in the - same loop, reducing overhead due to the dependency loop in the IIR filter. */ -static void deemphasis_stereo_simple(celt_sig *in[], opus_val16 *pcm, int N, const opus_val16 coef0, - celt_sig *mem) -{ - celt_sig * OPUS_RESTRICT x0; - celt_sig * OPUS_RESTRICT x1; - celt_sig m0, m1; - int j; - x0=in[0]; - x1=in[1]; - m0 = mem[0]; - m1 = mem[1]; - for (j=0;jmdct, &freq[b], out_syn[0]+NB*b, mode->window, overlap, shift, B, arch); } else { @@ -429,12 +345,6 @@ void celt_synthesis(const CELTMode *mode, celt_norm *X, celt_sig * out_syn[], clt_mdct_backward(&mode->mdct, &freq[b], out_syn[c]+NB*b, mode->window, overlap, shift, B, arch); } while (++cdownsample, 0, st->arch); } else { - int exc_length; /* Pitch-based PLC */ const opus_val16 *window; - opus_val16 *exc; opus_val16 fade = Q15ONE; int pitch_index; VARDECL(opus_val32, etmp); - VARDECL(opus_val16, _exc); - VARDECL(opus_val16, fir_tmp); + VARDECL(opus_val16, exc); if (loss_count == 0) { @@ -604,14 +519,8 @@ static void celt_decode_lost(CELTDecoder * OPUS_RESTRICT st, int N, int LM) fade = QCONST16(.8f,15); } - /* We want the excitation for 2 pitch periods in order to look for a - decaying signal, but we can't get more than MAX_PERIOD. */ - exc_length = IMIN(2*pitch_index, MAX_PERIOD); - ALLOC(etmp, overlap, opus_val32); - ALLOC(_exc, MAX_PERIOD+LPC_ORDER, opus_val16); - ALLOC(fir_tmp, exc_length, opus_val16); - exc = _exc+LPC_ORDER; + ALLOC(exc, MAX_PERIOD, opus_val16); window = mode->window; c=0; do { opus_val16 decay; @@ -620,11 +529,13 @@ static void celt_decode_lost(CELTDecoder * OPUS_RESTRICT st, int N, int LM) celt_sig *buf; int extrapolation_offset; int extrapolation_len; + int exc_length; int j; buf = decode_mem[c]; - for (i=0;iarch); - OPUS_COPY(exc+MAX_PERIOD-exc_length, fir_tmp, exc_length); + exc+MAX_PERIOD-exc_length, exc_length, LPC_ORDER, lpc_mem, st->arch); } /* Check if the waveform is decaying, and if so how fast. @@ -729,8 +630,9 @@ static void celt_decode_lost(CELTDecoder * OPUS_RESTRICT st, int N, int LM) tmp = ROUND16( buf[DECODE_BUFFER_SIZE-MAX_PERIOD-N+extrapolation_offset+j], SIG_SHIFT); - S1 += SHR32(MULT16_16(tmp, tmp), 10); + S1 += SHR32(MULT16_16(tmp, tmp), 8); } + { opus_val16 lpc_mem[LPC_ORDER]; /* Copy the last decoded samples (prior to the overlap region) to @@ -742,10 +644,6 @@ static void celt_decode_lost(CELTDecoder * OPUS_RESTRICT st, int N, int LM) celt_iir(buf+DECODE_BUFFER_SIZE-N, lpc+c*LPC_ORDER, buf+DECODE_BUFFER_SIZE-N, extrapolation_len, LPC_ORDER, lpc_mem, st->arch); -#ifdef FIXED_POINT - for (i=0; i < extrapolation_len; i++) - buf[DECODE_BUFFER_SIZE-N+i] = SATURATE(buf[DECODE_BUFFER_SIZE-N+i], SIG_SAT); -#endif } /* Check if the synthesis energy is higher than expected, which can @@ -756,7 +654,7 @@ static void celt_decode_lost(CELTDecoder * OPUS_RESTRICT st, int N, int LM) for (i=0;imode; nbEBands = mode->nbEBands; overlap = mode->overlap; @@ -1059,7 +956,7 @@ int celt_decode_with_ec(CELTDecoder * OPUS_RESTRICT st, const unsigned char *dat ALLOC(pulses, nbEBands, int); ALLOC(fine_priority, nbEBands, int); - codedBands = clt_compute_allocation(mode, start, end, offsets, cap, + codedBands = compute_allocation(mode, start, end, offsets, cap, alloc_trim, &intensity, &dual_stereo, bits, &balance, pulses, fine_quant, fine_priority, C, LM, dec, 0, 0, 0); @@ -1082,8 +979,7 @@ int celt_decode_with_ec(CELTDecoder * OPUS_RESTRICT st, const unsigned char *dat quant_all_bands(0, mode, start, end, X, C==2 ? X+N : NULL, collapse_masks, NULL, pulses, shortBlocks, spread_decision, dual_stereo, intensity, tf_res, - len*(8<rng, 0, - st->arch, st->disable_inv); + len*(8<rng, st->arch); if (anti_collapse_rsv > 0) { @@ -1338,26 +1234,6 @@ int opus_custom_decoder_ctl(CELTDecoder * OPUS_RESTRICT st, int request, ...) *value=st->rng; } break; - case OPUS_SET_PHASE_INVERSION_DISABLED_REQUEST: - { - opus_int32 value = va_arg(ap, opus_int32); - if(value<0 || value>1) - { - goto bad_arg; - } - st->disable_inv = value; - } - break; - case OPUS_GET_PHASE_INVERSION_DISABLED_REQUEST: - { - opus_int32 *value = va_arg(ap, opus_int32*); - if (!value) - { - goto bad_arg; - } - *value = st->disable_inv; - } - break; default: goto bad_request; } diff --git a/thirdparty/opus/celt/celt_encoder.c b/thirdparty/opus/celt/celt_encoder.c index 44cb0850abd..3ee7a4d3f7a 100644 --- a/thirdparty/opus/celt/celt_encoder.c +++ b/thirdparty/opus/celt/celt_encoder.c @@ -73,8 +73,8 @@ struct OpusCustomEncoder { int constrained_vbr; /* If zero, VBR can do whatever it likes with the rate */ int loss_rate; int lsb_depth; + int variable_duration; int lfe; - int disable_inv; int arch; /* Everything beyond this point gets cleared on a reset */ @@ -98,7 +98,6 @@ struct OpusCustomEncoder { #endif int consec_transient; AnalysisInfo analysis; - SILKInfo silk_info; opus_val32 preemph_memE[2]; opus_val32 preemph_memD[2]; @@ -124,7 +123,6 @@ struct OpusCustomEncoder { /* opus_val16 oldBandE[], Size = channels*mode->nbEBands */ /* opus_val16 oldLogE[], Size = channels*mode->nbEBands */ /* opus_val16 oldLogE2[], Size = channels*mode->nbEBands */ - /* opus_val16 energyError[], Size = channels*mode->nbEBands */ }; int celt_encoder_get_size(int channels) @@ -138,10 +136,9 @@ OPUS_CUSTOM_NOSTATIC int opus_custom_encoder_get_size(const CELTMode *mode, int int size = sizeof(struct CELTEncoder) + (channels*mode->overlap-1)*sizeof(celt_sig) /* celt_sig in_mem[channels*mode->overlap]; */ + channels*COMBFILTER_MAXPERIOD*sizeof(celt_sig) /* celt_sig prefilter_mem[channels*COMBFILTER_MAXPERIOD]; */ - + 4*channels*mode->nbEBands*sizeof(opus_val16); /* opus_val16 oldBandE[channels*mode->nbEBands]; */ + + 3*channels*mode->nbEBands*sizeof(opus_val16); /* opus_val16 oldBandE[channels*mode->nbEBands]; */ /* opus_val16 oldLogE[channels*mode->nbEBands]; */ /* opus_val16 oldLogE2[channels*mode->nbEBands]; */ - /* opus_val16 energyError[channels*mode->nbEBands]; */ return size; } @@ -181,6 +178,7 @@ static int opus_custom_encoder_init_arch(CELTEncoder *st, const CELTMode *mode, st->start = 0; st->end = st->mode->effEBands; st->signalling = 1; + st->arch = arch; st->constrained_vbr = 1; @@ -225,8 +223,7 @@ void opus_custom_encoder_destroy(CELTEncoder *st) static int transient_analysis(const opus_val32 * OPUS_RESTRICT in, int len, int C, - opus_val16 *tf_estimate, int *tf_chan, int allow_weak_transients, - int *weak_transient) + opus_val16 *tf_estimate, int *tf_chan) { int i; VARDECL(opus_val16, tmp); @@ -236,12 +233,6 @@ static int transient_analysis(const opus_val32 * OPUS_RESTRICT in, int len, int int c; opus_val16 tf_max; int len2; - /* Forward masking: 6.7 dB/ms. */ -#ifdef FIXED_POINT - int forward_shift = 4; -#else - opus_val16 forward_decay = QCONST16(.0625f,15); -#endif /* Table of 6*64/x, trained on real data to minimize the average error */ static const unsigned char inv_table[128] = { 255,255,156,110, 86, 70, 59, 51, 45, 40, 37, 33, 31, 28, 26, 25, @@ -256,19 +247,6 @@ static int transient_analysis(const opus_val32 * OPUS_RESTRICT in, int len, int SAVE_STACK; ALLOC(tmp, len, opus_val16); - *weak_transient = 0; - /* For lower bitrates, let's be more conservative and have a forward masking - decay of 3.3 dB/ms. This avoids having to code transients at very low - bitrate (mostly for hybrid), which can result in unstable energy and/or - partial collapse. */ - if (allow_weak_transients) - { -#ifdef FIXED_POINT - forward_shift = 5; -#else - forward_decay = QCONST16(.03125f,15); -#endif - } len2=len/2; for (c=0;c=0;i--) { - /* Backward masking: 13.9 dB/ms. */ #ifdef FIXED_POINT /* FIXME: Use PSHR16() instead */ tmp[i] = mem0 + PSHR32(tmp[i]-mem0,3); @@ -362,12 +339,6 @@ static int transient_analysis(const opus_val32 * OPUS_RESTRICT in, int len, int /* Compute harmonic mean discarding the unreliable boundaries The data is smooth, so we only take 1/4th of the samples */ unmask=0; - /* We should never see NaNs here. If we find any, then something really bad happened and we better abort - before it does any damage later on. If these asserts are disabled (no hardening), then the table - lookup a few lines below (id = ...) is likely to crash dur to an out-of-bounds read. DO NOT FIX - that crash on NaN since it could result in a worse issue later on. */ - celt_assert(!celt_isnan(tmp[0])); - celt_assert(!celt_isnan(norm)); for (i=12;i200; - /* For low bitrates, define "weak transients" that need to be - handled differently to avoid partial collapse. */ - if (allow_weak_transients && is_transient && mask_metric<600) { - is_transient = 0; - *weak_transient = 1; - } + /* Arbitrary metric for VBR boost */ tf_max = MAX16(0,celt_sqrt(27*mask_metric)-42); /* *tf_estimate = 1 + MIN16(1, sqrt(MAX16(0, tf_max-30))/20); */ @@ -583,7 +549,7 @@ static opus_val32 l1_metric(const celt_norm *tmp, int N, int LM, opus_val16 bias static int tf_analysis(const CELTMode *m, int len, int isTransient, int *tf_res, int lambda, celt_norm *X, int N0, int LM, - opus_val16 tf_estimate, int tf_chan, int *importance) + int *tf_sum, opus_val16 tf_estimate, int tf_chan) { int i; VARDECL(int, metric); @@ -608,6 +574,7 @@ static int tf_analysis(const CELTMode *m, int len, int isTransient, ALLOC(path0, len, int); ALLOC(path1, len, int); + *tf_sum = 0; for (i=0;i> 10; - trim = QCONST16(4.f, 8) + QCONST16(1.f/16.f, 8)*frac; - } if (C==2) { opus_val16 sum = 0; /* Q10 */ @@ -849,7 +809,7 @@ static int alloc_trim_analysis(const CELTMode *m, const celt_norm *X, } while (++c=0;i--) - mask[i] = MAX16(mask[i], mask[i+1] - QCONST16(3.f, DB_SHIFT)); - for (i=0;i> shift; - } - /*for (i=0;i 50 && LM>=1 && !lfe) { @@ -1089,42 +1012,22 @@ static opus_val16 dynalloc_analysis(const opus_val16 *bandLogE, const opus_val16 } for (i=start;i=12) - follower[i] = HALF16(follower[i]); - } -#ifdef DISABLE_FLOAT_API - (void)analysis; -#else - if (analysis->valid) - { - for (i=start;ileak_boost[i]; - } -#endif for (i=start;i=12) + follower[i] = HALF16(follower[i]); follower[i] = MIN16(follower[i], QCONST16(4, DB_SHIFT)); width = C*(eBands[i+1]-eBands[i])<>BITRES>>3 > 2*effectiveBytes/3) + && (tot_boost+boost_bits)>>BITRES>>3 > effectiveBytes/4) { - opus_int32 cap = ((2*effectiveBytes/3)<valid) - gain1 = (opus_val16)(gain1 * analysis->max_pitch_ratio); -#else - (void)analysis; -#endif + /* Gain threshold for enabling the prefilter/postfilter */ pf_threshold = QCONST16(.2f,15); @@ -1298,7 +1193,7 @@ static int compute_vbr(const CELTMode *mode, AnalysisInfo *analysis, opus_int32 int LM, opus_int32 bitrate, int lastCodedBands, int C, int intensity, int constrained_vbr, opus_val16 stereo_saving, int tot_boost, opus_val16 tf_estimate, int pitch_change, opus_val16 maxDepth, - int lfe, int has_surround_mask, opus_val16 surround_masking, + int variable_duration, int lfe, int has_surround_mask, opus_val16 surround_masking, opus_val16 temporal_vbr) { /* The target rate in 8th bits per frame */ @@ -1340,9 +1235,10 @@ static int compute_vbr(const CELTMode *mode, AnalysisInfo *analysis, opus_int32 SHR32(MULT16_16(stereo_saving-QCONST16(0.1f,8),(coded_stereo_dof<tonality-.15f)-0.12f; + tonal = MAX16(0.f,analysis->tonality-.15f)-0.09f; tonal_target = target + (opus_int32)((coded_bins<channels; @@ -1439,6 +1343,7 @@ int celt_encode_with_ec(CELTEncoder * OPUS_RESTRICT st, const opus_val16 * pcm, int end; int effEnd; int codedBands; + int tf_sum; int alloc_trim; int pitch_index=COMBFILTER_MINPERIOD; opus_val16 gain1 = 0; @@ -1450,7 +1355,6 @@ int celt_encode_with_ec(CELTEncoder * OPUS_RESTRICT st, const opus_val16 * pcm, opus_int32 total_boost; opus_int32 balance; opus_int32 tell; - opus_int32 tell0_frac; int prefilter_tapset=0; int pf_on; int anti_collapse_rsv; @@ -1472,10 +1376,7 @@ int celt_encode_with_ec(CELTEncoder * OPUS_RESTRICT st, const opus_val16 * pcm, opus_val16 surround_masking=0; opus_val16 temporal_vbr=0; opus_val16 surround_trim = 0; - opus_int32 equiv_rate; - int hybrid; - int weak_transient = 0; - int enable_tf_analysis; + opus_int32 equiv_rate = 510000; VARDECL(opus_val16, surround_dynalloc); ALLOC_STACK; @@ -1485,7 +1386,6 @@ int celt_encode_with_ec(CELTEncoder * OPUS_RESTRICT st, const opus_val16 * pcm, eBands = mode->eBands; start = st->start; end = st->end; - hybrid = start != 0; tf_estimate = 0; if (nbCompressedBytes<2 || pcm==NULL) { @@ -1509,14 +1409,12 @@ int celt_encode_with_ec(CELTEncoder * OPUS_RESTRICT st, const opus_val16 * pcm, oldBandE = (opus_val16*)(st->in_mem+CC*(overlap+COMBFILTER_MAXPERIOD)); oldLogE = oldBandE + CC*nbEBands; oldLogE2 = oldLogE + CC*nbEBands; - energyError = oldLogE2 + CC*nbEBands; if (enc==NULL) { - tell0_frac=tell=1; + tell=1; nbFilledBytes=0; } else { - tell0_frac=ec_tell_frac(enc); tell=ec_tell(enc); nbFilledBytes=(tell+4)>>3; } @@ -1569,11 +1467,10 @@ int celt_encode_with_ec(CELTEncoder * OPUS_RESTRICT st, const opus_val16 * pcm, if (st->bitrate!=OPUS_BITRATE_MAX) nbCompressedBytes = IMAX(2, IMIN(nbCompressedBytes, (tmp+4*mode->Fs)/(8*mode->Fs)-!!st->signalling)); - effectiveBytes = nbCompressedBytes - nbFilledBytes; + effectiveBytes = nbCompressedBytes; } - equiv_rate = ((opus_int32)nbCompressedBytes*8*50 >> (3-LM)) - (40*C+20)*((400>>LM) - 50); if (st->bitrate != OPUS_BITRATE_MAX) - equiv_rate = IMIN(equiv_rate, st->bitrate - (40*C+20)*((400>>LM) - 50)); + equiv_rate = st->bitrate - (40*C+20)*((400>>LM) - 50); if (enc==NULL) { @@ -1661,17 +1558,17 @@ int celt_encode_with_ec(CELTEncoder * OPUS_RESTRICT st, const opus_val16 * pcm, { int enabled; int qg; - enabled = ((st->lfe&&nbAvailableBytes>3) || nbAvailableBytes>12*C) && !hybrid && !silence && !st->disable_pf - && st->complexity >= 5; + enabled = ((st->lfe&&nbAvailableBytes>3) || nbAvailableBytes>12*C) && start==0 && !silence && !st->disable_pf + && st->complexity >= 5 && !(st->consec_transient && LM!=3 && st->variable_duration==OPUS_FRAMESIZE_VARIABLE); prefilter_tapset = st->tapset_decision; - pf_on = run_prefilter(st, in, prefilter_mem, CC, N, prefilter_tapset, &pitch_index, &gain1, &qg, enabled, nbAvailableBytes, &st->analysis); + pf_on = run_prefilter(st, in, prefilter_mem, CC, N, prefilter_tapset, &pitch_index, &gain1, &qg, enabled, nbAvailableBytes); if ((gain1 > QCONST16(.4f,15) || st->prefilter_gain > QCONST16(.4f,15)) && (!st->analysis.valid || st->analysis.tonality > .3) && (pitch_index > 1.26*st->prefilter_period || pitch_index < .79*st->prefilter_period)) pitch_change = 1; if (pf_on==0) { - if(!hybrid && tell+16<=total_bits) + if(start==0 && tell+16<=total_bits) ec_enc_bit_logp(enc, 0, 1); } else { /*This block is not gated by a total bits check only because @@ -1692,12 +1589,8 @@ int celt_encode_with_ec(CELTEncoder * OPUS_RESTRICT st, const opus_val16 * pcm, shortBlocks = 0; if (st->complexity >= 1 && !st->lfe) { - /* Reduces the likelihood of energy instability on fricatives at low bitrate - in hybrid mode. It seems like we still want to have real transients on vowels - though (small SILK quantization offset value). */ - int allow_weak_transients = hybrid && effectiveBytes<15 && st->silk_info.signalType != 2; isTransient = transient_analysis(in, N+overlap, CC, - &tf_estimate, &tf_chan, allow_weak_transients, &weak_transient); + &tf_estimate, &tf_chan); } if (LM>0 && ec_tell(enc)+3<=total_bits) { @@ -1717,19 +1610,16 @@ int celt_encode_with_ec(CELTEncoder * OPUS_RESTRICT st, const opus_val16 * pcm, if (secondMdct) { compute_mdcts(mode, 0, in, freq, C, CC, LM, st->upsample, st->arch); - compute_band_energies(mode, freq, bandE, effEnd, C, LM, st->arch); + compute_band_energies(mode, freq, bandE, effEnd, C, LM); amp2Log2(mode, effEnd, end, bandE, bandLogE2, C); for (i=0;iupsample, st->arch); - /* This should catch any NaN in the CELT input. Since we're not supposed to see any (they're filtered - at the Opus layer), just abort. */ - celt_assert(!celt_isnan(freq[0]) && (C==1 || !celt_isnan(freq[N]))); if (CC==2&&C==1) tf_chan = 0; - compute_band_energies(mode, freq, bandE, effEnd, C, LM, st->arch); + compute_band_energies(mode, freq, bandE, effEnd, C, LM); if (st->lfe) { @@ -1744,7 +1634,7 @@ int celt_encode_with_ec(CELTEncoder * OPUS_RESTRICT st, const opus_val16 * pcm, ALLOC(surround_dynalloc, C*nbEBands, opus_val16); OPUS_CLEAR(surround_dynalloc, end); /* This computes how much masking takes place between surround channels */ - if (!hybrid&&st->energy_mask&&!st->lfe) + if (start==0&&st->energy_mask&&!st->lfe) { int mask_end; int midband; @@ -1846,14 +1736,14 @@ int celt_encode_with_ec(CELTEncoder * OPUS_RESTRICT st, const opus_val16 * pcm, /* Last chance to catch any transient we might have missed in the time-domain analysis */ - if (LM>0 && ec_tell(enc)+3<=total_bits && !isTransient && st->complexity>=5 && !st->lfe && !hybrid) + if (LM>0 && ec_tell(enc)+3<=total_bits && !isTransient && st->complexity>=5 && !st->lfe) { if (patch_transient_decision(bandLogE, oldBandE, nbEBands, start, end, C)) { isTransient = 1; shortBlocks = M; compute_mdcts(mode, shortBlocks, in, freq, C, CC, LM, st->upsample, st->arch); - compute_band_energies(mode, freq, bandE, effEnd, C, LM, st->arch); + compute_band_energies(mode, freq, bandE, effEnd, C, LM); amp2Log2(mode, effEnd, end, bandE, bandLogE, C); /* Compensate for the scaling of short vs long mdcts */ for (i=0;i=15*C && !hybrid && st->complexity>=2 && !st->lfe; - - ALLOC(offsets, nbEBands, int); - ALLOC(importance, nbEBands, int); - ALLOC(spread_weight, nbEBands, int); - - maxDepth = dynalloc_analysis(bandLogE, bandLogE2, nbEBands, start, end, C, offsets, - st->lsb_depth, mode->logN, isTransient, st->vbr, st->constrained_vbr, - eBands, LM, effectiveBytes, &tot_boost, st->lfe, surround_dynalloc, &st->analysis, importance, spread_weight); - ALLOC(tf_res, nbEBands, int); /* Disable variable tf resolution for hybrid and at very low bitrate */ - if (enable_tf_analysis) + if (effectiveBytes>=15*C && start==0 && st->complexity>=2 && !st->lfe) { int lambda; - lambda = IMAX(80, 20480/effectiveBytes + 2); - tf_select = tf_analysis(mode, effEnd, isTransient, tf_res, lambda, X, N, LM, tf_estimate, tf_chan, importance); + if (effectiveBytes<40) + lambda = 12; + else if (effectiveBytes<60) + lambda = 6; + else if (effectiveBytes<100) + lambda = 4; + else + lambda = 3; + lambda*=2; + tf_select = tf_analysis(mode, effEnd, isTransient, tf_res, lambda, X, N, LM, &tf_sum, tf_estimate, tf_chan); for (i=effEnd;isilk_info.signalType != 2) - { - /* For low bitrate hybrid, we force temporal resolution to 5 ms rather than 2.5 ms. */ - for (i=0;iforce_intra, @@ -1936,15 +1798,7 @@ int celt_encode_with_ec(CELTEncoder * OPUS_RESTRICT st, const opus_val16 * pcm, { st->tapset_decision = 0; st->spread_decision = SPREAD_NORMAL; - } else if (hybrid) - { - if (st->complexity == 0) - st->spread_decision = SPREAD_NONE; - else if (isTransient) - st->spread_decision = SPREAD_NORMAL; - else - st->spread_decision = SPREAD_AGGRESSIVE; - } else if (shortBlocks || st->complexity < 3 || nbAvailableBytes < 10*C) + } else if (shortBlocks || st->complexity < 3 || nbAvailableBytes < 10*C || start != 0) { if (st->complexity == 0) st->spread_decision = SPREAD_NONE; @@ -1968,7 +1822,7 @@ int celt_encode_with_ec(CELTEncoder * OPUS_RESTRICT st, const opus_val16 * pcm, { st->spread_decision = spreading_decision(mode, X, &st->tonal_average, st->spread_decision, &st->hf_average, - &st->tapset_decision, pf_on&&!shortBlocks, effEnd, C, M, spread_weight); + &st->tapset_decision, pf_on&&!shortBlocks, effEnd, C, M); } /*printf("%d %d\n", st->tapset_decision, st->spread_decision);*/ /*printf("%f %d %f %d\n\n", st->analysis.tonality, st->spread_decision, st->analysis.tonality_slope, st->tapset_decision);*/ @@ -1976,6 +1830,11 @@ int celt_encode_with_ec(CELTEncoder * OPUS_RESTRICT st, const opus_val16 * pcm, ec_enc_icdf(enc, st->spread_decision, spread_icdf, 5); } + ALLOC(offsets, nbEBands, int); + + maxDepth = dynalloc_analysis(bandLogE, bandLogE2, nbEBands, start, end, C, offsets, + st->lsb_depth, mode->logN, isTransient, st->vbr, st->constrained_vbr, + eBands, LM, effectiveBytes, &tot_boost, st->lfe, surround_dynalloc); /* For LFE, everything interesting is in the first band */ if (st->lfe) offsets[0] = IMIN(8, effectiveBytes/3); @@ -2037,15 +1896,12 @@ int celt_encode_with_ec(CELTEncoder * OPUS_RESTRICT st, const opus_val16 * pcm, alloc_trim = 5; if (tell+(6< 0 || st->lfe) - { - st->stereo_saving = 0; + if (st->lfe) alloc_trim = 5; - } else { + else alloc_trim = alloc_trim_analysis(mode, X, bandLogE, end, LM, C, N, &st->analysis, &st->stereo_saving, tf_estimate, - st->intensity, surround_trim, equiv_rate, st->arch); - } + st->intensity, surround_trim, st->arch); ec_enc_icdf(enc, alloc_trim, trim_icdf, 7); tell = ec_tell_frac(enc); } @@ -2063,36 +1919,17 @@ int celt_encode_with_ec(CELTEncoder * OPUS_RESTRICT st, const opus_val16 * pcm, /* Don't attempt to use more than 510 kb/s, even for frames smaller than 20 ms. The CELT allocator will just not be able to use more than that anyway. */ nbCompressedBytes = IMIN(nbCompressedBytes,1275>>(3-LM)); - if (!hybrid) - { - base_target = vbr_rate - ((40*C+20)<constrained_vbr) base_target += (st->vbr_offset>>lm_diff); - if (!hybrid) - { - target = compute_vbr(mode, &st->analysis, base_target, LM, equiv_rate, + target = compute_vbr(mode, &st->analysis, base_target, LM, equiv_rate, st->lastCodedBands, C, st->intensity, st->constrained_vbr, st->stereo_saving, tot_boost, tf_estimate, pitch_change, maxDepth, - st->lfe, st->energy_mask!=NULL, surround_masking, + st->variable_duration, st->lfe, st->energy_mask!=NULL, surround_masking, temporal_vbr); - } else { - target = base_target; - /* Tonal frames (offset<100) need more bits than noisy (offset>100) ones. */ - if (st->silk_info.offset < 100) target += 12 << BITRES >> (3-LM); - if (st->silk_info.offset > 100) target -= 18 << BITRES >> (3-LM); - /* Boosting bitrate on transients and vowels with significant temporal - spikes. */ - target += (opus_int32)MULT16_16_Q14(tf_estimate-QCONST16(.25f,14), (50< QCONST16(.7f,14)) - target = IMAX(target, 50<>(BITRES+3)) + 2; - /* Take into account the 37 bits we need to have left in the packet to - signal a redundant frame in hybrid mode. Creating a shorter packet would - create an entropy coder desync. */ - if (hybrid) - min_allowed = IMAX(min_allowed, (tell0_frac+(37<>(BITRES+3)); + min_allowed = ((tell+total_boost+(1<<(BITRES+3))-1)>>(BITRES+3)) + 2 - nbFilledBytes; nbAvailableBytes = (target+(1<<(BITRES+2)))>>(BITRES+3); nbAvailableBytes = IMAX(min_allowed,nbAvailableBytes); - nbAvailableBytes = IMIN(nbCompressedBytes,nbAvailableBytes); + nbAvailableBytes = IMIN(nbCompressedBytes,nbAvailableBytes+nbFilledBytes) - nbFilledBytes; /* By how much did we "miss" the target on that frame */ delta = target - vbr_rate; @@ -2156,7 +1988,7 @@ int celt_encode_with_ec(CELTEncoder * OPUS_RESTRICT st, const opus_val16 * pcm, st->vbr_reservoir = 0; /*printf ("+%d\n", adjust);*/ } - nbCompressedBytes = IMIN(nbCompressedBytes,nbAvailableBytes); + nbCompressedBytes = IMIN(nbCompressedBytes,nbAvailableBytes+nbFilledBytes); /*printf("%d\n", nbCompressedBytes*50*8);*/ /* This moves the raw bits to take into account the new compressed size */ ec_enc_shrink(enc, nbCompressedBytes); @@ -2191,7 +2023,7 @@ int celt_encode_with_ec(CELTEncoder * OPUS_RESTRICT st, const opus_val16 * pcm, #endif if (st->lfe) signalBandwidth = 1; - codedBands = clt_compute_allocation(mode, start, end, offsets, cap, + codedBands = compute_allocation(mode, start, end, offsets, cap, alloc_trim, &st->intensity, &dual_stereo, bits, &balance, pulses, fine_quant, fine_priority, C, LM, enc, 1, st->lastCodedBands, signalBandwidth); if (st->lastCodedBands) @@ -2206,7 +2038,7 @@ int celt_encode_with_ec(CELTEncoder * OPUS_RESTRICT st, const opus_val16 * pcm, quant_all_bands(1, mode, start, end, X, C==2 ? X+N : NULL, collapse_masks, bandE, pulses, shortBlocks, st->spread_decision, dual_stereo, st->intensity, tf_res, nbCompressedBytes*(8<rng, st->complexity, st->arch, st->disable_inv); + balance, enc, LM, codedBands, &st->rng, st->arch); if (anti_collapse_rsv > 0) { @@ -2217,14 +2049,6 @@ int celt_encode_with_ec(CELTEncoder * OPUS_RESTRICT st, const opus_val16 * pcm, ec_enc_bits(enc, anti_collapse_on, 1); } quant_energy_finalise(mode, start, end, oldBandE, error, fine_quant, fine_priority, nbCompressedBytes*8-ec_tell(enc), enc, C); - OPUS_CLEAR(energyError, nbEBands*CC); - c=0; - do { - for (i=start;ilsb_depth; } break; - case OPUS_SET_PHASE_INVERSION_DISABLED_REQUEST: + case OPUS_SET_EXPERT_FRAME_DURATION_REQUEST: { opus_int32 value = va_arg(ap, opus_int32); - if(value<0 || value>1) - { - goto bad_arg; - } - st->disable_inv = value; - } - break; - case OPUS_GET_PHASE_INVERSION_DISABLED_REQUEST: - { - opus_int32 *value = va_arg(ap, opus_int32*); - if (!value) - { - goto bad_arg; - } - *value = st->disable_inv; + st->variable_duration = value; } break; case OPUS_RESET_STATE: @@ -2558,13 +2368,6 @@ int opus_custom_encoder_ctl(CELTEncoder * OPUS_RESTRICT st, int request, ...) OPUS_COPY(&st->analysis, info, 1); } break; - case CELT_SET_SILK_INFO_REQUEST: - { - SILKInfo *info = va_arg(ap, SILKInfo *); - if (info) - OPUS_COPY(&st->silk_info, info, 1); - } - break; case CELT_GET_MODE_REQUEST: { const CELTMode ** value = va_arg(ap, const CELTMode**); diff --git a/thirdparty/opus/celt/celt_lpc.c b/thirdparty/opus/celt/celt_lpc.c index 8ecb693ee98..b410a21c5f6 100644 --- a/thirdparty/opus/celt/celt_lpc.c +++ b/thirdparty/opus/celt/celt_lpc.c @@ -89,40 +89,58 @@ int p void celt_fir_c( - const opus_val16 *x, + const opus_val16 *_x, const opus_val16 *num, - opus_val16 *y, + opus_val16 *_y, int N, int ord, + opus_val16 *mem, int arch) { int i,j; VARDECL(opus_val16, rnum); + VARDECL(opus_val16, x); SAVE_STACK; - celt_assert(x != y); + ALLOC(rnum, ord, opus_val16); + ALLOC(x, N+ord, opus_val16); for(i=0;i_i){ - celt_sig_assert(p>q); + celt_assert(p>q); _k=_n; do p=CELT_PVQ_U_ROW[--_k][_n]; while(p>_i); diff --git a/thirdparty/opus/celt/entcode.h b/thirdparty/opus/celt/entcode.h index 3763e3f2842..13d6c84ef0f 100644 --- a/thirdparty/opus/celt/entcode.h +++ b/thirdparty/opus/celt/entcode.h @@ -122,7 +122,7 @@ opus_uint32 ec_tell_frac(ec_ctx *_this); /* Tested exhaustively for all n and for 1<=d<=256 */ static OPUS_INLINE opus_uint32 celt_udiv(opus_uint32 n, opus_uint32 d) { - celt_sig_assert(d>0); + celt_assert(d>0); #ifdef USE_SMALL_DIV_TABLE if (d>256) return n/d; @@ -138,7 +138,7 @@ static OPUS_INLINE opus_uint32 celt_udiv(opus_uint32 n, opus_uint32 d) { } static OPUS_INLINE opus_int32 celt_sudiv(opus_int32 n, opus_int32 d) { - celt_sig_assert(d>0); + celt_assert(d>0); #ifdef USE_SMALL_DIV_TABLE if (n<0) return -(opus_int32)celt_udiv(-n, d); diff --git a/thirdparty/opus/celt/entdec.h b/thirdparty/opus/celt/entdec.h index 025fc1870d6..d8ab3187308 100644 --- a/thirdparty/opus/celt/entdec.h +++ b/thirdparty/opus/celt/entdec.h @@ -85,7 +85,7 @@ int ec_dec_icdf(ec_dec *_this,const unsigned char *_icdf,unsigned _ftb); The bits must have been encoded with ec_enc_uint(). No call to ec_dec_update() is necessary after this call. _ft: The number of integers that can be decoded (one more than the max). - This must be at least 2, and no more than 2**32-1. + This must be at least one, and no more than 2**32-1. Return: The decoded bits.*/ opus_uint32 ec_dec_uint(ec_dec *_this,opus_uint32 _ft); diff --git a/thirdparty/opus/celt/entenc.h b/thirdparty/opus/celt/entenc.h index f502eaf6624..796bc4d5727 100644 --- a/thirdparty/opus/celt/entenc.h +++ b/thirdparty/opus/celt/entenc.h @@ -67,7 +67,7 @@ void ec_enc_icdf(ec_enc *_this,int _s,const unsigned char *_icdf,unsigned _ftb); /*Encodes a raw unsigned integer in the stream. _fl: The integer to encode. _ft: The number of integers that can be encoded (one more than the max). - This must be at least 2, and no more than 2**32-1.*/ + This must be at least one, and no more than 2**32-1.*/ void ec_enc_uint(ec_enc *_this,opus_uint32 _fl,opus_uint32 _ft); /*Encodes a sequence of raw bits in the stream. diff --git a/thirdparty/opus/celt/fixed_c5x.h b/thirdparty/opus/celt/fixed_c5x.h deleted file mode 100644 index ea95a998c3c..00000000000 --- a/thirdparty/opus/celt/fixed_c5x.h +++ /dev/null @@ -1,79 +0,0 @@ -/* Copyright (C) 2003 Jean-Marc Valin */ -/** - @file fixed_c5x.h - @brief Fixed-point operations for the TI C5x DSP family -*/ -/* - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions - are met: - - - Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - - - Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER - OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ - -#ifndef FIXED_C5X_H -#define FIXED_C5X_H - -#include "dsplib.h" - -#undef IMUL32 -static OPUS_INLINE long IMUL32(long i, long j) -{ - long ac0, ac1; - ac0 = _lmpy(i>>16,j); - ac1 = ac0 + _lmpy(i,j>>16); - return _lmpyu(i,j) + (ac1<<16); -} - -#undef MAX16 -#define MAX16(a,b) _max(a,b) - -#undef MIN16 -#define MIN16(a,b) _min(a,b) - -#undef MAX32 -#define MAX32(a,b) _lmax(a,b) - -#undef MIN32 -#define MIN32(a,b) _lmin(a,b) - -#undef VSHR32 -#define VSHR32(a, shift) _lshl(a,-(shift)) - -#undef MULT16_16_Q15 -#define MULT16_16_Q15(a,b) (_smpy(a,b)) - -#undef MULT16_16SU -#define MULT16_16SU(a,b) _lmpysu(a,b) - -#undef MULT_16_16 -#define MULT_16_16(a,b) _lmpy(a,b) - -/* FIXME: This is technically incorrect and is bound to cause problems. Is there any cleaner solution? */ -#undef MULT16_32_Q15 -#define MULT16_32_Q15(a,b) ADD32(SHL(MULT16_16((a),SHR((b),16)),1), SHR(MULT16_16SU((a),(b)),15)) - -#define celt_ilog2(x) (30 - _lnorm(x)) -#define OVERRIDE_CELT_ILOG2 - -#define celt_maxabs16(x, len) MAX32(EXTEND32(maxval((DATA *)x, len)),-EXTEND32(minval((DATA *)x, len))) -#define OVERRIDE_CELT_MAXABS16 - -#endif /* FIXED_C5X_H */ diff --git a/thirdparty/opus/celt/fixed_c6x.h b/thirdparty/opus/celt/fixed_c6x.h deleted file mode 100644 index bb6ad927803..00000000000 --- a/thirdparty/opus/celt/fixed_c6x.h +++ /dev/null @@ -1,70 +0,0 @@ -/* Copyright (C) 2008 CSIRO */ -/** - @file fixed_c6x.h - @brief Fixed-point operations for the TI C6x DSP family -*/ -/* - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions - are met: - - - Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - - - Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER - OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ - -#ifndef FIXED_C6X_H -#define FIXED_C6X_H - -#undef MULT16_16SU -#define MULT16_16SU(a,b) _mpysu(a,b) - -#undef MULT_16_16 -#define MULT_16_16(a,b) _mpy(a,b) - -#define celt_ilog2(x) (30 - _norm(x)) -#define OVERRIDE_CELT_ILOG2 - -#undef MULT16_32_Q15 -#define MULT16_32_Q15(a,b) (_mpylill(a, b) >> 15) - -#if 0 -#include "dsplib.h" - -#undef MAX16 -#define MAX16(a,b) _max(a,b) - -#undef MIN16 -#define MIN16(a,b) _min(a,b) - -#undef MAX32 -#define MAX32(a,b) _lmax(a,b) - -#undef MIN32 -#define MIN32(a,b) _lmin(a,b) - -#undef VSHR32 -#define VSHR32(a, shift) _lshl(a,-(shift)) - -#undef MULT16_16_Q15 -#define MULT16_16_Q15(a,b) (_smpy(a,b)) - -#define celt_maxabs16(x, len) MAX32(EXTEND32(maxval((DATA *)x, len)),-EXTEND32(minval((DATA *)x, len))) -#define OVERRIDE_CELT_MAXABS16 - -#endif /* FIXED_C6X_H */ diff --git a/thirdparty/opus/celt/fixed_debug.h b/thirdparty/opus/celt/fixed_debug.h index f435295234c..d28227f5dc7 100644 --- a/thirdparty/opus/celt/fixed_debug.h +++ b/thirdparty/opus/celt/fixed_debug.h @@ -59,14 +59,6 @@ extern opus_int64 celt_mips; #define SHR(a,b) SHR32(a,b) #define PSHR(a,b) PSHR32(a,b) -/** Add two 32-bit values, ignore any overflows */ -#define ADD32_ovflw(a,b) (celt_mips+=2,(opus_val32)((opus_uint32)(a)+(opus_uint32)(b))) -/** Subtract two 32-bit values, ignore any overflows */ -#define SUB32_ovflw(a,b) (celt_mips+=2,(opus_val32)((opus_uint32)(a)-(opus_uint32)(b))) -/* Avoid MSVC warning C4146: unary minus operator applied to unsigned type */ -/** Negate 32-bit value, ignore any overflows */ -#define NEG32_ovflw(a) (celt_mips+=2,(opus_val32)(0-(opus_uint32)(a))) - static OPUS_INLINE short NEG16(int x) { int res; @@ -235,11 +227,12 @@ static OPUS_INLINE int SHL32_(opus_int64 a, int shift, char *file, int line) #define VSHR32(a, shift) (((shift)>0) ? SHR32(a, shift) : SHL32(a, -(shift))) #define ROUND16(x,a) (celt_mips--,EXTRACT16(PSHR32((x),(a)))) -#define SROUND16(x,a) (celt_mips--,EXTRACT16(SATURATE(PSHR32(x,a), 32767))); - #define HALF16(x) (SHR16(x,1)) #define HALF32(x) (SHR32(x,1)) +//#define SHR(a,shift) ((a) >> (shift)) +//#define SHL(a,shift) ((a) << (shift)) + #define ADD16(a, b) ADD16_(a, b, __FILE__, __LINE__) static OPUS_INLINE short ADD16_(int a, int b, char *file, int line) { diff --git a/thirdparty/opus/celt/fixed_generic.h b/thirdparty/opus/celt/fixed_generic.h index 5f4abda76ed..1cfd6d69890 100644 --- a/thirdparty/opus/celt/fixed_generic.h +++ b/thirdparty/opus/celt/fixed_generic.h @@ -104,9 +104,6 @@ /** Shift by a and round-to-neareast 32-bit value. Result is a 16-bit value */ #define ROUND16(x,a) (EXTRACT16(PSHR32((x),(a)))) -/** Shift by a and round-to-neareast 32-bit value. Result is a saturated 16-bit value */ -#define SROUND16(x,a) EXTRACT16(SATURATE(PSHR32(x,a), 32767)); - /** Divide by two */ #define HALF16(x) (SHR16(x,1)) #define HALF32(x) (SHR32(x,1)) @@ -120,14 +117,6 @@ /** Subtract two 32-bit values */ #define SUB32(a,b) ((opus_val32)(a)-(opus_val32)(b)) -/** Add two 32-bit values, ignore any overflows */ -#define ADD32_ovflw(a,b) ((opus_val32)((opus_uint32)(a)+(opus_uint32)(b))) -/** Subtract two 32-bit values, ignore any overflows */ -#define SUB32_ovflw(a,b) ((opus_val32)((opus_uint32)(a)-(opus_uint32)(b))) -/* Avoid MSVC warning C4146: unary minus operator applied to unsigned type */ -/** Negate 32-bit value, ignore any overflows */ -#define NEG32_ovflw(a) ((opus_val32)(0-(opus_uint32)(a))) - /** 16x16 multiplication where the result fits in 16 bits */ #define MULT16_16_16(a,b) ((((opus_val16)(a))*((opus_val16)(b)))) diff --git a/thirdparty/opus/celt/float_cast.h b/thirdparty/opus/celt/float_cast.h index 889dae965fa..ed5a39b5433 100644 --- a/thirdparty/opus/celt/float_cast.h +++ b/thirdparty/opus/celt/float_cast.h @@ -61,13 +61,7 @@ ** the config.h file. */ -/* With GCC, when SSE is available, the fastest conversion is cvtss2si. */ -#if defined(__GNUC__) && defined(__SSE__) - -#include -static OPUS_INLINE opus_int32 float2int(float x) {return _mm_cvt_ss2si(_mm_set_ss(x));} - -#elif defined(HAVE_LRINTF) +#if (HAVE_LRINTF) /* These defines enable functionality introduced with the 1999 ISO C ** standard. They must be defined before the inclusion of math.h to @@ -96,10 +90,10 @@ static OPUS_INLINE opus_int32 float2int(float x) {return _mm_cvt_ss2si(_mm_set_s #include #define float2int(x) lrint(x) -#elif (defined(_MSC_VER) && _MSC_VER >= 1400) && (defined(_M_X64) || (defined(_M_IX86_FP) && _M_IX86_FP >= 1)) +#elif (defined(_MSC_VER) && _MSC_VER >= 1400) && defined (_M_X64) #include - static __inline long int float2int(float value) + __inline long int float2int(float value) { return _mm_cvtss_si32(_mm_load_ss(&value)); } @@ -110,7 +104,7 @@ static OPUS_INLINE opus_int32 float2int(float x) {return _mm_cvt_ss2si(_mm_set_s ** Therefore implement OPUS_INLINE versions of these functions here. */ - static __inline long int + __inline long int float2int (float flt) { int intgr; diff --git a/thirdparty/opus/celt/kiss_fft.c b/thirdparty/opus/celt/kiss_fft.c index 83775165d86..1f8fd05321a 100644 --- a/thirdparty/opus/celt/kiss_fft.c +++ b/thirdparty/opus/celt/kiss_fft.c @@ -82,8 +82,8 @@ static void kf_bfly2( C_SUB( Fout2[0] , Fout[0] , t ); C_ADDTO( Fout[0] , t ); - t.r = S_MUL(ADD32_ovflw(Fout2[1].r, Fout2[1].i), tw); - t.i = S_MUL(SUB32_ovflw(Fout2[1].i, Fout2[1].r), tw); + t.r = S_MUL(Fout2[1].r+Fout2[1].i, tw); + t.i = S_MUL(Fout2[1].i-Fout2[1].r, tw); C_SUB( Fout2[1] , Fout[1] , t ); C_ADDTO( Fout[1] , t ); @@ -92,8 +92,8 @@ static void kf_bfly2( C_SUB( Fout2[2] , Fout[2] , t ); C_ADDTO( Fout[2] , t ); - t.r = S_MUL(SUB32_ovflw(Fout2[3].i, Fout2[3].r), tw); - t.i = S_MUL(NEG32_ovflw(ADD32_ovflw(Fout2[3].i, Fout2[3].r)), tw); + t.r = S_MUL(Fout2[3].i-Fout2[3].r, tw); + t.i = S_MUL(-Fout2[3].i-Fout2[3].r, tw); C_SUB( Fout2[3] , Fout[3] , t ); C_ADDTO( Fout[3] , t ); Fout += 8; @@ -126,10 +126,10 @@ static void kf_bfly4( C_ADDTO( *Fout , scratch1 ); C_SUB( scratch1 , Fout[1] , Fout[3] ); - Fout[1].r = ADD32_ovflw(scratch0.r, scratch1.i); - Fout[1].i = SUB32_ovflw(scratch0.i, scratch1.r); - Fout[3].r = SUB32_ovflw(scratch0.r, scratch1.i); - Fout[3].i = ADD32_ovflw(scratch0.i, scratch1.r); + Fout[1].r = scratch0.r + scratch1.i; + Fout[1].i = scratch0.i - scratch1.r; + Fout[3].r = scratch0.r - scratch1.i; + Fout[3].i = scratch0.i + scratch1.r; Fout+=4; } } else { @@ -160,10 +160,10 @@ static void kf_bfly4( tw3 += fstride*3; C_ADDTO( *Fout , scratch[3] ); - Fout[m].r = ADD32_ovflw(scratch[5].r, scratch[4].i); - Fout[m].i = SUB32_ovflw(scratch[5].i, scratch[4].r); - Fout[m3].r = SUB32_ovflw(scratch[5].r, scratch[4].i); - Fout[m3].i = ADD32_ovflw(scratch[5].i, scratch[4].r); + Fout[m].r = scratch[5].r + scratch[4].i; + Fout[m].i = scratch[5].i - scratch[4].r; + Fout[m3].r = scratch[5].r - scratch[4].i; + Fout[m3].i = scratch[5].i + scratch[4].r; ++Fout; } } @@ -212,18 +212,18 @@ static void kf_bfly3( tw1 += fstride; tw2 += fstride*2; - Fout[m].r = SUB32_ovflw(Fout->r, HALF_OF(scratch[3].r)); - Fout[m].i = SUB32_ovflw(Fout->i, HALF_OF(scratch[3].i)); + Fout[m].r = Fout->r - HALF_OF(scratch[3].r); + Fout[m].i = Fout->i - HALF_OF(scratch[3].i); C_MULBYSCALAR( scratch[0] , epi3.i ); C_ADDTO(*Fout,scratch[3]); - Fout[m2].r = ADD32_ovflw(Fout[m].r, scratch[0].i); - Fout[m2].i = SUB32_ovflw(Fout[m].i, scratch[0].r); + Fout[m2].r = Fout[m].r + scratch[0].i; + Fout[m2].i = Fout[m].i - scratch[0].r; - Fout[m].r = SUB32_ovflw(Fout[m].r, scratch[0].i); - Fout[m].i = ADD32_ovflw(Fout[m].i, scratch[0].r); + Fout[m].r -= scratch[0].i; + Fout[m].i += scratch[0].r; ++Fout; } while(--k); @@ -282,22 +282,22 @@ static void kf_bfly5( C_ADD( scratch[8],scratch[2],scratch[3]); C_SUB( scratch[9],scratch[2],scratch[3]); - Fout0->r = ADD32_ovflw(Fout0->r, ADD32_ovflw(scratch[7].r, scratch[8].r)); - Fout0->i = ADD32_ovflw(Fout0->i, ADD32_ovflw(scratch[7].i, scratch[8].i)); + Fout0->r += scratch[7].r + scratch[8].r; + Fout0->i += scratch[7].i + scratch[8].i; - scratch[5].r = ADD32_ovflw(scratch[0].r, ADD32_ovflw(S_MUL(scratch[7].r,ya.r), S_MUL(scratch[8].r,yb.r))); - scratch[5].i = ADD32_ovflw(scratch[0].i, ADD32_ovflw(S_MUL(scratch[7].i,ya.r), S_MUL(scratch[8].i,yb.r))); + scratch[5].r = scratch[0].r + S_MUL(scratch[7].r,ya.r) + S_MUL(scratch[8].r,yb.r); + scratch[5].i = scratch[0].i + S_MUL(scratch[7].i,ya.r) + S_MUL(scratch[8].i,yb.r); - scratch[6].r = ADD32_ovflw(S_MUL(scratch[10].i,ya.i), S_MUL(scratch[9].i,yb.i)); - scratch[6].i = NEG32_ovflw(ADD32_ovflw(S_MUL(scratch[10].r,ya.i), S_MUL(scratch[9].r,yb.i))); + scratch[6].r = S_MUL(scratch[10].i,ya.i) + S_MUL(scratch[9].i,yb.i); + scratch[6].i = -S_MUL(scratch[10].r,ya.i) - S_MUL(scratch[9].r,yb.i); C_SUB(*Fout1,scratch[5],scratch[6]); C_ADD(*Fout4,scratch[5],scratch[6]); - scratch[11].r = ADD32_ovflw(scratch[0].r, ADD32_ovflw(S_MUL(scratch[7].r,yb.r), S_MUL(scratch[8].r,ya.r))); - scratch[11].i = ADD32_ovflw(scratch[0].i, ADD32_ovflw(S_MUL(scratch[7].i,yb.r), S_MUL(scratch[8].i,ya.r))); - scratch[12].r = SUB32_ovflw(S_MUL(scratch[9].i,ya.i), S_MUL(scratch[10].i,yb.i)); - scratch[12].i = SUB32_ovflw(S_MUL(scratch[10].r,yb.i), S_MUL(scratch[9].r,ya.i)); + scratch[11].r = scratch[0].r + S_MUL(scratch[7].r,yb.r) + S_MUL(scratch[8].r,ya.r); + scratch[11].i = scratch[0].i + S_MUL(scratch[7].i,yb.r) + S_MUL(scratch[8].i,ya.r); + scratch[12].r = - S_MUL(scratch[10].i,yb.i) + S_MUL(scratch[9].i,ya.i); + scratch[12].i = S_MUL(scratch[10].r,yb.i) - S_MUL(scratch[9].r,ya.i); C_ADD(*Fout2,scratch[11],scratch[12]); C_SUB(*Fout3,scratch[11],scratch[12]); diff --git a/thirdparty/opus/celt/mathops.c b/thirdparty/opus/celt/mathops.c index 6ee9b9e1016..21a01f52e43 100644 --- a/thirdparty/opus/celt/mathops.c +++ b/thirdparty/opus/celt/mathops.c @@ -38,8 +38,7 @@ #include "mathops.h" /*Compute floor(sqrt(_val)) with exact arithmetic. - _val must be greater than 0. - This has been tested on all possible 32-bit inputs greater than 0.*/ + This has been tested on all possible 32-bit inputs.*/ unsigned isqrt32(opus_uint32 _val){ unsigned b; unsigned g; @@ -183,7 +182,7 @@ opus_val32 celt_rcp(opus_val32 x) int i; opus_val16 n; opus_val16 r; - celt_sig_assert(x>0); + celt_assert2(x>0, "celt_rcp() only defined for positive values"); i = celt_ilog2(x); /* n is Q15 with range [0,1). */ n = VSHR32(x,i-15)-32768; diff --git a/thirdparty/opus/celt/mathops.h b/thirdparty/opus/celt/mathops.h index 5e86ff0dd25..a0525a96103 100644 --- a/thirdparty/opus/celt/mathops.h +++ b/thirdparty/opus/celt/mathops.h @@ -38,44 +38,11 @@ #include "entcode.h" #include "os_support.h" -#define PI 3.141592653f - /* Multiplies two 16-bit fractional values. Bit-exactness of this macro is important */ #define FRAC_MUL16(a,b) ((16384+((opus_int32)(opus_int16)(a)*(opus_int16)(b)))>>15) unsigned isqrt32(opus_uint32 _val); -/* CELT doesn't need it for fixed-point, by analysis.c does. */ -#if !defined(FIXED_POINT) || defined(ANALYSIS_C) -#define cA 0.43157974f -#define cB 0.67848403f -#define cC 0.08595542f -#define cE ((float)PI/2) -static OPUS_INLINE float fast_atan2f(float y, float x) { - float x2, y2; - x2 = x*x; - y2 = y*y; - /* For very small values, we don't care about the answer, so - we can just return 0. */ - if (x2 + y2 < 1e-18f) - { - return 0; - } - if(x20); + celt_assert2(x>0, "celt_ilog2() only defined for strictly positive numbers"); return EC_ILOG(x)-1; } #endif diff --git a/thirdparty/opus/celt/mdct.c b/thirdparty/opus/celt/mdct.c index 5c6dab5b757..5315ad11a37 100644 --- a/thirdparty/opus/celt/mdct.c +++ b/thirdparty/opus/celt/mdct.c @@ -270,8 +270,8 @@ void clt_mdct_backward_c(const mdct_lookup *l, kiss_fft_scalar *in, kiss_fft_sca int rev; kiss_fft_scalar yr, yi; rev = *bitrev++; - yr = ADD32_ovflw(S_MUL(*xp2, t[i]), S_MUL(*xp1, t[N4+i])); - yi = SUB32_ovflw(S_MUL(*xp1, t[i]), S_MUL(*xp2, t[N4+i])); + yr = S_MUL(*xp2, t[i]) + S_MUL(*xp1, t[N4+i]); + yi = S_MUL(*xp1, t[i]) - S_MUL(*xp2, t[N4+i]); /* We swap real and imag because we use an FFT instead of an IFFT. */ yp[2*rev+1] = yr; yp[2*rev] = yi; @@ -301,8 +301,8 @@ void clt_mdct_backward_c(const mdct_lookup *l, kiss_fft_scalar *in, kiss_fft_sca t0 = t[i]; t1 = t[N4+i]; /* We'd scale up by 2 here, but instead it's done when mixing the windows */ - yr = ADD32_ovflw(S_MUL(re,t0), S_MUL(im,t1)); - yi = SUB32_ovflw(S_MUL(re,t1), S_MUL(im,t0)); + yr = S_MUL(re,t0) + S_MUL(im,t1); + yi = S_MUL(re,t1) - S_MUL(im,t0); /* We swap real and imag because we're using an FFT instead of an IFFT. */ re = yp1[1]; im = yp1[0]; @@ -312,8 +312,8 @@ void clt_mdct_backward_c(const mdct_lookup *l, kiss_fft_scalar *in, kiss_fft_sca t0 = t[(N4-i-1)]; t1 = t[(N2-i-1)]; /* We'd scale up by 2 here, but instead it's done when mixing the windows */ - yr = ADD32_ovflw(S_MUL(re,t0), S_MUL(im,t1)); - yi = SUB32_ovflw(S_MUL(re,t1), S_MUL(im,t0)); + yr = S_MUL(re,t0) + S_MUL(im,t1); + yi = S_MUL(re,t1) - S_MUL(im,t0); yp1[0] = yr; yp0[1] = yi; yp0 += 2; @@ -333,8 +333,8 @@ void clt_mdct_backward_c(const mdct_lookup *l, kiss_fft_scalar *in, kiss_fft_sca kiss_fft_scalar x1, x2; x1 = *xp1; x2 = *yp1; - *yp1++ = SUB32_ovflw(MULT16_32_Q15(*wp2, x2), MULT16_32_Q15(*wp1, x1)); - *xp1-- = ADD32_ovflw(MULT16_32_Q15(*wp1, x2), MULT16_32_Q15(*wp2, x1)); + *yp1++ = MULT16_32_Q15(*wp2, x2) - MULT16_32_Q15(*wp1, x1); + *xp1-- = MULT16_32_Q15(*wp1, x2) + MULT16_32_Q15(*wp2, x1); wp1++; wp2--; } diff --git a/thirdparty/opus/celt/mips/celt_mipsr1.h b/thirdparty/opus/celt/mips/celt_mipsr1.h index c332fe0471e..e85661a6618 100644 --- a/thirdparty/opus/celt/mips/celt_mipsr1.h +++ b/thirdparty/opus/celt/mips/celt_mipsr1.h @@ -53,7 +53,6 @@ #include "celt_lpc.h" #include "vq.h" -#define OVERRIDE_COMB_FILTER_CONST #define OVERRIDE_comb_filter void comb_filter(opus_val32 *y, opus_val32 *x, int T0, int T1, int N, opus_val16 g0, opus_val16 g1, int tapset0, int tapset1, diff --git a/thirdparty/opus/celt/mips/vq_mipsr1.h b/thirdparty/opus/celt/mips/vq_mipsr1.h index f26a33e755e..54cef861337 100644 --- a/thirdparty/opus/celt/mips/vq_mipsr1.h +++ b/thirdparty/opus/celt/mips/vq_mipsr1.h @@ -36,6 +36,11 @@ #include "mathops.h" #include "arch.h" +static unsigned extract_collapse_mask(int *iy, int N, int B); +static void normalise_residual(int * OPUS_RESTRICT iy, celt_norm * OPUS_RESTRICT X, int N, opus_val32 Ryy, opus_val16 gain); +static void exp_rotation(celt_norm *X, int len, int dir, int stride, int K, int spread); +static void renormalise_vector_mips(celt_norm *X, int N, opus_val16 gain, int arch); + #define OVERRIDE_vq_exp_rotation1 static void exp_rotation1(celt_norm *X, int len, int stride, opus_val16 c, opus_val16 s) { @@ -64,7 +69,11 @@ static void exp_rotation1(celt_norm *X, int len, int stride, opus_val16 c, opus_ } #define OVERRIDE_renormalise_vector -void renormalise_vector(celt_norm *X, int N, opus_val16 gain, int arch) + +#define renormalise_vector(X, N, gain, arch) \ + (renormalise_vector_mips(X, N, gain, arch)) + +void renormalise_vector_mips(celt_norm *X, int N, opus_val16 gain, int arch) { int i; #ifdef FIXED_POINT diff --git a/thirdparty/opus/celt/modes.c b/thirdparty/opus/celt/modes.c index 390c5e8aeb3..911686e9055 100644 --- a/thirdparty/opus/celt/modes.c +++ b/thirdparty/opus/celt/modes.c @@ -427,7 +427,7 @@ void opus_custom_mode_destroy(CELTMode *mode) } #endif /* CUSTOM_MODES_ONLY */ opus_free((opus_int16*)mode->eBands); - opus_free((unsigned char*)mode->allocVectors); + opus_free((opus_int16*)mode->allocVectors); opus_free((opus_val16*)mode->window); opus_free((opus_int16*)mode->logN); diff --git a/thirdparty/opus/celt/pitch.c b/thirdparty/opus/celt/pitch.c index 872582a48a5..bf46e7d562b 100644 --- a/thirdparty/opus/celt/pitch.c +++ b/thirdparty/opus/celt/pitch.c @@ -102,9 +102,11 @@ static void find_best_pitch(opus_val32 *xcorr, opus_val16 *y, int len, } } -static void celt_fir5(opus_val16 *x, +static void celt_fir5(const opus_val16 *x, const opus_val16 *num, - int N) + opus_val16 *y, + int N, + opus_val16 *mem) { int i; opus_val16 num0, num1, num2, num3, num4; @@ -114,11 +116,11 @@ static void celt_fir5(opus_val16 *x, num2=num[2]; num3=num[3]; num4=num[4]; - mem0=0; - mem1=0; - mem2=0; - mem3=0; - mem4=0; + mem0=mem[0]; + mem1=mem[1]; + mem2=mem[2]; + mem3=mem[3]; + mem4=mem[4]; for (i=0;i>1); + celt_fir5(x_lp, lpc2, x_lp, len>>1, mem); } /* Pure C implementation. */ @@ -213,8 +220,13 @@ opus_val32 #else void #endif +#if defined(OVERRIDE_PITCH_XCORR) celt_pitch_xcorr_c(const opus_val16 *_x, const opus_val16 *_y, + opus_val32 *xcorr, int len, int max_pitch) +#else +celt_pitch_xcorr(const opus_val16 *_x, const opus_val16 *_y, opus_val32 *xcorr, int len, int max_pitch, int arch) +#endif { #if 0 /* This is a simple version of the pitch correlation that should work @@ -249,11 +261,15 @@ celt_pitch_xcorr_c(const opus_val16 *_x, const opus_val16 *_y, opus_val32 maxcorr=1; #endif celt_assert(max_pitch>0); - celt_sig_assert((((unsigned char *)_x-(unsigned char *)NULL)&3)==0); + celt_assert((((unsigned char *)_x-(unsigned char *)NULL)&3)==0); for (i=0;i>1;j++) sum += SHR32(MULT16_16(x_lp[j],y[i+j]), shift); #else - sum = celt_inner_prod(x_lp, y+i, len>>1, arch); + sum = celt_inner_prod_c(x_lp, y+i, len>>1); #endif xcorr[i] = MAX32(-1, sum); #ifdef FIXED_POINT @@ -404,7 +424,7 @@ static opus_val16 compute_pitch_gain(opus_val32 xy, opus_val32 xx, opus_val32 yy sx = celt_ilog2(xx)-14; sy = celt_ilog2(yy)-14; shift = sx + sy; - x2y2 = SHR32(MULT16_16(VSHR32(xx, sx), VSHR32(yy, sy)), 14); + x2y2 = MULT16_16_Q14(VSHR32(xx, sx), VSHR32(yy, sy)); if (shift & 1) { if (x2y2 < 32768) { diff --git a/thirdparty/opus/celt/pitch.h b/thirdparty/opus/celt/pitch.h index e425f56aeaa..d3503532a08 100644 --- a/thirdparty/opus/celt/pitch.h +++ b/thirdparty/opus/celt/pitch.h @@ -46,7 +46,8 @@ #include "mips/pitch_mipsr1.h" #endif -#if (defined(OPUS_ARM_ASM) || defined(OPUS_ARM_MAY_HAVE_NEON_INTR)) +#if ((defined(OPUS_ARM_ASM) && defined(FIXED_POINT)) \ + || defined(OPUS_ARM_MAY_HAVE_NEON_INTR)) # include "arm/pitch_arm.h" #endif @@ -183,10 +184,17 @@ opus_val32 void #endif celt_pitch_xcorr_c(const opus_val16 *_x, const opus_val16 *_y, + opus_val32 *xcorr, int len, int max_pitch); + +#if !defined(OVERRIDE_PITCH_XCORR) +#ifdef FIXED_POINT +opus_val32 +#else +void +#endif +celt_pitch_xcorr(const opus_val16 *_x, const opus_val16 *_y, opus_val32 *xcorr, int len, int max_pitch, int arch); -#ifndef OVERRIDE_PITCH_XCORR -# define celt_pitch_xcorr celt_pitch_xcorr_c #endif #endif diff --git a/thirdparty/opus/celt/quant_bands.c b/thirdparty/opus/celt/quant_bands.c index 39a221eda5f..95076e0af2d 100644 --- a/thirdparty/opus/celt/quant_bands.c +++ b/thirdparty/opus/celt/quant_bands.c @@ -418,7 +418,6 @@ void quant_energy_finalise(const CELTMode *m, int start, int end, opus_val16 *ol offset = (q2-.5f)*(1<<(14-fine_quant[i]-1))*(1.f/16384); #endif oldEBands[i+c*m->nbEBands] += offset; - error[i+c*m->nbEBands] -= offset; bits_left--; } while (++c < C); } @@ -457,7 +456,7 @@ void unquant_coarse_energy(const CELTMode *m, int start, int end, opus_val16 *ol /* It would be better to express this invariant as a test on C at function entry, but that isn't enough to make the static analyzer happy. */ - celt_sig_assert(c<2); + celt_assert(c<2); tell = ec_tell(dec); if(budget-tell>=15) { @@ -548,15 +547,9 @@ void amp2Log2(const CELTMode *m, int effEnd, int end, c=0; do { for (i=0;inbEBands] = - celt_log2(bandE[i+c*m->nbEBands]) + celt_log2(SHL32(bandE[i+c*m->nbEBands],2)) - SHL16((opus_val16)eMeans[i],6); -#ifdef FIXED_POINT - /* Compensate for bandE[] being Q12 but celt_log2() taking a Q14 input. */ - bandLogE[i+c*m->nbEBands] += QCONST16(2.f, DB_SHIFT); -#endif - } for (i=effEnd;inbEBands+i] = -QCONST16(14.f,DB_SHIFT); } while (++c < C); diff --git a/thirdparty/opus/celt/rate.c b/thirdparty/opus/celt/rate.c index 465e1ba26cb..7dfa5be8a63 100644 --- a/thirdparty/opus/celt/rate.c +++ b/thirdparty/opus/celt/rate.c @@ -348,17 +348,12 @@ static OPUS_INLINE int interp_bits2pulses(const CELTMode *m, int start, int end, /*This if() block is the only part of the allocation function that is not a mandatory part of the bitstream: any bands we choose to skip here must be explicitly signaled.*/ - int depth_threshold; - /*We choose a threshold with some hysteresis to keep bands from - fluctuating in and out, but we try not to fold below a certain point. */ - if (codedBands > 17) - depth_threshold = j (depth_threshold*band_width<>4 && j<=signalBandwidth)) + if (codedBands<=start+2 || (band_bits > ((j>4 && j<=signalBandwidth)) #endif { ec_enc_bit_logp(ec, 1, 1); @@ -529,7 +524,7 @@ static OPUS_INLINE int interp_bits2pulses(const CELTMode *m, int start, int end, return codedBands; } -int clt_compute_allocation(const CELTMode *m, int start, int end, const int *offsets, const int *cap, int alloc_trim, int *intensity, int *dual_stereo, +int compute_allocation(const CELTMode *m, int start, int end, const int *offsets, const int *cap, int alloc_trim, int *intensity, int *dual_stereo, opus_int32 total, opus_int32 *balance, int *pulses, int *ebits, int *fine_priority, int C, int LM, ec_ctx *ec, int encode, int prev, int signalBandwidth) { int lo, hi, len, j; diff --git a/thirdparty/opus/celt/rate.h b/thirdparty/opus/celt/rate.h index fad5e412daf..515f7687cec 100644 --- a/thirdparty/opus/celt/rate.h +++ b/thirdparty/opus/celt/rate.h @@ -95,7 +95,7 @@ static OPUS_INLINE int pulses2bits(const CELTMode *m, int band, int LM, int puls @param pulses Number of pulses per band (returned) @return Total number of bits allocated */ -int clt_compute_allocation(const CELTMode *m, int start, int end, const int *offsets, const int *cap, int alloc_trim, int *intensity, int *dual_stereo, +int compute_allocation(const CELTMode *m, int start, int end, const int *offsets, const int *cap, int alloc_trim, int *intensity, int *dual_stero, opus_int32 total, opus_int32 *balance, int *pulses, int *ebits, int *fine_priority, int C, int LM, ec_ctx *ec, int encode, int prev, int signalBandwidth); #endif diff --git a/thirdparty/opus/celt/static_modes_fixed_arm_ne10.h b/thirdparty/opus/celt/static_modes_fixed_arm_ne10.h index 76230921925..b8ef0cee983 100644 --- a/thirdparty/opus/celt/static_modes_fixed_arm_ne10.h +++ b/thirdparty/opus/celt/static_modes_fixed_arm_ne10.h @@ -1,7 +1,7 @@ /* The contents of this file was automatically generated by * dump_mode_arm_ne10.c with arguments: 48000 960 * It contains static definitions for some pre-defined modes. */ -#include +#include #ifndef NE10_FFT_PARAMS48000_960 #define NE10_FFT_PARAMS48000_960 diff --git a/thirdparty/opus/celt/static_modes_float_arm_ne10.h b/thirdparty/opus/celt/static_modes_float_arm_ne10.h index 66e1abb1013..934a82a420a 100644 --- a/thirdparty/opus/celt/static_modes_float_arm_ne10.h +++ b/thirdparty/opus/celt/static_modes_float_arm_ne10.h @@ -1,7 +1,7 @@ /* The contents of this file was automatically generated by * dump_mode_arm_ne10.c with arguments: 48000 960 * It contains static definitions for some pre-defined modes. */ -#include +#include #ifndef NE10_FFT_PARAMS48000_960 #define NE10_FFT_PARAMS48000_960 diff --git a/thirdparty/opus/celt/tests/test_unit_cwrs32.c b/thirdparty/opus/celt/tests/test_unit_cwrs32.c new file mode 100644 index 00000000000..36dd8af5f5c --- /dev/null +++ b/thirdparty/opus/celt/tests/test_unit_cwrs32.c @@ -0,0 +1,161 @@ +/* Copyright (c) 2008-2011 Xiph.Org Foundation, Mozilla Corporation, + Gregory Maxwell + Written by Jean-Marc Valin, Gregory Maxwell, and Timothy B. Terriberry */ +/* + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + - Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + - Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER + OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include + +#ifndef CUSTOM_MODES +#define CUSTOM_MODES +#else +#define TEST_CUSTOM_MODES +#endif + +#define CELT_C +#include "stack_alloc.h" +#include "entenc.c" +#include "entdec.c" +#include "entcode.c" +#include "cwrs.c" +#include "mathops.c" +#include "rate.h" + +#define NMAX (240) +#define KMAX (128) + +#ifdef TEST_CUSTOM_MODES + +#define NDIMS (44) +static const int pn[NDIMS]={ + 2, 3, 4, 5, 6, 7, 8, 9, 10, + 11, 12, 13, 14, 15, 16, 18, 20, 22, + 24, 26, 28, 30, 32, 36, 40, 44, 48, + 52, 56, 60, 64, 72, 80, 88, 96, 104, + 112, 120, 128, 144, 160, 176, 192, 208 +}; +static const int pkmax[NDIMS]={ + 128, 128, 128, 128, 88, 52, 36, 26, 22, + 18, 16, 15, 13, 12, 12, 11, 10, 9, + 9, 8, 8, 7, 7, 7, 7, 6, 6, + 6, 6, 6, 5, 5, 5, 5, 5, 5, + 4, 4, 4, 4, 4, 4, 4, 4 +}; + +#else /* TEST_CUSTOM_MODES */ + +#define NDIMS (22) +static const int pn[NDIMS]={ + 2, 3, 4, 6, 8, 9, 11, 12, 16, + 18, 22, 24, 32, 36, 44, 48, 64, 72, + 88, 96, 144, 176 +}; +static const int pkmax[NDIMS]={ + 128, 128, 128, 88, 36, 26, 18, 16, 12, + 11, 9, 9, 7, 7, 6, 6, 5, 5, + 5, 5, 4, 4 +}; + +#endif + +int main(void){ + int t; + int n; + ALLOC_STACK; + for(t=0;tpkmax[t])break; + printf("Testing CWRS with N=%i, K=%i...\n",n,k); +#if defined(SMALL_FOOTPRINT) + nc=ncwrs_urow(n,k,uu); +#else + nc=CELT_PVQ_V(n,k); +#endif + inc=nc/20000; + if(inc<1)inc=1; + for(i=0;i");*/ +#if defined(SMALL_FOOTPRINT) + ii=icwrs(n,k,&v,y,u); +#else + ii=icwrs(n,y); + v=CELT_PVQ_V(n,k); +#endif + if(ii!=i){ + fprintf(stderr,"Combination-index mismatch (%lu!=%lu).\n", + (long)ii,(long)i); + return 1; + } + if(v!=nc){ + fprintf(stderr,"Combination count mismatch (%lu!=%lu).\n", + (long)v,(long)nc); + return 2; + } + /*printf(" %6u\n",i);*/ + } + /*printf("\n");*/ + } + } + return 0; +} diff --git a/thirdparty/opus/celt/tests/test_unit_dft.c b/thirdparty/opus/celt/tests/test_unit_dft.c new file mode 100644 index 00000000000..6166eb0e4fa --- /dev/null +++ b/thirdparty/opus/celt/tests/test_unit_dft.c @@ -0,0 +1,189 @@ +/* Copyright (c) 2008 Xiph.Org Foundation + Written by Jean-Marc Valin */ +/* + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + - Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + - Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER + OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#define SKIP_CONFIG_H + +#ifndef CUSTOM_MODES +#define CUSTOM_MODES +#endif + +#include + +#define CELT_C +#define TEST_UNIT_DFT_C +#include "stack_alloc.h" +#include "kiss_fft.h" +#include "kiss_fft.c" +#include "mathops.c" +#include "entcode.c" + +#if defined(OPUS_X86_MAY_HAVE_SSE2) || defined(OPUS_X86_MAY_HAVE_SSE4_1) +# include "x86/x86cpu.c" +#elif defined(OPUS_ARM_ASM) || defined(OPUS_ARM_MAY_HAVE_NEON_INTR) +# include "arm/armcpu.c" +# include "celt_lpc.c" +# include "pitch.c" +# if defined(OPUS_ARM_MAY_HAVE_NEON_INTR) +# include "arm/celt_neon_intr.c" +# if defined(HAVE_ARM_NE10) +# include "mdct.c" +# include "arm/celt_ne10_fft.c" +# include "arm/celt_ne10_mdct.c" +# endif +# endif +# include "arm/arm_celt_map.c" +#endif + +#ifndef M_PI +#define M_PI 3.141592653 +#endif + +int ret = 0; + +void check(kiss_fft_cpx * in,kiss_fft_cpx * out,int nfft,int isinverse) +{ + int bin,k; + double errpow=0,sigpow=0, snr; + + for (bin=0;bin1) { + int k; + for (k=1;k +#include +#include +#include +#include "entcode.h" +#include "entenc.h" +#include "entdec.h" +#include + +#include "entenc.c" +#include "entdec.c" +#include "entcode.c" + +#ifndef M_LOG2E +# define M_LOG2E 1.4426950408889634074 +#endif +#define DATA_SIZE 10000000 +#define DATA_SIZE2 10000 + +int main(int _argc,char **_argv){ + ec_enc enc; + ec_dec dec; + long nbits; + long nbits2; + double entropy; + int ft; + int ftb; + int sz; + int i; + int ret; + unsigned int sym; + unsigned int seed; + unsigned char *ptr; + const char *env_seed; + ret=0; + entropy=0; + if (_argc > 2) { + fprintf(stderr, "Usage: %s []\n", _argv[0]); + return 1; + } + env_seed = getenv("SEED"); + if (_argc > 1) + seed = atoi(_argv[1]); + else if (env_seed) + seed = atoi(env_seed); + else + seed = time(NULL); + /*Testing encoding of raw bit values.*/ + ptr = (unsigned char *)malloc(DATA_SIZE); + ec_enc_init(&enc,ptr, DATA_SIZE); + for(ft=2;ft<1024;ft++){ + for(i=0;i>(rand()%11U))+1U)+10; + sz=rand()/((RAND_MAX>>(rand()%9U))+1U); + data=(unsigned *)malloc(sz*sizeof(*data)); + tell=(unsigned *)malloc((sz+1)*sizeof(*tell)); + ec_enc_init(&enc,ptr,DATA_SIZE2); + zeros = rand()%13==0; + tell[0]=ec_tell_frac(&enc); + for(j=0;j>(rand()%9U))+1U); + logp1=(unsigned *)malloc(sz*sizeof(*logp1)); + data=(unsigned *)malloc(sz*sizeof(*data)); + tell=(unsigned *)malloc((sz+1)*sizeof(*tell)); + enc_method=(unsigned *)malloc(sz*sizeof(*enc_method)); + ec_enc_init(&enc,ptr,DATA_SIZE2); + tell[0]=ec_tell_frac(&enc); + for(j=0;j>1)+1); + logp1[j]=(rand()%15)+1; + enc_method[j]=rand()/((RAND_MAX>>2)+1); + switch(enc_method[j]){ + case 0:{ + ec_encode(&enc,data[j]?(1<>2)+1); + switch(dec_method){ + case 0:{ + fs=ec_decode(&dec,1<=(1<=(1< +#include +#include "laplace.h" +#define CELT_C +#include "stack_alloc.h" + +#include "entenc.c" +#include "entdec.c" +#include "entcode.c" +#include "laplace.c" + +#define DATA_SIZE 40000 + +int ec_laplace_get_start_freq(int decay) +{ + opus_uint32 ft = 32768 - LAPLACE_MINP*(2*LAPLACE_NMIN+1); + int fs = (ft*(16384-decay))/(16384+decay); + return fs+LAPLACE_MINP; +} + +int main(void) +{ + int i; + int ret = 0; + ec_enc enc; + ec_dec dec; + unsigned char *ptr; + int val[10000], decay[10000]; + ALLOC_STACK; + ptr = (unsigned char *)malloc(DATA_SIZE); + ec_enc_init(&enc,ptr,DATA_SIZE); + + val[0] = 3; decay[0] = 6000; + val[1] = 0; decay[1] = 5800; + val[2] = -1; decay[2] = 5600; + for (i=3;i<10000;i++) + { + val[i] = rand()%15-7; + decay[i] = rand()%11000+5000; + } + for (i=0;i<10000;i++) + ec_laplace_encode(&enc, &val[i], + ec_laplace_get_start_freq(decay[i]), decay[i]); + + ec_enc_done(&enc); + + ec_dec_init(&dec,ec_get_buffer(&enc),ec_range_bytes(&enc)); + + for (i=0;i<10000;i++) + { + int d = ec_laplace_decode(&dec, + ec_laplace_get_start_freq(decay[i]), decay[i]); + if (d != val[i]) + { + fprintf (stderr, "Got %d instead of %d\n", d, val[i]); + ret = 1; + } + } + + free(ptr); + return ret; +} diff --git a/thirdparty/opus/celt/tests/test_unit_mathops.c b/thirdparty/opus/celt/tests/test_unit_mathops.c new file mode 100644 index 00000000000..fd3319da91c --- /dev/null +++ b/thirdparty/opus/celt/tests/test_unit_mathops.c @@ -0,0 +1,304 @@ +/* Copyright (c) 2008-2011 Xiph.Org Foundation, Mozilla Corporation, + Gregory Maxwell + Written by Jean-Marc Valin, Gregory Maxwell, and Timothy B. Terriberry */ +/* + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + - Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + - Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER + OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#ifndef CUSTOM_MODES +#define CUSTOM_MODES +#endif + +#define CELT_C + +#include +#include +#include "mathops.c" +#include "entenc.c" +#include "entdec.c" +#include "entcode.c" +#include "bands.c" +#include "quant_bands.c" +#include "laplace.c" +#include "vq.c" +#include "cwrs.c" +#include "pitch.c" +#include "celt_lpc.c" +#include "celt.c" + +#if defined(OPUS_X86_MAY_HAVE_SSE) || defined(OPUS_X86_MAY_HAVE_SSE2) || defined(OPUS_X86_MAY_HAVE_SSE4_1) +# if defined(OPUS_X86_MAY_HAVE_SSE) +# include "x86/pitch_sse.c" +# endif +# if defined(OPUS_X86_MAY_HAVE_SSE2) +# include "x86/pitch_sse2.c" +# endif +# if defined(OPUS_X86_MAY_HAVE_SSE4_1) +# include "x86/pitch_sse4_1.c" +# include "x86/celt_lpc_sse.c" +# endif +# include "x86/x86_celt_map.c" +#elif defined(OPUS_ARM_ASM) || defined(OPUS_ARM_MAY_HAVE_NEON_INTR) +# include "arm/armcpu.c" +# if defined(OPUS_ARM_MAY_HAVE_NEON_INTR) +# include "arm/celt_neon_intr.c" +# if defined(HAVE_ARM_NE10) +# include "kiss_fft.c" +# include "mdct.c" +# include "arm/celt_ne10_fft.c" +# include "arm/celt_ne10_mdct.c" +# endif +# endif +# include "arm/arm_celt_map.c" +#endif + +#ifdef FIXED_POINT +#define WORD "%d" +#else +#define WORD "%f" +#endif + +int ret = 0; + +void testdiv(void) +{ + opus_int32 i; + for (i=1;i<=327670;i++) + { + double prod; + opus_val32 val; + val = celt_rcp(i); +#ifdef FIXED_POINT + prod = (1./32768./65526.)*val*i; +#else + prod = val*i; +#endif + if (fabs(prod-1) > .00025) + { + fprintf (stderr, "div failed: 1/%d="WORD" (product = %f)\n", i, val, prod); + ret = 1; + } + } +} + +void testsqrt(void) +{ + opus_int32 i; + for (i=1;i<=1000000000;i++) + { + double ratio; + opus_val16 val; + val = celt_sqrt(i); + ratio = val/sqrt(i); + if (fabs(ratio - 1) > .0005 && fabs(val-sqrt(i)) > 2) + { + fprintf (stderr, "sqrt failed: sqrt(%d)="WORD" (ratio = %f)\n", i, val, ratio); + ret = 1; + } + i+= i>>10; + } +} + +void testbitexactcos(void) +{ + int i; + opus_int32 min_d,max_d,last,chk; + chk=max_d=0; + last=min_d=32767; + for(i=64;i<=16320;i++) + { + opus_int32 d; + opus_int32 q=bitexact_cos(i); + chk ^= q*i; + d = last - q; + if (d>max_d)max_d=d; + if (dmax_d)max_d=d; + if (d0.0009) + { + fprintf (stderr, "celt_log2 failed: fabs((1.442695040888963387*log(x))-celt_log2(x))>0.001 (x = %f, error = %f)\n", x,error); + ret = 1; + } + } +} + +void testexp2(void) +{ + float x; + for (x=-11.0;x<24.0;x+=0.0007) + { + float error = fabs(x-(1.442695040888963387*log(celt_exp2(x)))); + if (error>0.0002) + { + fprintf (stderr, "celt_exp2 failed: fabs(x-(1.442695040888963387*log(celt_exp2(x))))>0.0005 (x = %f, error = %f)\n", x,error); + ret = 1; + } + } +} + +void testexp2log2(void) +{ + float x; + for (x=-11.0;x<24.0;x+=0.0007) + { + float error = fabs(x-(celt_log2(celt_exp2(x)))); + if (error>0.001) + { + fprintf (stderr, "celt_log2/celt_exp2 failed: fabs(x-(celt_log2(celt_exp2(x))))>0.001 (x = %f, error = %f)\n", x,error); + ret = 1; + } + } +} +#else +void testlog2(void) +{ + opus_val32 x; + for (x=8;x<1073741824;x+=(x>>3)) + { + float error = fabs((1.442695040888963387*log(x/16384.0))-celt_log2(x)/1024.0); + if (error>0.003) + { + fprintf (stderr, "celt_log2 failed: x = %ld, error = %f\n", (long)x,error); + ret = 1; + } + } +} + +void testexp2(void) +{ + opus_val16 x; + for (x=-32768;x<15360;x++) + { + float error1 = fabs(x/1024.0-(1.442695040888963387*log(celt_exp2(x)/65536.0))); + float error2 = fabs(exp(0.6931471805599453094*x/1024.0)-celt_exp2(x)/65536.0); + if (error1>0.0002&&error2>0.00004) + { + fprintf (stderr, "celt_exp2 failed: x = "WORD", error1 = %f, error2 = %f\n", x,error1,error2); + ret = 1; + } + } +} + +void testexp2log2(void) +{ + opus_val32 x; + for (x=8;x<65536;x+=(x>>3)) + { + float error = fabs(x-0.25*celt_exp2(celt_log2(x)))/16384; + if (error>0.004) + { + fprintf (stderr, "celt_log2/celt_exp2 failed: fabs(x-(celt_exp2(celt_log2(x))))>0.001 (x = %ld, error = %f)\n", (long)x,error); + ret = 1; + } + } +} + +void testilog2(void) +{ + opus_val32 x; + for (x=1;x<=268435455;x+=127) + { + opus_val32 lg; + opus_val32 y; + + lg = celt_ilog2(x); + if (lg<0 || lg>=31) + { + printf("celt_ilog2 failed: 0<=celt_ilog2(x)<31 (x = %d, celt_ilog2(x) = %d)\n",x,lg); + ret = 1; + } + y = 1<>1)>=y) + { + printf("celt_ilog2 failed: 2**celt_ilog2(x)<=x<2**(celt_ilog2(x)+1) (x = %d, 2**celt_ilog2(x) = %d)\n",x,y); + ret = 1; + } + } +} +#endif + +int main(void) +{ + testbitexactcos(); + testbitexactlog2tan(); + testdiv(); + testsqrt(); + testlog2(); + testexp2(); + testexp2log2(); +#ifdef FIXED_POINT + testilog2(); +#endif + return ret; +} diff --git a/thirdparty/opus/celt/tests/test_unit_mdct.c b/thirdparty/opus/celt/tests/test_unit_mdct.c new file mode 100644 index 00000000000..8dbb9caa2e8 --- /dev/null +++ b/thirdparty/opus/celt/tests/test_unit_mdct.c @@ -0,0 +1,230 @@ +/* Copyright (c) 2008-2011 Xiph.Org Foundation + Written by Jean-Marc Valin */ +/* + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + - Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + - Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER + OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#define SKIP_CONFIG_H + +#ifndef CUSTOM_MODES +#define CUSTOM_MODES +#endif + +#include + +#define CELT_C +#include "mdct.h" +#include "stack_alloc.h" + +#include "kiss_fft.c" +#include "mdct.c" +#include "mathops.c" +#include "entcode.c" + +#if defined(OPUS_X86_MAY_HAVE_SSE2) || defined(OPUS_X86_MAY_HAVE_SSE4_1) +# include "x86/x86cpu.c" +#elif defined(OPUS_ARM_ASM) || defined(OPUS_ARM_MAY_HAVE_NEON_INTR) +# include "arm/armcpu.c" +# include "pitch.c" +# include "celt_lpc.c" +# if defined(OPUS_ARM_MAY_HAVE_NEON_INTR) +# include "arm/celt_neon_intr.c" +# if defined(HAVE_ARM_NE10) +# include "arm/celt_ne10_fft.c" +# include "arm/celt_ne10_mdct.c" +# endif +# endif +# include "arm/arm_celt_map.c" +#endif + +#ifndef M_PI +#define M_PI 3.141592653 +#endif + +int ret = 0; +void check(kiss_fft_scalar * in,kiss_fft_scalar * out,int nfft,int isinverse) +{ + int bin,k; + double errpow=0,sigpow=0; + double snr; + for (bin=0;bin1) { + int k; + for (k=1;k +#include +#include "vq.c" +#include "cwrs.c" +#include "entcode.c" +#include "entenc.c" +#include "entdec.c" +#include "mathops.c" +#include "bands.h" +#include "pitch.c" +#include "celt_lpc.c" +#include "celt.c" +#include + +#if defined(OPUS_X86_MAY_HAVE_SSE) || defined(OPUS_X86_MAY_HAVE_SSE2) || defined(OPUS_X86_MAY_HAVE_SSE4_1) +# if defined(OPUS_X86_MAY_HAVE_SSE) +# include "x86/pitch_sse.c" +# endif +# if defined(OPUS_X86_MAY_HAVE_SSE2) +# include "x86/pitch_sse2.c" +# endif +# if defined(OPUS_X86_MAY_HAVE_SSE4_1) +# include "x86/pitch_sse4_1.c" +# include "x86/celt_lpc_sse.c" +# endif +# include "x86/x86_celt_map.c" +#elif defined(OPUS_ARM_ASM) || defined(OPUS_ARM_MAY_HAVE_NEON_INTR) +# include "arm/armcpu.c" +# if defined(OPUS_ARM_MAY_HAVE_NEON_INTR) +# include "arm/celt_neon_intr.c" +# if defined(HAVE_ARM_NE10) +# include "kiss_fft.c" +# include "mdct.c" +# include "arm/celt_ne10_fft.c" +# include "arm/celt_ne10_mdct.c" +# endif +# endif +# include "arm/arm_celt_map.c" +#endif + +#define MAX_SIZE 100 + +int ret=0; +void test_rotation(int N, int K) +{ + int i; + double err = 0, ener = 0, snr, snr0; + opus_val16 x0[MAX_SIZE]; + opus_val16 x1[MAX_SIZE]; + for (i=0;i 20) + { + fprintf(stderr, "FAIL!\n"); + ret = 1; + } +} + +int main(void) +{ + ALLOC_STACK; + test_rotation(15, 3); + test_rotation(23, 5); + test_rotation(50, 3); + test_rotation(80, 1); + return ret; +} diff --git a/thirdparty/opus/celt/x86/vq_sse.h b/thirdparty/opus/celt/tests/test_unit_types.c similarity index 67% rename from thirdparty/opus/celt/x86/vq_sse.h rename to thirdparty/opus/celt/tests/test_unit_types.c index b4efe8f249f..67a0fb8ed3b 100644 --- a/thirdparty/opus/celt/x86/vq_sse.h +++ b/thirdparty/opus/celt/tests/test_unit_types.c @@ -1,4 +1,5 @@ -/* Copyright (c) 2016 Jean-Marc Valin */ +/* Copyright (c) 2008-2011 Xiph.Org Foundation + Written by Jean-Marc Valin */ /* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions @@ -24,27 +25,26 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef VQ_SSE_H -#define VQ_SSE_H - -#if defined(OPUS_X86_MAY_HAVE_SSE2) && !defined(FIXED_POINT) -#define OVERRIDE_OP_PVQ_SEARCH - -opus_val16 op_pvq_search_sse2(celt_norm *_X, int *iy, int K, int N, int arch); - -#if defined(OPUS_X86_PRESUME_SSE2) -#define op_pvq_search(x, iy, K, N, arch) \ - (op_pvq_search_sse2(x, iy, K, N, arch)) - -#else - -extern opus_val16 (*const OP_PVQ_SEARCH_IMPL[OPUS_ARCHMASK + 1])( - celt_norm *_X, int *iy, int K, int N, int arch); - -# define op_pvq_search(X, iy, K, N, arch) \ - ((*OP_PVQ_SEARCH_IMPL[(arch) & OPUS_ARCHMASK])(X, iy, K, N, arch)) - -#endif +#ifdef HAVE_CONFIG_H +#include "config.h" #endif -#endif +#include "opus_types.h" +#include + +int main(void) +{ + opus_int16 i = 1; + i <<= 14; + if (i>>14 != 1) + { + fprintf(stderr, "opus_int16 isn't 16 bits\n"); + return 1; + } + if (sizeof(opus_int16)*2 != sizeof(opus_int32)) + { + fprintf(stderr, "16*2 != 32\n"); + return 1; + } + return 0; +} diff --git a/thirdparty/opus/celt/vq.c b/thirdparty/opus/celt/vq.c index 8011e22548b..d29f38fd8ef 100644 --- a/thirdparty/opus/celt/vq.c +++ b/thirdparty/opus/celt/vq.c @@ -39,10 +39,6 @@ #include "rate.h" #include "pitch.h" -#if defined(MIPSr1_ASM) -#include "mips/vq_mipsr1.h" -#endif - #ifndef OVERRIDE_vq_exp_rotation1 static void exp_rotation1(celt_norm *X, int len, int stride, opus_val16 c, opus_val16 s) { @@ -71,7 +67,7 @@ static void exp_rotation1(celt_norm *X, int len, int stride, opus_val16 c, opus_ } #endif /* OVERRIDE_vq_exp_rotation1 */ -void exp_rotation(celt_norm *X, int len, int dir, int stride, int K, int spread) +static void exp_rotation(celt_norm *X, int len, int dir, int stride, int K, int spread) { static const int SPREAD_FACTOR[3]={15,10,5}; int i; @@ -162,27 +158,42 @@ static unsigned extract_collapse_mask(int *iy, int N, int B) return collapse_mask; } -opus_val16 op_pvq_search_c(celt_norm *X, int *iy, int K, int N, int arch) +unsigned alg_quant(celt_norm *X, int N, int K, int spread, int B, ec_enc *enc +#ifdef RESYNTH + , opus_val16 gain +#endif + ) { VARDECL(celt_norm, y); - VARDECL(int, signx); + VARDECL(int, iy); + VARDECL(opus_val16, signx); int i, j; + opus_val16 s; int pulsesLeft; opus_val32 sum; opus_val32 xy; opus_val16 yy; + unsigned collapse_mask; SAVE_STACK; - (void)arch; + celt_assert2(K>0, "alg_quant() needs at least one pulse"); + celt_assert2(N>1, "alg_quant() needs at least two dimensions"); + ALLOC(y, N, celt_norm); - ALLOC(signx, N, int); + ALLOC(iy, N, int); + ALLOC(signx, N, opus_val16); + + exp_rotation(X, N, 1, B, K, spread); /* Get rid of the sign */ sum = 0; j=0; do { - signx[j] = X[j]<0; - /* OPT: Make sure the compiler doesn't use a branch on ABS16(). */ - X[j] = ABS16(X[j]); + if (X[j]>0) + signx[j]=1; + else { + signx[j]=-1; + X[j]=-X[j]; + } iy[j] = 0; y[j] = 0; } while (++j=0); + celt_assert2(pulsesLeft>=1, "Allocated too many pulses in the quick pass"); /* This should never happen, but just in case it does (e.g. on silence) we fill the first bin with pulses. */ #ifdef FIXED_POINT_DEBUG - celt_sig_assert(pulsesLeft<=N+3); + celt_assert2(pulsesLeft<=N+3, "Not enough pulses in the quick pass"); #endif if (pulsesLeft > N+3) { @@ -250,12 +256,12 @@ opus_val16 op_pvq_search_c(celt_norm *X, int *iy, int K, int N, int arch) pulsesLeft=0; } + s = 1; for (i=0;i= best_num/best_den, but that way we can do it without any division */ - /* OPT: It's not clear whether a cmov is faster than a branch here - since the condition is more often false than true and using - a cmov introduces data dependencies across iterations. The optimal - choice may be architecture-dependent. */ - if (opus_unlikely(MULT16_16(best_den, Rxy) > MULT16_16(Ryy, best_num))) + /* OPT: Make sure to use conditional moves here */ + if (MULT16_16(best_den, Rxy) > MULT16_16(Ryy, best_num)) { best_den = Ryy; best_num = Rxy; @@ -311,47 +301,23 @@ opus_val16 op_pvq_search_c(celt_norm *X, int *iy, int K, int N, int arch) /* Only now that we've made the final choice, update y/iy */ /* Multiplying y[j] by 2 so we don't have to do it everywhere else */ - y[best_id] += 2; + y[best_id] += 2*s; iy[best_id]++; } /* Put the original sign back */ j=0; do { - /*iy[j] = signx[j] ? -iy[j] : iy[j];*/ - /* OPT: The is more likely to be compiled without a branch than the code above - but has the same performance otherwise. */ - iy[j] = (iy[j]^-signx[j]) + signx[j]; + X[j] = MULT16_16(signx[j],X[j]); + if (signx[j] < 0) + iy[j] = -iy[j]; } while (++j0, "alg_quant() needs at least one pulse"); - celt_assert2(N>1, "alg_quant() needs at least two dimensions"); - - /* Covers vectorization by up to 4. */ - ALLOC(iy, N+3, int); - - exp_rotation(X, N, 1, B, K, spread); - - yy = op_pvq_search(X, iy, K, N, arch); - encode_pulses(iy, N, K, enc); - if (resynth) - { - normalise_residual(iy, X, N, yy, gain); - exp_rotation(X, N, -1, B, K, spread); - } +#ifdef RESYNTH + normalise_residual(iy, X, N, yy, gain); + exp_rotation(X, N, -1, B, K, spread); +#endif collapse_mask = extract_collapse_mask(iy, N, B); RESTORE_STACK; @@ -435,7 +401,7 @@ int stereo_itheta(const celt_norm *X, const celt_norm *Y, int stereo, int N, int /* 0.63662 = 2/pi */ itheta = MULT16_16_Q15(QCONST16(0.63662f,15),celt_atan2p(side, mid)); #else - itheta = (int)floor(.5f+16384*0.63662f*fast_atan2f(side,mid)); + itheta = (int)floor(.5f+16384*0.63662f*atan2(side,mid)); #endif return itheta; diff --git a/thirdparty/opus/celt/vq.h b/thirdparty/opus/celt/vq.h index 45ec55918e3..5cfcbe50ea0 100644 --- a/thirdparty/opus/celt/vq.h +++ b/thirdparty/opus/celt/vq.h @@ -37,18 +37,10 @@ #include "entdec.h" #include "modes.h" -#if (defined(OPUS_X86_MAY_HAVE_SSE2) && !defined(FIXED_POINT)) -#include "x86/vq_sse.h" +#if defined(MIPSr1_ASM) +#include "mips/vq_mipsr1.h" #endif -void exp_rotation(celt_norm *X, int len, int dir, int stride, int K, int spread); - -opus_val16 op_pvq_search_c(celt_norm *X, int *iy, int K, int N, int arch); - -#if !defined(OVERRIDE_OP_PVQ_SEARCH) -#define op_pvq_search(x, iy, K, N, arch) \ - (op_pvq_search_c(x, iy, K, N, arch)) -#endif /** Algebraic pulse-vector quantiser. The signal x is replaced by the sum of * the pitch and a combination of pulses such that its norm is still equal @@ -59,8 +51,12 @@ opus_val16 op_pvq_search_c(celt_norm *X, int *iy, int K, int N, int arch); * @param enc Entropy encoder state * @ret A mask indicating which blocks in the band received pulses */ -unsigned alg_quant(celt_norm *X, int N, int K, int spread, int B, ec_enc *enc, - opus_val16 gain, int resynth, int arch); +unsigned alg_quant(celt_norm *X, int N, int K, int spread, int B, + ec_enc *enc +#ifdef RESYNTH + , opus_val16 gain +#endif + ); /** Algebraic pulse decoder * @param X Decoded normalised spectrum (returned) diff --git a/thirdparty/opus/celt/x86/celt_lpc_sse4_1.c b/thirdparty/opus/celt/x86/celt_lpc_sse.c similarity index 66% rename from thirdparty/opus/celt/x86/celt_lpc_sse4_1.c rename to thirdparty/opus/celt/x86/celt_lpc_sse.c index 5478568849a..67e5592acf3 100644 --- a/thirdparty/opus/celt/x86/celt_lpc_sse4_1.c +++ b/thirdparty/opus/celt/x86/celt_lpc_sse.c @@ -40,23 +40,65 @@ #if defined(FIXED_POINT) -void celt_fir_sse4_1(const opus_val16 *x, +void celt_fir_sse4_1(const opus_val16 *_x, const opus_val16 *num, - opus_val16 *y, + opus_val16 *_y, int N, int ord, + opus_val16 *mem, int arch) { int i,j; VARDECL(opus_val16, rnum); + VARDECL(opus_val16, x); __m128i vecNoA; opus_int32 noA ; SAVE_STACK; ALLOC(rnum, ord, opus_val16); + ALLOC(x, N+ord, opus_val16); for(i=0;i> 1; vecNoA = _mm_set_epi32(noA, noA, noA, noA); @@ -65,24 +107,25 @@ void celt_fir_sse4_1(const opus_val16 *x, opus_val32 sums[4] = {0}; __m128i vecSum, vecX; - xcorr_kernel(rnum, x+i-ord, sums, ord, arch); + xcorr_kernel(rnum, x+i, sums, ord, arch); vecSum = _mm_loadu_si128((__m128i *)sums); vecSum = _mm_add_epi32(vecSum, vecNoA); vecSum = _mm_srai_epi32(vecSum, SIG_SHIFT); - vecX = OP_CVTEPI16_EPI32_M64(x + i); + vecX = OP_CVTEPI16_EPI32_M64(_x + i); vecSum = _mm_add_epi32(vecSum, vecX); vecSum = _mm_packs_epi32(vecSum, vecSum); - _mm_storel_epi64((__m128i *)(y + i), vecSum); + _mm_storel_epi64((__m128i *)(_y + i), vecSum); } for (;i -#include -#include "celt_lpc.h" -#include "stack_alloc.h" -#include "mathops.h" -#include "vq.h" -#include "x86cpu.h" - - -#ifndef FIXED_POINT - -opus_val16 op_pvq_search_sse2(celt_norm *_X, int *iy, int K, int N, int arch) -{ - int i, j; - int pulsesLeft; - float xy, yy; - VARDECL(celt_norm, y); - VARDECL(celt_norm, X); - VARDECL(float, signy); - __m128 signmask; - __m128 sums; - __m128i fours; - SAVE_STACK; - - (void)arch; - /* All bits set to zero, except for the sign bit. */ - signmask = _mm_set_ps1(-0.f); - fours = _mm_set_epi32(4, 4, 4, 4); - ALLOC(y, N+3, celt_norm); - ALLOC(X, N+3, celt_norm); - ALLOC(signy, N+3, float); - - OPUS_COPY(X, _X, N); - X[N] = X[N+1] = X[N+2] = 0; - sums = _mm_setzero_ps(); - for (j=0;j (N>>1)) - { - __m128i pulses_sum; - __m128 yy4, xy4; - __m128 rcp4; - opus_val32 sum = _mm_cvtss_f32(sums); - /* If X is too small, just replace it with a pulse at 0 */ - /* Prevents infinities and NaNs from causing too many pulses - to be allocated. 64 is an approximation of infinity here. */ - if (!(sum > EPSILON && sum < 64)) - { - X[0] = QCONST16(1.f,14); - j=1; do - X[j]=0; - while (++j=0); - - /* This should never happen, but just in case it does (e.g. on silence) - we fill the first bin with pulses. */ - if (pulsesLeft > N+3) - { - opus_val16 tmp = (opus_val16)pulsesLeft; - yy = MAC16_16(yy, tmp, tmp); - yy = MAC16_16(yy, tmp, y[0]); - iy[0] += pulsesLeft; - pulsesLeft=0; - } - - for (i=0;i header file. */ -/* #undef HAVE_ALLOCA_H */ - -/* NE10 library is installed on host. Make sure it is on target! */ -/* #undef HAVE_ARM_NE10 */ +/* Opus configuration header */ +/* Based on the output of libopus configure script */ /* Define to 1 if you have the header file. */ #define HAVE_DLFCN_H 1 @@ -80,9 +41,6 @@ /* Define to 1 if you have the header file. */ #define HAVE_UNISTD_H 1 -/* Define to 1 if you have the `__malloc_hook' function. */ -#define HAVE___MALLOC_HOOK 1 - /* Define to the sub-directory in which libtool stores uninstalled libraries. */ #define LT_OBJDIR ".libs/" @@ -134,80 +92,9 @@ #endif // OPUS_ARM64_OPT -/* Define if binary requires Aarch64 Neon Intrinsics */ -/* #undef OPUS_ARM_PRESUME_AARCH64_NEON_INTR */ - -/* Define if binary requires EDSP instruction support */ -/* #undef OPUS_ARM_PRESUME_EDSP */ - -/* Define if binary requires ARMv6 media instruction support */ -/* #undef OPUS_ARM_PRESUME_MEDIA */ - -/* Define if binary requires NEON instruction support */ -/* #undef OPUS_ARM_PRESUME_NEON */ - -/* Define if binary requires NEON intrinsics support */ -/* #undef OPUS_ARM_PRESUME_NEON_INTR */ - /* This is a build of OPUS */ #define OPUS_BUILD /**/ -/* Run bit-exactness checks between optimized and c implementations */ -/* #undef OPUS_CHECK_ASM */ - -#ifndef OPUS_ARM_OPT -/* Use run-time CPU capabilities detection */ -#define OPUS_HAVE_RTCD 1 -#endif - -/* Compiler supports X86 AVX Intrinsics */ -/* #define OPUS_X86_MAY_HAVE_AVX */ - -/* Compiler supports X86 SSE Intrinsics */ -/* #define OPUS_X86_MAY_HAVE_SSE */ - -/* Compiler supports X86 SSE2 Intrinsics */ -/* #define OPUS_X86_MAY_HAVE_SSE2 */ - -/* Compiler supports X86 SSE4.1 Intrinsics */ -/* #define OPUS_X86_MAY_HAVE_SSE4_1 */ - -/* Define if binary requires AVX intrinsics support */ -/* #undef OPUS_X86_PRESUME_AVX */ - -/* Define if binary requires SSE intrinsics support */ -#define OPUS_X86_PRESUME_SSE 1 - -/* Define if binary requires SSE2 intrinsics support */ -#define OPUS_X86_PRESUME_SSE2 1 - -/* Define if binary requires SSE4.1 intrinsics support */ -#define OPUS_X86_PRESUME_SSE4_1 1 - -/* Define to the address where bug reports for this package should be sent. */ -#define PACKAGE_BUGREPORT "opus@xiph.org" - -/* Define to the full name of this package. */ -#define PACKAGE_NAME "opus" - -/* Define to the full name and version of this package. */ -#define PACKAGE_STRING "opus unknown" - -/* Define to the one symbol short name of this package. */ -#define PACKAGE_TARNAME "opus" - -/* Define to the home page for this package. */ -#define PACKAGE_URL "" - -/* Define to the version of this package. */ -#define PACKAGE_VERSION "unknown" - -/* Define to 1 if you have the ANSI C header files. */ -#define STDC_HEADERS 1 - -/* Make use of alloca */ -/* #undef USE_ALLOCA */ - #ifndef WIN32 /* Use C99 variable-size arrays */ #define VAR_ARRAYS 1 @@ -216,13 +103,11 @@ #define USE_ALLOCA 1 #endif -/* Define to empty if `const' does not conform to ANSI C. */ -/* #undef const */ - #ifndef OPUS_FIXED_POINT #define FLOAT_APPROX 1 #endif + /* Define to `__inline__' or `__inline' if that's what the C compiler calls it, or to nothing if 'inline' is not supported under any name. */ #ifndef __cplusplus diff --git a/thirdparty/opus/info.c b/thirdparty/opus/info.c index 3a1a5bf75b8..c36f9a9ee10 100644 --- a/thirdparty/opus/info.c +++ b/thirdparty/opus/info.c @@ -107,32 +107,26 @@ static int op_tags_ensure_capacity(OpusTags *_tags,size_t _ncomments){ char **user_comments; int *comment_lengths; int cur_ncomments; + char *binary_suffix_data; + int binary_suffix_len; size_t size; if(OP_UNLIKELY(_ncomments>=(size_t)INT_MAX))return OP_EFAULT; size=sizeof(*_tags->comment_lengths)*(_ncomments+1); if(size/sizeof(*_tags->comment_lengths)!=_ncomments+1)return OP_EFAULT; cur_ncomments=_tags->comments; - /*We only support growing. - Trimming requires cleaning up the allocated strings in the old space, and - is best handled separately if it's ever needed.*/ - OP_ASSERT(_ncomments>=(size_t)cur_ncomments); + comment_lengths=_tags->comment_lengths; + binary_suffix_len=comment_lengths==NULL?0:comment_lengths[cur_ncomments]; comment_lengths=(int *)_ogg_realloc(_tags->comment_lengths,size); if(OP_UNLIKELY(comment_lengths==NULL))return OP_EFAULT; - if(_tags->comment_lengths==NULL){ - OP_ASSERT(cur_ncomments==0); - comment_lengths[cur_ncomments]=0; - } - comment_lengths[_ncomments]=comment_lengths[cur_ncomments]; + comment_lengths[_ncomments]=binary_suffix_len; _tags->comment_lengths=comment_lengths; size=sizeof(*_tags->user_comments)*(_ncomments+1); if(size/sizeof(*_tags->user_comments)!=_ncomments+1)return OP_EFAULT; + user_comments=_tags->user_comments; + binary_suffix_data=user_comments==NULL?NULL:user_comments[cur_ncomments]; user_comments=(char **)_ogg_realloc(_tags->user_comments,size); if(OP_UNLIKELY(user_comments==NULL))return OP_EFAULT; - if(_tags->user_comments==NULL){ - OP_ASSERT(cur_ncomments==0); - user_comments[cur_ncomments]=NULL; - } - user_comments[_ncomments]=user_comments[cur_ncomments]; + user_comments[_ncomments]=binary_suffix_data; _tags->user_comments=user_comments; return 0; } @@ -281,30 +275,28 @@ int opus_tags_copy(OpusTags *_dst,const OpusTags *_src){ ret=opus_tags_copy_impl(&dst,_src); if(OP_UNLIKELY(ret<0))opus_tags_clear(&dst); else *_dst=*&dst; - return ret; + return 0; } int opus_tags_add(OpusTags *_tags,const char *_tag,const char *_value){ - char *comment; - size_t tag_len; - size_t value_len; - int ncomments; - int ret; + char *comment; + int tag_len; + int value_len; + int ncomments; + int ret; ncomments=_tags->comments; ret=op_tags_ensure_capacity(_tags,ncomments+1); if(OP_UNLIKELY(ret<0))return ret; tag_len=strlen(_tag); value_len=strlen(_value); /*+2 for '=' and '\0'.*/ - if(tag_len+value_len(size_t)INT_MAX-2)return OP_EFAULT; comment=(char *)_ogg_malloc(sizeof(*comment)*(tag_len+value_len+2)); if(OP_UNLIKELY(comment==NULL))return OP_EFAULT; memcpy(comment,_tag,sizeof(*comment)*tag_len); comment[tag_len]='='; memcpy(comment+tag_len+1,_value,sizeof(*comment)*(value_len+1)); _tags->user_comments[ncomments]=comment; - _tags->comment_lengths[ncomments]=(int)(tag_len+value_len+1); + _tags->comment_lengths[ncomments]=tag_len+value_len+1; _tags->comments=ncomments+1; return 0; } @@ -345,10 +337,7 @@ int opus_tags_set_binary_suffix(OpusTags *_tags, } int opus_tagcompare(const char *_tag_name,const char *_comment){ - size_t tag_len; - tag_len=strlen(_tag_name); - if(OP_UNLIKELY(tag_len>(size_t)INT_MAX))return -1; - return opus_tagncompare(_tag_name,(int)tag_len,_comment); + return opus_tagncompare(_tag_name,strlen(_tag_name),_comment); } int opus_tagncompare(const char *_tag_name,int _tag_len,const char *_comment){ @@ -359,18 +348,17 @@ int opus_tagncompare(const char *_tag_name,int _tag_len,const char *_comment){ } const char *opus_tags_query(const OpusTags *_tags,const char *_tag,int _count){ - char **user_comments; - size_t tag_len; - int found; - int ncomments; - int ci; + char **user_comments; + int tag_len; + int found; + int ncomments; + int ci; tag_len=strlen(_tag); - if(OP_UNLIKELY(tag_len>(size_t)INT_MAX))return NULL; ncomments=_tags->comments; user_comments=_tags->user_comments; found=0; for(ci=0;ci(size_t)INT_MAX))return 0; ncomments=_tags->comments; user_comments=_tags->user_comments; found=0; for(ci=0;cicomments; /*Look for the first valid tag with the name _tag_name and use that.*/ for(ci=0;ci=3&&memcmp(_buf,"\xFF\xD8\xFF",3)==0; + return _buf_sz>=11&&memcmp(_buf,"\xFF\xD8\xFF\xE0",4)==0 + &&(_buf[4]<<8|_buf[5])>=16&&memcmp(_buf+6,"JFIF",5)==0; } /*Tries to extract the width, height, bits per pixel, and palette size of a diff --git a/thirdparty/opus/internal.h b/thirdparty/opus/internal.h index 9ac17e028fc..ee48ea34c92 100644 --- a/thirdparty/opus/internal.h +++ b/thirdparty/opus/internal.h @@ -136,9 +136,6 @@ struct OggOpusLink{ that end-trimming calculations work properly. This is only valid for seekable sources.*/ opus_int64 end_offset; - /*The total duration of all prior links. - This is always zero for non-seekable sources.*/ - ogg_int64_t pcm_file_offset; /*The granule position of the last sample. This is only valid for seekable sources.*/ ogg_int64_t pcm_end; @@ -153,25 +150,23 @@ struct OggOpusLink{ }; struct OggOpusFile{ - /*The callbacks used to access the stream.*/ + /*The callbacks used to access the data source.*/ OpusFileCallbacks callbacks; - /*A FILE *, memory buffer, etc.*/ - void *stream; - /*Whether or not we can seek with this stream.*/ + /*A FILE *, memory bufer, etc.*/ + void *source; + /*Whether or not we can seek with this data source.*/ int seekable; /*The number of links in this chained Ogg Opus file.*/ int nlinks; /*The cached information from each link in a chained Ogg Opus file. - If stream isn't seekable (e.g., it's a pipe), only the current link + If source isn't seekable (e.g., it's a pipe), only the current link appears.*/ OggOpusLink *links; /*The number of serial numbers from a single link.*/ int nserialnos; /*The capacity of the list of serial numbers from a single link.*/ int cserialnos; - /*Storage for the list of serial numbers from a single link. - This is a scratch buffer used when scanning the BOS pages at the start of - each link.*/ + /*Storage for the list of serial numbers from a single link.*/ ogg_uint32_t *serialnos; /*This is the current offset of the data processed by the ogg_sync_state. After a seek, this should be set to the target offset so that we can track @@ -179,9 +174,9 @@ struct OggOpusFile{ After a call to op_get_next_page(), this will point to the first byte after that page.*/ opus_int64 offset; - /*The total size of this stream, or -1 if it's unseekable.*/ + /*The total size of this data source, or -1 if it's unseekable.*/ opus_int64 end; - /*Used to locate pages in the stream.*/ + /*Used to locate pages in the data source.*/ ogg_sync_state oy; /*One of OP_NOTOPEN, OP_PARTOPEN, OP_OPENED, OP_STREAMSET, OP_INITSET.*/ int ready_state; @@ -232,7 +227,7 @@ struct OggOpusFile{ /*The number of valid samples in the decoded buffer.*/ int od_buffer_size; /*The type of gain offset to apply. - One of OP_HEADER_GAIN, OP_ALBUM_GAIN, OP_TRACK_GAIN, or OP_ABSOLUTE_GAIN.*/ + One of OP_HEADER_GAIN, OP_TRACK_GAIN, or OP_ABSOLUTE_GAIN.*/ int gain_type; /*The offset to apply to the gain.*/ opus_int32 gain_offset_q8; diff --git a/thirdparty/opus/mapping_matrix.c b/thirdparty/opus/mapping_matrix.c deleted file mode 100644 index 31298af0575..00000000000 --- a/thirdparty/opus/mapping_matrix.c +++ /dev/null @@ -1,378 +0,0 @@ -/* Copyright (c) 2017 Google Inc. - Written by Andrew Allen */ -/* - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions - are met: - - - Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - - - Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER - OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include "arch.h" -#include "float_cast.h" -#include "opus_private.h" -#include "opus_defines.h" -#include "mapping_matrix.h" - -#define MATRIX_INDEX(nb_rows, row, col) (nb_rows * col + row) - -opus_int32 mapping_matrix_get_size(int rows, int cols) -{ - opus_int32 size; - - /* Mapping Matrix must only support up to 255 channels in or out. - * Additionally, the total cell count must be <= 65004 octets in order - * for the matrix to be stored in an OGG header. - */ - if (rows > 255 || cols > 255) - return 0; - size = rows * (opus_int32)cols * sizeof(opus_int16); - if (size > 65004) - return 0; - - return align(sizeof(MappingMatrix)) + align(size); -} - -opus_int16 *mapping_matrix_get_data(const MappingMatrix *matrix) -{ - /* void* cast avoids clang -Wcast-align warning */ - return (opus_int16*)(void*)((char*)matrix + align(sizeof(MappingMatrix))); -} - -void mapping_matrix_init(MappingMatrix * const matrix, - int rows, int cols, int gain, const opus_int16 *data, opus_int32 data_size) -{ - int i; - opus_int16 *ptr; - -#if !defined(ENABLE_ASSERTIONS) - (void)data_size; -#endif - celt_assert(align(data_size) == align(rows * cols * sizeof(opus_int16))); - - matrix->rows = rows; - matrix->cols = cols; - matrix->gain = gain; - ptr = mapping_matrix_get_data(matrix); - for (i = 0; i < rows * cols; i++) - { - ptr[i] = data[i]; - } -} - -#ifndef DISABLE_FLOAT_API -void mapping_matrix_multiply_channel_in_float( - const MappingMatrix *matrix, - const float *input, - int input_rows, - opus_val16 *output, - int output_row, - int output_rows, - int frame_size) -{ - /* Matrix data is ordered col-wise. */ - opus_int16* matrix_data; - int i, col; - - celt_assert(input_rows <= matrix->cols && output_rows <= matrix->rows); - - matrix_data = mapping_matrix_get_data(matrix); - - for (i = 0; i < frame_size; i++) - { - float tmp = 0; - for (col = 0; col < input_rows; col++) - { - tmp += - matrix_data[MATRIX_INDEX(matrix->rows, output_row, col)] * - input[MATRIX_INDEX(input_rows, col, i)]; - } -#if defined(FIXED_POINT) - output[output_rows * i] = FLOAT2INT16((1/32768.f)*tmp); -#else - output[output_rows * i] = (1/32768.f)*tmp; -#endif - } -} - -void mapping_matrix_multiply_channel_out_float( - const MappingMatrix *matrix, - const opus_val16 *input, - int input_row, - int input_rows, - float *output, - int output_rows, - int frame_size -) -{ - /* Matrix data is ordered col-wise. */ - opus_int16* matrix_data; - int i, row; - float input_sample; - - celt_assert(input_rows <= matrix->cols && output_rows <= matrix->rows); - - matrix_data = mapping_matrix_get_data(matrix); - - for (i = 0; i < frame_size; i++) - { -#if defined(FIXED_POINT) - input_sample = (1/32768.f)*input[input_rows * i]; -#else - input_sample = input[input_rows * i]; -#endif - for (row = 0; row < output_rows; row++) - { - float tmp = - (1/32768.f)*matrix_data[MATRIX_INDEX(matrix->rows, row, input_row)] * - input_sample; - output[MATRIX_INDEX(output_rows, row, i)] += tmp; - } - } -} -#endif /* DISABLE_FLOAT_API */ - -void mapping_matrix_multiply_channel_in_short( - const MappingMatrix *matrix, - const opus_int16 *input, - int input_rows, - opus_val16 *output, - int output_row, - int output_rows, - int frame_size) -{ - /* Matrix data is ordered col-wise. */ - opus_int16* matrix_data; - int i, col; - - celt_assert(input_rows <= matrix->cols && output_rows <= matrix->rows); - - matrix_data = mapping_matrix_get_data(matrix); - - for (i = 0; i < frame_size; i++) - { - opus_val32 tmp = 0; - for (col = 0; col < input_rows; col++) - { -#if defined(FIXED_POINT) - tmp += - ((opus_int32)matrix_data[MATRIX_INDEX(matrix->rows, output_row, col)] * - (opus_int32)input[MATRIX_INDEX(input_rows, col, i)]) >> 8; -#else - tmp += - matrix_data[MATRIX_INDEX(matrix->rows, output_row, col)] * - input[MATRIX_INDEX(input_rows, col, i)]; -#endif - } -#if defined(FIXED_POINT) - output[output_rows * i] = (opus_int16)((tmp + 64) >> 7); -#else - output[output_rows * i] = (1/(32768.f*32768.f))*tmp; -#endif - } -} - -void mapping_matrix_multiply_channel_out_short( - const MappingMatrix *matrix, - const opus_val16 *input, - int input_row, - int input_rows, - opus_int16 *output, - int output_rows, - int frame_size) -{ - /* Matrix data is ordered col-wise. */ - opus_int16* matrix_data; - int i, row; - opus_int32 input_sample; - - celt_assert(input_rows <= matrix->cols && output_rows <= matrix->rows); - - matrix_data = mapping_matrix_get_data(matrix); - - for (i = 0; i < frame_size; i++) - { -#if defined(FIXED_POINT) - input_sample = (opus_int32)input[input_rows * i]; -#else - input_sample = (opus_int32)FLOAT2INT16(input[input_rows * i]); -#endif - for (row = 0; row < output_rows; row++) - { - opus_int32 tmp = - (opus_int32)matrix_data[MATRIX_INDEX(matrix->rows, row, input_row)] * - input_sample; - output[MATRIX_INDEX(output_rows, row, i)] += (tmp + 16384) >> 15; - } - } -} - -const MappingMatrix mapping_matrix_foa_mixing = { 6, 6, 0 }; -const opus_int16 mapping_matrix_foa_mixing_data[36] = { - 16384, 0, -16384, 23170, 0, 0, 16384, 23170, - 16384, 0, 0, 0, 16384, 0, -16384, -23170, - 0, 0, 16384, -23170, 16384, 0, 0, 0, - 0, 0, 0, 0, 32767, 0, 0, 0, - 0, 0, 0, 32767 -}; - -const MappingMatrix mapping_matrix_soa_mixing = { 11, 11, 0 }; -const opus_int16 mapping_matrix_soa_mixing_data[121] = { - 10923, 7723, 13377, -13377, 11585, 9459, 7723, -16384, - -6689, 0, 0, 10923, 7723, 13377, 13377, -11585, - 9459, 7723, 16384, -6689, 0, 0, 10923, -15447, - 13377, 0, 0, -18919, 7723, 0, 13377, 0, - 0, 10923, 7723, -13377, -13377, 11585, -9459, 7723, - 16384, -6689, 0, 0, 10923, -7723, 0, 13377, - -16384, 0, -15447, 0, 9459, 0, 0, 10923, - -7723, 0, -13377, 16384, 0, -15447, 0, 9459, - 0, 0, 10923, 15447, 0, 0, 0, 0, - -15447, 0, -18919, 0, 0, 10923, 7723, -13377, - 13377, -11585, -9459, 7723, -16384, -6689, 0, 0, - 10923, -15447, -13377, 0, 0, 18919, 7723, 0, - 13377, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 32767, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 32767 -}; - -const MappingMatrix mapping_matrix_toa_mixing = { 18, 18, 0 }; -const opus_int16 mapping_matrix_toa_mixing_data[324] = { - 8208, 0, -881, 14369, 0, 0, -8192, -4163, - 13218, 0, 0, 0, 11095, -8836, -6218, 14833, - 0, 0, 8208, -10161, 881, 10161, -13218, -2944, - -8192, 2944, 0, -10488, -6218, 6248, -11095, -6248, - 0, -10488, 0, 0, 8208, 10161, 881, -10161, - -13218, 2944, -8192, -2944, 0, 10488, -6218, -6248, - -11095, 6248, 0, 10488, 0, 0, 8176, 5566, - -11552, 5566, 9681, -11205, 8192, -11205, 0, 4920, - -15158, 9756, -3334, 9756, 0, -4920, 0, 0, - 8176, 7871, 11552, 0, 0, 15846, 8192, 0, - -9681, -6958, 0, 13797, 3334, 0, -15158, 0, - 0, 0, 8176, 0, 11552, 7871, 0, 0, - 8192, 15846, 9681, 0, 0, 0, 3334, 13797, - 15158, 6958, 0, 0, 8176, 5566, -11552, -5566, - -9681, -11205, 8192, 11205, 0, 4920, 15158, 9756, - -3334, -9756, 0, 4920, 0, 0, 8208, 14369, - -881, 0, 0, -4163, -8192, 0, -13218, -14833, - 0, -8836, 11095, 0, 6218, 0, 0, 0, - 8208, 10161, 881, 10161, 13218, 2944, -8192, 2944, - 0, 10488, 6218, -6248, -11095, -6248, 0, -10488, - 0, 0, 8208, -14369, -881, 0, 0, 4163, - -8192, 0, -13218, 14833, 0, 8836, 11095, 0, - 6218, 0, 0, 0, 8208, 0, -881, -14369, - 0, 0, -8192, 4163, 13218, 0, 0, 0, - 11095, 8836, -6218, -14833, 0, 0, 8176, -5566, - -11552, 5566, -9681, 11205, 8192, -11205, 0, -4920, - 15158, -9756, -3334, 9756, 0, -4920, 0, 0, - 8176, 0, 11552, -7871, 0, 0, 8192, -15846, - 9681, 0, 0, 0, 3334, -13797, 15158, -6958, - 0, 0, 8176, -7871, 11552, 0, 0, -15846, - 8192, 0, -9681, 6958, 0, -13797, 3334, 0, - -15158, 0, 0, 0, 8176, -5566, -11552, -5566, - 9681, 11205, 8192, 11205, 0, -4920, -15158, -9756, - -3334, -9756, 0, 4920, 0, 0, 8208, -10161, - 881, -10161, 13218, -2944, -8192, -2944, 0, -10488, - 6218, 6248, -11095, 6248, 0, 10488, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 32767, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 32767 -}; - -const MappingMatrix mapping_matrix_foa_demixing = { 6, 6, 0 }; -const opus_int16 mapping_matrix_foa_demixing_data[36] = { - 16384, 16384, 16384, 16384, 0, 0, 0, 23170, - 0, -23170, 0, 0, -16384, 16384, -16384, 16384, - 0, 0, 23170, 0, -23170, 0, 0, 0, - 0, 0, 0, 0, 32767, 0, 0, 0, - 0, 0, 0, 32767 -}; - -const MappingMatrix mapping_matrix_soa_demixing = { 11, 11, 3050 }; -const opus_int16 mapping_matrix_soa_demixing_data[121] = { - 2771, 2771, 2771, 2771, 2771, 2771, 2771, 2771, - 2771, 0, 0, 10033, 10033, -20066, 10033, 14189, - 14189, -28378, 10033, -20066, 0, 0, 3393, 3393, - 3393, -3393, 0, 0, 0, -3393, -3393, 0, - 0, -17378, 17378, 0, -17378, -24576, 24576, 0, - 17378, 0, 0, 0, -14189, 14189, 0, -14189, - -28378, 28378, 0, 14189, 0, 0, 0, 2399, - 2399, -4799, -2399, 0, 0, 0, -2399, 4799, - 0, 0, 1959, 1959, 1959, 1959, -3918, -3918, - -3918, 1959, 1959, 0, 0, -4156, 4156, 0, - 4156, 0, 0, 0, -4156, 0, 0, 0, - 8192, 8192, -16384, 8192, 16384, 16384, -32768, 8192, - -16384, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 8312, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 8312 -}; - -const MappingMatrix mapping_matrix_toa_demixing = { 18, 18, 0 }; -const opus_int16 mapping_matrix_toa_demixing_data[324] = { - 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, - 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, - 0, 0, 0, -9779, 9779, 6263, 8857, 0, - 6263, 13829, 9779, -13829, 0, -6263, 0, -8857, - -6263, -9779, 0, 0, -3413, 3413, 3413, -11359, - 11359, 11359, -11359, -3413, 3413, -3413, -3413, -11359, - 11359, 11359, -11359, 3413, 0, 0, 13829, 9779, - -9779, 6263, 0, 8857, -6263, 0, 9779, 0, - -13829, 6263, -8857, 0, -6263, -9779, 0, 0, - 0, -15617, -15617, 6406, 0, 0, -6406, 0, - 15617, 0, 0, -6406, 0, 0, 6406, 15617, - 0, 0, 0, -5003, 5003, -10664, 15081, 0, - -10664, -7075, 5003, 7075, 0, 10664, 0, -15081, - 10664, -5003, 0, 0, -8176, -8176, -8176, 8208, - 8208, 8208, 8208, -8176, -8176, -8176, -8176, 8208, - 8208, 8208, 8208, -8176, 0, 0, -7075, 5003, - -5003, -10664, 0, 15081, 10664, 0, 5003, 0, - 7075, -10664, -15081, 0, 10664, -5003, 0, 0, - 15617, 0, 0, 0, -6406, 6406, 0, -15617, - 0, -15617, 15617, 0, 6406, -6406, 0, 0, - 0, 0, 0, -11393, 11393, 2993, -4233, 0, - 2993, -16112, 11393, 16112, 0, -2993, 0, 4233, - -2993, -11393, 0, 0, 0, -9974, -9974, -13617, - 0, 0, 13617, 0, 9974, 0, 0, 13617, - 0, 0, -13617, 9974, 0, 0, 0, 5579, - -5579, 10185, 14403, 0, 10185, -7890, -5579, 7890, - 0, -10185, 0, -14403, -10185, 5579, 0, 0, - 11826, -11826, -11826, -901, 901, 901, -901, 11826, - -11826, 11826, 11826, -901, 901, 901, -901, -11826, - 0, 0, -7890, -5579, 5579, 10185, 0, 14403, - -10185, 0, -5579, 0, 7890, 10185, -14403, 0, - -10185, 5579, 0, 0, -9974, 0, 0, 0, - -13617, 13617, 0, 9974, 0, 9974, -9974, 0, - 13617, -13617, 0, 0, 0, 0, 16112, -11393, - 11393, -2993, 0, 4233, 2993, 0, -11393, 0, - -16112, -2993, -4233, 0, 2993, 11393, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 32767, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 32767 -}; - diff --git a/thirdparty/opus/mapping_matrix.h b/thirdparty/opus/mapping_matrix.h deleted file mode 100644 index 98bc82df3eb..00000000000 --- a/thirdparty/opus/mapping_matrix.h +++ /dev/null @@ -1,133 +0,0 @@ -/* Copyright (c) 2017 Google Inc. - Written by Andrew Allen */ -/* - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions - are met: - - - Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - - - Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER - OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ - -/** - * @file mapping_matrix.h - * @brief Opus reference implementation mapping matrix API - */ - -#ifndef MAPPING_MATRIX_H -#define MAPPING_MATRIX_H - -#include "opus_types.h" -#include "opus_projection.h" - -#ifdef __cplusplus -extern "C" { -#endif - -typedef struct MappingMatrix -{ - int rows; /* number of channels outputted from matrix. */ - int cols; /* number of channels inputted to matrix. */ - int gain; /* in dB. S7.8-format. */ - /* Matrix cell data goes here using col-wise ordering. */ -} MappingMatrix; - -opus_int32 mapping_matrix_get_size(int rows, int cols); - -opus_int16 *mapping_matrix_get_data(const MappingMatrix *matrix); - -void mapping_matrix_init( - MappingMatrix * const matrix, - int rows, - int cols, - int gain, - const opus_int16 *data, - opus_int32 data_size -); - -#ifndef DISABLE_FLOAT_API -void mapping_matrix_multiply_channel_in_float( - const MappingMatrix *matrix, - const float *input, - int input_rows, - opus_val16 *output, - int output_row, - int output_rows, - int frame_size -); - -void mapping_matrix_multiply_channel_out_float( - const MappingMatrix *matrix, - const opus_val16 *input, - int input_row, - int input_rows, - float *output, - int output_rows, - int frame_size -); -#endif /* DISABLE_FLOAT_API */ - -void mapping_matrix_multiply_channel_in_short( - const MappingMatrix *matrix, - const opus_int16 *input, - int input_rows, - opus_val16 *output, - int output_row, - int output_rows, - int frame_size -); - -void mapping_matrix_multiply_channel_out_short( - const MappingMatrix *matrix, - const opus_val16 *input, - int input_row, - int input_rows, - opus_int16 *output, - int output_rows, - int frame_size -); - -/* Pre-computed mixing and demixing matrices for 1st to 3rd-order ambisonics. - * foa: first-order ambisonics - * soa: second-order ambisonics - * toa: third-order ambisonics - */ -extern const MappingMatrix mapping_matrix_foa_mixing; -extern const opus_int16 mapping_matrix_foa_mixing_data[36]; - -extern const MappingMatrix mapping_matrix_soa_mixing; -extern const opus_int16 mapping_matrix_soa_mixing_data[121]; - -extern const MappingMatrix mapping_matrix_toa_mixing; -extern const opus_int16 mapping_matrix_toa_mixing_data[324]; - -extern const MappingMatrix mapping_matrix_foa_demixing; -extern const opus_int16 mapping_matrix_foa_demixing_data[36]; - -extern const MappingMatrix mapping_matrix_soa_demixing; -extern const opus_int16 mapping_matrix_soa_demixing_data[121]; - -extern const MappingMatrix mapping_matrix_toa_demixing; -extern const opus_int16 mapping_matrix_toa_demixing_data[324]; - -#ifdef __cplusplus -} -#endif - -#endif /* MAPPING_MATRIX_H */ diff --git a/thirdparty/opus/mlp.c b/thirdparty/opus/mlp.c index 964c6a98f6d..ff9e50df472 100644 --- a/thirdparty/opus/mlp.c +++ b/thirdparty/opus/mlp.c @@ -1,5 +1,5 @@ /* Copyright (c) 2008-2011 Octasic Inc. - 2012-2017 Jean-Marc Valin */ + Written by Jean-Marc Valin */ /* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions @@ -29,13 +29,42 @@ #include "config.h" #endif -#include #include "opus_types.h" #include "opus_defines.h" + +#include +#include "mlp.h" #include "arch.h" #include "tansig_table.h" -#include "mlp.h" +#define MAX_NEURONS 100 +#if 0 +static OPUS_INLINE opus_val16 tansig_approx(opus_val32 _x) /* Q19 */ +{ + int i; + opus_val16 xx; /* Q11 */ + /*double x, y;*/ + opus_val16 dy, yy; /* Q14 */ + /*x = 1.9073e-06*_x;*/ + if (_x>=QCONST32(8,19)) + return QCONST32(1.,14); + if (_x<=-QCONST32(8,19)) + return -QCONST32(1.,14); + xx = EXTRACT16(SHR32(_x, 8)); + /*i = lrint(25*x);*/ + i = SHR32(ADD32(1024,MULT16_16(25, xx)),11); + /*x -= .04*i;*/ + xx -= EXTRACT16(SHR32(MULT16_16(20972,i),8)); + /*x = xx*(1./2048);*/ + /*y = tansig_table[250+i];*/ + yy = tansig_table[250+i]; + /*y = yy*(1./16384);*/ + dy = 16384-MULT16_16_Q14(yy,yy); + yy = yy + MULT16_16_Q14(MULT16_16_Q11(xx,dy),(16384 - MULT16_16_Q11(yy,xx))); + return yy; +} +#else +/*extern const float tansig_table[501];*/ static OPUS_INLINE float tansig_approx(float x) { int i; @@ -63,82 +92,54 @@ static OPUS_INLINE float tansig_approx(float x) y = y + x*dy*(1 - y*x); return sign*y; } +#endif -static OPUS_INLINE float sigmoid_approx(float x) +#if 0 +void mlp_process(const MLP *m, const opus_val16 *in, opus_val16 *out) { - return .5f + .5f*tansig_approx(.5f*x); + int j; + opus_val16 hidden[MAX_NEURONS]; + const opus_val16 *W = m->weights; + /* Copy to tmp_in */ + for (j=0;jtopo[1];j++) + { + int k; + opus_val32 sum = SHL32(EXTEND32(*W++),8); + for (k=0;ktopo[0];k++) + sum = MAC16_16(sum, in[k],*W++); + hidden[j] = tansig_approx(sum); + } + for (j=0;jtopo[2];j++) + { + int k; + opus_val32 sum = SHL32(EXTEND32(*W++),14); + for (k=0;ktopo[1];k++) + sum = MAC16_16(sum, hidden[k], *W++); + out[j] = tansig_approx(EXTRACT16(PSHR32(sum,17))); + } } - -static void gemm_accum(float *out, const opus_int8 *weights, int rows, int cols, int col_stride, const float *x) +#else +void mlp_process(const MLP *m, const float *in, float *out) { - int i, j; - for (i=0;iweights; + /* Copy to tmp_in */ + for (j=0;jtopo[1];j++) + { + int k; + float sum = *W++; + for (k=0;ktopo[0];k++) + sum = sum + in[k]**W++; + hidden[j] = tansig_approx(sum); + } + for (j=0;jtopo[2];j++) + { + int k; + float sum = *W++; + for (k=0;ktopo[1];k++) + sum = sum + hidden[k]**W++; + out[j] = tansig_approx(sum); + } } - -void compute_dense(const DenseLayer *layer, float *output, const float *input) -{ - int i; - int N, M; - int stride; - M = layer->nb_inputs; - N = layer->nb_neurons; - stride = N; - for (i=0;ibias[i]; - gemm_accum(output, layer->input_weights, N, M, stride, input); - for (i=0;isigmoid) { - for (i=0;inb_inputs; - N = gru->nb_neurons; - stride = 3*N; - /* Compute update gate. */ - for (i=0;ibias[i]; - gemm_accum(z, gru->input_weights, N, M, stride, input); - gemm_accum(z, gru->recurrent_weights, N, N, stride, state); - for (i=0;ibias[N + i]; - gemm_accum(r, &gru->input_weights[N], N, M, stride, input); - gemm_accum(r, &gru->recurrent_weights[N], N, N, stride, state); - for (i=0;ibias[2*N + i]; - for (i=0;iinput_weights[2*N], N, M, stride, input); - gemm_accum(h, &gru->recurrent_weights[2*N], N, N, stride, tmp); - for (i=0;i