diff options
author | Koen Vos <koen.vos@skype.net> | 2011-12-13 23:47:31 +0400 |
---|---|---|
committer | Jean-Marc Valin <jmvalin@jmvalin.ca> | 2011-12-13 23:47:31 +0400 |
commit | bf75c8ec4d0dded188bc7793de6da56c7ff0be1c (patch) | |
tree | c21bb05faf0a203b73e8f8aae90fc63dac27625d /silk | |
parent | 6619a736376221f2782cecff55d051c3ecfc2ff7 (diff) |
SILK fixes following last codec WG meeting
decoder:
- fixed incorrect scaling of filter states for the smallest quantization
step sizes
- NLSF2A now limits the prediction gain of LPC filters
encoder:
- increased damping of LTP coefficients in LTP analysis
- increased white noise fraction in noise shaping LPC analysis
- introduced maximum total prediction gain. Used by Burg's method to
exit early if prediction gain is exceeded. This improves packet
loss robustness and numerical robustness in Burg's method
- Prefiltered signal is now in int32 Q10 domain, from int16 Q0
- Increased max number of iterations in CBR gain control loop from 5 to 6
- Removed useless code from LTP scaling control
- Optimization: smarter LPC loop unrolling
- Switched default win32 compile mode to be floating-point
resampler:
- made resampler have constant delay of 0.75 ms; removed delay
compensation from silk code.
- removed obsolete table entries (~850 Bytes)
- increased downsampling filter order from 16 to 18/24/36 (depending on
frequency ratio)
- reoptimized filter coefficients
Diffstat (limited to 'silk')
69 files changed, 939 insertions, 979 deletions
@@ -54,7 +54,7 @@ static inline void silk_CNG_exc( idx = ( opus_int )( silk_RSHIFT( seed, 24 ) & exc_mask ); silk_assert( idx >= 0 ); silk_assert( idx <= CNG_BUF_MASK_MAX ); - residual_Q10[ i ] = ( opus_int16 )silk_SAT16( silk_SMULWW( exc_buf_Q10[ idx ], Gain_Q16 ) ); + residual_Q10[ i ] = (opus_int16)silk_SAT16( silk_SMULWW( exc_buf_Q10[ idx ], Gain_Q16 ) ); } *rand_seed = seed; } @@ -83,7 +83,7 @@ void silk_CNG( opus_int length /* I Length of residual */ ) { - opus_int i, j, subfr; + opus_int i, subfr; opus_int32 sum_Q6, max_Gain_Q16; opus_int16 A_Q12[ MAX_LPC_ORDER ]; opus_int32 CNG_sig_Q10[ MAX_FRAME_LENGTH + MAX_LPC_ORDER ]; @@ -133,7 +133,7 @@ void silk_CNG( /* Generate CNG signal, by synthesis filtering */ silk_memcpy( CNG_sig_Q10, psCNG->CNG_synth_state, MAX_LPC_ORDER * sizeof( opus_int32 ) ); for( i = 0; i < length; i++ ) { - /* Partially unrolled */ + silk_assert( psDec->LPC_order == 10 || psDec->LPC_order == 16 ); sum_Q6 = silk_SMULWB( CNG_sig_Q10[ MAX_LPC_ORDER + i - 1 ], A_Q12[ 0 ] ); sum_Q6 = silk_SMLAWB( sum_Q6, CNG_sig_Q10[ MAX_LPC_ORDER + i - 2 ], A_Q12[ 1 ] ); sum_Q6 = silk_SMLAWB( sum_Q6, CNG_sig_Q10[ MAX_LPC_ORDER + i - 3 ], A_Q12[ 2 ] ); @@ -144,8 +144,13 @@ void silk_CNG( sum_Q6 = silk_SMLAWB( sum_Q6, CNG_sig_Q10[ MAX_LPC_ORDER + i - 8 ], A_Q12[ 7 ] ); sum_Q6 = silk_SMLAWB( sum_Q6, CNG_sig_Q10[ MAX_LPC_ORDER + i - 9 ], A_Q12[ 8 ] ); sum_Q6 = silk_SMLAWB( sum_Q6, CNG_sig_Q10[ MAX_LPC_ORDER + i - 10 ], A_Q12[ 9 ] ); - for( j = 10; j < psDec->LPC_order; j++ ) { - sum_Q6 = silk_SMLAWB( sum_Q6, CNG_sig_Q10[ MAX_LPC_ORDER + i - j - 1 ], A_Q12[ j ] ); + if( psDec->LPC_order == 16 ) { + sum_Q6 = silk_SMLAWB( sum_Q6, CNG_sig_Q10[ MAX_LPC_ORDER + i - 11 ], A_Q12[ 10 ] ); + sum_Q6 = silk_SMLAWB( sum_Q6, CNG_sig_Q10[ MAX_LPC_ORDER + i - 12 ], A_Q12[ 11 ] ); + sum_Q6 = silk_SMLAWB( sum_Q6, CNG_sig_Q10[ MAX_LPC_ORDER + i - 13 ], A_Q12[ 12 ] ); + sum_Q6 = silk_SMLAWB( sum_Q6, CNG_sig_Q10[ MAX_LPC_ORDER + i - 14 ], A_Q12[ 13 ] ); + sum_Q6 = silk_SMLAWB( sum_Q6, CNG_sig_Q10[ MAX_LPC_ORDER + i - 15 ], A_Q12[ 14 ] ); + sum_Q6 = silk_SMLAWB( sum_Q6, CNG_sig_Q10[ MAX_LPC_ORDER + i - 16 ], A_Q12[ 15 ] ); } /* Update states */ diff --git a/silk/LPC_analysis_filter.c b/silk/LPC_analysis_filter.c index bf5c2843..e1a9d917 100644 --- a/silk/LPC_analysis_filter.c +++ b/silk/LPC_analysis_filter.c @@ -77,7 +77,7 @@ void silk_LPC_analysis_filter( out32 = silk_RSHIFT_ROUND( out32_Q12, 12 ); /* Saturate output */ - out[ ix ] = ( opus_int16 )silk_SAT16( out32 ); + out[ ix ] = (opus_int16)silk_SAT16( out32 ); } /* Set first d output samples to zero */ diff --git a/silk/LPC_inv_pred_gain.c b/silk/LPC_inv_pred_gain.c index 249da318..db529d14 100644 --- a/silk/LPC_inv_pred_gain.c +++ b/silk/LPC_inv_pred_gain.c @@ -38,24 +38,22 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. /* Compute inverse of LPC prediction gain, and */ /* test if LPC coefficients are stable (all poles within unit circle) */ -static opus_int LPC_inverse_pred_gain_QA( /* O Returns 1 if unstable, otherwise 0 */ - opus_int32 *invGain_Q30, /* O Inverse prediction gain, Q30 energy domain */ - opus_int32 A_QA[ 2 ][ SILK_MAX_ORDER_LPC ], /* I Prediction coefficients */ - const opus_int order /* I Prediction order */ +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 */ + const opus_int order /* I Prediction order */ ) { opus_int k, n, mult2Q; - opus_int32 rc_Q31, rc_mult1_Q30, rc_mult2, tmp_QA; + opus_int32 invGain_Q30, rc_Q31, rc_mult1_Q30, rc_mult2, tmp_QA; opus_int32 *Aold_QA, *Anew_QA; Anew_QA = A_QA[ order & 1 ]; - *invGain_Q30 = ( 1 << 30 ); + invGain_Q30 = 1 << 30; for( k = order - 1; k > 0; k-- ) { /* Check for stability */ if( ( Anew_QA[ k ] > A_LIMIT ) || ( Anew_QA[ k ] < -A_LIMIT ) ) { - *invGain_Q30 = 0; - return 1; + return 0; } /* Set RC equal to negated AR coef */ @@ -72,9 +70,9 @@ static opus_int LPC_inverse_pred_gain_QA( /* O Returns 1 if /* 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 ) ); + invGain_Q30 = silk_LSHIFT( silk_SMMUL( invGain_Q30, rc_mult1_Q30 ), 2 ); + silk_assert( invGain_Q30 >= 0 ); + silk_assert( invGain_Q30 <= ( 1 << 30 ) ); /* Swap pointers */ Aold_QA = Anew_QA; @@ -89,8 +87,7 @@ static opus_int LPC_inverse_pred_gain_QA( /* O Returns 1 if /* Check for stability */ if( ( Anew_QA[ 0 ] > A_LIMIT ) || ( Anew_QA[ 0 ] < -A_LIMIT ) ) { - *invGain_Q30 = 0; - return 1; + return 0; } /* Set RC equal to negated AR coef */ @@ -101,16 +98,15 @@ static opus_int LPC_inverse_pred_gain_QA( /* O Returns 1 if /* 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 ); + invGain_Q30 = silk_LSHIFT( silk_SMMUL( invGain_Q30, rc_mult1_Q30 ), 2 ); + silk_assert( invGain_Q30 >= 0 ); + silk_assert( invGain_Q30 <= 1<<30 ); - return 0; + return invGain_Q30; } /* For input in Q12 domain */ -opus_int silk_LPC_inverse_pred_gain( /* O Returns 1 if unstable, otherwise 0 */ - opus_int32 *invGain_Q30, /* O Inverse prediction gain, Q30 energy domain */ +opus_int32 silk_LPC_inverse_pred_gain( /* 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 */ ) @@ -118,30 +114,27 @@ opus_int silk_LPC_inverse_pred_gain( /* O Returns 1 if unstable opus_int k; opus_int32 Atmp_QA[ 2 ][ SILK_MAX_ORDER_LPC ]; opus_int32 *Anew_QA; - opus_int32 DC_resp=0; + 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_LSHIFT( (opus_int32)A_Q12[ k ], QA - 12 ); + Anew_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 ) { - *invGain_Q30 = 0; - return 1; + return 0; } - return LPC_inverse_pred_gain_QA( invGain_Q30, Atmp_QA, order ); + return LPC_inverse_pred_gain_QA( Atmp_QA, order ); } #ifdef FIXED_POINT /* For input in Q24 domain */ -/* This function is only used by the fixed-point build */ -opus_int silk_LPC_inverse_pred_gain_Q24( /* O Returns 1 if unstable, otherwise 0 */ - opus_int32 *invGain_Q30, /* O Inverse prediction gain, Q30 energy domain */ - const opus_int32 *A_Q24, /* I Prediction coefficients, Q24 [order] */ +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 */ ) { @@ -153,9 +146,9 @@ opus_int silk_LPC_inverse_pred_gain_Q24( /* O Returns 1 if unstabl /* Increase Q domain of the AR coefficients */ for( k = 0; k < order; k++ ) { - Anew_QA[ k ] = silk_RSHIFT( A_Q24[ k ], 24 - QA ); + Anew_QA[ k ] = silk_RSHIFT32( A_Q24[ k ], 24 - QA ); } - return LPC_inverse_pred_gain_QA( invGain_Q30, Atmp_QA, order ); + return LPC_inverse_pred_gain_QA( Atmp_QA, order ); } #endif diff --git a/silk/MacroDebug.h b/silk/MacroDebug.h index 8adf44e1..9d7e1f8a 100644 --- a/silk/MacroDebug.h +++ b/silk/MacroDebug.h @@ -91,24 +91,24 @@ static inline opus_int64 silk_SUB64(opus_int64 a, opus_int64 b){ static inline opus_int16 silk_ADD_SAT16( opus_int16 a16, opus_int16 b16 ) { opus_int16 res; res = (opus_int16)silk_SAT16( silk_ADD32( (opus_int32)(a16), (b16) ) ); - silk_assert( res == silk_SAT16( ( opus_int32 )a16 + ( opus_int32 )b16 ) ); + silk_assert( res == silk_SAT16( (opus_int32)a16 + (opus_int32)b16 ) ); return res; } #undef silk_ADD_SAT32 static inline opus_int32 silk_ADD_SAT32(opus_int32 a32, opus_int32 b32){ opus_int32 res; - res = ((((a32) + (b32)) & 0x80000000) == 0 ? \ + res = ((((a32) + (b32)) & 0x80000000) == 0 ? \ ((((a32) & (b32)) & 0x80000000) != 0 ? silk_int32_MIN : (a32)+(b32)) : \ ((((a32) | (b32)) & 0x80000000) == 0 ? silk_int32_MAX : (a32)+(b32)) ); - silk_assert( res == silk_SAT32( ( opus_int64 )a32 + ( opus_int64 )b32 ) ); + silk_assert( res == silk_SAT32( (opus_int64)a32 + (opus_int64)b32 ) ); return res; } #undef silk_ADD_SAT64 static inline opus_int64 silk_ADD_SAT64( opus_int64 a64, opus_int64 b64 ) { opus_int64 res; - res = ((((a64) + (b64)) & 0x8000000000000000LL) == 0 ? \ + res = ((((a64) + (b64)) & 0x8000000000000000LL) == 0 ? \ ((((a64) & (b64)) & 0x8000000000000000LL) != 0 ? silk_int64_MIN : (a64)+(b64)) : \ ((((a64) | (b64)) & 0x8000000000000000LL) == 0 ? silk_int64_MAX : (a64)+(b64)) ); if( res != a64 + b64 ) { @@ -126,24 +126,24 @@ static inline opus_int64 silk_ADD_SAT64( opus_int64 a64, opus_int64 b64 ) { static inline opus_int16 silk_SUB_SAT16( opus_int16 a16, opus_int16 b16 ) { opus_int16 res; res = (opus_int16)silk_SAT16( silk_SUB32( (opus_int32)(a16), (b16) ) ); - silk_assert( res == silk_SAT16( ( opus_int32 )a16 - ( opus_int32 )b16 ) ); + silk_assert( res == silk_SAT16( (opus_int32)a16 - (opus_int32)b16 ) ); return res; } #undef silk_SUB_SAT32 static inline opus_int32 silk_SUB_SAT32( opus_int32 a32, opus_int32 b32 ) { opus_int32 res; - res = ((((a32)-(b32)) & 0x80000000) == 0 ? \ + res = ((((a32)-(b32)) & 0x80000000) == 0 ? \ (( (a32) & ((b32)^0x80000000) & 0x80000000) ? silk_int32_MIN : (a32)-(b32)) : \ ((((a32)^0x80000000) & (b32) & 0x80000000) ? silk_int32_MAX : (a32)-(b32)) ); - silk_assert( res == silk_SAT32( ( opus_int64 )a32 - ( opus_int64 )b32 ) ); + silk_assert( res == silk_SAT32( (opus_int64)a32 - (opus_int64)b32 ) ); return res; } #undef silk_SUB_SAT64 static inline opus_int64 silk_SUB_SAT64( opus_int64 a64, opus_int64 b64 ) { opus_int64 res; - res = ((((a64)-(b64)) & 0x8000000000000000LL) == 0 ? \ + res = ((((a64)-(b64)) & 0x8000000000000000LL) == 0 ? \ (( (a64) & ((b64)^0x8000000000000000LL) & 0x8000000000000000LL) ? silk_int64_MIN : (a64)-(b64)) : \ ((((a64)^0x8000000000000000LL) & (b64) & 0x8000000000000000LL) ? silk_int64_MAX : (a64)-(b64)) ); diff --git a/silk/NLSF2A.c b/silk/NLSF2A.c index f2a26935..b10c6901 100644 --- a/silk/NLSF2A.c +++ b/silk/NLSF2A.c @@ -83,7 +83,7 @@ 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, invGain_Q30; + opus_int32 maxabs, absval, idx=0, sc_Q16; silk_assert( LSF_COS_TAB_SZ_FIX == 128 ); silk_assert( d==10||d==16 ); @@ -162,8 +162,8 @@ void silk_NLSF2A( } } - for( i = 1; i < MAX_LPC_STABILIZE_ITERATIONS; i++ ) { - if( silk_LPC_inverse_pred_gain( &invGain_Q30, a_Q12, d ) == 1 ) { + for( i = 1; 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_SMULBB( 9 + i, i ) ); /* 10_Q16 = 0.00015 */ @@ -175,7 +175,7 @@ void silk_NLSF2A( } } - if( i == MAX_LPC_STABILIZE_ITERATIONS ) { + if( i > MAX_LPC_STABILIZE_ITERATIONS ) { /* Reached the last iteration, set coefficients to zero */ for( k = 0; k < d; k++ ) { a_Q12[ k ] = 0; diff --git a/silk/NLSF_VQ.c b/silk/NLSF_VQ.c index e547542d..45108834 100644 --- a/silk/NLSF_VQ.c +++ b/silk/NLSF_VQ.c @@ -51,11 +51,11 @@ void silk_NLSF_VQ( 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 ]*/ + 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 ); /* 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 ]*/ + 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 ); sum_error_Q26 = silk_ADD_RSHIFT32( sum_error_Q26, sum_error_Q30, 4 ); diff --git a/silk/NLSF_decode.c b/silk/NLSF_decode.c index b1b83ae9..124be417 100644 --- a/silk/NLSF_decode.c +++ b/silk/NLSF_decode.c @@ -77,7 +77,7 @@ void silk_NLSF_decode( /* 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 ); + pNLSF_Q15[ i ] = silk_LSHIFT( (opus_int16)pCB_element[ i ], 7 ); } /* Unpack entropy table indices and predictor for current CB1 index */ @@ -91,8 +91,8 @@ void silk_NLSF_decode( /* Apply inverse square-rooted weights and add to output */ 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 ) ); + 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 ) ); pNLSF_Q15[ i ] = (opus_int16)silk_LIMIT( NLSF_Q15_tmp, 0, 32767 ); } diff --git a/silk/NLSF_encode.c b/silk/NLSF_encode.c index cc841605..5b204416 100644 --- a/silk/NLSF_encode.c +++ b/silk/NLSF_encode.c @@ -79,7 +79,7 @@ opus_int32 silk_NLSF_encode( /* O Returns /* Residual after first stage */ pCB_element = &psNLSF_CB->CB1_NLSF_Q8[ ind1 * psNLSF_CB->order ]; for( i = 0; i < psNLSF_CB->order; i++ ) { - NLSF_tmp_Q15[ i ] = silk_LSHIFT16( ( opus_int16 )pCB_element[ i ], 7 ); + NLSF_tmp_Q15[ i ] = silk_LSHIFT16( (opus_int16)pCB_element[ i ], 7 ); res_Q15[ i ] = pNLSF_Q15[ i ] - NLSF_tmp_Q15[ i ]; } @@ -88,13 +88,13 @@ opus_int32 silk_NLSF_encode( /* O Returns /* 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 ); + 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_adj_Q5[ i ] = silk_DIV32_16( silk_LSHIFT( (opus_int32)pW_QW[ i ], 5 ), W_tmp_QW[ i ] ); } /* Unpack entropy table indices and predictor for current CB1 index */ @@ -118,7 +118,7 @@ opus_int32 silk_NLSF_encode( /* O Returns /* Find the lowest rate-distortion error */ silk_insertion_sort_increasing( RD_Q25, &bestIndex, nSurvivors, 1 ); - NLSFIndices[ 0 ] = ( opus_int8 )tempIndices1[ bestIndex ]; + NLSFIndices[ 0 ] = (opus_int8)tempIndices1[ bestIndex ]; silk_memcpy( &NLSFIndices[ 1 ], &tempIndices2[ bestIndex * MAX_LPC_ORDER ], psNLSF_CB->order * sizeof( opus_int8 ) ); /* Decode */ @@ -34,10 +34,10 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. static inline void silk_nsq_scale_states( const silk_encoder_state *psEncC, /* I Encoder State */ silk_nsq_state *NSQ, /* I/O NSQ state */ - const opus_int16 x[], /* I input in Q0 */ + const opus_int32 x_Q10[], /* I input in Q0 */ 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_Q16[], /* O LTP state matching scaled input */ + 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 */ @@ -51,7 +51,7 @@ static inline void silk_noise_shape_quantizer( const opus_int32 x_sc_Q10[], /* I */ opus_int8 pulses[], /* O */ opus_int16 xq[], /* O */ - opus_int32 sLTP_Q16[], /* I/O LTP state */ + opus_int32 sLTP_Q15[], /* I/O LTP state */ 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 AR coefs */ @@ -71,7 +71,7 @@ void silk_NSQ( 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_int16 x[], /* I Prefiltered input signal */ + const opus_int32 x_Q10[], /* 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 */ @@ -85,14 +85,14 @@ void silk_NSQ( const opus_int LTP_scale_Q14 /* I LTP state scaling */ ) { - opus_int k, lag, start_idx, LSF_interpolation_flag; - const opus_int16 *A_Q12, *B_Q14, *AR_shp_Q13; - opus_int16 *pxq; - opus_int32 sLTP_Q16[ 2 * MAX_FRAME_LENGTH ]; - opus_int16 sLTP[ 2 * MAX_FRAME_LENGTH ]; - opus_int32 HarmShapeFIRPacked_Q14; - opus_int offset_Q10; - opus_int32 x_sc_Q10[ MAX_FRAME_LENGTH / MAX_NB_SUBFR ]; + opus_int k, lag, start_idx, LSF_interpolation_flag; + const opus_int16 *A_Q12, *B_Q14, *AR_shp_Q13; + opus_int16 *pxq; + opus_int32 sLTP_Q15[ 2 * MAX_FRAME_LENGTH ]; + opus_int16 sLTP[ 2 * MAX_FRAME_LENGTH ]; + opus_int32 HarmShapeFIRPacked_Q14; + opus_int offset_Q10; + opus_int32 x_sc_Q10[ MAX_SUB_FRAME_LENGTH ]; NSQ->rand_seed = psIndices->Seed; @@ -109,7 +109,7 @@ void silk_NSQ( LSF_interpolation_flag = 1; } - /* Setup pointers to start of sub frame */ + /* Set up pointers to start of sub frame */ NSQ->sLTP_shp_buf_idx = psEncC->ltp_mem_length; NSQ->sLTP_buf_idx = psEncC->ltp_mem_length; pxq = &NSQ->xq[ psEncC->ltp_mem_length ]; @@ -121,7 +121,7 @@ void silk_NSQ( /* 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 ); + HarmShapeFIRPacked_Q14 |= silk_LSHIFT( (opus_int32)silk_RSHIFT( HarmShapeGain_Q14[ k ], 1 ), 16 ); NSQ->rewhite_flag = 0; if( psIndices->signalType == TYPE_VOICED ) { @@ -142,13 +142,13 @@ void silk_NSQ( } } - silk_nsq_scale_states( psEncC, NSQ, x, x_sc_Q10, sLTP, sLTP_Q16, k, LTP_scale_Q14, Gains_Q16, pitchL, psIndices->signalType ); + silk_nsq_scale_states( psEncC, NSQ, x_Q10, 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_Q16, A_Q12, B_Q14, + 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 ); - x += psEncC->subfr_length; + x_Q10 += psEncC->subfr_length; pulses += psEncC->subfr_length; pxq += psEncC->subfr_length; } @@ -170,7 +170,7 @@ static inline void silk_noise_shape_quantizer( const opus_int32 x_sc_Q10[], /* I */ opus_int8 pulses[], /* O */ opus_int16 xq[], /* O */ - opus_int32 sLTP_Q16[], /* I/O LTP state */ + opus_int32 sLTP_Q15[], /* I/O LTP state */ 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 AR coefs */ @@ -187,16 +187,16 @@ static inline void silk_noise_shape_quantizer( ) { opus_int i, j; - opus_int32 LTP_pred_Q14, LPC_pred_Q10, n_AR_Q10, n_LTP_Q14; + opus_int32 LTP_pred_Q13, LPC_pred_Q10, n_AR_Q10, n_LTP_Q14; opus_int32 n_LF_Q10, r_Q10, rr_Q10, q1_Q10, q2_Q10, rd1_Q10, rd2_Q10; opus_int32 dither, exc_Q10, LPC_exc_Q10, xq_Q10; opus_int32 tmp1, tmp2, sLF_AR_shp_Q10; opus_int32 *psLPC_Q14, *shp_lag_ptr, *pred_lag_ptr; shp_lag_ptr = &NSQ->sLTP_shp_Q10[ NSQ->sLTP_shp_buf_idx - lag + HARM_SHAPE_FIR_TAPS / 2 ]; - pred_lag_ptr = &sLTP_Q16[ NSQ->sLTP_buf_idx - lag + LTP_ORDER / 2 ]; + pred_lag_ptr = &sLTP_Q15[ NSQ->sLTP_buf_idx - lag + LTP_ORDER / 2 ]; - /* Setup short term AR state */ + /* Set up short term AR state */ psLPC_Q14 = &NSQ->sLPC_Q14[ NSQ_LPC_BUF_LENGTH - 1 ]; for( i = 0; i < length; i++ ) { @@ -207,11 +207,7 @@ static inline void silk_noise_shape_quantizer( dither = silk_RSHIFT( NSQ->rand_seed, 31 ); /* Short-term prediction */ - silk_assert( ( predictLPCOrder & 1 ) == 0 ); /* check that order is even */ - silk_assert( ( (opus_int64)a_Q12 & 3 ) == 0 ); /* check that array starts at 4-byte aligned address */ - silk_assert( predictLPCOrder >= 10 ); /* check that unrolling works */ - - /* Partially unrolled */ + silk_assert( predictLPCOrder == 10 || predictLPCOrder == 16 ); LPC_pred_Q10 = silk_SMULWB( psLPC_Q14[ 0 ], a_Q12[ 0 ] ); LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, psLPC_Q14[ -1 ], a_Q12[ 1 ] ); LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, psLPC_Q14[ -2 ], a_Q12[ 2 ] ); @@ -222,21 +218,26 @@ static inline void silk_noise_shape_quantizer( LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, psLPC_Q14[ -7 ], a_Q12[ 7 ] ); LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, psLPC_Q14[ -8 ], a_Q12[ 8 ] ); LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, psLPC_Q14[ -9 ], a_Q12[ 9 ] ); - for( j = 10; j < predictLPCOrder; j ++ ) { - LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, psLPC_Q14[ -j ], a_Q12[ j ] ); + if( predictLPCOrder == 16 ) { + LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, psLPC_Q14[ -10 ], a_Q12[ 10 ] ); + LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, psLPC_Q14[ -11 ], a_Q12[ 11 ] ); + LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, psLPC_Q14[ -12 ], a_Q12[ 12 ] ); + LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, psLPC_Q14[ -13 ], a_Q12[ 13 ] ); + LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, psLPC_Q14[ -14 ], a_Q12[ 14 ] ); + LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, psLPC_Q14[ -15 ], a_Q12[ 15 ] ); } /* Long-term prediction */ if( signalType == TYPE_VOICED ) { /* Unrolled loop */ - LTP_pred_Q14 = silk_SMULWB( 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_Q13 = silk_SMULWB( pred_lag_ptr[ 0 ], b_Q14[ 0 ] ); + LTP_pred_Q13 = silk_SMLAWB( LTP_pred_Q13, pred_lag_ptr[ -1 ], b_Q14[ 1 ] ); + LTP_pred_Q13 = silk_SMLAWB( LTP_pred_Q13, pred_lag_ptr[ -2 ], b_Q14[ 2 ] ); + LTP_pred_Q13 = silk_SMLAWB( LTP_pred_Q13, pred_lag_ptr[ -3 ], b_Q14[ 3 ] ); + LTP_pred_Q13 = silk_SMLAWB( LTP_pred_Q13, pred_lag_ptr[ -4 ], b_Q14[ 4 ] ); pred_lag_ptr++; } else { - LTP_pred_Q14 = 0; + LTP_pred_Q13 = 0; } /* Noise shape feedback */ @@ -268,11 +269,11 @@ static inline void silk_noise_shape_quantizer( 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_SMLAWT( n_LTP_Q14, shp_lag_ptr[ -1 ], HarmShapeFIRPacked_Q14 ); n_LTP_Q14 = silk_LSHIFT( n_LTP_Q14, 6 ); shp_lag_ptr++; - tmp1 = silk_SUB32( LTP_pred_Q14, n_LTP_Q14 ); /* Add Q14 stuff */ + tmp1 = silk_SUB32( LTP_pred_Q13 << 1, n_LTP_Q14 ); /* Add Q14 stuff */ tmp1 = silk_RSHIFT( tmp1, 4 ); /* convert to Q10 */ tmp1 = silk_ADD32( tmp1, LPC_pred_Q10 ); /* add Q10 stuff */ tmp1 = silk_SUB32( tmp1, n_AR_Q10 ); /* subtract Q10 stuff */ @@ -324,18 +325,19 @@ static inline void silk_noise_shape_quantizer( q1_Q10 = q2_Q10; } - pulses[ i ] = ( opus_int8 )silk_RSHIFT_ROUND( q1_Q10, 10 ); + pulses[ i ] = (opus_int8)silk_RSHIFT_ROUND( q1_Q10, 10 ); /* Excitation */ exc_Q10 = q1_Q10 ^ dither; /* Add predictions */ - LPC_exc_Q10 = silk_ADD32( exc_Q10, silk_RSHIFT_ROUND( LTP_pred_Q14, 4 ) ); + LPC_exc_Q10 = silk_ADD32( exc_Q10, silk_RSHIFT_ROUND( LTP_pred_Q13, 3 ) ); xq_Q10 = silk_ADD32( LPC_exc_Q10, LPC_pred_Q10 ); /* Scale XQ back to normal level before saving */ xq[ i ] = ( opus_int16 )silk_SAT16( silk_RSHIFT_ROUND( silk_SMULWW( xq_Q10, Gain_Q16 ), 10 ) ); + /* DEBUG_STORE_DATA( enc.pcm, &xq[i], sizeof( opus_int16 ) ) */ /* Update states */ psLPC_Q14++; *psLPC_Q14 = silk_LSHIFT( xq_Q10, 4 ); @@ -343,7 +345,7 @@ static inline void silk_noise_shape_quantizer( NSQ->sLF_AR_shp_Q12 = silk_LSHIFT( sLF_AR_shp_Q10, 2 ); NSQ->sLTP_shp_Q10[ NSQ->sLTP_shp_buf_idx ] = silk_SUB32( sLF_AR_shp_Q10, n_LF_Q10 ); - sLTP_Q16[ NSQ->sLTP_buf_idx ] = silk_LSHIFT( LPC_exc_Q10, 6 ); + sLTP_Q15[ NSQ->sLTP_buf_idx ] = silk_LSHIFT( LPC_exc_Q10, 5 ); NSQ->sLTP_shp_buf_idx++; NSQ->sLTP_buf_idx++; @@ -358,10 +360,10 @@ static inline void silk_noise_shape_quantizer( static inline void silk_nsq_scale_states( const silk_encoder_state *psEncC, /* I Encoder State */ silk_nsq_state *NSQ, /* I/O NSQ state */ - const opus_int16 x[], /* I input in Q0 */ + const opus_int32 x_Q10[], /* I input in Q0 */ 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_Q16[], /* O LTP state matching scaled input */ + 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 */ @@ -370,22 +372,21 @@ static inline void silk_nsq_scale_states( ) { opus_int i, lag; - opus_int32 inv_gain_Q16, gain_adj_Q16, inv_gain_Q32; + opus_int32 inv_gain_Q16, gain_adj_Q16, inv_gain_Q31; inv_gain_Q16 = silk_INVERSE32_varQ( silk_max( Gains_Q16[ subfr ], 1 ), 32 ); - inv_gain_Q16 = silk_min( inv_gain_Q16, silk_int16_MAX ); lag = pitchL[ subfr ]; /* After rewhitening the LTP state is un-scaled, so scale with inv_gain_Q16 */ if( NSQ->rewhite_flag ) { - inv_gain_Q32 = silk_LSHIFT( inv_gain_Q16, 16 ); + inv_gain_Q31 = silk_LSHIFT( inv_gain_Q16, 15 ); if( subfr == 0 ) { /* Do LTP downscaling */ - inv_gain_Q32 = silk_LSHIFT( silk_SMULWB( inv_gain_Q32, LTP_scale_Q14 ), 2 ); + inv_gain_Q31 = silk_LSHIFT( silk_SMULWB( inv_gain_Q31, LTP_scale_Q14 ), 2 ); } for( i = NSQ->sLTP_buf_idx - lag - LTP_ORDER / 2; i < NSQ->sLTP_buf_idx; i++ ) { silk_assert( i < MAX_FRAME_LENGTH ); - sLTP_Q16[ i ] = silk_SMULWB( inv_gain_Q32, sLTP[ i ] ); + sLTP_Q15[ i ] = silk_SMULWB( inv_gain_Q31, sLTP[ i ] ); } } @@ -401,7 +402,7 @@ static inline void silk_nsq_scale_states( /* 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; i++ ) { - sLTP_Q16[ i ] = silk_SMULWW( gain_adj_Q16, sLTP_Q16[ i ] ); + sLTP_Q15[ i ] = silk_SMULWW( gain_adj_Q16, sLTP_Q15[ i ] ); } } @@ -418,10 +419,10 @@ static inline void silk_nsq_scale_states( /* Scale input */ for( i = 0; i < psEncC->subfr_length; i++ ) { - x_sc_Q10[ i ] = silk_RSHIFT( silk_SMULBB( x[ i ], ( opus_int16 )inv_gain_Q16 ), 6 ); + x_sc_Q10[ i ] = silk_SMULWW( x_Q10[ i ], inv_gain_Q16 ); } - /* save inv_gain */ + /* Save inv_gain */ silk_assert( inv_gain_Q16 != 0 ); NSQ->prev_inv_gain_Q16 = inv_gain_Q16; } diff --git a/silk/NSQ_del_dec.c b/silk/NSQ_del_dec.c index 4917ddbf..48d413b1 100644 --- a/silk/NSQ_del_dec.c +++ b/silk/NSQ_del_dec.c @@ -32,7 +32,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "main.h" typedef struct { - opus_int32 sLPC_Q14[ MAX_FRAME_LENGTH / MAX_NB_SUBFR + NSQ_LPC_BUF_LENGTH ]; + opus_int32 sLPC_Q14[ MAX_SUB_FRAME_LENGTH + NSQ_LPC_BUF_LENGTH ]; opus_int32 RandState[ DECISION_DELAY ]; opus_int32 Q_Q10[ DECISION_DELAY ]; opus_int32 Xq_Q10[ DECISION_DELAY ]; @@ -58,10 +58,10 @@ static 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_int16 x[], /* I Input in Q0 */ + const opus_int32 x_Q10[], /* I Input in Q0 */ 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_Q16[], /* O LTP state matching scaled input */ + opus_int32 sLTP_Q15[], /* O LTP state matching scaled input */ opus_int subfr, /* I Subframe number */ opus_int nStatesDelayedDecision, /* I Number of del dec states */ const opus_int LTP_scale_Q14, /* I LTP state scaling */ @@ -81,7 +81,7 @@ static inline void silk_noise_shape_quantizer_del_dec( const opus_int32 x_Q10[], /* I */ opus_int8 pulses[], /* O */ opus_int16 xq[], /* O */ - opus_int32 sLTP_Q16[], /* I/O LTP filter state */ + opus_int32 sLTP_Q15[], /* I/O LTP filter state */ opus_int32 delayedGain_Q16[], /* 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 */ @@ -107,7 +107,7 @@ void silk_NSQ_del_dec( 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_int16 x[], /* I Prefiltered input signal */ + const opus_int32 x_Q10[], /* 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 */ @@ -121,19 +121,19 @@ void silk_NSQ_del_dec( const opus_int LTP_scale_Q14 /* I LTP state scaling */ ) { - opus_int i, k, lag, start_idx, LSF_interpolation_flag, Winner_ind, subfr; - opus_int last_smple_idx, smpl_buf_idx, decisionDelay; - const opus_int16 *A_Q12, *B_Q14, *AR_shp_Q13; - opus_int16 *pxq; - opus_int32 sLTP_Q16[ 2 * MAX_FRAME_LENGTH ]; - opus_int16 sLTP[ 2 * MAX_FRAME_LENGTH ]; - opus_int32 HarmShapeFIRPacked_Q14; - opus_int offset_Q10; - opus_int32 RDmin_Q10; - opus_int32 x_sc_Q10[ MAX_SUB_FRAME_LENGTH ]; - opus_int32 delayedGain_Q16[ DECISION_DELAY ]; - NSQ_del_dec_struct psDelDec[ MAX_DEL_DEC_STATES ]; - NSQ_del_dec_struct *psDD; + opus_int i, k, lag, start_idx, LSF_interpolation_flag, Winner_ind, subfr; + opus_int last_smple_idx, smpl_buf_idx, decisionDelay; + const opus_int16 *A_Q12, *B_Q14, *AR_shp_Q13; + opus_int16 *pxq; + opus_int32 sLTP_Q15[ 2 * MAX_FRAME_LENGTH ]; + opus_int16 sLTP[ 2 * MAX_FRAME_LENGTH ]; + opus_int32 HarmShapeFIRPacked_Q14; + opus_int offset_Q10; + opus_int32 RDmin_Q10; + opus_int32 x_sc_Q10[ MAX_SUB_FRAME_LENGTH ]; + opus_int32 delayedGain_Q16[ DECISION_DELAY ]; + NSQ_del_dec_struct psDelDec[ MAX_DEL_DEC_STATES ]; + NSQ_del_dec_struct *psDD; /* Set unvoiced lag to the previous one, overwrite later for voiced */ lag = NSQ->lagPrev; @@ -175,7 +175,7 @@ void silk_NSQ_del_dec( LSF_interpolation_flag = 1; } - /* Setup pointers to start of sub frame */ + /* 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; @@ -188,7 +188,7 @@ void silk_NSQ_del_dec( /* 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 ); + HarmShapeFIRPacked_Q14 |= silk_LSHIFT( (opus_int32)silk_RSHIFT( HarmShapeGain_Q14[ k ], 1 ), 16 ); NSQ->rewhite_flag = 0; if( psIndices->signalType == TYPE_VOICED ) { @@ -220,8 +220,8 @@ void silk_NSQ_del_dec( last_smple_idx = smpl_buf_idx + decisionDelay; for( i = 0; i < decisionDelay; i++ ) { last_smple_idx = ( last_smple_idx - 1 ) & DECISION_DELAY_MASK; - 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( + 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_Q10[ last_smple_idx ], Gains_Q16[ 1 ] ), 10 ) ); NSQ->sLTP_shp_Q10[ NSQ->sLTP_shp_buf_idx - decisionDelay + i ] = psDD->Shape_Q10[ last_smple_idx ]; } @@ -241,15 +241,15 @@ void silk_NSQ_del_dec( } } - silk_nsq_del_dec_scale_states( psEncC, NSQ, psDelDec, x, x_sc_Q10, sLTP, sLTP_Q16, k, + silk_nsq_del_dec_scale_states( psEncC, NSQ, psDelDec, x_Q10, 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_Q16, + silk_noise_shape_quantizer_del_dec( NSQ, psDelDec, psIndices->signalType, x_sc_Q10, pulses, pxq, sLTP_Q15, delayedGain_Q16, 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 ); - x += psEncC->subfr_length; + x_Q10 += psEncC->subfr_length; pulses += psEncC->subfr_length; pxq += psEncC->subfr_length; } @@ -270,8 +270,8 @@ void silk_NSQ_del_dec( last_smple_idx = smpl_buf_idx + decisionDelay; for( i = 0; i < decisionDelay; i++ ) { last_smple_idx = ( last_smple_idx - 1 ) & DECISION_DELAY_MASK; - 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( + 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_Q10[ last_smple_idx ], Gains_Q16[ psEncC->nb_subfr - 1 ] ), 10 ) ); NSQ->sLTP_shp_Q10[ NSQ->sLTP_shp_buf_idx - decisionDelay + i ] = psDD->Shape_Q10[ last_smple_idx ]; } @@ -282,7 +282,8 @@ void silk_NSQ_del_dec( NSQ->sLF_AR_shp_Q12 = psDD->LF_AR_Q12; NSQ->lagPrev = pitchL[ psEncC->nb_subfr - 1 ]; - /* Save quantized speech and noise shaping signals */ + /* 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_Q10, &NSQ->sLTP_shp_Q10[ psEncC->frame_length ], psEncC->ltp_mem_length * sizeof( opus_int32 ) ); } @@ -297,7 +298,7 @@ static inline void silk_noise_shape_quantizer_del_dec( const opus_int32 x_Q10[], /* I */ opus_int8 pulses[], /* O */ opus_int16 xq[], /* O */ - opus_int32 sLTP_Q16[], /* I/O LTP filter state */ + opus_int32 sLTP_Q15[], /* I/O LTP filter state */ opus_int32 delayedGain_Q16[], /* 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 */ @@ -321,7 +322,7 @@ static inline void silk_noise_shape_quantizer_del_dec( { opus_int i, j, k, Winner_ind, RDmin_ind, RDmax_ind, last_smple_idx; opus_int32 Winner_rand_state; - opus_int32 LTP_pred_Q14, LPC_pred_Q10, n_AR_Q10, n_LTP_Q14, LTP_Q10; + opus_int32 LTP_pred_Q13, LPC_pred_Q10, n_AR_Q10, n_LTP_Q14, LTP_Q10; opus_int32 n_LF_Q10, r_Q10, rr_Q10, rd1_Q10, rd2_Q10, RDmin_Q10, RDmax_Q10; opus_int32 q1_Q10, q2_Q10, dither, exc_Q10, LPC_exc_Q10, xq_Q10; opus_int32 tmp1, tmp2, sLF_AR_shp_Q10; @@ -333,7 +334,7 @@ static inline void silk_noise_shape_quantizer_del_dec( silk_assert( nStatesDelayedDecision > 0 ); shp_lag_ptr = &NSQ->sLTP_shp_Q10[ NSQ->sLTP_shp_buf_idx - lag + HARM_SHAPE_FIR_TAPS / 2 ]; - pred_lag_ptr = &sLTP_Q16[ NSQ->sLTP_buf_idx - lag + LTP_ORDER / 2 ]; + pred_lag_ptr = &sLTP_Q15[ NSQ->sLTP_buf_idx - lag + LTP_ORDER / 2 ]; for( i = 0; i < length; i++ ) { /* Perform common calculations used in all states */ @@ -341,25 +342,25 @@ static inline void silk_noise_shape_quantizer_del_dec( /* Long-term prediction */ if( signalType == TYPE_VOICED ) { /* Unrolled loop */ - LTP_pred_Q14 = silk_SMULWB( 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_Q13 = silk_SMULWB( pred_lag_ptr[ 0 ], b_Q14[ 0 ] ); + LTP_pred_Q13 = silk_SMLAWB( LTP_pred_Q13, pred_lag_ptr[ -1 ], b_Q14[ 1 ] ); + LTP_pred_Q13 = silk_SMLAWB( LTP_pred_Q13, pred_lag_ptr[ -2 ], b_Q14[ 2 ] ); + LTP_pred_Q13 = silk_SMLAWB( LTP_pred_Q13, pred_lag_ptr[ -3 ], b_Q14[ 3 ] ); + LTP_pred_Q13 = silk_SMLAWB( LTP_pred_Q13, pred_lag_ptr[ -4 ], b_Q14[ 4 ] ); pred_lag_ptr++; } else { - LTP_pred_Q14 = 0; + LTP_pred_Q13 = 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_SMLAWT( n_LTP_Q14, shp_lag_ptr[ -1 ], HarmShapeFIRPacked_Q14 ); n_LTP_Q14 = silk_LSHIFT( n_LTP_Q14, 6 ); shp_lag_ptr++; - LTP_Q10 = silk_RSHIFT( silk_SUB32( LTP_pred_Q14, n_LTP_Q14 ), 4 ); + LTP_Q10 = silk_RSHIFT( silk_SUB32( LTP_pred_Q13 << 1, n_LTP_Q14 ), 4 ); } else { LTP_Q10 = 0; } @@ -380,10 +381,7 @@ static inline void silk_noise_shape_quantizer_del_dec( /* Pointer used in short term prediction and shaping */ psLPC_Q14 = &psDD->sLPC_Q14[ NSQ_LPC_BUF_LENGTH - 1 + i ]; /* Short-term prediction */ - silk_assert( predictLPCOrder >= 10 ); /* check that unrolling works */ - silk_assert( ( predictLPCOrder & 1 ) == 0 ); /* check that order is even */ - silk_assert( ( (opus_int64)a_Q12 & 3 ) == 0 ); /* check that array starts at 4-byte aligned address */ - /* Partially unrolled */ + silk_assert( predictLPCOrder == 10 || predictLPCOrder == 16 ); LPC_pred_Q10 = silk_SMULWB( psLPC_Q14[ 0 ], a_Q12[ 0 ] ); LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, psLPC_Q14[ -1 ], a_Q12[ 1 ] ); LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, psLPC_Q14[ -2 ], a_Q12[ 2 ] ); @@ -394,8 +392,13 @@ static inline void silk_noise_shape_quantizer_del_dec( LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, psLPC_Q14[ -7 ], a_Q12[ 7 ] ); LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, psLPC_Q14[ -8 ], a_Q12[ 8 ] ); LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, psLPC_Q14[ -9 ], a_Q12[ 9 ] ); - for( j = 10; j < predictLPCOrder; j ++ ) { - LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, psLPC_Q14[ -j ], a_Q12[ j ] ); + if( predictLPCOrder == 16 ) { + LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, psLPC_Q14[ -10 ], a_Q12[ 10 ] ); + LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, psLPC_Q14[ -11 ], a_Q12[ 11 ] ); + LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, psLPC_Q14[ -12 ], a_Q12[ 12 ] ); + LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, psLPC_Q14[ -13 ], a_Q12[ 13 ] ); + LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, psLPC_Q14[ -14 ], a_Q12[ 14 ] ); + LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, psLPC_Q14[ -15 ], a_Q12[ 15 ] ); } /* Noise shape feedback */ @@ -486,7 +489,7 @@ static inline void silk_noise_shape_quantizer_del_dec( exc_Q10 = psSS[ 0 ].Q_Q10 ^ dither; /* Add predictions */ - LPC_exc_Q10 = exc_Q10 + silk_RSHIFT_ROUND( LTP_pred_Q14, 4 ); + LPC_exc_Q10 = exc_Q10 + silk_RSHIFT_ROUND( LTP_pred_Q13, 3 ); xq_Q10 = silk_ADD32( LPC_exc_Q10, LPC_pred_Q10 ); /* Update states */ @@ -502,7 +505,7 @@ static inline void silk_noise_shape_quantizer_del_dec( exc_Q10 = psSS[ 1 ].Q_Q10 ^ dither; /* Add predictions */ - LPC_exc_Q10 = exc_Q10 + silk_RSHIFT_ROUND( LTP_pred_Q14, 4 ); + LPC_exc_Q10 = exc_Q10 + silk_RSHIFT_ROUND( LTP_pred_Q13, 3 ); xq_Q10 = silk_ADD32( LPC_exc_Q10, LPC_pred_Q10 ); /* Update states */ @@ -564,11 +567,11 @@ static inline void silk_noise_shape_quantizer_del_dec( /* Write samples from winner to output and long-term filter states */ psDD = &psDelDec[ Winner_ind ]; if( subfr > 0 || i >= decisionDelay ) { - pulses[ i - decisionDelay ] = ( opus_int8 )silk_RSHIFT_ROUND( psDD->Q_Q10[ last_smple_idx ], 10 ); - xq[ i - decisionDelay ] = ( opus_int16 )silk_SAT16( silk_RSHIFT_ROUND( + pulses[ i - decisionDelay ] = (opus_int8)silk_RSHIFT_ROUND( psDD->Q_Q10[ last_smple_idx ], 10 ); + xq[ i - decisionDelay ] = (opus_int16)silk_SAT16( silk_RSHIFT_ROUND( silk_SMULWW( psDD->Xq_Q10[ last_smple_idx ], delayedGain_Q16[ last_smple_idx ] ), 10 ) ); NSQ->sLTP_shp_Q10[ NSQ->sLTP_shp_buf_idx - decisionDelay ] = psDD->Shape_Q10[ last_smple_idx ]; - sLTP_Q16[ NSQ->sLTP_buf_idx - decisionDelay ] = psDD->Pred_Q16[ last_smple_idx ]; + sLTP_Q15[ NSQ->sLTP_buf_idx - decisionDelay ] = psDD->Pred_Q16[ last_smple_idx ] >> 1; } NSQ->sLTP_shp_buf_idx++; NSQ->sLTP_buf_idx++; @@ -600,10 +603,10 @@ static 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_int16 x[], /* I Input in Q0 */ + const opus_int32 x_Q10[], /* I Input in Q0 */ 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_Q16[], /* O LTP state matching scaled input */ + opus_int32 sLTP_Q15[], /* O LTP state matching scaled input */ opus_int subfr, /* I Subframe number */ opus_int nStatesDelayedDecision, /* I Number of del dec states */ const opus_int LTP_scale_Q14, /* I LTP state scaling */ @@ -614,23 +617,22 @@ static inline void silk_nsq_del_dec_scale_states( ) { opus_int i, k, lag; - opus_int32 inv_gain_Q16, gain_adj_Q16, inv_gain_Q32; - NSQ_del_dec_struct *psDD; + opus_int32 inv_gain_Q16, gain_adj_Q16, inv_gain_Q31; + NSQ_del_dec_struct *psDD; inv_gain_Q16 = silk_INVERSE32_varQ( silk_max( Gains_Q16[ subfr ], 1 ), 32 ); - inv_gain_Q16 = silk_min( inv_gain_Q16, silk_int16_MAX ); lag = pitchL[ subfr ]; /* After rewhitening the LTP state is un-scaled, so scale with inv_gain_Q16 */ if( NSQ->rewhite_flag ) { - inv_gain_Q32 = silk_LSHIFT( inv_gain_Q16, 16 ); + inv_gain_Q31 = silk_LSHIFT( inv_gain_Q16, 15 ); if( subfr == 0 ) { /* Do LTP downscaling */ - inv_gain_Q32 = silk_LSHIFT( silk_SMULWB( inv_gain_Q32, LTP_scale_Q14 ), 2 ); + inv_gain_Q31 = silk_LSHIFT( silk_SMULWB( inv_gain_Q31, LTP_scale_Q14 ), 2 ); } for( i = NSQ->sLTP_buf_idx - lag - LTP_ORDER / 2; i < NSQ->sLTP_buf_idx; i++ ) { silk_assert( i < MAX_FRAME_LENGTH ); - sLTP_Q16[ i ] = silk_SMULWB( inv_gain_Q32, sLTP[ i ] ); + sLTP_Q15[ i ] = silk_SMULWB( inv_gain_Q31, sLTP[ i ] ); } } @@ -646,7 +648,7 @@ static inline void silk_nsq_del_dec_scale_states( /* 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; i++ ) { - sLTP_Q16[ i ] = silk_SMULWW( gain_adj_Q16, sLTP_Q16[ i ] ); + sLTP_Q15[ i ] = silk_SMULWW( gain_adj_Q16, sLTP_Q15[ i ] ); } } @@ -672,7 +674,7 @@ static inline void silk_nsq_del_dec_scale_states( /* Scale input */ for( i = 0; i < psEncC->subfr_length; i++ ) { - x_sc_Q10[ i ] = silk_RSHIFT( silk_SMULBB( x[ i ], ( opus_int16 )inv_gain_Q16 ), 6 ); + x_sc_Q10[ i ] = silk_SMULWW( x_Q10[ i ], inv_gain_Q16 ); } /* save inv_gain */ @@ -192,7 +192,7 @@ static inline void silk_PLC_conceal( exc_buf_ptr = exc_buf; for( k = 0; k < 2; k++ ) { for( i = 0; i < psPLC->subfr_length; i++ ) { - exc_buf_ptr[ i ] = ( opus_int16 )silk_RSHIFT( + exc_buf_ptr[ i ] = (opus_int16)silk_RSHIFT( silk_SMULWW( psDec->exc_Q10[ i + ( k + psPLC->nb_subfr - 2 ) * psPLC->subfr_length ], psPLC->prevGain_Q16[ k ] ), 10 ); } exc_buf_ptr += psPLC->subfr_length; @@ -209,11 +209,11 @@ static inline void silk_PLC_conceal( rand_ptr = &psDec->exc_Q10[ silk_max_int( 0, psPLC->nb_subfr * psPLC->subfr_length - RAND_BUF_SIZE ) ]; } - /* Setup Gain to random noise component */ + /* Set up Gain to random noise component */ B_Q14 = psPLC->LTPCoef_Q14; rand_scale_Q14 = psPLC->randScale_Q14; - /* Setup attenuation gains */ + /* Set up attenuation gains */ harm_Gain_Q15 = HARM_ATT_Q15[ silk_min_int( NB_ATT - 1, psDec->lossCnt ) ]; if( psDec->prevSignalType == TYPE_VOICED ) { rand_Gain_Q15 = PLC_RAND_ATTENUATE_V_Q15[ silk_min_int( NB_ATT - 1, psDec->lossCnt ) ]; @@ -237,12 +237,12 @@ static inline void silk_PLC_conceal( rand_scale_Q14 -= B_Q14[ i ]; } rand_scale_Q14 = silk_max_16( 3277, rand_scale_Q14 ); /* 0.2 */ - rand_scale_Q14 = ( opus_int16 )silk_RSHIFT( silk_SMULBB( rand_scale_Q14, psPLC->prevLTP_scale_Q14 ), 14 ); + rand_scale_Q14 = (opus_int16)silk_RSHIFT( silk_SMULBB( rand_scale_Q14, psPLC->prevLTP_scale_Q14 ), 14 ); } else { /* Reduce random noise for unvoiced frames with high LPC gain */ opus_int32 invGain_Q30, down_scale_Q30; - silk_LPC_inverse_pred_gain( &invGain_Q30, psPLC->prevLPC_Q12, psDec->LPC_order ); + invGain_Q30 = silk_LPC_inverse_pred_gain( psPLC->prevLPC_Q12, psDec->LPC_order ); down_scale_Q30 = silk_min_32( silk_RSHIFT( 1 << 30, LOG2_INV_LPC_GAIN_HIGH_THRES ), invGain_Q30 ); down_scale_Q30 = silk_max_32( silk_RSHIFT( 1 << 30, LOG2_INV_LPC_GAIN_LOW_THRES ), down_scale_Q30 ); @@ -272,7 +272,7 @@ static inline void silk_PLC_conceal( /* LTP synthesis filtering */ /***************************/ for( k = 0; k < psDec->nb_subfr; k++ ) { - /* Setup pointer */ + /* Set up pointer */ pred_lag_ptr = &sLTP_Q14[ sLTP_buf_idx - lag + LTP_ORDER / 2 ]; for( i = 0; i < psDec->subfr_length; i++ ) { /* Unrolled loop */ @@ -334,7 +334,7 @@ static inline void silk_PLC_conceal( sLPC_Q14_ptr[ MAX_LPC_ORDER + i ] = silk_ADD_LSHIFT32( sLPC_Q14_ptr[ MAX_LPC_ORDER + i ], LPC_pred_Q10, 4 ); /* Scale with Gain */ - frame[ i ] = ( opus_int16 )silk_SAT16( silk_RSHIFT_ROUND( silk_SMULWW( sLPC_Q14_ptr[ MAX_LPC_ORDER + i ], psPLC->prevGain_Q16[ 1 ] ), 14 ) ); + frame[ i ] = (opus_int16)silk_SAT16( silk_RSHIFT_ROUND( silk_SMULWW( sLPC_Q14_ptr[ MAX_LPC_ORDER + i ], psPLC->prevGain_Q16[ 1 ] ), 14 ) ); } /* Save LPC state */ @@ -25,8 +25,8 @@ ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ***********************************************************************/ -#ifndef SILK_PLC_FIX_H -#define SILK_PLC_FIX_H +#ifndef SILK_PLC_H +#define SILK_PLC_H #include "main.h" diff --git a/silk/SigProc_FIX.h b/silk/SigProc_FIX.h index 6a4e3f42..02d9b78b 100644 --- a/silk/SigProc_FIX.h +++ b/silk/SigProc_FIX.h @@ -52,19 +52,20 @@ extern "C" * Initialize/reset the resampler state for a given pair of input/output sampling rates */ opus_int silk_resampler_init( - silk_resampler_state_struct *S, /* I/O Resampler state */ - opus_int32 Fs_Hz_in, /* I Input sampling rate (Hz) */ - opus_int32 Fs_Hz_out /* I Output sampling rate (Hz) */ + silk_resampler_state_struct *S, /* I/O Resampler state */ + opus_int32 Fs_Hz_in, /* I Input sampling rate (Hz) */ + opus_int32 Fs_Hz_out, /* I Output sampling rate (Hz) */ + opus_int forEnc /* I If 1: encoder; if 0: decoder */ ); /*! * Resampler: convert from one sampling rate to another */ opus_int silk_resampler( - silk_resampler_state_struct *S, /* I/O Resampler state */ - opus_int16 out[], /* O Output signal */ - const opus_int16 in[], /* I Input signal */ - opus_int32 inLen /* I Number of input samples */ + silk_resampler_state_struct *S, /* I/O Resampler state */ + opus_int16 out[], /* O Output signal */ + const opus_int16 in[], /* I Input signal */ + opus_int32 inLen /* I Number of input samples */ ); /*! @@ -127,15 +128,14 @@ void silk_bwexpander_32( /* Compute inverse of LPC prediction gain, and */ /* test if LPC coefficients are stable (all poles within unit circle) */ -opus_int silk_LPC_inverse_pred_gain( /* O Returns 1 if unstable, otherwise 0 */ - opus_int32 *invGain_Q30, /* O Inverse prediction gain, Q30 energy domain */ +opus_int32 silk_LPC_inverse_pred_gain( /* 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 silk_LPC_inverse_pred_gain_Q24( /* O Returns 1 if unstable, otherwise 0 */ - opus_int32 *invGain_Q30, /* O Inverse prediction gain, Q30 energy domain */ - const opus_int32 *A_Q24, /* I Prediction coefficients, Q24 [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 */ ); @@ -313,9 +313,9 @@ void silk_burg_modified( opus_int *res_nrg_Q, /* O Residual energy Q value */ opus_int32 A_Q16[], /* O Prediction coefficients (length order) */ const opus_int16 x[], /* I Input signal, length: nb_subfr * ( D + subfr_length ) */ + const opus_int32 minInvGain_Q30, /* I Inverse of max prediction gain */ const opus_int subfr_length, /* I Input signal subframe length (incl. D preceeding samples) */ const opus_int nb_subfr, /* I Number of subframes stacked in x */ - const opus_int32 WhiteNoiseFrac_Q32, /* I Fraction added to zero-lag autocorrelation */ const opus_int D /* I Order */ ); @@ -388,9 +388,9 @@ static inline opus_int32 silk_ROR32( opus_int32 a32, opus_int rot ) #endif /* Useful Macros that can be adjusted to other platforms */ -#define silk_memcpy(a, b, c) memcpy((a), (b), (c)) /* Dest, Src, ByteCount */ -#define silk_memset(a, b, c) memset((a), (b), (c)) /* Dest, value, ByteCount */ -#define silk_memmove(a, b, c) memmove((a), (b), (c)) /* Dest, Src, ByteCount */ +#define silk_memcpy(dest, src, size) memcpy((dest), (src), (size)) +#define silk_memset(dest, src, size) memset((dest), (src), (size)) +#define silk_memmove(dest, src, size) memmove((dest), (src), (size)) /* Fixed point macros */ @@ -204,7 +204,7 @@ opus_int silk_VAD_GetSA_Q8( /* O Return v sumSquared = silk_DIV32_16( sumSquared, VAD_N_BANDS ); /* Q14 */ /* Root-mean-square approximation, scale to dBs, and write to output pointer */ - pSNR_dB_Q7 = ( opus_int16 )( 3 * silk_SQRT_APPROX( sumSquared ) ); /* Q7 */ + pSNR_dB_Q7 = (opus_int16)( 3 * silk_SQRT_APPROX( sumSquared ) ); /* Q7 */ /*********************************/ /* Speech Probability Estimation */ diff --git a/silk/control_codec.c b/silk/control_codec.c index 829b08f7..16666d68 100644 --- a/silk/control_codec.c +++ b/silk/control_codec.c @@ -38,13 +38,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "tuning_parameters.h" #include "pitch_est_defines.h" -static const opus_int enc_delay_matrix[3][5] = { -/*SILK API 8 12 16 24 48 */ -/* 8 */ {5, 0, 3, 4, 8}, -/*12 */ {0, 6, 0, 0, 0}, -/*16 */ {4, 5, 11, 5, 18} -}; - opus_int silk_setup_resamplers( silk_encoder_state_Fxx *psEnc, /* I/O */ opus_int fs_kHz /* I */ @@ -150,7 +143,7 @@ opus_int silk_setup_resamplers( { if( psEnc->sCmn.fs_kHz == 0 ) { /* Initialize the resampler for enc_API.c preparing resampling from API_fs_Hz to fs_kHz */ - ret += silk_resampler_init( &psEnc->sCmn.resampler_state, psEnc->sCmn.API_fs_Hz, fs_kHz * 1000 ); + ret += silk_resampler_init( &psEnc->sCmn.resampler_state, psEnc->sCmn.API_fs_Hz, fs_kHz * 1000, 1 ); } else { /* Allocate worst case space for temporary upsampling, 8 to 48 kHz, so a factor 6 */ opus_int16 x_buf_API_fs_Hz[ ( 2 * MAX_FRAME_LENGTH_MS + LA_SHAPE_MS ) * MAX_API_FS_KHZ ]; @@ -168,7 +161,7 @@ opus_int silk_setup_resamplers( #endif /* Initialize resampler for temporary resampling of x_buf data to API_fs_Hz */ - ret += silk_resampler_init( &temp_resampler_state, silk_SMULBB( psEnc->sCmn.fs_kHz, 1000 ), psEnc->sCmn.API_fs_Hz ); + ret += silk_resampler_init( &temp_resampler_state, silk_SMULBB( psEnc->sCmn.fs_kHz, 1000 ), psEnc->sCmn.API_fs_Hz, 0 ); /* Temporary resampling of x_buf data to API_fs_Hz */ ret += silk_resampler( &temp_resampler_state, x_buf_API_fs_Hz, x_bufFIX, nSamples_temp ); @@ -177,7 +170,7 @@ opus_int silk_setup_resamplers( nSamples_temp = silk_DIV32_16( nSamples_temp * psEnc->sCmn.API_fs_Hz, silk_SMULBB( psEnc->sCmn.fs_kHz, 1000 ) ); /* Initialize the resampler for enc_API.c preparing resampling from API_fs_Hz to fs_kHz */ - ret += silk_resampler_init( &psEnc->sCmn.resampler_state, psEnc->sCmn.API_fs_Hz, silk_SMULBB( fs_kHz, 1000 ) ); + ret += silk_resampler_init( &psEnc->sCmn.resampler_state, psEnc->sCmn.API_fs_Hz, silk_SMULBB( fs_kHz, 1000 ), 1 ); /* Correct resampler state by resampling buffered data from API_fs_Hz to fs_kHz */ ret += silk_resampler( &psEnc->sCmn.resampler_state, x_bufFIX, x_buf_API_fs_Hz, nSamples_temp ); @@ -234,9 +227,6 @@ opus_int silk_setup_fs( psEnc->sCmn.TargetRate_bps = 0; /* trigger new SNR computation */ } - psEnc->sCmn.delay = enc_delay_matrix[rateID(fs_kHz*1000)][rateID(psEnc->sCmn.API_fs_Hz)]; - silk_assert(psEnc->sCmn.delay <= MAX_ENCODER_DELAY); - /* 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 ); @@ -336,7 +326,7 @@ opus_int silk_setup_complexity( psEncC->shapingLPCOrder = 10; psEncC->la_shape = 5 * psEncC->fs_kHz; psEncC->nStatesDelayedDecision = 1; - psEncC->useInterpolatedNLSFs = 1; + psEncC->useInterpolatedNLSFs = 0; psEncC->LTPQuantLowComplexity = 0; psEncC->NLSF_MSVQ_Survivors = 4; psEncC->warping_Q16 = 0; @@ -347,7 +337,7 @@ opus_int silk_setup_complexity( psEncC->shapingLPCOrder = 12; psEncC->la_shape = 5 * psEncC->fs_kHz; psEncC->nStatesDelayedDecision = 2; - psEncC->useInterpolatedNLSFs = 0; + psEncC->useInterpolatedNLSFs = 1; psEncC->LTPQuantLowComplexity = 0; psEncC->NLSF_MSVQ_Survivors = 8; psEncC->warping_Q16 = psEncC->fs_kHz * SILK_FIX_CONST( WARPING_MULTIPLIER, 16 ); @@ -358,7 +348,7 @@ opus_int silk_setup_complexity( psEncC->shapingLPCOrder = 14; psEncC->la_shape = 5 * psEncC->fs_kHz; psEncC->nStatesDelayedDecision = 3; - psEncC->useInterpolatedNLSFs = 0; + psEncC->useInterpolatedNLSFs = 1; psEncC->LTPQuantLowComplexity = 0; psEncC->NLSF_MSVQ_Survivors = 16; psEncC->warping_Q16 = psEncC->fs_kHz * SILK_FIX_CONST( WARPING_MULTIPLIER, 16 ); diff --git a/silk/dec_API.c b/silk/dec_API.c index 9fe62d9b..c456a6d4 100644 --- a/silk/dec_API.c +++ b/silk/dec_API.c @@ -83,9 +83,9 @@ opus_int silk_Decode( /* O Returns error co opus_int32 *nSamplesOut /* O Number of samples decoded */ ) { - opus_int i, n, delay, decode_only_middle = 0, ret = SILK_NO_ERROR; + opus_int i, n, decode_only_middle = 0, ret = SILK_NO_ERROR; opus_int32 nSamplesOutDec, LBRR_symbol; - opus_int16 samplesOut1_tmp[ 2 ][ MAX_FS_KHZ * MAX_FRAME_LENGTH_MS + 2 + MAX_DECODER_DELAY ]; + opus_int16 samplesOut1_tmp[ 2 ][ MAX_FS_KHZ * MAX_FRAME_LENGTH_MS + 2 ]; opus_int16 samplesOut2_tmp[ MAX_API_FS_KHZ * MAX_FRAME_LENGTH_MS ]; opus_int32 MS_pred_Q13[ 2 ] = { 0 }; opus_int16 *resample_out_ptr; @@ -139,13 +139,10 @@ opus_int silk_Decode( /* O Returns error co } } - delay = channel_state[ 0 ].delay; - if( decControl->nChannelsAPI == 2 && decControl->nChannelsInternal == 2 && ( psDec->nChannelsAPI == 1 || psDec->nChannelsInternal == 1 ) ) { silk_memset( psDec->sStereo.pred_prev_Q13, 0, sizeof( psDec->sStereo.pred_prev_Q13 ) ); silk_memset( psDec->sStereo.sSide, 0, sizeof( psDec->sStereo.sSide ) ); silk_memcpy( &channel_state[ 1 ].resampler_state, &channel_state[ 0 ].resampler_state, sizeof( silk_resampler_state_struct ) ); - silk_memcpy( &channel_state[ 1 ].delayBuf, &channel_state[ 0 ].delayBuf, sizeof(channel_state[ 0 ].delayBuf)); } psDec->nChannelsAPI = decControl->nChannelsAPI; psDec->nChannelsInternal = decControl->nChannelsInternal; @@ -264,20 +261,20 @@ opus_int silk_Decode( /* O Returns error co } else { condCoding = CODE_CONDITIONALLY; } - ret += silk_decode_frame( &channel_state[ n ], psRangeDec, &samplesOut1_tmp[ n ][ 2 + delay ], &nSamplesOutDec, lostFlag, condCoding); + ret += silk_decode_frame( &channel_state[ n ], psRangeDec, &samplesOut1_tmp[ n ][ 2 ], &nSamplesOutDec, lostFlag, condCoding); } else { - silk_memset( &samplesOut1_tmp[ n ][ 2 + delay ], 0, nSamplesOutDec * sizeof( opus_int16 ) ); + silk_memset( &samplesOut1_tmp[ n ][ 2 ], 0, nSamplesOutDec * sizeof( opus_int16 ) ); } channel_state[ n ].nFramesDecoded++; } if( decControl->nChannelsAPI == 2 && decControl->nChannelsInternal == 2 ) { /* Convert Mid/Side to Left/Right */ - silk_stereo_MS_to_LR( &psDec->sStereo, &samplesOut1_tmp[ 0 ][ delay ], &samplesOut1_tmp[ 1 ][ delay ], MS_pred_Q13, channel_state[ 0 ].fs_kHz, nSamplesOutDec ); + silk_stereo_MS_to_LR( &psDec->sStereo, samplesOut1_tmp[ 0 ], samplesOut1_tmp[ 1 ], MS_pred_Q13, channel_state[ 0 ].fs_kHz, nSamplesOutDec ); } else { /* Buffering */ - silk_memcpy( &samplesOut1_tmp[ 0 ][ delay ], psDec->sStereo.sMid, 2 * sizeof( opus_int16 ) ); - silk_memcpy( psDec->sStereo.sMid, &samplesOut1_tmp[ 0 ][ nSamplesOutDec + delay ], 2 * sizeof( opus_int16 ) ); + silk_memcpy( samplesOut1_tmp[ 0 ], psDec->sStereo.sMid, 2 * sizeof( opus_int16 ) ); + silk_memcpy( psDec->sStereo.sMid, &samplesOut1_tmp[ 0 ][ nSamplesOutDec ], 2 * sizeof( opus_int16 ) ); } /* Number of output samples */ @@ -292,10 +289,8 @@ opus_int silk_Decode( /* O Returns error co for( n = 0; n < silk_min( decControl->nChannelsAPI, decControl->nChannelsInternal ); n++ ) { - silk_memcpy(&samplesOut1_tmp[ n ][ 1 ], &channel_state[ n ].delayBuf[ MAX_DECODER_DELAY - delay ], delay * sizeof(opus_int16)); /* Resample decoded signal to API_sampleRate */ ret += silk_resampler( &channel_state[ n ].resampler_state, resample_out_ptr, &samplesOut1_tmp[ n ][ 1 ], nSamplesOutDec ); - silk_memcpy(channel_state[ n ].delayBuf, &samplesOut1_tmp[ n ][ 1 + nSamplesOutDec + delay - MAX_DECODER_DELAY ], MAX_DECODER_DELAY * sizeof(opus_int16)); /* Interleave if stereo output and stereo stream */ if( decControl->nChannelsAPI == 2 && decControl->nChannelsInternal == 2 ) { diff --git a/silk/decode_core.c b/silk/decode_core.c index 9a4c9f39..6633143d 100644 --- a/silk/decode_core.c +++ b/silk/decode_core.c @@ -41,11 +41,11 @@ void silk_decode_core( const opus_int pulses[ MAX_FRAME_LENGTH ] /* I Pulse signal */ ) { - opus_int i, j, k, lag = 0, start_idx, sLTP_buf_idx, NLSF_interpolation_flag, signalType; + opus_int i, k, lag = 0, start_idx, sLTP_buf_idx, NLSF_interpolation_flag, signalType; opus_int16 *A_Q12, *B_Q14, *pxq, A_Q12_tmp[ MAX_LPC_ORDER ]; opus_int16 sLTP[ MAX_FRAME_LENGTH ]; - opus_int32 sLTP_Q16[ 2 * MAX_FRAME_LENGTH ]; - opus_int32 LTP_pred_Q14, LPC_pred_Q10, Gain_Q10, inv_gain_Q16, inv_gain_Q32, gain_adj_Q16, rand_seed, offset_Q10; + opus_int32 sLTP_Q15[ 2 * MAX_FRAME_LENGTH ]; + opus_int32 LTP_pred_Q13, LPC_pred_Q10, Gain_Q10, inv_gain_Q16, inv_gain_Q31, gain_adj_Q16, rand_seed, offset_Q10; opus_int32 *pred_lag_ptr, *pexc_Q10, *pres_Q10; opus_int32 res_Q10[ MAX_SUB_FRAME_LENGTH ]; opus_int32 sLPC_Q14[ MAX_SUB_FRAME_LENGTH + MAX_LPC_ORDER ]; @@ -64,7 +64,7 @@ void silk_decode_core( rand_seed = psDec->indices.Seed; for( i = 0; i < psDec->frame_length; i++ ) { rand_seed = silk_RAND( rand_seed ); - psDec->exc_Q10[ i ] = silk_LSHIFT( ( opus_int32 )pulses[ i ], 10 ); + psDec->exc_Q10[ i ] = silk_LSHIFT( (opus_int32)pulses[ i ], 10 ); if( psDec->exc_Q10[ i ] > 0 ) { psDec->exc_Q10[ i ] -= QUANT_LEVEL_ADJUST_Q10; } else @@ -95,7 +95,6 @@ void silk_decode_core( Gain_Q10 = silk_RSHIFT( psDecCtrl->Gains_Q16[ k ], 6 ); inv_gain_Q16 = silk_INVERSE32_varQ( psDecCtrl->Gains_Q16[ k ], 32 ); - inv_gain_Q16 = silk_min( inv_gain_Q16, silk_int16_MAX ); /* Calculate Gain adjustment factor */ gain_adj_Q16 = 1 << 16; @@ -141,19 +140,19 @@ void silk_decode_core( A_Q12, psDec->ltp_mem_length - start_idx, psDec->LPC_order ); /* After rewhitening the LTP state is unscaled */ - inv_gain_Q32 = silk_LSHIFT( inv_gain_Q16, 16 ); + inv_gain_Q31 = silk_LSHIFT( inv_gain_Q16, 15 ); if( k == 0 ) { /* Do LTP downscaling to reduce inter-packet dependency */ - inv_gain_Q32 = silk_LSHIFT( silk_SMULWB( inv_gain_Q32, psDecCtrl->LTP_scale_Q14 ), 2 ); + inv_gain_Q31 = silk_LSHIFT( silk_SMULWB( inv_gain_Q31, psDecCtrl->LTP_scale_Q14 ), 2 ); } for( i = 0; i < lag + LTP_ORDER/2; i++ ) { - sLTP_Q16[ sLTP_buf_idx - i - 1 ] = silk_SMULWB( inv_gain_Q32, sLTP[ psDec->ltp_mem_length - i - 1 ] ); + sLTP_Q15[ sLTP_buf_idx - i - 1 ] = silk_SMULWB( inv_gain_Q31, sLTP[ psDec->ltp_mem_length - i - 1 ] ); } } else { /* Update LTP state when Gain changes */ if( gain_adj_Q16 != 1 << 16 ) { for( i = 0; i < lag + LTP_ORDER/2; i++ ) { - sLTP_Q16[ sLTP_buf_idx - i - 1 ] = silk_SMULWW( gain_adj_Q16, sLTP_Q16[ sLTP_buf_idx - i - 1 ] ); + sLTP_Q15[ sLTP_buf_idx - i - 1 ] = silk_SMULWW( gain_adj_Q16, sLTP_Q15[ sLTP_buf_idx - i - 1 ] ); } } } @@ -161,22 +160,22 @@ void silk_decode_core( /* Long-term prediction */ if( signalType == TYPE_VOICED ) { - /* Setup pointer */ - pred_lag_ptr = &sLTP_Q16[ sLTP_buf_idx - lag + LTP_ORDER / 2 ]; + /* Set up pointer */ + pred_lag_ptr = &sLTP_Q15[ sLTP_buf_idx - lag + LTP_ORDER / 2 ]; for( i = 0; i < psDec->subfr_length; i++ ) { /* Unrolled loop */ - LTP_pred_Q14 = silk_SMULWB( 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_Q13 = silk_SMULWB( pred_lag_ptr[ 0 ], B_Q14[ 0 ] ); + LTP_pred_Q13 = silk_SMLAWB( LTP_pred_Q13, pred_lag_ptr[ -1 ], B_Q14[ 1 ] ); + LTP_pred_Q13 = silk_SMLAWB( LTP_pred_Q13, pred_lag_ptr[ -2 ], B_Q14[ 2 ] ); + LTP_pred_Q13 = silk_SMLAWB( LTP_pred_Q13, pred_lag_ptr[ -3 ], B_Q14[ 3 ] ); + LTP_pred_Q13 = silk_SMLAWB( LTP_pred_Q13, pred_lag_ptr[ -4 ], B_Q14[ 4 ] ); pred_lag_ptr++; /* Generate LPC excitation */ - pres_Q10[ i ] = silk_ADD32( pexc_Q10[ i ], silk_RSHIFT_ROUND( LTP_pred_Q14, 4 ) ); + pres_Q10[ i ] = silk_ADD32( pexc_Q10[ i ], silk_RSHIFT_ROUND( LTP_pred_Q13, 3 ) ); /* Update states */ - sLTP_Q16[ sLTP_buf_idx ] = silk_LSHIFT( pres_Q10[ i ], 6 ); + sLTP_Q15[ sLTP_buf_idx ] = silk_LSHIFT( pres_Q10[ i ], 5 ); sLTP_buf_idx++; } } else { @@ -184,7 +183,8 @@ void silk_decode_core( } for( i = 0; i < psDec->subfr_length; i++ ) { - /* Partially unrolled */ + /* Short-term prediction */ + silk_assert( psDec->LPC_order == 10 || psDec->LPC_order == 16 ); LPC_pred_Q10 = silk_SMULWB( sLPC_Q14[ MAX_LPC_ORDER + i - 1 ], A_Q12_tmp[ 0 ] ); LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, sLPC_Q14[ MAX_LPC_ORDER + i - 2 ], A_Q12_tmp[ 1 ] ); LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, sLPC_Q14[ MAX_LPC_ORDER + i - 3 ], A_Q12_tmp[ 2 ] ); @@ -195,17 +195,23 @@ void silk_decode_core( LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, sLPC_Q14[ MAX_LPC_ORDER + i - 8 ], A_Q12_tmp[ 7 ] ); LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, sLPC_Q14[ MAX_LPC_ORDER + i - 9 ], A_Q12_tmp[ 8 ] ); LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, sLPC_Q14[ MAX_LPC_ORDER + i - 10 ], A_Q12_tmp[ 9 ] ); - for( j = 10; j < psDec->LPC_order; j++ ) { - LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, sLPC_Q14[ MAX_LPC_ORDER + i - j - 1 ], A_Q12_tmp[ j ] ); + if( psDec->LPC_order == 16 ) { + LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, sLPC_Q14[ MAX_LPC_ORDER + i - 11 ], A_Q12_tmp[ 10 ] ); + LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, sLPC_Q14[ MAX_LPC_ORDER + i - 12 ], A_Q12_tmp[ 11 ] ); + LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, sLPC_Q14[ MAX_LPC_ORDER + i - 13 ], A_Q12_tmp[ 12 ] ); + LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, sLPC_Q14[ MAX_LPC_ORDER + i - 14 ], A_Q12_tmp[ 13 ] ); + LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, sLPC_Q14[ MAX_LPC_ORDER + i - 15 ], A_Q12_tmp[ 14 ] ); + LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, sLPC_Q14[ MAX_LPC_ORDER + i - 16 ], A_Q12_tmp[ 15 ] ); } /* Add prediction to LPC excitation */ sLPC_Q14[ MAX_LPC_ORDER + i ] = silk_LSHIFT( silk_ADD32( pres_Q10[ i ], LPC_pred_Q10 ), 4 ); /* Scale with Gain */ - pxq[ i ] = ( opus_int16 )silk_SAT16( silk_RSHIFT_ROUND( silk_SMULWW( sLPC_Q14[ MAX_LPC_ORDER + i ], Gain_Q10 ), 8 ) ); + 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_Q10 += psDec->subfr_length; diff --git a/silk/decode_parameters.c b/silk/decode_parameters.c index 6c69cfab..c9728055 100644 --- a/silk/decode_parameters.c +++ b/silk/decode_parameters.c @@ -72,8 +72,7 @@ void silk_decode_parameters( silk_NLSF2A( psDecCtrl->PredCoef_Q12[ 0 ], pNLSF0_Q15, psDec->LPC_order ); } 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 ) ); + silk_memcpy( psDecCtrl->PredCoef_Q12[ 0 ], psDecCtrl->PredCoef_Q12[ 1 ], psDec->LPC_order * sizeof( opus_int16 ) ); } silk_memcpy( psDec->prevNLSF_Q15, pNLSF_Q15, psDec->LPC_order * sizeof( opus_int16 ) ); diff --git a/silk/decoder_set_fs.c b/silk/decoder_set_fs.c index 5579b20e..8c012d35 100644 --- a/silk/decoder_set_fs.c +++ b/silk/decoder_set_fs.c @@ -31,13 +31,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "main.h" -static const int dec_delay_matrix[3][5] = { -/*SILK API 8 12 16 24 48 */ -/* 8 */ {3, 0, 2, 0, 0}, -/*12 */ {0, 8, 5, 7, 5}, -/*16 */ {0, 0, 8, 5, 5} -}; - /* Set decoder sampling rate */ opus_int silk_decoder_set_fs( silk_decoder_state *psDec, /* I/O Decoder state pointer */ @@ -60,13 +53,9 @@ opus_int silk_decoder_set_fs( opus_int16 temp_buf[ MAX_FRAME_LENGTH_MS * MAX_API_FS_KHZ ]; silk_resampler_state_struct temp_resampler_state; - /* New delay value */ - psDec->delay = dec_delay_matrix[ rateID( silk_SMULBB( fs_kHz, 1000 ) ) ][ rateID( fs_API_Hz ) ]; - silk_assert( psDec->delay <= MAX_DECODER_DELAY ); - if( psDec->fs_kHz != fs_kHz && psDec->fs_kHz > 0 ) { /* Initialize resampler for temporary resampling of outBuf data to the new internal sampling rate */ - ret += silk_resampler_init( &temp_resampler_state, silk_SMULBB( psDec->fs_kHz, 1000 ), silk_SMULBB( fs_kHz, 1000 ) ); + ret += silk_resampler_init( &temp_resampler_state, silk_SMULBB( psDec->fs_kHz, 1000 ), silk_SMULBB( fs_kHz, 1000 ), 0 ); /* Temporary resampling of outBuf data to the new internal sampling rate */ silk_memcpy( temp_buf, psDec->outBuf, psDec->frame_length * sizeof( opus_int16 ) ); @@ -74,7 +63,7 @@ opus_int silk_decoder_set_fs( } /* Initialize the resampler for dec_API.c preparing resampling from fs_kHz to API_fs_Hz */ - ret += silk_resampler_init( &psDec->resampler_state, silk_SMULBB( fs_kHz, 1000 ), fs_API_Hz ); + ret += silk_resampler_init( &psDec->resampler_state, silk_SMULBB( fs_kHz, 1000 ), fs_API_Hz, 0 ); /* Correct resampler state by resampling buffered data from fs_kHz to API_fs_Hz */ ret += silk_resampler( &psDec->resampler_state, temp_buf, psDec->outBuf, frame_length ); diff --git a/silk/define.h b/silk/define.h index dcfdee93..fe2a659a 100644 --- a/silk/define.h +++ b/silk/define.h @@ -91,9 +91,6 @@ extern "C" #define MAX_FRAME_LENGTH_MS ( SUB_FRAME_LENGTH_MS * MAX_NB_SUBFR ) #define MAX_FRAME_LENGTH ( MAX_FRAME_LENGTH_MS * MAX_FS_KHZ ) -#define MAX_ENCODER_DELAY 18 -#define MAX_DECODER_DELAY 8 - /* Milliseconds of lookahead for pitch analysis */ #define LA_PITCH_MS 2 #define LA_PITCH_MAX ( LA_PITCH_MS * MAX_FS_KHZ ) @@ -133,7 +130,9 @@ extern "C" #define QUANT_LEVEL_ADJUST_Q10 80 /* Maximum numbers of iterations used to stabilize a LPC vector */ -#define MAX_LPC_STABILIZE_ITERATIONS 20 +#define MAX_LPC_STABILIZE_ITERATIONS 30 +#define MAX_PREDICTION_POWER_GAIN 1e4f +#define MAX_PREDICTION_POWER_GAIN_AFTER_RESET 1e2f #define MAX_LPC_ORDER 16 #define MIN_LPC_ORDER 10 diff --git a/silk/enc_API.c b/silk/enc_API.c index 02a8fd01..b993ed59 100644 --- a/silk/enc_API.c +++ b/silk/enc_API.c @@ -140,10 +140,10 @@ opus_int silk_Encode( /* O Returns error co opus_int n, i, nBits, flags, tmp_payloadSize_ms = 0, tmp_complexity = 0, ret = 0; opus_int nSamplesToBuffer, nBlocksOf10ms, nSamplesFromInput = 0; opus_int speech_act_thr_for_switch_Q8; - opus_int32 TargetRate_bps, MStargetRates_bps[ 2 ], channelRate_bps, LBRR_symbol; + opus_int32 TargetRate_bps, MStargetRates_bps[ 2 ], channelRate_bps, LBRR_symbol, sum; silk_encoder *psEnc = ( silk_encoder * )encState; - opus_int16 buf[ MAX_FRAME_LENGTH_MS * MAX_API_FS_KHZ + MAX_ENCODER_DELAY]; - opus_int transition, delay, curr_block, tot_blocks; + opus_int16 buf[ MAX_FRAME_LENGTH_MS * MAX_API_FS_KHZ ]; + opus_int transition, curr_block, tot_blocks; psEnc->state_Fxx[ 0 ].sCmn.nFramesEncoded = psEnc->state_Fxx[ 1 ].sCmn.nFramesEncoded = 0; @@ -233,7 +233,6 @@ opus_int silk_Encode( /* O Returns error co } silk_assert( encControl->nChannelsInternal == 1 || psEnc->state_Fxx[ 0 ].sCmn.fs_kHz == psEnc->state_Fxx[ 1 ].sCmn.fs_kHz ); - delay = psEnc->state_Fxx[ 0 ].sCmn.delay; /* Input buffering/resampling and encoding */ while( 1 ) { nSamplesToBuffer = psEnc->state_Fxx[ 0 ].sCmn.frame_length - psEnc->state_Fxx[ 0 ].sCmn.inputBufIx; @@ -243,15 +242,12 @@ opus_int silk_Encode( /* O Returns error co if( encControl->nChannelsAPI == 2 && encControl->nChannelsInternal == 2 ) { opus_int id = psEnc->state_Fxx[ 0 ].sCmn.nFramesEncoded; for( n = 0; n < nSamplesFromInput; n++ ) { - buf[ n+delay ] = samplesIn[ 2 * n ]; + buf[ n ] = samplesIn[ 2 * n ]; } - silk_memcpy(buf, &psEnc->state_Fxx[ 0 ].sCmn.delayBuf[ MAX_ENCODER_DELAY - delay ], delay * sizeof(opus_int16)); /* Making sure to start both resamplers from the same state when switching from mono to stereo */ - if(psEnc->nPrevChannelsInternal == 1 && id==0) { + if( psEnc->nPrevChannelsInternal == 1 && id==0 ) { silk_memcpy( &psEnc->state_Fxx[ 1 ].sCmn.resampler_state, &psEnc->state_Fxx[ 0 ].sCmn.resampler_state, sizeof(psEnc->state_Fxx[ 1 ].sCmn.resampler_state)); - silk_memcpy( &psEnc->state_Fxx[ 1 ].sCmn.delayBuf, &psEnc->state_Fxx[ 0 ].sCmn.delayBuf, MAX_ENCODER_DELAY*sizeof(opus_int16)); } - silk_memcpy(psEnc->state_Fxx[ 0 ].sCmn.delayBuf, buf + nSamplesFromInput + delay - MAX_ENCODER_DELAY, MAX_ENCODER_DELAY*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 ); @@ -260,25 +256,18 @@ opus_int silk_Encode( /* O Returns error co nSamplesToBuffer = psEnc->state_Fxx[ 1 ].sCmn.frame_length - psEnc->state_Fxx[ 1 ].sCmn.inputBufIx; nSamplesToBuffer = silk_min( nSamplesToBuffer, 10 * nBlocksOf10ms * psEnc->state_Fxx[ 1 ].sCmn.fs_kHz ); for( n = 0; n < nSamplesFromInput; n++ ) { - buf[ n + delay ] = samplesIn[ 2 * n + 1 ]; + buf[ n ] = samplesIn[ 2 * n + 1 ]; } - silk_memcpy(buf, &psEnc->state_Fxx[ 1 ].sCmn.delayBuf[ MAX_ENCODER_DELAY - delay ], delay * sizeof(opus_int16)); ret += silk_resampler( &psEnc->state_Fxx[ 1 ].sCmn.resampler_state, &psEnc->state_Fxx[ 1 ].sCmn.inputBuf[ psEnc->state_Fxx[ 1 ].sCmn.inputBufIx + 2 ], buf, nSamplesFromInput ); - silk_memcpy(psEnc->state_Fxx[ 1 ].sCmn.delayBuf, buf + nSamplesFromInput + delay - MAX_ENCODER_DELAY, MAX_ENCODER_DELAY*sizeof(opus_int16)); psEnc->state_Fxx[ 1 ].sCmn.inputBufIx += nSamplesToBuffer; } else if( encControl->nChannelsAPI == 2 && encControl->nChannelsInternal == 1 ) { /* Combine left and right channels before resampling */ for( n = 0; n < nSamplesFromInput; n++ ) { - buf[ n + delay ] = (opus_int16)silk_RSHIFT_ROUND( samplesIn[ 2 * n ] + samplesIn[ 2 * n + 1 ], 1 ); + sum = samplesIn[ 2 * n ] + samplesIn[ 2 * n + 1 ]; + buf[ n ] = (opus_int16)silk_RSHIFT_ROUND( sum, 1 ); } - if(psEnc->nPrevChannelsInternal == 2 && psEnc->state_Fxx[ 0 ].sCmn.nFramesEncoded==0) { - for( n = 0; n<MAX_ENCODER_DELAY; n++ ) { - psEnc->state_Fxx[ 0 ].sCmn.delayBuf[ n ] = silk_RSHIFT(psEnc->state_Fxx[ 0 ].sCmn.delayBuf[ n ]+(opus_int32)psEnc->state_Fxx[ 1 ].sCmn.delayBuf[ n ], 1); - } - } - silk_memcpy(buf, &psEnc->state_Fxx[ 0 ].sCmn.delayBuf[ MAX_ENCODER_DELAY - delay ], delay * 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 ); /* On the first mono frame, average the results for the two resampler states */ @@ -291,15 +280,12 @@ opus_int silk_Encode( /* O Returns error co + psEnc->state_Fxx[ 1 ].sCmn.inputBuf[ psEnc->state_Fxx[ 1 ].sCmn.inputBufIx+n+2 ], 1); } } - silk_memcpy(psEnc->state_Fxx[ 0 ].sCmn.delayBuf, buf + nSamplesFromInput + delay - MAX_ENCODER_DELAY, MAX_ENCODER_DELAY*sizeof(opus_int16)); psEnc->state_Fxx[ 0 ].sCmn.inputBufIx += nSamplesToBuffer; } else { silk_assert( encControl->nChannelsAPI == 1 && encControl->nChannelsInternal == 1 ); - silk_memcpy(buf + delay, samplesIn, nSamplesFromInput*sizeof(opus_int16)); - silk_memcpy(buf, &psEnc->state_Fxx[ 0 ].sCmn.delayBuf[ MAX_ENCODER_DELAY - delay ], delay * sizeof(opus_int16)); + 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 ); - silk_memcpy(psEnc->state_Fxx[ 0 ].sCmn.delayBuf, buf + nSamplesFromInput + delay - MAX_ENCODER_DELAY, MAX_ENCODER_DELAY*sizeof(opus_int16)); psEnc->state_Fxx[ 0 ].sCmn.inputBufIx += nSamplesToBuffer; } diff --git a/silk/fixed/LTP_analysis_filter_FIX.c b/silk/fixed/LTP_analysis_filter_FIX.c index aad7b6eb..33257f84 100644 --- a/silk/fixed/LTP_analysis_filter_FIX.c +++ b/silk/fixed/LTP_analysis_filter_FIX.c @@ -69,7 +69,7 @@ void silk_LTP_analysis_filter_FIX( LTP_est = silk_RSHIFT_ROUND( LTP_est, 14 ); /* round and -> Q0*/ /* Subtract long-term prediction */ - LTP_res_ptr[ i ] = ( opus_int16 )silk_SAT16( ( opus_int32 )x_ptr[ i ] - LTP_est ); + LTP_res_ptr[ i ] = (opus_int16)silk_SAT16( (opus_int32)x_ptr[ i ] - LTP_est ); /* Scale residual */ LTP_res_ptr[ i ] = silk_SMULWB( invGains_Q16[ k ], LTP_res_ptr[ i ] ); diff --git a/silk/fixed/LTP_scale_ctrl_FIX.c b/silk/fixed/LTP_scale_ctrl_FIX.c index 0f347e3b..0aace53a 100644 --- a/silk/fixed/LTP_scale_ctrl_FIX.c +++ b/silk/fixed/LTP_scale_ctrl_FIX.c @@ -40,16 +40,11 @@ void silk_LTP_scale_ctrl_FIX( { opus_int round_loss; - /* 1st order high-pass filter */ - psEnc->HPLTPredCodGain_Q7 = silk_max_int( psEncCtrl->LTPredCodGain_Q7 - silk_RSHIFT( psEnc->prevLTPredCodGain_Q7, 1 ), 0 ) - + silk_RSHIFT( psEnc->HPLTPredCodGain_Q7, 1 ); - psEnc->prevLTPredCodGain_Q7 = psEncCtrl->LTPredCodGain_Q7; - - /* Only scale if first frame in packet */ if( condCoding == CODE_INDEPENDENTLY ) { - round_loss = psEnc->sCmn.PacketLoss_perc + psEnc->sCmn.nFramesPerPacket - 1; + /* Only scale if first frame in packet */ + round_loss = psEnc->sCmn.PacketLoss_perc + psEnc->sCmn.nFramesPerPacket; psEnc->sCmn.indices.LTP_scaleIndex = (opus_int8)silk_LIMIT( - silk_SMULWB( silk_SMULBB( round_loss, psEnc->HPLTPredCodGain_Q7 ), SILK_FIX_CONST( 0.1, 9 ) ), 0, 2 ); + silk_SMULWB( silk_SMULBB( round_loss, psEncCtrl->LTPredCodGain_Q7 ), SILK_FIX_CONST( 0.1, 9 ) ), 0, 2 ); } else { /* Default is minimum scaling */ psEnc->sCmn.indices.LTP_scaleIndex = 0; diff --git a/silk/fixed/burg_modified_FIX.c b/silk/fixed/burg_modified_FIX.c index 69d87616..fc82d368 100644 --- a/silk/fixed/burg_modified_FIX.c +++ b/silk/fixed/burg_modified_FIX.c @@ -30,9 +30,10 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #endif #include "SigProc_FIX.h" +#include "define.h" +#include "tuning_parameters.h" #define MAX_FRAME_SIZE 384 /* subfr_length * nb_subfr = ( 0.005 * 16000 + 16 ) * 4 = 384 */ -#define MAX_NB_SUBFR 4 #define QA 25 #define N_BITS_HEAD_ROOM 2 @@ -45,26 +46,22 @@ void silk_burg_modified( opus_int *res_nrg_Q, /* O Residual energy Q value */ opus_int32 A_Q16[], /* O Prediction coefficients (length order) */ const opus_int16 x[], /* I Input signal, length: nb_subfr * ( D + subfr_length ) */ + const opus_int32 minInvGain_Q30, /* I Inverse of max prediction gain */ const opus_int subfr_length, /* I Input signal subframe length (incl. D preceeding samples) */ const opus_int nb_subfr, /* I Number of subframes stacked in x */ - const opus_int32 WhiteNoiseFrac_Q32, /* I Fraction added to zero-lag autocorrelation */ const opus_int D /* I Order */ ) { - opus_int k, n, s, lz, rshifts, rshifts_extra; - opus_int32 C0, num, nrg, rc_Q31, Atmp_QA, Atmp1, tmp1, tmp2, x1, x2; + opus_int k, n, s, lz, rshifts, rshifts_extra, 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 ]; opus_int32 C_last_row[ SILK_MAX_ORDER_LPC ]; opus_int32 Af_QA[ SILK_MAX_ORDER_LPC ]; - opus_int32 CAf[ SILK_MAX_ORDER_LPC + 1 ]; opus_int32 CAb[ SILK_MAX_ORDER_LPC + 1 ]; silk_assert( subfr_length * nb_subfr <= MAX_FRAME_SIZE ); - silk_assert( nb_subfr <= MAX_NB_SUBFR ); - /* Compute autocorrelations, added over subframes */ silk_sum_sqr_shift( &C0, &rshifts, x, nb_subfr * subfr_length ); @@ -84,6 +81,7 @@ void silk_burg_modified( } rshifts += rshifts_extra; } + 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 ) { for( s = 0; s < nb_subfr; s++ ) { @@ -105,8 +103,10 @@ void silk_burg_modified( silk_memcpy( C_last_row, C_first_row, SILK_MAX_ORDER_LPC * sizeof( opus_int32 ) ); /* Initialize */ - CAb[ 0 ] = CAf[ 0 ] = C0 + silk_SMMUL( WhiteNoiseFrac_Q32, C0 ) + 1; /* Q(-rshifts)*/ + CAb[ 0 ] = CAf[ 0 ] = C0 + silk_SMMUL( SILK_FIX_CONST( FIND_LPC_COND_FAC, 32 ), C0 ) + 1; /* Q(-rshifts) */ + invGain_Q30 = 1 << 30; + reached_max_gain = 0; for( n = 0; n < D; n++ ) { /* Update first row of correlation matrix (without first element) */ /* Update last row of correlation matrix (without last element, stored in reversed order) */ @@ -115,108 +115,155 @@ void silk_burg_modified( if( rshifts > -2 ) { for( s = 0; s < nb_subfr; s++ ) { x_ptr = x + s * subfr_length; - x1 = -silk_LSHIFT32( (opus_int32)x_ptr[ n ], 16 - rshifts ); /* Q(16-rshifts)*/ - x2 = -silk_LSHIFT32( (opus_int32)x_ptr[ subfr_length - n - 1 ], 16 - rshifts ); /* Q(16-rshifts)*/ - tmp1 = silk_LSHIFT32( (opus_int32)x_ptr[ n ], QA - 16 ); /* Q(QA-16)*/ - tmp2 = silk_LSHIFT32( (opus_int32)x_ptr[ subfr_length - n - 1 ], QA - 16 ); /* Q(QA-16)*/ + x1 = -silk_LSHIFT32( (opus_int32)x_ptr[ n ], 16 - rshifts ); /* Q(16-rshifts) */ + x2 = -silk_LSHIFT32( (opus_int32)x_ptr[ subfr_length - n - 1 ], 16 - rshifts ); /* Q(16-rshifts) */ + tmp1 = silk_LSHIFT32( (opus_int32)x_ptr[ n ], QA - 16 ); /* Q(QA-16) */ + tmp2 = silk_LSHIFT32( (opus_int32)x_ptr[ subfr_length - n - 1 ], QA - 16 ); /* Q(QA-16) */ for( k = 0; k < n; k++ ) { - C_first_row[ k ] = silk_SMLAWB( C_first_row[ k ], x1, x_ptr[ n - k - 1 ] ); /* Q( -rshifts )*/ - C_last_row[ k ] = silk_SMLAWB( C_last_row[ k ], x2, x_ptr[ subfr_length - n + k ] ); /* Q( -rshifts )*/ + C_first_row[ k ] = silk_SMLAWB( C_first_row[ k ], x1, x_ptr[ n - k - 1 ] ); /* Q( -rshifts ) */ + C_last_row[ k ] = silk_SMLAWB( C_last_row[ k ], x2, x_ptr[ subfr_length - n + k ] ); /* Q( -rshifts ) */ Atmp_QA = Af_QA[ k ]; - tmp1 = silk_SMLAWB( tmp1, Atmp_QA, x_ptr[ n - k - 1 ] ); /* Q(QA-16)*/ - tmp2 = silk_SMLAWB( tmp2, Atmp_QA, x_ptr[ subfr_length - n + k ] ); /* Q(QA-16)*/ + tmp1 = silk_SMLAWB( tmp1, Atmp_QA, x_ptr[ n - k - 1 ] ); /* Q(QA-16) */ + tmp2 = silk_SMLAWB( tmp2, Atmp_QA, x_ptr[ subfr_length - n + k ] ); /* Q(QA-16) */ } - tmp1 = silk_LSHIFT32( -tmp1, 32 - QA - rshifts ); /* Q(16-rshifts)*/ - tmp2 = silk_LSHIFT32( -tmp2, 32 - QA - rshifts ); /* Q(16-rshifts)*/ + tmp1 = silk_LSHIFT32( -tmp1, 32 - QA - rshifts ); /* Q(16-rshifts) */ + tmp2 = silk_LSHIFT32( -tmp2, 32 - QA - rshifts ); /* Q(16-rshifts) */ for( k = 0; k <= n; k++ ) { - CAf[ k ] = silk_SMLAWB( CAf[ k ], tmp1, x_ptr[ n - k ] ); /* Q( -rshift )*/ - CAb[ k ] = silk_SMLAWB( CAb[ k ], tmp2, x_ptr[ subfr_length - n + k - 1 ] ); /* Q( -rshift )*/ + CAf[ k ] = silk_SMLAWB( CAf[ k ], tmp1, x_ptr[ n - k ] ); /* Q( -rshift ) */ + CAb[ k ] = silk_SMLAWB( CAb[ k ], tmp2, x_ptr[ subfr_length - n + k - 1 ] ); /* Q( -rshift ) */ } } } else { for( s = 0; s < nb_subfr; s++ ) { x_ptr = x + s * subfr_length; - x1 = -silk_LSHIFT32( (opus_int32)x_ptr[ n ], -rshifts ); /* Q( -rshifts )*/ - x2 = -silk_LSHIFT32( (opus_int32)x_ptr[ subfr_length - n - 1 ], -rshifts ); /* Q( -rshifts )*/ - tmp1 = silk_LSHIFT32( (opus_int32)x_ptr[ n ], 17 ); /* Q17*/ - tmp2 = silk_LSHIFT32( (opus_int32)x_ptr[ subfr_length - n - 1 ], 17 ); /* Q17*/ + x1 = -silk_LSHIFT32( (opus_int32)x_ptr[ n ], -rshifts ); /* Q( -rshifts ) */ + x2 = -silk_LSHIFT32( (opus_int32)x_ptr[ subfr_length - n - 1 ], -rshifts ); /* Q( -rshifts ) */ + tmp1 = silk_LSHIFT32( (opus_int32)x_ptr[ n ], 17 ); /* Q17 */ + tmp2 = silk_LSHIFT32( (opus_int32)x_ptr[ subfr_length - n - 1 ], 17 ); /* Q17 */ for( k = 0; k < n; k++ ) { - 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*/ + 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 */ } - tmp1 = -tmp1; /* Q17*/ - tmp2 = -tmp2; /* Q17*/ + tmp1 = -tmp1; /* Q17 */ + tmp2 = -tmp2; /* Q17 */ for( k = 0; k <= n; k++ ) { CAf[ k ] = silk_SMLAWW( CAf[ k ], tmp1, - silk_LSHIFT32( (opus_int32)x_ptr[ n - k ], -rshifts - 1 ) ); /* Q( -rshift )*/ + silk_LSHIFT32( (opus_int32)x_ptr[ n - k ], -rshifts - 1 ) ); /* Q( -rshift ) */ CAb[ k ] = silk_SMLAWW( CAb[ k ], tmp2, - silk_LSHIFT32( (opus_int32)x_ptr[ subfr_length - n + k - 1 ], -rshifts - 1 ) ); /* Q( -rshift )*/ + silk_LSHIFT32( (opus_int32)x_ptr[ subfr_length - n + k - 1 ], -rshifts - 1 ) ); /* Q( -rshift ) */ } } } /* Calculate nominator and denominator for the next order reflection (parcor) coefficient */ - tmp1 = C_first_row[ n ]; /* Q( -rshifts )*/ - tmp2 = C_last_row[ n ]; /* Q( -rshifts )*/ - num = 0; /* Q( -rshifts )*/ - nrg = silk_ADD32( CAb[ 0 ], CAf[ 0 ] ); /* Q( 1-rshifts )*/ + tmp1 = C_first_row[ n ]; /* Q( -rshifts ) */ + tmp2 = C_last_row[ n ]; /* Q( -rshifts ) */ + num = 0; /* Q( -rshifts ) */ + nrg = silk_ADD32( CAb[ 0 ], CAf[ 0 ] ); /* Q( 1-rshifts ) */ for( k = 0; k < n; k++ ) { Atmp_QA = Af_QA[ k ]; lz = silk_CLZ32( silk_abs( Atmp_QA ) ) - 1; lz = silk_min( 32 - QA, lz ); - Atmp1 = silk_LSHIFT32( Atmp_QA, lz ); /* Q( QA + lz )*/ + Atmp1 = silk_LSHIFT32( Atmp_QA, lz ); /* Q( QA + lz ) */ - tmp1 = silk_ADD_LSHIFT32( tmp1, silk_SMMUL( C_last_row[ n - k - 1 ], Atmp1 ), 32 - QA - lz ); /* Q( -rshifts )*/ - tmp2 = silk_ADD_LSHIFT32( tmp2, silk_SMMUL( C_first_row[ n - k - 1 ], Atmp1 ), 32 - QA - lz ); /* Q( -rshifts )*/ - num = silk_ADD_LSHIFT32( num, silk_SMMUL( CAb[ n - k ], Atmp1 ), 32 - QA - lz ); /* Q( -rshifts )*/ + tmp1 = silk_ADD_LSHIFT32( tmp1, silk_SMMUL( C_last_row[ n - k - 1 ], Atmp1 ), 32 - QA - lz ); /* Q( -rshifts ) */ + tmp2 = silk_ADD_LSHIFT32( tmp2, silk_SMMUL( C_first_row[ n - k - 1 ], Atmp1 ), 32 - QA - lz ); /* Q( -rshifts ) */ + num = silk_ADD_LSHIFT32( num, silk_SMMUL( CAb[ n - k ], Atmp1 ), 32 - QA - lz ); /* Q( -rshifts ) */ nrg = silk_ADD_LSHIFT32( nrg, silk_SMMUL( silk_ADD32( CAb[ k + 1 ], CAf[ k + 1 ] ), - Atmp1 ), 32 - QA - lz ); /* Q( 1-rshifts )*/ + Atmp1 ), 32 - QA - lz ); /* Q( 1-rshifts ) */ } - CAf[ n + 1 ] = tmp1; /* Q( -rshifts )*/ - CAb[ n + 1 ] = tmp2; /* Q( -rshifts )*/ - num = silk_ADD32( num, tmp2 ); /* Q( -rshifts )*/ - num = silk_LSHIFT32( -num, 1 ); /* Q( 1-rshifts )*/ + CAf[ n + 1 ] = tmp1; /* Q( -rshifts ) */ + CAb[ n + 1 ] = tmp2; /* Q( -rshifts ) */ + num = silk_ADD32( num, tmp2 ); /* Q( -rshifts ) */ + num = silk_LSHIFT32( -num, 1 ); /* Q( 1-rshifts ) */ /* Calculate the next order reflection (parcor) coefficient */ if( silk_abs( num ) < nrg ) { rc_Q31 = silk_DIV32_varQ( num, nrg, 31 ); } else { - /* Negative energy or ratio too high; set remaining coefficients to zero and exit loop */ - silk_memset( &Af_QA[ n ], 0, ( D - n ) * sizeof( opus_int32 ) ); - silk_assert( 0 ); - break; + rc_Q31 = ( num > 0 ) ? silk_int32_MAX : silk_int32_MIN; + } + + /* Update inverse prediction gain */ + tmp1 = ( (opus_int32)1 << 30 ) - silk_SMMUL( rc_Q31, rc_Q31 ); + tmp1 = silk_LSHIFT( silk_SMMUL( invGain_Q30, tmp1 ), 2 ); + if( tmp1 <= minInvGain_Q30 ) { + /* Max prediction gain exceeded; set reflection coefficient such that max prediction gain is exactly hit */ + tmp2 = ( 1 << 30 ) - silk_DIV32_varQ( minInvGain_Q30, invGain_Q30, 30 ); /* Q30 */ + rc_Q31 = silk_SQRT_APPROX( tmp2 ); /* Q15 */ + /* Newton-Raphson iteration */ + rc_Q31 = silk_RSHIFT32( rc_Q31 + silk_DIV32( tmp2, rc_Q31 ), 1 ); /* Q15 */ + rc_Q31 = silk_LSHIFT32( rc_Q31, 16 ); /* Q31 */ + if( num < 0 ) { + /* Ensure adjusted reflection coefficients has the original sign */ + rc_Q31 = -rc_Q31; + } + invGain_Q30 = minInvGain_Q30; + reached_max_gain = 1; + } else { + invGain_Q30 = tmp1; } /* Update the AR coefficients */ for( k = 0; k < (n + 1) >> 1; k++ ) { - tmp1 = Af_QA[ k ]; /* QA*/ - tmp2 = Af_QA[ n - k - 1 ]; /* QA*/ - Af_QA[ k ] = silk_ADD_LSHIFT32( tmp1, silk_SMMUL( tmp2, rc_Q31 ), 1 ); /* QA*/ - Af_QA[ n - k - 1 ] = silk_ADD_LSHIFT32( tmp2, silk_SMMUL( tmp1, rc_Q31 ), 1 ); /* QA*/ + tmp1 = Af_QA[ k ]; /* QA */ + tmp2 = Af_QA[ n - k - 1 ]; /* QA */ + Af_QA[ k ] = silk_ADD_LSHIFT32( tmp1, silk_SMMUL( tmp2, rc_Q31 ), 1 ); /* QA */ + Af_QA[ n - k - 1 ] = silk_ADD_LSHIFT32( tmp2, silk_SMMUL( tmp1, rc_Q31 ), 1 ); /* QA */ + } + Af_QA[ n ] = silk_RSHIFT32( rc_Q31, 31 - QA ); /* QA */ + + if( reached_max_gain ) { + /* Reached max prediction gain; set remaining coefficients to zero and exit loop */ + for( k = n + 1; k < D; k++ ) { + Af_QA[ k ] = 0; + } + break; } - Af_QA[ n ] = silk_RSHIFT32( rc_Q31, 31 - QA ); /* QA*/ /* Update C * Af and C * Ab */ for( k = 0; k <= n + 1; k++ ) { - tmp1 = CAf[ k ]; /* Q( -rshifts )*/ - tmp2 = CAb[ n - k + 1 ]; /* Q( -rshifts )*/ - CAf[ k ] = silk_ADD_LSHIFT32( tmp1, silk_SMMUL( tmp2, rc_Q31 ), 1 ); /* Q( -rshifts )*/ - CAb[ n - k + 1 ] = silk_ADD_LSHIFT32( tmp2, silk_SMMUL( tmp1, rc_Q31 ), 1 ); /* Q( -rshifts )*/ + tmp1 = CAf[ k ]; /* Q( -rshifts ) */ + tmp2 = CAb[ n - k + 1 ]; /* Q( -rshifts ) */ + CAf[ k ] = silk_ADD_LSHIFT32( tmp1, silk_SMMUL( tmp2, rc_Q31 ), 1 ); /* Q( -rshifts ) */ + CAb[ n - k + 1 ] = silk_ADD_LSHIFT32( tmp2, silk_SMMUL( tmp1, rc_Q31 ), 1 ); /* Q( -rshifts ) */ } } - /* Return residual energy */ - nrg = CAf[ 0 ]; /* Q( -rshifts )*/ - tmp1 = 1 << 16; /* Q16*/ - for( k = 0; k < D; k++ ) { - Atmp1 = silk_RSHIFT_ROUND( Af_QA[ k ], QA - 16 ); /* Q16*/ - nrg = silk_SMLAWW( nrg, CAf[ k + 1 ], Atmp1 ); /* Q( -rshifts )*/ - tmp1 = silk_SMLAWW( tmp1, Atmp1, Atmp1 ); /* Q16*/ - A_Q16[ k ] = -Atmp1; - } - *res_nrg = silk_SMLAWW( nrg, silk_SMMUL( WhiteNoiseFrac_Q32, C0 ), -tmp1 ); /* Q( -rshifts )*/ - *res_nrg_Q = -rshifts; + if( reached_max_gain ) { + for( k = 0; k < D; k++ ) { + /* Scale coefficients */ + A_Q16[ k ] = -silk_RSHIFT_ROUND( Af_QA[ k ], QA - 16 ); + } + /* Subtract energy of preceeding samples from C0 */ + 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 ), rshifts ); + } + } else { + for( s = 0; s < nb_subfr; s++ ) { + x_ptr = x + s * subfr_length; + C0 -= silk_LSHIFT32( silk_inner_prod_aligned( x_ptr, x_ptr, D ), -rshifts ); + } + } + /* Approximate residual energy */ + *res_nrg = silk_LSHIFT( silk_SMMUL( invGain_Q30, C0 ), 2 ); + *res_nrg_Q = -rshifts; + } else { + /* Return residual energy */ + nrg = CAf[ 0 ]; /* Q( -rshifts ) */ + tmp1 = 1 << 16; /* Q16 */ + for( k = 0; k < D; k++ ) { + Atmp1 = silk_RSHIFT_ROUND( Af_QA[ k ], QA - 16 ); /* Q16 */ + nrg = silk_SMLAWW( nrg, CAf[ k + 1 ], Atmp1 ); /* Q( -rshifts ) */ + tmp1 = silk_SMLAWW( tmp1, Atmp1, Atmp1 ); /* Q16 */ + A_Q16[ k ] = -Atmp1; + } + *res_nrg = silk_SMLAWW( nrg, silk_SMMUL( FIND_LPC_COND_FAC, C0 ), -tmp1 ); /* Q( -rshifts ) */ + *res_nrg_Q = -rshifts; + } } diff --git a/silk/fixed/encode_frame_FIX.c b/silk/fixed/encode_frame_FIX.c index 855abdf3..11b9c69d 100644 --- a/silk/fixed/encode_frame_FIX.c +++ b/silk/fixed/encode_frame_FIX.c @@ -36,7 +36,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. static 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_int16 xfw[], /* I Input signal */ + const opus_int32 xfw_Q10[], /* I Input signal */ opus_int condCoding /* I The type of conditional coding used so far for this frame */ ); @@ -85,7 +85,7 @@ opus_int silk_encode_frame_FIX( silk_encoder_control_FIX sEncCtrl; opus_int i, iter, maxIter, found_upper, found_lower, ret = 0; opus_int16 *x_frame, *res_pitch_frame; - opus_int16 xfw[ MAX_FRAME_LENGTH ]; + opus_int32 xfw_Q10[ MAX_FRAME_LENGTH ]; opus_int16 res_pitch[ 2 * MAX_FRAME_LENGTH + LA_PITCH_MAX ]; ec_enc sRangeEnc_copy, sRangeEnc_copy2; silk_nsq_state sNSQ_copy, sNSQ_copy2; @@ -103,7 +103,7 @@ opus_int silk_encode_frame_FIX( psEnc->sCmn.indices.Seed = psEnc->sCmn.frameCounter++ & 3; /**************************************************************/ - /* Setup Input Pointers, and insert frame in input buffer */ + /* Set up Input Pointers, and insert frame in input buffer */ /*************************************************************/ /* pointers aligned with start of frame to encode */ x_frame = psEnc->x_buf + psEnc->sCmn.ltp_mem_length; /* start of frame to encode */ @@ -143,15 +143,15 @@ opus_int silk_encode_frame_FIX( /*****************************************/ /* Prefiltering for noise shaper */ /*****************************************/ - silk_prefilter_FIX( psEnc, &sEncCtrl, xfw, x_frame ); + silk_prefilter_FIX( psEnc, &sEncCtrl, xfw_Q10, x_frame ); /****************************************/ /* Low Bitrate Redundant Encoding */ /****************************************/ - silk_LBRR_encode_FIX( psEnc, &sEncCtrl, xfw, condCoding ); + silk_LBRR_encode_FIX( psEnc, &sEncCtrl, xfw_Q10, condCoding ); /* Loop over quantizer and entropy coding to control bitrate */ - maxIter = 5; + maxIter = 6; gainMult_Q8 = SILK_FIX_CONST( 1, 8 ); found_lower = 0; found_upper = 0; @@ -183,11 +183,11 @@ 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, psEnc->sCmn.pulses, + silk_NSQ_del_dec( &psEnc->sCmn, &psEnc->sCmn.sNSQ, &psEnc->sCmn.indices, xfw_Q10, psEnc->sCmn.pulses, sEncCtrl.PredCoef_Q12[ 0 ], sEncCtrl.LTPCoef_Q14, sEncCtrl.AR2_Q13, sEncCtrl.HarmShapeGain_Q14, sEncCtrl.Tilt_Q14, sEncCtrl.LF_shp_Q14, sEncCtrl.Gains_Q16, sEncCtrl.pitchL, sEncCtrl.Lambda_Q10, sEncCtrl.LTP_scale_Q14 ); } else { - silk_NSQ( &psEnc->sCmn, &psEnc->sCmn.sNSQ, &psEnc->sCmn.indices, xfw, psEnc->sCmn.pulses, + silk_NSQ( &psEnc->sCmn, &psEnc->sCmn.sNSQ, &psEnc->sCmn.indices, xfw_Q10, psEnc->sCmn.pulses, sEncCtrl.PredCoef_Q12[ 0 ], sEncCtrl.LTPCoef_Q14, sEncCtrl.AR2_Q13, sEncCtrl.HarmShapeGain_Q14, sEncCtrl.Tilt_Q14, sEncCtrl.LF_shp_Q14, sEncCtrl.Gains_Q16, sEncCtrl.pitchL, sEncCtrl.Lambda_Q10, sEncCtrl.LTP_scale_Q14 ); } @@ -316,7 +316,7 @@ opus_int silk_encode_frame_FIX( static 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_int16 xfw[], /* I Input signal */ + const opus_int32 xfw_Q10[], /* I Input signal */ opus_int condCoding /* I The type of conditional coding used so far for this frame */ ) { @@ -355,12 +355,12 @@ static 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, + silk_NSQ_del_dec( &psEnc->sCmn, &sNSQ_LBRR, psIndices_LBRR, xfw_Q10, 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->Gains_Q16, psEncCtrl->pitchL, psEncCtrl->Lambda_Q10, psEncCtrl->LTP_scale_Q14 ); } else { - silk_NSQ( &psEnc->sCmn, &sNSQ_LBRR, psIndices_LBRR, xfw, + silk_NSQ( &psEnc->sCmn, &sNSQ_LBRR, psIndices_LBRR, xfw_Q10, 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->Gains_Q16, psEncCtrl->pitchL, psEncCtrl->Lambda_Q10, psEncCtrl->LTP_scale_Q14 ); diff --git a/silk/fixed/find_LPC_FIX.c b/silk/fixed/find_LPC_FIX.c index 46192734..ba52fa2b 100644 --- a/silk/fixed/find_LPC_FIX.c +++ b/silk/fixed/find_LPC_FIX.c @@ -34,18 +34,13 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. /* Finds LPC vector from correlations, and converts to NLSF */ void silk_find_LPC_FIX( + silk_encoder_state *psEncC, /* I/O Encoder state */ opus_int16 NLSF_Q15[], /* O NLSFs */ - opus_int8 *interpIndex, /* O NLSF interpolation index, only used for NLSF interpolation */ - const opus_int16 prev_NLSFq_Q15[], /* I previous NLSFs, only used for NLSF interpolation */ - const opus_int useInterpNLSFs, /* I Flag */ - const opus_int firstFrameAfterReset, /* I Flag */ - const opus_int LPC_order, /* I LPC order */ const opus_int16 x[], /* I Input signal */ - const opus_int subfr_length, /* I Input signal subframe length including preceeding samples */ - const opus_int nb_subfr /* I Number of subframes */ + const opus_int32 minInvGain_Q30 /* I Inverse of max prediction gain */ ) { - opus_int k; + opus_int k, subfr_length; opus_int32 a_Q16[ MAX_LPC_ORDER ]; opus_int isInterpLower, shift; opus_int32 res_nrg0, res_nrg1; @@ -56,27 +51,19 @@ void silk_find_LPC_FIX( opus_int res_nrg_interp_Q, res_nrg_Q, res_tmp_nrg_Q; opus_int16 a_tmp_Q12[ MAX_LPC_ORDER ]; opus_int16 NLSF0_Q15[ MAX_LPC_ORDER ]; - opus_int16 LPC_res[ ( MAX_FRAME_LENGTH + MAX_NB_SUBFR * MAX_LPC_ORDER ) / 2 ]; + opus_int16 LPC_res[ MAX_FRAME_LENGTH + MAX_NB_SUBFR * MAX_LPC_ORDER ]; + + subfr_length = psEncC->subfr_length + psEncC->predictLPCOrder; /* Default: no interpolation */ - *interpIndex = 4; + psEncC->indices.NLSFInterpCoef_Q2 = 4; /* Burg AR analysis for the full frame */ - silk_burg_modified( &res_nrg, &res_nrg_Q, a_Q16, x, subfr_length, nb_subfr, SILK_FIX_CONST( FIND_LPC_COND_FAC, 32 ), LPC_order ); - - if( firstFrameAfterReset ) { - silk_bwexpander_32( a_Q16, LPC_order, SILK_FIX_CONST( FIND_LPC_CHIRP_FIRST_FRAME, 16 ) ); - } else { - silk_bwexpander_32( a_Q16, LPC_order, SILK_FIX_CONST( FIND_LPC_CHIRP, 16 ) ); - } - - if( useInterpNLSFs && !firstFrameAfterReset && nb_subfr == MAX_NB_SUBFR ) { + silk_burg_modified( &res_nrg, &res_nrg_Q, a_Q16, x, minInvGain_Q30, subfr_length, psEncC->nb_subfr, psEncC->predictLPCOrder ); + if( psEncC->useInterpolatedNLSFs && !psEncC->first_frame_after_reset && psEncC->nb_subfr == MAX_NB_SUBFR ) { /* Optimal solution for last 10 ms */ - silk_burg_modified( &res_tmp_nrg, &res_tmp_nrg_Q, a_tmp_Q16, x + ( MAX_NB_SUBFR >> 1 ) * subfr_length, - subfr_length, ( MAX_NB_SUBFR >> 1 ), SILK_FIX_CONST( FIND_LPC_COND_FAC, 32 ), LPC_order ); - - silk_bwexpander_32( a_tmp_Q16, LPC_order, SILK_FIX_CONST( FIND_LPC_CHIRP, 16 ) ); + silk_burg_modified( &res_tmp_nrg, &res_tmp_nrg_Q, a_tmp_Q16, x + 2 * subfr_length, minInvGain_Q30, subfr_length, 2, psEncC->predictLPCOrder ); /* subtract residual energy here, as that's easier than adding it to the */ /* residual energy of the first 10 ms in each iteration of the search below */ @@ -92,21 +79,21 @@ void silk_find_LPC_FIX( } /* Convert to NLSFs */ - silk_A2NLSF( NLSF_Q15, a_tmp_Q16, LPC_order ); + silk_A2NLSF( NLSF_Q15, a_tmp_Q16, psEncC->predictLPCOrder ); /* Search over interpolation indices to find the one with lowest residual energy */ for( k = 3; k >= 0; k-- ) { /* Interpolate NLSFs for first half */ - silk_interpolate( NLSF0_Q15, prev_NLSFq_Q15, NLSF_Q15, k, LPC_order ); + 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, LPC_order ); + silk_NLSF2A( a_tmp_Q12, NLSF0_Q15, psEncC->predictLPCOrder ); /* Calculate residual energy with NLSF interpolation */ - silk_LPC_analysis_filter( LPC_res, x, a_tmp_Q12, 2 * subfr_length, LPC_order ); + silk_LPC_analysis_filter( LPC_res, x, a_tmp_Q12, 2 * subfr_length, psEncC->predictLPCOrder ); - silk_sum_sqr_shift( &res_nrg0, &rshift0, LPC_res + LPC_order, subfr_length - LPC_order ); - silk_sum_sqr_shift( &res_nrg1, &rshift1, LPC_res + LPC_order + subfr_length, subfr_length - LPC_order ); + silk_sum_sqr_shift( &res_nrg0, &rshift0, LPC_res + psEncC->predictLPCOrder, subfr_length - psEncC->predictLPCOrder ); + silk_sum_sqr_shift( &res_nrg1, &rshift1, LPC_res + psEncC->predictLPCOrder + subfr_length, subfr_length - psEncC->predictLPCOrder ); /* Add subframe energies from first half frame */ shift = rshift0 - rshift1; @@ -144,15 +131,15 @@ void silk_find_LPC_FIX( /* Interpolation has lower residual energy */ res_nrg = res_nrg_interp; res_nrg_Q = res_nrg_interp_Q; - *interpIndex = (opus_int8)k; + psEncC->indices.NLSFInterpCoef_Q2 = (opus_int8)k; } } } - if( *interpIndex == 4 ) { + if( psEncC->indices.NLSFInterpCoef_Q2 == 4 ) { /* NLSF interpolation is currently inactive, calculate NLSFs from full frame AR coefficients */ - silk_A2NLSF( NLSF_Q15, a_Q16, LPC_order ); + silk_A2NLSF( NLSF_Q15, a_Q16, psEncC->predictLPCOrder ); } - silk_assert( *interpIndex == 4 || ( useInterpNLSFs && !firstFrameAfterReset && nb_subfr == MAX_NB_SUBFR ) ); + silk_assert( psEncC->indices.NLSFInterpCoef_Q2 == 4 || ( psEncC->useInterpolatedNLSFs && !psEncC->first_frame_after_reset && psEncC->nb_subfr == MAX_NB_SUBFR ) ); } diff --git a/silk/fixed/find_LTP_FIX.c b/silk/fixed/find_LTP_FIX.c index daa3fef3..078d84cb 100644 --- a/silk/fixed/find_LTP_FIX.c +++ b/silk/fixed/find_LTP_FIX.c @@ -113,7 +113,7 @@ void silk_find_LTP_FIX( silk_RSHIFT( silk_SMULWB( 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_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 */ /* Limit temp such that the below scaling never wraps around */ @@ -124,7 +124,7 @@ void silk_find_LTP_FIX( 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 ) ); + 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 ] ) */ @@ -216,16 +216,16 @@ void silk_find_LTP_FIX( 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 */ + 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 */ + delta_b_Q14[ i ] = silk_max_16( b_Q14_ptr[ i ], 1638 ); /* 1638_Q14 = 0.1_Q0 */ + temp32 += delta_b_Q14[ i ]; /* Q14 */ } - temp32 = silk_DIV32( g_Q26, temp32 ); /* Q14->Q12 */ + 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 ); + 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 ); } b_Q14_ptr += LTP_ORDER; } @@ -239,6 +239,6 @@ void silk_fit_LTP( 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 ) ); + LTP_coefs_Q14[ i ] = (opus_int16)silk_SAT16( silk_RSHIFT_ROUND( LTP_coefs_Q16[ i ], 2 ) ); } } diff --git a/silk/fixed/find_pitch_lags_FIX.c b/silk/fixed/find_pitch_lags_FIX.c index 0f411581..a830cdf6 100644 --- a/silk/fixed/find_pitch_lags_FIX.c +++ b/silk/fixed/find_pitch_lags_FIX.c @@ -50,7 +50,7 @@ void silk_find_pitch_lags_FIX( opus_int16 A_Q12[ MAX_FIND_PITCH_LPC_ORDER ]; /******************************************/ - /* Setup buffer lengths etc based on Fs */ + /* Set up buffer lengths etc based on Fs */ /******************************************/ buf_len = psEnc->sCmn.la_pitch + psEnc->sCmn.frame_length + psEnc->sCmn.ltp_mem_length; @@ -97,7 +97,7 @@ void silk_find_pitch_lags_FIX( /* Convert From 32 bit Q24 to 16 bit Q12 coefs */ for( i = 0; i < psEnc->sCmn.pitchEstimationLPCOrder; i++ ) { - A_Q12[ i ] = ( opus_int16 )silk_SAT16( silk_RSHIFT( A_Q24[ i ], 12 ) ); + A_Q12[ i ] = (opus_int16)silk_SAT16( silk_RSHIFT( A_Q24[ i ], 12 ) ); } /* Do BWE */ @@ -122,7 +122,7 @@ void silk_find_pitch_lags_FIX( /*****************************************/ if( silk_pitch_analysis_core( res, psEncCtrl->pitchL, &psEnc->sCmn.indices.lagIndex, &psEnc->sCmn.indices.contourIndex, &psEnc->LTPCorr_Q15, psEnc->sCmn.prevLag, psEnc->sCmn.pitchEstimationThreshold_Q16, - ( opus_int16 )thrhld_Q15, psEnc->sCmn.fs_kHz, psEnc->sCmn.pitchEstimationComplexity, psEnc->sCmn.nb_subfr ) == 0 ) + (opus_int16)thrhld_Q15, psEnc->sCmn.fs_kHz, psEnc->sCmn.pitchEstimationComplexity, psEnc->sCmn.nb_subfr ) == 0 ) { psEnc->sCmn.indices.signalType = TYPE_VOICED; } else { diff --git a/silk/fixed/find_pred_coefs_FIX.c b/silk/fixed/find_pred_coefs_FIX.c index 27e0c2c3..5f67e638 100644 --- a/silk/fixed/find_pred_coefs_FIX.c +++ b/silk/fixed/find_pred_coefs_FIX.c @@ -45,7 +45,7 @@ void silk_find_pred_coefs_FIX( opus_int16 NLSF_Q15[ MAX_LPC_ORDER ]; const opus_int16 *x_ptr; opus_int16 *x_pre_ptr, LPC_in_pre[ MAX_NB_SUBFR * MAX_LPC_ORDER + MAX_FRAME_LENGTH ]; - opus_int32 tmp, min_gain_Q16; + opus_int32 tmp, min_gain_Q16, minInvGain_Q30; opus_int LTP_corrs_rshift[ MAX_NB_SUBFR ]; /* weighting for weighted least squares */ @@ -111,10 +111,18 @@ void silk_find_pred_coefs_FIX( psEncCtrl->LTPredCodGain_Q7 = 0; } + /* Limit on total predictive coding gain */ + if( psEnc->sCmn.first_frame_after_reset ) { + minInvGain_Q30 = SILK_FIX_CONST( 1.0f / MAX_PREDICTION_POWER_GAIN_AFTER_RESET, 30 ); + } else { + minInvGain_Q30 = silk_log2lin( silk_SMLAWB( 16 << 7, psEncCtrl->LTPredCodGain_Q7, SILK_FIX_CONST( 1.0 / 3, 16 ) ) ); /* Q16 */ + minInvGain_Q30 = silk_DIV32_varQ( minInvGain_Q30, + silk_SMULWW( SILK_FIX_CONST( MAX_PREDICTION_POWER_GAIN, 0 ), + silk_SMLAWB( SILK_FIX_CONST( 0.1, 18 ), SILK_FIX_CONST( 0.9, 18 ), psEncCtrl->coding_quality_Q14 ) ), 14 ); + } + /* LPC_in_pre contains the LTP-filtered input for voiced, and the unfiltered input for unvoiced */ - silk_find_LPC_FIX( NLSF_Q15, &psEnc->sCmn.indices.NLSFInterpCoef_Q2, psEnc->sCmn.prev_NLSFq_Q15, - psEnc->sCmn.useInterpolatedNLSFs, psEnc->sCmn.first_frame_after_reset, psEnc->sCmn.predictLPCOrder, - LPC_in_pre, psEnc->sCmn.subfr_length + psEnc->sCmn.predictLPCOrder, psEnc->sCmn.nb_subfr ); + silk_find_LPC_FIX( &psEnc->sCmn, NLSF_Q15, LPC_in_pre, minInvGain_Q30 ); /* Quantize LSFs */ silk_process_NLSFs( &psEnc->sCmn, psEncCtrl->PredCoef_Q12, NLSF_Q15, psEnc->sCmn.prev_NLSFq_Q15 ); diff --git a/silk/fixed/main_FIX.h b/silk/fixed/main_FIX.h index 30782e12..9f178975 100644 --- a/silk/fixed/main_FIX.h +++ b/silk/fixed/main_FIX.h @@ -92,7 +92,7 @@ opus_int silk_control_encoder( void silk_prefilter_FIX( silk_encoder_state_FIX *psEnc, /* I/O Encoder state */ const silk_encoder_control_FIX *psEncCtrl, /* I Encoder control */ - opus_int16 xw[], /* O Weighted signal */ + opus_int32 xw_Q10[], /* O Weighted signal */ const opus_int16 x[] /* I Speech signal */ ); @@ -146,15 +146,10 @@ void silk_find_pred_coefs_FIX( /* LPC analysis */ void silk_find_LPC_FIX( + silk_encoder_state *psEncC, /* I/O Encoder state */ opus_int16 NLSF_Q15[], /* O NLSFs */ - opus_int8 *interpIndex, /* O NLSF interpolation index, only used for NLSF interpolation */ - const opus_int16 prev_NLSFq_Q15[], /* I previous NLSFs, only used for NLSF interpolation */ - const opus_int useInterpNLSFs, /* I Flag */ - const opus_int firstFrameAfterReset, /* I Flag */ - const opus_int LPC_order, /* I LPC order */ const opus_int16 x[], /* I Input signal */ - const opus_int subfr_length, /* I Input signal subframe length including preceeding samples */ - const opus_int nb_subfr /* I Number of subframes */ + const opus_int32 minInvGain_Q30 /* I Inverse of max prediction gain */ ); /* LTP analysis */ diff --git a/silk/fixed/noise_shape_analysis_FIX.c b/silk/fixed/noise_shape_analysis_FIX.c index d85c8ed9..94c5bb26 100644 --- a/silk/fixed/noise_shape_analysis_FIX.c +++ b/silk/fixed/noise_shape_analysis_FIX.c @@ -166,12 +166,12 @@ void silk_noise_shape_analysis_FIX( SNR_adj_dB_Q7 = psEnc->sCmn.SNR_dB_Q7; /* Input quality is the average of the quality in the lowest two VAD bands */ - psEncCtrl->input_quality_Q14 = ( opus_int )silk_RSHIFT( ( opus_int32 )psEnc->sCmn.input_quality_bands_Q15[ 0 ] + psEncCtrl->input_quality_Q14 = ( opus_int )silk_RSHIFT( (opus_int32)psEnc->sCmn.input_quality_bands_Q15[ 0 ] + psEnc->sCmn.input_quality_bands_Q15[ 1 ], 2 ); /* Coding quality level, between 0.0_Q0 and 1.0_Q0, but in Q14 */ psEncCtrl->coding_quality_Q14 = silk_RSHIFT( silk_sigm_Q15( silk_RSHIFT_ROUND( SNR_adj_dB_Q7 - - SILK_FIX_CONST( 18.0, 7 ), 4 ) ), 1 ); + SILK_FIX_CONST( 20.0, 7 ), 4 ) ), 1 ); /* Reduce coding SNR during low speech activity */ if( psEnc->sCmn.useCBR == 0 ) { @@ -326,8 +326,8 @@ void silk_noise_shape_analysis_FIX( silk_bwexpander_32( AR1_Q24, psEnc->sCmn.shapingLPCOrder, BWExp1_Q16 ); /* Ratio of prediction gains, in energy domain */ - silk_LPC_inverse_pred_gain_Q24( &pre_nrg_Q30, AR2_Q24, psEnc->sCmn.shapingLPCOrder ); - silk_LPC_inverse_pred_gain_Q24( &nrg, AR1_Q24, psEnc->sCmn.shapingLPCOrder ); + 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 ); diff --git a/silk/fixed/pitch_analysis_core_FIX.c b/silk/fixed/pitch_analysis_core_FIX.c index f76c611a..7471eb5a 100644 --- a/silk/fixed/pitch_analysis_core_FIX.c +++ b/silk/fixed/pitch_analysis_core_FIX.c @@ -116,7 +116,7 @@ opus_int silk_pitch_analysis_core( /* O Voicing estimate: 0 silk_assert( search_thres1_Q16 >= 0 && search_thres1_Q16 <= (1<<16) ); silk_assert( search_thres2_Q15 >= 0 && search_thres2_Q15 <= (1<<15) ); - /* Setup frame lengths max / min lag for the sampling frequency */ + /* Set up frame lengths max / min lag for the sampling frequency */ frame_length = ( PE_LTP_MEM_LENGTH_MS + nb_subfr * PE_SUBFR_LENGTH_MS ) * Fs_kHz; frame_length_4kHz = ( PE_LTP_MEM_LENGTH_MS + nb_subfr * PE_SUBFR_LENGTH_MS ) * 4; frame_length_8kHz = ( PE_LTP_MEM_LENGTH_MS + nb_subfr * PE_SUBFR_LENGTH_MS ) * 8; @@ -375,7 +375,7 @@ opus_int silk_pitch_analysis_core( /* O Voicing estimate: 0 prevLag_log2_Q7 = 0; } silk_assert( search_thres2_Q15 == silk_SAT16( search_thres2_Q15 ) ); - /* Setup stage 2 codebook based on number of subframes */ + /* Set up stage 2 codebook based on number of subframes */ if( nb_subfr == PE_MAX_NB_SUBFR ) { cbk_size = PE_NB_CBKS_STAGE2_EXT; Lag_CB_ptr = &silk_CB_lags_stage2[ 0 ][ 0 ]; @@ -500,7 +500,7 @@ opus_int silk_pitch_analysis_core( /* O Voicing estimate: 0 silk_assert( lag == silk_SAT16( lag ) ); contour_bias_Q20 = silk_DIV32_16( SILK_FIX_CONST( PE_FLATCONTOUR_BIAS, 20 ), lag ); - /* Setup cbk parameters acording to complexity setting and frame length */ + /* Set up codebook parameters acording to complexity setting and frame length */ if( nb_subfr == PE_MAX_NB_SUBFR ) { nb_cbk_search = (opus_int)silk_nb_cbk_searchs_stage3[ complexity ]; cbk_size = PE_NB_CBKS_STAGE3_MAX; diff --git a/silk/fixed/prefilter_FIX.c b/silk/fixed/prefilter_FIX.c index 437899fb..fe663fa8 100644 --- a/silk/fixed/prefilter_FIX.c +++ b/silk/fixed/prefilter_FIX.c @@ -36,7 +36,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 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_int16 xw[], /* O prefiltered signal */ + opus_int32 pxw_Q10[], /* 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 */ @@ -46,7 +46,7 @@ static inline void silk_prefilt_FIX( void silk_warped_LPC_analysis_filter_FIX( opus_int32 state[], /* I/O State [order + 1] */ - opus_int16 res[], /* O Residual signal [length] */ + 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 */ @@ -81,14 +81,14 @@ void silk_warped_LPC_analysis_filter_FIX( } state[ order ] = tmp1; acc_Q11 = silk_SMLAWB( acc_Q11, tmp1, coef_Q13[ order - 1 ] ); - res[ n ] = ( opus_int16 )silk_SAT16( ( opus_int32 )input[ n ] - silk_RSHIFT_ROUND( acc_Q11, 11 ) ); + 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_int16 xw[], /* O Weighted signal */ + opus_int32 xw_Q10[], /* O Weighted signal */ const opus_int16 x[] /* I Speech signal */ ) { @@ -97,16 +97,16 @@ void silk_prefilter_FIX( opus_int32 tmp_32; const opus_int16 *AR1_shp_Q13; const opus_int16 *px; - opus_int16 *pxw; + opus_int32 *pxw_Q10; opus_int HarmShapeGain_Q12, Tilt_Q14; opus_int32 HarmShapeFIRPacked_Q12, LF_shp_Q14; - opus_int32 x_filt_Q12[ MAX_FRAME_LENGTH / MAX_NB_SUBFR ]; - opus_int16 st_res[ ( MAX_FRAME_LENGTH / MAX_NB_SUBFR ) + MAX_LPC_ORDER ]; - opus_int16 B_Q12[ 2 ]; + opus_int32 x_filt_Q12[ MAX_SUB_FRAME_LENGTH ]; + opus_int32 st_res_Q2[ MAX_SUB_FRAME_LENGTH + MAX_LPC_ORDER ]; + opus_int16 B_Q10[ 2 ]; - /* Setup pointers */ + /* Set up pointers */ px = x; - pxw = xw; + pxw_Q10 = xw_Q10; lag = P->lagPrev; for( k = 0; k < psEnc->sCmn.nb_subfr; k++ ) { /* Update Variables that change per sub frame */ @@ -118,34 +118,33 @@ void silk_prefilter_FIX( HarmShapeGain_Q12 = silk_SMULWB( 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 ); + 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, AR1_shp_Q13, px, + 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 ); - /* reduce (mainly) low frequencies during harmonic emphasis */ - B_Q12[ 0 ] = silk_RSHIFT_ROUND( psEncCtrl->GainsPre_Q14[ k ], 2 ); + /* 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, 12 ); /* Q12 */ - B_Q12[ 1 ]= silk_SAT16( tmp_32 ); - - x_filt_Q12[ 0 ] = silk_SMLABB( silk_SMULBB( st_res[ 0 ], B_Q12[ 0 ] ), P->sHarmHP, B_Q12[ 1 ] ); + 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_SMLABB( silk_SMULBB( 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_SMLABB( silk_SMULBB( st_res[ j ], B_Q12[ 0 ] ), st_res[ j - 1 ], B_Q12[ 1 ] ); + x_filt_Q12[ j ] = silk_SMLABB( silk_SMULBB( st_res_Q2[ j ], B_Q10[ 0 ] ), st_res_Q2[ j - 1 ], B_Q10[ 1 ] ); } - P->sHarmHP = st_res[ psEnc->sCmn.subfr_length - 1 ]; + P->sHarmHP_Q2 = st_res_Q2[ psEnc->sCmn.subfr_length - 1 ]; - silk_prefilt_FIX( P, x_filt_Q12, pxw, HarmShapeFIRPacked_Q12, Tilt_Q14, + silk_prefilt_FIX( P, x_filt_Q12, pxw_Q10, HarmShapeFIRPacked_Q12, Tilt_Q14, LF_shp_Q14, lag, psEnc->sCmn.subfr_length ); px += psEnc->sCmn.subfr_length; - pxw += psEnc->sCmn.subfr_length; + pxw_Q10 += psEnc->sCmn.subfr_length; } P->lagPrev = psEncCtrl->pitchL[ psEnc->sCmn.nb_subfr - 1 ]; @@ -155,7 +154,7 @@ void silk_prefilter_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_int16 xw[], /* O prefiltered signal */ + opus_int32 xw_Q10[], /* 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 */ @@ -193,9 +192,9 @@ static inline void silk_prefilt_FIX( 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 ) ); + LTP_shp_buf[ LTP_shp_buf_idx ] = (opus_int16)silk_SAT16( silk_RSHIFT_ROUND( sLF_MA_shp_Q12, 12 ) ); - xw[i] = ( opus_int16 )silk_SAT16( silk_RSHIFT_ROUND( silk_SUB32( sLF_MA_shp_Q12, n_LTP_Q12 ), 12 ) ); + xw_Q10[i] = silk_RSHIFT_ROUND( silk_SUB32( sLF_MA_shp_Q12, n_LTP_Q12 ), 2 ); } /* Copy temp variable back to state */ diff --git a/silk/fixed/residual_energy16_FIX.c b/silk/fixed/residual_energy16_FIX.c index bbd10275..044469f0 100644 --- a/silk/fixed/residual_energy16_FIX.c +++ b/silk/fixed/residual_energy16_FIX.c @@ -57,7 +57,7 @@ opus_int32 silk_residual_energy16_covar_FIX( c_max = 0; for( i = 0; i < D; i++ ) { - c_max = silk_max_32( c_max, silk_abs( ( opus_int32 )c[ i ] ) ); + c_max = silk_max_32( c_max, silk_abs( (opus_int32)c[ i ] ) ); } Qxtra = silk_min_int( Qxtra, silk_CLZ32( c_max ) - 17 ); diff --git a/silk/fixed/schur_FIX.c b/silk/fixed/schur_FIX.c index 14e45780..f037f3f7 100644 --- a/silk/fixed/schur_FIX.c +++ b/silk/fixed/schur_FIX.c @@ -76,7 +76,7 @@ opus_int32 silk_schur( /* O Returns residual ene rc_tmp_Q15 = silk_SAT16( rc_tmp_Q15 ); /* Store */ - rc_Q15[ k ] = ( opus_int16 )rc_tmp_Q15; + rc_Q15[ k ] = (opus_int16)rc_tmp_Q15; /* Update correlations */ for( n = 0; n < order - k; n++ ) { diff --git a/silk/fixed/structs_FIX.h b/silk/fixed/structs_FIX.h index 4569492f..8ba14fa1 100644 --- a/silk/fixed/structs_FIX.h +++ b/silk/fixed/structs_FIX.h @@ -56,7 +56,7 @@ typedef struct { opus_int sLTP_shp_buf_idx; opus_int32 sLF_AR_shp_Q12; opus_int32 sLF_MA_shp_Q12; - opus_int sHarmHP; + opus_int32 sHarmHP_Q2; opus_int32 rand_seed; opus_int lagPrev; } silk_prefilter_state_FIX; @@ -72,10 +72,6 @@ typedef struct { /* 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 */ - - /* Parameters For LTP scaling Control */ - opus_int prevLTPredCodGain_Q7; - opus_int HPLTPredCodGain_Q7; } silk_encoder_state_FIX; /************************/ diff --git a/silk/fixed/warped_autocorrelation_FIX.c b/silk/fixed/warped_autocorrelation_FIX.c index c79c04f1..92912e5f 100644 --- a/silk/fixed/warped_autocorrelation_FIX.c +++ b/silk/fixed/warped_autocorrelation_FIX.c @@ -55,7 +55,7 @@ void silk_warped_autocorrelation_FIX( /* Loop over samples */ for( n = 0; n < length; n++ ) { - tmp1_QS = silk_LSHIFT32( ( opus_int32 )input[ n ], QS ); + tmp1_QS = silk_LSHIFT32( (opus_int32)input[ n ], QS ); /* Loop over allpass sections */ for( i = 0; i < order; i += 2 ) { /* Output of allpass section */ @@ -77,11 +77,11 @@ void silk_warped_autocorrelation_FIX( silk_assert( *scale >= -30 && *scale <= 12 ); if( lsh >= 0 ) { for( i = 0; i < order + 1; i++ ) { - corr[ i ] = ( opus_int32 )silk_CHECK_FIT32( silk_LSHIFT64( corr_QC[ i ], lsh ) ); + corr[ i ] = (opus_int32)silk_CHECK_FIT32( silk_LSHIFT64( corr_QC[ i ], lsh ) ); } } else { for( i = 0; i < order + 1; i++ ) { - corr[ i ] = ( opus_int32 )silk_CHECK_FIT32( silk_RSHIFT64( corr_QC[ i ], -lsh ) ); + corr[ i ] = (opus_int32)silk_CHECK_FIT32( silk_RSHIFT64( corr_QC[ i ], -lsh ) ); } } silk_assert( corr_QC[ 0 ] >= 0 ); /* If breaking, decrease QC*/ diff --git a/silk/float/LPC_inv_pred_gain_FLP.c b/silk/float/LPC_inv_pred_gain_FLP.c index d7a5d87e..59ed7d4c 100644 --- a/silk/float/LPC_inv_pred_gain_FLP.c +++ b/silk/float/LPC_inv_pred_gain_FLP.c @@ -37,29 +37,28 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. /* compute inverse of LPC prediction gain, and */ /* test if LPC coefficients are stable (all poles within unit circle) */ /* this code is based on silk_a2k_FLP() */ -opus_int silk_LPC_inverse_pred_gain_FLP( /* O returns 1 if unstable, otherwise 0 */ - silk_float *invGain, /* O inverse prediction gain, energy domain */ +silk_float silk_LPC_inverse_pred_gain_FLP( /* O return inverse prediction gain, energy domain */ const silk_float *A, /* I prediction coefficients [order] */ opus_int32 order /* I prediction order */ ) { opus_int k, n; - double rc, rc_mult1, rc_mult2; + double invGain, rc, rc_mult1, rc_mult2; silk_float Atmp[ 2 ][ SILK_MAX_ORDER_LPC ]; silk_float *Aold, *Anew; Anew = Atmp[ order & 1 ]; silk_memcpy( Anew, A, order * sizeof(silk_float) ); - *invGain = 1.0f; + invGain = 1.0; for( k = order - 1; k > 0; k-- ) { rc = -Anew[ k ]; if( rc > RC_THRESHOLD || rc < -RC_THRESHOLD ) { - return 1; + return 0.0f; } rc_mult1 = 1.0f - rc * rc; rc_mult2 = 1.0f / rc_mult1; - *invGain *= (silk_float)rc_mult1; + invGain *= rc_mult1; /* swap pointers */ Aold = Anew; Anew = Atmp[ k & 1 ]; @@ -69,9 +68,9 @@ opus_int silk_LPC_inverse_pred_gain_FLP( /* O returns 1 if unstable, other } rc = -Anew[ 0 ]; if( rc > RC_THRESHOLD || rc < -RC_THRESHOLD ) { - return 1; + return 0.0f; } rc_mult1 = 1.0f - rc * rc; - *invGain *= (silk_float)rc_mult1; - return 0; + invGain *= rc_mult1; + return (silk_float)invGain; } diff --git a/silk/float/LTP_scale_ctrl_FLP.c b/silk/float/LTP_scale_ctrl_FLP.c index ebfdbf49..2354ebe9 100644 --- a/silk/float/LTP_scale_ctrl_FLP.c +++ b/silk/float/LTP_scale_ctrl_FLP.c @@ -39,19 +39,14 @@ void silk_LTP_scale_ctrl_FLP( { opus_int round_loss; - /* 1st order high-pass filter */ - /*g_HP(n) = g(n) - 0.5 * g(n-1) + 0.5 * g_HP(n-1);*/ - psEnc->HPLTPredCodGain = silk_max_float( psEncCtrl->LTPredCodGain - 0.5f * psEnc->prevLTPredCodGain, 0.0f ) - + 0.5f * psEnc->HPLTPredCodGain; - psEnc->prevLTPredCodGain = psEncCtrl->LTPredCodGain; - - /* Only scale if first frame in packet */ if( condCoding == CODE_INDEPENDENTLY ) { + /* Only scale if first frame in packet */ round_loss = psEnc->sCmn.PacketLoss_perc + psEnc->sCmn.nFramesPerPacket; - psEnc->sCmn.indices.LTP_scaleIndex = (opus_int8)silk_LIMIT( round_loss * psEnc->HPLTPredCodGain * 0.1f, 0.0f, 2.0f ); + psEnc->sCmn.indices.LTP_scaleIndex = (opus_int8)silk_LIMIT( round_loss * psEncCtrl->LTPredCodGain * 0.1f, 0.0f, 2.0f ); } else { /* Default is minimum scaling */ psEnc->sCmn.indices.LTP_scaleIndex = 0; } + psEncCtrl->LTP_scale = (silk_float)silk_LTPScales_table_Q14[ psEnc->sCmn.indices.LTP_scaleIndex ] / 16384.0f; } diff --git a/silk/float/SigProc_FLP.h b/silk/float/SigProc_FLP.h index 7b2ba089..0d70ca1b 100644 --- a/silk/float/SigProc_FLP.h +++ b/silk/float/SigProc_FLP.h @@ -50,8 +50,7 @@ void silk_bwexpander_FLP( /* compute inverse of LPC prediction gain, and */ /* test if LPC coefficients are stable (all poles within unit circle) */ /* this code is based on silk_FLP_a2k() */ -opus_int silk_LPC_inverse_pred_gain_FLP( /* O returns 1 if unstable, otherwise 0 */ - silk_float *invGain, /* O inverse prediction gain, energy domain */ +silk_float silk_LPC_inverse_pred_gain_FLP( /* O return inverse prediction gain, energy domain */ const silk_float *A, /* I prediction coefficients [order] */ opus_int32 order /* I prediction order */ ); @@ -108,9 +107,9 @@ void silk_insertion_sort_decreasing_FLP( silk_float silk_burg_modified_FLP( /* O returns residual energy */ silk_float A[], /* O prediction coefficients (length order) */ const silk_float x[], /* I input signal, length: nb_subfr*(D+L_sub) */ + const silk_float minInvGain, /* I minimum inverse prediction gain */ const opus_int subfr_length, /* I input signal subframe length (incl. D preceeding samples) */ const opus_int nb_subfr, /* I number of subframes stacked in x */ - const silk_float WhiteNoiseFrac, /* I fraction added to zero-lag autocorrelation */ const opus_int D /* I order */ ); diff --git a/silk/float/burg_modified_FLP.c b/silk/float/burg_modified_FLP.c index b5862a54..2f6edfae 100644 --- a/silk/float/burg_modified_FLP.c +++ b/silk/float/burg_modified_FLP.c @@ -30,29 +30,29 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #endif #include "SigProc_FLP.h" +#include "tuning_parameters.h" +#include "define.h" #define MAX_FRAME_SIZE 384 /* subfr_length * nb_subfr = ( 0.005 * 16000 + 16 ) * 4 = 384*/ -#define MAX_NB_SUBFR 4 /* Compute reflection coefficients from input signal */ silk_float silk_burg_modified_FLP( /* O returns residual energy */ silk_float A[], /* O prediction coefficients (length order) */ const silk_float x[], /* I input signal, length: nb_subfr*(D+L_sub) */ + const silk_float minInvGain, /* I minimum inverse prediction gain */ const opus_int subfr_length, /* I input signal subframe length (incl. D preceeding samples) */ const opus_int nb_subfr, /* I number of subframes stacked in x */ - const silk_float WhiteNoiseFrac, /* I fraction added to zero-lag autocorrelation */ const opus_int D /* I order */ ) { - opus_int k, n, s; - double C0, num, nrg_f, nrg_b, rc, Atmp, tmp1, tmp2; + opus_int k, n, s, reached_max_gain; + double C0, invGain, num, nrg_f, nrg_b, rc, Atmp, tmp1, tmp2; const silk_float *x_ptr; - double C_first_row[ SILK_MAX_ORDER_LPC ], C_last_row[ SILK_MAX_ORDER_LPC ]; - double CAf[ SILK_MAX_ORDER_LPC + 1 ], CAb[ SILK_MAX_ORDER_LPC + 1 ]; - double Af[ SILK_MAX_ORDER_LPC ]; + double C_first_row[ SILK_MAX_ORDER_LPC ], C_last_row[ SILK_MAX_ORDER_LPC ]; + 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 ); - silk_assert( nb_subfr <= MAX_NB_SUBFR ); /* Compute autocorrelations, added over subframes */ C0 = silk_energy_FLP( x, nb_subfr * subfr_length ); @@ -66,8 +66,9 @@ silk_float silk_burg_modified_FLP( /* O returns residual energy silk_memcpy( C_last_row, C_first_row, SILK_MAX_ORDER_LPC * sizeof( double ) ); /* Initialize */ - CAb[ 0 ] = CAf[ 0 ] = C0 + WhiteNoiseFrac * C0 + 1e-9f; - + CAb[ 0 ] = CAf[ 0 ] = C0 + FIND_LPC_COND_FAC * C0 + 1e-9f; + invGain = 1.0f; + reached_max_gain = 0; for( n = 0; n < D; n++ ) { /* Update first row of correlation matrix (without first element) */ /* Update last row of correlation matrix (without last element, stored in reversed order) */ @@ -93,7 +94,7 @@ silk_float silk_burg_modified_FLP( /* O returns residual energy tmp2 = C_last_row[ n ]; for( k = 0; k < n; k++ ) { Atmp = Af[ k ]; - tmp1 += C_last_row[ n - k - 1 ] * Atmp; + tmp1 += C_last_row[ n - k - 1 ] * Atmp; tmp2 += C_first_row[ n - k - 1 ] * Atmp; } CAf[ n + 1 ] = tmp1; @@ -116,6 +117,21 @@ silk_float silk_burg_modified_FLP( /* O returns residual energy rc = -2.0 * num / ( nrg_f + nrg_b ); silk_assert( rc > -1.0 && rc < 1.0 ); + /* Update inverse prediction gain */ + tmp1 = invGain * ( 1.0 - rc * rc ); + if( tmp1 <= minInvGain ) { + /* Max prediction gain exceeded; set reflection coefficient such that max prediction gain is exactly hit */ + rc = sqrt( 1.0 - minInvGain / invGain ); + if( num > 0 ) { + /* Ensure adjusted reflection coefficients has the original sign */ + rc = -rc; + } + invGain = minInvGain; + reached_max_gain = 1; + } else { + invGain = tmp1; + } + /* Update the AR coefficients */ for( k = 0; k < (n + 1) >> 1; k++ ) { tmp1 = Af[ k ]; @@ -125,6 +141,14 @@ silk_float silk_burg_modified_FLP( /* O returns residual energy } Af[ n ] = rc; + if( reached_max_gain ) { + /* Reached max prediction gain; set remaining coefficients to zero and exit loop */ + for( k = n + 1; k < D; k++ ) { + Af[ k ] = 0.0; + } + break; + } + /* Update C * Af and C * Ab */ for( k = 0; k <= n + 1; k++ ) { tmp1 = CAf[ k ]; @@ -133,16 +157,30 @@ silk_float silk_burg_modified_FLP( /* O returns residual energy } } - /* Return residual energy */ - nrg_f = CAf[ 0 ]; - tmp1 = 1.0; - for( k = 0; k < D; k++ ) { - Atmp = Af[ k ]; - nrg_f += CAf[ k + 1 ] * Atmp; - tmp1 += Atmp * Atmp; - A[ k ] = (silk_float)(-Atmp); + if( reached_max_gain ) { + /* Convert to silk_float */ + for( k = 0; k < D; k++ ) { + A[ k ] = (silk_float)( -Af[ k ] ); + } + /* Subtract energy of preceeding samples from C0 */ + for( s = 0; s < nb_subfr; s++ ) { + C0 -= silk_energy_FLP( x + s * subfr_length, D ); + } + /* Approximate residual energy */ + nrg_f = C0 * invGain; + } else { + /* Compute residual energy and store coefficients as silk_float */ + nrg_f = CAf[ 0 ]; + tmp1 = 1.0; + for( k = 0; k < D; k++ ) { + Atmp = Af[ k ]; + nrg_f += CAf[ k + 1 ] * Atmp; + tmp1 += Atmp * Atmp; + A[ k ] = (silk_float)(-Atmp); + } + nrg_f -= FIND_LPC_COND_FAC * C0 * tmp1; } - nrg_f -= WhiteNoiseFrac * C0 * tmp1; + /* Return residual energy */ return (silk_float)nrg_f; } diff --git a/silk/float/encode_frame_FLP.c b/silk/float/encode_frame_FLP.c index faae848c..facb4104 100644 --- a/silk/float/encode_frame_FLP.c +++ b/silk/float/encode_frame_FLP.c @@ -104,8 +104,8 @@ opus_int silk_encode_frame_FLP( psEnc->sCmn.indices.Seed = psEnc->sCmn.frameCounter++ & 3; /**************************************************************/ - /* Setup Input Pointers, and insert frame in input buffer */ - /*************************************************************/ + /* Set up Input Pointers, and insert frame in input buffer */ + /**************************************************************/ /* pointers aligned with start of frame to encode */ x_frame = psEnc->x_buf + psEnc->sCmn.ltp_mem_length; /* start of frame to encode */ res_pitch_frame = res_pitch + psEnc->sCmn.ltp_mem_length; /* start of pitch LPC residual frame */ @@ -157,7 +157,7 @@ opus_int silk_encode_frame_FLP( silk_LBRR_encode_FLP( psEnc, &sEncCtrl, xfw, condCoding ); /* Loop over quantizer and entroy coding to control bitrate */ - maxIter = 5; + maxIter = 6; gainMult_Q8 = SILK_FIX_CONST( 1, 8 ); found_lower = 0; found_upper = 0; diff --git a/silk/float/find_LPC_FLP.c b/silk/float/find_LPC_FLP.c index 23de2e73..940a8c0a 100644 --- a/silk/float/find_LPC_FLP.c +++ b/silk/float/find_LPC_FLP.c @@ -29,73 +29,63 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "config.h" #endif +#include "define.h" #include "main_FLP.h" #include "tuning_parameters.h" +/* LPC analysis */ void silk_find_LPC_FLP( + silk_encoder_state *psEncC, /* I/O Encoder state */ opus_int16 NLSF_Q15[], /* O NLSFs */ - opus_int8 *interpIndex, /* O NLSF interp. index for NLSF interp. */ - const opus_int16 prev_NLSFq_Q15[], /* I Previous NLSFs, for NLSF interpolation */ - const opus_int useInterpNLSFs, /* I Flag */ - const opus_int firstFrameAfterReset, /* I Flag */ - const opus_int LPC_order, /* I LPC order */ const silk_float x[], /* I Input signal */ - const opus_int subfr_length, /* I Subframe length incl preceeding samples */ - const opus_int nb_subfr /* I Number of subframes */ + const silk_float minInvGain /* I Inverse of max prediction gain */ ) { - opus_int k; - silk_float a[ MAX_LPC_ORDER ]; + opus_int k, subfr_length; + silk_float a[ MAX_LPC_ORDER ]; /* Used only for NLSF interpolation */ - double res_nrg, res_nrg_2nd, res_nrg_interp; - opus_int16 NLSF0_Q15[ MAX_LPC_ORDER ]; - silk_float a_tmp[ MAX_LPC_ORDER ]; - silk_float LPC_res[ ( MAX_FRAME_LENGTH + MAX_NB_SUBFR * MAX_LPC_ORDER ) / 2 ]; + silk_float res_nrg, res_nrg_2nd, res_nrg_interp; + opus_int16 NLSF0_Q15[ MAX_LPC_ORDER ]; + silk_float a_tmp[ MAX_LPC_ORDER ]; + silk_float LPC_res[ MAX_FRAME_LENGTH + MAX_NB_SUBFR * MAX_LPC_ORDER ]; + + subfr_length = psEncC->subfr_length + psEncC->predictLPCOrder; /* Default: No interpolation */ - *interpIndex = 4; + psEncC->indices.NLSFInterpCoef_Q2 = 4; /* Burg AR analysis for the full frame */ - res_nrg = silk_burg_modified_FLP( a, x, subfr_length, nb_subfr, FIND_LPC_COND_FAC, LPC_order ); - - if( firstFrameAfterReset ) { - silk_bwexpander_FLP( a, LPC_order, FIND_LPC_CHIRP_FIRST_FRAME ); - } else { - silk_bwexpander_FLP( a_tmp, LPC_order, FIND_LPC_CHIRP ); - } + res_nrg = silk_burg_modified_FLP( a, x, minInvGain, subfr_length, psEncC->nb_subfr, psEncC->predictLPCOrder ); - if( useInterpNLSFs && !firstFrameAfterReset && nb_subfr == MAX_NB_SUBFR ) { + if( psEncC->useInterpolatedNLSFs && !psEncC->first_frame_after_reset && psEncC->nb_subfr == MAX_NB_SUBFR ) { /* Optimal solution for last 10 ms; subtract residual energy here, as that's easier than */ /* adding it to the residual energy of the first 10 ms in each iteration of the search below */ - res_nrg -= silk_burg_modified_FLP( a_tmp, x + ( MAX_NB_SUBFR / 2 ) * subfr_length, - subfr_length, MAX_NB_SUBFR / 2, FIND_LPC_COND_FAC, LPC_order ); - - silk_bwexpander_FLP( a_tmp, LPC_order, FIND_LPC_CHIRP ); + res_nrg -= silk_burg_modified_FLP( a_tmp, x + ( MAX_NB_SUBFR / 2 ) * subfr_length, minInvGain, subfr_length, MAX_NB_SUBFR / 2, psEncC->predictLPCOrder ); /* Convert to NLSFs */ - silk_A2NLSF_FLP( NLSF_Q15, a_tmp, LPC_order ); + silk_A2NLSF_FLP( NLSF_Q15, a_tmp, psEncC->predictLPCOrder ); /* Search over interpolation indices to find the one with lowest residual energy */ res_nrg_2nd = silk_float_MAX; for( k = 3; k >= 0; k-- ) { /* Interpolate NLSFs for first half */ - silk_interpolate( NLSF0_Q15, prev_NLSFq_Q15, NLSF_Q15, k, LPC_order ); + 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, LPC_order ); + silk_NLSF2A_FLP( a_tmp, NLSF0_Q15, psEncC->predictLPCOrder ); /* Calculate residual energy with LSF interpolation */ - silk_LPC_analysis_filter_FLP( LPC_res, a_tmp, x, 2 * subfr_length, LPC_order ); - res_nrg_interp = - silk_energy_FLP( LPC_res + LPC_order, subfr_length - LPC_order ) + - silk_energy_FLP( LPC_res + LPC_order + subfr_length, subfr_length - LPC_order ); + silk_LPC_analysis_filter_FLP( LPC_res, a_tmp, x, 2 * subfr_length, psEncC->predictLPCOrder ); + res_nrg_interp = (silk_float)( + silk_energy_FLP( LPC_res + psEncC->predictLPCOrder, subfr_length - psEncC->predictLPCOrder ) + + silk_energy_FLP( LPC_res + psEncC->predictLPCOrder + subfr_length, subfr_length - psEncC->predictLPCOrder ) ); /* Determine whether current interpolated NLSFs are best so far */ if( res_nrg_interp < res_nrg ) { /* Interpolation has lower residual energy */ res_nrg = res_nrg_interp; - *interpIndex = (opus_int8)k; + psEncC->indices.NLSFInterpCoef_Q2 = (opus_int8)k; } else if( res_nrg_interp > res_nrg_2nd ) { /* No reason to continue iterating - residual energies will continue to climb */ break; @@ -104,10 +94,11 @@ void silk_find_LPC_FLP( } } - if( *interpIndex == 4 ) { + if( psEncC->indices.NLSFInterpCoef_Q2 == 4 ) { /* NLSF interpolation is currently inactive, calculate NLSFs from full frame AR coefficients */ - silk_A2NLSF_FLP( NLSF_Q15, a, LPC_order ); + silk_A2NLSF_FLP( NLSF_Q15, a, psEncC->predictLPCOrder ); } - silk_assert( *interpIndex == 4 || ( useInterpNLSFs && !firstFrameAfterReset && nb_subfr == MAX_NB_SUBFR ) ); + silk_assert( psEncC->indices.NLSFInterpCoef_Q2 == 4 || + ( psEncC->useInterpolatedNLSFs && !psEncC->first_frame_after_reset && psEncC->nb_subfr == MAX_NB_SUBFR ) ); } diff --git a/silk/float/find_pitch_lags_FLP.c b/silk/float/find_pitch_lags_FLP.c index 43f7ff94..c037138f 100644 --- a/silk/float/find_pitch_lags_FLP.c +++ b/silk/float/find_pitch_lags_FLP.c @@ -50,7 +50,7 @@ void silk_find_pitch_lags_FLP( silk_float *Wsig_ptr; /******************************************/ - /* Setup buffer lengths etc based on Fs */ + /* Set up buffer lengths etc based on Fs */ /******************************************/ buf_len = psEnc->sCmn.la_pitch + psEnc->sCmn.frame_length + psEnc->sCmn.ltp_mem_length; diff --git a/silk/float/find_pred_coefs_FLP.c b/silk/float/find_pred_coefs_FLP.c index 03500c2c..71866778 100644 --- a/silk/float/find_pred_coefs_FLP.c +++ b/silk/float/find_pred_coefs_FLP.c @@ -46,6 +46,7 @@ void silk_find_pred_coefs_FLP( 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 ]; + silk_float minInvGain; /* Weighting for weighted least squares */ for( i = 0; i < psEnc->sCmn.nb_subfr; i++ ) { @@ -74,7 +75,6 @@ void silk_find_pred_coefs_FLP( /* Create LTP residual */ silk_LTP_analysis_filter_FLP( LPC_in_pre, x - psEnc->sCmn.predictLPCOrder, psEncCtrl->LTPCoef, psEncCtrl->pitchL, invGains, psEnc->sCmn.subfr_length, psEnc->sCmn.nb_subfr, psEnc->sCmn.predictLPCOrder ); - } else { /************/ /* UNVOICED */ @@ -88,15 +88,20 @@ void silk_find_pred_coefs_FLP( x_pre_ptr += psEnc->sCmn.subfr_length + psEnc->sCmn.predictLPCOrder; x_ptr += psEnc->sCmn.subfr_length; } - silk_memset( psEncCtrl->LTPCoef, 0, psEnc->sCmn.nb_subfr * LTP_ORDER * sizeof( silk_float ) ); psEncCtrl->LTPredCodGain = 0.0f; } + /* Limit on total predictive coding gain */ + if( psEnc->sCmn.first_frame_after_reset ) { + minInvGain = 1.0f / MAX_PREDICTION_POWER_GAIN_AFTER_RESET; + } else { + minInvGain = (silk_float)powf( 2, psEncCtrl->LTPredCodGain / 3 ) / MAX_PREDICTION_POWER_GAIN; + minInvGain /= 0.1f + 0.9f * psEncCtrl->coding_quality; + } + /* LPC_in_pre contains the LTP-filtered input for voiced, and the unfiltered input for unvoiced */ - silk_find_LPC_FLP( NLSF_Q15, &psEnc->sCmn.indices.NLSFInterpCoef_Q2, psEnc->sCmn.prev_NLSFq_Q15, - psEnc->sCmn.useInterpolatedNLSFs, psEnc->sCmn.first_frame_after_reset, psEnc->sCmn.predictLPCOrder, - LPC_in_pre, psEnc->sCmn.subfr_length + psEnc->sCmn.predictLPCOrder, psEnc->sCmn.nb_subfr ); + silk_find_LPC_FLP( &psEnc->sCmn, NLSF_Q15, LPC_in_pre, minInvGain ); /* Quantize LSFs */ silk_process_NLSFs_FLP( &psEnc->sCmn, psEncCtrl->PredCoef, NLSF_Q15, psEnc->sCmn.prev_NLSFq_Q15 ); diff --git a/silk/float/main_FLP.h b/silk/float/main_FLP.h index d2889009..5107921b 100644 --- a/silk/float/main_FLP.h +++ b/silk/float/main_FLP.h @@ -143,15 +143,10 @@ void silk_find_pred_coefs_FLP( /* LPC analysis */ void silk_find_LPC_FLP( + silk_encoder_state *psEncC, /* I/O Encoder state */ opus_int16 NLSF_Q15[], /* O NLSFs */ - opus_int8 *interpIndex, /* O NLSF interp. index for NLSF interp. */ - const opus_int16 prev_NLSFq_Q15[], /* I Previous NLSFs, for NLSF interpolation */ - const opus_int useInterpNLSFs, /* I Flag */ - const opus_int firstFrameAfterReset, /* I Flag */ - const opus_int LPC_order, /* I LPC order */ const silk_float x[], /* I Input signal */ - const opus_int subfr_length, /* I Subframe length incl preceeding samples */ - const opus_int nb_subfr /* I Number of subframes */ + const silk_float minInvGain /* I Prediction gain from LTP (dB) */ ); /* LTP analysis */ diff --git a/silk/float/noise_shape_analysis_FLP.c b/silk/float/noise_shape_analysis_FLP.c index e19ff70a..d1f1a69c 100644 --- a/silk/float/noise_shape_analysis_FLP.c +++ b/silk/float/noise_shape_analysis_FLP.c @@ -151,7 +151,7 @@ void silk_noise_shape_analysis_FLP( psEncCtrl->input_quality = 0.5f * ( psEnc->sCmn.input_quality_bands_Q15[ 0 ] + psEnc->sCmn.input_quality_bands_Q15[ 1 ] ) * ( 1.0f / 32768.0f ); /* Coding quality level, between 0.0 and 1.0 */ - psEncCtrl->coding_quality = silk_sigmoid( 0.25f * ( SNR_adj_dB - 18.0f ) ); + psEncCtrl->coding_quality = silk_sigmoid( 0.25f * ( SNR_adj_dB - 20.0f ) ); if( psEnc->sCmn.useCBR == 0 ) { /* Reduce coding SNR during low speech activity */ @@ -274,8 +274,8 @@ void silk_noise_shape_analysis_FLP( silk_bwexpander_FLP( &psEncCtrl->AR1[ k * MAX_SHAPE_LPC_ORDER ], psEnc->sCmn.shapingLPCOrder, BWExp1 ); /* Ratio of prediction gains, in energy domain */ - silk_LPC_inverse_pred_gain_FLP( &pre_nrg, &psEncCtrl->AR2[ k * MAX_SHAPE_LPC_ORDER ], psEnc->sCmn.shapingLPCOrder ); - silk_LPC_inverse_pred_gain_FLP( &nrg, &psEncCtrl->AR1[ k * MAX_SHAPE_LPC_ORDER ], psEnc->sCmn.shapingLPCOrder ); + 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 */ diff --git a/silk/float/pitch_analysis_core_FLP.c b/silk/float/pitch_analysis_core_FLP.c index c7980035..5546d09b 100644 --- a/silk/float/pitch_analysis_core_FLP.c +++ b/silk/float/pitch_analysis_core_FLP.c @@ -115,7 +115,7 @@ opus_int silk_pitch_analysis_core_FLP( /* O Voicing estimate: 0 voiced, silk_assert( search_thres1 >= 0.0f && search_thres1 <= 1.0f ); silk_assert( search_thres2 >= 0.0f && search_thres2 <= 1.0f ); - /* Setup frame lengths max / min lag for the sampling frequency */ + /* Set up frame lengths max / min lag for the sampling frequency */ frame_length = ( PE_LTP_MEM_LENGTH_MS + nb_subfr * PE_SUBFR_LENGTH_MS ) * Fs_kHz; frame_length_4kHz = ( PE_LTP_MEM_LENGTH_MS + nb_subfr * PE_SUBFR_LENGTH_MS ) * 4; frame_length_8kHz = ( PE_LTP_MEM_LENGTH_MS + nb_subfr * PE_SUBFR_LENGTH_MS ) * 8; @@ -322,7 +322,7 @@ opus_int silk_pitch_analysis_core_FLP( /* O Voicing estimate: 0 voiced, prevLag_log2 = 0; } - /* Setup stage 2 codebook based on number of subframes */ + /* Set up stage 2 codebook based on number of subframes */ if( nb_subfr == PE_MAX_NB_SUBFR ) { cbk_size = PE_NB_CBKS_STAGE2_EXT; Lag_CB_ptr = &silk_CB_lags_stage2[ 0 ][ 0 ]; @@ -419,7 +419,7 @@ opus_int silk_pitch_analysis_core_FLP( /* O Voicing estimate: 0 voiced, silk_assert( lag == silk_SAT16( lag ) ); contour_bias = PE_FLATCONTOUR_BIAS / lag; - /* Setup cbk parameters acording to complexity setting and frame length */ + /* Set up cbk parameters acording to complexity setting and frame length */ if( nb_subfr == PE_MAX_NB_SUBFR ) { nb_cbk_search = (opus_int)silk_nb_cbk_searchs_stage3[ complexity ]; cbk_size = PE_NB_CBKS_STAGE3_MAX; diff --git a/silk/float/prefilter_FLP.c b/silk/float/prefilter_FLP.c index 3dcf7b53..79ebf65f 100644 --- a/silk/float/prefilter_FLP.c +++ b/silk/float/prefilter_FLP.c @@ -108,7 +108,7 @@ void silk_prefilter_FLP( silk_float HarmShapeFIR[ 3 ]; silk_float st_res[ MAX_SUB_FRAME_LENGTH + MAX_LPC_ORDER ]; - /* Setup pointers */ + /* Set up pointers */ px = x; pxw = xw; lag = P->lagPrev; diff --git a/silk/float/process_gains_FLP.c b/silk/float/process_gains_FLP.c index 020f847b..edac122e 100644 --- a/silk/float/process_gains_FLP.c +++ b/silk/float/process_gains_FLP.c @@ -64,7 +64,7 @@ void silk_process_gains_FLP( /* Prepare gains for noise shaping quantization */ for( k = 0; k < psEnc->sCmn.nb_subfr; k++ ) { - pGains_Q16[ k ] = ( opus_int32 ) ( psEncCtrl->Gains[ k ] * 65536.0f ); + pGains_Q16[ k ] = (opus_int32)( psEncCtrl->Gains[ k ] * 65536.0f ); } /* Save unquantized gains and gain Index */ diff --git a/silk/float/structs_FLP.h b/silk/float/structs_FLP.h index f56a972a..b879fd17 100644 --- a/silk/float/structs_FLP.h +++ b/silk/float/structs_FLP.h @@ -72,10 +72,6 @@ typedef struct { /* 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 */ silk_float LTPCorr; /* Normalized correlation from pitch lag estimator */ - - /* Parameters for LTP scaling control */ - silk_float prevLTPredCodGain; - silk_float HPLTPredCodGain; } silk_encoder_state_FLP; /************************/ diff --git a/silk/float/wrappers_FLP.c b/silk/float/wrappers_FLP.c index 9fd91477..ad9c2a59 100644 --- a/silk/float/wrappers_FLP.c +++ b/silk/float/wrappers_FLP.c @@ -102,7 +102,7 @@ void silk_NSQ_wrapper_FLP( ) { opus_int i, j; - opus_int16 x_16[ MAX_FRAME_LENGTH ]; + opus_int32 x_Q10[ 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 ]; @@ -133,12 +133,12 @@ void silk_NSQ_wrapper_FLP( /* prediction and coding parameters */ for( i = 0; i < psEnc->sCmn.nb_subfr * LTP_ORDER; i++ ) { - LTPCoef_Q14[ i ] = ( opus_int16 )silk_float2int( psEncCtrl->LTPCoef[ i ] * 16384.0f ); + LTPCoef_Q14[ i ] = (opus_int16)silk_float2int( psEncCtrl->LTPCoef[ i ] * 16384.0f ); } for( j = 0; j < 2; j++ ) { for( i = 0; i < psEnc->sCmn.predictLPCOrder; i++ ) { - PredCoef_Q12[ j ][ i ] = ( opus_int16 )silk_float2int( psEncCtrl->PredCoef[ j ][ i ] * 4096.0f ); + PredCoef_Q12[ j ][ i ] = (opus_int16)silk_float2int( psEncCtrl->PredCoef[ j ][ i ] * 4096.0f ); } } @@ -154,14 +154,16 @@ void silk_NSQ_wrapper_FLP( } /* Convert input to fix */ - silk_float2short_array( x_16, x, psEnc->sCmn.frame_length ); + for( i = 0; i < psEnc->sCmn.frame_length; i++ ) { + x_Q10[ i ] = silk_float2int( 1024.0 * x[ i ] ); + } /* Call NSQ */ if( psEnc->sCmn.nStatesDelayedDecision > 1 || psEnc->sCmn.warping_Q16 > 0 ) { - silk_NSQ_del_dec( &psEnc->sCmn, psNSQ, psIndices, x_16, pulses, PredCoef_Q12[ 0 ], LTPCoef_Q14, + silk_NSQ_del_dec( &psEnc->sCmn, psNSQ, psIndices, x_Q10, pulses, PredCoef_Q12[ 0 ], LTPCoef_Q14, AR2_Q13, HarmShapeGain_Q14, Tilt_Q14, LF_shp_Q14, Gains_Q16, psEncCtrl->pitchL, Lambda_Q10, LTP_scale_Q14 ); } else { - silk_NSQ( &psEnc->sCmn, psNSQ, psIndices, x_16, pulses, PredCoef_Q12[ 0 ], LTPCoef_Q14, + silk_NSQ( &psEnc->sCmn, psNSQ, psIndices, x_Q10, pulses, PredCoef_Q12[ 0 ], LTPCoef_Q14, AR2_Q13, HarmShapeGain_Q14, Tilt_Q14, LF_shp_Q14, Gains_Q16, psEncCtrl->pitchL, Lambda_Q10, LTP_scale_Q14 ); } } diff --git a/silk/interpolate.c b/silk/interpolate.c index 0f40a935..216f7c70 100644 --- a/silk/interpolate.c +++ b/silk/interpolate.c @@ -46,6 +46,6 @@ void silk_interpolate( silk_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 ); + xi[ i ] = (opus_int16)silk_ADD_RSHIFT( x0[ i ], silk_SMULBB( x1[ i ] - x0[ i ], ifact_Q2 ), 2 ); } } diff --git a/silk/macros.h b/silk/macros.h index e3ab0e7f..e6121e8b 100644 --- a/silk/macros.h +++ b/silk/macros.h @@ -25,8 +25,12 @@ ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ***********************************************************************/ -#ifndef SILK_API_C_H -#define SILK_API_C_H +#ifndef SILK_MACROS_H +#define SILK_MACROS_H + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif /* This is an inline header file for general platform. */ @@ -128,5 +132,5 @@ static inline opus_int32 silk_CLZ32(opus_int32 in32) #endif #define matrix_c_adr(Matrix_base_adr, row, column, M) (Matrix_base_adr + ((row)+(M)*(column))) -#endif /* SILK_API_C_H */ +#endif /* SILK_MACROS_H */ diff --git a/silk/main.h b/silk/main.h index adf11f6e..1d9e7b83 100644 --- a/silk/main.h +++ b/silk/main.h @@ -38,9 +38,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "entenc.h" #include "entdec.h" -/* Simple way to make [8000, 12000, 16000, 24000, 48000] to [0,1,2,3,4] */ -#define rateID(R) ( ( ( ((R)>>12) - ((R)>16000) ) >> ((R)>24000) ) - 1 ) - /* Convert Left/Right stereo signal to adaptive Mid/Side representation */ void silk_stereo_LR_to_MS( stereo_enc_state *state, /* I/O State */ @@ -232,7 +229,7 @@ void silk_NSQ( 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_int16 x[], /* I Prefiltered input signal */ + const opus_int32 x_Q10[], /* 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 */ @@ -251,7 +248,7 @@ void silk_NSQ_del_dec( 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_int16 x[], /* I Prefiltered input signal */ + const opus_int32 x_Q10[], /* 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 */ diff --git a/silk/quant_LTP_gains.c b/silk/quant_LTP_gains.c index 47246592..d98798e3 100644 --- a/silk/quant_LTP_gains.c +++ b/silk/quant_LTP_gains.c @@ -59,7 +59,7 @@ void silk_quant_LTP_gains( cbk_ptr_Q7 = silk_LTP_vq_ptrs_Q7[ k ]; cbk_size = silk_LTP_vq_sizes[ k ]; - /* Setup pointer to first subframe */ + /* Set up pointer to first subframe */ W_Q18_ptr = W_Q18; b_Q14_ptr = B_Q14; diff --git a/silk/resampler.c b/silk/resampler.c index eeda054a..9055c813 100644 --- a/silk/resampler.c +++ b/silk/resampler.c @@ -29,30 +29,46 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "config.h" #endif -/* Matrix of resampling methods used: +/* + * Matrix of resampling methods used: * Fs_out (kHz) - * 8 12 16 24 48 + * 8 12 16 24 48 * * 8 C UF U UF UF * 12 AF C UF U UF * Fs_in (kHz) 16 D AF C UF UF - * 24 AIF D AF C U - * 48 DAF DAF AF D C - * - * default method: UF + * 24 AF D AF C U + * 48 AF AF AF D C * * C -> Copy (no resampling) * D -> Allpass-based 2x downsampling * U -> Allpass-based 2x upsampling - * DAF -> Allpass-based 2x downsampling followed by AR2 filter followed by FIR interpolation * UF -> Allpass-based 2x upsampling followed by FIR interpolation * AF -> AR2 filter followed by FIR interpolation - * - * Signals sampled above 48 kHz are not supported. */ #include "resampler_private.h" +/* Tables with delay compensation values to equalize total delay for different modes */ +static const opus_int8 delay_matrix_enc[ 5 ][ 3 ] = { +/* in \ out 8 12 16 */ +/* 8 */ { 6, 0, 3 }, +/* 12 */ { 0, 7, 3 }, +/* 16 */ { 0, 1, 10 }, +/* 24 */ { 0, 2, 6 }, +/* 48 */ { 18, 10, 12 } +}; + +static const opus_int8 delay_matrix_dec[ 3 ][ 5 ] = { +/* in \ out 8 12 16 24 48 */ +/* 8 */ { 4, 0, 2, 0, 0 }, +/* 12 */ { 0, 9, 4, 7, 4 }, +/* 16 */ { 0, 3, 12, 7, 7 } +}; + +/* Simple way to make [8000, 12000, 16000, 24000, 48000] to [0, 1, 2, 3, 4] */ +#define rateID(R) ( ( ( ((R)>>12) - ((R)>16000) ) >> ((R)>24000) ) - 1 ) + #define USE_silk_resampler_copy (0) #define USE_silk_resampler_private_up2_HQ_wrapper (1) #define USE_silk_resampler_private_IIR_FIR (2) @@ -60,27 +76,42 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. /* Initialize/reset the resampler state for a given pair of input/output sampling rates */ opus_int silk_resampler_init( - silk_resampler_state_struct *S, /* I/O Resampler state */ - opus_int32 Fs_Hz_in, /* I Input sampling rate (Hz) */ - opus_int32 Fs_Hz_out /* I Output sampling rate (Hz) */ + silk_resampler_state_struct *S, /* I/O Resampler state */ + opus_int32 Fs_Hz_in, /* I Input sampling rate (Hz) */ + opus_int32 Fs_Hz_out, /* I Output sampling rate (Hz) */ + opus_int forEnc /* I If 1: encoder; if 0: decoder */ ) { - opus_int32 up2 = 0, down2 = 0; + opus_int up2x; /* Clear state */ silk_memset( S, 0, sizeof( silk_resampler_state_struct ) ); /* Input checking */ - 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 && Fs_Hz_out != 24000 && Fs_Hz_out != 48000 ) ) { - silk_assert( 0 ); - return -1; + 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 ); + 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 ); + return -1; + } + S->inputDelay = delay_matrix_dec[ rateID( Fs_Hz_in ) ][ rateID( Fs_Hz_out ) ]; } + S->Fs_in_kHz = silk_DIV32_16( Fs_Hz_in, 1000 ); + S->Fs_out_kHz = silk_DIV32_16( Fs_Hz_out, 1000 ); + /* Number of samples processed per batch */ - S->batchSize = silk_DIV32_16( Fs_Hz_in, 100 ); + S->batchSize = S->Fs_in_kHz * RESAMPLER_MAX_BATCH_SIZE_MS; /* Find resampler with the right sampling ratio */ + up2x = 0; if( Fs_Hz_out > Fs_Hz_in ) { /* Upsample */ if( Fs_Hz_out == silk_MUL( Fs_Hz_in, 2 ) ) { /* Fs_out : Fs_in = 2 : 1 */ @@ -89,36 +120,35 @@ opus_int silk_resampler_init( } else { /* Default resampler */ S->resampler_function = USE_silk_resampler_private_IIR_FIR; - up2 = 1; + up2x = 1; } } else if ( Fs_Hz_out < Fs_Hz_in ) { /* Downsample */ + S->resampler_function = USE_silk_resampler_private_down_FIR; if( silk_MUL( Fs_Hz_out, 4 ) == silk_MUL( Fs_Hz_in, 3 ) ) { /* Fs_out : Fs_in = 3 : 4 */ S->FIR_Fracs = 3; + S->FIR_Order = RESAMPLER_DOWN_ORDER_FIR0; S->Coefs = silk_Resampler_3_4_COEFS; - S->resampler_function = USE_silk_resampler_private_down_FIR; } else if( silk_MUL( Fs_Hz_out, 3 ) == silk_MUL( Fs_Hz_in, 2 ) ) { /* Fs_out : Fs_in = 2 : 3 */ S->FIR_Fracs = 2; + S->FIR_Order = RESAMPLER_DOWN_ORDER_FIR0; S->Coefs = silk_Resampler_2_3_COEFS; - S->resampler_function = USE_silk_resampler_private_down_FIR; } else if( silk_MUL( Fs_Hz_out, 2 ) == Fs_Hz_in ) { /* Fs_out : Fs_in = 1 : 2 */ S->FIR_Fracs = 1; + S->FIR_Order = RESAMPLER_DOWN_ORDER_FIR1; S->Coefs = silk_Resampler_1_2_COEFS; - S->resampler_function = USE_silk_resampler_private_down_FIR; } else if( silk_MUL( Fs_Hz_out, 3 ) == Fs_Hz_in ) { /* Fs_out : Fs_in = 1 : 3 */ S->FIR_Fracs = 1; + S->FIR_Order = RESAMPLER_DOWN_ORDER_FIR2; S->Coefs = silk_Resampler_1_3_COEFS; - S->resampler_function = USE_silk_resampler_private_down_FIR; } else if( silk_MUL( Fs_Hz_out, 4 ) == Fs_Hz_in ) { /* Fs_out : Fs_in = 1 : 4 */ S->FIR_Fracs = 1; - down2 = 1; - S->Coefs = silk_Resampler_1_2_COEFS; - S->resampler_function = USE_silk_resampler_private_down_FIR; + S->FIR_Order = RESAMPLER_DOWN_ORDER_FIR2; + S->Coefs = silk_Resampler_1_4_COEFS; } else if( silk_MUL( Fs_Hz_out, 6 ) == Fs_Hz_in ) { /* Fs_out : Fs_in = 1 : 6 */ S->FIR_Fracs = 1; - down2 = 1; - S->Coefs = silk_Resampler_1_3_COEFS; - S->resampler_function = USE_silk_resampler_private_down_FIR; + S->FIR_Order = RESAMPLER_DOWN_ORDER_FIR2; + S->Coefs = silk_Resampler_1_6_COEFS; } else { /* None available */ silk_assert( 0 ); @@ -129,12 +159,10 @@ opus_int silk_resampler_init( S->resampler_function = USE_silk_resampler_copy; } - S->input2x = up2 | down2; - /* Ratio of input/output samples */ - S->invRatio_Q16 = silk_LSHIFT32( silk_DIV32( silk_LSHIFT32( Fs_Hz_in, 14 + up2 - down2 ), Fs_Hz_out ), 2 ); + S->invRatio_Q16 = silk_LSHIFT32( silk_DIV32( silk_LSHIFT32( Fs_Hz_in, 14 + up2x ), Fs_Hz_out ), 2 ); /* Make sure the ratio is rounded up */ - while( silk_SMULWW( S->invRatio_Q16, silk_LSHIFT32( Fs_Hz_out, down2 ) ) < silk_LSHIFT32( Fs_Hz_in, up2 ) ) { + while( silk_SMULWW( S->invRatio_Q16, Fs_Hz_out ) < silk_LSHIFT32( Fs_Hz_in, up2x ) ) { S->invRatio_Q16++; } @@ -142,26 +170,46 @@ opus_int silk_resampler_init( } /* Resampler: convert from one sampling rate to another */ +/* Input and output sampling rate are at most 48000 Hz */ opus_int silk_resampler( - silk_resampler_state_struct *S, /* I/O Resampler state */ - opus_int16 out[], /* O Output signal */ - const opus_int16 in[], /* I Input signal */ - opus_int32 inLen /* I Number of input samples */ + silk_resampler_state_struct *S, /* I/O Resampler state */ + opus_int16 out[], /* O Output signal */ + const opus_int16 in[], /* I Input signal */ + opus_int32 inLen /* I Number of input samples */ ) { - /* Input and output sampling rate are at most 48000 Hz */ + opus_int nSamples; + + /* Need at least 1 ms of input data */ + silk_assert( inLen >= S->Fs_in_kHz ); + /* Delay can't exceed the 1 ms of buffering */ + silk_assert( S->inputDelay <= S->Fs_in_kHz ); + + nSamples = S->Fs_in_kHz - S->inputDelay; + + /* Copy to delay buffer */ + silk_memcpy( &S->delayBuf[ S->inputDelay ], in, nSamples * sizeof( opus_int16 ) ); + switch( S->resampler_function ) { case USE_silk_resampler_private_up2_HQ_wrapper: - silk_resampler_private_up2_HQ_wrapper( S, out, in, inLen ); + silk_resampler_private_up2_HQ_wrapper( S, out, S->delayBuf, S->Fs_in_kHz ); + silk_resampler_private_up2_HQ_wrapper( S, &out[ S->Fs_out_kHz ], &in[ nSamples ], inLen - S->Fs_in_kHz ); break; case USE_silk_resampler_private_IIR_FIR: - silk_resampler_private_IIR_FIR( S, out, in, inLen ); + silk_resampler_private_IIR_FIR( S, out, S->delayBuf, S->Fs_in_kHz ); + silk_resampler_private_IIR_FIR( S, &out[ S->Fs_out_kHz ], &in[ nSamples ], inLen - S->Fs_in_kHz ); break; case USE_silk_resampler_private_down_FIR: - silk_resampler_private_down_FIR( S, out, in, inLen ); + silk_resampler_private_down_FIR( S, out, S->delayBuf, S->Fs_in_kHz ); + silk_resampler_private_down_FIR( S, &out[ S->Fs_out_kHz ], &in[ nSamples ], inLen - S->Fs_in_kHz ); break; default: - silk_memcpy( out, in, inLen * sizeof( opus_int16 ) ); + silk_memcpy( out, S->delayBuf, S->Fs_in_kHz * sizeof( opus_int16 ) ); + silk_memcpy( &out[ S->Fs_out_kHz ], &in[ nSamples ], ( inLen - S->Fs_in_kHz ) * sizeof( opus_int16 ) ); } + + /* Copy to delay buffer */ + silk_memcpy( S->delayBuf, &in[ inLen - S->inputDelay ], S->inputDelay * sizeof( opus_int16 ) ); + return 0; } diff --git a/silk/resampler_down2.c b/silk/resampler_down2.c index fe33d35d..3f6a8f9d 100644 --- a/silk/resampler_down2.c +++ b/silk/resampler_down2.c @@ -32,7 +32,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "SigProc_FIX.h" #include "resampler_rom.h" -/* Downsample by a factor 2, mediocre quality */ +/* Downsample by a factor 2 */ void silk_resampler_down2( opus_int32 *S, /* I/O State vector [ 2 ] */ opus_int16 *out, /* O Output signal [ len ] */ diff --git a/silk/resampler_private.h b/silk/resampler_private.h index 9e14c0f6..96fe83ed 100644 --- a/silk/resampler_private.h +++ b/silk/resampler_private.h @@ -25,8 +25,8 @@ ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ***********************************************************************/ -#ifndef SILK_RESAMPLER_H -#define SILK_RESAMPLER_H +#ifndef SILK_RESAMPLER_PRIVATE_H +#define SILK_RESAMPLER_PRIVATE_H #ifdef __cplusplus extern "C" { @@ -37,7 +37,9 @@ extern "C" { #include "resampler_rom.h" /* Number of input samples to process in the inner loop */ -#define RESAMPLER_MAX_BATCH_SIZE_IN 480 +#define RESAMPLER_MAX_BATCH_SIZE_MS 10 +#define RESAMPLER_MAX_FS_KHZ 48 +#define RESAMPLER_MAX_BATCH_SIZE_IN ( RESAMPLER_MAX_BATCH_SIZE_MS * RESAMPLER_MAX_FS_KHZ ) /* Description: Hybrid IIR/FIR polyphase implementation of resampling */ void silk_resampler_private_IIR_FIR( @@ -83,4 +85,4 @@ void silk_resampler_private_AR2( #ifdef __cplusplus } #endif -#endif /* SILK_RESAMPLER_H */ +#endif /* SILK_RESAMPLER_PRIVATE_H */ diff --git a/silk/resampler_private_IIR_FIR.c b/silk/resampler_private_IIR_FIR.c index 725f8576..f17fb5ca 100644 --- a/silk/resampler_private_IIR_FIR.c +++ b/silk/resampler_private_IIR_FIR.c @@ -45,15 +45,17 @@ static inline opus_int16 *silk_resampler_private_IIR_FIR_INTERPOL( /* Interpolate upsampled signal and store in output array */ for( index_Q16 = 0; index_Q16 < max_index_Q16; index_Q16 += index_increment_Q16 ) { - table_index = silk_SMULWB( index_Q16 & 0xFFFF, 144 ); + table_index = silk_SMULWB( index_Q16 & 0xFFFF, 12 ); buf_ptr = &buf[ index_Q16 >> 16 ]; - res_Q15 = silk_SMULBB( buf_ptr[ 0 ], silk_resampler_frac_FIR_144[ table_index ][ 0 ] ); - res_Q15 = silk_SMLABB( res_Q15, buf_ptr[ 1 ], silk_resampler_frac_FIR_144[ table_index ][ 1 ] ); - res_Q15 = silk_SMLABB( res_Q15, buf_ptr[ 2 ], silk_resampler_frac_FIR_144[ table_index ][ 2 ] ); - res_Q15 = silk_SMLABB( res_Q15, buf_ptr[ 3 ], silk_resampler_frac_FIR_144[ 143 - table_index ][ 2 ] ); - res_Q15 = silk_SMLABB( res_Q15, buf_ptr[ 4 ], silk_resampler_frac_FIR_144[ 143 - table_index ][ 1 ] ); - res_Q15 = silk_SMLABB( res_Q15, buf_ptr[ 5 ], silk_resampler_frac_FIR_144[ 143 - table_index ][ 0 ] ); + res_Q15 = silk_SMULBB( buf_ptr[ 0 ], silk_resampler_frac_FIR_12[ table_index ][ 0 ] ); + res_Q15 = silk_SMLABB( res_Q15, buf_ptr[ 1 ], silk_resampler_frac_FIR_12[ table_index ][ 1 ] ); + res_Q15 = silk_SMLABB( res_Q15, buf_ptr[ 2 ], silk_resampler_frac_FIR_12[ table_index ][ 2 ] ); + res_Q15 = silk_SMLABB( res_Q15, buf_ptr[ 3 ], silk_resampler_frac_FIR_12[ table_index ][ 3 ] ); + res_Q15 = silk_SMLABB( res_Q15, buf_ptr[ 4 ], silk_resampler_frac_FIR_12[ 11 - table_index ][ 3 ] ); + res_Q15 = silk_SMLABB( res_Q15, buf_ptr[ 5 ], silk_resampler_frac_FIR_12[ 11 - table_index ][ 2 ] ); + res_Q15 = silk_SMLABB( res_Q15, buf_ptr[ 6 ], silk_resampler_frac_FIR_12[ 11 - table_index ][ 1 ] ); + res_Q15 = silk_SMLABB( res_Q15, buf_ptr[ 7 ], silk_resampler_frac_FIR_12[ 11 - table_index ][ 0 ] ); *out++ = (opus_int16)silk_SAT16( silk_RSHIFT_ROUND( res_Q15, 15 ) ); } return out; @@ -69,34 +71,33 @@ void silk_resampler_private_IIR_FIR( silk_resampler_state_struct *S = (silk_resampler_state_struct *)SS; opus_int32 nSamplesIn; opus_int32 max_index_Q16, index_increment_Q16; - opus_int16 buf[ 2 * RESAMPLER_MAX_BATCH_SIZE_IN + RESAMPLER_ORDER_FIR_144 ]; + opus_int16 buf[ RESAMPLER_MAX_BATCH_SIZE_IN + RESAMPLER_ORDER_FIR_12 ]; /* Copy buffered samples to start of buffer */ - silk_memcpy( buf, S->sFIR, RESAMPLER_ORDER_FIR_144 * sizeof( opus_int32 ) ); + silk_memcpy( buf, S->sFIR, RESAMPLER_ORDER_FIR_12 * sizeof( opus_int32 ) ); /* Iterate over blocks of frameSizeIn input samples */ index_increment_Q16 = S->invRatio_Q16; while( 1 ) { nSamplesIn = silk_min( inLen, S->batchSize ); - silk_assert( S->input2x ); /* Upsample 2x */ - silk_resampler_private_up2_HQ( S->sIIR, &buf[ RESAMPLER_ORDER_FIR_144 ], in, nSamplesIn ); + silk_resampler_private_up2_HQ( S->sIIR, &buf[ RESAMPLER_ORDER_FIR_12 ], in, nSamplesIn ); - max_index_Q16 = silk_LSHIFT32( nSamplesIn, 16 + S->input2x ); /* +1 if 2x upsampling */ - out = silk_resampler_private_IIR_FIR_INTERPOL(out, buf, max_index_Q16, index_increment_Q16); + max_index_Q16 = silk_LSHIFT32( nSamplesIn, 16 + 1 ); /* + 1 because 2x upsampling */ + out = silk_resampler_private_IIR_FIR_INTERPOL( out, buf, max_index_Q16, index_increment_Q16 ); in += nSamplesIn; inLen -= nSamplesIn; if( inLen > 0 ) { /* More iterations to do; copy last part of filtered signal to beginning of buffer */ - silk_memcpy( buf, &buf[ nSamplesIn << S->input2x ], RESAMPLER_ORDER_FIR_144 * sizeof( opus_int32 ) ); + silk_memcpy( buf, &buf[ nSamplesIn << 1 ], RESAMPLER_ORDER_FIR_12 * sizeof( opus_int32 ) ); } else { break; } } /* Copy last part of filtered signal to the state for the next call */ - silk_memcpy( S->sFIR, &buf[nSamplesIn << S->input2x ], RESAMPLER_ORDER_FIR_144 * sizeof( opus_int32 ) ); + silk_memcpy( S->sFIR, &buf[ nSamplesIn << 1 ], RESAMPLER_ORDER_FIR_12 * sizeof( opus_int32 ) ); } diff --git a/silk/resampler_private_down_FIR.c b/silk/resampler_private_down_FIR.c index b9c2519b..d1ee15a3 100644 --- a/silk/resampler_private_down_FIR.c +++ b/silk/resampler_private_down_FIR.c @@ -32,86 +32,115 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "SigProc_FIX.h" #include "resampler_private.h" -static inline opus_int16 *silk_resampler_private_down_FIR_INTERPOL0( +static inline opus_int16 *silk_resampler_private_down_FIR_INTERPOL( opus_int16 *out, - opus_int32 *buf2, + opus_int32 *buf, const opus_int16 *FIR_Coefs, + opus_int FIR_Order, + opus_int FIR_Fracs, opus_int32 max_index_Q16, opus_int32 index_increment_Q16 ) { opus_int32 index_Q16, res_Q6; opus_int32 *buf_ptr; - - for( index_Q16 = 0; index_Q16 < max_index_Q16; index_Q16 += index_increment_Q16 ) { - /* Integer part gives pointer to buffered input */ - buf_ptr = buf2 + silk_RSHIFT( index_Q16, 16 ); - - /* Inner product */ - res_Q6 = silk_SMULWB( silk_ADD32( buf_ptr[ 0 ], buf_ptr[ 15 ] ), FIR_Coefs[ 0 ] ); - res_Q6 = silk_SMLAWB( res_Q6, silk_ADD32( buf_ptr[ 1 ], buf_ptr[ 14 ] ), FIR_Coefs[ 1 ] ); - res_Q6 = silk_SMLAWB( res_Q6, silk_ADD32( buf_ptr[ 2 ], buf_ptr[ 13 ] ), FIR_Coefs[ 2 ] ); - res_Q6 = silk_SMLAWB( res_Q6, silk_ADD32( buf_ptr[ 3 ], buf_ptr[ 12 ] ), FIR_Coefs[ 3 ] ); - res_Q6 = silk_SMLAWB( res_Q6, silk_ADD32( buf_ptr[ 4 ], buf_ptr[ 11 ] ), FIR_Coefs[ 4 ] ); - res_Q6 = silk_SMLAWB( res_Q6, silk_ADD32( buf_ptr[ 5 ], buf_ptr[ 10 ] ), FIR_Coefs[ 5 ] ); - res_Q6 = silk_SMLAWB( res_Q6, silk_ADD32( buf_ptr[ 6 ], buf_ptr[ 9 ] ), FIR_Coefs[ 6 ] ); - res_Q6 = silk_SMLAWB( res_Q6, silk_ADD32( buf_ptr[ 7 ], buf_ptr[ 8 ] ), FIR_Coefs[ 7 ] ); - - /* Scale down, saturate and store in output array */ - *out++ = (opus_int16)silk_SAT16( silk_RSHIFT_ROUND( res_Q6, 6 ) ); - } - return out; -} - -static inline opus_int16 *silk_resampler_private_down_FIR_INTERPOL1( - opus_int16 *out, - opus_int32 *buf2, - const opus_int16 *FIR_Coefs, - opus_int32 max_index_Q16, - opus_int32 index_increment_Q16, - opus_int32 FIR_Fracs -) -{ - opus_int32 index_Q16, res_Q6; - opus_int32 *buf_ptr; opus_int32 interpol_ind; const opus_int16 *interpol_ptr; - for( index_Q16 = 0; index_Q16 < max_index_Q16; index_Q16 += index_increment_Q16 ) { - /* Integer part gives pointer to buffered input */ - buf_ptr = buf2 + silk_RSHIFT( index_Q16, 16 ); - - /* Fractional part gives interpolation coefficients */ - interpol_ind = silk_SMULWB( index_Q16 & 0xFFFF, FIR_Fracs ); - - /* Inner product */ - interpol_ptr = &FIR_Coefs[ RESAMPLER_DOWN_ORDER_FIR / 2 * interpol_ind ]; - res_Q6 = silk_SMULWB( buf_ptr[ 0 ], interpol_ptr[ 0 ] ); - res_Q6 = silk_SMLAWB( res_Q6, buf_ptr[ 1 ], interpol_ptr[ 1 ] ); - res_Q6 = silk_SMLAWB( res_Q6, buf_ptr[ 2 ], interpol_ptr[ 2 ] ); - res_Q6 = silk_SMLAWB( res_Q6, buf_ptr[ 3 ], interpol_ptr[ 3 ] ); - res_Q6 = silk_SMLAWB( res_Q6, buf_ptr[ 4 ], interpol_ptr[ 4 ] ); - res_Q6 = silk_SMLAWB( res_Q6, buf_ptr[ 5 ], interpol_ptr[ 5 ] ); - res_Q6 = silk_SMLAWB( res_Q6, buf_ptr[ 6 ], interpol_ptr[ 6 ] ); - res_Q6 = silk_SMLAWB( res_Q6, buf_ptr[ 7 ], interpol_ptr[ 7 ] ); - interpol_ptr = &FIR_Coefs[ RESAMPLER_DOWN_ORDER_FIR / 2 * ( FIR_Fracs - 1 - interpol_ind ) ]; - res_Q6 = silk_SMLAWB( res_Q6, buf_ptr[ 15 ], interpol_ptr[ 0 ] ); - res_Q6 = silk_SMLAWB( res_Q6, buf_ptr[ 14 ], interpol_ptr[ 1 ] ); - res_Q6 = silk_SMLAWB( res_Q6, buf_ptr[ 13 ], interpol_ptr[ 2 ] ); - res_Q6 = silk_SMLAWB( res_Q6, buf_ptr[ 12 ], interpol_ptr[ 3 ] ); - res_Q6 = silk_SMLAWB( res_Q6, buf_ptr[ 11 ], interpol_ptr[ 4 ] ); - res_Q6 = silk_SMLAWB( res_Q6, buf_ptr[ 10 ], interpol_ptr[ 5 ] ); - res_Q6 = silk_SMLAWB( res_Q6, buf_ptr[ 9 ], interpol_ptr[ 6 ] ); - res_Q6 = silk_SMLAWB( res_Q6, buf_ptr[ 8 ], interpol_ptr[ 7 ] ); - - /* Scale down, saturate and store in output array */ - *out++ = (opus_int16)silk_SAT16( silk_RSHIFT_ROUND( res_Q6, 6 ) ); + switch( FIR_Order ) { + case RESAMPLER_DOWN_ORDER_FIR0: + for( index_Q16 = 0; index_Q16 < max_index_Q16; index_Q16 += index_increment_Q16 ) { + /* Integer part gives pointer to buffered input */ + buf_ptr = buf + silk_RSHIFT( index_Q16, 16 ); + + /* Fractional part gives interpolation coefficients */ + interpol_ind = silk_SMULWB( index_Q16 & 0xFFFF, FIR_Fracs ); + + /* Inner product */ + interpol_ptr = &FIR_Coefs[ RESAMPLER_DOWN_ORDER_FIR0 / 2 * interpol_ind ]; + res_Q6 = silk_SMULWB( buf_ptr[ 0 ], interpol_ptr[ 0 ] ); + res_Q6 = silk_SMLAWB( res_Q6, buf_ptr[ 1 ], interpol_ptr[ 1 ] ); + res_Q6 = silk_SMLAWB( res_Q6, buf_ptr[ 2 ], interpol_ptr[ 2 ] ); + res_Q6 = silk_SMLAWB( res_Q6, buf_ptr[ 3 ], interpol_ptr[ 3 ] ); + res_Q6 = silk_SMLAWB( res_Q6, buf_ptr[ 4 ], interpol_ptr[ 4 ] ); + res_Q6 = silk_SMLAWB( res_Q6, buf_ptr[ 5 ], interpol_ptr[ 5 ] ); + res_Q6 = silk_SMLAWB( res_Q6, buf_ptr[ 6 ], interpol_ptr[ 6 ] ); + res_Q6 = silk_SMLAWB( res_Q6, buf_ptr[ 7 ], interpol_ptr[ 7 ] ); + res_Q6 = silk_SMLAWB( res_Q6, buf_ptr[ 8 ], interpol_ptr[ 8 ] ); + interpol_ptr = &FIR_Coefs[ RESAMPLER_DOWN_ORDER_FIR0 / 2 * ( FIR_Fracs - 1 - interpol_ind ) ]; + res_Q6 = silk_SMLAWB( res_Q6, buf_ptr[ 17 ], interpol_ptr[ 0 ] ); + res_Q6 = silk_SMLAWB( res_Q6, buf_ptr[ 16 ], interpol_ptr[ 1 ] ); + res_Q6 = silk_SMLAWB( res_Q6, buf_ptr[ 15 ], interpol_ptr[ 2 ] ); + res_Q6 = silk_SMLAWB( res_Q6, buf_ptr[ 14 ], interpol_ptr[ 3 ] ); + res_Q6 = silk_SMLAWB( res_Q6, buf_ptr[ 13 ], interpol_ptr[ 4 ] ); + res_Q6 = silk_SMLAWB( res_Q6, buf_ptr[ 12 ], interpol_ptr[ 5 ] ); + res_Q6 = silk_SMLAWB( res_Q6, buf_ptr[ 11 ], interpol_ptr[ 6 ] ); + res_Q6 = silk_SMLAWB( res_Q6, buf_ptr[ 10 ], interpol_ptr[ 7 ] ); + res_Q6 = silk_SMLAWB( res_Q6, buf_ptr[ 9 ], interpol_ptr[ 8 ] ); + + /* Scale down, saturate and store in output array */ + *out++ = (opus_int16)silk_SAT16( silk_RSHIFT_ROUND( res_Q6, 6 ) ); + } + break; + case RESAMPLER_DOWN_ORDER_FIR1: + for( index_Q16 = 0; index_Q16 < max_index_Q16; index_Q16 += index_increment_Q16 ) { + /* Integer part gives pointer to buffered input */ + buf_ptr = buf + silk_RSHIFT( index_Q16, 16 ); + + /* Inner product */ + res_Q6 = silk_SMULWB( silk_ADD32( buf_ptr[ 0 ], buf_ptr[ 23 ] ), FIR_Coefs[ 0 ] ); + res_Q6 = silk_SMLAWB( res_Q6, silk_ADD32( buf_ptr[ 1 ], buf_ptr[ 22 ] ), FIR_Coefs[ 1 ] ); + res_Q6 = silk_SMLAWB( res_Q6, silk_ADD32( buf_ptr[ 2 ], buf_ptr[ 21 ] ), FIR_Coefs[ 2 ] ); + res_Q6 = silk_SMLAWB( res_Q6, silk_ADD32( buf_ptr[ 3 ], buf_ptr[ 20 ] ), FIR_Coefs[ 3 ] ); + res_Q6 = silk_SMLAWB( res_Q6, silk_ADD32( buf_ptr[ 4 ], buf_ptr[ 19 ] ), FIR_Coefs[ 4 ] ); + res_Q6 = silk_SMLAWB( res_Q6, silk_ADD32( buf_ptr[ 5 ], buf_ptr[ 18 ] ), FIR_Coefs[ 5 ] ); + res_Q6 = silk_SMLAWB( res_Q6, silk_ADD32( buf_ptr[ 6 ], buf_ptr[ 17 ] ), FIR_Coefs[ 6 ] ); + res_Q6 = silk_SMLAWB( res_Q6, silk_ADD32( buf_ptr[ 7 ], buf_ptr[ 16 ] ), FIR_Coefs[ 7 ] ); + res_Q6 = silk_SMLAWB( res_Q6, silk_ADD32( buf_ptr[ 8 ], buf_ptr[ 15 ] ), FIR_Coefs[ 8 ] ); + res_Q6 = silk_SMLAWB( res_Q6, silk_ADD32( buf_ptr[ 9 ], buf_ptr[ 14 ] ), FIR_Coefs[ 9 ] ); + res_Q6 = silk_SMLAWB( res_Q6, silk_ADD32( buf_ptr[ 10 ], buf_ptr[ 13 ] ), FIR_Coefs[ 10 ] ); + res_Q6 = silk_SMLAWB( res_Q6, silk_ADD32( buf_ptr[ 11 ], buf_ptr[ 12 ] ), FIR_Coefs[ 11 ] ); + + /* Scale down, saturate and store in output array */ + *out++ = (opus_int16)silk_SAT16( silk_RSHIFT_ROUND( res_Q6, 6 ) ); + } + break; + case RESAMPLER_DOWN_ORDER_FIR2: + for( index_Q16 = 0; index_Q16 < max_index_Q16; index_Q16 += index_increment_Q16 ) { + /* Integer part gives pointer to buffered input */ + buf_ptr = buf + silk_RSHIFT( index_Q16, 16 ); + + /* Inner product */ + res_Q6 = silk_SMULWB( silk_ADD32( buf_ptr[ 0 ], buf_ptr[ 35 ] ), FIR_Coefs[ 0 ] ); + res_Q6 = silk_SMLAWB( res_Q6, silk_ADD32( buf_ptr[ 1 ], buf_ptr[ 34 ] ), FIR_Coefs[ 1 ] ); + res_Q6 = silk_SMLAWB( res_Q6, silk_ADD32( buf_ptr[ 2 ], buf_ptr[ 33 ] ), FIR_Coefs[ 2 ] ); + res_Q6 = silk_SMLAWB( res_Q6, silk_ADD32( buf_ptr[ 3 ], buf_ptr[ 32 ] ), FIR_Coefs[ 3 ] ); + res_Q6 = silk_SMLAWB( res_Q6, silk_ADD32( buf_ptr[ 4 ], buf_ptr[ 31 ] ), FIR_Coefs[ 4 ] ); + res_Q6 = silk_SMLAWB( res_Q6, silk_ADD32( buf_ptr[ 5 ], buf_ptr[ 30 ] ), FIR_Coefs[ 5 ] ); + res_Q6 = silk_SMLAWB( res_Q6, silk_ADD32( buf_ptr[ 6 ], buf_ptr[ 29 ] ), FIR_Coefs[ 6 ] ); + res_Q6 = silk_SMLAWB( res_Q6, silk_ADD32( buf_ptr[ 7 ], buf_ptr[ 28 ] ), FIR_Coefs[ 7 ] ); + res_Q6 = silk_SMLAWB( res_Q6, silk_ADD32( buf_ptr[ 8 ], buf_ptr[ 27 ] ), FIR_Coefs[ 8 ] ); + res_Q6 = silk_SMLAWB( res_Q6, silk_ADD32( buf_ptr[ 9 ], buf_ptr[ 26 ] ), FIR_Coefs[ 9 ] ); + res_Q6 = silk_SMLAWB( res_Q6, silk_ADD32( buf_ptr[ 10 ], buf_ptr[ 25 ] ), FIR_Coefs[ 10 ] ); + res_Q6 = silk_SMLAWB( res_Q6, silk_ADD32( buf_ptr[ 11 ], buf_ptr[ 24 ] ), FIR_Coefs[ 11 ] ); + res_Q6 = silk_SMLAWB( res_Q6, silk_ADD32( buf_ptr[ 12 ], buf_ptr[ 23 ] ), FIR_Coefs[ 12 ] ); + res_Q6 = silk_SMLAWB( res_Q6, silk_ADD32( buf_ptr[ 13 ], buf_ptr[ 22 ] ), FIR_Coefs[ 13 ] ); + res_Q6 = silk_SMLAWB( res_Q6, silk_ADD32( buf_ptr[ 14 ], buf_ptr[ 21 ] ), FIR_Coefs[ 14 ] ); + res_Q6 = silk_SMLAWB( res_Q6, silk_ADD32( buf_ptr[ 15 ], buf_ptr[ 20 ] ), FIR_Coefs[ 15 ] ); + res_Q6 = silk_SMLAWB( res_Q6, silk_ADD32( buf_ptr[ 16 ], buf_ptr[ 19 ] ), FIR_Coefs[ 16 ] ); + res_Q6 = silk_SMLAWB( res_Q6, silk_ADD32( buf_ptr[ 17 ], buf_ptr[ 18 ] ), FIR_Coefs[ 17 ] ); + + /* Scale down, saturate and store in output array */ + *out++ = (opus_int16)silk_SAT16( silk_RSHIFT_ROUND( res_Q6, 6 ) ); + } + break; + default: + silk_assert( 0 ); } return out; } - -/* Resample with a 2x downsampler (optional), a 2nd order AR filter followed by FIR interpolation */ +/* Resample with a 2nd order AR filter followed by FIR interpolation */ void silk_resampler_private_down_FIR( void *SS, /* I/O Resampler state */ opus_int16 out[], /* O Output signal */ @@ -122,12 +151,11 @@ void silk_resampler_private_down_FIR( silk_resampler_state_struct *S = (silk_resampler_state_struct *)SS; opus_int32 nSamplesIn; opus_int32 max_index_Q16, index_increment_Q16; - opus_int16 buf1[ RESAMPLER_MAX_BATCH_SIZE_IN / 2 ]; - opus_int32 buf2[ RESAMPLER_MAX_BATCH_SIZE_IN + RESAMPLER_DOWN_ORDER_FIR ]; + opus_int32 buf[ RESAMPLER_MAX_BATCH_SIZE_IN + SILK_RESAMPLER_MAX_FIR_ORDER ]; const opus_int16 *FIR_Coefs; /* Copy buffered samples to start of buffer */ - silk_memcpy( buf2, S->sFIR, RESAMPLER_DOWN_ORDER_FIR * sizeof( opus_int32 ) ); + silk_memcpy( buf, S->sFIR, S->FIR_Order * sizeof( opus_int32 ) ); FIR_Coefs = &S->Coefs[ 2 ]; @@ -136,40 +164,26 @@ void silk_resampler_private_down_FIR( while( 1 ) { nSamplesIn = silk_min( inLen, S->batchSize ); - if( S->input2x == 1 ) { - /* Downsample 2x */ - silk_resampler_down2( S->sDown2, buf1, in, nSamplesIn ); - - nSamplesIn = silk_RSHIFT32( nSamplesIn, 1 ); - - /* Second-order AR filter (output in Q8) */ - silk_resampler_private_AR2( S->sIIR, &buf2[ RESAMPLER_DOWN_ORDER_FIR ], buf1, S->Coefs, nSamplesIn ); - } else { - /* Second-order AR filter (output in Q8) */ - silk_resampler_private_AR2( S->sIIR, &buf2[ RESAMPLER_DOWN_ORDER_FIR ], in, S->Coefs, nSamplesIn ); - } + /* Second-order AR filter (output in Q8) */ + silk_resampler_private_AR2( S->sIIR, &buf[ S->FIR_Order ], in, S->Coefs, nSamplesIn ); max_index_Q16 = silk_LSHIFT32( nSamplesIn, 16 ); /* Interpolate filtered signal */ - if( S->FIR_Fracs == 1 ) { - out = silk_resampler_private_down_FIR_INTERPOL0(out, buf2, FIR_Coefs, max_index_Q16, index_increment_Q16); - } else { - out = silk_resampler_private_down_FIR_INTERPOL1(out, buf2, FIR_Coefs, max_index_Q16, index_increment_Q16, S->FIR_Fracs); - } + out = silk_resampler_private_down_FIR_INTERPOL( out, buf, FIR_Coefs, S->FIR_Order, + S->FIR_Fracs, max_index_Q16, index_increment_Q16 ); - in += nSamplesIn << S->input2x; - inLen -= nSamplesIn << S->input2x; + in += nSamplesIn; + inLen -= nSamplesIn; - if( inLen > S->input2x ) { + if( inLen > 1 ) { /* More iterations to do; copy last part of filtered signal to beginning of buffer */ - silk_memcpy( buf2, &buf2[ nSamplesIn ], RESAMPLER_DOWN_ORDER_FIR * sizeof( opus_int32 ) ); + silk_memcpy( buf, &buf[ nSamplesIn ], S->FIR_Order * sizeof( opus_int32 ) ); } else { break; } } /* Copy last part of filtered signal to the state for the next call */ - silk_memcpy( S->sFIR, &buf2[ nSamplesIn ], RESAMPLER_DOWN_ORDER_FIR * sizeof( opus_int32 ) ); + silk_memcpy( S->sFIR, &buf[ nSamplesIn ], S->FIR_Order * sizeof( opus_int32 ) ); } - diff --git a/silk/resampler_private_up2_HQ.c b/silk/resampler_private_up2_HQ.c index 05e6afb3..09dc9c7d 100644 --- a/silk/resampler_private_up2_HQ.c +++ b/silk/resampler_private_up2_HQ.c @@ -46,9 +46,11 @@ void silk_resampler_private_up2_HQ( opus_int32 in32, out32_1, out32_2, Y, X; silk_assert( silk_resampler_up2_hq_0[ 0 ] > 0 ); - silk_assert( silk_resampler_up2_hq_0[ 1 ] < 0 ); + silk_assert( silk_resampler_up2_hq_0[ 1 ] > 0 ); + silk_assert( silk_resampler_up2_hq_0[ 2 ] < 0 ); silk_assert( silk_resampler_up2_hq_1[ 0 ] > 0 ); - silk_assert( silk_resampler_up2_hq_1[ 1 ] < 0 ); + silk_assert( silk_resampler_up2_hq_1[ 1 ] > 0 ); + silk_assert( silk_resampler_up2_hq_1[ 2 ] < 0 ); /* Internal variables and state are in Q10 format */ for( k = 0; k < len; k++ ) { @@ -63,41 +65,39 @@ void silk_resampler_private_up2_HQ( /* Second all-pass section for even output sample */ Y = silk_SUB32( out32_1, S[ 1 ] ); - X = silk_SMLAWB( Y, Y, silk_resampler_up2_hq_0[ 1 ] ); + X = silk_SMULWB( Y, silk_resampler_up2_hq_0[ 1 ] ); out32_2 = silk_ADD32( S[ 1 ], X ); S[ 1 ] = silk_ADD32( out32_1, X ); - /* Biquad notch filter */ - out32_2 = silk_SMLAWB( out32_2, S[ 5 ], silk_resampler_up2_hq_notch[ 2 ] ); - out32_2 = silk_SMLAWB( out32_2, S[ 4 ], silk_resampler_up2_hq_notch[ 1 ] ); - out32_1 = silk_SMLAWB( out32_2, S[ 4 ], silk_resampler_up2_hq_notch[ 0 ] ); - S[ 5 ] = silk_SUB32( out32_2, S[ 5 ] ); + /* Third all-pass section for even output sample */ + Y = silk_SUB32( out32_2, S[ 2 ] ); + X = silk_SMLAWB( Y, Y, silk_resampler_up2_hq_0[ 2 ] ); + out32_1 = silk_ADD32( S[ 2 ], X ); + S[ 2 ] = silk_ADD32( out32_2, X ); /* Apply gain in Q15, convert back to int16 and store to output */ - out[ 2 * k ] = (opus_int16)silk_SAT16( silk_RSHIFT32( - silk_SMLAWB( 256, out32_1, silk_resampler_up2_hq_notch[ 3 ] ), 9 ) ); + out[ 2 * k ] = (opus_int16)silk_SAT16( silk_RSHIFT_ROUND( out32_1, 10 ) ); /* First all-pass section for odd output sample */ - Y = silk_SUB32( in32, S[ 2 ] ); + Y = silk_SUB32( in32, S[ 3 ] ); X = silk_SMULWB( Y, silk_resampler_up2_hq_1[ 0 ] ); - out32_1 = silk_ADD32( S[ 2 ], X ); - S[ 2 ] = silk_ADD32( in32, X ); + out32_1 = silk_ADD32( S[ 3 ], X ); + S[ 3 ] = silk_ADD32( in32, X ); /* Second all-pass section for odd output sample */ - Y = silk_SUB32( out32_1, S[ 3 ] ); - X = silk_SMLAWB( Y, Y, silk_resampler_up2_hq_1[ 1 ] ); - out32_2 = silk_ADD32( S[ 3 ], X ); - S[ 3 ] = silk_ADD32( out32_1, X ); + Y = silk_SUB32( out32_1, S[ 4 ] ); + X = silk_SMULWB( Y, silk_resampler_up2_hq_1[ 1 ] ); + out32_2 = silk_ADD32( S[ 4 ], X ); + S[ 4 ] = silk_ADD32( out32_1, X ); - /* Biquad notch filter */ - out32_2 = silk_SMLAWB( out32_2, S[ 4 ], silk_resampler_up2_hq_notch[ 2 ] ); - out32_2 = silk_SMLAWB( out32_2, S[ 5 ], silk_resampler_up2_hq_notch[ 1 ] ); - out32_1 = silk_SMLAWB( out32_2, S[ 5 ], silk_resampler_up2_hq_notch[ 0 ] ); - S[ 4 ] = silk_SUB32( out32_2, S[ 4 ] ); + /* Third all-pass section for odd output sample */ + Y = silk_SUB32( out32_2, S[ 5 ] ); + X = silk_SMLAWB( Y, Y, silk_resampler_up2_hq_1[ 2 ] ); + out32_1 = silk_ADD32( S[ 5 ], X ); + S[ 5 ] = silk_ADD32( out32_2, X ); /* Apply gain in Q15, convert back to int16 and store to output */ - out[ 2 * k + 1 ] = (opus_int16)silk_SAT16( silk_RSHIFT32( - silk_SMLAWB( 256, out32_1, silk_resampler_up2_hq_notch[ 3 ] ), 9 ) ); + out[ 2 * k + 1 ] = (opus_int16)silk_SAT16( silk_RSHIFT_ROUND( out32_1, 10 ) ); } } diff --git a/silk/resampler_rom.c b/silk/resampler_rom.c index 15473e09..9c4750c3 100644 --- a/silk/resampler_rom.c +++ b/silk/resampler_rom.c @@ -30,7 +30,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #endif /* Filter coefficients for IIR/FIR polyphase resampling * - * Total size: < 600 Words (1.2 kB) */ + * Total size: 179 Words (358 Bytes) */ #include "resampler_private.h" @@ -39,32 +39,46 @@ const opus_int16 silk_resampler_down2_0 = 9872; const opus_int16 silk_resampler_down2_1 = 39809 - 65536; /* Tables for 2x upsampler, high quality */ -const opus_int16 silk_resampler_up2_hq_0[ 2 ] = { 4280, 33727 - 65536 }; -const opus_int16 silk_resampler_up2_hq_1[ 2 ] = { 16295, 54015 - 65536 }; -const opus_int16 silk_resampler_up2_hq_notch[ 4 ] = { 6554, -3932, 6554, 30573 }; +const opus_int16 silk_resampler_up2_hq_0[ 3 ] = { 1746, 14986, 39083 - 65536 }; +const opus_int16 silk_resampler_up2_hq_1[ 3 ] = { 6854, 25769, 55542 - 65536 }; -/* Tables with IIR and FIR coefficients for fractional downsamplers (90 Words) */ -silk_DWORD_ALIGN const opus_int16 silk_Resampler_3_4_COEFS[ 2 + 3 * RESAMPLER_DOWN_ORDER_FIR / 2 ] = { - -20253, -13986, - 86, 7, -151, 368, -542, 232, 11041, 21904, - 39, 90, -181, 216, -17, -877, 6408, 19695, - 2, 113, -108, 2, 314, -977, 2665, 15787, +/* Matlab code for the notch filter coefficients: */ +/* B = [1, 0.147, 1]; A = [1, 0.107, 0.89]; G = 0.93; freqz(G * B, A, 2^14, 16e3); axis([0, 8000, -10, 1]) */ +/* fprintf('\t%6d, %6d, %6d, %6d\n', round(B(2)*2^16), round(-A(2)*2^16), round((1-A(3))*2^16), round(G*2^15)) */ +const opus_int16 silk_resampler_up2_hq_notch[ 4 ] = { 9634, -7012, 7209, 30474 }; + +/* Tables with IIR and FIR coefficients for fractional downsamplers (123 Words) */ +silk_DWORD_ALIGN const opus_int16 silk_Resampler_3_4_COEFS[ 2 + 3 * RESAMPLER_DOWN_ORDER_FIR0 / 2 ] = { + -20694, -13867, + -49, 64, 17, -157, 353, -496, 163, 11047, 22205, + -39, 6, 91, -170, 186, 23, -896, 6336, 19928, + -19, -36, 102, -89, -24, 328, -951, 2568, 15909, +}; + +silk_DWORD_ALIGN const opus_int16 silk_Resampler_2_3_COEFS[ 2 + 2 * RESAMPLER_DOWN_ORDER_FIR0 / 2 ] = { + -14457, -14019, + 64, 128, -122, 36, 310, -768, 584, 9267, 17733, + 12, 128, 18, -142, 288, -117, -865, 4123, 14459, +}; + +silk_DWORD_ALIGN const opus_int16 silk_Resampler_1_2_COEFS[ 2 + RESAMPLER_DOWN_ORDER_FIR1 / 2 ] = { + 616, -14323, + -10, 39, 58, -46, -84, 120, 184, -315, -541, 1284, 5380, 9024, }; -silk_DWORD_ALIGN const opus_int16 silk_Resampler_2_3_COEFS[ 2 + 2 * RESAMPLER_DOWN_ORDER_FIR / 2 ] = { - -13997, -14120, - 60, -174, 71, 298, -800, 659, 9238, 17461, - 48, -40, -150, 314, -155, -845, 4188, 14293, +silk_DWORD_ALIGN const opus_int16 silk_Resampler_1_3_COEFS[ 2 + RESAMPLER_DOWN_ORDER_FIR2 / 2 ] = { + 16102, -15162, + -13, 0, 20, 26, 5, -31, -43, -4, 65, 90, 7, -157, -248, -44, 593, 1583, 2612, 3271, }; -silk_DWORD_ALIGN const opus_int16 silk_Resampler_1_2_COEFS[ 2 + RESAMPLER_DOWN_ORDER_FIR / 2 ] = { - 1233, -14293, - -91, 162, 169, -342, -505, 1332, 5281, 8742, +silk_DWORD_ALIGN const opus_int16 silk_Resampler_1_4_COEFS[ 2 + RESAMPLER_DOWN_ORDER_FIR2 / 2 ] = { + 22500, -15099, + 3, -14, -20, -15, 2, 25, 37, 25, -16, -71, -107, -79, 50, 292, 623, 982, 1288, 1464, }; -silk_DWORD_ALIGN const opus_int16 silk_Resampler_1_3_COEFS[ 2 + RESAMPLER_DOWN_ORDER_FIR / 2 ] = { - 16306, -14409, - 99, -201, -220, -16, 572, 1483, 2433, 3043, +silk_DWORD_ALIGN const opus_int16 silk_Resampler_1_6_COEFS[ 2 + RESAMPLER_DOWN_ORDER_FIR2 / 2 ] = { + 27540, -15257, + 17, 12, 8, 1, -10, -22, -30, -32, -22, 3, 44, 100, 168, 243, 317, 381, 429, 455, }; silk_DWORD_ALIGN const opus_int16 silk_Resampler_2_3_COEFS_LQ[ 2 + 2 * 2 ] = { @@ -73,150 +87,18 @@ silk_DWORD_ALIGN const opus_int16 silk_Resampler_2_3_COEFS_LQ[ 2 + 2 * 2 ] = { 1567, 8276, }; -/* Table with interplation fractions of 1/288 : 2/288 : 287/288 (432 Words) */ -silk_DWORD_ALIGN const opus_int16 silk_resampler_frac_FIR_144[ 144 ][ RESAMPLER_ORDER_FIR_144 / 2 ] = { - { -25, 58, 32526}, - { -8, -69, 32461}, - { 8, -195, 32393}, - { 25, -318, 32321}, - { 41, -439, 32244}, - { 57, -557, 32163}, - { 72, -673, 32079}, - { 88, -787, 31990}, - { 103, -899, 31897}, - { 118, -1009, 31801}, - { 133, -1116, 31700}, - { 148, -1221, 31596}, - { 162, -1324, 31488}, - { 177, -1424, 31376}, - { 191, -1522, 31260}, - { 205, -1618, 31140}, - { 218, -1712, 31017}, - { 231, -1803, 30890}, - { 245, -1893, 30759}, - { 257, -1980, 30625}, - { 270, -2065, 30487}, - { 282, -2147, 30346}, - { 295, -2228, 30201}, - { 306, -2306, 30052}, - { 318, -2382, 29900}, - { 330, -2456, 29745}, - { 341, -2528, 29586}, - { 352, -2597, 29424}, - { 362, -2664, 29259}, - { 373, -2730, 29090}, - { 383, -2793, 28918}, - { 393, -2854, 28743}, - { 402, -2912, 28565}, - { 411, -2969, 28384}, - { 421, -3024, 28199}, - { 429, -3076, 28012}, - { 438, -3126, 27822}, - { 446, -3175, 27628}, - { 454, -3221, 27432}, - { 462, -3265, 27233}, - { 469, -3307, 27031}, - { 476, -3348, 26826}, - { 483, -3386, 26619}, - { 490, -3422, 26409}, - { 496, -3456, 26196}, - { 502, -3488, 25981}, - { 508, -3518, 25763}, - { 514, -3547, 25543}, - { 519, -3573, 25320}, - { 524, -3597, 25095}, - { 529, -3620, 24867}, - { 533, -3640, 24637}, - { 538, -3659, 24405}, - { 541, -3676, 24171}, - { 545, -3691, 23934}, - { 548, -3704, 23696}, - { 552, -3716, 23455}, - { 554, -3726, 23212}, - { 557, -3733, 22967}, - { 559, -3740, 22721}, - { 561, -3744, 22472}, - { 563, -3747, 22222}, - { 565, -3748, 21970}, - { 566, -3747, 21716}, - { 567, -3745, 21460}, - { 568, -3741, 21203}, - { 568, -3735, 20944}, - { 568, -3728, 20684}, - { 568, -3719, 20422}, - { 568, -3708, 20159}, - { 568, -3697, 19894}, - { 567, -3683, 19628}, - { 566, -3668, 19361}, - { 564, -3652, 19093}, - { 563, -3634, 18823}, - { 561, -3614, 18552}, - { 559, -3594, 18280}, - { 557, -3571, 18008}, - { 554, -3548, 17734}, - { 552, -3523, 17459}, - { 549, -3497, 17183}, - { 546, -3469, 16907}, - { 542, -3440, 16630}, - { 539, -3410, 16352}, - { 535, -3379, 16074}, - { 531, -3346, 15794}, - { 527, -3312, 15515}, - { 522, -3277, 15235}, - { 517, -3241, 14954}, - { 513, -3203, 14673}, - { 507, -3165, 14392}, - { 502, -3125, 14110}, - { 497, -3085, 13828}, - { 491, -3043, 13546}, - { 485, -3000, 13264}, - { 479, -2957, 12982}, - { 473, -2912, 12699}, - { 466, -2867, 12417}, - { 460, -2820, 12135}, - { 453, -2772, 11853}, - { 446, -2724, 11571}, - { 439, -2675, 11289}, - { 432, -2625, 11008}, - { 424, -2574, 10727}, - { 417, -2522, 10446}, - { 409, -2470, 10166}, - { 401, -2417, 9886}, - { 393, -2363, 9607}, - { 385, -2309, 9328}, - { 376, -2253, 9050}, - { 368, -2198, 8773}, - { 359, -2141, 8497}, - { 351, -2084, 8221}, - { 342, -2026, 7946}, - { 333, -1968, 7672}, - { 324, -1910, 7399}, - { 315, -1850, 7127}, - { 305, -1791, 6856}, - { 296, -1731, 6586}, - { 286, -1670, 6317}, - { 277, -1609, 6049}, - { 267, -1548, 5783}, - { 257, -1486, 5517}, - { 247, -1424, 5254}, - { 237, -1362, 4991}, - { 227, -1300, 4730}, - { 217, -1237, 4470}, - { 207, -1174, 4212}, - { 197, -1110, 3956}, - { 187, -1047, 3701}, - { 176, -984, 3448}, - { 166, -920, 3196}, - { 155, -856, 2946}, - { 145, -792, 2698}, - { 134, -728, 2452}, - { 124, -664, 2207}, - { 113, -600, 1965}, - { 102, -536, 1724}, - { 92, -472, 1486}, - { 81, -408, 1249}, - { 70, -345, 1015}, - { 60, -281, 783}, - { 49, -217, 553}, - { 38, -154, 325}, +/* Table with interplation fractions of 1/24, 3/24, 5/24, ... , 23/24 : 23/24 (46 Words) */ +silk_DWORD_ALIGN const opus_int16 silk_resampler_frac_FIR_12[ 12 ][ RESAMPLER_ORDER_FIR_12 / 2 ] = { + { 189, -600, 617, 30567 }, + { 117, -159, -1070, 29704 }, + { 52, 221, -2392, 28276 }, + { -4, 529, -3350, 26341 }, + { -48, 758, -3956, 23973 }, + { -80, 905, -4235, 21254 }, + { -99, 972, -4222, 18278 }, + { -107, 967, -3957, 15143 }, + { -103, 896, -3487, 11950 }, + { -91, 773, -2865, 8798 }, + { -71, 611, -2143, 5784 }, + { -46, 425, -1375, 2996 }, }; diff --git a/silk/resampler_rom.h b/silk/resampler_rom.h index e273d641..c1ff59e0 100644 --- a/silk/resampler_rom.h +++ b/silk/resampler_rom.h @@ -36,27 +36,30 @@ extern "C" #include "typedef.h" #include "resampler_structs.h" -#define RESAMPLER_DOWN_ORDER_FIR 16 -#define RESAMPLER_ORDER_FIR_144 6 +#define RESAMPLER_DOWN_ORDER_FIR0 18 +#define RESAMPLER_DOWN_ORDER_FIR1 24 +#define RESAMPLER_DOWN_ORDER_FIR2 36 +#define RESAMPLER_ORDER_FIR_12 8 -/* Tables for 2x downsampler. Values above 32767 intentionally wrap to a negative value. */ +/* Tables for 2x downsampler */ extern const opus_int16 silk_resampler_down2_0; extern const opus_int16 silk_resampler_down2_1; -/* Tables for 2x upsampler, high quality. Values above 32767 intentionally wrap to a negative value. */ -extern const opus_int16 silk_resampler_up2_hq_0[ 2 ]; -extern const opus_int16 silk_resampler_up2_hq_1[ 2 ]; -extern const opus_int16 silk_resampler_up2_hq_notch[ 4 ]; +/* Tables for 2x upsampler, high quality */ +extern const opus_int16 silk_resampler_up2_hq_0[ 3 ]; +extern const opus_int16 silk_resampler_up2_hq_1[ 3 ]; /* Tables with IIR and FIR coefficients for fractional downsamplers */ -extern const opus_int16 silk_Resampler_3_4_COEFS[ 2 + 3 * RESAMPLER_DOWN_ORDER_FIR / 2 ]; -extern const opus_int16 silk_Resampler_2_3_COEFS[ 2 + 2 * RESAMPLER_DOWN_ORDER_FIR / 2 ]; -extern const opus_int16 silk_Resampler_1_2_COEFS[ 2 + RESAMPLER_DOWN_ORDER_FIR / 2 ]; -extern const opus_int16 silk_Resampler_1_3_COEFS[ 2 + RESAMPLER_DOWN_ORDER_FIR / 2 ]; +extern const opus_int16 silk_Resampler_3_4_COEFS[ 2 + 3 * RESAMPLER_DOWN_ORDER_FIR0 / 2 ]; +extern const opus_int16 silk_Resampler_2_3_COEFS[ 2 + 2 * RESAMPLER_DOWN_ORDER_FIR0 / 2 ]; +extern const opus_int16 silk_Resampler_1_2_COEFS[ 2 + RESAMPLER_DOWN_ORDER_FIR1 / 2 ]; +extern const opus_int16 silk_Resampler_1_3_COEFS[ 2 + RESAMPLER_DOWN_ORDER_FIR2 / 2 ]; +extern const opus_int16 silk_Resampler_1_4_COEFS[ 2 + RESAMPLER_DOWN_ORDER_FIR2 / 2 ]; +extern const opus_int16 silk_Resampler_1_6_COEFS[ 2 + RESAMPLER_DOWN_ORDER_FIR2 / 2 ]; extern const opus_int16 silk_Resampler_2_3_COEFS_LQ[ 2 + 2 * 2 ]; -/* Table with interplation fractions of 1/288 : 2/288 : 287/288 (432 Words) */ -extern const opus_int16 silk_resampler_frac_FIR_144[ 144 ][ RESAMPLER_ORDER_FIR_144 / 2 ]; +/* Table with interplation fractions of 1/24, 3/24, ..., 23/24 */ +extern const opus_int16 silk_resampler_frac_FIR_12[ 12 ][ RESAMPLER_ORDER_FIR_12 / 2 ]; #ifdef __cplusplus } diff --git a/silk/resampler_structs.h b/silk/resampler_structs.h index eb2844df..e5289efd 100644 --- a/silk/resampler_structs.h +++ b/silk/resampler_structs.h @@ -32,18 +32,21 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. extern "C" { #endif -#define SILK_RESAMPLER_MAX_FIR_ORDER 16 +#define SILK_RESAMPLER_MAX_FIR_ORDER 36 #define SILK_RESAMPLER_MAX_IIR_ORDER 6 typedef struct _silk_resampler_state_struct{ opus_int32 sIIR[ SILK_RESAMPLER_MAX_IIR_ORDER ]; /* this must be the first element of this struct */ opus_int32 sFIR[ SILK_RESAMPLER_MAX_FIR_ORDER ]; - opus_int32 sDown2[ 2 ]; - opus_int32 resampler_function; - opus_int32 batchSize; + opus_int16 delayBuf[ 48 ]; + opus_int resampler_function; + opus_int batchSize; opus_int32 invRatio_Q16; - opus_int32 FIR_Fracs; - opus_int32 input2x; + opus_int FIR_Order; + opus_int FIR_Fracs; + opus_int Fs_in_kHz; + opus_int Fs_out_kHz; + opus_int inputDelay; const opus_int16 *Coefs; } silk_resampler_state_struct; diff --git a/silk/stereo_LR_to_MS.c b/silk/stereo_LR_to_MS.c index df600e68..bc203941 100644 --- a/silk/stereo_LR_to_MS.c +++ b/silk/stereo_LR_to_MS.c @@ -198,9 +198,9 @@ void silk_stereo_LR_to_MS( pred0_Q13 += delta0_Q13; pred1_Q13 += delta1_Q13; w_Q24 += deltaw_Q24; - sum = silk_LSHIFT( silk_ADD_LSHIFT( mid[ n ] + mid[ n + 2 ], mid[ n + 1 ], 1 ), 9 ); /* Q11 */ - sum = silk_SMLAWB( silk_SMULWB( w_Q24, side[ n + 1 ] ), sum, pred0_Q13 ); /* Q8 */ - sum = silk_SMLAWB( sum, silk_LSHIFT( ( opus_int32 )mid[ n + 1 ], 11 ), pred1_Q13 ); /* Q8 */ + sum = silk_LSHIFT( silk_ADD_LSHIFT( mid[ n ] + mid[ n + 2 ], mid[ n + 1 ], 1 ), 9 ); /* Q11 */ + sum = silk_SMLAWB( silk_SMULWB( w_Q24, side[ n + 1 ] ), sum, pred0_Q13 ); /* Q8 */ + sum = silk_SMLAWB( sum, silk_LSHIFT( (opus_int32)mid[ n + 1 ], 11 ), pred1_Q13 ); /* Q8 */ x2[ n - 1 ] = (opus_int16)silk_SAT16( silk_RSHIFT_ROUND( sum, 8 ) ); } @@ -208,9 +208,9 @@ void silk_stereo_LR_to_MS( pred1_Q13 = -pred_Q13[ 1 ]; w_Q24 = silk_LSHIFT( width_Q14, 10 ); for( n = STEREO_INTERP_LEN_MS * fs_kHz; n < frame_length; n++ ) { - sum = silk_LSHIFT( silk_ADD_LSHIFT( mid[ n ] + mid[ n + 2 ], mid[ n + 1 ], 1 ), 9 ); /* Q11 */ - sum = silk_SMLAWB( silk_SMULWB( w_Q24, side[ n + 1 ] ), sum, pred0_Q13 ); /* Q8 */ - sum = silk_SMLAWB( sum, silk_LSHIFT( ( opus_int32 )mid[ n + 1 ], 11 ), pred1_Q13 ); /* Q8 */ + sum = silk_LSHIFT( silk_ADD_LSHIFT( mid[ n ] + mid[ n + 2 ], mid[ n + 1 ], 1 ), 9 ); /* Q11 */ + sum = silk_SMLAWB( silk_SMULWB( w_Q24, side[ n + 1 ] ), sum, pred0_Q13 ); /* Q8 */ + sum = silk_SMLAWB( sum, silk_LSHIFT( (opus_int32)mid[ n + 1 ], 11 ), pred1_Q13 ); /* Q8 */ x2[ n - 1 ] = (opus_int16)silk_SAT16( silk_RSHIFT_ROUND( sum, 8 ) ); } state->pred_prev_Q13[ 0 ] = (opus_int16)pred_Q13[ 0 ]; diff --git a/silk/stereo_MS_to_LR.c b/silk/stereo_MS_to_LR.c index e95e47b5..a9f105b5 100644 --- a/silk/stereo_MS_to_LR.c +++ b/silk/stereo_MS_to_LR.c @@ -59,17 +59,17 @@ void silk_stereo_MS_to_LR( for( n = 0; n < STEREO_INTERP_LEN_MS * fs_kHz; n++ ) { pred0_Q13 += delta0_Q13; pred1_Q13 += delta1_Q13; - sum = silk_LSHIFT( silk_ADD_LSHIFT( x1[ n ] + x1[ n + 2 ], x1[ n + 1 ], 1 ), 9 ); /* Q11 */ - sum = silk_SMLAWB( silk_LSHIFT( ( opus_int32 )x2[ n + 1 ], 8 ), sum, pred0_Q13 ); /* Q8 */ - sum = silk_SMLAWB( sum, silk_LSHIFT( ( opus_int32 )x1[ n + 1 ], 11 ), pred1_Q13 ); /* Q8 */ + sum = silk_LSHIFT( silk_ADD_LSHIFT( x1[ n ] + x1[ n + 2 ], x1[ n + 1 ], 1 ), 9 ); /* Q11 */ + sum = silk_SMLAWB( silk_LSHIFT( (opus_int32)x2[ n + 1 ], 8 ), sum, pred0_Q13 ); /* Q8 */ + sum = silk_SMLAWB( sum, silk_LSHIFT( (opus_int32)x1[ n + 1 ], 11 ), pred1_Q13 ); /* Q8 */ x2[ n + 1 ] = (opus_int16)silk_SAT16( silk_RSHIFT_ROUND( sum, 8 ) ); } pred0_Q13 = pred_Q13[ 0 ]; pred1_Q13 = pred_Q13[ 1 ]; for( n = STEREO_INTERP_LEN_MS * fs_kHz; n < frame_length; n++ ) { - sum = silk_LSHIFT( silk_ADD_LSHIFT( x1[ n ] + x1[ n + 2 ], x1[ n + 1 ], 1 ), 9 ); /* Q11 */ - sum = silk_SMLAWB( silk_LSHIFT( ( opus_int32 )x2[ n + 1 ], 8 ), sum, pred0_Q13 ); /* Q8 */ - sum = silk_SMLAWB( sum, silk_LSHIFT( ( opus_int32 )x1[ n + 1 ], 11 ), pred1_Q13 ); /* Q8 */ + sum = silk_LSHIFT( silk_ADD_LSHIFT( x1[ n ] + x1[ n + 2 ], x1[ n + 1 ], 1 ), 9 ); /* Q11 */ + sum = silk_SMLAWB( silk_LSHIFT( (opus_int32)x2[ n + 1 ], 8 ), sum, pred0_Q13 ); /* Q8 */ + sum = silk_SMLAWB( sum, silk_LSHIFT( (opus_int32)x1[ n + 1 ], 11 ), pred1_Q13 ); /* Q8 */ x2[ n + 1 ] = (opus_int16)silk_SAT16( silk_RSHIFT_ROUND( sum, 8 ) ); } state->pred_prev_Q13[ 0 ] = pred_Q13[ 0 ]; diff --git a/silk/structs.h b/silk/structs.h index 9f7fd298..338281b8 100644 --- a/silk/structs.h +++ b/silk/structs.h @@ -150,7 +150,6 @@ typedef struct { opus_int minInternal_fs_Hz; /* Minimum internal sampling frequency (Hz) */ opus_int desiredInternal_fs_Hz; /* Soft request for internal sampling frequency (Hz) */ opus_int fs_kHz; /* Internal sampling frequency (kHz) */ - opus_int delay; /* Number of samples of delay to apply */ opus_int nb_subfr; /* Number of 5 ms subframes in a frame */ opus_int frame_length; /* Frame length (samples) */ opus_int subfr_length; /* Subframe length (samples) */ @@ -194,7 +193,6 @@ typedef struct { /* Input/output buffering */ opus_int16 inputBuf[ MAX_FRAME_LENGTH + 2 ]; /* Buffer containing input signal */ - opus_int16 delayBuf[MAX_ENCODER_DELAY]; opus_int inputBufIx; opus_int nFramesPerPacket; opus_int nFramesEncoded; /* Number of frames analyzed in current packet */ @@ -261,8 +259,6 @@ typedef struct { opus_int32 exc_Q10[ MAX_FRAME_LENGTH ]; opus_int32 sLPC_Q14_buf[ MAX_LPC_ORDER ]; opus_int16 outBuf[ MAX_FRAME_LENGTH + 2 * MAX_SUB_FRAME_LENGTH ]; /* Buffer for output signal */ - opus_int16 delayBuf[ MAX_DECODER_DELAY ]; /* Buffer for delaying the SILK output prior to resampling */ - opus_int delay; /* How much decoder delay to add */ opus_int lagPrev; /* Previous Lag */ opus_int8 LastGainIndex; /* Previous gain index */ opus_int fs_kHz; /* Sampling frequency in kHz */ diff --git a/silk/tuning_parameters.h b/silk/tuning_parameters.h index d42a9639..ff0d0b68 100644 --- a/silk/tuning_parameters.h +++ b/silk/tuning_parameters.h @@ -51,13 +51,11 @@ extern "C" /*********************/ /* LPC analysis defines: regularization and bandwidth expansion */ -#define FIND_LPC_COND_FAC 2.5e-5f -#define FIND_LPC_CHIRP 0.99995f -#define FIND_LPC_CHIRP_FIRST_FRAME 0.96f +#define FIND_LPC_COND_FAC 1e-5f /* LTP analysis defines */ #define FIND_LTP_COND_FAC 1e-5f -#define LTP_DAMPING 0.01f +#define LTP_DAMPING 0.05f #define LTP_SMOOTHING 0.1f /* LTP quantization settings */ @@ -108,7 +106,7 @@ extern "C" #define WARPING_MULTIPLIER 0.015f /* fraction added to first autocorrelation value */ -#define SHAPE_WHITE_NOISE_FRACTION 1e-5f +#define SHAPE_WHITE_NOISE_FRACTION 5e-5f /* noise shaping filter chirp factor */ #define BANDWIDTH_EXPANSION 0.95f |