summaryrefslogtreecommitdiff
path: root/libs/libopus/silk
diff options
context:
space:
mode:
Diffstat (limited to 'libs/libopus/silk')
-rw-r--r--libs/libopus/silk/A2NLSF.c8
-rw-r--r--libs/libopus/silk/API.h3
-rw-r--r--libs/libopus/silk/CNG.c16
-rw-r--r--libs/libopus/silk/LPC_analysis_filter.c25
-rw-r--r--libs/libopus/silk/LPC_fit.c82
-rw-r--r--libs/libopus/silk/LPC_inv_pred_gain.c97
-rw-r--r--libs/libopus/silk/LP_variable_cutoff.c2
-rw-r--r--libs/libopus/silk/MacroCount.h12
-rw-r--r--libs/libopus/silk/MacroDebug.h3
-rw-r--r--libs/libopus/silk/NLSF2A.c59
-rw-r--r--libs/libopus/silk/NLSF_VQ.c44
-rw-r--r--libs/libopus/silk/NLSF_VQ_weights_laroia.c4
-rw-r--r--libs/libopus/silk/NLSF_decode.c22
-rw-r--r--libs/libopus/silk/NLSF_del_dec_quant.c8
-rw-r--r--libs/libopus/silk/NLSF_encode.c37
-rw-r--r--libs/libopus/silk/NSQ.c104
-rw-r--r--libs/libopus/silk/NSQ_del_dec.c129
-rw-r--r--libs/libopus/silk/PLC.c6
-rw-r--r--libs/libopus/silk/SigProc_FIX.h62
-rw-r--r--libs/libopus/silk/VAD.c22
-rw-r--r--libs/libopus/silk/VQ_WMat_EC.c129
-rw-r--r--libs/libopus/silk/arm/LPC_inv_pred_gain_arm.h57
-rw-r--r--libs/libopus/silk/arm/LPC_inv_pred_gain_neon_intr.c288
-rw-r--r--libs/libopus/silk/arm/NSQ_del_dec_arm.h100
-rw-r--r--libs/libopus/silk/arm/NSQ_del_dec_neon_intr.c1124
-rw-r--r--libs/libopus/silk/arm/NSQ_neon.h33
-rw-r--r--libs/libopus/silk/arm/arm_silk_map.c68
-rw-r--r--libs/libopus/silk/arm/biquad_alt_arm.h68
-rw-r--r--libs/libopus/silk/arm/biquad_alt_neon_intr.c156
-rw-r--r--libs/libopus/silk/arm/macros_armv4.h13
-rw-r--r--libs/libopus/silk/arm/macros_armv5e.h9
-rw-r--r--libs/libopus/silk/biquad_alt.c53
-rw-r--r--libs/libopus/silk/bwexpander.c2
-rw-r--r--libs/libopus/silk/bwexpander_32.c3
-rw-r--r--libs/libopus/silk/check_control_input.c22
-rw-r--r--libs/libopus/silk/control.h8
-rw-r--r--libs/libopus/silk/control_SNR.c103
-rw-r--r--libs/libopus/silk/control_audio_bandwidth.c16
-rw-r--r--libs/libopus/silk/control_codec.c105
-rw-r--r--libs/libopus/silk/debug.c10
-rw-r--r--libs/libopus/silk/debug.h38
-rw-r--r--libs/libopus/silk/dec_API.c6
-rw-r--r--libs/libopus/silk/decode_core.c6
-rw-r--r--libs/libopus/silk/decode_frame.c6
-rw-r--r--libs/libopus/silk/decode_indices.c2
-rw-r--r--libs/libopus/silk/decode_parameters.c4
-rw-r--r--libs/libopus/silk/decode_pitch.c4
-rw-r--r--libs/libopus/silk/decode_pulses.c2
-rw-r--r--libs/libopus/silk/decoder_set_fs.c8
-rw-r--r--libs/libopus/silk/define.h18
-rw-r--r--libs/libopus/silk/enc_API.c47
-rw-r--r--libs/libopus/silk/encode_indices.c6
-rw-r--r--libs/libopus/silk/encode_pulses.c2
-rw-r--r--libs/libopus/silk/fixed/apply_sine_window_FIX.c8
-rw-r--r--libs/libopus/silk/fixed/arm/warped_autocorrelation_FIX_arm.h68
-rw-r--r--libs/libopus/silk/fixed/arm/warped_autocorrelation_FIX_neon_intr.c265
-rw-r--r--libs/libopus/silk/fixed/burg_modified_FIX.c12
-rw-r--r--libs/libopus/silk/fixed/corrMatrix_FIX.c38
-rw-r--r--libs/libopus/silk/fixed/encode_frame_FIX.c123
-rw-r--r--libs/libopus/silk/fixed/find_LPC_FIX.c4
-rw-r--r--libs/libopus/silk/fixed/find_LTP_FIX.c238
-rw-r--r--libs/libopus/silk/fixed/find_pitch_lags_FIX.c20
-rw-r--r--libs/libopus/silk/fixed/find_pred_coefs_FIX.c27
-rw-r--r--libs/libopus/silk/fixed/k2a_FIX.c13
-rw-r--r--libs/libopus/silk/fixed/k2a_Q16_FIX.c15
-rw-r--r--libs/libopus/silk/fixed/main_FIX.h74
-rw-r--r--libs/libopus/silk/fixed/mips/noise_shape_analysis_FIX_mipsr1.h6
-rw-r--r--libs/libopus/silk/fixed/mips/prefilter_FIX_mipsr1.h184
-rw-r--r--libs/libopus/silk/fixed/mips/warped_autocorrelation_FIX_mipsr1.h4
-rw-r--r--libs/libopus/silk/fixed/noise_shape_analysis_FIX.c160
-rw-r--r--libs/libopus/silk/fixed/pitch_analysis_core_FIX.c125
-rw-r--r--libs/libopus/silk/fixed/prefilter_FIX.c221
-rw-r--r--libs/libopus/silk/fixed/residual_energy16_FIX.c8
-rw-r--r--libs/libopus/silk/fixed/residual_energy_FIX.c2
-rw-r--r--libs/libopus/silk/fixed/schur64_FIX.c7
-rw-r--r--libs/libopus/silk/fixed/schur_FIX.c15
-rw-r--r--libs/libopus/silk/fixed/solve_LS_FIX.c249
-rw-r--r--libs/libopus/silk/fixed/structs_FIX.h22
-rw-r--r--libs/libopus/silk/fixed/vector_ops_FIX.c2
-rw-r--r--libs/libopus/silk/fixed/warped_autocorrelation_FIX.c11
-rw-r--r--libs/libopus/silk/fixed/x86/burg_modified_FIX_sse4_1.c (renamed from libs/libopus/silk/fixed/x86/burg_modified_FIX_sse.c)71
-rw-r--r--libs/libopus/silk/fixed/x86/prefilter_FIX_sse.c160
-rw-r--r--libs/libopus/silk/fixed/x86/vector_ops_FIX_sse4_1.c (renamed from libs/libopus/silk/fixed/x86/vector_ops_FIX_sse.c)40
-rw-r--r--libs/libopus/silk/float/LPC_analysis_filter_FLP.c4
-rw-r--r--libs/libopus/silk/float/LPC_inv_pred_gain_FLP.c37
-rw-r--r--libs/libopus/silk/float/SigProc_FLP.h7
-rw-r--r--libs/libopus/silk/float/apply_sine_window_FLP.c4
-rw-r--r--libs/libopus/silk/float/burg_modified_FLP.c2
-rw-r--r--libs/libopus/silk/float/encode_frame_FLP.c105
-rw-r--r--libs/libopus/silk/float/energy_FLP.c5
-rw-r--r--libs/libopus/silk/float/find_LPC_FLP.c4
-rw-r--r--libs/libopus/silk/float/find_LTP_FLP.c108
-rw-r--r--libs/libopus/silk/float/find_pitch_lags_FLP.c2
-rw-r--r--libs/libopus/silk/float/find_pred_coefs_FLP.c14
-rw-r--r--libs/libopus/silk/float/inner_product_FLP.c5
-rw-r--r--libs/libopus/silk/float/k2a_FLP.c15
-rw-r--r--libs/libopus/silk/float/levinsondurbin_FLP.c81
-rw-r--r--libs/libopus/silk/float/main_FLP.h55
-rw-r--r--libs/libopus/silk/float/noise_shape_analysis_FLP.c149
-rw-r--r--libs/libopus/silk/float/pitch_analysis_core_FLP.c36
-rw-r--r--libs/libopus/silk/float/prefilter_FLP.c206
-rw-r--r--libs/libopus/silk/float/residual_energy_FLP.c2
-rw-r--r--libs/libopus/silk/float/schur_FLP.c16
-rw-r--r--libs/libopus/silk/float/solve_LS_FLP.c207
-rw-r--r--libs/libopus/silk/float/sort_FLP.c6
-rw-r--r--libs/libopus/silk/float/structs_FLP.h22
-rw-r--r--libs/libopus/silk/float/warped_autocorrelation_FLP.c6
-rw-r--r--libs/libopus/silk/float/wrappers_FLP.c49
-rw-r--r--libs/libopus/silk/gain_quant.c1
-rw-r--r--libs/libopus/silk/init_decoder.c1
-rw-r--r--libs/libopus/silk/interpolate.c4
-rw-r--r--libs/libopus/silk/lin2log.c2
-rw-r--r--libs/libopus/silk/macros.h8
-rw-r--r--libs/libopus/silk/main.h125
-rw-r--r--libs/libopus/silk/mips/NSQ_del_dec_mipsr1.h7
-rw-r--r--libs/libopus/silk/mips/sigproc_fix_mipsr1.h5
-rw-r--r--libs/libopus/silk/process_NLSFs.c10
-rw-r--r--libs/libopus/silk/quant_LTP_gains.c67
-rw-r--r--libs/libopus/silk/resampler.c10
-rw-r--r--libs/libopus/silk/resampler_down2.c4
-rw-r--r--libs/libopus/silk/resampler_private_down_FIR.c2
-rw-r--r--libs/libopus/silk/sort.c14
-rw-r--r--libs/libopus/silk/stereo_LR_to_MS.c2
-rw-r--r--libs/libopus/silk/stereo_encode_pred.c6
-rw-r--r--libs/libopus/silk/structs.h6
-rw-r--r--libs/libopus/silk/sum_sqr_shift.c51
-rw-r--r--libs/libopus/silk/tables.h8
-rw-r--r--libs/libopus/silk/tables_LTP.c2
-rw-r--r--libs/libopus/silk/tables_NLSF_CB_NB_MB.c36
-rw-r--r--libs/libopus/silk/tables_NLSF_CB_WB.c36
-rw-r--r--libs/libopus/silk/tables_other.c14
-rw-r--r--libs/libopus/silk/tuning_parameters.h28
-rw-r--r--libs/libopus/silk/typedef.h3
-rw-r--r--libs/libopus/silk/x86/NSQ_del_dec_sse4_1.c (renamed from libs/libopus/silk/x86/NSQ_del_dec_sse.c)199
-rw-r--r--libs/libopus/silk/x86/NSQ_sse4_1.c (renamed from libs/libopus/silk/x86/NSQ_sse.c)214
-rw-r--r--libs/libopus/silk/x86/SigProc_FIX_sse.h12
-rw-r--r--libs/libopus/silk/x86/VAD_sse4_1.c (renamed from libs/libopus/silk/x86/VAD_sse.c)34
-rw-r--r--libs/libopus/silk/x86/VQ_WMat_EC_sse.c142
-rw-r--r--libs/libopus/silk/x86/VQ_WMat_EC_sse4_1.c173
-rw-r--r--libs/libopus/silk/x86/main_sse.h199
-rw-r--r--libs/libopus/silk/x86/x86_silk_map.c99
141 files changed, 4535 insertions, 3589 deletions
diff --git a/libs/libopus/silk/A2NLSF.c b/libs/libopus/silk/A2NLSF.c
index b6e9e5ffc..b487686ff 100644
--- a/libs/libopus/silk/A2NLSF.c
+++ b/libs/libopus/silk/A2NLSF.c
@@ -40,7 +40,7 @@ POSSIBILITY OF SUCH DAMAGE.
/* Number of binary divisions, when not in low complexity mode */
#define BIN_DIV_STEPS_A2NLSF_FIX 3 /* must be no higher than 16 - log2( LSF_COS_TAB_SZ_FIX ) */
-#define MAX_ITERATIONS_A2NLSF_FIX 30
+#define MAX_ITERATIONS_A2NLSF_FIX 16
/* Helper function for A2NLSF(..) */
/* Transforms polynomials from cos(n*f) to cos(f)^n */
@@ -130,7 +130,7 @@ void silk_A2NLSF(
const opus_int d /* I Filter order (must be even) */
)
{
- opus_int i, k, m, dd, root_ix, ffrac;
+ opus_int i, k, m, dd, root_ix, ffrac;
opus_int32 xlo, xhi, xmid;
opus_int32 ylo, yhi, ymid, thr;
opus_int32 nom, den;
@@ -239,13 +239,13 @@ void silk_A2NLSF(
/* Set NLSFs to white spectrum and exit */
NLSF[ 0 ] = (opus_int16)silk_DIV32_16( 1 << 15, d + 1 );
for( k = 1; k < d; k++ ) {
- NLSF[ k ] = (opus_int16)silk_SMULBB( k + 1, NLSF[ 0 ] );
+ NLSF[ k ] = (opus_int16)silk_ADD16( NLSF[ k-1 ], NLSF[ 0 ] );
}
return;
}
/* Error: Apply progressively more bandwidth expansion and run again */
- silk_bwexpander_32( a_Q16, d, 65536 - silk_SMULBB( 10 + i, i ) ); /* 10_Q16 = 0.00015*/
+ silk_bwexpander_32( a_Q16, d, 65536 - silk_LSHIFT( 1, i ) );
silk_A2NLSF_init( a_Q16, P, Q, dd );
p = P; /* Pointer to polynomial */
diff --git a/libs/libopus/silk/API.h b/libs/libopus/silk/API.h
index 0131acbb0..4d90ff9aa 100644
--- a/libs/libopus/silk/API.h
+++ b/libs/libopus/silk/API.h
@@ -80,7 +80,8 @@ opus_int silk_Encode( /* O Returns error co
opus_int nSamplesIn, /* I Number of samples in input vector */
ec_enc *psRangeEnc, /* I/O Compressor data structure */
opus_int32 *nBytesOut, /* I/O Number of bytes in payload (input: Max bytes) */
- const opus_int prefillFlag /* I Flag to indicate prefilling buffers no coding */
+ const opus_int prefillFlag, /* I Flag to indicate prefilling buffers no coding */
+ int activity /* I Decision of Opus voice activity detector */
);
/****************************************/
diff --git a/libs/libopus/silk/CNG.c b/libs/libopus/silk/CNG.c
index 8443ad63b..2a910099e 100644
--- a/libs/libopus/silk/CNG.c
+++ b/libs/libopus/silk/CNG.c
@@ -118,6 +118,10 @@ void silk_CNG(
/* Smooth gains */
for( i = 0; i < psDec->nb_subfr; i++ ) {
psCNG->CNG_smth_Gain_Q16 += silk_SMULWB( psDecCtrl->Gains_Q16[ i ] - psCNG->CNG_smth_Gain_Q16, CNG_GAIN_SMTH_Q16 );
+ /* If the smoothed gain is 3 dB greater than this subframe's gain, use this subframe's gain to adapt faster. */
+ if( silk_SMULWW( psCNG->CNG_smth_Gain_Q16, CNG_GAIN_SMTH_THRESHOLD_Q16 ) > psDecCtrl->Gains_Q16[ i ] ) {
+ psCNG->CNG_smth_Gain_Q16 = psDecCtrl->Gains_Q16[ i ];
+ }
}
}
@@ -138,16 +142,16 @@ void silk_CNG(
gain_Q16 = silk_LSHIFT32( silk_SQRT_APPROX( gain_Q16 ), 8 );
}
gain_Q10 = silk_RSHIFT( gain_Q16, 6 );
-
+
silk_CNG_exc( CNG_sig_Q14 + MAX_LPC_ORDER, psCNG->CNG_exc_buf_Q14, length, &psCNG->rand_seed );
/* Convert CNG NLSF to filter representation */
- silk_NLSF2A( A_Q12, psCNG->CNG_smth_NLSF_Q15, psDec->LPC_order );
+ silk_NLSF2A( A_Q12, psCNG->CNG_smth_NLSF_Q15, psDec->LPC_order, psDec->arch );
/* Generate CNG signal, by synthesis filtering */
silk_memcpy( CNG_sig_Q14, psCNG->CNG_synth_state, MAX_LPC_ORDER * sizeof( opus_int32 ) );
+ celt_assert( psDec->LPC_order == 10 || psDec->LPC_order == 16 );
for( i = 0; i < length; i++ ) {
- silk_assert( psDec->LPC_order == 10 || psDec->LPC_order == 16 );
/* Avoids introducing a bias because silk_SMLAWB() always rounds to -inf */
LPC_pred_Q10 = silk_RSHIFT( psDec->LPC_order, 1 );
LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, CNG_sig_Q14[ MAX_LPC_ORDER + i - 1 ], A_Q12[ 0 ] );
@@ -170,11 +174,11 @@ void silk_CNG(
}
/* Update states */
- CNG_sig_Q14[ MAX_LPC_ORDER + i ] = silk_ADD_LSHIFT( CNG_sig_Q14[ MAX_LPC_ORDER + i ], LPC_pred_Q10, 4 );
-
+ CNG_sig_Q14[ MAX_LPC_ORDER + i ] = silk_ADD_SAT32( CNG_sig_Q14[ MAX_LPC_ORDER + i ], silk_LSHIFT_SAT32( LPC_pred_Q10, 4 ) );
+
/* Scale with Gain and add to input signal */
frame[ i ] = (opus_int16)silk_ADD_SAT16( frame[ i ], silk_SAT16( silk_RSHIFT_ROUND( silk_SMULWW( CNG_sig_Q14[ MAX_LPC_ORDER + i ], gain_Q10 ), 8 ) ) );
-
+
}
silk_memcpy( psCNG->CNG_synth_state, &CNG_sig_Q14[ length ], MAX_LPC_ORDER * sizeof( opus_int32 ) );
} else {
diff --git a/libs/libopus/silk/LPC_analysis_filter.c b/libs/libopus/silk/LPC_analysis_filter.c
index 20906673f..d34b5eb70 100644
--- a/libs/libopus/silk/LPC_analysis_filter.c
+++ b/libs/libopus/silk/LPC_analysis_filter.c
@@ -39,6 +39,13 @@ POSSIBILITY OF SUCH DAMAGE.
/* first d output samples are set to zero */
/*******************************************/
+/* OPT: Using celt_fir() for this function should be faster, but it may cause
+ integer overflows in intermediate values (not final results), which the
+ current implementation silences by casting to unsigned. Enabling
+ this should be safe in pretty much all cases, even though it is not technically
+ C89-compliant. */
+#define USE_CELT_FIR 0
+
void silk_LPC_analysis_filter(
opus_int16 *out, /* O Output signal */
const opus_int16 *in, /* I Input signal */
@@ -49,8 +56,7 @@ void silk_LPC_analysis_filter(
)
{
opus_int j;
-#ifdef FIXED_POINT
- opus_int16 mem[SILK_MAX_ORDER_LPC];
+#if defined(FIXED_POINT) && USE_CELT_FIR
opus_int16 num[SILK_MAX_ORDER_LPC];
#else
int ix;
@@ -58,19 +64,16 @@ void silk_LPC_analysis_filter(
const opus_int16 *in_ptr;
#endif
- silk_assert( d >= 6 );
- silk_assert( (d & 1) == 0 );
- silk_assert( d <= len );
+ celt_assert( d >= 6 );
+ celt_assert( (d & 1) == 0 );
+ celt_assert( d <= len );
-#ifdef FIXED_POINT
- silk_assert( d <= SILK_MAX_ORDER_LPC );
+#if defined(FIXED_POINT) && USE_CELT_FIR
+ celt_assert( d <= SILK_MAX_ORDER_LPC );
for ( j = 0; j < d; j++ ) {
num[ j ] = -B[ j ];
}
- for (j=0;j<d;j++) {
- mem[ j ] = in[ d - j - 1 ];
- }
- celt_fir( in + d, num, out + d, len - d, d, mem, arch );
+ celt_fir( in + d, num, out + d, len - d, d, arch );
for ( j = 0; j < d; j++ ) {
out[ j ] = 0;
}
diff --git a/libs/libopus/silk/LPC_fit.c b/libs/libopus/silk/LPC_fit.c
new file mode 100644
index 000000000..c0690a1fc
--- /dev/null
+++ b/libs/libopus/silk/LPC_fit.c
@@ -0,0 +1,82 @@
+/***********************************************************************
+Copyright (c) 2013, Koen Vos. All rights reserved.
+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 "SigProc_FIX.h"
+
+/* Convert int32 coefficients to int16 coefs and make sure there's no wrap-around.
+ This logic is reused in _celt_lpc(). Any bug fixes should also be applied there. */
+void silk_LPC_fit(
+ opus_int16 *a_QOUT, /* O Output signal */
+ opus_int32 *a_QIN, /* I/O Input signal */
+ const opus_int QOUT, /* I Input Q domain */
+ const opus_int QIN, /* I Input Q domain */
+ const opus_int d /* I Filter order */
+)
+{
+ opus_int i, k, idx = 0;
+ opus_int32 maxabs, absval, chirp_Q16;
+
+ /* Limit the maximum absolute value of the prediction coefficients, so that they'll fit in int16 */
+ for( i = 0; i < 10; i++ ) {
+ /* Find maximum absolute value and its index */
+ maxabs = 0;
+ for( k = 0; k < d; k++ ) {
+ absval = silk_abs( a_QIN[k] );
+ if( absval > maxabs ) {
+ maxabs = absval;
+ idx = k;
+ }
+ }
+ maxabs = silk_RSHIFT_ROUND( maxabs, QIN - QOUT );
+
+ if( maxabs > silk_int16_MAX ) {
+ /* Reduce magnitude of prediction coefficients */
+ maxabs = silk_min( maxabs, 163838 ); /* ( silk_int32_MAX >> 14 ) + silk_int16_MAX = 163838 */
+ chirp_Q16 = SILK_FIX_CONST( 0.999, 16 ) - silk_DIV32( silk_LSHIFT( maxabs - silk_int16_MAX, 14 ),
+ silk_RSHIFT32( silk_MUL( maxabs, idx + 1), 2 ) );
+ silk_bwexpander_32( a_QIN, d, chirp_Q16 );
+ } else {
+ break;
+ }
+ }
+
+ if( i == 10 ) {
+ /* Reached the last iteration, clip the coefficients */
+ for( k = 0; k < d; k++ ) {
+ a_QOUT[ k ] = (opus_int16)silk_SAT16( silk_RSHIFT_ROUND( a_QIN[ k ], QIN - QOUT ) );
+ a_QIN[ k ] = silk_LSHIFT( (opus_int32)a_QOUT[ k ], QIN - QOUT );
+ }
+ } else {
+ for( k = 0; k < d; k++ ) {
+ a_QOUT[ k ] = (opus_int16)silk_RSHIFT_ROUND( a_QIN[ k ], QIN - QOUT );
+ }
+ }
+}
diff --git a/libs/libopus/silk/LPC_inv_pred_gain.c b/libs/libopus/silk/LPC_inv_pred_gain.c
index 4af89aa5f..a3746a6ef 100644
--- a/libs/libopus/silk/LPC_inv_pred_gain.c
+++ b/libs/libopus/silk/LPC_inv_pred_gain.c
@@ -30,6 +30,7 @@ POSSIBILITY OF SUCH DAMAGE.
#endif
#include "SigProc_FIX.h"
+#include "define.h"
#define QA 24
#define A_LIMIT SILK_FIX_CONST( 0.99975, QA )
@@ -38,117 +39,103 @@ POSSIBILITY OF SUCH DAMAGE.
/* Compute inverse of LPC prediction gain, and */
/* test if LPC coefficients are stable (all poles within unit circle) */
-static opus_int32 LPC_inverse_pred_gain_QA( /* O Returns inverse prediction gain in energy domain, Q30 */
- opus_int32 A_QA[ 2 ][ SILK_MAX_ORDER_LPC ], /* I Prediction coefficients */
+static opus_int32 LPC_inverse_pred_gain_QA_c( /* O Returns inverse prediction gain in energy domain, Q30 */
+ opus_int32 A_QA[ SILK_MAX_ORDER_LPC ], /* I Prediction coefficients */
const opus_int order /* I Prediction order */
)
{
opus_int k, n, mult2Q;
- opus_int32 invGain_Q30, rc_Q31, rc_mult1_Q30, rc_mult2, tmp_QA;
- opus_int32 *Aold_QA, *Anew_QA;
+ opus_int32 invGain_Q30, rc_Q31, rc_mult1_Q30, rc_mult2, tmp1, tmp2;
- Anew_QA = A_QA[ order & 1 ];
-
- invGain_Q30 = (opus_int32)1 << 30;
+ invGain_Q30 = SILK_FIX_CONST( 1, 30 );
for( k = order - 1; k > 0; k-- ) {
/* Check for stability */
- if( ( Anew_QA[ k ] > A_LIMIT ) || ( Anew_QA[ k ] < -A_LIMIT ) ) {
+ if( ( A_QA[ k ] > A_LIMIT ) || ( A_QA[ k ] < -A_LIMIT ) ) {
return 0;
}
/* Set RC equal to negated AR coef */
- rc_Q31 = -silk_LSHIFT( Anew_QA[ k ], 31 - QA );
+ rc_Q31 = -silk_LSHIFT( A_QA[ k ], 31 - QA );
/* rc_mult1_Q30 range: [ 1 : 2^30 ] */
- rc_mult1_Q30 = ( (opus_int32)1 << 30 ) - silk_SMMUL( rc_Q31, rc_Q31 );
+ rc_mult1_Q30 = silk_SUB32( SILK_FIX_CONST( 1, 30 ), silk_SMMUL( rc_Q31, rc_Q31 ) );
silk_assert( rc_mult1_Q30 > ( 1 << 15 ) ); /* reduce A_LIMIT if fails */
silk_assert( rc_mult1_Q30 <= ( 1 << 30 ) );
- /* rc_mult2 range: [ 2^30 : silk_int32_MAX ] */
- mult2Q = 32 - silk_CLZ32( silk_abs( rc_mult1_Q30 ) );
- rc_mult2 = silk_INVERSE32_varQ( rc_mult1_Q30, mult2Q + 30 );
-
/* Update inverse gain */
/* invGain_Q30 range: [ 0 : 2^30 ] */
invGain_Q30 = silk_LSHIFT( silk_SMMUL( invGain_Q30, rc_mult1_Q30 ), 2 );
silk_assert( invGain_Q30 >= 0 );
silk_assert( invGain_Q30 <= ( 1 << 30 ) );
+ if( invGain_Q30 < SILK_FIX_CONST( 1.0f / MAX_PREDICTION_POWER_GAIN, 30 ) ) {
+ return 0;
+ }
- /* Swap pointers */
- Aold_QA = Anew_QA;
- Anew_QA = A_QA[ k & 1 ];
+ /* rc_mult2 range: [ 2^30 : silk_int32_MAX ] */
+ mult2Q = 32 - silk_CLZ32( silk_abs( rc_mult1_Q30 ) );
+ rc_mult2 = silk_INVERSE32_varQ( rc_mult1_Q30, mult2Q + 30 );
/* Update AR coefficient */
- for( n = 0; n < k; n++ ) {
- tmp_QA = Aold_QA[ n ] - MUL32_FRAC_Q( Aold_QA[ k - n - 1 ], rc_Q31, 31 );
- Anew_QA[ n ] = MUL32_FRAC_Q( tmp_QA, rc_mult2 , mult2Q );
+ for( n = 0; n < (k + 1) >> 1; n++ ) {
+ opus_int64 tmp64;
+ tmp1 = A_QA[ n ];
+ tmp2 = A_QA[ k - n - 1 ];
+ tmp64 = silk_RSHIFT_ROUND64( silk_SMULL( silk_SUB_SAT32(tmp1,
+ MUL32_FRAC_Q( tmp2, rc_Q31, 31 ) ), rc_mult2 ), mult2Q);
+ if( tmp64 > silk_int32_MAX || tmp64 < silk_int32_MIN ) {
+ return 0;
+ }
+ A_QA[ n ] = ( opus_int32 )tmp64;
+ tmp64 = silk_RSHIFT_ROUND64( silk_SMULL( silk_SUB_SAT32(tmp2,
+ MUL32_FRAC_Q( tmp1, rc_Q31, 31 ) ), rc_mult2), mult2Q);
+ if( tmp64 > silk_int32_MAX || tmp64 < silk_int32_MIN ) {
+ return 0;
+ }
+ A_QA[ k - n - 1 ] = ( opus_int32 )tmp64;
}
}
/* Check for stability */
- if( ( Anew_QA[ 0 ] > A_LIMIT ) || ( Anew_QA[ 0 ] < -A_LIMIT ) ) {
+ if( ( A_QA[ k ] > A_LIMIT ) || ( A_QA[ k ] < -A_LIMIT ) ) {
return 0;
}
/* Set RC equal to negated AR coef */
- rc_Q31 = -silk_LSHIFT( Anew_QA[ 0 ], 31 - QA );
+ rc_Q31 = -silk_LSHIFT( A_QA[ 0 ], 31 - QA );
/* Range: [ 1 : 2^30 ] */
- rc_mult1_Q30 = ( (opus_int32)1 << 30 ) - silk_SMMUL( rc_Q31, rc_Q31 );
+ rc_mult1_Q30 = silk_SUB32( SILK_FIX_CONST( 1, 30 ), silk_SMMUL( rc_Q31, rc_Q31 ) );
/* Update inverse gain */
/* Range: [ 0 : 2^30 ] */
invGain_Q30 = silk_LSHIFT( silk_SMMUL( invGain_Q30, rc_mult1_Q30 ), 2 );
- silk_assert( invGain_Q30 >= 0 );
- silk_assert( invGain_Q30 <= 1<<30 );
+ silk_assert( invGain_Q30 >= 0 );
+ silk_assert( invGain_Q30 <= ( 1 << 30 ) );
+ if( invGain_Q30 < SILK_FIX_CONST( 1.0f / MAX_PREDICTION_POWER_GAIN, 30 ) ) {
+ return 0;
+ }
return invGain_Q30;
}
/* For input in Q12 domain */
-opus_int32 silk_LPC_inverse_pred_gain( /* O Returns inverse prediction gain in energy domain, Q30 */
+opus_int32 silk_LPC_inverse_pred_gain_c( /* O Returns inverse prediction gain in energy domain, Q30 */
const opus_int16 *A_Q12, /* I Prediction coefficients, Q12 [order] */
const opus_int order /* I Prediction order */
)
{
opus_int k;
- opus_int32 Atmp_QA[ 2 ][ SILK_MAX_ORDER_LPC ];
- opus_int32 *Anew_QA;
+ opus_int32 Atmp_QA[ SILK_MAX_ORDER_LPC ];
opus_int32 DC_resp = 0;
- Anew_QA = Atmp_QA[ order & 1 ];
-
/* Increase Q domain of the AR coefficients */
for( k = 0; k < order; k++ ) {
DC_resp += (opus_int32)A_Q12[ k ];
- Anew_QA[ k ] = silk_LSHIFT32( (opus_int32)A_Q12[ k ], QA - 12 );
+ Atmp_QA[ k ] = silk_LSHIFT32( (opus_int32)A_Q12[ k ], QA - 12 );
}
/* If the DC is unstable, we don't even need to do the full calculations */
if( DC_resp >= 4096 ) {
return 0;
}
- return LPC_inverse_pred_gain_QA( Atmp_QA, order );
+ return LPC_inverse_pred_gain_QA_c( Atmp_QA, order );
}
-
-#ifdef FIXED_POINT
-
-/* For input in Q24 domain */
-opus_int32 silk_LPC_inverse_pred_gain_Q24( /* O Returns inverse prediction gain in energy domain, Q30 */
- const opus_int32 *A_Q24, /* I Prediction coefficients [order] */
- const opus_int order /* I Prediction order */
-)
-{
- opus_int k;
- opus_int32 Atmp_QA[ 2 ][ SILK_MAX_ORDER_LPC ];
- opus_int32 *Anew_QA;
-
- Anew_QA = Atmp_QA[ order & 1 ];
-
- /* Increase Q domain of the AR coefficients */
- for( k = 0; k < order; k++ ) {
- Anew_QA[ k ] = silk_RSHIFT32( A_Q24[ k ], 24 - QA );
- }
-
- return LPC_inverse_pred_gain_QA( Atmp_QA, order );
-}
-#endif
diff --git a/libs/libopus/silk/LP_variable_cutoff.c b/libs/libopus/silk/LP_variable_cutoff.c
index f639e1f89..79112ad35 100644
--- a/libs/libopus/silk/LP_variable_cutoff.c
+++ b/libs/libopus/silk/LP_variable_cutoff.c
@@ -130,6 +130,6 @@ void silk_LP_variable_cutoff(
/* ARMA low-pass filtering */
silk_assert( TRANSITION_NB == 3 && TRANSITION_NA == 2 );
- silk_biquad_alt( frame, B_Q28, A_Q28, psLP->In_LP_State, frame, frame_length, 1);
+ silk_biquad_alt_stride1( frame, B_Q28, A_Q28, psLP->In_LP_State, frame, frame_length);
}
}
diff --git a/libs/libopus/silk/MacroCount.h b/libs/libopus/silk/MacroCount.h
index 834817d05..dab2f57a6 100644
--- a/libs/libopus/silk/MacroCount.h
+++ b/libs/libopus/silk/MacroCount.h
@@ -27,9 +27,9 @@ POSSIBILITY OF SUCH DAMAGE.
#ifndef SIGPROCFIX_API_MACROCOUNT_H
#define SIGPROCFIX_API_MACROCOUNT_H
-#include <stdio.h>
#ifdef silk_MACRO_COUNT
+#include <stdio.h>
#define varDefine opus_int64 ops_count = 0;
extern opus_int64 ops_count;
@@ -319,14 +319,6 @@ static OPUS_INLINE opus_int32 silk_ADD_POS_SAT32(opus_int64 a, opus_int64 b){
return(tmp);
}
-#undef silk_ADD_POS_SAT64
-static OPUS_INLINE opus_int64 silk_ADD_POS_SAT64(opus_int64 a, opus_int64 b){
- opus_int64 tmp;
- ops_count += 1;
- tmp = ((((a)+(b)) & 0x8000000000000000LL) ? silk_int64_MAX : ((a)+(b)));
- return(tmp);
-}
-
#undef silk_LSHIFT8
static OPUS_INLINE opus_int8 silk_LSHIFT8(opus_int8 a, opus_int32 shift){
opus_int8 ret;
@@ -699,7 +691,7 @@ return(ret);
#undef silk_LIMIT_32
-static OPUS_INLINE opus_int silk_LIMIT_32(opus_int32 a, opus_int32 limit1, opus_int32 limit2)
+static OPUS_INLINE opus_int32 silk_LIMIT_32(opus_int32 a, opus_int32 limit1, opus_int32 limit2)
{
opus_int32 ret;
ops_count += 6;
diff --git a/libs/libopus/silk/MacroDebug.h b/libs/libopus/silk/MacroDebug.h
index 35aedc5c5..8dd4ce2ee 100644
--- a/libs/libopus/silk/MacroDebug.h
+++ b/libs/libopus/silk/MacroDebug.h
@@ -539,8 +539,7 @@ static OPUS_INLINE opus_int32 silk_DIV32_16_(opus_int32 a32, opus_int32 b32, cha
no checking needed for silk_POS_SAT32
no checking needed for silk_ADD_POS_SAT8
no checking needed for silk_ADD_POS_SAT16
- no checking needed for silk_ADD_POS_SAT32
- no checking needed for silk_ADD_POS_SAT64 */
+ no checking needed for silk_ADD_POS_SAT32 */
#undef silk_LSHIFT8
#define silk_LSHIFT8(a,b) silk_LSHIFT8_((a), (b), __FILE__, __LINE__)
diff --git a/libs/libopus/silk/NLSF2A.c b/libs/libopus/silk/NLSF2A.c
index b1c559ea6..d5b773063 100644
--- a/libs/libopus/silk/NLSF2A.c
+++ b/libs/libopus/silk/NLSF2A.c
@@ -66,7 +66,8 @@ static OPUS_INLINE void silk_NLSF2A_find_poly(
void silk_NLSF2A(
opus_int16 *a_Q12, /* O monic whitening filter coefficients in Q12, [ d ] */
const opus_int16 *NLSF, /* I normalized line spectral frequencies in Q15, [ d ] */
- const opus_int d /* I filter order (should be even) */
+ const opus_int d, /* I filter order (should be even) */
+ int arch /* I Run-time architecture */
)
{
/* This ordering was found to maximize quality. It improves numerical accuracy of
@@ -83,15 +84,14 @@ void silk_NLSF2A(
opus_int32 P[ SILK_MAX_ORDER_LPC / 2 + 1 ], Q[ SILK_MAX_ORDER_LPC / 2 + 1 ];
opus_int32 Ptmp, Qtmp, f_int, f_frac, cos_val, delta;
opus_int32 a32_QA1[ SILK_MAX_ORDER_LPC ];
- opus_int32 maxabs, absval, idx=0, sc_Q16;
silk_assert( LSF_COS_TAB_SZ_FIX == 128 );
- silk_assert( d==10||d==16 );
+ celt_assert( d==10 || d==16 );
/* convert LSFs to 2*cos(LSF), using piecewise linear curve from table */
ordering = d == 16 ? ordering16 : ordering10;
for( k = 0; k < d; k++ ) {
- silk_assert(NLSF[k] >= 0 );
+ silk_assert( NLSF[k] >= 0 );
/* f_int on a scale 0-127 (rounded down) */
f_int = silk_RSHIFT( NLSF[k], 15 - 7 );
@@ -126,52 +126,15 @@ void silk_NLSF2A(
a32_QA1[ d-k-1 ] = Qtmp - Ptmp; /* QA+1 */
}
- /* Limit the maximum absolute value of the prediction coefficients, so that they'll fit in int16 */
- for( i = 0; i < 10; i++ ) {
- /* Find maximum absolute value and its index */
- maxabs = 0;
- for( k = 0; k < d; k++ ) {
- absval = silk_abs( a32_QA1[k] );
- if( absval > maxabs ) {
- maxabs = absval;
- idx = k;
- }
- }
- maxabs = silk_RSHIFT_ROUND( maxabs, QA + 1 - 12 ); /* QA+1 -> Q12 */
-
- if( maxabs > silk_int16_MAX ) {
- /* Reduce magnitude of prediction coefficients */
- maxabs = silk_min( maxabs, 163838 ); /* ( silk_int32_MAX >> 14 ) + silk_int16_MAX = 163838 */
- sc_Q16 = SILK_FIX_CONST( 0.999, 16 ) - silk_DIV32( silk_LSHIFT( maxabs - silk_int16_MAX, 14 ),
- silk_RSHIFT32( silk_MUL( maxabs, idx + 1), 2 ) );
- silk_bwexpander_32( a32_QA1, d, sc_Q16 );
- } else {
- break;
- }
- }
+ /* Convert int32 coefficients to Q12 int16 coefs */
+ silk_LPC_fit( a_Q12, a32_QA1, 12, QA + 1, d );
- if( i == 10 ) {
- /* Reached the last iteration, clip the coefficients */
+ for( i = 0; silk_LPC_inverse_pred_gain( a_Q12, d, arch ) == 0 && i < MAX_LPC_STABILIZE_ITERATIONS; i++ ) {
+ /* Prediction coefficients are (too close to) unstable; apply bandwidth expansion */
+ /* on the unscaled coefficients, convert to Q12 and measure again */
+ silk_bwexpander_32( a32_QA1, d, 65536 - silk_LSHIFT( 2, i ) );
for( k = 0; k < d; k++ ) {
- a_Q12[ k ] = (opus_int16)silk_SAT16( silk_RSHIFT_ROUND( a32_QA1[ k ], QA + 1 - 12 ) ); /* QA+1 -> Q12 */
- a32_QA1[ k ] = silk_LSHIFT( (opus_int32)a_Q12[ k ], QA + 1 - 12 );
- }
- } else {
- for( k = 0; k < d; k++ ) {
- a_Q12[ k ] = (opus_int16)silk_RSHIFT_ROUND( a32_QA1[ k ], QA + 1 - 12 ); /* QA+1 -> Q12 */
- }
- }
-
- for( i = 0; i < MAX_LPC_STABILIZE_ITERATIONS; i++ ) {
- if( silk_LPC_inverse_pred_gain( a_Q12, d ) < SILK_FIX_CONST( 1.0 / MAX_PREDICTION_POWER_GAIN, 30 ) ) {
- /* Prediction coefficients are (too close to) unstable; apply bandwidth expansion */
- /* on the unscaled coefficients, convert to Q12 and measure again */
- silk_bwexpander_32( a32_QA1, d, 65536 - silk_LSHIFT( 2, i ) );
- for( k = 0; k < d; k++ ) {
- a_Q12[ k ] = (opus_int16)silk_RSHIFT_ROUND( a32_QA1[ k ], QA + 1 - 12 ); /* QA+1 -> Q12 */
- }
- } else {
- break;
+ a_Q12[ k ] = (opus_int16)silk_RSHIFT_ROUND( a32_QA1[ k ], QA + 1 - 12 ); /* QA+1 -> Q12 */
}
}
}
diff --git a/libs/libopus/silk/NLSF_VQ.c b/libs/libopus/silk/NLSF_VQ.c
index 69b6e22e1..b83182a79 100644
--- a/libs/libopus/silk/NLSF_VQ.c
+++ b/libs/libopus/silk/NLSF_VQ.c
@@ -33,36 +33,44 @@ POSSIBILITY OF SUCH DAMAGE.
/* Compute quantization errors for an LPC_order element input vector for a VQ codebook */
void silk_NLSF_VQ(
- opus_int32 err_Q26[], /* O Quantization errors [K] */
+ opus_int32 err_Q24[], /* O Quantization errors [K] */
const opus_int16 in_Q15[], /* I Input vectors to be quantized [LPC_order] */
const opus_uint8 pCB_Q8[], /* I Codebook vectors [K*LPC_order] */
+ const opus_int16 pWght_Q9[], /* I Codebook weights [K*LPC_order] */
const opus_int K, /* I Number of codebook vectors */
const opus_int LPC_order /* I Number of LPCs */
)
{
- opus_int i, m;
- opus_int32 diff_Q15, sum_error_Q30, sum_error_Q26;
+ opus_int i, m;
+ opus_int32 diff_Q15, diffw_Q24, sum_error_Q24, pred_Q24;
+ const opus_int16 *w_Q9_ptr;
+ const opus_uint8 *cb_Q8_ptr;
- silk_assert( LPC_order <= 16 );
- silk_assert( ( LPC_order & 1 ) == 0 );
+ celt_assert( ( LPC_order & 1 ) == 0 );
/* Loop over codebook */
+ cb_Q8_ptr = pCB_Q8;
+ w_Q9_ptr = pWght_Q9;
for( i = 0; i < K; i++ ) {
- sum_error_Q26 = 0;
- for( m = 0; m < LPC_order; m += 2 ) {
- /* Compute weighted squared quantization error for index m */
- diff_Q15 = silk_SUB_LSHIFT32( in_Q15[ m ], (opus_int32)*pCB_Q8++, 7 ); /* range: [ -32767 : 32767 ]*/
- sum_error_Q30 = silk_SMULBB( diff_Q15, diff_Q15 );
+ sum_error_Q24 = 0;
+ pred_Q24 = 0;
+ for( m = LPC_order-2; m >= 0; m -= 2 ) {
+ /* Compute weighted absolute predictive quantization error for index m + 1 */
+ diff_Q15 = silk_SUB_LSHIFT32( in_Q15[ m + 1 ], (opus_int32)cb_Q8_ptr[ m + 1 ], 7 ); /* range: [ -32767 : 32767 ]*/
+ diffw_Q24 = silk_SMULBB( diff_Q15, w_Q9_ptr[ m + 1 ] );
+ sum_error_Q24 = silk_ADD32( sum_error_Q24, silk_abs( silk_SUB_RSHIFT32( diffw_Q24, pred_Q24, 1 ) ) );
+ pred_Q24 = diffw_Q24;
- /* Compute weighted squared quantization error for index m + 1 */
- diff_Q15 = silk_SUB_LSHIFT32( in_Q15[m + 1], (opus_int32)*pCB_Q8++, 7 ); /* range: [ -32767 : 32767 ]*/
- sum_error_Q30 = silk_SMLABB( sum_error_Q30, diff_Q15, diff_Q15 );
+ /* Compute weighted absolute predictive quantization error for index m */
+ diff_Q15 = silk_SUB_LSHIFT32( in_Q15[ m ], (opus_int32)cb_Q8_ptr[ m ], 7 ); /* range: [ -32767 : 32767 ]*/
+ diffw_Q24 = silk_SMULBB( diff_Q15, w_Q9_ptr[ m ] );
+ sum_error_Q24 = silk_ADD32( sum_error_Q24, silk_abs( silk_SUB_RSHIFT32( diffw_Q24, pred_Q24, 1 ) ) );
+ pred_Q24 = diffw_Q24;
- sum_error_Q26 = silk_ADD_RSHIFT32( sum_error_Q26, sum_error_Q30, 4 );
-
- silk_assert( sum_error_Q26 >= 0 );
- silk_assert( sum_error_Q30 >= 0 );
+ silk_assert( sum_error_Q24 >= 0 );
}
- err_Q26[ i ] = sum_error_Q26;
+ err_Q24[ i ] = sum_error_Q24;
+ cb_Q8_ptr += LPC_order;
+ w_Q9_ptr += LPC_order;
}
}
diff --git a/libs/libopus/silk/NLSF_VQ_weights_laroia.c b/libs/libopus/silk/NLSF_VQ_weights_laroia.c
index 04894c59a..9873bcde1 100644
--- a/libs/libopus/silk/NLSF_VQ_weights_laroia.c
+++ b/libs/libopus/silk/NLSF_VQ_weights_laroia.c
@@ -48,8 +48,8 @@ void silk_NLSF_VQ_weights_laroia(
opus_int k;
opus_int32 tmp1_int, tmp2_int;
- silk_assert( D > 0 );
- silk_assert( ( D & 1 ) == 0 );
+ celt_assert( D > 0 );
+ celt_assert( ( D & 1 ) == 0 );
/* First value */
tmp1_int = silk_max_int( pNLSF_Q15[ 0 ], 1 );
diff --git a/libs/libopus/silk/NLSF_decode.c b/libs/libopus/silk/NLSF_decode.c
index 9f715060b..eeb0ba8c9 100644
--- a/libs/libopus/silk/NLSF_decode.c
+++ b/libs/libopus/silk/NLSF_decode.c
@@ -32,7 +32,7 @@ POSSIBILITY OF SUCH DAMAGE.
#include "main.h"
/* Predictive dequantizer for NLSF residuals */
-static OPUS_INLINE void silk_NLSF_residual_dequant( /* O Returns RD value in Q30 */
+static OPUS_INLINE void silk_NLSF_residual_dequant( /* O Returns RD value in Q30 */
opus_int16 x_Q10[], /* O Output [ order ] */
const opus_int8 indices[], /* I Quantization indices [ order ] */
const opus_uint8 pred_coef_Q8[], /* I Backward predictor coefs [ order ] */
@@ -70,15 +70,9 @@ void silk_NLSF_decode(
opus_uint8 pred_Q8[ MAX_LPC_ORDER ];
opus_int16 ec_ix[ MAX_LPC_ORDER ];
opus_int16 res_Q10[ MAX_LPC_ORDER ];
- opus_int16 W_tmp_QW[ MAX_LPC_ORDER ];
- opus_int32 W_tmp_Q9, NLSF_Q15_tmp;
+ opus_int32 NLSF_Q15_tmp;
const opus_uint8 *pCB_element;
-
- /* Decode first stage */
- pCB_element = &psNLSF_CB->CB1_NLSF_Q8[ NLSFIndices[ 0 ] * psNLSF_CB->order ];
- for( i = 0; i < psNLSF_CB->order; i++ ) {
- pNLSF_Q15[ i ] = silk_LSHIFT( (opus_int16)pCB_element[ i ], 7 );
- }
+ const opus_int16 *pCB_Wght_Q9;
/* Unpack entropy table indices and predictor for current CB1 index */
silk_NLSF_unpack( ec_ix, pred_Q8, psNLSF_CB, NLSFIndices[ 0 ] );
@@ -86,13 +80,11 @@ void silk_NLSF_decode(
/* Predictive residual dequantizer */
silk_NLSF_residual_dequant( res_Q10, &NLSFIndices[ 1 ], pred_Q8, psNLSF_CB->quantStepSize_Q16, psNLSF_CB->order );
- /* Weights from codebook vector */
- silk_NLSF_VQ_weights_laroia( W_tmp_QW, pNLSF_Q15, psNLSF_CB->order );
-
- /* Apply inverse square-rooted weights and add to output */
+ /* Apply inverse square-rooted weights to first stage and add to output */
+ pCB_element = &psNLSF_CB->CB1_NLSF_Q8[ NLSFIndices[ 0 ] * psNLSF_CB->order ];
+ pCB_Wght_Q9 = &psNLSF_CB->CB1_Wght_Q9[ NLSFIndices[ 0 ] * psNLSF_CB->order ];
for( i = 0; i < psNLSF_CB->order; i++ ) {
- W_tmp_Q9 = silk_SQRT_APPROX( silk_LSHIFT( (opus_int32)W_tmp_QW[ i ], 18 - NLSF_W_Q ) );
- NLSF_Q15_tmp = silk_ADD32( pNLSF_Q15[ i ], silk_DIV32_16( silk_LSHIFT( (opus_int32)res_Q10[ i ], 14 ), W_tmp_Q9 ) );
+ NLSF_Q15_tmp = silk_ADD_LSHIFT32( silk_DIV32_16( silk_LSHIFT( (opus_int32)res_Q10[ i ], 14 ), pCB_Wght_Q9[ i ] ), (opus_int16)pCB_element[ i ], 7 );
pNLSF_Q15[ i ] = (opus_int16)silk_LIMIT( NLSF_Q15_tmp, 0, 32767 );
}
diff --git a/libs/libopus/silk/NLSF_del_dec_quant.c b/libs/libopus/silk/NLSF_del_dec_quant.c
index de88fee06..44a16acd0 100644
--- a/libs/libopus/silk/NLSF_del_dec_quant.c
+++ b/libs/libopus/silk/NLSF_del_dec_quant.c
@@ -84,7 +84,7 @@ opus_int32 silk_NLSF_del_dec_quant( /* O Returns
nStates = 1;
RD_Q25[ 0 ] = 0;
prev_out_Q10[ 0 ] = 0;
- for( i = order - 1; ; i-- ) {
+ for( i = order - 1; i >= 0; i-- ) {
rates_Q5 = &ec_rates_Q5[ ec_ix[ i ] ];
in_Q10 = x_Q10[ i ];
for( j = 0; j < nStates; j++ ) {
@@ -131,7 +131,7 @@ opus_int32 silk_NLSF_del_dec_quant( /* O Returns
RD_Q25[ j + nStates ] = silk_SMLABB( silk_MLA( RD_tmp_Q25, silk_SMULBB( diff_Q10, diff_Q10 ), w_Q5[ i ] ), mu_Q20, rate1_Q5 );
}
- if( nStates <= ( NLSF_QUANT_DEL_DEC_STATES >> 1 ) ) {
+ if( nStates <= NLSF_QUANT_DEL_DEC_STATES/2 ) {
/* double number of states and copy */
for( j = 0; j < nStates; j++ ) {
ind[ j + nStates ][ i ] = ind[ j ][ i ] + 1;
@@ -140,7 +140,7 @@ opus_int32 silk_NLSF_del_dec_quant( /* O Returns
for( j = nStates; j < NLSF_QUANT_DEL_DEC_STATES; j++ ) {
ind[ j ][ i ] = ind[ j - nStates ][ i ];
}
- } else if( i > 0 ) {
+ } else {
/* sort lower and upper half of RD_Q25, pairwise */
for( j = 0; j < NLSF_QUANT_DEL_DEC_STATES; j++ ) {
if( RD_Q25[ j ] > RD_Q25[ j + NLSF_QUANT_DEL_DEC_STATES ] ) {
@@ -191,8 +191,6 @@ opus_int32 silk_NLSF_del_dec_quant( /* O Returns
for( j = 0; j < NLSF_QUANT_DEL_DEC_STATES; j++ ) {
ind[ j ][ i ] += silk_RSHIFT( ind_sort[ j ], NLSF_QUANT_DEL_DEC_STATES_LOG2 );
}
- } else { /* i == 0 */
- break;
}
}
diff --git a/libs/libopus/silk/NLSF_encode.c b/libs/libopus/silk/NLSF_encode.c
index f03c3f1c3..01ac7db78 100644
--- a/libs/libopus/silk/NLSF_encode.c
+++ b/libs/libopus/silk/NLSF_encode.c
@@ -37,9 +37,9 @@ POSSIBILITY OF SUCH DAMAGE.
/***********************/
opus_int32 silk_NLSF_encode( /* O Returns RD value in Q25 */
opus_int8 *NLSFIndices, /* I Codebook path vector [ LPC_ORDER + 1 ] */
- opus_int16 *pNLSF_Q15, /* I/O Quantized NLSF vector [ LPC_ORDER ] */
+ opus_int16 *pNLSF_Q15, /* I/O (Un)quantized NLSF vector [ LPC_ORDER ] */
const silk_NLSF_CB_struct *psNLSF_CB, /* I Codebook object */
- const opus_int16 *pW_QW, /* I NLSF weight vector [ LPC_ORDER ] */
+ const opus_int16 *pW_Q2, /* I NLSF weight vector [ LPC_ORDER ] */
const opus_int NLSF_mu_Q20, /* I Rate weight for the RD optimization */
const opus_int nSurvivors, /* I Max survivors after first stage */
const opus_int signalType /* I Signal type: 0/1/2 */
@@ -47,34 +47,32 @@ opus_int32 silk_NLSF_encode( /* O Returns
{
opus_int i, s, ind1, bestIndex, prob_Q8, bits_q7;
opus_int32 W_tmp_Q9, ret;
- VARDECL( opus_int32, err_Q26 );
+ VARDECL( opus_int32, err_Q24 );
VARDECL( opus_int32, RD_Q25 );
VARDECL( opus_int, tempIndices1 );
VARDECL( opus_int8, tempIndices2 );
- opus_int16 res_Q15[ MAX_LPC_ORDER ];
opus_int16 res_Q10[ MAX_LPC_ORDER ];
opus_int16 NLSF_tmp_Q15[ MAX_LPC_ORDER ];
- opus_int16 W_tmp_QW[ MAX_LPC_ORDER ];
opus_int16 W_adj_Q5[ MAX_LPC_ORDER ];
opus_uint8 pred_Q8[ MAX_LPC_ORDER ];
opus_int16 ec_ix[ MAX_LPC_ORDER ];
const opus_uint8 *pCB_element, *iCDF_ptr;
+ const opus_int16 *pCB_Wght_Q9;
SAVE_STACK;
- silk_assert( nSurvivors <= NLSF_VQ_MAX_SURVIVORS );
- silk_assert( signalType >= 0 && signalType <= 2 );
+ celt_assert( signalType >= 0 && signalType <= 2 );
silk_assert( NLSF_mu_Q20 <= 32767 && NLSF_mu_Q20 >= 0 );
/* NLSF stabilization */
silk_NLSF_stabilize( pNLSF_Q15, psNLSF_CB->deltaMin_Q15, psNLSF_CB->order );
/* First stage: VQ */
- ALLOC( err_Q26, psNLSF_CB->nVectors, opus_int32 );
- silk_NLSF_VQ( err_Q26, pNLSF_Q15, psNLSF_CB->CB1_NLSF_Q8, psNLSF_CB->nVectors, psNLSF_CB->order );
+ ALLOC( err_Q24, psNLSF_CB->nVectors, opus_int32 );
+ silk_NLSF_VQ( err_Q24, pNLSF_Q15, psNLSF_CB->CB1_NLSF_Q8, psNLSF_CB->CB1_Wght_Q9, psNLSF_CB->nVectors, psNLSF_CB->order );
/* Sort the quantization errors */
ALLOC( tempIndices1, nSurvivors, opus_int );
- silk_insertion_sort_increasing( err_Q26, tempIndices1, psNLSF_CB->nVectors, nSurvivors );
+ silk_insertion_sort_increasing( err_Q24, tempIndices1, psNLSF_CB->nVectors, nSurvivors );
ALLOC( RD_Q25, nSurvivors, opus_int32 );
ALLOC( tempIndices2, nSurvivors * MAX_LPC_ORDER, opus_int8 );
@@ -85,23 +83,12 @@ opus_int32 silk_NLSF_encode( /* O Returns
/* Residual after first stage */
pCB_element = &psNLSF_CB->CB1_NLSF_Q8[ ind1 * psNLSF_CB->order ];
+ pCB_Wght_Q9 = &psNLSF_CB->CB1_Wght_Q9[ ind1 * psNLSF_CB->order ];
for( i = 0; i < psNLSF_CB->order; i++ ) {
NLSF_tmp_Q15[ i ] = silk_LSHIFT16( (opus_int16)pCB_element[ i ], 7 );
- res_Q15[ i ] = pNLSF_Q15[ i ] - NLSF_tmp_Q15[ i ];
- }
-
- /* Weights from codebook vector */
- silk_NLSF_VQ_weights_laroia( W_tmp_QW, NLSF_tmp_Q15, psNLSF_CB->order );
-
- /* Apply square-rooted weights */
- for( i = 0; i < psNLSF_CB->order; i++ ) {
- W_tmp_Q9 = silk_SQRT_APPROX( silk_LSHIFT( (opus_int32)W_tmp_QW[ i ], 18 - NLSF_W_Q ) );
- res_Q10[ i ] = (opus_int16)silk_RSHIFT( silk_SMULBB( res_Q15[ i ], W_tmp_Q9 ), 14 );
- }
-
- /* Modify input weights accordingly */
- for( i = 0; i < psNLSF_CB->order; i++ ) {
- W_adj_Q5[ i ] = silk_DIV32_16( silk_LSHIFT( (opus_int32)pW_QW[ i ], 5 ), W_tmp_QW[ i ] );
+ W_tmp_Q9 = pCB_Wght_Q9[ i ];
+ res_Q10[ i ] = (opus_int16)silk_RSHIFT( silk_SMULBB( pNLSF_Q15[ i ] - NLSF_tmp_Q15[ i ], W_tmp_Q9 ), 14 );
+ W_adj_Q5[ i ] = silk_DIV32_varQ( (opus_int32)pW_Q2[ i ], silk_SMULBB( W_tmp_Q9, W_tmp_Q9 ), 21 );
}
/* Unpack entropy table indices and predictor for current CB1 index */
diff --git a/libs/libopus/silk/NSQ.c b/libs/libopus/silk/NSQ.c
index 43e3fee7e..45dd45ce8 100644
--- a/libs/libopus/silk/NSQ.c
+++ b/libs/libopus/silk/NSQ.c
@@ -37,7 +37,7 @@ POSSIBILITY OF SUCH DAMAGE.
static OPUS_INLINE void silk_nsq_scale_states(
const silk_encoder_state *psEncC, /* I Encoder State */
silk_nsq_state *NSQ, /* I/O NSQ state */
- const opus_int32 x_Q3[], /* I input in Q3 */
+ const opus_int16 x16[], /* I input */
opus_int32 x_sc_Q10[], /* O input scaled with 1/Gain */
const opus_int16 sLTP[], /* I re-whitened LTP state in Q0 */
opus_int32 sLTP_Q15[], /* O LTP state matching scaled input */
@@ -75,21 +75,21 @@ static OPUS_INLINE void silk_noise_shape_quantizer(
void silk_NSQ_c
(
- const silk_encoder_state *psEncC, /* I/O Encoder State */
- silk_nsq_state *NSQ, /* I/O NSQ state */
- SideInfoIndices *psIndices, /* I/O Quantization Indices */
- const opus_int32 x_Q3[], /* I Prefiltered input signal */
- opus_int8 pulses[], /* O Quantized pulse signal */
- const opus_int16 PredCoef_Q12[ 2 * MAX_LPC_ORDER ], /* I Short term prediction coefs */
- const opus_int16 LTPCoef_Q14[ LTP_ORDER * MAX_NB_SUBFR ], /* I Long term prediction coefs */
- const opus_int16 AR2_Q13[ MAX_NB_SUBFR * MAX_SHAPE_LPC_ORDER ], /* I Noise shaping coefs */
- const opus_int HarmShapeGain_Q14[ MAX_NB_SUBFR ], /* I Long term shaping coefs */
- const opus_int Tilt_Q14[ MAX_NB_SUBFR ], /* I Spectral tilt */
- const opus_int32 LF_shp_Q14[ MAX_NB_SUBFR ], /* I Low frequency shaping coefs */
- const opus_int32 Gains_Q16[ MAX_NB_SUBFR ], /* I Quantization step sizes */
- const opus_int pitchL[ MAX_NB_SUBFR ], /* I Pitch lags */
- const opus_int Lambda_Q10, /* I Rate/distortion tradeoff */
- const opus_int LTP_scale_Q14 /* I LTP state scaling */
+ const silk_encoder_state *psEncC, /* I Encoder State */
+ silk_nsq_state *NSQ, /* I/O NSQ state */
+ SideInfoIndices *psIndices, /* I/O Quantization Indices */
+ const opus_int16 x16[], /* I Input */
+ opus_int8 pulses[], /* O Quantized pulse signal */
+ const opus_int16 PredCoef_Q12[ 2 * MAX_LPC_ORDER ], /* I Short term prediction coefs */
+ const opus_int16 LTPCoef_Q14[ LTP_ORDER * MAX_NB_SUBFR ], /* I Long term prediction coefs */
+ const opus_int16 AR_Q13[ MAX_NB_SUBFR * MAX_SHAPE_LPC_ORDER ], /* I Noise shaping coefs */
+ const opus_int HarmShapeGain_Q14[ MAX_NB_SUBFR ], /* I Long term shaping coefs */
+ const opus_int Tilt_Q14[ MAX_NB_SUBFR ], /* I Spectral tilt */
+ const opus_int32 LF_shp_Q14[ MAX_NB_SUBFR ], /* I Low frequency shaping coefs */
+ const opus_int32 Gains_Q16[ MAX_NB_SUBFR ], /* I Quantization step sizes */
+ const opus_int pitchL[ MAX_NB_SUBFR ], /* I Pitch lags */
+ const opus_int Lambda_Q10, /* I Rate/distortion tradeoff */
+ const opus_int LTP_scale_Q14 /* I LTP state scaling */
)
{
opus_int k, lag, start_idx, LSF_interpolation_flag;
@@ -117,8 +117,7 @@ void silk_NSQ_c
LSF_interpolation_flag = 1;
}
- ALLOC( sLTP_Q15,
- psEncC->ltp_mem_length + psEncC->frame_length, opus_int32 );
+ ALLOC( sLTP_Q15, psEncC->ltp_mem_length + psEncC->frame_length, opus_int32 );
ALLOC( sLTP, psEncC->ltp_mem_length + psEncC->frame_length, opus_int16 );
ALLOC( x_sc_Q10, psEncC->subfr_length, opus_int32 );
/* Set up pointers to start of sub frame */
@@ -128,7 +127,7 @@ void silk_NSQ_c
for( k = 0; k < psEncC->nb_subfr; k++ ) {
A_Q12 = &PredCoef_Q12[ (( k >> 1 ) | ( 1 - LSF_interpolation_flag )) * MAX_LPC_ORDER ];
B_Q14 = &LTPCoef_Q14[ k * LTP_ORDER ];
- AR_shp_Q13 = &AR2_Q13[ k * MAX_SHAPE_LPC_ORDER ];
+ AR_shp_Q13 = &AR_Q13[ k * MAX_SHAPE_LPC_ORDER ];
/* Noise shape parameters */
silk_assert( HarmShapeGain_Q14[ k ] >= 0 );
@@ -144,7 +143,7 @@ void silk_NSQ_c
if( ( k & ( 3 - silk_LSHIFT( LSF_interpolation_flag, 1 ) ) ) == 0 ) {
/* Rewhiten with new A coefs */
start_idx = psEncC->ltp_mem_length - lag - psEncC->predictLPCOrder - LTP_ORDER / 2;
- silk_assert( start_idx > 0 );
+ celt_assert( start_idx > 0 );
silk_LPC_analysis_filter( &sLTP[ start_idx ], &NSQ->xq[ start_idx + k * psEncC->subfr_length ],
A_Q12, psEncC->ltp_mem_length - start_idx, psEncC->predictLPCOrder, psEncC->arch );
@@ -154,13 +153,13 @@ void silk_NSQ_c
}
}
- silk_nsq_scale_states( psEncC, NSQ, x_Q3, x_sc_Q10, sLTP, sLTP_Q15, k, LTP_scale_Q14, Gains_Q16, pitchL, psIndices->signalType );
+ silk_nsq_scale_states( psEncC, NSQ, x16, x_sc_Q10, sLTP, sLTP_Q15, k, LTP_scale_Q14, Gains_Q16, pitchL, psIndices->signalType );
silk_noise_shape_quantizer( NSQ, psIndices->signalType, x_sc_Q10, pulses, pxq, sLTP_Q15, A_Q12, B_Q14,
AR_shp_Q13, lag, HarmShapeFIRPacked_Q14, Tilt_Q14[ k ], LF_shp_Q14[ k ], Gains_Q16[ k ], Lambda_Q10,
offset_Q10, psEncC->subfr_length, psEncC->shapingLPCOrder, psEncC->predictLPCOrder, psEncC->arch );
- x_Q3 += psEncC->subfr_length;
+ x16 += psEncC->subfr_length;
pulses += psEncC->subfr_length;
pxq += psEncC->subfr_length;
}
@@ -169,15 +168,14 @@ void silk_NSQ_c
NSQ->lagPrev = pitchL[ psEncC->nb_subfr - 1 ];
/* Save quantized speech and noise shaping signals */
- /* DEBUG_STORE_DATA( enc.pcm, &NSQ->xq[ psEncC->ltp_mem_length ], psEncC->frame_length * sizeof( opus_int16 ) ) */
silk_memmove( NSQ->xq, &NSQ->xq[ psEncC->frame_length ], psEncC->ltp_mem_length * sizeof( opus_int16 ) );
silk_memmove( NSQ->sLTP_shp_Q14, &NSQ->sLTP_shp_Q14[ psEncC->frame_length ], psEncC->ltp_mem_length * sizeof( opus_int32 ) );
RESTORE_STACK;
}
-/***********************************/
-/* silk_noise_shape_quantizer */
-/***********************************/
+/******************************/
+/* silk_noise_shape_quantizer */
+/******************************/
#if !defined(OPUS_X86_MAY_HAVE_SSE4_1)
static OPUS_INLINE
@@ -249,22 +247,22 @@ void silk_noise_shape_quantizer(
}
/* Noise shape feedback */
- silk_assert( ( shapingLPCOrder & 1 ) == 0 ); /* check that order is even */
- n_AR_Q12 = silk_NSQ_noise_shape_feedback_loop(psLPC_Q14, NSQ->sAR2_Q14, AR_shp_Q13, shapingLPCOrder, arch);
+ celt_assert( ( shapingLPCOrder & 1 ) == 0 ); /* check that order is even */
+ n_AR_Q12 = silk_NSQ_noise_shape_feedback_loop(&NSQ->sDiff_shp_Q14, NSQ->sAR2_Q14, AR_shp_Q13, shapingLPCOrder, arch);
n_AR_Q12 = silk_SMLAWB( n_AR_Q12, NSQ->sLF_AR_shp_Q14, Tilt_Q14 );
n_LF_Q12 = silk_SMULWB( NSQ->sLTP_shp_Q14[ NSQ->sLTP_shp_buf_idx - 1 ], LF_shp_Q14 );
n_LF_Q12 = silk_SMLAWT( n_LF_Q12, NSQ->sLF_AR_shp_Q14, LF_shp_Q14 );
- silk_assert( lag > 0 || signalType != TYPE_VOICED );
+ celt_assert( lag > 0 || signalType != TYPE_VOICED );
/* Combine prediction and noise shaping signals */
tmp1 = silk_SUB32( silk_LSHIFT32( LPC_pred_Q10, 2 ), n_AR_Q12 ); /* Q12 */
tmp1 = silk_SUB32( tmp1, n_LF_Q12 ); /* Q12 */
if( lag > 0 ) {
/* Symmetric, packed FIR coefficients */
- n_LTP_Q13 = silk_SMULWB( silk_ADD32( shp_lag_ptr[ 0 ], shp_lag_ptr[ -2 ] ), HarmShapeFIRPacked_Q14 );
+ n_LTP_Q13 = silk_SMULWB( silk_ADD_SAT32( shp_lag_ptr[ 0 ], shp_lag_ptr[ -2 ] ), HarmShapeFIRPacked_Q14 );
n_LTP_Q13 = silk_SMLAWT( n_LTP_Q13, shp_lag_ptr[ -1 ], HarmShapeFIRPacked_Q14 );
n_LTP_Q13 = silk_LSHIFT( n_LTP_Q13, 1 );
shp_lag_ptr++;
@@ -279,14 +277,27 @@ void silk_noise_shape_quantizer(
r_Q10 = silk_SUB32( x_sc_Q10[ i ], tmp1 ); /* residual error Q10 */
/* Flip sign depending on dither */
- if ( NSQ->rand_seed < 0 ) {
- r_Q10 = -r_Q10;
+ if( NSQ->rand_seed < 0 ) {
+ r_Q10 = -r_Q10;
}
r_Q10 = silk_LIMIT_32( r_Q10, -(31 << 10), 30 << 10 );
/* Find two quantization level candidates and measure their rate-distortion */
q1_Q10 = silk_SUB32( r_Q10, offset_Q10 );
q1_Q0 = silk_RSHIFT( q1_Q10, 10 );
+ if (Lambda_Q10 > 2048) {
+ /* For aggressive RDO, the bias becomes more than one pulse. */
+ int rdo_offset = Lambda_Q10/2 - 512;
+ if (q1_Q10 > rdo_offset) {
+ q1_Q0 = silk_RSHIFT( q1_Q10 - rdo_offset, 10 );
+ } else if (q1_Q10 < -rdo_offset) {
+ q1_Q0 = silk_RSHIFT( q1_Q10 + rdo_offset, 10 );
+ } else if (q1_Q10 < 0) {
+ q1_Q0 = -1;
+ } else {
+ q1_Q0 = 0;
+ }
+ }
if( q1_Q0 > 0 ) {
q1_Q10 = silk_SUB32( silk_LSHIFT( q1_Q0, 10 ), QUANT_LEVEL_ADJUST_Q10 );
q1_Q10 = silk_ADD32( q1_Q10, offset_Q10 );
@@ -337,7 +348,8 @@ void silk_noise_shape_quantizer(
/* Update states */
psLPC_Q14++;
*psLPC_Q14 = xq_Q14;
- sLF_AR_shp_Q14 = silk_SUB_LSHIFT32( xq_Q14, n_AR_Q12, 2 );
+ NSQ->sDiff_shp_Q14 = silk_SUB_LSHIFT32( xq_Q14, x_sc_Q10[ i ], 4 );
+ sLF_AR_shp_Q14 = silk_SUB_LSHIFT32( NSQ->sDiff_shp_Q14, n_AR_Q12, 2 );
NSQ->sLF_AR_shp_Q14 = sLF_AR_shp_Q14;
NSQ->sLTP_shp_Q14[ NSQ->sLTP_shp_buf_idx ] = silk_SUB_LSHIFT32( sLF_AR_shp_Q14, n_LF_Q12, 2 );
@@ -356,7 +368,7 @@ void silk_noise_shape_quantizer(
static OPUS_INLINE void silk_nsq_scale_states(
const silk_encoder_state *psEncC, /* I Encoder State */
silk_nsq_state *NSQ, /* I/O NSQ state */
- const opus_int32 x_Q3[], /* I input in Q3 */
+ const opus_int16 x16[], /* I input */
opus_int32 x_sc_Q10[], /* O input scaled with 1/Gain */
const opus_int16 sLTP[], /* I re-whitened LTP state in Q0 */
opus_int32 sLTP_Q15[], /* O LTP state matching scaled input */
@@ -368,28 +380,18 @@ static OPUS_INLINE void silk_nsq_scale_states(
)
{
opus_int i, lag;
- opus_int32 gain_adj_Q16, inv_gain_Q31, inv_gain_Q23;
+ opus_int32 gain_adj_Q16, inv_gain_Q31, inv_gain_Q26;
lag = pitchL[ subfr ];
inv_gain_Q31 = silk_INVERSE32_varQ( silk_max( Gains_Q16[ subfr ], 1 ), 47 );
silk_assert( inv_gain_Q31 != 0 );
- /* Calculate gain adjustment factor */
- if( Gains_Q16[ subfr ] != NSQ->prev_gain_Q16 ) {
- gain_adj_Q16 = silk_DIV32_varQ( NSQ->prev_gain_Q16, Gains_Q16[ subfr ], 16 );
- } else {
- gain_adj_Q16 = (opus_int32)1 << 16;
- }
-
/* Scale input */
- inv_gain_Q23 = silk_RSHIFT_ROUND( inv_gain_Q31, 8 );
+ inv_gain_Q26 = silk_RSHIFT_ROUND( inv_gain_Q31, 5 );
for( i = 0; i < psEncC->subfr_length; i++ ) {
- x_sc_Q10[ i ] = silk_SMULWW( x_Q3[ i ], inv_gain_Q23 );
+ x_sc_Q10[ i ] = silk_SMULWW( x16[ i ], inv_gain_Q26 );
}
- /* Save inverse gain */
- NSQ->prev_gain_Q16 = Gains_Q16[ subfr ];
-
/* After rewhitening the LTP state is un-scaled, so scale with inv_gain_Q16 */
if( NSQ->rewhite_flag ) {
if( subfr == 0 ) {
@@ -403,7 +405,9 @@ static OPUS_INLINE void silk_nsq_scale_states(
}
/* Adjust for changing gain */
- if( gain_adj_Q16 != (opus_int32)1 << 16 ) {
+ if( Gains_Q16[ subfr ] != NSQ->prev_gain_Q16 ) {
+ gain_adj_Q16 = silk_DIV32_varQ( NSQ->prev_gain_Q16, Gains_Q16[ subfr ], 16 );
+
/* Scale long-term shaping state */
for( i = NSQ->sLTP_shp_buf_idx - psEncC->ltp_mem_length; i < NSQ->sLTP_shp_buf_idx; i++ ) {
NSQ->sLTP_shp_Q14[ i ] = silk_SMULWW( gain_adj_Q16, NSQ->sLTP_shp_Q14[ i ] );
@@ -417,6 +421,7 @@ static OPUS_INLINE void silk_nsq_scale_states(
}
NSQ->sLF_AR_shp_Q14 = silk_SMULWW( gain_adj_Q16, NSQ->sLF_AR_shp_Q14 );
+ NSQ->sDiff_shp_Q14 = silk_SMULWW( gain_adj_Q16, NSQ->sDiff_shp_Q14 );
/* Scale short-term prediction and shaping states */
for( i = 0; i < NSQ_LPC_BUF_LENGTH; i++ ) {
@@ -425,5 +430,8 @@ static OPUS_INLINE void silk_nsq_scale_states(
for( i = 0; i < MAX_SHAPE_LPC_ORDER; i++ ) {
NSQ->sAR2_Q14[ i ] = silk_SMULWW( gain_adj_Q16, NSQ->sAR2_Q14[ i ] );
}
+
+ /* Save inverse gain */
+ NSQ->prev_gain_Q16 = Gains_Q16[ subfr ];
}
}
diff --git a/libs/libopus/silk/NSQ_del_dec.c b/libs/libopus/silk/NSQ_del_dec.c
index ab6feeac9..41f3fc93e 100644
--- a/libs/libopus/silk/NSQ_del_dec.c
+++ b/libs/libopus/silk/NSQ_del_dec.c
@@ -43,6 +43,7 @@ typedef struct {
opus_int32 Shape_Q14[ DECISION_DELAY ];
opus_int32 sAR2_Q14[ MAX_SHAPE_LPC_ORDER ];
opus_int32 LF_AR_Q14;
+ opus_int32 Diff_Q14;
opus_int32 Seed;
opus_int32 SeedInit;
opus_int32 RD_Q10;
@@ -53,6 +54,7 @@ typedef struct {
opus_int32 RD_Q10;
opus_int32 xq_Q14;
opus_int32 LF_AR_Q14;
+ opus_int32 Diff_Q14;
opus_int32 sLTP_shp_Q14;
opus_int32 LPC_exc_Q14;
} NSQ_sample_struct;
@@ -66,7 +68,7 @@ static OPUS_INLINE void silk_nsq_del_dec_scale_states(
const silk_encoder_state *psEncC, /* I Encoder State */
silk_nsq_state *NSQ, /* I/O NSQ state */
NSQ_del_dec_struct psDelDec[], /* I/O Delayed decision states */
- const opus_int32 x_Q3[], /* I Input in Q3 */
+ const opus_int16 x16[], /* I Input */
opus_int32 x_sc_Q10[], /* O Input scaled with 1/Gain in Q10 */
const opus_int16 sLTP[], /* I Re-whitened LTP state in Q0 */
opus_int32 sLTP_Q15[], /* O LTP state matching scaled input */
@@ -107,27 +109,27 @@ static OPUS_INLINE void silk_noise_shape_quantizer_del_dec(
opus_int predictLPCOrder, /* I Prediction filter order */
opus_int warping_Q16, /* I */
opus_int nStatesDelayedDecision, /* I Number of states in decision tree */
- opus_int *smpl_buf_idx, /* I Index to newest samples in buffers */
+ opus_int *smpl_buf_idx, /* I/O Index to newest samples in buffers */
opus_int decisionDelay, /* I */
int arch /* I */
);
void silk_NSQ_del_dec_c(
- const silk_encoder_state *psEncC, /* I/O Encoder State */
- silk_nsq_state *NSQ, /* I/O NSQ state */
- SideInfoIndices *psIndices, /* I/O Quantization Indices */
- const opus_int32 x_Q3[], /* I Prefiltered input signal */
- opus_int8 pulses[], /* O Quantized pulse signal */
- const opus_int16 PredCoef_Q12[ 2 * MAX_LPC_ORDER ], /* I Short term prediction coefs */
- const opus_int16 LTPCoef_Q14[ LTP_ORDER * MAX_NB_SUBFR ], /* I Long term prediction coefs */
- const opus_int16 AR2_Q13[ MAX_NB_SUBFR * MAX_SHAPE_LPC_ORDER ], /* I Noise shaping coefs */
- const opus_int HarmShapeGain_Q14[ MAX_NB_SUBFR ], /* I Long term shaping coefs */
- const opus_int Tilt_Q14[ MAX_NB_SUBFR ], /* I Spectral tilt */
- const opus_int32 LF_shp_Q14[ MAX_NB_SUBFR ], /* I Low frequency shaping coefs */
- const opus_int32 Gains_Q16[ MAX_NB_SUBFR ], /* I Quantization step sizes */
- const opus_int pitchL[ MAX_NB_SUBFR ], /* I Pitch lags */
- const opus_int Lambda_Q10, /* I Rate/distortion tradeoff */
- const opus_int LTP_scale_Q14 /* I LTP state scaling */
+ const silk_encoder_state *psEncC, /* I Encoder State */
+ silk_nsq_state *NSQ, /* I/O NSQ state */
+ SideInfoIndices *psIndices, /* I/O Quantization Indices */
+ const opus_int16 x16[], /* I Input */
+ opus_int8 pulses[], /* O Quantized pulse signal */
+ const opus_int16 PredCoef_Q12[ 2 * MAX_LPC_ORDER ], /* I Short term prediction coefs */
+ const opus_int16 LTPCoef_Q14[ LTP_ORDER * MAX_NB_SUBFR ], /* I Long term prediction coefs */
+ const opus_int16 AR_Q13[ MAX_NB_SUBFR * MAX_SHAPE_LPC_ORDER ], /* I Noise shaping coefs */
+ const opus_int HarmShapeGain_Q14[ MAX_NB_SUBFR ], /* I Long term shaping coefs */
+ const opus_int Tilt_Q14[ MAX_NB_SUBFR ], /* I Spectral tilt */
+ const opus_int32 LF_shp_Q14[ MAX_NB_SUBFR ], /* I Low frequency shaping coefs */
+ const opus_int32 Gains_Q16[ MAX_NB_SUBFR ], /* I Quantization step sizes */
+ const opus_int pitchL[ MAX_NB_SUBFR ], /* I Pitch lags */
+ const opus_int Lambda_Q10, /* I Rate/distortion tradeoff */
+ const opus_int LTP_scale_Q14 /* I LTP state scaling */
)
{
opus_int i, k, lag, start_idx, LSF_interpolation_flag, Winner_ind, subfr;
@@ -159,6 +161,7 @@ void silk_NSQ_del_dec_c(
psDD->SeedInit = psDD->Seed;
psDD->RD_Q10 = 0;
psDD->LF_AR_Q14 = NSQ->sLF_AR_shp_Q14;
+ psDD->Diff_Q14 = NSQ->sDiff_shp_Q14;
psDD->Shape_Q14[ 0 ] = NSQ->sLTP_shp_Q14[ psEncC->ltp_mem_length - 1 ];
silk_memcpy( psDD->sLPC_Q14, NSQ->sLPC_Q14, NSQ_LPC_BUF_LENGTH * sizeof( opus_int32 ) );
silk_memcpy( psDD->sAR2_Q14, NSQ->sAR2_Q14, sizeof( NSQ->sAR2_Q14 ) );
@@ -186,8 +189,7 @@ void silk_NSQ_del_dec_c(
LSF_interpolation_flag = 1;
}
- ALLOC( sLTP_Q15,
- psEncC->ltp_mem_length + psEncC->frame_length, opus_int32 );
+ ALLOC( sLTP_Q15, psEncC->ltp_mem_length + psEncC->frame_length, opus_int32 );
ALLOC( sLTP, psEncC->ltp_mem_length + psEncC->frame_length, opus_int16 );
ALLOC( x_sc_Q10, psEncC->subfr_length, opus_int32 );
ALLOC( delayedGain_Q10, DECISION_DELAY, opus_int32 );
@@ -199,7 +201,7 @@ void silk_NSQ_del_dec_c(
for( k = 0; k < psEncC->nb_subfr; k++ ) {
A_Q12 = &PredCoef_Q12[ ( ( k >> 1 ) | ( 1 - LSF_interpolation_flag ) ) * MAX_LPC_ORDER ];
B_Q14 = &LTPCoef_Q14[ k * LTP_ORDER ];
- AR_shp_Q13 = &AR2_Q13[ k * MAX_SHAPE_LPC_ORDER ];
+ AR_shp_Q13 = &AR_Q13[ k * MAX_SHAPE_LPC_ORDER ];
/* Noise shape parameters */
silk_assert( HarmShapeGain_Q14[ k ] >= 0 );
@@ -235,7 +237,8 @@ void silk_NSQ_del_dec_c(
psDD = &psDelDec[ Winner_ind ];
last_smple_idx = smpl_buf_idx + decisionDelay;
for( i = 0; i < decisionDelay; i++ ) {
- last_smple_idx = ( last_smple_idx - 1 ) & DECISION_DELAY_MASK;
+ last_smple_idx = ( last_smple_idx - 1 ) % DECISION_DELAY;
+ if( last_smple_idx < 0 ) last_smple_idx += DECISION_DELAY;
pulses[ i - decisionDelay ] = (opus_int8)silk_RSHIFT_ROUND( psDD->Q_Q10[ last_smple_idx ], 10 );
pxq[ i - decisionDelay ] = (opus_int16)silk_SAT16( silk_RSHIFT_ROUND(
silk_SMULWW( psDD->Xq_Q14[ last_smple_idx ], Gains_Q16[ 1 ] ), 14 ) );
@@ -247,7 +250,7 @@ void silk_NSQ_del_dec_c(
/* Rewhiten with new A coefs */
start_idx = psEncC->ltp_mem_length - lag - psEncC->predictLPCOrder - LTP_ORDER / 2;
- silk_assert( start_idx > 0 );
+ celt_assert( start_idx > 0 );
silk_LPC_analysis_filter( &sLTP[ start_idx ], &NSQ->xq[ start_idx + k * psEncC->subfr_length ],
A_Q12, psEncC->ltp_mem_length - start_idx, psEncC->predictLPCOrder, psEncC->arch );
@@ -257,7 +260,7 @@ void silk_NSQ_del_dec_c(
}
}
- silk_nsq_del_dec_scale_states( psEncC, NSQ, psDelDec, x_Q3, x_sc_Q10, sLTP, sLTP_Q15, k,
+ silk_nsq_del_dec_scale_states( psEncC, NSQ, psDelDec, x16, x_sc_Q10, sLTP, sLTP_Q15, k,
psEncC->nStatesDelayedDecision, LTP_scale_Q14, Gains_Q16, pitchL, psIndices->signalType, decisionDelay );
silk_noise_shape_quantizer_del_dec( NSQ, psDelDec, psIndices->signalType, x_sc_Q10, pulses, pxq, sLTP_Q15,
@@ -265,7 +268,7 @@ void silk_NSQ_del_dec_c(
Gains_Q16[ k ], Lambda_Q10, offset_Q10, psEncC->subfr_length, subfr++, psEncC->shapingLPCOrder,
psEncC->predictLPCOrder, psEncC->warping_Q16, psEncC->nStatesDelayedDecision, &smpl_buf_idx, decisionDelay, psEncC->arch );
- x_Q3 += psEncC->subfr_length;
+ x16 += psEncC->subfr_length;
pulses += psEncC->subfr_length;
pxq += psEncC->subfr_length;
}
@@ -286,7 +289,9 @@ void silk_NSQ_del_dec_c(
last_smple_idx = smpl_buf_idx + decisionDelay;
Gain_Q10 = silk_RSHIFT32( Gains_Q16[ psEncC->nb_subfr - 1 ], 6 );
for( i = 0; i < decisionDelay; i++ ) {
- last_smple_idx = ( last_smple_idx - 1 ) & DECISION_DELAY_MASK;
+ last_smple_idx = ( last_smple_idx - 1 ) % DECISION_DELAY;
+ if( last_smple_idx < 0 ) last_smple_idx += DECISION_DELAY;
+
pulses[ i - decisionDelay ] = (opus_int8)silk_RSHIFT_ROUND( psDD->Q_Q10[ last_smple_idx ], 10 );
pxq[ i - decisionDelay ] = (opus_int16)silk_SAT16( silk_RSHIFT_ROUND(
silk_SMULWW( psDD->Xq_Q14[ last_smple_idx ], Gain_Q10 ), 8 ) );
@@ -297,10 +302,10 @@ void silk_NSQ_del_dec_c(
/* Update states */
NSQ->sLF_AR_shp_Q14 = psDD->LF_AR_Q14;
+ NSQ->sDiff_shp_Q14 = psDD->Diff_Q14;
NSQ->lagPrev = pitchL[ psEncC->nb_subfr - 1 ];
/* Save quantized speech signal */
- /* DEBUG_STORE_DATA( enc.pcm, &NSQ->xq[psEncC->ltp_mem_length], psEncC->frame_length * sizeof( opus_int16 ) ) */
silk_memmove( NSQ->xq, &NSQ->xq[ psEncC->frame_length ], psEncC->ltp_mem_length * sizeof( opus_int16 ) );
silk_memmove( NSQ->sLTP_shp_Q14, &NSQ->sLTP_shp_Q14[ psEncC->frame_length ], psEncC->ltp_mem_length * sizeof( opus_int32 ) );
RESTORE_STACK;
@@ -335,7 +340,7 @@ static OPUS_INLINE void silk_noise_shape_quantizer_del_dec(
opus_int predictLPCOrder, /* I Prediction filter order */
opus_int warping_Q16, /* I */
opus_int nStatesDelayedDecision, /* I Number of states in decision tree */
- opus_int *smpl_buf_idx, /* I Index to newest samples in buffers */
+ opus_int *smpl_buf_idx, /* I/O Index to newest samples in buffers */
opus_int decisionDelay, /* I */
int arch /* I */
)
@@ -356,7 +361,7 @@ static OPUS_INLINE void silk_noise_shape_quantizer_del_dec(
NSQ_sample_struct *psSS;
SAVE_STACK;
- silk_assert( nStatesDelayedDecision > 0 );
+ celt_assert( nStatesDelayedDecision > 0 );
ALLOC( psSampleState, nStatesDelayedDecision, NSQ_sample_pair );
shp_lag_ptr = &NSQ->sLTP_shp_Q14[ NSQ->sLTP_shp_buf_idx - lag + HARM_SHAPE_FIR_TAPS / 2 ];
@@ -389,8 +394,8 @@ static OPUS_INLINE void silk_noise_shape_quantizer_del_dec(
/* Long-term shaping */
if( lag > 0 ) {
/* Symmetric, packed FIR coefficients */
- n_LTP_Q14 = silk_SMULWB( silk_ADD32( shp_lag_ptr[ 0 ], shp_lag_ptr[ -2 ] ), HarmShapeFIRPacked_Q14 );
- n_LTP_Q14 = silk_SMLAWT( n_LTP_Q14, shp_lag_ptr[ -1 ], HarmShapeFIRPacked_Q14 );
+ n_LTP_Q14 = silk_SMULWB( silk_ADD_SAT32( shp_lag_ptr[ 0 ], shp_lag_ptr[ -2 ] ), HarmShapeFIRPacked_Q14 );
+ n_LTP_Q14 = silk_SMLAWT( n_LTP_Q14, shp_lag_ptr[ -1 ], HarmShapeFIRPacked_Q14 );
n_LTP_Q14 = silk_SUB_LSHIFT32( LTP_pred_Q14, n_LTP_Q14, 2 ); /* Q12 -> Q14 */
shp_lag_ptr++;
} else {
@@ -414,9 +419,9 @@ static OPUS_INLINE void silk_noise_shape_quantizer_del_dec(
LPC_pred_Q14 = silk_LSHIFT( LPC_pred_Q14, 4 ); /* Q10 -> Q14 */
/* Noise shape feedback */
- silk_assert( ( shapingLPCOrder & 1 ) == 0 ); /* check that order is even */
+ celt_assert( ( shapingLPCOrder & 1 ) == 0 ); /* check that order is even */
/* Output of lowpass section */
- tmp2 = silk_SMLAWB( psLPC_Q14[ 0 ], psDD->sAR2_Q14[ 0 ], warping_Q16 );
+ tmp2 = silk_SMLAWB( psDD->Diff_Q14, psDD->sAR2_Q14[ 0 ], warping_Q16 );
/* Output of allpass section */
tmp1 = silk_SMLAWB( psDD->sAR2_Q14[ 0 ], psDD->sAR2_Q14[ 1 ] - tmp2, warping_Q16 );
psDD->sAR2_Q14[ 0 ] = tmp2;
@@ -446,9 +451,9 @@ static OPUS_INLINE void silk_noise_shape_quantizer_del_dec(
/* Input minus prediction plus noise feedback */
/* r = x[ i ] - LTP_pred - LPC_pred + n_AR + n_Tilt + n_LF + n_LTP */
- tmp1 = silk_ADD32( n_AR_Q14, n_LF_Q14 ); /* Q14 */
+ tmp1 = silk_ADD_SAT32( n_AR_Q14, n_LF_Q14 ); /* Q14 */
tmp2 = silk_ADD32( n_LTP_Q14, LPC_pred_Q14 ); /* Q13 */
- tmp1 = silk_SUB32( tmp2, tmp1 ); /* Q13 */
+ tmp1 = silk_SUB_SAT32( tmp2, tmp1 ); /* Q13 */
tmp1 = silk_RSHIFT_ROUND( tmp1, 4 ); /* Q10 */
r_Q10 = silk_SUB32( x_Q10[ i ], tmp1 ); /* residual error Q10 */
@@ -462,6 +467,19 @@ static OPUS_INLINE void silk_noise_shape_quantizer_del_dec(
/* Find two quantization level candidates and measure their rate-distortion */
q1_Q10 = silk_SUB32( r_Q10, offset_Q10 );
q1_Q0 = silk_RSHIFT( q1_Q10, 10 );
+ if (Lambda_Q10 > 2048) {
+ /* For aggressive RDO, the bias becomes more than one pulse. */
+ int rdo_offset = Lambda_Q10/2 - 512;
+ if (q1_Q10 > rdo_offset) {
+ q1_Q0 = silk_RSHIFT( q1_Q10 - rdo_offset, 10 );
+ } else if (q1_Q10 < -rdo_offset) {
+ q1_Q0 = silk_RSHIFT( q1_Q10 + rdo_offset, 10 );
+ } else if (q1_Q10 < 0) {
+ q1_Q0 = -1;
+ } else {
+ q1_Q0 = 0;
+ }
+ }
if( q1_Q0 > 0 ) {
q1_Q10 = silk_SUB32( silk_LSHIFT( q1_Q0, 10 ), QUANT_LEVEL_ADJUST_Q10 );
q1_Q10 = silk_ADD32( q1_Q10, offset_Q10 );
@@ -515,8 +533,9 @@ static OPUS_INLINE void silk_noise_shape_quantizer_del_dec(
xq_Q14 = silk_ADD32( LPC_exc_Q14, LPC_pred_Q14 );
/* Update states */
- sLF_AR_shp_Q14 = silk_SUB32( xq_Q14, n_AR_Q14 );
- psSS[ 0 ].sLTP_shp_Q14 = silk_SUB32( sLF_AR_shp_Q14, n_LF_Q14 );
+ psSS[ 0 ].Diff_Q14 = silk_SUB_LSHIFT32( xq_Q14, x_Q10[ i ], 4 );
+ sLF_AR_shp_Q14 = silk_SUB32( psSS[ 0 ].Diff_Q14, n_AR_Q14 );
+ psSS[ 0 ].sLTP_shp_Q14 = silk_SUB_SAT32( sLF_AR_shp_Q14, n_LF_Q14 );
psSS[ 0 ].LF_AR_Q14 = sLF_AR_shp_Q14;
psSS[ 0 ].LPC_exc_Q14 = LPC_exc_Q14;
psSS[ 0 ].xq_Q14 = xq_Q14;
@@ -529,21 +548,22 @@ static OPUS_INLINE void silk_noise_shape_quantizer_del_dec(
exc_Q14 = -exc_Q14;
}
-
/* Add predictions */
LPC_exc_Q14 = silk_ADD32( exc_Q14, LTP_pred_Q14 );
xq_Q14 = silk_ADD32( LPC_exc_Q14, LPC_pred_Q14 );
/* Update states */
- sLF_AR_shp_Q14 = silk_SUB32( xq_Q14, n_AR_Q14 );
- psSS[ 1 ].sLTP_shp_Q14 = silk_SUB32( sLF_AR_shp_Q14, n_LF_Q14 );
+ psSS[ 1 ].Diff_Q14 = silk_SUB_LSHIFT32( xq_Q14, x_Q10[ i ], 4 );
+ sLF_AR_shp_Q14 = silk_SUB32( psSS[ 1 ].Diff_Q14, n_AR_Q14 );
+ psSS[ 1 ].sLTP_shp_Q14 = silk_SUB_SAT32( sLF_AR_shp_Q14, n_LF_Q14 );
psSS[ 1 ].LF_AR_Q14 = sLF_AR_shp_Q14;
psSS[ 1 ].LPC_exc_Q14 = LPC_exc_Q14;
psSS[ 1 ].xq_Q14 = xq_Q14;
}
- *smpl_buf_idx = ( *smpl_buf_idx - 1 ) & DECISION_DELAY_MASK; /* Index to newest samples */
- last_smple_idx = ( *smpl_buf_idx + decisionDelay ) & DECISION_DELAY_MASK; /* Index to decisionDelay old samples */
+ *smpl_buf_idx = ( *smpl_buf_idx - 1 ) % DECISION_DELAY;
+ if( *smpl_buf_idx < 0 ) *smpl_buf_idx += DECISION_DELAY;
+ last_smple_idx = ( *smpl_buf_idx + decisionDelay ) % DECISION_DELAY;
/* Find winner */
RDmin_Q10 = psSampleState[ 0 ][ 0 ].RD_Q10;
@@ -607,6 +627,7 @@ static OPUS_INLINE void silk_noise_shape_quantizer_del_dec(
psDD = &psDelDec[ k ];
psSS = &psSampleState[ k ][ 0 ];
psDD->LF_AR_Q14 = psSS->LF_AR_Q14;
+ psDD->Diff_Q14 = psSS->Diff_Q14;
psDD->sLPC_Q14[ NSQ_LPC_BUF_LENGTH + i ] = psSS->xq_Q14;
psDD->Xq_Q14[ *smpl_buf_idx ] = psSS->xq_Q14;
psDD->Q_Q10[ *smpl_buf_idx ] = psSS->Q_Q10;
@@ -631,7 +652,7 @@ static OPUS_INLINE void silk_nsq_del_dec_scale_states(
const silk_encoder_state *psEncC, /* I Encoder State */
silk_nsq_state *NSQ, /* I/O NSQ state */
NSQ_del_dec_struct psDelDec[], /* I/O Delayed decision states */
- const opus_int32 x_Q3[], /* I Input in Q3 */
+ const opus_int16 x16[], /* I Input */
opus_int32 x_sc_Q10[], /* O Input scaled with 1/Gain in Q10 */
const opus_int16 sLTP[], /* I Re-whitened LTP state in Q0 */
opus_int32 sLTP_Q15[], /* O LTP state matching scaled input */
@@ -645,29 +666,19 @@ static OPUS_INLINE void silk_nsq_del_dec_scale_states(
)
{
opus_int i, k, lag;
- opus_int32 gain_adj_Q16, inv_gain_Q31, inv_gain_Q23;
+ opus_int32 gain_adj_Q16, inv_gain_Q31, inv_gain_Q26;
NSQ_del_dec_struct *psDD;
lag = pitchL[ subfr ];
inv_gain_Q31 = silk_INVERSE32_varQ( silk_max( Gains_Q16[ subfr ], 1 ), 47 );
silk_assert( inv_gain_Q31 != 0 );
- /* Calculate gain adjustment factor */
- if( Gains_Q16[ subfr ] != NSQ->prev_gain_Q16 ) {
- gain_adj_Q16 = silk_DIV32_varQ( NSQ->prev_gain_Q16, Gains_Q16[ subfr ], 16 );
- } else {
- gain_adj_Q16 = (opus_int32)1 << 16;
- }
-
/* Scale input */
- inv_gain_Q23 = silk_RSHIFT_ROUND( inv_gain_Q31, 8 );
+ inv_gain_Q26 = silk_RSHIFT_ROUND( inv_gain_Q31, 5 );
for( i = 0; i < psEncC->subfr_length; i++ ) {
- x_sc_Q10[ i ] = silk_SMULWW( x_Q3[ i ], inv_gain_Q23 );
+ x_sc_Q10[ i ] = silk_SMULWW( x16[ i ], inv_gain_Q26 );
}
- /* Save inverse gain */
- NSQ->prev_gain_Q16 = Gains_Q16[ subfr ];
-
/* After rewhitening the LTP state is un-scaled, so scale with inv_gain_Q16 */
if( NSQ->rewhite_flag ) {
if( subfr == 0 ) {
@@ -681,7 +692,9 @@ static OPUS_INLINE void silk_nsq_del_dec_scale_states(
}
/* Adjust for changing gain */
- if( gain_adj_Q16 != (opus_int32)1 << 16 ) {
+ if( Gains_Q16[ subfr ] != NSQ->prev_gain_Q16 ) {
+ gain_adj_Q16 = silk_DIV32_varQ( NSQ->prev_gain_Q16, Gains_Q16[ subfr ], 16 );
+
/* Scale long-term shaping state */
for( i = NSQ->sLTP_shp_buf_idx - psEncC->ltp_mem_length; i < NSQ->sLTP_shp_buf_idx; i++ ) {
NSQ->sLTP_shp_Q14[ i ] = silk_SMULWW( gain_adj_Q16, NSQ->sLTP_shp_Q14[ i ] );
@@ -699,6 +712,7 @@ static OPUS_INLINE void silk_nsq_del_dec_scale_states(
/* Scale scalar states */
psDD->LF_AR_Q14 = silk_SMULWW( gain_adj_Q16, psDD->LF_AR_Q14 );
+ psDD->Diff_Q14 = silk_SMULWW( gain_adj_Q16, psDD->Diff_Q14 );
/* Scale short-term prediction and shaping states */
for( i = 0; i < NSQ_LPC_BUF_LENGTH; i++ ) {
@@ -712,5 +726,8 @@ static OPUS_INLINE void silk_nsq_del_dec_scale_states(
psDD->Shape_Q14[ i ] = silk_SMULWW( gain_adj_Q16, psDD->Shape_Q14[ i ] );
}
}
+
+ /* Save inverse gain */
+ NSQ->prev_gain_Q16 = Gains_Q16[ subfr ];
}
}
diff --git a/libs/libopus/silk/PLC.c b/libs/libopus/silk/PLC.c
index fb6ea887b..4667440db 100644
--- a/libs/libopus/silk/PLC.c
+++ b/libs/libopus/silk/PLC.c
@@ -275,7 +275,7 @@ static OPUS_INLINE void silk_PLC_conceal(
/* Reduce random noise for unvoiced frames with high LPC gain */
opus_int32 invGain_Q30, down_scale_Q30;
- invGain_Q30 = silk_LPC_inverse_pred_gain( psPLC->prevLPC_Q12, psDec->LPC_order );
+ invGain_Q30 = silk_LPC_inverse_pred_gain( psPLC->prevLPC_Q12, psDec->LPC_order, arch );
down_scale_Q30 = silk_min_32( silk_RSHIFT( (opus_int32)1 << 30, LOG2_INV_LPC_GAIN_HIGH_THRES ), invGain_Q30 );
down_scale_Q30 = silk_max_32( silk_RSHIFT( (opus_int32)1 << 30, LOG2_INV_LPC_GAIN_LOW_THRES ), down_scale_Q30 );
@@ -291,7 +291,7 @@ static OPUS_INLINE void silk_PLC_conceal(
/* Rewhiten LTP state */
idx = psDec->ltp_mem_length - lag - psDec->LPC_order - LTP_ORDER / 2;
- silk_assert( idx > 0 );
+ celt_assert( idx > 0 );
silk_LPC_analysis_filter( &sLTP[ idx ], &psDec->outBuf[ idx ], A_Q12, psDec->ltp_mem_length - idx, psDec->LPC_order, arch );
/* Scale LTP state */
inv_gain_Q30 = silk_INVERSE32_varQ( psPLC->prevGain_Q16[ 1 ], 46 );
@@ -345,7 +345,7 @@ static OPUS_INLINE void silk_PLC_conceal(
/* Copy LPC state */
silk_memcpy( sLPC_Q14_ptr, psDec->sLPC_Q14_buf, MAX_LPC_ORDER * sizeof( opus_int32 ) );
- silk_assert( psDec->LPC_order >= 10 ); /* check that unrolling works */
+ celt_assert( psDec->LPC_order >= 10 ); /* check that unrolling works */
for( i = 0; i < psDec->frame_length; i++ ) {
/* partly unrolled */
/* Avoids introducing a bias because silk_SMLAWB() always rounds to -inf */
diff --git a/libs/libopus/silk/SigProc_FIX.h b/libs/libopus/silk/SigProc_FIX.h
index b63299441..1d9bf2f16 100644
--- a/libs/libopus/silk/SigProc_FIX.h
+++ b/libs/libopus/silk/SigProc_FIX.h
@@ -35,7 +35,7 @@ extern "C"
/*#define silk_MACRO_COUNT */ /* Used to enable WMOPS counting */
-#define SILK_MAX_ORDER_LPC 16 /* max order of the LPC analysis in schur() and k2a() */
+#define SILK_MAX_ORDER_LPC 24 /* max order of the LPC analysis in schur() and k2a() */
#include <string.h> /* for memset(), memcpy(), memmove() */
#include "typedef.h"
@@ -47,6 +47,11 @@ extern "C"
#include "x86/SigProc_FIX_sse.h"
#endif
+#if (defined(OPUS_ARM_ASM) || defined(OPUS_ARM_MAY_HAVE_NEON_INTR))
+#include "arm/biquad_alt_arm.h"
+#include "arm/LPC_inv_pred_gain_arm.h"
+#endif
+
/********************************************************************/
/* SIGNAL PROCESSING FUNCTIONS */
/********************************************************************/
@@ -96,14 +101,22 @@ void silk_resampler_down2_3(
* slower than biquad() but uses more precise coefficients
* can handle (slowly) varying coefficients
*/
-void silk_biquad_alt(
+void silk_biquad_alt_stride1(
const opus_int16 *in, /* I input signal */
const opus_int32 *B_Q28, /* I MA coefficients [3] */
const opus_int32 *A_Q28, /* I AR coefficients [2] */
opus_int32 *S, /* I/O State vector [2] */
opus_int16 *out, /* O output signal */
- const opus_int32 len, /* I signal length (must be even) */
- opus_int stride /* I Operate on interleaved signal if > 1 */
+ const opus_int32 len /* I signal length (must be even) */
+);
+
+void silk_biquad_alt_stride2_c(
+ const opus_int16 *in, /* I input signal */
+ const opus_int32 *B_Q28, /* I MA coefficients [3] */
+ const opus_int32 *A_Q28, /* I AR coefficients [2] */
+ opus_int32 *S, /* I/O State vector [4] */
+ opus_int16 *out, /* O output signal */
+ const opus_int32 len /* I signal length (must be even) */
);
/* Variable order MA prediction error filter. */
@@ -132,17 +145,11 @@ void silk_bwexpander_32(
/* Compute inverse of LPC prediction gain, and */
/* test if LPC coefficients are stable (all poles within unit circle) */
-opus_int32 silk_LPC_inverse_pred_gain( /* O Returns inverse prediction gain in energy domain, Q30 */
+opus_int32 silk_LPC_inverse_pred_gain_c( /* O Returns inverse prediction gain in energy domain, Q30 */
const opus_int16 *A_Q12, /* I Prediction coefficients, Q12 [order] */
const opus_int order /* I Prediction order */
);
-/* For input in Q24 domain */
-opus_int32 silk_LPC_inverse_pred_gain_Q24( /* O Returns inverse prediction gain in energy domain, Q30 */
- const opus_int32 *A_Q24, /* I Prediction coefficients [order] */
- const opus_int order /* I Prediction order */
-);
-
/* Split signal in two decimated bands using first-order allpass filters */
void silk_ana_filt_bank_1(
const opus_int16 *in, /* I Input signal [N] */
@@ -152,6 +159,14 @@ void silk_ana_filt_bank_1(
const opus_int32 N /* I Number of input samples */
);
+#if !defined(OVERRIDE_silk_biquad_alt_stride2)
+#define silk_biquad_alt_stride2(in, B_Q28, A_Q28, S, out, len, arch) ((void)(arch), silk_biquad_alt_stride2_c(in, B_Q28, A_Q28, S, out, len))
+#endif
+
+#if !defined(OVERRIDE_silk_LPC_inverse_pred_gain)
+#define silk_LPC_inverse_pred_gain(A_Q12, order, arch) ((void)(arch), silk_LPC_inverse_pred_gain_c(A_Q12, order))
+#endif
+
/********************************************************************/
/* SCALAR FUNCTIONS */
/********************************************************************/
@@ -271,7 +286,17 @@ void silk_A2NLSF(
void silk_NLSF2A(
opus_int16 *a_Q12, /* O monic whitening filter coefficients in Q12, [ d ] */
const opus_int16 *NLSF, /* I normalized line spectral frequencies in Q15, [ d ] */
- const opus_int d /* I filter order (should be even) */
+ const opus_int d, /* I filter order (should be even) */
+ int arch /* I Run-time architecture */
+);
+
+/* Convert int32 coefficients to int16 coefs and make sure there's no wrap-around */
+void silk_LPC_fit(
+ opus_int16 *a_QOUT, /* O Output signal */
+ opus_int32 *a_QIN, /* I/O Input signal */
+ const opus_int QOUT, /* I Input Q domain */
+ const opus_int QIN, /* I Input Q domain */
+ const opus_int d /* I Filter order */
);
void silk_insertion_sort_increasing(
@@ -356,7 +381,7 @@ opus_int32 silk_inner_prod_aligned_scale(
const opus_int len /* I vector lengths */
);
-opus_int64 silk_inner_prod16_aligned_64_c(
+opus_int64 silk_inner_prod16_c(
const opus_int16 *inVec1, /* I input vector 1 */
const opus_int16 *inVec2, /* I input vector 2 */
const opus_int len /* I vector lengths */
@@ -471,8 +496,7 @@ static OPUS_INLINE opus_int32 silk_ROR32( opus_int32 a32, opus_int rot )
/* Add with saturation for positive input values */
#define silk_ADD_POS_SAT8(a, b) ((((a)+(b)) & 0x80) ? silk_int8_MAX : ((a)+(b)))
#define silk_ADD_POS_SAT16(a, b) ((((a)+(b)) & 0x8000) ? silk_int16_MAX : ((a)+(b)))
-#define silk_ADD_POS_SAT32(a, b) ((((a)+(b)) & 0x80000000) ? silk_int32_MAX : ((a)+(b)))
-#define silk_ADD_POS_SAT64(a, b) ((((a)+(b)) & 0x8000000000000000LL) ? silk_int64_MAX : ((a)+(b)))
+#define silk_ADD_POS_SAT32(a, b) ((((opus_uint32)(a)+(opus_uint32)(b)) & 0x80000000) ? silk_int32_MAX : ((a)+(b)))
#define silk_LSHIFT8(a, shift) ((opus_int8)((opus_uint8)(a)<<(shift))) /* shift >= 0, shift < 8 */
#define silk_LSHIFT16(a, shift) ((opus_int16)((opus_uint16)(a)<<(shift))) /* shift >= 0, shift < 16 */
@@ -572,7 +596,9 @@ static OPUS_INLINE opus_int64 silk_max_64(opus_int64 a, opus_int64 b)
/* Make sure to store the result as the seed for the next call (also in between */
/* frames), otherwise result won't be random at all. When only using some of the */
/* bits, take the most significant bits by right-shifting. */
-#define silk_RAND(seed) (silk_MLA_ovflw(907633515, (seed), 196314165))
+#define RAND_MULTIPLIER 196314165
+#define RAND_INCREMENT 907633515
+#define silk_RAND(seed) (silk_MLA_ovflw((RAND_INCREMENT), (seed), (RAND_MULTIPLIER)))
/* Add some multiplication functions that can be easily mapped to ARM. */
@@ -587,8 +613,8 @@ static OPUS_INLINE opus_int64 silk_max_64(opus_int64 a, opus_int64 b)
#define silk_burg_modified(res_nrg, res_nrg_Q, A_Q16, x, minInvGain_Q30, subfr_length, nb_subfr, D, arch) \
((void)(arch), silk_burg_modified_c(res_nrg, res_nrg_Q, A_Q16, x, minInvGain_Q30, subfr_length, nb_subfr, D, arch))
-#define silk_inner_prod16_aligned_64(inVec1, inVec2, len, arch) \
- ((void)(arch),silk_inner_prod16_aligned_64_c(inVec1, inVec2, len))
+#define silk_inner_prod16(inVec1, inVec2, len, arch) \
+ ((void)(arch),silk_inner_prod16_c(inVec1, inVec2, len))
#endif
#include "Inlines.h"
diff --git a/libs/libopus/silk/VAD.c b/libs/libopus/silk/VAD.c
index 0a782af2f..d0cda5216 100644
--- a/libs/libopus/silk/VAD.c
+++ b/libs/libopus/silk/VAD.c
@@ -101,9 +101,9 @@ opus_int silk_VAD_GetSA_Q8_c( /* O Return v
/* Safety checks */
silk_assert( VAD_N_BANDS == 4 );
- silk_assert( MAX_FRAME_LENGTH >= psEncC->frame_length );
- silk_assert( psEncC->frame_length <= 512 );
- silk_assert( psEncC->frame_length == 8 * silk_RSHIFT( psEncC->frame_length, 3 ) );
+ celt_assert( MAX_FRAME_LENGTH >= psEncC->frame_length );
+ celt_assert( psEncC->frame_length <= 512 );
+ celt_assert( psEncC->frame_length == 8 * silk_RSHIFT( psEncC->frame_length, 3 ) );
/***********************/
/* Filter and Decimate */
@@ -252,15 +252,14 @@ opus_int silk_VAD_GetSA_Q8_c( /* O Return v
speech_nrg += ( b + 1 ) * silk_RSHIFT( Xnrg[ b ] - psSilk_VAD->NL[ b ], 4 );
}
+ if( psEncC->frame_length == 20 * psEncC->fs_kHz ) {
+ speech_nrg = silk_RSHIFT32( speech_nrg, 1 );
+ }
/* Power scaling */
if( speech_nrg <= 0 ) {
SA_Q15 = silk_RSHIFT( SA_Q15, 1 );
- } else if( speech_nrg < 32768 ) {
- if( psEncC->frame_length == 10 * psEncC->fs_kHz ) {
- speech_nrg = silk_LSHIFT_SAT32( speech_nrg, 16 );
- } else {
- speech_nrg = silk_LSHIFT_SAT32( speech_nrg, 15 );
- }
+ } else if( speech_nrg < 16384 ) {
+ speech_nrg = silk_LSHIFT32( speech_nrg, 16 );
/* square-root */
speech_nrg = silk_SQRT_APPROX( speech_nrg );
@@ -313,6 +312,8 @@ void silk_VAD_GetNoiseLevels(
/* Initially faster smoothing */
if( psSilk_VAD->counter < 1000 ) { /* 1000 = 20 sec */
min_coef = silk_DIV32_16( silk_int16_MAX, silk_RSHIFT( psSilk_VAD->counter, 4 ) + 1 );
+ /* Increment frame counter */
+ psSilk_VAD->counter++;
} else {
min_coef = 0;
}
@@ -356,7 +357,4 @@ void silk_VAD_GetNoiseLevels(
/* Store as part of state */
psSilk_VAD->NL[ k ] = nl;
}
-
- /* Increment frame counter */
- psSilk_VAD->counter++;
}
diff --git a/libs/libopus/silk/VQ_WMat_EC.c b/libs/libopus/silk/VQ_WMat_EC.c
index 7983f1db8..245a7e4b0 100644
--- a/libs/libopus/silk/VQ_WMat_EC.c
+++ b/libs/libopus/silk/VQ_WMat_EC.c
@@ -34,84 +34,95 @@ POSSIBILITY OF SUCH DAMAGE.
/* Entropy constrained matrix-weighted VQ, hard-coded to 5-element vectors, for a single input data vector */
void silk_VQ_WMat_EC_c(
opus_int8 *ind, /* O index of best codebook vector */
- opus_int32 *rate_dist_Q14, /* O best weighted quant error + mu * rate */
+ opus_int32 *res_nrg_Q15, /* O best residual energy */
+ opus_int32 *rate_dist_Q8, /* O best total bitrate */
opus_int *gain_Q7, /* O sum of absolute LTP coefficients */
- const opus_int16 *in_Q14, /* I input vector to be quantized */
- const opus_int32 *W_Q18, /* I weighting matrix */
+ const opus_int32 *XX_Q17, /* I correlation matrix */
+ const opus_int32 *xX_Q17, /* I correlation vector */
const opus_int8 *cb_Q7, /* I codebook */
const opus_uint8 *cb_gain_Q7, /* I codebook effective gain */
const opus_uint8 *cl_Q5, /* I code length for each codebook vector */
- const opus_int mu_Q9, /* I tradeoff betw. weighted error and rate */
+ const opus_int subfr_len, /* I number of samples per subframe */
const opus_int32 max_gain_Q7, /* I maximum sum of absolute LTP coefficients */
- opus_int L /* I number of vectors in codebook */
+ const opus_int L /* I number of vectors in codebook */
)
{
opus_int k, gain_tmp_Q7;
const opus_int8 *cb_row_Q7;
- opus_int16 diff_Q14[ 5 ];
- opus_int32 sum1_Q14, sum2_Q16;
+ opus_int32 neg_xX_Q24[ 5 ];
+ opus_int32 sum1_Q15, sum2_Q24;
+ opus_int32 bits_res_Q8, bits_tot_Q8;
+
+ /* Negate and convert to new Q domain */
+ neg_xX_Q24[ 0 ] = -silk_LSHIFT32( xX_Q17[ 0 ], 7 );
+ neg_xX_Q24[ 1 ] = -silk_LSHIFT32( xX_Q17[ 1 ], 7 );
+ neg_xX_Q24[ 2 ] = -silk_LSHIFT32( xX_Q17[ 2 ], 7 );
+ neg_xX_Q24[ 3 ] = -silk_LSHIFT32( xX_Q17[ 3 ], 7 );
+ neg_xX_Q24[ 4 ] = -silk_LSHIFT32( xX_Q17[ 4 ], 7 );
/* Loop over codebook */
- *rate_dist_Q14 = silk_int32_MAX;
+ *rate_dist_Q8 = silk_int32_MAX;
+ *res_nrg_Q15 = silk_int32_MAX;
cb_row_Q7 = cb_Q7;
+ /* If things go really bad, at least *ind is set to something safe. */
+ *ind = 0;
for( k = 0; k < L; k++ ) {
+ opus_int32 penalty;
gain_tmp_Q7 = cb_gain_Q7[k];
-
- diff_Q14[ 0 ] = in_Q14[ 0 ] - silk_LSHIFT( cb_row_Q7[ 0 ], 7 );
- diff_Q14[ 1 ] = in_Q14[ 1 ] - silk_LSHIFT( cb_row_Q7[ 1 ], 7 );
- diff_Q14[ 2 ] = in_Q14[ 2 ] - silk_LSHIFT( cb_row_Q7[ 2 ], 7 );
- diff_Q14[ 3 ] = in_Q14[ 3 ] - silk_LSHIFT( cb_row_Q7[ 3 ], 7 );
- diff_Q14[ 4 ] = in_Q14[ 4 ] - silk_LSHIFT( cb_row_Q7[ 4 ], 7 );
-
/* Weighted rate */
- sum1_Q14 = silk_SMULBB( mu_Q9, cl_Q5[ k ] );
+ /* Quantization error: 1 - 2 * xX * cb + cb' * XX * cb */
+ sum1_Q15 = SILK_FIX_CONST( 1.001, 15 );
/* Penalty for too large gain */
- sum1_Q14 = silk_ADD_LSHIFT32( sum1_Q14, silk_max( silk_SUB32( gain_tmp_Q7, max_gain_Q7 ), 0 ), 10 );
-
- silk_assert( sum1_Q14 >= 0 );
-
- /* first row of W_Q18 */
- sum2_Q16 = silk_SMULWB( W_Q18[ 1 ], diff_Q14[ 1 ] );
- sum2_Q16 = silk_SMLAWB( sum2_Q16, W_Q18[ 2 ], diff_Q14[ 2 ] );
- sum2_Q16 = silk_SMLAWB( sum2_Q16, W_Q18[ 3 ], diff_Q14[ 3 ] );
- sum2_Q16 = silk_SMLAWB( sum2_Q16, W_Q18[ 4 ], diff_Q14[ 4 ] );
- sum2_Q16 = silk_LSHIFT( sum2_Q16, 1 );
- sum2_Q16 = silk_SMLAWB( sum2_Q16, W_Q18[ 0 ], diff_Q14[ 0 ] );
- sum1_Q14 = silk_SMLAWB( sum1_Q14, sum2_Q16, diff_Q14[ 0 ] );
-
- /* second row of W_Q18 */
- sum2_Q16 = silk_SMULWB( W_Q18[ 7 ], diff_Q14[ 2 ] );
- sum2_Q16 = silk_SMLAWB( sum2_Q16, W_Q18[ 8 ], diff_Q14[ 3 ] );
- sum2_Q16 = silk_SMLAWB( sum2_Q16, W_Q18[ 9 ], diff_Q14[ 4 ] );
- sum2_Q16 = silk_LSHIFT( sum2_Q16, 1 );
- sum2_Q16 = silk_SMLAWB( sum2_Q16, W_Q18[ 6 ], diff_Q14[ 1 ] );
- sum1_Q14 = silk_SMLAWB( sum1_Q14, sum2_Q16, diff_Q14[ 1 ] );
-
- /* third row of W_Q18 */
- sum2_Q16 = silk_SMULWB( W_Q18[ 13 ], diff_Q14[ 3 ] );
- sum2_Q16 = silk_SMLAWB( sum2_Q16, W_Q18[ 14 ], diff_Q14[ 4 ] );
- sum2_Q16 = silk_LSHIFT( sum2_Q16, 1 );
- sum2_Q16 = silk_SMLAWB( sum2_Q16, W_Q18[ 12 ], diff_Q14[ 2 ] );
- sum1_Q14 = silk_SMLAWB( sum1_Q14, sum2_Q16, diff_Q14[ 2 ] );
-
- /* fourth row of W_Q18 */
- sum2_Q16 = silk_SMULWB( W_Q18[ 19 ], diff_Q14[ 4 ] );
- sum2_Q16 = silk_LSHIFT( sum2_Q16, 1 );
- sum2_Q16 = silk_SMLAWB( sum2_Q16, W_Q18[ 18 ], diff_Q14[ 3 ] );
- sum1_Q14 = silk_SMLAWB( sum1_Q14, sum2_Q16, diff_Q14[ 3 ] );
-
- /* last row of W_Q18 */
- sum2_Q16 = silk_SMULWB( W_Q18[ 24 ], diff_Q14[ 4 ] );
- sum1_Q14 = silk_SMLAWB( sum1_Q14, sum2_Q16, diff_Q14[ 4 ] );
-
- silk_assert( sum1_Q14 >= 0 );
+ penalty = silk_LSHIFT32( silk_max( silk_SUB32( gain_tmp_Q7, max_gain_Q7 ), 0 ), 11 );
+
+ /* first row of XX_Q17 */
+ sum2_Q24 = silk_MLA( neg_xX_Q24[ 0 ], XX_Q17[ 1 ], cb_row_Q7[ 1 ] );
+ sum2_Q24 = silk_MLA( sum2_Q24, XX_Q17[ 2 ], cb_row_Q7[ 2 ] );
+ sum2_Q24 = silk_MLA( sum2_Q24, XX_Q17[ 3 ], cb_row_Q7[ 3 ] );
+ sum2_Q24 = silk_MLA( sum2_Q24, XX_Q17[ 4 ], cb_row_Q7[ 4 ] );
+ sum2_Q24 = silk_LSHIFT32( sum2_Q24, 1 );
+ sum2_Q24 = silk_MLA( sum2_Q24, XX_Q17[ 0 ], cb_row_Q7[ 0 ] );
+ sum1_Q15 = silk_SMLAWB( sum1_Q15, sum2_Q24, cb_row_Q7[ 0 ] );
+
+ /* second row of XX_Q17 */
+ sum2_Q24 = silk_MLA( neg_xX_Q24[ 1 ], XX_Q17[ 7 ], cb_row_Q7[ 2 ] );
+ sum2_Q24 = silk_MLA( sum2_Q24, XX_Q17[ 8 ], cb_row_Q7[ 3 ] );
+ sum2_Q24 = silk_MLA( sum2_Q24, XX_Q17[ 9 ], cb_row_Q7[ 4 ] );
+ sum2_Q24 = silk_LSHIFT32( sum2_Q24, 1 );
+ sum2_Q24 = silk_MLA( sum2_Q24, XX_Q17[ 6 ], cb_row_Q7[ 1 ] );
+ sum1_Q15 = silk_SMLAWB( sum1_Q15, sum2_Q24, cb_row_Q7[ 1 ] );
+
+ /* third row of XX_Q17 */
+ sum2_Q24 = silk_MLA( neg_xX_Q24[ 2 ], XX_Q17[ 13 ], cb_row_Q7[ 3 ] );
+ sum2_Q24 = silk_MLA( sum2_Q24, XX_Q17[ 14 ], cb_row_Q7[ 4 ] );
+ sum2_Q24 = silk_LSHIFT32( sum2_Q24, 1 );
+ sum2_Q24 = silk_MLA( sum2_Q24, XX_Q17[ 12 ], cb_row_Q7[ 2 ] );
+ sum1_Q15 = silk_SMLAWB( sum1_Q15, sum2_Q24, cb_row_Q7[ 2 ] );
+
+ /* fourth row of XX_Q17 */
+ sum2_Q24 = silk_MLA( neg_xX_Q24[ 3 ], XX_Q17[ 19 ], cb_row_Q7[ 4 ] );
+ sum2_Q24 = silk_LSHIFT32( sum2_Q24, 1 );
+ sum2_Q24 = silk_MLA( sum2_Q24, XX_Q17[ 18 ], cb_row_Q7[ 3 ] );
+ sum1_Q15 = silk_SMLAWB( sum1_Q15, sum2_Q24, cb_row_Q7[ 3 ] );
+
+ /* last row of XX_Q17 */
+ sum2_Q24 = silk_LSHIFT32( neg_xX_Q24[ 4 ], 1 );
+ sum2_Q24 = silk_MLA( sum2_Q24, XX_Q17[ 24 ], cb_row_Q7[ 4 ] );
+ sum1_Q15 = silk_SMLAWB( sum1_Q15, sum2_Q24, cb_row_Q7[ 4 ] );
/* find best */
- if( sum1_Q14 < *rate_dist_Q14 ) {
- *rate_dist_Q14 = sum1_Q14;
- *ind = (opus_int8)k;
- *gain_Q7 = gain_tmp_Q7;
+ if( sum1_Q15 >= 0 ) {
+ /* Translate residual energy to bits using high-rate assumption (6 dB ==> 1 bit/sample) */
+ bits_res_Q8 = silk_SMULBB( subfr_len, silk_lin2log( sum1_Q15 + penalty) - (15 << 7) );
+ /* In the following line we reduce the codelength component by half ("-1"); seems to slightly improve quality */
+ bits_tot_Q8 = silk_ADD_LSHIFT32( bits_res_Q8, cl_Q5[ k ], 3-1 );
+ if( bits_tot_Q8 <= *rate_dist_Q8 ) {
+ *rate_dist_Q8 = bits_tot_Q8;
+ *res_nrg_Q15 = sum1_Q15 + penalty;
+ *ind = (opus_int8)k;
+ *gain_Q7 = gain_tmp_Q7;
+ }
}
/* Go to next cbk vector */
diff --git a/libs/libopus/silk/arm/LPC_inv_pred_gain_arm.h b/libs/libopus/silk/arm/LPC_inv_pred_gain_arm.h
new file mode 100644
index 000000000..9895b555c
--- /dev/null
+++ b/libs/libopus/silk/arm/LPC_inv_pred_gain_arm.h
@@ -0,0 +1,57 @@
+/***********************************************************************
+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.
+***********************************************************************/
+
+#ifndef SILK_LPC_INV_PRED_GAIN_ARM_H
+# define SILK_LPC_INV_PRED_GAIN_ARM_H
+
+# include "celt/arm/armcpu.h"
+
+# if defined(OPUS_ARM_MAY_HAVE_NEON_INTR)
+opus_int32 silk_LPC_inverse_pred_gain_neon( /* O Returns inverse prediction gain in energy domain, Q30 */
+ const opus_int16 *A_Q12, /* I Prediction coefficients, Q12 [order] */
+ const opus_int order /* I Prediction order */
+);
+
+# if !defined(OPUS_HAVE_RTCD) && defined(OPUS_ARM_PRESUME_NEON)
+# define OVERRIDE_silk_LPC_inverse_pred_gain (1)
+# define silk_LPC_inverse_pred_gain(A_Q12, order, arch) ((void)(arch), PRESUME_NEON(silk_LPC_inverse_pred_gain)(A_Q12, order))
+# endif
+# endif
+
+# if !defined(OVERRIDE_silk_LPC_inverse_pred_gain)
+/*Is run-time CPU detection enabled on this platform?*/
+# if defined(OPUS_HAVE_RTCD) && (defined(OPUS_ARM_MAY_HAVE_NEON_INTR) && !defined(OPUS_ARM_PRESUME_NEON_INTR))
+extern opus_int32 (*const SILK_LPC_INVERSE_PRED_GAIN_IMPL[OPUS_ARCHMASK+1])(const opus_int16 *A_Q12, const opus_int order);
+# define OVERRIDE_silk_LPC_inverse_pred_gain (1)
+# define silk_LPC_inverse_pred_gain(A_Q12, order, arch) ((*SILK_LPC_INVERSE_PRED_GAIN_IMPL[(arch)&OPUS_ARCHMASK])(A_Q12, order))
+# elif defined(OPUS_ARM_PRESUME_NEON_INTR)
+# define OVERRIDE_silk_LPC_inverse_pred_gain (1)
+# define silk_LPC_inverse_pred_gain(A_Q12, order, arch) ((void)(arch), silk_LPC_inverse_pred_gain_neon(A_Q12, order))
+# endif
+# endif
+
+#endif /* end SILK_LPC_INV_PRED_GAIN_ARM_H */
diff --git a/libs/libopus/silk/arm/LPC_inv_pred_gain_neon_intr.c b/libs/libopus/silk/arm/LPC_inv_pred_gain_neon_intr.c
new file mode 100644
index 000000000..726e6667b
--- /dev/null
+++ b/libs/libopus/silk/arm/LPC_inv_pred_gain_neon_intr.c
@@ -0,0 +1,288 @@
+/***********************************************************************
+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 <arm_neon.h>
+#include "SigProc_FIX.h"
+#include "define.h"
+
+#define QA 24
+#define A_LIMIT SILK_FIX_CONST( 0.99975, QA )
+
+#define MUL32_FRAC_Q(a32, b32, Q) ((opus_int32)(silk_RSHIFT_ROUND64(silk_SMULL(a32, b32), Q)))
+
+/* The difficulty is how to judge a 64-bit signed integer tmp64 is 32-bit overflowed,
+ * since NEON has no 64-bit min, max or comparison instructions.
+ * A failed idea is to compare the results of vmovn(tmp64) and vqmovn(tmp64) whether they are equal or not.
+ * However, this idea fails when the tmp64 is something like 0xFFFFFFF980000000.
+ * Here we know that mult2Q >= 1, so the highest bit (bit 63, sign bit) of tmp64 must equal to bit 62.
+ * tmp64 was shifted left by 1 and we got tmp64'. If high_half(tmp64') != 0 and high_half(tmp64') != -1,
+ * then we know that bit 31 to bit 63 of tmp64 can not all be the sign bit, and therefore tmp64 is 32-bit overflowed.
+ * That is, we judge if tmp64' > 0x00000000FFFFFFFF, or tmp64' <= 0xFFFFFFFF00000000.
+ * We use narrowing shift right 31 bits to tmp32' to save data bandwidth and instructions.
+ * That is, we judge if tmp32' > 0x00000000, or tmp32' <= 0xFFFFFFFF.
+ */
+
+/* Compute inverse of LPC prediction gain, and */
+/* test if LPC coefficients are stable (all poles within unit circle) */
+static OPUS_INLINE opus_int32 LPC_inverse_pred_gain_QA_neon( /* O Returns inverse prediction gain in energy domain, Q30 */
+ opus_int32 A_QA[ SILK_MAX_ORDER_LPC ], /* I Prediction coefficients */
+ const opus_int order /* I Prediction order */
+)
+{
+ opus_int k, n, mult2Q;
+ opus_int32 invGain_Q30, rc_Q31, rc_mult1_Q30, rc_mult2, tmp1, tmp2;
+ opus_int32 max, min;
+ int32x4_t max_s32x4, min_s32x4;
+ int32x2_t max_s32x2, min_s32x2;
+
+ max_s32x4 = vdupq_n_s32( silk_int32_MIN );
+ min_s32x4 = vdupq_n_s32( silk_int32_MAX );
+ invGain_Q30 = SILK_FIX_CONST( 1, 30 );
+ for( k = order - 1; k > 0; k-- ) {
+ int32x2_t rc_Q31_s32x2, rc_mult2_s32x2;
+ int64x2_t mult2Q_s64x2;
+
+ /* Check for stability */
+ if( ( A_QA[ k ] > A_LIMIT ) || ( A_QA[ k ] < -A_LIMIT ) ) {
+ return 0;
+ }
+
+ /* Set RC equal to negated AR coef */
+ rc_Q31 = -silk_LSHIFT( A_QA[ k ], 31 - QA );
+
+ /* rc_mult1_Q30 range: [ 1 : 2^30 ] */
+ rc_mult1_Q30 = silk_SUB32( SILK_FIX_CONST( 1, 30 ), silk_SMMUL( rc_Q31, rc_Q31 ) );
+ silk_assert( rc_mult1_Q30 > ( 1 << 15 ) ); /* reduce A_LIMIT if fails */
+ silk_assert( rc_mult1_Q30 <= ( 1 << 30 ) );
+
+ /* Update inverse gain */
+ /* invGain_Q30 range: [ 0 : 2^30 ] */
+ invGain_Q30 = silk_LSHIFT( silk_SMMUL( invGain_Q30, rc_mult1_Q30 ), 2 );
+ silk_assert( invGain_Q30 >= 0 );
+ silk_assert( invGain_Q30 <= ( 1 << 30 ) );
+ if( invGain_Q30 < SILK_FIX_CONST( 1.0f / MAX_PREDICTION_POWER_GAIN, 30 ) ) {
+ return 0;
+ }
+
+ /* rc_mult2 range: [ 2^30 : silk_int32_MAX ] */
+ mult2Q = 32 - silk_CLZ32( silk_abs( rc_mult1_Q30 ) );
+ rc_mult2 = silk_INVERSE32_varQ( rc_mult1_Q30, mult2Q + 30 );
+
+ /* Update AR coefficient */
+ rc_Q31_s32x2 = vdup_n_s32( rc_Q31 );
+ mult2Q_s64x2 = vdupq_n_s64( -mult2Q );
+ rc_mult2_s32x2 = vdup_n_s32( rc_mult2 );
+
+ for( n = 0; n < ( ( k + 1 ) >> 1 ) - 3; n += 4 ) {
+ /* We always calculate extra elements of A_QA buffer when ( k % 4 ) != 0, to take the advantage of SIMD parallelization. */
+ int32x4_t tmp1_s32x4, tmp2_s32x4, t0_s32x4, t1_s32x4, s0_s32x4, s1_s32x4, t_QA0_s32x4, t_QA1_s32x4;
+ int64x2_t t0_s64x2, t1_s64x2, t2_s64x2, t3_s64x2;
+ tmp1_s32x4 = vld1q_s32( A_QA + n );
+ tmp2_s32x4 = vld1q_s32( A_QA + k - n - 4 );
+ tmp2_s32x4 = vrev64q_s32( tmp2_s32x4 );
+ tmp2_s32x4 = vcombine_s32( vget_high_s32( tmp2_s32x4 ), vget_low_s32( tmp2_s32x4 ) );
+ t0_s32x4 = vqrdmulhq_lane_s32( tmp2_s32x4, rc_Q31_s32x2, 0 );
+ t1_s32x4 = vqrdmulhq_lane_s32( tmp1_s32x4, rc_Q31_s32x2, 0 );
+ t_QA0_s32x4 = vqsubq_s32( tmp1_s32x4, t0_s32x4 );
+ t_QA1_s32x4 = vqsubq_s32( tmp2_s32x4, t1_s32x4 );
+ t0_s64x2 = vmull_s32( vget_low_s32 ( t_QA0_s32x4 ), rc_mult2_s32x2 );
+ t1_s64x2 = vmull_s32( vget_high_s32( t_QA0_s32x4 ), rc_mult2_s32x2 );
+ t2_s64x2 = vmull_s32( vget_low_s32 ( t_QA1_s32x4 ), rc_mult2_s32x2 );
+ t3_s64x2 = vmull_s32( vget_high_s32( t_QA1_s32x4 ), rc_mult2_s32x2 );
+ t0_s64x2 = vrshlq_s64( t0_s64x2, mult2Q_s64x2 );
+ t1_s64x2 = vrshlq_s64( t1_s64x2, mult2Q_s64x2 );
+ t2_s64x2 = vrshlq_s64( t2_s64x2, mult2Q_s64x2 );
+ t3_s64x2 = vrshlq_s64( t3_s64x2, mult2Q_s64x2 );
+ t0_s32x4 = vcombine_s32( vmovn_s64( t0_s64x2 ), vmovn_s64( t1_s64x2 ) );
+ t1_s32x4 = vcombine_s32( vmovn_s64( t2_s64x2 ), vmovn_s64( t3_s64x2 ) );
+ s0_s32x4 = vcombine_s32( vshrn_n_s64( t0_s64x2, 31 ), vshrn_n_s64( t1_s64x2, 31 ) );
+ s1_s32x4 = vcombine_s32( vshrn_n_s64( t2_s64x2, 31 ), vshrn_n_s64( t3_s64x2, 31 ) );
+ max_s32x4 = vmaxq_s32( max_s32x4, s0_s32x4 );
+ min_s32x4 = vminq_s32( min_s32x4, s0_s32x4 );
+ max_s32x4 = vmaxq_s32( max_s32x4, s1_s32x4 );
+ min_s32x4 = vminq_s32( min_s32x4, s1_s32x4 );
+ t1_s32x4 = vrev64q_s32( t1_s32x4 );
+ t1_s32x4 = vcombine_s32( vget_high_s32( t1_s32x4 ), vget_low_s32( t1_s32x4 ) );
+ vst1q_s32( A_QA + n, t0_s32x4 );
+ vst1q_s32( A_QA + k - n - 4, t1_s32x4 );
+ }
+ for( ; n < (k + 1) >> 1; n++ ) {
+ opus_int64 tmp64;
+ tmp1 = A_QA[ n ];
+ tmp2 = A_QA[ k - n - 1 ];
+ tmp64 = silk_RSHIFT_ROUND64( silk_SMULL( silk_SUB_SAT32(tmp1,
+ MUL32_FRAC_Q( tmp2, rc_Q31, 31 ) ), rc_mult2 ), mult2Q);
+ if( tmp64 > silk_int32_MAX || tmp64 < silk_int32_MIN ) {
+ return 0;
+ }
+ A_QA[ n ] = ( opus_int32 )tmp64;
+ tmp64 = silk_RSHIFT_ROUND64( silk_SMULL( silk_SUB_SAT32(tmp2,
+ MUL32_FRAC_Q( tmp1, rc_Q31, 31 ) ), rc_mult2), mult2Q);
+ if( tmp64 > silk_int32_MAX || tmp64 < silk_int32_MIN ) {
+ return 0;
+ }
+ A_QA[ k - n - 1 ] = ( opus_int32 )tmp64;
+ }
+ }
+
+ /* Check for stability */
+ if( ( A_QA[ k ] > A_LIMIT ) || ( A_QA[ k ] < -A_LIMIT ) ) {
+ return 0;
+ }
+
+ max_s32x2 = vmax_s32( vget_low_s32( max_s32x4 ), vget_high_s32( max_s32x4 ) );
+ min_s32x2 = vmin_s32( vget_low_s32( min_s32x4 ), vget_high_s32( min_s32x4 ) );
+ max_s32x2 = vmax_s32( max_s32x2, vreinterpret_s32_s64( vshr_n_s64( vreinterpret_s64_s32( max_s32x2 ), 32 ) ) );
+ min_s32x2 = vmin_s32( min_s32x2, vreinterpret_s32_s64( vshr_n_s64( vreinterpret_s64_s32( min_s32x2 ), 32 ) ) );
+ max = vget_lane_s32( max_s32x2, 0 );
+ min = vget_lane_s32( min_s32x2, 0 );
+ if( ( max > 0 ) || ( min < -1 ) ) {
+ return 0;
+ }
+
+ /* Set RC equal to negated AR coef */
+ rc_Q31 = -silk_LSHIFT( A_QA[ 0 ], 31 - QA );
+
+ /* Range: [ 1 : 2^30 ] */
+ rc_mult1_Q30 = silk_SUB32( SILK_FIX_CONST( 1, 30 ), silk_SMMUL( rc_Q31, rc_Q31 ) );
+
+ /* Update inverse gain */
+ /* Range: [ 0 : 2^30 ] */
+ invGain_Q30 = silk_LSHIFT( silk_SMMUL( invGain_Q30, rc_mult1_Q30 ), 2 );
+ silk_assert( invGain_Q30 >= 0 );
+ silk_assert( invGain_Q30 <= ( 1 << 30 ) );
+ if( invGain_Q30 < SILK_FIX_CONST( 1.0f / MAX_PREDICTION_POWER_GAIN, 30 ) ) {
+ return 0;
+ }
+
+ return invGain_Q30;
+}
+
+/* For input in Q12 domain */
+opus_int32 silk_LPC_inverse_pred_gain_neon( /* O Returns inverse prediction gain in energy domain, Q30 */
+ const opus_int16 *A_Q12, /* I Prediction coefficients, Q12 [order] */
+ const opus_int order /* I Prediction order */
+)
+{
+#ifdef OPUS_CHECK_ASM
+ const opus_int32 invGain_Q30_c = silk_LPC_inverse_pred_gain_c( A_Q12, order );
+#endif
+
+ opus_int32 invGain_Q30;
+ if( ( SILK_MAX_ORDER_LPC != 24 ) || ( order & 1 )) {
+ invGain_Q30 = silk_LPC_inverse_pred_gain_c( A_Q12, order );
+ }
+ else {
+ opus_int32 Atmp_QA[ SILK_MAX_ORDER_LPC ];
+ opus_int32 DC_resp;
+ int16x8_t t0_s16x8, t1_s16x8, t2_s16x8;
+ int32x4_t t0_s32x4;
+ const opus_int leftover = order & 7;
+
+ /* Increase Q domain of the AR coefficients */
+ t0_s16x8 = vld1q_s16( A_Q12 + 0 );
+ t1_s16x8 = vld1q_s16( A_Q12 + 8 );
+ if ( order > 16 ) {
+ t2_s16x8 = vld1q_s16( A_Q12 + 16 );
+ }
+ t0_s32x4 = vpaddlq_s16( t0_s16x8 );
+
+ switch( order - leftover )
+ {
+ case 24:
+ t0_s32x4 = vpadalq_s16( t0_s32x4, t2_s16x8 );
+ vst1q_s32( Atmp_QA + 16, vshll_n_s16( vget_low_s16 ( t2_s16x8 ), QA - 12 ) );
+ vst1q_s32( Atmp_QA + 20, vshll_n_s16( vget_high_s16( t2_s16x8 ), QA - 12 ) );
+ /* FALLTHROUGH */
+
+ case 16:
+ t0_s32x4 = vpadalq_s16( t0_s32x4, t1_s16x8 );
+ vst1q_s32( Atmp_QA + 8, vshll_n_s16( vget_low_s16 ( t1_s16x8 ), QA - 12 ) );
+ vst1q_s32( Atmp_QA + 12, vshll_n_s16( vget_high_s16( t1_s16x8 ), QA - 12 ) );
+ /* FALLTHROUGH */
+
+ case 8:
+ {
+ const int32x2_t t_s32x2 = vpadd_s32( vget_low_s32( t0_s32x4 ), vget_high_s32( t0_s32x4 ) );
+ const int64x1_t t_s64x1 = vpaddl_s32( t_s32x2 );
+ DC_resp = vget_lane_s32( vreinterpret_s32_s64( t_s64x1 ), 0 );
+ vst1q_s32( Atmp_QA + 0, vshll_n_s16( vget_low_s16 ( t0_s16x8 ), QA - 12 ) );
+ vst1q_s32( Atmp_QA + 4, vshll_n_s16( vget_high_s16( t0_s16x8 ), QA - 12 ) );
+ }
+ break;
+
+ default:
+ DC_resp = 0;
+ break;
+ }
+ A_Q12 += order - leftover;
+
+ switch( leftover )
+ {
+ case 6:
+ DC_resp += (opus_int32)A_Q12[ 5 ];
+ DC_resp += (opus_int32)A_Q12[ 4 ];
+ Atmp_QA[ order - leftover + 5 ] = silk_LSHIFT32( (opus_int32)A_Q12[ 5 ], QA - 12 );
+ Atmp_QA[ order - leftover + 4 ] = silk_LSHIFT32( (opus_int32)A_Q12[ 4 ], QA - 12 );
+ /* FALLTHROUGH */
+
+ case 4:
+ DC_resp += (opus_int32)A_Q12[ 3 ];
+ DC_resp += (opus_int32)A_Q12[ 2 ];
+ Atmp_QA[ order - leftover + 3 ] = silk_LSHIFT32( (opus_int32)A_Q12[ 3 ], QA - 12 );
+ Atmp_QA[ order - leftover + 2 ] = silk_LSHIFT32( (opus_int32)A_Q12[ 2 ], QA - 12 );
+ /* FALLTHROUGH */
+
+ case 2:
+ DC_resp += (opus_int32)A_Q12[ 1 ];
+ DC_resp += (opus_int32)A_Q12[ 0 ];
+ Atmp_QA[ order - leftover + 1 ] = silk_LSHIFT32( (opus_int32)A_Q12[ 1 ], QA - 12 );
+ Atmp_QA[ order - leftover + 0 ] = silk_LSHIFT32( (opus_int32)A_Q12[ 0 ], QA - 12 );
+ /* FALLTHROUGH */
+
+ default:
+ break;
+ }
+
+ /* If the DC is unstable, we don't even need to do the full calculations */
+ if( DC_resp >= 4096 ) {
+ invGain_Q30 = 0;
+ } else {
+ invGain_Q30 = LPC_inverse_pred_gain_QA_neon( Atmp_QA, order );
+ }
+ }
+
+#ifdef OPUS_CHECK_ASM
+ silk_assert( invGain_Q30_c == invGain_Q30 );
+#endif
+
+ return invGain_Q30;
+}
diff --git a/libs/libopus/silk/arm/NSQ_del_dec_arm.h b/libs/libopus/silk/arm/NSQ_del_dec_arm.h
new file mode 100644
index 000000000..9e76e1692
--- /dev/null
+++ b/libs/libopus/silk/arm/NSQ_del_dec_arm.h
@@ -0,0 +1,100 @@
+/***********************************************************************
+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.
+***********************************************************************/
+
+#ifndef SILK_NSQ_DEL_DEC_ARM_H
+#define SILK_NSQ_DEL_DEC_ARM_H
+
+#include "celt/arm/armcpu.h"
+
+#if defined(OPUS_ARM_MAY_HAVE_NEON_INTR)
+void silk_NSQ_del_dec_neon(
+ const silk_encoder_state *psEncC, silk_nsq_state *NSQ,
+ SideInfoIndices *psIndices, const opus_int16 x16[], opus_int8 pulses[],
+ const opus_int16 PredCoef_Q12[2 * MAX_LPC_ORDER],
+ const opus_int16 LTPCoef_Q14[LTP_ORDER * MAX_NB_SUBFR],
+ const opus_int16 AR_Q13[MAX_NB_SUBFR * MAX_SHAPE_LPC_ORDER],
+ const opus_int HarmShapeGain_Q14[MAX_NB_SUBFR],
+ const opus_int Tilt_Q14[MAX_NB_SUBFR],
+ const opus_int32 LF_shp_Q14[MAX_NB_SUBFR],
+ const opus_int32 Gains_Q16[MAX_NB_SUBFR],
+ const opus_int pitchL[MAX_NB_SUBFR], const opus_int Lambda_Q10,
+ const opus_int LTP_scale_Q14);
+
+#if !defined(OPUS_HAVE_RTCD)
+#define OVERRIDE_silk_NSQ_del_dec (1)
+#define silk_NSQ_del_dec(psEncC, NSQ, psIndices, x16, pulses, PredCoef_Q12, \
+ LTPCoef_Q14, AR_Q13, HarmShapeGain_Q14, Tilt_Q14, \
+ LF_shp_Q14, Gains_Q16, pitchL, Lambda_Q10, \
+ LTP_scale_Q14, arch) \
+ ((void)(arch), \
+ PRESUME_NEON(silk_NSQ_del_dec)( \
+ psEncC, NSQ, psIndices, x16, pulses, PredCoef_Q12, LTPCoef_Q14, \
+ AR_Q13, HarmShapeGain_Q14, Tilt_Q14, LF_shp_Q14, Gains_Q16, pitchL, \
+ Lambda_Q10, LTP_scale_Q14))
+#endif
+#endif
+
+#if !defined(OVERRIDE_silk_NSQ_del_dec)
+/*Is run-time CPU detection enabled on this platform?*/
+#if defined(OPUS_HAVE_RTCD) && (defined(OPUS_ARM_MAY_HAVE_NEON_INTR) && \
+ !defined(OPUS_ARM_PRESUME_NEON_INTR))
+extern void (*const SILK_NSQ_DEL_DEC_IMPL[OPUS_ARCHMASK + 1])(
+ const silk_encoder_state *psEncC, silk_nsq_state *NSQ,
+ SideInfoIndices *psIndices, const opus_int16 x16[], opus_int8 pulses[],
+ const opus_int16 PredCoef_Q12[2 * MAX_LPC_ORDER],
+ const opus_int16 LTPCoef_Q14[LTP_ORDER * MAX_NB_SUBFR],
+ const opus_int16 AR_Q13[MAX_NB_SUBFR * MAX_SHAPE_LPC_ORDER],
+ const opus_int HarmShapeGain_Q14[MAX_NB_SUBFR],
+ const opus_int Tilt_Q14[MAX_NB_SUBFR],
+ const opus_int32 LF_shp_Q14[MAX_NB_SUBFR],
+ const opus_int32 Gains_Q16[MAX_NB_SUBFR],
+ const opus_int pitchL[MAX_NB_SUBFR], const opus_int Lambda_Q10,
+ const opus_int LTP_scale_Q14);
+#define OVERRIDE_silk_NSQ_del_dec (1)
+#define silk_NSQ_del_dec(psEncC, NSQ, psIndices, x16, pulses, PredCoef_Q12, \
+ LTPCoef_Q14, AR_Q13, HarmShapeGain_Q14, Tilt_Q14, \
+ LF_shp_Q14, Gains_Q16, pitchL, Lambda_Q10, \
+ LTP_scale_Q14, arch) \
+ ((*SILK_NSQ_DEL_DEC_IMPL[(arch)&OPUS_ARCHMASK])( \
+ psEncC, NSQ, psIndices, x16, pulses, PredCoef_Q12, LTPCoef_Q14, \
+ AR_Q13, HarmShapeGain_Q14, Tilt_Q14, LF_shp_Q14, Gains_Q16, pitchL, \
+ Lambda_Q10, LTP_scale_Q14))
+#elif defined(OPUS_ARM_PRESUME_NEON_INTR)
+#define OVERRIDE_silk_NSQ_del_dec (1)
+#define silk_NSQ_del_dec(psEncC, NSQ, psIndices, x16, pulses, PredCoef_Q12, \
+ LTPCoef_Q14, AR_Q13, HarmShapeGain_Q14, Tilt_Q14, \
+ LF_shp_Q14, Gains_Q16, pitchL, Lambda_Q10, \
+ LTP_scale_Q14, arch) \
+ ((void)(arch), \
+ silk_NSQ_del_dec_neon(psEncC, NSQ, psIndices, x16, pulses, PredCoef_Q12, \
+ LTPCoef_Q14, AR_Q13, HarmShapeGain_Q14, Tilt_Q14, \
+ LF_shp_Q14, Gains_Q16, pitchL, Lambda_Q10, \
+ LTP_scale_Q14))
+#endif
+#endif
+
+#endif /* end SILK_NSQ_DEL_DEC_ARM_H */
diff --git a/libs/libopus/silk/arm/NSQ_del_dec_neon_intr.c b/libs/libopus/silk/arm/NSQ_del_dec_neon_intr.c
new file mode 100644
index 000000000..212410f36
--- /dev/null
+++ b/libs/libopus/silk/arm/NSQ_del_dec_neon_intr.c
@@ -0,0 +1,1124 @@
+/***********************************************************************
+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 <arm_neon.h>
+#ifdef OPUS_CHECK_ASM
+# include <string.h>
+#endif
+#include "main.h"
+#include "stack_alloc.h"
+
+/* NEON intrinsics optimization now can only parallelize up to 4 delay decision states. */
+/* If there are more states, C function is called, and this optimization must be expanded. */
+#define NEON_MAX_DEL_DEC_STATES 4
+
+typedef struct {
+ opus_int32 sLPC_Q14[ MAX_SUB_FRAME_LENGTH + NSQ_LPC_BUF_LENGTH ][ NEON_MAX_DEL_DEC_STATES ];
+ opus_int32 RandState[ DECISION_DELAY ][ NEON_MAX_DEL_DEC_STATES ];
+ opus_int32 Q_Q10[ DECISION_DELAY ][ NEON_MAX_DEL_DEC_STATES ];
+ opus_int32 Xq_Q14[ DECISION_DELAY ][ NEON_MAX_DEL_DEC_STATES ];
+ opus_int32 Pred_Q15[ DECISION_DELAY ][ NEON_MAX_DEL_DEC_STATES ];
+ opus_int32 Shape_Q14[ DECISION_DELAY ][ NEON_MAX_DEL_DEC_STATES ];
+ opus_int32 sAR2_Q14[ MAX_SHAPE_LPC_ORDER ][ NEON_MAX_DEL_DEC_STATES ];
+ opus_int32 LF_AR_Q14[ NEON_MAX_DEL_DEC_STATES ];
+ opus_int32 Diff_Q14[ NEON_MAX_DEL_DEC_STATES ];
+ opus_int32 Seed[ NEON_MAX_DEL_DEC_STATES ];
+ opus_int32 SeedInit[ NEON_MAX_DEL_DEC_STATES ];
+ opus_int32 RD_Q10[ NEON_MAX_DEL_DEC_STATES ];
+} NSQ_del_decs_struct;
+
+typedef struct {
+ opus_int32 Q_Q10[ NEON_MAX_DEL_DEC_STATES ];
+ opus_int32 RD_Q10[ NEON_MAX_DEL_DEC_STATES ];
+ opus_int32 xq_Q14[ NEON_MAX_DEL_DEC_STATES ];
+ opus_int32 LF_AR_Q14[ NEON_MAX_DEL_DEC_STATES ];
+ opus_int32 Diff_Q14[ NEON_MAX_DEL_DEC_STATES ];
+ opus_int32 sLTP_shp_Q14[ NEON_MAX_DEL_DEC_STATES ];
+ opus_int32 LPC_exc_Q14[ NEON_MAX_DEL_DEC_STATES ];
+} NSQ_samples_struct;
+
+static OPUS_INLINE void silk_nsq_del_dec_scale_states_neon(
+ const silk_encoder_state *psEncC, /* I Encoder State */
+ silk_nsq_state *NSQ, /* I/O NSQ state */
+ NSQ_del_decs_struct psDelDec[], /* I/O Delayed decision states */
+ const opus_int16 x16[], /* I Input */
+ opus_int32 x_sc_Q10[], /* O Input scaled with 1/Gain in Q10 */
+ const opus_int16 sLTP[], /* I Re-whitened LTP state in Q0 */
+ opus_int32 sLTP_Q15[], /* O LTP state matching scaled input */
+ opus_int subfr, /* I Subframe number */
+ const opus_int LTP_scale_Q14, /* I LTP state scaling */
+ const opus_int32 Gains_Q16[ MAX_NB_SUBFR ], /* I */
+ const opus_int pitchL[ MAX_NB_SUBFR ], /* I Pitch lag */
+ const opus_int signal_type, /* I Signal type */
+ const opus_int decisionDelay /* I Decision delay */
+);
+
+/******************************************/
+/* Noise shape quantizer for one subframe */
+/******************************************/
+static OPUS_INLINE void silk_noise_shape_quantizer_del_dec_neon(
+ silk_nsq_state *NSQ, /* I/O NSQ state */
+ NSQ_del_decs_struct psDelDec[], /* I/O Delayed decision states */
+ opus_int signalType, /* I Signal type */
+ const opus_int32 x_Q10[], /* I */
+ opus_int8 pulses[], /* O */
+ opus_int16 xq[], /* O */
+ opus_int32 sLTP_Q15[], /* I/O LTP filter state */
+ opus_int32 delayedGain_Q10[], /* I/O Gain delay buffer */
+ const opus_int16 a_Q12[], /* I Short term prediction coefs */
+ const opus_int16 b_Q14[], /* I Long term prediction coefs */
+ const opus_int16 AR_shp_Q13[], /* I Noise shaping coefs */
+ opus_int lag, /* I Pitch lag */
+ opus_int32 HarmShapeFIRPacked_Q14, /* I */
+ opus_int Tilt_Q14, /* I Spectral tilt */
+ opus_int32 LF_shp_Q14, /* I */
+ opus_int32 Gain_Q16, /* I */
+ opus_int Lambda_Q10, /* I */
+ opus_int offset_Q10, /* I */
+ opus_int length, /* I Input length */
+ opus_int subfr, /* I Subframe number */
+ opus_int shapingLPCOrder, /* I Shaping LPC filter order */
+ opus_int predictLPCOrder, /* I Prediction filter order */
+ opus_int warping_Q16, /* I */
+ opus_int nStatesDelayedDecision, /* I Number of states in decision tree */
+ opus_int *smpl_buf_idx, /* I/O Index to newest samples in buffers */
+ opus_int decisionDelay /* I */
+);
+
+static OPUS_INLINE void copy_winner_state_kernel(
+ const NSQ_del_decs_struct *psDelDec,
+ const opus_int offset,
+ const opus_int last_smple_idx,
+ const opus_int Winner_ind,
+ const int32x2_t gain_lo_s32x2,
+ const int32x2_t gain_hi_s32x2,
+ const int32x4_t shift_s32x4,
+ int32x4_t t0_s32x4,
+ int32x4_t t1_s32x4,
+ opus_int8 *const pulses,
+ opus_int16 *pxq,
+ silk_nsq_state *NSQ
+)
+{
+ int16x8_t t_s16x8;
+ int32x4_t o0_s32x4, o1_s32x4;
+
+ t0_s32x4 = vld1q_lane_s32( &psDelDec->Q_Q10[ last_smple_idx - 0 ][ Winner_ind ], t0_s32x4, 0 );
+ t0_s32x4 = vld1q_lane_s32( &psDelDec->Q_Q10[ last_smple_idx - 1 ][ Winner_ind ], t0_s32x4, 1 );
+ t0_s32x4 = vld1q_lane_s32( &psDelDec->Q_Q10[ last_smple_idx - 2 ][ Winner_ind ], t0_s32x4, 2 );
+ t0_s32x4 = vld1q_lane_s32( &psDelDec->Q_Q10[ last_smple_idx - 3 ][ Winner_ind ], t0_s32x4, 3 );
+ t1_s32x4 = vld1q_lane_s32( &psDelDec->Q_Q10[ last_smple_idx - 4 ][ Winner_ind ], t1_s32x4, 0 );
+ t1_s32x4 = vld1q_lane_s32( &psDelDec->Q_Q10[ last_smple_idx - 5 ][ Winner_ind ], t1_s32x4, 1 );
+ t1_s32x4 = vld1q_lane_s32( &psDelDec->Q_Q10[ last_smple_idx - 6 ][ Winner_ind ], t1_s32x4, 2 );
+ t1_s32x4 = vld1q_lane_s32( &psDelDec->Q_Q10[ last_smple_idx - 7 ][ Winner_ind ], t1_s32x4, 3 );
+ t_s16x8 = vcombine_s16( vrshrn_n_s32( t0_s32x4, 10 ), vrshrn_n_s32( t1_s32x4, 10 ) );
+ vst1_s8( &pulses[ offset ], vmovn_s16( t_s16x8 ) );
+
+ t0_s32x4 = vld1q_lane_s32( &psDelDec->Xq_Q14[ last_smple_idx - 0 ][ Winner_ind ], t0_s32x4, 0 );
+ t0_s32x4 = vld1q_lane_s32( &psDelDec->Xq_Q14[ last_smple_idx - 1 ][ Winner_ind ], t0_s32x4, 1 );
+ t0_s32x4 = vld1q_lane_s32( &psDelDec->Xq_Q14[ last_smple_idx - 2 ][ Winner_ind ], t0_s32x4, 2 );
+ t0_s32x4 = vld1q_lane_s32( &psDelDec->Xq_Q14[ last_smple_idx - 3 ][ Winner_ind ], t0_s32x4, 3 );
+ t1_s32x4 = vld1q_lane_s32( &psDelDec->Xq_Q14[ last_smple_idx - 4 ][ Winner_ind ], t1_s32x4, 0 );
+ t1_s32x4 = vld1q_lane_s32( &psDelDec->Xq_Q14[ last_smple_idx - 5 ][ Winner_ind ], t1_s32x4, 1 );
+ t1_s32x4 = vld1q_lane_s32( &psDelDec->Xq_Q14[ last_smple_idx - 6 ][ Winner_ind ], t1_s32x4, 2 );
+ t1_s32x4 = vld1q_lane_s32( &psDelDec->Xq_Q14[ last_smple_idx - 7 ][ Winner_ind ], t1_s32x4, 3 );
+ o0_s32x4 = vqdmulhq_lane_s32( t0_s32x4, gain_lo_s32x2, 0 );
+ o1_s32x4 = vqdmulhq_lane_s32( t1_s32x4, gain_lo_s32x2, 0 );
+ o0_s32x4 = vmlaq_lane_s32( o0_s32x4, t0_s32x4, gain_hi_s32x2, 0 );
+ o1_s32x4 = vmlaq_lane_s32( o1_s32x4, t1_s32x4, gain_hi_s32x2, 0 );
+ o0_s32x4 = vrshlq_s32( o0_s32x4, shift_s32x4 );
+ o1_s32x4 = vrshlq_s32( o1_s32x4, shift_s32x4 );
+ vst1_s16( &pxq[ offset + 0 ], vqmovn_s32( o0_s32x4 ) );
+ vst1_s16( &pxq[ offset + 4 ], vqmovn_s32( o1_s32x4 ) );
+
+ t0_s32x4 = vld1q_lane_s32( &psDelDec->Shape_Q14[ last_smple_idx - 0 ][ Winner_ind ], t0_s32x4, 0 );
+ t0_s32x4 = vld1q_lane_s32( &psDelDec->Shape_Q14[ last_smple_idx - 1 ][ Winner_ind ], t0_s32x4, 1 );
+ t0_s32x4 = vld1q_lane_s32( &psDelDec->Shape_Q14[ last_smple_idx - 2 ][ Winner_ind ], t0_s32x4, 2 );
+ t0_s32x4 = vld1q_lane_s32( &psDelDec->Shape_Q14[ last_smple_idx - 3 ][ Winner_ind ], t0_s32x4, 3 );
+ t1_s32x4 = vld1q_lane_s32( &psDelDec->Shape_Q14[ last_smple_idx - 4 ][ Winner_ind ], t1_s32x4, 0 );
+ t1_s32x4 = vld1q_lane_s32( &psDelDec->Shape_Q14[ last_smple_idx - 5 ][ Winner_ind ], t1_s32x4, 1 );
+ t1_s32x4 = vld1q_lane_s32( &psDelDec->Shape_Q14[ last_smple_idx - 6 ][ Winner_ind ], t1_s32x4, 2 );
+ t1_s32x4 = vld1q_lane_s32( &psDelDec->Shape_Q14[ last_smple_idx - 7 ][ Winner_ind ], t1_s32x4, 3 );
+ vst1q_s32( &NSQ->sLTP_shp_Q14[ NSQ->sLTP_shp_buf_idx + offset + 0 ], t0_s32x4 );
+ vst1q_s32( &NSQ->sLTP_shp_Q14[ NSQ->sLTP_shp_buf_idx + offset + 4 ], t1_s32x4 );
+}
+
+static OPUS_INLINE void copy_winner_state(
+ const NSQ_del_decs_struct *psDelDec,
+ const opus_int decisionDelay,
+ const opus_int smpl_buf_idx,
+ const opus_int Winner_ind,
+ const opus_int32 gain,
+ const opus_int32 shift,
+ opus_int8 *const pulses,
+ opus_int16 *pxq,
+ silk_nsq_state *NSQ
+)
+{
+ opus_int i, last_smple_idx;
+ const int32x2_t gain_lo_s32x2 = vdup_n_s32( silk_LSHIFT32( gain & 0x0000FFFF, 15 ) );
+ const int32x2_t gain_hi_s32x2 = vdup_n_s32( gain >> 16 );
+ const int32x4_t shift_s32x4 = vdupq_n_s32( -shift );
+ int32x4_t t0_s32x4, t1_s32x4;
+
+ t0_s32x4 = t1_s32x4 = vdupq_n_s32( 0 ); /* initialization */
+ last_smple_idx = smpl_buf_idx + decisionDelay - 1 + DECISION_DELAY;
+ if( last_smple_idx >= DECISION_DELAY ) last_smple_idx -= DECISION_DELAY;
+ if( last_smple_idx >= DECISION_DELAY ) last_smple_idx -= DECISION_DELAY;
+
+ for( i = 0; ( i < ( decisionDelay - 7 ) ) && ( last_smple_idx >= 7 ); i += 8, last_smple_idx -= 8 ) {
+ copy_winner_state_kernel( psDelDec, i - decisionDelay, last_smple_idx, Winner_ind, gain_lo_s32x2, gain_hi_s32x2, shift_s32x4, t0_s32x4, t1_s32x4, pulses, pxq, NSQ );
+ }
+ for( ; ( i < decisionDelay ) && ( last_smple_idx >= 0 ); i++, last_smple_idx-- ) {
+ pulses[ i - decisionDelay ] = (opus_int8)silk_RSHIFT_ROUND( psDelDec->Q_Q10[ last_smple_idx ][ Winner_ind ], 10 );
+ pxq[ i - decisionDelay ] = (opus_int16)silk_SAT16( silk_RSHIFT_ROUND( silk_SMULWW( psDelDec->Xq_Q14[ last_smple_idx ][ Winner_ind ], gain ), shift ) );
+ NSQ->sLTP_shp_Q14[ NSQ->sLTP_shp_buf_idx - decisionDelay + i ] = psDelDec->Shape_Q14[ last_smple_idx ][ Winner_ind ];
+ }
+
+ last_smple_idx += DECISION_DELAY;
+ for( ; i < ( decisionDelay - 7 ); i++, last_smple_idx-- ) {
+ copy_winner_state_kernel( psDelDec, i - decisionDelay, last_smple_idx, Winner_ind, gain_lo_s32x2, gain_hi_s32x2, shift_s32x4, t0_s32x4, t1_s32x4, pulses, pxq, NSQ );
+ }
+ for( ; i < decisionDelay; i++, last_smple_idx-- ) {
+ pulses[ i - decisionDelay ] = (opus_int8)silk_RSHIFT_ROUND( psDelDec->Q_Q10[ last_smple_idx ][ Winner_ind ], 10 );
+ pxq[ i - decisionDelay ] = (opus_int16)silk_SAT16( silk_RSHIFT_ROUND( silk_SMULWW( psDelDec->Xq_Q14[ last_smple_idx ][ Winner_ind ], gain ), shift ) );
+ NSQ->sLTP_shp_Q14[ NSQ->sLTP_shp_buf_idx - decisionDelay + i ] = psDelDec->Shape_Q14[ last_smple_idx ][ Winner_ind ];
+ }
+}
+
+void silk_NSQ_del_dec_neon(
+ const silk_encoder_state *psEncC, /* I Encoder State */
+ silk_nsq_state *NSQ, /* I/O NSQ state */
+ SideInfoIndices *psIndices, /* I/O Quantization Indices */
+ const opus_int16 x16[], /* I Input */
+ opus_int8 pulses[], /* O Quantized pulse signal */
+ const opus_int16 PredCoef_Q12[ 2 * MAX_LPC_ORDER ], /* I Short term prediction coefs */
+ const opus_int16 LTPCoef_Q14[ LTP_ORDER * MAX_NB_SUBFR ], /* I Long term prediction coefs */
+ const opus_int16 AR_Q13[ MAX_NB_SUBFR * MAX_SHAPE_LPC_ORDER ], /* I Noise shaping coefs */
+ const opus_int HarmShapeGain_Q14[ MAX_NB_SUBFR ], /* I Long term shaping coefs */
+ const opus_int Tilt_Q14[ MAX_NB_SUBFR ], /* I Spectral tilt */
+ const opus_int32 LF_shp_Q14[ MAX_NB_SUBFR ], /* I Low frequency shaping coefs */
+ const opus_int32 Gains_Q16[ MAX_NB_SUBFR ], /* I Quantization step sizes */
+ const opus_int pitchL[ MAX_NB_SUBFR ], /* I Pitch lags */
+ const opus_int Lambda_Q10, /* I Rate/distortion tradeoff */
+ const opus_int LTP_scale_Q14 /* I LTP state scaling */
+)
+{
+#ifdef OPUS_CHECK_ASM
+ silk_nsq_state NSQ_c;
+ SideInfoIndices psIndices_c;
+ opus_int8 pulses_c[ MAX_FRAME_LENGTH ];
+ const opus_int8 *const pulses_a = pulses;
+
+ ( void )pulses_a;
+ silk_memcpy( &NSQ_c, NSQ, sizeof( NSQ_c ) );
+ silk_memcpy( &psIndices_c, psIndices, sizeof( psIndices_c ) );
+ silk_memcpy( pulses_c, pulses, sizeof( pulses_c ) );
+ silk_NSQ_del_dec_c( psEncC, &NSQ_c, &psIndices_c, x16, pulses_c, PredCoef_Q12, LTPCoef_Q14, AR_Q13, HarmShapeGain_Q14, Tilt_Q14, LF_shp_Q14, Gains_Q16,
+ pitchL, Lambda_Q10, LTP_scale_Q14 );
+#endif
+
+ /* The optimization parallelizes the different delay decision states. */
+ if(( psEncC->nStatesDelayedDecision > NEON_MAX_DEL_DEC_STATES ) || ( psEncC->nStatesDelayedDecision <= 2 )) {
+ /* NEON intrinsics optimization now can only parallelize up to 4 delay decision states. */
+ /* If there are more states, C function is called, and this optimization must be expanded. */
+ /* When the number of delay decision states is less than 3, there are penalties using this */
+ /* optimization, and C function is called. */
+ /* When the number of delay decision states is 2, it's better to specialize another */
+ /* structure NSQ_del_dec2_struct and optimize with shorter NEON registers. (Low priority) */
+ silk_NSQ_del_dec_c( psEncC, NSQ, psIndices, x16, pulses, PredCoef_Q12, LTPCoef_Q14, AR_Q13, HarmShapeGain_Q14,
+ Tilt_Q14, LF_shp_Q14, Gains_Q16, pitchL, Lambda_Q10, LTP_scale_Q14 );
+ } else {
+ opus_int i, k, lag, start_idx, LSF_interpolation_flag, Winner_ind, subfr;
+ opus_int smpl_buf_idx, decisionDelay;
+ const opus_int16 *A_Q12, *B_Q14, *AR_shp_Q13;
+ opus_int16 *pxq;
+ VARDECL( opus_int32, sLTP_Q15 );
+ VARDECL( opus_int16, sLTP );
+ opus_int32 HarmShapeFIRPacked_Q14;
+ opus_int offset_Q10;
+ opus_int32 RDmin_Q10, Gain_Q10;
+ VARDECL( opus_int32, x_sc_Q10 );
+ VARDECL( opus_int32, delayedGain_Q10 );
+ VARDECL( NSQ_del_decs_struct, psDelDec );
+ int32x4_t t_s32x4;
+ SAVE_STACK;
+
+ /* Set unvoiced lag to the previous one, overwrite later for voiced */
+ lag = NSQ->lagPrev;
+
+ silk_assert( NSQ->prev_gain_Q16 != 0 );
+
+ /* Initialize delayed decision states */
+ ALLOC( psDelDec, 1, NSQ_del_decs_struct );
+ /* Only RandState and RD_Q10 need to be initialized to 0. */
+ silk_memset( psDelDec->RandState, 0, sizeof( psDelDec->RandState ) );
+ vst1q_s32( psDelDec->RD_Q10, vdupq_n_s32( 0 ) );
+
+ for( k = 0; k < psEncC->nStatesDelayedDecision; k++ ) {
+ psDelDec->SeedInit[ k ] = psDelDec->Seed[ k ] = ( k + psIndices->Seed ) & 3;
+ }
+ vst1q_s32( psDelDec->LF_AR_Q14, vld1q_dup_s32( &NSQ->sLF_AR_shp_Q14 ) );
+ vst1q_s32( psDelDec->Diff_Q14, vld1q_dup_s32( &NSQ->sDiff_shp_Q14 ) );
+ vst1q_s32( psDelDec->Shape_Q14[ 0 ], vld1q_dup_s32( &NSQ->sLTP_shp_Q14[ psEncC->ltp_mem_length - 1 ] ) );
+ for( i = 0; i < NSQ_LPC_BUF_LENGTH; i++ ) {
+ vst1q_s32( psDelDec->sLPC_Q14[ i ], vld1q_dup_s32( &NSQ->sLPC_Q14[ i ] ) );
+ }
+ for( i = 0; i < (opus_int)( sizeof( NSQ->sAR2_Q14 ) / sizeof( NSQ->sAR2_Q14[ 0 ] ) ); i++ ) {
+ vst1q_s32( psDelDec->sAR2_Q14[ i ], vld1q_dup_s32( &NSQ->sAR2_Q14[ i ] ) );
+ }
+
+ offset_Q10 = silk_Quantization_Offsets_Q10[ psIndices->signalType >> 1 ][ psIndices->quantOffsetType ];
+ smpl_buf_idx = 0; /* index of oldest samples */
+
+ decisionDelay = silk_min_int( DECISION_DELAY, psEncC->subfr_length );
+
+ /* For voiced frames limit the decision delay to lower than the pitch lag */
+ if( psIndices->signalType == TYPE_VOICED ) {
+ opus_int pitch_min = pitchL[ 0 ];
+ for( k = 1; k < psEncC->nb_subfr; k++ ) {
+ pitch_min = silk_min_int( pitch_min, pitchL[ k ] );
+ }
+ decisionDelay = silk_min_int( decisionDelay, pitch_min - LTP_ORDER / 2 - 1 );
+ } else {
+ if( lag > 0 ) {
+ decisionDelay = silk_min_int( decisionDelay, lag - LTP_ORDER / 2 - 1 );
+ }
+ }
+
+ if( psIndices->NLSFInterpCoef_Q2 == 4 ) {
+ LSF_interpolation_flag = 0;
+ } else {
+ LSF_interpolation_flag = 1;
+ }
+
+ ALLOC( sLTP_Q15, psEncC->ltp_mem_length + psEncC->frame_length, opus_int32 );
+ ALLOC( sLTP, psEncC->ltp_mem_length + psEncC->frame_length, opus_int16 );
+ ALLOC( x_sc_Q10, psEncC->subfr_length, opus_int32 );
+ ALLOC( delayedGain_Q10, DECISION_DELAY, opus_int32 );
+ /* Set up pointers to start of sub frame */
+ pxq = &NSQ->xq[ psEncC->ltp_mem_length ];
+ NSQ->sLTP_shp_buf_idx = psEncC->ltp_mem_length;
+ NSQ->sLTP_buf_idx = psEncC->ltp_mem_length;
+ subfr = 0;
+ for( k = 0; k < psEncC->nb_subfr; k++ ) {
+ A_Q12 = &PredCoef_Q12[ ( ( k >> 1 ) | ( 1 - LSF_interpolation_flag ) ) * MAX_LPC_ORDER ];
+ B_Q14 = &LTPCoef_Q14[ k * LTP_ORDER ];
+ AR_shp_Q13 = &AR_Q13[ k * MAX_SHAPE_LPC_ORDER ];
+
+ /* Noise shape parameters */
+ silk_assert( HarmShapeGain_Q14[ k ] >= 0 );
+ HarmShapeFIRPacked_Q14 = silk_RSHIFT( HarmShapeGain_Q14[ k ], 2 );
+ HarmShapeFIRPacked_Q14 |= silk_LSHIFT( (opus_int32)silk_RSHIFT( HarmShapeGain_Q14[ k ], 1 ), 16 );
+
+ NSQ->rewhite_flag = 0;
+ if( psIndices->signalType == TYPE_VOICED ) {
+ /* Voiced */
+ lag = pitchL[ k ];
+
+ /* Re-whitening */
+ if( ( k & ( 3 - silk_LSHIFT( LSF_interpolation_flag, 1 ) ) ) == 0 ) {
+ if( k == 2 ) {
+ /* RESET DELAYED DECISIONS */
+ /* Find winner */
+ int32x4_t RD_Q10_s32x4;
+ RDmin_Q10 = psDelDec->RD_Q10[ 0 ];
+ Winner_ind = 0;
+ for( i = 1; i < psEncC->nStatesDelayedDecision; i++ ) {
+ if( psDelDec->RD_Q10[ i ] < RDmin_Q10 ) {
+ RDmin_Q10 = psDelDec->RD_Q10[ i ];
+ Winner_ind = i;
+ }
+ }
+ psDelDec->RD_Q10[ Winner_ind ] -= ( silk_int32_MAX >> 4 );
+ RD_Q10_s32x4 = vld1q_s32( psDelDec->RD_Q10 );
+ RD_Q10_s32x4 = vaddq_s32( RD_Q10_s32x4, vdupq_n_s32( silk_int32_MAX >> 4 ) );
+ vst1q_s32( psDelDec->RD_Q10, RD_Q10_s32x4 );
+
+ /* Copy final part of signals from winner state to output and long-term filter states */
+ copy_winner_state( psDelDec, decisionDelay, smpl_buf_idx, Winner_ind, Gains_Q16[ 1 ], 14, pulses, pxq, NSQ );
+
+ subfr = 0;
+ }
+
+ /* Rewhiten with new A coefs */
+ start_idx = psEncC->ltp_mem_length - lag - psEncC->predictLPCOrder - LTP_ORDER / 2;
+ silk_assert( start_idx > 0 );
+
+ silk_LPC_analysis_filter( &sLTP[ start_idx ], &NSQ->xq[ start_idx + k * psEncC->subfr_length ],
+ A_Q12, psEncC->ltp_mem_length - start_idx, psEncC->predictLPCOrder, psEncC->arch );
+
+ NSQ->sLTP_buf_idx = psEncC->ltp_mem_length;
+ NSQ->rewhite_flag = 1;
+ }
+ }
+
+ silk_nsq_del_dec_scale_states_neon( psEncC, NSQ, psDelDec, x16, x_sc_Q10, sLTP, sLTP_Q15, k,
+ LTP_scale_Q14, Gains_Q16, pitchL, psIndices->signalType, decisionDelay );
+
+ silk_noise_shape_quantizer_del_dec_neon( NSQ, psDelDec, psIndices->signalType, x_sc_Q10, pulses, pxq, sLTP_Q15,
+ delayedGain_Q10, A_Q12, B_Q14, AR_shp_Q13, lag, HarmShapeFIRPacked_Q14, Tilt_Q14[ k ], LF_shp_Q14[ k ],
+ Gains_Q16[ k ], Lambda_Q10, offset_Q10, psEncC->subfr_length, subfr++, psEncC->shapingLPCOrder,
+ psEncC->predictLPCOrder, psEncC->warping_Q16, psEncC->nStatesDelayedDecision, &smpl_buf_idx, decisionDelay );
+
+ x16 += psEncC->subfr_length;
+ pulses += psEncC->subfr_length;
+ pxq += psEncC->subfr_length;
+ }
+
+ /* Find winner */
+ RDmin_Q10 = psDelDec->RD_Q10[ 0 ];
+ Winner_ind = 0;
+ for( k = 1; k < psEncC->nStatesDelayedDecision; k++ ) {
+ if( psDelDec->RD_Q10[ k ] < RDmin_Q10 ) {
+ RDmin_Q10 = psDelDec->RD_Q10[ k ];
+ Winner_ind = k;
+ }
+ }
+
+ /* Copy final part of signals from winner state to output and long-term filter states */
+ psIndices->Seed = psDelDec->SeedInit[ Winner_ind ];
+ Gain_Q10 = silk_RSHIFT32( Gains_Q16[ psEncC->nb_subfr - 1 ], 6 );
+ copy_winner_state( psDelDec, decisionDelay, smpl_buf_idx, Winner_ind, Gain_Q10, 8, pulses, pxq, NSQ );
+
+ t_s32x4 = vdupq_n_s32( 0 ); /* initialization */
+ for( i = 0; i < ( NSQ_LPC_BUF_LENGTH - 3 ); i += 4 ) {
+ t_s32x4 = vld1q_lane_s32( &psDelDec->sLPC_Q14[ i + 0 ][ Winner_ind ], t_s32x4, 0 );
+ t_s32x4 = vld1q_lane_s32( &psDelDec->sLPC_Q14[ i + 1 ][ Winner_ind ], t_s32x4, 1 );
+ t_s32x4 = vld1q_lane_s32( &psDelDec->sLPC_Q14[ i + 2 ][ Winner_ind ], t_s32x4, 2 );
+ t_s32x4 = vld1q_lane_s32( &psDelDec->sLPC_Q14[ i + 3 ][ Winner_ind ], t_s32x4, 3 );
+ vst1q_s32( &NSQ->sLPC_Q14[ i ], t_s32x4 );
+ }
+
+ for( ; i < NSQ_LPC_BUF_LENGTH; i++ ) {
+ NSQ->sLPC_Q14[ i ] = psDelDec->sLPC_Q14[ i ][ Winner_ind ];
+ }
+
+ for( i = 0; i < (opus_int)( sizeof( NSQ->sAR2_Q14 ) / sizeof( NSQ->sAR2_Q14[ 0 ] ) - 3 ); i += 4 ) {
+ t_s32x4 = vld1q_lane_s32( &psDelDec->sAR2_Q14[ i + 0 ][ Winner_ind ], t_s32x4, 0 );
+ t_s32x4 = vld1q_lane_s32( &psDelDec->sAR2_Q14[ i + 1 ][ Winner_ind ], t_s32x4, 1 );
+ t_s32x4 = vld1q_lane_s32( &psDelDec->sAR2_Q14[ i + 2 ][ Winner_ind ], t_s32x4, 2 );
+ t_s32x4 = vld1q_lane_s32( &psDelDec->sAR2_Q14[ i + 3 ][ Winner_ind ], t_s32x4, 3 );
+ vst1q_s32( &NSQ->sAR2_Q14[ i ], t_s32x4 );
+ }
+
+ for( ; i < (opus_int)( sizeof( NSQ->sAR2_Q14 ) / sizeof( NSQ->sAR2_Q14[ 0 ] ) ); i++ ) {
+ NSQ->sAR2_Q14[ i ] = psDelDec->sAR2_Q14[ i ][ Winner_ind ];
+ }
+
+ /* Update states */
+ NSQ->sLF_AR_shp_Q14 = psDelDec->LF_AR_Q14[ Winner_ind ];
+ NSQ->sDiff_shp_Q14 = psDelDec->Diff_Q14[ Winner_ind ];
+ NSQ->lagPrev = pitchL[ psEncC->nb_subfr - 1 ];
+
+ /* Save quantized speech signal */
+ silk_memmove( NSQ->xq, &NSQ->xq[ psEncC->frame_length ], psEncC->ltp_mem_length * sizeof( opus_int16 ) );
+ silk_memmove( NSQ->sLTP_shp_Q14, &NSQ->sLTP_shp_Q14[ psEncC->frame_length ], psEncC->ltp_mem_length * sizeof( opus_int32 ) );
+ RESTORE_STACK;
+ }
+
+#ifdef OPUS_CHECK_ASM
+ silk_assert( !memcmp( &NSQ_c, NSQ, sizeof( NSQ_c ) ) );
+ silk_assert( !memcmp( &psIndices_c, psIndices, sizeof( psIndices_c ) ) );
+ silk_assert( !memcmp( pulses_c, pulses_a, sizeof( pulses_c ) ) );
+#endif
+}
+
+/******************************************/
+/* Noise shape quantizer for one subframe */
+/******************************************/
+/* Note: Function silk_short_prediction_create_arch_coef_neon() defined in NSQ_neon.h is actually a hacking C function. */
+/* Therefore here we append "_local" to the NEON function name to avoid confusion. */
+static OPUS_INLINE void silk_short_prediction_create_arch_coef_neon_local(opus_int32 *out, const opus_int16 *in, opus_int order)
+{
+ int16x8_t t_s16x8;
+ int32x4_t t0_s32x4, t1_s32x4, t2_s32x4, t3_s32x4;
+ silk_assert( order == 10 || order == 16 );
+
+ t_s16x8 = vld1q_s16( in + 0 ); /* 7 6 5 4 3 2 1 0 */
+ t_s16x8 = vrev64q_s16( t_s16x8 ); /* 4 5 6 7 0 1 2 3 */
+ t2_s32x4 = vshll_n_s16( vget_high_s16( t_s16x8 ), 15 ); /* 4 5 6 7 */
+ t3_s32x4 = vshll_n_s16( vget_low_s16( t_s16x8 ), 15 ); /* 0 1 2 3 */
+
+ if( order == 16 ) {
+ t_s16x8 = vld1q_s16( in + 8 ); /* F E D C B A 9 8 */
+ t_s16x8 = vrev64q_s16( t_s16x8 ); /* C D E F 8 9 A B */
+ t0_s32x4 = vshll_n_s16( vget_high_s16( t_s16x8 ), 15 ); /* C D E F */
+ t1_s32x4 = vshll_n_s16( vget_low_s16( t_s16x8 ), 15 ); /* 8 9 A B */
+ } else {
+ int16x4_t t_s16x4;
+
+ t0_s32x4 = vdupq_n_s32( 0 ); /* zero zero zero zero */
+ t_s16x4 = vld1_s16( in + 6 ); /* 9 8 7 6 */
+ t_s16x4 = vrev64_s16( t_s16x4 ); /* 6 7 8 9 */
+ t1_s32x4 = vshll_n_s16( t_s16x4, 15 );
+ t1_s32x4 = vcombine_s32( vget_low_s32(t0_s32x4), vget_low_s32( t1_s32x4 ) ); /* 8 9 zero zero */
+ }
+ vst1q_s32( out + 0, t0_s32x4 );
+ vst1q_s32( out + 4, t1_s32x4 );
+ vst1q_s32( out + 8, t2_s32x4 );
+ vst1q_s32( out + 12, t3_s32x4 );
+}
+
+static OPUS_INLINE int32x4_t silk_SMLAWB_lane0_neon(
+ const int32x4_t out_s32x4,
+ const int32x4_t in_s32x4,
+ const int32x2_t coef_s32x2
+)
+{
+ return vaddq_s32( out_s32x4, vqdmulhq_lane_s32( in_s32x4, coef_s32x2, 0 ) );
+}
+
+static OPUS_INLINE int32x4_t silk_SMLAWB_lane1_neon(
+ const int32x4_t out_s32x4,
+ const int32x4_t in_s32x4,
+ const int32x2_t coef_s32x2
+)
+{
+ return vaddq_s32( out_s32x4, vqdmulhq_lane_s32( in_s32x4, coef_s32x2, 1 ) );
+}
+
+/* Note: This function has different return value than silk_noise_shape_quantizer_short_prediction_neon(). */
+/* Therefore here we append "_local" to the function name to avoid confusion. */
+static OPUS_INLINE int32x4_t silk_noise_shape_quantizer_short_prediction_neon_local(const opus_int32 *buf32, const opus_int32 *a_Q12_arch, opus_int order)
+{
+ const int32x4_t a_Q12_arch0_s32x4 = vld1q_s32( a_Q12_arch + 0 );
+ const int32x4_t a_Q12_arch1_s32x4 = vld1q_s32( a_Q12_arch + 4 );
+ const int32x4_t a_Q12_arch2_s32x4 = vld1q_s32( a_Q12_arch + 8 );
+ const int32x4_t a_Q12_arch3_s32x4 = vld1q_s32( a_Q12_arch + 12 );
+ int32x4_t LPC_pred_Q14_s32x4;
+
+ silk_assert( order == 10 || order == 16 );
+ /* Avoids introducing a bias because silk_SMLAWB() always rounds to -inf */
+ LPC_pred_Q14_s32x4 = vdupq_n_s32( silk_RSHIFT( order, 1 ) );
+ LPC_pred_Q14_s32x4 = silk_SMLAWB_lane0_neon( LPC_pred_Q14_s32x4, vld1q_s32( buf32 + 0 * NEON_MAX_DEL_DEC_STATES ), vget_low_s32( a_Q12_arch0_s32x4 ) );
+ LPC_pred_Q14_s32x4 = silk_SMLAWB_lane1_neon( LPC_pred_Q14_s32x4, vld1q_s32( buf32 + 1 * NEON_MAX_DEL_DEC_STATES ), vget_low_s32( a_Q12_arch0_s32x4 ) );
+ LPC_pred_Q14_s32x4 = silk_SMLAWB_lane0_neon( LPC_pred_Q14_s32x4, vld1q_s32( buf32 + 2 * NEON_MAX_DEL_DEC_STATES ), vget_high_s32( a_Q12_arch0_s32x4 ) );
+ LPC_pred_Q14_s32x4 = silk_SMLAWB_lane1_neon( LPC_pred_Q14_s32x4, vld1q_s32( buf32 + 3 * NEON_MAX_DEL_DEC_STATES ), vget_high_s32( a_Q12_arch0_s32x4 ) );
+ LPC_pred_Q14_s32x4 = silk_SMLAWB_lane0_neon( LPC_pred_Q14_s32x4, vld1q_s32( buf32 + 4 * NEON_MAX_DEL_DEC_STATES ), vget_low_s32( a_Q12_arch1_s32x4 ) );
+ LPC_pred_Q14_s32x4 = silk_SMLAWB_lane1_neon( LPC_pred_Q14_s32x4, vld1q_s32( buf32 + 5 * NEON_MAX_DEL_DEC_STATES ), vget_low_s32( a_Q12_arch1_s32x4 ) );
+ LPC_pred_Q14_s32x4 = silk_SMLAWB_lane0_neon( LPC_pred_Q14_s32x4, vld1q_s32( buf32 + 6 * NEON_MAX_DEL_DEC_STATES ), vget_high_s32( a_Q12_arch1_s32x4 ) );
+ LPC_pred_Q14_s32x4 = silk_SMLAWB_lane1_neon( LPC_pred_Q14_s32x4, vld1q_s32( buf32 + 7 * NEON_MAX_DEL_DEC_STATES ), vget_high_s32( a_Q12_arch1_s32x4 ) );
+ LPC_pred_Q14_s32x4 = silk_SMLAWB_lane0_neon( LPC_pred_Q14_s32x4, vld1q_s32( buf32 + 8 * NEON_MAX_DEL_DEC_STATES ), vget_low_s32( a_Q12_arch2_s32x4 ) );
+ LPC_pred_Q14_s32x4 = silk_SMLAWB_lane1_neon( LPC_pred_Q14_s32x4, vld1q_s32( buf32 + 9 * NEON_MAX_DEL_DEC_STATES ), vget_low_s32( a_Q12_arch2_s32x4 ) );
+ LPC_pred_Q14_s32x4 = silk_SMLAWB_lane0_neon( LPC_pred_Q14_s32x4, vld1q_s32( buf32 + 10 * NEON_MAX_DEL_DEC_STATES ), vget_high_s32( a_Q12_arch2_s32x4 ) );
+ LPC_pred_Q14_s32x4 = silk_SMLAWB_lane1_neon( LPC_pred_Q14_s32x4, vld1q_s32( buf32 + 11 * NEON_MAX_DEL_DEC_STATES ), vget_high_s32( a_Q12_arch2_s32x4 ) );
+ LPC_pred_Q14_s32x4 = silk_SMLAWB_lane0_neon( LPC_pred_Q14_s32x4, vld1q_s32( buf32 + 12 * NEON_MAX_DEL_DEC_STATES ), vget_low_s32( a_Q12_arch3_s32x4 ) );
+ LPC_pred_Q14_s32x4 = silk_SMLAWB_lane1_neon( LPC_pred_Q14_s32x4, vld1q_s32( buf32 + 13 * NEON_MAX_DEL_DEC_STATES ), vget_low_s32( a_Q12_arch3_s32x4 ) );
+ LPC_pred_Q14_s32x4 = silk_SMLAWB_lane0_neon( LPC_pred_Q14_s32x4, vld1q_s32( buf32 + 14 * NEON_MAX_DEL_DEC_STATES ), vget_high_s32( a_Q12_arch3_s32x4 ) );
+ LPC_pred_Q14_s32x4 = silk_SMLAWB_lane1_neon( LPC_pred_Q14_s32x4, vld1q_s32( buf32 + 15 * NEON_MAX_DEL_DEC_STATES ), vget_high_s32( a_Q12_arch3_s32x4 ) );
+
+ return LPC_pred_Q14_s32x4;
+}
+
+static OPUS_INLINE void silk_noise_shape_quantizer_del_dec_neon(
+ silk_nsq_state *NSQ, /* I/O NSQ state */
+ NSQ_del_decs_struct psDelDec[], /* I/O Delayed decision states */
+ opus_int signalType, /* I Signal type */
+ const opus_int32 x_Q10[], /* I */
+ opus_int8 pulses[], /* O */
+ opus_int16 xq[], /* O */
+ opus_int32 sLTP_Q15[], /* I/O LTP filter state */
+ opus_int32 delayedGain_Q10[], /* I/O Gain delay buffer */
+ const opus_int16 a_Q12[], /* I Short term prediction coefs */
+ const opus_int16 b_Q14[], /* I Long term prediction coefs */
+ const opus_int16 AR_shp_Q13[], /* I Noise shaping coefs */
+ opus_int lag, /* I Pitch lag */
+ opus_int32 HarmShapeFIRPacked_Q14, /* I */
+ opus_int Tilt_Q14, /* I Spectral tilt */
+ opus_int32 LF_shp_Q14, /* I */
+ opus_int32 Gain_Q16, /* I */
+ opus_int Lambda_Q10, /* I */
+ opus_int offset_Q10, /* I */
+ opus_int length, /* I Input length */
+ opus_int subfr, /* I Subframe number */
+ opus_int shapingLPCOrder, /* I Shaping LPC filter order */
+ opus_int predictLPCOrder, /* I Prediction filter order */
+ opus_int warping_Q16, /* I */
+ opus_int nStatesDelayedDecision, /* I Number of states in decision tree */
+ opus_int *smpl_buf_idx, /* I/O Index to newest samples in buffers */
+ opus_int decisionDelay /* I */
+)
+{
+ opus_int i, j, k, Winner_ind, RDmin_ind, RDmax_ind, last_smple_idx;
+ opus_int32 Winner_rand_state;
+ opus_int32 LTP_pred_Q14, n_LTP_Q14;
+ opus_int32 RDmin_Q10, RDmax_Q10;
+ opus_int32 Gain_Q10;
+ opus_int32 *pred_lag_ptr, *shp_lag_ptr;
+ opus_int32 a_Q12_arch[MAX_LPC_ORDER];
+ const int32x2_t warping_Q16_s32x2 = vdup_n_s32( silk_LSHIFT32( warping_Q16, 16 ) >> 1 );
+ const opus_int32 LF_shp_Q29 = silk_LSHIFT32( LF_shp_Q14, 16 ) >> 1;
+ opus_int32 AR_shp_Q28[ MAX_SHAPE_LPC_ORDER ];
+ const uint32x4_t rand_multiplier_u32x4 = vdupq_n_u32( RAND_MULTIPLIER );
+ const uint32x4_t rand_increment_u32x4 = vdupq_n_u32( RAND_INCREMENT );
+
+ VARDECL( NSQ_samples_struct, psSampleState );
+ SAVE_STACK;
+
+ silk_assert( nStatesDelayedDecision > 0 );
+ silk_assert( ( shapingLPCOrder & 1 ) == 0 ); /* check that order is even */
+ ALLOC( psSampleState, 2, NSQ_samples_struct );
+
+ shp_lag_ptr = &NSQ->sLTP_shp_Q14[ NSQ->sLTP_shp_buf_idx - lag + HARM_SHAPE_FIR_TAPS / 2 ];
+ pred_lag_ptr = &sLTP_Q15[ NSQ->sLTP_buf_idx - lag + LTP_ORDER / 2 ];
+ Gain_Q10 = silk_RSHIFT( Gain_Q16, 6 );
+
+ for( i = 0; i < ( MAX_SHAPE_LPC_ORDER - 7 ); i += 8 ) {
+ const int16x8_t t_s16x8 = vld1q_s16( AR_shp_Q13 + i );
+ vst1q_s32( AR_shp_Q28 + i + 0, vshll_n_s16( vget_low_s16( t_s16x8 ), 15 ) );
+ vst1q_s32( AR_shp_Q28 + i + 4, vshll_n_s16( vget_high_s16( t_s16x8 ), 15 ) );
+ }
+
+ for( ; i < MAX_SHAPE_LPC_ORDER; i++ ) {
+ AR_shp_Q28[i] = silk_LSHIFT32( AR_shp_Q13[i], 15 );
+ }
+
+ silk_short_prediction_create_arch_coef_neon_local( a_Q12_arch, a_Q12, predictLPCOrder );
+
+ for( i = 0; i < length; i++ ) {
+ int32x4_t Seed_s32x4, LPC_pred_Q14_s32x4;
+ int32x4_t sign_s32x4, tmp1_s32x4, tmp2_s32x4;
+ int32x4_t n_AR_Q14_s32x4, n_LF_Q14_s32x4;
+ int32x2_t AR_shp_Q28_s32x2;
+ int16x4_t r_Q10_s16x4, rr_Q10_s16x4;
+
+ /* Perform common calculations used in all states */
+
+ /* Long-term prediction */
+ if( signalType == TYPE_VOICED ) {
+ /* Unrolled loop */
+ /* Avoids introducing a bias because silk_SMLAWB() always rounds to -inf */
+ LTP_pred_Q14 = 2;
+ LTP_pred_Q14 = silk_SMLAWB( LTP_pred_Q14, pred_lag_ptr[ 0 ], b_Q14[ 0 ] );
+ LTP_pred_Q14 = silk_SMLAWB( LTP_pred_Q14, pred_lag_ptr[ -1 ], b_Q14[ 1 ] );
+ LTP_pred_Q14 = silk_SMLAWB( LTP_pred_Q14, pred_lag_ptr[ -2 ], b_Q14[ 2 ] );
+ LTP_pred_Q14 = silk_SMLAWB( LTP_pred_Q14, pred_lag_ptr[ -3 ], b_Q14[ 3 ] );
+ LTP_pred_Q14 = silk_SMLAWB( LTP_pred_Q14, pred_lag_ptr[ -4 ], b_Q14[ 4 ] );
+ LTP_pred_Q14 = silk_LSHIFT( LTP_pred_Q14, 1 ); /* Q13 -> Q14 */
+ pred_lag_ptr++;
+ } else {
+ LTP_pred_Q14 = 0;
+ }
+
+ /* Long-term shaping */
+ if( lag > 0 ) {
+ /* Symmetric, packed FIR coefficients */
+ n_LTP_Q14 = silk_SMULWB( silk_ADD32( shp_lag_ptr[ 0 ], shp_lag_ptr[ -2 ] ), HarmShapeFIRPacked_Q14 );
+ n_LTP_Q14 = silk_SMLAWT( n_LTP_Q14, shp_lag_ptr[ -1 ], HarmShapeFIRPacked_Q14 );
+ n_LTP_Q14 = silk_SUB_LSHIFT32( LTP_pred_Q14, n_LTP_Q14, 2 ); /* Q12 -> Q14 */
+ shp_lag_ptr++;
+ } else {
+ n_LTP_Q14 = 0;
+ }
+
+ /* Generate dither */
+ Seed_s32x4 = vld1q_s32( psDelDec->Seed );
+ Seed_s32x4 = vreinterpretq_s32_u32( vmlaq_u32( rand_increment_u32x4, vreinterpretq_u32_s32( Seed_s32x4 ), rand_multiplier_u32x4 ) );
+ vst1q_s32( psDelDec->Seed, Seed_s32x4 );
+
+ /* Short-term prediction */
+ LPC_pred_Q14_s32x4 = silk_noise_shape_quantizer_short_prediction_neon_local(psDelDec->sLPC_Q14[ NSQ_LPC_BUF_LENGTH - 16 + i ], a_Q12_arch, predictLPCOrder);
+ LPC_pred_Q14_s32x4 = vshlq_n_s32( LPC_pred_Q14_s32x4, 4 ); /* Q10 -> Q14 */
+
+ /* Noise shape feedback */
+ /* Output of lowpass section */
+ tmp2_s32x4 = silk_SMLAWB_lane0_neon( vld1q_s32( psDelDec->Diff_Q14 ), vld1q_s32( psDelDec->sAR2_Q14[ 0 ] ), warping_Q16_s32x2 );
+ /* Output of allpass section */
+ tmp1_s32x4 = vsubq_s32( vld1q_s32( psDelDec->sAR2_Q14[ 1 ] ), tmp2_s32x4 );
+ tmp1_s32x4 = silk_SMLAWB_lane0_neon( vld1q_s32( psDelDec->sAR2_Q14[ 0 ] ), tmp1_s32x4, warping_Q16_s32x2 );
+ vst1q_s32( psDelDec->sAR2_Q14[ 0 ], tmp2_s32x4 );
+ AR_shp_Q28_s32x2 = vld1_s32( AR_shp_Q28 );
+ n_AR_Q14_s32x4 = vaddq_s32( vdupq_n_s32( silk_RSHIFT( shapingLPCOrder, 1 ) ), vqdmulhq_lane_s32( tmp2_s32x4, AR_shp_Q28_s32x2, 0 ) );
+
+ /* Loop over allpass sections */
+ for( j = 2; j < shapingLPCOrder; j += 2 ) {
+ /* Output of allpass section */
+ tmp2_s32x4 = vsubq_s32( vld1q_s32( psDelDec->sAR2_Q14[ j + 0 ] ), tmp1_s32x4 );
+ tmp2_s32x4 = silk_SMLAWB_lane0_neon( vld1q_s32( psDelDec->sAR2_Q14[ j - 1 ] ), tmp2_s32x4, warping_Q16_s32x2 );
+ vst1q_s32( psDelDec->sAR2_Q14[ j - 1 ], tmp1_s32x4 );
+ n_AR_Q14_s32x4 = vaddq_s32( n_AR_Q14_s32x4, vqdmulhq_lane_s32( tmp1_s32x4, AR_shp_Q28_s32x2, 1 ) );
+ /* Output of allpass section */
+ tmp1_s32x4 = vsubq_s32( vld1q_s32( psDelDec->sAR2_Q14[ j + 1 ] ), tmp2_s32x4 );
+ tmp1_s32x4 = silk_SMLAWB_lane0_neon( vld1q_s32( psDelDec->sAR2_Q14[ j + 0 ] ), tmp1_s32x4, warping_Q16_s32x2 );
+ vst1q_s32( psDelDec->sAR2_Q14[ j + 0 ], tmp2_s32x4 );
+ AR_shp_Q28_s32x2 = vld1_s32( &AR_shp_Q28[ j ] );
+ n_AR_Q14_s32x4 = vaddq_s32( n_AR_Q14_s32x4, vqdmulhq_lane_s32( tmp2_s32x4, AR_shp_Q28_s32x2, 0 ) );
+ }
+ vst1q_s32( psDelDec->sAR2_Q14[ shapingLPCOrder - 1 ], tmp1_s32x4 );
+ n_AR_Q14_s32x4 = vaddq_s32( n_AR_Q14_s32x4, vqdmulhq_lane_s32( tmp1_s32x4, AR_shp_Q28_s32x2, 1 ) );
+ n_AR_Q14_s32x4 = vshlq_n_s32( n_AR_Q14_s32x4, 1 ); /* Q11 -> Q12 */
+ n_AR_Q14_s32x4 = vaddq_s32( n_AR_Q14_s32x4, vqdmulhq_n_s32( vld1q_s32( psDelDec->LF_AR_Q14 ), silk_LSHIFT32( Tilt_Q14, 16 ) >> 1 ) ); /* Q12 */
+ n_AR_Q14_s32x4 = vshlq_n_s32( n_AR_Q14_s32x4, 2 ); /* Q12 -> Q14 */
+ n_LF_Q14_s32x4 = vqdmulhq_n_s32( vld1q_s32( psDelDec->Shape_Q14[ *smpl_buf_idx ] ), LF_shp_Q29 ); /* Q12 */
+ n_LF_Q14_s32x4 = vaddq_s32( n_LF_Q14_s32x4, vqdmulhq_n_s32( vld1q_s32( psDelDec->LF_AR_Q14 ), silk_LSHIFT32( LF_shp_Q14 >> 16 , 15 ) ) ); /* Q12 */
+ n_LF_Q14_s32x4 = vshlq_n_s32( n_LF_Q14_s32x4, 2 ); /* Q12 -> Q14 */
+
+ /* Input minus prediction plus noise feedback */
+ /* r = x[ i ] - LTP_pred - LPC_pred + n_AR + n_Tilt + n_LF + n_LTP */
+ tmp1_s32x4 = vaddq_s32( n_AR_Q14_s32x4, n_LF_Q14_s32x4 ); /* Q14 */
+ tmp2_s32x4 = vaddq_s32( vdupq_n_s32( n_LTP_Q14 ), LPC_pred_Q14_s32x4 ); /* Q13 */
+ tmp1_s32x4 = vsubq_s32( tmp2_s32x4, tmp1_s32x4 ); /* Q13 */
+ tmp1_s32x4 = vrshrq_n_s32( tmp1_s32x4, 4 ); /* Q10 */
+ tmp1_s32x4 = vsubq_s32( vdupq_n_s32( x_Q10[ i ] ), tmp1_s32x4 ); /* residual error Q10 */
+
+ /* Flip sign depending on dither */
+ sign_s32x4 = vreinterpretq_s32_u32( vcltq_s32( Seed_s32x4, vdupq_n_s32( 0 ) ) );
+ tmp1_s32x4 = veorq_s32( tmp1_s32x4, sign_s32x4 );
+ tmp1_s32x4 = vsubq_s32( tmp1_s32x4, sign_s32x4 );
+ tmp1_s32x4 = vmaxq_s32( tmp1_s32x4, vdupq_n_s32( -( 31 << 10 ) ) );
+ tmp1_s32x4 = vminq_s32( tmp1_s32x4, vdupq_n_s32( 30 << 10 ) );
+ r_Q10_s16x4 = vmovn_s32( tmp1_s32x4 );
+
+ /* Find two quantization level candidates and measure their rate-distortion */
+ {
+ int16x4_t q1_Q10_s16x4 = vsub_s16( r_Q10_s16x4, vdup_n_s16( offset_Q10 ) );
+ int16x4_t q1_Q0_s16x4 = vshr_n_s16( q1_Q10_s16x4, 10 );
+ int16x4_t q2_Q10_s16x4;
+ int32x4_t rd1_Q10_s32x4, rd2_Q10_s32x4;
+ uint32x4_t t_u32x4;
+
+ if( Lambda_Q10 > 2048 ) {
+ /* For aggressive RDO, the bias becomes more than one pulse. */
+ const int rdo_offset = Lambda_Q10/2 - 512;
+ const uint16x4_t greaterThanRdo = vcgt_s16( q1_Q10_s16x4, vdup_n_s16( rdo_offset ) );
+ const uint16x4_t lessThanMinusRdo = vclt_s16( q1_Q10_s16x4, vdup_n_s16( -rdo_offset ) );
+ /* If Lambda_Q10 > 32767, then q1_Q0, q1_Q10 and q2_Q10 must change to 32-bit. */
+ silk_assert( Lambda_Q10 <= 32767 );
+
+ q1_Q0_s16x4 = vreinterpret_s16_u16( vclt_s16( q1_Q10_s16x4, vdup_n_s16( 0 ) ) );
+ q1_Q0_s16x4 = vbsl_s16( greaterThanRdo, vsub_s16( q1_Q10_s16x4, vdup_n_s16( rdo_offset ) ), q1_Q0_s16x4 );
+ q1_Q0_s16x4 = vbsl_s16( lessThanMinusRdo, vadd_s16( q1_Q10_s16x4, vdup_n_s16( rdo_offset ) ), q1_Q0_s16x4 );
+ q1_Q0_s16x4 = vshr_n_s16( q1_Q0_s16x4, 10 );
+ }
+ {
+ const uint16x4_t equal0_u16x4 = vceq_s16( q1_Q0_s16x4, vdup_n_s16( 0 ) );
+ const uint16x4_t equalMinus1_u16x4 = vceq_s16( q1_Q0_s16x4, vdup_n_s16( -1 ) );
+ const uint16x4_t lessThanMinus1_u16x4 = vclt_s16( q1_Q0_s16x4, vdup_n_s16( -1 ) );
+ int16x4_t tmp1_s16x4, tmp2_s16x4;
+
+ q1_Q10_s16x4 = vshl_n_s16( q1_Q0_s16x4, 10 );
+ tmp1_s16x4 = vadd_s16( q1_Q10_s16x4, vdup_n_s16( offset_Q10 - QUANT_LEVEL_ADJUST_Q10 ) );
+ q1_Q10_s16x4 = vadd_s16( q1_Q10_s16x4, vdup_n_s16( offset_Q10 + QUANT_LEVEL_ADJUST_Q10 ) );
+ q1_Q10_s16x4 = vbsl_s16( lessThanMinus1_u16x4, q1_Q10_s16x4, tmp1_s16x4 );
+ q1_Q10_s16x4 = vbsl_s16( equal0_u16x4, vdup_n_s16( offset_Q10 ), q1_Q10_s16x4 );
+ q1_Q10_s16x4 = vbsl_s16( equalMinus1_u16x4, vdup_n_s16( offset_Q10 - ( 1024 - QUANT_LEVEL_ADJUST_Q10 ) ), q1_Q10_s16x4 );
+ q2_Q10_s16x4 = vadd_s16( q1_Q10_s16x4, vdup_n_s16( 1024 ) );
+ q2_Q10_s16x4 = vbsl_s16( equal0_u16x4, vdup_n_s16( offset_Q10 + 1024 - QUANT_LEVEL_ADJUST_Q10 ), q2_Q10_s16x4 );
+ q2_Q10_s16x4 = vbsl_s16( equalMinus1_u16x4, vdup_n_s16( offset_Q10 ), q2_Q10_s16x4 );
+ tmp1_s16x4 = q1_Q10_s16x4;
+ tmp2_s16x4 = q2_Q10_s16x4;
+ tmp1_s16x4 = vbsl_s16( vorr_u16( equalMinus1_u16x4, lessThanMinus1_u16x4 ), vneg_s16( tmp1_s16x4 ), tmp1_s16x4 );
+ tmp2_s16x4 = vbsl_s16( lessThanMinus1_u16x4, vneg_s16( tmp2_s16x4 ), tmp2_s16x4 );
+ rd1_Q10_s32x4 = vmull_s16( tmp1_s16x4, vdup_n_s16( Lambda_Q10 ) );
+ rd2_Q10_s32x4 = vmull_s16( tmp2_s16x4, vdup_n_s16( Lambda_Q10 ) );
+ }
+
+ rr_Q10_s16x4 = vsub_s16( r_Q10_s16x4, q1_Q10_s16x4 );
+ rd1_Q10_s32x4 = vmlal_s16( rd1_Q10_s32x4, rr_Q10_s16x4, rr_Q10_s16x4 );
+ rd1_Q10_s32x4 = vshrq_n_s32( rd1_Q10_s32x4, 10 );
+
+ rr_Q10_s16x4 = vsub_s16( r_Q10_s16x4, q2_Q10_s16x4 );
+ rd2_Q10_s32x4 = vmlal_s16( rd2_Q10_s32x4, rr_Q10_s16x4, rr_Q10_s16x4 );
+ rd2_Q10_s32x4 = vshrq_n_s32( rd2_Q10_s32x4, 10 );
+
+ tmp2_s32x4 = vld1q_s32( psDelDec->RD_Q10 );
+ tmp1_s32x4 = vaddq_s32( tmp2_s32x4, vminq_s32( rd1_Q10_s32x4, rd2_Q10_s32x4 ) );
+ tmp2_s32x4 = vaddq_s32( tmp2_s32x4, vmaxq_s32( rd1_Q10_s32x4, rd2_Q10_s32x4 ) );
+ vst1q_s32( psSampleState[ 0 ].RD_Q10, tmp1_s32x4 );
+ vst1q_s32( psSampleState[ 1 ].RD_Q10, tmp2_s32x4 );
+ t_u32x4 = vcltq_s32( rd1_Q10_s32x4, rd2_Q10_s32x4 );
+ tmp1_s32x4 = vbslq_s32( t_u32x4, vmovl_s16( q1_Q10_s16x4 ), vmovl_s16( q2_Q10_s16x4 ) );
+ tmp2_s32x4 = vbslq_s32( t_u32x4, vmovl_s16( q2_Q10_s16x4 ), vmovl_s16( q1_Q10_s16x4 ) );
+ vst1q_s32( psSampleState[ 0 ].Q_Q10, tmp1_s32x4 );
+ vst1q_s32( psSampleState[ 1 ].Q_Q10, tmp2_s32x4 );
+ }
+
+ {
+ /* Update states for best quantization */
+ int32x4_t exc_Q14_s32x4, LPC_exc_Q14_s32x4, xq_Q14_s32x4, sLF_AR_shp_Q14_s32x4;
+
+ /* Quantized excitation */
+ exc_Q14_s32x4 = vshlq_n_s32( tmp1_s32x4, 4 );
+ exc_Q14_s32x4 = veorq_s32( exc_Q14_s32x4, sign_s32x4 );
+ exc_Q14_s32x4 = vsubq_s32( exc_Q14_s32x4, sign_s32x4 );
+
+ /* Add predictions */
+ LPC_exc_Q14_s32x4 = vaddq_s32( exc_Q14_s32x4, vdupq_n_s32( LTP_pred_Q14 ) );
+ xq_Q14_s32x4 = vaddq_s32( LPC_exc_Q14_s32x4, LPC_pred_Q14_s32x4 );
+
+ /* Update states */
+ tmp1_s32x4 = vsubq_s32( xq_Q14_s32x4, vshlq_n_s32( vdupq_n_s32( x_Q10[ i ] ), 4 ) );
+ vst1q_s32( psSampleState[ 0 ].Diff_Q14, tmp1_s32x4 );
+ sLF_AR_shp_Q14_s32x4 = vsubq_s32( tmp1_s32x4, n_AR_Q14_s32x4 );
+ vst1q_s32( psSampleState[ 0 ].sLTP_shp_Q14, vsubq_s32( sLF_AR_shp_Q14_s32x4, n_LF_Q14_s32x4 ) );
+ vst1q_s32( psSampleState[ 0 ].LF_AR_Q14, sLF_AR_shp_Q14_s32x4 );
+ vst1q_s32( psSampleState[ 0 ].LPC_exc_Q14, LPC_exc_Q14_s32x4 );
+ vst1q_s32( psSampleState[ 0 ].xq_Q14, xq_Q14_s32x4 );
+
+ /* Quantized excitation */
+ exc_Q14_s32x4 = vshlq_n_s32( tmp2_s32x4, 4 );
+ exc_Q14_s32x4 = veorq_s32( exc_Q14_s32x4, sign_s32x4 );
+ exc_Q14_s32x4 = vsubq_s32( exc_Q14_s32x4, sign_s32x4 );
+
+ /* Add predictions */
+ LPC_exc_Q14_s32x4 = vaddq_s32( exc_Q14_s32x4, vdupq_n_s32( LTP_pred_Q14 ) );
+ xq_Q14_s32x4 = vaddq_s32( LPC_exc_Q14_s32x4, LPC_pred_Q14_s32x4 );
+
+ /* Update states */
+ tmp1_s32x4 = vsubq_s32( xq_Q14_s32x4, vshlq_n_s32( vdupq_n_s32( x_Q10[ i ] ), 4 ) );
+ vst1q_s32( psSampleState[ 1 ].Diff_Q14, tmp1_s32x4 );
+ sLF_AR_shp_Q14_s32x4 = vsubq_s32( tmp1_s32x4, n_AR_Q14_s32x4 );
+ vst1q_s32( psSampleState[ 1 ].sLTP_shp_Q14, vsubq_s32( sLF_AR_shp_Q14_s32x4, n_LF_Q14_s32x4 ) );
+ vst1q_s32( psSampleState[ 1 ].LF_AR_Q14, sLF_AR_shp_Q14_s32x4 );
+ vst1q_s32( psSampleState[ 1 ].LPC_exc_Q14, LPC_exc_Q14_s32x4 );
+ vst1q_s32( psSampleState[ 1 ].xq_Q14, xq_Q14_s32x4 );
+ }
+
+ *smpl_buf_idx = *smpl_buf_idx ? ( *smpl_buf_idx - 1 ) : ( DECISION_DELAY - 1);
+ last_smple_idx = *smpl_buf_idx + decisionDelay + DECISION_DELAY;
+ if( last_smple_idx >= DECISION_DELAY ) last_smple_idx -= DECISION_DELAY;
+ if( last_smple_idx >= DECISION_DELAY ) last_smple_idx -= DECISION_DELAY;
+
+ /* Find winner */
+ RDmin_Q10 = psSampleState[ 0 ].RD_Q10[ 0 ];
+ Winner_ind = 0;
+ for( k = 1; k < nStatesDelayedDecision; k++ ) {
+ if( psSampleState[ 0 ].RD_Q10[ k ] < RDmin_Q10 ) {
+ RDmin_Q10 = psSampleState[ 0 ].RD_Q10[ k ];
+ Winner_ind = k;
+ }
+ }
+
+ /* Increase RD values of expired states */
+ {
+ uint32x4_t t_u32x4;
+ Winner_rand_state = psDelDec->RandState[ last_smple_idx ][ Winner_ind ];
+ t_u32x4 = vceqq_s32( vld1q_s32( psDelDec->RandState[ last_smple_idx ] ), vdupq_n_s32( Winner_rand_state ) );
+ t_u32x4 = vmvnq_u32( t_u32x4 );
+ t_u32x4 = vshrq_n_u32( t_u32x4, 5 );
+ tmp1_s32x4 = vld1q_s32( psSampleState[ 0 ].RD_Q10 );
+ tmp2_s32x4 = vld1q_s32( psSampleState[ 1 ].RD_Q10 );
+ tmp1_s32x4 = vaddq_s32( tmp1_s32x4, vreinterpretq_s32_u32( t_u32x4 ) );
+ tmp2_s32x4 = vaddq_s32( tmp2_s32x4, vreinterpretq_s32_u32( t_u32x4 ) );
+ vst1q_s32( psSampleState[ 0 ].RD_Q10, tmp1_s32x4 );
+ vst1q_s32( psSampleState[ 1 ].RD_Q10, tmp2_s32x4 );
+
+ /* Find worst in first set and best in second set */
+ RDmax_Q10 = psSampleState[ 0 ].RD_Q10[ 0 ];
+ RDmin_Q10 = psSampleState[ 1 ].RD_Q10[ 0 ];
+ RDmax_ind = 0;
+ RDmin_ind = 0;
+ for( k = 1; k < nStatesDelayedDecision; k++ ) {
+ /* find worst in first set */
+ if( psSampleState[ 0 ].RD_Q10[ k ] > RDmax_Q10 ) {
+ RDmax_Q10 = psSampleState[ 0 ].RD_Q10[ k ];
+ RDmax_ind = k;
+ }
+ /* find best in second set */
+ if( psSampleState[ 1 ].RD_Q10[ k ] < RDmin_Q10 ) {
+ RDmin_Q10 = psSampleState[ 1 ].RD_Q10[ k ];
+ RDmin_ind = k;
+ }
+ }
+ }
+
+ /* Replace a state if best from second set outperforms worst in first set */
+ if( RDmin_Q10 < RDmax_Q10 ) {
+ opus_int32 (*ptr)[NEON_MAX_DEL_DEC_STATES] = psDelDec->RandState;
+ const int numOthers = (int)( ( sizeof( NSQ_del_decs_struct ) - sizeof( ( (NSQ_del_decs_struct *)0 )->sLPC_Q14 ) )
+ / ( NEON_MAX_DEL_DEC_STATES * sizeof( opus_int32 ) ) );
+ /* Only ( predictLPCOrder - 1 ) of sLPC_Q14 buffer need to be updated, though the first several */
+ /* useless sLPC_Q14[] will be different comparing with C when predictLPCOrder < NSQ_LPC_BUF_LENGTH. */
+ /* Here just update constant ( NSQ_LPC_BUF_LENGTH - 1 ) for simplicity. */
+ for( j = i + 1; j < i + NSQ_LPC_BUF_LENGTH; j++ ) {
+ psDelDec->sLPC_Q14[ j ][ RDmax_ind ] = psDelDec->sLPC_Q14[ j ][ RDmin_ind ];
+ }
+ for( j = 0; j < numOthers; j++ ) {
+ ptr[ j ][ RDmax_ind ] = ptr[ j ][ RDmin_ind ];
+ }
+
+ psSampleState[ 0 ].Q_Q10[ RDmax_ind ] = psSampleState[ 1 ].Q_Q10[ RDmin_ind ];
+ psSampleState[ 0 ].RD_Q10[ RDmax_ind ] = psSampleState[ 1 ].RD_Q10[ RDmin_ind ];
+ psSampleState[ 0 ].xq_Q14[ RDmax_ind ] = psSampleState[ 1 ].xq_Q14[ RDmin_ind ];
+ psSampleState[ 0 ].LF_AR_Q14[ RDmax_ind ] = psSampleState[ 1 ].LF_AR_Q14[ RDmin_ind ];
+ psSampleState[ 0 ].Diff_Q14[ RDmax_ind ] = psSampleState[ 1 ].Diff_Q14[ RDmin_ind ];
+ psSampleState[ 0 ].sLTP_shp_Q14[ RDmax_ind ] = psSampleState[ 1 ].sLTP_shp_Q14[ RDmin_ind ];
+ psSampleState[ 0 ].LPC_exc_Q14[ RDmax_ind ] = psSampleState[ 1 ].LPC_exc_Q14[ RDmin_ind ];
+ }
+
+ /* Write samples from winner to output and long-term filter states */
+ if( subfr > 0 || i >= decisionDelay ) {
+ pulses[ i - decisionDelay ] = (opus_int8)silk_RSHIFT_ROUND( psDelDec->Q_Q10[ last_smple_idx ][ Winner_ind ], 10 );
+ xq[ i - decisionDelay ] = (opus_int16)silk_SAT16( silk_RSHIFT_ROUND(
+ silk_SMULWW( psDelDec->Xq_Q14[ last_smple_idx ][ Winner_ind ], delayedGain_Q10[ last_smple_idx ] ), 8 ) );
+ NSQ->sLTP_shp_Q14[ NSQ->sLTP_shp_buf_idx - decisionDelay ] = psDelDec->Shape_Q14[ last_smple_idx ][ Winner_ind ];
+ sLTP_Q15[ NSQ->sLTP_buf_idx - decisionDelay ] = psDelDec->Pred_Q15[ last_smple_idx ][ Winner_ind ];
+ }
+ NSQ->sLTP_shp_buf_idx++;
+ NSQ->sLTP_buf_idx++;
+
+ /* Update states */
+ vst1q_s32( psDelDec->LF_AR_Q14, vld1q_s32( psSampleState[ 0 ].LF_AR_Q14 ) );
+ vst1q_s32( psDelDec->Diff_Q14, vld1q_s32( psSampleState[ 0 ].Diff_Q14 ) );
+ vst1q_s32( psDelDec->sLPC_Q14[ NSQ_LPC_BUF_LENGTH + i ], vld1q_s32( psSampleState[ 0 ].xq_Q14 ) );
+ vst1q_s32( psDelDec->Xq_Q14[ *smpl_buf_idx ], vld1q_s32( psSampleState[ 0 ].xq_Q14 ) );
+ tmp1_s32x4 = vld1q_s32( psSampleState[ 0 ].Q_Q10 );
+ vst1q_s32( psDelDec->Q_Q10[ *smpl_buf_idx ], tmp1_s32x4 );
+ vst1q_s32( psDelDec->Pred_Q15[ *smpl_buf_idx ], vshlq_n_s32( vld1q_s32( psSampleState[ 0 ].LPC_exc_Q14 ), 1 ) );
+ vst1q_s32( psDelDec->Shape_Q14[ *smpl_buf_idx ], vld1q_s32( psSampleState[ 0 ].sLTP_shp_Q14 ) );
+ tmp1_s32x4 = vrshrq_n_s32( tmp1_s32x4, 10 );
+ tmp1_s32x4 = vaddq_s32( vld1q_s32( psDelDec->Seed ), tmp1_s32x4 );
+ vst1q_s32( psDelDec->Seed, tmp1_s32x4 );
+ vst1q_s32( psDelDec->RandState[ *smpl_buf_idx ], tmp1_s32x4 );
+ vst1q_s32( psDelDec->RD_Q10, vld1q_s32( psSampleState[ 0 ].RD_Q10 ) );
+ delayedGain_Q10[ *smpl_buf_idx ] = Gain_Q10;
+ }
+ /* Update LPC states */
+ silk_memcpy( psDelDec->sLPC_Q14[ 0 ], psDelDec->sLPC_Q14[ length ], NEON_MAX_DEL_DEC_STATES * NSQ_LPC_BUF_LENGTH * sizeof( opus_int32 ) );
+
+ RESTORE_STACK;
+}
+
+static OPUS_INLINE void silk_SMULWB_8_neon(
+ const opus_int16 *a,
+ const int32x2_t b,
+ opus_int32 *o
+)
+{
+ const int16x8_t a_s16x8 = vld1q_s16( a );
+ int32x4_t o0_s32x4, o1_s32x4;
+
+ o0_s32x4 = vshll_n_s16( vget_low_s16( a_s16x8 ), 15 );
+ o1_s32x4 = vshll_n_s16( vget_high_s16( a_s16x8 ), 15 );
+ o0_s32x4 = vqdmulhq_lane_s32( o0_s32x4, b, 0 );
+ o1_s32x4 = vqdmulhq_lane_s32( o1_s32x4, b, 0 );
+ vst1q_s32( o, o0_s32x4 );
+ vst1q_s32( o + 4, o1_s32x4 );
+}
+
+/* Only works when ( b >= -65536 ) && ( b < 65536 ). */
+static OPUS_INLINE void silk_SMULWW_small_b_4_neon(
+ opus_int32 *a,
+ const int32x2_t b_s32x2)
+{
+ int32x4_t o_s32x4;
+
+ o_s32x4 = vld1q_s32( a );
+ o_s32x4 = vqdmulhq_lane_s32( o_s32x4, b_s32x2, 0 );
+ vst1q_s32( a, o_s32x4 );
+}
+
+/* Only works when ( b >= -65536 ) && ( b < 65536 ). */
+static OPUS_INLINE void silk_SMULWW_small_b_8_neon(
+ opus_int32 *a,
+ const int32x2_t b_s32x2
+)
+{
+ int32x4_t o0_s32x4, o1_s32x4;
+
+ o0_s32x4 = vld1q_s32( a );
+ o1_s32x4 = vld1q_s32( a + 4 );
+ o0_s32x4 = vqdmulhq_lane_s32( o0_s32x4, b_s32x2, 0 );
+ o1_s32x4 = vqdmulhq_lane_s32( o1_s32x4, b_s32x2, 0 );
+ vst1q_s32( a, o0_s32x4 );
+ vst1q_s32( a + 4, o1_s32x4 );
+}
+
+static OPUS_INLINE void silk_SMULWW_4_neon(
+ opus_int32 *a,
+ const int32x2_t b_s32x2)
+{
+ int32x4_t a_s32x4, o_s32x4;
+
+ a_s32x4 = vld1q_s32( a );
+ o_s32x4 = vqdmulhq_lane_s32( a_s32x4, b_s32x2, 0 );
+ o_s32x4 = vmlaq_lane_s32( o_s32x4, a_s32x4, b_s32x2, 1 );
+ vst1q_s32( a, o_s32x4 );
+}
+
+static OPUS_INLINE void silk_SMULWW_8_neon(
+ opus_int32 *a,
+ const int32x2_t b_s32x2
+)
+{
+ int32x4_t a0_s32x4, a1_s32x4, o0_s32x4, o1_s32x4;
+
+ a0_s32x4 = vld1q_s32( a );
+ a1_s32x4 = vld1q_s32( a + 4 );
+ o0_s32x4 = vqdmulhq_lane_s32( a0_s32x4, b_s32x2, 0 );
+ o1_s32x4 = vqdmulhq_lane_s32( a1_s32x4, b_s32x2, 0 );
+ o0_s32x4 = vmlaq_lane_s32( o0_s32x4, a0_s32x4, b_s32x2, 1 );
+ o1_s32x4 = vmlaq_lane_s32( o1_s32x4, a1_s32x4, b_s32x2, 1 );
+ vst1q_s32( a, o0_s32x4 );
+ vst1q_s32( a + 4, o1_s32x4 );
+}
+
+static OPUS_INLINE void silk_SMULWW_loop_neon(
+ const opus_int16 *a,
+ const opus_int32 b,
+ opus_int32 *o,
+ const opus_int loop_num
+)
+{
+ opus_int i;
+ int32x2_t b_s32x2;
+
+ b_s32x2 = vdup_n_s32( b );
+ for( i = 0; i < loop_num - 7; i += 8 ) {
+ silk_SMULWB_8_neon( a + i, b_s32x2, o + i );
+ }
+ for( ; i < loop_num; i++ ) {
+ o[ i ] = silk_SMULWW( a[ i ], b );
+ }
+}
+
+static OPUS_INLINE void silk_nsq_del_dec_scale_states_neon(
+ const silk_encoder_state *psEncC, /* I Encoder State */
+ silk_nsq_state *NSQ, /* I/O NSQ state */
+ NSQ_del_decs_struct psDelDec[], /* I/O Delayed decision states */
+ const opus_int16 x16[], /* I Input */
+ opus_int32 x_sc_Q10[], /* O Input scaled with 1/Gain in Q10 */
+ const opus_int16 sLTP[], /* I Re-whitened LTP state in Q0 */
+ opus_int32 sLTP_Q15[], /* O LTP state matching scaled input */
+ opus_int subfr, /* I Subframe number */
+ const opus_int LTP_scale_Q14, /* I LTP state scaling */
+ const opus_int32 Gains_Q16[ MAX_NB_SUBFR ], /* I */
+ const opus_int pitchL[ MAX_NB_SUBFR ], /* I Pitch lag */
+ const opus_int signal_type, /* I Signal type */
+ const opus_int decisionDelay /* I Decision delay */
+)
+{
+ opus_int i, lag;
+ opus_int32 gain_adj_Q16, inv_gain_Q31, inv_gain_Q26;
+
+ lag = pitchL[ subfr ];
+ inv_gain_Q31 = silk_INVERSE32_varQ( silk_max( Gains_Q16[ subfr ], 1 ), 47 );
+ silk_assert( inv_gain_Q31 != 0 );
+
+ /* Scale input */
+ inv_gain_Q26 = silk_RSHIFT_ROUND( inv_gain_Q31, 5 );
+ silk_SMULWW_loop_neon( x16, inv_gain_Q26, x_sc_Q10, psEncC->subfr_length );
+
+ /* After rewhitening the LTP state is un-scaled, so scale with inv_gain_Q16 */
+ if( NSQ->rewhite_flag ) {
+ if( subfr == 0 ) {
+ /* Do LTP downscaling */
+ inv_gain_Q31 = silk_LSHIFT( silk_SMULWB( inv_gain_Q31, LTP_scale_Q14 ), 2 );
+ }
+ silk_SMULWW_loop_neon( sLTP + NSQ->sLTP_buf_idx - lag - LTP_ORDER / 2, inv_gain_Q31, sLTP_Q15 + NSQ->sLTP_buf_idx - lag - LTP_ORDER / 2, lag + LTP_ORDER / 2 );
+ }
+
+ /* Adjust for changing gain */
+ if( Gains_Q16[ subfr ] != NSQ->prev_gain_Q16 ) {
+ int32x2_t gain_adj_Q16_s32x2;
+ gain_adj_Q16 = silk_DIV32_varQ( NSQ->prev_gain_Q16, Gains_Q16[ subfr ], 16 );
+
+ /* Scale long-term shaping state */
+ if( ( gain_adj_Q16 >= -65536 ) && ( gain_adj_Q16 < 65536 ) ) {
+ gain_adj_Q16_s32x2 = vdup_n_s32( silk_LSHIFT32( gain_adj_Q16, 15 ) );
+ for( i = NSQ->sLTP_shp_buf_idx - psEncC->ltp_mem_length; i < NSQ->sLTP_shp_buf_idx - 7; i += 8 ) {
+ silk_SMULWW_small_b_8_neon( NSQ->sLTP_shp_Q14 + i, gain_adj_Q16_s32x2 );
+ }
+ for( ; i < NSQ->sLTP_shp_buf_idx; i++ ) {
+ NSQ->sLTP_shp_Q14[ i ] = silk_SMULWW( gain_adj_Q16, NSQ->sLTP_shp_Q14[ i ] );
+ }
+
+ /* Scale long-term prediction state */
+ if( signal_type == TYPE_VOICED && NSQ->rewhite_flag == 0 ) {
+ for( i = NSQ->sLTP_buf_idx - lag - LTP_ORDER / 2; i < NSQ->sLTP_buf_idx - decisionDelay - 7; i += 8 ) {
+ silk_SMULWW_small_b_8_neon( sLTP_Q15 + i, gain_adj_Q16_s32x2 );
+ }
+ for( ; i < NSQ->sLTP_buf_idx - decisionDelay; i++ ) {
+ sLTP_Q15[ i ] = silk_SMULWW( gain_adj_Q16, sLTP_Q15[ i ] );
+ }
+ }
+
+ /* Scale scalar states */
+ silk_SMULWW_small_b_4_neon( psDelDec->LF_AR_Q14, gain_adj_Q16_s32x2 );
+ silk_SMULWW_small_b_4_neon( psDelDec->Diff_Q14, gain_adj_Q16_s32x2 );
+
+ /* Scale short-term prediction and shaping states */
+ for( i = 0; i < NSQ_LPC_BUF_LENGTH; i++ ) {
+ silk_SMULWW_small_b_4_neon( psDelDec->sLPC_Q14[ i ], gain_adj_Q16_s32x2 );
+ }
+
+ for( i = 0; i < MAX_SHAPE_LPC_ORDER; i++ ) {
+ silk_SMULWW_small_b_4_neon( psDelDec->sAR2_Q14[ i ], gain_adj_Q16_s32x2 );
+ }
+
+ for( i = 0; i < DECISION_DELAY; i++ ) {
+ silk_SMULWW_small_b_4_neon( psDelDec->Pred_Q15[ i ], gain_adj_Q16_s32x2 );
+ silk_SMULWW_small_b_4_neon( psDelDec->Shape_Q14[ i ], gain_adj_Q16_s32x2 );
+ }
+ } else {
+ gain_adj_Q16_s32x2 = vdup_n_s32( silk_LSHIFT32( gain_adj_Q16 & 0x0000FFFF, 15 ) );
+ gain_adj_Q16_s32x2 = vset_lane_s32( gain_adj_Q16 >> 16, gain_adj_Q16_s32x2, 1 );
+ for( i = NSQ->sLTP_shp_buf_idx - psEncC->ltp_mem_length; i < NSQ->sLTP_shp_buf_idx - 7; i += 8 ) {
+ silk_SMULWW_8_neon( NSQ->sLTP_shp_Q14 + i, gain_adj_Q16_s32x2 );
+ }
+ for( ; i < NSQ->sLTP_shp_buf_idx; i++ ) {
+ NSQ->sLTP_shp_Q14[ i ] = silk_SMULWW( gain_adj_Q16, NSQ->sLTP_shp_Q14[ i ] );
+ }
+
+ /* Scale long-term prediction state */
+ if( signal_type == TYPE_VOICED && NSQ->rewhite_flag == 0 ) {
+ for( i = NSQ->sLTP_buf_idx - lag - LTP_ORDER / 2; i < NSQ->sLTP_buf_idx - decisionDelay - 7; i += 8 ) {
+ silk_SMULWW_8_neon( sLTP_Q15 + i, gain_adj_Q16_s32x2 );
+ }
+ for( ; i < NSQ->sLTP_buf_idx - decisionDelay; i++ ) {
+ sLTP_Q15[ i ] = silk_SMULWW( gain_adj_Q16, sLTP_Q15[ i ] );
+ }
+ }
+
+ /* Scale scalar states */
+ silk_SMULWW_4_neon( psDelDec->LF_AR_Q14, gain_adj_Q16_s32x2 );
+ silk_SMULWW_4_neon( psDelDec->Diff_Q14, gain_adj_Q16_s32x2 );
+
+ /* Scale short-term prediction and shaping states */
+ for( i = 0; i < NSQ_LPC_BUF_LENGTH; i++ ) {
+ silk_SMULWW_4_neon( psDelDec->sLPC_Q14[ i ], gain_adj_Q16_s32x2 );
+ }
+
+ for( i = 0; i < MAX_SHAPE_LPC_ORDER; i++ ) {
+ silk_SMULWW_4_neon( psDelDec->sAR2_Q14[ i ], gain_adj_Q16_s32x2 );
+ }
+
+ for( i = 0; i < DECISION_DELAY; i++ ) {
+ silk_SMULWW_4_neon( psDelDec->Pred_Q15[ i ], gain_adj_Q16_s32x2 );
+ silk_SMULWW_4_neon( psDelDec->Shape_Q14[ i ], gain_adj_Q16_s32x2 );
+ }
+ }
+
+ /* Save inverse gain */
+ NSQ->prev_gain_Q16 = Gains_Q16[ subfr ];
+ }
+}
diff --git a/libs/libopus/silk/arm/NSQ_neon.h b/libs/libopus/silk/arm/NSQ_neon.h
index 77c946af8..b31d9442d 100644
--- a/libs/libopus/silk/arm/NSQ_neon.h
+++ b/libs/libopus/silk/arm/NSQ_neon.h
@@ -28,30 +28,31 @@ POSSIBILITY OF SUCH DAMAGE.
#define SILK_NSQ_NEON_H
#include "cpu_support.h"
+#include "SigProc_FIX.h"
#undef silk_short_prediction_create_arch_coef
/* For vectorized calc, reverse a_Q12 coefs, convert to 32-bit, and shift for vqdmulhq_s32. */
static OPUS_INLINE void silk_short_prediction_create_arch_coef_neon(opus_int32 *out, const opus_int16 *in, opus_int order)
{
- out[15] = in[0] << 15;
- out[14] = in[1] << 15;
- out[13] = in[2] << 15;
- out[12] = in[3] << 15;
- out[11] = in[4] << 15;
- out[10] = in[5] << 15;
- out[9] = in[6] << 15;
- out[8] = in[7] << 15;
- out[7] = in[8] << 15;
- out[6] = in[9] << 15;
+ out[15] = silk_LSHIFT32(in[0], 15);
+ out[14] = silk_LSHIFT32(in[1], 15);
+ out[13] = silk_LSHIFT32(in[2], 15);
+ out[12] = silk_LSHIFT32(in[3], 15);
+ out[11] = silk_LSHIFT32(in[4], 15);
+ out[10] = silk_LSHIFT32(in[5], 15);
+ out[9] = silk_LSHIFT32(in[6], 15);
+ out[8] = silk_LSHIFT32(in[7], 15);
+ out[7] = silk_LSHIFT32(in[8], 15);
+ out[6] = silk_LSHIFT32(in[9], 15);
if (order == 16)
{
- out[5] = in[10] << 15;
- out[4] = in[11] << 15;
- out[3] = in[12] << 15;
- out[2] = in[13] << 15;
- out[1] = in[14] << 15;
- out[0] = in[15] << 15;
+ out[5] = silk_LSHIFT32(in[10], 15);
+ out[4] = silk_LSHIFT32(in[11], 15);
+ out[3] = silk_LSHIFT32(in[12], 15);
+ out[2] = silk_LSHIFT32(in[13], 15);
+ out[1] = silk_LSHIFT32(in[14], 15);
+ out[0] = silk_LSHIFT32(in[15], 15);
}
else
{
diff --git a/libs/libopus/silk/arm/arm_silk_map.c b/libs/libopus/silk/arm/arm_silk_map.c
index 9bd86a7b2..0b9bfec2c 100644
--- a/libs/libopus/silk/arm/arm_silk_map.c
+++ b/libs/libopus/silk/arm/arm_silk_map.c
@@ -28,13 +28,62 @@ POSSIBILITY OF SUCH DAMAGE.
# include "config.h"
#endif
+#include "main_FIX.h"
#include "NSQ.h"
+#include "SigProc_FIX.h"
#if defined(OPUS_HAVE_RTCD)
# if (defined(OPUS_ARM_MAY_HAVE_NEON_INTR) && \
!defined(OPUS_ARM_PRESUME_NEON_INTR))
+void (*const SILK_BIQUAD_ALT_STRIDE2_IMPL[OPUS_ARCHMASK + 1])(
+ const opus_int16 *in, /* I input signal */
+ const opus_int32 *B_Q28, /* I MA coefficients [3] */
+ const opus_int32 *A_Q28, /* I AR coefficients [2] */
+ opus_int32 *S, /* I/O State vector [4] */
+ opus_int16 *out, /* O output signal */
+ const opus_int32 len /* I signal length (must be even) */
+) = {
+ silk_biquad_alt_stride2_c, /* ARMv4 */
+ silk_biquad_alt_stride2_c, /* EDSP */
+ silk_biquad_alt_stride2_c, /* Media */
+ silk_biquad_alt_stride2_neon, /* Neon */
+};
+
+opus_int32 (*const SILK_LPC_INVERSE_PRED_GAIN_IMPL[OPUS_ARCHMASK + 1])( /* O Returns inverse prediction gain in energy domain, Q30 */
+ const opus_int16 *A_Q12, /* I Prediction coefficients, Q12 [order] */
+ const opus_int order /* I Prediction order */
+) = {
+ silk_LPC_inverse_pred_gain_c, /* ARMv4 */
+ silk_LPC_inverse_pred_gain_c, /* EDSP */
+ silk_LPC_inverse_pred_gain_c, /* Media */
+ silk_LPC_inverse_pred_gain_neon, /* Neon */
+};
+
+void (*const SILK_NSQ_DEL_DEC_IMPL[OPUS_ARCHMASK + 1])(
+ const silk_encoder_state *psEncC, /* I Encoder State */
+ silk_nsq_state *NSQ, /* I/O NSQ state */
+ SideInfoIndices *psIndices, /* I/O Quantization Indices */
+ const opus_int16 x16[], /* I Input */
+ opus_int8 pulses[], /* O Quantized pulse signal */
+ const opus_int16 PredCoef_Q12[ 2 * MAX_LPC_ORDER ], /* I Short term prediction coefs */
+ const opus_int16 LTPCoef_Q14[ LTP_ORDER * MAX_NB_SUBFR ], /* I Long term prediction coefs */
+ const opus_int16 AR_Q13[ MAX_NB_SUBFR * MAX_SHAPE_LPC_ORDER ], /* I Noise shaping coefs */
+ const opus_int HarmShapeGain_Q14[ MAX_NB_SUBFR ], /* I Long term shaping coefs */
+ const opus_int Tilt_Q14[ MAX_NB_SUBFR ], /* I Spectral tilt */
+ const opus_int32 LF_shp_Q14[ MAX_NB_SUBFR ], /* I Low frequency shaping coefs */
+ const opus_int32 Gains_Q16[ MAX_NB_SUBFR ], /* I Quantization step sizes */
+ const opus_int pitchL[ MAX_NB_SUBFR ], /* I Pitch lags */
+ const opus_int Lambda_Q10, /* I Rate/distortion tradeoff */
+ const opus_int LTP_scale_Q14 /* I LTP state scaling */
+) = {
+ silk_NSQ_del_dec_c, /* ARMv4 */
+ silk_NSQ_del_dec_c, /* EDSP */
+ silk_NSQ_del_dec_c, /* Media */
+ silk_NSQ_del_dec_neon, /* Neon */
+};
+
/*There is no table for silk_noise_shape_quantizer_short_prediction because the
NEON version takes different parameters than the C version.
Instead RTCD is done via if statements at the call sites.
@@ -52,4 +101,23 @@ opus_int32
# endif
+# if defined(FIXED_POINT) && \
+ defined(OPUS_ARM_MAY_HAVE_NEON_INTR) && !defined(OPUS_ARM_PRESUME_NEON_INTR)
+
+void (*const SILK_WARPED_AUTOCORRELATION_FIX_IMPL[OPUS_ARCHMASK + 1])(
+ opus_int32 *corr, /* O Result [order + 1] */
+ opus_int *scale, /* O Scaling of the correlation vector */
+ const opus_int16 *input, /* I Input data to correlate */
+ const opus_int warping_Q16, /* I Warping coefficient */
+ const opus_int length, /* I Length of input */
+ const opus_int order /* I Correlation order (even) */
+) = {
+ silk_warped_autocorrelation_FIX_c, /* ARMv4 */
+ silk_warped_autocorrelation_FIX_c, /* EDSP */
+ silk_warped_autocorrelation_FIX_c, /* Media */
+ silk_warped_autocorrelation_FIX_neon, /* Neon */
+};
+
+# endif
+
#endif /* OPUS_HAVE_RTCD */
diff --git a/libs/libopus/silk/arm/biquad_alt_arm.h b/libs/libopus/silk/arm/biquad_alt_arm.h
new file mode 100644
index 000000000..66ea9f43d
--- /dev/null
+++ b/libs/libopus/silk/arm/biquad_alt_arm.h
@@ -0,0 +1,68 @@
+/***********************************************************************
+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.
+***********************************************************************/
+
+#ifndef SILK_BIQUAD_ALT_ARM_H
+# define SILK_BIQUAD_ALT_ARM_H
+
+# include "celt/arm/armcpu.h"
+
+# if defined(OPUS_ARM_MAY_HAVE_NEON_INTR)
+void silk_biquad_alt_stride2_neon(
+ const opus_int16 *in, /* I input signal */
+ const opus_int32 *B_Q28, /* I MA coefficients [3] */
+ const opus_int32 *A_Q28, /* I AR coefficients [2] */
+ opus_int32 *S, /* I/O State vector [4] */
+ opus_int16 *out, /* O output signal */
+ const opus_int32 len /* I signal length (must be even) */
+);
+
+# if !defined(OPUS_HAVE_RTCD) && defined(OPUS_ARM_PRESUME_NEON)
+# define OVERRIDE_silk_biquad_alt_stride2 (1)
+# define silk_biquad_alt_stride2(in, B_Q28, A_Q28, S, out, len, arch) ((void)(arch), PRESUME_NEON(silk_biquad_alt_stride2)(in, B_Q28, A_Q28, S, out, len))
+# endif
+# endif
+
+# if !defined(OVERRIDE_silk_biquad_alt_stride2)
+/*Is run-time CPU detection enabled on this platform?*/
+# if defined(OPUS_HAVE_RTCD) && (defined(OPUS_ARM_MAY_HAVE_NEON_INTR) && !defined(OPUS_ARM_PRESUME_NEON_INTR))
+extern void (*const SILK_BIQUAD_ALT_STRIDE2_IMPL[OPUS_ARCHMASK+1])(
+ const opus_int16 *in, /* I input signal */
+ const opus_int32 *B_Q28, /* I MA coefficients [3] */
+ const opus_int32 *A_Q28, /* I AR coefficients [2] */
+ opus_int32 *S, /* I/O State vector [4] */
+ opus_int16 *out, /* O output signal */
+ const opus_int32 len /* I signal length (must be even) */
+ );
+# define OVERRIDE_silk_biquad_alt_stride2 (1)
+# define silk_biquad_alt_stride2(in, B_Q28, A_Q28, S, out, len, arch) ((*SILK_BIQUAD_ALT_STRIDE2_IMPL[(arch)&OPUS_ARCHMASK])(in, B_Q28, A_Q28, S, out, len))
+# elif defined(OPUS_ARM_PRESUME_NEON_INTR)
+# define OVERRIDE_silk_biquad_alt_stride2 (1)
+# define silk_biquad_alt_stride2(in, B_Q28, A_Q28, S, out, len, arch) ((void)(arch), silk_biquad_alt_stride2_neon(in, B_Q28, A_Q28, S, out, len))
+# endif
+# endif
+
+#endif /* end SILK_BIQUAD_ALT_ARM_H */
diff --git a/libs/libopus/silk/arm/biquad_alt_neon_intr.c b/libs/libopus/silk/arm/biquad_alt_neon_intr.c
new file mode 100644
index 000000000..971573318
--- /dev/null
+++ b/libs/libopus/silk/arm/biquad_alt_neon_intr.c
@@ -0,0 +1,156 @@
+/***********************************************************************
+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 <arm_neon.h>
+#ifdef OPUS_CHECK_ASM
+# include <string.h>
+# include "stack_alloc.h"
+#endif
+#include "SigProc_FIX.h"
+
+static inline void silk_biquad_alt_stride2_kernel( const int32x4_t A_L_s32x4, const int32x4_t A_U_s32x4, const int32x4_t B_Q28_s32x4, const int32x2_t t_s32x2, const int32x4_t in_s32x4, int32x4_t *S_s32x4, int32x2_t *out32_Q14_s32x2 )
+{
+ int32x4_t t_s32x4, out32_Q14_s32x4;
+
+ *out32_Q14_s32x2 = vadd_s32( vget_low_s32( *S_s32x4 ), t_s32x2 ); /* silk_SMLAWB( S{0,1}, B_Q28[ 0 ], in{0,1} ) */
+ *S_s32x4 = vcombine_s32( vget_high_s32( *S_s32x4 ), vdup_n_s32( 0 ) ); /* S{0,1} = S{2,3}; S{2,3} = 0; */
+ *out32_Q14_s32x2 = vshl_n_s32( *out32_Q14_s32x2, 2 ); /* out32_Q14_{0,1} = silk_LSHIFT( silk_SMLAWB( S{0,1}, B_Q28[ 0 ], in{0,1} ), 2 ); */
+ out32_Q14_s32x4 = vcombine_s32( *out32_Q14_s32x2, *out32_Q14_s32x2 ); /* out32_Q14_{0,1,0,1} */
+ t_s32x4 = vqdmulhq_s32( out32_Q14_s32x4, A_L_s32x4 ); /* silk_SMULWB( out32_Q14_{0,1,0,1}, A{0,0,1,1}_L_Q28 ) */
+ *S_s32x4 = vrsraq_n_s32( *S_s32x4, t_s32x4, 14 ); /* S{0,1} = S{2,3} + silk_RSHIFT_ROUND(); S{2,3} = silk_RSHIFT_ROUND(); */
+ t_s32x4 = vqdmulhq_s32( out32_Q14_s32x4, A_U_s32x4 ); /* silk_SMULWB( out32_Q14_{0,1,0,1}, A{0,0,1,1}_U_Q28 ) */
+ *S_s32x4 = vaddq_s32( *S_s32x4, t_s32x4 ); /* S0 = silk_SMLAWB( S{0,1,2,3}, out32_Q14_{0,1,0,1}, A{0,0,1,1}_U_Q28 ); */
+ t_s32x4 = vqdmulhq_s32( in_s32x4, B_Q28_s32x4 ); /* silk_SMULWB( B_Q28[ {1,1,2,2} ], in{0,1,0,1} ) */
+ *S_s32x4 = vaddq_s32( *S_s32x4, t_s32x4 ); /* S0 = silk_SMLAWB( S0, B_Q28[ {1,1,2,2} ], in{0,1,0,1} ); */
+}
+
+void silk_biquad_alt_stride2_neon(
+ const opus_int16 *in, /* I input signal */
+ const opus_int32 *B_Q28, /* I MA coefficients [3] */
+ const opus_int32 *A_Q28, /* I AR coefficients [2] */
+ opus_int32 *S, /* I/O State vector [4] */
+ opus_int16 *out, /* O output signal */
+ const opus_int32 len /* I signal length (must be even) */
+)
+{
+ /* DIRECT FORM II TRANSPOSED (uses 2 element state vector) */
+ opus_int k = 0;
+ const int32x2_t offset_s32x2 = vdup_n_s32( (1<<14) - 1 );
+ const int32x4_t offset_s32x4 = vcombine_s32( offset_s32x2, offset_s32x2 );
+ int16x4_t in_s16x4 = vdup_n_s16( 0 );
+ int16x4_t out_s16x4;
+ int32x2_t A_Q28_s32x2, A_L_s32x2, A_U_s32x2, B_Q28_s32x2, t_s32x2;
+ int32x4_t A_L_s32x4, A_U_s32x4, B_Q28_s32x4, S_s32x4, out32_Q14_s32x4;
+ int32x2x2_t t0_s32x2x2, t1_s32x2x2, t2_s32x2x2, S_s32x2x2;
+
+#ifdef OPUS_CHECK_ASM
+ opus_int32 S_c[ 4 ];
+ VARDECL( opus_int16, out_c );
+ SAVE_STACK;
+ ALLOC( out_c, 2 * len, opus_int16 );
+
+ silk_memcpy( &S_c, S, sizeof( S_c ) );
+ silk_biquad_alt_stride2_c( in, B_Q28, A_Q28, S_c, out_c, len );
+#endif
+
+ /* Negate A_Q28 values and split in two parts */
+ A_Q28_s32x2 = vld1_s32( A_Q28 );
+ A_Q28_s32x2 = vneg_s32( A_Q28_s32x2 );
+ A_L_s32x2 = vshl_n_s32( A_Q28_s32x2, 18 ); /* ( -A_Q28[] & 0x00003FFF ) << 18 */
+ A_L_s32x2 = vreinterpret_s32_u32( vshr_n_u32( vreinterpret_u32_s32( A_L_s32x2 ), 3 ) ); /* ( -A_Q28[] & 0x00003FFF ) << 15 */
+ A_U_s32x2 = vshr_n_s32( A_Q28_s32x2, 14 ); /* silk_RSHIFT( -A_Q28[], 14 ) */
+ A_U_s32x2 = vshl_n_s32( A_U_s32x2, 16 ); /* silk_RSHIFT( -A_Q28[], 14 ) << 16 (Clip two leading bits to conform to C function.) */
+ A_U_s32x2 = vshr_n_s32( A_U_s32x2, 1 ); /* silk_RSHIFT( -A_Q28[], 14 ) << 15 */
+
+ B_Q28_s32x2 = vld1_s32( B_Q28 );
+ t_s32x2 = vld1_s32( B_Q28 + 1 );
+ t0_s32x2x2 = vzip_s32( A_L_s32x2, A_L_s32x2 );
+ t1_s32x2x2 = vzip_s32( A_U_s32x2, A_U_s32x2 );
+ t2_s32x2x2 = vzip_s32( t_s32x2, t_s32x2 );
+ A_L_s32x4 = vcombine_s32( t0_s32x2x2.val[ 0 ], t0_s32x2x2.val[ 1 ] ); /* A{0,0,1,1}_L_Q28 */
+ A_U_s32x4 = vcombine_s32( t1_s32x2x2.val[ 0 ], t1_s32x2x2.val[ 1 ] ); /* A{0,0,1,1}_U_Q28 */
+ B_Q28_s32x4 = vcombine_s32( t2_s32x2x2.val[ 0 ], t2_s32x2x2.val[ 1 ] ); /* B_Q28[ {1,1,2,2} ] */
+ S_s32x4 = vld1q_s32( S ); /* S0 = S[ 0 ]; S3 = S[ 3 ]; */
+ S_s32x2x2 = vtrn_s32( vget_low_s32( S_s32x4 ), vget_high_s32( S_s32x4 ) ); /* S2 = S[ 1 ]; S1 = S[ 2 ]; */
+ S_s32x4 = vcombine_s32( S_s32x2x2.val[ 0 ], S_s32x2x2.val[ 1 ] );
+
+ for( ; k < len - 1; k += 2 ) {
+ int32x4_t in_s32x4[ 2 ], t_s32x4;
+ int32x2_t out32_Q14_s32x2[ 2 ];
+
+ /* S[ 2 * i + 0 ], S[ 2 * i + 1 ], S[ 2 * i + 2 ], S[ 2 * i + 3 ]: Q12 */
+ in_s16x4 = vld1_s16( &in[ 2 * k ] ); /* in{0,1,2,3} = in[ 2 * k + {0,1,2,3} ]; */
+ in_s32x4[ 0 ] = vshll_n_s16( in_s16x4, 15 ); /* in{0,1,2,3} << 15 */
+ t_s32x4 = vqdmulhq_lane_s32( in_s32x4[ 0 ], B_Q28_s32x2, 0 ); /* silk_SMULWB( B_Q28[ 0 ], in{0,1,2,3} ) */
+ in_s32x4[ 1 ] = vcombine_s32( vget_high_s32( in_s32x4[ 0 ] ), vget_high_s32( in_s32x4[ 0 ] ) ); /* in{2,3,2,3} << 15 */
+ in_s32x4[ 0 ] = vcombine_s32( vget_low_s32 ( in_s32x4[ 0 ] ), vget_low_s32 ( in_s32x4[ 0 ] ) ); /* in{0,1,0,1} << 15 */
+ silk_biquad_alt_stride2_kernel( A_L_s32x4, A_U_s32x4, B_Q28_s32x4, vget_low_s32 ( t_s32x4 ), in_s32x4[ 0 ], &S_s32x4, &out32_Q14_s32x2[ 0 ] );
+ silk_biquad_alt_stride2_kernel( A_L_s32x4, A_U_s32x4, B_Q28_s32x4, vget_high_s32( t_s32x4 ), in_s32x4[ 1 ], &S_s32x4, &out32_Q14_s32x2[ 1 ] );
+
+ /* Scale back to Q0 and saturate */
+ out32_Q14_s32x4 = vcombine_s32( out32_Q14_s32x2[ 0 ], out32_Q14_s32x2[ 1 ] ); /* out32_Q14_{0,1,2,3} */
+ out32_Q14_s32x4 = vaddq_s32( out32_Q14_s32x4, offset_s32x4 ); /* out32_Q14_{0,1,2,3} + (1<<14) - 1 */
+ out_s16x4 = vqshrn_n_s32( out32_Q14_s32x4, 14 ); /* (opus_int16)silk_SAT16( silk_RSHIFT( out32_Q14_{0,1,2,3} + (1<<14) - 1, 14 ) ) */
+ vst1_s16( &out[ 2 * k ], out_s16x4 ); /* out[ 2 * k + {0,1,2,3} ] = (opus_int16)silk_SAT16( silk_RSHIFT( out32_Q14_{0,1,2,3} + (1<<14) - 1, 14 ) ); */
+ }
+
+ /* Process leftover. */
+ if( k < len ) {
+ int32x4_t in_s32x4;
+ int32x2_t out32_Q14_s32x2;
+
+ /* S[ 2 * i + 0 ], S[ 2 * i + 1 ]: Q12 */
+ in_s16x4 = vld1_lane_s16( &in[ 2 * k + 0 ], in_s16x4, 0 ); /* in{0,1} = in[ 2 * k + {0,1} ]; */
+ in_s16x4 = vld1_lane_s16( &in[ 2 * k + 1 ], in_s16x4, 1 ); /* in{0,1} = in[ 2 * k + {0,1} ]; */
+ in_s32x4 = vshll_n_s16( in_s16x4, 15 ); /* in{0,1} << 15 */
+ t_s32x2 = vqdmulh_lane_s32( vget_low_s32( in_s32x4 ), B_Q28_s32x2, 0 ); /* silk_SMULWB( B_Q28[ 0 ], in{0,1} ) */
+ in_s32x4 = vcombine_s32( vget_low_s32( in_s32x4 ), vget_low_s32( in_s32x4 ) ); /* in{0,1,0,1} << 15 */
+ silk_biquad_alt_stride2_kernel( A_L_s32x4, A_U_s32x4, B_Q28_s32x4, t_s32x2, in_s32x4, &S_s32x4, &out32_Q14_s32x2 );
+
+ /* Scale back to Q0 and saturate */
+ out32_Q14_s32x2 = vadd_s32( out32_Q14_s32x2, offset_s32x2 ); /* out32_Q14_{0,1} + (1<<14) - 1 */
+ out32_Q14_s32x4 = vcombine_s32( out32_Q14_s32x2, out32_Q14_s32x2 ); /* out32_Q14_{0,1,0,1} + (1<<14) - 1 */
+ out_s16x4 = vqshrn_n_s32( out32_Q14_s32x4, 14 ); /* (opus_int16)silk_SAT16( silk_RSHIFT( out32_Q14_{0,1,0,1} + (1<<14) - 1, 14 ) ) */
+ vst1_lane_s16( &out[ 2 * k + 0 ], out_s16x4, 0 ); /* out[ 2 * k + 0 ] = (opus_int16)silk_SAT16( silk_RSHIFT( out32_Q14_0 + (1<<14) - 1, 14 ) ); */
+ vst1_lane_s16( &out[ 2 * k + 1 ], out_s16x4, 1 ); /* out[ 2 * k + 1 ] = (opus_int16)silk_SAT16( silk_RSHIFT( out32_Q14_1 + (1<<14) - 1, 14 ) ); */
+ }
+
+ vst1q_lane_s32( &S[ 0 ], S_s32x4, 0 ); /* S[ 0 ] = S0; */
+ vst1q_lane_s32( &S[ 1 ], S_s32x4, 2 ); /* S[ 1 ] = S2; */
+ vst1q_lane_s32( &S[ 2 ], S_s32x4, 1 ); /* S[ 2 ] = S1; */
+ vst1q_lane_s32( &S[ 3 ], S_s32x4, 3 ); /* S[ 3 ] = S3; */
+
+#ifdef OPUS_CHECK_ASM
+ silk_assert( !memcmp( S_c, S, sizeof( S_c ) ) );
+ silk_assert( !memcmp( out_c, out, 2 * len * sizeof( opus_int16 ) ) );
+ RESTORE_STACK;
+#endif
+}
diff --git a/libs/libopus/silk/arm/macros_armv4.h b/libs/libopus/silk/arm/macros_armv4.h
index 3f30e9728..877eb18dd 100644
--- a/libs/libopus/silk/arm/macros_armv4.h
+++ b/libs/libopus/silk/arm/macros_armv4.h
@@ -28,6 +28,11 @@ POSSIBILITY OF SUCH DAMAGE.
#ifndef SILK_MACROS_ARMv4_H
#define SILK_MACROS_ARMv4_H
+/* This macro only avoids the undefined behaviour from a left shift of
+ a negative value. It should only be used in macros that can't include
+ SigProc_FIX.h. In other cases, use silk_LSHIFT32(). */
+#define SAFE_SHL(a,b) ((opus_int32)((opus_uint32)(a) << (b)))
+
/* (a32 * (opus_int32)((opus_int16)(b32))) >> 16 output have to be 32bit int */
#undef silk_SMULWB
static OPUS_INLINE opus_int32 silk_SMULWB_armv4(opus_int32 a, opus_int16 b)
@@ -38,7 +43,7 @@ static OPUS_INLINE opus_int32 silk_SMULWB_armv4(opus_int32 a, opus_int16 b)
"#silk_SMULWB\n\t"
"smull %0, %1, %2, %3\n\t"
: "=&r"(rd_lo), "=&r"(rd_hi)
- : "%r"(a), "r"(b<<16)
+ : "%r"(a), "r"(SAFE_SHL(b,16))
);
return rd_hi;
}
@@ -80,7 +85,7 @@ static OPUS_INLINE opus_int32 silk_SMULWW_armv4(opus_int32 a, opus_int32 b)
: "=&r"(rd_lo), "=&r"(rd_hi)
: "%r"(a), "r"(b)
);
- return (rd_hi<<16)+(rd_lo>>16);
+ return SAFE_SHL(rd_hi,16)+(rd_lo>>16);
}
#define silk_SMULWW(a, b) (silk_SMULWW_armv4(a, b))
@@ -96,8 +101,10 @@ static OPUS_INLINE opus_int32 silk_SMLAWW_armv4(opus_int32 a, opus_int32 b,
: "=&r"(rd_lo), "=&r"(rd_hi)
: "%r"(b), "r"(c)
);
- return a+(rd_hi<<16)+(rd_lo>>16);
+ return a+SAFE_SHL(rd_hi,16)+(rd_lo>>16);
}
#define silk_SMLAWW(a, b, c) (silk_SMLAWW_armv4(a, b, c))
+#undef SAFE_SHL
+
#endif /* SILK_MACROS_ARMv4_H */
diff --git a/libs/libopus/silk/arm/macros_armv5e.h b/libs/libopus/silk/arm/macros_armv5e.h
index aad4117e4..b14ec65dd 100644
--- a/libs/libopus/silk/arm/macros_armv5e.h
+++ b/libs/libopus/silk/arm/macros_armv5e.h
@@ -29,6 +29,11 @@ POSSIBILITY OF SUCH DAMAGE.
#ifndef SILK_MACROS_ARMv5E_H
#define SILK_MACROS_ARMv5E_H
+/* This macro only avoids the undefined behaviour from a left shift of
+ a negative value. It should only be used in macros that can't include
+ SigProc_FIX.h. In other cases, use silk_LSHIFT32(). */
+#define SAFE_SHL(a,b) ((opus_int32)((opus_uint32)(a) << (b)))
+
/* (a32 * (opus_int32)((opus_int16)(b32))) >> 16 output have to be 32bit int */
#undef silk_SMULWB
static OPUS_INLINE opus_int32 silk_SMULWB_armv5e(opus_int32 a, opus_int16 b)
@@ -190,7 +195,7 @@ static OPUS_INLINE opus_int32 silk_CLZ16_armv5(opus_int16 in16)
"#silk_CLZ16\n\t"
"clz %0, %1;\n"
: "=r"(res)
- : "r"(in16<<16|0x8000)
+ : "r"(SAFE_SHL(in16,16)|0x8000)
);
return res;
}
@@ -210,4 +215,6 @@ static OPUS_INLINE opus_int32 silk_CLZ32_armv5(opus_int32 in32)
}
#define silk_CLZ32(in32) (silk_CLZ32_armv5(in32))
+#undef SAFE_SHL
+
#endif /* SILK_MACROS_ARMv5E_H */
diff --git a/libs/libopus/silk/biquad_alt.c b/libs/libopus/silk/biquad_alt.c
index d55f5ee92..54566a43c 100644
--- a/libs/libopus/silk/biquad_alt.c
+++ b/libs/libopus/silk/biquad_alt.c
@@ -39,14 +39,13 @@ POSSIBILITY OF SUCH DAMAGE.
#include "SigProc_FIX.h"
/* Second order ARMA filter, alternative implementation */
-void silk_biquad_alt(
+void silk_biquad_alt_stride1(
const opus_int16 *in, /* I input signal */
const opus_int32 *B_Q28, /* I MA coefficients [3] */
const opus_int32 *A_Q28, /* I AR coefficients [2] */
opus_int32 *S, /* I/O State vector [2] */
opus_int16 *out, /* O output signal */
- const opus_int32 len, /* I signal length (must be even) */
- opus_int stride /* I Operate on interleaved signal if > 1 */
+ const opus_int32 len /* I signal length (must be even) */
)
{
/* DIRECT FORM II TRANSPOSED (uses 2 element state vector) */
@@ -61,7 +60,7 @@ void silk_biquad_alt(
for( k = 0; k < len; k++ ) {
/* S[ 0 ], S[ 1 ]: Q12 */
- inval = in[ k * stride ];
+ inval = in[ k ];
out32_Q14 = silk_LSHIFT( silk_SMLAWB( S[ 0 ], B_Q28[ 0 ], inval ), 2 );
S[ 0 ] = S[1] + silk_RSHIFT_ROUND( silk_SMULWB( out32_Q14, A0_L_Q28 ), 14 );
@@ -73,6 +72,50 @@ void silk_biquad_alt(
S[ 1 ] = silk_SMLAWB( S[ 1 ], B_Q28[ 2 ], inval );
/* Scale back to Q0 and saturate */
- out[ k * stride ] = (opus_int16)silk_SAT16( silk_RSHIFT( out32_Q14 + (1<<14) - 1, 14 ) );
+ out[ k ] = (opus_int16)silk_SAT16( silk_RSHIFT( out32_Q14 + (1<<14) - 1, 14 ) );
+ }
+}
+
+void silk_biquad_alt_stride2_c(
+ const opus_int16 *in, /* I input signal */
+ const opus_int32 *B_Q28, /* I MA coefficients [3] */
+ const opus_int32 *A_Q28, /* I AR coefficients [2] */
+ opus_int32 *S, /* I/O State vector [4] */
+ opus_int16 *out, /* O output signal */
+ const opus_int32 len /* I signal length (must be even) */
+)
+{
+ /* DIRECT FORM II TRANSPOSED (uses 2 element state vector) */
+ opus_int k;
+ opus_int32 A0_U_Q28, A0_L_Q28, A1_U_Q28, A1_L_Q28, out32_Q14[ 2 ];
+
+ /* Negate A_Q28 values and split in two parts */
+ A0_L_Q28 = ( -A_Q28[ 0 ] ) & 0x00003FFF; /* lower part */
+ A0_U_Q28 = silk_RSHIFT( -A_Q28[ 0 ], 14 ); /* upper part */
+ A1_L_Q28 = ( -A_Q28[ 1 ] ) & 0x00003FFF; /* lower part */
+ A1_U_Q28 = silk_RSHIFT( -A_Q28[ 1 ], 14 ); /* upper part */
+
+ for( k = 0; k < len; k++ ) {
+ /* S[ 0 ], S[ 1 ], S[ 2 ], S[ 3 ]: Q12 */
+ out32_Q14[ 0 ] = silk_LSHIFT( silk_SMLAWB( S[ 0 ], B_Q28[ 0 ], in[ 2 * k + 0 ] ), 2 );
+ out32_Q14[ 1 ] = silk_LSHIFT( silk_SMLAWB( S[ 2 ], B_Q28[ 0 ], in[ 2 * k + 1 ] ), 2 );
+
+ S[ 0 ] = S[ 1 ] + silk_RSHIFT_ROUND( silk_SMULWB( out32_Q14[ 0 ], A0_L_Q28 ), 14 );
+ S[ 2 ] = S[ 3 ] + silk_RSHIFT_ROUND( silk_SMULWB( out32_Q14[ 1 ], A0_L_Q28 ), 14 );
+ S[ 0 ] = silk_SMLAWB( S[ 0 ], out32_Q14[ 0 ], A0_U_Q28 );
+ S[ 2 ] = silk_SMLAWB( S[ 2 ], out32_Q14[ 1 ], A0_U_Q28 );
+ S[ 0 ] = silk_SMLAWB( S[ 0 ], B_Q28[ 1 ], in[ 2 * k + 0 ] );
+ S[ 2 ] = silk_SMLAWB( S[ 2 ], B_Q28[ 1 ], in[ 2 * k + 1 ] );
+
+ S[ 1 ] = silk_RSHIFT_ROUND( silk_SMULWB( out32_Q14[ 0 ], A1_L_Q28 ), 14 );
+ S[ 3 ] = silk_RSHIFT_ROUND( silk_SMULWB( out32_Q14[ 1 ], A1_L_Q28 ), 14 );
+ S[ 1 ] = silk_SMLAWB( S[ 1 ], out32_Q14[ 0 ], A1_U_Q28 );
+ S[ 3 ] = silk_SMLAWB( S[ 3 ], out32_Q14[ 1 ], A1_U_Q28 );
+ S[ 1 ] = silk_SMLAWB( S[ 1 ], B_Q28[ 2 ], in[ 2 * k + 0 ] );
+ S[ 3 ] = silk_SMLAWB( S[ 3 ], B_Q28[ 2 ], in[ 2 * k + 1 ] );
+
+ /* Scale back to Q0 and saturate */
+ out[ 2 * k + 0 ] = (opus_int16)silk_SAT16( silk_RSHIFT( out32_Q14[ 0 ] + (1<<14) - 1, 14 ) );
+ out[ 2 * k + 1 ] = (opus_int16)silk_SAT16( silk_RSHIFT( out32_Q14[ 1 ] + (1<<14) - 1, 14 ) );
}
}
diff --git a/libs/libopus/silk/bwexpander.c b/libs/libopus/silk/bwexpander.c
index 2eb445669..afa97907e 100644
--- a/libs/libopus/silk/bwexpander.c
+++ b/libs/libopus/silk/bwexpander.c
@@ -45,7 +45,7 @@ void silk_bwexpander(
/* Bias in silk_SMULWB can lead to unstable filters */
for( i = 0; i < d - 1; i++ ) {
ar[ i ] = (opus_int16)silk_RSHIFT_ROUND( silk_MUL( chirp_Q16, ar[ i ] ), 16 );
- chirp_Q16 += silk_RSHIFT_ROUND( silk_MUL( chirp_Q16, chirp_minus_one_Q16 ), 16 );
+ chirp_Q16 += silk_RSHIFT_ROUND( silk_MUL( chirp_Q16, chirp_minus_one_Q16 ), 16 );
}
ar[ d - 1 ] = (opus_int16)silk_RSHIFT_ROUND( silk_MUL( chirp_Q16, ar[ d - 1 ] ), 16 );
}
diff --git a/libs/libopus/silk/bwexpander_32.c b/libs/libopus/silk/bwexpander_32.c
index d0010f73d..0f32b9df1 100644
--- a/libs/libopus/silk/bwexpander_32.c
+++ b/libs/libopus/silk/bwexpander_32.c
@@ -31,7 +31,8 @@ POSSIBILITY OF SUCH DAMAGE.
#include "SigProc_FIX.h"
-/* Chirp (bandwidth expand) LP AR filter */
+/* Chirp (bandwidth expand) LP AR filter.
+ This logic is reused in _celt_lpc(). Any bug fixes should also be applied there. */
void silk_bwexpander_32(
opus_int32 *ar, /* I/O AR filter to be expanded (without leading 1) */
const opus_int d, /* I Length of ar */
diff --git a/libs/libopus/silk/check_control_input.c b/libs/libopus/silk/check_control_input.c
index b5de9ce48..739fb01f1 100644
--- a/libs/libopus/silk/check_control_input.c
+++ b/libs/libopus/silk/check_control_input.c
@@ -38,7 +38,7 @@ opus_int check_control_input(
silk_EncControlStruct *encControl /* I Control structure */
)
{
- silk_assert( encControl != NULL );
+ celt_assert( encControl != NULL );
if( ( ( encControl->API_sampleRate != 8000 ) &&
( encControl->API_sampleRate != 12000 ) &&
@@ -59,46 +59,46 @@ opus_int check_control_input(
( encControl->minInternalSampleRate > encControl->desiredInternalSampleRate ) ||
( encControl->maxInternalSampleRate < encControl->desiredInternalSampleRate ) ||
( encControl->minInternalSampleRate > encControl->maxInternalSampleRate ) ) {
- silk_assert( 0 );
+ celt_assert( 0 );
return SILK_ENC_FS_NOT_SUPPORTED;
}
if( encControl->payloadSize_ms != 10 &&
encControl->payloadSize_ms != 20 &&
encControl->payloadSize_ms != 40 &&
encControl->payloadSize_ms != 60 ) {
- silk_assert( 0 );
+ celt_assert( 0 );
return SILK_ENC_PACKET_SIZE_NOT_SUPPORTED;
}
if( encControl->packetLossPercentage < 0 || encControl->packetLossPercentage > 100 ) {
- silk_assert( 0 );
+ celt_assert( 0 );
return SILK_ENC_INVALID_LOSS_RATE;
}
if( encControl->useDTX < 0 || encControl->useDTX > 1 ) {
- silk_assert( 0 );
+ celt_assert( 0 );
return SILK_ENC_INVALID_DTX_SETTING;
}
if( encControl->useCBR < 0 || encControl->useCBR > 1 ) {
- silk_assert( 0 );
+ celt_assert( 0 );
return SILK_ENC_INVALID_CBR_SETTING;
}
if( encControl->useInBandFEC < 0 || encControl->useInBandFEC > 1 ) {
- silk_assert( 0 );
+ celt_assert( 0 );
return SILK_ENC_INVALID_INBAND_FEC_SETTING;
}
if( encControl->nChannelsAPI < 1 || encControl->nChannelsAPI > ENCODER_NUM_CHANNELS ) {
- silk_assert( 0 );
+ celt_assert( 0 );
return SILK_ENC_INVALID_NUMBER_OF_CHANNELS_ERROR;
}
if( encControl->nChannelsInternal < 1 || encControl->nChannelsInternal > ENCODER_NUM_CHANNELS ) {
- silk_assert( 0 );
+ celt_assert( 0 );
return SILK_ENC_INVALID_NUMBER_OF_CHANNELS_ERROR;
}
if( encControl->nChannelsInternal > encControl->nChannelsAPI ) {
- silk_assert( 0 );
+ celt_assert( 0 );
return SILK_ENC_INVALID_NUMBER_OF_CHANNELS_ERROR;
}
if( encControl->complexity < 0 || encControl->complexity > 10 ) {
- silk_assert( 0 );
+ celt_assert( 0 );
return SILK_ENC_INVALID_COMPLEXITY_SETTING;
}
diff --git a/libs/libopus/silk/control.h b/libs/libopus/silk/control.h
index 747e5426a..b76ec33cd 100644
--- a/libs/libopus/silk/control.h
+++ b/libs/libopus/silk/control.h
@@ -77,6 +77,9 @@ typedef struct {
/* I: Flag to enable in-band Forward Error Correction (FEC); 0/1 */
opus_int useInBandFEC;
+ /* I: Flag to actually code in-band Forward Error Correction (FEC) in the current packet; 0/1 */
+ opus_int LBRR_coded;
+
/* I: Flag to enable discontinuous transmission (DTX); 0/1 */
opus_int useDTX;
@@ -110,6 +113,11 @@ typedef struct {
/* O: Tells the Opus encoder we're ready to switch */
opus_int switchReady;
+ /* O: SILK Signal type */
+ opus_int signalType;
+
+ /* O: SILK offset (dithering) */
+ opus_int offset;
} silk_EncControlStruct;
/**************************************************************************/
diff --git a/libs/libopus/silk/control_SNR.c b/libs/libopus/silk/control_SNR.c
index cee87eb0d..9a6db2754 100644
--- a/libs/libopus/silk/control_SNR.c
+++ b/libs/libopus/silk/control_SNR.c
@@ -32,45 +32,82 @@ POSSIBILITY OF SUCH DAMAGE.
#include "main.h"
#include "tuning_parameters.h"
+/* These tables hold SNR values divided by 21 (so they fit in 8 bits)
+ for different target bitrates spaced at 400 bps interval. The first
+ 10 values are omitted (0-4 kb/s) because they're all zeros.
+ These tables were obtained by running different SNRs through the
+ encoder and measuring the active bitrate. */
+static const unsigned char silk_TargetRate_NB_21[117 - 10] = {
+ 0, 15, 39, 52, 61, 68,
+ 74, 79, 84, 88, 92, 95, 99,102,105,108,111,114,117,119,122,124,
+ 126,129,131,133,135,137,139,142,143,145,147,149,151,153,155,157,
+ 158,160,162,163,165,167,168,170,171,173,174,176,177,179,180,182,
+ 183,185,186,187,189,190,192,193,194,196,197,199,200,201,203,204,
+ 205,207,208,209,211,212,213,215,216,217,219,220,221,223,224,225,
+ 227,228,230,231,232,234,235,236,238,239,241,242,243,245,246,248,
+ 249,250,252,253,255
+};
+
+static const unsigned char silk_TargetRate_MB_21[165 - 10] = {
+ 0, 0, 28, 43, 52, 59,
+ 65, 70, 74, 78, 81, 85, 87, 90, 93, 95, 98,100,102,105,107,109,
+ 111,113,115,116,118,120,122,123,125,127,128,130,131,133,134,136,
+ 137,138,140,141,143,144,145,147,148,149,151,152,153,154,156,157,
+ 158,159,160,162,163,164,165,166,167,168,169,171,172,173,174,175,
+ 176,177,178,179,180,181,182,183,184,185,186,187,188,188,189,190,
+ 191,192,193,194,195,196,197,198,199,200,201,202,203,203,204,205,
+ 206,207,208,209,210,211,212,213,214,214,215,216,217,218,219,220,
+ 221,222,223,224,224,225,226,227,228,229,230,231,232,233,234,235,
+ 236,236,237,238,239,240,241,242,243,244,245,246,247,248,249,250,
+ 251,252,253,254,255
+};
+
+static const unsigned char silk_TargetRate_WB_21[201 - 10] = {
+ 0, 0, 0, 8, 29, 41,
+ 49, 56, 62, 66, 70, 74, 77, 80, 83, 86, 88, 91, 93, 95, 97, 99,
+ 101,103,105,107,108,110,112,113,115,116,118,119,121,122,123,125,
+ 126,127,129,130,131,132,134,135,136,137,138,140,141,142,143,144,
+ 145,146,147,148,149,150,151,152,153,154,156,157,158,159,159,160,
+ 161,162,163,164,165,166,167,168,169,170,171,171,172,173,174,175,
+ 176,177,177,178,179,180,181,181,182,183,184,185,185,186,187,188,
+ 189,189,190,191,192,192,193,194,195,195,196,197,198,198,199,200,
+ 200,201,202,203,203,204,205,206,206,207,208,209,209,210,211,211,
+ 212,213,214,214,215,216,216,217,218,219,219,220,221,221,222,223,
+ 224,224,225,226,226,227,228,229,229,230,231,232,232,233,234,234,
+ 235,236,237,237,238,239,240,240,241,242,243,243,244,245,246,246,
+ 247,248,249,249,250,251,252,253,255
+};
+
/* Control SNR of redidual quantizer */
opus_int silk_control_SNR(
silk_encoder_state *psEncC, /* I/O Pointer to Silk encoder state */
opus_int32 TargetRate_bps /* I Target max bitrate (bps) */
)
{
- opus_int k, ret = SILK_NO_ERROR;
- opus_int32 frac_Q6;
- const opus_int32 *rateTable;
-
- /* Set bitrate/coding quality */
- TargetRate_bps = silk_LIMIT( TargetRate_bps, MIN_TARGET_RATE_BPS, MAX_TARGET_RATE_BPS );
- if( TargetRate_bps != psEncC->TargetRate_bps ) {
- psEncC->TargetRate_bps = TargetRate_bps;
-
- /* If new TargetRate_bps, translate to SNR_dB value */
- if( psEncC->fs_kHz == 8 ) {
- rateTable = silk_TargetRate_table_NB;
- } else if( psEncC->fs_kHz == 12 ) {
- rateTable = silk_TargetRate_table_MB;
- } else {
- rateTable = silk_TargetRate_table_WB;
- }
+ int id;
+ int bound;
+ const unsigned char *snr_table;
- /* Reduce bitrate for 10 ms modes in these calculations */
- if( psEncC->nb_subfr == 2 ) {
- TargetRate_bps -= REDUCE_BITRATE_10_MS_BPS;
- }
-
- /* Find bitrate interval in table and interpolate */
- for( k = 1; k < TARGET_RATE_TAB_SZ; k++ ) {
- if( TargetRate_bps <= rateTable[ k ] ) {
- frac_Q6 = silk_DIV32( silk_LSHIFT( TargetRate_bps - rateTable[ k - 1 ], 6 ),
- rateTable[ k ] - rateTable[ k - 1 ] );
- psEncC->SNR_dB_Q7 = silk_LSHIFT( silk_SNR_table_Q1[ k - 1 ], 6 ) + silk_MUL( frac_Q6, silk_SNR_table_Q1[ k ] - silk_SNR_table_Q1[ k - 1 ] );
- break;
- }
- }
+ psEncC->TargetRate_bps = TargetRate_bps;
+ if( psEncC->nb_subfr == 2 ) {
+ TargetRate_bps -= 2000 + psEncC->fs_kHz/16;
}
-
- return ret;
+ if( psEncC->fs_kHz == 8 ) {
+ bound = sizeof(silk_TargetRate_NB_21);
+ snr_table = silk_TargetRate_NB_21;
+ } else if( psEncC->fs_kHz == 12 ) {
+ bound = sizeof(silk_TargetRate_MB_21);
+ snr_table = silk_TargetRate_MB_21;
+ } else {
+ bound = sizeof(silk_TargetRate_WB_21);
+ snr_table = silk_TargetRate_WB_21;
+ }
+ id = (TargetRate_bps+200)/400;
+ id = silk_min(id - 10, bound-1);
+ if( id <= 0 ) {
+ psEncC->SNR_dB_Q7 = 0;
+ } else {
+ psEncC->SNR_dB_Q7 = snr_table[id]*21;
+ }
+ return SILK_NO_ERROR;
}
diff --git a/libs/libopus/silk/control_audio_bandwidth.c b/libs/libopus/silk/control_audio_bandwidth.c
index 4f9bc5cbd..f6d22d839 100644
--- a/libs/libopus/silk/control_audio_bandwidth.c
+++ b/libs/libopus/silk/control_audio_bandwidth.c
@@ -39,9 +39,15 @@ opus_int silk_control_audio_bandwidth(
)
{
opus_int fs_kHz;
+ opus_int orig_kHz;
opus_int32 fs_Hz;
- fs_kHz = psEncC->fs_kHz;
+ orig_kHz = psEncC->fs_kHz;
+ /* Handle a bandwidth-switching reset where we need to be aware what the last sampling rate was. */
+ if( orig_kHz == 0 ) {
+ orig_kHz = psEncC->sLP.saved_fs_kHz;
+ }
+ fs_kHz = orig_kHz;
fs_Hz = silk_SMULBB( fs_kHz, 1000 );
if( fs_Hz == 0 ) {
/* Encoder has just been initialized */
@@ -61,7 +67,7 @@ opus_int silk_control_audio_bandwidth(
}
if( psEncC->allow_bandwidth_switch || encControl->opusCanSwitch ) {
/* Check if we should switch down */
- if( silk_SMULBB( psEncC->fs_kHz, 1000 ) > psEncC->desiredInternal_fs_Hz )
+ if( silk_SMULBB( orig_kHz, 1000 ) > psEncC->desiredInternal_fs_Hz )
{
/* Switch down */
if( psEncC->sLP.mode == 0 ) {
@@ -76,7 +82,7 @@ opus_int silk_control_audio_bandwidth(
psEncC->sLP.mode = 0;
/* Switch to a lower sample frequency */
- fs_kHz = psEncC->fs_kHz == 16 ? 12 : 8;
+ fs_kHz = orig_kHz == 16 ? 12 : 8;
} else {
if( psEncC->sLP.transition_frame_no <= 0 ) {
encControl->switchReady = 1;
@@ -90,12 +96,12 @@ opus_int silk_control_audio_bandwidth(
}
else
/* Check if we should switch up */
- if( silk_SMULBB( psEncC->fs_kHz, 1000 ) < psEncC->desiredInternal_fs_Hz )
+ if( silk_SMULBB( orig_kHz, 1000 ) < psEncC->desiredInternal_fs_Hz )
{
/* Switch up */
if( encControl->opusCanSwitch ) {
/* Switch to a higher sample frequency */
- fs_kHz = psEncC->fs_kHz == 8 ? 12 : 16;
+ fs_kHz = orig_kHz == 8 ? 12 : 16;
/* New transition */
psEncC->sLP.transition_frame_no = 0;
diff --git a/libs/libopus/silk/control_codec.c b/libs/libopus/silk/control_codec.c
index 044eea3f2..52aa8fded 100644
--- a/libs/libopus/silk/control_codec.c
+++ b/libs/libopus/silk/control_codec.c
@@ -57,7 +57,7 @@ static opus_int silk_setup_complexity(
static OPUS_INLINE opus_int silk_setup_LBRR(
silk_encoder_state *psEncC, /* I/O */
- const opus_int32 TargetRate_bps /* I */
+ const silk_EncControlStruct *encControl /* I */
);
@@ -65,7 +65,6 @@ static OPUS_INLINE opus_int silk_setup_LBRR(
opus_int silk_control_encoder(
silk_encoder_state_Fxx *psEnc, /* I/O Pointer to Silk encoder state */
silk_EncControlStruct *encControl, /* I Control structure */
- const opus_int32 TargetRate_bps, /* I Target max bitrate (bps) */
const opus_int allow_bw_switch, /* I Flag to allow switching audio bandwidth */
const opus_int channelNb, /* I Channel number */
const opus_int force_fs_kHz
@@ -125,7 +124,7 @@ opus_int silk_control_encoder(
/********************************************/
/* Set LBRR usage */
/********************************************/
- ret += silk_setup_LBRR( &psEnc->sCmn, TargetRate_bps );
+ ret += silk_setup_LBRR( &psEnc->sCmn, encControl );
psEnc->sCmn.controlled_since_last_payload = 1;
@@ -239,12 +238,11 @@ static opus_int silk_setup_fs(
}
/* Set internal sampling frequency */
- silk_assert( fs_kHz == 8 || fs_kHz == 12 || fs_kHz == 16 );
- silk_assert( psEnc->sCmn.nb_subfr == 2 || psEnc->sCmn.nb_subfr == 4 );
+ celt_assert( fs_kHz == 8 || fs_kHz == 12 || fs_kHz == 16 );
+ celt_assert( psEnc->sCmn.nb_subfr == 2 || psEnc->sCmn.nb_subfr == 4 );
if( psEnc->sCmn.fs_kHz != fs_kHz ) {
/* reset part of the state */
silk_memset( &psEnc->sShape, 0, sizeof( psEnc->sShape ) );
- silk_memset( &psEnc->sPrefilt, 0, sizeof( psEnc->sPrefilt ) );
silk_memset( &psEnc->sCmn.sNSQ, 0, sizeof( psEnc->sCmn.sNSQ ) );
silk_memset( psEnc->sCmn.prev_NLSFq_Q15, 0, sizeof( psEnc->sCmn.prev_NLSFq_Q15 ) );
silk_memset( &psEnc->sCmn.sLP.In_LP_State, 0, sizeof( psEnc->sCmn.sLP.In_LP_State ) );
@@ -255,7 +253,6 @@ static opus_int silk_setup_fs(
/* Initialize non-zero parameters */
psEnc->sCmn.prevLag = 100;
psEnc->sCmn.first_frame_after_reset = 1;
- psEnc->sPrefilt.lagPrev = 100;
psEnc->sShape.LastGainIndex = 10;
psEnc->sCmn.sNSQ.lagPrev = 100;
psEnc->sCmn.sNSQ.prev_gain_Q16 = 65536;
@@ -293,19 +290,16 @@ static opus_int silk_setup_fs(
psEnc->sCmn.pitch_LPC_win_length = silk_SMULBB( FIND_PITCH_LPC_WIN_MS_2_SF, fs_kHz );
}
if( psEnc->sCmn.fs_kHz == 16 ) {
- psEnc->sCmn.mu_LTP_Q9 = SILK_FIX_CONST( MU_LTP_QUANT_WB, 9 );
psEnc->sCmn.pitch_lag_low_bits_iCDF = silk_uniform8_iCDF;
} else if( psEnc->sCmn.fs_kHz == 12 ) {
- psEnc->sCmn.mu_LTP_Q9 = SILK_FIX_CONST( MU_LTP_QUANT_MB, 9 );
psEnc->sCmn.pitch_lag_low_bits_iCDF = silk_uniform6_iCDF;
} else {
- psEnc->sCmn.mu_LTP_Q9 = SILK_FIX_CONST( MU_LTP_QUANT_NB, 9 );
psEnc->sCmn.pitch_lag_low_bits_iCDF = silk_uniform4_iCDF;
}
}
/* Check that settings are valid */
- silk_assert( ( psEnc->sCmn.subfr_length * psEnc->sCmn.nb_subfr ) == psEnc->sCmn.frame_length );
+ celt_assert( ( psEnc->sCmn.subfr_length * psEnc->sCmn.nb_subfr ) == psEnc->sCmn.frame_length );
return ret;
}
@@ -318,61 +312,76 @@ static opus_int silk_setup_complexity(
opus_int ret = 0;
/* Set encoding complexity */
- silk_assert( Complexity >= 0 && Complexity <= 10 );
- if( Complexity < 2 ) {
+ celt_assert( Complexity >= 0 && Complexity <= 10 );
+ if( Complexity < 1 ) {
psEncC->pitchEstimationComplexity = SILK_PE_MIN_COMPLEX;
psEncC->pitchEstimationThreshold_Q16 = SILK_FIX_CONST( 0.8, 16 );
psEncC->pitchEstimationLPCOrder = 6;
- psEncC->shapingLPCOrder = 8;
+ psEncC->shapingLPCOrder = 12;
psEncC->la_shape = 3 * psEncC->fs_kHz;
psEncC->nStatesDelayedDecision = 1;
psEncC->useInterpolatedNLSFs = 0;
- psEncC->LTPQuantLowComplexity = 1;
psEncC->NLSF_MSVQ_Survivors = 2;
psEncC->warping_Q16 = 0;
- } else if( Complexity < 4 ) {
+ } else if( Complexity < 2 ) {
psEncC->pitchEstimationComplexity = SILK_PE_MID_COMPLEX;
psEncC->pitchEstimationThreshold_Q16 = SILK_FIX_CONST( 0.76, 16 );
psEncC->pitchEstimationLPCOrder = 8;
- psEncC->shapingLPCOrder = 10;
+ psEncC->shapingLPCOrder = 14;
psEncC->la_shape = 5 * psEncC->fs_kHz;
psEncC->nStatesDelayedDecision = 1;
psEncC->useInterpolatedNLSFs = 0;
- psEncC->LTPQuantLowComplexity = 0;
+ psEncC->NLSF_MSVQ_Survivors = 3;
+ psEncC->warping_Q16 = 0;
+ } else if( Complexity < 3 ) {
+ psEncC->pitchEstimationComplexity = SILK_PE_MIN_COMPLEX;
+ psEncC->pitchEstimationThreshold_Q16 = SILK_FIX_CONST( 0.8, 16 );
+ psEncC->pitchEstimationLPCOrder = 6;
+ psEncC->shapingLPCOrder = 12;
+ psEncC->la_shape = 3 * psEncC->fs_kHz;
+ psEncC->nStatesDelayedDecision = 2;
+ psEncC->useInterpolatedNLSFs = 0;
+ psEncC->NLSF_MSVQ_Survivors = 2;
+ psEncC->warping_Q16 = 0;
+ } else if( Complexity < 4 ) {
+ psEncC->pitchEstimationComplexity = SILK_PE_MID_COMPLEX;
+ psEncC->pitchEstimationThreshold_Q16 = SILK_FIX_CONST( 0.76, 16 );
+ psEncC->pitchEstimationLPCOrder = 8;
+ psEncC->shapingLPCOrder = 14;
+ psEncC->la_shape = 5 * psEncC->fs_kHz;
+ psEncC->nStatesDelayedDecision = 2;
+ psEncC->useInterpolatedNLSFs = 0;
psEncC->NLSF_MSVQ_Survivors = 4;
psEncC->warping_Q16 = 0;
} else if( Complexity < 6 ) {
psEncC->pitchEstimationComplexity = SILK_PE_MID_COMPLEX;
psEncC->pitchEstimationThreshold_Q16 = SILK_FIX_CONST( 0.74, 16 );
psEncC->pitchEstimationLPCOrder = 10;
- psEncC->shapingLPCOrder = 12;
+ psEncC->shapingLPCOrder = 16;
psEncC->la_shape = 5 * psEncC->fs_kHz;
psEncC->nStatesDelayedDecision = 2;
psEncC->useInterpolatedNLSFs = 1;
- psEncC->LTPQuantLowComplexity = 0;
- psEncC->NLSF_MSVQ_Survivors = 8;
+ psEncC->NLSF_MSVQ_Survivors = 6;
psEncC->warping_Q16 = psEncC->fs_kHz * SILK_FIX_CONST( WARPING_MULTIPLIER, 16 );
} else if( Complexity < 8 ) {
psEncC->pitchEstimationComplexity = SILK_PE_MID_COMPLEX;
psEncC->pitchEstimationThreshold_Q16 = SILK_FIX_CONST( 0.72, 16 );
psEncC->pitchEstimationLPCOrder = 12;
- psEncC->shapingLPCOrder = 14;
+ psEncC->shapingLPCOrder = 20;
psEncC->la_shape = 5 * psEncC->fs_kHz;
psEncC->nStatesDelayedDecision = 3;
psEncC->useInterpolatedNLSFs = 1;
- psEncC->LTPQuantLowComplexity = 0;
- psEncC->NLSF_MSVQ_Survivors = 16;
+ psEncC->NLSF_MSVQ_Survivors = 8;
psEncC->warping_Q16 = psEncC->fs_kHz * SILK_FIX_CONST( WARPING_MULTIPLIER, 16 );
} else {
psEncC->pitchEstimationComplexity = SILK_PE_MAX_COMPLEX;
psEncC->pitchEstimationThreshold_Q16 = SILK_FIX_CONST( 0.7, 16 );
psEncC->pitchEstimationLPCOrder = 16;
- psEncC->shapingLPCOrder = 16;
+ psEncC->shapingLPCOrder = 24;
psEncC->la_shape = 5 * psEncC->fs_kHz;
psEncC->nStatesDelayedDecision = MAX_DEL_DEC_STATES;
psEncC->useInterpolatedNLSFs = 1;
- psEncC->LTPQuantLowComplexity = 0;
- psEncC->NLSF_MSVQ_Survivors = 32;
+ psEncC->NLSF_MSVQ_Survivors = 16;
psEncC->warping_Q16 = psEncC->fs_kHz * SILK_FIX_CONST( WARPING_MULTIPLIER, 16 );
}
@@ -381,46 +390,32 @@ static opus_int silk_setup_complexity(
psEncC->shapeWinLength = SUB_FRAME_LENGTH_MS * psEncC->fs_kHz + 2 * psEncC->la_shape;
psEncC->Complexity = Complexity;
- silk_assert( psEncC->pitchEstimationLPCOrder <= MAX_FIND_PITCH_LPC_ORDER );
- silk_assert( psEncC->shapingLPCOrder <= MAX_SHAPE_LPC_ORDER );
- silk_assert( psEncC->nStatesDelayedDecision <= MAX_DEL_DEC_STATES );
- silk_assert( psEncC->warping_Q16 <= 32767 );
- silk_assert( psEncC->la_shape <= LA_SHAPE_MAX );
- silk_assert( psEncC->shapeWinLength <= SHAPE_LPC_WIN_MAX );
- silk_assert( psEncC->NLSF_MSVQ_Survivors <= NLSF_VQ_MAX_SURVIVORS );
+ celt_assert( psEncC->pitchEstimationLPCOrder <= MAX_FIND_PITCH_LPC_ORDER );
+ celt_assert( psEncC->shapingLPCOrder <= MAX_SHAPE_LPC_ORDER );
+ celt_assert( psEncC->nStatesDelayedDecision <= MAX_DEL_DEC_STATES );
+ celt_assert( psEncC->warping_Q16 <= 32767 );
+ celt_assert( psEncC->la_shape <= LA_SHAPE_MAX );
+ celt_assert( psEncC->shapeWinLength <= SHAPE_LPC_WIN_MAX );
return ret;
}
static OPUS_INLINE opus_int silk_setup_LBRR(
silk_encoder_state *psEncC, /* I/O */
- const opus_int32 TargetRate_bps /* I */
+ const silk_EncControlStruct *encControl /* I */
)
{
opus_int LBRR_in_previous_packet, ret = SILK_NO_ERROR;
- opus_int32 LBRR_rate_thres_bps;
LBRR_in_previous_packet = psEncC->LBRR_enabled;
- psEncC->LBRR_enabled = 0;
- if( psEncC->useInBandFEC && psEncC->PacketLoss_perc > 0 ) {
- if( psEncC->fs_kHz == 8 ) {
- LBRR_rate_thres_bps = LBRR_NB_MIN_RATE_BPS;
- } else if( psEncC->fs_kHz == 12 ) {
- LBRR_rate_thres_bps = LBRR_MB_MIN_RATE_BPS;
+ psEncC->LBRR_enabled = encControl->LBRR_coded;
+ if( psEncC->LBRR_enabled ) {
+ /* Set gain increase for coding LBRR excitation */
+ if( LBRR_in_previous_packet == 0 ) {
+ /* Previous packet did not have LBRR, and was therefore coded at a higher bitrate */
+ psEncC->LBRR_GainIncreases = 7;
} else {
- LBRR_rate_thres_bps = LBRR_WB_MIN_RATE_BPS;
- }
- LBRR_rate_thres_bps = silk_SMULWB( silk_MUL( LBRR_rate_thres_bps, 125 - silk_min( psEncC->PacketLoss_perc, 25 ) ), SILK_FIX_CONST( 0.01, 16 ) );
-
- if( TargetRate_bps > LBRR_rate_thres_bps ) {
- /* Set gain increase for coding LBRR excitation */
- if( LBRR_in_previous_packet == 0 ) {
- /* Previous packet did not have LBRR, and was therefore coded at a higher bitrate */
- psEncC->LBRR_GainIncreases = 7;
- } else {
- psEncC->LBRR_GainIncreases = silk_max_int( 7 - silk_SMULWB( (opus_int32)psEncC->PacketLoss_perc, SILK_FIX_CONST( 0.4, 16 ) ), 2 );
- }
- psEncC->LBRR_enabled = 1;
+ psEncC->LBRR_GainIncreases = silk_max_int( 7 - silk_SMULWB( (opus_int32)psEncC->PacketLoss_perc, SILK_FIX_CONST( 0.4, 16 ) ), 2 );
}
}
diff --git a/libs/libopus/silk/debug.c b/libs/libopus/silk/debug.c
index 9253faf71..eb0c36ef1 100644
--- a/libs/libopus/silk/debug.c
+++ b/libs/libopus/silk/debug.c
@@ -30,18 +30,20 @@ POSSIBILITY OF SUCH DAMAGE.
#endif
#include "debug.h"
+
+#if SILK_DEBUG || SILK_TIC_TOC
#include "SigProc_FIX.h"
+#endif
#if SILK_TIC_TOC
-#ifdef _WIN32
-
#if (defined(_WIN32) || defined(_WINCE))
#include <windows.h> /* timer */
#else /* Linux or Mac*/
#include <sys/time.h>
#endif
+#ifdef _WIN32
unsigned long silk_GetHighResolutionTime(void) /* O time in usec*/
{
/* Returns a time counter in microsec */
@@ -65,7 +67,7 @@ unsigned long GetHighResolutionTime(void) /* O time in usec*/
int silk_Timer_nTimers = 0;
int silk_Timer_depth_ctr = 0;
char silk_Timer_tags[silk_NUM_TIMERS_MAX][silk_NUM_TIMERS_MAX_TAG_LEN];
-#ifdef WIN32
+#ifdef _WIN32
LARGE_INTEGER silk_Timer_start[silk_NUM_TIMERS_MAX];
#else
unsigned long silk_Timer_start[silk_NUM_TIMERS_MAX];
@@ -76,7 +78,7 @@ opus_int64 silk_Timer_sum[silk_NUM_TIMERS_MAX];
opus_int64 silk_Timer_max[silk_NUM_TIMERS_MAX];
opus_int64 silk_Timer_depth[silk_NUM_TIMERS_MAX];
-#ifdef WIN32
+#ifdef _WIN32
void silk_TimerSave(char *file_name)
{
if( silk_Timer_nTimers > 0 )
diff --git a/libs/libopus/silk/debug.h b/libs/libopus/silk/debug.h
index efb6d3e99..36163e478 100644
--- a/libs/libopus/silk/debug.h
+++ b/libs/libopus/silk/debug.h
@@ -28,41 +28,29 @@ POSSIBILITY OF SUCH DAMAGE.
#ifndef SILK_DEBUG_H
#define SILK_DEBUG_H
+/* Set to 1 to enable DEBUG_STORE_DATA() macros for dumping
+ * intermediate signals from the codec.
+ */
+#define SILK_DEBUG 0
+
+/* Flag for using timers */
+#define SILK_TIC_TOC 0
+
+#if SILK_DEBUG || SILK_TIC_TOC
#include "typedef.h"
-#include <stdio.h> /* file writing */
#include <string.h> /* strcpy, strcmp */
+#include <stdio.h> /* file writing */
+#endif
#ifdef __cplusplus
extern "C"
{
#endif
-unsigned long GetHighResolutionTime(void); /* O time in usec*/
-
-/* make SILK_DEBUG dependent on compiler's _DEBUG */
-#if defined _WIN32
- #ifdef _DEBUG
- #define SILK_DEBUG 1
- #else
- #define SILK_DEBUG 0
- #endif
-
- /* overrule the above */
- #if 0
- /* #define NO_ASSERTS*/
- #undef SILK_DEBUG
- #define SILK_DEBUG 1
- #endif
-#else
- #define SILK_DEBUG 0
-#endif
-
-/* Flag for using timers */
-#define SILK_TIC_TOC 0
-
-
#if SILK_TIC_TOC
+unsigned long GetHighResolutionTime(void); /* O time in usec*/
+
#if (defined(_WIN32) || defined(_WINCE))
#include <windows.h> /* timer */
#else /* Linux or Mac*/
diff --git a/libs/libopus/silk/dec_API.c b/libs/libopus/silk/dec_API.c
index b7d8ed48d..7d5ca7fb9 100644
--- a/libs/libopus/silk/dec_API.c
+++ b/libs/libopus/silk/dec_API.c
@@ -104,7 +104,7 @@ opus_int silk_Decode( /* O Returns error co
int delay_stack_alloc;
SAVE_STACK;
- silk_assert( decControl->nChannelsInternal == 1 || decControl->nChannelsInternal == 2 );
+ celt_assert( decControl->nChannelsInternal == 1 || decControl->nChannelsInternal == 2 );
/**********************************/
/* Test if first frame in payload */
@@ -143,13 +143,13 @@ opus_int silk_Decode( /* O Returns error co
channel_state[ n ].nFramesPerPacket = 3;
channel_state[ n ].nb_subfr = 4;
} else {
- silk_assert( 0 );
+ celt_assert( 0 );
RESTORE_STACK;
return SILK_DEC_INVALID_FRAME_SIZE;
}
fs_kHz_dec = ( decControl->internalSampleRate >> 10 ) + 1;
if( fs_kHz_dec != 8 && fs_kHz_dec != 12 && fs_kHz_dec != 16 ) {
- silk_assert( 0 );
+ celt_assert( 0 );
RESTORE_STACK;
return SILK_DEC_INVALID_SAMPLING_FREQUENCY;
}
diff --git a/libs/libopus/silk/decode_core.c b/libs/libopus/silk/decode_core.c
index e569c0e72..1c352a652 100644
--- a/libs/libopus/silk/decode_core.c
+++ b/libs/libopus/silk/decode_core.c
@@ -141,7 +141,7 @@ void silk_decode_core(
if( k == 0 || ( k == 2 && NLSF_interpolation_flag ) ) {
/* Rewhiten with new A coefs */
start_idx = psDec->ltp_mem_length - lag - psDec->LPC_order - LTP_ORDER / 2;
- silk_assert( start_idx > 0 );
+ celt_assert( start_idx > 0 );
if( k == 2 ) {
silk_memcpy( &psDec->outBuf[ psDec->ltp_mem_length ], xq, 2 * psDec->subfr_length * sizeof( opus_int16 ) );
@@ -196,7 +196,7 @@ void silk_decode_core(
for( i = 0; i < psDec->subfr_length; i++ ) {
/* Short-term prediction */
- silk_assert( psDec->LPC_order == 10 || psDec->LPC_order == 16 );
+ celt_assert( psDec->LPC_order == 10 || psDec->LPC_order == 16 );
/* Avoids introducing a bias because silk_SMLAWB() always rounds to -inf */
LPC_pred_Q10 = silk_RSHIFT( psDec->LPC_order, 1 );
LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, sLPC_Q14[ MAX_LPC_ORDER + i - 1 ], A_Q12_tmp[ 0 ] );
@@ -225,8 +225,6 @@ void silk_decode_core(
pxq[ i ] = (opus_int16)silk_SAT16( silk_RSHIFT_ROUND( silk_SMULWW( sLPC_Q14[ MAX_LPC_ORDER + i ], Gain_Q10 ), 8 ) );
}
- /* DEBUG_STORE_DATA( dec.pcm, pxq, psDec->subfr_length * sizeof( opus_int16 ) ) */
-
/* Update LPC filter state */
silk_memcpy( sLPC_Q14, &sLPC_Q14[ psDec->subfr_length ], MAX_LPC_ORDER * sizeof( opus_int32 ) );
pexc_Q14 += psDec->subfr_length;
diff --git a/libs/libopus/silk/decode_frame.c b/libs/libopus/silk/decode_frame.c
index a605d95ac..4f36f854c 100644
--- a/libs/libopus/silk/decode_frame.c
+++ b/libs/libopus/silk/decode_frame.c
@@ -55,7 +55,7 @@ opus_int silk_decode_frame(
psDecCtrl->LTP_scale_Q14 = 0;
/* Safety checks */
- silk_assert( L > 0 && L <= MAX_FRAME_LENGTH );
+ celt_assert( L > 0 && L <= MAX_FRAME_LENGTH );
if( lostFlag == FLAG_DECODE_NORMAL ||
( lostFlag == FLAG_DECODE_LBRR && psDec->LBRR_flags[ psDec->nFramesDecoded ] == 1 ) )
@@ -91,7 +91,7 @@ opus_int silk_decode_frame(
psDec->lossCnt = 0;
psDec->prevSignalType = psDec->indices.signalType;
- silk_assert( psDec->prevSignalType >= 0 && psDec->prevSignalType <= 2 );
+ celt_assert( psDec->prevSignalType >= 0 && psDec->prevSignalType <= 2 );
/* A frame has been decoded without errors */
psDec->first_frame_after_reset = 0;
@@ -103,7 +103,7 @@ opus_int silk_decode_frame(
/*************************/
/* Update output buffer. */
/*************************/
- silk_assert( psDec->ltp_mem_length >= psDec->frame_length );
+ celt_assert( psDec->ltp_mem_length >= psDec->frame_length );
mv_len = psDec->ltp_mem_length - psDec->frame_length;
silk_memmove( psDec->outBuf, &psDec->outBuf[ psDec->frame_length ], mv_len * sizeof(opus_int16) );
silk_memcpy( &psDec->outBuf[ mv_len ], pOut, psDec->frame_length * sizeof( opus_int16 ) );
diff --git a/libs/libopus/silk/decode_indices.c b/libs/libopus/silk/decode_indices.c
index 7afe5c26c..0bb4a997a 100644
--- a/libs/libopus/silk/decode_indices.c
+++ b/libs/libopus/silk/decode_indices.c
@@ -79,7 +79,7 @@ void silk_decode_indices(
/**********************/
psDec->indices.NLSFIndices[ 0 ] = (opus_int8)ec_dec_icdf( psRangeDec, &psDec->psNLSF_CB->CB1_iCDF[ ( psDec->indices.signalType >> 1 ) * psDec->psNLSF_CB->nVectors ], 8 );
silk_NLSF_unpack( ec_ix, pred_Q8, psDec->psNLSF_CB, psDec->indices.NLSFIndices[ 0 ] );
- silk_assert( psDec->psNLSF_CB->order == psDec->LPC_order );
+ celt_assert( psDec->psNLSF_CB->order == psDec->LPC_order );
for( i = 0; i < psDec->psNLSF_CB->order; i++ ) {
Ix = ec_dec_icdf( psRangeDec, &psDec->psNLSF_CB->ec_iCDF[ ec_ix[ i ] ], 8 );
if( Ix == 0 ) {
diff --git a/libs/libopus/silk/decode_parameters.c b/libs/libopus/silk/decode_parameters.c
index e345b1dce..a56a40985 100644
--- a/libs/libopus/silk/decode_parameters.c
+++ b/libs/libopus/silk/decode_parameters.c
@@ -52,7 +52,7 @@ void silk_decode_parameters(
silk_NLSF_decode( pNLSF_Q15, psDec->indices.NLSFIndices, psDec->psNLSF_CB );
/* Convert NLSF parameters to AR prediction filter coefficients */
- silk_NLSF2A( psDecCtrl->PredCoef_Q12[ 1 ], pNLSF_Q15, psDec->LPC_order );
+ silk_NLSF2A( psDecCtrl->PredCoef_Q12[ 1 ], pNLSF_Q15, psDec->LPC_order, psDec->arch );
/* If just reset, e.g., because internal Fs changed, do not allow interpolation */
/* improves the case of packet loss in the first frame after a switch */
@@ -69,7 +69,7 @@ void silk_decode_parameters(
}
/* Convert NLSF parameters to AR prediction filter coefficients */
- silk_NLSF2A( psDecCtrl->PredCoef_Q12[ 0 ], pNLSF0_Q15, psDec->LPC_order );
+ silk_NLSF2A( psDecCtrl->PredCoef_Q12[ 0 ], pNLSF0_Q15, psDec->LPC_order, psDec->arch );
} else {
/* Copy LPC coefficients for first half from second half */
silk_memcpy( psDecCtrl->PredCoef_Q12[ 0 ], psDecCtrl->PredCoef_Q12[ 1 ], psDec->LPC_order * sizeof( opus_int16 ) );
diff --git a/libs/libopus/silk/decode_pitch.c b/libs/libopus/silk/decode_pitch.c
index fedbc6a52..fd1b6bf55 100644
--- a/libs/libopus/silk/decode_pitch.c
+++ b/libs/libopus/silk/decode_pitch.c
@@ -51,7 +51,7 @@ void silk_decode_pitch(
Lag_CB_ptr = &silk_CB_lags_stage2[ 0 ][ 0 ];
cbk_size = PE_NB_CBKS_STAGE2_EXT;
} else {
- silk_assert( nb_subfr == PE_MAX_NB_SUBFR >> 1 );
+ celt_assert( nb_subfr == PE_MAX_NB_SUBFR >> 1 );
Lag_CB_ptr = &silk_CB_lags_stage2_10_ms[ 0 ][ 0 ];
cbk_size = PE_NB_CBKS_STAGE2_10MS;
}
@@ -60,7 +60,7 @@ void silk_decode_pitch(
Lag_CB_ptr = &silk_CB_lags_stage3[ 0 ][ 0 ];
cbk_size = PE_NB_CBKS_STAGE3_MAX;
} else {
- silk_assert( nb_subfr == PE_MAX_NB_SUBFR >> 1 );
+ celt_assert( nb_subfr == PE_MAX_NB_SUBFR >> 1 );
Lag_CB_ptr = &silk_CB_lags_stage3_10_ms[ 0 ][ 0 ];
cbk_size = PE_NB_CBKS_STAGE3_10MS;
}
diff --git a/libs/libopus/silk/decode_pulses.c b/libs/libopus/silk/decode_pulses.c
index d6bbec922..a56d2d307 100644
--- a/libs/libopus/silk/decode_pulses.c
+++ b/libs/libopus/silk/decode_pulses.c
@@ -56,7 +56,7 @@ void silk_decode_pulses(
silk_assert( 1 << LOG2_SHELL_CODEC_FRAME_LENGTH == SHELL_CODEC_FRAME_LENGTH );
iter = silk_RSHIFT( frame_length, LOG2_SHELL_CODEC_FRAME_LENGTH );
if( iter * SHELL_CODEC_FRAME_LENGTH < frame_length ) {
- silk_assert( frame_length == 12 * 10 ); /* Make sure only happens for 10 ms @ 12 kHz */
+ celt_assert( frame_length == 12 * 10 ); /* Make sure only happens for 10 ms @ 12 kHz */
iter++;
}
diff --git a/libs/libopus/silk/decoder_set_fs.c b/libs/libopus/silk/decoder_set_fs.c
index eef0fd25e..d9a13d0f0 100644
--- a/libs/libopus/silk/decoder_set_fs.c
+++ b/libs/libopus/silk/decoder_set_fs.c
@@ -40,8 +40,8 @@ opus_int silk_decoder_set_fs(
{
opus_int frame_length, ret = 0;
- silk_assert( fs_kHz == 8 || fs_kHz == 12 || fs_kHz == 16 );
- silk_assert( psDec->nb_subfr == MAX_NB_SUBFR || psDec->nb_subfr == MAX_NB_SUBFR/2 );
+ celt_assert( fs_kHz == 8 || fs_kHz == 12 || fs_kHz == 16 );
+ celt_assert( psDec->nb_subfr == MAX_NB_SUBFR || psDec->nb_subfr == MAX_NB_SUBFR/2 );
/* New (sub)frame length */
psDec->subfr_length = silk_SMULBB( SUB_FRAME_LENGTH_MS, fs_kHz );
@@ -86,7 +86,7 @@ opus_int silk_decoder_set_fs(
psDec->pitch_lag_low_bits_iCDF = silk_uniform4_iCDF;
} else {
/* unsupported sampling rate */
- silk_assert( 0 );
+ celt_assert( 0 );
}
psDec->first_frame_after_reset = 1;
psDec->lagPrev = 100;
@@ -101,7 +101,7 @@ opus_int silk_decoder_set_fs(
}
/* Check that settings are valid */
- silk_assert( psDec->frame_length > 0 && psDec->frame_length <= MAX_FRAME_LENGTH );
+ celt_assert( psDec->frame_length > 0 && psDec->frame_length <= MAX_FRAME_LENGTH );
return ret;
}
diff --git a/libs/libopus/silk/define.h b/libs/libopus/silk/define.h
index 19c9b00e2..491c86f33 100644
--- a/libs/libopus/silk/define.h
+++ b/libs/libopus/silk/define.h
@@ -46,7 +46,6 @@ extern "C"
/* Limits on bitrate */
#define MIN_TARGET_RATE_BPS 5000
#define MAX_TARGET_RATE_BPS 80000
-#define TARGET_RATE_TAB_SZ 8
/* LBRR thresholds */
#define LBRR_NB_MIN_RATE_BPS 12000
@@ -56,6 +55,12 @@ extern "C"
/* DTX settings */
#define NB_SPEECH_FRAMES_BEFORE_DTX 10 /* eq 200 ms */
#define MAX_CONSECUTIVE_DTX 20 /* eq 400 ms */
+#define DTX_ACTIVITY_THRESHOLD 0.1f
+
+/* VAD decision */
+#define VAD_NO_DECISION -1
+#define VAD_NO_ACTIVITY 0
+#define VAD_ACTIVITY 1
/* Maximum sampling frequency */
#define MAX_FS_KHZ 16
@@ -147,7 +152,7 @@ extern "C"
#define USE_HARM_SHAPING 1
/* Max LPC order of noise shaping filters */
-#define MAX_SHAPE_LPC_ORDER 16
+#define MAX_SHAPE_LPC_ORDER 24
#define HARM_SHAPE_FIR_TAPS 3
@@ -157,8 +162,7 @@ extern "C"
#define LTP_BUF_LENGTH 512
#define LTP_MASK ( LTP_BUF_LENGTH - 1 )
-#define DECISION_DELAY 32
-#define DECISION_DELAY_MASK ( DECISION_DELAY - 1 )
+#define DECISION_DELAY 40
/* Number of subframes for excitation entropy coding */
#define SHELL_CODEC_FRAME_LENGTH 16
@@ -173,11 +177,7 @@ extern "C"
#define MAX_MATRIX_SIZE MAX_LPC_ORDER /* Max of LPC Order and LTP order */
-#if( MAX_LPC_ORDER > DECISION_DELAY )
# define NSQ_LPC_BUF_LENGTH MAX_LPC_ORDER
-#else
-# define NSQ_LPC_BUF_LENGTH DECISION_DELAY
-#endif
/***************************/
/* Voice activity detector */
@@ -205,7 +205,6 @@ extern "C"
/******************/
#define NLSF_W_Q 2
#define NLSF_VQ_MAX_VECTORS 32
-#define NLSF_VQ_MAX_SURVIVORS 32
#define NLSF_QUANT_MAX_AMPLITUDE 4
#define NLSF_QUANT_MAX_AMPLITUDE_EXT 10
#define NLSF_QUANT_LEVEL_ADJ 0.1
@@ -226,6 +225,7 @@ extern "C"
/* Defines for CN generation */
#define CNG_BUF_MASK_MAX 255 /* 2^floor(log2(MAX_FRAME_LENGTH))-1 */
#define CNG_GAIN_SMTH_Q16 4634 /* 0.25^(1/4) */
+#define CNG_GAIN_SMTH_THRESHOLD_Q16 46396 /* -3 dB */
#define CNG_NLSF_SMTH_Q16 16348 /* 0.25 */
#ifdef __cplusplus
diff --git a/libs/libopus/silk/enc_API.c b/libs/libopus/silk/enc_API.c
index f8060286d..55a33f37e 100644
--- a/libs/libopus/silk/enc_API.c
+++ b/libs/libopus/silk/enc_API.c
@@ -82,7 +82,7 @@ opus_int silk_InitEncoder( /* O Returns error co
silk_memset( psEnc, 0, sizeof( silk_encoder ) );
for( n = 0; n < ENCODER_NUM_CHANNELS; n++ ) {
if( ret += silk_init_encoder( &psEnc->state_Fxx[ n ], arch ) ) {
- silk_assert( 0 );
+ celt_assert( 0 );
}
}
@@ -91,7 +91,7 @@ opus_int silk_InitEncoder( /* O Returns error co
/* Read control structure */
if( ret += silk_QueryEncoder( encState, encStatus ) ) {
- silk_assert( 0 );
+ celt_assert( 0 );
}
return ret;
@@ -144,7 +144,8 @@ opus_int silk_Encode( /* O Returns error co
opus_int nSamplesIn, /* I Number of samples in input vector */
ec_enc *psRangeEnc, /* I/O Compressor data structure */
opus_int32 *nBytesOut, /* I/O Number of bytes in payload (input: Max bytes) */
- const opus_int prefillFlag /* I Flag to indicate prefilling buffers no coding */
+ const opus_int prefillFlag, /* I Flag to indicate prefilling buffers no coding */
+ opus_int activity /* I Decision of Opus voice activity detector */
)
{
opus_int n, i, nBits, flags, tmp_payloadSize_ms = 0, tmp_complexity = 0, ret = 0;
@@ -166,7 +167,7 @@ opus_int silk_Encode( /* O Returns error co
/* Check values in encoder control structure */
if( ( ret = check_control_input( encControl ) ) != 0 ) {
- silk_assert( 0 );
+ celt_assert( 0 );
RESTORE_STACK;
return ret;
}
@@ -199,16 +200,26 @@ opus_int silk_Encode( /* O Returns error co
tot_blocks = ( nBlocksOf10ms > 1 ) ? nBlocksOf10ms >> 1 : 1;
curr_block = 0;
if( prefillFlag ) {
+ silk_LP_state save_LP;
/* Only accept input length of 10 ms */
if( nBlocksOf10ms != 1 ) {
- silk_assert( 0 );
+ celt_assert( 0 );
RESTORE_STACK;
return SILK_ENC_INPUT_INVALID_NO_OF_SAMPLES;
}
+ if ( prefillFlag == 2 ) {
+ save_LP = psEnc->state_Fxx[ 0 ].sCmn.sLP;
+ /* Save the sampling rate so the bandwidth switching code can keep handling transitions. */
+ save_LP.saved_fs_kHz = psEnc->state_Fxx[ 0 ].sCmn.fs_kHz;
+ }
/* Reset Encoder */
for( n = 0; n < encControl->nChannelsInternal; n++ ) {
ret = silk_init_encoder( &psEnc->state_Fxx[ n ], psEnc->state_Fxx[ n ].sCmn.arch );
- silk_assert( !ret );
+ /* Restore the variable LP state. */
+ if ( prefillFlag == 2 ) {
+ psEnc->state_Fxx[ n ].sCmn.sLP = save_LP;
+ }
+ celt_assert( !ret );
}
tmp_payloadSize_ms = encControl->payloadSize_ms;
encControl->payloadSize_ms = 10;
@@ -221,23 +232,22 @@ opus_int silk_Encode( /* O Returns error co
} else {
/* Only accept input lengths that are a multiple of 10 ms */
if( nBlocksOf10ms * encControl->API_sampleRate != 100 * nSamplesIn || nSamplesIn < 0 ) {
- silk_assert( 0 );
+ celt_assert( 0 );
RESTORE_STACK;
return SILK_ENC_INPUT_INVALID_NO_OF_SAMPLES;
}
/* Make sure no more than one packet can be produced */
if( 1000 * (opus_int32)nSamplesIn > encControl->payloadSize_ms * encControl->API_sampleRate ) {
- silk_assert( 0 );
+ celt_assert( 0 );
RESTORE_STACK;
return SILK_ENC_INPUT_INVALID_NO_OF_SAMPLES;
}
}
- TargetRate_bps = silk_RSHIFT32( encControl->bitRate, encControl->nChannelsInternal - 1 );
for( n = 0; n < encControl->nChannelsInternal; n++ ) {
/* Force the side channel to the same rate as the mid */
opus_int force_fs_kHz = (n==1) ? psEnc->state_Fxx[0].sCmn.fs_kHz : 0;
- if( ( ret = silk_control_encoder( &psEnc->state_Fxx[ n ], encControl, TargetRate_bps, psEnc->allowBandwidthSwitch, n, force_fs_kHz ) ) != 0 ) {
+ if( ( ret = silk_control_encoder( &psEnc->state_Fxx[ n ], encControl, psEnc->allowBandwidthSwitch, n, force_fs_kHz ) ) != 0 ) {
silk_assert( 0 );
RESTORE_STACK;
return ret;
@@ -249,7 +259,7 @@ opus_int silk_Encode( /* O Returns error co
}
psEnc->state_Fxx[ n ].sCmn.inDTX = psEnc->state_Fxx[ n ].sCmn.useDTX;
}
- silk_assert( encControl->nChannelsInternal == 1 || psEnc->state_Fxx[ 0 ].sCmn.fs_kHz == psEnc->state_Fxx[ 1 ].sCmn.fs_kHz );
+ celt_assert( encControl->nChannelsInternal == 1 || psEnc->state_Fxx[ 0 ].sCmn.fs_kHz == psEnc->state_Fxx[ 1 ].sCmn.fs_kHz );
/* Input buffering/resampling and encoding */
nSamplesToBufferMax =
@@ -307,7 +317,7 @@ opus_int silk_Encode( /* O Returns error co
}
psEnc->state_Fxx[ 0 ].sCmn.inputBufIx += nSamplesToBuffer;
} else {
- silk_assert( encControl->nChannelsAPI == 1 && encControl->nChannelsInternal == 1 );
+ celt_assert( encControl->nChannelsAPI == 1 && encControl->nChannelsInternal == 1 );
silk_memcpy(buf, samplesIn, nSamplesFromInput*sizeof(opus_int16));
ret += silk_resampler( &psEnc->state_Fxx[ 0 ].sCmn.resampler_state,
&psEnc->state_Fxx[ 0 ].sCmn.inputBuf[ psEnc->state_Fxx[ 0 ].sCmn.inputBufIx + 2 ], buf, nSamplesFromInput );
@@ -323,8 +333,8 @@ opus_int silk_Encode( /* O Returns error co
/* Silk encoder */
if( psEnc->state_Fxx[ 0 ].sCmn.inputBufIx >= psEnc->state_Fxx[ 0 ].sCmn.frame_length ) {
/* Enough data in input buffer, so encode */
- silk_assert( psEnc->state_Fxx[ 0 ].sCmn.inputBufIx == psEnc->state_Fxx[ 0 ].sCmn.frame_length );
- silk_assert( encControl->nChannelsInternal == 1 || psEnc->state_Fxx[ 1 ].sCmn.inputBufIx == psEnc->state_Fxx[ 1 ].sCmn.frame_length );
+ celt_assert( psEnc->state_Fxx[ 0 ].sCmn.inputBufIx == psEnc->state_Fxx[ 0 ].sCmn.frame_length );
+ celt_assert( encControl->nChannelsInternal == 1 || psEnc->state_Fxx[ 1 ].sCmn.inputBufIx == psEnc->state_Fxx[ 1 ].sCmn.frame_length );
/* Deal with LBRR data */
if( psEnc->state_Fxx[ 0 ].sCmn.nFramesEncoded == 0 && !prefillFlag ) {
@@ -416,7 +426,6 @@ opus_int silk_Encode( /* O Returns error co
/* Reset side channel encoder memory for first frame with side coding */
if( psEnc->prev_decode_only_middle == 1 ) {
silk_memset( &psEnc->state_Fxx[ 1 ].sShape, 0, sizeof( psEnc->state_Fxx[ 1 ].sShape ) );
- silk_memset( &psEnc->state_Fxx[ 1 ].sPrefilt, 0, sizeof( psEnc->state_Fxx[ 1 ].sPrefilt ) );
silk_memset( &psEnc->state_Fxx[ 1 ].sCmn.sNSQ, 0, sizeof( psEnc->state_Fxx[ 1 ].sCmn.sNSQ ) );
silk_memset( psEnc->state_Fxx[ 1 ].sCmn.prev_NLSFq_Q15, 0, sizeof( psEnc->state_Fxx[ 1 ].sCmn.prev_NLSFq_Q15 ) );
silk_memset( &psEnc->state_Fxx[ 1 ].sCmn.sLP.In_LP_State, 0, sizeof( psEnc->state_Fxx[ 1 ].sCmn.sLP.In_LP_State ) );
@@ -427,7 +436,7 @@ opus_int silk_Encode( /* O Returns error co
psEnc->state_Fxx[ 1 ].sCmn.sNSQ.prev_gain_Q16 = 65536;
psEnc->state_Fxx[ 1 ].sCmn.first_frame_after_reset = 1;
}
- silk_encode_do_VAD_Fxx( &psEnc->state_Fxx[ 1 ] );
+ silk_encode_do_VAD_Fxx( &psEnc->state_Fxx[ 1 ], activity );
} else {
psEnc->state_Fxx[ 1 ].sCmn.VAD_flags[ psEnc->state_Fxx[ 0 ].sCmn.nFramesEncoded ] = 0;
}
@@ -442,7 +451,7 @@ opus_int silk_Encode( /* O Returns error co
silk_memcpy( psEnc->state_Fxx[ 0 ].sCmn.inputBuf, psEnc->sStereo.sMid, 2 * sizeof( opus_int16 ) );
silk_memcpy( psEnc->sStereo.sMid, &psEnc->state_Fxx[ 0 ].sCmn.inputBuf[ psEnc->state_Fxx[ 0 ].sCmn.frame_length ], 2 * sizeof( opus_int16 ) );
}
- silk_encode_do_VAD_Fxx( &psEnc->state_Fxx[ 0 ] );
+ silk_encode_do_VAD_Fxx( &psEnc->state_Fxx[ 0 ], activity );
/* Encode */
for( n = 0; n < encControl->nChannelsInternal; n++ ) {
@@ -557,6 +566,10 @@ opus_int silk_Encode( /* O Returns error co
}
}
+ encControl->signalType = psEnc->state_Fxx[0].sCmn.indices.signalType;
+ encControl->offset = silk_Quantization_Offsets_Q10
+ [ psEnc->state_Fxx[0].sCmn.indices.signalType >> 1 ]
+ [ psEnc->state_Fxx[0].sCmn.indices.quantOffsetType ];
RESTORE_STACK;
return ret;
}
diff --git a/libs/libopus/silk/encode_indices.c b/libs/libopus/silk/encode_indices.c
index 666c8c0b1..4bcbc3347 100644
--- a/libs/libopus/silk/encode_indices.c
+++ b/libs/libopus/silk/encode_indices.c
@@ -56,8 +56,8 @@ void silk_encode_indices(
/* Encode signal type and quantizer offset */
/*******************************************/
typeOffset = 2 * psIndices->signalType + psIndices->quantOffsetType;
- silk_assert( typeOffset >= 0 && typeOffset < 6 );
- silk_assert( encode_LBRR == 0 || typeOffset >= 2 );
+ celt_assert( typeOffset >= 0 && typeOffset < 6 );
+ celt_assert( encode_LBRR == 0 || typeOffset >= 2 );
if( encode_LBRR || typeOffset >= 2 ) {
ec_enc_icdf( psRangeEnc, typeOffset - 2, silk_type_offset_VAD_iCDF, 8 );
} else {
@@ -90,7 +90,7 @@ void silk_encode_indices(
/****************/
ec_enc_icdf( psRangeEnc, psIndices->NLSFIndices[ 0 ], &psEncC->psNLSF_CB->CB1_iCDF[ ( psIndices->signalType >> 1 ) * psEncC->psNLSF_CB->nVectors ], 8 );
silk_NLSF_unpack( ec_ix, pred_Q8, psEncC->psNLSF_CB, psIndices->NLSFIndices[ 0 ] );
- silk_assert( psEncC->psNLSF_CB->order == psEncC->predictLPCOrder );
+ celt_assert( psEncC->psNLSF_CB->order == psEncC->predictLPCOrder );
for( i = 0; i < psEncC->psNLSF_CB->order; i++ ) {
if( psIndices->NLSFIndices[ i+1 ] >= NLSF_QUANT_MAX_AMPLITUDE ) {
ec_enc_icdf( psRangeEnc, 2 * NLSF_QUANT_MAX_AMPLITUDE, &psEncC->psNLSF_CB->ec_iCDF[ ec_ix[ i ] ], 8 );
diff --git a/libs/libopus/silk/encode_pulses.c b/libs/libopus/silk/encode_pulses.c
index ab00264f9..8a1999138 100644
--- a/libs/libopus/silk/encode_pulses.c
+++ b/libs/libopus/silk/encode_pulses.c
@@ -86,7 +86,7 @@ void silk_encode_pulses(
silk_assert( 1 << LOG2_SHELL_CODEC_FRAME_LENGTH == SHELL_CODEC_FRAME_LENGTH );
iter = silk_RSHIFT( frame_length, LOG2_SHELL_CODEC_FRAME_LENGTH );
if( iter * SHELL_CODEC_FRAME_LENGTH < frame_length ) {
- silk_assert( frame_length == 12 * 10 ); /* Make sure only happens for 10 ms @ 12 kHz */
+ celt_assert( frame_length == 12 * 10 ); /* Make sure only happens for 10 ms @ 12 kHz */
iter++;
silk_memset( &pulses[ frame_length ], 0, SHELL_CODEC_FRAME_LENGTH * sizeof(opus_int8));
}
diff --git a/libs/libopus/silk/fixed/apply_sine_window_FIX.c b/libs/libopus/silk/fixed/apply_sine_window_FIX.c
index 4502b7130..03e088a6d 100644
--- a/libs/libopus/silk/fixed/apply_sine_window_FIX.c
+++ b/libs/libopus/silk/fixed/apply_sine_window_FIX.c
@@ -57,15 +57,15 @@ void silk_apply_sine_window(
opus_int k, f_Q16, c_Q16;
opus_int32 S0_Q16, S1_Q16;
- silk_assert( win_type == 1 || win_type == 2 );
+ celt_assert( win_type == 1 || win_type == 2 );
/* Length must be in a range from 16 to 120 and a multiple of 4 */
- silk_assert( length >= 16 && length <= 120 );
- silk_assert( ( length & 3 ) == 0 );
+ celt_assert( length >= 16 && length <= 120 );
+ celt_assert( ( length & 3 ) == 0 );
/* Frequency */
k = ( length >> 2 ) - 4;
- silk_assert( k >= 0 && k <= 26 );
+ celt_assert( k >= 0 && k <= 26 );
f_Q16 = (opus_int)freq_table_Q16[ k ];
/* Factor used for cosine approximation */
diff --git a/libs/libopus/silk/fixed/arm/warped_autocorrelation_FIX_arm.h b/libs/libopus/silk/fixed/arm/warped_autocorrelation_FIX_arm.h
new file mode 100644
index 000000000..1992e4328
--- /dev/null
+++ b/libs/libopus/silk/fixed/arm/warped_autocorrelation_FIX_arm.h
@@ -0,0 +1,68 @@
+/***********************************************************************
+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.
+***********************************************************************/
+
+#ifndef SILK_WARPED_AUTOCORRELATION_FIX_ARM_H
+# define SILK_WARPED_AUTOCORRELATION_FIX_ARM_H
+
+# include "celt/arm/armcpu.h"
+
+# if defined(FIXED_POINT)
+
+# if defined(OPUS_ARM_MAY_HAVE_NEON_INTR)
+void silk_warped_autocorrelation_FIX_neon(
+ opus_int32 *corr, /* O Result [order + 1] */
+ opus_int *scale, /* O Scaling of the correlation vector */
+ const opus_int16 *input, /* I Input data to correlate */
+ const opus_int warping_Q16, /* I Warping coefficient */
+ const opus_int length, /* I Length of input */
+ const opus_int order /* I Correlation order (even) */
+);
+
+# if !defined(OPUS_HAVE_RTCD) && defined(OPUS_ARM_PRESUME_NEON)
+# define OVERRIDE_silk_warped_autocorrelation_FIX (1)
+# define silk_warped_autocorrelation_FIX(corr, scale, input, warping_Q16, length, order, arch) \
+ ((void)(arch), PRESUME_NEON(silk_warped_autocorrelation_FIX)(corr, scale, input, warping_Q16, length, order))
+# endif
+# endif
+
+# if !defined(OVERRIDE_silk_warped_autocorrelation_FIX)
+/*Is run-time CPU detection enabled on this platform?*/
+# if defined(OPUS_HAVE_RTCD) && (defined(OPUS_ARM_MAY_HAVE_NEON_INTR) && !defined(OPUS_ARM_PRESUME_NEON_INTR))
+extern void (*const SILK_WARPED_AUTOCORRELATION_FIX_IMPL[OPUS_ARCHMASK+1])(opus_int32*, opus_int*, const opus_int16*, const opus_int, const opus_int, const opus_int);
+# define OVERRIDE_silk_warped_autocorrelation_FIX (1)
+# define silk_warped_autocorrelation_FIX(corr, scale, input, warping_Q16, length, order, arch) \
+ ((*SILK_WARPED_AUTOCORRELATION_FIX_IMPL[(arch)&OPUS_ARCHMASK])(corr, scale, input, warping_Q16, length, order))
+# elif defined(OPUS_ARM_PRESUME_NEON_INTR)
+# define OVERRIDE_silk_warped_autocorrelation_FIX (1)
+# define silk_warped_autocorrelation_FIX(corr, scale, input, warping_Q16, length, order, arch) \
+ ((void)(arch), silk_warped_autocorrelation_FIX_neon(corr, scale, input, warping_Q16, length, order))
+# endif
+# endif
+
+# endif /* end FIXED_POINT */
+
+#endif /* end SILK_WARPED_AUTOCORRELATION_FIX_ARM_H */
diff --git a/libs/libopus/silk/fixed/arm/warped_autocorrelation_FIX_neon_intr.c b/libs/libopus/silk/fixed/arm/warped_autocorrelation_FIX_neon_intr.c
new file mode 100644
index 000000000..6f3be025c
--- /dev/null
+++ b/libs/libopus/silk/fixed/arm/warped_autocorrelation_FIX_neon_intr.c
@@ -0,0 +1,265 @@
+/***********************************************************************
+Copyright (c) 2017 Google Inc., 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.
+- 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 <arm_neon.h>
+#ifdef OPUS_CHECK_ASM
+# include <string.h>
+#endif
+#include "stack_alloc.h"
+#include "main_FIX.h"
+
+static OPUS_INLINE void calc_corr( const opus_int32 *const input_QS, opus_int64 *const corr_QC, const opus_int offset, const int32x4_t state_QS_s32x4 )
+{
+ int64x2_t corr_QC_s64x2[ 2 ], t_s64x2[ 2 ];
+ const int32x4_t input_QS_s32x4 = vld1q_s32( input_QS + offset );
+ corr_QC_s64x2[ 0 ] = vld1q_s64( corr_QC + offset + 0 );
+ corr_QC_s64x2[ 1 ] = vld1q_s64( corr_QC + offset + 2 );
+ t_s64x2[ 0 ] = vmull_s32( vget_low_s32( state_QS_s32x4 ), vget_low_s32( input_QS_s32x4 ) );
+ t_s64x2[ 1 ] = vmull_s32( vget_high_s32( state_QS_s32x4 ), vget_high_s32( input_QS_s32x4 ) );
+ corr_QC_s64x2[ 0 ] = vsraq_n_s64( corr_QC_s64x2[ 0 ], t_s64x2[ 0 ], 2 * QS - QC );
+ corr_QC_s64x2[ 1 ] = vsraq_n_s64( corr_QC_s64x2[ 1 ], t_s64x2[ 1 ], 2 * QS - QC );
+ vst1q_s64( corr_QC + offset + 0, corr_QC_s64x2[ 0 ] );
+ vst1q_s64( corr_QC + offset + 2, corr_QC_s64x2[ 1 ] );
+}
+
+static OPUS_INLINE int32x4_t calc_state( const int32x4_t state_QS0_s32x4, const int32x4_t state_QS0_1_s32x4, const int32x4_t state_QS1_1_s32x4, const int32x4_t warping_Q16_s32x4 )
+{
+ int32x4_t t_s32x4 = vsubq_s32( state_QS0_s32x4, state_QS0_1_s32x4 );
+ t_s32x4 = vqdmulhq_s32( t_s32x4, warping_Q16_s32x4 );
+ return vaddq_s32( state_QS1_1_s32x4, t_s32x4 );
+}
+
+void silk_warped_autocorrelation_FIX_neon(
+ opus_int32 *corr, /* O Result [order + 1] */
+ opus_int *scale, /* O Scaling of the correlation vector */
+ const opus_int16 *input, /* I Input data to correlate */
+ const opus_int warping_Q16, /* I Warping coefficient */
+ const opus_int length, /* I Length of input */
+ const opus_int order /* I Correlation order (even) */
+)
+{
+ if( ( MAX_SHAPE_LPC_ORDER > 24 ) || ( order < 6 ) ) {
+ silk_warped_autocorrelation_FIX_c( corr, scale, input, warping_Q16, length, order );
+ } else {
+ opus_int n, i, lsh;
+ opus_int64 corr_QC[ MAX_SHAPE_LPC_ORDER + 1 ] = { 0 }; /* In reverse order */
+ opus_int64 corr_QC_orderT;
+ int64x2_t lsh_s64x2;
+ const opus_int orderT = ( order + 3 ) & ~3;
+ opus_int64 *corr_QCT;
+ opus_int32 *input_QS;
+ VARDECL( opus_int32, input_QST );
+ VARDECL( opus_int32, state );
+ SAVE_STACK;
+
+ /* Order must be even */
+ silk_assert( ( order & 1 ) == 0 );
+ silk_assert( 2 * QS - QC >= 0 );
+
+ /* The additional +4 is to ensure a later vld1q_s32 call does not overflow. */
+ /* Strictly, only +3 is needed but +4 simplifies initialization using the 4x32 neon load. */
+ ALLOC( input_QST, length + 2 * MAX_SHAPE_LPC_ORDER + 4, opus_int32 );
+
+ input_QS = input_QST;
+ /* input_QS has zero paddings in the beginning and end. */
+ vst1q_s32( input_QS, vdupq_n_s32( 0 ) );
+ input_QS += 4;
+ vst1q_s32( input_QS, vdupq_n_s32( 0 ) );
+ input_QS += 4;
+ vst1q_s32( input_QS, vdupq_n_s32( 0 ) );
+ input_QS += 4;
+ vst1q_s32( input_QS, vdupq_n_s32( 0 ) );
+ input_QS += 4;
+ vst1q_s32( input_QS, vdupq_n_s32( 0 ) );
+ input_QS += 4;
+ vst1q_s32( input_QS, vdupq_n_s32( 0 ) );
+ input_QS += 4;
+
+ /* Loop over samples */
+ for( n = 0; n < length - 7; n += 8, input_QS += 8 ) {
+ const int16x8_t t0_s16x4 = vld1q_s16( input + n );
+ vst1q_s32( input_QS + 0, vshll_n_s16( vget_low_s16( t0_s16x4 ), QS ) );
+ vst1q_s32( input_QS + 4, vshll_n_s16( vget_high_s16( t0_s16x4 ), QS ) );
+ }
+ for( ; n < length; n++, input_QS++ ) {
+ input_QS[ 0 ] = silk_LSHIFT32( (opus_int32)input[ n ], QS );
+ }
+ vst1q_s32( input_QS, vdupq_n_s32( 0 ) );
+ input_QS += 4;
+ vst1q_s32( input_QS, vdupq_n_s32( 0 ) );
+ input_QS += 4;
+ vst1q_s32( input_QS, vdupq_n_s32( 0 ) );
+ input_QS += 4;
+ vst1q_s32( input_QS, vdupq_n_s32( 0 ) );
+ input_QS += 4;
+ vst1q_s32( input_QS, vdupq_n_s32( 0 ) );
+ input_QS += 4;
+ vst1q_s32( input_QS, vdupq_n_s32( 0 ) );
+ input_QS += 4;
+ vst1q_s32( input_QS, vdupq_n_s32( 0 ) );
+ input_QS = input_QST + MAX_SHAPE_LPC_ORDER - orderT;
+
+ /* The following loop runs ( length + order ) times, with ( order ) extra epilogues. */
+ /* The zero paddings in input_QS guarantee corr_QC's correctness even with the extra epilogues. */
+ /* The values of state_QS will be polluted by the extra epilogues, however they are temporary values. */
+
+ /* Keep the C code here to help understand the intrinsics optimization. */
+ /*
+ {
+ opus_int32 state_QS[ 2 ][ MAX_SHAPE_LPC_ORDER + 1 ] = { 0 };
+ opus_int32 *state_QST[ 3 ];
+ state_QST[ 0 ] = state_QS[ 0 ];
+ state_QST[ 1 ] = state_QS[ 1 ];
+ for( n = 0; n < length + order; n++, input_QS++ ) {
+ state_QST[ 0 ][ orderT ] = input_QS[ orderT ];
+ for( i = 0; i < orderT; i++ ) {
+ corr_QC[ i ] += silk_RSHIFT64( silk_SMULL( state_QST[ 0 ][ i ], input_QS[ i ] ), 2 * QS - QC );
+ state_QST[ 1 ][ i ] = silk_SMLAWB( state_QST[ 1 ][ i + 1 ], state_QST[ 0 ][ i ] - state_QST[ 0 ][ i + 1 ], warping_Q16 );
+ }
+ state_QST[ 2 ] = state_QST[ 0 ];
+ state_QST[ 0 ] = state_QST[ 1 ];
+ state_QST[ 1 ] = state_QST[ 2 ];
+ }
+ }
+ */
+
+ {
+ const int32x4_t warping_Q16_s32x4 = vdupq_n_s32( warping_Q16 << 15 );
+ const opus_int32 *in = input_QS + orderT;
+ opus_int o = orderT;
+ int32x4_t state_QS_s32x4[ 3 ][ 2 ];
+
+ /* The additional +4 is to ensure a later vld1q_s32 call does not overflow. */
+ ALLOC( state, length + order + 4, opus_int32 );
+ state_QS_s32x4[ 2 ][ 1 ] = vdupq_n_s32( 0 );
+
+ /* Calculate 8 taps of all inputs in each loop. */
+ do {
+ state_QS_s32x4[ 0 ][ 0 ] = state_QS_s32x4[ 0 ][ 1 ] =
+ state_QS_s32x4[ 1 ][ 0 ] = state_QS_s32x4[ 1 ][ 1 ] = vdupq_n_s32( 0 );
+ n = 0;
+ do {
+ calc_corr( input_QS + n, corr_QC, o - 8, state_QS_s32x4[ 0 ][ 0 ] );
+ calc_corr( input_QS + n, corr_QC, o - 4, state_QS_s32x4[ 0 ][ 1 ] );
+ state_QS_s32x4[ 2 ][ 1 ] = vld1q_s32( in + n );
+ vst1q_lane_s32( state + n, state_QS_s32x4[ 0 ][ 0 ], 0 );
+ state_QS_s32x4[ 2 ][ 0 ] = vextq_s32( state_QS_s32x4[ 0 ][ 0 ], state_QS_s32x4[ 0 ][ 1 ], 1 );
+ state_QS_s32x4[ 2 ][ 1 ] = vextq_s32( state_QS_s32x4[ 0 ][ 1 ], state_QS_s32x4[ 2 ][ 1 ], 1 );
+ state_QS_s32x4[ 0 ][ 0 ] = calc_state( state_QS_s32x4[ 0 ][ 0 ], state_QS_s32x4[ 2 ][ 0 ], state_QS_s32x4[ 1 ][ 0 ], warping_Q16_s32x4 );
+ state_QS_s32x4[ 0 ][ 1 ] = calc_state( state_QS_s32x4[ 0 ][ 1 ], state_QS_s32x4[ 2 ][ 1 ], state_QS_s32x4[ 1 ][ 1 ], warping_Q16_s32x4 );
+ state_QS_s32x4[ 1 ][ 0 ] = state_QS_s32x4[ 2 ][ 0 ];
+ state_QS_s32x4[ 1 ][ 1 ] = state_QS_s32x4[ 2 ][ 1 ];
+ } while( ++n < ( length + order ) );
+ in = state;
+ o -= 8;
+ } while( o > 4 );
+
+ if( o ) {
+ /* Calculate the last 4 taps of all inputs. */
+ opus_int32 *stateT = state;
+ silk_assert( o == 4 );
+ state_QS_s32x4[ 0 ][ 0 ] = state_QS_s32x4[ 1 ][ 0 ] = vdupq_n_s32( 0 );
+ n = length + order;
+ do {
+ calc_corr( input_QS, corr_QC, 0, state_QS_s32x4[ 0 ][ 0 ] );
+ state_QS_s32x4[ 2 ][ 0 ] = vld1q_s32( stateT );
+ vst1q_lane_s32( stateT, state_QS_s32x4[ 0 ][ 0 ], 0 );
+ state_QS_s32x4[ 2 ][ 0 ] = vextq_s32( state_QS_s32x4[ 0 ][ 0 ], state_QS_s32x4[ 2 ][ 0 ], 1 );
+ state_QS_s32x4[ 0 ][ 0 ] = calc_state( state_QS_s32x4[ 0 ][ 0 ], state_QS_s32x4[ 2 ][ 0 ], state_QS_s32x4[ 1 ][ 0 ], warping_Q16_s32x4 );
+ state_QS_s32x4[ 1 ][ 0 ] = state_QS_s32x4[ 2 ][ 0 ];
+ input_QS++;
+ stateT++;
+ } while( --n );
+ }
+ }
+
+ {
+ const opus_int16 *inputT = input;
+ int32x4_t t_s32x4;
+ int64x1_t t_s64x1;
+ int64x2_t t_s64x2 = vdupq_n_s64( 0 );
+ for( n = 0; n <= length - 8; n += 8 ) {
+ int16x8_t input_s16x8 = vld1q_s16( inputT );
+ t_s32x4 = vmull_s16( vget_low_s16( input_s16x8 ), vget_low_s16( input_s16x8 ) );
+ t_s32x4 = vmlal_s16( t_s32x4, vget_high_s16( input_s16x8 ), vget_high_s16( input_s16x8 ) );
+ t_s64x2 = vaddw_s32( t_s64x2, vget_low_s32( t_s32x4 ) );
+ t_s64x2 = vaddw_s32( t_s64x2, vget_high_s32( t_s32x4 ) );
+ inputT += 8;
+ }
+ t_s64x1 = vadd_s64( vget_low_s64( t_s64x2 ), vget_high_s64( t_s64x2 ) );
+ corr_QC_orderT = vget_lane_s64( t_s64x1, 0 );
+ for( ; n < length; n++ ) {
+ corr_QC_orderT += silk_SMULL( input[ n ], input[ n ] );
+ }
+ corr_QC_orderT = silk_LSHIFT64( corr_QC_orderT, QC );
+ corr_QC[ orderT ] = corr_QC_orderT;
+ }
+
+ corr_QCT = corr_QC + orderT - order;
+ lsh = silk_CLZ64( corr_QC_orderT ) - 35;
+ lsh = silk_LIMIT( lsh, -12 - QC, 30 - QC );
+ *scale = -( QC + lsh );
+ silk_assert( *scale >= -30 && *scale <= 12 );
+ lsh_s64x2 = vdupq_n_s64( lsh );
+ for( i = 0; i <= order - 3; i += 4 ) {
+ int32x4_t corr_s32x4;
+ int64x2_t corr_QC0_s64x2, corr_QC1_s64x2;
+ corr_QC0_s64x2 = vld1q_s64( corr_QCT + i );
+ corr_QC1_s64x2 = vld1q_s64( corr_QCT + i + 2 );
+ corr_QC0_s64x2 = vshlq_s64( corr_QC0_s64x2, lsh_s64x2 );
+ corr_QC1_s64x2 = vshlq_s64( corr_QC1_s64x2, lsh_s64x2 );
+ corr_s32x4 = vcombine_s32( vmovn_s64( corr_QC1_s64x2 ), vmovn_s64( corr_QC0_s64x2 ) );
+ corr_s32x4 = vrev64q_s32( corr_s32x4 );
+ vst1q_s32( corr + order - i - 3, corr_s32x4 );
+ }
+ if( lsh >= 0 ) {
+ for( ; i < order + 1; i++ ) {
+ corr[ order - i ] = (opus_int32)silk_CHECK_FIT32( silk_LSHIFT64( corr_QCT[ i ], lsh ) );
+ }
+ } else {
+ for( ; i < order + 1; i++ ) {
+ corr[ order - i ] = (opus_int32)silk_CHECK_FIT32( silk_RSHIFT64( corr_QCT[ i ], -lsh ) );
+ }
+ }
+ silk_assert( corr_QCT[ order ] >= 0 ); /* If breaking, decrease QC*/
+ RESTORE_STACK;
+ }
+
+#ifdef OPUS_CHECK_ASM
+ {
+ opus_int32 corr_c[ MAX_SHAPE_LPC_ORDER + 1 ];
+ opus_int scale_c;
+ silk_warped_autocorrelation_FIX_c( corr_c, &scale_c, input, warping_Q16, length, order );
+ silk_assert( !memcmp( corr_c, corr, sizeof( corr_c[ 0 ] ) * ( order + 1 ) ) );
+ silk_assert( scale_c == *scale );
+ }
+#endif
+}
diff --git a/libs/libopus/silk/fixed/burg_modified_FIX.c b/libs/libopus/silk/fixed/burg_modified_FIX.c
index 17d0e0993..185a12b17 100644
--- a/libs/libopus/silk/fixed/burg_modified_FIX.c
+++ b/libs/libopus/silk/fixed/burg_modified_FIX.c
@@ -37,7 +37,7 @@ POSSIBILITY OF SUCH DAMAGE.
#define MAX_FRAME_SIZE 384 /* subfr_length * nb_subfr = ( 0.005 * 16000 + 16 ) * 4 = 384 */
#define QA 25
-#define N_BITS_HEAD_ROOM 2
+#define N_BITS_HEAD_ROOM 3
#define MIN_RSHIFTS -16
#define MAX_RSHIFTS (32 - QA)
@@ -65,10 +65,10 @@ void silk_burg_modified_c(
opus_int32 xcorr[ SILK_MAX_ORDER_LPC ];
opus_int64 C0_64;
- silk_assert( subfr_length * nb_subfr <= MAX_FRAME_SIZE );
+ celt_assert( subfr_length * nb_subfr <= MAX_FRAME_SIZE );
/* Compute autocorrelations, added over subframes */
- C0_64 = silk_inner_prod16_aligned_64( x, x, subfr_length*nb_subfr, arch );
+ C0_64 = silk_inner_prod16( x, x, subfr_length*nb_subfr, arch );
lz = silk_CLZ64(C0_64);
rshifts = 32 + 1 + N_BITS_HEAD_ROOM - lz;
if (rshifts > MAX_RSHIFTS) rshifts = MAX_RSHIFTS;
@@ -87,7 +87,7 @@ void silk_burg_modified_c(
x_ptr = x + s * subfr_length;
for( n = 1; n < D + 1; n++ ) {
C_first_row[ n - 1 ] += (opus_int32)silk_RSHIFT64(
- silk_inner_prod16_aligned_64( x_ptr, x_ptr + n, subfr_length - n, arch ), rshifts );
+ silk_inner_prod16( x_ptr, x_ptr + n, subfr_length - n, arch ), rshifts );
}
}
} else {
@@ -150,7 +150,7 @@ void silk_burg_modified_c(
C_first_row[ k ] = silk_MLA( C_first_row[ k ], x1, x_ptr[ n - k - 1 ] ); /* Q( -rshifts ) */
C_last_row[ k ] = silk_MLA( C_last_row[ k ], x2, x_ptr[ subfr_length - n + k ] ); /* Q( -rshifts ) */
Atmp1 = silk_RSHIFT_ROUND( Af_QA[ k ], QA - 17 ); /* Q17 */
- /* We sometimes have get overflows in the multiplications (even beyond +/- 2^32),
+ /* We sometimes get overflows in the multiplications (even beyond +/- 2^32),
but they cancel each other and the real result seems to always fit in a 32-bit
signed integer. This was determined experimentally, not theoretically (unfortunately). */
tmp1 = silk_MLA_ovflw( tmp1, x_ptr[ n - k - 1 ], Atmp1 ); /* Q17 */
@@ -253,7 +253,7 @@ void silk_burg_modified_c(
if( rshifts > 0 ) {
for( s = 0; s < nb_subfr; s++ ) {
x_ptr = x + s * subfr_length;
- C0 -= (opus_int32)silk_RSHIFT64( silk_inner_prod16_aligned_64( x_ptr, x_ptr, D, arch ), rshifts );
+ C0 -= (opus_int32)silk_RSHIFT64( silk_inner_prod16( x_ptr, x_ptr, D, arch ), rshifts );
}
} else {
for( s = 0; s < nb_subfr; s++ ) {
diff --git a/libs/libopus/silk/fixed/corrMatrix_FIX.c b/libs/libopus/silk/fixed/corrMatrix_FIX.c
index c1d437c78..1b4a29c23 100644
--- a/libs/libopus/silk/fixed/corrMatrix_FIX.c
+++ b/libs/libopus/silk/fixed/corrMatrix_FIX.c
@@ -58,7 +58,7 @@ void silk_corrVector_FIX(
for( lag = 0; lag < order; lag++ ) {
inner_prod = 0;
for( i = 0; i < L; i++ ) {
- inner_prod += silk_RSHIFT32( silk_SMULBB( ptr1[ i ], ptr2[i] ), rshifts );
+ inner_prod = silk_ADD_RSHIFT32( inner_prod, silk_SMULBB( ptr1[ i ], ptr2[i] ), rshifts );
}
Xt[ lag ] = inner_prod; /* X[:,lag]'*t */
ptr1--; /* Go to next column of X */
@@ -77,61 +77,54 @@ void silk_corrMatrix_FIX(
const opus_int16 *x, /* I x vector [L + order - 1] used to form data matrix X */
const opus_int L, /* I Length of vectors */
const opus_int order, /* I Max lag for correlation */
- const opus_int head_room, /* I Desired headroom */
opus_int32 *XX, /* O Pointer to X'*X correlation matrix [ order x order ] */
- opus_int *rshifts, /* I/O Right shifts of correlations */
+ opus_int32 *nrg, /* O Energy of x vector */
+ opus_int *rshifts, /* O Right shifts of correlations and energy */
int arch /* I Run-time architecture */
)
{
- opus_int i, j, lag, rshifts_local, head_room_rshifts;
+ opus_int i, j, lag;
opus_int32 energy;
const opus_int16 *ptr1, *ptr2;
/* Calculate energy to find shift used to fit in 32 bits */
- silk_sum_sqr_shift( &energy, &rshifts_local, x, L + order - 1 );
- /* Add shifts to get the desired head room */
- head_room_rshifts = silk_max( head_room - silk_CLZ32( energy ), 0 );
-
- energy = silk_RSHIFT32( energy, head_room_rshifts );
- rshifts_local += head_room_rshifts;
+ silk_sum_sqr_shift( nrg, rshifts, x, L + order - 1 );
+ energy = *nrg;
/* Calculate energy of first column (0) of X: X[:,0]'*X[:,0] */
/* Remove contribution of first order - 1 samples */
for( i = 0; i < order - 1; i++ ) {
- energy -= silk_RSHIFT32( silk_SMULBB( x[ i ], x[ i ] ), rshifts_local );
- }
- if( rshifts_local < *rshifts ) {
- /* Adjust energy */
- energy = silk_RSHIFT32( energy, *rshifts - rshifts_local );
- rshifts_local = *rshifts;
+ energy -= silk_RSHIFT32( silk_SMULBB( x[ i ], x[ i ] ), *rshifts );
}
/* Calculate energy of remaining columns of X: X[:,j]'*X[:,j] */
/* Fill out the diagonal of the correlation matrix */
matrix_ptr( XX, 0, 0, order ) = energy;
+ silk_assert( energy >= 0 );
ptr1 = &x[ order - 1 ]; /* First sample of column 0 of X */
for( j = 1; j < order; j++ ) {
- energy = silk_SUB32( energy, silk_RSHIFT32( silk_SMULBB( ptr1[ L - j ], ptr1[ L - j ] ), rshifts_local ) );
- energy = silk_ADD32( energy, silk_RSHIFT32( silk_SMULBB( ptr1[ -j ], ptr1[ -j ] ), rshifts_local ) );
+ energy = silk_SUB32( energy, silk_RSHIFT32( silk_SMULBB( ptr1[ L - j ], ptr1[ L - j ] ), *rshifts ) );
+ energy = silk_ADD32( energy, silk_RSHIFT32( silk_SMULBB( ptr1[ -j ], ptr1[ -j ] ), *rshifts ) );
matrix_ptr( XX, j, j, order ) = energy;
+ silk_assert( energy >= 0 );
}
ptr2 = &x[ order - 2 ]; /* First sample of column 1 of X */
/* Calculate the remaining elements of the correlation matrix */
- if( rshifts_local > 0 ) {
+ if( *rshifts > 0 ) {
/* Right shifting used */
for( lag = 1; lag < order; lag++ ) {
/* Inner product of column 0 and column lag: X[:,0]'*X[:,lag] */
energy = 0;
for( i = 0; i < L; i++ ) {
- energy += silk_RSHIFT32( silk_SMULBB( ptr1[ i ], ptr2[i] ), rshifts_local );
+ energy += silk_RSHIFT32( silk_SMULBB( ptr1[ i ], ptr2[i] ), *rshifts );
}
/* Calculate remaining off diagonal: X[:,j]'*X[:,j + lag] */
matrix_ptr( XX, lag, 0, order ) = energy;
matrix_ptr( XX, 0, lag, order ) = energy;
for( j = 1; j < ( order - lag ); j++ ) {
- energy = silk_SUB32( energy, silk_RSHIFT32( silk_SMULBB( ptr1[ L - j ], ptr2[ L - j ] ), rshifts_local ) );
- energy = silk_ADD32( energy, silk_RSHIFT32( silk_SMULBB( ptr1[ -j ], ptr2[ -j ] ), rshifts_local ) );
+ energy = silk_SUB32( energy, silk_RSHIFT32( silk_SMULBB( ptr1[ L - j ], ptr2[ L - j ] ), *rshifts ) );
+ energy = silk_ADD32( energy, silk_RSHIFT32( silk_SMULBB( ptr1[ -j ], ptr2[ -j ] ), *rshifts ) );
matrix_ptr( XX, lag + j, j, order ) = energy;
matrix_ptr( XX, j, lag + j, order ) = energy;
}
@@ -153,6 +146,5 @@ void silk_corrMatrix_FIX(
ptr2--;/* Update pointer to first sample of next column (lag) in X */
}
}
- *rshifts = rshifts_local;
}
diff --git a/libs/libopus/silk/fixed/encode_frame_FIX.c b/libs/libopus/silk/fixed/encode_frame_FIX.c
index 5ef44b03f..a02bf87db 100644
--- a/libs/libopus/silk/fixed/encode_frame_FIX.c
+++ b/libs/libopus/silk/fixed/encode_frame_FIX.c
@@ -29,6 +29,7 @@ POSSIBILITY OF SUCH DAMAGE.
#include "config.h"
#endif
+#include <stdlib.h>
#include "main_FIX.h"
#include "stack_alloc.h"
#include "tuning_parameters.h"
@@ -37,26 +38,33 @@ POSSIBILITY OF SUCH DAMAGE.
static OPUS_INLINE void silk_LBRR_encode_FIX(
silk_encoder_state_FIX *psEnc, /* I/O Pointer to Silk FIX encoder state */
silk_encoder_control_FIX *psEncCtrl, /* I/O Pointer to Silk FIX encoder control struct */
- const opus_int32 xfw_Q3[], /* I Input signal */
+ const opus_int16 x16[], /* I Input signal */
opus_int condCoding /* I The type of conditional coding used so far for this frame */
);
void silk_encode_do_VAD_FIX(
- silk_encoder_state_FIX *psEnc /* I/O Pointer to Silk FIX encoder state */
+ silk_encoder_state_FIX *psEnc, /* I/O Pointer to Silk FIX encoder state */
+ opus_int activity /* I Decision of Opus voice activity detector */
)
{
+ const opus_int activity_threshold = SILK_FIX_CONST( SPEECH_ACTIVITY_DTX_THRES, 8 );
+
/****************************/
/* Voice Activity Detection */
/****************************/
silk_VAD_GetSA_Q8( &psEnc->sCmn, psEnc->sCmn.inputBuf + 1, psEnc->sCmn.arch );
+ /* If Opus VAD is inactive and Silk VAD is active: lower Silk VAD to just under the threshold */
+ if( activity == VAD_NO_ACTIVITY && psEnc->sCmn.speech_activity_Q8 >= activity_threshold ) {
+ psEnc->sCmn.speech_activity_Q8 = activity_threshold - 1;
+ }
/**************************************************/
/* Convert speech activity into VAD and DTX flags */
/**************************************************/
- if( psEnc->sCmn.speech_activity_Q8 < SILK_FIX_CONST( SPEECH_ACTIVITY_DTX_THRES, 8 ) ) {
+ if( psEnc->sCmn.speech_activity_Q8 < activity_threshold ) {
psEnc->sCmn.indices.signalType = TYPE_NO_VOICE_ACTIVITY;
psEnc->sCmn.noSpeechCounter++;
- if( psEnc->sCmn.noSpeechCounter < NB_SPEECH_FRAMES_BEFORE_DTX ) {
+ if( psEnc->sCmn.noSpeechCounter <= NB_SPEECH_FRAMES_BEFORE_DTX ) {
psEnc->sCmn.inDTX = 0;
} else if( psEnc->sCmn.noSpeechCounter > MAX_CONSECUTIVE_DTX + NB_SPEECH_FRAMES_BEFORE_DTX ) {
psEnc->sCmn.noSpeechCounter = NB_SPEECH_FRAMES_BEFORE_DTX;
@@ -94,6 +102,9 @@ opus_int silk_encode_frame_FIX(
opus_int16 ec_prevLagIndex_copy;
opus_int ec_prevSignalType_copy;
opus_int8 LastGainIndex_copy2;
+ opus_int gain_lock[ MAX_NB_SUBFR ] = {0};
+ opus_int16 best_gain_mult[ MAX_NB_SUBFR ];
+ opus_int best_sum[ MAX_NB_SUBFR ];
SAVE_STACK;
/* This is totally unnecessary but many compilers (including gcc) are too dumb to realise it */
@@ -118,7 +129,6 @@ opus_int silk_encode_frame_FIX(
silk_memcpy( x_frame + LA_SHAPE_MS * psEnc->sCmn.fs_kHz, psEnc->sCmn.inputBuf + 1, psEnc->sCmn.frame_length * sizeof( opus_int16 ) );
if( !psEnc->sCmn.prefillFlag ) {
- VARDECL( opus_int32, xfw_Q3 );
VARDECL( opus_int16, res_pitch );
VARDECL( opus_uint8, ec_buf_copy );
opus_int16 *res_pitch_frame;
@@ -132,7 +142,7 @@ opus_int silk_encode_frame_FIX(
/*****************************************/
/* Find pitch lags, initial LPC analysis */
/*****************************************/
- silk_find_pitch_lags_FIX( psEnc, &sEncCtrl, res_pitch, x_frame, psEnc->sCmn.arch );
+ silk_find_pitch_lags_FIX( psEnc, &sEncCtrl, res_pitch, x_frame - psEnc->sCmn.ltp_mem_length, psEnc->sCmn.arch );
/************************/
/* Noise shape analysis */
@@ -142,23 +152,17 @@ opus_int silk_encode_frame_FIX(
/***************************************************/
/* Find linear prediction coefficients (LPC + LTP) */
/***************************************************/
- silk_find_pred_coefs_FIX( psEnc, &sEncCtrl, res_pitch, x_frame, condCoding );
+ silk_find_pred_coefs_FIX( psEnc, &sEncCtrl, res_pitch_frame, x_frame, condCoding );
/****************************************/
/* Process gains */
/****************************************/
silk_process_gains_FIX( psEnc, &sEncCtrl, condCoding );
- /*****************************************/
- /* Prefiltering for noise shaper */
- /*****************************************/
- ALLOC( xfw_Q3, psEnc->sCmn.frame_length, opus_int32 );
- silk_prefilter_FIX( psEnc, &sEncCtrl, xfw_Q3, x_frame );
-
/****************************************/
/* Low Bitrate Redundant Encoding */
/****************************************/
- silk_LBRR_encode_FIX( psEnc, &sEncCtrl, xfw_Q3, condCoding );
+ silk_LBRR_encode_FIX( psEnc, &sEncCtrl, x_frame, condCoding );
/* Loop over quantizer and entropy coding to control bitrate */
maxIter = 6;
@@ -194,17 +198,21 @@ opus_int silk_encode_frame_FIX(
/* Noise shaping quantization */
/*****************************************/
if( psEnc->sCmn.nStatesDelayedDecision > 1 || psEnc->sCmn.warping_Q16 > 0 ) {
- silk_NSQ_del_dec( &psEnc->sCmn, &psEnc->sCmn.sNSQ, &psEnc->sCmn.indices, xfw_Q3, psEnc->sCmn.pulses,
- sEncCtrl.PredCoef_Q12[ 0 ], sEncCtrl.LTPCoef_Q14, sEncCtrl.AR2_Q13, sEncCtrl.HarmShapeGain_Q14,
+ silk_NSQ_del_dec( &psEnc->sCmn, &psEnc->sCmn.sNSQ, &psEnc->sCmn.indices, x_frame, psEnc->sCmn.pulses,
+ sEncCtrl.PredCoef_Q12[ 0 ], sEncCtrl.LTPCoef_Q14, sEncCtrl.AR_Q13, sEncCtrl.HarmShapeGain_Q14,
sEncCtrl.Tilt_Q14, sEncCtrl.LF_shp_Q14, sEncCtrl.Gains_Q16, sEncCtrl.pitchL, sEncCtrl.Lambda_Q10, sEncCtrl.LTP_scale_Q14,
psEnc->sCmn.arch );
} else {
- silk_NSQ( &psEnc->sCmn, &psEnc->sCmn.sNSQ, &psEnc->sCmn.indices, xfw_Q3, psEnc->sCmn.pulses,
- sEncCtrl.PredCoef_Q12[ 0 ], sEncCtrl.LTPCoef_Q14, sEncCtrl.AR2_Q13, sEncCtrl.HarmShapeGain_Q14,
+ silk_NSQ( &psEnc->sCmn, &psEnc->sCmn.sNSQ, &psEnc->sCmn.indices, x_frame, psEnc->sCmn.pulses,
+ sEncCtrl.PredCoef_Q12[ 0 ], sEncCtrl.LTPCoef_Q14, sEncCtrl.AR_Q13, sEncCtrl.HarmShapeGain_Q14,
sEncCtrl.Tilt_Q14, sEncCtrl.LF_shp_Q14, sEncCtrl.Gains_Q16, sEncCtrl.pitchL, sEncCtrl.Lambda_Q10, sEncCtrl.LTP_scale_Q14,
psEnc->sCmn.arch);
}
+ if ( iter == maxIter && !found_lower ) {
+ silk_memcpy( &sRangeEnc_copy2, psRangeEnc, sizeof( ec_enc ) );
+ }
+
/****************************************/
/* Encode Parameters */
/****************************************/
@@ -218,6 +226,33 @@ opus_int silk_encode_frame_FIX(
nBits = ec_tell( psRangeEnc );
+ /* If we still bust after the last iteration, do some damage control. */
+ if ( iter == maxIter && !found_lower && nBits > maxBits ) {
+ silk_memcpy( psRangeEnc, &sRangeEnc_copy2, sizeof( ec_enc ) );
+
+ /* Keep gains the same as the last frame. */
+ psEnc->sShape.LastGainIndex = sEncCtrl.lastGainIndexPrev;
+ for ( i = 0; i < psEnc->sCmn.nb_subfr; i++ ) {
+ psEnc->sCmn.indices.GainsIndices[ i ] = 4;
+ }
+ if (condCoding != CODE_CONDITIONALLY) {
+ psEnc->sCmn.indices.GainsIndices[ 0 ] = sEncCtrl.lastGainIndexPrev;
+ }
+ psEnc->sCmn.ec_prevLagIndex = ec_prevLagIndex_copy;
+ psEnc->sCmn.ec_prevSignalType = ec_prevSignalType_copy;
+ /* Clear all pulses. */
+ for ( i = 0; i < psEnc->sCmn.frame_length; i++ ) {
+ psEnc->sCmn.pulses[ i ] = 0;
+ }
+
+ silk_encode_indices( &psEnc->sCmn, psRangeEnc, psEnc->sCmn.nFramesEncoded, 0, condCoding );
+
+ silk_encode_pulses( psRangeEnc, psEnc->sCmn.indices.signalType, psEnc->sCmn.indices.quantOffsetType,
+ psEnc->sCmn.pulses, psEnc->sCmn.frame_length );
+
+ nBits = ec_tell( psRangeEnc );
+ }
+
if( useCBR == 0 && iter == 0 && nBits <= maxBits ) {
break;
}
@@ -227,7 +262,7 @@ opus_int silk_encode_frame_FIX(
if( found_lower && ( gainsID == gainsID_lower || nBits > maxBits ) ) {
/* Restore output state from earlier iteration that did meet the bitrate budget */
silk_memcpy( psRangeEnc, &sRangeEnc_copy2, sizeof( ec_enc ) );
- silk_assert( sRangeEnc_copy2.offs <= 1275 );
+ celt_assert( sRangeEnc_copy2.offs <= 1275 );
silk_memcpy( psRangeEnc->buf, ec_buf_copy, sRangeEnc_copy2.offs );
silk_memcpy( &psEnc->sCmn.sNSQ, &sNSQ_copy2, sizeof( silk_nsq_state ) );
psEnc->sShape.LastGainIndex = LastGainIndex_copy2;
@@ -255,7 +290,7 @@ opus_int silk_encode_frame_FIX(
gainsID_lower = gainsID;
/* Copy part of the output state */
silk_memcpy( &sRangeEnc_copy2, psRangeEnc, sizeof( ec_enc ) );
- silk_assert( psRangeEnc->offs <= 1275 );
+ celt_assert( psRangeEnc->offs <= 1275 );
silk_memcpy( ec_buf_copy, psRangeEnc->buf, psRangeEnc->offs );
silk_memcpy( &sNSQ_copy2, &psEnc->sCmn.sNSQ, sizeof( silk_nsq_state ) );
LastGainIndex_copy2 = psEnc->sShape.LastGainIndex;
@@ -265,15 +300,35 @@ opus_int silk_encode_frame_FIX(
break;
}
+ if ( !found_lower && nBits > maxBits ) {
+ int j;
+ for ( i = 0; i < psEnc->sCmn.nb_subfr; i++ ) {
+ int sum=0;
+ for ( j = i*psEnc->sCmn.subfr_length; j < (i+1)*psEnc->sCmn.subfr_length; j++ ) {
+ sum += abs( psEnc->sCmn.pulses[j] );
+ }
+ if ( iter == 0 || (sum < best_sum[i] && !gain_lock[i]) ) {
+ best_sum[i] = sum;
+ best_gain_mult[i] = gainMult_Q8;
+ } else {
+ gain_lock[i] = 1;
+ }
+ }
+ }
if( ( found_lower & found_upper ) == 0 ) {
/* Adjust gain according to high-rate rate/distortion curve */
- opus_int32 gain_factor_Q16;
- gain_factor_Q16 = silk_log2lin( silk_LSHIFT( nBits - maxBits, 7 ) / psEnc->sCmn.frame_length + SILK_FIX_CONST( 16, 7 ) );
- gain_factor_Q16 = silk_min_32( gain_factor_Q16, SILK_FIX_CONST( 2, 16 ) );
if( nBits > maxBits ) {
- gain_factor_Q16 = silk_max_32( gain_factor_Q16, SILK_FIX_CONST( 1.3, 16 ) );
+ if (gainMult_Q8 < 16384) {
+ gainMult_Q8 *= 2;
+ } else {
+ gainMult_Q8 = 32767;
+ }
+ } else {
+ opus_int32 gain_factor_Q16;
+ gain_factor_Q16 = silk_log2lin( silk_LSHIFT( nBits - maxBits, 7 ) / psEnc->sCmn.frame_length + SILK_FIX_CONST( 16, 7 ) );
+ gainMult_Q8 = silk_SMULWB( gain_factor_Q16, gainMult_Q8 );
}
- gainMult_Q8 = silk_SMULWB( gain_factor_Q16, gainMult_Q8 );
+
} else {
/* Adjust gain by interpolating */
gainMult_Q8 = gainMult_lower + silk_DIV32_16( silk_MUL( gainMult_upper - gainMult_lower, maxBits - nBits_lower ), nBits_upper - nBits_lower );
@@ -287,7 +342,13 @@ opus_int silk_encode_frame_FIX(
}
for( i = 0; i < psEnc->sCmn.nb_subfr; i++ ) {
- sEncCtrl.Gains_Q16[ i ] = silk_LSHIFT_SAT32( silk_SMULWB( sEncCtrl.GainsUnq_Q16[ i ], gainMult_Q8 ), 8 );
+ opus_int16 tmp;
+ if ( gain_lock[i] ) {
+ tmp = best_gain_mult[i];
+ } else {
+ tmp = gainMult_Q8;
+ }
+ sEncCtrl.Gains_Q16[ i ] = silk_LSHIFT_SAT32( silk_SMULWB( sEncCtrl.GainsUnq_Q16[ i ], tmp ), 8 );
}
/* Quantize gains */
@@ -331,7 +392,7 @@ opus_int silk_encode_frame_FIX(
static OPUS_INLINE void silk_LBRR_encode_FIX(
silk_encoder_state_FIX *psEnc, /* I/O Pointer to Silk FIX encoder state */
silk_encoder_control_FIX *psEncCtrl, /* I/O Pointer to Silk FIX encoder control struct */
- const opus_int32 xfw_Q3[], /* I Input signal */
+ const opus_int16 x16[], /* I Input signal */
opus_int condCoding /* I The type of conditional coding used so far for this frame */
)
{
@@ -370,14 +431,14 @@ static OPUS_INLINE void silk_LBRR_encode_FIX(
/* Noise shaping quantization */
/*****************************************/
if( psEnc->sCmn.nStatesDelayedDecision > 1 || psEnc->sCmn.warping_Q16 > 0 ) {
- silk_NSQ_del_dec( &psEnc->sCmn, &sNSQ_LBRR, psIndices_LBRR, xfw_Q3,
+ silk_NSQ_del_dec( &psEnc->sCmn, &sNSQ_LBRR, psIndices_LBRR, x16,
psEnc->sCmn.pulses_LBRR[ psEnc->sCmn.nFramesEncoded ], psEncCtrl->PredCoef_Q12[ 0 ], psEncCtrl->LTPCoef_Q14,
- psEncCtrl->AR2_Q13, psEncCtrl->HarmShapeGain_Q14, psEncCtrl->Tilt_Q14, psEncCtrl->LF_shp_Q14,
+ psEncCtrl->AR_Q13, psEncCtrl->HarmShapeGain_Q14, psEncCtrl->Tilt_Q14, psEncCtrl->LF_shp_Q14,
psEncCtrl->Gains_Q16, psEncCtrl->pitchL, psEncCtrl->Lambda_Q10, psEncCtrl->LTP_scale_Q14, psEnc->sCmn.arch );
} else {
- silk_NSQ( &psEnc->sCmn, &sNSQ_LBRR, psIndices_LBRR, xfw_Q3,
+ silk_NSQ( &psEnc->sCmn, &sNSQ_LBRR, psIndices_LBRR, x16,
psEnc->sCmn.pulses_LBRR[ psEnc->sCmn.nFramesEncoded ], psEncCtrl->PredCoef_Q12[ 0 ], psEncCtrl->LTPCoef_Q14,
- psEncCtrl->AR2_Q13, psEncCtrl->HarmShapeGain_Q14, psEncCtrl->Tilt_Q14, psEncCtrl->LF_shp_Q14,
+ psEncCtrl->AR_Q13, psEncCtrl->HarmShapeGain_Q14, psEncCtrl->Tilt_Q14, psEncCtrl->LF_shp_Q14,
psEncCtrl->Gains_Q16, psEncCtrl->pitchL, psEncCtrl->Lambda_Q10, psEncCtrl->LTP_scale_Q14, psEnc->sCmn.arch );
}
diff --git a/libs/libopus/silk/fixed/find_LPC_FIX.c b/libs/libopus/silk/fixed/find_LPC_FIX.c
index e11cdc86e..c762a0f2a 100644
--- a/libs/libopus/silk/fixed/find_LPC_FIX.c
+++ b/libs/libopus/silk/fixed/find_LPC_FIX.c
@@ -92,7 +92,7 @@ void silk_find_LPC_FIX(
silk_interpolate( NLSF0_Q15, psEncC->prev_NLSFq_Q15, NLSF_Q15, k, psEncC->predictLPCOrder );
/* Convert to LPC for residual energy evaluation */
- silk_NLSF2A( a_tmp_Q12, NLSF0_Q15, psEncC->predictLPCOrder );
+ silk_NLSF2A( a_tmp_Q12, NLSF0_Q15, psEncC->predictLPCOrder, psEncC->arch );
/* Calculate residual energy with NLSF interpolation */
silk_LPC_analysis_filter( LPC_res, x, a_tmp_Q12, 2 * subfr_length, psEncC->predictLPCOrder, psEncC->arch );
@@ -146,6 +146,6 @@ void silk_find_LPC_FIX(
silk_A2NLSF( NLSF_Q15, a_Q16, psEncC->predictLPCOrder );
}
- silk_assert( psEncC->indices.NLSFInterpCoef_Q2 == 4 || ( psEncC->useInterpolatedNLSFs && !psEncC->first_frame_after_reset && psEncC->nb_subfr == MAX_NB_SUBFR ) );
+ celt_assert( psEncC->indices.NLSFInterpCoef_Q2 == 4 || ( psEncC->useInterpolatedNLSFs && !psEncC->first_frame_after_reset && psEncC->nb_subfr == MAX_NB_SUBFR ) );
RESTORE_STACK;
}
diff --git a/libs/libopus/silk/fixed/find_LTP_FIX.c b/libs/libopus/silk/fixed/find_LTP_FIX.c
index 1314a2813..62d4afb25 100644
--- a/libs/libopus/silk/fixed/find_LTP_FIX.c
+++ b/libs/libopus/silk/fixed/find_LTP_FIX.c
@@ -32,214 +32,68 @@ POSSIBILITY OF SUCH DAMAGE.
#include "main_FIX.h"
#include "tuning_parameters.h"
-/* Head room for correlations */
-#define LTP_CORRS_HEAD_ROOM 2
-
-void silk_fit_LTP(
- opus_int32 LTP_coefs_Q16[ LTP_ORDER ],
- opus_int16 LTP_coefs_Q14[ LTP_ORDER ]
-);
-
void silk_find_LTP_FIX(
- opus_int16 b_Q14[ MAX_NB_SUBFR * LTP_ORDER ], /* O LTP coefs */
- opus_int32 WLTP[ MAX_NB_SUBFR * LTP_ORDER * LTP_ORDER ], /* O Weight for LTP quantization */
- opus_int *LTPredCodGain_Q7, /* O LTP coding gain */
- const opus_int16 r_lpc[], /* I residual signal after LPC signal + state for first 10 ms */
+ opus_int32 XXLTP_Q17[ MAX_NB_SUBFR * LTP_ORDER * LTP_ORDER ], /* O Correlation matrix */
+ opus_int32 xXLTP_Q17[ MAX_NB_SUBFR * LTP_ORDER ], /* O Correlation vector */
+ const opus_int16 r_ptr[], /* I Residual signal after LPC */
const opus_int lag[ MAX_NB_SUBFR ], /* I LTP lags */
- const opus_int32 Wght_Q15[ MAX_NB_SUBFR ], /* I weights */
- const opus_int subfr_length, /* I subframe length */
- const opus_int nb_subfr, /* I number of subframes */
- const opus_int mem_offset, /* I number of samples in LTP memory */
- opus_int corr_rshifts[ MAX_NB_SUBFR ], /* O right shifts applied to correlations */
+ const opus_int subfr_length, /* I Subframe length */
+ const opus_int nb_subfr, /* I Number of subframes */
int arch /* I Run-time architecture */
)
{
- opus_int i, k, lshift;
- const opus_int16 *r_ptr, *lag_ptr;
- opus_int16 *b_Q14_ptr;
-
- opus_int32 regu;
- opus_int32 *WLTP_ptr;
- opus_int32 b_Q16[ LTP_ORDER ], delta_b_Q14[ LTP_ORDER ], d_Q14[ MAX_NB_SUBFR ], nrg[ MAX_NB_SUBFR ], g_Q26;
- opus_int32 w[ MAX_NB_SUBFR ], WLTP_max, max_abs_d_Q14, max_w_bits;
-
- opus_int32 temp32, denom32;
- opus_int extra_shifts;
- opus_int rr_shifts, maxRshifts, maxRshifts_wxtra, LZs;
- opus_int32 LPC_res_nrg, LPC_LTP_res_nrg, div_Q16;
- opus_int32 Rr[ LTP_ORDER ], rr[ MAX_NB_SUBFR ];
- opus_int32 wd, m_Q12;
-
- b_Q14_ptr = b_Q14;
- WLTP_ptr = WLTP;
- r_ptr = &r_lpc[ mem_offset ];
+ opus_int i, k, extra_shifts;
+ opus_int xx_shifts, xX_shifts, XX_shifts;
+ const opus_int16 *lag_ptr;
+ opus_int32 *XXLTP_Q17_ptr, *xXLTP_Q17_ptr;
+ opus_int32 xx, nrg, temp;
+
+ xXLTP_Q17_ptr = xXLTP_Q17;
+ XXLTP_Q17_ptr = XXLTP_Q17;
for( k = 0; k < nb_subfr; k++ ) {
lag_ptr = r_ptr - ( lag[ k ] + LTP_ORDER / 2 );
- silk_sum_sqr_shift( &rr[ k ], &rr_shifts, r_ptr, subfr_length ); /* rr[ k ] in Q( -rr_shifts ) */
-
- /* Assure headroom */
- LZs = silk_CLZ32( rr[k] );
- if( LZs < LTP_CORRS_HEAD_ROOM ) {
- rr[ k ] = silk_RSHIFT_ROUND( rr[ k ], LTP_CORRS_HEAD_ROOM - LZs );
- rr_shifts += ( LTP_CORRS_HEAD_ROOM - LZs );
- }
- corr_rshifts[ k ] = rr_shifts;
- silk_corrMatrix_FIX( lag_ptr, subfr_length, LTP_ORDER, LTP_CORRS_HEAD_ROOM, WLTP_ptr, &corr_rshifts[ k ], arch ); /* WLTP_fix_ptr in Q( -corr_rshifts[ k ] ) */
-
- /* The correlation vector always has lower max abs value than rr and/or RR so head room is assured */
- silk_corrVector_FIX( lag_ptr, r_ptr, subfr_length, LTP_ORDER, Rr, corr_rshifts[ k ], arch ); /* Rr_fix_ptr in Q( -corr_rshifts[ k ] ) */
- if( corr_rshifts[ k ] > rr_shifts ) {
- rr[ k ] = silk_RSHIFT( rr[ k ], corr_rshifts[ k ] - rr_shifts ); /* rr[ k ] in Q( -corr_rshifts[ k ] ) */
+ silk_sum_sqr_shift( &xx, &xx_shifts, r_ptr, subfr_length + LTP_ORDER ); /* xx in Q( -xx_shifts ) */
+ silk_corrMatrix_FIX( lag_ptr, subfr_length, LTP_ORDER, XXLTP_Q17_ptr, &nrg, &XX_shifts, arch ); /* XXLTP_Q17_ptr and nrg in Q( -XX_shifts ) */
+ extra_shifts = xx_shifts - XX_shifts;
+ if( extra_shifts > 0 ) {
+ /* Shift XX */
+ xX_shifts = xx_shifts;
+ for( i = 0; i < LTP_ORDER * LTP_ORDER; i++ ) {
+ XXLTP_Q17_ptr[ i ] = silk_RSHIFT32( XXLTP_Q17_ptr[ i ], extra_shifts ); /* Q( -xX_shifts ) */
+ }
+ nrg = silk_RSHIFT32( nrg, extra_shifts ); /* Q( -xX_shifts ) */
+ } else if( extra_shifts < 0 ) {
+ /* Shift xx */
+ xX_shifts = XX_shifts;
+ xx = silk_RSHIFT32( xx, -extra_shifts ); /* Q( -xX_shifts ) */
+ } else {
+ xX_shifts = xx_shifts;
}
- silk_assert( rr[ k ] >= 0 );
-
- regu = 1;
- regu = silk_SMLAWB( regu, rr[ k ], SILK_FIX_CONST( LTP_DAMPING/3, 16 ) );
- regu = silk_SMLAWB( regu, matrix_ptr( WLTP_ptr, 0, 0, LTP_ORDER ), SILK_FIX_CONST( LTP_DAMPING/3, 16 ) );
- regu = silk_SMLAWB( regu, matrix_ptr( WLTP_ptr, LTP_ORDER-1, LTP_ORDER-1, LTP_ORDER ), SILK_FIX_CONST( LTP_DAMPING/3, 16 ) );
- silk_regularize_correlations_FIX( WLTP_ptr, &rr[k], regu, LTP_ORDER );
-
- silk_solve_LDL_FIX( WLTP_ptr, LTP_ORDER, Rr, b_Q16 ); /* WLTP_fix_ptr and Rr_fix_ptr both in Q(-corr_rshifts[k]) */
-
- /* Limit and store in Q14 */
- silk_fit_LTP( b_Q16, b_Q14_ptr );
-
- /* Calculate residual energy */
- nrg[ k ] = silk_residual_energy16_covar_FIX( b_Q14_ptr, WLTP_ptr, Rr, rr[ k ], LTP_ORDER, 14 ); /* nrg_fix in Q( -corr_rshifts[ k ] ) */
-
- /* temp = Wght[ k ] / ( nrg[ k ] * Wght[ k ] + 0.01f * subfr_length ); */
- extra_shifts = silk_min_int( corr_rshifts[ k ], LTP_CORRS_HEAD_ROOM );
- denom32 = silk_LSHIFT_SAT32( silk_SMULWB( nrg[ k ], Wght_Q15[ k ] ), 1 + extra_shifts ) + /* Q( -corr_rshifts[ k ] + extra_shifts ) */
- silk_RSHIFT( silk_SMULWB( (opus_int32)subfr_length, 655 ), corr_rshifts[ k ] - extra_shifts ); /* Q( -corr_rshifts[ k ] + extra_shifts ) */
- denom32 = silk_max( denom32, 1 );
- silk_assert( ((opus_int64)Wght_Q15[ k ] << 16 ) < silk_int32_MAX ); /* Wght always < 0.5 in Q0 */
- temp32 = silk_DIV32( silk_LSHIFT( (opus_int32)Wght_Q15[ k ], 16 ), denom32 ); /* Q( 15 + 16 + corr_rshifts[k] - extra_shifts ) */
- temp32 = silk_RSHIFT( temp32, 31 + corr_rshifts[ k ] - extra_shifts - 26 ); /* Q26 */
+ silk_corrVector_FIX( lag_ptr, r_ptr, subfr_length, LTP_ORDER, xXLTP_Q17_ptr, xX_shifts, arch ); /* xXLTP_Q17_ptr in Q( -xX_shifts ) */
- /* Limit temp such that the below scaling never wraps around */
- WLTP_max = 0;
+ /* At this point all correlations are in Q(-xX_shifts) */
+ temp = silk_SMLAWB( 1, nrg, SILK_FIX_CONST( LTP_CORR_INV_MAX, 16 ) );
+ temp = silk_max( temp, xx );
+TIC(div)
+#if 0
for( i = 0; i < LTP_ORDER * LTP_ORDER; i++ ) {
- WLTP_max = silk_max( WLTP_ptr[ i ], WLTP_max );
+ XXLTP_Q17_ptr[ i ] = silk_DIV32_varQ( XXLTP_Q17_ptr[ i ], temp, 17 );
}
- lshift = silk_CLZ32( WLTP_max ) - 1 - 3; /* keep 3 bits free for vq_nearest_neighbor_fix */
- silk_assert( 26 - 18 + lshift >= 0 );
- if( 26 - 18 + lshift < 31 ) {
- temp32 = silk_min_32( temp32, silk_LSHIFT( (opus_int32)1, 26 - 18 + lshift ) );
- }
-
- silk_scale_vector32_Q26_lshift_18( WLTP_ptr, temp32, LTP_ORDER * LTP_ORDER ); /* WLTP_ptr in Q( 18 - corr_rshifts[ k ] ) */
-
- w[ k ] = matrix_ptr( WLTP_ptr, LTP_ORDER/2, LTP_ORDER/2, LTP_ORDER ); /* w in Q( 18 - corr_rshifts[ k ] ) */
- silk_assert( w[k] >= 0 );
-
- r_ptr += subfr_length;
- b_Q14_ptr += LTP_ORDER;
- WLTP_ptr += LTP_ORDER * LTP_ORDER;
- }
-
- maxRshifts = 0;
- for( k = 0; k < nb_subfr; k++ ) {
- maxRshifts = silk_max_int( corr_rshifts[ k ], maxRshifts );
- }
-
- /* Compute LTP coding gain */
- if( LTPredCodGain_Q7 != NULL ) {
- LPC_LTP_res_nrg = 0;
- LPC_res_nrg = 0;
- silk_assert( LTP_CORRS_HEAD_ROOM >= 2 ); /* Check that no overflow will happen when adding */
- for( k = 0; k < nb_subfr; k++ ) {
- LPC_res_nrg = silk_ADD32( LPC_res_nrg, silk_RSHIFT( silk_ADD32( silk_SMULWB( rr[ k ], Wght_Q15[ k ] ), 1 ), 1 + ( maxRshifts - corr_rshifts[ k ] ) ) ); /* Q( -maxRshifts ) */
- LPC_LTP_res_nrg = silk_ADD32( LPC_LTP_res_nrg, silk_RSHIFT( silk_ADD32( silk_SMULWB( nrg[ k ], Wght_Q15[ k ] ), 1 ), 1 + ( maxRshifts - corr_rshifts[ k ] ) ) ); /* Q( -maxRshifts ) */
- }
- LPC_LTP_res_nrg = silk_max( LPC_LTP_res_nrg, 1 ); /* avoid division by zero */
-
- div_Q16 = silk_DIV32_varQ( LPC_res_nrg, LPC_LTP_res_nrg, 16 );
- *LTPredCodGain_Q7 = ( opus_int )silk_SMULBB( 3, silk_lin2log( div_Q16 ) - ( 16 << 7 ) );
-
- silk_assert( *LTPredCodGain_Q7 == ( opus_int )silk_SAT16( silk_MUL( 3, silk_lin2log( div_Q16 ) - ( 16 << 7 ) ) ) );
- }
-
- /* smoothing */
- /* d = sum( B, 1 ); */
- b_Q14_ptr = b_Q14;
- for( k = 0; k < nb_subfr; k++ ) {
- d_Q14[ k ] = 0;
for( i = 0; i < LTP_ORDER; i++ ) {
- d_Q14[ k ] += b_Q14_ptr[ i ];
- }
- b_Q14_ptr += LTP_ORDER;
- }
-
- /* m = ( w * d' ) / ( sum( w ) + 1e-3 ); */
-
- /* Find maximum absolute value of d_Q14 and the bits used by w in Q0 */
- max_abs_d_Q14 = 0;
- max_w_bits = 0;
- for( k = 0; k < nb_subfr; k++ ) {
- max_abs_d_Q14 = silk_max_32( max_abs_d_Q14, silk_abs( d_Q14[ k ] ) );
- /* w[ k ] is in Q( 18 - corr_rshifts[ k ] ) */
- /* Find bits needed in Q( 18 - maxRshifts ) */
- max_w_bits = silk_max_32( max_w_bits, 32 - silk_CLZ32( w[ k ] ) + corr_rshifts[ k ] - maxRshifts );
- }
-
- /* max_abs_d_Q14 = (5 << 15); worst case, i.e. LTP_ORDER * -silk_int16_MIN */
- silk_assert( max_abs_d_Q14 <= ( 5 << 15 ) );
-
- /* How many bits is needed for w*d' in Q( 18 - maxRshifts ) in the worst case, of all d_Q14's being equal to max_abs_d_Q14 */
- extra_shifts = max_w_bits + 32 - silk_CLZ32( max_abs_d_Q14 ) - 14;
-
- /* Subtract what we got available; bits in output var plus maxRshifts */
- extra_shifts -= ( 32 - 1 - 2 + maxRshifts ); /* Keep sign bit free as well as 2 bits for accumulation */
- extra_shifts = silk_max_int( extra_shifts, 0 );
-
- maxRshifts_wxtra = maxRshifts + extra_shifts;
-
- temp32 = silk_RSHIFT( 262, maxRshifts + extra_shifts ) + 1; /* 1e-3f in Q( 18 - (maxRshifts + extra_shifts) ) */
- wd = 0;
- for( k = 0; k < nb_subfr; k++ ) {
- /* w has at least 2 bits of headroom so no overflow should happen */
- temp32 = silk_ADD32( temp32, silk_RSHIFT( w[ k ], maxRshifts_wxtra - corr_rshifts[ k ] ) ); /* Q( 18 - maxRshifts_wxtra ) */
- wd = silk_ADD32( wd, silk_LSHIFT( silk_SMULWW( silk_RSHIFT( w[ k ], maxRshifts_wxtra - corr_rshifts[ k ] ), d_Q14[ k ] ), 2 ) ); /* Q( 18 - maxRshifts_wxtra ) */
- }
- m_Q12 = silk_DIV32_varQ( wd, temp32, 12 );
-
- b_Q14_ptr = b_Q14;
- for( k = 0; k < nb_subfr; k++ ) {
- /* w_fix[ k ] from Q( 18 - corr_rshifts[ k ] ) to Q( 16 ) */
- if( 2 - corr_rshifts[k] > 0 ) {
- temp32 = silk_RSHIFT( w[ k ], 2 - corr_rshifts[ k ] );
- } else {
- temp32 = silk_LSHIFT_SAT32( w[ k ], corr_rshifts[ k ] - 2 );
+ xXLTP_Q17_ptr[ i ] = silk_DIV32_varQ( xXLTP_Q17_ptr[ i ], temp, 17 );
}
-
- g_Q26 = silk_MUL(
- silk_DIV32(
- SILK_FIX_CONST( LTP_SMOOTHING, 26 ),
- silk_RSHIFT( SILK_FIX_CONST( LTP_SMOOTHING, 26 ), 10 ) + temp32 ), /* Q10 */
- silk_LSHIFT_SAT32( silk_SUB_SAT32( (opus_int32)m_Q12, silk_RSHIFT( d_Q14[ k ], 2 ) ), 4 ) ); /* Q16 */
-
- temp32 = 0;
- for( i = 0; i < LTP_ORDER; i++ ) {
- delta_b_Q14[ i ] = silk_max_16( b_Q14_ptr[ i ], 1638 ); /* 1638_Q14 = 0.1_Q0 */
- temp32 += delta_b_Q14[ i ]; /* Q14 */
+#else
+ for( i = 0; i < LTP_ORDER * LTP_ORDER; i++ ) {
+ XXLTP_Q17_ptr[ i ] = (opus_int32)( silk_LSHIFT64( (opus_int64)XXLTP_Q17_ptr[ i ], 17 ) / temp );
}
- temp32 = silk_DIV32( g_Q26, temp32 ); /* Q14 -> Q12 */
for( i = 0; i < LTP_ORDER; i++ ) {
- b_Q14_ptr[ i ] = silk_LIMIT_32( (opus_int32)b_Q14_ptr[ i ] + silk_SMULWB( silk_LSHIFT_SAT32( temp32, 4 ), delta_b_Q14[ i ] ), -16000, 28000 );
+ xXLTP_Q17_ptr[ i ] = (opus_int32)( silk_LSHIFT64( (opus_int64)xXLTP_Q17_ptr[ i ], 17 ) / temp );
}
- b_Q14_ptr += LTP_ORDER;
- }
-}
-
-void silk_fit_LTP(
- opus_int32 LTP_coefs_Q16[ LTP_ORDER ],
- opus_int16 LTP_coefs_Q14[ LTP_ORDER ]
-)
-{
- opus_int i;
-
- for( i = 0; i < LTP_ORDER; i++ ) {
- LTP_coefs_Q14[ i ] = (opus_int16)silk_SAT16( silk_RSHIFT_ROUND( LTP_coefs_Q16[ i ], 2 ) );
+#endif
+TOC(div)
+ r_ptr += subfr_length;
+ XXLTP_Q17_ptr += LTP_ORDER * LTP_ORDER;
+ xXLTP_Q17_ptr += LTP_ORDER;
}
}
diff --git a/libs/libopus/silk/fixed/find_pitch_lags_FIX.c b/libs/libopus/silk/fixed/find_pitch_lags_FIX.c
index b8440a824..6c3379f2b 100644
--- a/libs/libopus/silk/fixed/find_pitch_lags_FIX.c
+++ b/libs/libopus/silk/fixed/find_pitch_lags_FIX.c
@@ -44,7 +44,7 @@ void silk_find_pitch_lags_FIX(
{
opus_int buf_len, i, scale;
opus_int32 thrhld_Q13, res_nrg;
- const opus_int16 *x_buf, *x_buf_ptr;
+ const opus_int16 *x_ptr;
VARDECL( opus_int16, Wsig );
opus_int16 *Wsig_ptr;
opus_int32 auto_corr[ MAX_FIND_PITCH_LPC_ORDER + 1 ];
@@ -59,9 +59,7 @@ void silk_find_pitch_lags_FIX(
buf_len = psEnc->sCmn.la_pitch + psEnc->sCmn.frame_length + psEnc->sCmn.ltp_mem_length;
/* Safety check */
- silk_assert( buf_len >= psEnc->sCmn.pitch_LPC_win_length );
-
- x_buf = x - psEnc->sCmn.ltp_mem_length;
+ celt_assert( buf_len >= psEnc->sCmn.pitch_LPC_win_length );
/*************************************/
/* Estimate LPC AR coefficients */
@@ -72,19 +70,19 @@ void silk_find_pitch_lags_FIX(
ALLOC( Wsig, psEnc->sCmn.pitch_LPC_win_length, opus_int16 );
/* First LA_LTP samples */
- x_buf_ptr = x_buf + buf_len - psEnc->sCmn.pitch_LPC_win_length;
+ x_ptr = x + buf_len - psEnc->sCmn.pitch_LPC_win_length;
Wsig_ptr = Wsig;
- silk_apply_sine_window( Wsig_ptr, x_buf_ptr, 1, psEnc->sCmn.la_pitch );
+ silk_apply_sine_window( Wsig_ptr, x_ptr, 1, psEnc->sCmn.la_pitch );
/* Middle un - windowed samples */
Wsig_ptr += psEnc->sCmn.la_pitch;
- x_buf_ptr += psEnc->sCmn.la_pitch;
- silk_memcpy( Wsig_ptr, x_buf_ptr, ( psEnc->sCmn.pitch_LPC_win_length - silk_LSHIFT( psEnc->sCmn.la_pitch, 1 ) ) * sizeof( opus_int16 ) );
+ x_ptr += psEnc->sCmn.la_pitch;
+ silk_memcpy( Wsig_ptr, x_ptr, ( psEnc->sCmn.pitch_LPC_win_length - silk_LSHIFT( psEnc->sCmn.la_pitch, 1 ) ) * sizeof( opus_int16 ) );
/* Last LA_LTP samples */
Wsig_ptr += psEnc->sCmn.pitch_LPC_win_length - silk_LSHIFT( psEnc->sCmn.la_pitch, 1 );
- x_buf_ptr += psEnc->sCmn.pitch_LPC_win_length - silk_LSHIFT( psEnc->sCmn.la_pitch, 1 );
- silk_apply_sine_window( Wsig_ptr, x_buf_ptr, 2, psEnc->sCmn.la_pitch );
+ x_ptr += psEnc->sCmn.pitch_LPC_win_length - silk_LSHIFT( psEnc->sCmn.la_pitch, 1 );
+ silk_apply_sine_window( Wsig_ptr, x_ptr, 2, psEnc->sCmn.la_pitch );
/* Calculate autocorrelation sequence */
silk_autocorr( auto_corr, &scale, Wsig, psEnc->sCmn.pitch_LPC_win_length, psEnc->sCmn.pitchEstimationLPCOrder + 1, arch );
@@ -112,7 +110,7 @@ void silk_find_pitch_lags_FIX(
/*****************************************/
/* LPC analysis filtering */
/*****************************************/
- silk_LPC_analysis_filter( res, x_buf, A_Q12, buf_len, psEnc->sCmn.pitchEstimationLPCOrder, psEnc->sCmn.arch );
+ silk_LPC_analysis_filter( res, x, A_Q12, buf_len, psEnc->sCmn.pitchEstimationLPCOrder, psEnc->sCmn.arch );
if( psEnc->sCmn.indices.signalType != TYPE_NO_VOICE_ACTIVITY && psEnc->sCmn.first_frame_after_reset == 0 ) {
/* Threshold for pitch estimator */
diff --git a/libs/libopus/silk/fixed/find_pred_coefs_FIX.c b/libs/libopus/silk/fixed/find_pred_coefs_FIX.c
index d308e9cf5..606d86334 100644
--- a/libs/libopus/silk/fixed/find_pred_coefs_FIX.c
+++ b/libs/libopus/silk/fixed/find_pred_coefs_FIX.c
@@ -41,13 +41,12 @@ void silk_find_pred_coefs_FIX(
)
{
opus_int i;
- opus_int32 invGains_Q16[ MAX_NB_SUBFR ], local_gains[ MAX_NB_SUBFR ], Wght_Q15[ MAX_NB_SUBFR ];
+ opus_int32 invGains_Q16[ MAX_NB_SUBFR ], local_gains[ MAX_NB_SUBFR ];
opus_int16 NLSF_Q15[ MAX_LPC_ORDER ];
const opus_int16 *x_ptr;
opus_int16 *x_pre_ptr;
VARDECL( opus_int16, LPC_in_pre );
- opus_int32 tmp, min_gain_Q16, minInvGain_Q30;
- opus_int LTP_corrs_rshift[ MAX_NB_SUBFR ];
+ opus_int32 min_gain_Q16, minInvGain_Q30;
SAVE_STACK;
/* weighting for weighted least squares */
@@ -61,13 +60,11 @@ void silk_find_pred_coefs_FIX(
/* Invert and normalize gains, and ensure that maximum invGains_Q16 is within range of a 16 bit int */
invGains_Q16[ i ] = silk_DIV32_varQ( min_gain_Q16, psEncCtrl->Gains_Q16[ i ], 16 - 2 );
- /* Ensure Wght_Q15 a minimum value 1 */
- invGains_Q16[ i ] = silk_max( invGains_Q16[ i ], 363 );
+ /* Limit inverse */
+ invGains_Q16[ i ] = silk_max( invGains_Q16[ i ], 100 );
/* Square the inverted gains */
silk_assert( invGains_Q16[ i ] == silk_SAT16( invGains_Q16[ i ] ) );
- tmp = silk_SMULWB( invGains_Q16[ i ], invGains_Q16[ i ] );
- Wght_Q15[ i ] = silk_RSHIFT( tmp, 1 );
/* Invert the inverted and normalized gains */
local_gains[ i ] = silk_DIV32( ( (opus_int32)1 << 16 ), invGains_Q16[ i ] );
@@ -77,24 +74,24 @@ void silk_find_pred_coefs_FIX(
psEnc->sCmn.nb_subfr * psEnc->sCmn.predictLPCOrder
+ psEnc->sCmn.frame_length, opus_int16 );
if( psEnc->sCmn.indices.signalType == TYPE_VOICED ) {
- VARDECL( opus_int32, WLTP );
+ VARDECL( opus_int32, xXLTP_Q17 );
+ VARDECL( opus_int32, XXLTP_Q17 );
/**********/
/* VOICED */
/**********/
- silk_assert( psEnc->sCmn.ltp_mem_length - psEnc->sCmn.predictLPCOrder >= psEncCtrl->pitchL[ 0 ] + LTP_ORDER / 2 );
+ celt_assert( psEnc->sCmn.ltp_mem_length - psEnc->sCmn.predictLPCOrder >= psEncCtrl->pitchL[ 0 ] + LTP_ORDER / 2 );
- ALLOC( WLTP, psEnc->sCmn.nb_subfr * LTP_ORDER * LTP_ORDER, opus_int32 );
+ ALLOC( xXLTP_Q17, psEnc->sCmn.nb_subfr * LTP_ORDER, opus_int32 );
+ ALLOC( XXLTP_Q17, psEnc->sCmn.nb_subfr * LTP_ORDER * LTP_ORDER, opus_int32 );
/* LTP analysis */
- silk_find_LTP_FIX( psEncCtrl->LTPCoef_Q14, WLTP, &psEncCtrl->LTPredCodGain_Q7,
- res_pitch, psEncCtrl->pitchL, Wght_Q15, psEnc->sCmn.subfr_length,
- psEnc->sCmn.nb_subfr, psEnc->sCmn.ltp_mem_length, LTP_corrs_rshift, psEnc->sCmn.arch );
+ silk_find_LTP_FIX( XXLTP_Q17, xXLTP_Q17, res_pitch,
+ psEncCtrl->pitchL, psEnc->sCmn.subfr_length, psEnc->sCmn.nb_subfr, psEnc->sCmn.arch );
/* Quantize LTP gain parameters */
silk_quant_LTP_gains( psEncCtrl->LTPCoef_Q14, psEnc->sCmn.indices.LTPIndex, &psEnc->sCmn.indices.PERIndex,
- &psEnc->sCmn.sum_log_gain_Q7, WLTP, psEnc->sCmn.mu_LTP_Q9, psEnc->sCmn.LTPQuantLowComplexity, psEnc->sCmn.nb_subfr,
- psEnc->sCmn.arch);
+ &psEnc->sCmn.sum_log_gain_Q7, &psEncCtrl->LTPredCodGain_Q7, XXLTP_Q17, xXLTP_Q17, psEnc->sCmn.subfr_length, psEnc->sCmn.nb_subfr, psEnc->sCmn.arch );
/* Control LTP scaling */
silk_LTP_scale_ctrl_FIX( psEnc, psEncCtrl, condCoding );
diff --git a/libs/libopus/silk/fixed/k2a_FIX.c b/libs/libopus/silk/fixed/k2a_FIX.c
index 5fee599bc..549f6eada 100644
--- a/libs/libopus/silk/fixed/k2a_FIX.c
+++ b/libs/libopus/silk/fixed/k2a_FIX.c
@@ -39,14 +39,15 @@ void silk_k2a(
)
{
opus_int k, n;
- opus_int32 Atmp[ SILK_MAX_ORDER_LPC ];
+ opus_int32 rc, tmp1, tmp2;
for( k = 0; k < order; k++ ) {
- for( n = 0; n < k; n++ ) {
- Atmp[ n ] = A_Q24[ n ];
- }
- for( n = 0; n < k; n++ ) {
- A_Q24[ n ] = silk_SMLAWB( A_Q24[ n ], silk_LSHIFT( Atmp[ k - n - 1 ], 1 ), rc_Q15[ k ] );
+ rc = rc_Q15[ k ];
+ for( n = 0; n < (k + 1) >> 1; n++ ) {
+ tmp1 = A_Q24[ n ];
+ tmp2 = A_Q24[ k - n - 1 ];
+ A_Q24[ n ] = silk_SMLAWB( tmp1, silk_LSHIFT( tmp2, 1 ), rc );
+ A_Q24[ k - n - 1 ] = silk_SMLAWB( tmp2, silk_LSHIFT( tmp1, 1 ), rc );
}
A_Q24[ k ] = -silk_LSHIFT( (opus_int32)rc_Q15[ k ], 9 );
}
diff --git a/libs/libopus/silk/fixed/k2a_Q16_FIX.c b/libs/libopus/silk/fixed/k2a_Q16_FIX.c
index 3b0398754..1595aa621 100644
--- a/libs/libopus/silk/fixed/k2a_Q16_FIX.c
+++ b/libs/libopus/silk/fixed/k2a_Q16_FIX.c
@@ -39,15 +39,16 @@ void silk_k2a_Q16(
)
{
opus_int k, n;
- opus_int32 Atmp[ SILK_MAX_ORDER_LPC ];
+ opus_int32 rc, tmp1, tmp2;
for( k = 0; k < order; k++ ) {
- for( n = 0; n < k; n++ ) {
- Atmp[ n ] = A_Q24[ n ];
+ rc = rc_Q16[ k ];
+ for( n = 0; n < (k + 1) >> 1; n++ ) {
+ tmp1 = A_Q24[ n ];
+ tmp2 = A_Q24[ k - n - 1 ];
+ A_Q24[ n ] = silk_SMLAWW( tmp1, tmp2, rc );
+ A_Q24[ k - n - 1 ] = silk_SMLAWW( tmp2, tmp1, rc );
}
- for( n = 0; n < k; n++ ) {
- A_Q24[ n ] = silk_SMLAWW( A_Q24[ n ], Atmp[ k - n - 1 ], rc_Q16[ k ] );
- }
- A_Q24[ k ] = -silk_LSHIFT( rc_Q16[ k ], 8 );
+ A_Q24[ k ] = -silk_LSHIFT( rc, 8 );
}
}
diff --git a/libs/libopus/silk/fixed/main_FIX.h b/libs/libopus/silk/fixed/main_FIX.h
index 375b5eb32..6d2112e51 100644
--- a/libs/libopus/silk/fixed/main_FIX.h
+++ b/libs/libopus/silk/fixed/main_FIX.h
@@ -36,6 +36,11 @@ POSSIBILITY OF SUCH DAMAGE.
#include "debug.h"
#include "entenc.h"
+#if ((defined(OPUS_ARM_ASM) && defined(FIXED_POINT)) \
+ || defined(OPUS_ARM_MAY_HAVE_NEON_INTR))
+#include "fixed/arm/warped_autocorrelation_FIX_arm.h"
+#endif
+
#ifndef FORCE_CPP_BUILD
#ifdef __cplusplus
extern "C"
@@ -47,6 +52,9 @@ extern "C"
#define silk_encode_do_VAD_Fxx silk_encode_do_VAD_FIX
#define silk_encode_frame_Fxx silk_encode_frame_FIX
+#define QC 10
+#define QS 13
+
/*********************/
/* Encoder Functions */
/*********************/
@@ -58,7 +66,8 @@ void silk_HP_variable_cutoff(
/* Encoder main function */
void silk_encode_do_VAD_FIX(
- silk_encoder_state_FIX *psEnc /* I/O Pointer to Silk FIX encoder state */
+ silk_encoder_state_FIX *psEnc, /* I/O Pointer to Silk FIX encoder state */
+ opus_int activity /* I Decision of Opus voice activity detector */
);
/* Encoder main function */
@@ -81,33 +90,11 @@ opus_int silk_init_encoder(
opus_int silk_control_encoder(
silk_encoder_state_Fxx *psEnc, /* I/O Pointer to Silk encoder state */
silk_EncControlStruct *encControl, /* I Control structure */
- const opus_int32 TargetRate_bps, /* I Target max bitrate (bps) */
const opus_int allow_bw_switch, /* I Flag to allow switching audio bandwidth */
const opus_int channelNb, /* I Channel number */
const opus_int force_fs_kHz
);
-/****************/
-/* Prefiltering */
-/****************/
-void silk_prefilter_FIX(
- silk_encoder_state_FIX *psEnc, /* I/O Encoder state */
- const silk_encoder_control_FIX *psEncCtrl, /* I Encoder control */
- opus_int32 xw_Q10[], /* O Weighted signal */
- const opus_int16 x[] /* I Speech signal */
-);
-
-void silk_warped_LPC_analysis_filter_FIX_c(
- opus_int32 state[], /* I/O State [order + 1] */
- opus_int32 res_Q2[], /* O Residual signal [length] */
- const opus_int16 coef_Q13[], /* I Coefficients [order] */
- const opus_int16 input[], /* I Input signal [length] */
- const opus_int16 lambda_Q16, /* I Warping factor */
- const opus_int length, /* I Length of input signal */
- const opus_int order /* I Filter order (even) */
-);
-
-
/**************************/
/* Noise shaping analysis */
/**************************/
@@ -121,7 +108,7 @@ void silk_noise_shape_analysis_FIX(
);
/* Autocorrelations for a warped frequency axis */
-void silk_warped_autocorrelation_FIX(
+void silk_warped_autocorrelation_FIX_c(
opus_int32 *corr, /* O Result [order + 1] */
opus_int *scale, /* O Scaling of the correlation vector */
const opus_int16 *input, /* I Input data to correlate */
@@ -130,6 +117,11 @@ void silk_warped_autocorrelation_FIX(
const opus_int order /* I Correlation order (even) */
);
+#if !defined(OVERRIDE_silk_warped_autocorrelation_FIX)
+#define silk_warped_autocorrelation_FIX(corr, scale, input, warping_Q16, length, order, arch) \
+ ((void)(arch), silk_warped_autocorrelation_FIX_c(corr, scale, input, warping_Q16, length, order))
+#endif
+
/* Calculation of LTP state scaling */
void silk_LTP_scale_ctrl_FIX(
silk_encoder_state_FIX *psEnc, /* I/O encoder state */
@@ -168,16 +160,12 @@ void silk_find_LPC_FIX(
/* LTP analysis */
void silk_find_LTP_FIX(
- opus_int16 b_Q14[ MAX_NB_SUBFR * LTP_ORDER ], /* O LTP coefs */
- opus_int32 WLTP[ MAX_NB_SUBFR * LTP_ORDER * LTP_ORDER ], /* O Weight for LTP quantization */
- opus_int *LTPredCodGain_Q7, /* O LTP coding gain */
- const opus_int16 r_lpc[], /* I residual signal after LPC signal + state for first 10 ms */
+ opus_int32 XXLTP_Q17[ MAX_NB_SUBFR * LTP_ORDER * LTP_ORDER ], /* O Correlation matrix */
+ opus_int32 xXLTP_Q17[ MAX_NB_SUBFR * LTP_ORDER ], /* O Correlation vector */
+ const opus_int16 r_lpc[], /* I Residual signal after LPC */
const opus_int lag[ MAX_NB_SUBFR ], /* I LTP lags */
- const opus_int32 Wght_Q15[ MAX_NB_SUBFR ], /* I weights */
- const opus_int subfr_length, /* I subframe length */
- const opus_int nb_subfr, /* I number of subframes */
- const opus_int mem_offset, /* I number of samples in LTP memory */
- opus_int corr_rshifts[ MAX_NB_SUBFR ], /* O right shifts applied to correlations */
+ const opus_int subfr_length, /* I Subframe length */
+ const opus_int nb_subfr, /* I Number of subframes */
int arch /* I Run-time architecture */
);
@@ -231,9 +219,9 @@ void silk_corrMatrix_FIX(
const opus_int16 *x, /* I x vector [L + order - 1] used to form data matrix X */
const opus_int L, /* I Length of vectors */
const opus_int order, /* I Max lag for correlation */
- const opus_int head_room, /* I Desired headroom */
opus_int32 *XX, /* O Pointer to X'*X correlation matrix [ order x order ] */
- opus_int *rshifts, /* I/O Right shifts of correlations */
+ opus_int32 *nrg, /* O Energy of x vector */
+ opus_int *rshifts, /* O Right shifts of correlations */
int arch /* I Run-time architecture */
);
@@ -248,22 +236,6 @@ void silk_corrVector_FIX(
int arch /* I Run-time architecture */
);
-/* Add noise to matrix diagonal */
-void silk_regularize_correlations_FIX(
- opus_int32 *XX, /* I/O Correlation matrices */
- opus_int32 *xx, /* I/O Correlation values */
- opus_int32 noise, /* I Noise to add */
- opus_int D /* I Dimension of XX */
-);
-
-/* Solves Ax = b, assuming A is symmetric */
-void silk_solve_LDL_FIX(
- opus_int32 *A, /* I Pointer to symetric square matrix A */
- opus_int M, /* I Size of matrix */
- const opus_int32 *b, /* I Pointer to b vector */
- opus_int32 *x_Q16 /* O Pointer to x solution vector */
-);
-
#ifndef FORCE_CPP_BUILD
#ifdef __cplusplus
}
diff --git a/libs/libopus/silk/fixed/mips/noise_shape_analysis_FIX_mipsr1.h b/libs/libopus/silk/fixed/mips/noise_shape_analysis_FIX_mipsr1.h
index c30481e43..3999b5bd0 100644
--- a/libs/libopus/silk/fixed/mips/noise_shape_analysis_FIX_mipsr1.h
+++ b/libs/libopus/silk/fixed/mips/noise_shape_analysis_FIX_mipsr1.h
@@ -169,7 +169,7 @@ void silk_noise_shape_analysis_FIX(
if( psEnc->sCmn.warping_Q16 > 0 ) {
/* Calculate warped auto correlation */
- silk_warped_autocorrelation_FIX( auto_corr, &scale, x_windowed, warping_Q16, psEnc->sCmn.shapeWinLength, psEnc->sCmn.shapingLPCOrder );
+ silk_warped_autocorrelation_FIX( auto_corr, &scale, x_windowed, warping_Q16, psEnc->sCmn.shapeWinLength, psEnc->sCmn.shapingLPCOrder, arch );
} else {
/* Calculate regular auto correlation */
silk_autocorr( auto_corr, &scale, x_windowed, psEnc->sCmn.shapeWinLength, psEnc->sCmn.shapingLPCOrder + 1, arch );
@@ -224,8 +224,8 @@ void silk_noise_shape_analysis_FIX(
silk_bwexpander_32( AR1_Q24, psEnc->sCmn.shapingLPCOrder, BWExp1_Q16 );
/* Ratio of prediction gains, in energy domain */
- pre_nrg_Q30 = silk_LPC_inverse_pred_gain_Q24( AR2_Q24, psEnc->sCmn.shapingLPCOrder );
- nrg = silk_LPC_inverse_pred_gain_Q24( AR1_Q24, psEnc->sCmn.shapingLPCOrder );
+ pre_nrg_Q30 = silk_LPC_inverse_pred_gain_Q24( AR2_Q24, psEnc->sCmn.shapingLPCOrder, arch );
+ nrg = silk_LPC_inverse_pred_gain_Q24( AR1_Q24, psEnc->sCmn.shapingLPCOrder, arch );
/*psEncCtrl->GainsPre[ k ] = 1.0f - 0.7f * ( 1.0f - pre_nrg / nrg ) = 0.3f + 0.7f * pre_nrg / nrg;*/
pre_nrg_Q30 = silk_LSHIFT32( silk_SMULWB( pre_nrg_Q30, SILK_FIX_CONST( 0.7, 15 ) ), 1 );
diff --git a/libs/libopus/silk/fixed/mips/prefilter_FIX_mipsr1.h b/libs/libopus/silk/fixed/mips/prefilter_FIX_mipsr1.h
deleted file mode 100644
index 21b256885..000000000
--- a/libs/libopus/silk/fixed/mips/prefilter_FIX_mipsr1.h
+++ /dev/null
@@ -1,184 +0,0 @@
-/***********************************************************************
-Copyright (c) 2006-2011, Skype Limited. All rights reserved.
-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.
-***********************************************************************/
-#ifndef __PREFILTER_FIX_MIPSR1_H__
-#define __PREFILTER_FIX_MIPSR1_H__
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "main_FIX.h"
-#include "stack_alloc.h"
-#include "tuning_parameters.h"
-
-#define OVERRIDE_silk_warped_LPC_analysis_filter_FIX
-void silk_warped_LPC_analysis_filter_FIX(
- opus_int32 state[], /* I/O State [order + 1] */
- opus_int32 res_Q2[], /* O Residual signal [length] */
- const opus_int16 coef_Q13[], /* I Coefficients [order] */
- const opus_int16 input[], /* I Input signal [length] */
- const opus_int16 lambda_Q16, /* I Warping factor */
- const opus_int length, /* I Length of input signal */
- const opus_int order, /* I Filter order (even) */
- int arch
-)
-{
- opus_int n, i;
- opus_int32 acc_Q11, acc_Q22, tmp1, tmp2, tmp3, tmp4;
- opus_int32 state_cur, state_next;
-
- (void)arch;
-
- /* Order must be even */
- /* Length must be even */
-
- silk_assert( ( order & 1 ) == 0 );
- silk_assert( ( length & 1 ) == 0 );
-
- for( n = 0; n < length; n+=2 ) {
- /* Output of lowpass section */
- tmp2 = silk_SMLAWB( state[ 0 ], state[ 1 ], lambda_Q16 );
- state_cur = silk_LSHIFT( input[ n ], 14 );
- /* Output of allpass section */
- tmp1 = silk_SMLAWB( state[ 1 ], state[ 2 ] - tmp2, lambda_Q16 );
- state_next = tmp2;
- acc_Q11 = silk_RSHIFT( order, 1 );
- acc_Q11 = silk_SMLAWB( acc_Q11, tmp2, coef_Q13[ 0 ] );
-
-
- /* Output of lowpass section */
- tmp4 = silk_SMLAWB( state_cur, state_next, lambda_Q16 );
- state[ 0 ] = silk_LSHIFT( input[ n+1 ], 14 );
- /* Output of allpass section */
- tmp3 = silk_SMLAWB( state_next, tmp1 - tmp4, lambda_Q16 );
- state[ 1 ] = tmp4;
- acc_Q22 = silk_RSHIFT( order, 1 );
- acc_Q22 = silk_SMLAWB( acc_Q22, tmp4, coef_Q13[ 0 ] );
-
- /* Loop over allpass sections */
- for( i = 2; i < order; i += 2 ) {
- /* Output of allpass section */
- tmp2 = silk_SMLAWB( state[ i ], state[ i + 1 ] - tmp1, lambda_Q16 );
- state_cur = tmp1;
- acc_Q11 = silk_SMLAWB( acc_Q11, tmp1, coef_Q13[ i - 1 ] );
- /* Output of allpass section */
- tmp1 = silk_SMLAWB( state[ i + 1 ], state[ i + 2 ] - tmp2, lambda_Q16 );
- state_next = tmp2;
- acc_Q11 = silk_SMLAWB( acc_Q11, tmp2, coef_Q13[ i ] );
-
-
- /* Output of allpass section */
- tmp4 = silk_SMLAWB( state_cur, state_next - tmp3, lambda_Q16 );
- state[ i ] = tmp3;
- acc_Q22 = silk_SMLAWB( acc_Q22, tmp3, coef_Q13[ i - 1 ] );
- /* Output of allpass section */
- tmp3 = silk_SMLAWB( state_next, tmp1 - tmp4, lambda_Q16 );
- state[ i + 1 ] = tmp4;
- acc_Q22 = silk_SMLAWB( acc_Q22, tmp4, coef_Q13[ i ] );
- }
- acc_Q11 = silk_SMLAWB( acc_Q11, tmp1, coef_Q13[ order - 1 ] );
- res_Q2[ n ] = silk_LSHIFT( (opus_int32)input[ n ], 2 ) - silk_RSHIFT_ROUND( acc_Q11, 9 );
-
- state[ order ] = tmp3;
- acc_Q22 = silk_SMLAWB( acc_Q22, tmp3, coef_Q13[ order - 1 ] );
- res_Q2[ n+1 ] = silk_LSHIFT( (opus_int32)input[ n+1 ], 2 ) - silk_RSHIFT_ROUND( acc_Q22, 9 );
- }
-}
-
-
-
-/* Prefilter for finding Quantizer input signal */
-#define OVERRIDE_silk_prefilt_FIX
-static inline void silk_prefilt_FIX(
- silk_prefilter_state_FIX *P, /* I/O state */
- opus_int32 st_res_Q12[], /* I short term residual signal */
- opus_int32 xw_Q3[], /* O prefiltered signal */
- opus_int32 HarmShapeFIRPacked_Q12, /* I Harmonic shaping coeficients */
- opus_int Tilt_Q14, /* I Tilt shaping coeficient */
- opus_int32 LF_shp_Q14, /* I Low-frequancy shaping coeficients */
- opus_int lag, /* I Lag for harmonic shaping */
- opus_int length /* I Length of signals */
-)
-{
- opus_int i, idx, LTP_shp_buf_idx;
- opus_int32 n_LTP_Q12, n_Tilt_Q10, n_LF_Q10;
- opus_int32 sLF_MA_shp_Q12, sLF_AR_shp_Q12;
- opus_int16 *LTP_shp_buf;
-
- /* To speed up use temp variables instead of using the struct */
- LTP_shp_buf = P->sLTP_shp;
- LTP_shp_buf_idx = P->sLTP_shp_buf_idx;
- sLF_AR_shp_Q12 = P->sLF_AR_shp_Q12;
- sLF_MA_shp_Q12 = P->sLF_MA_shp_Q12;
-
- if( lag > 0 ) {
- for( i = 0; i < length; i++ ) {
- /* unrolled loop */
- silk_assert( HARM_SHAPE_FIR_TAPS == 3 );
- idx = lag + LTP_shp_buf_idx;
- n_LTP_Q12 = silk_SMULBB( LTP_shp_buf[ ( idx - HARM_SHAPE_FIR_TAPS / 2 - 1) & LTP_MASK ], HarmShapeFIRPacked_Q12 );
- n_LTP_Q12 = silk_SMLABT( n_LTP_Q12, LTP_shp_buf[ ( idx - HARM_SHAPE_FIR_TAPS / 2 ) & LTP_MASK ], HarmShapeFIRPacked_Q12 );
- n_LTP_Q12 = silk_SMLABB( n_LTP_Q12, LTP_shp_buf[ ( idx - HARM_SHAPE_FIR_TAPS / 2 + 1) & LTP_MASK ], HarmShapeFIRPacked_Q12 );
-
- n_Tilt_Q10 = silk_SMULWB( sLF_AR_shp_Q12, Tilt_Q14 );
- n_LF_Q10 = silk_SMLAWB( silk_SMULWT( sLF_AR_shp_Q12, LF_shp_Q14 ), sLF_MA_shp_Q12, LF_shp_Q14 );
-
- sLF_AR_shp_Q12 = silk_SUB32( st_res_Q12[ i ], silk_LSHIFT( n_Tilt_Q10, 2 ) );
- sLF_MA_shp_Q12 = silk_SUB32( sLF_AR_shp_Q12, silk_LSHIFT( n_LF_Q10, 2 ) );
-
- LTP_shp_buf_idx = ( LTP_shp_buf_idx - 1 ) & LTP_MASK;
- LTP_shp_buf[ LTP_shp_buf_idx ] = (opus_int16)silk_SAT16( silk_RSHIFT_ROUND( sLF_MA_shp_Q12, 12 ) );
-
- xw_Q3[i] = silk_RSHIFT_ROUND( silk_SUB32( sLF_MA_shp_Q12, n_LTP_Q12 ), 9 );
- }
- }
- else
- {
- for( i = 0; i < length; i++ ) {
-
- n_LTP_Q12 = 0;
-
- n_Tilt_Q10 = silk_SMULWB( sLF_AR_shp_Q12, Tilt_Q14 );
- n_LF_Q10 = silk_SMLAWB( silk_SMULWT( sLF_AR_shp_Q12, LF_shp_Q14 ), sLF_MA_shp_Q12, LF_shp_Q14 );
-
- sLF_AR_shp_Q12 = silk_SUB32( st_res_Q12[ i ], silk_LSHIFT( n_Tilt_Q10, 2 ) );
- sLF_MA_shp_Q12 = silk_SUB32( sLF_AR_shp_Q12, silk_LSHIFT( n_LF_Q10, 2 ) );
-
- LTP_shp_buf_idx = ( LTP_shp_buf_idx - 1 ) & LTP_MASK;
- LTP_shp_buf[ LTP_shp_buf_idx ] = (opus_int16)silk_SAT16( silk_RSHIFT_ROUND( sLF_MA_shp_Q12, 12 ) );
-
- xw_Q3[i] = silk_RSHIFT_ROUND( sLF_MA_shp_Q12, 9 );
- }
- }
-
- /* Copy temp variable back to state */
- P->sLF_AR_shp_Q12 = sLF_AR_shp_Q12;
- P->sLF_MA_shp_Q12 = sLF_MA_shp_Q12;
- P->sLTP_shp_buf_idx = LTP_shp_buf_idx;
-}
-
-#endif /* __PREFILTER_FIX_MIPSR1_H__ */
diff --git a/libs/libopus/silk/fixed/mips/warped_autocorrelation_FIX_mipsr1.h b/libs/libopus/silk/fixed/mips/warped_autocorrelation_FIX_mipsr1.h
index e803ef0fc..66eb2ed26 100644
--- a/libs/libopus/silk/fixed/mips/warped_autocorrelation_FIX_mipsr1.h
+++ b/libs/libopus/silk/fixed/mips/warped_autocorrelation_FIX_mipsr1.h
@@ -41,8 +41,8 @@ POSSIBILITY OF SUCH DAMAGE.
#define QS 14
/* Autocorrelations for a warped frequency axis */
-#define OVERRIDE_silk_warped_autocorrelation_FIX
-void silk_warped_autocorrelation_FIX(
+#define OVERRIDE_silk_warped_autocorrelation_FIX_c
+void silk_warped_autocorrelation_FIX_c(
opus_int32 *corr, /* O Result [order + 1] */
opus_int *scale, /* O Scaling of the correlation vector */
const opus_int16 *input, /* I Input data to correlate */
diff --git a/libs/libopus/silk/fixed/noise_shape_analysis_FIX.c b/libs/libopus/silk/fixed/noise_shape_analysis_FIX.c
index 22a89f75a..85fea0bf0 100644
--- a/libs/libopus/silk/fixed/noise_shape_analysis_FIX.c
+++ b/libs/libopus/silk/fixed/noise_shape_analysis_FIX.c
@@ -57,88 +57,79 @@ static OPUS_INLINE opus_int32 warped_gain( /* gain in Q16*/
/* Convert warped filter coefficients to monic pseudo-warped coefficients and limit maximum */
/* amplitude of monic warped coefficients by using bandwidth expansion on the true coefficients */
static OPUS_INLINE void limit_warped_coefs(
- opus_int32 *coefs_syn_Q24,
- opus_int32 *coefs_ana_Q24,
+ opus_int32 *coefs_Q24,
opus_int lambda_Q16,
opus_int32 limit_Q24,
opus_int order
) {
opus_int i, iter, ind = 0;
- opus_int32 tmp, maxabs_Q24, chirp_Q16, gain_syn_Q16, gain_ana_Q16;
+ opus_int32 tmp, maxabs_Q24, chirp_Q16, gain_Q16;
opus_int32 nom_Q16, den_Q24;
+ opus_int32 limit_Q20, maxabs_Q20;
/* Convert to monic coefficients */
lambda_Q16 = -lambda_Q16;
for( i = order - 1; i > 0; i-- ) {
- coefs_syn_Q24[ i - 1 ] = silk_SMLAWB( coefs_syn_Q24[ i - 1 ], coefs_syn_Q24[ i ], lambda_Q16 );
- coefs_ana_Q24[ i - 1 ] = silk_SMLAWB( coefs_ana_Q24[ i - 1 ], coefs_ana_Q24[ i ], lambda_Q16 );
+ coefs_Q24[ i - 1 ] = silk_SMLAWB( coefs_Q24[ i - 1 ], coefs_Q24[ i ], lambda_Q16 );
}
lambda_Q16 = -lambda_Q16;
- nom_Q16 = silk_SMLAWB( SILK_FIX_CONST( 1.0, 16 ), -(opus_int32)lambda_Q16, lambda_Q16 );
- den_Q24 = silk_SMLAWB( SILK_FIX_CONST( 1.0, 24 ), coefs_syn_Q24[ 0 ], lambda_Q16 );
- gain_syn_Q16 = silk_DIV32_varQ( nom_Q16, den_Q24, 24 );
- den_Q24 = silk_SMLAWB( SILK_FIX_CONST( 1.0, 24 ), coefs_ana_Q24[ 0 ], lambda_Q16 );
- gain_ana_Q16 = silk_DIV32_varQ( nom_Q16, den_Q24, 24 );
+ nom_Q16 = silk_SMLAWB( SILK_FIX_CONST( 1.0, 16 ), -(opus_int32)lambda_Q16, lambda_Q16 );
+ den_Q24 = silk_SMLAWB( SILK_FIX_CONST( 1.0, 24 ), coefs_Q24[ 0 ], lambda_Q16 );
+ gain_Q16 = silk_DIV32_varQ( nom_Q16, den_Q24, 24 );
for( i = 0; i < order; i++ ) {
- coefs_syn_Q24[ i ] = silk_SMULWW( gain_syn_Q16, coefs_syn_Q24[ i ] );
- coefs_ana_Q24[ i ] = silk_SMULWW( gain_ana_Q16, coefs_ana_Q24[ i ] );
+ coefs_Q24[ i ] = silk_SMULWW( gain_Q16, coefs_Q24[ i ] );
}
-
+ limit_Q20 = silk_RSHIFT(limit_Q24, 4);
for( iter = 0; iter < 10; iter++ ) {
/* Find maximum absolute value */
maxabs_Q24 = -1;
for( i = 0; i < order; i++ ) {
- tmp = silk_max( silk_abs_int32( coefs_syn_Q24[ i ] ), silk_abs_int32( coefs_ana_Q24[ i ] ) );
+ tmp = silk_abs_int32( coefs_Q24[ i ] );
if( tmp > maxabs_Q24 ) {
maxabs_Q24 = tmp;
ind = i;
}
}
- if( maxabs_Q24 <= limit_Q24 ) {
+ /* Use Q20 to avoid any overflow when multiplying by (ind + 1) later. */
+ maxabs_Q20 = silk_RSHIFT(maxabs_Q24, 4);
+ if( maxabs_Q20 <= limit_Q20 ) {
/* Coefficients are within range - done */
return;
}
/* Convert back to true warped coefficients */
for( i = 1; i < order; i++ ) {
- coefs_syn_Q24[ i - 1 ] = silk_SMLAWB( coefs_syn_Q24[ i - 1 ], coefs_syn_Q24[ i ], lambda_Q16 );
- coefs_ana_Q24[ i - 1 ] = silk_SMLAWB( coefs_ana_Q24[ i - 1 ], coefs_ana_Q24[ i ], lambda_Q16 );
+ coefs_Q24[ i - 1 ] = silk_SMLAWB( coefs_Q24[ i - 1 ], coefs_Q24[ i ], lambda_Q16 );
}
- gain_syn_Q16 = silk_INVERSE32_varQ( gain_syn_Q16, 32 );
- gain_ana_Q16 = silk_INVERSE32_varQ( gain_ana_Q16, 32 );
+ gain_Q16 = silk_INVERSE32_varQ( gain_Q16, 32 );
for( i = 0; i < order; i++ ) {
- coefs_syn_Q24[ i ] = silk_SMULWW( gain_syn_Q16, coefs_syn_Q24[ i ] );
- coefs_ana_Q24[ i ] = silk_SMULWW( gain_ana_Q16, coefs_ana_Q24[ i ] );
+ coefs_Q24[ i ] = silk_SMULWW( gain_Q16, coefs_Q24[ i ] );
}
/* Apply bandwidth expansion */
chirp_Q16 = SILK_FIX_CONST( 0.99, 16 ) - silk_DIV32_varQ(
- silk_SMULWB( maxabs_Q24 - limit_Q24, silk_SMLABB( SILK_FIX_CONST( 0.8, 10 ), SILK_FIX_CONST( 0.1, 10 ), iter ) ),
- silk_MUL( maxabs_Q24, ind + 1 ), 22 );
- silk_bwexpander_32( coefs_syn_Q24, order, chirp_Q16 );
- silk_bwexpander_32( coefs_ana_Q24, order, chirp_Q16 );
+ silk_SMULWB( maxabs_Q20 - limit_Q20, silk_SMLABB( SILK_FIX_CONST( 0.8, 10 ), SILK_FIX_CONST( 0.1, 10 ), iter ) ),
+ silk_MUL( maxabs_Q20, ind + 1 ), 22 );
+ silk_bwexpander_32( coefs_Q24, order, chirp_Q16 );
/* Convert to monic warped coefficients */
lambda_Q16 = -lambda_Q16;
for( i = order - 1; i > 0; i-- ) {
- coefs_syn_Q24[ i - 1 ] = silk_SMLAWB( coefs_syn_Q24[ i - 1 ], coefs_syn_Q24[ i ], lambda_Q16 );
- coefs_ana_Q24[ i - 1 ] = silk_SMLAWB( coefs_ana_Q24[ i - 1 ], coefs_ana_Q24[ i ], lambda_Q16 );
+ coefs_Q24[ i - 1 ] = silk_SMLAWB( coefs_Q24[ i - 1 ], coefs_Q24[ i ], lambda_Q16 );
}
lambda_Q16 = -lambda_Q16;
nom_Q16 = silk_SMLAWB( SILK_FIX_CONST( 1.0, 16 ), -(opus_int32)lambda_Q16, lambda_Q16 );
- den_Q24 = silk_SMLAWB( SILK_FIX_CONST( 1.0, 24 ), coefs_syn_Q24[ 0 ], lambda_Q16 );
- gain_syn_Q16 = silk_DIV32_varQ( nom_Q16, den_Q24, 24 );
- den_Q24 = silk_SMLAWB( SILK_FIX_CONST( 1.0, 24 ), coefs_ana_Q24[ 0 ], lambda_Q16 );
- gain_ana_Q16 = silk_DIV32_varQ( nom_Q16, den_Q24, 24 );
+ den_Q24 = silk_SMLAWB( SILK_FIX_CONST( 1.0, 24 ), coefs_Q24[ 0 ], lambda_Q16 );
+ gain_Q16 = silk_DIV32_varQ( nom_Q16, den_Q24, 24 );
for( i = 0; i < order; i++ ) {
- coefs_syn_Q24[ i ] = silk_SMULWW( gain_syn_Q16, coefs_syn_Q24[ i ] );
- coefs_ana_Q24[ i ] = silk_SMULWW( gain_ana_Q16, coefs_ana_Q24[ i ] );
+ coefs_Q24[ i ] = silk_SMULWW( gain_Q16, coefs_Q24[ i ] );
}
}
silk_assert( 0 );
}
-#if defined(MIPSr1_ASM)
+/* Disable MIPS version until it's updated. */
+#if 0 && defined(MIPSr1_ASM)
#include "mips/noise_shape_analysis_FIX_mipsr1.h"
#endif
@@ -155,14 +146,13 @@ void silk_noise_shape_analysis_FIX(
)
{
silk_shape_state_FIX *psShapeSt = &psEnc->sShape;
- opus_int k, i, nSamples, Qnrg, b_Q14, warping_Q16, scale = 0;
- opus_int32 SNR_adj_dB_Q7, HarmBoost_Q16, HarmShapeGain_Q16, Tilt_Q16, tmp32;
- opus_int32 nrg, pre_nrg_Q30, log_energy_Q7, log_energy_prev_Q7, energy_variation_Q7;
- opus_int32 delta_Q16, BWExp1_Q16, BWExp2_Q16, gain_mult_Q16, gain_add_Q16, strength_Q16, b_Q8;
+ opus_int k, i, nSamples, nSegs, Qnrg, b_Q14, warping_Q16, scale = 0;
+ opus_int32 SNR_adj_dB_Q7, HarmShapeGain_Q16, Tilt_Q16, tmp32;
+ opus_int32 nrg, log_energy_Q7, log_energy_prev_Q7, energy_variation_Q7;
+ opus_int32 BWExp_Q16, gain_mult_Q16, gain_add_Q16, strength_Q16, b_Q8;
opus_int32 auto_corr[ MAX_SHAPE_LPC_ORDER + 1 ];
opus_int32 refl_coef_Q16[ MAX_SHAPE_LPC_ORDER ];
- opus_int32 AR1_Q24[ MAX_SHAPE_LPC_ORDER ];
- opus_int32 AR2_Q24[ MAX_SHAPE_LPC_ORDER ];
+ opus_int32 AR_Q24[ MAX_SHAPE_LPC_ORDER ];
VARDECL( opus_int16, x_windowed );
const opus_int16 *x_ptr, *pitch_res_ptr;
SAVE_STACK;
@@ -209,14 +199,14 @@ void silk_noise_shape_analysis_FIX(
if( psEnc->sCmn.indices.signalType == TYPE_VOICED ) {
/* Initially set to 0; may be overruled in process_gains(..) */
psEnc->sCmn.indices.quantOffsetType = 0;
- psEncCtrl->sparseness_Q8 = 0;
} else {
/* Sparseness measure, based on relative fluctuations of energy per 2 milliseconds */
nSamples = silk_LSHIFT( psEnc->sCmn.fs_kHz, 1 );
energy_variation_Q7 = 0;
log_energy_prev_Q7 = 0;
pitch_res_ptr = pitch_res;
- for( k = 0; k < silk_SMULBB( SUB_FRAME_LENGTH_MS, psEnc->sCmn.nb_subfr ) / 2; k++ ) {
+ nSegs = silk_SMULBB( SUB_FRAME_LENGTH_MS, psEnc->sCmn.nb_subfr ) / 2;
+ for( k = 0; k < nSegs; k++ ) {
silk_sum_sqr_shift( &nrg, &scale, pitch_res_ptr, nSamples );
nrg += silk_RSHIFT( nSamples, scale ); /* Q(-scale)*/
@@ -228,18 +218,12 @@ void silk_noise_shape_analysis_FIX(
pitch_res_ptr += nSamples;
}
- psEncCtrl->sparseness_Q8 = silk_RSHIFT( silk_sigm_Q15( silk_SMULWB( energy_variation_Q7 -
- SILK_FIX_CONST( 5.0, 7 ), SILK_FIX_CONST( 0.1, 16 ) ) ), 7 );
-
/* Set quantization offset depending on sparseness measure */
- if( psEncCtrl->sparseness_Q8 > SILK_FIX_CONST( SPARSENESS_THRESHOLD_QNT_OFFSET, 8 ) ) {
+ if( energy_variation_Q7 > SILK_FIX_CONST( ENERGY_VARIATION_THRESHOLD_QNT_OFFSET, 7 ) * (nSegs-1) ) {
psEnc->sCmn.indices.quantOffsetType = 0;
} else {
psEnc->sCmn.indices.quantOffsetType = 1;
}
-
- /* Increase coding SNR for sparse signals */
- SNR_adj_dB_Q7 = silk_SMLAWB( SNR_adj_dB_Q7, SILK_FIX_CONST( SPARSE_SNR_INCR_dB, 15 ), psEncCtrl->sparseness_Q8 - SILK_FIX_CONST( 0.5, 8 ) );
}
/*******************************/
@@ -247,14 +231,8 @@ void silk_noise_shape_analysis_FIX(
/*******************************/
/* More BWE for signals with high prediction gain */
strength_Q16 = silk_SMULWB( psEncCtrl->predGain_Q16, SILK_FIX_CONST( FIND_PITCH_WHITE_NOISE_FRACTION, 16 ) );
- BWExp1_Q16 = BWExp2_Q16 = silk_DIV32_varQ( SILK_FIX_CONST( BANDWIDTH_EXPANSION, 16 ),
+ BWExp_Q16 = silk_DIV32_varQ( SILK_FIX_CONST( BANDWIDTH_EXPANSION, 16 ),
silk_SMLAWW( SILK_FIX_CONST( 1.0, 16 ), strength_Q16, strength_Q16 ), 16 );
- delta_Q16 = silk_SMULWB( SILK_FIX_CONST( 1.0, 16 ) - silk_SMULBB( 3, psEncCtrl->coding_quality_Q14 ),
- SILK_FIX_CONST( LOW_RATE_BANDWIDTH_EXPANSION_DELTA, 16 ) );
- BWExp1_Q16 = silk_SUB32( BWExp1_Q16, delta_Q16 );
- BWExp2_Q16 = silk_ADD32( BWExp2_Q16, delta_Q16 );
- /* BWExp1 will be applied after BWExp2, so make it relative */
- BWExp1_Q16 = silk_DIV32_16( silk_LSHIFT( BWExp1_Q16, 14 ), silk_RSHIFT( BWExp2_Q16, 2 ) );
if( psEnc->sCmn.warping_Q16 > 0 ) {
/* Slightly more warping in analysis will move quantization noise up in frequency, where it's better masked */
@@ -284,7 +262,7 @@ void silk_noise_shape_analysis_FIX(
if( psEnc->sCmn.warping_Q16 > 0 ) {
/* Calculate warped auto correlation */
- silk_warped_autocorrelation_FIX( auto_corr, &scale, x_windowed, warping_Q16, psEnc->sCmn.shapeWinLength, psEnc->sCmn.shapingLPCOrder );
+ silk_warped_autocorrelation_FIX( auto_corr, &scale, x_windowed, warping_Q16, psEnc->sCmn.shapeWinLength, psEnc->sCmn.shapingLPCOrder, arch );
} else {
/* Calculate regular auto correlation */
silk_autocorr( auto_corr, &scale, x_windowed, psEnc->sCmn.shapeWinLength, psEnc->sCmn.shapingLPCOrder + 1, arch );
@@ -299,7 +277,7 @@ void silk_noise_shape_analysis_FIX(
silk_assert( nrg >= 0 );
/* Convert reflection coefficients to prediction coefficients */
- silk_k2a_Q16( AR2_Q24, refl_coef_Q16, psEnc->sCmn.shapingLPCOrder );
+ silk_k2a_Q16( AR_Q24, refl_coef_Q16, psEnc->sCmn.shapingLPCOrder );
Qnrg = -scale; /* range: -12...30*/
silk_assert( Qnrg >= -12 );
@@ -318,40 +296,34 @@ void silk_noise_shape_analysis_FIX(
if( psEnc->sCmn.warping_Q16 > 0 ) {
/* Adjust gain for warping */
- gain_mult_Q16 = warped_gain( AR2_Q24, warping_Q16, psEnc->sCmn.shapingLPCOrder );
- silk_assert( psEncCtrl->Gains_Q16[ k ] >= 0 );
- if ( silk_SMULWW( silk_RSHIFT_ROUND( psEncCtrl->Gains_Q16[ k ], 1 ), gain_mult_Q16 ) >= ( silk_int32_MAX >> 1 ) ) {
- psEncCtrl->Gains_Q16[ k ] = silk_int32_MAX;
+ gain_mult_Q16 = warped_gain( AR_Q24, warping_Q16, psEnc->sCmn.shapingLPCOrder );
+ silk_assert( psEncCtrl->Gains_Q16[ k ] > 0 );
+ if( psEncCtrl->Gains_Q16[ k ] < SILK_FIX_CONST( 0.25, 16 ) ) {
+ psEncCtrl->Gains_Q16[ k ] = silk_SMULWW( psEncCtrl->Gains_Q16[ k ], gain_mult_Q16 );
} else {
- psEncCtrl->Gains_Q16[ k ] = silk_SMULWW( psEncCtrl->Gains_Q16[ k ], gain_mult_Q16 );
+ psEncCtrl->Gains_Q16[ k ] = silk_SMULWW( silk_RSHIFT_ROUND( psEncCtrl->Gains_Q16[ k ], 1 ), gain_mult_Q16 );
+ if ( psEncCtrl->Gains_Q16[ k ] >= ( silk_int32_MAX >> 1 ) ) {
+ psEncCtrl->Gains_Q16[ k ] = silk_int32_MAX;
+ } else {
+ psEncCtrl->Gains_Q16[ k ] = silk_LSHIFT32( psEncCtrl->Gains_Q16[ k ], 1 );
+ }
}
+ silk_assert( psEncCtrl->Gains_Q16[ k ] > 0 );
}
- /* Bandwidth expansion for synthesis filter shaping */
- silk_bwexpander_32( AR2_Q24, psEnc->sCmn.shapingLPCOrder, BWExp2_Q16 );
-
- /* Compute noise shaping filter coefficients */
- silk_memcpy( AR1_Q24, AR2_Q24, psEnc->sCmn.shapingLPCOrder * sizeof( opus_int32 ) );
-
- /* Bandwidth expansion for analysis filter shaping */
- silk_assert( BWExp1_Q16 <= SILK_FIX_CONST( 1.0, 16 ) );
- silk_bwexpander_32( AR1_Q24, psEnc->sCmn.shapingLPCOrder, BWExp1_Q16 );
-
- /* Ratio of prediction gains, in energy domain */
- pre_nrg_Q30 = silk_LPC_inverse_pred_gain_Q24( AR2_Q24, psEnc->sCmn.shapingLPCOrder );
- nrg = silk_LPC_inverse_pred_gain_Q24( AR1_Q24, psEnc->sCmn.shapingLPCOrder );
-
- /*psEncCtrl->GainsPre[ k ] = 1.0f - 0.7f * ( 1.0f - pre_nrg / nrg ) = 0.3f + 0.7f * pre_nrg / nrg;*/
- pre_nrg_Q30 = silk_LSHIFT32( silk_SMULWB( pre_nrg_Q30, SILK_FIX_CONST( 0.7, 15 ) ), 1 );
- psEncCtrl->GainsPre_Q14[ k ] = ( opus_int ) SILK_FIX_CONST( 0.3, 14 ) + silk_DIV32_varQ( pre_nrg_Q30, nrg, 14 );
+ /* Bandwidth expansion */
+ silk_bwexpander_32( AR_Q24, psEnc->sCmn.shapingLPCOrder, BWExp_Q16 );
- /* Convert to monic warped prediction coefficients and limit absolute values */
- limit_warped_coefs( AR2_Q24, AR1_Q24, warping_Q16, SILK_FIX_CONST( 3.999, 24 ), psEnc->sCmn.shapingLPCOrder );
+ if( psEnc->sCmn.warping_Q16 > 0 ) {
+ /* Convert to monic warped prediction coefficients and limit absolute values */
+ limit_warped_coefs( AR_Q24, warping_Q16, SILK_FIX_CONST( 3.999, 24 ), psEnc->sCmn.shapingLPCOrder );
- /* Convert from Q24 to Q13 and store in int16 */
- for( i = 0; i < psEnc->sCmn.shapingLPCOrder; i++ ) {
- psEncCtrl->AR1_Q13[ k * MAX_SHAPE_LPC_ORDER + i ] = (opus_int16)silk_SAT16( silk_RSHIFT_ROUND( AR1_Q24[ i ], 11 ) );
- psEncCtrl->AR2_Q13[ k * MAX_SHAPE_LPC_ORDER + i ] = (opus_int16)silk_SAT16( silk_RSHIFT_ROUND( AR2_Q24[ i ], 11 ) );
+ /* Convert from Q24 to Q13 and store in int16 */
+ for( i = 0; i < psEnc->sCmn.shapingLPCOrder; i++ ) {
+ psEncCtrl->AR_Q13[ k * MAX_SHAPE_LPC_ORDER + i ] = (opus_int16)silk_SAT16( silk_RSHIFT_ROUND( AR_Q24[ i ], 11 ) );
+ }
+ } else {
+ silk_LPC_fit( &psEncCtrl->AR_Q13[ k * MAX_SHAPE_LPC_ORDER ], AR_Q24, 13, 24, psEnc->sCmn.shapingLPCOrder );
}
}
@@ -368,11 +340,6 @@ void silk_noise_shape_analysis_FIX(
psEncCtrl->Gains_Q16[ k ] = silk_ADD_POS_SAT32( psEncCtrl->Gains_Q16[ k ], gain_add_Q16 );
}
- gain_mult_Q16 = SILK_FIX_CONST( 1.0, 16 ) + silk_RSHIFT_ROUND( silk_MLA( SILK_FIX_CONST( INPUT_TILT, 26 ),
- psEncCtrl->coding_quality_Q14, SILK_FIX_CONST( HIGH_RATE_INPUT_TILT, 12 ) ), 10 );
- for( k = 0; k < psEnc->sCmn.nb_subfr; k++ ) {
- psEncCtrl->GainsPre_Q14[ k ] = silk_SMULWB( gain_mult_Q16, psEncCtrl->GainsPre_Q14[ k ] );
- }
/************************************************/
/* Control low-frequency shaping and noise tilt */
@@ -410,14 +377,6 @@ void silk_noise_shape_analysis_FIX(
/****************************/
/* HARMONIC SHAPING CONTROL */
/****************************/
- /* Control boosting of harmonic frequencies */
- HarmBoost_Q16 = silk_SMULWB( silk_SMULWB( SILK_FIX_CONST( 1.0, 17 ) - silk_LSHIFT( psEncCtrl->coding_quality_Q14, 3 ),
- psEnc->LTPCorr_Q15 ), SILK_FIX_CONST( LOW_RATE_HARMONIC_BOOST, 16 ) );
-
- /* More harmonic boost for noisy input signals */
- HarmBoost_Q16 = silk_SMLAWB( HarmBoost_Q16,
- SILK_FIX_CONST( 1.0, 16 ) - silk_LSHIFT( psEncCtrl->input_quality_Q14, 2 ), SILK_FIX_CONST( LOW_INPUT_QUALITY_HARMONIC_BOOST, 16 ) );
-
if( USE_HARM_SHAPING && psEnc->sCmn.indices.signalType == TYPE_VOICED ) {
/* More harmonic noise shaping for high bitrates or noisy input */
HarmShapeGain_Q16 = silk_SMLAWB( SILK_FIX_CONST( HARMONIC_SHAPING, 16 ),
@@ -435,14 +394,11 @@ void silk_noise_shape_analysis_FIX(
/* Smooth over subframes */
/*************************/
for( k = 0; k < MAX_NB_SUBFR; k++ ) {
- psShapeSt->HarmBoost_smth_Q16 =
- silk_SMLAWB( psShapeSt->HarmBoost_smth_Q16, HarmBoost_Q16 - psShapeSt->HarmBoost_smth_Q16, SILK_FIX_CONST( SUBFR_SMTH_COEF, 16 ) );
psShapeSt->HarmShapeGain_smth_Q16 =
silk_SMLAWB( psShapeSt->HarmShapeGain_smth_Q16, HarmShapeGain_Q16 - psShapeSt->HarmShapeGain_smth_Q16, SILK_FIX_CONST( SUBFR_SMTH_COEF, 16 ) );
psShapeSt->Tilt_smth_Q16 =
silk_SMLAWB( psShapeSt->Tilt_smth_Q16, Tilt_Q16 - psShapeSt->Tilt_smth_Q16, SILK_FIX_CONST( SUBFR_SMTH_COEF, 16 ) );
- psEncCtrl->HarmBoost_Q14[ k ] = ( opus_int )silk_RSHIFT_ROUND( psShapeSt->HarmBoost_smth_Q16, 2 );
psEncCtrl->HarmShapeGain_Q14[ k ] = ( opus_int )silk_RSHIFT_ROUND( psShapeSt->HarmShapeGain_smth_Q16, 2 );
psEncCtrl->Tilt_Q14[ k ] = ( opus_int )silk_RSHIFT_ROUND( psShapeSt->Tilt_smth_Q16, 2 );
}
diff --git a/libs/libopus/silk/fixed/pitch_analysis_core_FIX.c b/libs/libopus/silk/fixed/pitch_analysis_core_FIX.c
index 01bb9fc0a..14729046d 100644
--- a/libs/libopus/silk/fixed/pitch_analysis_core_FIX.c
+++ b/libs/libopus/silk/fixed/pitch_analysis_core_FIX.c
@@ -80,7 +80,7 @@ static void silk_P_Ana_calc_energy_st3(
/* FIXED POINT CORE PITCH ANALYSIS FUNCTION */
/*************************************************************/
opus_int silk_pitch_analysis_core( /* O Voicing estimate: 0 voiced, 1 unvoiced */
- const opus_int16 *frame, /* I Signal of length PE_FRAME_LENGTH_MS*Fs_kHz */
+ const opus_int16 *frame_unscaled, /* I Signal of length PE_FRAME_LENGTH_MS*Fs_kHz */
opus_int *pitch_out, /* O 4 pitch lag values */
opus_int16 *lagIndex, /* O Lag Index */
opus_int8 *contourIndex, /* O Pitch contour Index */
@@ -94,16 +94,17 @@ opus_int silk_pitch_analysis_core( /* O Voicing estimate: 0
int arch /* I Run-time architecture */
)
{
- VARDECL( opus_int16, frame_8kHz );
+ VARDECL( opus_int16, frame_8kHz_buf );
VARDECL( opus_int16, frame_4kHz );
+ VARDECL( opus_int16, frame_scaled );
opus_int32 filt_state[ 6 ];
- const opus_int16 *input_frame_ptr;
+ const opus_int16 *frame, *frame_8kHz;
opus_int i, k, d, j;
VARDECL( opus_int16, C );
VARDECL( opus_int32, xcorr32 );
const opus_int16 *target_ptr, *basis_ptr;
- opus_int32 cross_corr, normalizer, energy, shift, energy_basis, energy_target;
- opus_int d_srch[ PE_D_SRCH_LENGTH ], Cmax, length_d_srch, length_d_comp;
+ opus_int32 cross_corr, normalizer, energy, energy_basis, energy_target;
+ opus_int d_srch[ PE_D_SRCH_LENGTH ], Cmax, length_d_srch, length_d_comp, shift;
VARDECL( opus_int16, d_comp );
opus_int32 sum, threshold, lag_counter;
opus_int CBimax, CBimax_new, CBimax_old, lag, start_lag, end_lag, lag_new;
@@ -119,12 +120,13 @@ opus_int silk_pitch_analysis_core( /* O Voicing estimate: 0
opus_int32 delta_lag_log2_sqr_Q7, lag_log2_Q7, prevLag_log2_Q7, prev_lag_bias_Q13;
const opus_int8 *Lag_CB_ptr;
SAVE_STACK;
+
/* Check for valid sampling frequency */
- silk_assert( Fs_kHz == 8 || Fs_kHz == 12 || Fs_kHz == 16 );
+ celt_assert( Fs_kHz == 8 || Fs_kHz == 12 || Fs_kHz == 16 );
/* Check for valid complexity setting */
- silk_assert( complexity >= SILK_PE_MIN_COMPLEX );
- silk_assert( complexity <= SILK_PE_MAX_COMPLEX );
+ celt_assert( complexity >= SILK_PE_MIN_COMPLEX );
+ celt_assert( complexity <= SILK_PE_MAX_COMPLEX );
silk_assert( search_thres1_Q16 >= 0 && search_thres1_Q16 <= (1<<16) );
silk_assert( search_thres2_Q13 >= 0 && search_thres2_Q13 <= (1<<13) );
@@ -137,17 +139,33 @@ opus_int silk_pitch_analysis_core( /* O Voicing estimate: 0
min_lag = PE_MIN_LAG_MS * Fs_kHz;
max_lag = PE_MAX_LAG_MS * Fs_kHz - 1;
+ /* Downscale input if necessary */
+ silk_sum_sqr_shift( &energy, &shift, frame_unscaled, frame_length );
+ shift += 3 - silk_CLZ32( energy ); /* at least two bits headroom */
+ ALLOC( frame_scaled, frame_length, opus_int16 );
+ if( shift > 0 ) {
+ shift = silk_RSHIFT( shift + 1, 1 );
+ for( i = 0; i < frame_length; i++ ) {
+ frame_scaled[ i ] = silk_RSHIFT( frame_unscaled[ i ], shift );
+ }
+ frame = frame_scaled;
+ } else {
+ frame = frame_unscaled;
+ }
+
+ ALLOC( frame_8kHz_buf, ( Fs_kHz == 8 ) ? 1 : frame_length_8kHz, opus_int16 );
/* Resample from input sampled at Fs_kHz to 8 kHz */
- ALLOC( frame_8kHz, frame_length_8kHz, opus_int16 );
if( Fs_kHz == 16 ) {
silk_memset( filt_state, 0, 2 * sizeof( opus_int32 ) );
- silk_resampler_down2( filt_state, frame_8kHz, frame, frame_length );
+ silk_resampler_down2( filt_state, frame_8kHz_buf, frame, frame_length );
+ frame_8kHz = frame_8kHz_buf;
} else if( Fs_kHz == 12 ) {
silk_memset( filt_state, 0, 6 * sizeof( opus_int32 ) );
- silk_resampler_down2_3( filt_state, frame_8kHz, frame, frame_length );
+ silk_resampler_down2_3( filt_state, frame_8kHz_buf, frame, frame_length );
+ frame_8kHz = frame_8kHz_buf;
} else {
- silk_assert( Fs_kHz == 8 );
- silk_memcpy( frame_8kHz, frame, frame_length_8kHz * sizeof(opus_int16) );
+ celt_assert( Fs_kHz == 8 );
+ frame_8kHz = frame;
}
/* Decimate again to 4 kHz */
@@ -160,19 +178,6 @@ opus_int silk_pitch_analysis_core( /* O Voicing estimate: 0
frame_4kHz[ i ] = silk_ADD_SAT16( frame_4kHz[ i ], frame_4kHz[ i - 1 ] );
}
- /*******************************************************************************
- ** Scale 4 kHz signal down to prevent correlations measures from overflowing
- ** find scaling as max scaling for each 8kHz(?) subframe
- *******************************************************************************/
-
- /* Inner product is calculated with different lengths, so scale for the worst case */
- silk_sum_sqr_shift( &energy, &shift, frame_4kHz, frame_length_4kHz );
- if( shift > 0 ) {
- shift = silk_RSHIFT( shift, 1 );
- for( i = 0; i < frame_length_4kHz; i++ ) {
- frame_4kHz[ i ] = silk_RSHIFT( frame_4kHz[ i ], shift );
- }
- }
/******************************************************************************
* FIRST STAGE, operating in 4 khz
@@ -183,14 +188,14 @@ opus_int silk_pitch_analysis_core( /* O Voicing estimate: 0
target_ptr = &frame_4kHz[ silk_LSHIFT( SF_LENGTH_4KHZ, 2 ) ];
for( k = 0; k < nb_subfr >> 1; k++ ) {
/* Check that we are within range of the array */
- silk_assert( target_ptr >= frame_4kHz );
- silk_assert( target_ptr + SF_LENGTH_8KHZ <= frame_4kHz + frame_length_4kHz );
+ celt_assert( target_ptr >= frame_4kHz );
+ celt_assert( target_ptr + SF_LENGTH_8KHZ <= frame_4kHz + frame_length_4kHz );
basis_ptr = target_ptr - MIN_LAG_4KHZ;
/* Check that we are within range of the array */
- silk_assert( basis_ptr >= frame_4kHz );
- silk_assert( basis_ptr + SF_LENGTH_8KHZ <= frame_4kHz + frame_length_4kHz );
+ celt_assert( basis_ptr >= frame_4kHz );
+ celt_assert( basis_ptr + SF_LENGTH_8KHZ <= frame_4kHz + frame_length_4kHz );
celt_pitch_xcorr( target_ptr, target_ptr - MAX_LAG_4KHZ, xcorr32, SF_LENGTH_8KHZ, MAX_LAG_4KHZ - MIN_LAG_4KHZ + 1, arch );
@@ -244,7 +249,7 @@ opus_int silk_pitch_analysis_core( /* O Voicing estimate: 0
/* Sort */
length_d_srch = silk_ADD_LSHIFT32( 4, complexity, 1 );
- silk_assert( 3 * length_d_srch <= PE_D_SRCH_LENGTH );
+ celt_assert( 3 * length_d_srch <= PE_D_SRCH_LENGTH );
silk_insertion_sort_decreasing_int16( C, d_srch, CSTRIDE_4KHZ,
length_d_srch );
@@ -269,7 +274,7 @@ opus_int silk_pitch_analysis_core( /* O Voicing estimate: 0
break;
}
}
- silk_assert( length_d_srch > 0 );
+ celt_assert( length_d_srch > 0 );
ALLOC( d_comp, D_COMP_STRIDE, opus_int16 );
for( i = D_COMP_MIN; i < D_COMP_MAX; i++ ) {
@@ -311,18 +316,6 @@ opus_int silk_pitch_analysis_core( /* O Voicing estimate: 0
** SECOND STAGE, operating at 8 kHz, on lag sections with high correlation
*************************************************************************************/
- /******************************************************************************
- ** Scale signal down to avoid correlations measures from overflowing
- *******************************************************************************/
- /* find scaling as max scaling for each subframe */
- silk_sum_sqr_shift( &energy, &shift, frame_8kHz, frame_length_8kHz );
- if( shift > 0 ) {
- shift = silk_RSHIFT( shift, 1 );
- for( i = 0; i < frame_length_8kHz; i++ ) {
- frame_8kHz[ i ] = silk_RSHIFT( frame_8kHz[ i ], shift );
- }
- }
-
/*********************************************************************************
* Find energy of each subframe projected onto its history, for a range of delays
*********************************************************************************/
@@ -332,8 +325,8 @@ opus_int silk_pitch_analysis_core( /* O Voicing estimate: 0
for( k = 0; k < nb_subfr; k++ ) {
/* Check that we are within range of the array */
- silk_assert( target_ptr >= frame_8kHz );
- silk_assert( target_ptr + SF_LENGTH_8KHZ <= frame_8kHz + frame_length_8kHz );
+ celt_assert( target_ptr >= frame_8kHz );
+ celt_assert( target_ptr + SF_LENGTH_8KHZ <= frame_8kHz + frame_length_8kHz );
energy_target = silk_ADD32( silk_inner_prod_aligned( target_ptr, target_ptr, SF_LENGTH_8KHZ, arch ), 1 );
for( j = 0; j < length_d_comp; j++ ) {
@@ -462,24 +455,6 @@ opus_int silk_pitch_analysis_core( /* O Voicing estimate: 0
silk_assert( *LTPCorr_Q15 >= 0 );
if( Fs_kHz > 8 ) {
- VARDECL( opus_int16, scratch_mem );
- /***************************************************************************/
- /* Scale input signal down to avoid correlations measures from overflowing */
- /***************************************************************************/
- /* find scaling as max scaling for each subframe */
- silk_sum_sqr_shift( &energy, &shift, frame, frame_length );
- ALLOC( scratch_mem, shift > 0 ? frame_length : ALLOC_NONE, opus_int16 );
- if( shift > 0 ) {
- /* Move signal to scratch mem because the input signal should be unchanged */
- shift = silk_RSHIFT( shift, 1 );
- for( i = 0; i < frame_length; i++ ) {
- scratch_mem[ i ] = silk_RSHIFT( frame[ i ], shift );
- }
- input_frame_ptr = scratch_mem;
- } else {
- input_frame_ptr = frame;
- }
-
/* Search in original signal */
CBimax_old = CBimax;
@@ -519,14 +494,14 @@ opus_int silk_pitch_analysis_core( /* O Voicing estimate: 0
/* Calculate the correlations and energies needed in stage 3 */
ALLOC( energies_st3, nb_subfr * nb_cbk_search, silk_pe_stage3_vals );
ALLOC( cross_corr_st3, nb_subfr * nb_cbk_search, silk_pe_stage3_vals );
- silk_P_Ana_calc_corr_st3( cross_corr_st3, input_frame_ptr, start_lag, sf_length, nb_subfr, complexity, arch );
- silk_P_Ana_calc_energy_st3( energies_st3, input_frame_ptr, start_lag, sf_length, nb_subfr, complexity, arch );
+ silk_P_Ana_calc_corr_st3( cross_corr_st3, frame, start_lag, sf_length, nb_subfr, complexity, arch );
+ silk_P_Ana_calc_energy_st3( energies_st3, frame, start_lag, sf_length, nb_subfr, complexity, arch );
lag_counter = 0;
silk_assert( lag == silk_SAT16( lag ) );
contour_bias_Q15 = silk_DIV32_16( SILK_FIX_CONST( PE_FLATCONTOUR_BIAS, 15 ), lag );
- target_ptr = &input_frame_ptr[ PE_LTP_MEM_LENGTH_MS * Fs_kHz ];
+ target_ptr = &frame[ PE_LTP_MEM_LENGTH_MS * Fs_kHz ];
energy_target = silk_ADD32( silk_inner_prod_aligned( target_ptr, target_ptr, nb_subfr * sf_length, arch ), 1 );
for( d = start_lag; d <= end_lag; d++ ) {
for( j = 0; j < nb_cbk_search; j++ ) {
@@ -575,7 +550,7 @@ opus_int silk_pitch_analysis_core( /* O Voicing estimate: 0
*lagIndex = (opus_int16)( lag - MIN_LAG_8KHZ );
*contourIndex = (opus_int8)CBimax;
}
- silk_assert( *lagIndex >= 0 );
+ celt_assert( *lagIndex >= 0 );
/* return as voiced */
RESTORE_STACK;
return 0;
@@ -612,8 +587,8 @@ static void silk_P_Ana_calc_corr_st3(
const opus_int8 *Lag_range_ptr, *Lag_CB_ptr;
SAVE_STACK;
- silk_assert( complexity >= SILK_PE_MIN_COMPLEX );
- silk_assert( complexity <= SILK_PE_MAX_COMPLEX );
+ celt_assert( complexity >= SILK_PE_MIN_COMPLEX );
+ celt_assert( complexity <= SILK_PE_MAX_COMPLEX );
if( nb_subfr == PE_MAX_NB_SUBFR ) {
Lag_range_ptr = &silk_Lag_range_stage3[ complexity ][ 0 ][ 0 ];
@@ -621,7 +596,7 @@ static void silk_P_Ana_calc_corr_st3(
nb_cbk_search = silk_nb_cbk_searchs_stage3[ complexity ];
cbk_size = PE_NB_CBKS_STAGE3_MAX;
} else {
- silk_assert( nb_subfr == PE_MAX_NB_SUBFR >> 1);
+ celt_assert( nb_subfr == PE_MAX_NB_SUBFR >> 1);
Lag_range_ptr = &silk_Lag_range_stage3_10_ms[ 0 ][ 0 ];
Lag_CB_ptr = &silk_CB_lags_stage3_10_ms[ 0 ][ 0 ];
nb_cbk_search = PE_NB_CBKS_STAGE3_10MS;
@@ -637,7 +612,7 @@ static void silk_P_Ana_calc_corr_st3(
/* Calculate the correlations for each subframe */
lag_low = matrix_ptr( Lag_range_ptr, k, 0, 2 );
lag_high = matrix_ptr( Lag_range_ptr, k, 1, 2 );
- silk_assert(lag_high-lag_low+1 <= SCRATCH_SIZE);
+ celt_assert(lag_high-lag_low+1 <= SCRATCH_SIZE);
celt_pitch_xcorr( target_ptr, target_ptr - start_lag - lag_high, xcorr32, sf_length, lag_high - lag_low + 1, arch );
for( j = lag_low; j <= lag_high; j++ ) {
silk_assert( lag_counter < SCRATCH_SIZE );
@@ -684,8 +659,8 @@ static void silk_P_Ana_calc_energy_st3(
const opus_int8 *Lag_range_ptr, *Lag_CB_ptr;
SAVE_STACK;
- silk_assert( complexity >= SILK_PE_MIN_COMPLEX );
- silk_assert( complexity <= SILK_PE_MAX_COMPLEX );
+ celt_assert( complexity >= SILK_PE_MIN_COMPLEX );
+ celt_assert( complexity <= SILK_PE_MAX_COMPLEX );
if( nb_subfr == PE_MAX_NB_SUBFR ) {
Lag_range_ptr = &silk_Lag_range_stage3[ complexity ][ 0 ][ 0 ];
@@ -693,7 +668,7 @@ static void silk_P_Ana_calc_energy_st3(
nb_cbk_search = silk_nb_cbk_searchs_stage3[ complexity ];
cbk_size = PE_NB_CBKS_STAGE3_MAX;
} else {
- silk_assert( nb_subfr == PE_MAX_NB_SUBFR >> 1);
+ celt_assert( nb_subfr == PE_MAX_NB_SUBFR >> 1);
Lag_range_ptr = &silk_Lag_range_stage3_10_ms[ 0 ][ 0 ];
Lag_CB_ptr = &silk_CB_lags_stage3_10_ms[ 0 ][ 0 ];
nb_cbk_search = PE_NB_CBKS_STAGE3_10MS;
diff --git a/libs/libopus/silk/fixed/prefilter_FIX.c b/libs/libopus/silk/fixed/prefilter_FIX.c
deleted file mode 100644
index 6a8e35152..000000000
--- a/libs/libopus/silk/fixed/prefilter_FIX.c
+++ /dev/null
@@ -1,221 +0,0 @@
-/***********************************************************************
-Copyright (c) 2006-2011, Skype Limited. All rights reserved.
-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 "main_FIX.h"
-#include "stack_alloc.h"
-#include "tuning_parameters.h"
-
-#if defined(MIPSr1_ASM)
-#include "mips/prefilter_FIX_mipsr1.h"
-#endif
-
-
-#if !defined(OVERRIDE_silk_warped_LPC_analysis_filter_FIX)
-#define silk_warped_LPC_analysis_filter_FIX(state, res_Q2, coef_Q13, input, lambda_Q16, length, order, arch) \
- ((void)(arch),silk_warped_LPC_analysis_filter_FIX_c(state, res_Q2, coef_Q13, input, lambda_Q16, length, order))
-#endif
-
-/* Prefilter for finding Quantizer input signal */
-static OPUS_INLINE void silk_prefilt_FIX(
- silk_prefilter_state_FIX *P, /* I/O state */
- opus_int32 st_res_Q12[], /* I short term residual signal */
- opus_int32 xw_Q3[], /* O prefiltered signal */
- opus_int32 HarmShapeFIRPacked_Q12, /* I Harmonic shaping coeficients */
- opus_int Tilt_Q14, /* I Tilt shaping coeficient */
- opus_int32 LF_shp_Q14, /* I Low-frequancy shaping coeficients */
- opus_int lag, /* I Lag for harmonic shaping */
- opus_int length /* I Length of signals */
-);
-
-void silk_warped_LPC_analysis_filter_FIX_c(
- opus_int32 state[], /* I/O State [order + 1] */
- opus_int32 res_Q2[], /* O Residual signal [length] */
- const opus_int16 coef_Q13[], /* I Coefficients [order] */
- const opus_int16 input[], /* I Input signal [length] */
- const opus_int16 lambda_Q16, /* I Warping factor */
- const opus_int length, /* I Length of input signal */
- const opus_int order /* I Filter order (even) */
-)
-{
- opus_int n, i;
- opus_int32 acc_Q11, tmp1, tmp2;
-
- /* Order must be even */
- silk_assert( ( order & 1 ) == 0 );
-
- for( n = 0; n < length; n++ ) {
- /* Output of lowpass section */
- tmp2 = silk_SMLAWB( state[ 0 ], state[ 1 ], lambda_Q16 );
- state[ 0 ] = silk_LSHIFT( input[ n ], 14 );
- /* Output of allpass section */
- tmp1 = silk_SMLAWB( state[ 1 ], state[ 2 ] - tmp2, lambda_Q16 );
- state[ 1 ] = tmp2;
- acc_Q11 = silk_RSHIFT( order, 1 );
- acc_Q11 = silk_SMLAWB( acc_Q11, tmp2, coef_Q13[ 0 ] );
- /* Loop over allpass sections */
- for( i = 2; i < order; i += 2 ) {
- /* Output of allpass section */
- tmp2 = silk_SMLAWB( state[ i ], state[ i + 1 ] - tmp1, lambda_Q16 );
- state[ i ] = tmp1;
- acc_Q11 = silk_SMLAWB( acc_Q11, tmp1, coef_Q13[ i - 1 ] );
- /* Output of allpass section */
- tmp1 = silk_SMLAWB( state[ i + 1 ], state[ i + 2 ] - tmp2, lambda_Q16 );
- state[ i + 1 ] = tmp2;
- acc_Q11 = silk_SMLAWB( acc_Q11, tmp2, coef_Q13[ i ] );
- }
- state[ order ] = tmp1;
- acc_Q11 = silk_SMLAWB( acc_Q11, tmp1, coef_Q13[ order - 1 ] );
- res_Q2[ n ] = silk_LSHIFT( (opus_int32)input[ n ], 2 ) - silk_RSHIFT_ROUND( acc_Q11, 9 );
- }
-}
-
-void silk_prefilter_FIX(
- silk_encoder_state_FIX *psEnc, /* I/O Encoder state */
- const silk_encoder_control_FIX *psEncCtrl, /* I Encoder control */
- opus_int32 xw_Q3[], /* O Weighted signal */
- const opus_int16 x[] /* I Speech signal */
-)
-{
- silk_prefilter_state_FIX *P = &psEnc->sPrefilt;
- opus_int j, k, lag;
- opus_int32 tmp_32;
- const opus_int16 *AR1_shp_Q13;
- const opus_int16 *px;
- opus_int32 *pxw_Q3;
- opus_int HarmShapeGain_Q12, Tilt_Q14;
- opus_int32 HarmShapeFIRPacked_Q12, LF_shp_Q14;
- VARDECL( opus_int32, x_filt_Q12 );
- VARDECL( opus_int32, st_res_Q2 );
- opus_int16 B_Q10[ 2 ];
- SAVE_STACK;
-
- /* Set up pointers */
- px = x;
- pxw_Q3 = xw_Q3;
- lag = P->lagPrev;
- ALLOC( x_filt_Q12, psEnc->sCmn.subfr_length, opus_int32 );
- ALLOC( st_res_Q2, psEnc->sCmn.subfr_length, opus_int32 );
- for( k = 0; k < psEnc->sCmn.nb_subfr; k++ ) {
- /* Update Variables that change per sub frame */
- if( psEnc->sCmn.indices.signalType == TYPE_VOICED ) {
- lag = psEncCtrl->pitchL[ k ];
- }
-
- /* Noise shape parameters */
- HarmShapeGain_Q12 = silk_SMULWB( (opus_int32)psEncCtrl->HarmShapeGain_Q14[ k ], 16384 - psEncCtrl->HarmBoost_Q14[ k ] );
- silk_assert( HarmShapeGain_Q12 >= 0 );
- HarmShapeFIRPacked_Q12 = silk_RSHIFT( HarmShapeGain_Q12, 2 );
- HarmShapeFIRPacked_Q12 |= silk_LSHIFT( (opus_int32)silk_RSHIFT( HarmShapeGain_Q12, 1 ), 16 );
- Tilt_Q14 = psEncCtrl->Tilt_Q14[ k ];
- LF_shp_Q14 = psEncCtrl->LF_shp_Q14[ k ];
- AR1_shp_Q13 = &psEncCtrl->AR1_Q13[ k * MAX_SHAPE_LPC_ORDER ];
-
- /* Short term FIR filtering*/
- silk_warped_LPC_analysis_filter_FIX( P->sAR_shp, st_res_Q2, AR1_shp_Q13, px,
- psEnc->sCmn.warping_Q16, psEnc->sCmn.subfr_length, psEnc->sCmn.shapingLPCOrder, psEnc->sCmn.arch );
-
- /* Reduce (mainly) low frequencies during harmonic emphasis */
- B_Q10[ 0 ] = silk_RSHIFT_ROUND( psEncCtrl->GainsPre_Q14[ k ], 4 );
- tmp_32 = silk_SMLABB( SILK_FIX_CONST( INPUT_TILT, 26 ), psEncCtrl->HarmBoost_Q14[ k ], HarmShapeGain_Q12 ); /* Q26 */
- tmp_32 = silk_SMLABB( tmp_32, psEncCtrl->coding_quality_Q14, SILK_FIX_CONST( HIGH_RATE_INPUT_TILT, 12 ) ); /* Q26 */
- tmp_32 = silk_SMULWB( tmp_32, -psEncCtrl->GainsPre_Q14[ k ] ); /* Q24 */
- tmp_32 = silk_RSHIFT_ROUND( tmp_32, 14 ); /* Q10 */
- B_Q10[ 1 ]= silk_SAT16( tmp_32 );
- x_filt_Q12[ 0 ] = silk_MLA( silk_MUL( st_res_Q2[ 0 ], B_Q10[ 0 ] ), P->sHarmHP_Q2, B_Q10[ 1 ] );
- for( j = 1; j < psEnc->sCmn.subfr_length; j++ ) {
- x_filt_Q12[ j ] = silk_MLA( silk_MUL( st_res_Q2[ j ], B_Q10[ 0 ] ), st_res_Q2[ j - 1 ], B_Q10[ 1 ] );
- }
- P->sHarmHP_Q2 = st_res_Q2[ psEnc->sCmn.subfr_length - 1 ];
-
- silk_prefilt_FIX( P, x_filt_Q12, pxw_Q3, HarmShapeFIRPacked_Q12, Tilt_Q14, LF_shp_Q14, lag, psEnc->sCmn.subfr_length );
-
- px += psEnc->sCmn.subfr_length;
- pxw_Q3 += psEnc->sCmn.subfr_length;
- }
-
- P->lagPrev = psEncCtrl->pitchL[ psEnc->sCmn.nb_subfr - 1 ];
- RESTORE_STACK;
-}
-
-#ifndef OVERRIDE_silk_prefilt_FIX
-/* Prefilter for finding Quantizer input signal */
-static OPUS_INLINE void silk_prefilt_FIX(
- silk_prefilter_state_FIX *P, /* I/O state */
- opus_int32 st_res_Q12[], /* I short term residual signal */
- opus_int32 xw_Q3[], /* O prefiltered signal */
- opus_int32 HarmShapeFIRPacked_Q12, /* I Harmonic shaping coeficients */
- opus_int Tilt_Q14, /* I Tilt shaping coeficient */
- opus_int32 LF_shp_Q14, /* I Low-frequancy shaping coeficients */
- opus_int lag, /* I Lag for harmonic shaping */
- opus_int length /* I Length of signals */
-)
-{
- opus_int i, idx, LTP_shp_buf_idx;
- opus_int32 n_LTP_Q12, n_Tilt_Q10, n_LF_Q10;
- opus_int32 sLF_MA_shp_Q12, sLF_AR_shp_Q12;
- opus_int16 *LTP_shp_buf;
-
- /* To speed up use temp variables instead of using the struct */
- LTP_shp_buf = P->sLTP_shp;
- LTP_shp_buf_idx = P->sLTP_shp_buf_idx;
- sLF_AR_shp_Q12 = P->sLF_AR_shp_Q12;
- sLF_MA_shp_Q12 = P->sLF_MA_shp_Q12;
-
- for( i = 0; i < length; i++ ) {
- if( lag > 0 ) {
- /* unrolled loop */
- silk_assert( HARM_SHAPE_FIR_TAPS == 3 );
- idx = lag + LTP_shp_buf_idx;
- n_LTP_Q12 = silk_SMULBB( LTP_shp_buf[ ( idx - HARM_SHAPE_FIR_TAPS / 2 - 1) & LTP_MASK ], HarmShapeFIRPacked_Q12 );
- n_LTP_Q12 = silk_SMLABT( n_LTP_Q12, LTP_shp_buf[ ( idx - HARM_SHAPE_FIR_TAPS / 2 ) & LTP_MASK ], HarmShapeFIRPacked_Q12 );
- n_LTP_Q12 = silk_SMLABB( n_LTP_Q12, LTP_shp_buf[ ( idx - HARM_SHAPE_FIR_TAPS / 2 + 1) & LTP_MASK ], HarmShapeFIRPacked_Q12 );
- } else {
- n_LTP_Q12 = 0;
- }
-
- n_Tilt_Q10 = silk_SMULWB( sLF_AR_shp_Q12, Tilt_Q14 );
- n_LF_Q10 = silk_SMLAWB( silk_SMULWT( sLF_AR_shp_Q12, LF_shp_Q14 ), sLF_MA_shp_Q12, LF_shp_Q14 );
-
- sLF_AR_shp_Q12 = silk_SUB32( st_res_Q12[ i ], silk_LSHIFT( n_Tilt_Q10, 2 ) );
- sLF_MA_shp_Q12 = silk_SUB32( sLF_AR_shp_Q12, silk_LSHIFT( n_LF_Q10, 2 ) );
-
- LTP_shp_buf_idx = ( LTP_shp_buf_idx - 1 ) & LTP_MASK;
- LTP_shp_buf[ LTP_shp_buf_idx ] = (opus_int16)silk_SAT16( silk_RSHIFT_ROUND( sLF_MA_shp_Q12, 12 ) );
-
- xw_Q3[i] = silk_RSHIFT_ROUND( silk_SUB32( sLF_MA_shp_Q12, n_LTP_Q12 ), 9 );
- }
-
- /* Copy temp variable back to state */
- P->sLF_AR_shp_Q12 = sLF_AR_shp_Q12;
- P->sLF_MA_shp_Q12 = sLF_MA_shp_Q12;
- P->sLTP_shp_buf_idx = LTP_shp_buf_idx;
-}
-#endif /* OVERRIDE_silk_prefilt_FIX */
diff --git a/libs/libopus/silk/fixed/residual_energy16_FIX.c b/libs/libopus/silk/fixed/residual_energy16_FIX.c
index ebffb2a66..7f130f3d3 100644
--- a/libs/libopus/silk/fixed/residual_energy16_FIX.c
+++ b/libs/libopus/silk/fixed/residual_energy16_FIX.c
@@ -47,10 +47,10 @@ opus_int32 silk_residual_energy16_covar_FIX(
const opus_int32 *pRow;
/* Safety checks */
- silk_assert( D >= 0 );
- silk_assert( D <= 16 );
- silk_assert( cQ > 0 );
- silk_assert( cQ < 16 );
+ celt_assert( D >= 0 );
+ celt_assert( D <= 16 );
+ celt_assert( cQ > 0 );
+ celt_assert( cQ < 16 );
lshifts = 16 - cQ;
Qxtra = lshifts;
diff --git a/libs/libopus/silk/fixed/residual_energy_FIX.c b/libs/libopus/silk/fixed/residual_energy_FIX.c
index 41f74778e..6c7cade9a 100644
--- a/libs/libopus/silk/fixed/residual_energy_FIX.c
+++ b/libs/libopus/silk/fixed/residual_energy_FIX.c
@@ -58,7 +58,7 @@ void silk_residual_energy_FIX(
/* Filter input to create the LPC residual for each frame half, and measure subframe energies */
ALLOC( LPC_res, ( MAX_NB_SUBFR >> 1 ) * offset, opus_int16 );
- silk_assert( ( nb_subfr >> 1 ) * ( MAX_NB_SUBFR >> 1 ) == nb_subfr );
+ celt_assert( ( nb_subfr >> 1 ) * ( MAX_NB_SUBFR >> 1 ) == nb_subfr );
for( i = 0; i < nb_subfr >> 1; i++ ) {
/* Calculate half frame LPC residual signal including preceding samples */
silk_LPC_analysis_filter( LPC_res, x_ptr, a_Q12[ i ], ( MAX_NB_SUBFR >> 1 ) * offset, LPC_order, arch );
diff --git a/libs/libopus/silk/fixed/schur64_FIX.c b/libs/libopus/silk/fixed/schur64_FIX.c
index 764a10ef3..4b7e19ea5 100644
--- a/libs/libopus/silk/fixed/schur64_FIX.c
+++ b/libs/libopus/silk/fixed/schur64_FIX.c
@@ -43,7 +43,7 @@ opus_int32 silk_schur64( /* O returns residual ene
opus_int32 C[ SILK_MAX_ORDER_LPC + 1 ][ 2 ];
opus_int32 Ctmp1_Q30, Ctmp2_Q30, rc_tmp_Q31;
- silk_assert( order==6||order==8||order==10||order==12||order==14||order==16 );
+ celt_assert( order >= 0 && order <= SILK_MAX_ORDER_LPC );
/* Check for invalid input */
if( c[ 0 ] <= 0 ) {
@@ -51,9 +51,10 @@ opus_int32 silk_schur64( /* O returns residual ene
return 0;
}
- for( k = 0; k < order + 1; k++ ) {
+ k = 0;
+ do {
C[ k ][ 0 ] = C[ k ][ 1 ] = c[ k ];
- }
+ } while( ++k <= order );
for( k = 0; k < order; k++ ) {
/* Check that we won't be getting an unstable rc, otherwise stop here. */
diff --git a/libs/libopus/silk/fixed/schur_FIX.c b/libs/libopus/silk/fixed/schur_FIX.c
index c4c0ef23b..2840f6b1a 100644
--- a/libs/libopus/silk/fixed/schur_FIX.c
+++ b/libs/libopus/silk/fixed/schur_FIX.c
@@ -43,28 +43,29 @@ opus_int32 silk_schur( /* O Returns residual ene
opus_int32 C[ SILK_MAX_ORDER_LPC + 1 ][ 2 ];
opus_int32 Ctmp1, Ctmp2, rc_tmp_Q15;
- silk_assert( order==6||order==8||order==10||order==12||order==14||order==16 );
+ celt_assert( order >= 0 && order <= SILK_MAX_ORDER_LPC );
/* Get number of leading zeros */
lz = silk_CLZ32( c[ 0 ] );
/* Copy correlations and adjust level to Q30 */
+ k = 0;
if( lz < 2 ) {
/* lz must be 1, so shift one to the right */
- for( k = 0; k < order + 1; k++ ) {
+ do {
C[ k ][ 0 ] = C[ k ][ 1 ] = silk_RSHIFT( c[ k ], 1 );
- }
+ } while( ++k <= order );
} else if( lz > 2 ) {
/* Shift to the left */
lz -= 2;
- for( k = 0; k < order + 1; k++ ) {
+ do {
C[ k ][ 0 ] = C[ k ][ 1 ] = silk_LSHIFT( c[ k ], lz );
- }
+ } while( ++k <= order );
} else {
/* No need to shift */
- for( k = 0; k < order + 1; k++ ) {
+ do {
C[ k ][ 0 ] = C[ k ][ 1 ] = c[ k ];
- }
+ } while( ++k <= order );
}
for( k = 0; k < order; k++ ) {
diff --git a/libs/libopus/silk/fixed/solve_LS_FIX.c b/libs/libopus/silk/fixed/solve_LS_FIX.c
deleted file mode 100644
index 51d7d49d0..000000000
--- a/libs/libopus/silk/fixed/solve_LS_FIX.c
+++ /dev/null
@@ -1,249 +0,0 @@
-/***********************************************************************
-Copyright (c) 2006-2011, Skype Limited. All rights reserved.
-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 "main_FIX.h"
-#include "stack_alloc.h"
-#include "tuning_parameters.h"
-
-/*****************************/
-/* Internal function headers */
-/*****************************/
-
-typedef struct {
- opus_int32 Q36_part;
- opus_int32 Q48_part;
-} inv_D_t;
-
-/* Factorize square matrix A into LDL form */
-static OPUS_INLINE void silk_LDL_factorize_FIX(
- opus_int32 *A, /* I/O Pointer to Symetric Square Matrix */
- opus_int M, /* I Size of Matrix */
- opus_int32 *L_Q16, /* I/O Pointer to Square Upper triangular Matrix */
- inv_D_t *inv_D /* I/O Pointer to vector holding inverted diagonal elements of D */
-);
-
-/* Solve Lx = b, when L is lower triangular and has ones on the diagonal */
-static OPUS_INLINE void silk_LS_SolveFirst_FIX(
- const opus_int32 *L_Q16, /* I Pointer to Lower Triangular Matrix */
- opus_int M, /* I Dim of Matrix equation */
- const opus_int32 *b, /* I b Vector */
- opus_int32 *x_Q16 /* O x Vector */
-);
-
-/* Solve L^t*x = b, where L is lower triangular with ones on the diagonal */
-static OPUS_INLINE void silk_LS_SolveLast_FIX(
- const opus_int32 *L_Q16, /* I Pointer to Lower Triangular Matrix */
- const opus_int M, /* I Dim of Matrix equation */
- const opus_int32 *b, /* I b Vector */
- opus_int32 *x_Q16 /* O x Vector */
-);
-
-static OPUS_INLINE void silk_LS_divide_Q16_FIX(
- opus_int32 T[], /* I/O Numenator vector */
- inv_D_t *inv_D, /* I 1 / D vector */
- opus_int M /* I dimension */
-);
-
-/* Solves Ax = b, assuming A is symmetric */
-void silk_solve_LDL_FIX(
- opus_int32 *A, /* I Pointer to symetric square matrix A */
- opus_int M, /* I Size of matrix */
- const opus_int32 *b, /* I Pointer to b vector */
- opus_int32 *x_Q16 /* O Pointer to x solution vector */
-)
-{
- VARDECL( opus_int32, L_Q16 );
- opus_int32 Y[ MAX_MATRIX_SIZE ];
- inv_D_t inv_D[ MAX_MATRIX_SIZE ];
- SAVE_STACK;
-
- silk_assert( M <= MAX_MATRIX_SIZE );
- ALLOC( L_Q16, M * M, opus_int32 );
-
- /***************************************************
- Factorize A by LDL such that A = L*D*L',
- where L is lower triangular with ones on diagonal
- ****************************************************/
- silk_LDL_factorize_FIX( A, M, L_Q16, inv_D );
-
- /****************************************************
- * substitute D*L'*x = Y. ie:
- L*D*L'*x = b => L*Y = b <=> Y = inv(L)*b
- ******************************************************/
- silk_LS_SolveFirst_FIX( L_Q16, M, b, Y );
-
- /****************************************************
- D*L'*x = Y <=> L'*x = inv(D)*Y, because D is
- diagonal just multiply with 1/d_i
- ****************************************************/
- silk_LS_divide_Q16_FIX( Y, inv_D, M );
-
- /****************************************************
- x = inv(L') * inv(D) * Y
- *****************************************************/
- silk_LS_SolveLast_FIX( L_Q16, M, Y, x_Q16 );
- RESTORE_STACK;
-}
-
-static OPUS_INLINE void silk_LDL_factorize_FIX(
- opus_int32 *A, /* I/O Pointer to Symetric Square Matrix */
- opus_int M, /* I Size of Matrix */
- opus_int32 *L_Q16, /* I/O Pointer to Square Upper triangular Matrix */
- inv_D_t *inv_D /* I/O Pointer to vector holding inverted diagonal elements of D */
-)
-{
- opus_int i, j, k, status, loop_count;
- const opus_int32 *ptr1, *ptr2;
- opus_int32 diag_min_value, tmp_32, err;
- opus_int32 v_Q0[ MAX_MATRIX_SIZE ], D_Q0[ MAX_MATRIX_SIZE ];
- opus_int32 one_div_diag_Q36, one_div_diag_Q40, one_div_diag_Q48;
-
- silk_assert( M <= MAX_MATRIX_SIZE );
-
- status = 1;
- diag_min_value = silk_max_32( silk_SMMUL( silk_ADD_SAT32( A[ 0 ], A[ silk_SMULBB( M, M ) - 1 ] ), SILK_FIX_CONST( FIND_LTP_COND_FAC, 31 ) ), 1 << 9 );
- for( loop_count = 0; loop_count < M && status == 1; loop_count++ ) {
- status = 0;
- for( j = 0; j < M; j++ ) {
- ptr1 = matrix_adr( L_Q16, j, 0, M );
- tmp_32 = 0;
- for( i = 0; i < j; i++ ) {
- v_Q0[ i ] = silk_SMULWW( D_Q0[ i ], ptr1[ i ] ); /* Q0 */
- tmp_32 = silk_SMLAWW( tmp_32, v_Q0[ i ], ptr1[ i ] ); /* Q0 */
- }
- tmp_32 = silk_SUB32( matrix_ptr( A, j, j, M ), tmp_32 );
-
- if( tmp_32 < diag_min_value ) {
- tmp_32 = silk_SUB32( silk_SMULBB( loop_count + 1, diag_min_value ), tmp_32 );
- /* Matrix not positive semi-definite, or ill conditioned */
- for( i = 0; i < M; i++ ) {
- matrix_ptr( A, i, i, M ) = silk_ADD32( matrix_ptr( A, i, i, M ), tmp_32 );
- }
- status = 1;
- break;
- }
- D_Q0[ j ] = tmp_32; /* always < max(Correlation) */
-
- /* two-step division */
- one_div_diag_Q36 = silk_INVERSE32_varQ( tmp_32, 36 ); /* Q36 */
- one_div_diag_Q40 = silk_LSHIFT( one_div_diag_Q36, 4 ); /* Q40 */
- err = silk_SUB32( (opus_int32)1 << 24, silk_SMULWW( tmp_32, one_div_diag_Q40 ) ); /* Q24 */
- one_div_diag_Q48 = silk_SMULWW( err, one_div_diag_Q40 ); /* Q48 */
-
- /* Save 1/Ds */
- inv_D[ j ].Q36_part = one_div_diag_Q36;
- inv_D[ j ].Q48_part = one_div_diag_Q48;
-
- matrix_ptr( L_Q16, j, j, M ) = 65536; /* 1.0 in Q16 */
- ptr1 = matrix_adr( A, j, 0, M );
- ptr2 = matrix_adr( L_Q16, j + 1, 0, M );
- for( i = j + 1; i < M; i++ ) {
- tmp_32 = 0;
- for( k = 0; k < j; k++ ) {
- tmp_32 = silk_SMLAWW( tmp_32, v_Q0[ k ], ptr2[ k ] ); /* Q0 */
- }
- tmp_32 = silk_SUB32( ptr1[ i ], tmp_32 ); /* always < max(Correlation) */
-
- /* tmp_32 / D_Q0[j] : Divide to Q16 */
- matrix_ptr( L_Q16, i, j, M ) = silk_ADD32( silk_SMMUL( tmp_32, one_div_diag_Q48 ),
- silk_RSHIFT( silk_SMULWW( tmp_32, one_div_diag_Q36 ), 4 ) );
-
- /* go to next column */
- ptr2 += M;
- }
- }
- }
-
- silk_assert( status == 0 );
-}
-
-static OPUS_INLINE void silk_LS_divide_Q16_FIX(
- opus_int32 T[], /* I/O Numenator vector */
- inv_D_t *inv_D, /* I 1 / D vector */
- opus_int M /* I dimension */
-)
-{
- opus_int i;
- opus_int32 tmp_32;
- opus_int32 one_div_diag_Q36, one_div_diag_Q48;
-
- for( i = 0; i < M; i++ ) {
- one_div_diag_Q36 = inv_D[ i ].Q36_part;
- one_div_diag_Q48 = inv_D[ i ].Q48_part;
-
- tmp_32 = T[ i ];
- T[ i ] = silk_ADD32( silk_SMMUL( tmp_32, one_div_diag_Q48 ), silk_RSHIFT( silk_SMULWW( tmp_32, one_div_diag_Q36 ), 4 ) );
- }
-}
-
-/* Solve Lx = b, when L is lower triangular and has ones on the diagonal */
-static OPUS_INLINE void silk_LS_SolveFirst_FIX(
- const opus_int32 *L_Q16, /* I Pointer to Lower Triangular Matrix */
- opus_int M, /* I Dim of Matrix equation */
- const opus_int32 *b, /* I b Vector */
- opus_int32 *x_Q16 /* O x Vector */
-)
-{
- opus_int i, j;
- const opus_int32 *ptr32;
- opus_int32 tmp_32;
-
- for( i = 0; i < M; i++ ) {
- ptr32 = matrix_adr( L_Q16, i, 0, M );
- tmp_32 = 0;
- for( j = 0; j < i; j++ ) {
- tmp_32 = silk_SMLAWW( tmp_32, ptr32[ j ], x_Q16[ j ] );
- }
- x_Q16[ i ] = silk_SUB32( b[ i ], tmp_32 );
- }
-}
-
-/* Solve L^t*x = b, where L is lower triangular with ones on the diagonal */
-static OPUS_INLINE void silk_LS_SolveLast_FIX(
- const opus_int32 *L_Q16, /* I Pointer to Lower Triangular Matrix */
- const opus_int M, /* I Dim of Matrix equation */
- const opus_int32 *b, /* I b Vector */
- opus_int32 *x_Q16 /* O x Vector */
-)
-{
- opus_int i, j;
- const opus_int32 *ptr32;
- opus_int32 tmp_32;
-
- for( i = M - 1; i >= 0; i-- ) {
- ptr32 = matrix_adr( L_Q16, 0, i, M );
- tmp_32 = 0;
- for( j = M - 1; j > i; j-- ) {
- tmp_32 = silk_SMLAWW( tmp_32, ptr32[ silk_SMULBB( j, M ) ], x_Q16[ j ] );
- }
- x_Q16[ i ] = silk_SUB32( b[ i ], tmp_32 );
- }
-}
diff --git a/libs/libopus/silk/fixed/structs_FIX.h b/libs/libopus/silk/fixed/structs_FIX.h
index 3294b2512..2774a97b2 100644
--- a/libs/libopus/silk/fixed/structs_FIX.h
+++ b/libs/libopus/silk/fixed/structs_FIX.h
@@ -48,30 +48,16 @@ typedef struct {
} silk_shape_state_FIX;
/********************************/
-/* Prefilter state */
-/********************************/
-typedef struct {
- opus_int16 sLTP_shp[ LTP_BUF_LENGTH ];
- opus_int32 sAR_shp[ MAX_SHAPE_LPC_ORDER + 1 ];
- opus_int sLTP_shp_buf_idx;
- opus_int32 sLF_AR_shp_Q12;
- opus_int32 sLF_MA_shp_Q12;
- opus_int32 sHarmHP_Q2;
- opus_int32 rand_seed;
- opus_int lagPrev;
-} silk_prefilter_state_FIX;
-
-/********************************/
/* Encoder state FIX */
/********************************/
typedef struct {
silk_encoder_state sCmn; /* Common struct, shared with floating-point code */
silk_shape_state_FIX sShape; /* Shape state */
- silk_prefilter_state_FIX sPrefilt; /* Prefilter State */
/* Buffer for find pitch and noise shape analysis */
silk_DWORD_ALIGN opus_int16 x_buf[ 2 * MAX_FRAME_LENGTH + LA_SHAPE_MAX ];/* Buffer for find pitch and noise shape analysis */
opus_int LTPCorr_Q15; /* Normalized correlation from pitch lag estimator */
+ opus_int32 resNrgSmth;
} silk_encoder_state_FIX;
/************************/
@@ -87,11 +73,8 @@ typedef struct {
/* Noise shaping parameters */
/* Testing */
- silk_DWORD_ALIGN opus_int16 AR1_Q13[ MAX_NB_SUBFR * MAX_SHAPE_LPC_ORDER ];
- silk_DWORD_ALIGN opus_int16 AR2_Q13[ MAX_NB_SUBFR * MAX_SHAPE_LPC_ORDER ];
+ silk_DWORD_ALIGN opus_int16 AR_Q13[ MAX_NB_SUBFR * MAX_SHAPE_LPC_ORDER ];
opus_int32 LF_shp_Q14[ MAX_NB_SUBFR ]; /* Packs two int16 coefficients per int32 value */
- opus_int GainsPre_Q14[ MAX_NB_SUBFR ];
- opus_int HarmBoost_Q14[ MAX_NB_SUBFR ];
opus_int Tilt_Q14[ MAX_NB_SUBFR ];
opus_int HarmShapeGain_Q14[ MAX_NB_SUBFR ];
opus_int Lambda_Q10;
@@ -99,7 +82,6 @@ typedef struct {
opus_int coding_quality_Q14;
/* measures */
- opus_int sparseness_Q8;
opus_int32 predGain_Q16;
opus_int LTPredCodGain_Q7;
opus_int32 ResNrg[ MAX_NB_SUBFR ]; /* Residual energy per subframe */
diff --git a/libs/libopus/silk/fixed/vector_ops_FIX.c b/libs/libopus/silk/fixed/vector_ops_FIX.c
index d94980014..dcf84070a 100644
--- a/libs/libopus/silk/fixed/vector_ops_FIX.c
+++ b/libs/libopus/silk/fixed/vector_ops_FIX.c
@@ -87,7 +87,7 @@ opus_int32 silk_inner_prod_aligned(
#endif
}
-opus_int64 silk_inner_prod16_aligned_64_c(
+opus_int64 silk_inner_prod16_c(
const opus_int16 *inVec1, /* I input vector 1 */
const opus_int16 *inVec2, /* I input vector 2 */
const opus_int len /* I vector lengths */
diff --git a/libs/libopus/silk/fixed/warped_autocorrelation_FIX.c b/libs/libopus/silk/fixed/warped_autocorrelation_FIX.c
index 6ca6c1184..5c79553bc 100644
--- a/libs/libopus/silk/fixed/warped_autocorrelation_FIX.c
+++ b/libs/libopus/silk/fixed/warped_autocorrelation_FIX.c
@@ -31,17 +31,14 @@ POSSIBILITY OF SUCH DAMAGE.
#include "main_FIX.h"
-#define QC 10
-#define QS 14
-
#if defined(MIPSr1_ASM)
#include "mips/warped_autocorrelation_FIX_mipsr1.h"
#endif
-#ifndef OVERRIDE_silk_warped_autocorrelation_FIX
/* Autocorrelations for a warped frequency axis */
-void silk_warped_autocorrelation_FIX(
+#ifndef OVERRIDE_silk_warped_autocorrelation_FIX_c
+void silk_warped_autocorrelation_FIX_c(
opus_int32 *corr, /* O Result [order + 1] */
opus_int *scale, /* O Scaling of the correlation vector */
const opus_int16 *input, /* I Input data to correlate */
@@ -56,7 +53,7 @@ void silk_warped_autocorrelation_FIX(
opus_int64 corr_QC[ MAX_SHAPE_LPC_ORDER + 1 ] = { 0 };
/* Order must be even */
- silk_assert( ( order & 1 ) == 0 );
+ celt_assert( ( order & 1 ) == 0 );
silk_assert( 2 * QS - QC >= 0 );
/* Loop over samples */
@@ -92,4 +89,4 @@ void silk_warped_autocorrelation_FIX(
}
silk_assert( corr_QC[ 0 ] >= 0 ); /* If breaking, decrease QC*/
}
-#endif /* OVERRIDE_silk_warped_autocorrelation_FIX */
+#endif /* OVERRIDE_silk_warped_autocorrelation_FIX_c */
diff --git a/libs/libopus/silk/fixed/x86/burg_modified_FIX_sse.c b/libs/libopus/silk/fixed/x86/burg_modified_FIX_sse4_1.c
index 3c3583c5f..e58bf079e 100644
--- a/libs/libopus/silk/fixed/x86/burg_modified_FIX_sse.c
+++ b/libs/libopus/silk/fixed/x86/burg_modified_FIX_sse4_1.c
@@ -1,5 +1,5 @@
-/* Copyright (c) 2014, Cisco Systems, INC
- Written by XiangMingZhu WeiZhou MinPeng YanWang
+/* Copyright (c) 2014-2020, Cisco Systems, INC
+ Written by XiangMingZhu WeiZhou MinPeng YanWang FrancisQuiers
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
@@ -42,7 +42,7 @@
#define MAX_FRAME_SIZE 384 /* subfr_length * nb_subfr = ( 0.005 * 16000 + 16 ) * 4 = 384 */
#define QA 25
-#define N_BITS_HEAD_ROOM 2
+#define N_BITS_HEAD_ROOM 3
#define MIN_RSHIFTS -16
#define MAX_RSHIFTS (32 - QA)
@@ -59,7 +59,7 @@ void silk_burg_modified_sse4_1(
int arch /* I Run-time architecture */
)
{
- opus_int k, n, s, lz, rshifts, rshifts_extra, reached_max_gain;
+ opus_int k, n, s, lz, rshifts, reached_max_gain;
opus_int32 C0, num, nrg, rc_Q31, invGain_Q30, Atmp_QA, Atmp1, tmp1, tmp2, x1, x2;
const opus_int16 *x_ptr;
opus_int32 C_first_row[ SILK_MAX_ORDER_LPC ];
@@ -68,30 +68,26 @@ void silk_burg_modified_sse4_1(
opus_int32 CAf[ SILK_MAX_ORDER_LPC + 1 ];
opus_int32 CAb[ SILK_MAX_ORDER_LPC + 1 ];
opus_int32 xcorr[ SILK_MAX_ORDER_LPC ];
+ opus_int64 C0_64;
__m128i FIRST_3210, LAST_3210, ATMP_3210, TMP1_3210, TMP2_3210, T1_3210, T2_3210, PTR_3210, SUBFR_3210, X1_3210, X2_3210;
__m128i CONST1 = _mm_set1_epi32(1);
- silk_assert( subfr_length * nb_subfr <= MAX_FRAME_SIZE );
+ celt_assert( subfr_length * nb_subfr <= MAX_FRAME_SIZE );
/* Compute autocorrelations, added over subframes */
- silk_sum_sqr_shift( &C0, &rshifts, x, nb_subfr * subfr_length );
- if( rshifts > MAX_RSHIFTS ) {
- C0 = silk_LSHIFT32( C0, rshifts - MAX_RSHIFTS );
- silk_assert( C0 > 0 );
- rshifts = MAX_RSHIFTS;
+ C0_64 = silk_inner_prod16( x, x, subfr_length*nb_subfr, arch );
+ lz = silk_CLZ64(C0_64);
+ rshifts = 32 + 1 + N_BITS_HEAD_ROOM - lz;
+ if (rshifts > MAX_RSHIFTS) rshifts = MAX_RSHIFTS;
+ if (rshifts < MIN_RSHIFTS) rshifts = MIN_RSHIFTS;
+
+ if (rshifts > 0) {
+ C0 = (opus_int32)silk_RSHIFT64(C0_64, rshifts );
} else {
- lz = silk_CLZ32( C0 ) - 1;
- rshifts_extra = N_BITS_HEAD_ROOM - lz;
- if( rshifts_extra > 0 ) {
- rshifts_extra = silk_min( rshifts_extra, MAX_RSHIFTS - rshifts );
- C0 = silk_RSHIFT32( C0, rshifts_extra );
- } else {
- rshifts_extra = silk_max( rshifts_extra, MIN_RSHIFTS - rshifts );
- C0 = silk_LSHIFT32( C0, -rshifts_extra );
- }
- rshifts += rshifts_extra;
+ C0 = silk_LSHIFT32((opus_int32)C0_64, -rshifts );
}
+
CAb[ 0 ] = CAf[ 0 ] = C0 + silk_SMMUL( SILK_FIX_CONST( FIND_LPC_COND_FAC, 32 ), C0 ) + 1; /* Q(-rshifts) */
silk_memset( C_first_row, 0, SILK_MAX_ORDER_LPC * sizeof( opus_int32 ) );
if( rshifts > 0 ) {
@@ -99,7 +95,7 @@ void silk_burg_modified_sse4_1(
x_ptr = x + s * subfr_length;
for( n = 1; n < D + 1; n++ ) {
C_first_row[ n - 1 ] += (opus_int32)silk_RSHIFT64(
- silk_inner_prod16_aligned_64( x_ptr, x_ptr + n, subfr_length - n, arch ), rshifts );
+ silk_inner_prod16( x_ptr, x_ptr + n, subfr_length - n, arch ), rshifts );
}
}
} else {
@@ -203,8 +199,11 @@ void silk_burg_modified_sse4_1(
C_first_row[ k ] = silk_MLA( C_first_row[ k ], x1, x_ptr[ n - k - 1 ] ); /* Q( -rshifts ) */
C_last_row[ k ] = silk_MLA( C_last_row[ k ], x2, x_ptr[ subfr_length - n + k ] ); /* Q( -rshifts ) */
Atmp1 = silk_RSHIFT_ROUND( Af_QA[ k ], QA - 17 ); /* Q17 */
- tmp1 = silk_MLA( tmp1, x_ptr[ n - k - 1 ], Atmp1 ); /* Q17 */
- tmp2 = silk_MLA( tmp2, x_ptr[ subfr_length - n + k ], Atmp1 ); /* Q17 */
+ /* We sometimes get overflows in the multiplications (even beyond +/- 2^32),
+ but they cancel each other and the real result seems to always fit in a 32-bit
+ signed integer. This was determined experimentally, not theoretically (unfortunately). */
+ tmp1 = silk_MLA_ovflw( tmp1, x_ptr[ n - k - 1 ], Atmp1 ); /* Q17 */
+ tmp2 = silk_MLA_ovflw( tmp2, x_ptr[ subfr_length - n + k ], Atmp1 ); /* Q17 */
}
tmp1 = -tmp1; /* Q17 */
@@ -350,7 +349,7 @@ void silk_burg_modified_sse4_1(
if( rshifts > 0 ) {
for( s = 0; s < nb_subfr; s++ ) {
x_ptr = x + s * subfr_length;
- C0 -= (opus_int32)silk_RSHIFT64( silk_inner_prod16_aligned_64( x_ptr, x_ptr, D, arch ), rshifts );
+ C0 -= (opus_int32)silk_RSHIFT64( silk_inner_prod16( x_ptr, x_ptr, D, arch ), rshifts );
}
} else {
for( s = 0; s < nb_subfr; s++ ) {
@@ -374,4 +373,28 @@ void silk_burg_modified_sse4_1(
*res_nrg = silk_SMLAWW( nrg, silk_SMMUL( SILK_FIX_CONST( FIND_LPC_COND_FAC, 32 ), C0 ), -tmp1 );/* Q( -rshifts ) */
*res_nrg_Q = -rshifts;
}
+
+#ifdef OPUS_CHECK_ASM
+ {
+ opus_int32 res_nrg_c = 0;
+ opus_int res_nrg_Q_c = 0;
+ opus_int32 A_Q16_c[ MAX_LPC_ORDER ] = {0};
+
+ silk_burg_modified_c(
+ &res_nrg_c,
+ &res_nrg_Q_c,
+ A_Q16_c,
+ x,
+ minInvGain_Q30,
+ subfr_length,
+ nb_subfr,
+ D,
+ 0
+ );
+
+ silk_assert( *res_nrg == res_nrg_c );
+ silk_assert( *res_nrg_Q == res_nrg_Q_c );
+ silk_assert( !memcmp( A_Q16, A_Q16_c, D * sizeof( *A_Q16 ) ) );
+ }
+#endif
}
diff --git a/libs/libopus/silk/fixed/x86/prefilter_FIX_sse.c b/libs/libopus/silk/fixed/x86/prefilter_FIX_sse.c
deleted file mode 100644
index 488a603f5..000000000
--- a/libs/libopus/silk/fixed/x86/prefilter_FIX_sse.c
+++ /dev/null
@@ -1,160 +0,0 @@
-/* Copyright (c) 2014, Cisco Systems, INC
- Written by XiangMingZhu WeiZhou MinPeng YanWang
-
- 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 <xmmintrin.h>
-#include <emmintrin.h>
-#include <smmintrin.h>
-#include "main.h"
-#include "celt/x86/x86cpu.h"
-
-void silk_warped_LPC_analysis_filter_FIX_sse4_1(
- opus_int32 state[], /* I/O State [order + 1] */
- opus_int32 res_Q2[], /* O Residual signal [length] */
- const opus_int16 coef_Q13[], /* I Coefficients [order] */
- const opus_int16 input[], /* I Input signal [length] */
- const opus_int16 lambda_Q16, /* I Warping factor */
- const opus_int length, /* I Length of input signal */
- const opus_int order /* I Filter order (even) */
-)
-{
- opus_int n, i;
- opus_int32 acc_Q11, tmp1, tmp2;
-
- /* Order must be even */
- silk_assert( ( order & 1 ) == 0 );
-
- if (order == 10)
- {
- if (0 == lambda_Q16)
- {
- __m128i coef_Q13_3210, coef_Q13_7654;
- __m128i coef_Q13_0123, coef_Q13_4567;
- __m128i state_0123, state_4567;
- __m128i xmm_product1, xmm_product2;
- __m128i xmm_tempa, xmm_tempb;
-
- register opus_int32 sum;
- register opus_int32 state_8, state_9, state_a;
- register opus_int64 coef_Q13_8, coef_Q13_9;
-
- silk_assert( length > 0 );
-
- coef_Q13_3210 = OP_CVTEPI16_EPI32_M64( &coef_Q13[ 0 ] );
- coef_Q13_7654 = OP_CVTEPI16_EPI32_M64( &coef_Q13[ 4 ] );
-
- coef_Q13_0123 = _mm_shuffle_epi32( coef_Q13_3210, _MM_SHUFFLE( 0, 1, 2, 3 ) );
- coef_Q13_4567 = _mm_shuffle_epi32( coef_Q13_7654, _MM_SHUFFLE( 0, 1, 2, 3 ) );
-
- coef_Q13_8 = (opus_int64) coef_Q13[ 8 ];
- coef_Q13_9 = (opus_int64) coef_Q13[ 9 ];
-
- state_0123 = _mm_loadu_si128( (__m128i *)(&state[ 0 ] ) );
- state_4567 = _mm_loadu_si128( (__m128i *)(&state[ 4 ] ) );
-
- state_0123 = _mm_shuffle_epi32( state_0123, _MM_SHUFFLE( 0, 1, 2, 3 ) );
- state_4567 = _mm_shuffle_epi32( state_4567, _MM_SHUFFLE( 0, 1, 2, 3 ) );
-
- state_8 = state[ 8 ];
- state_9 = state[ 9 ];
- state_a = 0;
-
- for( n = 0; n < length; n++ )
- {
- xmm_product1 = _mm_mul_epi32( coef_Q13_0123, state_0123 ); /* 64-bit multiply, only 2 pairs */
- xmm_product2 = _mm_mul_epi32( coef_Q13_4567, state_4567 );
-
- xmm_tempa = _mm_shuffle_epi32( state_0123, _MM_SHUFFLE( 0, 1, 2, 3 ) );
- xmm_tempb = _mm_shuffle_epi32( state_4567, _MM_SHUFFLE( 0, 1, 2, 3 ) );
-
- xmm_product1 = _mm_srli_epi64( xmm_product1, 16 ); /* >> 16, zero extending works */
- xmm_product2 = _mm_srli_epi64( xmm_product2, 16 );
-
- xmm_tempa = _mm_mul_epi32( coef_Q13_3210, xmm_tempa );
- xmm_tempb = _mm_mul_epi32( coef_Q13_7654, xmm_tempb );
-
- xmm_tempa = _mm_srli_epi64( xmm_tempa, 16 );
- xmm_tempb = _mm_srli_epi64( xmm_tempb, 16 );
-
- xmm_tempa = _mm_add_epi32( xmm_tempa, xmm_product1 );
- xmm_tempb = _mm_add_epi32( xmm_tempb, xmm_product2 );
- xmm_tempa = _mm_add_epi32( xmm_tempa, xmm_tempb );
-
- sum = (coef_Q13_8 * state_8) >> 16;
- sum += (coef_Q13_9 * state_9) >> 16;
-
- xmm_tempa = _mm_add_epi32( xmm_tempa, _mm_shuffle_epi32( xmm_tempa, _MM_SHUFFLE( 0, 0, 0, 2 ) ) );
- sum += _mm_cvtsi128_si32( xmm_tempa);
- res_Q2[ n ] = silk_LSHIFT( (opus_int32)input[ n ], 2 ) - silk_RSHIFT_ROUND( ( 5 + sum ), 9);
-
- /* move right */
- state_a = state_9;
- state_9 = state_8;
- state_8 = _mm_cvtsi128_si32( state_4567 );
- state_4567 = _mm_alignr_epi8( state_0123, state_4567, 4 );
-
- state_0123 = _mm_alignr_epi8( _mm_cvtsi32_si128( silk_LSHIFT( input[ n ], 14 ) ), state_0123, 4 );
- }
-
- _mm_storeu_si128( (__m128i *)( &state[ 0 ] ), _mm_shuffle_epi32( state_0123, _MM_SHUFFLE( 0, 1, 2, 3 ) ) );
- _mm_storeu_si128( (__m128i *)( &state[ 4 ] ), _mm_shuffle_epi32( state_4567, _MM_SHUFFLE( 0, 1, 2, 3 ) ) );
- state[ 8 ] = state_8;
- state[ 9 ] = state_9;
- state[ 10 ] = state_a;
-
- return;
- }
- }
-
- for( n = 0; n < length; n++ ) {
- /* Output of lowpass section */
- tmp2 = silk_SMLAWB( state[ 0 ], state[ 1 ], lambda_Q16 );
- state[ 0 ] = silk_LSHIFT( input[ n ], 14 );
- /* Output of allpass section */
- tmp1 = silk_SMLAWB( state[ 1 ], state[ 2 ] - tmp2, lambda_Q16 );
- state[ 1 ] = tmp2;
- acc_Q11 = silk_RSHIFT( order, 1 );
- acc_Q11 = silk_SMLAWB( acc_Q11, tmp2, coef_Q13[ 0 ] );
- /* Loop over allpass sections */
- for( i = 2; i < order; i += 2 ) {
- /* Output of allpass section */
- tmp2 = silk_SMLAWB( state[ i ], state[ i + 1 ] - tmp1, lambda_Q16 );
- state[ i ] = tmp1;
- acc_Q11 = silk_SMLAWB( acc_Q11, tmp1, coef_Q13[ i - 1 ] );
- /* Output of allpass section */
- tmp1 = silk_SMLAWB( state[ i + 1 ], state[ i + 2 ] - tmp2, lambda_Q16 );
- state[ i + 1 ] = tmp2;
- acc_Q11 = silk_SMLAWB( acc_Q11, tmp2, coef_Q13[ i ] );
- }
- state[ order ] = tmp1;
- acc_Q11 = silk_SMLAWB( acc_Q11, tmp1, coef_Q13[ order - 1 ] );
- res_Q2[ n ] = silk_LSHIFT( (opus_int32)input[ n ], 2 ) - silk_RSHIFT_ROUND( acc_Q11, 9 );
- }
-}
diff --git a/libs/libopus/silk/fixed/x86/vector_ops_FIX_sse.c b/libs/libopus/silk/fixed/x86/vector_ops_FIX_sse4_1.c
index c1e90564d..0cfb08d90 100644
--- a/libs/libopus/silk/fixed/x86/vector_ops_FIX_sse.c
+++ b/libs/libopus/silk/fixed/x86/vector_ops_FIX_sse4_1.c
@@ -37,39 +37,36 @@
#include "SigProc_FIX.h"
#include "pitch.h"
-opus_int64 silk_inner_prod16_aligned_64_sse4_1(
+opus_int64 silk_inner_prod16_sse4_1(
const opus_int16 *inVec1, /* I input vector 1 */
const opus_int16 *inVec2, /* I input vector 2 */
const opus_int len /* I vector lengths */
)
{
- opus_int i, dataSize8;
+ opus_int i, dataSize4;
opus_int64 sum;
- __m128i xmm_tempa;
- __m128i inVec1_76543210, acc1;
- __m128i inVec2_76543210, acc2;
+ __m128i xmm_prod_20, xmm_prod_31;
+ __m128i inVec1_3210, acc1;
+ __m128i inVec2_3210, acc2;
sum = 0;
- dataSize8 = len & ~7;
+ dataSize4 = len & ~3;
acc1 = _mm_setzero_si128();
acc2 = _mm_setzero_si128();
- for( i = 0; i < dataSize8; i += 8 ) {
- inVec1_76543210 = _mm_loadu_si128( (__m128i *)(&inVec1[i + 0] ) );
- inVec2_76543210 = _mm_loadu_si128( (__m128i *)(&inVec2[i + 0] ) );
+ for( i = 0; i < dataSize4; i += 4 ) {
+ inVec1_3210 = OP_CVTEPI16_EPI32_M64( &inVec1[i + 0] );
+ inVec2_3210 = OP_CVTEPI16_EPI32_M64( &inVec2[i + 0] );
+ xmm_prod_20 = _mm_mul_epi32( inVec1_3210, inVec2_3210 );
- /* only when all 4 operands are -32768 (0x8000), this results in wrap around */
- inVec1_76543210 = _mm_madd_epi16( inVec1_76543210, inVec2_76543210 );
+ inVec1_3210 = _mm_shuffle_epi32( inVec1_3210, _MM_SHUFFLE( 0, 3, 2, 1 ) );
+ inVec2_3210 = _mm_shuffle_epi32( inVec2_3210, _MM_SHUFFLE( 0, 3, 2, 1 ) );
+ xmm_prod_31 = _mm_mul_epi32( inVec1_3210, inVec2_3210 );
- xmm_tempa = _mm_cvtepi32_epi64( inVec1_76543210 );
- /* equal shift right 8 bytes */
- inVec1_76543210 = _mm_shuffle_epi32( inVec1_76543210, _MM_SHUFFLE( 0, 0, 3, 2 ) );
- inVec1_76543210 = _mm_cvtepi32_epi64( inVec1_76543210 );
-
- acc1 = _mm_add_epi64( acc1, xmm_tempa );
- acc2 = _mm_add_epi64( acc2, inVec1_76543210 );
+ acc1 = _mm_add_epi64( acc1, xmm_prod_20 );
+ acc2 = _mm_add_epi64( acc2, xmm_prod_31 );
}
acc1 = _mm_add_epi64( acc1, acc2 );
@@ -84,5 +81,12 @@ opus_int64 silk_inner_prod16_aligned_64_sse4_1(
sum = silk_SMLABB( sum, inVec1[ i ], inVec2[ i ] );
}
+#ifdef OPUS_CHECK_ASM
+ {
+ opus_int64 sum_c = silk_inner_prod16_c( inVec1, inVec2, len );
+ silk_assert( sum == sum_c );
+ }
+#endif
+
return sum;
}
diff --git a/libs/libopus/silk/float/LPC_analysis_filter_FLP.c b/libs/libopus/silk/float/LPC_analysis_filter_FLP.c
index cae89a0a1..0e1a1fed0 100644
--- a/libs/libopus/silk/float/LPC_analysis_filter_FLP.c
+++ b/libs/libopus/silk/float/LPC_analysis_filter_FLP.c
@@ -215,7 +215,7 @@ void silk_LPC_analysis_filter_FLP(
const opus_int Order /* I LPC order */
)
{
- silk_assert( Order <= length );
+ celt_assert( Order <= length );
switch( Order ) {
case 6:
@@ -239,7 +239,7 @@ void silk_LPC_analysis_filter_FLP(
break;
default:
- silk_assert( 0 );
+ celt_assert( 0 );
break;
}
diff --git a/libs/libopus/silk/float/LPC_inv_pred_gain_FLP.c b/libs/libopus/silk/float/LPC_inv_pred_gain_FLP.c
index 25178bacd..2be2122d6 100644
--- a/libs/libopus/silk/float/LPC_inv_pred_gain_FLP.c
+++ b/libs/libopus/silk/float/LPC_inv_pred_gain_FLP.c
@@ -31,8 +31,7 @@ POSSIBILITY OF SUCH DAMAGE.
#include "SigProc_FIX.h"
#include "SigProc_FLP.h"
-
-#define RC_THRESHOLD 0.9999f
+#include "define.h"
/* compute inverse of LPC prediction gain, and */
/* test if LPC coefficients are stable (all poles within unit circle) */
@@ -43,34 +42,32 @@ silk_float silk_LPC_inverse_pred_gain_FLP( /* O return inverse prediction ga
)
{
opus_int k, n;
- double invGain, rc, rc_mult1, rc_mult2;
- silk_float Atmp[ 2 ][ SILK_MAX_ORDER_LPC ];
- silk_float *Aold, *Anew;
+ double invGain, rc, rc_mult1, rc_mult2, tmp1, tmp2;
+ silk_float Atmp[ SILK_MAX_ORDER_LPC ];
- Anew = Atmp[ order & 1 ];
- silk_memcpy( Anew, A, order * sizeof(silk_float) );
+ silk_memcpy( Atmp, A, order * sizeof(silk_float) );
invGain = 1.0;
for( k = order - 1; k > 0; k-- ) {
- rc = -Anew[ k ];
- if( rc > RC_THRESHOLD || rc < -RC_THRESHOLD ) {
+ rc = -Atmp[ k ];
+ rc_mult1 = 1.0f - rc * rc;
+ invGain *= rc_mult1;
+ if( invGain * MAX_PREDICTION_POWER_GAIN < 1.0f ) {
return 0.0f;
}
- rc_mult1 = 1.0f - rc * rc;
rc_mult2 = 1.0f / rc_mult1;
- invGain *= rc_mult1;
- /* swap pointers */
- Aold = Anew;
- Anew = Atmp[ k & 1 ];
- for( n = 0; n < k; n++ ) {
- Anew[ n ] = (silk_float)( ( Aold[ n ] - Aold[ k - n - 1 ] * rc ) * rc_mult2 );
+ for( n = 0; n < (k + 1) >> 1; n++ ) {
+ tmp1 = Atmp[ n ];
+ tmp2 = Atmp[ k - n - 1 ];
+ Atmp[ n ] = (silk_float)( ( tmp1 - tmp2 * rc ) * rc_mult2 );
+ Atmp[ k - n - 1 ] = (silk_float)( ( tmp2 - tmp1 * rc ) * rc_mult2 );
}
}
- rc = -Anew[ 0 ];
- if( rc > RC_THRESHOLD || rc < -RC_THRESHOLD ) {
- return 0.0f;
- }
+ rc = -Atmp[ 0 ];
rc_mult1 = 1.0f - rc * rc;
invGain *= rc_mult1;
+ if( invGain * MAX_PREDICTION_POWER_GAIN < 1.0f ) {
+ return 0.0f;
+ }
return (silk_float)invGain;
}
diff --git a/libs/libopus/silk/float/SigProc_FLP.h b/libs/libopus/silk/float/SigProc_FLP.h
index f0cb3733b..953de8b09 100644
--- a/libs/libopus/silk/float/SigProc_FLP.h
+++ b/libs/libopus/silk/float/SigProc_FLP.h
@@ -68,13 +68,6 @@ void silk_k2a_FLP(
opus_int32 order /* I prediction order */
);
-/* Solve the normal equations using the Levinson-Durbin recursion */
-silk_float silk_levinsondurbin_FLP( /* O prediction error energy */
- silk_float A[], /* O prediction coefficients [order] */
- const silk_float corr[], /* I input auto-correlations [order + 1] */
- const opus_int order /* I prediction order */
-);
-
/* compute autocorrelation */
void silk_autocorrelation_FLP(
silk_float *results, /* O result (length correlationCount) */
diff --git a/libs/libopus/silk/float/apply_sine_window_FLP.c b/libs/libopus/silk/float/apply_sine_window_FLP.c
index 6aae57c0a..e49e71799 100644
--- a/libs/libopus/silk/float/apply_sine_window_FLP.c
+++ b/libs/libopus/silk/float/apply_sine_window_FLP.c
@@ -45,10 +45,10 @@ void silk_apply_sine_window_FLP(
opus_int k;
silk_float freq, c, S0, S1;
- silk_assert( win_type == 1 || win_type == 2 );
+ celt_assert( win_type == 1 || win_type == 2 );
/* Length must be multiple of 4 */
- silk_assert( ( length & 3 ) == 0 );
+ celt_assert( ( length & 3 ) == 0 );
freq = PI / ( length + 1 );
diff --git a/libs/libopus/silk/float/burg_modified_FLP.c b/libs/libopus/silk/float/burg_modified_FLP.c
index ea5dc25a9..756b76a35 100644
--- a/libs/libopus/silk/float/burg_modified_FLP.c
+++ b/libs/libopus/silk/float/burg_modified_FLP.c
@@ -52,7 +52,7 @@ silk_float silk_burg_modified_FLP( /* O returns residual energy
double CAf[ SILK_MAX_ORDER_LPC + 1 ], CAb[ SILK_MAX_ORDER_LPC + 1 ];
double Af[ SILK_MAX_ORDER_LPC ];
- silk_assert( subfr_length * nb_subfr <= MAX_FRAME_SIZE );
+ celt_assert( subfr_length * nb_subfr <= MAX_FRAME_SIZE );
/* Compute autocorrelations, added over subframes */
C0 = silk_energy_FLP( x, nb_subfr * subfr_length );
diff --git a/libs/libopus/silk/float/encode_frame_FLP.c b/libs/libopus/silk/float/encode_frame_FLP.c
index 2092a4d9e..b029c3f5c 100644
--- a/libs/libopus/silk/float/encode_frame_FLP.c
+++ b/libs/libopus/silk/float/encode_frame_FLP.c
@@ -29,6 +29,7 @@ POSSIBILITY OF SUCH DAMAGE.
#include "config.h"
#endif
+#include <stdlib.h>
#include "main_FLP.h"
#include "tuning_parameters.h"
@@ -41,21 +42,28 @@ static OPUS_INLINE void silk_LBRR_encode_FLP(
);
void silk_encode_do_VAD_FLP(
- silk_encoder_state_FLP *psEnc /* I/O Encoder state FLP */
+ silk_encoder_state_FLP *psEnc, /* I/O Encoder state FLP */
+ opus_int activity /* I Decision of Opus voice activity detector */
)
{
+ const opus_int activity_threshold = SILK_FIX_CONST( SPEECH_ACTIVITY_DTX_THRES, 8 );
+
/****************************/
/* Voice Activity Detection */
/****************************/
silk_VAD_GetSA_Q8( &psEnc->sCmn, psEnc->sCmn.inputBuf + 1, psEnc->sCmn.arch );
+ /* If Opus VAD is inactive and Silk VAD is active: lower Silk VAD to just under the threshold */
+ if( activity == VAD_NO_ACTIVITY && psEnc->sCmn.speech_activity_Q8 >= activity_threshold ) {
+ psEnc->sCmn.speech_activity_Q8 = activity_threshold - 1;
+ }
/**************************************************/
/* Convert speech activity into VAD and DTX flags */
/**************************************************/
- if( psEnc->sCmn.speech_activity_Q8 < SILK_FIX_CONST( SPEECH_ACTIVITY_DTX_THRES, 8 ) ) {
+ if( psEnc->sCmn.speech_activity_Q8 < activity_threshold ) {
psEnc->sCmn.indices.signalType = TYPE_NO_VOICE_ACTIVITY;
psEnc->sCmn.noSpeechCounter++;
- if( psEnc->sCmn.noSpeechCounter < NB_SPEECH_FRAMES_BEFORE_DTX ) {
+ if( psEnc->sCmn.noSpeechCounter <= NB_SPEECH_FRAMES_BEFORE_DTX ) {
psEnc->sCmn.inDTX = 0;
} else if( psEnc->sCmn.noSpeechCounter > MAX_CONSECUTIVE_DTX + NB_SPEECH_FRAMES_BEFORE_DTX ) {
psEnc->sCmn.noSpeechCounter = NB_SPEECH_FRAMES_BEFORE_DTX;
@@ -85,7 +93,6 @@ opus_int silk_encode_frame_FLP(
silk_encoder_control_FLP sEncCtrl;
opus_int i, iter, maxIter, found_upper, found_lower, ret = 0;
silk_float *x_frame, *res_pitch_frame;
- silk_float xfw[ MAX_FRAME_LENGTH ];
silk_float res_pitch[ 2 * MAX_FRAME_LENGTH + LA_PITCH_MAX ];
ec_enc sRangeEnc_copy, sRangeEnc_copy2;
silk_nsq_state sNSQ_copy, sNSQ_copy2;
@@ -97,6 +104,9 @@ opus_int silk_encode_frame_FLP(
opus_int8 LastGainIndex_copy2;
opus_int32 pGains_Q16[ MAX_NB_SUBFR ];
opus_uint8 ec_buf_copy[ 1275 ];
+ opus_int gain_lock[ MAX_NB_SUBFR ] = {0};
+ opus_int16 best_gain_mult[ MAX_NB_SUBFR ];
+ opus_int best_sum[ MAX_NB_SUBFR ];
/* This is totally unnecessary but many compilers (including gcc) are too dumb to realise it */
LastGainIndex_copy2 = nBits_lower = nBits_upper = gainMult_lower = gainMult_upper = 0;
@@ -139,22 +149,17 @@ opus_int silk_encode_frame_FLP(
/***************************************************/
/* Find linear prediction coefficients (LPC + LTP) */
/***************************************************/
- silk_find_pred_coefs_FLP( psEnc, &sEncCtrl, res_pitch, x_frame, condCoding );
+ silk_find_pred_coefs_FLP( psEnc, &sEncCtrl, res_pitch_frame, x_frame, condCoding );
/****************************************/
/* Process gains */
/****************************************/
silk_process_gains_FLP( psEnc, &sEncCtrl, condCoding );
- /*****************************************/
- /* Prefiltering for noise shaper */
- /*****************************************/
- silk_prefilter_FLP( psEnc, &sEncCtrl, xfw, x_frame );
-
/****************************************/
/* Low Bitrate Redundant Encoding */
/****************************************/
- silk_LBRR_encode_FLP( psEnc, &sEncCtrl, xfw, condCoding );
+ silk_LBRR_encode_FLP( psEnc, &sEncCtrl, x_frame, condCoding );
/* Loop over quantizer and entroy coding to control bitrate */
maxIter = 6;
@@ -188,7 +193,11 @@ opus_int silk_encode_frame_FLP(
/*****************************************/
/* Noise shaping quantization */
/*****************************************/
- silk_NSQ_wrapper_FLP( psEnc, &sEncCtrl, &psEnc->sCmn.indices, &psEnc->sCmn.sNSQ, psEnc->sCmn.pulses, xfw );
+ silk_NSQ_wrapper_FLP( psEnc, &sEncCtrl, &psEnc->sCmn.indices, &psEnc->sCmn.sNSQ, psEnc->sCmn.pulses, x_frame );
+
+ if ( iter == maxIter && !found_lower ) {
+ silk_memcpy( &sRangeEnc_copy2, psRangeEnc, sizeof( ec_enc ) );
+ }
/****************************************/
/* Encode Parameters */
@@ -203,6 +212,33 @@ opus_int silk_encode_frame_FLP(
nBits = ec_tell( psRangeEnc );
+ /* If we still bust after the last iteration, do some damage control. */
+ if ( iter == maxIter && !found_lower && nBits > maxBits ) {
+ silk_memcpy( psRangeEnc, &sRangeEnc_copy2, sizeof( ec_enc ) );
+
+ /* Keep gains the same as the last frame. */
+ psEnc->sShape.LastGainIndex = sEncCtrl.lastGainIndexPrev;
+ for ( i = 0; i < psEnc->sCmn.nb_subfr; i++ ) {
+ psEnc->sCmn.indices.GainsIndices[ i ] = 4;
+ }
+ if (condCoding != CODE_CONDITIONALLY) {
+ psEnc->sCmn.indices.GainsIndices[ 0 ] = sEncCtrl.lastGainIndexPrev;
+ }
+ psEnc->sCmn.ec_prevLagIndex = ec_prevLagIndex_copy;
+ psEnc->sCmn.ec_prevSignalType = ec_prevSignalType_copy;
+ /* Clear all pulses. */
+ for ( i = 0; i < psEnc->sCmn.frame_length; i++ ) {
+ psEnc->sCmn.pulses[ i ] = 0;
+ }
+
+ silk_encode_indices( &psEnc->sCmn, psRangeEnc, psEnc->sCmn.nFramesEncoded, 0, condCoding );
+
+ silk_encode_pulses( psRangeEnc, psEnc->sCmn.indices.signalType, psEnc->sCmn.indices.quantOffsetType,
+ psEnc->sCmn.pulses, psEnc->sCmn.frame_length );
+
+ nBits = ec_tell( psRangeEnc );
+ }
+
if( useCBR == 0 && iter == 0 && nBits <= maxBits ) {
break;
}
@@ -212,7 +248,7 @@ opus_int silk_encode_frame_FLP(
if( found_lower && ( gainsID == gainsID_lower || nBits > maxBits ) ) {
/* Restore output state from earlier iteration that did meet the bitrate budget */
silk_memcpy( psRangeEnc, &sRangeEnc_copy2, sizeof( ec_enc ) );
- silk_assert( sRangeEnc_copy2.offs <= 1275 );
+ celt_assert( sRangeEnc_copy2.offs <= 1275 );
silk_memcpy( psRangeEnc->buf, ec_buf_copy, sRangeEnc_copy2.offs );
silk_memcpy( &psEnc->sCmn.sNSQ, &sNSQ_copy2, sizeof( silk_nsq_state ) );
psEnc->sShape.LastGainIndex = LastGainIndex_copy2;
@@ -223,7 +259,9 @@ opus_int silk_encode_frame_FLP(
if( nBits > maxBits ) {
if( found_lower == 0 && iter >= 2 ) {
/* Adjust the quantizer's rate/distortion tradeoff and discard previous "upper" results */
- sEncCtrl.Lambda *= 1.5f;
+ sEncCtrl.Lambda = silk_max_float(sEncCtrl.Lambda*1.5f, 1.5f);
+ /* Reducing dithering can help us hit the target. */
+ psEnc->sCmn.indices.quantOffsetType = 0;
found_upper = 0;
gainsID_upper = -1;
} else {
@@ -240,7 +278,7 @@ opus_int silk_encode_frame_FLP(
gainsID_lower = gainsID;
/* Copy part of the output state */
silk_memcpy( &sRangeEnc_copy2, psRangeEnc, sizeof( ec_enc ) );
- silk_assert( psRangeEnc->offs <= 1275 );
+ celt_assert( psRangeEnc->offs <= 1275 );
silk_memcpy( ec_buf_copy, psRangeEnc->buf, psRangeEnc->offs );
silk_memcpy( &sNSQ_copy2, &psEnc->sCmn.sNSQ, sizeof( silk_nsq_state ) );
LastGainIndex_copy2 = psEnc->sShape.LastGainIndex;
@@ -250,15 +288,34 @@ opus_int silk_encode_frame_FLP(
break;
}
+ if ( !found_lower && nBits > maxBits ) {
+ int j;
+ for ( i = 0; i < psEnc->sCmn.nb_subfr; i++ ) {
+ int sum=0;
+ for ( j = i*psEnc->sCmn.subfr_length; j < (i+1)*psEnc->sCmn.subfr_length; j++ ) {
+ sum += abs( psEnc->sCmn.pulses[j] );
+ }
+ if ( iter == 0 || (sum < best_sum[i] && !gain_lock[i]) ) {
+ best_sum[i] = sum;
+ best_gain_mult[i] = gainMult_Q8;
+ } else {
+ gain_lock[i] = 1;
+ }
+ }
+ }
if( ( found_lower & found_upper ) == 0 ) {
/* Adjust gain according to high-rate rate/distortion curve */
- opus_int32 gain_factor_Q16;
- gain_factor_Q16 = silk_log2lin( silk_LSHIFT( nBits - maxBits, 7 ) / psEnc->sCmn.frame_length + SILK_FIX_CONST( 16, 7 ) );
- gain_factor_Q16 = silk_min_32( gain_factor_Q16, SILK_FIX_CONST( 2, 16 ) );
if( nBits > maxBits ) {
- gain_factor_Q16 = silk_max_32( gain_factor_Q16, SILK_FIX_CONST( 1.3, 16 ) );
+ if (gainMult_Q8 < 16384) {
+ gainMult_Q8 *= 2;
+ } else {
+ gainMult_Q8 = 32767;
+ }
+ } else {
+ opus_int32 gain_factor_Q16;
+ gain_factor_Q16 = silk_log2lin( silk_LSHIFT( nBits - maxBits, 7 ) / psEnc->sCmn.frame_length + SILK_FIX_CONST( 16, 7 ) );
+ gainMult_Q8 = silk_SMULWB( gain_factor_Q16, gainMult_Q8 );
}
- gainMult_Q8 = silk_SMULWB( gain_factor_Q16, gainMult_Q8 );
} else {
/* Adjust gain by interpolating */
gainMult_Q8 = gainMult_lower + ( ( gainMult_upper - gainMult_lower ) * ( maxBits - nBits_lower ) ) / ( nBits_upper - nBits_lower );
@@ -272,7 +329,13 @@ opus_int silk_encode_frame_FLP(
}
for( i = 0; i < psEnc->sCmn.nb_subfr; i++ ) {
- pGains_Q16[ i ] = silk_LSHIFT_SAT32( silk_SMULWB( sEncCtrl.GainsUnq_Q16[ i ], gainMult_Q8 ), 8 );
+ opus_int16 tmp;
+ if ( gain_lock[i] ) {
+ tmp = best_gain_mult[i];
+ } else {
+ tmp = gainMult_Q8;
+ }
+ pGains_Q16[ i ] = silk_LSHIFT_SAT32( silk_SMULWB( sEncCtrl.GainsUnq_Q16[ i ], tmp ), 8 );
}
/* Quantize gains */
diff --git a/libs/libopus/silk/float/energy_FLP.c b/libs/libopus/silk/float/energy_FLP.c
index 24b8179f9..7bc7173c9 100644
--- a/libs/libopus/silk/float/energy_FLP.c
+++ b/libs/libopus/silk/float/energy_FLP.c
@@ -37,13 +37,12 @@ double silk_energy_FLP(
opus_int dataSize
)
{
- opus_int i, dataSize4;
+ opus_int i;
double result;
/* 4x unrolled loop */
result = 0.0;
- dataSize4 = dataSize & 0xFFFC;
- for( i = 0; i < dataSize4; i += 4 ) {
+ for( i = 0; i < dataSize - 3; i += 4 ) {
result += data[ i + 0 ] * (double)data[ i + 0 ] +
data[ i + 1 ] * (double)data[ i + 1 ] +
data[ i + 2 ] * (double)data[ i + 2 ] +
diff --git a/libs/libopus/silk/float/find_LPC_FLP.c b/libs/libopus/silk/float/find_LPC_FLP.c
index fcfe1c368..fa3ffe7f8 100644
--- a/libs/libopus/silk/float/find_LPC_FLP.c
+++ b/libs/libopus/silk/float/find_LPC_FLP.c
@@ -73,7 +73,7 @@ void silk_find_LPC_FLP(
silk_interpolate( NLSF0_Q15, psEncC->prev_NLSFq_Q15, NLSF_Q15, k, psEncC->predictLPCOrder );
/* Convert to LPC for residual energy evaluation */
- silk_NLSF2A_FLP( a_tmp, NLSF0_Q15, psEncC->predictLPCOrder );
+ silk_NLSF2A_FLP( a_tmp, NLSF0_Q15, psEncC->predictLPCOrder, psEncC->arch );
/* Calculate residual energy with LSF interpolation */
silk_LPC_analysis_filter_FLP( LPC_res, a_tmp, x, 2 * subfr_length, psEncC->predictLPCOrder );
@@ -99,6 +99,6 @@ void silk_find_LPC_FLP(
silk_A2NLSF_FLP( NLSF_Q15, a, psEncC->predictLPCOrder );
}
- silk_assert( psEncC->indices.NLSFInterpCoef_Q2 == 4 ||
+ celt_assert( psEncC->indices.NLSFInterpCoef_Q2 == 4 ||
( psEncC->useInterpolatedNLSFs && !psEncC->first_frame_after_reset && psEncC->nb_subfr == MAX_NB_SUBFR ) );
}
diff --git a/libs/libopus/silk/float/find_LTP_FLP.c b/libs/libopus/silk/float/find_LTP_FLP.c
index 722999601..f97064930 100644
--- a/libs/libopus/silk/float/find_LTP_FLP.c
+++ b/libs/libopus/silk/float/find_LTP_FLP.c
@@ -33,100 +33,32 @@ POSSIBILITY OF SUCH DAMAGE.
#include "tuning_parameters.h"
void silk_find_LTP_FLP(
- silk_float b[ MAX_NB_SUBFR * LTP_ORDER ], /* O LTP coefs */
- silk_float WLTP[ MAX_NB_SUBFR * LTP_ORDER * LTP_ORDER ], /* O Weight for LTP quantization */
- silk_float *LTPredCodGain, /* O LTP coding gain */
- const silk_float r_lpc[], /* I LPC residual */
- const opus_int lag[ MAX_NB_SUBFR ], /* I LTP lags */
- const silk_float Wght[ MAX_NB_SUBFR ], /* I Weights */
+ silk_float XX[ MAX_NB_SUBFR * LTP_ORDER * LTP_ORDER ], /* O Weight for LTP quantization */
+ silk_float xX[ MAX_NB_SUBFR * LTP_ORDER ], /* O Weight for LTP quantization */
+ const silk_float r_ptr[], /* I LPC residual */
+ const opus_int lag[ MAX_NB_SUBFR ], /* I LTP lags */
const opus_int subfr_length, /* I Subframe length */
- const opus_int nb_subfr, /* I number of subframes */
- const opus_int mem_offset /* I Number of samples in LTP memory */
+ const opus_int nb_subfr /* I number of subframes */
)
{
- opus_int i, k;
- silk_float *b_ptr, temp, *WLTP_ptr;
- silk_float LPC_res_nrg, LPC_LTP_res_nrg;
- silk_float d[ MAX_NB_SUBFR ], m, g, delta_b[ LTP_ORDER ];
- silk_float w[ MAX_NB_SUBFR ], nrg[ MAX_NB_SUBFR ], regu;
- silk_float Rr[ LTP_ORDER ], rr[ MAX_NB_SUBFR ];
- const silk_float *r_ptr, *lag_ptr;
+ opus_int k;
+ silk_float *xX_ptr, *XX_ptr;
+ const silk_float *lag_ptr;
+ silk_float xx, temp;
- b_ptr = b;
- WLTP_ptr = WLTP;
- r_ptr = &r_lpc[ mem_offset ];
+ xX_ptr = xX;
+ XX_ptr = XX;
for( k = 0; k < nb_subfr; k++ ) {
lag_ptr = r_ptr - ( lag[ k ] + LTP_ORDER / 2 );
+ silk_corrMatrix_FLP( lag_ptr, subfr_length, LTP_ORDER, XX_ptr );
+ silk_corrVector_FLP( lag_ptr, r_ptr, subfr_length, LTP_ORDER, xX_ptr );
+ xx = ( silk_float )silk_energy_FLP( r_ptr, subfr_length + LTP_ORDER );
+ temp = 1.0f / silk_max( xx, LTP_CORR_INV_MAX * 0.5f * ( XX_ptr[ 0 ] + XX_ptr[ 24 ] ) + 1.0f );
+ silk_scale_vector_FLP( XX_ptr, temp, LTP_ORDER * LTP_ORDER );
+ silk_scale_vector_FLP( xX_ptr, temp, LTP_ORDER );
- silk_corrMatrix_FLP( lag_ptr, subfr_length, LTP_ORDER, WLTP_ptr );
- silk_corrVector_FLP( lag_ptr, r_ptr, subfr_length, LTP_ORDER, Rr );
-
- rr[ k ] = ( silk_float )silk_energy_FLP( r_ptr, subfr_length );
- regu = 1.0f + rr[ k ] +
- matrix_ptr( WLTP_ptr, 0, 0, LTP_ORDER ) +
- matrix_ptr( WLTP_ptr, LTP_ORDER-1, LTP_ORDER-1, LTP_ORDER );
- regu *= LTP_DAMPING / 3;
- silk_regularize_correlations_FLP( WLTP_ptr, &rr[ k ], regu, LTP_ORDER );
- silk_solve_LDL_FLP( WLTP_ptr, LTP_ORDER, Rr, b_ptr );
-
- /* Calculate residual energy */
- nrg[ k ] = silk_residual_energy_covar_FLP( b_ptr, WLTP_ptr, Rr, rr[ k ], LTP_ORDER );
-
- temp = Wght[ k ] / ( nrg[ k ] * Wght[ k ] + 0.01f * subfr_length );
- silk_scale_vector_FLP( WLTP_ptr, temp, LTP_ORDER * LTP_ORDER );
- w[ k ] = matrix_ptr( WLTP_ptr, LTP_ORDER / 2, LTP_ORDER / 2, LTP_ORDER );
-
- r_ptr += subfr_length;
- b_ptr += LTP_ORDER;
- WLTP_ptr += LTP_ORDER * LTP_ORDER;
- }
-
- /* Compute LTP coding gain */
- if( LTPredCodGain != NULL ) {
- LPC_LTP_res_nrg = 1e-6f;
- LPC_res_nrg = 0.0f;
- for( k = 0; k < nb_subfr; k++ ) {
- LPC_res_nrg += rr[ k ] * Wght[ k ];
- LPC_LTP_res_nrg += nrg[ k ] * Wght[ k ];
- }
-
- silk_assert( LPC_LTP_res_nrg > 0 );
- *LTPredCodGain = 3.0f * silk_log2( LPC_res_nrg / LPC_LTP_res_nrg );
- }
-
- /* Smoothing */
- /* d = sum( B, 1 ); */
- b_ptr = b;
- for( k = 0; k < nb_subfr; k++ ) {
- d[ k ] = 0;
- for( i = 0; i < LTP_ORDER; i++ ) {
- d[ k ] += b_ptr[ i ];
- }
- b_ptr += LTP_ORDER;
- }
- /* m = ( w * d' ) / ( sum( w ) + 1e-3 ); */
- temp = 1e-3f;
- for( k = 0; k < nb_subfr; k++ ) {
- temp += w[ k ];
- }
- m = 0;
- for( k = 0; k < nb_subfr; k++ ) {
- m += d[ k ] * w[ k ];
- }
- m = m / temp;
-
- b_ptr = b;
- for( k = 0; k < nb_subfr; k++ ) {
- g = LTP_SMOOTHING / ( LTP_SMOOTHING + w[ k ] ) * ( m - d[ k ] );
- temp = 0;
- for( i = 0; i < LTP_ORDER; i++ ) {
- delta_b[ i ] = silk_max_float( b_ptr[ i ], 0.1f );
- temp += delta_b[ i ];
- }
- temp = g / temp;
- for( i = 0; i < LTP_ORDER; i++ ) {
- b_ptr[ i ] = b_ptr[ i ] + delta_b[ i ] * temp;
- }
- b_ptr += LTP_ORDER;
+ r_ptr += subfr_length;
+ XX_ptr += LTP_ORDER * LTP_ORDER;
+ xX_ptr += LTP_ORDER;
}
}
diff --git a/libs/libopus/silk/float/find_pitch_lags_FLP.c b/libs/libopus/silk/float/find_pitch_lags_FLP.c
index f3b22d25c..dedbcd283 100644
--- a/libs/libopus/silk/float/find_pitch_lags_FLP.c
+++ b/libs/libopus/silk/float/find_pitch_lags_FLP.c
@@ -56,7 +56,7 @@ void silk_find_pitch_lags_FLP(
buf_len = psEnc->sCmn.la_pitch + psEnc->sCmn.frame_length + psEnc->sCmn.ltp_mem_length;
/* Safety check */
- silk_assert( buf_len >= psEnc->sCmn.pitch_LPC_win_length );
+ celt_assert( buf_len >= psEnc->sCmn.pitch_LPC_win_length );
x_buf = x - psEnc->sCmn.ltp_mem_length;
diff --git a/libs/libopus/silk/float/find_pred_coefs_FLP.c b/libs/libopus/silk/float/find_pred_coefs_FLP.c
index 1af4fe5f1..dcf7c5202 100644
--- a/libs/libopus/silk/float/find_pred_coefs_FLP.c
+++ b/libs/libopus/silk/float/find_pred_coefs_FLP.c
@@ -41,8 +41,9 @@ void silk_find_pred_coefs_FLP(
)
{
opus_int i;
- silk_float WLTP[ MAX_NB_SUBFR * LTP_ORDER * LTP_ORDER ];
- silk_float invGains[ MAX_NB_SUBFR ], Wght[ MAX_NB_SUBFR ];
+ silk_float XXLTP[ MAX_NB_SUBFR * LTP_ORDER * LTP_ORDER ];
+ silk_float xXLTP[ MAX_NB_SUBFR * LTP_ORDER ];
+ silk_float invGains[ MAX_NB_SUBFR ];
opus_int16 NLSF_Q15[ MAX_LPC_ORDER ];
const silk_float *x_ptr;
silk_float *x_pre_ptr, LPC_in_pre[ MAX_NB_SUBFR * MAX_LPC_ORDER + MAX_FRAME_LENGTH ];
@@ -52,23 +53,20 @@ void silk_find_pred_coefs_FLP(
for( i = 0; i < psEnc->sCmn.nb_subfr; i++ ) {
silk_assert( psEncCtrl->Gains[ i ] > 0.0f );
invGains[ i ] = 1.0f / psEncCtrl->Gains[ i ];
- Wght[ i ] = invGains[ i ] * invGains[ i ];
}
if( psEnc->sCmn.indices.signalType == TYPE_VOICED ) {
/**********/
/* VOICED */
/**********/
- silk_assert( psEnc->sCmn.ltp_mem_length - psEnc->sCmn.predictLPCOrder >= psEncCtrl->pitchL[ 0 ] + LTP_ORDER / 2 );
+ celt_assert( psEnc->sCmn.ltp_mem_length - psEnc->sCmn.predictLPCOrder >= psEncCtrl->pitchL[ 0 ] + LTP_ORDER / 2 );
/* LTP analysis */
- silk_find_LTP_FLP( psEncCtrl->LTPCoef, WLTP, &psEncCtrl->LTPredCodGain, res_pitch,
- psEncCtrl->pitchL, Wght, psEnc->sCmn.subfr_length, psEnc->sCmn.nb_subfr, psEnc->sCmn.ltp_mem_length );
+ silk_find_LTP_FLP( XXLTP, xXLTP, res_pitch, psEncCtrl->pitchL, psEnc->sCmn.subfr_length, psEnc->sCmn.nb_subfr );
/* Quantize LTP gain parameters */
silk_quant_LTP_gains_FLP( psEncCtrl->LTPCoef, psEnc->sCmn.indices.LTPIndex, &psEnc->sCmn.indices.PERIndex,
- &psEnc->sCmn.sum_log_gain_Q7, WLTP, psEnc->sCmn.mu_LTP_Q9, psEnc->sCmn.LTPQuantLowComplexity, psEnc->sCmn.nb_subfr,
- psEnc->sCmn.arch );
+ &psEnc->sCmn.sum_log_gain_Q7, &psEncCtrl->LTPredCodGain, XXLTP, xXLTP, psEnc->sCmn.subfr_length, psEnc->sCmn.nb_subfr, psEnc->sCmn.arch );
/* Control LTP scaling */
silk_LTP_scale_ctrl_FLP( psEnc, psEncCtrl, condCoding );
diff --git a/libs/libopus/silk/float/inner_product_FLP.c b/libs/libopus/silk/float/inner_product_FLP.c
index 029c01291..cdd39d24c 100644
--- a/libs/libopus/silk/float/inner_product_FLP.c
+++ b/libs/libopus/silk/float/inner_product_FLP.c
@@ -38,13 +38,12 @@ double silk_inner_product_FLP(
opus_int dataSize
)
{
- opus_int i, dataSize4;
+ opus_int i;
double result;
/* 4x unrolled loop */
result = 0.0;
- dataSize4 = dataSize & 0xFFFC;
- for( i = 0; i < dataSize4; i += 4 ) {
+ for( i = 0; i < dataSize - 3; i += 4 ) {
result += data1[ i + 0 ] * (double)data2[ i + 0 ] +
data1[ i + 1 ] * (double)data2[ i + 1 ] +
data1[ i + 2 ] * (double)data2[ i + 2 ] +
diff --git a/libs/libopus/silk/float/k2a_FLP.c b/libs/libopus/silk/float/k2a_FLP.c
index 12af4e766..1448008db 100644
--- a/libs/libopus/silk/float/k2a_FLP.c
+++ b/libs/libopus/silk/float/k2a_FLP.c
@@ -39,15 +39,16 @@ void silk_k2a_FLP(
)
{
opus_int k, n;
- silk_float Atmp[ SILK_MAX_ORDER_LPC ];
+ silk_float rck, tmp1, tmp2;
for( k = 0; k < order; k++ ) {
- for( n = 0; n < k; n++ ) {
- Atmp[ n ] = A[ n ];
+ rck = rc[ k ];
+ for( n = 0; n < (k + 1) >> 1; n++ ) {
+ tmp1 = A[ n ];
+ tmp2 = A[ k - n - 1 ];
+ A[ n ] = tmp1 + tmp2 * rck;
+ A[ k - n - 1 ] = tmp2 + tmp1 * rck;
}
- for( n = 0; n < k; n++ ) {
- A[ n ] += Atmp[ k - n - 1 ] * rc[ k ];
- }
- A[ k ] = -rc[ k ];
+ A[ k ] = -rck;
}
}
diff --git a/libs/libopus/silk/float/levinsondurbin_FLP.c b/libs/libopus/silk/float/levinsondurbin_FLP.c
deleted file mode 100644
index f0ba60698..000000000
--- a/libs/libopus/silk/float/levinsondurbin_FLP.c
+++ /dev/null
@@ -1,81 +0,0 @@
-/***********************************************************************
-Copyright (c) 2006-2011, Skype Limited. All rights reserved.
-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 "SigProc_FLP.h"
-
-/* Solve the normal equations using the Levinson-Durbin recursion */
-silk_float silk_levinsondurbin_FLP( /* O prediction error energy */
- silk_float A[], /* O prediction coefficients [order] */
- const silk_float corr[], /* I input auto-correlations [order + 1] */
- const opus_int order /* I prediction order */
-)
-{
- opus_int i, mHalf, m;
- silk_float min_nrg, nrg, t, km, Atmp1, Atmp2;
-
- min_nrg = 1e-12f * corr[ 0 ] + 1e-9f;
- nrg = corr[ 0 ];
- nrg = silk_max_float(min_nrg, nrg);
- A[ 0 ] = corr[ 1 ] / nrg;
- nrg -= A[ 0 ] * corr[ 1 ];
- nrg = silk_max_float(min_nrg, nrg);
-
- for( m = 1; m < order; m++ )
- {
- t = corr[ m + 1 ];
- for( i = 0; i < m; i++ ) {
- t -= A[ i ] * corr[ m - i ];
- }
-
- /* reflection coefficient */
- km = t / nrg;
-
- /* residual energy */
- nrg -= km * t;
- nrg = silk_max_float(min_nrg, nrg);
-
- mHalf = m >> 1;
- for( i = 0; i < mHalf; i++ ) {
- Atmp1 = A[ i ];
- Atmp2 = A[ m - i - 1 ];
- A[ m - i - 1 ] -= km * Atmp1;
- A[ i ] -= km * Atmp2;
- }
- if( m & 1 ) {
- A[ mHalf ] -= km * A[ mHalf ];
- }
- A[ m ] = km;
- }
-
- /* return the residual energy */
- return nrg;
-}
-
diff --git a/libs/libopus/silk/float/main_FLP.h b/libs/libopus/silk/float/main_FLP.h
index e5a75972e..5dc0ccf4a 100644
--- a/libs/libopus/silk/float/main_FLP.h
+++ b/libs/libopus/silk/float/main_FLP.h
@@ -56,7 +56,8 @@ void silk_HP_variable_cutoff(
/* Encoder main function */
void silk_encode_do_VAD_FLP(
- silk_encoder_state_FLP *psEnc /* I/O Encoder state FLP */
+ silk_encoder_state_FLP *psEnc, /* I/O Encoder state FLP */
+ opus_int activity /* I Decision of Opus voice activity detector */
);
/* Encoder main function */
@@ -79,22 +80,11 @@ opus_int silk_init_encoder(
opus_int silk_control_encoder(
silk_encoder_state_FLP *psEnc, /* I/O Pointer to Silk encoder state FLP */
silk_EncControlStruct *encControl, /* I Control structure */
- const opus_int32 TargetRate_bps, /* I Target max bitrate (bps) */
const opus_int allow_bw_switch, /* I Flag to allow switching audio bandwidth */
const opus_int channelNb, /* I Channel number */
const opus_int force_fs_kHz
);
-/****************/
-/* Prefiltering */
-/****************/
-void silk_prefilter_FLP(
- silk_encoder_state_FLP *psEnc, /* I/O Encoder state FLP */
- const silk_encoder_control_FLP *psEncCtrl, /* I Encoder control FLP */
- silk_float xw[], /* O Weighted signal */
- const silk_float x[] /* I Speech signal */
-);
-
/**************************/
/* Noise shaping analysis */
/**************************/
@@ -153,15 +143,12 @@ void silk_find_LPC_FLP(
/* LTP analysis */
void silk_find_LTP_FLP(
- silk_float b[ MAX_NB_SUBFR * LTP_ORDER ], /* O LTP coefs */
- silk_float WLTP[ MAX_NB_SUBFR * LTP_ORDER * LTP_ORDER ], /* O Weight for LTP quantization */
- silk_float *LTPredCodGain, /* O LTP coding gain */
- const silk_float r_lpc[], /* I LPC residual */
+ silk_float XX[ MAX_NB_SUBFR * LTP_ORDER * LTP_ORDER ], /* O Weight for LTP quantization */
+ silk_float xX[ MAX_NB_SUBFR * LTP_ORDER ], /* O Weight for LTP quantization */
+ const silk_float r_ptr[], /* I LPC residual */
const opus_int lag[ MAX_NB_SUBFR ], /* I LTP lags */
- const silk_float Wght[ MAX_NB_SUBFR ], /* I Weights */
const opus_int subfr_length, /* I Subframe length */
- const opus_int nb_subfr, /* I number of subframes */
- const opus_int mem_offset /* I Number of samples in LTP memory */
+ const opus_int nb_subfr /* I number of subframes */
);
void silk_LTP_analysis_filter_FLP(
@@ -198,14 +185,15 @@ void silk_LPC_analysis_filter_FLP(
/* LTP tap quantizer */
void silk_quant_LTP_gains_FLP(
- silk_float B[ MAX_NB_SUBFR * LTP_ORDER ], /* I/O (Un-)quantized LTP gains */
+ silk_float B[ MAX_NB_SUBFR * LTP_ORDER ], /* O Quantized LTP gains */
opus_int8 cbk_index[ MAX_NB_SUBFR ], /* O Codebook index */
opus_int8 *periodicity_index, /* O Periodicity index */
opus_int32 *sum_log_gain_Q7, /* I/O Cumulative max prediction gain */
- const silk_float W[ MAX_NB_SUBFR * LTP_ORDER * LTP_ORDER ], /* I Error weights */
- const opus_int mu_Q10, /* I Mu value (R/D tradeoff) */
- const opus_int lowComplexity, /* I Flag for low complexity */
- const opus_int nb_subfr, /* I number of subframes */
+ silk_float *pred_gain_dB, /* O LTP prediction gain */
+ const silk_float XX[ MAX_NB_SUBFR * LTP_ORDER * LTP_ORDER ], /* I Correlation matrix */
+ const silk_float xX[ MAX_NB_SUBFR * LTP_ORDER ], /* I Correlation vector */
+ const opus_int subfr_len, /* I Number of samples per subframe */
+ const opus_int nb_subfr, /* I Number of subframes */
int arch /* I Run-time architecture */
);
@@ -245,22 +233,6 @@ void silk_corrVector_FLP(
silk_float *Xt /* O X'*t correlation vector [order] */
);
-/* Add noise to matrix diagonal */
-void silk_regularize_correlations_FLP(
- silk_float *XX, /* I/O Correlation matrices */
- silk_float *xx, /* I/O Correlation values */
- const silk_float noise, /* I Noise energy to add */
- const opus_int D /* I Dimension of XX */
-);
-
-/* Function to solve linear equation Ax = b, where A is an MxM symmetric matrix */
-void silk_solve_LDL_FLP(
- silk_float *A, /* I/O Symmetric square matrix, out: reg. */
- const opus_int M, /* I Size of matrix */
- const silk_float *b, /* I Pointer to b vector */
- silk_float *x /* O Pointer to x solution vector */
-);
-
/* Apply sine window to signal vector. */
/* Window types: */
/* 1 -> sine window from 0 to pi/2 */
@@ -285,7 +257,8 @@ void silk_A2NLSF_FLP(
void silk_NLSF2A_FLP(
silk_float *pAR, /* O LPC coefficients [ LPC_order ] */
const opus_int16 *NLSF_Q15, /* I NLSF vector [ LPC_order ] */
- const opus_int LPC_order /* I LPC order */
+ const opus_int LPC_order, /* I LPC order */
+ int arch /* I Run-time architecture */
);
/* Limit, stabilize, and quantize NLSFs */
diff --git a/libs/libopus/silk/float/noise_shape_analysis_FLP.c b/libs/libopus/silk/float/noise_shape_analysis_FLP.c
index 65f6ea587..cb3d8a50b 100644
--- a/libs/libopus/silk/float/noise_shape_analysis_FLP.c
+++ b/libs/libopus/silk/float/noise_shape_analysis_FLP.c
@@ -55,25 +55,21 @@ static OPUS_INLINE silk_float warped_gain(
/* Convert warped filter coefficients to monic pseudo-warped coefficients and limit maximum */
/* amplitude of monic warped coefficients by using bandwidth expansion on the true coefficients */
static OPUS_INLINE void warped_true2monic_coefs(
- silk_float *coefs_syn,
- silk_float *coefs_ana,
+ silk_float *coefs,
silk_float lambda,
silk_float limit,
opus_int order
) {
opus_int i, iter, ind = 0;
- silk_float tmp, maxabs, chirp, gain_syn, gain_ana;
+ silk_float tmp, maxabs, chirp, gain;
/* Convert to monic coefficients */
for( i = order - 1; i > 0; i-- ) {
- coefs_syn[ i - 1 ] -= lambda * coefs_syn[ i ];
- coefs_ana[ i - 1 ] -= lambda * coefs_ana[ i ];
+ coefs[ i - 1 ] -= lambda * coefs[ i ];
}
- gain_syn = ( 1.0f - lambda * lambda ) / ( 1.0f + lambda * coefs_syn[ 0 ] );
- gain_ana = ( 1.0f - lambda * lambda ) / ( 1.0f + lambda * coefs_ana[ 0 ] );
+ gain = ( 1.0f - lambda * lambda ) / ( 1.0f + lambda * coefs[ 0 ] );
for( i = 0; i < order; i++ ) {
- coefs_syn[ i ] *= gain_syn;
- coefs_ana[ i ] *= gain_ana;
+ coefs[ i ] *= gain;
}
/* Limit */
@@ -81,7 +77,7 @@ static OPUS_INLINE void warped_true2monic_coefs(
/* Find maximum absolute value */
maxabs = -1.0f;
for( i = 0; i < order; i++ ) {
- tmp = silk_max( silk_abs_float( coefs_syn[ i ] ), silk_abs_float( coefs_ana[ i ] ) );
+ tmp = silk_abs_float( coefs[ i ] );
if( tmp > maxabs ) {
maxabs = tmp;
ind = i;
@@ -94,36 +90,59 @@ static OPUS_INLINE void warped_true2monic_coefs(
/* Convert back to true warped coefficients */
for( i = 1; i < order; i++ ) {
- coefs_syn[ i - 1 ] += lambda * coefs_syn[ i ];
- coefs_ana[ i - 1 ] += lambda * coefs_ana[ i ];
+ coefs[ i - 1 ] += lambda * coefs[ i ];
}
- gain_syn = 1.0f / gain_syn;
- gain_ana = 1.0f / gain_ana;
+ gain = 1.0f / gain;
for( i = 0; i < order; i++ ) {
- coefs_syn[ i ] *= gain_syn;
- coefs_ana[ i ] *= gain_ana;
+ coefs[ i ] *= gain;
}
/* Apply bandwidth expansion */
chirp = 0.99f - ( 0.8f + 0.1f * iter ) * ( maxabs - limit ) / ( maxabs * ( ind + 1 ) );
- silk_bwexpander_FLP( coefs_syn, order, chirp );
- silk_bwexpander_FLP( coefs_ana, order, chirp );
+ silk_bwexpander_FLP( coefs, order, chirp );
/* Convert to monic warped coefficients */
for( i = order - 1; i > 0; i-- ) {
- coefs_syn[ i - 1 ] -= lambda * coefs_syn[ i ];
- coefs_ana[ i - 1 ] -= lambda * coefs_ana[ i ];
+ coefs[ i - 1 ] -= lambda * coefs[ i ];
}
- gain_syn = ( 1.0f - lambda * lambda ) / ( 1.0f + lambda * coefs_syn[ 0 ] );
- gain_ana = ( 1.0f - lambda * lambda ) / ( 1.0f + lambda * coefs_ana[ 0 ] );
+ gain = ( 1.0f - lambda * lambda ) / ( 1.0f + lambda * coefs[ 0 ] );
for( i = 0; i < order; i++ ) {
- coefs_syn[ i ] *= gain_syn;
- coefs_ana[ i ] *= gain_ana;
+ coefs[ i ] *= gain;
}
}
silk_assert( 0 );
}
+static OPUS_INLINE void limit_coefs(
+ silk_float *coefs,
+ silk_float limit,
+ opus_int order
+) {
+ opus_int i, iter, ind = 0;
+ silk_float tmp, maxabs, chirp;
+
+ for( iter = 0; iter < 10; iter++ ) {
+ /* Find maximum absolute value */
+ maxabs = -1.0f;
+ for( i = 0; i < order; i++ ) {
+ tmp = silk_abs_float( coefs[ i ] );
+ if( tmp > maxabs ) {
+ maxabs = tmp;
+ ind = i;
+ }
+ }
+ if( maxabs <= limit ) {
+ /* Coefficients are within range - done */
+ return;
+ }
+
+ /* Apply bandwidth expansion */
+ chirp = 0.99f - ( 0.8f + 0.1f * iter ) * ( maxabs - limit ) / ( maxabs * ( ind + 1 ) );
+ silk_bwexpander_FLP( coefs, order, chirp );
+ }
+ silk_assert( 0 );
+}
+
/* Compute noise shaping coefficients and initial gain values */
void silk_noise_shape_analysis_FLP(
silk_encoder_state_FLP *psEnc, /* I/O Encoder state FLP */
@@ -133,12 +152,13 @@ void silk_noise_shape_analysis_FLP(
)
{
silk_shape_state_FLP *psShapeSt = &psEnc->sShape;
- opus_int k, nSamples;
- silk_float SNR_adj_dB, HarmBoost, HarmShapeGain, Tilt;
- silk_float nrg, pre_nrg, log_energy, log_energy_prev, energy_variation;
- silk_float delta, BWExp1, BWExp2, gain_mult, gain_add, strength, b, warping;
+ opus_int k, nSamples, nSegs;
+ silk_float SNR_adj_dB, HarmShapeGain, Tilt;
+ silk_float nrg, log_energy, log_energy_prev, energy_variation;
+ silk_float BWExp, gain_mult, gain_add, strength, b, warping;
silk_float x_windowed[ SHAPE_LPC_WIN_MAX ];
silk_float auto_corr[ MAX_SHAPE_LPC_ORDER + 1 ];
+ silk_float rc[ MAX_SHAPE_LPC_ORDER + 1 ];
const silk_float *x_ptr, *pitch_res_ptr;
/* Point to start of first LPC analysis block */
@@ -176,14 +196,14 @@ void silk_noise_shape_analysis_FLP(
if( psEnc->sCmn.indices.signalType == TYPE_VOICED ) {
/* Initially set to 0; may be overruled in process_gains(..) */
psEnc->sCmn.indices.quantOffsetType = 0;
- psEncCtrl->sparseness = 0.0f;
} else {
/* Sparseness measure, based on relative fluctuations of energy per 2 milliseconds */
nSamples = 2 * psEnc->sCmn.fs_kHz;
energy_variation = 0.0f;
log_energy_prev = 0.0f;
pitch_res_ptr = pitch_res;
- for( k = 0; k < silk_SMULBB( SUB_FRAME_LENGTH_MS, psEnc->sCmn.nb_subfr ) / 2; k++ ) {
+ nSegs = silk_SMULBB( SUB_FRAME_LENGTH_MS, psEnc->sCmn.nb_subfr ) / 2;
+ for( k = 0; k < nSegs; k++ ) {
nrg = ( silk_float )nSamples + ( silk_float )silk_energy_FLP( pitch_res_ptr, nSamples );
log_energy = silk_log2( nrg );
if( k > 0 ) {
@@ -192,17 +212,13 @@ void silk_noise_shape_analysis_FLP(
log_energy_prev = log_energy;
pitch_res_ptr += nSamples;
}
- psEncCtrl->sparseness = silk_sigmoid( 0.4f * ( energy_variation - 5.0f ) );
/* Set quantization offset depending on sparseness measure */
- if( psEncCtrl->sparseness > SPARSENESS_THRESHOLD_QNT_OFFSET ) {
+ if( energy_variation > ENERGY_VARIATION_THRESHOLD_QNT_OFFSET * (nSegs-1) ) {
psEnc->sCmn.indices.quantOffsetType = 0;
} else {
psEnc->sCmn.indices.quantOffsetType = 1;
}
-
- /* Increase coding SNR for sparse signals */
- SNR_adj_dB += SPARSE_SNR_INCR_dB * ( psEncCtrl->sparseness - 0.5f );
}
/*******************************/
@@ -210,19 +226,10 @@ void silk_noise_shape_analysis_FLP(
/*******************************/
/* More BWE for signals with high prediction gain */
strength = FIND_PITCH_WHITE_NOISE_FRACTION * psEncCtrl->predGain; /* between 0.0 and 1.0 */
- BWExp1 = BWExp2 = BANDWIDTH_EXPANSION / ( 1.0f + strength * strength );
- delta = LOW_RATE_BANDWIDTH_EXPANSION_DELTA * ( 1.0f - 0.75f * psEncCtrl->coding_quality );
- BWExp1 -= delta;
- BWExp2 += delta;
- /* BWExp1 will be applied after BWExp2, so make it relative */
- BWExp1 /= BWExp2;
-
- if( psEnc->sCmn.warping_Q16 > 0 ) {
- /* Slightly more warping in analysis will move quantization noise up in frequency, where it's better masked */
- warping = (silk_float)psEnc->sCmn.warping_Q16 / 65536.0f + 0.01f * psEncCtrl->coding_quality;
- } else {
- warping = 0.0f;
- }
+ BWExp = BANDWIDTH_EXPANSION / ( 1.0f + strength * strength );
+
+ /* Slightly more warping in analysis will move quantization noise up in frequency, where it's better masked */
+ warping = (silk_float)psEnc->sCmn.warping_Q16 / 65536.0f + 0.01f * psEncCtrl->coding_quality;
/********************************************/
/* Compute noise shaping AR coefs and gains */
@@ -252,37 +259,28 @@ void silk_noise_shape_analysis_FLP(
}
/* Add white noise, as a fraction of energy */
- auto_corr[ 0 ] += auto_corr[ 0 ] * SHAPE_WHITE_NOISE_FRACTION;
+ auto_corr[ 0 ] += auto_corr[ 0 ] * SHAPE_WHITE_NOISE_FRACTION + 1.0f;
/* Convert correlations to prediction coefficients, and compute residual energy */
- nrg = silk_levinsondurbin_FLP( &psEncCtrl->AR2[ k * MAX_SHAPE_LPC_ORDER ], auto_corr, psEnc->sCmn.shapingLPCOrder );
+ nrg = silk_schur_FLP( rc, auto_corr, psEnc->sCmn.shapingLPCOrder );
+ silk_k2a_FLP( &psEncCtrl->AR[ k * MAX_SHAPE_LPC_ORDER ], rc, psEnc->sCmn.shapingLPCOrder );
psEncCtrl->Gains[ k ] = ( silk_float )sqrt( nrg );
if( psEnc->sCmn.warping_Q16 > 0 ) {
/* Adjust gain for warping */
- psEncCtrl->Gains[ k ] *= warped_gain( &psEncCtrl->AR2[ k * MAX_SHAPE_LPC_ORDER ], warping, psEnc->sCmn.shapingLPCOrder );
+ psEncCtrl->Gains[ k ] *= warped_gain( &psEncCtrl->AR[ k * MAX_SHAPE_LPC_ORDER ], warping, psEnc->sCmn.shapingLPCOrder );
}
/* Bandwidth expansion for synthesis filter shaping */
- silk_bwexpander_FLP( &psEncCtrl->AR2[ k * MAX_SHAPE_LPC_ORDER ], psEnc->sCmn.shapingLPCOrder, BWExp2 );
-
- /* Compute noise shaping filter coefficients */
- silk_memcpy(
- &psEncCtrl->AR1[ k * MAX_SHAPE_LPC_ORDER ],
- &psEncCtrl->AR2[ k * MAX_SHAPE_LPC_ORDER ],
- psEnc->sCmn.shapingLPCOrder * sizeof( silk_float ) );
+ silk_bwexpander_FLP( &psEncCtrl->AR[ k * MAX_SHAPE_LPC_ORDER ], psEnc->sCmn.shapingLPCOrder, BWExp );
- /* Bandwidth expansion for analysis filter shaping */
- silk_bwexpander_FLP( &psEncCtrl->AR1[ k * MAX_SHAPE_LPC_ORDER ], psEnc->sCmn.shapingLPCOrder, BWExp1 );
-
- /* Ratio of prediction gains, in energy domain */
- pre_nrg = silk_LPC_inverse_pred_gain_FLP( &psEncCtrl->AR2[ k * MAX_SHAPE_LPC_ORDER ], psEnc->sCmn.shapingLPCOrder );
- nrg = silk_LPC_inverse_pred_gain_FLP( &psEncCtrl->AR1[ k * MAX_SHAPE_LPC_ORDER ], psEnc->sCmn.shapingLPCOrder );
- psEncCtrl->GainsPre[ k ] = 1.0f - 0.7f * ( 1.0f - pre_nrg / nrg );
-
- /* Convert to monic warped prediction coefficients and limit absolute values */
- warped_true2monic_coefs( &psEncCtrl->AR2[ k * MAX_SHAPE_LPC_ORDER ], &psEncCtrl->AR1[ k * MAX_SHAPE_LPC_ORDER ],
- warping, 3.999f, psEnc->sCmn.shapingLPCOrder );
+ if( psEnc->sCmn.warping_Q16 > 0 ) {
+ /* Convert to monic warped prediction coefficients and limit absolute values */
+ warped_true2monic_coefs( &psEncCtrl->AR[ k * MAX_SHAPE_LPC_ORDER ], warping, 3.999f, psEnc->sCmn.shapingLPCOrder );
+ } else {
+ /* Limit absolute values */
+ limit_coefs( &psEncCtrl->AR[ k * MAX_SHAPE_LPC_ORDER ], 3.999f, psEnc->sCmn.shapingLPCOrder );
+ }
}
/*****************/
@@ -296,11 +294,6 @@ void silk_noise_shape_analysis_FLP(
psEncCtrl->Gains[ k ] += gain_add;
}
- gain_mult = 1.0f + INPUT_TILT + psEncCtrl->coding_quality * HIGH_RATE_INPUT_TILT;
- for( k = 0; k < psEnc->sCmn.nb_subfr; k++ ) {
- psEncCtrl->GainsPre[ k ] *= gain_mult;
- }
-
/************************************************/
/* Control low-frequency shaping and noise tilt */
/************************************************/
@@ -331,12 +324,6 @@ void silk_noise_shape_analysis_FLP(
/****************************/
/* HARMONIC SHAPING CONTROL */
/****************************/
- /* Control boosting of harmonic frequencies */
- HarmBoost = LOW_RATE_HARMONIC_BOOST * ( 1.0f - psEncCtrl->coding_quality ) * psEnc->LTPCorr;
-
- /* More harmonic boost for noisy input signals */
- HarmBoost += LOW_INPUT_QUALITY_HARMONIC_BOOST * ( 1.0f - psEncCtrl->input_quality );
-
if( USE_HARM_SHAPING && psEnc->sCmn.indices.signalType == TYPE_VOICED ) {
/* Harmonic noise shaping */
HarmShapeGain = HARMONIC_SHAPING;
@@ -355,8 +342,6 @@ void silk_noise_shape_analysis_FLP(
/* Smooth over subframes */
/*************************/
for( k = 0; k < psEnc->sCmn.nb_subfr; k++ ) {
- psShapeSt->HarmBoost_smth += SUBFR_SMTH_COEF * ( HarmBoost - psShapeSt->HarmBoost_smth );
- psEncCtrl->HarmBoost[ k ] = psShapeSt->HarmBoost_smth;
psShapeSt->HarmShapeGain_smth += SUBFR_SMTH_COEF * ( HarmShapeGain - psShapeSt->HarmShapeGain_smth );
psEncCtrl->HarmShapeGain[ k ] = psShapeSt->HarmShapeGain_smth;
psShapeSt->Tilt_smth += SUBFR_SMTH_COEF * ( Tilt - psShapeSt->Tilt_smth );
diff --git a/libs/libopus/silk/float/pitch_analysis_core_FLP.c b/libs/libopus/silk/float/pitch_analysis_core_FLP.c
index d0e637a29..f351bc371 100644
--- a/libs/libopus/silk/float/pitch_analysis_core_FLP.c
+++ b/libs/libopus/silk/float/pitch_analysis_core_FLP.c
@@ -109,11 +109,11 @@ opus_int silk_pitch_analysis_core_FLP( /* O Voicing estimate: 0 voiced,
const opus_int8 *Lag_CB_ptr;
/* Check for valid sampling frequency */
- silk_assert( Fs_kHz == 8 || Fs_kHz == 12 || Fs_kHz == 16 );
+ celt_assert( Fs_kHz == 8 || Fs_kHz == 12 || Fs_kHz == 16 );
/* Check for valid complexity setting */
- silk_assert( complexity >= SILK_PE_MIN_COMPLEX );
- silk_assert( complexity <= SILK_PE_MAX_COMPLEX );
+ celt_assert( complexity >= SILK_PE_MIN_COMPLEX );
+ celt_assert( complexity <= SILK_PE_MAX_COMPLEX );
silk_assert( search_thres1 >= 0.0f && search_thres1 <= 1.0f );
silk_assert( search_thres2 >= 0.0f && search_thres2 <= 1.0f );
@@ -148,7 +148,7 @@ opus_int silk_pitch_analysis_core_FLP( /* O Voicing estimate: 0 voiced,
silk_resampler_down2_3( filt_state, frame_8_FIX, frame_12_FIX, frame_length );
silk_short2float_array( frame_8kHz, frame_8_FIX, frame_length_8kHz );
} else {
- silk_assert( Fs_kHz == 8 );
+ celt_assert( Fs_kHz == 8 );
silk_float2short_array( frame_8_FIX, frame, frame_length_8kHz );
}
@@ -159,7 +159,7 @@ opus_int silk_pitch_analysis_core_FLP( /* O Voicing estimate: 0 voiced,
/* Low-pass filter */
for( i = frame_length_4kHz - 1; i > 0; i-- ) {
- frame_4kHz[ i ] += frame_4kHz[ i - 1 ];
+ frame_4kHz[ i ] = silk_ADD_SAT16( frame_4kHz[ i ], frame_4kHz[ i - 1 ] );
}
/******************************************************************************
@@ -169,14 +169,14 @@ opus_int silk_pitch_analysis_core_FLP( /* O Voicing estimate: 0 voiced,
target_ptr = &frame_4kHz[ silk_LSHIFT( sf_length_4kHz, 2 ) ];
for( k = 0; k < nb_subfr >> 1; k++ ) {
/* Check that we are within range of the array */
- silk_assert( target_ptr >= frame_4kHz );
- silk_assert( target_ptr + sf_length_8kHz <= frame_4kHz + frame_length_4kHz );
+ celt_assert( target_ptr >= frame_4kHz );
+ celt_assert( target_ptr + sf_length_8kHz <= frame_4kHz + frame_length_4kHz );
basis_ptr = target_ptr - min_lag_4kHz;
/* Check that we are within range of the array */
- silk_assert( basis_ptr >= frame_4kHz );
- silk_assert( basis_ptr + sf_length_8kHz <= frame_4kHz + frame_length_4kHz );
+ celt_assert( basis_ptr >= frame_4kHz );
+ celt_assert( basis_ptr + sf_length_8kHz <= frame_4kHz + frame_length_4kHz );
celt_pitch_xcorr( target_ptr, target_ptr-max_lag_4kHz, xcorr, sf_length_8kHz, max_lag_4kHz - min_lag_4kHz + 1, arch );
@@ -215,7 +215,7 @@ opus_int silk_pitch_analysis_core_FLP( /* O Voicing estimate: 0 voiced,
/* Sort */
length_d_srch = 4 + 2 * complexity;
- silk_assert( 3 * length_d_srch <= PE_D_SRCH_LENGTH );
+ celt_assert( 3 * length_d_srch <= PE_D_SRCH_LENGTH );
silk_insertion_sort_decreasing_FLP( &C[ 0 ][ min_lag_4kHz ], d_srch, max_lag_4kHz - min_lag_4kHz + 1, length_d_srch );
/* Escape if correlation is very low already here */
@@ -238,7 +238,7 @@ opus_int silk_pitch_analysis_core_FLP( /* O Voicing estimate: 0 voiced,
break;
}
}
- silk_assert( length_d_srch > 0 );
+ celt_assert( length_d_srch > 0 );
for( i = min_lag_8kHz - 5; i < max_lag_8kHz + 5; i++ ) {
d_comp[ i ] = 0;
@@ -471,7 +471,7 @@ opus_int silk_pitch_analysis_core_FLP( /* O Voicing estimate: 0 voiced,
*lagIndex = (opus_int16)( lag - min_lag_8kHz );
*contourIndex = (opus_int8)CBimax;
}
- silk_assert( *lagIndex >= 0 );
+ celt_assert( *lagIndex >= 0 );
/* return as voiced */
return 0;
}
@@ -506,8 +506,8 @@ static void silk_P_Ana_calc_corr_st3(
opus_val32 xcorr[ SCRATCH_SIZE ];
const opus_int8 *Lag_range_ptr, *Lag_CB_ptr;
- silk_assert( complexity >= SILK_PE_MIN_COMPLEX );
- silk_assert( complexity <= SILK_PE_MAX_COMPLEX );
+ celt_assert( complexity >= SILK_PE_MIN_COMPLEX );
+ celt_assert( complexity <= SILK_PE_MAX_COMPLEX );
if( nb_subfr == PE_MAX_NB_SUBFR ) {
Lag_range_ptr = &silk_Lag_range_stage3[ complexity ][ 0 ][ 0 ];
@@ -515,7 +515,7 @@ static void silk_P_Ana_calc_corr_st3(
nb_cbk_search = silk_nb_cbk_searchs_stage3[ complexity ];
cbk_size = PE_NB_CBKS_STAGE3_MAX;
} else {
- silk_assert( nb_subfr == PE_MAX_NB_SUBFR >> 1);
+ celt_assert( nb_subfr == PE_MAX_NB_SUBFR >> 1);
Lag_range_ptr = &silk_Lag_range_stage3_10_ms[ 0 ][ 0 ];
Lag_CB_ptr = &silk_CB_lags_stage3_10_ms[ 0 ][ 0 ];
nb_cbk_search = PE_NB_CBKS_STAGE3_10MS;
@@ -572,8 +572,8 @@ static void silk_P_Ana_calc_energy_st3(
silk_float scratch_mem[ SCRATCH_SIZE ];
const opus_int8 *Lag_range_ptr, *Lag_CB_ptr;
- silk_assert( complexity >= SILK_PE_MIN_COMPLEX );
- silk_assert( complexity <= SILK_PE_MAX_COMPLEX );
+ celt_assert( complexity >= SILK_PE_MIN_COMPLEX );
+ celt_assert( complexity <= SILK_PE_MAX_COMPLEX );
if( nb_subfr == PE_MAX_NB_SUBFR ) {
Lag_range_ptr = &silk_Lag_range_stage3[ complexity ][ 0 ][ 0 ];
@@ -581,7 +581,7 @@ static void silk_P_Ana_calc_energy_st3(
nb_cbk_search = silk_nb_cbk_searchs_stage3[ complexity ];
cbk_size = PE_NB_CBKS_STAGE3_MAX;
} else {
- silk_assert( nb_subfr == PE_MAX_NB_SUBFR >> 1);
+ celt_assert( nb_subfr == PE_MAX_NB_SUBFR >> 1);
Lag_range_ptr = &silk_Lag_range_stage3_10_ms[ 0 ][ 0 ];
Lag_CB_ptr = &silk_CB_lags_stage3_10_ms[ 0 ][ 0 ];
nb_cbk_search = PE_NB_CBKS_STAGE3_10MS;
diff --git a/libs/libopus/silk/float/prefilter_FLP.c b/libs/libopus/silk/float/prefilter_FLP.c
deleted file mode 100644
index 8bc32fb41..000000000
--- a/libs/libopus/silk/float/prefilter_FLP.c
+++ /dev/null
@@ -1,206 +0,0 @@
-/***********************************************************************
-Copyright (c) 2006-2011, Skype Limited. All rights reserved.
-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 "main_FLP.h"
-#include "tuning_parameters.h"
-
-/*
-* Prefilter for finding Quantizer input signal
-*/
-static OPUS_INLINE void silk_prefilt_FLP(
- silk_prefilter_state_FLP *P, /* I/O state */
- silk_float st_res[], /* I */
- silk_float xw[], /* O */
- silk_float *HarmShapeFIR, /* I */
- silk_float Tilt, /* I */
- silk_float LF_MA_shp, /* I */
- silk_float LF_AR_shp, /* I */
- opus_int lag, /* I */
- opus_int length /* I */
-);
-
-static void silk_warped_LPC_analysis_filter_FLP(
- silk_float state[], /* I/O State [order + 1] */
- silk_float res[], /* O Residual signal [length] */
- const silk_float coef[], /* I Coefficients [order] */
- const silk_float input[], /* I Input signal [length] */
- const silk_float lambda, /* I Warping factor */
- const opus_int length, /* I Length of input signal */
- const opus_int order /* I Filter order (even) */
-)
-{
- opus_int n, i;
- silk_float acc, tmp1, tmp2;
-
- /* Order must be even */
- silk_assert( ( order & 1 ) == 0 );
-
- for( n = 0; n < length; n++ ) {
- /* Output of lowpass section */
- tmp2 = state[ 0 ] + lambda * state[ 1 ];
- state[ 0 ] = input[ n ];
- /* Output of allpass section */
- tmp1 = state[ 1 ] + lambda * ( state[ 2 ] - tmp2 );
- state[ 1 ] = tmp2;
- acc = coef[ 0 ] * tmp2;
- /* Loop over allpass sections */
- for( i = 2; i < order; i += 2 ) {
- /* Output of allpass section */
- tmp2 = state[ i ] + lambda * ( state[ i + 1 ] - tmp1 );
- state[ i ] = tmp1;
- acc += coef[ i - 1 ] * tmp1;
- /* Output of allpass section */
- tmp1 = state[ i + 1 ] + lambda * ( state[ i + 2 ] - tmp2 );
- state[ i + 1 ] = tmp2;
- acc += coef[ i ] * tmp2;
- }
- state[ order ] = tmp1;
- acc += coef[ order - 1 ] * tmp1;
- res[ n ] = input[ n ] - acc;
- }
-}
-
-/*
-* silk_prefilter. Main prefilter function
-*/
-void silk_prefilter_FLP(
- silk_encoder_state_FLP *psEnc, /* I/O Encoder state FLP */
- const silk_encoder_control_FLP *psEncCtrl, /* I Encoder control FLP */
- silk_float xw[], /* O Weighted signal */
- const silk_float x[] /* I Speech signal */
-)
-{
- silk_prefilter_state_FLP *P = &psEnc->sPrefilt;
- opus_int j, k, lag;
- silk_float HarmShapeGain, Tilt, LF_MA_shp, LF_AR_shp;
- silk_float B[ 2 ];
- const silk_float *AR1_shp;
- const silk_float *px;
- silk_float *pxw;
- silk_float HarmShapeFIR[ 3 ];
- silk_float st_res[ MAX_SUB_FRAME_LENGTH + MAX_LPC_ORDER ];
-
- /* Set up pointers */
- px = x;
- pxw = xw;
- lag = P->lagPrev;
- for( k = 0; k < psEnc->sCmn.nb_subfr; k++ ) {
- /* Update Variables that change per sub frame */
- if( psEnc->sCmn.indices.signalType == TYPE_VOICED ) {
- lag = psEncCtrl->pitchL[ k ];
- }
-
- /* Noise shape parameters */
- HarmShapeGain = psEncCtrl->HarmShapeGain[ k ] * ( 1.0f - psEncCtrl->HarmBoost[ k ] );
- HarmShapeFIR[ 0 ] = 0.25f * HarmShapeGain;
- HarmShapeFIR[ 1 ] = 32767.0f / 65536.0f * HarmShapeGain;
- HarmShapeFIR[ 2 ] = 0.25f * HarmShapeGain;
- Tilt = psEncCtrl->Tilt[ k ];
- LF_MA_shp = psEncCtrl->LF_MA_shp[ k ];
- LF_AR_shp = psEncCtrl->LF_AR_shp[ k ];
- AR1_shp = &psEncCtrl->AR1[ k * MAX_SHAPE_LPC_ORDER ];
-
- /* Short term FIR filtering */
- silk_warped_LPC_analysis_filter_FLP( P->sAR_shp, st_res, AR1_shp, px,
- (silk_float)psEnc->sCmn.warping_Q16 / 65536.0f, psEnc->sCmn.subfr_length, psEnc->sCmn.shapingLPCOrder );
-
- /* Reduce (mainly) low frequencies during harmonic emphasis */
- B[ 0 ] = psEncCtrl->GainsPre[ k ];
- B[ 1 ] = -psEncCtrl->GainsPre[ k ] *
- ( psEncCtrl->HarmBoost[ k ] * HarmShapeGain + INPUT_TILT + psEncCtrl->coding_quality * HIGH_RATE_INPUT_TILT );
- pxw[ 0 ] = B[ 0 ] * st_res[ 0 ] + B[ 1 ] * P->sHarmHP;
- for( j = 1; j < psEnc->sCmn.subfr_length; j++ ) {
- pxw[ j ] = B[ 0 ] * st_res[ j ] + B[ 1 ] * st_res[ j - 1 ];
- }
- P->sHarmHP = st_res[ psEnc->sCmn.subfr_length - 1 ];
-
- silk_prefilt_FLP( P, pxw, pxw, HarmShapeFIR, Tilt, LF_MA_shp, LF_AR_shp, lag, psEnc->sCmn.subfr_length );
-
- px += psEnc->sCmn.subfr_length;
- pxw += psEnc->sCmn.subfr_length;
- }
- P->lagPrev = psEncCtrl->pitchL[ psEnc->sCmn.nb_subfr - 1 ];
-}
-
-/*
-* Prefilter for finding Quantizer input signal
-*/
-static OPUS_INLINE void silk_prefilt_FLP(
- silk_prefilter_state_FLP *P, /* I/O state */
- silk_float st_res[], /* I */
- silk_float xw[], /* O */
- silk_float *HarmShapeFIR, /* I */
- silk_float Tilt, /* I */
- silk_float LF_MA_shp, /* I */
- silk_float LF_AR_shp, /* I */
- opus_int lag, /* I */
- opus_int length /* I */
-)
-{
- opus_int i;
- opus_int idx, LTP_shp_buf_idx;
- silk_float n_Tilt, n_LF, n_LTP;
- silk_float sLF_AR_shp, sLF_MA_shp;
- silk_float *LTP_shp_buf;
-
- /* To speed up use temp variables instead of using the struct */
- LTP_shp_buf = P->sLTP_shp;
- LTP_shp_buf_idx = P->sLTP_shp_buf_idx;
- sLF_AR_shp = P->sLF_AR_shp;
- sLF_MA_shp = P->sLF_MA_shp;
-
- for( i = 0; i < length; i++ ) {
- if( lag > 0 ) {
- silk_assert( HARM_SHAPE_FIR_TAPS == 3 );
- idx = lag + LTP_shp_buf_idx;
- n_LTP = LTP_shp_buf[ ( idx - HARM_SHAPE_FIR_TAPS / 2 - 1) & LTP_MASK ] * HarmShapeFIR[ 0 ];
- n_LTP += LTP_shp_buf[ ( idx - HARM_SHAPE_FIR_TAPS / 2 ) & LTP_MASK ] * HarmShapeFIR[ 1 ];
- n_LTP += LTP_shp_buf[ ( idx - HARM_SHAPE_FIR_TAPS / 2 + 1) & LTP_MASK ] * HarmShapeFIR[ 2 ];
- } else {
- n_LTP = 0;
- }
-
- n_Tilt = sLF_AR_shp * Tilt;
- n_LF = sLF_AR_shp * LF_AR_shp + sLF_MA_shp * LF_MA_shp;
-
- sLF_AR_shp = st_res[ i ] - n_Tilt;
- sLF_MA_shp = sLF_AR_shp - n_LF;
-
- LTP_shp_buf_idx = ( LTP_shp_buf_idx - 1 ) & LTP_MASK;
- LTP_shp_buf[ LTP_shp_buf_idx ] = sLF_MA_shp;
-
- xw[ i ] = sLF_MA_shp - n_LTP;
- }
- /* Copy temp variable back to state */
- P->sLF_AR_shp = sLF_AR_shp;
- P->sLF_MA_shp = sLF_MA_shp;
- P->sLTP_shp_buf_idx = LTP_shp_buf_idx;
-}
diff --git a/libs/libopus/silk/float/residual_energy_FLP.c b/libs/libopus/silk/float/residual_energy_FLP.c
index b2e03a86a..1bd07b33a 100644
--- a/libs/libopus/silk/float/residual_energy_FLP.c
+++ b/libs/libopus/silk/float/residual_energy_FLP.c
@@ -47,7 +47,7 @@ silk_float silk_residual_energy_covar_FLP( /* O
silk_float tmp, nrg = 0.0f, regularization;
/* Safety checks */
- silk_assert( D >= 0 );
+ celt_assert( D >= 0 );
regularization = REGULARIZATION_FACTOR * ( wXX[ 0 ] + wXX[ D * D - 1 ] );
for( k = 0; k < MAX_ITERATIONS_RESIDUAL_NRG; k++ ) {
diff --git a/libs/libopus/silk/float/schur_FLP.c b/libs/libopus/silk/float/schur_FLP.c
index ee436f835..8526c748d 100644
--- a/libs/libopus/silk/float/schur_FLP.c
+++ b/libs/libopus/silk/float/schur_FLP.c
@@ -38,22 +38,23 @@ silk_float silk_schur_FLP( /* O returns residual energy
)
{
opus_int k, n;
- silk_float C[ SILK_MAX_ORDER_LPC + 1 ][ 2 ];
- silk_float Ctmp1, Ctmp2, rc_tmp;
+ double C[ SILK_MAX_ORDER_LPC + 1 ][ 2 ];
+ double Ctmp1, Ctmp2, rc_tmp;
- silk_assert( order==6||order==8||order==10||order==12||order==14||order==16 );
+ celt_assert( order >= 0 && order <= SILK_MAX_ORDER_LPC );
/* Copy correlations */
- for( k = 0; k < order+1; k++ ) {
+ k = 0;
+ do {
C[ k ][ 0 ] = C[ k ][ 1 ] = auto_corr[ k ];
- }
+ } while( ++k <= order );
for( k = 0; k < order; k++ ) {
/* Get reflection coefficient */
rc_tmp = -C[ k + 1 ][ 0 ] / silk_max_float( C[ 0 ][ 1 ], 1e-9f );
/* Save the output */
- refl_coef[ k ] = rc_tmp;
+ refl_coef[ k ] = (silk_float)rc_tmp;
/* Update correlations */
for( n = 0; n < order - k; n++ ) {
@@ -65,6 +66,5 @@ silk_float silk_schur_FLP( /* O returns residual energy
}
/* Return residual energy */
- return C[ 0 ][ 1 ];
+ return (silk_float)C[ 0 ][ 1 ];
}
-
diff --git a/libs/libopus/silk/float/solve_LS_FLP.c b/libs/libopus/silk/float/solve_LS_FLP.c
deleted file mode 100644
index 7c90d665a..000000000
--- a/libs/libopus/silk/float/solve_LS_FLP.c
+++ /dev/null
@@ -1,207 +0,0 @@
-/***********************************************************************
-Copyright (c) 2006-2011, Skype Limited. All rights reserved.
-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 "main_FLP.h"
-#include "tuning_parameters.h"
-
-/**********************************************************************
- * LDL Factorisation. Finds the upper triangular matrix L and the diagonal
- * Matrix D (only the diagonal elements returned in a vector)such that
- * the symmetric matric A is given by A = L*D*L'.
- **********************************************************************/
-static OPUS_INLINE void silk_LDL_FLP(
- silk_float *A, /* I/O Pointer to Symetric Square Matrix */
- opus_int M, /* I Size of Matrix */
- silk_float *L, /* I/O Pointer to Square Upper triangular Matrix */
- silk_float *Dinv /* I/O Pointer to vector holding the inverse diagonal elements of D */
-);
-
-/**********************************************************************
- * Function to solve linear equation Ax = b, when A is a MxM lower
- * triangular matrix, with ones on the diagonal.
- **********************************************************************/
-static OPUS_INLINE void silk_SolveWithLowerTriangularWdiagOnes_FLP(
- const silk_float *L, /* I Pointer to Lower Triangular Matrix */
- opus_int M, /* I Dim of Matrix equation */
- const silk_float *b, /* I b Vector */
- silk_float *x /* O x Vector */
-);
-
-/**********************************************************************
- * Function to solve linear equation (A^T)x = b, when A is a MxM lower
- * triangular, with ones on the diagonal. (ie then A^T is upper triangular)
- **********************************************************************/
-static OPUS_INLINE void silk_SolveWithUpperTriangularFromLowerWdiagOnes_FLP(
- const silk_float *L, /* I Pointer to Lower Triangular Matrix */
- opus_int M, /* I Dim of Matrix equation */
- const silk_float *b, /* I b Vector */
- silk_float *x /* O x Vector */
-);
-
-/**********************************************************************
- * Function to solve linear equation Ax = b, when A is a MxM
- * symmetric square matrix - using LDL factorisation
- **********************************************************************/
-void silk_solve_LDL_FLP(
- silk_float *A, /* I/O Symmetric square matrix, out: reg. */
- const opus_int M, /* I Size of matrix */
- const silk_float *b, /* I Pointer to b vector */
- silk_float *x /* O Pointer to x solution vector */
-)
-{
- opus_int i;
- silk_float L[ MAX_MATRIX_SIZE ][ MAX_MATRIX_SIZE ];
- silk_float T[ MAX_MATRIX_SIZE ];
- silk_float Dinv[ MAX_MATRIX_SIZE ]; /* inverse diagonal elements of D*/
-
- silk_assert( M <= MAX_MATRIX_SIZE );
-
- /***************************************************
- Factorize A by LDL such that A = L*D*(L^T),
- where L is lower triangular with ones on diagonal
- ****************************************************/
- silk_LDL_FLP( A, M, &L[ 0 ][ 0 ], Dinv );
-
- /****************************************************
- * substitute D*(L^T) = T. ie:
- L*D*(L^T)*x = b => L*T = b <=> T = inv(L)*b
- ******************************************************/
- silk_SolveWithLowerTriangularWdiagOnes_FLP( &L[ 0 ][ 0 ], M, b, T );
-
- /****************************************************
- D*(L^T)*x = T <=> (L^T)*x = inv(D)*T, because D is
- diagonal just multiply with 1/d_i
- ****************************************************/
- for( i = 0; i < M; i++ ) {
- T[ i ] = T[ i ] * Dinv[ i ];
- }
- /****************************************************
- x = inv(L') * inv(D) * T
- *****************************************************/
- silk_SolveWithUpperTriangularFromLowerWdiagOnes_FLP( &L[ 0 ][ 0 ], M, T, x );
-}
-
-static OPUS_INLINE void silk_SolveWithUpperTriangularFromLowerWdiagOnes_FLP(
- const silk_float *L, /* I Pointer to Lower Triangular Matrix */
- opus_int M, /* I Dim of Matrix equation */
- const silk_float *b, /* I b Vector */
- silk_float *x /* O x Vector */
-)
-{
- opus_int i, j;
- silk_float temp;
- const silk_float *ptr1;
-
- for( i = M - 1; i >= 0; i-- ) {
- ptr1 = matrix_adr( L, 0, i, M );
- temp = 0;
- for( j = M - 1; j > i ; j-- ) {
- temp += ptr1[ j * M ] * x[ j ];
- }
- temp = b[ i ] - temp;
- x[ i ] = temp;
- }
-}
-
-static OPUS_INLINE void silk_SolveWithLowerTriangularWdiagOnes_FLP(
- const silk_float *L, /* I Pointer to Lower Triangular Matrix */
- opus_int M, /* I Dim of Matrix equation */
- const silk_float *b, /* I b Vector */
- silk_float *x /* O x Vector */
-)
-{
- opus_int i, j;
- silk_float temp;
- const silk_float *ptr1;
-
- for( i = 0; i < M; i++ ) {
- ptr1 = matrix_adr( L, i, 0, M );
- temp = 0;
- for( j = 0; j < i; j++ ) {
- temp += ptr1[ j ] * x[ j ];
- }
- temp = b[ i ] - temp;
- x[ i ] = temp;
- }
-}
-
-static OPUS_INLINE void silk_LDL_FLP(
- silk_float *A, /* I/O Pointer to Symetric Square Matrix */
- opus_int M, /* I Size of Matrix */
- silk_float *L, /* I/O Pointer to Square Upper triangular Matrix */
- silk_float *Dinv /* I/O Pointer to vector holding the inverse diagonal elements of D */
-)
-{
- opus_int i, j, k, loop_count, err = 1;
- silk_float *ptr1, *ptr2;
- double temp, diag_min_value;
- silk_float v[ MAX_MATRIX_SIZE ], D[ MAX_MATRIX_SIZE ]; /* temp arrays*/
-
- silk_assert( M <= MAX_MATRIX_SIZE );
-
- diag_min_value = FIND_LTP_COND_FAC * 0.5f * ( A[ 0 ] + A[ M * M - 1 ] );
- for( loop_count = 0; loop_count < M && err == 1; loop_count++ ) {
- err = 0;
- for( j = 0; j < M; j++ ) {
- ptr1 = matrix_adr( L, j, 0, M );
- temp = matrix_ptr( A, j, j, M ); /* element in row j column j*/
- for( i = 0; i < j; i++ ) {
- v[ i ] = ptr1[ i ] * D[ i ];
- temp -= ptr1[ i ] * v[ i ];
- }
- if( temp < diag_min_value ) {
- /* Badly conditioned matrix: add white noise and run again */
- temp = ( loop_count + 1 ) * diag_min_value - temp;
- for( i = 0; i < M; i++ ) {
- matrix_ptr( A, i, i, M ) += ( silk_float )temp;
- }
- err = 1;
- break;
- }
- D[ j ] = ( silk_float )temp;
- Dinv[ j ] = ( silk_float )( 1.0f / temp );
- matrix_ptr( L, j, j, M ) = 1.0f;
-
- ptr1 = matrix_adr( A, j, 0, M );
- ptr2 = matrix_adr( L, j + 1, 0, M);
- for( i = j + 1; i < M; i++ ) {
- temp = 0.0;
- for( k = 0; k < j; k++ ) {
- temp += ptr2[ k ] * v[ k ];
- }
- matrix_ptr( L, i, j, M ) = ( silk_float )( ( ptr1[ i ] - temp ) * Dinv[ j ] );
- ptr2 += M; /* go to next column*/
- }
- }
- }
- silk_assert( err == 0 );
-}
-
diff --git a/libs/libopus/silk/float/sort_FLP.c b/libs/libopus/silk/float/sort_FLP.c
index f08d7592c..0e18f3195 100644
--- a/libs/libopus/silk/float/sort_FLP.c
+++ b/libs/libopus/silk/float/sort_FLP.c
@@ -47,9 +47,9 @@ void silk_insertion_sort_decreasing_FLP(
opus_int i, j;
/* Safety checks */
- silk_assert( K > 0 );
- silk_assert( L > 0 );
- silk_assert( L >= K );
+ celt_assert( K > 0 );
+ celt_assert( L > 0 );
+ celt_assert( L >= K );
/* Write start indices in index vector */
for( i = 0; i < K; i++ ) {
diff --git a/libs/libopus/silk/float/structs_FLP.h b/libs/libopus/silk/float/structs_FLP.h
index 14d647ced..3150b386e 100644
--- a/libs/libopus/silk/float/structs_FLP.h
+++ b/libs/libopus/silk/float/structs_FLP.h
@@ -42,32 +42,16 @@ extern "C"
/********************************/
typedef struct {
opus_int8 LastGainIndex;
- silk_float HarmBoost_smth;
silk_float HarmShapeGain_smth;
silk_float Tilt_smth;
} silk_shape_state_FLP;
/********************************/
-/* Prefilter state */
-/********************************/
-typedef struct {
- silk_float sLTP_shp[ LTP_BUF_LENGTH ];
- silk_float sAR_shp[ MAX_SHAPE_LPC_ORDER + 1 ];
- opus_int sLTP_shp_buf_idx;
- silk_float sLF_AR_shp;
- silk_float sLF_MA_shp;
- silk_float sHarmHP;
- opus_int32 rand_seed;
- opus_int lagPrev;
-} silk_prefilter_state_FLP;
-
-/********************************/
/* Encoder state FLP */
/********************************/
typedef struct {
silk_encoder_state sCmn; /* Common struct, shared with fixed-point code */
silk_shape_state_FLP sShape; /* Noise shaping state */
- silk_prefilter_state_FLP sPrefilt; /* Prefilter State */
/* Buffer for find pitch and noise shape analysis */
silk_float x_buf[ 2 * MAX_FRAME_LENGTH + LA_SHAPE_MAX ];/* Buffer for find pitch and noise shape analysis */
@@ -86,12 +70,9 @@ typedef struct {
opus_int pitchL[ MAX_NB_SUBFR ];
/* Noise shaping parameters */
- silk_float AR1[ MAX_NB_SUBFR * MAX_SHAPE_LPC_ORDER ];
- silk_float AR2[ MAX_NB_SUBFR * MAX_SHAPE_LPC_ORDER ];
+ silk_float AR[ MAX_NB_SUBFR * MAX_SHAPE_LPC_ORDER ];
silk_float LF_MA_shp[ MAX_NB_SUBFR ];
silk_float LF_AR_shp[ MAX_NB_SUBFR ];
- silk_float GainsPre[ MAX_NB_SUBFR ];
- silk_float HarmBoost[ MAX_NB_SUBFR ];
silk_float Tilt[ MAX_NB_SUBFR ];
silk_float HarmShapeGain[ MAX_NB_SUBFR ];
silk_float Lambda;
@@ -99,7 +80,6 @@ typedef struct {
silk_float coding_quality;
/* Measures */
- silk_float sparseness;
silk_float predGain;
silk_float LTPredCodGain;
silk_float ResNrg[ MAX_NB_SUBFR ]; /* Residual energy per subframe */
diff --git a/libs/libopus/silk/float/warped_autocorrelation_FLP.c b/libs/libopus/silk/float/warped_autocorrelation_FLP.c
index 542414f48..09186e73d 100644
--- a/libs/libopus/silk/float/warped_autocorrelation_FLP.c
+++ b/libs/libopus/silk/float/warped_autocorrelation_FLP.c
@@ -42,11 +42,11 @@ void silk_warped_autocorrelation_FLP(
{
opus_int n, i;
double tmp1, tmp2;
- double state[ MAX_SHAPE_LPC_ORDER + 1 ] = { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 };
- double C[ MAX_SHAPE_LPC_ORDER + 1 ] = { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 };
+ double state[ MAX_SHAPE_LPC_ORDER + 1 ] = { 0 };
+ double C[ MAX_SHAPE_LPC_ORDER + 1 ] = { 0 };
/* Order must be even */
- silk_assert( ( order & 1 ) == 0 );
+ celt_assert( ( order & 1 ) == 0 );
/* Loop over samples */
for( n = 0; n < length; n++ ) {
diff --git a/libs/libopus/silk/float/wrappers_FLP.c b/libs/libopus/silk/float/wrappers_FLP.c
index 6666b8efa..ad90b874a 100644
--- a/libs/libopus/silk/float/wrappers_FLP.c
+++ b/libs/libopus/silk/float/wrappers_FLP.c
@@ -54,13 +54,14 @@ void silk_A2NLSF_FLP(
void silk_NLSF2A_FLP(
silk_float *pAR, /* O LPC coefficients [ LPC_order ] */
const opus_int16 *NLSF_Q15, /* I NLSF vector [ LPC_order ] */
- const opus_int LPC_order /* I LPC order */
+ const opus_int LPC_order, /* I LPC order */
+ int arch /* I Run-time architecture */
)
{
opus_int i;
opus_int16 a_fix_Q12[ MAX_LPC_ORDER ];
- silk_NLSF2A( a_fix_Q12, NLSF_Q15, LPC_order );
+ silk_NLSF2A( a_fix_Q12, NLSF_Q15, LPC_order, arch );
for( i = 0; i < LPC_order; i++ ) {
pAR[ i ] = ( silk_float )a_fix_Q12[ i ] * ( 1.0f / 4096.0f );
@@ -102,14 +103,14 @@ void silk_NSQ_wrapper_FLP(
)
{
opus_int i, j;
- opus_int32 x_Q3[ MAX_FRAME_LENGTH ];
+ opus_int16 x16[ MAX_FRAME_LENGTH ];
opus_int32 Gains_Q16[ MAX_NB_SUBFR ];
silk_DWORD_ALIGN opus_int16 PredCoef_Q12[ 2 ][ MAX_LPC_ORDER ];
opus_int16 LTPCoef_Q14[ LTP_ORDER * MAX_NB_SUBFR ];
opus_int LTP_scale_Q14;
/* Noise shaping parameters */
- opus_int16 AR2_Q13[ MAX_NB_SUBFR * MAX_SHAPE_LPC_ORDER ];
+ opus_int16 AR_Q13[ MAX_NB_SUBFR * MAX_SHAPE_LPC_ORDER ];
opus_int32 LF_shp_Q14[ MAX_NB_SUBFR ]; /* Packs two int16 coefficients per int32 value */
opus_int Lambda_Q10;
opus_int Tilt_Q14[ MAX_NB_SUBFR ];
@@ -119,7 +120,7 @@ void silk_NSQ_wrapper_FLP(
/* Noise shape parameters */
for( i = 0; i < psEnc->sCmn.nb_subfr; i++ ) {
for( j = 0; j < psEnc->sCmn.shapingLPCOrder; j++ ) {
- AR2_Q13[ i * MAX_SHAPE_LPC_ORDER + j ] = silk_float2int( psEncCtrl->AR2[ i * MAX_SHAPE_LPC_ORDER + j ] * 8192.0f );
+ AR_Q13[ i * MAX_SHAPE_LPC_ORDER + j ] = silk_float2int( psEncCtrl->AR[ i * MAX_SHAPE_LPC_ORDER + j ] * 8192.0f );
}
}
@@ -155,16 +156,16 @@ void silk_NSQ_wrapper_FLP(
/* Convert input to fix */
for( i = 0; i < psEnc->sCmn.frame_length; i++ ) {
- x_Q3[ i ] = silk_float2int( 8.0f * x[ i ] );
+ x16[ i ] = silk_float2int( x[ i ] );
}
/* Call NSQ */
if( psEnc->sCmn.nStatesDelayedDecision > 1 || psEnc->sCmn.warping_Q16 > 0 ) {
- silk_NSQ_del_dec( &psEnc->sCmn, psNSQ, psIndices, x_Q3, pulses, PredCoef_Q12[ 0 ], LTPCoef_Q14,
- AR2_Q13, HarmShapeGain_Q14, Tilt_Q14, LF_shp_Q14, Gains_Q16, psEncCtrl->pitchL, Lambda_Q10, LTP_scale_Q14, psEnc->sCmn.arch );
+ silk_NSQ_del_dec( &psEnc->sCmn, psNSQ, psIndices, x16, pulses, PredCoef_Q12[ 0 ], LTPCoef_Q14,
+ AR_Q13, HarmShapeGain_Q14, Tilt_Q14, LF_shp_Q14, Gains_Q16, psEncCtrl->pitchL, Lambda_Q10, LTP_scale_Q14, psEnc->sCmn.arch );
} else {
- silk_NSQ( &psEnc->sCmn, psNSQ, psIndices, x_Q3, pulses, PredCoef_Q12[ 0 ], LTPCoef_Q14,
- AR2_Q13, HarmShapeGain_Q14, Tilt_Q14, LF_shp_Q14, Gains_Q16, psEncCtrl->pitchL, Lambda_Q10, LTP_scale_Q14, psEnc->sCmn.arch );
+ silk_NSQ( &psEnc->sCmn, psNSQ, psIndices, x16, pulses, PredCoef_Q12[ 0 ], LTPCoef_Q14,
+ AR_Q13, HarmShapeGain_Q14, Tilt_Q14, LF_shp_Q14, Gains_Q16, psEncCtrl->pitchL, Lambda_Q10, LTP_scale_Q14, psEnc->sCmn.arch );
}
}
@@ -172,31 +173,35 @@ void silk_NSQ_wrapper_FLP(
/* Floating-point Silk LTP quantiation wrapper */
/***********************************************/
void silk_quant_LTP_gains_FLP(
- silk_float B[ MAX_NB_SUBFR * LTP_ORDER ], /* I/O (Un-)quantized LTP gains */
+ silk_float B[ MAX_NB_SUBFR * LTP_ORDER ], /* O Quantized LTP gains */
opus_int8 cbk_index[ MAX_NB_SUBFR ], /* O Codebook index */
opus_int8 *periodicity_index, /* O Periodicity index */
opus_int32 *sum_log_gain_Q7, /* I/O Cumulative max prediction gain */
- const silk_float W[ MAX_NB_SUBFR * LTP_ORDER * LTP_ORDER ], /* I Error weights */
- const opus_int mu_Q10, /* I Mu value (R/D tradeoff) */
- const opus_int lowComplexity, /* I Flag for low complexity */
- const opus_int nb_subfr, /* I number of subframes */
+ silk_float *pred_gain_dB, /* O LTP prediction gain */
+ const silk_float XX[ MAX_NB_SUBFR * LTP_ORDER * LTP_ORDER ], /* I Correlation matrix */
+ const silk_float xX[ MAX_NB_SUBFR * LTP_ORDER ], /* I Correlation vector */
+ const opus_int subfr_len, /* I Number of samples per subframe */
+ const opus_int nb_subfr, /* I Number of subframes */
int arch /* I Run-time architecture */
)
{
- opus_int i;
+ opus_int i, pred_gain_dB_Q7;
opus_int16 B_Q14[ MAX_NB_SUBFR * LTP_ORDER ];
- opus_int32 W_Q18[ MAX_NB_SUBFR*LTP_ORDER*LTP_ORDER ];
+ opus_int32 XX_Q17[ MAX_NB_SUBFR * LTP_ORDER * LTP_ORDER ];
+ opus_int32 xX_Q17[ MAX_NB_SUBFR * LTP_ORDER ];
- for( i = 0; i < nb_subfr * LTP_ORDER; i++ ) {
- B_Q14[ i ] = (opus_int16)silk_float2int( B[ i ] * 16384.0f );
- }
for( i = 0; i < nb_subfr * LTP_ORDER * LTP_ORDER; i++ ) {
- W_Q18[ i ] = (opus_int32)silk_float2int( W[ i ] * 262144.0f );
+ XX_Q17[ i ] = (opus_int32)silk_float2int( XX[ i ] * 131072.0f );
+ }
+ for( i = 0; i < nb_subfr * LTP_ORDER; i++ ) {
+ xX_Q17[ i ] = (opus_int32)silk_float2int( xX[ i ] * 131072.0f );
}
- silk_quant_LTP_gains( B_Q14, cbk_index, periodicity_index, sum_log_gain_Q7, W_Q18, mu_Q10, lowComplexity, nb_subfr, arch );
+ silk_quant_LTP_gains( B_Q14, cbk_index, periodicity_index, sum_log_gain_Q7, &pred_gain_dB_Q7, XX_Q17, xX_Q17, subfr_len, nb_subfr, arch );
for( i = 0; i < nb_subfr * LTP_ORDER; i++ ) {
B[ i ] = (silk_float)B_Q14[ i ] * ( 1.0f / 16384.0f );
}
+
+ *pred_gain_dB = (silk_float)pred_gain_dB_Q7 * ( 1.0f / 128.0f );
}
diff --git a/libs/libopus/silk/gain_quant.c b/libs/libopus/silk/gain_quant.c
index 64ccd0611..ee65245aa 100644
--- a/libs/libopus/silk/gain_quant.c
+++ b/libs/libopus/silk/gain_quant.c
@@ -76,6 +76,7 @@ void silk_gains_quant(
/* Accumulate deltas */
if( ind[ k ] > double_step_size_threshold ) {
*prev_ind += silk_LSHIFT( ind[ k ], 1 ) - double_step_size_threshold;
+ *prev_ind = silk_min_int( *prev_ind, N_LEVELS_QGAIN - 1 );
} else {
*prev_ind += ind[ k ];
}
diff --git a/libs/libopus/silk/init_decoder.c b/libs/libopus/silk/init_decoder.c
index f887c6788..16c03dcd1 100644
--- a/libs/libopus/silk/init_decoder.c
+++ b/libs/libopus/silk/init_decoder.c
@@ -44,6 +44,7 @@ opus_int silk_init_decoder(
/* Used to deactivate LSF interpolation */
psDec->first_frame_after_reset = 1;
psDec->prev_gain_Q16 = 65536;
+ psDec->arch = opus_select_arch();
/* Reset CNG state */
silk_CNG_Reset( psDec );
diff --git a/libs/libopus/silk/interpolate.c b/libs/libopus/silk/interpolate.c
index 1bd8ca4d5..833c28ef8 100644
--- a/libs/libopus/silk/interpolate.c
+++ b/libs/libopus/silk/interpolate.c
@@ -42,8 +42,8 @@ void silk_interpolate(
{
opus_int i;
- silk_assert( ifact_Q2 >= 0 );
- silk_assert( ifact_Q2 <= 4 );
+ celt_assert( ifact_Q2 >= 0 );
+ celt_assert( ifact_Q2 <= 4 );
for( i = 0; i < d; i++ ) {
xi[ i ] = (opus_int16)silk_ADD_RSHIFT( x0[ i ], silk_SMULBB( x1[ i ] - x0[ i ], ifact_Q2 ), 2 );
diff --git a/libs/libopus/silk/lin2log.c b/libs/libopus/silk/lin2log.c
index d4fe51532..0d5155aa8 100644
--- a/libs/libopus/silk/lin2log.c
+++ b/libs/libopus/silk/lin2log.c
@@ -41,6 +41,6 @@ opus_int32 silk_lin2log(
silk_CLZ_FRAC( inLin, &lz, &frac_Q7 );
/* Piece-wise parabolic approximation */
- return silk_LSHIFT( 31 - lz, 7 ) + silk_SMLAWB( frac_Q7, silk_MUL( frac_Q7, 128 - frac_Q7 ), 179 );
+ return silk_ADD_LSHIFT32( silk_SMLAWB( frac_Q7, silk_MUL( frac_Q7, 128 - frac_Q7 ), 179 ), 31 - lz, 7 );
}
diff --git a/libs/libopus/silk/macros.h b/libs/libopus/silk/macros.h
index d3ca34752..3c67b6e5d 100644
--- a/libs/libopus/silk/macros.h
+++ b/libs/libopus/silk/macros.h
@@ -36,14 +36,6 @@ POSSIBILITY OF SUCH DAMAGE.
#include "opus_defines.h"
#include "arch.h"
-#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
-
/* This is an OPUS_INLINE header file for general platform. */
/* (a32 * (opus_int32)((opus_int16)(b32))) >> 16 output have to be 32bit int */
diff --git a/libs/libopus/silk/main.h b/libs/libopus/silk/main.h
index 2f90d68f7..a5f568758 100644
--- a/libs/libopus/silk/main.h
+++ b/libs/libopus/silk/main.h
@@ -42,6 +42,10 @@ POSSIBILITY OF SUCH DAMAGE.
#include "x86/main_sse.h"
#endif
+#if (defined(OPUS_ARM_ASM) || defined(OPUS_ARM_MAY_HAVE_NEON_INTR))
+#include "arm/NSQ_del_dec_arm.h"
+#endif
+
/* Convert Left/Right stereo signal to adaptive Mid/Side representation */
void silk_stereo_LR_to_MS(
stereo_enc_state *state, /* I/O State */
@@ -109,22 +113,22 @@ void silk_stereo_decode_mid_only(
/* Encodes signs of excitation */
void silk_encode_signs(
- ec_enc *psRangeEnc, /* I/O Compressor data structure */
- const opus_int8 pulses[], /* I pulse signal */
- opus_int length, /* I length of input */
- const opus_int signalType, /* I Signal type */
- const opus_int quantOffsetType, /* I Quantization offset type */
- const opus_int sum_pulses[ MAX_NB_SHELL_BLOCKS ] /* I Sum of absolute pulses per block */
+ ec_enc *psRangeEnc, /* I/O Compressor data structure */
+ const opus_int8 pulses[], /* I pulse signal */
+ opus_int length, /* I length of input */
+ const opus_int signalType, /* I Signal type */
+ const opus_int quantOffsetType, /* I Quantization offset type */
+ const opus_int sum_pulses[ MAX_NB_SHELL_BLOCKS ] /* I Sum of absolute pulses per block */
);
/* Decodes signs of excitation */
void silk_decode_signs(
- ec_dec *psRangeDec, /* I/O Compressor data structure */
- opus_int16 pulses[], /* I/O pulse signal */
- opus_int length, /* I length of input */
- const opus_int signalType, /* I Signal type */
- const opus_int quantOffsetType, /* I Quantization offset type */
- const opus_int sum_pulses[ MAX_NB_SHELL_BLOCKS ] /* I Sum of absolute pulses per block */
+ ec_dec *psRangeDec, /* I/O Compressor data structure */
+ opus_int16 pulses[], /* I/O pulse signal */
+ opus_int length, /* I length of input */
+ const opus_int signalType, /* I Signal type */
+ const opus_int quantOffsetType, /* I Quantization offset type */
+ const opus_int sum_pulses[ MAX_NB_SHELL_BLOCKS ] /* I Sum of absolute pulses per block */
);
/* Check encoder control struct */
@@ -205,37 +209,37 @@ void silk_interpolate(
/* LTP tap quantizer */
void silk_quant_LTP_gains(
- opus_int16 B_Q14[ MAX_NB_SUBFR * LTP_ORDER ], /* I/O (un)quantized LTP gains */
+ opus_int16 B_Q14[ MAX_NB_SUBFR * LTP_ORDER ], /* O Quantized LTP gains */
opus_int8 cbk_index[ MAX_NB_SUBFR ], /* O Codebook Index */
opus_int8 *periodicity_index, /* O Periodicity Index */
opus_int32 *sum_gain_dB_Q7, /* I/O Cumulative max prediction gain */
- const opus_int32 W_Q18[ MAX_NB_SUBFR*LTP_ORDER*LTP_ORDER ], /* I Error Weights in Q18 */
- opus_int mu_Q9, /* I Mu value (R/D tradeoff) */
- opus_int lowComplexity, /* I Flag for low complexity */
- const opus_int nb_subfr, /* I number of subframes */
+ opus_int *pred_gain_dB_Q7, /* O LTP prediction gain */
+ const opus_int32 XX_Q17[ MAX_NB_SUBFR*LTP_ORDER*LTP_ORDER ], /* I Correlation matrix in Q18 */
+ const opus_int32 xX_Q17[ MAX_NB_SUBFR*LTP_ORDER ], /* I Correlation vector in Q18 */
+ const opus_int subfr_len, /* I Number of samples per subframe */
+ const opus_int nb_subfr, /* I Number of subframes */
int arch /* I Run-time architecture */
);
/* Entropy constrained matrix-weighted VQ, for a single input data vector */
void silk_VQ_WMat_EC_c(
opus_int8 *ind, /* O index of best codebook vector */
- opus_int32 *rate_dist_Q14, /* O best weighted quant error + mu * rate */
+ opus_int32 *res_nrg_Q15, /* O best residual energy */
+ opus_int32 *rate_dist_Q8, /* O best total bitrate */
opus_int *gain_Q7, /* O sum of absolute LTP coefficients */
- const opus_int16 *in_Q14, /* I input vector to be quantized */
- const opus_int32 *W_Q18, /* I weighting matrix */
+ const opus_int32 *XX_Q17, /* I correlation matrix */
+ const opus_int32 *xX_Q17, /* I correlation vector */
const opus_int8 *cb_Q7, /* I codebook */
const opus_uint8 *cb_gain_Q7, /* I codebook effective gain */
const opus_uint8 *cl_Q5, /* I code length for each codebook vector */
- const opus_int mu_Q9, /* I tradeoff betw. weighted error and rate */
+ const opus_int subfr_len, /* I number of samples per subframe */
const opus_int32 max_gain_Q7, /* I maximum sum of absolute LTP coefficients */
- opus_int L /* I number of vectors in codebook */
+ const opus_int L /* I number of vectors in codebook */
);
#if !defined(OVERRIDE_silk_VQ_WMat_EC)
-#define silk_VQ_WMat_EC(ind, rate_dist_Q14, gain_Q7, in_Q14, W_Q18, cb_Q7, cb_gain_Q7, cl_Q5, \
- mu_Q9, max_gain_Q7, L, arch) \
- ((void)(arch),silk_VQ_WMat_EC_c(ind, rate_dist_Q14, gain_Q7, in_Q14, W_Q18, cb_Q7, cb_gain_Q7, cl_Q5, \
- mu_Q9, max_gain_Q7, L))
+#define silk_VQ_WMat_EC(ind, res_nrg_Q15, rate_dist_Q8, gain_Q7, XX_Q17, xX_Q17, cb_Q7, cb_gain_Q7, cl_Q5, subfr_len, max_gain_Q7, L, arch) \
+ ((void)(arch),silk_VQ_WMat_EC_c(ind, res_nrg_Q15, rate_dist_Q8, gain_Q7, XX_Q17, xX_Q17, cb_Q7, cb_gain_Q7, cl_Q5, subfr_len, max_gain_Q7, L))
#endif
/************************************/
@@ -243,53 +247,53 @@ void silk_VQ_WMat_EC_c(
/************************************/
void silk_NSQ_c(
- const silk_encoder_state *psEncC, /* I/O Encoder State */
- silk_nsq_state *NSQ, /* I/O NSQ state */
- SideInfoIndices *psIndices, /* I/O Quantization Indices */
- const opus_int32 x_Q3[], /* I Prefiltered input signal */
- opus_int8 pulses[], /* O Quantized pulse signal */
- const opus_int16 PredCoef_Q12[ 2 * MAX_LPC_ORDER ], /* I Short term prediction coefs */
- const opus_int16 LTPCoef_Q14[ LTP_ORDER * MAX_NB_SUBFR ], /* I Long term prediction coefs */
- const opus_int16 AR2_Q13[ MAX_NB_SUBFR * MAX_SHAPE_LPC_ORDER ], /* I Noise shaping coefs */
- const opus_int HarmShapeGain_Q14[ MAX_NB_SUBFR ], /* I Long term shaping coefs */
- const opus_int Tilt_Q14[ MAX_NB_SUBFR ], /* I Spectral tilt */
- const opus_int32 LF_shp_Q14[ MAX_NB_SUBFR ], /* I Low frequency shaping coefs */
- const opus_int32 Gains_Q16[ MAX_NB_SUBFR ], /* I Quantization step sizes */
- const opus_int pitchL[ MAX_NB_SUBFR ], /* I Pitch lags */
- const opus_int Lambda_Q10, /* I Rate/distortion tradeoff */
- const opus_int LTP_scale_Q14 /* I LTP state scaling */
+ const silk_encoder_state *psEncC, /* I Encoder State */
+ silk_nsq_state *NSQ, /* I/O NSQ state */
+ SideInfoIndices *psIndices, /* I/O Quantization Indices */
+ const opus_int16 x16[], /* I Input */
+ opus_int8 pulses[], /* O Quantized pulse signal */
+ const opus_int16 PredCoef_Q12[ 2 * MAX_LPC_ORDER ], /* I Short term prediction coefs */
+ const opus_int16 LTPCoef_Q14[ LTP_ORDER * MAX_NB_SUBFR ], /* I Long term prediction coefs */
+ const opus_int16 AR_Q13[ MAX_NB_SUBFR * MAX_SHAPE_LPC_ORDER ], /* I Noise shaping coefs */
+ const opus_int HarmShapeGain_Q14[ MAX_NB_SUBFR ], /* I Long term shaping coefs */
+ const opus_int Tilt_Q14[ MAX_NB_SUBFR ], /* I Spectral tilt */
+ const opus_int32 LF_shp_Q14[ MAX_NB_SUBFR ], /* I Low frequency shaping coefs */
+ const opus_int32 Gains_Q16[ MAX_NB_SUBFR ], /* I Quantization step sizes */
+ const opus_int pitchL[ MAX_NB_SUBFR ], /* I Pitch lags */
+ const opus_int Lambda_Q10, /* I Rate/distortion tradeoff */
+ const opus_int LTP_scale_Q14 /* I LTP state scaling */
);
#if !defined(OVERRIDE_silk_NSQ)
-#define silk_NSQ(psEncC, NSQ, psIndices, x_Q3, pulses, PredCoef_Q12, LTPCoef_Q14, AR2_Q13, \
+#define silk_NSQ(psEncC, NSQ, psIndices, x16, pulses, PredCoef_Q12, LTPCoef_Q14, AR_Q13, \
HarmShapeGain_Q14, Tilt_Q14, LF_shp_Q14, Gains_Q16, pitchL, Lambda_Q10, LTP_scale_Q14, arch) \
- ((void)(arch),silk_NSQ_c(psEncC, NSQ, psIndices, x_Q3, pulses, PredCoef_Q12, LTPCoef_Q14, AR2_Q13, \
+ ((void)(arch),silk_NSQ_c(psEncC, NSQ, psIndices, x16, pulses, PredCoef_Q12, LTPCoef_Q14, AR_Q13, \
HarmShapeGain_Q14, Tilt_Q14, LF_shp_Q14, Gains_Q16, pitchL, Lambda_Q10, LTP_scale_Q14))
#endif
/* Noise shaping using delayed decision */
void silk_NSQ_del_dec_c(
- const silk_encoder_state *psEncC, /* I/O Encoder State */
- silk_nsq_state *NSQ, /* I/O NSQ state */
- SideInfoIndices *psIndices, /* I/O Quantization Indices */
- const opus_int32 x_Q3[], /* I Prefiltered input signal */
- opus_int8 pulses[], /* O Quantized pulse signal */
- const opus_int16 PredCoef_Q12[ 2 * MAX_LPC_ORDER ], /* I Short term prediction coefs */
- const opus_int16 LTPCoef_Q14[ LTP_ORDER * MAX_NB_SUBFR ], /* I Long term prediction coefs */
- const opus_int16 AR2_Q13[ MAX_NB_SUBFR * MAX_SHAPE_LPC_ORDER ], /* I Noise shaping coefs */
- const opus_int HarmShapeGain_Q14[ MAX_NB_SUBFR ], /* I Long term shaping coefs */
- const opus_int Tilt_Q14[ MAX_NB_SUBFR ], /* I Spectral tilt */
- const opus_int32 LF_shp_Q14[ MAX_NB_SUBFR ], /* I Low frequency shaping coefs */
- const opus_int32 Gains_Q16[ MAX_NB_SUBFR ], /* I Quantization step sizes */
- const opus_int pitchL[ MAX_NB_SUBFR ], /* I Pitch lags */
- const opus_int Lambda_Q10, /* I Rate/distortion tradeoff */
- const opus_int LTP_scale_Q14 /* I LTP state scaling */
+ const silk_encoder_state *psEncC, /* I Encoder State */
+ silk_nsq_state *NSQ, /* I/O NSQ state */
+ SideInfoIndices *psIndices, /* I/O Quantization Indices */
+ const opus_int16 x16[], /* I Input */
+ opus_int8 pulses[], /* O Quantized pulse signal */
+ const opus_int16 PredCoef_Q12[ 2 * MAX_LPC_ORDER ], /* I Short term prediction coefs */
+ const opus_int16 LTPCoef_Q14[ LTP_ORDER * MAX_NB_SUBFR ], /* I Long term prediction coefs */
+ const opus_int16 AR_Q13[ MAX_NB_SUBFR * MAX_SHAPE_LPC_ORDER ], /* I Noise shaping coefs */
+ const opus_int HarmShapeGain_Q14[ MAX_NB_SUBFR ], /* I Long term shaping coefs */
+ const opus_int Tilt_Q14[ MAX_NB_SUBFR ], /* I Spectral tilt */
+ const opus_int32 LF_shp_Q14[ MAX_NB_SUBFR ], /* I Low frequency shaping coefs */
+ const opus_int32 Gains_Q16[ MAX_NB_SUBFR ], /* I Quantization step sizes */
+ const opus_int pitchL[ MAX_NB_SUBFR ], /* I Pitch lags */
+ const opus_int Lambda_Q10, /* I Rate/distortion tradeoff */
+ const opus_int LTP_scale_Q14 /* I LTP state scaling */
);
#if !defined(OVERRIDE_silk_NSQ_del_dec)
-#define silk_NSQ_del_dec(psEncC, NSQ, psIndices, x_Q3, pulses, PredCoef_Q12, LTPCoef_Q14, AR2_Q13, \
+#define silk_NSQ_del_dec(psEncC, NSQ, psIndices, x16, pulses, PredCoef_Q12, LTPCoef_Q14, AR_Q13, \
HarmShapeGain_Q14, Tilt_Q14, LF_shp_Q14, Gains_Q16, pitchL, Lambda_Q10, LTP_scale_Q14, arch) \
- ((void)(arch),silk_NSQ_del_dec_c(psEncC, NSQ, psIndices, x_Q3, pulses, PredCoef_Q12, LTPCoef_Q14, AR2_Q13, \
+ ((void)(arch),silk_NSQ_del_dec_c(psEncC, NSQ, psIndices, x16, pulses, PredCoef_Q12, LTPCoef_Q14, AR_Q13, \
HarmShapeGain_Q14, Tilt_Q14, LF_shp_Q14, Gains_Q16, pitchL, Lambda_Q10, LTP_scale_Q14))
#endif
@@ -346,6 +350,7 @@ void silk_NLSF_VQ(
opus_int32 err_Q26[], /* O Quantization errors [K] */
const opus_int16 in_Q15[], /* I Input vectors to be quantized [LPC_order] */
const opus_uint8 pCB_Q8[], /* I Codebook vectors [K*LPC_order] */
+ const opus_int16 pWght_Q9[], /* I Codebook weights [K*LPC_order] */
const opus_int K, /* I Number of codebook vectors */
const opus_int LPC_order /* I Number of LPCs */
);
diff --git a/libs/libopus/silk/mips/NSQ_del_dec_mipsr1.h b/libs/libopus/silk/mips/NSQ_del_dec_mipsr1.h
index ad1cfe2a9..cd70713a8 100644
--- a/libs/libopus/silk/mips/NSQ_del_dec_mipsr1.h
+++ b/libs/libopus/silk/mips/NSQ_del_dec_mipsr1.h
@@ -61,7 +61,7 @@ static inline void silk_noise_shape_quantizer_del_dec(
opus_int predictLPCOrder, /* I Prediction filter order */
opus_int warping_Q16, /* I */
opus_int nStatesDelayedDecision, /* I Number of states in decision tree */
- opus_int *smpl_buf_idx, /* I Index to newest samples in buffers */
+ opus_int *smpl_buf_idx, /* I/O Index to newest samples in buffers */
opus_int decisionDelay, /* I */
int arch /* I */
)
@@ -323,8 +323,9 @@ static inline void silk_noise_shape_quantizer_del_dec(
psSS[ 1 ].xq_Q14 = xq_Q14;
}
- *smpl_buf_idx = ( *smpl_buf_idx - 1 ) & DECISION_DELAY_MASK; /* Index to newest samples */
- last_smple_idx = ( *smpl_buf_idx + decisionDelay ) & DECISION_DELAY_MASK; /* Index to decisionDelay old samples */
+ *smpl_buf_idx = ( *smpl_buf_idx - 1 ) % DECISION_DELAY;
+ if( *smpl_buf_idx < 0 ) *smpl_buf_idx += DECISION_DELAY;
+ last_smple_idx = ( *smpl_buf_idx + decisionDelay ) % DECISION_DELAY;
/* Find winner */
RDmin_Q10 = psSampleState[ 0 ][ 0 ].RD_Q10;
diff --git a/libs/libopus/silk/mips/sigproc_fix_mipsr1.h b/libs/libopus/silk/mips/sigproc_fix_mipsr1.h
index 3b0a69536..51520c0a6 100644
--- a/libs/libopus/silk/mips/sigproc_fix_mipsr1.h
+++ b/libs/libopus/silk/mips/sigproc_fix_mipsr1.h
@@ -28,11 +28,6 @@ POSSIBILITY OF SUCH DAMAGE.
#ifndef SILK_SIGPROC_FIX_MIPSR1_H
#define SILK_SIGPROC_FIX_MIPSR1_H
-#ifdef __cplusplus
-extern "C"
-{
-#endif
-
#undef silk_SAT16
static inline short int silk_SAT16(int a)
{
diff --git a/libs/libopus/silk/process_NLSFs.c b/libs/libopus/silk/process_NLSFs.c
index 0ab71f016..d13080954 100644
--- a/libs/libopus/silk/process_NLSFs.c
+++ b/libs/libopus/silk/process_NLSFs.c
@@ -48,7 +48,7 @@ void silk_process_NLSFs(
silk_assert( psEncC->speech_activity_Q8 >= 0 );
silk_assert( psEncC->speech_activity_Q8 <= SILK_FIX_CONST( 1.0, 8 ) );
- silk_assert( psEncC->useInterpolatedNLSFs == 1 || psEncC->indices.NLSFInterpCoef_Q2 == ( 1 << 2 ) );
+ celt_assert( psEncC->useInterpolatedNLSFs == 1 || psEncC->indices.NLSFInterpCoef_Q2 == ( 1 << 2 ) );
/***********************/
/* Calculate mu values */
@@ -60,7 +60,7 @@ void silk_process_NLSFs(
NLSF_mu_Q20 = silk_ADD_RSHIFT( NLSF_mu_Q20, NLSF_mu_Q20, 1 );
}
- silk_assert( NLSF_mu_Q20 > 0 );
+ celt_assert( NLSF_mu_Q20 > 0 );
silk_assert( NLSF_mu_Q20 <= SILK_FIX_CONST( 0.005, 20 ) );
/* Calculate NLSF weights */
@@ -89,7 +89,7 @@ void silk_process_NLSFs(
NLSF_mu_Q20, psEncC->NLSF_MSVQ_Survivors, psEncC->indices.signalType );
/* Convert quantized NLSFs back to LPC coefficients */
- silk_NLSF2A( PredCoef_Q12[ 1 ], pNLSF_Q15, psEncC->predictLPCOrder );
+ silk_NLSF2A( PredCoef_Q12[ 1 ], pNLSF_Q15, psEncC->predictLPCOrder, psEncC->arch );
if( doInterpolate ) {
/* Calculate the interpolated, quantized LSF vector for the first half */
@@ -97,11 +97,11 @@ void silk_process_NLSFs(
psEncC->indices.NLSFInterpCoef_Q2, psEncC->predictLPCOrder );
/* Convert back to LPC coefficients */
- silk_NLSF2A( PredCoef_Q12[ 0 ], pNLSF0_temp_Q15, psEncC->predictLPCOrder );
+ silk_NLSF2A( PredCoef_Q12[ 0 ], pNLSF0_temp_Q15, psEncC->predictLPCOrder, psEncC->arch );
} else {
/* Copy LPC coefficients for first half from second half */
- silk_assert( psEncC->predictLPCOrder <= MAX_LPC_ORDER );
+ celt_assert( psEncC->predictLPCOrder <= MAX_LPC_ORDER );
silk_memcpy( PredCoef_Q12[ 0 ], PredCoef_Q12[ 1 ], psEncC->predictLPCOrder * sizeof( opus_int16 ) );
}
}
diff --git a/libs/libopus/silk/quant_LTP_gains.c b/libs/libopus/silk/quant_LTP_gains.c
index 513a8c446..d6b8eff8d 100644
--- a/libs/libopus/silk/quant_LTP_gains.c
+++ b/libs/libopus/silk/quant_LTP_gains.c
@@ -33,14 +33,15 @@ POSSIBILITY OF SUCH DAMAGE.
#include "tuning_parameters.h"
void silk_quant_LTP_gains(
- opus_int16 B_Q14[ MAX_NB_SUBFR * LTP_ORDER ], /* I/O (un)quantized LTP gains */
+ opus_int16 B_Q14[ MAX_NB_SUBFR * LTP_ORDER ], /* O Quantized LTP gains */
opus_int8 cbk_index[ MAX_NB_SUBFR ], /* O Codebook Index */
opus_int8 *periodicity_index, /* O Periodicity Index */
opus_int32 *sum_log_gain_Q7, /* I/O Cumulative max prediction gain */
- const opus_int32 W_Q18[ MAX_NB_SUBFR*LTP_ORDER*LTP_ORDER ], /* I Error Weights in Q18 */
- opus_int mu_Q9, /* I Mu value (R/D tradeoff) */
- opus_int lowComplexity, /* I Flag for low complexity */
- const opus_int nb_subfr, /* I number of subframes */
+ opus_int *pred_gain_dB_Q7, /* O LTP prediction gain */
+ const opus_int32 XX_Q17[ MAX_NB_SUBFR*LTP_ORDER*LTP_ORDER ], /* I Correlation matrix in Q18 */
+ const opus_int32 xX_Q17[ MAX_NB_SUBFR*LTP_ORDER ], /* I Correlation vector in Q18 */
+ const opus_int subfr_len, /* I Number of samples per subframe */
+ const opus_int nb_subfr, /* I Number of subframes */
int arch /* I Run-time architecture */
)
{
@@ -49,16 +50,16 @@ void silk_quant_LTP_gains(
const opus_uint8 *cl_ptr_Q5;
const opus_int8 *cbk_ptr_Q7;
const opus_uint8 *cbk_gain_ptr_Q7;
- const opus_int16 *b_Q14_ptr;
- const opus_int32 *W_Q18_ptr;
- opus_int32 rate_dist_Q14_subfr, rate_dist_Q14, min_rate_dist_Q14;
- opus_int32 sum_log_gain_tmp_Q7, best_sum_log_gain_Q7, max_gain_Q7, gain_Q7;
+ const opus_int32 *XX_Q17_ptr, *xX_Q17_ptr;
+ opus_int32 res_nrg_Q15_subfr, res_nrg_Q15, rate_dist_Q7_subfr, rate_dist_Q7, min_rate_dist_Q7;
+ opus_int32 sum_log_gain_tmp_Q7, best_sum_log_gain_Q7, max_gain_Q7;
+ opus_int gain_Q7;
/***************************************************/
/* iterate over different codebooks with different */
/* rates/distortions, and choose best */
/***************************************************/
- min_rate_dist_Q14 = silk_int32_MAX;
+ min_rate_dist_Q7 = silk_int32_MAX;
best_sum_log_gain_Q7 = 0;
for( k = 0; k < 3; k++ ) {
/* Safety margin for pitch gain control, to take into account factors
@@ -70,53 +71,47 @@ void silk_quant_LTP_gains(
cbk_gain_ptr_Q7 = silk_LTP_vq_gain_ptrs_Q7[ k ];
cbk_size = silk_LTP_vq_sizes[ k ];
- /* Set up pointer to first subframe */
- W_Q18_ptr = W_Q18;
- b_Q14_ptr = B_Q14;
+ /* Set up pointers to first subframe */
+ XX_Q17_ptr = XX_Q17;
+ xX_Q17_ptr = xX_Q17;
- rate_dist_Q14 = 0;
+ res_nrg_Q15 = 0;
+ rate_dist_Q7 = 0;
sum_log_gain_tmp_Q7 = *sum_log_gain_Q7;
for( j = 0; j < nb_subfr; j++ ) {
max_gain_Q7 = silk_log2lin( ( SILK_FIX_CONST( MAX_SUM_LOG_GAIN_DB / 6.0, 7 ) - sum_log_gain_tmp_Q7 )
+ SILK_FIX_CONST( 7, 7 ) ) - gain_safety;
-
silk_VQ_WMat_EC(
&temp_idx[ j ], /* O index of best codebook vector */
- &rate_dist_Q14_subfr, /* O best weighted quantization error + mu * rate */
+ &res_nrg_Q15_subfr, /* O residual energy */
+ &rate_dist_Q7_subfr, /* O best weighted quantization error + mu * rate */
&gain_Q7, /* O sum of absolute LTP coefficients */
- b_Q14_ptr, /* I input vector to be quantized */
- W_Q18_ptr, /* I weighting matrix */
+ XX_Q17_ptr, /* I correlation matrix */
+ xX_Q17_ptr, /* I correlation vector */
cbk_ptr_Q7, /* I codebook */
cbk_gain_ptr_Q7, /* I codebook effective gains */
cl_ptr_Q5, /* I code length for each codebook vector */
- mu_Q9, /* I tradeoff between weighted error and rate */
+ subfr_len, /* I number of samples per subframe */
max_gain_Q7, /* I maximum sum of absolute LTP coefficients */
cbk_size, /* I number of vectors in codebook */
arch /* I Run-time architecture */
);
- rate_dist_Q14 = silk_ADD_POS_SAT32( rate_dist_Q14, rate_dist_Q14_subfr );
+ res_nrg_Q15 = silk_ADD_POS_SAT32( res_nrg_Q15, res_nrg_Q15_subfr );
+ rate_dist_Q7 = silk_ADD_POS_SAT32( rate_dist_Q7, rate_dist_Q7_subfr );
sum_log_gain_tmp_Q7 = silk_max(0, sum_log_gain_tmp_Q7
+ silk_lin2log( gain_safety + gain_Q7 ) - SILK_FIX_CONST( 7, 7 ));
- b_Q14_ptr += LTP_ORDER;
- W_Q18_ptr += LTP_ORDER * LTP_ORDER;
+ XX_Q17_ptr += LTP_ORDER * LTP_ORDER;
+ xX_Q17_ptr += LTP_ORDER;
}
- /* Avoid never finding a codebook */
- rate_dist_Q14 = silk_min( silk_int32_MAX - 1, rate_dist_Q14 );
-
- if( rate_dist_Q14 < min_rate_dist_Q14 ) {
- min_rate_dist_Q14 = rate_dist_Q14;
+ if( rate_dist_Q7 <= min_rate_dist_Q7 ) {
+ min_rate_dist_Q7 = rate_dist_Q7;
*periodicity_index = (opus_int8)k;
silk_memcpy( cbk_index, temp_idx, nb_subfr * sizeof( opus_int8 ) );
best_sum_log_gain_Q7 = sum_log_gain_tmp_Q7;
}
-
- /* Break early in low-complexity mode if rate distortion is below threshold */
- if( lowComplexity && ( rate_dist_Q14 < silk_LTP_gain_middle_avg_RD_Q14 ) ) {
- break;
- }
}
cbk_ptr_Q7 = silk_LTP_vq_ptrs_Q7[ *periodicity_index ];
@@ -125,5 +120,13 @@ void silk_quant_LTP_gains(
B_Q14[ j * LTP_ORDER + k ] = silk_LSHIFT( cbk_ptr_Q7[ cbk_index[ j ] * LTP_ORDER + k ], 7 );
}
}
+
+ if( nb_subfr == 2 ) {
+ res_nrg_Q15 = silk_RSHIFT32( res_nrg_Q15, 1 );
+ } else {
+ res_nrg_Q15 = silk_RSHIFT32( res_nrg_Q15, 2 );
+ }
+
*sum_log_gain_Q7 = best_sum_log_gain_Q7;
+ *pred_gain_dB_Q7 = (opus_int)silk_SMULBB( -3, silk_lin2log( res_nrg_Q15 ) - ( 15 << 7 ) );
}
diff --git a/libs/libopus/silk/resampler.c b/libs/libopus/silk/resampler.c
index 374fbb372..1f11e5089 100644
--- a/libs/libopus/silk/resampler.c
+++ b/libs/libopus/silk/resampler.c
@@ -91,14 +91,14 @@ opus_int silk_resampler_init(
if( forEnc ) {
if( ( Fs_Hz_in != 8000 && Fs_Hz_in != 12000 && Fs_Hz_in != 16000 && Fs_Hz_in != 24000 && Fs_Hz_in != 48000 ) ||
( Fs_Hz_out != 8000 && Fs_Hz_out != 12000 && Fs_Hz_out != 16000 ) ) {
- silk_assert( 0 );
+ celt_assert( 0 );
return -1;
}
S->inputDelay = delay_matrix_enc[ rateID( Fs_Hz_in ) ][ rateID( Fs_Hz_out ) ];
} else {
if( ( Fs_Hz_in != 8000 && Fs_Hz_in != 12000 && Fs_Hz_in != 16000 ) ||
( Fs_Hz_out != 8000 && Fs_Hz_out != 12000 && Fs_Hz_out != 16000 && Fs_Hz_out != 24000 && Fs_Hz_out != 48000 ) ) {
- silk_assert( 0 );
+ celt_assert( 0 );
return -1;
}
S->inputDelay = delay_matrix_dec[ rateID( Fs_Hz_in ) ][ rateID( Fs_Hz_out ) ];
@@ -151,7 +151,7 @@ opus_int silk_resampler_init(
S->Coefs = silk_Resampler_1_6_COEFS;
} else {
/* None available */
- silk_assert( 0 );
+ celt_assert( 0 );
return -1;
}
} else {
@@ -181,9 +181,9 @@ opus_int silk_resampler(
opus_int nSamples;
/* Need at least 1 ms of input data */
- silk_assert( inLen >= S->Fs_in_kHz );
+ celt_assert( inLen >= S->Fs_in_kHz );
/* Delay can't exceed the 1 ms of buffering */
- silk_assert( S->inputDelay <= S->Fs_in_kHz );
+ celt_assert( S->inputDelay <= S->Fs_in_kHz );
nSamples = S->Fs_in_kHz - S->inputDelay;
diff --git a/libs/libopus/silk/resampler_down2.c b/libs/libopus/silk/resampler_down2.c
index cec363464..971d7bfd4 100644
--- a/libs/libopus/silk/resampler_down2.c
+++ b/libs/libopus/silk/resampler_down2.c
@@ -43,8 +43,8 @@ void silk_resampler_down2(
opus_int32 k, len2 = silk_RSHIFT32( inLen, 1 );
opus_int32 in32, out32, Y, X;
- silk_assert( silk_resampler_down2_0 > 0 );
- silk_assert( silk_resampler_down2_1 < 0 );
+ celt_assert( silk_resampler_down2_0 > 0 );
+ celt_assert( silk_resampler_down2_1 < 0 );
/* Internal variables and state are in Q10 format */
for( k = 0; k < len2; k++ ) {
diff --git a/libs/libopus/silk/resampler_private_down_FIR.c b/libs/libopus/silk/resampler_private_down_FIR.c
index 783e42b35..3e8735a35 100644
--- a/libs/libopus/silk/resampler_private_down_FIR.c
+++ b/libs/libopus/silk/resampler_private_down_FIR.c
@@ -136,7 +136,7 @@ static OPUS_INLINE opus_int16 *silk_resampler_private_down_FIR_INTERPOL(
}
break;
default:
- silk_assert( 0 );
+ celt_assert( 0 );
}
return out;
}
diff --git a/libs/libopus/silk/sort.c b/libs/libopus/silk/sort.c
index 7187c9efb..4fba16f83 100644
--- a/libs/libopus/silk/sort.c
+++ b/libs/libopus/silk/sort.c
@@ -48,9 +48,9 @@ void silk_insertion_sort_increasing(
opus_int i, j;
/* Safety checks */
- silk_assert( K > 0 );
- silk_assert( L > 0 );
- silk_assert( L >= K );
+ celt_assert( K > 0 );
+ celt_assert( L > 0 );
+ celt_assert( L >= K );
/* Write start indices in index vector */
for( i = 0; i < K; i++ ) {
@@ -96,9 +96,9 @@ void silk_insertion_sort_decreasing_int16(
opus_int value;
/* Safety checks */
- silk_assert( K > 0 );
- silk_assert( L > 0 );
- silk_assert( L >= K );
+ celt_assert( K > 0 );
+ celt_assert( L > 0 );
+ celt_assert( L >= K );
/* Write start indices in index vector */
for( i = 0; i < K; i++ ) {
@@ -141,7 +141,7 @@ void silk_insertion_sort_increasing_all_values_int16(
opus_int i, j;
/* Safety checks */
- silk_assert( L > 0 );
+ celt_assert( L > 0 );
/* Sort vector elements by value, increasing order */
for( i = 1; i < L; i++ ) {
diff --git a/libs/libopus/silk/stereo_LR_to_MS.c b/libs/libopus/silk/stereo_LR_to_MS.c
index dda0298de..c8226663c 100644
--- a/libs/libopus/silk/stereo_LR_to_MS.c
+++ b/libs/libopus/silk/stereo_LR_to_MS.c
@@ -109,7 +109,7 @@ void silk_stereo_LR_to_MS(
if( total_rate_bps < 1 ) {
total_rate_bps = 1;
}
- min_mid_rate_bps = silk_SMLABB( 2000, fs_kHz, 900 );
+ min_mid_rate_bps = silk_SMLABB( 2000, fs_kHz, 600 );
silk_assert( min_mid_rate_bps < 32767 );
/* Default bitrate distribution: 8 parts for Mid and (5+3*frac) parts for Side. so: mid_rate = ( 8 / ( 13 + 3 * frac ) ) * total_ rate */
frac_3_Q16 = silk_MUL( 3, frac_Q16 );
diff --git a/libs/libopus/silk/stereo_encode_pred.c b/libs/libopus/silk/stereo_encode_pred.c
index e6dd19506..03becb673 100644
--- a/libs/libopus/silk/stereo_encode_pred.c
+++ b/libs/libopus/silk/stereo_encode_pred.c
@@ -41,11 +41,11 @@ void silk_stereo_encode_pred(
/* Entropy coding */
n = 5 * ix[ 0 ][ 2 ] + ix[ 1 ][ 2 ];
- silk_assert( n < 25 );
+ celt_assert( n < 25 );
ec_enc_icdf( psRangeEnc, n, silk_stereo_pred_joint_iCDF, 8 );
for( n = 0; n < 2; n++ ) {
- silk_assert( ix[ n ][ 0 ] < 3 );
- silk_assert( ix[ n ][ 1 ] < STEREO_QUANT_SUB_STEPS );
+ celt_assert( ix[ n ][ 0 ] < 3 );
+ celt_assert( ix[ n ][ 1 ] < STEREO_QUANT_SUB_STEPS );
ec_enc_icdf( psRangeEnc, ix[ n ][ 0 ], silk_uniform3_iCDF, 8 );
ec_enc_icdf( psRangeEnc, ix[ n ][ 1 ], silk_uniform5_iCDF, 8 );
}
diff --git a/libs/libopus/silk/structs.h b/libs/libopus/silk/structs.h
index 827829dc6..3380c757b 100644
--- a/libs/libopus/silk/structs.h
+++ b/libs/libopus/silk/structs.h
@@ -48,6 +48,7 @@ typedef struct {
opus_int32 sLPC_Q14[ MAX_SUB_FRAME_LENGTH + NSQ_LPC_BUF_LENGTH ];
opus_int32 sAR2_Q14[ MAX_SHAPE_LPC_ORDER ];
opus_int32 sLF_AR_shp_Q14;
+ opus_int32 sDiff_shp_Q14;
opus_int lagPrev;
opus_int sLTP_buf_idx;
opus_int sLTP_shp_buf_idx;
@@ -77,6 +78,7 @@ typedef struct {
opus_int32 In_LP_State[ 2 ]; /* Low pass filter state */
opus_int32 transition_frame_no; /* Counter which is mapped to a cut-off frequency */
opus_int mode; /* Operating mode, <0: switch down, >0: switch up; 0: do nothing */
+ opus_int32 saved_fs_kHz; /* If non-zero, holds the last sampling rate before a bandwidth switching reset. */
} silk_LP_state;
/* Structure containing NLSF codebook */
@@ -86,6 +88,7 @@ typedef struct {
const opus_int16 quantStepSize_Q16;
const opus_int16 invQuantStepSize_Q6;
const opus_uint8 *CB1_NLSF_Q8;
+ const opus_int16 *CB1_Wght_Q9;
const opus_uint8 *CB1_iCDF;
const opus_uint8 *pred_Q8;
const opus_uint8 *ec_sel;
@@ -169,8 +172,6 @@ typedef struct {
opus_int pitchEstimationComplexity; /* Complexity level for pitch estimator */
opus_int pitchEstimationLPCOrder; /* Whitening filter order for pitch estimator */
opus_int32 pitchEstimationThreshold_Q16; /* Threshold for pitch estimator */
- opus_int LTPQuantLowComplexity; /* Flag for low complexity LTP quantization */
- opus_int mu_LTP_Q9; /* Rate-distortion tradeoff in LTP quantization */
opus_int32 sum_log_gain_Q7; /* Cumulative max prediction gain */
opus_int NLSF_MSVQ_Survivors; /* Number of survivors in NLSF MSVQ */
opus_int first_frame_after_reset; /* Flag for deactivating NLSF interpolation, pitch prediction */
@@ -301,6 +302,7 @@ typedef struct {
/* Stuff used for PLC */
opus_int lossCnt;
opus_int prevSignalType;
+ int arch;
silk_PLC_struct sPLC;
diff --git a/libs/libopus/silk/sum_sqr_shift.c b/libs/libopus/silk/sum_sqr_shift.c
index 129df191d..4fd0c3d7d 100644
--- a/libs/libopus/silk/sum_sqr_shift.c
+++ b/libs/libopus/silk/sum_sqr_shift.c
@@ -41,43 +41,40 @@ void silk_sum_sqr_shift(
)
{
opus_int i, shft;
- opus_int32 nrg_tmp, nrg;
+ opus_uint32 nrg_tmp;
+ opus_int32 nrg;
- nrg = 0;
- shft = 0;
- len--;
- for( i = 0; i < len; i += 2 ) {
- nrg = silk_SMLABB_ovflw( nrg, x[ i ], x[ i ] );
- nrg = silk_SMLABB_ovflw( nrg, x[ i + 1 ], x[ i + 1 ] );
- if( nrg < 0 ) {
- /* Scale down */
- nrg = (opus_int32)silk_RSHIFT_uint( (opus_uint32)nrg, 2 );
- shft = 2;
- i+=2;
- break;
- }
+ /* Do a first run with the maximum shift we could have. */
+ shft = 31-silk_CLZ32(len);
+ /* Let's be conservative with rounding and start with nrg=len. */
+ nrg = len;
+ for( i = 0; i < len - 1; i += 2 ) {
+ nrg_tmp = silk_SMULBB( x[ i ], x[ i ] );
+ nrg_tmp = silk_SMLABB_ovflw( nrg_tmp, x[ i + 1 ], x[ i + 1 ] );
+ nrg = (opus_int32)silk_ADD_RSHIFT_uint( nrg, nrg_tmp, shft );
}
- for( ; i < len; i += 2 ) {
+ if( i < len ) {
+ /* One sample left to process */
+ nrg_tmp = silk_SMULBB( x[ i ], x[ i ] );
+ nrg = (opus_int32)silk_ADD_RSHIFT_uint( nrg, nrg_tmp, shft );
+ }
+ silk_assert( nrg >= 0 );
+ /* Make sure the result will fit in a 32-bit signed integer with two bits
+ of headroom. */
+ shft = silk_max_32(0, shft+3 - silk_CLZ32(nrg));
+ nrg = 0;
+ for( i = 0 ; i < len - 1; i += 2 ) {
nrg_tmp = silk_SMULBB( x[ i ], x[ i ] );
nrg_tmp = silk_SMLABB_ovflw( nrg_tmp, x[ i + 1 ], x[ i + 1 ] );
- nrg = (opus_int32)silk_ADD_RSHIFT_uint( nrg, (opus_uint32)nrg_tmp, shft );
- if( nrg < 0 ) {
- /* Scale down */
- nrg = (opus_int32)silk_RSHIFT_uint( (opus_uint32)nrg, 2 );
- shft += 2;
- }
+ nrg = (opus_int32)silk_ADD_RSHIFT_uint( nrg, nrg_tmp, shft );
}
- if( i == len ) {
+ if( i < len ) {
/* One sample left to process */
nrg_tmp = silk_SMULBB( x[ i ], x[ i ] );
nrg = (opus_int32)silk_ADD_RSHIFT_uint( nrg, nrg_tmp, shft );
}
- /* Make sure to have at least one extra leading zero (two leading zeros in total) */
- if( nrg & 0xC0000000 ) {
- nrg = silk_RSHIFT_uint( (opus_uint32)nrg, 2 );
- shft += 2;
- }
+ silk_assert( nrg >= 0 );
/* Output arguments */
*shift = shft;
diff --git a/libs/libopus/silk/tables.h b/libs/libopus/silk/tables.h
index 7fea6fda3..95230c451 100644
--- a/libs/libopus/silk/tables.h
+++ b/libs/libopus/silk/tables.h
@@ -76,10 +76,8 @@ extern const opus_uint8 silk_NLSF_EXT_iCDF[ 7 ];
extern const opus_uint8 silk_LTP_per_index_iCDF[ 3 ]; /* 3 */
extern const opus_uint8 * const silk_LTP_gain_iCDF_ptrs[ NB_LTP_CBKS ]; /* 3 */
extern const opus_uint8 * const silk_LTP_gain_BITS_Q5_ptrs[ NB_LTP_CBKS ]; /* 3 */
-extern const opus_int16 silk_LTP_gain_middle_avg_RD_Q14;
extern const opus_int8 * const silk_LTP_vq_ptrs_Q7[ NB_LTP_CBKS ]; /* 168 */
extern const opus_uint8 * const silk_LTP_vq_gain_ptrs_Q7[NB_LTP_CBKS];
-
extern const opus_int8 silk_LTP_vq_sizes[ NB_LTP_CBKS ]; /* 3 */
extern const opus_uint8 silk_LTPscale_iCDF[ 3 ]; /* 4 */
@@ -99,12 +97,6 @@ extern const opus_uint8 silk_NLSF_interpolation_factor_iCDF[ 5 ];
extern const silk_NLSF_CB_struct silk_NLSF_CB_WB; /* 1040 */
extern const silk_NLSF_CB_struct silk_NLSF_CB_NB_MB; /* 728 */
-/* Piece-wise linear mapping from bitrate in kbps to coding quality in dB SNR */
-extern const opus_int32 silk_TargetRate_table_NB[ TARGET_RATE_TAB_SZ ]; /* 32 */
-extern const opus_int32 silk_TargetRate_table_MB[ TARGET_RATE_TAB_SZ ]; /* 32 */
-extern const opus_int32 silk_TargetRate_table_WB[ TARGET_RATE_TAB_SZ ]; /* 32 */
-extern const opus_int16 silk_SNR_table_Q1[ TARGET_RATE_TAB_SZ ]; /* 32 */
-
/* Quantization offsets */
extern const opus_int16 silk_Quantization_Offsets_Q10[ 2 ][ 2 ]; /* 8 */
diff --git a/libs/libopus/silk/tables_LTP.c b/libs/libopus/silk/tables_LTP.c
index 0e6a0254d..5e12c8643 100644
--- a/libs/libopus/silk/tables_LTP.c
+++ b/libs/libopus/silk/tables_LTP.c
@@ -51,8 +51,6 @@ static const opus_uint8 silk_LTP_gain_iCDF_2[32] = {
24, 20, 16, 12, 9, 5, 2, 0
};
-const opus_int16 silk_LTP_gain_middle_avg_RD_Q14 = 12304;
-
static const opus_uint8 silk_LTP_gain_BITS_Q5_0[8] = {
15, 131, 138, 138, 155, 155, 173, 173
};
diff --git a/libs/libopus/silk/tables_NLSF_CB_NB_MB.c b/libs/libopus/silk/tables_NLSF_CB_NB_MB.c
index 8c59d207a..195d5b95b 100644
--- a/libs/libopus/silk/tables_NLSF_CB_NB_MB.c
+++ b/libs/libopus/silk/tables_NLSF_CB_NB_MB.c
@@ -74,6 +74,41 @@ static const opus_uint8 silk_NLSF_CB1_NB_MB_Q8[ 320 ] = {
64, 84, 104, 118, 156, 177, 201, 230
};
+static const opus_int16 silk_NLSF_CB1_Wght_Q9[ 320 ] = {
+ 2897, 2314, 2314, 2314, 2287, 2287, 2314, 2300, 2327, 2287,
+ 2888, 2580, 2394, 2367, 2314, 2274, 2274, 2274, 2274, 2194,
+ 2487, 2340, 2340, 2314, 2314, 2314, 2340, 2340, 2367, 2354,
+ 3216, 2766, 2340, 2340, 2314, 2274, 2221, 2207, 2261, 2194,
+ 2460, 2474, 2367, 2394, 2394, 2394, 2394, 2367, 2407, 2314,
+ 3479, 3056, 2127, 2207, 2274, 2274, 2274, 2287, 2314, 2261,
+ 3282, 3141, 2580, 2394, 2247, 2221, 2207, 2194, 2194, 2114,
+ 4096, 3845, 2221, 2620, 2620, 2407, 2314, 2394, 2367, 2074,
+ 3178, 3244, 2367, 2221, 2553, 2434, 2340, 2314, 2167, 2221,
+ 3338, 3488, 2726, 2194, 2261, 2460, 2354, 2367, 2207, 2101,
+ 2354, 2420, 2327, 2367, 2394, 2420, 2420, 2420, 2460, 2367,
+ 3779, 3629, 2434, 2527, 2367, 2274, 2274, 2300, 2207, 2048,
+ 3254, 3225, 2713, 2846, 2447, 2327, 2300, 2300, 2274, 2127,
+ 3263, 3300, 2753, 2806, 2447, 2261, 2261, 2247, 2127, 2101,
+ 2873, 2981, 2633, 2367, 2407, 2354, 2194, 2247, 2247, 2114,
+ 3225, 3197, 2633, 2580, 2274, 2181, 2247, 2221, 2221, 2141,
+ 3178, 3310, 2740, 2407, 2274, 2274, 2274, 2287, 2194, 2114,
+ 3141, 3272, 2460, 2061, 2287, 2500, 2367, 2487, 2434, 2181,
+ 3507, 3282, 2314, 2700, 2647, 2474, 2367, 2394, 2340, 2127,
+ 3423, 3535, 3038, 3056, 2300, 1950, 2221, 2274, 2274, 2274,
+ 3404, 3366, 2087, 2687, 2873, 2354, 2420, 2274, 2474, 2540,
+ 3760, 3488, 1950, 2660, 2897, 2527, 2394, 2367, 2460, 2261,
+ 3028, 3272, 2740, 2888, 2740, 2154, 2127, 2287, 2234, 2247,
+ 3695, 3657, 2025, 1969, 2660, 2700, 2580, 2500, 2327, 2367,
+ 3207, 3413, 2354, 2074, 2888, 2888, 2340, 2487, 2247, 2167,
+ 3338, 3366, 2846, 2780, 2327, 2154, 2274, 2287, 2114, 2061,
+ 2327, 2300, 2181, 2167, 2181, 2367, 2633, 2700, 2700, 2553,
+ 2407, 2434, 2221, 2261, 2221, 2221, 2340, 2420, 2607, 2700,
+ 3038, 3244, 2806, 2888, 2474, 2074, 2300, 2314, 2354, 2380,
+ 2221, 2154, 2127, 2287, 2500, 2793, 2793, 2620, 2580, 2367,
+ 3676, 3713, 2234, 1838, 2181, 2753, 2726, 2673, 2513, 2207,
+ 2793, 3160, 2726, 2553, 2846, 2513, 2181, 2394, 2221, 2181
+};
+
static const opus_uint8 silk_NLSF_CB1_iCDF_NB_MB[ 64 ] = {
212, 178, 148, 129, 108, 96, 85, 82,
79, 77, 61, 59, 57, 56, 51, 49,
@@ -150,6 +185,7 @@ const silk_NLSF_CB_struct silk_NLSF_CB_NB_MB =
SILK_FIX_CONST( 0.18, 16 ),
SILK_FIX_CONST( 1.0 / 0.18, 6 ),
silk_NLSF_CB1_NB_MB_Q8,
+ silk_NLSF_CB1_Wght_Q9,
silk_NLSF_CB1_iCDF_NB_MB,
silk_NLSF_PRED_NB_MB_Q8,
silk_NLSF_CB2_SELECT_NB_MB,
diff --git a/libs/libopus/silk/tables_NLSF_CB_WB.c b/libs/libopus/silk/tables_NLSF_CB_WB.c
index 50af87eb2..5cc9f57bf 100644
--- a/libs/libopus/silk/tables_NLSF_CB_WB.c
+++ b/libs/libopus/silk/tables_NLSF_CB_WB.c
@@ -98,6 +98,41 @@ static const opus_uint8 silk_NLSF_CB1_WB_Q8[ 512 ] = {
110, 119, 129, 141, 175, 198, 218, 237
};
+static const opus_int16 silk_NLSF_CB1_WB_Wght_Q9[ 512 ] = {
+ 3657, 2925, 2925, 2925, 2925, 2925, 2925, 2925, 2925, 2925, 2925, 2925, 2963, 2963, 2925, 2846,
+ 3216, 3085, 2972, 3056, 3056, 3010, 3010, 3010, 2963, 2963, 3010, 2972, 2888, 2846, 2846, 2726,
+ 3920, 4014, 2981, 3207, 3207, 2934, 3056, 2846, 3122, 3244, 2925, 2846, 2620, 2553, 2780, 2925,
+ 3516, 3197, 3010, 3103, 3019, 2888, 2925, 2925, 2925, 2925, 2888, 2888, 2888, 2888, 2888, 2753,
+ 5054, 5054, 2934, 3573, 3385, 3056, 3085, 2793, 3160, 3160, 2972, 2846, 2513, 2540, 2753, 2888,
+ 4428, 4149, 2700, 2753, 2972, 3010, 2925, 2846, 2981, 3019, 2925, 2925, 2925, 2925, 2888, 2726,
+ 3620, 3019, 2972, 3056, 3056, 2873, 2806, 3056, 3216, 3047, 2981, 3291, 3291, 2981, 3310, 2991,
+ 5227, 5014, 2540, 3338, 3526, 3385, 3197, 3094, 3376, 2981, 2700, 2647, 2687, 2793, 2846, 2673,
+ 5081, 5174, 4615, 4428, 2460, 2897, 3047, 3207, 3169, 2687, 2740, 2888, 2846, 2793, 2846, 2700,
+ 3122, 2888, 2963, 2925, 2925, 2925, 2925, 2963, 2963, 2963, 2963, 2925, 2925, 2963, 2963, 2963,
+ 4202, 3207, 2981, 3103, 3010, 2888, 2888, 2925, 2972, 2873, 2916, 3019, 2972, 3010, 3197, 2873,
+ 3760, 3760, 3244, 3103, 2981, 2888, 2925, 2888, 2972, 2934, 2793, 2793, 2846, 2888, 2888, 2660,
+ 3854, 4014, 3207, 3122, 3244, 2934, 3047, 2963, 2963, 3085, 2846, 2793, 2793, 2793, 2793, 2580,
+ 3845, 4080, 3357, 3516, 3094, 2740, 3010, 2934, 3122, 3085, 2846, 2846, 2647, 2647, 2846, 2806,
+ 5147, 4894, 3225, 3845, 3441, 3169, 2897, 3413, 3451, 2700, 2580, 2673, 2740, 2846, 2806, 2753,
+ 4109, 3789, 3291, 3160, 2925, 2888, 2888, 2925, 2793, 2740, 2793, 2740, 2793, 2846, 2888, 2806,
+ 5081, 5054, 3047, 3545, 3244, 3056, 3085, 2944, 3103, 2897, 2740, 2740, 2740, 2846, 2793, 2620,
+ 4309, 4309, 2860, 2527, 3207, 3376, 3376, 3075, 3075, 3376, 3056, 2846, 2647, 2580, 2726, 2753,
+ 3056, 2916, 2806, 2888, 2740, 2687, 2897, 3103, 3150, 3150, 3216, 3169, 3056, 3010, 2963, 2846,
+ 4375, 3882, 2925, 2888, 2846, 2888, 2846, 2846, 2888, 2888, 2888, 2846, 2888, 2925, 2888, 2846,
+ 2981, 2916, 2916, 2981, 2981, 3056, 3122, 3216, 3150, 3056, 3010, 2972, 2972, 2972, 2925, 2740,
+ 4229, 4149, 3310, 3347, 2925, 2963, 2888, 2981, 2981, 2846, 2793, 2740, 2846, 2846, 2846, 2793,
+ 4080, 4014, 3103, 3010, 2925, 2925, 2925, 2888, 2925, 2925, 2846, 2846, 2846, 2793, 2888, 2780,
+ 4615, 4575, 3169, 3441, 3207, 2981, 2897, 3038, 3122, 2740, 2687, 2687, 2687, 2740, 2793, 2700,
+ 4149, 4269, 3789, 3657, 2726, 2780, 2888, 2888, 3010, 2972, 2925, 2846, 2687, 2687, 2793, 2888,
+ 4215, 3554, 2753, 2846, 2846, 2888, 2888, 2888, 2925, 2925, 2888, 2925, 2925, 2925, 2963, 2888,
+ 5174, 4921, 2261, 3432, 3789, 3479, 3347, 2846, 3310, 3479, 3150, 2897, 2460, 2487, 2753, 2925,
+ 3451, 3685, 3122, 3197, 3357, 3047, 3207, 3207, 2981, 3216, 3085, 2925, 2925, 2687, 2540, 2434,
+ 2981, 3010, 2793, 2793, 2740, 2793, 2846, 2972, 3056, 3103, 3150, 3150, 3150, 3103, 3010, 3010,
+ 2944, 2873, 2687, 2726, 2780, 3010, 3432, 3545, 3357, 3244, 3056, 3010, 2963, 2925, 2888, 2846,
+ 3019, 2944, 2897, 3010, 3010, 2972, 3019, 3103, 3056, 3056, 3010, 2888, 2846, 2925, 2925, 2888,
+ 3920, 3967, 3010, 3197, 3357, 3216, 3291, 3291, 3479, 3704, 3441, 2726, 2181, 2460, 2580, 2607
+};
+
static const opus_uint8 silk_NLSF_CB1_iCDF_WB[ 64 ] = {
225, 204, 201, 184, 183, 175, 158, 154,
153, 135, 119, 115, 113, 110, 109, 99,
@@ -188,6 +223,7 @@ const silk_NLSF_CB_struct silk_NLSF_CB_WB =
SILK_FIX_CONST( 0.15, 16 ),
SILK_FIX_CONST( 1.0 / 0.15, 6 ),
silk_NLSF_CB1_WB_Q8,
+ silk_NLSF_CB1_WB_Wght_Q9,
silk_NLSF_CB1_iCDF_WB,
silk_NLSF_PRED_WB_Q8,
silk_NLSF_CB2_SELECT_WB,
diff --git a/libs/libopus/silk/tables_other.c b/libs/libopus/silk/tables_other.c
index 398686bf2..e34d90777 100644
--- a/libs/libopus/silk/tables_other.c
+++ b/libs/libopus/silk/tables_other.c
@@ -38,20 +38,6 @@ extern "C"
{
#endif
-/* Piece-wise linear mapping from bitrate in kbps to coding quality in dB SNR */
-const opus_int32 silk_TargetRate_table_NB[ TARGET_RATE_TAB_SZ ] = {
- 0, 8000, 9400, 11500, 13500, 17500, 25000, MAX_TARGET_RATE_BPS
-};
-const opus_int32 silk_TargetRate_table_MB[ TARGET_RATE_TAB_SZ ] = {
- 0, 9000, 12000, 14500, 18500, 24500, 35500, MAX_TARGET_RATE_BPS
-};
-const opus_int32 silk_TargetRate_table_WB[ TARGET_RATE_TAB_SZ ] = {
- 0, 10500, 14000, 17000, 21500, 28500, 42000, MAX_TARGET_RATE_BPS
-};
-const opus_int16 silk_SNR_table_Q1[ TARGET_RATE_TAB_SZ ] = {
- 18, 29, 38, 40, 46, 52, 62, 84
-};
-
/* Tables for stereo predictor coding */
const opus_int16 silk_stereo_pred_quant_Q13[ STEREO_QUANT_TAB_SIZE ] = {
-13732, -10050, -8266, -7526, -6500, -5000, -2950, -820,
diff --git a/libs/libopus/silk/tuning_parameters.h b/libs/libopus/silk/tuning_parameters.h
index 5b8f40423..d70275fd8 100644
--- a/libs/libopus/silk/tuning_parameters.h
+++ b/libs/libopus/silk/tuning_parameters.h
@@ -53,19 +53,12 @@ extern "C"
/* LPC analysis regularization */
#define FIND_LPC_COND_FAC 1e-5f
-/* LTP analysis defines */
-#define FIND_LTP_COND_FAC 1e-5f
-#define LTP_DAMPING 0.05f
-#define LTP_SMOOTHING 0.1f
-
-/* LTP quantization settings */
-#define MU_LTP_QUANT_NB 0.03f
-#define MU_LTP_QUANT_MB 0.025f
-#define MU_LTP_QUANT_WB 0.02f
-
/* Max cumulative LTP gain */
#define MAX_SUM_LOG_GAIN_DB 250.0f
+/* LTP analysis defines */
+#define LTP_CORR_INV_MAX 0.03f
+
/***********************/
/* High pass filtering */
/***********************/
@@ -103,25 +96,16 @@ extern "C"
#define SPARSE_SNR_INCR_dB 2.0f
/* threshold for sparseness measure above which to use lower quantization offset during unvoiced */
-#define SPARSENESS_THRESHOLD_QNT_OFFSET 0.75f
+#define ENERGY_VARIATION_THRESHOLD_QNT_OFFSET 0.6f
/* warping control */
#define WARPING_MULTIPLIER 0.015f
/* fraction added to first autocorrelation value */
-#define SHAPE_WHITE_NOISE_FRACTION 5e-5f
+#define SHAPE_WHITE_NOISE_FRACTION 3e-5f
/* noise shaping filter chirp factor */
-#define BANDWIDTH_EXPANSION 0.95f
-
-/* difference between chirp factors for analysis and synthesis noise shaping filters at low bitrates */
-#define LOW_RATE_BANDWIDTH_EXPANSION_DELTA 0.01f
-
-/* extra harmonic boosting (signal shaping) at low bitrates */
-#define LOW_RATE_HARMONIC_BOOST 0.1f
-
-/* extra harmonic boosting (signal shaping) for noisy input signals */
-#define LOW_INPUT_QUALITY_HARMONIC_BOOST 0.1f
+#define BANDWIDTH_EXPANSION 0.94f
/* harmonic noise shaping */
#define HARMONIC_SHAPING 0.3f
diff --git a/libs/libopus/silk/typedef.h b/libs/libopus/silk/typedef.h
index 97b7e709b..793d2c0c1 100644
--- a/libs/libopus/silk/typedef.h
+++ b/libs/libopus/silk/typedef.h
@@ -67,6 +67,9 @@ __attribute__((noreturn))
static OPUS_INLINE void _silk_fatal(const char *str, const char *file, int line)
{
fprintf (stderr, "Fatal (internal) error in %s, line %d: %s\n", file, line, str);
+#if defined(_MSC_VER)
+ _set_abort_behavior( 0, _WRITE_ABORT_MSG);
+#endif
abort();
}
# define silk_assert(COND) {if (!(COND)) {silk_fatal("assertion failed: " #COND);}}
diff --git a/libs/libopus/silk/x86/NSQ_del_dec_sse.c b/libs/libopus/silk/x86/NSQ_del_dec_sse4_1.c
index 21d4a8bc1..42735c528 100644
--- a/libs/libopus/silk/x86/NSQ_del_dec_sse.c
+++ b/libs/libopus/silk/x86/NSQ_del_dec_sse4_1.c
@@ -1,5 +1,5 @@
-/* Copyright (c) 2014, Cisco Systems, INC
- Written by XiangMingZhu WeiZhou MinPeng YanWang
+/* Copyright (c) 2014-2020, Cisco Systems, INC
+ Written by XiangMingZhu WeiZhou MinPeng YanWang FrancisQuiers
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
@@ -46,6 +46,7 @@ typedef struct {
opus_int32 Shape_Q14[ DECISION_DELAY ];
opus_int32 sAR2_Q14[ MAX_SHAPE_LPC_ORDER ];
opus_int32 LF_AR_Q14;
+ opus_int32 Diff_Q14;
opus_int32 Seed;
opus_int32 SeedInit;
opus_int32 RD_Q10;
@@ -56,6 +57,7 @@ typedef struct {
opus_int32 RD_Q10;
opus_int32 xq_Q14;
opus_int32 LF_AR_Q14;
+ opus_int32 Diff_Q14;
opus_int32 sLTP_shp_Q14;
opus_int32 LPC_exc_Q14;
} NSQ_sample_struct;
@@ -66,7 +68,7 @@ static OPUS_INLINE void silk_nsq_del_dec_scale_states_sse4_1(
const silk_encoder_state *psEncC, /* I Encoder State */
silk_nsq_state *NSQ, /* I/O NSQ state */
NSQ_del_dec_struct psDelDec[], /* I/O Delayed decision states */
- const opus_int32 x_Q3[], /* I Input in Q3 */
+ const opus_int16 x16[], /* I Input */
opus_int32 x_sc_Q10[], /* O Input scaled with 1/Gain in Q10 */
const opus_int16 sLTP[], /* I Re-whitened LTP state in Q0 */
opus_int32 sLTP_Q15[], /* O LTP state matching scaled input */
@@ -107,26 +109,26 @@ static OPUS_INLINE void silk_noise_shape_quantizer_del_dec_sse4_1(
opus_int predictLPCOrder, /* I Prediction filter order */
opus_int warping_Q16, /* I */
opus_int nStatesDelayedDecision, /* I Number of states in decision tree */
- opus_int *smpl_buf_idx, /* I Index to newest samples in buffers */
+ opus_int *smpl_buf_idx, /* I/O Index to newest samples in buffers */
opus_int decisionDelay /* I */
);
void silk_NSQ_del_dec_sse4_1(
- const silk_encoder_state *psEncC, /* I/O Encoder State */
- silk_nsq_state *NSQ, /* I/O NSQ state */
- SideInfoIndices *psIndices, /* I/O Quantization Indices */
- const opus_int32 x_Q3[], /* I Prefiltered input signal */
- opus_int8 pulses[], /* O Quantized pulse signal */
- const opus_int16 PredCoef_Q12[ 2 * MAX_LPC_ORDER ], /* I Short term prediction coefs */
- const opus_int16 LTPCoef_Q14[ LTP_ORDER * MAX_NB_SUBFR ], /* I Long term prediction coefs */
- const opus_int16 AR2_Q13[ MAX_NB_SUBFR * MAX_SHAPE_LPC_ORDER ], /* I Noise shaping coefs */
- const opus_int HarmShapeGain_Q14[ MAX_NB_SUBFR ], /* I Long term shaping coefs */
- const opus_int Tilt_Q14[ MAX_NB_SUBFR ], /* I Spectral tilt */
- const opus_int32 LF_shp_Q14[ MAX_NB_SUBFR ], /* I Low frequency shaping coefs */
- const opus_int32 Gains_Q16[ MAX_NB_SUBFR ], /* I Quantization step sizes */
- const opus_int pitchL[ MAX_NB_SUBFR ], /* I Pitch lags */
- const opus_int Lambda_Q10, /* I Rate/distortion tradeoff */
- const opus_int LTP_scale_Q14 /* I LTP state scaling */
+ const silk_encoder_state *psEncC, /* I Encoder State */
+ silk_nsq_state *NSQ, /* I/O NSQ state */
+ SideInfoIndices *psIndices, /* I/O Quantization Indices */
+ const opus_int16 x16[], /* I Input */
+ opus_int8 pulses[], /* O Quantized pulse signal */
+ const opus_int16 PredCoef_Q12[ 2 * MAX_LPC_ORDER ], /* I Short term prediction coefs */
+ const opus_int16 LTPCoef_Q14[ LTP_ORDER * MAX_NB_SUBFR ], /* I Long term prediction coefs */
+ const opus_int16 AR_Q13[ MAX_NB_SUBFR * MAX_SHAPE_LPC_ORDER ], /* I Noise shaping coefs */
+ const opus_int HarmShapeGain_Q14[ MAX_NB_SUBFR ], /* I Long term shaping coefs */
+ const opus_int Tilt_Q14[ MAX_NB_SUBFR ], /* I Spectral tilt */
+ const opus_int32 LF_shp_Q14[ MAX_NB_SUBFR ], /* I Low frequency shaping coefs */
+ const opus_int32 Gains_Q16[ MAX_NB_SUBFR ], /* I Quantization step sizes */
+ const opus_int pitchL[ MAX_NB_SUBFR ], /* I Pitch lags */
+ const opus_int Lambda_Q10, /* I Rate/distortion tradeoff */
+ const opus_int LTP_scale_Q14 /* I LTP state scaling */
)
{
opus_int i, k, lag, start_idx, LSF_interpolation_flag, Winner_ind, subfr;
@@ -142,8 +144,39 @@ void silk_NSQ_del_dec_sse4_1(
VARDECL( opus_int32, delayedGain_Q10 );
VARDECL( NSQ_del_dec_struct, psDelDec );
NSQ_del_dec_struct *psDD;
+#ifdef OPUS_CHECK_ASM
+ silk_nsq_state NSQ_c;
+ SideInfoIndices psIndices_c;
+ opus_int8 pulses_c[ MAX_FRAME_LENGTH ];
+ const opus_int8 *const pulses_a = pulses;
+#endif
SAVE_STACK;
+#ifdef OPUS_CHECK_ASM
+ ( void )pulses_a;
+ silk_memcpy( &NSQ_c, NSQ, sizeof( NSQ_c ) );
+ silk_memcpy( &psIndices_c, psIndices, sizeof( psIndices_c ) );
+ silk_assert( psEncC->nb_subfr * psEncC->subfr_length <= MAX_FRAME_LENGTH );
+ silk_memcpy( pulses_c, pulses, psEncC->nb_subfr * psEncC->subfr_length * sizeof( pulses[0] ) );
+ silk_NSQ_del_dec_c(
+ psEncC,
+ &NSQ_c,
+ &psIndices_c,
+ x16,
+ pulses_c,
+ PredCoef_Q12,
+ LTPCoef_Q14,
+ AR_Q13,
+ HarmShapeGain_Q14,
+ Tilt_Q14,
+ LF_shp_Q14,
+ Gains_Q16,
+ pitchL,
+ Lambda_Q10,
+ LTP_scale_Q14
+ );
+#endif
+
/* Set unvoiced lag to the previous one, overwrite later for voiced */
lag = NSQ->lagPrev;
@@ -158,6 +191,7 @@ void silk_NSQ_del_dec_sse4_1(
psDD->SeedInit = psDD->Seed;
psDD->RD_Q10 = 0;
psDD->LF_AR_Q14 = NSQ->sLF_AR_shp_Q14;
+ psDD->Diff_Q14 = NSQ->sDiff_shp_Q14;
psDD->Shape_Q14[ 0 ] = NSQ->sLTP_shp_Q14[ psEncC->ltp_mem_length - 1 ];
silk_memcpy( psDD->sLPC_Q14, NSQ->sLPC_Q14, NSQ_LPC_BUF_LENGTH * sizeof( opus_int32 ) );
silk_memcpy( psDD->sAR2_Q14, NSQ->sAR2_Q14, sizeof( NSQ->sAR2_Q14 ) );
@@ -185,8 +219,7 @@ void silk_NSQ_del_dec_sse4_1(
LSF_interpolation_flag = 1;
}
- ALLOC( sLTP_Q15,
- psEncC->ltp_mem_length + psEncC->frame_length, opus_int32 );
+ ALLOC( sLTP_Q15, psEncC->ltp_mem_length + psEncC->frame_length, opus_int32 );
ALLOC( sLTP, psEncC->ltp_mem_length + psEncC->frame_length, opus_int16 );
ALLOC( x_sc_Q10, psEncC->subfr_length, opus_int32 );
ALLOC( delayedGain_Q10, DECISION_DELAY, opus_int32 );
@@ -198,7 +231,7 @@ void silk_NSQ_del_dec_sse4_1(
for( k = 0; k < psEncC->nb_subfr; k++ ) {
A_Q12 = &PredCoef_Q12[ ( ( k >> 1 ) | ( 1 - LSF_interpolation_flag ) ) * MAX_LPC_ORDER ];
B_Q14 = &LTPCoef_Q14[ k * LTP_ORDER ];
- AR_shp_Q13 = &AR2_Q13[ k * MAX_SHAPE_LPC_ORDER ];
+ AR_shp_Q13 = &AR_Q13[ k * MAX_SHAPE_LPC_ORDER ];
/* Noise shape parameters */
silk_assert( HarmShapeGain_Q14[ k ] >= 0 );
@@ -234,7 +267,8 @@ void silk_NSQ_del_dec_sse4_1(
psDD = &psDelDec[ Winner_ind ];
last_smple_idx = smpl_buf_idx + decisionDelay;
for( i = 0; i < decisionDelay; i++ ) {
- last_smple_idx = ( last_smple_idx - 1 ) & DECISION_DELAY_MASK;
+ last_smple_idx = ( last_smple_idx - 1 ) % DECISION_DELAY;
+ if( last_smple_idx < 0 ) last_smple_idx += DECISION_DELAY;
pulses[ i - decisionDelay ] = (opus_int8)silk_RSHIFT_ROUND( psDD->Q_Q10[ last_smple_idx ], 10 );
pxq[ i - decisionDelay ] = (opus_int16)silk_SAT16( silk_RSHIFT_ROUND(
silk_SMULWW( psDD->Xq_Q14[ last_smple_idx ], Gains_Q16[ 1 ] ), 14 ) );
@@ -246,7 +280,7 @@ void silk_NSQ_del_dec_sse4_1(
/* Rewhiten with new A coefs */
start_idx = psEncC->ltp_mem_length - lag - psEncC->predictLPCOrder - LTP_ORDER / 2;
- silk_assert( start_idx > 0 );
+ celt_assert( start_idx > 0 );
silk_LPC_analysis_filter( &sLTP[ start_idx ], &NSQ->xq[ start_idx + k * psEncC->subfr_length ],
A_Q12, psEncC->ltp_mem_length - start_idx, psEncC->predictLPCOrder, psEncC->arch );
@@ -256,7 +290,7 @@ void silk_NSQ_del_dec_sse4_1(
}
}
- silk_nsq_del_dec_scale_states_sse4_1( psEncC, NSQ, psDelDec, x_Q3, x_sc_Q10, sLTP, sLTP_Q15, k,
+ silk_nsq_del_dec_scale_states_sse4_1( psEncC, NSQ, psDelDec, x16, x_sc_Q10, sLTP, sLTP_Q15, k,
psEncC->nStatesDelayedDecision, LTP_scale_Q14, Gains_Q16, pitchL, psIndices->signalType, decisionDelay );
silk_noise_shape_quantizer_del_dec_sse4_1( NSQ, psDelDec, psIndices->signalType, x_sc_Q10, pulses, pxq, sLTP_Q15,
@@ -264,7 +298,7 @@ void silk_NSQ_del_dec_sse4_1(
Gains_Q16[ k ], Lambda_Q10, offset_Q10, psEncC->subfr_length, subfr++, psEncC->shapingLPCOrder,
psEncC->predictLPCOrder, psEncC->warping_Q16, psEncC->nStatesDelayedDecision, &smpl_buf_idx, decisionDelay );
- x_Q3 += psEncC->subfr_length;
+ x16 += psEncC->subfr_length;
pulses += psEncC->subfr_length;
pxq += psEncC->subfr_length;
}
@@ -285,7 +319,9 @@ void silk_NSQ_del_dec_sse4_1(
last_smple_idx = smpl_buf_idx + decisionDelay;
Gain_Q10 = silk_RSHIFT32( Gains_Q16[ psEncC->nb_subfr - 1 ], 6 );
for( i = 0; i < decisionDelay; i++ ) {
- last_smple_idx = ( last_smple_idx - 1 ) & DECISION_DELAY_MASK;
+ last_smple_idx = ( last_smple_idx - 1 ) % DECISION_DELAY;
+ if( last_smple_idx < 0 ) last_smple_idx += DECISION_DELAY;
+
pulses[ i - decisionDelay ] = (opus_int8)silk_RSHIFT_ROUND( psDD->Q_Q10[ last_smple_idx ], 10 );
pxq[ i - decisionDelay ] = (opus_int16)silk_SAT16( silk_RSHIFT_ROUND(
silk_SMULWW( psDD->Xq_Q14[ last_smple_idx ], Gain_Q10 ), 8 ) );
@@ -296,12 +332,19 @@ void silk_NSQ_del_dec_sse4_1(
/* Update states */
NSQ->sLF_AR_shp_Q14 = psDD->LF_AR_Q14;
+ NSQ->sDiff_shp_Q14 = psDD->Diff_Q14;
NSQ->lagPrev = pitchL[ psEncC->nb_subfr - 1 ];
/* Save quantized speech signal */
- /* DEBUG_STORE_DATA( enc.pcm, &NSQ->xq[psEncC->ltp_mem_length], psEncC->frame_length * sizeof( opus_int16 ) ) */
silk_memmove( NSQ->xq, &NSQ->xq[ psEncC->frame_length ], psEncC->ltp_mem_length * sizeof( opus_int16 ) );
silk_memmove( NSQ->sLTP_shp_Q14, &NSQ->sLTP_shp_Q14[ psEncC->frame_length ], psEncC->ltp_mem_length * sizeof( opus_int32 ) );
+
+#ifdef OPUS_CHECK_ASM
+ silk_assert( !memcmp( &NSQ_c, NSQ, sizeof( NSQ_c ) ) );
+ silk_assert( !memcmp( &psIndices_c, psIndices, sizeof( psIndices_c ) ) );
+ silk_assert( !memcmp( pulses_c, pulses_a, psEncC->nb_subfr * psEncC->subfr_length * sizeof( pulses[0] ) ) );
+#endif
+
RESTORE_STACK;
}
@@ -333,7 +376,7 @@ static OPUS_INLINE void silk_noise_shape_quantizer_del_dec_sse4_1(
opus_int predictLPCOrder, /* I Prediction filter order */
opus_int warping_Q16, /* I */
opus_int nStatesDelayedDecision, /* I Number of states in decision tree */
- opus_int *smpl_buf_idx, /* I Index to newest samples in buffers */
+ opus_int *smpl_buf_idx, /* I/O Index to newest samples in buffers */
opus_int decisionDelay /* I */
)
{
@@ -344,6 +387,7 @@ static OPUS_INLINE void silk_noise_shape_quantizer_del_dec_sse4_1(
opus_int32 q1_Q0, q1_Q10, q2_Q10, exc_Q14, LPC_exc_Q14, xq_Q14, Gain_Q10;
opus_int32 tmp1, tmp2, sLF_AR_shp_Q14;
opus_int32 *pred_lag_ptr, *shp_lag_ptr, *psLPC_Q14;
+
VARDECL( NSQ_sample_pair, psSampleState );
NSQ_del_dec_struct *psDD;
NSQ_sample_struct *psSS;
@@ -352,9 +396,11 @@ static OPUS_INLINE void silk_noise_shape_quantizer_del_dec_sse4_1(
__m128i b_Q12_0123, b_sr_Q12_0123;
SAVE_STACK;
- silk_assert( nStatesDelayedDecision > 0 );
+ celt_assert( nStatesDelayedDecision > 0 );
ALLOC( psSampleState, nStatesDelayedDecision, NSQ_sample_pair );
+ int rdo_offset = (Lambda_Q10 >> 1) - 512;
+
shp_lag_ptr = &NSQ->sLTP_shp_Q14[ NSQ->sLTP_shp_buf_idx - lag + HARM_SHAPE_FIR_TAPS / 2 ];
pred_lag_ptr = &sLTP_Q15[ NSQ->sLTP_buf_idx - lag + LTP_ORDER / 2 ];
Gain_Q10 = silk_RSHIFT( Gain_Q16, 6 );
@@ -406,8 +452,8 @@ static OPUS_INLINE void silk_noise_shape_quantizer_del_dec_sse4_1(
/* Long-term shaping */
if( lag > 0 ) {
/* Symmetric, packed FIR coefficients */
- n_LTP_Q14 = silk_SMULWB( silk_ADD32( shp_lag_ptr[ 0 ], shp_lag_ptr[ -2 ] ), HarmShapeFIRPacked_Q14 );
- n_LTP_Q14 = silk_SMLAWT( n_LTP_Q14, shp_lag_ptr[ -1 ], HarmShapeFIRPacked_Q14 );
+ n_LTP_Q14 = silk_SMULWB( silk_ADD_SAT32( shp_lag_ptr[ 0 ], shp_lag_ptr[ -2 ] ), HarmShapeFIRPacked_Q14 );
+ n_LTP_Q14 = silk_SMLAWT( n_LTP_Q14, shp_lag_ptr[ -1 ], HarmShapeFIRPacked_Q14 );
n_LTP_Q14 = silk_SUB_LSHIFT32( LTP_pred_Q14, n_LTP_Q14, 2 ); /* Q12 -> Q14 */
shp_lag_ptr++;
} else {
@@ -477,7 +523,7 @@ static OPUS_INLINE void silk_noise_shape_quantizer_del_dec_sse4_1(
psLPC_Q14_tmp = _mm_srli_epi64( psLPC_Q14_tmp, 16 );
tmpb = _mm_add_epi32( tmpb, psLPC_Q14_tmp );
- /* setp 4 */
+ /* step 4 */
psLPC_Q14_tmp = _mm_loadu_si128( (__m128i *)(&psLPC_Q14[ -15 ] ) );
psLPC_Q14_tmp = _mm_shuffle_epi32( psLPC_Q14_tmp, 0x1B );
tmpa = _mm_mul_epi32( psLPC_Q14_tmp, a_Q12_CDEF );
@@ -510,9 +556,9 @@ static OPUS_INLINE void silk_noise_shape_quantizer_del_dec_sse4_1(
LPC_pred_Q14 = silk_LSHIFT( LPC_pred_Q14, 4 ); /* Q10 -> Q14 */
/* Noise shape feedback */
- silk_assert( ( shapingLPCOrder & 1 ) == 0 ); /* check that order is even */
+ celt_assert( ( shapingLPCOrder & 1 ) == 0 ); /* check that order is even */
/* Output of lowpass section */
- tmp2 = silk_SMLAWB( psLPC_Q14[ 0 ], psDD->sAR2_Q14[ 0 ], warping_Q16 );
+ tmp2 = silk_SMLAWB( psDD->Diff_Q14, psDD->sAR2_Q14[ 0 ], warping_Q16 );
/* Output of allpass section */
tmp1 = silk_SMLAWB( psDD->sAR2_Q14[ 0 ], psDD->sAR2_Q14[ 1 ] - tmp2, warping_Q16 );
psDD->sAR2_Q14[ 0 ] = tmp2;
@@ -542,9 +588,9 @@ static OPUS_INLINE void silk_noise_shape_quantizer_del_dec_sse4_1(
/* Input minus prediction plus noise feedback */
/* r = x[ i ] - LTP_pred - LPC_pred + n_AR + n_Tilt + n_LF + n_LTP */
- tmp1 = silk_ADD32( n_AR_Q14, n_LF_Q14 ); /* Q14 */
+ tmp1 = silk_ADD_SAT32( n_AR_Q14, n_LF_Q14 ); /* Q14 */
tmp2 = silk_ADD32( n_LTP_Q14, LPC_pred_Q14 ); /* Q13 */
- tmp1 = silk_SUB32( tmp2, tmp1 ); /* Q13 */
+ tmp1 = silk_SUB_SAT32( tmp2, tmp1 ); /* Q13 */
tmp1 = silk_RSHIFT_ROUND( tmp1, 4 ); /* Q10 */
r_Q10 = silk_SUB32( x_Q10[ i ], tmp1 ); /* residual error Q10 */
@@ -558,6 +604,18 @@ static OPUS_INLINE void silk_noise_shape_quantizer_del_dec_sse4_1(
/* Find two quantization level candidates and measure their rate-distortion */
q1_Q10 = silk_SUB32( r_Q10, offset_Q10 );
q1_Q0 = silk_RSHIFT( q1_Q10, 10 );
+ if (Lambda_Q10 > 2048) {
+ /* For aggressive RDO, the bias becomes more than one pulse. */
+ if (q1_Q10 > rdo_offset) {
+ q1_Q0 = silk_RSHIFT( q1_Q10 - rdo_offset, 10 );
+ } else if (q1_Q10 < -rdo_offset) {
+ q1_Q0 = silk_RSHIFT( q1_Q10 + rdo_offset, 10 );
+ } else if (q1_Q10 < 0) {
+ q1_Q0 = -1;
+ } else {
+ q1_Q0 = 0;
+ }
+ }
if( q1_Q0 > 0 ) {
q1_Q10 = silk_SUB32( silk_LSHIFT( q1_Q0, 10 ), QUANT_LEVEL_ADJUST_Q10 );
q1_Q10 = silk_ADD32( q1_Q10, offset_Q10 );
@@ -611,8 +669,9 @@ static OPUS_INLINE void silk_noise_shape_quantizer_del_dec_sse4_1(
xq_Q14 = silk_ADD32( LPC_exc_Q14, LPC_pred_Q14 );
/* Update states */
- sLF_AR_shp_Q14 = silk_SUB32( xq_Q14, n_AR_Q14 );
- psSS[ 0 ].sLTP_shp_Q14 = silk_SUB32( sLF_AR_shp_Q14, n_LF_Q14 );
+ psSS[ 0 ].Diff_Q14 = silk_SUB_LSHIFT32( xq_Q14, x_Q10[ i ], 4 );
+ sLF_AR_shp_Q14 = silk_SUB32( psSS[ 0 ].Diff_Q14, n_AR_Q14 );
+ psSS[ 0 ].sLTP_shp_Q14 = silk_SUB_SAT32( sLF_AR_shp_Q14, n_LF_Q14 );
psSS[ 0 ].LF_AR_Q14 = sLF_AR_shp_Q14;
psSS[ 0 ].LPC_exc_Q14 = LPC_exc_Q14;
psSS[ 0 ].xq_Q14 = xq_Q14;
@@ -625,21 +684,22 @@ static OPUS_INLINE void silk_noise_shape_quantizer_del_dec_sse4_1(
exc_Q14 = -exc_Q14;
}
-
/* Add predictions */
LPC_exc_Q14 = silk_ADD32( exc_Q14, LTP_pred_Q14 );
xq_Q14 = silk_ADD32( LPC_exc_Q14, LPC_pred_Q14 );
/* Update states */
- sLF_AR_shp_Q14 = silk_SUB32( xq_Q14, n_AR_Q14 );
- psSS[ 1 ].sLTP_shp_Q14 = silk_SUB32( sLF_AR_shp_Q14, n_LF_Q14 );
+ psSS[ 1 ].Diff_Q14 = silk_SUB_LSHIFT32( xq_Q14, x_Q10[ i ], 4 );
+ sLF_AR_shp_Q14 = silk_SUB32( psSS[ 1 ].Diff_Q14, n_AR_Q14 );
+ psSS[ 1 ].sLTP_shp_Q14 = silk_SUB_SAT32( sLF_AR_shp_Q14, n_LF_Q14 );
psSS[ 1 ].LF_AR_Q14 = sLF_AR_shp_Q14;
psSS[ 1 ].LPC_exc_Q14 = LPC_exc_Q14;
psSS[ 1 ].xq_Q14 = xq_Q14;
}
}
- *smpl_buf_idx = ( *smpl_buf_idx - 1 ) & DECISION_DELAY_MASK; /* Index to newest samples */
- last_smple_idx = ( *smpl_buf_idx + decisionDelay ) & DECISION_DELAY_MASK; /* Index to decisionDelay old samples */
+ *smpl_buf_idx = ( *smpl_buf_idx - 1 ) % DECISION_DELAY;
+ if( *smpl_buf_idx < 0 ) *smpl_buf_idx += DECISION_DELAY;
+ last_smple_idx = ( *smpl_buf_idx + decisionDelay ) % DECISION_DELAY;
/* Find winner */
RDmin_Q10 = psSampleState[ 0 ][ 0 ].RD_Q10;
@@ -703,6 +763,7 @@ static OPUS_INLINE void silk_noise_shape_quantizer_del_dec_sse4_1(
psDD = &psDelDec[ k ];
psSS = &psSampleState[ k ][ 0 ];
psDD->LF_AR_Q14 = psSS->LF_AR_Q14;
+ psDD->Diff_Q14 = psSS->Diff_Q14;
psDD->sLPC_Q14[ NSQ_LPC_BUF_LENGTH + i ] = psSS->xq_Q14;
psDD->Xq_Q14[ *smpl_buf_idx ] = psSS->xq_Q14;
psDD->Q_Q10[ *smpl_buf_idx ] = psSS->Q_Q10;
@@ -726,7 +787,7 @@ static OPUS_INLINE void silk_nsq_del_dec_scale_states_sse4_1(
const silk_encoder_state *psEncC, /* I Encoder State */
silk_nsq_state *NSQ, /* I/O NSQ state */
NSQ_del_dec_struct psDelDec[], /* I/O Delayed decision states */
- const opus_int32 x_Q3[], /* I Input in Q3 */
+ const opus_int16 x16[], /* I Input */
opus_int32 x_sc_Q10[], /* O Input scaled with 1/Gain in Q10 */
const opus_int16 sLTP[], /* I Re-whitened LTP state in Q0 */
opus_int32 sLTP_Q15[], /* O LTP state matching scaled input */
@@ -740,51 +801,41 @@ static OPUS_INLINE void silk_nsq_del_dec_scale_states_sse4_1(
)
{
opus_int i, k, lag;
- opus_int32 gain_adj_Q16, inv_gain_Q31, inv_gain_Q23;
+ opus_int32 gain_adj_Q16, inv_gain_Q31, inv_gain_Q26;
NSQ_del_dec_struct *psDD;
- __m128i xmm_inv_gain_Q23, xmm_x_Q3_x2x0, xmm_x_Q3_x3x1;
+ __m128i xmm_inv_gain_Q26, xmm_x16_x2x0, xmm_x16_x3x1;
lag = pitchL[ subfr ];
inv_gain_Q31 = silk_INVERSE32_varQ( silk_max( Gains_Q16[ subfr ], 1 ), 47 );
-
silk_assert( inv_gain_Q31 != 0 );
- /* Calculate gain adjustment factor */
- if( Gains_Q16[ subfr ] != NSQ->prev_gain_Q16 ) {
- gain_adj_Q16 = silk_DIV32_varQ( NSQ->prev_gain_Q16, Gains_Q16[ subfr ], 16 );
- } else {
- gain_adj_Q16 = (opus_int32)1 << 16;
- }
-
/* Scale input */
- inv_gain_Q23 = silk_RSHIFT_ROUND( inv_gain_Q31, 8 );
+ inv_gain_Q26 = silk_RSHIFT_ROUND( inv_gain_Q31, 5 );
- /* prepare inv_gain_Q23 in packed 4 32-bits */
- xmm_inv_gain_Q23 = _mm_set1_epi32(inv_gain_Q23);
+ /* prepare inv_gain_Q26 in packed 4 32-bits */
+ xmm_inv_gain_Q26 = _mm_set1_epi32(inv_gain_Q26);
for( i = 0; i < psEncC->subfr_length - 3; i += 4 ) {
- xmm_x_Q3_x2x0 = _mm_loadu_si128( (__m128i *)(&(x_Q3[ i ] ) ) );
+ xmm_x16_x2x0 = OP_CVTEPI16_EPI32_M64( &(x16[ i ] ) );
+
/* equal shift right 4 bytes*/
- xmm_x_Q3_x3x1 = _mm_shuffle_epi32( xmm_x_Q3_x2x0, _MM_SHUFFLE( 0, 3, 2, 1 ) );
+ xmm_x16_x3x1 = _mm_shuffle_epi32( xmm_x16_x2x0, _MM_SHUFFLE( 0, 3, 2, 1 ) );
- xmm_x_Q3_x2x0 = _mm_mul_epi32( xmm_x_Q3_x2x0, xmm_inv_gain_Q23 );
- xmm_x_Q3_x3x1 = _mm_mul_epi32( xmm_x_Q3_x3x1, xmm_inv_gain_Q23 );
+ xmm_x16_x2x0 = _mm_mul_epi32( xmm_x16_x2x0, xmm_inv_gain_Q26 );
+ xmm_x16_x3x1 = _mm_mul_epi32( xmm_x16_x3x1, xmm_inv_gain_Q26 );
- xmm_x_Q3_x2x0 = _mm_srli_epi64( xmm_x_Q3_x2x0, 16 );
- xmm_x_Q3_x3x1 = _mm_slli_epi64( xmm_x_Q3_x3x1, 16 );
+ xmm_x16_x2x0 = _mm_srli_epi64( xmm_x16_x2x0, 16 );
+ xmm_x16_x3x1 = _mm_slli_epi64( xmm_x16_x3x1, 16 );
- xmm_x_Q3_x2x0 = _mm_blend_epi16( xmm_x_Q3_x2x0, xmm_x_Q3_x3x1, 0xCC );
+ xmm_x16_x2x0 = _mm_blend_epi16( xmm_x16_x2x0, xmm_x16_x3x1, 0xCC );
- _mm_storeu_si128( (__m128i *)(&(x_sc_Q10[ i ])), xmm_x_Q3_x2x0 );
+ _mm_storeu_si128( (__m128i *)(&(x_sc_Q10[ i ] ) ), xmm_x16_x2x0 );
}
for( ; i < psEncC->subfr_length; i++ ) {
- x_sc_Q10[ i ] = silk_SMULWW( x_Q3[ i ], inv_gain_Q23 );
+ x_sc_Q10[ i ] = silk_SMULWW( x16[ i ], inv_gain_Q26 );
}
- /* Save inverse gain */
- NSQ->prev_gain_Q16 = Gains_Q16[ subfr ];
-
/* After rewhitening the LTP state is un-scaled, so scale with inv_gain_Q16 */
if( NSQ->rewhite_flag ) {
if( subfr == 0 ) {
@@ -798,7 +849,9 @@ static OPUS_INLINE void silk_nsq_del_dec_scale_states_sse4_1(
}
/* Adjust for changing gain */
- if( gain_adj_Q16 != (opus_int32)1 << 16 ) {
+ if( Gains_Q16[ subfr ] != NSQ->prev_gain_Q16 ) {
+ gain_adj_Q16 = silk_DIV32_varQ( NSQ->prev_gain_Q16, Gains_Q16[ subfr ], 16 );
+
/* Scale long-term shaping state */
{
__m128i xmm_gain_adj_Q16, xmm_sLTP_shp_Q14_x2x0, xmm_sLTP_shp_Q14_x3x1;
@@ -839,6 +892,7 @@ static OPUS_INLINE void silk_nsq_del_dec_scale_states_sse4_1(
/* Scale scalar states */
psDD->LF_AR_Q14 = silk_SMULWW( gain_adj_Q16, psDD->LF_AR_Q14 );
+ psDD->Diff_Q14 = silk_SMULWW( gain_adj_Q16, psDD->Diff_Q14 );
/* Scale short-term prediction and shaping states */
for( i = 0; i < NSQ_LPC_BUF_LENGTH; i++ ) {
@@ -853,5 +907,8 @@ static OPUS_INLINE void silk_nsq_del_dec_scale_states_sse4_1(
}
}
}
+
+ /* Save inverse gain */
+ NSQ->prev_gain_Q16 = Gains_Q16[ subfr ];
}
}
diff --git a/libs/libopus/silk/x86/NSQ_sse.c b/libs/libopus/silk/x86/NSQ_sse4_1.c
index bb3c5f195..a2a74659b 100644
--- a/libs/libopus/silk/x86/NSQ_sse.c
+++ b/libs/libopus/silk/x86/NSQ_sse4_1.c
@@ -1,5 +1,5 @@
-/* Copyright (c) 2014, Cisco Systems, INC
- Written by XiangMingZhu WeiZhou MinPeng YanWang
+/* Copyright (c) 2014-2020, Cisco Systems, INC
+ Written by XiangMingZhu WeiZhou MinPeng YanWang FrancisQuiers
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
@@ -37,17 +37,17 @@
#include "stack_alloc.h"
static OPUS_INLINE void silk_nsq_scale_states_sse4_1(
- const silk_encoder_state *psEncC, /* I Encoder State */
- silk_nsq_state *NSQ, /* I/O NSQ state */
- const opus_int32 x_Q3[], /* I input in Q3 */
- opus_int32 x_sc_Q10[], /* O input scaled with 1/Gain */
- const opus_int16 sLTP[], /* I re-whitened LTP state in Q0 */
- opus_int32 sLTP_Q15[], /* O LTP state matching scaled input */
- opus_int subfr, /* I subframe number */
- const opus_int LTP_scale_Q14, /* I */
- const opus_int32 Gains_Q16[ MAX_NB_SUBFR ], /* I */
- const opus_int pitchL[ MAX_NB_SUBFR ], /* I Pitch lag */
- const opus_int signal_type /* I Signal type */
+ const silk_encoder_state *psEncC, /* I Encoder State */
+ silk_nsq_state *NSQ, /* I/O NSQ state */
+ const opus_int16 x16[], /* I input */
+ opus_int32 x_sc_Q10[], /* O input scaled with 1/Gain */
+ const opus_int16 sLTP[], /* I re-whitened LTP state in Q0 */
+ opus_int32 sLTP_Q15[], /* O LTP state matching scaled input */
+ opus_int subfr, /* I subframe number */
+ const opus_int LTP_scale_Q14, /* I */
+ const opus_int32 Gains_Q16[ MAX_NB_SUBFR ], /* I */
+ const opus_int pitchL[ MAX_NB_SUBFR ], /* I Pitch lag */
+ const opus_int signal_type /* I Signal type */
);
static OPUS_INLINE void silk_noise_shape_quantizer_10_16_sse4_1(
@@ -65,27 +65,28 @@ static OPUS_INLINE void silk_noise_shape_quantizer_10_16_sse4_1(
opus_int Tilt_Q14, /* I Spectral tilt */
opus_int32 LF_shp_Q14, /* I */
opus_int32 Gain_Q16, /* I */
+ opus_int Lambda_Q10, /* I */
opus_int offset_Q10, /* I */
opus_int length, /* I Input length */
opus_int32 table[][4] /* I */
);
void silk_NSQ_sse4_1(
- const silk_encoder_state *psEncC, /* I/O Encoder State */
- silk_nsq_state *NSQ, /* I/O NSQ state */
- SideInfoIndices *psIndices, /* I/O Quantization Indices */
- const opus_int32 x_Q3[], /* I Prefiltered input signal */
- opus_int8 pulses[], /* O Quantized pulse signal */
- const opus_int16 PredCoef_Q12[ 2 * MAX_LPC_ORDER ], /* I Short term prediction coefs */
- const opus_int16 LTPCoef_Q14[ LTP_ORDER * MAX_NB_SUBFR ], /* I Long term prediction coefs */
- const opus_int16 AR2_Q13[ MAX_NB_SUBFR * MAX_SHAPE_LPC_ORDER ], /* I Noise shaping coefs */
- const opus_int HarmShapeGain_Q14[ MAX_NB_SUBFR ], /* I Long term shaping coefs */
- const opus_int Tilt_Q14[ MAX_NB_SUBFR ], /* I Spectral tilt */
- const opus_int32 LF_shp_Q14[ MAX_NB_SUBFR ], /* I Low frequency shaping coefs */
- const opus_int32 Gains_Q16[ MAX_NB_SUBFR ], /* I Quantization step sizes */
- const opus_int pitchL[ MAX_NB_SUBFR ], /* I Pitch lags */
- const opus_int Lambda_Q10, /* I Rate/distortion tradeoff */
- const opus_int LTP_scale_Q14 /* I LTP state scaling */
+ const silk_encoder_state *psEncC, /* I Encoder State */
+ silk_nsq_state *NSQ, /* I/O NSQ state */
+ SideInfoIndices *psIndices, /* I/O Quantization Indices */
+ const opus_int16 x16[], /* I Input */
+ opus_int8 pulses[], /* O Quantized pulse signal */
+ const opus_int16 PredCoef_Q12[ 2 * MAX_LPC_ORDER ], /* I Short term prediction coefs */
+ const opus_int16 LTPCoef_Q14[ LTP_ORDER * MAX_NB_SUBFR ], /* I Long term prediction coefs */
+ const opus_int16 AR_Q13[ MAX_NB_SUBFR * MAX_SHAPE_LPC_ORDER ], /* I Noise shaping coefs */
+ const opus_int HarmShapeGain_Q14[ MAX_NB_SUBFR ], /* I Long term shaping coefs */
+ const opus_int Tilt_Q14[ MAX_NB_SUBFR ], /* I Spectral tilt */
+ const opus_int32 LF_shp_Q14[ MAX_NB_SUBFR ], /* I Low frequency shaping coefs */
+ const opus_int32 Gains_Q16[ MAX_NB_SUBFR ], /* I Quantization step sizes */
+ const opus_int pitchL[ MAX_NB_SUBFR ], /* I Pitch lags */
+ const opus_int Lambda_Q10, /* I Rate/distortion tradeoff */
+ const opus_int LTP_scale_Q14 /* I LTP state scaling */
)
{
opus_int k, lag, start_idx, LSF_interpolation_flag;
@@ -101,8 +102,41 @@ void silk_NSQ_sse4_1(
opus_int32 tmp1;
opus_int32 q1_Q10, q2_Q10, rd1_Q20, rd2_Q20;
+#ifdef OPUS_CHECK_ASM
+ silk_nsq_state NSQ_c;
+ SideInfoIndices psIndices_c;
+ opus_int8 pulses_c[ MAX_FRAME_LENGTH ];
+ const opus_int8 *const pulses_a = pulses;
+#endif
+
SAVE_STACK;
+#ifdef OPUS_CHECK_ASM
+ ( void )pulses_a;
+ silk_memcpy( &NSQ_c, NSQ, sizeof( NSQ_c ) );
+ silk_memcpy( &psIndices_c, psIndices, sizeof( psIndices_c ) );
+ silk_assert( psEncC->nb_subfr * psEncC->subfr_length <= MAX_FRAME_LENGTH );
+ silk_memcpy( pulses_c, pulses, psEncC->nb_subfr * psEncC->subfr_length * sizeof( pulses[0] ) );
+
+ silk_NSQ_c(
+ psEncC,
+ &NSQ_c,
+ &psIndices_c,
+ x16,
+ pulses_c,
+ PredCoef_Q12,
+ LTPCoef_Q14,
+ AR_Q13,
+ HarmShapeGain_Q14,
+ Tilt_Q14,
+ LF_shp_Q14,
+ Gains_Q16,
+ pitchL,
+ Lambda_Q10,
+ LTP_scale_Q14
+ );
+#endif
+
NSQ->rand_seed = psIndices->Seed;
/* Set unvoiced lag to the previous one, overwrite later for voiced */
@@ -172,8 +206,7 @@ void silk_NSQ_sse4_1(
LSF_interpolation_flag = 1;
}
- ALLOC( sLTP_Q15,
- psEncC->ltp_mem_length + psEncC->frame_length, opus_int32 );
+ ALLOC( sLTP_Q15, psEncC->ltp_mem_length + psEncC->frame_length, opus_int32 );
ALLOC( sLTP, psEncC->ltp_mem_length + psEncC->frame_length, opus_int16 );
ALLOC( x_sc_Q10, psEncC->subfr_length, opus_int32 );
/* Set up pointers to start of sub frame */
@@ -183,7 +216,7 @@ void silk_NSQ_sse4_1(
for( k = 0; k < psEncC->nb_subfr; k++ ) {
A_Q12 = &PredCoef_Q12[ (( k >> 1 ) | ( 1 - LSF_interpolation_flag )) * MAX_LPC_ORDER ];
B_Q14 = &LTPCoef_Q14[ k * LTP_ORDER ];
- AR_shp_Q13 = &AR2_Q13[ k * MAX_SHAPE_LPC_ORDER ];
+ AR_shp_Q13 = &AR_Q13[ k * MAX_SHAPE_LPC_ORDER ];
/* Noise shape parameters */
silk_assert( HarmShapeGain_Q14[ k ] >= 0 );
@@ -199,7 +232,7 @@ void silk_NSQ_sse4_1(
if( ( k & ( 3 - silk_LSHIFT( LSF_interpolation_flag, 1 ) ) ) == 0 ) {
/* Rewhiten with new A coefs */
start_idx = psEncC->ltp_mem_length - lag - psEncC->predictLPCOrder - LTP_ORDER / 2;
- silk_assert( start_idx > 0 );
+ celt_assert( start_idx > 0 );
silk_LPC_analysis_filter( &sLTP[ start_idx ], &NSQ->xq[ start_idx + k * psEncC->subfr_length ],
A_Q12, psEncC->ltp_mem_length - start_idx, psEncC->predictLPCOrder, psEncC->arch );
@@ -209,12 +242,12 @@ void silk_NSQ_sse4_1(
}
}
- silk_nsq_scale_states_sse4_1( psEncC, NSQ, x_Q3, x_sc_Q10, sLTP, sLTP_Q15, k, LTP_scale_Q14, Gains_Q16, pitchL, psIndices->signalType );
+ silk_nsq_scale_states_sse4_1( psEncC, NSQ, x16, x_sc_Q10, sLTP, sLTP_Q15, k, LTP_scale_Q14, Gains_Q16, pitchL, psIndices->signalType );
if ( opus_likely( ( 10 == psEncC->shapingLPCOrder ) && ( 16 == psEncC->predictLPCOrder) ) )
{
silk_noise_shape_quantizer_10_16_sse4_1( NSQ, psIndices->signalType, x_sc_Q10, pulses, pxq, sLTP_Q15, A_Q12, B_Q14,
- AR_shp_Q13, lag, HarmShapeFIRPacked_Q14, Tilt_Q14[ k ], LF_shp_Q14[ k ], Gains_Q16[ k ],
+ AR_shp_Q13, lag, HarmShapeFIRPacked_Q14, Tilt_Q14[ k ], LF_shp_Q14[ k ], Gains_Q16[ k ], Lambda_Q10,
offset_Q10, psEncC->subfr_length, &(table[32]) );
}
else
@@ -224,7 +257,7 @@ void silk_NSQ_sse4_1(
offset_Q10, psEncC->subfr_length, psEncC->shapingLPCOrder, psEncC->predictLPCOrder, psEncC->arch );
}
- x_Q3 += psEncC->subfr_length;
+ x16 += psEncC->subfr_length;
pulses += psEncC->subfr_length;
pxq += psEncC->subfr_length;
}
@@ -233,15 +266,21 @@ void silk_NSQ_sse4_1(
NSQ->lagPrev = pitchL[ psEncC->nb_subfr - 1 ];
/* Save quantized speech and noise shaping signals */
- /* DEBUG_STORE_DATA( enc.pcm, &NSQ->xq[ psEncC->ltp_mem_length ], psEncC->frame_length * sizeof( opus_int16 ) ) */
silk_memmove( NSQ->xq, &NSQ->xq[ psEncC->frame_length ], psEncC->ltp_mem_length * sizeof( opus_int16 ) );
silk_memmove( NSQ->sLTP_shp_Q14, &NSQ->sLTP_shp_Q14[ psEncC->frame_length ], psEncC->ltp_mem_length * sizeof( opus_int32 ) );
+
+#ifdef OPUS_CHECK_ASM
+ silk_assert( !memcmp( &NSQ_c, NSQ, sizeof( NSQ_c ) ) );
+ silk_assert( !memcmp( &psIndices_c, psIndices, sizeof( psIndices_c ) ) );
+ silk_assert( !memcmp( pulses_c, pulses_a, psEncC->nb_subfr * psEncC->subfr_length * sizeof( pulses[0] ) ) );
+#endif
+
RESTORE_STACK;
}
-/***********************************/
-/* silk_noise_shape_quantizer_10_16 */
-/***********************************/
+/************************************/
+/* silk_noise_shape_quantizer_10_16 */
+/************************************/
static OPUS_INLINE void silk_noise_shape_quantizer_10_16_sse4_1(
silk_nsq_state *NSQ, /* I/O NSQ state */
opus_int signalType, /* I Signal type */
@@ -257,6 +296,7 @@ static OPUS_INLINE void silk_noise_shape_quantizer_10_16_sse4_1(
opus_int Tilt_Q14, /* I Spectral tilt */
opus_int32 LF_shp_Q14, /* I */
opus_int32 Gain_Q16, /* I */
+ opus_int Lambda_Q10, /* I */
opus_int offset_Q10, /* I */
opus_int length, /* I Input length */
opus_int32 table[][4] /* I */
@@ -265,7 +305,7 @@ static OPUS_INLINE void silk_noise_shape_quantizer_10_16_sse4_1(
opus_int i;
opus_int32 LTP_pred_Q13, LPC_pred_Q10, n_AR_Q12, n_LTP_Q13;
opus_int32 n_LF_Q12, r_Q10, q1_Q0, q1_Q10, q2_Q10;
- opus_int32 exc_Q14, LPC_exc_Q14, xq_Q14, Gain_Q10;
+ opus_int32 exc_Q14, LPC_exc_Q14, xq_Q14, Gain_Q10, sDiff_shp_Q14;
opus_int32 tmp1, tmp2, sLF_AR_shp_Q14;
opus_int32 *psLPC_Q14, *shp_lag_ptr, *pred_lag_ptr;
@@ -280,6 +320,8 @@ static OPUS_INLINE void silk_noise_shape_quantizer_10_16_sse4_1(
__m128i sAR2_Q14_hi_76543210, sAR2_Q14_lo_76543210;
__m128i AR_shp_Q13_76543210;
+ int rdo_offset = (Lambda_Q10 >> 1) - 512;
+
shp_lag_ptr = &NSQ->sLTP_shp_Q14[ NSQ->sLTP_shp_buf_idx - lag + HARM_SHAPE_FIR_TAPS / 2 ];
pred_lag_ptr = &sLTP_Q15[ NSQ->sLTP_buf_idx - lag + LTP_ORDER / 2 ];
Gain_Q10 = silk_RSHIFT( Gain_Q16, 6 );
@@ -289,6 +331,7 @@ static OPUS_INLINE void silk_noise_shape_quantizer_10_16_sse4_1(
sLF_AR_shp_Q14 = NSQ->sLF_AR_shp_Q14;
xq_Q14 = psLPC_Q14[ 0 ];
+ sDiff_shp_Q14 = NSQ->sDiff_shp_Q14;
LTP_pred_Q13 = 0;
/* load a_Q12 */
@@ -431,8 +474,8 @@ static OPUS_INLINE void silk_noise_shape_quantizer_10_16_sse4_1(
sAR2_Q14_hi_76543210 = _mm_slli_si128( sAR2_Q14_hi_76543210, 2 );
sAR2_Q14_lo_76543210 = _mm_slli_si128( sAR2_Q14_lo_76543210, 2 );
- sAR2_Q14_hi_76543210 = _mm_insert_epi16( sAR2_Q14_hi_76543210, (xq_Q14 >> 16), 0 );
- sAR2_Q14_lo_76543210 = _mm_insert_epi16( sAR2_Q14_lo_76543210, (xq_Q14), 0 );
+ sAR2_Q14_hi_76543210 = _mm_insert_epi16( sAR2_Q14_hi_76543210, (sDiff_shp_Q14 >> 16), 0 );
+ sAR2_Q14_lo_76543210 = _mm_insert_epi16( sAR2_Q14_lo_76543210, (sDiff_shp_Q14), 0 );
/* high part, use pmaddwd, results in 4 32-bit */
xmm_hi_07 = _mm_madd_epi16( sAR2_Q14_hi_76543210, AR_shp_Q13_76543210 );
@@ -463,14 +506,14 @@ static OPUS_INLINE void silk_noise_shape_quantizer_10_16_sse4_1(
n_LF_Q12 = silk_SMULWB( NSQ->sLTP_shp_Q14[ NSQ->sLTP_shp_buf_idx - 1 ], LF_shp_Q14 );
n_LF_Q12 = silk_SMLAWT( n_LF_Q12, sLF_AR_shp_Q14, LF_shp_Q14 );
- silk_assert( lag > 0 || signalType != TYPE_VOICED );
+ celt_assert( lag > 0 || signalType != TYPE_VOICED );
/* Combine prediction and noise shaping signals */
tmp1 = silk_SUB32( silk_LSHIFT32( LPC_pred_Q10, 2 ), n_AR_Q12 ); /* Q12 */
tmp1 = silk_SUB32( tmp1, n_LF_Q12 ); /* Q12 */
if( lag > 0 ) {
/* Symmetric, packed FIR coefficients */
- n_LTP_Q13 = silk_SMULWB( silk_ADD32( shp_lag_ptr[ 0 ], shp_lag_ptr[ -2 ] ), HarmShapeFIRPacked_Q14 );
+ n_LTP_Q13 = silk_SMULWB( silk_ADD_SAT32( shp_lag_ptr[ 0 ], shp_lag_ptr[ -2 ] ), HarmShapeFIRPacked_Q14 );
n_LTP_Q13 = silk_SMLAWT( n_LTP_Q13, shp_lag_ptr[ -1 ], HarmShapeFIRPacked_Q14 );
n_LTP_Q13 = silk_LSHIFT( n_LTP_Q13, 1 );
shp_lag_ptr++;
@@ -496,6 +539,18 @@ static OPUS_INLINE void silk_noise_shape_quantizer_10_16_sse4_1(
/* Find two quantization level candidates and measure their rate-distortion */
q1_Q10 = silk_SUB32( r_Q10, offset_Q10 );
q1_Q0 = silk_RSHIFT( q1_Q10, 10 );
+ if (Lambda_Q10 > 2048) {
+ /* For aggressive RDO, the bias becomes more than one pulse. */
+ if (q1_Q10 > rdo_offset) {
+ q1_Q0 = silk_RSHIFT( q1_Q10 - rdo_offset, 10 );
+ } else if (q1_Q10 < -rdo_offset) {
+ q1_Q0 = silk_RSHIFT( q1_Q10 + rdo_offset, 10 );
+ } else if (q1_Q10 < 0) {
+ q1_Q0 = -1;
+ } else {
+ q1_Q0 = 0;
+ }
+ }
q1_Q10 = table[q1_Q0][0];
q2_Q10 = table[q1_Q0][1];
@@ -520,7 +575,8 @@ static OPUS_INLINE void silk_noise_shape_quantizer_10_16_sse4_1(
/* Update states */
psLPC_Q14++;
*psLPC_Q14 = xq_Q14;
- sLF_AR_shp_Q14 = silk_SUB_LSHIFT32( xq_Q14, n_AR_Q12, 2 );
+ NSQ->sDiff_shp_Q14 = silk_SUB_LSHIFT32( xq_Q14, x_sc_Q10[ i ], 4 );
+ sLF_AR_shp_Q14 = silk_SUB_LSHIFT32( NSQ->sDiff_shp_Q14, n_AR_Q12, 2 );
NSQ->sLTP_shp_Q14[ NSQ->sLTP_shp_buf_idx ] = silk_SUB_LSHIFT32( sLF_AR_shp_Q14, n_LF_Q12, 2 );
sLTP_Q15[ NSQ->sLTP_buf_idx ] = silk_LSHIFT( LPC_exc_Q14, 1 );
@@ -601,64 +657,54 @@ static OPUS_INLINE void silk_noise_shape_quantizer_10_16_sse4_1(
}
static OPUS_INLINE void silk_nsq_scale_states_sse4_1(
- const silk_encoder_state *psEncC, /* I Encoder State */
- silk_nsq_state *NSQ, /* I/O NSQ state */
- const opus_int32 x_Q3[], /* I input in Q3 */
- opus_int32 x_sc_Q10[], /* O input scaled with 1/Gain */
- const opus_int16 sLTP[], /* I re-whitened LTP state in Q0 */
- opus_int32 sLTP_Q15[], /* O LTP state matching scaled input */
- opus_int subfr, /* I subframe number */
- const opus_int LTP_scale_Q14, /* I */
- const opus_int32 Gains_Q16[ MAX_NB_SUBFR ], /* I */
- const opus_int pitchL[ MAX_NB_SUBFR ], /* I Pitch lag */
- const opus_int signal_type /* I Signal type */
+ const silk_encoder_state *psEncC, /* I Encoder State */
+ silk_nsq_state *NSQ, /* I/O NSQ state */
+ const opus_int16 x16[], /* I input */
+ opus_int32 x_sc_Q10[], /* O input scaled with 1/Gain */
+ const opus_int16 sLTP[], /* I re-whitened LTP state in Q0 */
+ opus_int32 sLTP_Q15[], /* O LTP state matching scaled input */
+ opus_int subfr, /* I subframe number */
+ const opus_int LTP_scale_Q14, /* I */
+ const opus_int32 Gains_Q16[ MAX_NB_SUBFR ], /* I */
+ const opus_int pitchL[ MAX_NB_SUBFR ], /* I Pitch lag */
+ const opus_int signal_type /* I Signal type */
)
{
opus_int i, lag;
- opus_int32 gain_adj_Q16, inv_gain_Q31, inv_gain_Q23;
- __m128i xmm_inv_gain_Q23, xmm_x_Q3_x2x0, xmm_x_Q3_x3x1;
+ opus_int32 gain_adj_Q16, inv_gain_Q31, inv_gain_Q26;
+ __m128i xmm_inv_gain_Q26, xmm_x16_x2x0, xmm_x16_x3x1;
lag = pitchL[ subfr ];
inv_gain_Q31 = silk_INVERSE32_varQ( silk_max( Gains_Q16[ subfr ], 1 ), 47 );
silk_assert( inv_gain_Q31 != 0 );
- /* Calculate gain adjustment factor */
- if( Gains_Q16[ subfr ] != NSQ->prev_gain_Q16 ) {
- gain_adj_Q16 = silk_DIV32_varQ( NSQ->prev_gain_Q16, Gains_Q16[ subfr ], 16 );
- } else {
- gain_adj_Q16 = (opus_int32)1 << 16;
- }
-
/* Scale input */
- inv_gain_Q23 = silk_RSHIFT_ROUND( inv_gain_Q31, 8 );
+ inv_gain_Q26 = silk_RSHIFT_ROUND( inv_gain_Q31, 5 );
- /* prepare inv_gain_Q23 in packed 4 32-bits */
- xmm_inv_gain_Q23 = _mm_set1_epi32(inv_gain_Q23);
+ /* prepare inv_gain_Q26 in packed 4 32-bits */
+ xmm_inv_gain_Q26 = _mm_set1_epi32(inv_gain_Q26);
for( i = 0; i < psEncC->subfr_length - 3; i += 4 ) {
- xmm_x_Q3_x2x0 = _mm_loadu_si128( (__m128i *)(&(x_Q3[ i ] ) ) );
+ xmm_x16_x2x0 = OP_CVTEPI16_EPI32_M64( &(x16[ i ] ) );
/* equal shift right 4 bytes*/
- xmm_x_Q3_x3x1 = _mm_shuffle_epi32( xmm_x_Q3_x2x0, _MM_SHUFFLE( 0, 3, 2, 1 ) );
+ xmm_x16_x3x1 = _mm_shuffle_epi32( xmm_x16_x2x0, _MM_SHUFFLE( 0, 3, 2, 1 ) );
- xmm_x_Q3_x2x0 = _mm_mul_epi32( xmm_x_Q3_x2x0, xmm_inv_gain_Q23 );
- xmm_x_Q3_x3x1 = _mm_mul_epi32( xmm_x_Q3_x3x1, xmm_inv_gain_Q23 );
+ xmm_x16_x2x0 = _mm_mul_epi32( xmm_x16_x2x0, xmm_inv_gain_Q26 );
+ xmm_x16_x3x1 = _mm_mul_epi32( xmm_x16_x3x1, xmm_inv_gain_Q26 );
- xmm_x_Q3_x2x0 = _mm_srli_epi64( xmm_x_Q3_x2x0, 16 );
- xmm_x_Q3_x3x1 = _mm_slli_epi64( xmm_x_Q3_x3x1, 16 );
+ xmm_x16_x2x0 = _mm_srli_epi64( xmm_x16_x2x0, 16 );
+ xmm_x16_x3x1 = _mm_slli_epi64( xmm_x16_x3x1, 16 );
- xmm_x_Q3_x2x0 = _mm_blend_epi16( xmm_x_Q3_x2x0, xmm_x_Q3_x3x1, 0xCC );
+ xmm_x16_x2x0 = _mm_blend_epi16( xmm_x16_x2x0, xmm_x16_x3x1, 0xCC );
- _mm_storeu_si128( (__m128i *)(&(x_sc_Q10[ i ] ) ), xmm_x_Q3_x2x0 );
+ _mm_storeu_si128( (__m128i *)(&(x_sc_Q10[ i ] ) ), xmm_x16_x2x0 );
}
for( ; i < psEncC->subfr_length; i++ ) {
- x_sc_Q10[ i ] = silk_SMULWW( x_Q3[ i ], inv_gain_Q23 );
+ x_sc_Q10[ i ] = silk_SMULWW( x16[ i ], inv_gain_Q26 );
}
- /* Save inverse gain */
- NSQ->prev_gain_Q16 = Gains_Q16[ subfr ];
-
/* After rewhitening the LTP state is un-scaled, so scale with inv_gain_Q16 */
if( NSQ->rewhite_flag ) {
if( subfr == 0 ) {
@@ -672,7 +718,9 @@ static OPUS_INLINE void silk_nsq_scale_states_sse4_1(
}
/* Adjust for changing gain */
- if( gain_adj_Q16 != (opus_int32)1 << 16 ) {
+ if( Gains_Q16[ subfr ] != NSQ->prev_gain_Q16 ) {
+ gain_adj_Q16 = silk_DIV32_varQ( NSQ->prev_gain_Q16, Gains_Q16[ subfr ], 16 );
+
/* Scale long-term shaping state */
__m128i xmm_gain_adj_Q16, xmm_sLTP_shp_Q14_x2x0, xmm_sLTP_shp_Q14_x3x1;
@@ -708,6 +756,7 @@ static OPUS_INLINE void silk_nsq_scale_states_sse4_1(
}
NSQ->sLF_AR_shp_Q14 = silk_SMULWW( gain_adj_Q16, NSQ->sLF_AR_shp_Q14 );
+ NSQ->sDiff_shp_Q14 = silk_SMULWW( gain_adj_Q16, NSQ->sDiff_shp_Q14 );
/* Scale short-term prediction and shaping states */
for( i = 0; i < NSQ_LPC_BUF_LENGTH; i++ ) {
@@ -716,5 +765,8 @@ static OPUS_INLINE void silk_nsq_scale_states_sse4_1(
for( i = 0; i < MAX_SHAPE_LPC_ORDER; i++ ) {
NSQ->sAR2_Q14[ i ] = silk_SMULWW( gain_adj_Q16, NSQ->sAR2_Q14[ i ] );
}
+
+ /* Save inverse gain */
+ NSQ->prev_gain_Q16 = Gains_Q16[ subfr ];
}
}
diff --git a/libs/libopus/silk/x86/SigProc_FIX_sse.h b/libs/libopus/silk/x86/SigProc_FIX_sse.h
index 61efa8da4..e49d5d4ec 100644
--- a/libs/libopus/silk/x86/SigProc_FIX_sse.h
+++ b/libs/libopus/silk/x86/SigProc_FIX_sse.h
@@ -67,7 +67,7 @@ extern void (*const SILK_BURG_MODIFIED_IMPL[OPUS_ARCHMASK + 1])(
#endif
-opus_int64 silk_inner_prod16_aligned_64_sse4_1(
+opus_int64 silk_inner_prod16_sse4_1(
const opus_int16 *inVec1,
const opus_int16 *inVec2,
const opus_int len
@@ -76,18 +76,18 @@ opus_int64 silk_inner_prod16_aligned_64_sse4_1(
#if defined(OPUS_X86_PRESUME_SSE4_1)
-#define silk_inner_prod16_aligned_64(inVec1, inVec2, len, arch) \
- ((void)(arch),silk_inner_prod16_aligned_64_sse4_1(inVec1, inVec2, len))
+#define silk_inner_prod16(inVec1, inVec2, len, arch) \
+ ((void)(arch),silk_inner_prod16_sse4_1(inVec1, inVec2, len))
#else
-extern opus_int64 (*const SILK_INNER_PROD16_ALIGNED_64_IMPL[OPUS_ARCHMASK + 1])(
+extern opus_int64 (*const SILK_INNER_PROD16_IMPL[OPUS_ARCHMASK + 1])(
const opus_int16 *inVec1,
const opus_int16 *inVec2,
const opus_int len);
-# define silk_inner_prod16_aligned_64(inVec1, inVec2, len, arch) \
- ((*SILK_INNER_PROD16_ALIGNED_64_IMPL[(arch) & OPUS_ARCHMASK])(inVec1, inVec2, len))
+# define silk_inner_prod16(inVec1, inVec2, len, arch) \
+ ((*SILK_INNER_PROD16_IMPL[(arch) & OPUS_ARCHMASK])(inVec1, inVec2, len))
#endif
#endif
diff --git a/libs/libopus/silk/x86/VAD_sse.c b/libs/libopus/silk/x86/VAD_sse4_1.c
index 4e90f4410..e7eaf9714 100644
--- a/libs/libopus/silk/x86/VAD_sse.c
+++ b/libs/libopus/silk/x86/VAD_sse4_1.c
@@ -1,5 +1,5 @@
-/* Copyright (c) 2014, Cisco Systems, INC
- Written by XiangMingZhu WeiZhou MinPeng YanWang
+/* Copyright (c) 2014-2020, Cisco Systems, INC
+ Written by XiangMingZhu WeiZhou MinPeng YanWang FrancisQuiers
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
@@ -63,11 +63,19 @@ opus_int silk_VAD_GetSA_Q8_sse4_1( /* O Return value, 0 if s
SAVE_STACK;
+#ifdef OPUS_CHECK_ASM
+ silk_encoder_state psEncC_c;
+ opus_int ret_c;
+
+ silk_memcpy( &psEncC_c, psEncC, sizeof( psEncC_c ) );
+ ret_c = silk_VAD_GetSA_Q8_c( &psEncC_c, pIn );
+#endif
+
/* Safety checks */
silk_assert( VAD_N_BANDS == 4 );
- silk_assert( MAX_FRAME_LENGTH >= psEncC->frame_length );
- silk_assert( psEncC->frame_length <= 512 );
- silk_assert( psEncC->frame_length == 8 * silk_RSHIFT( psEncC->frame_length, 3 ) );
+ celt_assert( MAX_FRAME_LENGTH >= psEncC->frame_length );
+ celt_assert( psEncC->frame_length <= 512 );
+ celt_assert( psEncC->frame_length == 8 * silk_RSHIFT( psEncC->frame_length, 3 ) );
/***********************/
/* Filter and Decimate */
@@ -233,15 +241,14 @@ opus_int silk_VAD_GetSA_Q8_sse4_1( /* O Return value, 0 if s
speech_nrg += ( b + 1 ) * silk_RSHIFT( Xnrg[ b ] - psSilk_VAD->NL[ b ], 4 );
}
+ if( psEncC->frame_length == 20 * psEncC->fs_kHz ) {
+ speech_nrg = silk_RSHIFT32( speech_nrg, 1 );
+ }
/* Power scaling */
if( speech_nrg <= 0 ) {
SA_Q15 = silk_RSHIFT( SA_Q15, 1 );
- } else if( speech_nrg < 32768 ) {
- if( psEncC->frame_length == 10 * psEncC->fs_kHz ) {
- speech_nrg = silk_LSHIFT_SAT32( speech_nrg, 16 );
- } else {
- speech_nrg = silk_LSHIFT_SAT32( speech_nrg, 15 );
- }
+ } else if( speech_nrg < 16384 ) {
+ speech_nrg = silk_LSHIFT32( speech_nrg, 16 );
/* square-root */
speech_nrg = silk_SQRT_APPROX( speech_nrg );
@@ -272,6 +279,11 @@ opus_int silk_VAD_GetSA_Q8_sse4_1( /* O Return value, 0 if s
psEncC->input_quality_bands_Q15[ b ] = silk_sigm_Q15( silk_RSHIFT( SNR_Q7 - 16 * 128, 4 ) );
}
+#ifdef OPUS_CHECK_ASM
+ silk_assert( ret == ret_c );
+ silk_assert( !memcmp( &psEncC_c, psEncC, sizeof( psEncC_c ) ) );
+#endif
+
RESTORE_STACK;
return( ret );
}
diff --git a/libs/libopus/silk/x86/VQ_WMat_EC_sse.c b/libs/libopus/silk/x86/VQ_WMat_EC_sse.c
deleted file mode 100644
index 74d6c6d0e..000000000
--- a/libs/libopus/silk/x86/VQ_WMat_EC_sse.c
+++ /dev/null
@@ -1,142 +0,0 @@
-/* Copyright (c) 2014, Cisco Systems, INC
- Written by XiangMingZhu WeiZhou MinPeng YanWang
-
- 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 <xmmintrin.h>
-#include <emmintrin.h>
-#include <smmintrin.h>
-#include "main.h"
-#include "celt/x86/x86cpu.h"
-
-/* Entropy constrained matrix-weighted VQ, hard-coded to 5-element vectors, for a single input data vector */
-void silk_VQ_WMat_EC_sse4_1(
- opus_int8 *ind, /* O index of best codebook vector */
- opus_int32 *rate_dist_Q14, /* O best weighted quant error + mu * rate */
- opus_int *gain_Q7, /* O sum of absolute LTP coefficients */
- const opus_int16 *in_Q14, /* I input vector to be quantized */
- const opus_int32 *W_Q18, /* I weighting matrix */
- const opus_int8 *cb_Q7, /* I codebook */
- const opus_uint8 *cb_gain_Q7, /* I codebook effective gain */
- const opus_uint8 *cl_Q5, /* I code length for each codebook vector */
- const opus_int mu_Q9, /* I tradeoff betw. weighted error and rate */
- const opus_int32 max_gain_Q7, /* I maximum sum of absolute LTP coefficients */
- opus_int L /* I number of vectors in codebook */
-)
-{
- opus_int k, gain_tmp_Q7;
- const opus_int8 *cb_row_Q7;
- opus_int16 diff_Q14[ 5 ];
- opus_int32 sum1_Q14, sum2_Q16;
-
- __m128i C_tmp1, C_tmp2, C_tmp3, C_tmp4, C_tmp5;
- /* Loop over codebook */
- *rate_dist_Q14 = silk_int32_MAX;
- cb_row_Q7 = cb_Q7;
- for( k = 0; k < L; k++ ) {
- gain_tmp_Q7 = cb_gain_Q7[k];
-
- diff_Q14[ 0 ] = in_Q14[ 0 ] - silk_LSHIFT( cb_row_Q7[ 0 ], 7 );
-
- C_tmp1 = OP_CVTEPI16_EPI32_M64( &in_Q14[ 1 ] );
- C_tmp2 = OP_CVTEPI8_EPI32_M32( &cb_row_Q7[ 1 ] );
- C_tmp2 = _mm_slli_epi32( C_tmp2, 7 );
- C_tmp1 = _mm_sub_epi32( C_tmp1, C_tmp2 );
-
- diff_Q14[ 1 ] = _mm_extract_epi16( C_tmp1, 0 );
- diff_Q14[ 2 ] = _mm_extract_epi16( C_tmp1, 2 );
- diff_Q14[ 3 ] = _mm_extract_epi16( C_tmp1, 4 );
- diff_Q14[ 4 ] = _mm_extract_epi16( C_tmp1, 6 );
-
- /* Weighted rate */
- sum1_Q14 = silk_SMULBB( mu_Q9, cl_Q5[ k ] );
-
- /* Penalty for too large gain */
- sum1_Q14 = silk_ADD_LSHIFT32( sum1_Q14, silk_max( silk_SUB32( gain_tmp_Q7, max_gain_Q7 ), 0 ), 10 );
-
- silk_assert( sum1_Q14 >= 0 );
-
- /* first row of W_Q18 */
- C_tmp3 = _mm_loadu_si128( (__m128i *)(&W_Q18[ 1 ] ) );
- C_tmp4 = _mm_mul_epi32( C_tmp3, C_tmp1 );
- C_tmp4 = _mm_srli_si128( C_tmp4, 2 );
-
- C_tmp1 = _mm_shuffle_epi32( C_tmp1, _MM_SHUFFLE( 0, 3, 2, 1 ) ); /* shift right 4 bytes */
- C_tmp3 = _mm_shuffle_epi32( C_tmp3, _MM_SHUFFLE( 0, 3, 2, 1 ) ); /* shift right 4 bytes */
-
- C_tmp5 = _mm_mul_epi32( C_tmp3, C_tmp1 );
- C_tmp5 = _mm_srli_si128( C_tmp5, 2 );
-
- C_tmp5 = _mm_add_epi32( C_tmp4, C_tmp5 );
- C_tmp5 = _mm_slli_epi32( C_tmp5, 1 );
-
- C_tmp5 = _mm_add_epi32( C_tmp5, _mm_shuffle_epi32( C_tmp5, _MM_SHUFFLE( 0, 0, 0, 2 ) ) );
- sum2_Q16 = _mm_cvtsi128_si32( C_tmp5 );
-
- sum2_Q16 = silk_SMLAWB( sum2_Q16, W_Q18[ 0 ], diff_Q14[ 0 ] );
- sum1_Q14 = silk_SMLAWB( sum1_Q14, sum2_Q16, diff_Q14[ 0 ] );
-
- /* second row of W_Q18 */
- sum2_Q16 = silk_SMULWB( W_Q18[ 7 ], diff_Q14[ 2 ] );
- sum2_Q16 = silk_SMLAWB( sum2_Q16, W_Q18[ 8 ], diff_Q14[ 3 ] );
- sum2_Q16 = silk_SMLAWB( sum2_Q16, W_Q18[ 9 ], diff_Q14[ 4 ] );
- sum2_Q16 = silk_LSHIFT( sum2_Q16, 1 );
- sum2_Q16 = silk_SMLAWB( sum2_Q16, W_Q18[ 6 ], diff_Q14[ 1 ] );
- sum1_Q14 = silk_SMLAWB( sum1_Q14, sum2_Q16, diff_Q14[ 1 ] );
-
- /* third row of W_Q18 */
- sum2_Q16 = silk_SMULWB( W_Q18[ 13 ], diff_Q14[ 3 ] );
- sum2_Q16 = silk_SMLAWB( sum2_Q16, W_Q18[ 14 ], diff_Q14[ 4 ] );
- sum2_Q16 = silk_LSHIFT( sum2_Q16, 1 );
- sum2_Q16 = silk_SMLAWB( sum2_Q16, W_Q18[ 12 ], diff_Q14[ 2 ] );
- sum1_Q14 = silk_SMLAWB( sum1_Q14, sum2_Q16, diff_Q14[ 2 ] );
-
- /* fourth row of W_Q18 */
- sum2_Q16 = silk_SMULWB( W_Q18[ 19 ], diff_Q14[ 4 ] );
- sum2_Q16 = silk_LSHIFT( sum2_Q16, 1 );
- sum2_Q16 = silk_SMLAWB( sum2_Q16, W_Q18[ 18 ], diff_Q14[ 3 ] );
- sum1_Q14 = silk_SMLAWB( sum1_Q14, sum2_Q16, diff_Q14[ 3 ] );
-
- /* last row of W_Q18 */
- sum2_Q16 = silk_SMULWB( W_Q18[ 24 ], diff_Q14[ 4 ] );
- sum1_Q14 = silk_SMLAWB( sum1_Q14, sum2_Q16, diff_Q14[ 4 ] );
-
- silk_assert( sum1_Q14 >= 0 );
-
- /* find best */
- if( sum1_Q14 < *rate_dist_Q14 ) {
- *rate_dist_Q14 = sum1_Q14;
- *ind = (opus_int8)k;
- *gain_Q7 = gain_tmp_Q7;
- }
-
- /* Go to next cbk vector */
- cb_row_Q7 += LTP_ORDER;
- }
-}
diff --git a/libs/libopus/silk/x86/VQ_WMat_EC_sse4_1.c b/libs/libopus/silk/x86/VQ_WMat_EC_sse4_1.c
new file mode 100644
index 000000000..2c7d18d05
--- /dev/null
+++ b/libs/libopus/silk/x86/VQ_WMat_EC_sse4_1.c
@@ -0,0 +1,173 @@
+/* Copyright (c) 2014-2020, Cisco Systems, INC
+ Written by XiangMingZhu WeiZhou MinPeng YanWang FrancisQuiers
+
+ 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 <xmmintrin.h>
+#include <emmintrin.h>
+#include <smmintrin.h>
+#include "main.h"
+#include "celt/x86/x86cpu.h"
+
+/* Entropy constrained matrix-weighted VQ, hard-coded to 5-element vectors, for a single input data vector */
+void silk_VQ_WMat_EC_sse4_1(
+ opus_int8 *ind, /* O index of best codebook vector */
+ opus_int32 *res_nrg_Q15, /* O best residual energy */
+ opus_int32 *rate_dist_Q8, /* O best total bitrate */
+ opus_int *gain_Q7, /* O sum of absolute LTP coefficients */
+ const opus_int32 *XX_Q17, /* I correlation matrix */
+ const opus_int32 *xX_Q17, /* I correlation vector */
+ const opus_int8 *cb_Q7, /* I codebook */
+ const opus_uint8 *cb_gain_Q7, /* I codebook effective gain */
+ const opus_uint8 *cl_Q5, /* I code length for each codebook vector */
+ const opus_int subfr_len, /* I number of samples per subframe */
+ const opus_int32 max_gain_Q7, /* I maximum sum of absolute LTP coefficients */
+ const opus_int L /* I number of vectors in codebook */
+)
+{
+ opus_int k, gain_tmp_Q7;
+ const opus_int8 *cb_row_Q7;
+ opus_int32 neg_xX_Q24[ 5 ];
+ opus_int32 sum1_Q15, sum2_Q24;
+ opus_int32 bits_res_Q8, bits_tot_Q8;
+ __m128i v_XX_31_Q17, v_XX_42_Q17, v_cb_row_31_Q7, v_cb_row_42_Q7, v_acc1_Q24, v_acc2_Q24;
+
+ /* Negate and convert to new Q domain */
+ neg_xX_Q24[ 0 ] = -silk_LSHIFT32( xX_Q17[ 0 ], 7 );
+ neg_xX_Q24[ 1 ] = -silk_LSHIFT32( xX_Q17[ 1 ], 7 );
+ neg_xX_Q24[ 2 ] = -silk_LSHIFT32( xX_Q17[ 2 ], 7 );
+ neg_xX_Q24[ 3 ] = -silk_LSHIFT32( xX_Q17[ 3 ], 7 );
+ neg_xX_Q24[ 4 ] = -silk_LSHIFT32( xX_Q17[ 4 ], 7 );
+
+ v_XX_31_Q17 = _mm_loadu_si128( (__m128i *)(&XX_Q17[ 1 ] ) );
+ v_XX_42_Q17 = _mm_shuffle_epi32( v_XX_31_Q17, _MM_SHUFFLE( 0, 3, 2, 1 ) );
+
+ /* Loop over codebook */
+ *rate_dist_Q8 = silk_int32_MAX;
+ *res_nrg_Q15 = silk_int32_MAX;
+ cb_row_Q7 = cb_Q7;
+ /* If things go really bad, at least *ind is set to something safe. */
+ *ind = 0;
+ for( k = 0; k < L; k++ ) {
+ opus_int32 penalty;
+ gain_tmp_Q7 = cb_gain_Q7[k];
+ /* Weighted rate */
+ /* Quantization error: 1 - 2 * xX * cb + cb' * XX * cb */
+ sum1_Q15 = SILK_FIX_CONST( 1.001, 15 );
+
+ /* Penalty for too large gain */
+ penalty = silk_LSHIFT32( silk_max( silk_SUB32( gain_tmp_Q7, max_gain_Q7 ), 0 ), 11 );
+
+ /* first row of XX_Q17 */
+ v_cb_row_31_Q7 = OP_CVTEPI8_EPI32_M32( &cb_row_Q7[ 1 ] );
+ v_cb_row_42_Q7 = _mm_shuffle_epi32( v_cb_row_31_Q7, _MM_SHUFFLE( 0, 3, 2, 1 ) );
+ v_cb_row_31_Q7 = _mm_mul_epi32( v_XX_31_Q17, v_cb_row_31_Q7 );
+ v_cb_row_42_Q7 = _mm_mul_epi32( v_XX_42_Q17, v_cb_row_42_Q7 );
+ v_acc1_Q24 = _mm_add_epi64( v_cb_row_31_Q7, v_cb_row_42_Q7);
+ v_acc2_Q24 = _mm_shuffle_epi32( v_acc1_Q24, _MM_SHUFFLE( 1, 0, 3, 2 ) );
+ v_acc1_Q24 = _mm_add_epi64( v_acc1_Q24, v_acc2_Q24);
+ sum2_Q24 = _mm_cvtsi128_si32( v_acc1_Q24 );
+ sum2_Q24 = silk_ADD32( neg_xX_Q24[ 0 ], sum2_Q24 );
+ sum2_Q24 = silk_LSHIFT32( sum2_Q24, 1 );
+ sum2_Q24 = silk_MLA( sum2_Q24, XX_Q17[ 0 ], cb_row_Q7[ 0 ] );
+ sum1_Q15 = silk_SMLAWB( sum1_Q15, sum2_Q24, cb_row_Q7[ 0 ] );
+
+ /* second row of XX_Q17 */
+ sum2_Q24 = silk_MLA( neg_xX_Q24[ 1 ], XX_Q17[ 7 ], cb_row_Q7[ 2 ] );
+ sum2_Q24 = silk_MLA( sum2_Q24, XX_Q17[ 8 ], cb_row_Q7[ 3 ] );
+ sum2_Q24 = silk_MLA( sum2_Q24, XX_Q17[ 9 ], cb_row_Q7[ 4 ] );
+ sum2_Q24 = silk_LSHIFT32( sum2_Q24, 1 );
+ sum2_Q24 = silk_MLA( sum2_Q24, XX_Q17[ 6 ], cb_row_Q7[ 1 ] );
+ sum1_Q15 = silk_SMLAWB( sum1_Q15, sum2_Q24, cb_row_Q7[ 1 ] );
+
+ /* third row of XX_Q17 */
+ sum2_Q24 = silk_MLA( neg_xX_Q24[ 2 ], XX_Q17[ 13 ], cb_row_Q7[ 3 ] );
+ sum2_Q24 = silk_MLA( sum2_Q24, XX_Q17[ 14 ], cb_row_Q7[ 4 ] );
+ sum2_Q24 = silk_LSHIFT32( sum2_Q24, 1 );
+ sum2_Q24 = silk_MLA( sum2_Q24, XX_Q17[ 12 ], cb_row_Q7[ 2 ] );
+ sum1_Q15 = silk_SMLAWB( sum1_Q15, sum2_Q24, cb_row_Q7[ 2 ] );
+
+ /* fourth row of XX_Q17 */
+ sum2_Q24 = silk_MLA( neg_xX_Q24[ 3 ], XX_Q17[ 19 ], cb_row_Q7[ 4 ] );
+ sum2_Q24 = silk_LSHIFT32( sum2_Q24, 1 );
+ sum2_Q24 = silk_MLA( sum2_Q24, XX_Q17[ 18 ], cb_row_Q7[ 3 ] );
+ sum1_Q15 = silk_SMLAWB( sum1_Q15, sum2_Q24, cb_row_Q7[ 3 ] );
+
+ /* last row of XX_Q17 */
+ sum2_Q24 = silk_LSHIFT32( neg_xX_Q24[ 4 ], 1 );
+ sum2_Q24 = silk_MLA( sum2_Q24, XX_Q17[ 24 ], cb_row_Q7[ 4 ] );
+ sum1_Q15 = silk_SMLAWB( sum1_Q15, sum2_Q24, cb_row_Q7[ 4 ] );
+
+ /* find best */
+ if( sum1_Q15 >= 0 ) {
+ /* Translate residual energy to bits using high-rate assumption (6 dB ==> 1 bit/sample) */
+ bits_res_Q8 = silk_SMULBB( subfr_len, silk_lin2log( sum1_Q15 + penalty) - (15 << 7) );
+ /* In the following line we reduce the codelength component by half ("-1"); seems to slightly improve quality */
+ bits_tot_Q8 = silk_ADD_LSHIFT32( bits_res_Q8, cl_Q5[ k ], 3-1 );
+ if( bits_tot_Q8 <= *rate_dist_Q8 ) {
+ *rate_dist_Q8 = bits_tot_Q8;
+ *res_nrg_Q15 = sum1_Q15 + penalty;
+ *ind = (opus_int8)k;
+ *gain_Q7 = gain_tmp_Q7;
+ }
+ }
+
+ /* Go to next cbk vector */
+ cb_row_Q7 += LTP_ORDER;
+ }
+
+#ifdef OPUS_CHECK_ASM
+ {
+ opus_int8 ind_c = 0;
+ opus_int32 res_nrg_Q15_c = 0;
+ opus_int32 rate_dist_Q8_c = 0;
+ opus_int gain_Q7_c = 0;
+
+ silk_VQ_WMat_EC_c(
+ &ind_c,
+ &res_nrg_Q15_c,
+ &rate_dist_Q8_c,
+ &gain_Q7_c,
+ XX_Q17,
+ xX_Q17,
+ cb_Q7,
+ cb_gain_Q7,
+ cl_Q5,
+ subfr_len,
+ max_gain_Q7,
+ L
+ );
+
+ silk_assert( *ind == ind_c );
+ silk_assert( *res_nrg_Q15 == res_nrg_Q15_c );
+ silk_assert( *rate_dist_Q8 == rate_dist_Q8_c );
+ silk_assert( *gain_Q7 == gain_Q7_c );
+ }
+#endif
+}
diff --git a/libs/libopus/silk/x86/main_sse.h b/libs/libopus/silk/x86/main_sse.h
index d8d61310e..0a0391a2d 100644
--- a/libs/libopus/silk/x86/main_sse.h
+++ b/libs/libopus/silk/x86/main_sse.h
@@ -38,66 +38,68 @@
void silk_VQ_WMat_EC_sse4_1(
opus_int8 *ind, /* O index of best codebook vector */
- opus_int32 *rate_dist_Q14, /* O best weighted quant error + mu * rate */
+ opus_int32 *res_nrg_Q15, /* O best residual energy */
+ opus_int32 *rate_dist_Q8, /* O best total bitrate */
opus_int *gain_Q7, /* O sum of absolute LTP coefficients */
- const opus_int16 *in_Q14, /* I input vector to be quantized */
- const opus_int32 *W_Q18, /* I weighting matrix */
+ const opus_int32 *XX_Q17, /* I correlation matrix */
+ const opus_int32 *xX_Q17, /* I correlation vector */
const opus_int8 *cb_Q7, /* I codebook */
const opus_uint8 *cb_gain_Q7, /* I codebook effective gain */
const opus_uint8 *cl_Q5, /* I code length for each codebook vector */
- const opus_int mu_Q9, /* I tradeoff betw. weighted error and rate */
+ const opus_int subfr_len, /* I number of samples per subframe */
const opus_int32 max_gain_Q7, /* I maximum sum of absolute LTP coefficients */
- opus_int L /* I number of vectors in codebook */
+ const opus_int L /* I number of vectors in codebook */
);
#if defined OPUS_X86_PRESUME_SSE4_1
-#define silk_VQ_WMat_EC(ind, rate_dist_Q14, gain_Q7, in_Q14, W_Q18, cb_Q7, cb_gain_Q7, cl_Q5, \
- mu_Q9, max_gain_Q7, L, arch) \
- ((void)(arch),silk_VQ_WMat_EC_sse4_1(ind, rate_dist_Q14, gain_Q7, in_Q14, W_Q18, cb_Q7, cb_gain_Q7, cl_Q5, \
- mu_Q9, max_gain_Q7, L))
+#define silk_VQ_WMat_EC(ind, res_nrg_Q15, rate_dist_Q8, gain_Q7, XX_Q17, xX_Q17, cb_Q7, cb_gain_Q7, cl_Q5, \
+ subfr_len, max_gain_Q7, L, arch) \
+ ((void)(arch),silk_VQ_WMat_EC_sse4_1(ind, res_nrg_Q15, rate_dist_Q8, gain_Q7, XX_Q17, xX_Q17, cb_Q7, cb_gain_Q7, cl_Q5, \
+ subfr_len, max_gain_Q7, L))
#else
extern void (*const SILK_VQ_WMAT_EC_IMPL[OPUS_ARCHMASK + 1])(
opus_int8 *ind, /* O index of best codebook vector */
- opus_int32 *rate_dist_Q14, /* O best weighted quant error + mu * rate */
+ opus_int32 *res_nrg_Q15, /* O best residual energy */
+ opus_int32 *rate_dist_Q8, /* O best total bitrate */
opus_int *gain_Q7, /* O sum of absolute LTP coefficients */
- const opus_int16 *in_Q14, /* I input vector to be quantized */
- const opus_int32 *W_Q18, /* I weighting matrix */
+ const opus_int32 *XX_Q17, /* I correlation matrix */
+ const opus_int32 *xX_Q17, /* I correlation vector */
const opus_int8 *cb_Q7, /* I codebook */
const opus_uint8 *cb_gain_Q7, /* I codebook effective gain */
const opus_uint8 *cl_Q5, /* I code length for each codebook vector */
- const opus_int mu_Q9, /* I tradeoff betw. weighted error and rate */
+ const opus_int subfr_len, /* I number of samples per subframe */
const opus_int32 max_gain_Q7, /* I maximum sum of absolute LTP coefficients */
- opus_int L /* I number of vectors in codebook */
+ const opus_int L /* I number of vectors in codebook */
);
-# define silk_VQ_WMat_EC(ind, rate_dist_Q14, gain_Q7, in_Q14, W_Q18, cb_Q7, cb_gain_Q7, cl_Q5, \
- mu_Q9, max_gain_Q7, L, arch) \
- ((*SILK_VQ_WMAT_EC_IMPL[(arch) & OPUS_ARCHMASK])(ind, rate_dist_Q14, gain_Q7, in_Q14, W_Q18, cb_Q7, cb_gain_Q7, cl_Q5, \
- mu_Q9, max_gain_Q7, L))
+# define silk_VQ_WMat_EC(ind, res_nrg_Q15, rate_dist_Q8, gain_Q7, XX_Q17, xX_Q17, cb_Q7, cb_gain_Q7, cl_Q5, \
+ subfr_len, max_gain_Q7, L, arch) \
+ ((*SILK_VQ_WMAT_EC_IMPL[(arch) & OPUS_ARCHMASK])(ind, res_nrg_Q15, rate_dist_Q8, gain_Q7, XX_Q17, xX_Q17, cb_Q7, cb_gain_Q7, cl_Q5, \
+ subfr_len, max_gain_Q7, L))
#endif
# define OVERRIDE_silk_NSQ
void silk_NSQ_sse4_1(
- const silk_encoder_state *psEncC, /* I/O Encoder State */
- silk_nsq_state *NSQ, /* I/O NSQ state */
- SideInfoIndices *psIndices, /* I/O Quantization Indices */
- const opus_int32 x_Q3[], /* I Prefiltered input signal */
- opus_int8 pulses[], /* O Quantized pulse signal */
- const opus_int16 PredCoef_Q12[ 2 * MAX_LPC_ORDER ], /* I Short term prediction coefs */
- const opus_int16 LTPCoef_Q14[ LTP_ORDER * MAX_NB_SUBFR ], /* I Long term prediction coefs */
- const opus_int16 AR2_Q13[ MAX_NB_SUBFR * MAX_SHAPE_LPC_ORDER ], /* I Noise shaping coefs */
- const opus_int HarmShapeGain_Q14[ MAX_NB_SUBFR ], /* I Long term shaping coefs */
- const opus_int Tilt_Q14[ MAX_NB_SUBFR ], /* I Spectral tilt */
- const opus_int32 LF_shp_Q14[ MAX_NB_SUBFR ], /* I Low frequency shaping coefs */
- const opus_int32 Gains_Q16[ MAX_NB_SUBFR ], /* I Quantization step sizes */
- const opus_int pitchL[ MAX_NB_SUBFR ], /* I Pitch lags */
- const opus_int Lambda_Q10, /* I Rate/distortion tradeoff */
- const opus_int LTP_scale_Q14 /* I LTP state scaling */
+ const silk_encoder_state *psEncC, /* I Encoder State */
+ silk_nsq_state *NSQ, /* I/O NSQ state */
+ SideInfoIndices *psIndices, /* I/O Quantization Indices */
+ const opus_int16 x16[], /* I Input */
+ opus_int8 pulses[], /* O Quantized pulse signal */
+ const opus_int16 PredCoef_Q12[ 2 * MAX_LPC_ORDER ], /* I Short term prediction coefs */
+ const opus_int16 LTPCoef_Q14[ LTP_ORDER * MAX_NB_SUBFR ], /* I Long term prediction coefs */
+ const opus_int16 AR_Q13[ MAX_NB_SUBFR * MAX_SHAPE_LPC_ORDER ], /* I Noise shaping coefs */
+ const opus_int HarmShapeGain_Q14[ MAX_NB_SUBFR ], /* I Long term shaping coefs */
+ const opus_int Tilt_Q14[ MAX_NB_SUBFR ], /* I Spectral tilt */
+ const opus_int32 LF_shp_Q14[ MAX_NB_SUBFR ], /* I Low frequency shaping coefs */
+ const opus_int32 Gains_Q16[ MAX_NB_SUBFR ], /* I Quantization step sizes */
+ const opus_int pitchL[ MAX_NB_SUBFR ], /* I Pitch lags */
+ const opus_int Lambda_Q10, /* I Rate/distortion tradeoff */
+ const opus_int LTP_scale_Q14 /* I LTP state scaling */
);
#if defined OPUS_X86_PRESUME_SSE4_1
@@ -110,21 +112,21 @@ void silk_NSQ_sse4_1(
#else
extern void (*const SILK_NSQ_IMPL[OPUS_ARCHMASK + 1])(
- const silk_encoder_state *psEncC, /* I/O Encoder State */
- silk_nsq_state *NSQ, /* I/O NSQ state */
- SideInfoIndices *psIndices, /* I/O Quantization Indices */
- const opus_int32 x_Q3[], /* I Prefiltered input signal */
- opus_int8 pulses[], /* O Quantized pulse signal */
- const opus_int16 PredCoef_Q12[ 2 * MAX_LPC_ORDER ], /* I Short term prediction coefs */
- const opus_int16 LTPCoef_Q14[ LTP_ORDER * MAX_NB_SUBFR ], /* I Long term prediction coefs */
- const opus_int16 AR2_Q13[ MAX_NB_SUBFR * MAX_SHAPE_LPC_ORDER ], /* I Noise shaping coefs */
- const opus_int HarmShapeGain_Q14[ MAX_NB_SUBFR ], /* I Long term shaping coefs */
- const opus_int Tilt_Q14[ MAX_NB_SUBFR ], /* I Spectral tilt */
- const opus_int32 LF_shp_Q14[ MAX_NB_SUBFR ], /* I Low frequency shaping coefs */
- const opus_int32 Gains_Q16[ MAX_NB_SUBFR ], /* I Quantization step sizes */
- const opus_int pitchL[ MAX_NB_SUBFR ], /* I Pitch lags */
- const opus_int Lambda_Q10, /* I Rate/distortion tradeoff */
- const opus_int LTP_scale_Q14 /* I LTP state scaling */
+ const silk_encoder_state *psEncC, /* I Encoder State */
+ silk_nsq_state *NSQ, /* I/O NSQ state */
+ SideInfoIndices *psIndices, /* I/O Quantization Indices */
+ const opus_int16 x16[], /* I Input */
+ opus_int8 pulses[], /* O Quantized pulse signal */
+ const opus_int16 PredCoef_Q12[ 2 * MAX_LPC_ORDER ], /* I Short term prediction coefs */
+ const opus_int16 LTPCoef_Q14[ LTP_ORDER * MAX_NB_SUBFR ], /* I Long term prediction coefs */
+ const opus_int16 AR_Q13[ MAX_NB_SUBFR * MAX_SHAPE_LPC_ORDER ], /* I Noise shaping coefs */
+ const opus_int HarmShapeGain_Q14[ MAX_NB_SUBFR ], /* I Long term shaping coefs */
+ const opus_int Tilt_Q14[ MAX_NB_SUBFR ], /* I Spectral tilt */
+ const opus_int32 LF_shp_Q14[ MAX_NB_SUBFR ], /* I Low frequency shaping coefs */
+ const opus_int32 Gains_Q16[ MAX_NB_SUBFR ], /* I Quantization step sizes */
+ const opus_int pitchL[ MAX_NB_SUBFR ], /* I Pitch lags */
+ const opus_int Lambda_Q10, /* I Rate/distortion tradeoff */
+ const opus_int LTP_scale_Q14 /* I LTP state scaling */
);
# define silk_NSQ(psEncC, NSQ, psIndices, x_Q3, pulses, PredCoef_Q12, LTPCoef_Q14, AR2_Q13, \
@@ -137,53 +139,53 @@ extern void (*const SILK_NSQ_IMPL[OPUS_ARCHMASK + 1])(
# define OVERRIDE_silk_NSQ_del_dec
void silk_NSQ_del_dec_sse4_1(
- const silk_encoder_state *psEncC, /* I/O Encoder State */
- silk_nsq_state *NSQ, /* I/O NSQ state */
- SideInfoIndices *psIndices, /* I/O Quantization Indices */
- const opus_int32 x_Q3[], /* I Prefiltered input signal */
- opus_int8 pulses[], /* O Quantized pulse signal */
- const opus_int16 PredCoef_Q12[ 2 * MAX_LPC_ORDER ], /* I Short term prediction coefs */
- const opus_int16 LTPCoef_Q14[ LTP_ORDER * MAX_NB_SUBFR ], /* I Long term prediction coefs */
- const opus_int16 AR2_Q13[ MAX_NB_SUBFR * MAX_SHAPE_LPC_ORDER ], /* I Noise shaping coefs */
- const opus_int HarmShapeGain_Q14[ MAX_NB_SUBFR ], /* I Long term shaping coefs */
- const opus_int Tilt_Q14[ MAX_NB_SUBFR ], /* I Spectral tilt */
- const opus_int32 LF_shp_Q14[ MAX_NB_SUBFR ], /* I Low frequency shaping coefs */
- const opus_int32 Gains_Q16[ MAX_NB_SUBFR ], /* I Quantization step sizes */
- const opus_int pitchL[ MAX_NB_SUBFR ], /* I Pitch lags */
- const opus_int Lambda_Q10, /* I Rate/distortion tradeoff */
- const opus_int LTP_scale_Q14 /* I LTP state scaling */
+ const silk_encoder_state *psEncC, /* I Encoder State */
+ silk_nsq_state *NSQ, /* I/O NSQ state */
+ SideInfoIndices *psIndices, /* I/O Quantization Indices */
+ const opus_int16 x16[], /* I Input */
+ opus_int8 pulses[], /* O Quantized pulse signal */
+ const opus_int16 PredCoef_Q12[ 2 * MAX_LPC_ORDER ], /* I Short term prediction coefs */
+ const opus_int16 LTPCoef_Q14[ LTP_ORDER * MAX_NB_SUBFR ], /* I Long term prediction coefs */
+ const opus_int16 AR_Q13[ MAX_NB_SUBFR * MAX_SHAPE_LPC_ORDER ], /* I Noise shaping coefs */
+ const opus_int HarmShapeGain_Q14[ MAX_NB_SUBFR ], /* I Long term shaping coefs */
+ const opus_int Tilt_Q14[ MAX_NB_SUBFR ], /* I Spectral tilt */
+ const opus_int32 LF_shp_Q14[ MAX_NB_SUBFR ], /* I Low frequency shaping coefs */
+ const opus_int32 Gains_Q16[ MAX_NB_SUBFR ], /* I Quantization step sizes */
+ const opus_int pitchL[ MAX_NB_SUBFR ], /* I Pitch lags */
+ const opus_int Lambda_Q10, /* I Rate/distortion tradeoff */
+ const opus_int LTP_scale_Q14 /* I LTP state scaling */
);
#if defined OPUS_X86_PRESUME_SSE4_1
-#define silk_NSQ_del_dec(psEncC, NSQ, psIndices, x_Q3, pulses, PredCoef_Q12, LTPCoef_Q14, AR2_Q13, \
+#define silk_NSQ_del_dec(psEncC, NSQ, psIndices, x16, pulses, PredCoef_Q12, LTPCoef_Q14, AR_Q13, \
HarmShapeGain_Q14, Tilt_Q14, LF_shp_Q14, Gains_Q16, pitchL, Lambda_Q10, LTP_scale_Q14, arch) \
- ((void)(arch),silk_NSQ_del_dec_sse4_1(psEncC, NSQ, psIndices, x_Q3, pulses, PredCoef_Q12, LTPCoef_Q14, AR2_Q13, \
+ ((void)(arch),silk_NSQ_del_dec_sse4_1(psEncC, NSQ, psIndices, x16, pulses, PredCoef_Q12, LTPCoef_Q14, AR_Q13, \
HarmShapeGain_Q14, Tilt_Q14, LF_shp_Q14, Gains_Q16, pitchL, Lambda_Q10, LTP_scale_Q14))
#else
extern void (*const SILK_NSQ_DEL_DEC_IMPL[OPUS_ARCHMASK + 1])(
- const silk_encoder_state *psEncC, /* I/O Encoder State */
- silk_nsq_state *NSQ, /* I/O NSQ state */
- SideInfoIndices *psIndices, /* I/O Quantization Indices */
- const opus_int32 x_Q3[], /* I Prefiltered input signal */
- opus_int8 pulses[], /* O Quantized pulse signal */
- const opus_int16 PredCoef_Q12[ 2 * MAX_LPC_ORDER ], /* I Short term prediction coefs */
- const opus_int16 LTPCoef_Q14[ LTP_ORDER * MAX_NB_SUBFR ], /* I Long term prediction coefs */
- const opus_int16 AR2_Q13[ MAX_NB_SUBFR * MAX_SHAPE_LPC_ORDER ], /* I Noise shaping coefs */
- const opus_int HarmShapeGain_Q14[ MAX_NB_SUBFR ], /* I Long term shaping coefs */
- const opus_int Tilt_Q14[ MAX_NB_SUBFR ], /* I Spectral tilt */
- const opus_int32 LF_shp_Q14[ MAX_NB_SUBFR ], /* I Low frequency shaping coefs */
- const opus_int32 Gains_Q16[ MAX_NB_SUBFR ], /* I Quantization step sizes */
- const opus_int pitchL[ MAX_NB_SUBFR ], /* I Pitch lags */
- const opus_int Lambda_Q10, /* I Rate/distortion tradeoff */
- const opus_int LTP_scale_Q14 /* I LTP state scaling */
+ const silk_encoder_state *psEncC, /* I Encoder State */
+ silk_nsq_state *NSQ, /* I/O NSQ state */
+ SideInfoIndices *psIndices, /* I/O Quantization Indices */
+ const opus_int16 x16[], /* I Input */
+ opus_int8 pulses[], /* O Quantized pulse signal */
+ const opus_int16 PredCoef_Q12[ 2 * MAX_LPC_ORDER ], /* I Short term prediction coefs */
+ const opus_int16 LTPCoef_Q14[ LTP_ORDER * MAX_NB_SUBFR ], /* I Long term prediction coefs */
+ const opus_int16 AR_Q13[ MAX_NB_SUBFR * MAX_SHAPE_LPC_ORDER ], /* I Noise shaping coefs */
+ const opus_int HarmShapeGain_Q14[ MAX_NB_SUBFR ], /* I Long term shaping coefs */
+ const opus_int Tilt_Q14[ MAX_NB_SUBFR ], /* I Spectral tilt */
+ const opus_int32 LF_shp_Q14[ MAX_NB_SUBFR ], /* I Low frequency shaping coefs */
+ const opus_int32 Gains_Q16[ MAX_NB_SUBFR ], /* I Quantization step sizes */
+ const opus_int pitchL[ MAX_NB_SUBFR ], /* I Pitch lags */
+ const opus_int Lambda_Q10, /* I Rate/distortion tradeoff */
+ const opus_int LTP_scale_Q14 /* I LTP state scaling */
);
-# define silk_NSQ_del_dec(psEncC, NSQ, psIndices, x_Q3, pulses, PredCoef_Q12, LTPCoef_Q14, AR2_Q13, \
+# define silk_NSQ_del_dec(psEncC, NSQ, psIndices, x16, pulses, PredCoef_Q12, LTPCoef_Q14, AR_Q13, \
HarmShapeGain_Q14, Tilt_Q14, LF_shp_Q14, Gains_Q16, pitchL, Lambda_Q10, LTP_scale_Q14, arch) \
- ((*SILK_NSQ_DEL_DEC_IMPL[(arch) & OPUS_ARCHMASK])(psEncC, NSQ, psIndices, x_Q3, pulses, PredCoef_Q12, LTPCoef_Q14, AR2_Q13, \
+ ((*SILK_NSQ_DEL_DEC_IMPL[(arch) & OPUS_ARCHMASK])(psEncC, NSQ, psIndices, x16, pulses, PredCoef_Q12, LTPCoef_Q14, AR_Q13, \
HarmShapeGain_Q14, Tilt_Q14, LF_shp_Q14, Gains_Q16, pitchL, Lambda_Q10, LTP_scale_Q14))
#endif
@@ -238,39 +240,6 @@ extern opus_int (*const SILK_VAD_GETSA_Q8_IMPL[OPUS_ARCHMASK + 1])(
silk_encoder_state *psEnC,
const opus_int16 pIn[]);
-# define OVERRIDE_silk_warped_LPC_analysis_filter_FIX
-
-#endif
-
-void silk_warped_LPC_analysis_filter_FIX_sse4_1(
- opus_int32 state[], /* I/O State [order + 1] */
- opus_int32 res_Q2[], /* O Residual signal [length] */
- const opus_int16 coef_Q13[], /* I Coefficients [order] */
- const opus_int16 input[], /* I Input signal [length] */
- const opus_int16 lambda_Q16, /* I Warping factor */
- const opus_int length, /* I Length of input signal */
- const opus_int order /* I Filter order (even) */
-);
-
-#if defined(OPUS_X86_PRESUME_SSE4_1)
-#define silk_warped_LPC_analysis_filter_FIX(state, res_Q2, coef_Q13, input, lambda_Q16, length, order, arch) \
- ((void)(arch),silk_warped_LPC_analysis_filter_FIX_c(state, res_Q2, coef_Q13, input, lambda_Q16, length, order))
-
-#else
-
-extern void (*const SILK_WARPED_LPC_ANALYSIS_FILTER_FIX_IMPL[OPUS_ARCHMASK + 1])(
- opus_int32 state[], /* I/O State [order + 1] */
- opus_int32 res_Q2[], /* O Residual signal [length] */
- const opus_int16 coef_Q13[], /* I Coefficients [order] */
- const opus_int16 input[], /* I Input signal [length] */
- const opus_int16 lambda_Q16, /* I Warping factor */
- const opus_int length, /* I Length of input signal */
- const opus_int order /* I Filter order (even) */
-);
-
-# define silk_warped_LPC_analysis_filter_FIX(state, res_Q2, coef_Q13, input, lambda_Q16, length, order, arch) \
- ((*SILK_WARPED_LPC_ANALYSIS_FILTER_FIX_IMPL[(arch) & OPUS_ARCHMASK])(state, res_Q2, coef_Q13, input, lambda_Q16, length, order))
-
#endif
# endif
diff --git a/libs/libopus/silk/x86/x86_silk_map.c b/libs/libopus/silk/x86/x86_silk_map.c
index 818841f2c..ca13cde91 100644
--- a/libs/libopus/silk/x86/x86_silk_map.c
+++ b/libs/libopus/silk/x86/x86_silk_map.c
@@ -41,16 +41,16 @@
#include "fixed/main_FIX.h"
-opus_int64 (*const SILK_INNER_PROD16_ALIGNED_64_IMPL[ OPUS_ARCHMASK + 1 ] )(
+opus_int64 (*const SILK_INNER_PROD16_IMPL[ OPUS_ARCHMASK + 1 ] )(
const opus_int16 *inVec1,
const opus_int16 *inVec2,
const opus_int len
) = {
- silk_inner_prod16_aligned_64_c, /* non-sse */
- silk_inner_prod16_aligned_64_c,
- silk_inner_prod16_aligned_64_c,
- MAY_HAVE_SSE4_1( silk_inner_prod16_aligned_64 ), /* sse4.1 */
- MAY_HAVE_SSE4_1( silk_inner_prod16_aligned_64 ) /* avx */
+ silk_inner_prod16_c, /* non-sse */
+ silk_inner_prod16_c,
+ silk_inner_prod16_c,
+ MAY_HAVE_SSE4_1( silk_inner_prod16 ), /* sse4.1 */
+ MAY_HAVE_SSE4_1( silk_inner_prod16 ) /* avx */
};
#endif
@@ -67,21 +67,21 @@ opus_int (*const SILK_VAD_GETSA_Q8_IMPL[ OPUS_ARCHMASK + 1 ] )(
};
void (*const SILK_NSQ_IMPL[ OPUS_ARCHMASK + 1 ] )(
- const silk_encoder_state *psEncC, /* I/O Encoder State */
- silk_nsq_state *NSQ, /* I/O NSQ state */
- SideInfoIndices *psIndices, /* I/O Quantization Indices */
- const opus_int32 x_Q3[], /* I Prefiltered input signal */
- opus_int8 pulses[], /* O Quantized pulse signal */
- const opus_int16 PredCoef_Q12[ 2 * MAX_LPC_ORDER ], /* I Short term prediction coefs */
- const opus_int16 LTPCoef_Q14[ LTP_ORDER * MAX_NB_SUBFR ], /* I Long term prediction coefs */
- const opus_int16 AR2_Q13[ MAX_NB_SUBFR * MAX_SHAPE_LPC_ORDER ], /* I Noise shaping coefs */
- const opus_int HarmShapeGain_Q14[ MAX_NB_SUBFR ], /* I Long term shaping coefs */
- const opus_int Tilt_Q14[ MAX_NB_SUBFR ], /* I Spectral tilt */
- const opus_int32 LF_shp_Q14[ MAX_NB_SUBFR ], /* I Low frequency shaping coefs */
- const opus_int32 Gains_Q16[ MAX_NB_SUBFR ], /* I Quantization step sizes */
- const opus_int pitchL[ MAX_NB_SUBFR ], /* I Pitch lags */
- const opus_int Lambda_Q10, /* I Rate/distortion tradeoff */
- const opus_int LTP_scale_Q14 /* I LTP state scaling */
+ const silk_encoder_state *psEncC, /* I Encoder State */
+ silk_nsq_state *NSQ, /* I/O NSQ state */
+ SideInfoIndices *psIndices, /* I/O Quantization Indices */
+ const opus_int16 x16[], /* I Input */
+ opus_int8 pulses[], /* O Quantized pulse signal */
+ const opus_int16 PredCoef_Q12[ 2 * MAX_LPC_ORDER ], /* I Short term prediction coefs */
+ const opus_int16 LTPCoef_Q14[ LTP_ORDER * MAX_NB_SUBFR ], /* I Long term prediction coefs */
+ const opus_int16 AR_Q13[ MAX_NB_SUBFR * MAX_SHAPE_LPC_ORDER ], /* I Noise shaping coefs */
+ const opus_int HarmShapeGain_Q14[ MAX_NB_SUBFR ], /* I Long term shaping coefs */
+ const opus_int Tilt_Q14[ MAX_NB_SUBFR ], /* I Spectral tilt */
+ const opus_int32 LF_shp_Q14[ MAX_NB_SUBFR ], /* I Low frequency shaping coefs */
+ const opus_int32 Gains_Q16[ MAX_NB_SUBFR ], /* I Quantization step sizes */
+ const opus_int pitchL[ MAX_NB_SUBFR ], /* I Pitch lags */
+ const opus_int Lambda_Q10, /* I Rate/distortion tradeoff */
+ const opus_int LTP_scale_Q14 /* I LTP state scaling */
) = {
silk_NSQ_c, /* non-sse */
silk_NSQ_c,
@@ -92,16 +92,17 @@ void (*const SILK_NSQ_IMPL[ OPUS_ARCHMASK + 1 ] )(
void (*const SILK_VQ_WMAT_EC_IMPL[ OPUS_ARCHMASK + 1 ] )(
opus_int8 *ind, /* O index of best codebook vector */
- opus_int32 *rate_dist_Q14, /* O best weighted quant error + mu * rate */
+ opus_int32 *res_nrg_Q15, /* O best residual energy */
+ opus_int32 *rate_dist_Q8, /* O best total bitrate */
opus_int *gain_Q7, /* O sum of absolute LTP coefficients */
- const opus_int16 *in_Q14, /* I input vector to be quantized */
- const opus_int32 *W_Q18, /* I weighting matrix */
+ const opus_int32 *XX_Q17, /* I correlation matrix */
+ const opus_int32 *xX_Q17, /* I correlation vector */
const opus_int8 *cb_Q7, /* I codebook */
const opus_uint8 *cb_gain_Q7, /* I codebook effective gain */
const opus_uint8 *cl_Q5, /* I code length for each codebook vector */
- const opus_int mu_Q9, /* I tradeoff betw. weighted error and rate */
+ const opus_int subfr_len, /* I number of samples per subframe */
const opus_int32 max_gain_Q7, /* I maximum sum of absolute LTP coefficients */
- opus_int L /* I number of vectors in codebook */
+ const opus_int L /* I number of vectors in codebook */
) = {
silk_VQ_WMat_EC_c, /* non-sse */
silk_VQ_WMat_EC_c,
@@ -111,21 +112,21 @@ void (*const SILK_VQ_WMAT_EC_IMPL[ OPUS_ARCHMASK + 1 ] )(
};
void (*const SILK_NSQ_DEL_DEC_IMPL[ OPUS_ARCHMASK + 1 ] )(
- const silk_encoder_state *psEncC, /* I/O Encoder State */
- silk_nsq_state *NSQ, /* I/O NSQ state */
- SideInfoIndices *psIndices, /* I/O Quantization Indices */
- const opus_int32 x_Q3[], /* I Prefiltered input signal */
- opus_int8 pulses[], /* O Quantized pulse signal */
- const opus_int16 PredCoef_Q12[ 2 * MAX_LPC_ORDER ], /* I Short term prediction coefs */
- const opus_int16 LTPCoef_Q14[ LTP_ORDER * MAX_NB_SUBFR ], /* I Long term prediction coefs */
- const opus_int16 AR2_Q13[ MAX_NB_SUBFR * MAX_SHAPE_LPC_ORDER ], /* I Noise shaping coefs */
- const opus_int HarmShapeGain_Q14[ MAX_NB_SUBFR ], /* I Long term shaping coefs */
- const opus_int Tilt_Q14[ MAX_NB_SUBFR ], /* I Spectral tilt */
- const opus_int32 LF_shp_Q14[ MAX_NB_SUBFR ], /* I Low frequency shaping coefs */
- const opus_int32 Gains_Q16[ MAX_NB_SUBFR ], /* I Quantization step sizes */
- const opus_int pitchL[ MAX_NB_SUBFR ], /* I Pitch lags */
- const opus_int Lambda_Q10, /* I Rate/distortion tradeoff */
- const opus_int LTP_scale_Q14 /* I LTP state scaling */
+ const silk_encoder_state *psEncC, /* I Encoder State */
+ silk_nsq_state *NSQ, /* I/O NSQ state */
+ SideInfoIndices *psIndices, /* I/O Quantization Indices */
+ const opus_int16 x16[], /* I Input */
+ opus_int8 pulses[], /* O Quantized pulse signal */
+ const opus_int16 PredCoef_Q12[ 2 * MAX_LPC_ORDER ], /* I Short term prediction coefs */
+ const opus_int16 LTPCoef_Q14[ LTP_ORDER * MAX_NB_SUBFR ], /* I Long term prediction coefs */
+ const opus_int16 AR_Q13[ MAX_NB_SUBFR * MAX_SHAPE_LPC_ORDER ], /* I Noise shaping coefs */
+ const opus_int HarmShapeGain_Q14[ MAX_NB_SUBFR ], /* I Long term shaping coefs */
+ const opus_int Tilt_Q14[ MAX_NB_SUBFR ], /* I Spectral tilt */
+ const opus_int32 LF_shp_Q14[ MAX_NB_SUBFR ], /* I Low frequency shaping coefs */
+ const opus_int32 Gains_Q16[ MAX_NB_SUBFR ], /* I Quantization step sizes */
+ const opus_int pitchL[ MAX_NB_SUBFR ], /* I Pitch lags */
+ const opus_int Lambda_Q10, /* I Rate/distortion tradeoff */
+ const opus_int LTP_scale_Q14 /* I LTP state scaling */
) = {
silk_NSQ_del_dec_c, /* non-sse */
silk_NSQ_del_dec_c,
@@ -136,22 +137,6 @@ void (*const SILK_NSQ_DEL_DEC_IMPL[ OPUS_ARCHMASK + 1 ] )(
#if defined(FIXED_POINT)
-void (*const SILK_WARPED_LPC_ANALYSIS_FILTER_FIX_IMPL[ OPUS_ARCHMASK + 1 ] )(
- opus_int32 state[], /* I/O State [order + 1] */
- opus_int32 res_Q2[], /* O Residual signal [length] */
- const opus_int16 coef_Q13[], /* I Coefficients [order] */
- const opus_int16 input[], /* I Input signal [length] */
- const opus_int16 lambda_Q16, /* I Warping factor */
- const opus_int length, /* I Length of input signal */
- const opus_int order /* I Filter order (even) */
-) = {
- silk_warped_LPC_analysis_filter_FIX_c, /* non-sse */
- silk_warped_LPC_analysis_filter_FIX_c,
- silk_warped_LPC_analysis_filter_FIX_c,
- MAY_HAVE_SSE4_1( silk_warped_LPC_analysis_filter_FIX ), /* sse4.1 */
- MAY_HAVE_SSE4_1( silk_warped_LPC_analysis_filter_FIX ) /* avx */
-};
-
void (*const SILK_BURG_MODIFIED_IMPL[ OPUS_ARCHMASK + 1 ] )(
opus_int32 *res_nrg, /* O Residual energy */
opus_int *res_nrg_Q, /* O Residual energy Q value */