ref: bf75c8ec4d0dded188bc7793de6da56c7ff0be1c
parent: 6619a736376221f2782cecff55d051c3ecfc2ff7
author: Koen Vos <[email protected]>
date: Tue Dec 13 09:47:31 EST 2011
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
--- a/silk/CNG.c
+++ b/silk/CNG.c
@@ -54,7 +54,7 @@
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 @@
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 @@
/* 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 @@
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 */
--- a/silk/LPC_analysis_filter.c
+++ b/silk/LPC_analysis_filter.c
@@ -77,7 +77,7 @@
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 */
--- a/silk/LPC_inv_pred_gain.c
+++ b/silk/LPC_inv_pred_gain.c
@@ -38,24 +38,22 @@
/* 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 @@
/* 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 @@
/* 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 @@
/* 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,7 +114,7 @@
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 ];
@@ -125,23 +121,20 @@
/* 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 @@
/* 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
--- a/silk/MacroDebug.h
+++ b/silk/MacroDebug.h
@@ -91,7 +91,7 @@
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;
}
@@ -98,10 +98,10 @@
#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;
}
@@ -108,7 +108,7 @@
#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,7 +126,7 @@
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;
}
@@ -133,10 +133,10 @@
#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;
}
@@ -143,7 +143,7 @@
#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)) );
--- a/silk/NLSF2A.c
+++ b/silk/NLSF2A.c
@@ -83,7 +83,7 @@
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 @@
}
}
- 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 @@
}
}
- 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;
--- a/silk/NLSF_VQ.c
+++ b/silk/NLSF_VQ.c
@@ -51,11 +51,11 @@
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 );
--- a/silk/NLSF_decode.c
+++ b/silk/NLSF_decode.c
@@ -77,7 +77,7 @@
/* 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 @@
/* 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 );
}
--- a/silk/NLSF_encode.c
+++ b/silk/NLSF_encode.c
@@ -79,7 +79,7 @@
/* 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 @@
/* 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 @@
/* 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 */
--- a/silk/NSQ.c
+++ b/silk/NSQ.c
@@ -34,10 +34,10 @@
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 @@
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 @@
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 @@
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 @@
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 @@
/* 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 @@
}
}
- 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 @@
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,7 +187,7 @@
)
{
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;
@@ -194,9 +194,9 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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_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 @@
)
{
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 @@
/* 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 @@
/* 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;
}
--- a/silk/NSQ_del_dec.c
+++ b/silk/NSQ_del_dec.c
@@ -32,7 +32,7 @@
#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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
/* 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 @@
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 @@
}
}
- 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 @@
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 @@
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 @@
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 @@
{
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 @@
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,14 +342,14 @@
/* 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 */
@@ -355,11 +356,11 @@
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 @@
/* 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 @@
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 @@
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 @@
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 @@
/* 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 @@
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 @@
)
{
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 @@
/* 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 @@
/* 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 */
--- a/silk/PLC.c
+++ b/silk/PLC.c
@@ -192,7 +192,7 @@
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 @@
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 @@
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 @@
/* 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 @@
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 */
--- a/silk/PLC.h
+++ b/silk/PLC.h
@@ -25,8 +25,8 @@
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"
--- a/silk/SigProc_FIX.h
+++ b/silk/SigProc_FIX.h
@@ -52,9 +52,10 @@
* 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 */
);
/*!
@@ -61,10 +62,10 @@
* 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 @@
/* 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 @@
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 @@
#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 */
--- a/silk/VAD.c
+++ b/silk/VAD.c
@@ -204,7 +204,7 @@
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 */
--- a/silk/control_codec.c
+++ b/silk/control_codec.c
@@ -38,13 +38,6 @@
#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 @@
{
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 @@
#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 @@
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 @@
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 @@
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 @@
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 @@
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 );
--- a/silk/dec_API.c
+++ b/silk/dec_API.c
@@ -83,9 +83,9 @@
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 @@
}
}
- 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,9 +261,9 @@
} 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++;
}
@@ -273,11 +270,11 @@
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 @@
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 ) {
--- a/silk/decode_core.c
+++ b/silk/decode_core.c
@@ -41,11 +41,11 @@
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 @@
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 @@
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 @@
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 @@
/* 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 @@
}
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,8 +195,13 @@
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 */
@@ -203,9 +208,10 @@
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;
--- a/silk/decode_parameters.c
+++ b/silk/decode_parameters.c
@@ -72,8 +72,7 @@
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 ) );
--- a/silk/decoder_set_fs.c
+++ b/silk/decoder_set_fs.c
@@ -31,13 +31,6 @@
#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_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 @@
}
/* 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 );
--- a/silk/define.h
+++ b/silk/define.h
@@ -91,9 +91,6 @@
#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 @@
#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
--- a/silk/enc_API.c
+++ b/silk/enc_API.c
@@ -140,10 +140,10 @@
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 @@
}
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 @@
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 @@
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 @@
+ 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;
}
--- a/silk/fixed/LTP_analysis_filter_FIX.c
+++ b/silk/fixed/LTP_analysis_filter_FIX.c
@@ -69,7 +69,7 @@
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 ] );
--- a/silk/fixed/LTP_scale_ctrl_FIX.c
+++ b/silk/fixed/LTP_scale_ctrl_FIX.c
@@ -40,16 +40,11 @@
{
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;
--- a/silk/fixed/burg_modified_FIX.c
+++ b/silk/fixed/burg_modified_FIX.c
@@ -30,9 +30,10 @@
#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,27 +46,23 @@
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 );
if( rshifts > MAX_RSHIFTS ) {
@@ -84,6 +81,7 @@
}
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 @@
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 @@
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*/
+ 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;
+ }
+
/* 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;
+ }
}
--- a/silk/fixed/encode_frame_FIX.c
+++ b/silk/fixed/encode_frame_FIX.c
@@ -36,7 +36,7 @@
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 @@
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 @@
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 @@
/*****************************************/
/* 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 @@
/* 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 @@
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 @@
/* 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 );
--- a/silk/fixed/find_LPC_FIX.c
+++ b/silk/fixed/find_LPC_FIX.c
@@ -34,18 +34,13 @@
/* 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,28 +51,20 @@
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 );
+ silk_burg_modified( &res_nrg, &res_nrg_Q, a_Q16, x, minInvGain_Q30, subfr_length, psEncC->nb_subfr, psEncC->predictLPCOrder );
- 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 ) {
-
+ 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_burg_modified( &res_tmp_nrg, &res_tmp_nrg_Q, a_tmp_Q16, x + 2 * subfr_length, minInvGain_Q30, subfr_length, 2, psEncC->predictLPCOrder );
- silk_bwexpander_32( a_tmp_Q16, LPC_order, SILK_FIX_CONST( FIND_LPC_CHIRP, 16 ) );
-
/* 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 */
shift = res_tmp_nrg_Q - res_nrg_Q;
@@ -92,21 +79,21 @@
}
/* 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 @@
/* 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 ) );
}
--- a/silk/fixed/find_LTP_FIX.c
+++ b/silk/fixed/find_LTP_FIX.c
@@ -113,7 +113,7 @@
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 @@
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 @@
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 @@
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 ) );
}
}
--- a/silk/fixed/find_pitch_lags_FIX.c
+++ b/silk/fixed/find_pitch_lags_FIX.c
@@ -50,7 +50,7 @@
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 @@
/* 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 @@
/*****************************************/
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 {
--- a/silk/fixed/find_pred_coefs_FIX.c
+++ b/silk/fixed/find_pred_coefs_FIX.c
@@ -45,7 +45,7 @@
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 @@
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 );
--- a/silk/fixed/main_FIX.h
+++ b/silk/fixed/main_FIX.h
@@ -92,7 +92,7 @@
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 @@
/* 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 */
--- a/silk/fixed/noise_shape_analysis_FIX.c
+++ b/silk/fixed/noise_shape_analysis_FIX.c
@@ -166,12 +166,12 @@
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 @@
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 );
--- a/silk/fixed/pitch_analysis_core_FIX.c
+++ b/silk/fixed/pitch_analysis_core_FIX.c
@@ -116,7 +116,7 @@
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 @@
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 @@
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;
--- a/silk/fixed/prefilter_FIX.c
+++ b/silk/fixed/prefilter_FIX.c
@@ -36,7 +36,7 @@
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 @@
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,7 +81,7 @@
}
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 );
}
}
@@ -88,7 +88,7 @@
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 @@
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 @@
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 @@
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 @@
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 */
--- a/silk/fixed/residual_energy16_FIX.c
+++ b/silk/fixed/residual_energy16_FIX.c
@@ -57,7 +57,7 @@
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 );
--- a/silk/fixed/schur_FIX.c
+++ b/silk/fixed/schur_FIX.c
@@ -76,7 +76,7 @@
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++ ) {
--- a/silk/fixed/structs_FIX.h
+++ b/silk/fixed/structs_FIX.h
@@ -56,7 +56,7 @@
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 @@
/* 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;
/************************/
--- a/silk/fixed/warped_autocorrelation_FIX.c
+++ b/silk/fixed/warped_autocorrelation_FIX.c
@@ -55,7 +55,7 @@
/* 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 @@
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*/
--- a/silk/float/LPC_inv_pred_gain_FLP.c
+++ b/silk/float/LPC_inv_pred_gain_FLP.c
@@ -37,14 +37,13 @@
/* 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;
@@ -51,15 +50,15 @@
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 @@
}
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;
}
--- a/silk/float/LTP_scale_ctrl_FLP.c
+++ b/silk/float/LTP_scale_ctrl_FLP.c
@@ -39,19 +39,14 @@
{
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;
}
--- a/silk/float/SigProc_FLP.h
+++ b/silk/float/SigProc_FLP.h
@@ -50,8 +50,7 @@
/* 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 @@
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 */
);
--- a/silk/float/burg_modified_FLP.c
+++ b/silk/float/burg_modified_FLP.c
@@ -30,29 +30,29 @@
#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_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 @@
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 @@
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 @@
}
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 @@
}
}
- /* 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;
}
--- a/silk/float/encode_frame_FLP.c
+++ b/silk/float/encode_frame_FLP.c
@@ -104,8 +104,8 @@
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 @@
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;
--- a/silk/float/find_LPC_FLP.c
+++ b/silk/float/find_LPC_FLP.c
@@ -29,73 +29,63 @@
#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 );
+ res_nrg = silk_burg_modified_FLP( a, x, minInvGain, subfr_length, psEncC->nb_subfr, psEncC->predictLPCOrder );
- if( firstFrameAfterReset ) {
- silk_bwexpander_FLP( a, LPC_order, FIND_LPC_CHIRP_FIRST_FRAME );
- } else {
- silk_bwexpander_FLP( a_tmp, LPC_order, FIND_LPC_CHIRP );
- }
-
- 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 );
+ res_nrg -= silk_burg_modified_FLP( a_tmp, x + ( MAX_NB_SUBFR / 2 ) * subfr_length, minInvGain, subfr_length, MAX_NB_SUBFR / 2, psEncC->predictLPCOrder );
- silk_bwexpander_FLP( a_tmp, LPC_order, FIND_LPC_CHIRP );
-
/* 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 @@
}
}
- 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 ) );
}
--- a/silk/float/find_pitch_lags_FLP.c
+++ b/silk/float/find_pitch_lags_FLP.c
@@ -50,7 +50,7 @@
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;
--- a/silk/float/find_pred_coefs_FLP.c
+++ b/silk/float/find_pred_coefs_FLP.c
@@ -46,6 +46,7 @@
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 @@
/* 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 @@
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 );
--- a/silk/float/main_FLP.h
+++ b/silk/float/main_FLP.h
@@ -143,15 +143,10 @@
/* 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 */
--- a/silk/float/noise_shape_analysis_FLP.c
+++ b/silk/float/noise_shape_analysis_FLP.c
@@ -151,7 +151,7 @@
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 @@
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 */
--- a/silk/float/pitch_analysis_core_FLP.c
+++ b/silk/float/pitch_analysis_core_FLP.c
@@ -115,7 +115,7 @@
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 @@
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 @@
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;
--- a/silk/float/prefilter_FLP.c
+++ b/silk/float/prefilter_FLP.c
@@ -108,7 +108,7 @@
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;
--- a/silk/float/process_gains_FLP.c
+++ b/silk/float/process_gains_FLP.c
@@ -64,7 +64,7 @@
/* 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 */
--- a/silk/float/structs_FLP.h
+++ b/silk/float/structs_FLP.h
@@ -72,10 +72,6 @@
/* 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;
/************************/
--- a/silk/float/wrappers_FLP.c
+++ b/silk/float/wrappers_FLP.c
@@ -102,7 +102,7 @@
)
{
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 @@
/* 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 @@
}
/* 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 );
}
}
--- a/silk/interpolate.c
+++ b/silk/interpolate.c
@@ -46,6 +46,6 @@
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 );
}
}
--- a/silk/macros.h
+++ b/silk/macros.h
@@ -25,9 +25,13 @@
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. */
/* (a32 * (opus_int32)((opus_int16)(b32))) >> 16 output have to be 32bit int */
@@ -128,5 +132,5 @@
#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 */
--- a/silk/main.h
+++ b/silk/main.h
@@ -38,9 +38,6 @@
#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 @@
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 @@
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 */
--- a/silk/quant_LTP_gains.c
+++ b/silk/quant_LTP_gains.c
@@ -59,7 +59,7 @@
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;
--- a/silk/resampler.c
+++ b/silk/resampler.c
@@ -29,30 +29,46 @@
#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
+ * 24 AF D AF C U
+ * 48 AF AF AF D C
*
- * default method: UF
- *
* 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 @@
/* 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 @@
} 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 @@
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 @@
}
/* 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;
}
--- a/silk/resampler_down2.c
+++ b/silk/resampler_down2.c
@@ -32,7 +32,7 @@
#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 ] */
--- a/silk/resampler_private.h
+++ b/silk/resampler_private.h
@@ -25,8 +25,8 @@
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 @@
#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 @@
#ifdef __cplusplus
}
#endif
-#endif /* SILK_RESAMPLER_H */
+#endif /* SILK_RESAMPLER_PRIVATE_H */
--- a/silk/resampler_private_IIR_FIR.c
+++ b/silk/resampler_private_IIR_FIR.c
@@ -45,15 +45,17 @@
/* 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,10 +71,10 @@
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;
@@ -79,18 +81,17 @@
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;
}
@@ -97,6 +98,6 @@
}
/* 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 ) );
}
--- a/silk/resampler_private_down_FIR.c
+++ b/silk/resampler_private_down_FIR.c
@@ -32,10 +32,12 @@
#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
)
@@ -42,76 +44,103 @@
{
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 );
+ 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 );
- /* 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 ] );
+ /* Fractional part gives interpolation coefficients */
+ interpol_ind = silk_SMULWB( index_Q16 & 0xFFFF, FIR_Fracs );
- /* Scale down, saturate and store in output array */
- *out++ = (opus_int16)silk_SAT16( silk_RSHIFT_ROUND( res_Q6, 6 ) );
- }
- return out;
-}
+ /* 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 ] );
-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;
+ /* 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 );
- 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[ 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 ] );
- /* Fractional part gives interpolation coefficients */
- interpol_ind = silk_SMULWB( index_Q16 & 0xFFFF, FIR_Fracs );
+ /* 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 */
- 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 ] );
+ /* 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 ) );
+ /* 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 @@
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,34 +164,21 @@
while( 1 ) {
nSamplesIn = silk_min( inLen, S->batchSize );
- if( S->input2x == 1 ) {
- /* Downsample 2x */
- silk_resampler_down2( S->sDown2, buf1, in, nSamplesIn );
+ /* Second-order AR filter (output in Q8) */
+ silk_resampler_private_AR2( S->sIIR, &buf[ S->FIR_Order ], in, S->Coefs, 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 );
- }
-
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;
}
@@ -170,6 +185,5 @@
}
/* 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 ) );
}
-
--- a/silk/resampler_private_up2_HQ.c
+++ b/silk/resampler_private_up2_HQ.c
@@ -46,9 +46,11 @@
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 @@
/* 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 ) );
}
}
--- a/silk/resampler_rom.c
+++ b/silk/resampler_rom.c
@@ -30,7 +30,7 @@
#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,34 +39,48 @@
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_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_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_FIR / 2 ] = {
- 1233, -14293,
- -91, 162, 169, -342, -505, 1332, 5281, 8742,
+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_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_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_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_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 ] = {
-2797, -6507,
4697, 10739,
@@ -73,150 +87,18 @@
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 },
};
--- a/silk/resampler_rom.h
+++ b/silk/resampler_rom.h
@@ -36,27 +36,30 @@
#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
}
--- a/silk/resampler_structs.h
+++ b/silk/resampler_structs.h
@@ -32,18 +32,21 @@
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;
--- a/silk/stereo_LR_to_MS.c
+++ b/silk/stereo_LR_to_MS.c
@@ -198,9 +198,9 @@
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 @@
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 ];
--- a/silk/stereo_MS_to_LR.c
+++ b/silk/stereo_MS_to_LR.c
@@ -59,17 +59,17 @@
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 ];
--- a/silk/structs.h
+++ b/silk/structs.h
@@ -150,7 +150,6 @@
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 @@
/* 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 @@
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 */
--- a/silk/tuning_parameters.h
+++ b/silk/tuning_parameters.h
@@ -51,13 +51,11 @@
/*********************/
/* 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 @@
#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
--- a/src/opus_encoder.c
+++ b/src/opus_encoder.c
@@ -126,10 +126,6 @@
{ 48000, 24000}, /* stereo */
};
-static const int celt_delay_table[5] = {
-/* API 8 12 16 24 48 */
- 10, 16, 21, 27, 55
-};
int opus_encoder_get_size(int channels)
{
int silkEncSizeBytes, celtEncSizeBytes;
@@ -209,11 +205,11 @@
st->voice_ratio = -1;
st->encoder_buffer = st->Fs/100;
- st->delay_compensation = st->Fs/400;
+ /* Delay compensation of 4 ms (2.5 ms for SILK's extra look-ahead
+ + 1.5 ms for SILK resamplers and stereo prediction) */
+ st->delay_compensation = st->Fs/250;
- st->delay_compensation += celt_delay_table[rateID(st->Fs)];
-
- st->hybrid_stereo_width_Q14 = 1 << 14;
+ st->hybrid_stereo_width_Q14 = 1 << 14;
st->variable_HP_smth2_Q15 = silk_LSHIFT( silk_lin2log( VARIABLE_HP_MIN_CUTOFF_HZ ), 8 );
st->first = 1;
st->mode = MODE_HYBRID;
--- a/win32/config.h
+++ b/win32/config.h
@@ -1,21 +1,21 @@
-#ifndef CONFIG_H
-#define CONFIG_H
-
-#define CELT_BUILD 1
-
-#define restrict
-#define inline __inline
-
-#define USE_ALLOCA 1
-
-/* Comment out the next line for floating-point code */
-/*#define FIXED_POINT 1 */
-
-#define OPUS_BUILD 1
-
-/* Get rid of the CELT VS compile warnings */
-#if 1
-#pragma warning(disable : 4996)/* This function or variable may be unsafe. Consider using fopen_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details. */
-#endif
-
-#endif CONFIG_H
+#ifndef CONFIG_H
+#define CONFIG_H
+
+#define CELT_BUILD 1
+
+#define restrict
+#define inline __inline
+
+#define USE_ALLOCA 1
+
+/* Comment out the next line for floating-point code */
+/*#define FIXED_POINT 1 */
+
+#define OPUS_BUILD 1
+
+/* Get rid of the CELT VS compile warnings */
+#if 1
+#pragma warning(disable : 4996)/* This function or variable may be unsafe. Consider using fopen_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details. */
+#endif
+
+#endif CONFIG_H