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
This commit is contained in:
Koen Vos 2011-12-13 14:47:31 -05:00 committed by Jean-Marc Valin
parent 6619a73637
commit bf75c8ec4d
71 changed files with 961 additions and 1005 deletions

View file

@ -54,7 +54,7 @@ static inline void silk_CNG_exc(
idx = ( opus_int )( silk_RSHIFT( seed, 24 ) & exc_mask ); idx = ( opus_int )( silk_RSHIFT( seed, 24 ) & exc_mask );
silk_assert( idx >= 0 ); silk_assert( idx >= 0 );
silk_assert( idx <= CNG_BUF_MASK_MAX ); 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; *rand_seed = seed;
} }
@ -83,7 +83,7 @@ void silk_CNG(
opus_int length /* I Length of residual */ opus_int length /* I Length of residual */
) )
{ {
opus_int i, j, subfr; opus_int i, subfr;
opus_int32 sum_Q6, max_Gain_Q16; opus_int32 sum_Q6, max_Gain_Q16;
opus_int16 A_Q12[ MAX_LPC_ORDER ]; opus_int16 A_Q12[ MAX_LPC_ORDER ];
opus_int32 CNG_sig_Q10[ MAX_FRAME_LENGTH + MAX_LPC_ORDER ]; opus_int32 CNG_sig_Q10[ MAX_FRAME_LENGTH + MAX_LPC_ORDER ];
@ -133,7 +133,7 @@ void silk_CNG(
/* Generate CNG signal, by synthesis filtering */ /* Generate CNG signal, by synthesis filtering */
silk_memcpy( CNG_sig_Q10, psCNG->CNG_synth_state, MAX_LPC_ORDER * sizeof( opus_int32 ) ); silk_memcpy( CNG_sig_Q10, psCNG->CNG_synth_state, MAX_LPC_ORDER * sizeof( opus_int32 ) );
for( i = 0; i < length; i++ ) { 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_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 - 2 ], A_Q12[ 1 ] );
sum_Q6 = silk_SMLAWB( sum_Q6, CNG_sig_Q10[ MAX_LPC_ORDER + i - 3 ], A_Q12[ 2 ] ); sum_Q6 = silk_SMLAWB( sum_Q6, CNG_sig_Q10[ MAX_LPC_ORDER + i - 3 ], A_Q12[ 2 ] );
@ -144,8 +144,13 @@ void silk_CNG(
sum_Q6 = silk_SMLAWB( sum_Q6, CNG_sig_Q10[ MAX_LPC_ORDER + i - 8 ], A_Q12[ 7 ] ); sum_Q6 = silk_SMLAWB( sum_Q6, CNG_sig_Q10[ MAX_LPC_ORDER + i - 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 - 9 ], A_Q12[ 8 ] );
sum_Q6 = silk_SMLAWB( sum_Q6, CNG_sig_Q10[ MAX_LPC_ORDER + i - 10 ], A_Q12[ 9 ] ); 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++ ) { if( psDec->LPC_order == 16 ) {
sum_Q6 = silk_SMLAWB( sum_Q6, CNG_sig_Q10[ MAX_LPC_ORDER + i - j - 1 ], A_Q12[ j ] ); 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 */ /* Update states */

View file

@ -77,7 +77,7 @@ void silk_LPC_analysis_filter(
out32 = silk_RSHIFT_ROUND( out32_Q12, 12 ); out32 = silk_RSHIFT_ROUND( out32_Q12, 12 );
/* Saturate output */ /* Saturate output */
out[ ix ] = ( opus_int16 )silk_SAT16( out32 ); out[ ix ] = (opus_int16)silk_SAT16( out32 );
} }
/* Set first d output samples to zero */ /* Set first d output samples to zero */

View file

@ -38,24 +38,22 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
/* Compute inverse of LPC prediction gain, and */ /* Compute inverse of LPC prediction gain, and */
/* test if LPC coefficients are stable (all poles within unit circle) */ /* 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 */ static opus_int32 LPC_inverse_pred_gain_QA( /* O Returns inverse prediction gain in energy domain, Q30 */
opus_int32 *invGain_Q30, /* O Inverse prediction gain, Q30 energy domain */
opus_int32 A_QA[ 2 ][ SILK_MAX_ORDER_LPC ], /* I Prediction coefficients */ opus_int32 A_QA[ 2 ][ SILK_MAX_ORDER_LPC ], /* I Prediction coefficients */
const opus_int order /* I Prediction order */ const opus_int order /* I Prediction order */
) )
{ {
opus_int k, n, mult2Q; 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; opus_int32 *Aold_QA, *Anew_QA;
Anew_QA = A_QA[ order & 1 ]; Anew_QA = A_QA[ order & 1 ];
*invGain_Q30 = ( 1 << 30 ); invGain_Q30 = 1 << 30;
for( k = order - 1; k > 0; k-- ) { for( k = order - 1; k > 0; k-- ) {
/* Check for stability */ /* Check for stability */
if( ( Anew_QA[ k ] > A_LIMIT ) || ( Anew_QA[ k ] < -A_LIMIT ) ) { if( ( Anew_QA[ k ] > A_LIMIT ) || ( Anew_QA[ k ] < -A_LIMIT ) ) {
*invGain_Q30 = 0; return 0;
return 1;
} }
/* Set RC equal to negated AR coef */ /* Set RC equal to negated AR coef */
@ -72,9 +70,9 @@ static opus_int LPC_inverse_pred_gain_QA( /* O Returns 1 if
/* Update inverse gain */ /* Update inverse gain */
/* invGain_Q30 range: [ 0 : 2^30 ] */ /* invGain_Q30 range: [ 0 : 2^30 ] */
*invGain_Q30 = silk_LSHIFT( silk_SMMUL( *invGain_Q30, rc_mult1_Q30 ), 2 ); invGain_Q30 = silk_LSHIFT( silk_SMMUL( invGain_Q30, rc_mult1_Q30 ), 2 );
silk_assert( *invGain_Q30 >= 0 ); silk_assert( invGain_Q30 >= 0 );
silk_assert( *invGain_Q30 <= ( 1 << 30 ) ); silk_assert( invGain_Q30 <= ( 1 << 30 ) );
/* Swap pointers */ /* Swap pointers */
Aold_QA = Anew_QA; Aold_QA = Anew_QA;
@ -89,8 +87,7 @@ static opus_int LPC_inverse_pred_gain_QA( /* O Returns 1 if
/* Check for stability */ /* Check for stability */
if( ( Anew_QA[ 0 ] > A_LIMIT ) || ( Anew_QA[ 0 ] < -A_LIMIT ) ) { if( ( Anew_QA[ 0 ] > A_LIMIT ) || ( Anew_QA[ 0 ] < -A_LIMIT ) ) {
*invGain_Q30 = 0; return 0;
return 1;
} }
/* Set RC equal to negated AR coef */ /* Set RC equal to negated AR coef */
@ -101,16 +98,15 @@ static opus_int LPC_inverse_pred_gain_QA( /* O Returns 1 if
/* Update inverse gain */ /* Update inverse gain */
/* Range: [ 0 : 2^30 ] */ /* Range: [ 0 : 2^30 ] */
*invGain_Q30 = silk_LSHIFT( silk_SMMUL( *invGain_Q30, rc_mult1_Q30 ), 2 ); invGain_Q30 = silk_LSHIFT( silk_SMMUL( invGain_Q30, rc_mult1_Q30 ), 2 );
silk_assert( *invGain_Q30 >= 0 ); silk_assert( invGain_Q30 >= 0 );
silk_assert( *invGain_Q30 <= 1<<30 ); silk_assert( invGain_Q30 <= 1<<30 );
return 0; return invGain_Q30;
} }
/* For input in Q12 domain */ /* For input in Q12 domain */
opus_int silk_LPC_inverse_pred_gain( /* O Returns 1 if unstable, otherwise 0 */ opus_int32 silk_LPC_inverse_pred_gain( /* O Returns inverse prediction gain in energy domain, Q30 */
opus_int32 *invGain_Q30, /* O Inverse prediction gain, Q30 energy domain */
const opus_int16 *A_Q12, /* I Prediction coefficients, Q12 [order] */ const opus_int16 *A_Q12, /* I Prediction coefficients, Q12 [order] */
const opus_int order /* I Prediction order */ const opus_int order /* I Prediction order */
) )
@ -118,30 +114,27 @@ opus_int silk_LPC_inverse_pred_gain( /* O Returns 1 if unstable
opus_int k; opus_int k;
opus_int32 Atmp_QA[ 2 ][ SILK_MAX_ORDER_LPC ]; opus_int32 Atmp_QA[ 2 ][ SILK_MAX_ORDER_LPC ];
opus_int32 *Anew_QA; opus_int32 *Anew_QA;
opus_int32 DC_resp=0; opus_int32 DC_resp = 0;
Anew_QA = Atmp_QA[ order & 1 ]; Anew_QA = Atmp_QA[ order & 1 ];
/* Increase Q domain of the AR coefficients */ /* Increase Q domain of the AR coefficients */
for( k = 0; k < order; k++ ) { for( k = 0; k < order; k++ ) {
DC_resp += (opus_int32)A_Q12[ 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 the DC is unstable, we don't even need to do the full calculations */
if( DC_resp >= 4096 ) { if( DC_resp >= 4096 ) {
*invGain_Q30 = 0; return 0;
return 1;
} }
return LPC_inverse_pred_gain_QA( invGain_Q30, Atmp_QA, order ); return LPC_inverse_pred_gain_QA( Atmp_QA, order );
} }
#ifdef FIXED_POINT #ifdef FIXED_POINT
/* For input in Q24 domain */ /* For input in Q24 domain */
/* This function is only used by the fixed-point build */ opus_int32 silk_LPC_inverse_pred_gain_Q24( /* O Returns inverse prediction gain in energy domain, Q30 */
opus_int silk_LPC_inverse_pred_gain_Q24( /* O Returns 1 if unstable, otherwise 0 */ const opus_int32 *A_Q24, /* I Prediction coefficients [order] */
opus_int32 *invGain_Q30, /* O Inverse prediction gain, Q30 energy domain */
const opus_int32 *A_Q24, /* I Prediction coefficients, Q24 [order] */
const opus_int order /* I Prediction order */ const opus_int order /* I Prediction order */
) )
{ {
@ -153,9 +146,9 @@ opus_int silk_LPC_inverse_pred_gain_Q24( /* O Returns 1 if unstabl
/* Increase Q domain of the AR coefficients */ /* Increase Q domain of the AR coefficients */
for( k = 0; k < order; k++ ) { 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 #endif

View file

@ -91,7 +91,7 @@ static inline opus_int64 silk_SUB64(opus_int64 a, opus_int64 b){
static inline opus_int16 silk_ADD_SAT16( opus_int16 a16, opus_int16 b16 ) { static inline opus_int16 silk_ADD_SAT16( opus_int16 a16, opus_int16 b16 ) {
opus_int16 res; opus_int16 res;
res = (opus_int16)silk_SAT16( silk_ADD32( (opus_int32)(a16), (b16) ) ); 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; return res;
} }
@ -101,7 +101,7 @@ static inline opus_int32 silk_ADD_SAT32(opus_int32 a32, opus_int32 b32){
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_MIN : (a32)+(b32)) : \
((((a32) | (b32)) & 0x80000000) == 0 ? silk_int32_MAX : (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; return res;
} }
@ -126,7 +126,7 @@ static inline opus_int64 silk_ADD_SAT64( opus_int64 a64, opus_int64 b64 ) {
static inline opus_int16 silk_SUB_SAT16( opus_int16 a16, opus_int16 b16 ) { static inline opus_int16 silk_SUB_SAT16( opus_int16 a16, opus_int16 b16 ) {
opus_int16 res; opus_int16 res;
res = (opus_int16)silk_SAT16( silk_SUB32( (opus_int32)(a16), (b16) ) ); 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; return res;
} }
@ -136,7 +136,7 @@ static inline opus_int32 silk_SUB_SAT32( opus_int32 a32, opus_int32 b32 ) {
res = ((((a32)-(b32)) & 0x80000000) == 0 ? \ res = ((((a32)-(b32)) & 0x80000000) == 0 ? \
(( (a32) & ((b32)^0x80000000) & 0x80000000) ? silk_int32_MIN : (a32)-(b32)) : \ (( (a32) & ((b32)^0x80000000) & 0x80000000) ? silk_int32_MIN : (a32)-(b32)) : \
((((a32)^0x80000000) & (b32) & 0x80000000) ? silk_int32_MAX : (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; return res;
} }

View file

@ -83,7 +83,7 @@ void silk_NLSF2A(
opus_int32 P[ SILK_MAX_ORDER_LPC / 2 + 1 ], Q[ SILK_MAX_ORDER_LPC / 2 + 1 ]; opus_int32 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 Ptmp, Qtmp, f_int, f_frac, cos_val, delta;
opus_int32 a32_QA1[ SILK_MAX_ORDER_LPC ]; 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( LSF_COS_TAB_SZ_FIX == 128 );
silk_assert( d==10||d==16 ); silk_assert( d==10||d==16 );
@ -162,8 +162,8 @@ void silk_NLSF2A(
} }
} }
for( i = 1; i < MAX_LPC_STABILIZE_ITERATIONS; i++ ) { for( i = 1; i <= MAX_LPC_STABILIZE_ITERATIONS; i++ ) {
if( silk_LPC_inverse_pred_gain( &invGain_Q30, a_Q12, d ) == 1 ) { 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 */ /* Prediction coefficients are (too close to) unstable; apply bandwidth expansion */
/* on the unscaled coefficients, convert to Q12 and measure again */ /* 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 */ silk_bwexpander_32( a32_QA1, d, 65536 - silk_SMULBB( 9 + i, i ) ); /* 10_Q16 = 0.00015 */
@ -175,7 +175,7 @@ void silk_NLSF2A(
} }
} }
if( i == MAX_LPC_STABILIZE_ITERATIONS ) { if( i > MAX_LPC_STABILIZE_ITERATIONS ) {
/* Reached the last iteration, set coefficients to zero */ /* Reached the last iteration, set coefficients to zero */
for( k = 0; k < d; k++ ) { for( k = 0; k < d; k++ ) {
a_Q12[ k ] = 0; a_Q12[ k ] = 0;

View file

@ -51,11 +51,11 @@ void silk_NLSF_VQ(
sum_error_Q26 = 0; sum_error_Q26 = 0;
for( m = 0; m < LPC_order; m += 2 ) { for( m = 0; m < LPC_order; m += 2 ) {
/* Compute weighted squared quantization error for index m */ /* 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 ); sum_error_Q30 = silk_SMULBB( diff_Q15, diff_Q15 );
/* Compute weighted squared quantization error for index m + 1 */ /* 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_Q30 = silk_SMLABB( sum_error_Q30, diff_Q15, diff_Q15 );
sum_error_Q26 = silk_ADD_RSHIFT32( sum_error_Q26, sum_error_Q30, 4 ); sum_error_Q26 = silk_ADD_RSHIFT32( sum_error_Q26, sum_error_Q30, 4 );

View file

@ -77,7 +77,7 @@ void silk_NLSF_decode(
/* Decode first stage */ /* Decode first stage */
pCB_element = &psNLSF_CB->CB1_NLSF_Q8[ NLSFIndices[ 0 ] * psNLSF_CB->order ]; pCB_element = &psNLSF_CB->CB1_NLSF_Q8[ NLSFIndices[ 0 ] * psNLSF_CB->order ];
for( i = 0; i < psNLSF_CB->order; i++ ) { 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 */ /* Unpack entropy table indices and predictor for current CB1 index */
@ -91,8 +91,8 @@ void silk_NLSF_decode(
/* Apply inverse square-rooted weights and add to output */ /* Apply inverse square-rooted weights and add to output */
for( i = 0; i < psNLSF_CB->order; i++ ) { 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 ) ); W_tmp_Q9 = silk_SQRT_APPROX( silk_LSHIFT( (opus_int32)W_tmp_QW[ i ], 18 - NLSF_W_Q ) );
NLSF_Q15_tmp = silk_ADD32( pNLSF_Q15[ i ], silk_DIV32_16( silk_LSHIFT( ( opus_int32 )res_Q10[ i ], 14 ), W_tmp_Q9 ) ); NLSF_Q15_tmp = silk_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 ); pNLSF_Q15[ i ] = (opus_int16)silk_LIMIT( NLSF_Q15_tmp, 0, 32767 );
} }

View file

@ -79,7 +79,7 @@ opus_int32 silk_NLSF_encode( /* O Returns
/* Residual after first stage */ /* Residual after first stage */
pCB_element = &psNLSF_CB->CB1_NLSF_Q8[ ind1 * psNLSF_CB->order ]; pCB_element = &psNLSF_CB->CB1_NLSF_Q8[ ind1 * psNLSF_CB->order ];
for( i = 0; i < psNLSF_CB->order; i++ ) { 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 ]; res_Q15[ i ] = pNLSF_Q15[ i ] - NLSF_tmp_Q15[ i ];
} }
@ -88,13 +88,13 @@ opus_int32 silk_NLSF_encode( /* O Returns
/* Apply square-rooted weights */ /* Apply square-rooted weights */
for( i = 0; i < psNLSF_CB->order; i++ ) { 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 ) ); 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 ); res_Q10[ i ] = (opus_int16)silk_RSHIFT( silk_SMULBB( res_Q15[ i ], W_tmp_Q9 ), 14 );
} }
/* Modify input weights accordingly */ /* Modify input weights accordingly */
for( i = 0; i < psNLSF_CB->order; i++ ) { 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 */ /* Unpack entropy table indices and predictor for current CB1 index */
@ -118,7 +118,7 @@ opus_int32 silk_NLSF_encode( /* O Returns
/* Find the lowest rate-distortion error */ /* Find the lowest rate-distortion error */
silk_insertion_sort_increasing( RD_Q25, &bestIndex, nSurvivors, 1 ); 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 ) ); silk_memcpy( &NLSFIndices[ 1 ], &tempIndices2[ bestIndex * MAX_LPC_ORDER ], psNLSF_CB->order * sizeof( opus_int8 ) );
/* Decode */ /* Decode */

View file

@ -34,10 +34,10 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
static inline void silk_nsq_scale_states( static inline void silk_nsq_scale_states(
const silk_encoder_state *psEncC, /* I Encoder State */ const silk_encoder_state *psEncC, /* I Encoder State */
silk_nsq_state *NSQ, /* I/O NSQ 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 */ opus_int32 x_sc_Q10[], /* O input scaled with 1/Gain */
const opus_int16 sLTP[], /* I re-whitened LTP state in Q0 */ 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 subfr, /* I subframe number */
const opus_int LTP_scale_Q14, /* I */ const opus_int LTP_scale_Q14, /* I */
const opus_int32 Gains_Q16[ MAX_NB_SUBFR ], /* I */ const opus_int32 Gains_Q16[ MAX_NB_SUBFR ], /* I */
@ -51,7 +51,7 @@ static inline void silk_noise_shape_quantizer(
const opus_int32 x_sc_Q10[], /* I */ const opus_int32 x_sc_Q10[], /* I */
opus_int8 pulses[], /* O */ opus_int8 pulses[], /* O */
opus_int16 xq[], /* 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 a_Q12[], /* I Short term prediction coefs */
const opus_int16 b_Q14[], /* I Long term prediction coefs */ const opus_int16 b_Q14[], /* I Long term prediction coefs */
const opus_int16 AR_shp_Q13[], /* I Noise shaping AR coefs */ const opus_int16 AR_shp_Q13[], /* I Noise shaping AR coefs */
@ -71,7 +71,7 @@ void silk_NSQ(
const silk_encoder_state *psEncC, /* I/O Encoder State */ const silk_encoder_state *psEncC, /* I/O Encoder State */
silk_nsq_state *NSQ, /* I/O NSQ state */ silk_nsq_state *NSQ, /* I/O NSQ state */
SideInfoIndices *psIndices, /* I/O Quantization Indices */ 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 */ opus_int8 pulses[], /* O Quantized pulse signal */
const opus_int16 PredCoef_Q12[ 2 * MAX_LPC_ORDER ], /* I Short term prediction coefs */ const opus_int16 PredCoef_Q12[ 2 * MAX_LPC_ORDER ], /* I Short term prediction coefs */
const opus_int16 LTPCoef_Q14[ LTP_ORDER * MAX_NB_SUBFR ], /* I Long term prediction coefs */ const opus_int16 LTPCoef_Q14[ LTP_ORDER * MAX_NB_SUBFR ], /* I Long term prediction coefs */
@ -88,11 +88,11 @@ void silk_NSQ(
opus_int k, lag, start_idx, LSF_interpolation_flag; opus_int k, lag, start_idx, LSF_interpolation_flag;
const opus_int16 *A_Q12, *B_Q14, *AR_shp_Q13; const opus_int16 *A_Q12, *B_Q14, *AR_shp_Q13;
opus_int16 *pxq; opus_int16 *pxq;
opus_int32 sLTP_Q16[ 2 * MAX_FRAME_LENGTH ]; opus_int32 sLTP_Q15[ 2 * MAX_FRAME_LENGTH ];
opus_int16 sLTP[ 2 * MAX_FRAME_LENGTH ]; opus_int16 sLTP[ 2 * MAX_FRAME_LENGTH ];
opus_int32 HarmShapeFIRPacked_Q14; opus_int32 HarmShapeFIRPacked_Q14;
opus_int offset_Q10; opus_int offset_Q10;
opus_int32 x_sc_Q10[ MAX_FRAME_LENGTH / MAX_NB_SUBFR ]; opus_int32 x_sc_Q10[ MAX_SUB_FRAME_LENGTH ];
NSQ->rand_seed = psIndices->Seed; NSQ->rand_seed = psIndices->Seed;
@ -109,7 +109,7 @@ void silk_NSQ(
LSF_interpolation_flag = 1; 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_shp_buf_idx = psEncC->ltp_mem_length;
NSQ->sLTP_buf_idx = psEncC->ltp_mem_length; NSQ->sLTP_buf_idx = psEncC->ltp_mem_length;
pxq = &NSQ->xq[ psEncC->ltp_mem_length ]; pxq = &NSQ->xq[ psEncC->ltp_mem_length ];
@ -121,7 +121,7 @@ void silk_NSQ(
/* Noise shape parameters */ /* Noise shape parameters */
silk_assert( HarmShapeGain_Q14[ k ] >= 0 ); silk_assert( HarmShapeGain_Q14[ k ] >= 0 );
HarmShapeFIRPacked_Q14 = silk_RSHIFT( HarmShapeGain_Q14[ k ], 2 ); 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; NSQ->rewhite_flag = 0;
if( psIndices->signalType == TYPE_VOICED ) { if( psIndices->signalType == TYPE_VOICED ) {
@ -142,13 +142,13 @@ void silk_NSQ(
} }
} }
silk_nsq_scale_states( psEncC, NSQ, x, x_sc_Q10, sLTP, sLTP_Q16, k, LTP_scale_Q14, Gains_Q16, pitchL, psIndices->signalType ); silk_nsq_scale_states( psEncC, NSQ, x_Q10, x_sc_Q10, sLTP, sLTP_Q15, k, LTP_scale_Q14, Gains_Q16, pitchL, psIndices->signalType );
silk_noise_shape_quantizer( NSQ, psIndices->signalType, x_sc_Q10, pulses, pxq, sLTP_Q16, A_Q12, B_Q14, silk_noise_shape_quantizer( NSQ, psIndices->signalType, x_sc_Q10, pulses, pxq, sLTP_Q15, A_Q12, B_Q14,
AR_shp_Q13, lag, HarmShapeFIRPacked_Q14, Tilt_Q14[ k ], LF_shp_Q14[ k ], Gains_Q16[ k ], Lambda_Q10, 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 ); offset_Q10, psEncC->subfr_length, psEncC->shapingLPCOrder, psEncC->predictLPCOrder );
x += psEncC->subfr_length; x_Q10 += psEncC->subfr_length;
pulses += psEncC->subfr_length; pulses += psEncC->subfr_length;
pxq += psEncC->subfr_length; pxq += psEncC->subfr_length;
} }
@ -170,7 +170,7 @@ static inline void silk_noise_shape_quantizer(
const opus_int32 x_sc_Q10[], /* I */ const opus_int32 x_sc_Q10[], /* I */
opus_int8 pulses[], /* O */ opus_int8 pulses[], /* O */
opus_int16 xq[], /* 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 a_Q12[], /* I Short term prediction coefs */
const opus_int16 b_Q14[], /* I Long term prediction coefs */ const opus_int16 b_Q14[], /* I Long term prediction coefs */
const opus_int16 AR_shp_Q13[], /* I Noise shaping AR coefs */ const opus_int16 AR_shp_Q13[], /* I Noise shaping AR coefs */
@ -187,16 +187,16 @@ static inline void silk_noise_shape_quantizer(
) )
{ {
opus_int i, j; opus_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 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 dither, exc_Q10, LPC_exc_Q10, xq_Q10;
opus_int32 tmp1, tmp2, sLF_AR_shp_Q10; opus_int32 tmp1, tmp2, sLF_AR_shp_Q10;
opus_int32 *psLPC_Q14, *shp_lag_ptr, *pred_lag_ptr; 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 ]; 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 ]; psLPC_Q14 = &NSQ->sLPC_Q14[ NSQ_LPC_BUF_LENGTH - 1 ];
for( i = 0; i < length; i++ ) { for( i = 0; i < length; i++ ) {
@ -207,11 +207,7 @@ static inline void silk_noise_shape_quantizer(
dither = silk_RSHIFT( NSQ->rand_seed, 31 ); dither = silk_RSHIFT( NSQ->rand_seed, 31 );
/* Short-term prediction */ /* Short-term prediction */
silk_assert( ( predictLPCOrder & 1 ) == 0 ); /* check that order is even */ silk_assert( predictLPCOrder == 10 || predictLPCOrder == 16 );
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 */
LPC_pred_Q10 = silk_SMULWB( psLPC_Q14[ 0 ], a_Q12[ 0 ] ); 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[ -1 ], a_Q12[ 1 ] );
LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, psLPC_Q14[ -2 ], a_Q12[ 2 ] ); LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, psLPC_Q14[ -2 ], a_Q12[ 2 ] );
@ -222,21 +218,26 @@ static inline void silk_noise_shape_quantizer(
LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, psLPC_Q14[ -7 ], a_Q12[ 7 ] ); LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, psLPC_Q14[ -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[ -8 ], a_Q12[ 8 ] );
LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, psLPC_Q14[ -9 ], a_Q12[ 9 ] ); LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, psLPC_Q14[ -9 ], a_Q12[ 9 ] );
for( j = 10; j < predictLPCOrder; j ++ ) { if( predictLPCOrder == 16 ) {
LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, psLPC_Q14[ -j ], a_Q12[ j ] ); 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 */ /* Long-term prediction */
if( signalType == TYPE_VOICED ) { if( signalType == TYPE_VOICED ) {
/* Unrolled loop */ /* Unrolled loop */
LTP_pred_Q14 = silk_SMULWB( pred_lag_ptr[ 0 ], b_Q14[ 0 ] ); LTP_pred_Q13 = 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_Q13 = silk_SMLAWB( LTP_pred_Q13, pred_lag_ptr[ -1 ], b_Q14[ 1 ] );
LTP_pred_Q14 = silk_SMLAWB( LTP_pred_Q14, pred_lag_ptr[ -2 ], b_Q14[ 2 ] ); LTP_pred_Q13 = silk_SMLAWB( LTP_pred_Q13, pred_lag_ptr[ -2 ], b_Q14[ 2 ] );
LTP_pred_Q14 = silk_SMLAWB( LTP_pred_Q14, pred_lag_ptr[ -3 ], b_Q14[ 3 ] ); LTP_pred_Q13 = silk_SMLAWB( LTP_pred_Q13, 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_SMLAWB( LTP_pred_Q13, pred_lag_ptr[ -4 ], b_Q14[ 4 ] );
pred_lag_ptr++; pred_lag_ptr++;
} else { } else {
LTP_pred_Q14 = 0; LTP_pred_Q13 = 0;
} }
/* Noise shape feedback */ /* Noise shape feedback */
@ -272,7 +273,7 @@ static inline void silk_noise_shape_quantizer(
n_LTP_Q14 = silk_LSHIFT( n_LTP_Q14, 6 ); n_LTP_Q14 = silk_LSHIFT( n_LTP_Q14, 6 );
shp_lag_ptr++; 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_RSHIFT( tmp1, 4 ); /* convert to Q10 */
tmp1 = silk_ADD32( tmp1, LPC_pred_Q10 ); /* add Q10 stuff */ tmp1 = silk_ADD32( tmp1, LPC_pred_Q10 ); /* add Q10 stuff */
tmp1 = silk_SUB32( tmp1, n_AR_Q10 ); /* subtract Q10 stuff */ tmp1 = silk_SUB32( tmp1, n_AR_Q10 ); /* subtract Q10 stuff */
@ -324,18 +325,19 @@ static inline void silk_noise_shape_quantizer(
q1_Q10 = q2_Q10; 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 */ /* Excitation */
exc_Q10 = q1_Q10 ^ dither; exc_Q10 = q1_Q10 ^ dither;
/* Add predictions */ /* 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 ); xq_Q10 = silk_ADD32( LPC_exc_Q10, LPC_pred_Q10 );
/* Scale XQ back to normal level before saving */ /* Scale XQ back to normal level before saving */
xq[ i ] = ( opus_int16 )silk_SAT16( silk_RSHIFT_ROUND( silk_SMULWW( xq_Q10, Gain_Q16 ), 10 ) ); 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 */ /* Update states */
psLPC_Q14++; psLPC_Q14++;
*psLPC_Q14 = silk_LSHIFT( xq_Q10, 4 ); *psLPC_Q14 = silk_LSHIFT( xq_Q10, 4 );
@ -343,7 +345,7 @@ static inline void silk_noise_shape_quantizer(
NSQ->sLF_AR_shp_Q12 = silk_LSHIFT( sLF_AR_shp_Q10, 2 ); NSQ->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 ); 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_shp_buf_idx++;
NSQ->sLTP_buf_idx++; NSQ->sLTP_buf_idx++;
@ -358,10 +360,10 @@ static inline void silk_noise_shape_quantizer(
static inline void silk_nsq_scale_states( static inline void silk_nsq_scale_states(
const silk_encoder_state *psEncC, /* I Encoder State */ const silk_encoder_state *psEncC, /* I Encoder State */
silk_nsq_state *NSQ, /* I/O NSQ 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 */ opus_int32 x_sc_Q10[], /* O input scaled with 1/Gain */
const opus_int16 sLTP[], /* I re-whitened LTP state in Q0 */ 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 subfr, /* I subframe number */
const opus_int LTP_scale_Q14, /* I */ const opus_int LTP_scale_Q14, /* I */
const opus_int32 Gains_Q16[ MAX_NB_SUBFR ], /* I */ const opus_int32 Gains_Q16[ MAX_NB_SUBFR ], /* I */
@ -370,22 +372,21 @@ static inline void silk_nsq_scale_states(
) )
{ {
opus_int i, lag; opus_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_INVERSE32_varQ( silk_max( Gains_Q16[ subfr ], 1 ), 32 );
inv_gain_Q16 = silk_min( inv_gain_Q16, silk_int16_MAX );
lag = pitchL[ subfr ]; lag = pitchL[ subfr ];
/* After rewhitening the LTP state is un-scaled, so scale with inv_gain_Q16 */ /* After rewhitening the LTP state is un-scaled, so scale with inv_gain_Q16 */
if( NSQ->rewhite_flag ) { 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 ) { if( subfr == 0 ) {
/* Do LTP downscaling */ /* 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++ ) { for( i = NSQ->sLTP_buf_idx - lag - LTP_ORDER / 2; i < NSQ->sLTP_buf_idx; i++ ) {
silk_assert( i < MAX_FRAME_LENGTH ); silk_assert( i < MAX_FRAME_LENGTH );
sLTP_Q16[ i ] = silk_SMULWB( inv_gain_Q32, sLTP[ i ] ); sLTP_Q15[ i ] = silk_SMULWB( inv_gain_Q31, sLTP[ i ] );
} }
} }
@ -401,7 +402,7 @@ static inline void silk_nsq_scale_states(
/* Scale long-term prediction state */ /* Scale long-term prediction state */
if( signal_type == TYPE_VOICED && NSQ->rewhite_flag == 0 ) { 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++ ) { for( i = NSQ->sLTP_buf_idx - lag - LTP_ORDER / 2; i < NSQ->sLTP_buf_idx; i++ ) {
sLTP_Q16[ i ] = silk_SMULWW( gain_adj_Q16, sLTP_Q16[ i ] ); sLTP_Q15[ i ] = silk_SMULWW( gain_adj_Q16, sLTP_Q15[ i ] );
} }
} }
@ -418,10 +419,10 @@ static inline void silk_nsq_scale_states(
/* Scale input */ /* Scale input */
for( i = 0; i < psEncC->subfr_length; i++ ) { 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 ); silk_assert( inv_gain_Q16 != 0 );
NSQ->prev_inv_gain_Q16 = inv_gain_Q16; NSQ->prev_inv_gain_Q16 = inv_gain_Q16;
} }

View file

@ -32,7 +32,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "main.h" #include "main.h"
typedef struct { 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 RandState[ DECISION_DELAY ];
opus_int32 Q_Q10[ DECISION_DELAY ]; opus_int32 Q_Q10[ DECISION_DELAY ];
opus_int32 Xq_Q10[ DECISION_DELAY ]; opus_int32 Xq_Q10[ DECISION_DELAY ];
@ -58,10 +58,10 @@ static inline void silk_nsq_del_dec_scale_states(
const silk_encoder_state *psEncC, /* I Encoder State */ const silk_encoder_state *psEncC, /* I Encoder State */
silk_nsq_state *NSQ, /* I/O NSQ state */ silk_nsq_state *NSQ, /* I/O NSQ state */
NSQ_del_dec_struct psDelDec[], /* I/O Delayed decision states */ 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 */ opus_int32 x_sc_Q10[], /* O Input scaled with 1/Gain in Q10 */
const opus_int16 sLTP[], /* I Re-whitened LTP state in Q0 */ 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 subfr, /* I Subframe number */
opus_int nStatesDelayedDecision, /* I Number of del dec states */ opus_int nStatesDelayedDecision, /* I Number of del dec states */
const opus_int LTP_scale_Q14, /* I LTP state scaling */ const opus_int LTP_scale_Q14, /* I LTP state scaling */
@ -81,7 +81,7 @@ static inline void silk_noise_shape_quantizer_del_dec(
const opus_int32 x_Q10[], /* I */ const opus_int32 x_Q10[], /* I */
opus_int8 pulses[], /* O */ opus_int8 pulses[], /* O */
opus_int16 xq[], /* 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 */ opus_int32 delayedGain_Q16[], /* I/O Gain delay buffer */
const opus_int16 a_Q12[], /* I Short term prediction coefs */ const opus_int16 a_Q12[], /* I Short term prediction coefs */
const opus_int16 b_Q14[], /* I Long term prediction coefs */ const opus_int16 b_Q14[], /* I Long term prediction coefs */
@ -107,7 +107,7 @@ void silk_NSQ_del_dec(
const silk_encoder_state *psEncC, /* I/O Encoder State */ const silk_encoder_state *psEncC, /* I/O Encoder State */
silk_nsq_state *NSQ, /* I/O NSQ state */ silk_nsq_state *NSQ, /* I/O NSQ state */
SideInfoIndices *psIndices, /* I/O Quantization Indices */ 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 */ opus_int8 pulses[], /* O Quantized pulse signal */
const opus_int16 PredCoef_Q12[ 2 * MAX_LPC_ORDER ], /* I Short term prediction coefs */ const opus_int16 PredCoef_Q12[ 2 * MAX_LPC_ORDER ], /* I Short term prediction coefs */
const opus_int16 LTPCoef_Q14[ LTP_ORDER * MAX_NB_SUBFR ], /* I Long term prediction coefs */ const opus_int16 LTPCoef_Q14[ LTP_ORDER * MAX_NB_SUBFR ], /* I Long term prediction coefs */
@ -125,7 +125,7 @@ void silk_NSQ_del_dec(
opus_int last_smple_idx, smpl_buf_idx, decisionDelay; opus_int last_smple_idx, smpl_buf_idx, decisionDelay;
const opus_int16 *A_Q12, *B_Q14, *AR_shp_Q13; const opus_int16 *A_Q12, *B_Q14, *AR_shp_Q13;
opus_int16 *pxq; opus_int16 *pxq;
opus_int32 sLTP_Q16[ 2 * MAX_FRAME_LENGTH ]; opus_int32 sLTP_Q15[ 2 * MAX_FRAME_LENGTH ];
opus_int16 sLTP[ 2 * MAX_FRAME_LENGTH ]; opus_int16 sLTP[ 2 * MAX_FRAME_LENGTH ];
opus_int32 HarmShapeFIRPacked_Q14; opus_int32 HarmShapeFIRPacked_Q14;
opus_int offset_Q10; opus_int offset_Q10;
@ -175,7 +175,7 @@ void silk_NSQ_del_dec(
LSF_interpolation_flag = 1; 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 ]; pxq = &NSQ->xq[ psEncC->ltp_mem_length ];
NSQ->sLTP_shp_buf_idx = psEncC->ltp_mem_length; NSQ->sLTP_shp_buf_idx = psEncC->ltp_mem_length;
NSQ->sLTP_buf_idx = psEncC->ltp_mem_length; NSQ->sLTP_buf_idx = psEncC->ltp_mem_length;
@ -188,7 +188,7 @@ void silk_NSQ_del_dec(
/* Noise shape parameters */ /* Noise shape parameters */
silk_assert( HarmShapeGain_Q14[ k ] >= 0 ); silk_assert( HarmShapeGain_Q14[ k ] >= 0 );
HarmShapeFIRPacked_Q14 = silk_RSHIFT( HarmShapeGain_Q14[ k ], 2 ); 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; NSQ->rewhite_flag = 0;
if( psIndices->signalType == TYPE_VOICED ) { if( psIndices->signalType == TYPE_VOICED ) {
@ -220,8 +220,8 @@ void silk_NSQ_del_dec(
last_smple_idx = smpl_buf_idx + decisionDelay; last_smple_idx = smpl_buf_idx + decisionDelay;
for( i = 0; i < decisionDelay; i++ ) { for( i = 0; i < decisionDelay; i++ ) {
last_smple_idx = ( last_smple_idx - 1 ) & DECISION_DELAY_MASK; last_smple_idx = ( last_smple_idx - 1 ) & DECISION_DELAY_MASK;
pulses[ i - decisionDelay ] = ( opus_int8 )silk_RSHIFT_ROUND( psDD->Q_Q10[ last_smple_idx ], 10 ); 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( pxq[ i - decisionDelay ] = (opus_int16)silk_SAT16( silk_RSHIFT_ROUND(
silk_SMULWW( psDD->Xq_Q10[ last_smple_idx ], Gains_Q16[ 1 ] ), 10 ) ); 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 ]; NSQ->sLTP_shp_Q10[ NSQ->sLTP_shp_buf_idx - decisionDelay + i ] = psDD->Shape_Q10[ last_smple_idx ];
} }
@ -241,15 +241,15 @@ void silk_NSQ_del_dec(
} }
} }
silk_nsq_del_dec_scale_states( psEncC, NSQ, psDelDec, x, x_sc_Q10, sLTP, sLTP_Q16, k, silk_nsq_del_dec_scale_states( psEncC, NSQ, psDelDec, x_Q10, x_sc_Q10, sLTP, sLTP_Q15, k,
psEncC->nStatesDelayedDecision, LTP_scale_Q14, Gains_Q16, pitchL, psIndices->signalType, decisionDelay ); 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 ], 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, Gains_Q16[ k ], Lambda_Q10, offset_Q10, psEncC->subfr_length, subfr++, psEncC->shapingLPCOrder,
psEncC->predictLPCOrder, psEncC->warping_Q16, psEncC->nStatesDelayedDecision, &smpl_buf_idx, decisionDelay ); psEncC->predictLPCOrder, psEncC->warping_Q16, psEncC->nStatesDelayedDecision, &smpl_buf_idx, decisionDelay );
x += psEncC->subfr_length; x_Q10 += psEncC->subfr_length;
pulses += psEncC->subfr_length; pulses += psEncC->subfr_length;
pxq += psEncC->subfr_length; pxq += psEncC->subfr_length;
} }
@ -270,8 +270,8 @@ void silk_NSQ_del_dec(
last_smple_idx = smpl_buf_idx + decisionDelay; last_smple_idx = smpl_buf_idx + decisionDelay;
for( i = 0; i < decisionDelay; i++ ) { for( i = 0; i < decisionDelay; i++ ) {
last_smple_idx = ( last_smple_idx - 1 ) & DECISION_DELAY_MASK; last_smple_idx = ( last_smple_idx - 1 ) & DECISION_DELAY_MASK;
pulses[ i - decisionDelay ] = ( opus_int8 )silk_RSHIFT_ROUND( psDD->Q_Q10[ last_smple_idx ], 10 ); 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( 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 ) ); 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 ]; NSQ->sLTP_shp_Q10[ NSQ->sLTP_shp_buf_idx - decisionDelay + i ] = psDD->Shape_Q10[ last_smple_idx ];
} }
@ -282,7 +282,8 @@ void silk_NSQ_del_dec(
NSQ->sLF_AR_shp_Q12 = psDD->LF_AR_Q12; NSQ->sLF_AR_shp_Q12 = psDD->LF_AR_Q12;
NSQ->lagPrev = pitchL[ psEncC->nb_subfr - 1 ]; 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->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 ) ); silk_memmove( NSQ->sLTP_shp_Q10, &NSQ->sLTP_shp_Q10[ psEncC->frame_length ], psEncC->ltp_mem_length * sizeof( opus_int32 ) );
} }
@ -297,7 +298,7 @@ static inline void silk_noise_shape_quantizer_del_dec(
const opus_int32 x_Q10[], /* I */ const opus_int32 x_Q10[], /* I */
opus_int8 pulses[], /* O */ opus_int8 pulses[], /* O */
opus_int16 xq[], /* 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 */ opus_int32 delayedGain_Q16[], /* I/O Gain delay buffer */
const opus_int16 a_Q12[], /* I Short term prediction coefs */ const opus_int16 a_Q12[], /* I Short term prediction coefs */
const opus_int16 b_Q14[], /* I Long term prediction coefs */ const opus_int16 b_Q14[], /* I Long term prediction coefs */
@ -321,7 +322,7 @@ static inline void silk_noise_shape_quantizer_del_dec(
{ {
opus_int i, j, k, Winner_ind, RDmin_ind, RDmax_ind, last_smple_idx; opus_int i, j, k, Winner_ind, RDmin_ind, RDmax_ind, last_smple_idx;
opus_int32 Winner_rand_state; 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 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 q1_Q10, q2_Q10, dither, exc_Q10, LPC_exc_Q10, xq_Q10;
opus_int32 tmp1, tmp2, sLF_AR_shp_Q10; opus_int32 tmp1, tmp2, sLF_AR_shp_Q10;
@ -333,7 +334,7 @@ static inline void silk_noise_shape_quantizer_del_dec(
silk_assert( nStatesDelayedDecision > 0 ); silk_assert( nStatesDelayedDecision > 0 );
shp_lag_ptr = &NSQ->sLTP_shp_Q10[ NSQ->sLTP_shp_buf_idx - lag + HARM_SHAPE_FIR_TAPS / 2 ]; 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++ ) { for( i = 0; i < length; i++ ) {
/* Perform common calculations used in all states */ /* Perform common calculations used in all states */
@ -341,14 +342,14 @@ static inline void silk_noise_shape_quantizer_del_dec(
/* Long-term prediction */ /* Long-term prediction */
if( signalType == TYPE_VOICED ) { if( signalType == TYPE_VOICED ) {
/* Unrolled loop */ /* Unrolled loop */
LTP_pred_Q14 = silk_SMULWB( pred_lag_ptr[ 0 ], b_Q14[ 0 ] ); LTP_pred_Q13 = 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_Q13 = silk_SMLAWB( LTP_pred_Q13, pred_lag_ptr[ -1 ], b_Q14[ 1 ] );
LTP_pred_Q14 = silk_SMLAWB( LTP_pred_Q14, pred_lag_ptr[ -2 ], b_Q14[ 2 ] ); LTP_pred_Q13 = silk_SMLAWB( LTP_pred_Q13, pred_lag_ptr[ -2 ], b_Q14[ 2 ] );
LTP_pred_Q14 = silk_SMLAWB( LTP_pred_Q14, pred_lag_ptr[ -3 ], b_Q14[ 3 ] ); LTP_pred_Q13 = silk_SMLAWB( LTP_pred_Q13, 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_SMLAWB( LTP_pred_Q13, pred_lag_ptr[ -4 ], b_Q14[ 4 ] );
pred_lag_ptr++; pred_lag_ptr++;
} else { } else {
LTP_pred_Q14 = 0; LTP_pred_Q13 = 0;
} }
/* Long-term shaping */ /* Long-term shaping */
@ -359,7 +360,7 @@ static inline void silk_noise_shape_quantizer_del_dec(
n_LTP_Q14 = silk_LSHIFT( n_LTP_Q14, 6 ); n_LTP_Q14 = silk_LSHIFT( n_LTP_Q14, 6 );
shp_lag_ptr++; 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 { } else {
LTP_Q10 = 0; LTP_Q10 = 0;
} }
@ -380,10 +381,7 @@ static inline void silk_noise_shape_quantizer_del_dec(
/* Pointer used in short term prediction and shaping */ /* Pointer used in short term prediction and shaping */
psLPC_Q14 = &psDD->sLPC_Q14[ NSQ_LPC_BUF_LENGTH - 1 + i ]; psLPC_Q14 = &psDD->sLPC_Q14[ NSQ_LPC_BUF_LENGTH - 1 + i ];
/* Short-term prediction */ /* Short-term prediction */
silk_assert( predictLPCOrder >= 10 ); /* check that unrolling works */ silk_assert( predictLPCOrder == 10 || predictLPCOrder == 16 );
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 */
LPC_pred_Q10 = silk_SMULWB( psLPC_Q14[ 0 ], a_Q12[ 0 ] ); 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[ -1 ], a_Q12[ 1 ] );
LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, psLPC_Q14[ -2 ], a_Q12[ 2 ] ); LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, psLPC_Q14[ -2 ], a_Q12[ 2 ] );
@ -394,8 +392,13 @@ static inline void silk_noise_shape_quantizer_del_dec(
LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, psLPC_Q14[ -7 ], a_Q12[ 7 ] ); LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, psLPC_Q14[ -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[ -8 ], a_Q12[ 8 ] );
LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, psLPC_Q14[ -9 ], a_Q12[ 9 ] ); LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, psLPC_Q14[ -9 ], a_Q12[ 9 ] );
for( j = 10; j < predictLPCOrder; j ++ ) { if( predictLPCOrder == 16 ) {
LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, psLPC_Q14[ -j ], a_Q12[ j ] ); 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 */ /* Noise shape feedback */
@ -486,7 +489,7 @@ static inline void silk_noise_shape_quantizer_del_dec(
exc_Q10 = psSS[ 0 ].Q_Q10 ^ dither; exc_Q10 = psSS[ 0 ].Q_Q10 ^ dither;
/* Add predictions */ /* 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 ); xq_Q10 = silk_ADD32( LPC_exc_Q10, LPC_pred_Q10 );
/* Update states */ /* Update states */
@ -502,7 +505,7 @@ static inline void silk_noise_shape_quantizer_del_dec(
exc_Q10 = psSS[ 1 ].Q_Q10 ^ dither; exc_Q10 = psSS[ 1 ].Q_Q10 ^ dither;
/* Add predictions */ /* 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 ); xq_Q10 = silk_ADD32( LPC_exc_Q10, LPC_pred_Q10 );
/* Update states */ /* Update states */
@ -564,11 +567,11 @@ static inline void silk_noise_shape_quantizer_del_dec(
/* Write samples from winner to output and long-term filter states */ /* Write samples from winner to output and long-term filter states */
psDD = &psDelDec[ Winner_ind ]; psDD = &psDelDec[ Winner_ind ];
if( subfr > 0 || i >= decisionDelay ) { if( subfr > 0 || i >= decisionDelay ) {
pulses[ i - decisionDelay ] = ( opus_int8 )silk_RSHIFT_ROUND( psDD->Q_Q10[ last_smple_idx ], 10 ); 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( xq[ i - decisionDelay ] = (opus_int16)silk_SAT16( silk_RSHIFT_ROUND(
silk_SMULWW( psDD->Xq_Q10[ last_smple_idx ], delayedGain_Q16[ last_smple_idx ] ), 10 ) ); 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 ]; 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_shp_buf_idx++;
NSQ->sLTP_buf_idx++; NSQ->sLTP_buf_idx++;
@ -600,10 +603,10 @@ static inline void silk_nsq_del_dec_scale_states(
const silk_encoder_state *psEncC, /* I Encoder State */ const silk_encoder_state *psEncC, /* I Encoder State */
silk_nsq_state *NSQ, /* I/O NSQ state */ silk_nsq_state *NSQ, /* I/O NSQ state */
NSQ_del_dec_struct psDelDec[], /* I/O Delayed decision states */ 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 */ opus_int32 x_sc_Q10[], /* O Input scaled with 1/Gain in Q10 */
const opus_int16 sLTP[], /* I Re-whitened LTP state in Q0 */ 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 subfr, /* I Subframe number */
opus_int nStatesDelayedDecision, /* I Number of del dec states */ opus_int nStatesDelayedDecision, /* I Number of del dec states */
const opus_int LTP_scale_Q14, /* I LTP state scaling */ const opus_int LTP_scale_Q14, /* I LTP state scaling */
@ -614,23 +617,22 @@ static inline void silk_nsq_del_dec_scale_states(
) )
{ {
opus_int i, k, lag; opus_int i, k, lag;
opus_int32 inv_gain_Q16, gain_adj_Q16, inv_gain_Q32; opus_int32 inv_gain_Q16, gain_adj_Q16, inv_gain_Q31;
NSQ_del_dec_struct *psDD; NSQ_del_dec_struct *psDD;
inv_gain_Q16 = silk_INVERSE32_varQ( silk_max( Gains_Q16[ subfr ], 1 ), 32 ); 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 ]; lag = pitchL[ subfr ];
/* After rewhitening the LTP state is un-scaled, so scale with inv_gain_Q16 */ /* After rewhitening the LTP state is un-scaled, so scale with inv_gain_Q16 */
if( NSQ->rewhite_flag ) { 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 ) { if( subfr == 0 ) {
/* Do LTP downscaling */ /* 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++ ) { for( i = NSQ->sLTP_buf_idx - lag - LTP_ORDER / 2; i < NSQ->sLTP_buf_idx; i++ ) {
silk_assert( i < MAX_FRAME_LENGTH ); silk_assert( i < MAX_FRAME_LENGTH );
sLTP_Q16[ i ] = silk_SMULWB( inv_gain_Q32, sLTP[ i ] ); sLTP_Q15[ i ] = silk_SMULWB( inv_gain_Q31, sLTP[ i ] );
} }
} }
@ -646,7 +648,7 @@ static inline void silk_nsq_del_dec_scale_states(
/* Scale long-term prediction state */ /* Scale long-term prediction state */
if( signal_type == TYPE_VOICED && NSQ->rewhite_flag == 0 ) { 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++ ) { for( i = NSQ->sLTP_buf_idx - lag - LTP_ORDER / 2; i < NSQ->sLTP_buf_idx - decisionDelay; i++ ) {
sLTP_Q16[ i ] = silk_SMULWW( gain_adj_Q16, sLTP_Q16[ i ] ); sLTP_Q15[ i ] = silk_SMULWW( gain_adj_Q16, sLTP_Q15[ i ] );
} }
} }
@ -672,7 +674,7 @@ static inline void silk_nsq_del_dec_scale_states(
/* Scale input */ /* Scale input */
for( i = 0; i < psEncC->subfr_length; i++ ) { 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 */

View file

@ -192,7 +192,7 @@ static inline void silk_PLC_conceal(
exc_buf_ptr = exc_buf; exc_buf_ptr = exc_buf;
for( k = 0; k < 2; k++ ) { for( k = 0; k < 2; k++ ) {
for( i = 0; i < psPLC->subfr_length; i++ ) { 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 ); 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; exc_buf_ptr += psPLC->subfr_length;
@ -209,11 +209,11 @@ static inline void silk_PLC_conceal(
rand_ptr = &psDec->exc_Q10[ silk_max_int( 0, psPLC->nb_subfr * psPLC->subfr_length - RAND_BUF_SIZE ) ]; 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; B_Q14 = psPLC->LTPCoef_Q14;
rand_scale_Q14 = psPLC->randScale_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 ) ]; harm_Gain_Q15 = HARM_ATT_Q15[ silk_min_int( NB_ATT - 1, psDec->lossCnt ) ];
if( psDec->prevSignalType == TYPE_VOICED ) { if( psDec->prevSignalType == TYPE_VOICED ) {
rand_Gain_Q15 = PLC_RAND_ATTENUATE_V_Q15[ silk_min_int( NB_ATT - 1, psDec->lossCnt ) ]; rand_Gain_Q15 = PLC_RAND_ATTENUATE_V_Q15[ silk_min_int( NB_ATT - 1, psDec->lossCnt ) ];
@ -237,12 +237,12 @@ static inline void silk_PLC_conceal(
rand_scale_Q14 -= B_Q14[ i ]; rand_scale_Q14 -= B_Q14[ i ];
} }
rand_scale_Q14 = silk_max_16( 3277, rand_scale_Q14 ); /* 0.2 */ 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 { } else {
/* Reduce random noise for unvoiced frames with high LPC gain */ /* Reduce random noise for unvoiced frames with high LPC gain */
opus_int32 invGain_Q30, down_scale_Q30; 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_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 ); down_scale_Q30 = silk_max_32( silk_RSHIFT( 1 << 30, LOG2_INV_LPC_GAIN_LOW_THRES ), down_scale_Q30 );
@ -272,7 +272,7 @@ static inline void silk_PLC_conceal(
/* LTP synthesis filtering */ /* LTP synthesis filtering */
/***************************/ /***************************/
for( k = 0; k < psDec->nb_subfr; k++ ) { 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 ]; pred_lag_ptr = &sLTP_Q14[ sLTP_buf_idx - lag + LTP_ORDER / 2 ];
for( i = 0; i < psDec->subfr_length; i++ ) { for( i = 0; i < psDec->subfr_length; i++ ) {
/* Unrolled loop */ /* Unrolled loop */
@ -334,7 +334,7 @@ static inline void silk_PLC_conceal(
sLPC_Q14_ptr[ MAX_LPC_ORDER + i ] = silk_ADD_LSHIFT32( sLPC_Q14_ptr[ MAX_LPC_ORDER + i ], LPC_pred_Q10, 4 ); sLPC_Q14_ptr[ MAX_LPC_ORDER + i ] = silk_ADD_LSHIFT32( sLPC_Q14_ptr[ MAX_LPC_ORDER + i ], LPC_pred_Q10, 4 );
/* Scale with Gain */ /* 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 */ /* Save LPC state */

View file

@ -25,8 +25,8 @@ ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
***********************************************************************/ ***********************************************************************/
#ifndef SILK_PLC_FIX_H #ifndef SILK_PLC_H
#define SILK_PLC_FIX_H #define SILK_PLC_H
#include "main.h" #include "main.h"

View file

@ -54,7 +54,8 @@ extern "C"
opus_int silk_resampler_init( opus_int silk_resampler_init(
silk_resampler_state_struct *S, /* I/O Resampler state */ silk_resampler_state_struct *S, /* I/O Resampler state */
opus_int32 Fs_Hz_in, /* I Input sampling rate (Hz) */ opus_int32 Fs_Hz_in, /* I Input sampling rate (Hz) */
opus_int32 Fs_Hz_out /* I Output sampling rate (Hz) */ opus_int32 Fs_Hz_out, /* I Output sampling rate (Hz) */
opus_int forEnc /* I If 1: encoder; if 0: decoder */
); );
/*! /*!
@ -127,15 +128,14 @@ void silk_bwexpander_32(
/* Compute inverse of LPC prediction gain, and */ /* Compute inverse of LPC prediction gain, and */
/* test if LPC coefficients are stable (all poles within unit circle) */ /* 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 silk_LPC_inverse_pred_gain( /* O Returns inverse prediction gain in energy domain, Q30 */
opus_int32 *invGain_Q30, /* O Inverse prediction gain, Q30 energy domain */
const opus_int16 *A_Q12, /* I Prediction coefficients, Q12 [order] */ const opus_int16 *A_Q12, /* I Prediction coefficients, Q12 [order] */
const opus_int order /* I Prediction order */ const opus_int order /* I Prediction order */
); );
opus_int silk_LPC_inverse_pred_gain_Q24( /* O Returns 1 if unstable, otherwise 0 */ /* For input in Q24 domain */
opus_int32 *invGain_Q30, /* O Inverse prediction gain, Q30 energy 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, Q24 [order] */ const opus_int32 *A_Q24, /* I Prediction coefficients [order] */
const opus_int order /* I Prediction order */ const opus_int order /* I Prediction order */
); );
@ -313,9 +313,9 @@ void silk_burg_modified(
opus_int *res_nrg_Q, /* O Residual energy Q value */ opus_int *res_nrg_Q, /* O Residual energy Q value */
opus_int32 A_Q16[], /* O Prediction coefficients (length order) */ opus_int32 A_Q16[], /* O Prediction coefficients (length order) */
const opus_int16 x[], /* I Input signal, length: nb_subfr * ( D + subfr_length ) */ 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 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_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 */ const opus_int D /* I Order */
); );
@ -388,9 +388,9 @@ static inline opus_int32 silk_ROR32( opus_int32 a32, opus_int rot )
#endif #endif
/* Useful Macros that can be adjusted to other platforms */ /* Useful Macros that can be adjusted to other platforms */
#define silk_memcpy(a, b, c) memcpy((a), (b), (c)) /* Dest, Src, ByteCount */ #define silk_memcpy(dest, src, size) memcpy((dest), (src), (size))
#define silk_memset(a, b, c) memset((a), (b), (c)) /* Dest, value, ByteCount */ #define silk_memset(dest, src, size) memset((dest), (src), (size))
#define silk_memmove(a, b, c) memmove((a), (b), (c)) /* Dest, Src, ByteCount */ #define silk_memmove(dest, src, size) memmove((dest), (src), (size))
/* Fixed point macros */ /* Fixed point macros */

View file

@ -204,7 +204,7 @@ opus_int silk_VAD_GetSA_Q8( /* O Return v
sumSquared = silk_DIV32_16( sumSquared, VAD_N_BANDS ); /* Q14 */ sumSquared = silk_DIV32_16( sumSquared, VAD_N_BANDS ); /* Q14 */
/* Root-mean-square approximation, scale to dBs, and write to output pointer */ /* 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 */ /* Speech Probability Estimation */

View file

@ -38,13 +38,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "tuning_parameters.h" #include "tuning_parameters.h"
#include "pitch_est_defines.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( opus_int silk_setup_resamplers(
silk_encoder_state_Fxx *psEnc, /* I/O */ silk_encoder_state_Fxx *psEnc, /* I/O */
opus_int fs_kHz /* I */ opus_int fs_kHz /* I */
@ -150,7 +143,7 @@ opus_int silk_setup_resamplers(
{ {
if( psEnc->sCmn.fs_kHz == 0 ) { if( psEnc->sCmn.fs_kHz == 0 ) {
/* Initialize the resampler for enc_API.c preparing resampling from API_fs_Hz to fs_kHz */ /* 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 { } else {
/* Allocate worst case space for temporary upsampling, 8 to 48 kHz, so a factor 6 */ /* 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 ]; opus_int16 x_buf_API_fs_Hz[ ( 2 * MAX_FRAME_LENGTH_MS + LA_SHAPE_MS ) * MAX_API_FS_KHZ ];
@ -168,7 +161,7 @@ opus_int silk_setup_resamplers(
#endif #endif
/* Initialize resampler for temporary resampling of x_buf data to API_fs_Hz */ /* 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 */ /* 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 ); ret += silk_resampler( &temp_resampler_state, x_buf_API_fs_Hz, x_bufFIX, nSamples_temp );
@ -177,7 +170,7 @@ opus_int silk_setup_resamplers(
nSamples_temp = silk_DIV32_16( nSamples_temp * psEnc->sCmn.API_fs_Hz, silk_SMULBB( psEnc->sCmn.fs_kHz, 1000 ) ); 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 */ /* 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 */ /* 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 ); ret += silk_resampler( &psEnc->sCmn.resampler_state, x_bufFIX, x_buf_API_fs_Hz, nSamples_temp );
@ -234,9 +227,6 @@ opus_int silk_setup_fs(
psEnc->sCmn.TargetRate_bps = 0; /* trigger new SNR computation */ psEnc->sCmn.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 */ /* Set internal sampling frequency */
silk_assert( fs_kHz == 8 || fs_kHz == 12 || fs_kHz == 16 ); silk_assert( fs_kHz == 8 || fs_kHz == 12 || fs_kHz == 16 );
silk_assert( psEnc->sCmn.nb_subfr == 2 || psEnc->sCmn.nb_subfr == 4 ); silk_assert( psEnc->sCmn.nb_subfr == 2 || psEnc->sCmn.nb_subfr == 4 );
@ -336,7 +326,7 @@ opus_int silk_setup_complexity(
psEncC->shapingLPCOrder = 10; psEncC->shapingLPCOrder = 10;
psEncC->la_shape = 5 * psEncC->fs_kHz; psEncC->la_shape = 5 * psEncC->fs_kHz;
psEncC->nStatesDelayedDecision = 1; psEncC->nStatesDelayedDecision = 1;
psEncC->useInterpolatedNLSFs = 1; psEncC->useInterpolatedNLSFs = 0;
psEncC->LTPQuantLowComplexity = 0; psEncC->LTPQuantLowComplexity = 0;
psEncC->NLSF_MSVQ_Survivors = 4; psEncC->NLSF_MSVQ_Survivors = 4;
psEncC->warping_Q16 = 0; psEncC->warping_Q16 = 0;
@ -347,7 +337,7 @@ opus_int silk_setup_complexity(
psEncC->shapingLPCOrder = 12; psEncC->shapingLPCOrder = 12;
psEncC->la_shape = 5 * psEncC->fs_kHz; psEncC->la_shape = 5 * psEncC->fs_kHz;
psEncC->nStatesDelayedDecision = 2; psEncC->nStatesDelayedDecision = 2;
psEncC->useInterpolatedNLSFs = 0; psEncC->useInterpolatedNLSFs = 1;
psEncC->LTPQuantLowComplexity = 0; psEncC->LTPQuantLowComplexity = 0;
psEncC->NLSF_MSVQ_Survivors = 8; psEncC->NLSF_MSVQ_Survivors = 8;
psEncC->warping_Q16 = psEncC->fs_kHz * SILK_FIX_CONST( WARPING_MULTIPLIER, 16 ); psEncC->warping_Q16 = psEncC->fs_kHz * SILK_FIX_CONST( WARPING_MULTIPLIER, 16 );
@ -358,7 +348,7 @@ opus_int silk_setup_complexity(
psEncC->shapingLPCOrder = 14; psEncC->shapingLPCOrder = 14;
psEncC->la_shape = 5 * psEncC->fs_kHz; psEncC->la_shape = 5 * psEncC->fs_kHz;
psEncC->nStatesDelayedDecision = 3; psEncC->nStatesDelayedDecision = 3;
psEncC->useInterpolatedNLSFs = 0; psEncC->useInterpolatedNLSFs = 1;
psEncC->LTPQuantLowComplexity = 0; psEncC->LTPQuantLowComplexity = 0;
psEncC->NLSF_MSVQ_Survivors = 16; psEncC->NLSF_MSVQ_Survivors = 16;
psEncC->warping_Q16 = psEncC->fs_kHz * SILK_FIX_CONST( WARPING_MULTIPLIER, 16 ); psEncC->warping_Q16 = psEncC->fs_kHz * SILK_FIX_CONST( WARPING_MULTIPLIER, 16 );

View file

@ -83,9 +83,9 @@ opus_int silk_Decode( /* O Returns error co
opus_int32 *nSamplesOut /* O Number of samples decoded */ 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_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_int16 samplesOut2_tmp[ MAX_API_FS_KHZ * MAX_FRAME_LENGTH_MS ];
opus_int32 MS_pred_Q13[ 2 ] = { 0 }; opus_int32 MS_pred_Q13[ 2 ] = { 0 };
opus_int16 *resample_out_ptr; opus_int16 *resample_out_ptr;
@ -139,13 +139,10 @@ opus_int silk_Decode( /* O Returns error co
} }
} }
delay = channel_state[ 0 ].delay;
if( decControl->nChannelsAPI == 2 && decControl->nChannelsInternal == 2 && ( psDec->nChannelsAPI == 1 || psDec->nChannelsInternal == 1 ) ) { 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.pred_prev_Q13, 0, sizeof( psDec->sStereo.pred_prev_Q13 ) );
silk_memset( psDec->sStereo.sSide, 0, sizeof( psDec->sStereo.sSide ) ); 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 ].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->nChannelsAPI = decControl->nChannelsAPI;
psDec->nChannelsInternal = decControl->nChannelsInternal; psDec->nChannelsInternal = decControl->nChannelsInternal;
@ -264,20 +261,20 @@ opus_int silk_Decode( /* O Returns error co
} else { } else {
condCoding = CODE_CONDITIONALLY; 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 { } 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++; channel_state[ n ].nFramesDecoded++;
} }
if( decControl->nChannelsAPI == 2 && decControl->nChannelsInternal == 2 ) { if( decControl->nChannelsAPI == 2 && decControl->nChannelsInternal == 2 ) {
/* Convert Mid/Side to Left/Right */ /* 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 { } else {
/* Buffering */ /* Buffering */
silk_memcpy( &samplesOut1_tmp[ 0 ][ delay ], psDec->sStereo.sMid, 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 + delay ], 2 * sizeof( opus_int16 ) ); silk_memcpy( psDec->sStereo.sMid, &samplesOut1_tmp[ 0 ][ nSamplesOutDec ], 2 * sizeof( opus_int16 ) );
} }
/* Number of output samples */ /* Number of output samples */
@ -292,10 +289,8 @@ opus_int silk_Decode( /* O Returns error co
for( n = 0; n < silk_min( decControl->nChannelsAPI, decControl->nChannelsInternal ); n++ ) { 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 */ /* Resample decoded signal to API_sampleRate */
ret += silk_resampler( &channel_state[ n ].resampler_state, resample_out_ptr, &samplesOut1_tmp[ n ][ 1 ], nSamplesOutDec ); 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 */ /* Interleave if stereo output and stereo stream */
if( decControl->nChannelsAPI == 2 && decControl->nChannelsInternal == 2 ) { if( decControl->nChannelsAPI == 2 && decControl->nChannelsInternal == 2 ) {

View file

@ -41,11 +41,11 @@ void silk_decode_core(
const opus_int pulses[ MAX_FRAME_LENGTH ] /* I Pulse signal */ 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 *A_Q12, *B_Q14, *pxq, A_Q12_tmp[ MAX_LPC_ORDER ];
opus_int16 sLTP[ MAX_FRAME_LENGTH ]; opus_int16 sLTP[ MAX_FRAME_LENGTH ];
opus_int32 sLTP_Q16[ 2 * MAX_FRAME_LENGTH ]; opus_int32 sLTP_Q15[ 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 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 *pred_lag_ptr, *pexc_Q10, *pres_Q10;
opus_int32 res_Q10[ MAX_SUB_FRAME_LENGTH ]; opus_int32 res_Q10[ MAX_SUB_FRAME_LENGTH ];
opus_int32 sLPC_Q14[ MAX_SUB_FRAME_LENGTH + MAX_LPC_ORDER ]; opus_int32 sLPC_Q14[ MAX_SUB_FRAME_LENGTH + MAX_LPC_ORDER ];
@ -64,7 +64,7 @@ void silk_decode_core(
rand_seed = psDec->indices.Seed; rand_seed = psDec->indices.Seed;
for( i = 0; i < psDec->frame_length; i++ ) { for( i = 0; i < psDec->frame_length; i++ ) {
rand_seed = silk_RAND( rand_seed ); 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 ) { if( psDec->exc_Q10[ i ] > 0 ) {
psDec->exc_Q10[ i ] -= QUANT_LEVEL_ADJUST_Q10; psDec->exc_Q10[ i ] -= QUANT_LEVEL_ADJUST_Q10;
} else } else
@ -95,7 +95,6 @@ void silk_decode_core(
Gain_Q10 = silk_RSHIFT( psDecCtrl->Gains_Q16[ k ], 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_INVERSE32_varQ( psDecCtrl->Gains_Q16[ k ], 32 );
inv_gain_Q16 = silk_min( inv_gain_Q16, silk_int16_MAX );
/* Calculate Gain adjustment factor */ /* Calculate Gain adjustment factor */
gain_adj_Q16 = 1 << 16; gain_adj_Q16 = 1 << 16;
@ -141,19 +140,19 @@ void silk_decode_core(
A_Q12, psDec->ltp_mem_length - start_idx, psDec->LPC_order ); A_Q12, psDec->ltp_mem_length - start_idx, psDec->LPC_order );
/* After rewhitening the LTP state is unscaled */ /* 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 ) { if( k == 0 ) {
/* Do LTP downscaling to reduce inter-packet dependency */ /* 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++ ) { 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 { } else {
/* Update LTP state when Gain changes */ /* Update LTP state when Gain changes */
if( gain_adj_Q16 != 1 << 16 ) { if( gain_adj_Q16 != 1 << 16 ) {
for( i = 0; i < lag + LTP_ORDER/2; i++ ) { for( i = 0; i < lag + LTP_ORDER/2; i++ ) {
sLTP_Q16[ sLTP_buf_idx - i - 1 ] = silk_SMULWW( gain_adj_Q16, sLTP_Q16[ sLTP_buf_idx - i - 1 ] ); sLTP_Q15[ sLTP_buf_idx - i - 1 ] = silk_SMULWW( gain_adj_Q16, sLTP_Q15[ sLTP_buf_idx - i - 1 ] );
} }
} }
} }
@ -161,22 +160,22 @@ void silk_decode_core(
/* Long-term prediction */ /* Long-term prediction */
if( signalType == TYPE_VOICED ) { if( signalType == TYPE_VOICED ) {
/* Setup pointer */ /* Set up pointer */
pred_lag_ptr = &sLTP_Q16[ sLTP_buf_idx - lag + LTP_ORDER / 2 ]; pred_lag_ptr = &sLTP_Q15[ sLTP_buf_idx - lag + LTP_ORDER / 2 ];
for( i = 0; i < psDec->subfr_length; i++ ) { for( i = 0; i < psDec->subfr_length; i++ ) {
/* Unrolled loop */ /* Unrolled loop */
LTP_pred_Q14 = silk_SMULWB( pred_lag_ptr[ 0 ], B_Q14[ 0 ] ); LTP_pred_Q13 = 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_Q13 = silk_SMLAWB( LTP_pred_Q13, pred_lag_ptr[ -1 ], B_Q14[ 1 ] );
LTP_pred_Q14 = silk_SMLAWB( LTP_pred_Q14, pred_lag_ptr[ -2 ], B_Q14[ 2 ] ); LTP_pred_Q13 = silk_SMLAWB( LTP_pred_Q13, pred_lag_ptr[ -2 ], B_Q14[ 2 ] );
LTP_pred_Q14 = silk_SMLAWB( LTP_pred_Q14, pred_lag_ptr[ -3 ], B_Q14[ 3 ] ); LTP_pred_Q13 = silk_SMLAWB( LTP_pred_Q13, 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_SMLAWB( LTP_pred_Q13, pred_lag_ptr[ -4 ], B_Q14[ 4 ] );
pred_lag_ptr++; pred_lag_ptr++;
/* Generate LPC excitation */ /* 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 */ /* 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++; sLTP_buf_idx++;
} }
} else { } else {
@ -184,7 +183,8 @@ void silk_decode_core(
} }
for( i = 0; i < psDec->subfr_length; i++ ) { 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_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 - 2 ], A_Q12_tmp[ 1 ] );
LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, sLPC_Q14[ MAX_LPC_ORDER + i - 3 ], A_Q12_tmp[ 2 ] ); LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, sLPC_Q14[ MAX_LPC_ORDER + i - 3 ], A_Q12_tmp[ 2 ] );
@ -195,17 +195,23 @@ void silk_decode_core(
LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, sLPC_Q14[ MAX_LPC_ORDER + i - 8 ], A_Q12_tmp[ 7 ] ); LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, sLPC_Q14[ MAX_LPC_ORDER + i - 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 - 9 ], A_Q12_tmp[ 8 ] );
LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, sLPC_Q14[ MAX_LPC_ORDER + i - 10 ], A_Q12_tmp[ 9 ] ); 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++ ) { if( psDec->LPC_order == 16 ) {
LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, sLPC_Q14[ MAX_LPC_ORDER + i - j - 1 ], A_Q12_tmp[ j ] ); 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 */ /* Add prediction to LPC excitation */
sLPC_Q14[ MAX_LPC_ORDER + i ] = silk_LSHIFT( silk_ADD32( pres_Q10[ i ], LPC_pred_Q10 ), 4 ); sLPC_Q14[ MAX_LPC_ORDER + i ] = silk_LSHIFT( silk_ADD32( pres_Q10[ i ], LPC_pred_Q10 ), 4 );
/* Scale with Gain */ /* 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 */ /* Update LPC filter state */
silk_memcpy( sLPC_Q14, &sLPC_Q14[ psDec->subfr_length ], MAX_LPC_ORDER * sizeof( opus_int32 ) ); silk_memcpy( sLPC_Q14, &sLPC_Q14[ psDec->subfr_length ], MAX_LPC_ORDER * sizeof( opus_int32 ) );
pexc_Q10 += psDec->subfr_length; pexc_Q10 += psDec->subfr_length;

View file

@ -72,8 +72,7 @@ void silk_decode_parameters(
silk_NLSF2A( psDecCtrl->PredCoef_Q12[ 0 ], pNLSF0_Q15, psDec->LPC_order ); silk_NLSF2A( psDecCtrl->PredCoef_Q12[ 0 ], pNLSF0_Q15, psDec->LPC_order );
} else { } else {
/* Copy LPC coefficients for first half from second half */ /* Copy LPC coefficients for first half from second half */
silk_memcpy( psDecCtrl->PredCoef_Q12[ 0 ], psDecCtrl->PredCoef_Q12[ 1 ], silk_memcpy( psDecCtrl->PredCoef_Q12[ 0 ], psDecCtrl->PredCoef_Q12[ 1 ], psDec->LPC_order * sizeof( opus_int16 ) );
psDec->LPC_order * sizeof( opus_int16 ) );
} }
silk_memcpy( psDec->prevNLSF_Q15, pNLSF_Q15, psDec->LPC_order * sizeof( opus_int16 ) ); silk_memcpy( psDec->prevNLSF_Q15, pNLSF_Q15, psDec->LPC_order * sizeof( opus_int16 ) );

View file

@ -31,13 +31,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "main.h" #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 */ /* Set decoder sampling rate */
opus_int silk_decoder_set_fs( opus_int silk_decoder_set_fs(
silk_decoder_state *psDec, /* I/O Decoder state pointer */ silk_decoder_state *psDec, /* I/O Decoder state pointer */
@ -60,13 +53,9 @@ opus_int silk_decoder_set_fs(
opus_int16 temp_buf[ MAX_FRAME_LENGTH_MS * MAX_API_FS_KHZ ]; opus_int16 temp_buf[ MAX_FRAME_LENGTH_MS * MAX_API_FS_KHZ ];
silk_resampler_state_struct temp_resampler_state; 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 ) { if( psDec->fs_kHz != fs_kHz && psDec->fs_kHz > 0 ) {
/* Initialize resampler for temporary resampling of outBuf data to the new internal sampling rate */ /* 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 */ /* Temporary resampling of outBuf data to the new internal sampling rate */
silk_memcpy( temp_buf, psDec->outBuf, psDec->frame_length * sizeof( opus_int16 ) ); silk_memcpy( temp_buf, psDec->outBuf, psDec->frame_length * sizeof( opus_int16 ) );
@ -74,7 +63,7 @@ opus_int silk_decoder_set_fs(
} }
/* Initialize the resampler for dec_API.c preparing resampling from fs_kHz to API_fs_Hz */ /* 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 */ /* 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 ); ret += silk_resampler( &psDec->resampler_state, temp_buf, psDec->outBuf, frame_length );

View file

@ -91,9 +91,6 @@ extern "C"
#define MAX_FRAME_LENGTH_MS ( SUB_FRAME_LENGTH_MS * MAX_NB_SUBFR ) #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_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 */ /* Milliseconds of lookahead for pitch analysis */
#define LA_PITCH_MS 2 #define LA_PITCH_MS 2
#define LA_PITCH_MAX ( LA_PITCH_MS * MAX_FS_KHZ ) #define LA_PITCH_MAX ( LA_PITCH_MS * MAX_FS_KHZ )
@ -133,7 +130,9 @@ extern "C"
#define QUANT_LEVEL_ADJUST_Q10 80 #define QUANT_LEVEL_ADJUST_Q10 80
/* Maximum numbers of iterations used to stabilize a LPC vector */ /* 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 MAX_LPC_ORDER 16
#define MIN_LPC_ORDER 10 #define MIN_LPC_ORDER 10

View file

@ -140,10 +140,10 @@ opus_int silk_Encode( /* O Returns error co
opus_int n, i, nBits, flags, tmp_payloadSize_ms = 0, tmp_complexity = 0, ret = 0; opus_int n, i, nBits, flags, tmp_payloadSize_ms = 0, tmp_complexity = 0, ret = 0;
opus_int nSamplesToBuffer, nBlocksOf10ms, nSamplesFromInput = 0; opus_int nSamplesToBuffer, nBlocksOf10ms, nSamplesFromInput = 0;
opus_int speech_act_thr_for_switch_Q8; 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; silk_encoder *psEnc = ( silk_encoder * )encState;
opus_int16 buf[ MAX_FRAME_LENGTH_MS * MAX_API_FS_KHZ + MAX_ENCODER_DELAY]; opus_int16 buf[ MAX_FRAME_LENGTH_MS * MAX_API_FS_KHZ ];
opus_int transition, delay, curr_block, tot_blocks; opus_int transition, curr_block, tot_blocks;
psEnc->state_Fxx[ 0 ].sCmn.nFramesEncoded = psEnc->state_Fxx[ 1 ].sCmn.nFramesEncoded = 0; psEnc->state_Fxx[ 0 ].sCmn.nFramesEncoded = psEnc->state_Fxx[ 1 ].sCmn.nFramesEncoded = 0;
@ -233,7 +233,6 @@ opus_int silk_Encode( /* O Returns error co
} }
silk_assert( encControl->nChannelsInternal == 1 || psEnc->state_Fxx[ 0 ].sCmn.fs_kHz == psEnc->state_Fxx[ 1 ].sCmn.fs_kHz ); 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 */ /* Input buffering/resampling and encoding */
while( 1 ) { while( 1 ) {
nSamplesToBuffer = psEnc->state_Fxx[ 0 ].sCmn.frame_length - psEnc->state_Fxx[ 0 ].sCmn.inputBufIx; nSamplesToBuffer = psEnc->state_Fxx[ 0 ].sCmn.frame_length - psEnc->state_Fxx[ 0 ].sCmn.inputBufIx;
@ -243,15 +242,12 @@ opus_int silk_Encode( /* O Returns error co
if( encControl->nChannelsAPI == 2 && encControl->nChannelsInternal == 2 ) { if( encControl->nChannelsAPI == 2 && encControl->nChannelsInternal == 2 ) {
opus_int id = psEnc->state_Fxx[ 0 ].sCmn.nFramesEncoded; opus_int id = psEnc->state_Fxx[ 0 ].sCmn.nFramesEncoded;
for( n = 0; n < nSamplesFromInput; n++ ) { 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 */ /* 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.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, 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 ); &psEnc->state_Fxx[ 0 ].sCmn.inputBuf[ psEnc->state_Fxx[ 0 ].sCmn.inputBufIx + 2 ], buf, nSamplesFromInput );
@ -260,25 +256,18 @@ opus_int silk_Encode( /* O Returns error co
nSamplesToBuffer = psEnc->state_Fxx[ 1 ].sCmn.frame_length - psEnc->state_Fxx[ 1 ].sCmn.inputBufIx; nSamplesToBuffer = 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 ); nSamplesToBuffer = silk_min( nSamplesToBuffer, 10 * nBlocksOf10ms * psEnc->state_Fxx[ 1 ].sCmn.fs_kHz );
for( n = 0; n < nSamplesFromInput; n++ ) { 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, 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 ); &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; psEnc->state_Fxx[ 1 ].sCmn.inputBufIx += nSamplesToBuffer;
} else if( encControl->nChannelsAPI == 2 && encControl->nChannelsInternal == 1 ) { } else if( encControl->nChannelsAPI == 2 && encControl->nChannelsInternal == 1 ) {
/* Combine left and right channels before resampling */ /* Combine left and right channels before resampling */
for( n = 0; n < nSamplesFromInput; n++ ) { 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, 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 ); &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 */ /* On the first mono frame, average the results for the two resampler states */
@ -291,15 +280,12 @@ opus_int silk_Encode( /* O Returns error co
+ psEnc->state_Fxx[ 1 ].sCmn.inputBuf[ psEnc->state_Fxx[ 1 ].sCmn.inputBufIx+n+2 ], 1); + 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; psEnc->state_Fxx[ 0 ].sCmn.inputBufIx += nSamplesToBuffer;
} else { } else {
silk_assert( encControl->nChannelsAPI == 1 && encControl->nChannelsInternal == 1 ); silk_assert( encControl->nChannelsAPI == 1 && encControl->nChannelsInternal == 1 );
silk_memcpy(buf + delay, samplesIn, nSamplesFromInput*sizeof(opus_int16)); silk_memcpy(buf, samplesIn, nSamplesFromInput*sizeof(opus_int16));
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, 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 ); &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; psEnc->state_Fxx[ 0 ].sCmn.inputBufIx += nSamplesToBuffer;
} }

View file

@ -69,7 +69,7 @@ void silk_LTP_analysis_filter_FIX(
LTP_est = silk_RSHIFT_ROUND( LTP_est, 14 ); /* round and -> Q0*/ LTP_est = silk_RSHIFT_ROUND( LTP_est, 14 ); /* round and -> Q0*/
/* Subtract long-term prediction */ /* 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 */ /* Scale residual */
LTP_res_ptr[ i ] = silk_SMULWB( invGains_Q16[ k ], LTP_res_ptr[ i ] ); LTP_res_ptr[ i ] = silk_SMULWB( invGains_Q16[ k ], LTP_res_ptr[ i ] );

View file

@ -40,16 +40,11 @@ void silk_LTP_scale_ctrl_FIX(
{ {
opus_int round_loss; 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 ) { 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( 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 { } else {
/* Default is minimum scaling */ /* Default is minimum scaling */
psEnc->sCmn.indices.LTP_scaleIndex = 0; psEnc->sCmn.indices.LTP_scaleIndex = 0;

View file

@ -30,9 +30,10 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#endif #endif
#include "SigProc_FIX.h" #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_FRAME_SIZE 384 /* subfr_length * nb_subfr = ( 0.005 * 16000 + 16 ) * 4 = 384 */
#define MAX_NB_SUBFR 4
#define QA 25 #define QA 25
#define N_BITS_HEAD_ROOM 2 #define N_BITS_HEAD_ROOM 2
@ -45,26 +46,22 @@ void silk_burg_modified(
opus_int *res_nrg_Q, /* O Residual energy Q value */ opus_int *res_nrg_Q, /* O Residual energy Q value */
opus_int32 A_Q16[], /* O Prediction coefficients (length order) */ opus_int32 A_Q16[], /* O Prediction coefficients (length order) */
const opus_int16 x[], /* I Input signal, length: nb_subfr * ( D + subfr_length ) */ 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 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_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 */ const opus_int D /* I Order */
) )
{ {
opus_int k, n, s, lz, rshifts, rshifts_extra; opus_int k, n, s, lz, rshifts, rshifts_extra, reached_max_gain;
opus_int32 C0, num, nrg, rc_Q31, Atmp_QA, Atmp1, tmp1, tmp2, x1, x2; opus_int32 C0, num, nrg, rc_Q31, invGain_Q30, Atmp_QA, Atmp1, tmp1, tmp2, x1, x2;
const opus_int16 *x_ptr; const opus_int16 *x_ptr;
opus_int32 C_first_row[ SILK_MAX_ORDER_LPC ]; opus_int32 C_first_row[ SILK_MAX_ORDER_LPC ];
opus_int32 C_last_row[ SILK_MAX_ORDER_LPC ]; opus_int32 C_last_row[ SILK_MAX_ORDER_LPC ];
opus_int32 Af_QA[ SILK_MAX_ORDER_LPC ]; opus_int32 Af_QA[ SILK_MAX_ORDER_LPC ];
opus_int32 CAf[ SILK_MAX_ORDER_LPC + 1 ]; opus_int32 CAf[ SILK_MAX_ORDER_LPC + 1 ];
opus_int32 CAb[ SILK_MAX_ORDER_LPC + 1 ]; opus_int32 CAb[ SILK_MAX_ORDER_LPC + 1 ];
silk_assert( subfr_length * nb_subfr <= MAX_FRAME_SIZE ); silk_assert( subfr_length * nb_subfr <= MAX_FRAME_SIZE );
silk_assert( nb_subfr <= MAX_NB_SUBFR );
/* Compute autocorrelations, added over subframes */ /* Compute autocorrelations, added over subframes */
silk_sum_sqr_shift( &C0, &rshifts, x, nb_subfr * subfr_length ); silk_sum_sqr_shift( &C0, &rshifts, x, nb_subfr * subfr_length );
@ -84,6 +81,7 @@ void silk_burg_modified(
} }
rshifts += rshifts_extra; 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 ) ); silk_memset( C_first_row, 0, SILK_MAX_ORDER_LPC * sizeof( opus_int32 ) );
if( rshifts > 0 ) { if( rshifts > 0 ) {
for( s = 0; s < nb_subfr; s++ ) { for( s = 0; s < nb_subfr; s++ ) {
@ -105,8 +103,10 @@ void silk_burg_modified(
silk_memcpy( C_last_row, C_first_row, SILK_MAX_ORDER_LPC * sizeof( opus_int32 ) ); silk_memcpy( C_last_row, C_first_row, SILK_MAX_ORDER_LPC * sizeof( opus_int32 ) );
/* Initialize */ /* 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++ ) { for( n = 0; n < D; n++ ) {
/* Update first row of correlation matrix (without first element) */ /* Update first row of correlation matrix (without first element) */
/* Update last row of correlation matrix (without last element, stored in reversed order) */ /* Update last row of correlation matrix (without last element, stored in reversed order) */
@ -115,108 +115,155 @@ void silk_burg_modified(
if( rshifts > -2 ) { if( rshifts > -2 ) {
for( s = 0; s < nb_subfr; s++ ) { for( s = 0; s < nb_subfr; s++ ) {
x_ptr = x + s * subfr_length; x_ptr = x + s * subfr_length;
x1 = -silk_LSHIFT32( (opus_int32)x_ptr[ n ], 16 - rshifts ); /* Q(16-rshifts)*/ 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)*/ 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)*/ 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)*/ tmp2 = silk_LSHIFT32( (opus_int32)x_ptr[ subfr_length - n - 1 ], QA - 16 ); /* Q(QA-16) */
for( k = 0; k < n; k++ ) { 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_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_last_row[ k ] = silk_SMLAWB( C_last_row[ k ], x2, x_ptr[ subfr_length - n + k ] ); /* Q( -rshifts ) */
Atmp_QA = Af_QA[ k ]; Atmp_QA = Af_QA[ k ];
tmp1 = silk_SMLAWB( tmp1, Atmp_QA, x_ptr[ n - k - 1 ] ); /* 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)*/ 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)*/ tmp1 = silk_LSHIFT32( -tmp1, 32 - QA - rshifts ); /* Q(16-rshifts) */
tmp2 = silk_LSHIFT32( -tmp2, 32 - QA - rshifts ); /* Q(16-rshifts)*/ tmp2 = silk_LSHIFT32( -tmp2, 32 - QA - rshifts ); /* Q(16-rshifts) */
for( k = 0; k <= n; k++ ) { for( k = 0; k <= n; k++ ) {
CAf[ k ] = silk_SMLAWB( CAf[ k ], tmp1, x_ptr[ n - k ] ); /* 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 )*/ CAb[ k ] = silk_SMLAWB( CAb[ k ], tmp2, x_ptr[ subfr_length - n + k - 1 ] ); /* Q( -rshift ) */
} }
} }
} else { } else {
for( s = 0; s < nb_subfr; s++ ) { for( s = 0; s < nb_subfr; s++ ) {
x_ptr = x + s * subfr_length; x_ptr = x + s * subfr_length;
x1 = -silk_LSHIFT32( (opus_int32)x_ptr[ n ], -rshifts ); /* Q( -rshifts )*/ 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 )*/ x2 = -silk_LSHIFT32( (opus_int32)x_ptr[ subfr_length - n - 1 ], -rshifts ); /* Q( -rshifts ) */
tmp1 = silk_LSHIFT32( (opus_int32)x_ptr[ n ], 17 ); /* Q17*/ tmp1 = silk_LSHIFT32( (opus_int32)x_ptr[ n ], 17 ); /* Q17 */
tmp2 = silk_LSHIFT32( (opus_int32)x_ptr[ subfr_length - n - 1 ], 17 ); /* Q17*/ tmp2 = silk_LSHIFT32( (opus_int32)x_ptr[ subfr_length - n - 1 ], 17 ); /* Q17 */
for( k = 0; k < n; k++ ) { 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_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 )*/ 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*/ Atmp1 = silk_RSHIFT_ROUND( Af_QA[ k ], QA - 17 ); /* Q17 */
tmp1 = silk_MLA( tmp1, x_ptr[ n - k - 1 ], Atmp1 ); /* Q17*/ tmp1 = silk_MLA( tmp1, x_ptr[ n - k - 1 ], Atmp1 ); /* Q17 */
tmp2 = silk_MLA( tmp2, x_ptr[ subfr_length - n + k ], Atmp1 ); /* Q17*/ tmp2 = silk_MLA( tmp2, x_ptr[ subfr_length - n + k ], Atmp1 ); /* Q17 */
} }
tmp1 = -tmp1; /* Q17*/ tmp1 = -tmp1; /* Q17 */
tmp2 = -tmp2; /* Q17*/ tmp2 = -tmp2; /* Q17 */
for( k = 0; k <= n; k++ ) { for( k = 0; k <= n; k++ ) {
CAf[ k ] = silk_SMLAWW( CAf[ k ], tmp1, 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, 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 */ /* Calculate nominator and denominator for the next order reflection (parcor) coefficient */
tmp1 = C_first_row[ n ]; /* Q( -rshifts )*/ tmp1 = C_first_row[ n ]; /* Q( -rshifts ) */
tmp2 = C_last_row[ n ]; /* Q( -rshifts )*/ tmp2 = C_last_row[ n ]; /* Q( -rshifts ) */
num = 0; /* Q( -rshifts )*/ num = 0; /* Q( -rshifts ) */
nrg = silk_ADD32( CAb[ 0 ], CAf[ 0 ] ); /* Q( 1-rshifts )*/ nrg = silk_ADD32( CAb[ 0 ], CAf[ 0 ] ); /* Q( 1-rshifts ) */
for( k = 0; k < n; k++ ) { for( k = 0; k < n; k++ ) {
Atmp_QA = Af_QA[ k ]; Atmp_QA = Af_QA[ k ];
lz = silk_CLZ32( silk_abs( Atmp_QA ) ) - 1; lz = silk_CLZ32( silk_abs( Atmp_QA ) ) - 1;
lz = silk_min( 32 - QA, lz ); 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 )*/ 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 )*/ 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 )*/ 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 ] ), 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 )*/ CAf[ n + 1 ] = tmp1; /* Q( -rshifts ) */
CAb[ n + 1 ] = tmp2; /* Q( -rshifts )*/ CAb[ n + 1 ] = tmp2; /* Q( -rshifts ) */
num = silk_ADD32( num, tmp2 ); /* Q( -rshifts )*/ num = silk_ADD32( num, tmp2 ); /* Q( -rshifts ) */
num = silk_LSHIFT32( -num, 1 ); /* Q( 1-rshifts )*/ num = silk_LSHIFT32( -num, 1 ); /* Q( 1-rshifts ) */
/* Calculate the next order reflection (parcor) coefficient */ /* Calculate the next order reflection (parcor) coefficient */
if( silk_abs( num ) < nrg ) { if( silk_abs( num ) < nrg ) {
rc_Q31 = silk_DIV32_varQ( num, nrg, 31 ); rc_Q31 = silk_DIV32_varQ( num, nrg, 31 );
} else { } else {
/* Negative energy or ratio too high; set remaining coefficients to zero and exit loop */ rc_Q31 = ( num > 0 ) ? silk_int32_MAX : silk_int32_MIN;
silk_memset( &Af_QA[ n ], 0, ( D - n ) * sizeof( opus_int32 ) ); }
silk_assert( 0 );
break; /* 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 */ /* Update the AR coefficients */
for( k = 0; k < (n + 1) >> 1; k++ ) { for( k = 0; k < (n + 1) >> 1; k++ ) {
tmp1 = Af_QA[ k ]; /* QA*/ tmp1 = Af_QA[ k ]; /* QA */
tmp2 = Af_QA[ n - k - 1 ]; /* QA*/ tmp2 = Af_QA[ n - k - 1 ]; /* QA */
Af_QA[ k ] = silk_ADD_LSHIFT32( tmp1, silk_SMMUL( tmp2, rc_Q31 ), 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 - k - 1 ] = silk_ADD_LSHIFT32( tmp2, silk_SMMUL( tmp1, rc_Q31 ), 1 ); /* QA */
}
Af_QA[ n ] = silk_RSHIFT32( rc_Q31, 31 - QA ); /* QA */
if( reached_max_gain ) {
/* Reached max prediction gain; set remaining coefficients to zero and exit loop */
for( k = n + 1; k < D; k++ ) {
Af_QA[ k ] = 0;
}
break;
} }
Af_QA[ n ] = silk_RSHIFT32( rc_Q31, 31 - QA ); /* QA*/
/* Update C * Af and C * Ab */ /* Update C * Af and C * Ab */
for( k = 0; k <= n + 1; k++ ) { for( k = 0; k <= n + 1; k++ ) {
tmp1 = CAf[ k ]; /* Q( -rshifts )*/ tmp1 = CAf[ k ]; /* Q( -rshifts ) */
tmp2 = CAb[ n - k + 1 ]; /* Q( -rshifts )*/ tmp2 = CAb[ n - k + 1 ]; /* Q( -rshifts ) */
CAf[ k ] = silk_ADD_LSHIFT32( tmp1, silk_SMMUL( tmp2, rc_Q31 ), 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 )*/ CAb[ n - k + 1 ] = silk_ADD_LSHIFT32( tmp2, silk_SMMUL( tmp1, rc_Q31 ), 1 ); /* Q( -rshifts ) */
} }
} }
/* Return residual energy */ if( reached_max_gain ) {
nrg = CAf[ 0 ]; /* Q( -rshifts )*/
tmp1 = 1 << 16; /* Q16*/
for( k = 0; k < D; k++ ) { for( k = 0; k < D; k++ ) {
Atmp1 = silk_RSHIFT_ROUND( Af_QA[ k ], QA - 16 ); /* Q16*/ /* Scale coefficients */
nrg = silk_SMLAWW( nrg, CAf[ k + 1 ], Atmp1 ); /* Q( -rshifts )*/ A_Q16[ k ] = -silk_RSHIFT_ROUND( Af_QA[ k ], QA - 16 );
tmp1 = silk_SMLAWW( tmp1, Atmp1, Atmp1 ); /* Q16*/ }
/* 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; A_Q16[ k ] = -Atmp1;
} }
*res_nrg = silk_SMLAWW( nrg, silk_SMMUL( WhiteNoiseFrac_Q32, C0 ), -tmp1 ); /* Q( -rshifts )*/ *res_nrg = silk_SMLAWW( nrg, silk_SMMUL( FIND_LPC_COND_FAC, C0 ), -tmp1 ); /* Q( -rshifts ) */
*res_nrg_Q = -rshifts; *res_nrg_Q = -rshifts;
}
} }

View file

@ -36,7 +36,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
static inline void silk_LBRR_encode_FIX( static inline void silk_LBRR_encode_FIX(
silk_encoder_state_FIX *psEnc, /* I/O Pointer to Silk FIX encoder state */ silk_encoder_state_FIX *psEnc, /* I/O Pointer to Silk FIX encoder state */
silk_encoder_control_FIX *psEncCtrl, /* I/O Pointer to Silk FIX encoder control struct */ 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 */ opus_int condCoding /* I The type of conditional coding used so far for this frame */
); );
@ -85,7 +85,7 @@ opus_int silk_encode_frame_FIX(
silk_encoder_control_FIX sEncCtrl; silk_encoder_control_FIX sEncCtrl;
opus_int i, iter, maxIter, found_upper, found_lower, ret = 0; opus_int i, iter, maxIter, found_upper, found_lower, ret = 0;
opus_int16 *x_frame, *res_pitch_frame; 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 ]; opus_int16 res_pitch[ 2 * MAX_FRAME_LENGTH + LA_PITCH_MAX ];
ec_enc sRangeEnc_copy, sRangeEnc_copy2; ec_enc sRangeEnc_copy, sRangeEnc_copy2;
silk_nsq_state sNSQ_copy, sNSQ_copy2; silk_nsq_state sNSQ_copy, sNSQ_copy2;
@ -103,7 +103,7 @@ opus_int silk_encode_frame_FIX(
psEnc->sCmn.indices.Seed = psEnc->sCmn.frameCounter++ & 3; 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 */ /* pointers aligned with start of frame to encode */
x_frame = psEnc->x_buf + psEnc->sCmn.ltp_mem_length; /* start of frame to encode */ x_frame = psEnc->x_buf + psEnc->sCmn.ltp_mem_length; /* start of frame to encode */
@ -143,15 +143,15 @@ opus_int silk_encode_frame_FIX(
/*****************************************/ /*****************************************/
/* Prefiltering for noise shaper */ /* 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 */ /* 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 */ /* Loop over quantizer and entropy coding to control bitrate */
maxIter = 5; maxIter = 6;
gainMult_Q8 = SILK_FIX_CONST( 1, 8 ); gainMult_Q8 = SILK_FIX_CONST( 1, 8 );
found_lower = 0; found_lower = 0;
found_upper = 0; found_upper = 0;
@ -183,11 +183,11 @@ opus_int silk_encode_frame_FIX(
/* Noise shaping quantization */ /* Noise shaping quantization */
/*****************************************/ /*****************************************/
if( psEnc->sCmn.nStatesDelayedDecision > 1 || psEnc->sCmn.warping_Q16 > 0 ) { 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.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 ); sEncCtrl.Tilt_Q14, sEncCtrl.LF_shp_Q14, sEncCtrl.Gains_Q16, sEncCtrl.pitchL, sEncCtrl.Lambda_Q10, sEncCtrl.LTP_scale_Q14 );
} else { } 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.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 ); sEncCtrl.Tilt_Q14, sEncCtrl.LF_shp_Q14, sEncCtrl.Gains_Q16, sEncCtrl.pitchL, sEncCtrl.Lambda_Q10, sEncCtrl.LTP_scale_Q14 );
} }
@ -316,7 +316,7 @@ opus_int silk_encode_frame_FIX(
static inline void silk_LBRR_encode_FIX( static inline void silk_LBRR_encode_FIX(
silk_encoder_state_FIX *psEnc, /* I/O Pointer to Silk FIX encoder state */ silk_encoder_state_FIX *psEnc, /* I/O Pointer to Silk FIX encoder state */
silk_encoder_control_FIX *psEncCtrl, /* I/O Pointer to Silk FIX encoder control struct */ 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 */ opus_int condCoding /* I The type of conditional coding used so far for this frame */
) )
{ {
@ -355,12 +355,12 @@ static inline void silk_LBRR_encode_FIX(
/* Noise shaping quantization */ /* Noise shaping quantization */
/*****************************************/ /*****************************************/
if( psEnc->sCmn.nStatesDelayedDecision > 1 || psEnc->sCmn.warping_Q16 > 0 ) { 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, 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->AR2_Q13, psEncCtrl->HarmShapeGain_Q14, psEncCtrl->Tilt_Q14, psEncCtrl->LF_shp_Q14,
psEncCtrl->Gains_Q16, psEncCtrl->pitchL, psEncCtrl->Lambda_Q10, psEncCtrl->LTP_scale_Q14 ); psEncCtrl->Gains_Q16, psEncCtrl->pitchL, psEncCtrl->Lambda_Q10, psEncCtrl->LTP_scale_Q14 );
} else { } 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, 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->AR2_Q13, psEncCtrl->HarmShapeGain_Q14, psEncCtrl->Tilt_Q14, psEncCtrl->LF_shp_Q14,
psEncCtrl->Gains_Q16, psEncCtrl->pitchL, psEncCtrl->Lambda_Q10, psEncCtrl->LTP_scale_Q14 ); psEncCtrl->Gains_Q16, psEncCtrl->pitchL, psEncCtrl->Lambda_Q10, psEncCtrl->LTP_scale_Q14 );

View file

@ -34,18 +34,13 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
/* Finds LPC vector from correlations, and converts to NLSF */ /* Finds LPC vector from correlations, and converts to NLSF */
void silk_find_LPC_FIX( void silk_find_LPC_FIX(
silk_encoder_state *psEncC, /* I/O Encoder state */
opus_int16 NLSF_Q15[], /* O NLSFs */ 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_int16 x[], /* I Input signal */
const opus_int subfr_length, /* I Input signal subframe length including preceeding samples */ const opus_int32 minInvGain_Q30 /* I Inverse of max prediction gain */
const opus_int nb_subfr /* I Number of subframes */
) )
{ {
opus_int k; opus_int k, subfr_length;
opus_int32 a_Q16[ MAX_LPC_ORDER ]; opus_int32 a_Q16[ MAX_LPC_ORDER ];
opus_int isInterpLower, shift; opus_int isInterpLower, shift;
opus_int32 res_nrg0, res_nrg1; opus_int32 res_nrg0, res_nrg1;
@ -56,27 +51,19 @@ void silk_find_LPC_FIX(
opus_int res_nrg_interp_Q, res_nrg_Q, res_tmp_nrg_Q; opus_int res_nrg_interp_Q, res_nrg_Q, res_tmp_nrg_Q;
opus_int16 a_tmp_Q12[ MAX_LPC_ORDER ]; opus_int16 a_tmp_Q12[ MAX_LPC_ORDER ];
opus_int16 NLSF0_Q15[ 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 */ /* Default: no interpolation */
*interpIndex = 4; psEncC->indices.NLSFInterpCoef_Q2 = 4;
/* Burg AR analysis for the full frame */ /* 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 */ /* 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, silk_burg_modified( &res_tmp_nrg, &res_tmp_nrg_Q, a_tmp_Q16, x + 2 * subfr_length, minInvGain_Q30, subfr_length, 2, psEncC->predictLPCOrder );
subfr_length, ( MAX_NB_SUBFR >> 1 ), SILK_FIX_CONST( FIND_LPC_COND_FAC, 32 ), LPC_order );
silk_bwexpander_32( a_tmp_Q16, LPC_order, SILK_FIX_CONST( FIND_LPC_CHIRP, 16 ) );
/* subtract residual energy here, as that's easier than adding it to the */ /* 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 */ /* residual energy of the first 10 ms in each iteration of the search below */
@ -92,21 +79,21 @@ void silk_find_LPC_FIX(
} }
/* Convert to NLSFs */ /* 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 */ /* Search over interpolation indices to find the one with lowest residual energy */
for( k = 3; k >= 0; k-- ) { for( k = 3; k >= 0; k-- ) {
/* Interpolate NLSFs for first half */ /* 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 */ /* 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 */ /* 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_nrg0, &rshift0, LPC_res + psEncC->predictLPCOrder, subfr_length - psEncC->predictLPCOrder );
silk_sum_sqr_shift( &res_nrg1, &rshift1, LPC_res + LPC_order + subfr_length, subfr_length - LPC_order ); silk_sum_sqr_shift( &res_nrg1, &rshift1, LPC_res + psEncC->predictLPCOrder + subfr_length, subfr_length - psEncC->predictLPCOrder );
/* Add subframe energies from first half frame */ /* Add subframe energies from first half frame */
shift = rshift0 - rshift1; shift = rshift0 - rshift1;
@ -144,15 +131,15 @@ void silk_find_LPC_FIX(
/* Interpolation has lower residual energy */ /* Interpolation has lower residual energy */
res_nrg = res_nrg_interp; res_nrg = res_nrg_interp;
res_nrg_Q = res_nrg_interp_Q; 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 */ /* 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 ) );
} }

View file

@ -113,7 +113,7 @@ void silk_find_LTP_FIX(
silk_RSHIFT( silk_SMULWB( subfr_length, 655 ), corr_rshifts[ k ] - extra_shifts ); /* Q( -corr_rshifts[ k ] + extra_shifts ) */ silk_RSHIFT( silk_SMULWB( subfr_length, 655 ), corr_rshifts[ k ] - extra_shifts ); /* Q( -corr_rshifts[ k ] + extra_shifts ) */
denom32 = silk_max( denom32, 1 ); denom32 = silk_max( denom32, 1 );
silk_assert( ((opus_int64)Wght_Q15[ k ] << 16 ) < silk_int32_MAX ); /* Wght always < 0.5 in Q0 */ 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 */ temp32 = silk_RSHIFT( temp32, 31 + corr_rshifts[ k ] - extra_shifts - 26 ); /* Q26 */
/* Limit temp such that the below scaling never wraps around */ /* Limit temp such that the below scaling never wraps around */
@ -124,7 +124,7 @@ void silk_find_LTP_FIX(
lshift = silk_CLZ32( WLTP_max ) - 1 - 3; /* keep 3 bits free for vq_nearest_neighbor_fix */ lshift = silk_CLZ32( WLTP_max ) - 1 - 3; /* keep 3 bits free for vq_nearest_neighbor_fix */
silk_assert( 26 - 18 + lshift >= 0 ); silk_assert( 26 - 18 + lshift >= 0 );
if( 26 - 18 + lshift < 31 ) { 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 ] ) */ silk_scale_vector32_Q26_lshift_18( WLTP_ptr, temp32, LTP_ORDER * LTP_ORDER ); /* WLTP_ptr in Q( 18 - corr_rshifts[ k ] ) */
@ -216,16 +216,16 @@ void silk_find_LTP_FIX(
silk_DIV32( silk_DIV32(
SILK_FIX_CONST( LTP_SMOOTHING, 26 ), SILK_FIX_CONST( LTP_SMOOTHING, 26 ),
silk_RSHIFT( SILK_FIX_CONST( LTP_SMOOTHING, 26 ), 10 ) + temp32 ), /* Q10 */ 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; temp32 = 0;
for( i = 0; i < LTP_ORDER; i++ ) { for( i = 0; i < LTP_ORDER; i++ ) {
delta_b_Q14[ i ] = silk_max_16( b_Q14_ptr[ i ], 1638 ); /* 1638_Q14 = 0.1_Q0 */ delta_b_Q14[ i ] = silk_max_16( b_Q14_ptr[ i ], 1638 ); /* 1638_Q14 = 0.1_Q0 */
temp32 += delta_b_Q14[ i ]; /* Q14 */ 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++ ) { 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; b_Q14_ptr += LTP_ORDER;
} }
@ -239,6 +239,6 @@ void silk_fit_LTP(
opus_int i; opus_int i;
for( i = 0; i < LTP_ORDER; 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 ) );
} }
} }

View file

@ -50,7 +50,7 @@ void silk_find_pitch_lags_FIX(
opus_int16 A_Q12[ MAX_FIND_PITCH_LPC_ORDER ]; 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; buf_len = psEnc->sCmn.la_pitch + psEnc->sCmn.frame_length + psEnc->sCmn.ltp_mem_length;
@ -97,7 +97,7 @@ void silk_find_pitch_lags_FIX(
/* Convert From 32 bit Q24 to 16 bit Q12 coefs */ /* Convert From 32 bit Q24 to 16 bit Q12 coefs */
for( i = 0; i < psEnc->sCmn.pitchEstimationLPCOrder; i++ ) { 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 */ /* Do BWE */
@ -122,7 +122,7 @@ void silk_find_pitch_lags_FIX(
/*****************************************/ /*****************************************/
if( silk_pitch_analysis_core( res, psEncCtrl->pitchL, &psEnc->sCmn.indices.lagIndex, &psEnc->sCmn.indices.contourIndex, 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, &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; psEnc->sCmn.indices.signalType = TYPE_VOICED;
} else { } else {

View file

@ -45,7 +45,7 @@ void silk_find_pred_coefs_FIX(
opus_int16 NLSF_Q15[ MAX_LPC_ORDER ]; opus_int16 NLSF_Q15[ MAX_LPC_ORDER ];
const opus_int16 *x_ptr; const opus_int16 *x_ptr;
opus_int16 *x_pre_ptr, LPC_in_pre[ MAX_NB_SUBFR * MAX_LPC_ORDER + MAX_FRAME_LENGTH ]; 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 ]; opus_int LTP_corrs_rshift[ MAX_NB_SUBFR ];
/* weighting for weighted least squares */ /* weighting for weighted least squares */
@ -111,10 +111,18 @@ void silk_find_pred_coefs_FIX(
psEncCtrl->LTPredCodGain_Q7 = 0; 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 */ /* 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, silk_find_LPC_FIX( &psEnc->sCmn, NLSF_Q15, LPC_in_pre, minInvGain_Q30 );
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 );
/* Quantize LSFs */ /* Quantize LSFs */
silk_process_NLSFs( &psEnc->sCmn, psEncCtrl->PredCoef_Q12, NLSF_Q15, psEnc->sCmn.prev_NLSFq_Q15 ); silk_process_NLSFs( &psEnc->sCmn, psEncCtrl->PredCoef_Q12, NLSF_Q15, psEnc->sCmn.prev_NLSFq_Q15 );

View file

@ -92,7 +92,7 @@ opus_int silk_control_encoder(
void silk_prefilter_FIX( void silk_prefilter_FIX(
silk_encoder_state_FIX *psEnc, /* I/O Encoder state */ silk_encoder_state_FIX *psEnc, /* I/O Encoder state */
const silk_encoder_control_FIX *psEncCtrl, /* I Encoder control */ 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 */ const opus_int16 x[] /* I Speech signal */
); );
@ -146,15 +146,10 @@ void silk_find_pred_coefs_FIX(
/* LPC analysis */ /* LPC analysis */
void silk_find_LPC_FIX( void silk_find_LPC_FIX(
silk_encoder_state *psEncC, /* I/O Encoder state */
opus_int16 NLSF_Q15[], /* O NLSFs */ 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_int16 x[], /* I Input signal */
const opus_int subfr_length, /* I Input signal subframe length including preceeding samples */ const opus_int32 minInvGain_Q30 /* I Inverse of max prediction gain */
const opus_int nb_subfr /* I Number of subframes */
); );
/* LTP analysis */ /* LTP analysis */

View file

@ -166,12 +166,12 @@ void silk_noise_shape_analysis_FIX(
SNR_adj_dB_Q7 = psEnc->sCmn.SNR_dB_Q7; SNR_adj_dB_Q7 = psEnc->sCmn.SNR_dB_Q7;
/* Input quality is the average of the quality in the lowest two VAD bands */ /* 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 ); + psEnc->sCmn.input_quality_bands_Q15[ 1 ], 2 );
/* Coding quality level, between 0.0_Q0 and 1.0_Q0, but in Q14 */ /* 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 - 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 */ /* Reduce coding SNR during low speech activity */
if( psEnc->sCmn.useCBR == 0 ) { if( psEnc->sCmn.useCBR == 0 ) {
@ -326,8 +326,8 @@ void silk_noise_shape_analysis_FIX(
silk_bwexpander_32( AR1_Q24, psEnc->sCmn.shapingLPCOrder, BWExp1_Q16 ); silk_bwexpander_32( AR1_Q24, psEnc->sCmn.shapingLPCOrder, BWExp1_Q16 );
/* Ratio of prediction gains, in energy domain */ /* Ratio of prediction gains, in energy domain */
silk_LPC_inverse_pred_gain_Q24( &pre_nrg_Q30, AR2_Q24, psEnc->sCmn.shapingLPCOrder ); pre_nrg_Q30 = silk_LPC_inverse_pred_gain_Q24( AR2_Q24, psEnc->sCmn.shapingLPCOrder );
silk_LPC_inverse_pred_gain_Q24( &nrg, AR1_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;*/ /*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 ); pre_nrg_Q30 = silk_LSHIFT32( silk_SMULWB( pre_nrg_Q30, SILK_FIX_CONST( 0.7, 15 ) ), 1 );

View file

@ -116,7 +116,7 @@ opus_int silk_pitch_analysis_core( /* O Voicing estimate: 0
silk_assert( search_thres1_Q16 >= 0 && search_thres1_Q16 <= (1<<16) ); silk_assert( search_thres1_Q16 >= 0 && search_thres1_Q16 <= (1<<16) );
silk_assert( search_thres2_Q15 >= 0 && search_thres2_Q15 <= (1<<15) ); 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 = ( 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_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; frame_length_8kHz = ( PE_LTP_MEM_LENGTH_MS + nb_subfr * PE_SUBFR_LENGTH_MS ) * 8;
@ -375,7 +375,7 @@ opus_int silk_pitch_analysis_core( /* O Voicing estimate: 0
prevLag_log2_Q7 = 0; prevLag_log2_Q7 = 0;
} }
silk_assert( search_thres2_Q15 == silk_SAT16( search_thres2_Q15 ) ); 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 ) { if( nb_subfr == PE_MAX_NB_SUBFR ) {
cbk_size = PE_NB_CBKS_STAGE2_EXT; cbk_size = PE_NB_CBKS_STAGE2_EXT;
Lag_CB_ptr = &silk_CB_lags_stage2[ 0 ][ 0 ]; Lag_CB_ptr = &silk_CB_lags_stage2[ 0 ][ 0 ];
@ -500,7 +500,7 @@ opus_int silk_pitch_analysis_core( /* O Voicing estimate: 0
silk_assert( lag == silk_SAT16( lag ) ); silk_assert( lag == silk_SAT16( lag ) );
contour_bias_Q20 = silk_DIV32_16( SILK_FIX_CONST( PE_FLATCONTOUR_BIAS, 20 ), 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 ) { if( nb_subfr == PE_MAX_NB_SUBFR ) {
nb_cbk_search = (opus_int)silk_nb_cbk_searchs_stage3[ complexity ]; nb_cbk_search = (opus_int)silk_nb_cbk_searchs_stage3[ complexity ];
cbk_size = PE_NB_CBKS_STAGE3_MAX; cbk_size = PE_NB_CBKS_STAGE3_MAX;

View file

@ -36,7 +36,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
static inline void silk_prefilt_FIX( static inline void silk_prefilt_FIX(
silk_prefilter_state_FIX *P, /* I/O state */ silk_prefilter_state_FIX *P, /* I/O state */
opus_int32 st_res_Q12[], /* I short term residual signal */ 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_int32 HarmShapeFIRPacked_Q12, /* I Harmonic shaping coeficients */
opus_int Tilt_Q14, /* I Tilt shaping coeficient */ opus_int Tilt_Q14, /* I Tilt shaping coeficient */
opus_int32 LF_shp_Q14, /* I Low-frequancy shaping coeficients */ opus_int32 LF_shp_Q14, /* I Low-frequancy shaping coeficients */
@ -46,7 +46,7 @@ static inline void silk_prefilt_FIX(
void silk_warped_LPC_analysis_filter_FIX( void silk_warped_LPC_analysis_filter_FIX(
opus_int32 state[], /* I/O State [order + 1] */ 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 coef_Q13[], /* I Coefficients [order] */
const opus_int16 input[], /* I Input signal [length] */ const opus_int16 input[], /* I Input signal [length] */
const opus_int16 lambda_Q16, /* I Warping factor */ const opus_int16 lambda_Q16, /* I Warping factor */
@ -81,14 +81,14 @@ void silk_warped_LPC_analysis_filter_FIX(
} }
state[ order ] = tmp1; state[ order ] = tmp1;
acc_Q11 = silk_SMLAWB( acc_Q11, tmp1, coef_Q13[ order - 1 ] ); acc_Q11 = silk_SMLAWB( acc_Q11, tmp1, coef_Q13[ order - 1 ] );
res[ n ] = ( opus_int16 )silk_SAT16( ( opus_int32 )input[ n ] - silk_RSHIFT_ROUND( acc_Q11, 11 ) ); res_Q2[ n ] = silk_LSHIFT( (opus_int32)input[ n ], 2 ) - silk_RSHIFT_ROUND( acc_Q11, 9 );
} }
} }
void silk_prefilter_FIX( void silk_prefilter_FIX(
silk_encoder_state_FIX *psEnc, /* I/O Encoder state */ silk_encoder_state_FIX *psEnc, /* I/O Encoder state */
const silk_encoder_control_FIX *psEncCtrl, /* I Encoder control */ 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 */ const opus_int16 x[] /* I Speech signal */
) )
{ {
@ -97,16 +97,16 @@ void silk_prefilter_FIX(
opus_int32 tmp_32; opus_int32 tmp_32;
const opus_int16 *AR1_shp_Q13; const opus_int16 *AR1_shp_Q13;
const opus_int16 *px; const opus_int16 *px;
opus_int16 *pxw; opus_int32 *pxw_Q10;
opus_int HarmShapeGain_Q12, Tilt_Q14; opus_int HarmShapeGain_Q12, Tilt_Q14;
opus_int32 HarmShapeFIRPacked_Q12, LF_shp_Q14; opus_int32 HarmShapeFIRPacked_Q12, LF_shp_Q14;
opus_int32 x_filt_Q12[ MAX_FRAME_LENGTH / MAX_NB_SUBFR ]; opus_int32 x_filt_Q12[ MAX_SUB_FRAME_LENGTH ];
opus_int16 st_res[ ( MAX_FRAME_LENGTH / MAX_NB_SUBFR ) + MAX_LPC_ORDER ]; opus_int32 st_res_Q2[ MAX_SUB_FRAME_LENGTH + MAX_LPC_ORDER ];
opus_int16 B_Q12[ 2 ]; opus_int16 B_Q10[ 2 ];
/* Setup pointers */ /* Set up pointers */
px = x; px = x;
pxw = xw; pxw_Q10 = xw_Q10;
lag = P->lagPrev; lag = P->lagPrev;
for( k = 0; k < psEnc->sCmn.nb_subfr; k++ ) { for( k = 0; k < psEnc->sCmn.nb_subfr; k++ ) {
/* Update Variables that change per sub frame */ /* Update Variables that change per sub frame */
@ -118,34 +118,33 @@ void silk_prefilter_FIX(
HarmShapeGain_Q12 = silk_SMULWB( psEncCtrl->HarmShapeGain_Q14[ k ], 16384 - psEncCtrl->HarmBoost_Q14[ k ] ); HarmShapeGain_Q12 = silk_SMULWB( psEncCtrl->HarmShapeGain_Q14[ k ], 16384 - psEncCtrl->HarmBoost_Q14[ k ] );
silk_assert( HarmShapeGain_Q12 >= 0 ); silk_assert( HarmShapeGain_Q12 >= 0 );
HarmShapeFIRPacked_Q12 = silk_RSHIFT( HarmShapeGain_Q12, 2 ); 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 ]; Tilt_Q14 = psEncCtrl->Tilt_Q14[ k ];
LF_shp_Q14 = psEncCtrl->LF_shp_Q14[ k ]; LF_shp_Q14 = psEncCtrl->LF_shp_Q14[ k ];
AR1_shp_Q13 = &psEncCtrl->AR1_Q13[ k * MAX_SHAPE_LPC_ORDER ]; AR1_shp_Q13 = &psEncCtrl->AR1_Q13[ k * MAX_SHAPE_LPC_ORDER ];
/* Short term FIR filtering*/ /* 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 ); psEnc->sCmn.warping_Q16, psEnc->sCmn.subfr_length, psEnc->sCmn.shapingLPCOrder );
/* reduce (mainly) low frequencies during harmonic emphasis */ /* Reduce (mainly) low frequencies during harmonic emphasis */
B_Q12[ 0 ] = silk_RSHIFT_ROUND( psEncCtrl->GainsPre_Q14[ k ], 2 ); 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( 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_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_SMULWB( tmp_32, -psEncCtrl->GainsPre_Q14[ k ] ); /* Q24 */
tmp_32 = silk_RSHIFT_ROUND( tmp_32, 12 ); /* Q12 */ tmp_32 = silk_RSHIFT_ROUND( tmp_32, 14 ); /* Q10 */
B_Q12[ 1 ]= silk_SAT16( tmp_32 ); 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 ] );
x_filt_Q12[ 0 ] = silk_SMLABB( silk_SMULBB( st_res[ 0 ], B_Q12[ 0 ] ), P->sHarmHP, B_Q12[ 1 ] );
for( j = 1; j < psEnc->sCmn.subfr_length; j++ ) { 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 ); LF_shp_Q14, lag, psEnc->sCmn.subfr_length );
px += 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 ]; P->lagPrev = psEncCtrl->pitchL[ psEnc->sCmn.nb_subfr - 1 ];
@ -155,7 +154,7 @@ void silk_prefilter_FIX(
static inline void silk_prefilt_FIX( static inline void silk_prefilt_FIX(
silk_prefilter_state_FIX *P, /* I/O state */ silk_prefilter_state_FIX *P, /* I/O state */
opus_int32 st_res_Q12[], /* I short term residual signal */ 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_int32 HarmShapeFIRPacked_Q12, /* I Harmonic shaping coeficients */
opus_int Tilt_Q14, /* I Tilt shaping coeficient */ opus_int Tilt_Q14, /* I Tilt shaping coeficient */
opus_int32 LF_shp_Q14, /* I Low-frequancy shaping coeficients */ opus_int32 LF_shp_Q14, /* I Low-frequancy shaping coeficients */
@ -193,9 +192,9 @@ static inline void silk_prefilt_FIX(
sLF_MA_shp_Q12 = silk_SUB32( sLF_AR_shp_Q12, silk_LSHIFT( n_LF_Q10, 2 ) ); 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_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 */ /* Copy temp variable back to state */

View file

@ -57,7 +57,7 @@ opus_int32 silk_residual_energy16_covar_FIX(
c_max = 0; c_max = 0;
for( i = 0; i < D; i++ ) { 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 ); Qxtra = silk_min_int( Qxtra, silk_CLZ32( c_max ) - 17 );

View file

@ -76,7 +76,7 @@ opus_int32 silk_schur( /* O Returns residual ene
rc_tmp_Q15 = silk_SAT16( rc_tmp_Q15 ); rc_tmp_Q15 = silk_SAT16( rc_tmp_Q15 );
/* Store */ /* Store */
rc_Q15[ k ] = ( opus_int16 )rc_tmp_Q15; rc_Q15[ k ] = (opus_int16)rc_tmp_Q15;
/* Update correlations */ /* Update correlations */
for( n = 0; n < order - k; n++ ) { for( n = 0; n < order - k; n++ ) {

View file

@ -56,7 +56,7 @@ typedef struct {
opus_int sLTP_shp_buf_idx; opus_int sLTP_shp_buf_idx;
opus_int32 sLF_AR_shp_Q12; opus_int32 sLF_AR_shp_Q12;
opus_int32 sLF_MA_shp_Q12; opus_int32 sLF_MA_shp_Q12;
opus_int sHarmHP; opus_int32 sHarmHP_Q2;
opus_int32 rand_seed; opus_int32 rand_seed;
opus_int lagPrev; opus_int lagPrev;
} silk_prefilter_state_FIX; } silk_prefilter_state_FIX;
@ -72,10 +72,6 @@ typedef struct {
/* Buffer for find pitch and noise shape analysis */ /* 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 */ silk_DWORD_ALIGN opus_int16 x_buf[ 2 * MAX_FRAME_LENGTH + LA_SHAPE_MAX ];/* Buffer for find pitch and noise shape analysis */
opus_int LTPCorr_Q15; /* Normalized correlation from pitch lag estimator */ opus_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; } silk_encoder_state_FIX;
/************************/ /************************/

View file

@ -55,7 +55,7 @@ void silk_warped_autocorrelation_FIX(
/* Loop over samples */ /* Loop over samples */
for( n = 0; n < length; n++ ) { 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 */ /* Loop over allpass sections */
for( i = 0; i < order; i += 2 ) { for( i = 0; i < order; i += 2 ) {
/* Output of allpass section */ /* Output of allpass section */
@ -77,11 +77,11 @@ void silk_warped_autocorrelation_FIX(
silk_assert( *scale >= -30 && *scale <= 12 ); silk_assert( *scale >= -30 && *scale <= 12 );
if( lsh >= 0 ) { if( lsh >= 0 ) {
for( i = 0; i < order + 1; i++ ) { 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 { } else {
for( i = 0; i < order + 1; i++ ) { 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*/ silk_assert( corr_QC[ 0 ] >= 0 ); /* If breaking, decrease QC*/

View file

@ -37,29 +37,28 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
/* compute inverse of LPC prediction gain, and */ /* compute inverse of LPC prediction gain, and */
/* test if LPC coefficients are stable (all poles within unit circle) */ /* test if LPC coefficients are stable (all poles within unit circle) */
/* this code is based on silk_a2k_FLP() */ /* 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 silk_LPC_inverse_pred_gain_FLP( /* O return inverse prediction gain, energy domain */
silk_float *invGain, /* O inverse prediction gain, energy domain */
const silk_float *A, /* I prediction coefficients [order] */ const silk_float *A, /* I prediction coefficients [order] */
opus_int32 order /* I prediction order */ opus_int32 order /* I prediction order */
) )
{ {
opus_int k, n; 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 Atmp[ 2 ][ SILK_MAX_ORDER_LPC ];
silk_float *Aold, *Anew; silk_float *Aold, *Anew;
Anew = Atmp[ order & 1 ]; Anew = Atmp[ order & 1 ];
silk_memcpy( Anew, A, order * sizeof(silk_float) ); silk_memcpy( Anew, A, order * sizeof(silk_float) );
*invGain = 1.0f; invGain = 1.0;
for( k = order - 1; k > 0; k-- ) { for( k = order - 1; k > 0; k-- ) {
rc = -Anew[ k ]; rc = -Anew[ k ];
if( rc > RC_THRESHOLD || rc < -RC_THRESHOLD ) { if( rc > RC_THRESHOLD || rc < -RC_THRESHOLD ) {
return 1; return 0.0f;
} }
rc_mult1 = 1.0f - rc * rc; rc_mult1 = 1.0f - rc * rc;
rc_mult2 = 1.0f / rc_mult1; rc_mult2 = 1.0f / rc_mult1;
*invGain *= (silk_float)rc_mult1; invGain *= rc_mult1;
/* swap pointers */ /* swap pointers */
Aold = Anew; Aold = Anew;
Anew = Atmp[ k & 1 ]; Anew = Atmp[ k & 1 ];
@ -69,9 +68,9 @@ opus_int silk_LPC_inverse_pred_gain_FLP( /* O returns 1 if unstable, other
} }
rc = -Anew[ 0 ]; rc = -Anew[ 0 ];
if( rc > RC_THRESHOLD || rc < -RC_THRESHOLD ) { if( rc > RC_THRESHOLD || rc < -RC_THRESHOLD ) {
return 1; return 0.0f;
} }
rc_mult1 = 1.0f - rc * rc; rc_mult1 = 1.0f - rc * rc;
*invGain *= (silk_float)rc_mult1; invGain *= rc_mult1;
return 0; return (silk_float)invGain;
} }

View file

@ -39,19 +39,14 @@ void silk_LTP_scale_ctrl_FLP(
{ {
opus_int round_loss; 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 ) { if( condCoding == CODE_INDEPENDENTLY ) {
/* Only scale if first frame in packet */
round_loss = psEnc->sCmn.PacketLoss_perc + psEnc->sCmn.nFramesPerPacket; 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 { } else {
/* Default is minimum scaling */ /* Default is minimum scaling */
psEnc->sCmn.indices.LTP_scaleIndex = 0; psEnc->sCmn.indices.LTP_scaleIndex = 0;
} }
psEncCtrl->LTP_scale = (silk_float)silk_LTPScales_table_Q14[ psEnc->sCmn.indices.LTP_scaleIndex ] / 16384.0f; psEncCtrl->LTP_scale = (silk_float)silk_LTPScales_table_Q14[ psEnc->sCmn.indices.LTP_scaleIndex ] / 16384.0f;
} }

View file

@ -50,8 +50,7 @@ void silk_bwexpander_FLP(
/* compute inverse of LPC prediction gain, and */ /* compute inverse of LPC prediction gain, and */
/* test if LPC coefficients are stable (all poles within unit circle) */ /* test if LPC coefficients are stable (all poles within unit circle) */
/* this code is based on silk_FLP_a2k() */ /* 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 silk_LPC_inverse_pred_gain_FLP( /* O return inverse prediction gain, energy domain */
silk_float *invGain, /* O inverse prediction gain, energy domain */
const silk_float *A, /* I prediction coefficients [order] */ const silk_float *A, /* I prediction coefficients [order] */
opus_int32 order /* I prediction order */ opus_int32 order /* I prediction order */
); );
@ -108,9 +107,9 @@ void silk_insertion_sort_decreasing_FLP(
silk_float silk_burg_modified_FLP( /* O returns residual energy */ silk_float silk_burg_modified_FLP( /* O returns residual energy */
silk_float A[], /* O prediction coefficients (length order) */ silk_float A[], /* O prediction coefficients (length order) */
const silk_float x[], /* I input signal, length: nb_subfr*(D+L_sub) */ 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 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_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 */ const opus_int D /* I order */
); );

View file

@ -30,29 +30,29 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#endif #endif
#include "SigProc_FLP.h" #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_FRAME_SIZE 384 /* subfr_length * nb_subfr = ( 0.005 * 16000 + 16 ) * 4 = 384*/
#define MAX_NB_SUBFR 4
/* Compute reflection coefficients from input signal */ /* Compute reflection coefficients from input signal */
silk_float silk_burg_modified_FLP( /* O returns residual energy */ silk_float silk_burg_modified_FLP( /* O returns residual energy */
silk_float A[], /* O prediction coefficients (length order) */ silk_float A[], /* O prediction coefficients (length order) */
const silk_float x[], /* I input signal, length: nb_subfr*(D+L_sub) */ 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 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_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 */ const opus_int D /* I order */
) )
{ {
opus_int k, n, s; opus_int k, n, s, reached_max_gain;
double C0, num, nrg_f, nrg_b, rc, Atmp, tmp1, tmp2; double C0, invGain, num, nrg_f, nrg_b, rc, Atmp, tmp1, tmp2;
const silk_float *x_ptr; const silk_float *x_ptr;
double C_first_row[ SILK_MAX_ORDER_LPC ], C_last_row[ 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 CAf[ SILK_MAX_ORDER_LPC + 1 ], CAb[ SILK_MAX_ORDER_LPC + 1 ];
double Af[ SILK_MAX_ORDER_LPC ]; double Af[ SILK_MAX_ORDER_LPC ];
silk_assert( subfr_length * nb_subfr <= MAX_FRAME_SIZE ); silk_assert( subfr_length * nb_subfr <= MAX_FRAME_SIZE );
silk_assert( nb_subfr <= MAX_NB_SUBFR );
/* Compute autocorrelations, added over subframes */ /* Compute autocorrelations, added over subframes */
C0 = silk_energy_FLP( x, nb_subfr * subfr_length ); C0 = silk_energy_FLP( x, nb_subfr * subfr_length );
@ -66,8 +66,9 @@ silk_float silk_burg_modified_FLP( /* O returns residual energy
silk_memcpy( C_last_row, C_first_row, SILK_MAX_ORDER_LPC * sizeof( double ) ); silk_memcpy( C_last_row, C_first_row, SILK_MAX_ORDER_LPC * sizeof( double ) );
/* Initialize */ /* 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++ ) { for( n = 0; n < D; n++ ) {
/* Update first row of correlation matrix (without first element) */ /* Update first row of correlation matrix (without first element) */
/* Update last row of correlation matrix (without last element, stored in reversed order) */ /* Update last row of correlation matrix (without last element, stored in reversed order) */
@ -116,6 +117,21 @@ silk_float silk_burg_modified_FLP( /* O returns residual energy
rc = -2.0 * num / ( nrg_f + nrg_b ); rc = -2.0 * num / ( nrg_f + nrg_b );
silk_assert( rc > -1.0 && rc < 1.0 ); 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 */ /* Update the AR coefficients */
for( k = 0; k < (n + 1) >> 1; k++ ) { for( k = 0; k < (n + 1) >> 1; k++ ) {
tmp1 = Af[ k ]; tmp1 = Af[ k ];
@ -125,6 +141,14 @@ silk_float silk_burg_modified_FLP( /* O returns residual energy
} }
Af[ n ] = rc; 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 */ /* Update C * Af and C * Ab */
for( k = 0; k <= n + 1; k++ ) { for( k = 0; k <= n + 1; k++ ) {
tmp1 = CAf[ k ]; tmp1 = CAf[ k ];
@ -133,7 +157,19 @@ silk_float silk_burg_modified_FLP( /* O returns residual energy
} }
} }
/* Return residual energy */ 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 ]; nrg_f = CAf[ 0 ];
tmp1 = 1.0; tmp1 = 1.0;
for( k = 0; k < D; k++ ) { for( k = 0; k < D; k++ ) {
@ -142,7 +178,9 @@ silk_float silk_burg_modified_FLP( /* O returns residual energy
tmp1 += Atmp * Atmp; tmp1 += Atmp * Atmp;
A[ k ] = (silk_float)(-Atmp); A[ k ] = (silk_float)(-Atmp);
} }
nrg_f -= WhiteNoiseFrac * C0 * tmp1; nrg_f -= FIND_LPC_COND_FAC * C0 * tmp1;
}
/* Return residual energy */
return (silk_float)nrg_f; return (silk_float)nrg_f;
} }

View file

@ -104,8 +104,8 @@ opus_int silk_encode_frame_FLP(
psEnc->sCmn.indices.Seed = psEnc->sCmn.frameCounter++ & 3; 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 */ /* pointers aligned with start of frame to encode */
x_frame = psEnc->x_buf + psEnc->sCmn.ltp_mem_length; /* 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 */ res_pitch_frame = res_pitch + psEnc->sCmn.ltp_mem_length; /* start of pitch LPC residual frame */
@ -157,7 +157,7 @@ opus_int silk_encode_frame_FLP(
silk_LBRR_encode_FLP( psEnc, &sEncCtrl, xfw, condCoding ); silk_LBRR_encode_FLP( psEnc, &sEncCtrl, xfw, condCoding );
/* Loop over quantizer and entroy coding to control bitrate */ /* Loop over quantizer and entroy coding to control bitrate */
maxIter = 5; maxIter = 6;
gainMult_Q8 = SILK_FIX_CONST( 1, 8 ); gainMult_Q8 = SILK_FIX_CONST( 1, 8 );
found_lower = 0; found_lower = 0;
found_upper = 0; found_upper = 0;

View file

@ -29,73 +29,63 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "config.h" #include "config.h"
#endif #endif
#include "define.h"
#include "main_FLP.h" #include "main_FLP.h"
#include "tuning_parameters.h" #include "tuning_parameters.h"
/* LPC analysis */
void silk_find_LPC_FLP( void silk_find_LPC_FLP(
silk_encoder_state *psEncC, /* I/O Encoder state */
opus_int16 NLSF_Q15[], /* O NLSFs */ 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 silk_float x[], /* I Input signal */
const opus_int subfr_length, /* I Subframe length incl preceeding samples */ const silk_float minInvGain /* I Inverse of max prediction gain */
const opus_int nb_subfr /* I Number of subframes */
) )
{ {
opus_int k; opus_int k, subfr_length;
silk_float a[ MAX_LPC_ORDER ]; silk_float a[ MAX_LPC_ORDER ];
/* Used only for NLSF interpolation */ /* Used only for NLSF interpolation */
double res_nrg, res_nrg_2nd, res_nrg_interp; silk_float res_nrg, res_nrg_2nd, res_nrg_interp;
opus_int16 NLSF0_Q15[ MAX_LPC_ORDER ]; opus_int16 NLSF0_Q15[ MAX_LPC_ORDER ];
silk_float a_tmp[ 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 LPC_res[ MAX_FRAME_LENGTH + MAX_NB_SUBFR * MAX_LPC_ORDER ];
subfr_length = psEncC->subfr_length + psEncC->predictLPCOrder;
/* Default: No interpolation */ /* Default: No interpolation */
*interpIndex = 4; psEncC->indices.NLSFInterpCoef_Q2 = 4;
/* Burg AR analysis for the full frame */ /* 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 ) { if( psEncC->useInterpolatedNLSFs && !psEncC->first_frame_after_reset && psEncC->nb_subfr == MAX_NB_SUBFR ) {
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 ) {
/* Optimal solution for last 10 ms; subtract residual energy here, as that's easier than */ /* 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 */ /* 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, res_nrg -= silk_burg_modified_FLP( a_tmp, x + ( MAX_NB_SUBFR / 2 ) * subfr_length, minInvGain, subfr_length, MAX_NB_SUBFR / 2, psEncC->predictLPCOrder );
subfr_length, MAX_NB_SUBFR / 2, FIND_LPC_COND_FAC, LPC_order );
silk_bwexpander_FLP( a_tmp, LPC_order, FIND_LPC_CHIRP );
/* Convert to NLSFs */ /* 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 */ /* Search over interpolation indices to find the one with lowest residual energy */
res_nrg_2nd = silk_float_MAX; res_nrg_2nd = silk_float_MAX;
for( k = 3; k >= 0; k-- ) { for( k = 3; k >= 0; k-- ) {
/* Interpolate NLSFs for first half */ /* 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 */ /* 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 */ /* Calculate residual energy with LSF interpolation */
silk_LPC_analysis_filter_FLP( LPC_res, a_tmp, x, 2 * subfr_length, LPC_order ); silk_LPC_analysis_filter_FLP( LPC_res, a_tmp, x, 2 * subfr_length, psEncC->predictLPCOrder );
res_nrg_interp = res_nrg_interp = (silk_float)(
silk_energy_FLP( LPC_res + LPC_order, subfr_length - LPC_order ) + silk_energy_FLP( LPC_res + psEncC->predictLPCOrder, subfr_length - psEncC->predictLPCOrder ) +
silk_energy_FLP( LPC_res + LPC_order + subfr_length, subfr_length - LPC_order ); silk_energy_FLP( LPC_res + psEncC->predictLPCOrder + subfr_length, subfr_length - psEncC->predictLPCOrder ) );
/* Determine whether current interpolated NLSFs are best so far */ /* Determine whether current interpolated NLSFs are best so far */
if( res_nrg_interp < res_nrg ) { if( res_nrg_interp < res_nrg ) {
/* Interpolation has lower residual energy */ /* Interpolation has lower residual energy */
res_nrg = res_nrg_interp; res_nrg = res_nrg_interp;
*interpIndex = (opus_int8)k; psEncC->indices.NLSFInterpCoef_Q2 = (opus_int8)k;
} else if( res_nrg_interp > res_nrg_2nd ) { } else if( res_nrg_interp > res_nrg_2nd ) {
/* No reason to continue iterating - residual energies will continue to climb */ /* No reason to continue iterating - residual energies will continue to climb */
break; break;
@ -104,10 +94,11 @@ void silk_find_LPC_FLP(
} }
} }
if( *interpIndex == 4 ) { if( psEncC->indices.NLSFInterpCoef_Q2 == 4 ) {
/* NLSF interpolation is currently inactive, calculate NLSFs from full frame AR coefficients */ /* 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 ) );
} }

View file

@ -50,7 +50,7 @@ void silk_find_pitch_lags_FLP(
silk_float *Wsig_ptr; 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; buf_len = psEnc->sCmn.la_pitch + psEnc->sCmn.frame_length + psEnc->sCmn.ltp_mem_length;

View file

@ -46,6 +46,7 @@ void silk_find_pred_coefs_FLP(
opus_int16 NLSF_Q15[ MAX_LPC_ORDER ]; opus_int16 NLSF_Q15[ MAX_LPC_ORDER ];
const silk_float *x_ptr; const silk_float *x_ptr;
silk_float *x_pre_ptr, LPC_in_pre[ MAX_NB_SUBFR * MAX_LPC_ORDER + MAX_FRAME_LENGTH ]; 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 */ /* Weighting for weighted least squares */
for( i = 0; i < psEnc->sCmn.nb_subfr; i++ ) { for( i = 0; i < psEnc->sCmn.nb_subfr; i++ ) {
@ -74,7 +75,6 @@ void silk_find_pred_coefs_FLP(
/* Create LTP residual */ /* Create LTP residual */
silk_LTP_analysis_filter_FLP( LPC_in_pre, x - psEnc->sCmn.predictLPCOrder, psEncCtrl->LTPCoef, 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 ); psEncCtrl->pitchL, invGains, psEnc->sCmn.subfr_length, psEnc->sCmn.nb_subfr, psEnc->sCmn.predictLPCOrder );
} else { } else {
/************/ /************/
/* UNVOICED */ /* UNVOICED */
@ -88,15 +88,20 @@ void silk_find_pred_coefs_FLP(
x_pre_ptr += psEnc->sCmn.subfr_length + psEnc->sCmn.predictLPCOrder; x_pre_ptr += psEnc->sCmn.subfr_length + psEnc->sCmn.predictLPCOrder;
x_ptr += psEnc->sCmn.subfr_length; x_ptr += psEnc->sCmn.subfr_length;
} }
silk_memset( psEncCtrl->LTPCoef, 0, psEnc->sCmn.nb_subfr * LTP_ORDER * sizeof( silk_float ) ); silk_memset( psEncCtrl->LTPCoef, 0, psEnc->sCmn.nb_subfr * LTP_ORDER * sizeof( silk_float ) );
psEncCtrl->LTPredCodGain = 0.0f; 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 */ /* 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, silk_find_LPC_FLP( &psEnc->sCmn, NLSF_Q15, LPC_in_pre, minInvGain );
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 );
/* Quantize LSFs */ /* Quantize LSFs */
silk_process_NLSFs_FLP( &psEnc->sCmn, psEncCtrl->PredCoef, NLSF_Q15, psEnc->sCmn.prev_NLSFq_Q15 ); silk_process_NLSFs_FLP( &psEnc->sCmn, psEncCtrl->PredCoef, NLSF_Q15, psEnc->sCmn.prev_NLSFq_Q15 );

View file

@ -143,15 +143,10 @@ void silk_find_pred_coefs_FLP(
/* LPC analysis */ /* LPC analysis */
void silk_find_LPC_FLP( void silk_find_LPC_FLP(
silk_encoder_state *psEncC, /* I/O Encoder state */
opus_int16 NLSF_Q15[], /* O NLSFs */ 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 silk_float x[], /* I Input signal */
const opus_int subfr_length, /* I Subframe length incl preceeding samples */ const silk_float minInvGain /* I Prediction gain from LTP (dB) */
const opus_int nb_subfr /* I Number of subframes */
); );
/* LTP analysis */ /* LTP analysis */

View file

@ -151,7 +151,7 @@ void silk_noise_shape_analysis_FLP(
psEncCtrl->input_quality = 0.5f * ( psEnc->sCmn.input_quality_bands_Q15[ 0 ] + psEnc->sCmn.input_quality_bands_Q15[ 1 ] ) * ( 1.0f / 32768.0f ); 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 */ /* 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 ) { if( psEnc->sCmn.useCBR == 0 ) {
/* Reduce coding SNR during low speech activity */ /* Reduce coding SNR during low speech activity */
@ -274,8 +274,8 @@ void silk_noise_shape_analysis_FLP(
silk_bwexpander_FLP( &psEncCtrl->AR1[ k * MAX_SHAPE_LPC_ORDER ], psEnc->sCmn.shapingLPCOrder, BWExp1 ); silk_bwexpander_FLP( &psEncCtrl->AR1[ k * MAX_SHAPE_LPC_ORDER ], psEnc->sCmn.shapingLPCOrder, BWExp1 );
/* Ratio of prediction gains, in energy domain */ /* 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 ); pre_nrg = silk_LPC_inverse_pred_gain_FLP( &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 ); 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 ); psEncCtrl->GainsPre[ k ] = 1.0f - 0.7f * ( 1.0f - pre_nrg / nrg );
/* Convert to monic warped prediction coefficients and limit absolute values */ /* Convert to monic warped prediction coefficients and limit absolute values */

View file

@ -115,7 +115,7 @@ opus_int silk_pitch_analysis_core_FLP( /* O Voicing estimate: 0 voiced,
silk_assert( search_thres1 >= 0.0f && search_thres1 <= 1.0f ); silk_assert( search_thres1 >= 0.0f && search_thres1 <= 1.0f );
silk_assert( search_thres2 >= 0.0f && search_thres2 <= 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 = ( 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_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; frame_length_8kHz = ( PE_LTP_MEM_LENGTH_MS + nb_subfr * PE_SUBFR_LENGTH_MS ) * 8;
@ -322,7 +322,7 @@ opus_int silk_pitch_analysis_core_FLP( /* O Voicing estimate: 0 voiced,
prevLag_log2 = 0; 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 ) { if( nb_subfr == PE_MAX_NB_SUBFR ) {
cbk_size = PE_NB_CBKS_STAGE2_EXT; cbk_size = PE_NB_CBKS_STAGE2_EXT;
Lag_CB_ptr = &silk_CB_lags_stage2[ 0 ][ 0 ]; Lag_CB_ptr = &silk_CB_lags_stage2[ 0 ][ 0 ];
@ -419,7 +419,7 @@ opus_int silk_pitch_analysis_core_FLP( /* O Voicing estimate: 0 voiced,
silk_assert( lag == silk_SAT16( lag ) ); silk_assert( lag == silk_SAT16( lag ) );
contour_bias = PE_FLATCONTOUR_BIAS / 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 ) { if( nb_subfr == PE_MAX_NB_SUBFR ) {
nb_cbk_search = (opus_int)silk_nb_cbk_searchs_stage3[ complexity ]; nb_cbk_search = (opus_int)silk_nb_cbk_searchs_stage3[ complexity ];
cbk_size = PE_NB_CBKS_STAGE3_MAX; cbk_size = PE_NB_CBKS_STAGE3_MAX;

View file

@ -108,7 +108,7 @@ void silk_prefilter_FLP(
silk_float HarmShapeFIR[ 3 ]; silk_float HarmShapeFIR[ 3 ];
silk_float st_res[ MAX_SUB_FRAME_LENGTH + MAX_LPC_ORDER ]; silk_float st_res[ MAX_SUB_FRAME_LENGTH + MAX_LPC_ORDER ];
/* Setup pointers */ /* Set up pointers */
px = x; px = x;
pxw = xw; pxw = xw;
lag = P->lagPrev; lag = P->lagPrev;

View file

@ -64,7 +64,7 @@ void silk_process_gains_FLP(
/* Prepare gains for noise shaping quantization */ /* Prepare gains for noise shaping quantization */
for( k = 0; k < psEnc->sCmn.nb_subfr; k++ ) { 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 */ /* Save unquantized gains and gain Index */

View file

@ -72,10 +72,6 @@ typedef struct {
/* Buffer for find pitch and noise shape analysis */ /* 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 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 */ silk_float LTPCorr; /* Normalized correlation from pitch lag estimator */
/* Parameters for LTP scaling control */
silk_float prevLTPredCodGain;
silk_float HPLTPredCodGain;
} silk_encoder_state_FLP; } silk_encoder_state_FLP;
/************************/ /************************/

View file

@ -102,7 +102,7 @@ void silk_NSQ_wrapper_FLP(
) )
{ {
opus_int i, j; 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 ]; opus_int32 Gains_Q16[ MAX_NB_SUBFR ];
silk_DWORD_ALIGN opus_int16 PredCoef_Q12[ 2 ][ MAX_LPC_ORDER ]; silk_DWORD_ALIGN opus_int16 PredCoef_Q12[ 2 ][ MAX_LPC_ORDER ];
opus_int16 LTPCoef_Q14[ LTP_ORDER * MAX_NB_SUBFR ]; opus_int16 LTPCoef_Q14[ LTP_ORDER * MAX_NB_SUBFR ];
@ -133,12 +133,12 @@ void silk_NSQ_wrapper_FLP(
/* prediction and coding parameters */ /* prediction and coding parameters */
for( i = 0; i < psEnc->sCmn.nb_subfr * LTP_ORDER; i++ ) { 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( j = 0; j < 2; j++ ) {
for( i = 0; i < psEnc->sCmn.predictLPCOrder; i++ ) { for( i = 0; i < psEnc->sCmn.predictLPCOrder; i++ ) {
PredCoef_Q12[ j ][ i ] = ( opus_int16 )silk_float2int( psEncCtrl->PredCoef[ j ][ i ] * 4096.0f ); PredCoef_Q12[ j ][ i ] = (opus_int16)silk_float2int( psEncCtrl->PredCoef[ j ][ i ] * 4096.0f );
} }
} }
@ -154,14 +154,16 @@ void silk_NSQ_wrapper_FLP(
} }
/* Convert input to fix */ /* 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 */ /* Call NSQ */
if( psEnc->sCmn.nStatesDelayedDecision > 1 || psEnc->sCmn.warping_Q16 > 0 ) { 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 ); AR2_Q13, HarmShapeGain_Q14, Tilt_Q14, LF_shp_Q14, Gains_Q16, psEncCtrl->pitchL, Lambda_Q10, LTP_scale_Q14 );
} else { } 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 ); AR2_Q13, HarmShapeGain_Q14, Tilt_Q14, LF_shp_Q14, Gains_Q16, psEncCtrl->pitchL, Lambda_Q10, LTP_scale_Q14 );
} }
} }

View file

@ -46,6 +46,6 @@ void silk_interpolate(
silk_assert( ifact_Q2 <= 4 ); silk_assert( ifact_Q2 <= 4 );
for( i = 0; i < d; i++ ) { 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 );
} }
} }

View file

@ -25,8 +25,12 @@ ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
***********************************************************************/ ***********************************************************************/
#ifndef SILK_API_C_H #ifndef SILK_MACROS_H
#define SILK_API_C_H #define SILK_MACROS_H
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
/* This is an inline header file for general platform. */ /* This is an inline header file for general platform. */
@ -128,5 +132,5 @@ static inline opus_int32 silk_CLZ32(opus_int32 in32)
#endif #endif
#define matrix_c_adr(Matrix_base_adr, row, column, M) (Matrix_base_adr + ((row)+(M)*(column))) #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 */

View file

@ -38,9 +38,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "entenc.h" #include "entenc.h"
#include "entdec.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 */ /* Convert Left/Right stereo signal to adaptive Mid/Side representation */
void silk_stereo_LR_to_MS( void silk_stereo_LR_to_MS(
stereo_enc_state *state, /* I/O State */ stereo_enc_state *state, /* I/O State */
@ -232,7 +229,7 @@ void silk_NSQ(
const silk_encoder_state *psEncC, /* I/O Encoder State */ const silk_encoder_state *psEncC, /* I/O Encoder State */
silk_nsq_state *NSQ, /* I/O NSQ state */ silk_nsq_state *NSQ, /* I/O NSQ state */
SideInfoIndices *psIndices, /* I/O Quantization Indices */ 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 */ opus_int8 pulses[], /* O Quantized pulse signal */
const opus_int16 PredCoef_Q12[ 2 * MAX_LPC_ORDER ], /* I Short term prediction coefs */ const opus_int16 PredCoef_Q12[ 2 * MAX_LPC_ORDER ], /* I Short term prediction coefs */
const opus_int16 LTPCoef_Q14[ LTP_ORDER * MAX_NB_SUBFR ], /* I Long term prediction coefs */ const opus_int16 LTPCoef_Q14[ LTP_ORDER * MAX_NB_SUBFR ], /* I Long term prediction coefs */
@ -251,7 +248,7 @@ void silk_NSQ_del_dec(
const silk_encoder_state *psEncC, /* I/O Encoder State */ const silk_encoder_state *psEncC, /* I/O Encoder State */
silk_nsq_state *NSQ, /* I/O NSQ state */ silk_nsq_state *NSQ, /* I/O NSQ state */
SideInfoIndices *psIndices, /* I/O Quantization Indices */ 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 */ opus_int8 pulses[], /* O Quantized pulse signal */
const opus_int16 PredCoef_Q12[ 2 * MAX_LPC_ORDER ], /* I Short term prediction coefs */ const opus_int16 PredCoef_Q12[ 2 * MAX_LPC_ORDER ], /* I Short term prediction coefs */
const opus_int16 LTPCoef_Q14[ LTP_ORDER * MAX_NB_SUBFR ], /* I Long term prediction coefs */ const opus_int16 LTPCoef_Q14[ LTP_ORDER * MAX_NB_SUBFR ], /* I Long term prediction coefs */

View file

@ -59,7 +59,7 @@ void silk_quant_LTP_gains(
cbk_ptr_Q7 = silk_LTP_vq_ptrs_Q7[ k ]; cbk_ptr_Q7 = silk_LTP_vq_ptrs_Q7[ k ];
cbk_size = silk_LTP_vq_sizes[ k ]; cbk_size = silk_LTP_vq_sizes[ k ];
/* Setup pointer to first subframe */ /* Set up pointer to first subframe */
W_Q18_ptr = W_Q18; W_Q18_ptr = W_Q18;
b_Q14_ptr = B_Q14; b_Q14_ptr = B_Q14;

View file

@ -29,30 +29,46 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "config.h" #include "config.h"
#endif #endif
/* Matrix of resampling methods used: /*
* Matrix of resampling methods used:
* Fs_out (kHz) * Fs_out (kHz)
* 8 12 16 24 48 * 8 12 16 24 48
* *
* 8 C UF U UF UF * 8 C UF U UF UF
* 12 AF C UF U UF * 12 AF C UF U UF
* Fs_in (kHz) 16 D AF C UF UF * Fs_in (kHz) 16 D AF C UF UF
* 24 AIF D AF C U * 24 AF D AF C U
* 48 DAF DAF AF D C * 48 AF AF AF D C
*
* default method: UF
* *
* C -> Copy (no resampling) * C -> Copy (no resampling)
* D -> Allpass-based 2x downsampling * D -> Allpass-based 2x downsampling
* U -> Allpass-based 2x upsampling * 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 * UF -> Allpass-based 2x upsampling followed by FIR interpolation
* AF -> AR2 filter followed by FIR interpolation * AF -> AR2 filter followed by FIR interpolation
*
* Signals sampled above 48 kHz are not supported.
*/ */
#include "resampler_private.h" #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_copy (0)
#define USE_silk_resampler_private_up2_HQ_wrapper (1) #define USE_silk_resampler_private_up2_HQ_wrapper (1)
#define USE_silk_resampler_private_IIR_FIR (2) #define USE_silk_resampler_private_IIR_FIR (2)
@ -62,25 +78,40 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
opus_int silk_resampler_init( opus_int silk_resampler_init(
silk_resampler_state_struct *S, /* I/O Resampler state */ silk_resampler_state_struct *S, /* I/O Resampler state */
opus_int32 Fs_Hz_in, /* I Input sampling rate (Hz) */ opus_int32 Fs_Hz_in, /* I Input sampling rate (Hz) */
opus_int32 Fs_Hz_out /* I Output 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 */ /* Clear state */
silk_memset( S, 0, sizeof( silk_resampler_state_struct ) ); silk_memset( S, 0, sizeof( silk_resampler_state_struct ) );
/* Input checking */ /* Input checking */
if( forEnc ) {
if( ( Fs_Hz_in != 8000 && Fs_Hz_in != 12000 && Fs_Hz_in != 16000 && Fs_Hz_in != 24000 && Fs_Hz_in != 48000 ) || 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 ) ) { ( Fs_Hz_out != 8000 && Fs_Hz_out != 12000 && Fs_Hz_out != 16000 && Fs_Hz_out != 24000 && Fs_Hz_out != 48000 ) ) {
silk_assert( 0 ); silk_assert( 0 );
return -1; 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 */ /* 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 */ /* Find resampler with the right sampling ratio */
up2x = 0;
if( Fs_Hz_out > Fs_Hz_in ) { if( Fs_Hz_out > Fs_Hz_in ) {
/* Upsample */ /* Upsample */
if( Fs_Hz_out == silk_MUL( Fs_Hz_in, 2 ) ) { /* Fs_out : Fs_in = 2 : 1 */ if( Fs_Hz_out == silk_MUL( Fs_Hz_in, 2 ) ) { /* Fs_out : Fs_in = 2 : 1 */
@ -89,36 +120,35 @@ opus_int silk_resampler_init(
} else { } else {
/* Default resampler */ /* Default resampler */
S->resampler_function = USE_silk_resampler_private_IIR_FIR; S->resampler_function = USE_silk_resampler_private_IIR_FIR;
up2 = 1; up2x = 1;
} }
} else if ( Fs_Hz_out < Fs_Hz_in ) { } else if ( Fs_Hz_out < Fs_Hz_in ) {
/* Downsample */ /* 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 */ 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_Fracs = 3;
S->FIR_Order = RESAMPLER_DOWN_ORDER_FIR0;
S->Coefs = silk_Resampler_3_4_COEFS; 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 */ } 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_Fracs = 2;
S->FIR_Order = RESAMPLER_DOWN_ORDER_FIR0;
S->Coefs = silk_Resampler_2_3_COEFS; 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 */ } else if( silk_MUL( Fs_Hz_out, 2 ) == Fs_Hz_in ) { /* Fs_out : Fs_in = 1 : 2 */
S->FIR_Fracs = 1; S->FIR_Fracs = 1;
S->FIR_Order = RESAMPLER_DOWN_ORDER_FIR1;
S->Coefs = silk_Resampler_1_2_COEFS; 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 */ } else if( silk_MUL( Fs_Hz_out, 3 ) == Fs_Hz_in ) { /* Fs_out : Fs_in = 1 : 3 */
S->FIR_Fracs = 1; S->FIR_Fracs = 1;
S->FIR_Order = RESAMPLER_DOWN_ORDER_FIR2;
S->Coefs = silk_Resampler_1_3_COEFS; 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 */ } else if( silk_MUL( Fs_Hz_out, 4 ) == Fs_Hz_in ) { /* Fs_out : Fs_in = 1 : 4 */
S->FIR_Fracs = 1; S->FIR_Fracs = 1;
down2 = 1; S->FIR_Order = RESAMPLER_DOWN_ORDER_FIR2;
S->Coefs = silk_Resampler_1_2_COEFS; S->Coefs = silk_Resampler_1_4_COEFS;
S->resampler_function = USE_silk_resampler_private_down_FIR;
} else if( silk_MUL( Fs_Hz_out, 6 ) == Fs_Hz_in ) { /* Fs_out : Fs_in = 1 : 6 */ } else if( silk_MUL( Fs_Hz_out, 6 ) == Fs_Hz_in ) { /* Fs_out : Fs_in = 1 : 6 */
S->FIR_Fracs = 1; S->FIR_Fracs = 1;
down2 = 1; S->FIR_Order = RESAMPLER_DOWN_ORDER_FIR2;
S->Coefs = silk_Resampler_1_3_COEFS; S->Coefs = silk_Resampler_1_6_COEFS;
S->resampler_function = USE_silk_resampler_private_down_FIR;
} else { } else {
/* None available */ /* None available */
silk_assert( 0 ); silk_assert( 0 );
@ -129,12 +159,10 @@ opus_int silk_resampler_init(
S->resampler_function = USE_silk_resampler_copy; S->resampler_function = USE_silk_resampler_copy;
} }
S->input2x = up2 | down2;
/* Ratio of input/output samples */ /* 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 */ /* 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++; S->invRatio_Q16++;
} }
@ -142,6 +170,7 @@ opus_int silk_resampler_init(
} }
/* Resampler: convert from one sampling rate to another */ /* Resampler: convert from one sampling rate to another */
/* Input and output sampling rate are at most 48000 Hz */
opus_int silk_resampler( opus_int silk_resampler(
silk_resampler_state_struct *S, /* I/O Resampler state */ silk_resampler_state_struct *S, /* I/O Resampler state */
opus_int16 out[], /* O Output signal */ opus_int16 out[], /* O Output signal */
@ -149,19 +178,38 @@ opus_int silk_resampler(
opus_int32 inLen /* I Number of input samples */ 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 ) { switch( S->resampler_function ) {
case USE_silk_resampler_private_up2_HQ_wrapper: 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; break;
case USE_silk_resampler_private_IIR_FIR: 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; break;
case USE_silk_resampler_private_down_FIR: 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; break;
default: 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; return 0;
} }

View file

@ -32,7 +32,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "SigProc_FIX.h" #include "SigProc_FIX.h"
#include "resampler_rom.h" #include "resampler_rom.h"
/* Downsample by a factor 2, mediocre quality */ /* Downsample by a factor 2 */
void silk_resampler_down2( void silk_resampler_down2(
opus_int32 *S, /* I/O State vector [ 2 ] */ opus_int32 *S, /* I/O State vector [ 2 ] */
opus_int16 *out, /* O Output signal [ len ] */ opus_int16 *out, /* O Output signal [ len ] */

View file

@ -25,8 +25,8 @@ ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
***********************************************************************/ ***********************************************************************/
#ifndef SILK_RESAMPLER_H #ifndef SILK_RESAMPLER_PRIVATE_H
#define SILK_RESAMPLER_H #define SILK_RESAMPLER_PRIVATE_H
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
@ -37,7 +37,9 @@ extern "C" {
#include "resampler_rom.h" #include "resampler_rom.h"
/* Number of input samples to process in the inner loop */ /* 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 */ /* Description: Hybrid IIR/FIR polyphase implementation of resampling */
void silk_resampler_private_IIR_FIR( void silk_resampler_private_IIR_FIR(
@ -83,4 +85,4 @@ void silk_resampler_private_AR2(
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif
#endif /* SILK_RESAMPLER_H */ #endif /* SILK_RESAMPLER_PRIVATE_H */

View file

@ -45,15 +45,17 @@ static inline opus_int16 *silk_resampler_private_IIR_FIR_INTERPOL(
/* Interpolate upsampled signal and store in output array */ /* Interpolate upsampled signal and store in output array */
for( index_Q16 = 0; index_Q16 < max_index_Q16; index_Q16 += index_increment_Q16 ) { 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 ]; buf_ptr = &buf[ index_Q16 >> 16 ];
res_Q15 = silk_SMULBB( buf_ptr[ 0 ], silk_resampler_frac_FIR_144[ 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_144[ table_index ][ 1 ] ); 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_144[ table_index ][ 2 ] ); 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_144[ 143 - 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_144[ 143 - table_index ][ 1 ] ); 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_144[ 143 - table_index ][ 0 ] ); 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 ) ); *out++ = (opus_int16)silk_SAT16( silk_RSHIFT_ROUND( res_Q15, 15 ) );
} }
return out; return out;
@ -69,34 +71,33 @@ void silk_resampler_private_IIR_FIR(
silk_resampler_state_struct *S = (silk_resampler_state_struct *)SS; silk_resampler_state_struct *S = (silk_resampler_state_struct *)SS;
opus_int32 nSamplesIn; opus_int32 nSamplesIn;
opus_int32 max_index_Q16, index_increment_Q16; 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 */ /* 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 */ /* Iterate over blocks of frameSizeIn input samples */
index_increment_Q16 = S->invRatio_Q16; index_increment_Q16 = S->invRatio_Q16;
while( 1 ) { while( 1 ) {
nSamplesIn = silk_min( inLen, S->batchSize ); nSamplesIn = silk_min( inLen, S->batchSize );
silk_assert( S->input2x );
/* Upsample 2x */ /* 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 */ 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); out = silk_resampler_private_IIR_FIR_INTERPOL( out, buf, max_index_Q16, index_increment_Q16 );
in += nSamplesIn; in += nSamplesIn;
inLen -= nSamplesIn; inLen -= nSamplesIn;
if( inLen > 0 ) { if( inLen > 0 ) {
/* More iterations to do; copy last part of filtered signal to beginning of buffer */ /* 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 { } else {
break; break;
} }
} }
/* Copy last part of filtered signal to the state for the next call */ /* 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 ) );
} }

View file

@ -32,60 +32,32 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "SigProc_FIX.h" #include "SigProc_FIX.h"
#include "resampler_private.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_int16 *out,
opus_int32 *buf2, opus_int32 *buf,
const opus_int16 *FIR_Coefs, const opus_int16 *FIR_Coefs,
opus_int FIR_Order,
opus_int FIR_Fracs,
opus_int32 max_index_Q16, opus_int32 max_index_Q16,
opus_int32 index_increment_Q16 opus_int32 index_increment_Q16
) )
{
opus_int32 index_Q16, res_Q6;
opus_int32 *buf_ptr;
for( index_Q16 = 0; index_Q16 < max_index_Q16; index_Q16 += index_increment_Q16 ) {
/* Integer part gives pointer to buffered input */
buf_ptr = buf2 + silk_RSHIFT( index_Q16, 16 );
/* Inner product */
res_Q6 = silk_SMULWB( silk_ADD32( buf_ptr[ 0 ], buf_ptr[ 15 ] ), FIR_Coefs[ 0 ] );
res_Q6 = silk_SMLAWB( res_Q6, silk_ADD32( buf_ptr[ 1 ], buf_ptr[ 14 ] ), FIR_Coefs[ 1 ] );
res_Q6 = silk_SMLAWB( res_Q6, silk_ADD32( buf_ptr[ 2 ], buf_ptr[ 13 ] ), FIR_Coefs[ 2 ] );
res_Q6 = silk_SMLAWB( res_Q6, silk_ADD32( buf_ptr[ 3 ], buf_ptr[ 12 ] ), FIR_Coefs[ 3 ] );
res_Q6 = silk_SMLAWB( res_Q6, silk_ADD32( buf_ptr[ 4 ], buf_ptr[ 11 ] ), FIR_Coefs[ 4 ] );
res_Q6 = silk_SMLAWB( res_Q6, silk_ADD32( buf_ptr[ 5 ], buf_ptr[ 10 ] ), FIR_Coefs[ 5 ] );
res_Q6 = silk_SMLAWB( res_Q6, silk_ADD32( buf_ptr[ 6 ], buf_ptr[ 9 ] ), FIR_Coefs[ 6 ] );
res_Q6 = silk_SMLAWB( res_Q6, silk_ADD32( buf_ptr[ 7 ], buf_ptr[ 8 ] ), FIR_Coefs[ 7 ] );
/* Scale down, saturate and store in output array */
*out++ = (opus_int16)silk_SAT16( silk_RSHIFT_ROUND( res_Q6, 6 ) );
}
return out;
}
static inline opus_int16 *silk_resampler_private_down_FIR_INTERPOL1(
opus_int16 *out,
opus_int32 *buf2,
const opus_int16 *FIR_Coefs,
opus_int32 max_index_Q16,
opus_int32 index_increment_Q16,
opus_int32 FIR_Fracs
)
{ {
opus_int32 index_Q16, res_Q6; opus_int32 index_Q16, res_Q6;
opus_int32 *buf_ptr; opus_int32 *buf_ptr;
opus_int32 interpol_ind; opus_int32 interpol_ind;
const opus_int16 *interpol_ptr; const opus_int16 *interpol_ptr;
switch( FIR_Order ) {
case RESAMPLER_DOWN_ORDER_FIR0:
for( index_Q16 = 0; index_Q16 < max_index_Q16; index_Q16 += index_increment_Q16 ) { for( index_Q16 = 0; index_Q16 < max_index_Q16; index_Q16 += index_increment_Q16 ) {
/* Integer part gives pointer to buffered input */ /* Integer part gives pointer to buffered input */
buf_ptr = buf2 + silk_RSHIFT( index_Q16, 16 ); buf_ptr = buf + silk_RSHIFT( index_Q16, 16 );
/* Fractional part gives interpolation coefficients */ /* Fractional part gives interpolation coefficients */
interpol_ind = silk_SMULWB( index_Q16 & 0xFFFF, FIR_Fracs ); interpol_ind = silk_SMULWB( index_Q16 & 0xFFFF, FIR_Fracs );
/* Inner product */ /* Inner product */
interpol_ptr = &FIR_Coefs[ RESAMPLER_DOWN_ORDER_FIR / 2 * interpol_ind ]; interpol_ptr = &FIR_Coefs[ RESAMPLER_DOWN_ORDER_FIR0 / 2 * interpol_ind ];
res_Q6 = silk_SMULWB( buf_ptr[ 0 ], interpol_ptr[ 0 ] ); 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[ 1 ], interpol_ptr[ 1 ] );
res_Q6 = silk_SMLAWB( res_Q6, buf_ptr[ 2 ], interpol_ptr[ 2 ] ); res_Q6 = silk_SMLAWB( res_Q6, buf_ptr[ 2 ], interpol_ptr[ 2 ] );
@ -94,24 +66,81 @@ static inline opus_int16 *silk_resampler_private_down_FIR_INTERPOL1(
res_Q6 = silk_SMLAWB( res_Q6, buf_ptr[ 5 ], interpol_ptr[ 5 ] ); 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[ 6 ], interpol_ptr[ 6 ] );
res_Q6 = silk_SMLAWB( res_Q6, buf_ptr[ 7 ], interpol_ptr[ 7 ] ); 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[ 8 ], interpol_ptr[ 8 ] );
res_Q6 = silk_SMLAWB( res_Q6, buf_ptr[ 15 ], interpol_ptr[ 0 ] ); interpol_ptr = &FIR_Coefs[ RESAMPLER_DOWN_ORDER_FIR0 / 2 * ( FIR_Fracs - 1 - interpol_ind ) ];
res_Q6 = silk_SMLAWB( res_Q6, buf_ptr[ 14 ], interpol_ptr[ 1 ] ); res_Q6 = silk_SMLAWB( res_Q6, buf_ptr[ 17 ], interpol_ptr[ 0 ] );
res_Q6 = silk_SMLAWB( res_Q6, buf_ptr[ 13 ], interpol_ptr[ 2 ] ); res_Q6 = silk_SMLAWB( res_Q6, buf_ptr[ 16 ], interpol_ptr[ 1 ] );
res_Q6 = silk_SMLAWB( res_Q6, buf_ptr[ 12 ], interpol_ptr[ 3 ] ); res_Q6 = silk_SMLAWB( res_Q6, buf_ptr[ 15 ], interpol_ptr[ 2 ] );
res_Q6 = silk_SMLAWB( res_Q6, buf_ptr[ 11 ], interpol_ptr[ 4 ] ); res_Q6 = silk_SMLAWB( res_Q6, buf_ptr[ 14 ], interpol_ptr[ 3 ] );
res_Q6 = silk_SMLAWB( res_Q6, buf_ptr[ 10 ], interpol_ptr[ 5 ] ); res_Q6 = silk_SMLAWB( res_Q6, buf_ptr[ 13 ], interpol_ptr[ 4 ] );
res_Q6 = silk_SMLAWB( res_Q6, buf_ptr[ 9 ], interpol_ptr[ 6 ] ); res_Q6 = silk_SMLAWB( res_Q6, buf_ptr[ 12 ], interpol_ptr[ 5 ] );
res_Q6 = silk_SMLAWB( res_Q6, buf_ptr[ 8 ], interpol_ptr[ 7 ] ); res_Q6 = silk_SMLAWB( res_Q6, buf_ptr[ 11 ], interpol_ptr[ 6 ] );
res_Q6 = silk_SMLAWB( res_Q6, buf_ptr[ 10 ], interpol_ptr[ 7 ] );
res_Q6 = silk_SMLAWB( res_Q6, buf_ptr[ 9 ], interpol_ptr[ 8 ] );
/* Scale down, saturate and store in output array */ /* Scale down, saturate and store in output array */
*out++ = (opus_int16)silk_SAT16( silk_RSHIFT_ROUND( res_Q6, 6 ) ); *out++ = (opus_int16)silk_SAT16( silk_RSHIFT_ROUND( res_Q6, 6 ) );
} }
break;
case RESAMPLER_DOWN_ORDER_FIR1:
for( index_Q16 = 0; index_Q16 < max_index_Q16; index_Q16 += index_increment_Q16 ) {
/* Integer part gives pointer to buffered input */
buf_ptr = buf + silk_RSHIFT( index_Q16, 16 );
/* Inner product */
res_Q6 = silk_SMULWB( silk_ADD32( buf_ptr[ 0 ], buf_ptr[ 23 ] ), FIR_Coefs[ 0 ] );
res_Q6 = silk_SMLAWB( res_Q6, silk_ADD32( buf_ptr[ 1 ], buf_ptr[ 22 ] ), FIR_Coefs[ 1 ] );
res_Q6 = silk_SMLAWB( res_Q6, silk_ADD32( buf_ptr[ 2 ], buf_ptr[ 21 ] ), FIR_Coefs[ 2 ] );
res_Q6 = silk_SMLAWB( res_Q6, silk_ADD32( buf_ptr[ 3 ], buf_ptr[ 20 ] ), FIR_Coefs[ 3 ] );
res_Q6 = silk_SMLAWB( res_Q6, silk_ADD32( buf_ptr[ 4 ], buf_ptr[ 19 ] ), FIR_Coefs[ 4 ] );
res_Q6 = silk_SMLAWB( res_Q6, silk_ADD32( buf_ptr[ 5 ], buf_ptr[ 18 ] ), FIR_Coefs[ 5 ] );
res_Q6 = silk_SMLAWB( res_Q6, silk_ADD32( buf_ptr[ 6 ], buf_ptr[ 17 ] ), FIR_Coefs[ 6 ] );
res_Q6 = silk_SMLAWB( res_Q6, silk_ADD32( buf_ptr[ 7 ], buf_ptr[ 16 ] ), FIR_Coefs[ 7 ] );
res_Q6 = silk_SMLAWB( res_Q6, silk_ADD32( buf_ptr[ 8 ], buf_ptr[ 15 ] ), FIR_Coefs[ 8 ] );
res_Q6 = silk_SMLAWB( res_Q6, silk_ADD32( buf_ptr[ 9 ], buf_ptr[ 14 ] ), FIR_Coefs[ 9 ] );
res_Q6 = silk_SMLAWB( res_Q6, silk_ADD32( buf_ptr[ 10 ], buf_ptr[ 13 ] ), FIR_Coefs[ 10 ] );
res_Q6 = silk_SMLAWB( res_Q6, silk_ADD32( buf_ptr[ 11 ], buf_ptr[ 12 ] ), FIR_Coefs[ 11 ] );
/* Scale down, saturate and store in output array */
*out++ = (opus_int16)silk_SAT16( silk_RSHIFT_ROUND( res_Q6, 6 ) );
}
break;
case RESAMPLER_DOWN_ORDER_FIR2:
for( index_Q16 = 0; index_Q16 < max_index_Q16; index_Q16 += index_increment_Q16 ) {
/* Integer part gives pointer to buffered input */
buf_ptr = buf + silk_RSHIFT( index_Q16, 16 );
/* Inner product */
res_Q6 = silk_SMULWB( silk_ADD32( buf_ptr[ 0 ], buf_ptr[ 35 ] ), FIR_Coefs[ 0 ] );
res_Q6 = silk_SMLAWB( res_Q6, silk_ADD32( buf_ptr[ 1 ], buf_ptr[ 34 ] ), FIR_Coefs[ 1 ] );
res_Q6 = silk_SMLAWB( res_Q6, silk_ADD32( buf_ptr[ 2 ], buf_ptr[ 33 ] ), FIR_Coefs[ 2 ] );
res_Q6 = silk_SMLAWB( res_Q6, silk_ADD32( buf_ptr[ 3 ], buf_ptr[ 32 ] ), FIR_Coefs[ 3 ] );
res_Q6 = silk_SMLAWB( res_Q6, silk_ADD32( buf_ptr[ 4 ], buf_ptr[ 31 ] ), FIR_Coefs[ 4 ] );
res_Q6 = silk_SMLAWB( res_Q6, silk_ADD32( buf_ptr[ 5 ], buf_ptr[ 30 ] ), FIR_Coefs[ 5 ] );
res_Q6 = silk_SMLAWB( res_Q6, silk_ADD32( buf_ptr[ 6 ], buf_ptr[ 29 ] ), FIR_Coefs[ 6 ] );
res_Q6 = silk_SMLAWB( res_Q6, silk_ADD32( buf_ptr[ 7 ], buf_ptr[ 28 ] ), FIR_Coefs[ 7 ] );
res_Q6 = silk_SMLAWB( res_Q6, silk_ADD32( buf_ptr[ 8 ], buf_ptr[ 27 ] ), FIR_Coefs[ 8 ] );
res_Q6 = silk_SMLAWB( res_Q6, silk_ADD32( buf_ptr[ 9 ], buf_ptr[ 26 ] ), FIR_Coefs[ 9 ] );
res_Q6 = silk_SMLAWB( res_Q6, silk_ADD32( buf_ptr[ 10 ], buf_ptr[ 25 ] ), FIR_Coefs[ 10 ] );
res_Q6 = silk_SMLAWB( res_Q6, silk_ADD32( buf_ptr[ 11 ], buf_ptr[ 24 ] ), FIR_Coefs[ 11 ] );
res_Q6 = silk_SMLAWB( res_Q6, silk_ADD32( buf_ptr[ 12 ], buf_ptr[ 23 ] ), FIR_Coefs[ 12 ] );
res_Q6 = silk_SMLAWB( res_Q6, silk_ADD32( buf_ptr[ 13 ], buf_ptr[ 22 ] ), FIR_Coefs[ 13 ] );
res_Q6 = silk_SMLAWB( res_Q6, silk_ADD32( buf_ptr[ 14 ], buf_ptr[ 21 ] ), FIR_Coefs[ 14 ] );
res_Q6 = silk_SMLAWB( res_Q6, silk_ADD32( buf_ptr[ 15 ], buf_ptr[ 20 ] ), FIR_Coefs[ 15 ] );
res_Q6 = silk_SMLAWB( res_Q6, silk_ADD32( buf_ptr[ 16 ], buf_ptr[ 19 ] ), FIR_Coefs[ 16 ] );
res_Q6 = silk_SMLAWB( res_Q6, silk_ADD32( buf_ptr[ 17 ], buf_ptr[ 18 ] ), FIR_Coefs[ 17 ] );
/* Scale down, saturate and store in output array */
*out++ = (opus_int16)silk_SAT16( silk_RSHIFT_ROUND( res_Q6, 6 ) );
}
break;
default:
silk_assert( 0 );
}
return out; return out;
} }
/* Resample with a 2nd order AR filter followed by FIR interpolation */
/* Resample with a 2x downsampler (optional), a 2nd order AR filter followed by FIR interpolation */
void silk_resampler_private_down_FIR( void silk_resampler_private_down_FIR(
void *SS, /* I/O Resampler state */ void *SS, /* I/O Resampler state */
opus_int16 out[], /* O Output signal */ opus_int16 out[], /* O Output signal */
@ -122,12 +151,11 @@ void silk_resampler_private_down_FIR(
silk_resampler_state_struct *S = (silk_resampler_state_struct *)SS; silk_resampler_state_struct *S = (silk_resampler_state_struct *)SS;
opus_int32 nSamplesIn; opus_int32 nSamplesIn;
opus_int32 max_index_Q16, index_increment_Q16; opus_int32 max_index_Q16, index_increment_Q16;
opus_int16 buf1[ RESAMPLER_MAX_BATCH_SIZE_IN / 2 ]; opus_int32 buf[ RESAMPLER_MAX_BATCH_SIZE_IN + SILK_RESAMPLER_MAX_FIR_ORDER ];
opus_int32 buf2[ RESAMPLER_MAX_BATCH_SIZE_IN + RESAMPLER_DOWN_ORDER_FIR ];
const opus_int16 *FIR_Coefs; const opus_int16 *FIR_Coefs;
/* Copy buffered samples to start of buffer */ /* 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 ]; FIR_Coefs = &S->Coefs[ 2 ];
@ -136,40 +164,26 @@ void silk_resampler_private_down_FIR(
while( 1 ) { while( 1 ) {
nSamplesIn = silk_min( inLen, S->batchSize ); nSamplesIn = silk_min( inLen, S->batchSize );
if( S->input2x == 1 ) {
/* Downsample 2x */
silk_resampler_down2( S->sDown2, buf1, in, nSamplesIn );
nSamplesIn = silk_RSHIFT32( nSamplesIn, 1 );
/* Second-order AR filter (output in Q8) */ /* Second-order AR filter (output in Q8) */
silk_resampler_private_AR2( S->sIIR, &buf2[ RESAMPLER_DOWN_ORDER_FIR ], buf1, S->Coefs, nSamplesIn ); silk_resampler_private_AR2( S->sIIR, &buf[ S->FIR_Order ], in, 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 ); max_index_Q16 = silk_LSHIFT32( nSamplesIn, 16 );
/* Interpolate filtered signal */ /* Interpolate filtered signal */
if( S->FIR_Fracs == 1 ) { out = silk_resampler_private_down_FIR_INTERPOL( out, buf, FIR_Coefs, S->FIR_Order,
out = silk_resampler_private_down_FIR_INTERPOL0(out, buf2, FIR_Coefs, max_index_Q16, index_increment_Q16); S->FIR_Fracs, 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);
}
in += nSamplesIn << S->input2x; in += nSamplesIn;
inLen -= nSamplesIn << S->input2x; inLen -= nSamplesIn;
if( inLen > S->input2x ) { if( inLen > 1 ) {
/* More iterations to do; copy last part of filtered signal to beginning of buffer */ /* 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 { } else {
break; break;
} }
} }
/* Copy last part of filtered signal to the state for the next call */ /* 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 ) );
} }

View file

@ -46,9 +46,11 @@ void silk_resampler_private_up2_HQ(
opus_int32 in32, out32_1, out32_2, Y, X; 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[ 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[ 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 */ /* Internal variables and state are in Q10 format */
for( k = 0; k < len; k++ ) { for( k = 0; k < len; k++ ) {
@ -63,41 +65,39 @@ void silk_resampler_private_up2_HQ(
/* Second all-pass section for even output sample */ /* Second all-pass section for even output sample */
Y = silk_SUB32( out32_1, S[ 1 ] ); 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 ); out32_2 = silk_ADD32( S[ 1 ], X );
S[ 1 ] = silk_ADD32( out32_1, X ); S[ 1 ] = silk_ADD32( out32_1, X );
/* Biquad notch filter */ /* Third all-pass section for even output sample */
out32_2 = silk_SMLAWB( out32_2, S[ 5 ], silk_resampler_up2_hq_notch[ 2 ] ); Y = silk_SUB32( out32_2, S[ 2 ] );
out32_2 = silk_SMLAWB( out32_2, S[ 4 ], silk_resampler_up2_hq_notch[ 1 ] ); X = silk_SMLAWB( Y, Y, silk_resampler_up2_hq_0[ 2 ] );
out32_1 = silk_SMLAWB( out32_2, S[ 4 ], silk_resampler_up2_hq_notch[ 0 ] ); out32_1 = silk_ADD32( S[ 2 ], X );
S[ 5 ] = silk_SUB32( out32_2, S[ 5 ] ); S[ 2 ] = silk_ADD32( out32_2, X );
/* Apply gain in Q15, convert back to int16 and store to output */ /* Apply gain in Q15, convert back to int16 and store to output */
out[ 2 * k ] = (opus_int16)silk_SAT16( silk_RSHIFT32( out[ 2 * k ] = (opus_int16)silk_SAT16( silk_RSHIFT_ROUND( out32_1, 10 ) );
silk_SMLAWB( 256, out32_1, silk_resampler_up2_hq_notch[ 3 ] ), 9 ) );
/* First all-pass section for odd output sample */ /* 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 ] ); X = silk_SMULWB( Y, silk_resampler_up2_hq_1[ 0 ] );
out32_1 = silk_ADD32( S[ 2 ], X ); out32_1 = silk_ADD32( S[ 3 ], X );
S[ 2 ] = silk_ADD32( in32, X ); S[ 3 ] = silk_ADD32( in32, X );
/* Second all-pass section for odd output sample */ /* Second all-pass section for odd output sample */
Y = silk_SUB32( out32_1, S[ 3 ] ); Y = silk_SUB32( out32_1, S[ 4 ] );
X = silk_SMLAWB( Y, Y, silk_resampler_up2_hq_1[ 1 ] ); X = silk_SMULWB( Y, silk_resampler_up2_hq_1[ 1 ] );
out32_2 = silk_ADD32( S[ 3 ], X ); out32_2 = silk_ADD32( S[ 4 ], X );
S[ 3 ] = silk_ADD32( out32_1, X ); S[ 4 ] = silk_ADD32( out32_1, X );
/* Biquad notch filter */ /* Third all-pass section for odd output sample */
out32_2 = silk_SMLAWB( out32_2, S[ 4 ], silk_resampler_up2_hq_notch[ 2 ] ); Y = silk_SUB32( out32_2, S[ 5 ] );
out32_2 = silk_SMLAWB( out32_2, S[ 5 ], silk_resampler_up2_hq_notch[ 1 ] ); X = silk_SMLAWB( Y, Y, silk_resampler_up2_hq_1[ 2 ] );
out32_1 = silk_SMLAWB( out32_2, S[ 5 ], silk_resampler_up2_hq_notch[ 0 ] ); out32_1 = silk_ADD32( S[ 5 ], X );
S[ 4 ] = silk_SUB32( out32_2, S[ 4 ] ); S[ 5 ] = silk_ADD32( out32_2, X );
/* Apply gain in Q15, convert back to int16 and store to output */ /* Apply gain in Q15, convert back to int16 and store to output */
out[ 2 * k + 1 ] = (opus_int16)silk_SAT16( silk_RSHIFT32( out[ 2 * k + 1 ] = (opus_int16)silk_SAT16( silk_RSHIFT_ROUND( out32_1, 10 ) );
silk_SMLAWB( 256, out32_1, silk_resampler_up2_hq_notch[ 3 ] ), 9 ) );
} }
} }

View file

@ -30,7 +30,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#endif #endif
/* Filter coefficients for IIR/FIR polyphase resampling * /* Filter coefficients for IIR/FIR polyphase resampling *
* Total size: < 600 Words (1.2 kB) */ * Total size: 179 Words (358 Bytes) */
#include "resampler_private.h" #include "resampler_private.h"
@ -39,32 +39,46 @@ const opus_int16 silk_resampler_down2_0 = 9872;
const opus_int16 silk_resampler_down2_1 = 39809 - 65536; const opus_int16 silk_resampler_down2_1 = 39809 - 65536;
/* Tables for 2x upsampler, high quality */ /* 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_0[ 3 ] = { 1746, 14986, 39083 - 65536 };
const opus_int16 silk_resampler_up2_hq_1[ 2 ] = { 16295, 54015 - 65536 }; const opus_int16 silk_resampler_up2_hq_1[ 3 ] = { 6854, 25769, 55542 - 65536 };
const opus_int16 silk_resampler_up2_hq_notch[ 4 ] = { 6554, -3932, 6554, 30573 };
/* Tables with IIR and FIR coefficients for fractional downsamplers (90 Words) */ /* Matlab code for the notch filter coefficients: */
silk_DWORD_ALIGN const opus_int16 silk_Resampler_3_4_COEFS[ 2 + 3 * RESAMPLER_DOWN_ORDER_FIR / 2 ] = { /* 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]) */
-20253, -13986, /* 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)) */
86, 7, -151, 368, -542, 232, 11041, 21904, const opus_int16 silk_resampler_up2_hq_notch[ 4 ] = { 9634, -7012, 7209, 30474 };
39, 90, -181, 216, -17, -877, 6408, 19695,
2, 113, -108, 2, 314, -977, 2665, 15787, /* 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 ] = { silk_DWORD_ALIGN const opus_int16 silk_Resampler_2_3_COEFS[ 2 + 2 * RESAMPLER_DOWN_ORDER_FIR0 / 2 ] = {
-13997, -14120, -14457, -14019,
60, -174, 71, 298, -800, 659, 9238, 17461, 64, 128, -122, 36, 310, -768, 584, 9267, 17733,
48, -40, -150, 314, -155, -845, 4188, 14293, 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 ] = { silk_DWORD_ALIGN const opus_int16 silk_Resampler_1_2_COEFS[ 2 + RESAMPLER_DOWN_ORDER_FIR1 / 2 ] = {
1233, -14293, 616, -14323,
-91, 162, 169, -342, -505, 1332, 5281, 8742, -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 ] = { silk_DWORD_ALIGN const opus_int16 silk_Resampler_1_3_COEFS[ 2 + RESAMPLER_DOWN_ORDER_FIR2 / 2 ] = {
16306, -14409, 16102, -15162,
99, -201, -220, -16, 572, 1483, 2433, 3043, -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 ] = { silk_DWORD_ALIGN const opus_int16 silk_Resampler_2_3_COEFS_LQ[ 2 + 2 * 2 ] = {
@ -73,150 +87,18 @@ silk_DWORD_ALIGN const opus_int16 silk_Resampler_2_3_COEFS_LQ[ 2 + 2 * 2 ] = {
1567, 8276, 1567, 8276,
}; };
/* Table with interplation fractions of 1/288 : 2/288 : 287/288 (432 Words) */ /* 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_144[ 144 ][ RESAMPLER_ORDER_FIR_144 / 2 ] = { silk_DWORD_ALIGN const opus_int16 silk_resampler_frac_FIR_12[ 12 ][ RESAMPLER_ORDER_FIR_12 / 2 ] = {
{ -25, 58, 32526}, { 189, -600, 617, 30567 },
{ -8, -69, 32461}, { 117, -159, -1070, 29704 },
{ 8, -195, 32393}, { 52, 221, -2392, 28276 },
{ 25, -318, 32321}, { -4, 529, -3350, 26341 },
{ 41, -439, 32244}, { -48, 758, -3956, 23973 },
{ 57, -557, 32163}, { -80, 905, -4235, 21254 },
{ 72, -673, 32079}, { -99, 972, -4222, 18278 },
{ 88, -787, 31990}, { -107, 967, -3957, 15143 },
{ 103, -899, 31897}, { -103, 896, -3487, 11950 },
{ 118, -1009, 31801}, { -91, 773, -2865, 8798 },
{ 133, -1116, 31700}, { -71, 611, -2143, 5784 },
{ 148, -1221, 31596}, { -46, 425, -1375, 2996 },
{ 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},
}; };

View file

@ -36,27 +36,30 @@ extern "C"
#include "typedef.h" #include "typedef.h"
#include "resampler_structs.h" #include "resampler_structs.h"
#define RESAMPLER_DOWN_ORDER_FIR 16 #define RESAMPLER_DOWN_ORDER_FIR0 18
#define RESAMPLER_ORDER_FIR_144 6 #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_0;
extern const opus_int16 silk_resampler_down2_1; extern const opus_int16 silk_resampler_down2_1;
/* Tables for 2x upsampler, high quality. Values above 32767 intentionally wrap to a negative value. */ /* Tables for 2x upsampler, high quality */
extern const opus_int16 silk_resampler_up2_hq_0[ 2 ]; extern const opus_int16 silk_resampler_up2_hq_0[ 3 ];
extern const opus_int16 silk_resampler_up2_hq_1[ 2 ]; extern const opus_int16 silk_resampler_up2_hq_1[ 3 ];
extern const opus_int16 silk_resampler_up2_hq_notch[ 4 ];
/* Tables with IIR and FIR coefficients for fractional downsamplers */ /* 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_3_4_COEFS[ 2 + 3 * RESAMPLER_DOWN_ORDER_FIR0 / 2 ];
extern const opus_int16 silk_Resampler_2_3_COEFS[ 2 + 2 * RESAMPLER_DOWN_ORDER_FIR / 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_FIR / 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_FIR / 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 ]; 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) */ /* Table with interplation fractions of 1/24, 3/24, ..., 23/24 */
extern const opus_int16 silk_resampler_frac_FIR_144[ 144 ][ RESAMPLER_ORDER_FIR_144 / 2 ]; extern const opus_int16 silk_resampler_frac_FIR_12[ 12 ][ RESAMPLER_ORDER_FIR_12 / 2 ];
#ifdef __cplusplus #ifdef __cplusplus
} }

View file

@ -32,18 +32,21 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
extern "C" { extern "C" {
#endif #endif
#define SILK_RESAMPLER_MAX_FIR_ORDER 16 #define SILK_RESAMPLER_MAX_FIR_ORDER 36
#define SILK_RESAMPLER_MAX_IIR_ORDER 6 #define SILK_RESAMPLER_MAX_IIR_ORDER 6
typedef struct _silk_resampler_state_struct{ 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 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 sFIR[ SILK_RESAMPLER_MAX_FIR_ORDER ];
opus_int32 sDown2[ 2 ]; opus_int16 delayBuf[ 48 ];
opus_int32 resampler_function; opus_int resampler_function;
opus_int32 batchSize; opus_int batchSize;
opus_int32 invRatio_Q16; opus_int32 invRatio_Q16;
opus_int32 FIR_Fracs; opus_int FIR_Order;
opus_int32 input2x; opus_int FIR_Fracs;
opus_int Fs_in_kHz;
opus_int Fs_out_kHz;
opus_int inputDelay;
const opus_int16 *Coefs; const opus_int16 *Coefs;
} silk_resampler_state_struct; } silk_resampler_state_struct;

View file

@ -200,7 +200,7 @@ void silk_stereo_LR_to_MS(
w_Q24 += deltaw_Q24; w_Q24 += deltaw_Q24;
sum = silk_LSHIFT( silk_ADD_LSHIFT( mid[ n ] + mid[ n + 2 ], mid[ n + 1 ], 1 ), 9 ); /* Q11 */ 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( 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_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 ) ); x2[ n - 1 ] = (opus_int16)silk_SAT16( silk_RSHIFT_ROUND( sum, 8 ) );
} }
@ -210,7 +210,7 @@ void silk_stereo_LR_to_MS(
for( n = STEREO_INTERP_LEN_MS * fs_kHz; n < frame_length; n++ ) { 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_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( 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_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 ) ); x2[ n - 1 ] = (opus_int16)silk_SAT16( silk_RSHIFT_ROUND( sum, 8 ) );
} }
state->pred_prev_Q13[ 0 ] = (opus_int16)pred_Q13[ 0 ]; state->pred_prev_Q13[ 0 ] = (opus_int16)pred_Q13[ 0 ];

View file

@ -60,16 +60,16 @@ void silk_stereo_MS_to_LR(
pred0_Q13 += delta0_Q13; pred0_Q13 += delta0_Q13;
pred1_Q13 += delta1_Q13; pred1_Q13 += delta1_Q13;
sum = silk_LSHIFT( silk_ADD_LSHIFT( x1[ n ] + x1[ n + 2 ], x1[ n + 1 ], 1 ), 9 ); /* Q11 */ 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( 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_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 ) ); x2[ n + 1 ] = (opus_int16)silk_SAT16( silk_RSHIFT_ROUND( sum, 8 ) );
} }
pred0_Q13 = pred_Q13[ 0 ]; pred0_Q13 = pred_Q13[ 0 ];
pred1_Q13 = pred_Q13[ 1 ]; pred1_Q13 = pred_Q13[ 1 ];
for( n = STEREO_INTERP_LEN_MS * fs_kHz; n < frame_length; n++ ) { 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_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( 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_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 ) ); x2[ n + 1 ] = (opus_int16)silk_SAT16( silk_RSHIFT_ROUND( sum, 8 ) );
} }
state->pred_prev_Q13[ 0 ] = pred_Q13[ 0 ]; state->pred_prev_Q13[ 0 ] = pred_Q13[ 0 ];

View file

@ -150,7 +150,6 @@ typedef struct {
opus_int minInternal_fs_Hz; /* Minimum internal sampling frequency (Hz) */ opus_int minInternal_fs_Hz; /* Minimum internal sampling frequency (Hz) */
opus_int desiredInternal_fs_Hz; /* Soft request for 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 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 nb_subfr; /* Number of 5 ms subframes in a frame */
opus_int frame_length; /* Frame length (samples) */ opus_int frame_length; /* Frame length (samples) */
opus_int subfr_length; /* Subframe length (samples) */ opus_int subfr_length; /* Subframe length (samples) */
@ -194,7 +193,6 @@ typedef struct {
/* Input/output buffering */ /* Input/output buffering */
opus_int16 inputBuf[ MAX_FRAME_LENGTH + 2 ]; /* Buffer containing input signal */ opus_int16 inputBuf[ MAX_FRAME_LENGTH + 2 ]; /* Buffer containing input signal */
opus_int16 delayBuf[MAX_ENCODER_DELAY];
opus_int inputBufIx; opus_int inputBufIx;
opus_int nFramesPerPacket; opus_int nFramesPerPacket;
opus_int nFramesEncoded; /* Number of frames analyzed in current packet */ opus_int nFramesEncoded; /* Number of frames analyzed in current packet */
@ -261,8 +259,6 @@ typedef struct {
opus_int32 exc_Q10[ MAX_FRAME_LENGTH ]; opus_int32 exc_Q10[ MAX_FRAME_LENGTH ];
opus_int32 sLPC_Q14_buf[ MAX_LPC_ORDER ]; 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 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_int lagPrev; /* Previous Lag */
opus_int8 LastGainIndex; /* Previous gain index */ opus_int8 LastGainIndex; /* Previous gain index */
opus_int fs_kHz; /* Sampling frequency in kHz */ opus_int fs_kHz; /* Sampling frequency in kHz */

View file

@ -51,13 +51,11 @@ extern "C"
/*********************/ /*********************/
/* LPC analysis defines: regularization and bandwidth expansion */ /* LPC analysis defines: regularization and bandwidth expansion */
#define FIND_LPC_COND_FAC 2.5e-5f #define FIND_LPC_COND_FAC 1e-5f
#define FIND_LPC_CHIRP 0.99995f
#define FIND_LPC_CHIRP_FIRST_FRAME 0.96f
/* LTP analysis defines */ /* LTP analysis defines */
#define FIND_LTP_COND_FAC 1e-5f #define FIND_LTP_COND_FAC 1e-5f
#define LTP_DAMPING 0.01f #define LTP_DAMPING 0.05f
#define LTP_SMOOTHING 0.1f #define LTP_SMOOTHING 0.1f
/* LTP quantization settings */ /* LTP quantization settings */
@ -108,7 +106,7 @@ extern "C"
#define WARPING_MULTIPLIER 0.015f #define WARPING_MULTIPLIER 0.015f
/* fraction added to first autocorrelation value */ /* 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 */ /* noise shaping filter chirp factor */
#define BANDWIDTH_EXPANSION 0.95f #define BANDWIDTH_EXPANSION 0.95f

View file

@ -126,10 +126,6 @@ static const opus_int32 mode_thresholds[2][2] = {
{ 48000, 24000}, /* stereo */ { 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 opus_encoder_get_size(int channels)
{ {
int silkEncSizeBytes, celtEncSizeBytes; int silkEncSizeBytes, celtEncSizeBytes;
@ -209,9 +205,9 @@ int opus_encoder_init(OpusEncoder* st, opus_int32 Fs, int channels, int applicat
st->voice_ratio = -1; st->voice_ratio = -1;
st->encoder_buffer = st->Fs/100; 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 += celt_delay_table[rateID(st->Fs)]; st->delay_compensation = st->Fs/250;
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->variable_HP_smth2_Q15 = silk_LSHIFT( silk_lin2log( VARIABLE_HP_MIN_CUTOFF_HZ ), 8 );