/* Variable order MA filter */ void SKP_Silk_MA( const SKP_int16 *in, /* I: input signal */ const SKP_int16 *B, /* I: MA coefficients, Q13 [order+1] */ SKP_int32 *S, /* I/O: state vector [order] */ SKP_int16 *out, /* O: output signal */ const SKP_int32 len, /* I: signal length */ const SKP_int32 order /* I: filter order */ ) { SKP_int k, d, in16; SKP_int32 out32; for( k = 0; k < len; k++ ) { in16 = in[ k ]; out32 = SKP_SMLABB( S[ 0 ], in16, B[ 0 ] ); out32 = SKP_RSHIFT_ROUND( out32, 13 ); for( d = 1; d < order; d++ ) { S[ d - 1 ] = SKP_SMLABB( S[ d ], in16, B[ d ] ); } S[ order - 1 ] = SKP_SMULBB( in16, B[ order ] ); /* Limit */ out[ k ] = (SKP_int16)SKP_SAT16( out32 ); } }
/* Can handle slowly varying filter coefficients */ void SKP_Silk_biquad( const SKP_int16 *in, /* I: input signal */ const SKP_int16 *B, /* I: MA coefficients, Q13 [3] */ const SKP_int16 *A, /* I: AR coefficients, Q13 [2] */ SKP_int32 *S, /* I/O: state vector [2] */ SKP_int16 *out, /* O: output signal */ const SKP_int32 len /* I: signal length */ ) { SKP_int k, in16; SKP_int32 A0_neg, A1_neg, S0, S1, out32, tmp32; S0 = S[ 0 ]; S1 = S[ 1 ]; A0_neg = -A[ 0 ]; A1_neg = -A[ 1 ]; for( k = 0; k < len; k++ ) { /* S[ 0 ], S[ 1 ]: Q13 */ in16 = in[ k ]; out32 = SKP_SMLABB( S0, in16, B[ 0 ] ); S0 = SKP_SMLABB( S1, in16, B[ 1 ] ); S0 += SKP_LSHIFT( SKP_SMULWB( out32, A0_neg ), 3 ); S1 = SKP_LSHIFT( SKP_SMULWB( out32, A1_neg ), 3 ); S1 = SKP_SMLABB( S1, in16, B[ 2 ] ); tmp32 = SKP_RSHIFT_ROUND( out32, 13 ) + 1; out[ k ] = (SKP_int16)SKP_SAT16( tmp32 ); } S[ 0 ] = S0; S[ 1 ] = S1; }
/* Variable order MA filter */ void SKP_Silk_MA( const SKP_int16 *in, /* I: input signal */ const SKP_int16 *B, /* I: MA coefficients, Q13 [order+1] */ SKP_int32 *S, /* I/O: state vector [order] */ SKP_int16 *out, /* O: output signal */ const SKP_int32 len, /* I: signal length */ const SKP_int32 order /* I: filter order */ ) { SKP_int k, in16; SKP_int32 out32; switch(order) { case 8: for( k = 0; k < len; k++ ) { in16 = in[ k ]; out32 = SKP_SMLABB( S[ 0 ], in16, B[ 0 ] ); out32 = SKP_RSHIFT_ROUND( out32, 13 ); FILTER_LOOP_ORDER_8(S, B + 1, in16); out[ k ] = (SKP_int16) SKP_SAT16(out32); } break; case 10: for( k = 0; k < len; k++ ) { in16 = in[ k ]; out32 = SKP_SMLABB( S[ 0 ], in16, B[ 0 ] ); out32 = SKP_RSHIFT_ROUND( out32, 13 ); FILTER_LOOP_ORDER_10(S, B + 1, in16); out[ k ] = (SKP_int16) SKP_SAT16(out32); } break; case 12: for( k = 0; k < len; k++ ) { in16 = in[ k ]; out32 = SKP_SMLABB( S[ 0 ], in16, B[ 0 ] ); out32 = SKP_RSHIFT_ROUND( out32, 13 ); FILTER_LOOP_ORDER_12(S, B + 1, in16); out[ k ] = (SKP_int16) SKP_SAT16(out32); } break; case 16: for( k = 0; k < len; k++ ) { in16 = in[ k ]; out32 = SKP_SMLABB( S[ 0 ], in16, B[ 0 ] ); out32 = SKP_RSHIFT_ROUND( out32, 13 ); FILTER_LOOP_ORDER_16(S, B + 1, in16); out[ k ] = (SKP_int16) SKP_SAT16(out32); } break; default: for( k = 0; k < len; k++ ) { in16 = in[ k ]; out32 = SKP_SMLABB( S[ 0 ], in16, B[ 0 ] ); out32 = SKP_RSHIFT_ROUND( out32, 13 ); FILTER_LOOP_ORDER_ANY(S, B + 1, in16, order); out[ k ] = (SKP_int16) SKP_SAT16(out32); } } }
/* Upsample using a combination of allpass-based 2x upsampling and FIR interpolation */ void SKP_Silk_resampler_private_IIR_FIR( void *SS, /* I/O: Resampler state */ SKP_int16 out[], /* O: Output signal */ const SKP_int16 in[], /* I: Input signal */ SKP_int32 inLen /* I: Number of input samples */ ) { SKP_Silk_resampler_state_struct *S = (SKP_Silk_resampler_state_struct *)SS; SKP_int32 nSamplesIn, table_index; SKP_int32 max_index_Q16, index_Q16, index_increment_Q16, res_Q15; SKP_int16 buf[ 2 * RESAMPLER_MAX_BATCH_SIZE_IN + RESAMPLER_ORDER_FIR_144 ]; SKP_int16 *buf_ptr; /* Copy buffered samples to start of buffer */ SKP_memcpy( buf, S->sFIR, RESAMPLER_ORDER_FIR_144 * sizeof( SKP_int32 ) ); /* Iterate over blocks of frameSizeIn input samples */ index_increment_Q16 = S->invRatio_Q16; while( 1 ) { nSamplesIn = SKP_min( inLen, S->batchSize ); if( S->input2x == 1 ) { /* Upsample 2x */ S->up2_function( S->sIIR, &buf[ RESAMPLER_ORDER_FIR_144 ], in, nSamplesIn ); } else { /* Fourth-order ARMA filter */ SKP_Silk_resampler_private_ARMA4( S->sIIR, &buf[ RESAMPLER_ORDER_FIR_144 ], in, S->Coefs, nSamplesIn ); } max_index_Q16 = SKP_LSHIFT32( nSamplesIn, 16 + S->input2x ); /* +1 if 2x upsampling */ /* Interpolate upsampled signal and store in output array */ for( index_Q16 = 0; index_Q16 < max_index_Q16; index_Q16 += index_increment_Q16 ) { table_index = SKP_SMULWB( index_Q16 & 0xFFFF, 144 ); buf_ptr = &buf[ index_Q16 >> 16 ]; res_Q15 = SKP_SMULBB( buf_ptr[ 0 ], SKP_Silk_resampler_frac_FIR_144[ table_index ][ 0 ] ); res_Q15 = SKP_SMLABB( res_Q15, buf_ptr[ 1 ], SKP_Silk_resampler_frac_FIR_144[ table_index ][ 1 ] ); res_Q15 = SKP_SMLABB( res_Q15, buf_ptr[ 2 ], SKP_Silk_resampler_frac_FIR_144[ table_index ][ 2 ] ); res_Q15 = SKP_SMLABB( res_Q15, buf_ptr[ 3 ], SKP_Silk_resampler_frac_FIR_144[ 143 - table_index ][ 2 ] ); res_Q15 = SKP_SMLABB( res_Q15, buf_ptr[ 4 ], SKP_Silk_resampler_frac_FIR_144[ 143 - table_index ][ 1 ] ); res_Q15 = SKP_SMLABB( res_Q15, buf_ptr[ 5 ], SKP_Silk_resampler_frac_FIR_144[ 143 - table_index ][ 0 ] ); *out++ = (SKP_int16)SKP_SAT16( SKP_RSHIFT_ROUND( res_Q15, 15 ) ); } in += nSamplesIn; inLen -= nSamplesIn; if( inLen > 0 ) { /* More iterations to do; copy last part of filtered signal to beginning of buffer */ SKP_memcpy( buf, &buf[ nSamplesIn << S->input2x ], RESAMPLER_ORDER_FIR_144 * sizeof( SKP_int32 ) ); } else { break; } } /* Copy last part of filtered signal to the state for the next call */ SKP_memcpy( S->sFIR, &buf[nSamplesIn << S->input2x ], RESAMPLER_ORDER_FIR_144 * sizeof( SKP_int32 ) ); }
/* Inverse filter of SKP_Silk_LPC_synthesis_filter */ void SKP_Silk_LPC_analysis_filter( const SKP_int16 *in, /* I: Input signal */ const SKP_int16 *B, /* I: MA prediction coefficients, Q12 [order] */ SKP_int16 *S, /* I/O: State vector [order] */ SKP_int16 *out, /* O: Output signal */ const SKP_int32 len, /* I: Signal length */ const SKP_int32 Order /* I: Filter order */ ) { SKP_int k, j, idx, Order_half = SKP_RSHIFT( Order, 1 ); SKP_int32 Btmp, B_align_Q12[ SigProc_MAX_ORDER_LPC >> 1 ], out32_Q12, out32; SKP_int16 SA, SB; /* Order must be even */ SKP_assert( 2 * Order_half == Order ); /* Combine two A_Q12 values and ensure 32-bit alignment */ for( k = 0; k < Order_half; k++ ) { idx = SKP_SMULBB( 2, k ); B_align_Q12[ k ] = ( ( (SKP_int32)B[ idx ] ) & 0x0000ffff ) | SKP_LSHIFT( (SKP_int32)B[ idx + 1 ], 16 ); } /* S[] values are in Q0 */ for( k = 0; k < len; k++ ) { SA = S[ 0 ]; out32_Q12 = 0; for( j = 0; j < ( Order_half - 1 ); j++ ) { idx = SKP_SMULBB( 2, j ) + 1; /* Multiply-add two prediction coefficients for each loop */ Btmp = B_align_Q12[ j ]; SB = S[ idx ]; S[ idx ] = SA; out32_Q12 = SKP_SMLABB( out32_Q12, SA, Btmp ); out32_Q12 = SKP_SMLABT( out32_Q12, SB, Btmp ); SA = S[ idx + 1 ]; S[ idx + 1 ] = SB; } /* Unrolled loop: epilog */ Btmp = B_align_Q12[ Order_half - 1 ]; SB = S[ Order - 1 ]; S[ Order - 1 ] = SA; out32_Q12 = SKP_SMLABB( out32_Q12, SA, Btmp ); out32_Q12 = SKP_SMLABT( out32_Q12, SB, Btmp ); /* Subtract prediction */ out32_Q12 = SKP_SUB_SAT32( SKP_LSHIFT( (SKP_int32)in[ k ], 12 ), out32_Q12 ); /* Scale to Q0 */ out32 = SKP_RSHIFT_ROUND( out32_Q12, 12 ); /* Saturate output */ out[ k ] = (SKP_int16)SKP_SAT16( out32 ); /* Move input line */ S[ 0 ] = in[ k ]; } }
void SKP_Silk_MA_Prediction_Q13( const SKP_int16 *in, /* I: input signal */ const SKP_int16 *B, /* I: MA prediction coefficients, Q13 [order] */ SKP_int32 *S, /* I/O: state vector [order] */ SKP_int16 *out, /* O: output signal */ SKP_int32 len, /* I: signal length */ SKP_int32 order /* I: filter order */ ) { SKP_int k, d, in16; SKP_int32 out32, B32; if( ( order & 1 ) == 0 && (SKP_int32)( (SKP_int_ptr_size)B & 3 ) == 0 ) { /* Even order and 4-byte aligned coefficient array */ /* NOTE: the code below loads two int16 values in an int32, and multiplies each using the */ /* SMLABB and SMLABT instructions. On a big-endian CPU the two int16 variables would be */ /* loaded in reverse order and the code will give the wrong result. In that case swapping */ /* the SMLABB and SMLABT instructions should solve the problem. */ for( k = 0; k < len; k++ ) { in16 = in[ k ]; out32 = SKP_LSHIFT( in16, 13 ) - S[ 0 ]; out32 = SKP_RSHIFT_ROUND( out32, 13 ); for( d = 0; d < order - 2; d += 2 ) { B32 = *( (SKP_int32*)&B[ d ] ); /* read two coefficients at once */ S[ d ] = SKP_SMLABB( S[ d + 1 ], in16, B32 ); S[ d + 1 ] = SKP_SMLABT( S[ d + 2 ], in16, B32 ); } B32 = *( (SKP_int32*)&B[ d ] ); /* read two coefficients at once */ S[ order - 2 ] = SKP_SMLABB( S[ order - 1 ], in16, B32 ); S[ order - 1 ] = SKP_SMULBT( in16, B32 ); /* Limit */ out[ k ] = (SKP_int16)SKP_SAT16( out32 ); } } else { /* Odd order or not 4-byte aligned coefficient array */ for( k = 0; k < len; k++ ) { in16 = in[ k ]; out32 = SKP_LSHIFT( in16, 13 ) - S[ 0 ]; out32 = SKP_RSHIFT_ROUND( out32, 13 ); for( d = 0; d < order - 1; d++ ) { S[ d ] = SKP_SMLABB( S[ d + 1 ], in16, B[ d ] ); } S[ order - 1 ] = SKP_SMULBB( in16, B[ order - 1 ] ); /* Limit */ out[ k ] = (SKP_int16)SKP_SAT16( out32 ); } } }
/* Compute quantization errors for an LPC_order element input vector for a VQ codebook */ void silk_NLSF_VQ( SKP_int32 err_Q26[], /* O Quantization errors [K] */ const SKP_int16 in_Q15[], /* I Input vectors to be quantized [LPC_order] */ const SKP_uint8 pCB_Q8[], /* I Codebook vectors [K*LPC_order] */ const SKP_int K, /* I Number of codebook vectors */ const SKP_int LPC_order /* I Number of LPCs */ ) { SKP_int i, m; SKP_int32 diff_Q15, sum_error_Q30, sum_error_Q26; SKP_assert( LPC_order <= 16 ); SKP_assert( ( LPC_order & 1 ) == 0 ); /* Loop over codebook */ for( i = 0; i < K; i++ ) { sum_error_Q26 = 0; for( m = 0; m < LPC_order; m += 2 ) { /* Compute weighted squared quantization error for index m */ diff_Q15 = SKP_SUB_LSHIFT32( in_Q15[ m ], ( SKP_int32 )*pCB_Q8++, 7 ); // range: [ -32767 : 32767 ] sum_error_Q30 = SKP_SMULBB( diff_Q15, diff_Q15 ); /* Compute weighted squared quantization error for index m + 1 */ diff_Q15 = SKP_SUB_LSHIFT32( in_Q15[m + 1], ( SKP_int32 )*pCB_Q8++, 7 ); // range: [ -32767 : 32767 ] sum_error_Q30 = SKP_SMLABB( sum_error_Q30, diff_Q15, diff_Q15 ); sum_error_Q26 = SKP_ADD_RSHIFT32( sum_error_Q26, sum_error_Q30, 4 ); SKP_assert( sum_error_Q26 >= 0 ); SKP_assert( sum_error_Q30 >= 0 ); } err_Q26[ i ] = sum_error_Q26; } }
/* Decode mid/side predictors */ void silk_stereo_decode_pred( ec_dec *psRangeDec, /* I/O Compressor data structure */ opus_int *decode_only_mid, /* O Flag that only mid channel has been coded */ opus_int32 pred_Q13[] /* O Predictors */ ) { opus_int n, ix[ 2 ][ 3 ]; opus_int32 low_Q13, step_Q13; /* Entropy decoding */ n = ec_dec_icdf( psRangeDec, silk_stereo_pred_joint_iCDF, 8 ); ix[ 0 ][ 2 ] = SKP_DIV32_16( n, 5 ); ix[ 1 ][ 2 ] = n - 5 * ix[ 0 ][ 2 ]; for( n = 0; n < 2; n++ ) { ix[ n ][ 0 ] = ec_dec_icdf( psRangeDec, silk_uniform3_iCDF, 8 ); ix[ n ][ 1 ] = ec_dec_icdf( psRangeDec, silk_uniform5_iCDF, 8 ); } /* Dequantize */ for( n = 0; n < 2; n++ ) { ix[ n ][ 0 ] += 3 * ix[ n ][ 2 ]; low_Q13 = silk_stereo_pred_quant_Q13[ ix[ n ][ 0 ] ]; step_Q13 = SKP_SMULWB( silk_stereo_pred_quant_Q13[ ix[ n ][ 0 ] + 1 ] - low_Q13, SILK_FIX_CONST( 0.5 / STEREO_QUANT_SUB_STEPS, 16 ) ); pred_Q13[ n ] = SKP_SMLABB( low_Q13, step_Q13, 2 * ix[ n ][ 1 ] + 1 ); } /* Subtract second from first predictor (helps when actually applying these) */ pred_Q13[ 0 ] -= pred_Q13[ 1 ]; /* Decode flag that only mid channel is coded */ *decode_only_mid = ec_dec_icdf( psRangeDec, silk_stereo_only_code_mid_iCDF, 8 ); }
SKP_INLINE SKP_int16 *SKP_Silk_resampler_private_IIR_FIR_INTERPOL( SKP_int16 * out, SKP_int16 * buf, SKP_int32 max_index_Q16 , SKP_int32 index_increment_Q16 ){ SKP_int32 index_Q16, res_Q15; SKP_int16 *buf_ptr; SKP_int32 table_index; /* Interpolate upsampled signal and store in output array */ for( index_Q16 = 0; index_Q16 < max_index_Q16; index_Q16 += index_increment_Q16 ) { table_index = SKP_SMULWB( index_Q16 & 0xFFFF, 144 ); buf_ptr = &buf[ index_Q16 >> 16 ]; res_Q15 = SKP_SMULBB( buf_ptr[ 0 ], SKP_Silk_resampler_frac_FIR_144[ table_index ][ 0 ] ); res_Q15 = SKP_SMLABB( res_Q15, buf_ptr[ 1 ], SKP_Silk_resampler_frac_FIR_144[ table_index ][ 1 ] ); res_Q15 = SKP_SMLABB( res_Q15, buf_ptr[ 2 ], SKP_Silk_resampler_frac_FIR_144[ table_index ][ 2 ] ); res_Q15 = SKP_SMLABB( res_Q15, buf_ptr[ 3 ], SKP_Silk_resampler_frac_FIR_144[ 143 - table_index ][ 2 ] ); res_Q15 = SKP_SMLABB( res_Q15, buf_ptr[ 4 ], SKP_Silk_resampler_frac_FIR_144[ 143 - table_index ][ 1 ] ); res_Q15 = SKP_SMLABB( res_Q15, buf_ptr[ 5 ], SKP_Silk_resampler_frac_FIR_144[ 143 - table_index ][ 0 ] ); *out++ = (SKP_int16)SKP_SAT16( SKP_RSHIFT_ROUND( res_Q15, 15 ) ); } return out; }
opus_int32 silk_inner_prod_aligned( const opus_int16 *const inVec1, /* I input vector 1 */ const opus_int16 *const inVec2, /* I input vector 2 */ const opus_int len /* I vector lengths */ ) { opus_int i; opus_int32 sum = 0; for( i = 0; i < len; i++ ) { sum = SKP_SMLABB( sum, inVec1[ i ], inVec2[ i ] ); } return sum; }
/* SKP_Silk_prefilter. Prefilter for finding Quantizer input signal */ SKP_INLINE void SKP_Silk_prefilt_FIX( SKP_Silk_prefilter_state_FIX *P, /* I/O state */ SKP_int32 st_res_Q12[], /* I short term residual signal */ SKP_int16 xw[], /* O prefiltered signal */ SKP_int32 HarmShapeFIRPacked_Q12, /* I Harmonic shaping coeficients */ SKP_int Tilt_Q14, /* I Tilt shaping coeficient */ SKP_int32 LF_shp_Q14, /* I Low-frequancy shaping coeficients*/ SKP_int lag, /* I Lag for harmonic shaping */ SKP_int length /* I Length of signals */ ) { SKP_int i, idx, LTP_shp_buf_idx; SKP_int32 n_LTP_Q12, n_Tilt_Q10, n_LF_Q10; SKP_int32 sLF_MA_shp_Q12, sLF_AR_shp_Q12; SKP_int16 *LTP_shp_buf; /* To speed up use temp variables instead of using the struct */ LTP_shp_buf = P->sLTP_shp; LTP_shp_buf_idx = P->sLTP_shp_buf_idx; sLF_AR_shp_Q12 = P->sLF_AR_shp_Q12; sLF_MA_shp_Q12 = P->sLF_MA_shp_Q12; for( i = 0; i < length; i++ ) { if( lag > 0 ) { /* unrolled loop */ SKP_assert( HARM_SHAPE_FIR_TAPS == 3 ); idx = lag + LTP_shp_buf_idx; n_LTP_Q12 = SKP_SMULBB( LTP_shp_buf[ ( idx - HARM_SHAPE_FIR_TAPS / 2 - 1) & LTP_MASK ], HarmShapeFIRPacked_Q12 ); n_LTP_Q12 = SKP_SMLABT( n_LTP_Q12, LTP_shp_buf[ ( idx - HARM_SHAPE_FIR_TAPS / 2 ) & LTP_MASK ], HarmShapeFIRPacked_Q12 ); n_LTP_Q12 = SKP_SMLABB( n_LTP_Q12, LTP_shp_buf[ ( idx - HARM_SHAPE_FIR_TAPS / 2 + 1) & LTP_MASK ], HarmShapeFIRPacked_Q12 ); } else { n_LTP_Q12 = 0; } n_Tilt_Q10 = SKP_SMULWB( sLF_AR_shp_Q12, Tilt_Q14 ); n_LF_Q10 = SKP_SMLAWB( SKP_SMULWT( sLF_AR_shp_Q12, LF_shp_Q14 ), sLF_MA_shp_Q12, LF_shp_Q14 ); sLF_AR_shp_Q12 = SKP_SUB32( st_res_Q12[ i ], SKP_LSHIFT( n_Tilt_Q10, 2 ) ); sLF_MA_shp_Q12 = SKP_SUB32( sLF_AR_shp_Q12, SKP_LSHIFT( n_LF_Q10, 2 ) ); LTP_shp_buf_idx = ( LTP_shp_buf_idx - 1 ) & LTP_MASK; LTP_shp_buf[ LTP_shp_buf_idx ] = ( SKP_int16 )SKP_SAT16( SKP_RSHIFT_ROUND( sLF_MA_shp_Q12, 12 ) ); xw[i] = ( SKP_int16 )SKP_SAT16( SKP_RSHIFT_ROUND( SKP_SUB32( sLF_MA_shp_Q12, n_LTP_Q12 ), 12 ) ); } /* Copy temp variable back to state */ P->sLF_AR_shp_Q12 = sLF_AR_shp_Q12; P->sLF_MA_shp_Q12 = sLF_MA_shp_Q12; P->sLTP_shp_buf_idx = LTP_shp_buf_idx; }
/* Generic filter loop. Runs about 10..25% faster than the unrolled C implementation. */ SKP_INLINE void FILTER_LOOP_ORDER_ANY(SKP_int32 * S, const SKP_int16 * B, SKP_int16 in16, SKP_int32 order) { SKP_int d; /* Unroll for 4 elements */ for(d = 0; d < order - 4; d += 4) { S[d + 0] = SKP_SMLABB(S[d + 1], in16, B[d + 0]); S[d + 1] = SKP_SMLABB(S[d + 2], in16, B[d + 1]); S[d + 2] = SKP_SMLABB(S[d + 3], in16, B[d + 2]); S[d + 3] = SKP_SMLABB(S[d + 4], in16, B[d + 3]); } if(d < order - 2) { S[d + 0] = SKP_SMLABB(S[d + 1], in16, B[d + 0]); S[d + 1] = SKP_SMLABB(S[d + 2], in16, B[d + 1]); d += 2; } if(d == order - 2) S[d] = SKP_SMLABB(S[d + 1], in16, B[d]); S[order - 1] = SKP_SMULBB(in16, B[order - 1]); }
/* Rate-Distortion calculations for multiple input data vectors */ void SKP_Silk_NLSF_VQ_rate_distortion_FIX(int32_t * pRD_Q20, /* O Rate-distortion values [psNLSF_CBS->nVectors*N] */ const SKP_Silk_NLSF_CBS * psNLSF_CBS, /* I NLSF codebook stage struct */ const int *in_Q15, /* I Input vectors to be quantized */ const int *w_Q6, /* I Weight vector */ const int32_t * rate_acc_Q5, /* I Accumulated rates from previous stage */ const int mu_Q15, /* I Weight between weighted error and rate */ const int N, /* I Number of input vectors to be quantized */ const int LPC_order /* I LPC order */ ) { int i, n; int32_t *pRD_vec_Q20; /* Compute weighted quantization errors for all input vectors over one codebook stage */ SKP_Silk_NLSF_VQ_sum_error_FIX(pRD_Q20, in_Q15, w_Q6, psNLSF_CBS->CB_NLSF_Q15, N, psNLSF_CBS->nVectors, LPC_order); /* Loop over input vectors */ pRD_vec_Q20 = pRD_Q20; for (n = 0; n < N; n++) { /* Add rate cost to error for each codebook vector */ for (i = 0; i < psNLSF_CBS->nVectors; i++) { assert(rate_acc_Q5[n] + psNLSF_CBS->Rates_Q5[i] >= 0); assert(rate_acc_Q5[n] + psNLSF_CBS->Rates_Q5[i] <= int16_t_MAX); pRD_vec_Q20[i] = SKP_SMLABB(pRD_vec_Q20[i], rate_acc_Q5[n] + psNLSF_CBS->Rates_Q5[i], mu_Q15); assert(pRD_vec_Q20[i] >= 0); } pRD_vec_Q20 += psNLSF_CBS->nVectors; } }
/* Calculates correlation matrix X'*X */ void SKP_Silk_corrMatrix_FIX( const SKP_int16 *x, /* I x vector [L + order - 1] used to form data matrix X */ const SKP_int L, /* I Length of vectors */ const SKP_int order, /* I Max lag for correlation */ const SKP_int head_room, /* I Desired headroom */ SKP_int32 *XX, /* O Pointer to X'*X correlation matrix [ order x order ]*/ SKP_int *rshifts /* I/O Right shifts of correlations */ ) { SKP_int i, j, lag, rshifts_local, head_room_rshifts; SKP_int32 energy; const SKP_int16 *ptr1, *ptr2; /* Calculate energy to find shift used to fit in 32 bits */ SKP_Silk_sum_sqr_shift( &energy, &rshifts_local, x, L + order - 1 ); /* Add shifts to get the desired head room */ head_room_rshifts = SKP_max( head_room - SKP_Silk_CLZ32( energy ), 0 ); energy = SKP_RSHIFT32( energy, head_room_rshifts ); rshifts_local += head_room_rshifts; /* Calculate energy of first column (0) of X: X[:,0]'*X[:,0] */ /* Remove contribution of first order - 1 samples */ for( i = 0; i < order - 1; i++ ) { energy -= SKP_RSHIFT32( SKP_SMULBB( x[ i ], x[ i ] ), rshifts_local ); } if( rshifts_local < *rshifts ) { /* Adjust energy */ energy = SKP_RSHIFT32( energy, *rshifts - rshifts_local ); rshifts_local = *rshifts; } /* Calculate energy of remaining columns of X: X[:,j]'*X[:,j] */ /* Fill out the diagonal of the correlation matrix */ matrix_ptr( XX, 0, 0, order ) = energy; ptr1 = &x[ order - 1 ]; /* First sample of column 0 of X */ for( j = 1; j < order; j++ ) { energy = SKP_SUB32( energy, SKP_RSHIFT32( SKP_SMULBB( ptr1[ L - j ], ptr1[ L - j ] ), rshifts_local ) ); energy = SKP_ADD32( energy, SKP_RSHIFT32( SKP_SMULBB( ptr1[ -j ], ptr1[ -j ] ), rshifts_local ) ); matrix_ptr( XX, j, j, order ) = energy; } ptr2 = &x[ order - 2 ]; /* First sample of column 1 of X */ /* Calculate the remaining elements of the correlation matrix */ if( rshifts_local > 0 ) { /* Right shifting used */ for( lag = 1; lag < order; lag++ ) { /* Inner product of column 0 and column lag: X[:,0]'*X[:,lag] */ energy = 0; for( i = 0; i < L; i++ ) { energy += SKP_RSHIFT32( SKP_SMULBB( ptr1[ i ], ptr2[i] ), rshifts_local ); } /* Calculate remaining off diagonal: X[:,j]'*X[:,j + lag] */ matrix_ptr( XX, lag, 0, order ) = energy; matrix_ptr( XX, 0, lag, order ) = energy; for( j = 1; j < ( order - lag ); j++ ) { energy = SKP_SUB32( energy, SKP_RSHIFT32( SKP_SMULBB( ptr1[ L - j ], ptr2[ L - j ] ), rshifts_local ) ); energy = SKP_ADD32( energy, SKP_RSHIFT32( SKP_SMULBB( ptr1[ -j ], ptr2[ -j ] ), rshifts_local ) ); matrix_ptr( XX, lag + j, j, order ) = energy; matrix_ptr( XX, j, lag + j, order ) = energy; } ptr2--; /* Update pointer to first sample of next column (lag) in X */ } } else { for( lag = 1; lag < order; lag++ ) { /* Inner product of column 0 and column lag: X[:,0]'*X[:,lag] */ energy = SKP_Silk_inner_prod_aligned( ptr1, ptr2, L ); matrix_ptr( XX, lag, 0, order ) = energy; matrix_ptr( XX, 0, lag, order ) = energy; /* Calculate remaining off diagonal: X[:,j]'*X[:,j + lag] */ for( j = 1; j < ( order - lag ); j++ ) { energy = SKP_SUB32( energy, SKP_SMULBB( ptr1[ L - j ], ptr2[ L - j ] ) ); energy = SKP_SMLABB( energy, ptr1[ -j ], ptr2[ -j ] ); matrix_ptr( XX, lag + j, j, order ) = energy; matrix_ptr( XX, j, lag + j, order ) = energy; } ptr2--;/* Update pointer to first sample of next column (lag) in X */ } } *rshifts = rshifts_local; }
/* Find pitch lags */ void SKP_Silk_find_pitch_lags_FIX( SKP_Silk_encoder_state_FIX *psEnc, /* I/O encoder state */ SKP_Silk_encoder_control_FIX *psEncCtrl, /* I/O encoder control */ SKP_int16 res[], /* O residual */ const SKP_int16 x[] /* I Speech signal */ ) { SKP_Silk_predict_state_FIX *psPredSt = &psEnc->sPred; SKP_int buf_len, i, scale; SKP_int32 thrhld_Q15, res_nrg; const SKP_int16 *x_buf, *x_buf_ptr; SKP_int16 Wsig[ FIND_PITCH_LPC_WIN_MAX ], *Wsig_ptr; SKP_int32 auto_corr[ MAX_FIND_PITCH_LPC_ORDER + 1 ]; SKP_int16 rc_Q15[ MAX_FIND_PITCH_LPC_ORDER ]; SKP_int32 A_Q24[ MAX_FIND_PITCH_LPC_ORDER ]; SKP_int32 FiltState[ MAX_FIND_PITCH_LPC_ORDER ]; SKP_int16 A_Q12[ MAX_FIND_PITCH_LPC_ORDER ]; /******************************************/ /* Setup buffer lengths etc based on Fs */ /******************************************/ buf_len = SKP_ADD_LSHIFT( psEnc->sCmn.la_pitch, psEnc->sCmn.frame_length, 1 ); /* Safty check */ SKP_assert( buf_len >= psPredSt->pitch_LPC_win_length ); x_buf = x - psEnc->sCmn.frame_length; /*************************************/ /* Estimate LPC AR coefficients */ /*************************************/ /* Calculate windowed signal */ /* First LA_LTP samples */ x_buf_ptr = x_buf + buf_len - psPredSt->pitch_LPC_win_length; Wsig_ptr = Wsig; SKP_Silk_apply_sine_window_new( Wsig_ptr, x_buf_ptr, 1, psEnc->sCmn.la_pitch ); /* Middle un - windowed samples */ Wsig_ptr += psEnc->sCmn.la_pitch; x_buf_ptr += psEnc->sCmn.la_pitch; SKP_memcpy( Wsig_ptr, x_buf_ptr, ( psPredSt->pitch_LPC_win_length - SKP_LSHIFT( psEnc->sCmn.la_pitch, 1 ) ) * sizeof( SKP_int16 ) ); /* Last LA_LTP samples */ Wsig_ptr += psPredSt->pitch_LPC_win_length - SKP_LSHIFT( psEnc->sCmn.la_pitch, 1 ); x_buf_ptr += psPredSt->pitch_LPC_win_length - SKP_LSHIFT( psEnc->sCmn.la_pitch, 1 ); SKP_Silk_apply_sine_window_new( Wsig_ptr, x_buf_ptr, 2, psEnc->sCmn.la_pitch ); /* Calculate autocorrelation sequence */ SKP_Silk_autocorr( auto_corr, &scale, Wsig, psPredSt->pitch_LPC_win_length, psEnc->sCmn.pitchEstimationLPCOrder + 1 ); /* Add white noise, as fraction of energy */ auto_corr[ 0 ] = SKP_SMLAWB( auto_corr[ 0 ], auto_corr[ 0 ], SKP_FIX_CONST( FIND_PITCH_WHITE_NOISE_FRACTION, 16 ) ); /* Calculate the reflection coefficients using schur */ res_nrg = SKP_Silk_schur( rc_Q15, auto_corr, psEnc->sCmn.pitchEstimationLPCOrder ); /* Prediction gain */ psEncCtrl->predGain_Q16 = SKP_DIV32_varQ( auto_corr[ 0 ], SKP_max_int( res_nrg, 1 ), 16 ); /* Convert reflection coefficients to prediction coefficients */ SKP_Silk_k2a( A_Q24, rc_Q15, psEnc->sCmn.pitchEstimationLPCOrder ); /* Convert From 32 bit Q24 to 16 bit Q12 coefs */ for( i = 0; i < psEnc->sCmn.pitchEstimationLPCOrder; i++ ) { A_Q12[ i ] = ( SKP_int16 )SKP_SAT16( SKP_RSHIFT( A_Q24[ i ], 12 ) ); } /* Do BWE */ SKP_Silk_bwexpander( A_Q12, psEnc->sCmn.pitchEstimationLPCOrder, SKP_FIX_CONST( FIND_PITCH_BANDWITH_EXPANSION, 16 ) ); /*****************************************/ /* LPC analysis filtering */ /*****************************************/ SKP_memset( FiltState, 0, psEnc->sCmn.pitchEstimationLPCOrder * sizeof( SKP_int32 ) ); /* Not really necessary, but Valgrind will complain otherwise */ SKP_Silk_MA_Prediction( x_buf, A_Q12, FiltState, res, buf_len, psEnc->sCmn.pitchEstimationLPCOrder ); SKP_memset( res, 0, psEnc->sCmn.pitchEstimationLPCOrder * sizeof( SKP_int16 ) ); /* Threshold for pitch estimator */ thrhld_Q15 = SKP_FIX_CONST( 0.45, 15 ); thrhld_Q15 = SKP_SMLABB( thrhld_Q15, SKP_FIX_CONST( -0.004, 15 ), psEnc->sCmn.pitchEstimationLPCOrder ); thrhld_Q15 = SKP_SMLABB( thrhld_Q15, SKP_FIX_CONST( -0.1, 7 ), psEnc->speech_activity_Q8 ); thrhld_Q15 = SKP_SMLABB( thrhld_Q15, SKP_FIX_CONST( 0.15, 15 ), psEnc->sCmn.prev_sigtype ); thrhld_Q15 = SKP_SMLAWB( thrhld_Q15, SKP_FIX_CONST( -0.1, 16 ), psEncCtrl->input_tilt_Q15 ); thrhld_Q15 = SKP_SAT16( thrhld_Q15 ); /*****************************************/ /* Call pitch estimator */ /*****************************************/ psEncCtrl->sCmn.sigtype = SKP_Silk_pitch_analysis_core( res, psEncCtrl->sCmn.pitchL, &psEncCtrl->sCmn.lagIndex, &psEncCtrl->sCmn.contourIndex, &psEnc->LTPCorr_Q15, psEnc->sCmn.prevLag, psEnc->sCmn.pitchEstimationThreshold_Q16, ( SKP_int16 )thrhld_Q15, psEnc->sCmn.fs_kHz, psEnc->sCmn.pitchEstimationComplexity, SKP_FALSE ); }
void SKP_Silk_prefilter_FIX( SKP_Silk_encoder_state_FIX *psEnc, /* I/O Encoder state FIX */ const SKP_Silk_encoder_control_FIX *psEncCtrl, /* I Encoder control FIX */ SKP_int16 xw[], /* O Weighted signal */ const SKP_int16 x[] /* I Speech signal */ ) { SKP_Silk_prefilter_state_FIX *P = &psEnc->sPrefilt; SKP_int j, k, lag; SKP_int32 tmp_32; const SKP_int16 *AR1_shp_Q13; const SKP_int16 *px; SKP_int16 *pxw; SKP_int HarmShapeGain_Q12, Tilt_Q14; SKP_int32 HarmShapeFIRPacked_Q12, LF_shp_Q14; SKP_int32 x_filt_Q12[ MAX_FRAME_LENGTH / NB_SUBFR ]; SKP_int16 st_res[ ( MAX_FRAME_LENGTH / NB_SUBFR ) + MAX_SHAPE_LPC_ORDER ]; SKP_int16 B_Q12[ 2 ]; /* Setup pointers */ px = x; pxw = xw; lag = P->lagPrev; for( k = 0; k < NB_SUBFR; k++ ) { /* Update Variables that change per sub frame */ if( psEncCtrl->sCmn.sigtype == SIG_TYPE_VOICED ) { lag = psEncCtrl->sCmn.pitchL[ k ]; } /* Noise shape parameters */ HarmShapeGain_Q12 = SKP_SMULWB( psEncCtrl->HarmShapeGain_Q14[ k ], 16384 - psEncCtrl->HarmBoost_Q14[ k ] ); SKP_assert( HarmShapeGain_Q12 >= 0 ); HarmShapeFIRPacked_Q12 = SKP_RSHIFT( HarmShapeGain_Q12, 2 ); HarmShapeFIRPacked_Q12 |= SKP_LSHIFT( ( SKP_int32 )SKP_RSHIFT( HarmShapeGain_Q12, 1 ), 16 ); Tilt_Q14 = psEncCtrl->Tilt_Q14[ k ]; LF_shp_Q14 = psEncCtrl->LF_shp_Q14[ k ]; AR1_shp_Q13 = &psEncCtrl->AR1_Q13[ k * MAX_SHAPE_LPC_ORDER ]; /* Short term FIR filtering*/ SKP_Silk_warped_LPC_analysis_filter_FIX( P->sAR_shp, st_res, AR1_shp_Q13, px, psEnc->sCmn.warping_Q16, psEnc->sCmn.subfr_length, psEnc->sCmn.shapingLPCOrder ); /* reduce (mainly) low frequencies during harmonic emphasis */ B_Q12[ 0 ] = SKP_RSHIFT_ROUND( psEncCtrl->GainsPre_Q14[ k ], 2 ); tmp_32 = SKP_SMLABB( SKP_FIX_CONST( INPUT_TILT, 26 ), psEncCtrl->HarmBoost_Q14[ k ], HarmShapeGain_Q12 ); /* Q26 */ tmp_32 = SKP_SMLABB( tmp_32, psEncCtrl->coding_quality_Q14, SKP_FIX_CONST( HIGH_RATE_INPUT_TILT, 12 ) ); /* Q26 */ tmp_32 = SKP_SMULWB( tmp_32, -psEncCtrl->GainsPre_Q14[ k ] ); /* Q24 */ tmp_32 = SKP_RSHIFT_ROUND( tmp_32, 12 ); /* Q12 */ B_Q12[ 1 ]= SKP_SAT16( tmp_32 ); x_filt_Q12[ 0 ] = SKP_SMLABB( SKP_SMULBB( st_res[ 0 ], B_Q12[ 0 ] ), P->sHarmHP, B_Q12[ 1 ] ); for( j = 1; j < psEnc->sCmn.subfr_length; j++ ) { x_filt_Q12[ j ] = SKP_SMLABB( SKP_SMULBB( st_res[ j ], B_Q12[ 0 ] ), st_res[ j - 1 ], B_Q12[ 1 ] ); } P->sHarmHP = st_res[ psEnc->sCmn.subfr_length - 1 ]; SKP_Silk_prefilt_FIX( P, x_filt_Q12, pxw, HarmShapeFIRPacked_Q12, Tilt_Q14, LF_shp_Q14, lag, psEnc->sCmn.subfr_length ); px += psEnc->sCmn.subfr_length; pxw += psEnc->sCmn.subfr_length; } P->lagPrev = psEncCtrl->sCmn.pitchL[ NB_SUBFR - 1 ]; }
/* Find pitch lags */ void SKP_Silk_find_pitch_lags_FIX( SKP_Silk_encoder_state_FIX *psEnc, /* I/O encoder state */ SKP_Silk_encoder_control_FIX *psEncCtrl, /* I/O encoder control */ SKP_int16 res[], /* O residual */ const SKP_int16 x[] /* I Speech signal */ ) { SKP_Silk_predict_state_FIX *psPredSt = &psEnc->sPred; SKP_int buf_len, i; SKP_int32 scale; SKP_int32 thrhld_Q15; const SKP_int16 *x_buf, *x_buf_ptr; SKP_int16 Wsig[ FIND_PITCH_LPC_WIN_MAX ], *Wsig_ptr; SKP_int32 auto_corr[ FIND_PITCH_LPC_ORDER_MAX + 1 ]; SKP_int16 rc_Q15[ FIND_PITCH_LPC_ORDER_MAX ]; SKP_int32 A_Q24[ FIND_PITCH_LPC_ORDER_MAX ]; SKP_int32 FiltState[ FIND_PITCH_LPC_ORDER_MAX ]; SKP_int16 A_Q12[ FIND_PITCH_LPC_ORDER_MAX ]; /******************************************/ /* Setup buffer lengths etc based of Fs. */ /******************************************/ buf_len = SKP_ADD_LSHIFT( psEnc->sCmn.la_pitch, psEnc->sCmn.frame_length, 1 ); /* Safty check */ SKP_assert( buf_len >= psPredSt->pitch_LPC_win_length ); x_buf = x - psEnc->sCmn.frame_length; /*************************************/ /* Estimate LPC AR coeficients */ /*************************************/ /* Calculate windowed signal */ /* First LA_LTP samples */ x_buf_ptr = x_buf + buf_len - psPredSt->pitch_LPC_win_length; Wsig_ptr = Wsig; SKP_Silk_apply_sine_window( Wsig_ptr, x_buf_ptr, 1, psEnc->sCmn.la_pitch ); /* Middle un - windowed samples */ Wsig_ptr += psEnc->sCmn.la_pitch; x_buf_ptr += psEnc->sCmn.la_pitch; SKP_memcpy( Wsig_ptr, x_buf_ptr, ( psPredSt->pitch_LPC_win_length - SKP_LSHIFT( psEnc->sCmn.la_pitch, 1 ) ) * sizeof( SKP_int16 ) ); /* Last LA_LTP samples */ Wsig_ptr += psPredSt->pitch_LPC_win_length - SKP_LSHIFT( psEnc->sCmn.la_pitch, 1 ); x_buf_ptr += psPredSt->pitch_LPC_win_length - SKP_LSHIFT( psEnc->sCmn.la_pitch, 1 ); SKP_Silk_apply_sine_window( Wsig_ptr, x_buf_ptr, 2, psEnc->sCmn.la_pitch ); /* Calculate autocorrelation sequence */ SKP_Silk_autocorr( auto_corr, &scale, Wsig, psPredSt->pitch_LPC_win_length, psEnc->sCmn.pitchEstimationLPCOrder + 1 ); /* add white noise, as fraction of energy */ auto_corr[ 0 ] = SKP_SMLAWB( auto_corr[ 0 ], auto_corr[ 0 ], FIND_PITCH_WHITE_NOISE_FRACTION_Q16 ); /* calculate the reflection coefficients using schur */ SKP_Silk_schur( rc_Q15, auto_corr, psEnc->sCmn.pitchEstimationLPCOrder ); /* convert reflection coefficients to prediction coefficients */ SKP_Silk_k2a( A_Q24, rc_Q15, psEnc->sCmn.pitchEstimationLPCOrder ); /* Convert From 32 bit Q24 to 16 bit Q12 coefs */ for( i = 0; i < psEnc->sCmn.pitchEstimationLPCOrder; i++ ) { A_Q12[ i ] = ( SKP_int16 )SKP_SAT16( SKP_RSHIFT( A_Q24[ i ], 12 ) ); } /* Do BWE */ SKP_Silk_bwexpander( A_Q12, psEnc->sCmn.pitchEstimationLPCOrder, FIND_PITCH_BANDWITH_EXPANSION_Q16 ); /*****************************************/ /* LPC analysis filtering */ /*****************************************/ SKP_memset( FiltState, 0, psEnc->sCmn.pitchEstimationLPCOrder * sizeof( SKP_int16 ) ); SKP_Silk_MA_Prediction( x_buf, A_Q12, FiltState, res, buf_len, psEnc->sCmn.pitchEstimationLPCOrder ); SKP_memset( res, 0, psEnc->sCmn.pitchEstimationLPCOrder * sizeof( SKP_int16 ) ); /* Threshold for pitch estimator */ thrhld_Q15 = ( 1 << 14 ); // 0.5f in Q15 thrhld_Q15 = SKP_SMLABB( thrhld_Q15, -131, psEnc->sCmn.pitchEstimationLPCOrder ); thrhld_Q15 = SKP_SMLABB( thrhld_Q15, -13, ( SKP_int16 )SKP_Silk_SQRT_APPROX( SKP_LSHIFT( ( SKP_int32 )psEnc->speech_activity_Q8, 8 ) ) ); thrhld_Q15 = SKP_SMLABB( thrhld_Q15, 4587, psEnc->sCmn.prev_sigtype ); thrhld_Q15 = SKP_MLA( thrhld_Q15, -31, SKP_RSHIFT( psEncCtrl->input_tilt_Q15, 8 ) ); thrhld_Q15 = SKP_SAT16( thrhld_Q15 ); /*****************************************/ /* Call Pitch estimator */ /*****************************************/ psEncCtrl->sCmn.sigtype = SKP_Silk_pitch_analysis_core( res, psEncCtrl->sCmn.pitchL, &psEncCtrl->sCmn.lagIndex, &psEncCtrl->sCmn.contourIndex, &psEnc->LTPCorr_Q15, psEnc->sCmn.prevLag, psEnc->pitchEstimationThreshold_Q16, ( SKP_int16 )thrhld_Q15, psEnc->sCmn.fs_kHz, psEnc->sCmn.pitchEstimationComplexity ); }
/* Resamples input data with a factor 2/3 */ void SKP_Silk_resample_2_3_coarsest( SKP_int16 *out, /* O: Output signal */ SKP_int16 *S, /* I/O: Resampler state [ SigProc_Resample_2_3_coarsest_NUM_FIR_COEFS - 1 ] */ const SKP_int16 *in, /* I: Input signal */ const SKP_int frameLenIn, /* I: Number of input samples */ SKP_int16 *scratch /* I: Scratch memory [ frameLenIn + SigProc_Resample_2_3_coarsest_NUM_FIR_COEFS - 1 ] */ ) { SKP_int32 n, ind, interpol_ind, tmp, index_Q16; SKP_int16 *in_ptr; SKP_int frameLenOut; const SKP_int16 *interpol_ptr; /* Copy buffered samples to start of scratch */ SKP_memcpy( scratch, S, ( SigProc_Resample_2_3_coarsest_NUM_FIR_COEFS - 1 ) * sizeof( SKP_int16 ) ); /* Then append by the input signal */ SKP_memcpy( &scratch[ SigProc_Resample_2_3_coarsest_NUM_FIR_COEFS - 1 ], in, frameLenIn * sizeof( SKP_int16 ) ); frameLenOut = SKP_SMULWB( SKP_LSHIFT( (SKP_int32)frameLenIn, 1 ), 21846 ); // 21846_Q15 = (2/3)_Q0 rounded _up_ index_Q16 = 0; SKP_assert( frameLenIn == ( ( frameLenOut * 3 ) / 2 ) ); /* Interpolate */ for( n = frameLenOut; n > 0; n-- ) { /* Integer part */ ind = SKP_RSHIFT( index_Q16, 16 ); /* Pointer to buffered input */ in_ptr = scratch + ind; /* Fractional part */ interpol_ind = ( SKP_SMULWB( index_Q16, SigProc_Resample_2_3_coarsest_NUM_INTERPOLATORS ) & ( SigProc_Resample_2_3_coarsest_NUM_INTERPOLATORS - 1 ) ); /* Pointer to FIR taps */ interpol_ptr = SigProc_Resample_2_3_coarsest_INTERPOL[ interpol_ind ]; /* Interpolate: Hardcoded for 10 FIR taps */ SKP_assert( SigProc_Resample_2_3_coarsest_NUM_FIR_COEFS == 10 ); tmp = SKP_SMULBB( interpol_ptr[ 0 ], in_ptr[ 0 ] ); tmp = SKP_SMLABB( tmp, interpol_ptr[ 1 ], in_ptr[ 1 ] ); tmp = SKP_SMLABB( tmp, interpol_ptr[ 2 ], in_ptr[ 2 ] ); tmp = SKP_SMLABB( tmp, interpol_ptr[ 3 ], in_ptr[ 3 ] ); tmp = SKP_SMLABB( tmp, interpol_ptr[ 4 ], in_ptr[ 4 ] ); tmp = SKP_SMLABB( tmp, interpol_ptr[ 5 ], in_ptr[ 5 ] ); tmp = SKP_SMLABB( tmp, interpol_ptr[ 6 ], in_ptr[ 6 ] ); tmp = SKP_SMLABB( tmp, interpol_ptr[ 7 ], in_ptr[ 7 ] ); tmp = SKP_SMLABB( tmp, interpol_ptr[ 8 ], in_ptr[ 8 ] ); tmp = SKP_SMLABB( tmp, interpol_ptr[ 9 ], in_ptr[ 9 ] ); /* Round, saturate and store to output array */ *out++ = (SKP_int16)SKP_SAT16( SKP_RSHIFT_ROUND( tmp, 15 ) ); /* Update index */ index_Q16 += ( ( 1 << 16 ) + ( 1 << 15 ) ); // (3/2)_Q0; } /* Move last part of input signal to the sample buffer to prepare for the next call */ SKP_memcpy( S, &in[ frameLenIn - ( SigProc_Resample_2_3_coarsest_NUM_FIR_COEFS - 1 ) ], ( SigProc_Resample_2_3_coarsest_NUM_FIR_COEFS - 1 ) * sizeof( SKP_int16 ) ); }
void SKP_Silk_prefilter_FIX( SKP_Silk_encoder_state_FIX *psEnc, /* I/O Encoder state FIX */ const SKP_Silk_encoder_control_FIX *psEncCtrl, /* I Encoder control FIX */ SKP_int16 xw[], /* O Weighted signal */ const SKP_int16 x[] /* I Speech signal */ ) { SKP_Silk_prefilter_state_FIX *P = &psEnc->sPrefilt; SKP_int j, k, lag; SKP_int32 tmp_32; const SKP_int16 *AR1_shp_Q13; const SKP_int16 *px; SKP_int16 *pxw; SKP_int HarmShapeGain_Q12, Tilt_Q14; SKP_int32 HarmShapeFIRPacked_Q12, LF_shp_Q14; SKP_int32 x_filt_Q12[ MAX_FRAME_LENGTH / NB_SUBFR ]; SKP_int16 st_res[ ( MAX_FRAME_LENGTH / NB_SUBFR ) + MAX_SHAPE_LPC_ORDER ]; #if !defined(_SYSTEM_IS_BIG_ENDIAN) SKP_int32 B_Q12; #else SKP_int16 B_Q12[ 2 ]; #endif /* Setup pointers */ px = x; pxw = xw; lag = P->lagPrev; for( k = 0; k < NB_SUBFR; k++ ) { /* Update Variables that change per sub frame */ if( psEncCtrl->sCmn.sigtype == SIG_TYPE_VOICED ) { lag = psEncCtrl->sCmn.pitchL[ k ]; } /* Noise shape parameters */ HarmShapeGain_Q12 = SKP_SMULWB( psEncCtrl->HarmShapeGain_Q14[ k ], 16384 - psEncCtrl->HarmBoost_Q14[ k ] ); SKP_assert( HarmShapeGain_Q12 >= 0 ); HarmShapeFIRPacked_Q12 = SKP_RSHIFT( HarmShapeGain_Q12, 2 ); HarmShapeFIRPacked_Q12 |= SKP_LSHIFT( ( SKP_int32 )SKP_RSHIFT( HarmShapeGain_Q12, 1 ), 16 ); Tilt_Q14 = psEncCtrl->Tilt_Q14[ k ]; LF_shp_Q14 = psEncCtrl->LF_shp_Q14[ k ]; AR1_shp_Q13 = &psEncCtrl->AR1_Q13[ k * MAX_SHAPE_LPC_ORDER ]; /* Short term FIR filtering*/ SKP_Silk_warped_LPC_analysis_filter_FIX( P->sAR_shp, st_res, AR1_shp_Q13, px, psEnc->sCmn.warping_Q16, psEnc->sCmn.subfr_length, psEnc->sCmn.shapingLPCOrder ); /* reduce (mainly) low frequencies during harmonic emphasis */ #if !defined(_SYSTEM_IS_BIG_ENDIAN) /* NOTE: the code below loads two int16 values in an int32, and multiplies each using the */ /* SMLABB and SMLABT instructions. On a big-endian CPU the two int16 variables would be */ /* loaded in reverse order and the code will give the wrong result. In that case swapping */ /* the SMLABB and SMLABT instructions should solve the problem. */ B_Q12 = SKP_RSHIFT_ROUND( psEncCtrl->GainsPre_Q14[ k ], 2 ); tmp_32 = SKP_SMLABB( SKP_FIX_CONST( INPUT_TILT, 26 ), psEncCtrl->HarmBoost_Q14[ k ], HarmShapeGain_Q12 ); /* Q26 */ tmp_32 = SKP_SMLABB( tmp_32, psEncCtrl->coding_quality_Q14, SKP_FIX_CONST( HIGH_RATE_INPUT_TILT, 12 ) ); /* Q26 */ tmp_32 = SKP_SMULWB( tmp_32, -psEncCtrl->GainsPre_Q14[ k ] ); /* Q24 */ tmp_32 = SKP_RSHIFT_ROUND( tmp_32, 12 ); /* Q12 */ B_Q12 |= SKP_LSHIFT( SKP_SAT16( tmp_32 ), 16 ); x_filt_Q12[ 0 ] = SKP_SMLABT( SKP_SMULBB( st_res[ 0 ], B_Q12 ), P->sHarmHP, B_Q12 ); for( j = 1; j < psEnc->sCmn.subfr_length; j++ ) { x_filt_Q12[ j ] = SKP_SMLABT( SKP_SMULBB( st_res[ j ], B_Q12 ), st_res[ j - 1 ], B_Q12 ); } #else B_Q12[ 0 ] = SKP_RSHIFT_ROUND( psEncCtrl->GainsPre_Q14[ k ], 2 ); tmp_32 = SKP_SMLABB( SKP_FIX_CONST( INPUT_TILT, 26 ), psEncCtrl->HarmBoost_Q14[ k ], HarmShapeGain_Q12 ); /* Q26 */ tmp_32 = SKP_SMLABB( tmp_32, psEncCtrl->coding_quality_Q14, SKP_FIX_CONST( HIGH_RATE_INPUT_TILT, 12 ) ); /* Q26 */ tmp_32 = SKP_SMULWB( tmp_32, -psEncCtrl->GainsPre_Q14[ k ] ); /* Q24 */ tmp_32 = SKP_RSHIFT_ROUND( tmp_32, 12 ); /* Q12 */ B_Q12[ 1 ]= SKP_SAT16( tmp_32 ); x_filt_Q12[ 0 ] = SKP_SMLABB( SKP_SMULBB( st_res[ 0 ], B_Q12[ 0 ] ), P->sHarmHP, B_Q12[ 1 ] ); for( j = 1; j < psEnc->sCmn.subfr_length; j++ ) { x_filt_Q12[ j ] = SKP_SMLABB( SKP_SMULBB( st_res[ j ], B_Q12[ 0 ] ), st_res[ j - 1 ], B_Q12[ 1 ] ); } #endif P->sHarmHP = st_res[ psEnc->sCmn.subfr_length - 1 ]; SKP_Silk_prefilt_FIX( P, x_filt_Q12, pxw, HarmShapeFIRPacked_Q12, Tilt_Q14, LF_shp_Q14, lag, psEnc->sCmn.subfr_length ); px += psEnc->sCmn.subfr_length; pxw += psEnc->sCmn.subfr_length; } P->lagPrev = psEncCtrl->sCmn.pitchL[ NB_SUBFR - 1 ]; }
SKP_int SKP_Silk_VAD_GetSA_Q8( /* O Return value, 0 if success */ SKP_Silk_encoder_state *psEncC, /* I/O Encoder state */ const SKP_int16 pIn[] /* I PCM input */ ) { SKP_int SA_Q15, pSNR_dB_Q7, input_tilt; SKP_int decimated_framelength, dec_subframe_length, dec_subframe_offset, SNR_Q7, i, b, s; SKP_int32 sumSquared, smooth_coef_Q16; SKP_int16 HPstateTmp; SKP_int16 X[ VAD_N_BANDS ][ MAX_FRAME_LENGTH / 2 ]; SKP_int32 Xnrg[ VAD_N_BANDS ]; SKP_int32 NrgToNoiseRatio_Q8[ VAD_N_BANDS ]; SKP_int32 speech_nrg, x_tmp; SKP_int ret = 0; SKP_Silk_VAD_state *psSilk_VAD = &psEncC->sVAD; /* Safety checks */ SKP_assert( VAD_N_BANDS == 4 ); SKP_assert( MAX_FRAME_LENGTH >= psEncC->frame_length ); SKP_assert( psEncC->frame_length <= 512 ); SKP_assert( psEncC->frame_length == 8 * SKP_RSHIFT( psEncC->frame_length, 3 ) ); /***********************/ /* Filter and Decimate */ /***********************/ /* 0-8 kHz to 0-4 kHz and 4-8 kHz */ SKP_Silk_ana_filt_bank_1( pIn, &psSilk_VAD->AnaState[ 0 ], &X[ 0 ][ 0 ], &X[ 3 ][ 0 ], psEncC->frame_length ); /* 0-4 kHz to 0-2 kHz and 2-4 kHz */ SKP_Silk_ana_filt_bank_1( &X[ 0 ][ 0 ], &psSilk_VAD->AnaState1[ 0 ], &X[ 0 ][ 0 ], &X[ 2 ][ 0 ], SKP_RSHIFT( psEncC->frame_length, 1 ) ); /* 0-2 kHz to 0-1 kHz and 1-2 kHz */ SKP_Silk_ana_filt_bank_1( &X[ 0 ][ 0 ], &psSilk_VAD->AnaState2[ 0 ], &X[ 0 ][ 0 ], &X[ 1 ][ 0 ], SKP_RSHIFT( psEncC->frame_length, 2 ) ); /*********************************************/ /* HP filter on lowest band (differentiator) */ /*********************************************/ decimated_framelength = SKP_RSHIFT( psEncC->frame_length, 3 ); X[ 0 ][ decimated_framelength - 1 ] = SKP_RSHIFT( X[ 0 ][ decimated_framelength - 1 ], 1 ); HPstateTmp = X[ 0 ][ decimated_framelength - 1 ]; for( i = decimated_framelength - 1; i > 0; i-- ) { X[ 0 ][ i - 1 ] = SKP_RSHIFT( X[ 0 ][ i - 1 ], 1 ); X[ 0 ][ i ] -= X[ 0 ][ i - 1 ]; } X[ 0 ][ 0 ] -= psSilk_VAD->HPstate; psSilk_VAD->HPstate = HPstateTmp; /*************************************/ /* Calculate the energy in each band */ /*************************************/ for( b = 0; b < VAD_N_BANDS; b++ ) { /* Find the decimated framelength in the non-uniformly divided bands */ decimated_framelength = SKP_RSHIFT( psEncC->frame_length, SKP_min_int( VAD_N_BANDS - b, VAD_N_BANDS - 1 ) ); /* Split length into subframe lengths */ dec_subframe_length = SKP_RSHIFT( decimated_framelength, VAD_INTERNAL_SUBFRAMES_LOG2 ); dec_subframe_offset = 0; /* Compute energy per sub-frame */ /* initialize with summed energy of last subframe */ Xnrg[ b ] = psSilk_VAD->XnrgSubfr[ b ]; for( s = 0; s < VAD_INTERNAL_SUBFRAMES; s++ ) { sumSquared = 0; for( i = 0; i < dec_subframe_length; i++ ) { /* The energy will be less than dec_subframe_length * ( SKP_int16_MIN / 8 ) ^ 2. */ /* Therefore we can accumulate with no risk of overflow (unless dec_subframe_length > 128) */ x_tmp = SKP_RSHIFT( X[ b ][ i + dec_subframe_offset ], 3 ); sumSquared = SKP_SMLABB( sumSquared, x_tmp, x_tmp ); /* Safety check */ SKP_assert( sumSquared >= 0 ); } /* Add/saturate summed energy of current subframe */ if( s < VAD_INTERNAL_SUBFRAMES - 1 ) { Xnrg[ b ] = SKP_ADD_POS_SAT32( Xnrg[ b ], sumSquared ); } else { /* Look-ahead subframe */ Xnrg[ b ] = SKP_ADD_POS_SAT32( Xnrg[ b ], SKP_RSHIFT( sumSquared, 1 ) ); } dec_subframe_offset += dec_subframe_length; } psSilk_VAD->XnrgSubfr[ b ] = sumSquared; } /********************/ /* Noise estimation */ /********************/ SKP_Silk_VAD_GetNoiseLevels( &Xnrg[ 0 ], psSilk_VAD ); /***********************************************/ /* Signal-plus-noise to noise ratio estimation */ /***********************************************/ sumSquared = 0; input_tilt = 0; for( b = 0; b < VAD_N_BANDS; b++ ) { speech_nrg = Xnrg[ b ] - psSilk_VAD->NL[ b ]; if( speech_nrg > 0 ) { /* Divide, with sufficient resolution */ if( ( Xnrg[ b ] & 0xFF800000 ) == 0 ) { NrgToNoiseRatio_Q8[ b ] = SKP_DIV32( SKP_LSHIFT( Xnrg[ b ], 8 ), psSilk_VAD->NL[ b ] + 1 ); } else { NrgToNoiseRatio_Q8[ b ] = SKP_DIV32( Xnrg[ b ], SKP_RSHIFT( psSilk_VAD->NL[ b ], 8 ) + 1 ); } /* Convert to log domain */ SNR_Q7 = SKP_Silk_lin2log( NrgToNoiseRatio_Q8[ b ] ) - 8 * 128; /* Sum-of-squares */ sumSquared = SKP_SMLABB( sumSquared, SNR_Q7, SNR_Q7 ); /* Q14 */ /* Tilt measure */ if( speech_nrg < ( 1 << 20 ) ) { /* Scale down SNR value for small subband speech energies */ SNR_Q7 = SKP_SMULWB( SKP_LSHIFT( SKP_Silk_SQRT_APPROX( speech_nrg ), 6 ), SNR_Q7 ); } input_tilt = SKP_SMLAWB( input_tilt, tiltWeights[ b ], SNR_Q7 ); } else { NrgToNoiseRatio_Q8[ b ] = 256; } } /* Mean-of-squares */ sumSquared = SKP_DIV32_16( sumSquared, VAD_N_BANDS ); /* Q14 */ /* Root-mean-square approximation, scale to dBs, and write to output pointer */ pSNR_dB_Q7 = ( SKP_int16 )( 3 * SKP_Silk_SQRT_APPROX( sumSquared ) ); /* Q7 */ /*********************************/ /* Speech Probability Estimation */ /*********************************/ SA_Q15 = SKP_Silk_sigm_Q15( SKP_SMULWB( VAD_SNR_FACTOR_Q16, pSNR_dB_Q7 ) - VAD_NEGATIVE_OFFSET_Q5 ); /**************************/ /* Frequency Tilt Measure */ /**************************/ psEncC->input_tilt_Q15 = SKP_LSHIFT( SKP_Silk_sigm_Q15( input_tilt ) - 16384, 1 ); /**************************************************/ /* Scale the sigmoid output based on power levels */ /**************************************************/ speech_nrg = 0; for( b = 0; b < VAD_N_BANDS; b++ ) { /* Accumulate signal-without-noise energies, higher frequency bands have more weight */ speech_nrg += ( b + 1 ) * SKP_RSHIFT( Xnrg[ b ] - psSilk_VAD->NL[ b ], 4 ); } /* Power scaling */ if( speech_nrg <= 0 ) { SA_Q15 = SKP_RSHIFT( SA_Q15, 1 ); } else if( speech_nrg < 32768 ) { if( psEncC->frame_length == 10 * psEncC->fs_kHz ) { speech_nrg = SKP_LSHIFT_SAT32( speech_nrg, 16 ); } else { speech_nrg = SKP_LSHIFT_SAT32( speech_nrg, 15 ); } /* square-root */ speech_nrg = SKP_Silk_SQRT_APPROX( speech_nrg ); SA_Q15 = SKP_SMULWB( 32768 + speech_nrg, SA_Q15 ); } /* Copy the resulting speech activity in Q8 */ psEncC->speech_activity_Q8 = SKP_min_int( SKP_RSHIFT( SA_Q15, 7 ), SKP_uint8_MAX ); /***********************************/ /* Energy Level and SNR estimation */ /***********************************/ /* Smoothing coefficient */ smooth_coef_Q16 = SKP_SMULWB( VAD_SNR_SMOOTH_COEF_Q18, SKP_SMULWB( SA_Q15, SA_Q15 ) ); if( psEncC->frame_length == 10 * psEncC->fs_kHz ) { smooth_coef_Q16 >>= 1; }
/* amplitude of monic warped coefficients by using bandwidth expansion on the true coefficients */ SKP_INLINE void limit_warped_coefs( SKP_int32 *coefs_syn_Q24, SKP_int32 *coefs_ana_Q24, SKP_int lambda_Q16, SKP_int32 limit_Q24, SKP_int order ) { SKP_int i, iter, ind = 0; SKP_int32 tmp, maxabs_Q24, chirp_Q16, gain_syn_Q16, gain_ana_Q16; SKP_int32 nom_Q16, den_Q24; /* Convert to monic coefficients */ lambda_Q16 = -lambda_Q16; for( i = order - 1; i > 0; i-- ) { coefs_syn_Q24[ i - 1 ] = SKP_SMLAWB( coefs_syn_Q24[ i - 1 ], coefs_syn_Q24[ i ], lambda_Q16 ); coefs_ana_Q24[ i - 1 ] = SKP_SMLAWB( coefs_ana_Q24[ i - 1 ], coefs_ana_Q24[ i ], lambda_Q16 ); } lambda_Q16 = -lambda_Q16; nom_Q16 = SKP_SMLAWB( SKP_FIX_CONST( 1.0, 16 ), -lambda_Q16, lambda_Q16 ); den_Q24 = SKP_SMLAWB( SKP_FIX_CONST( 1.0, 24 ), coefs_syn_Q24[ 0 ], lambda_Q16 ); gain_syn_Q16 = SKP_DIV32_varQ( nom_Q16, den_Q24, 24 ); den_Q24 = SKP_SMLAWB( SKP_FIX_CONST( 1.0, 24 ), coefs_ana_Q24[ 0 ], lambda_Q16 ); gain_ana_Q16 = SKP_DIV32_varQ( nom_Q16, den_Q24, 24 ); for( i = 0; i < order; i++ ) { coefs_syn_Q24[ i ] = SKP_SMULWW( gain_syn_Q16, coefs_syn_Q24[ i ] ); coefs_ana_Q24[ i ] = SKP_SMULWW( gain_ana_Q16, coefs_ana_Q24[ i ] ); } for( iter = 0; iter < 10; iter++ ) { /* Find maximum absolute value */ maxabs_Q24 = -1; for( i = 0; i < order; i++ ) { tmp = SKP_max( SKP_abs_int32( coefs_syn_Q24[ i ] ), SKP_abs_int32( coefs_ana_Q24[ i ] ) ); if( tmp > maxabs_Q24 ) { maxabs_Q24 = tmp; ind = i; } } if( maxabs_Q24 <= limit_Q24 ) { /* Coefficients are within range - done */ return; } /* Convert back to true warped coefficients */ for( i = 1; i < order; i++ ) { coefs_syn_Q24[ i - 1 ] = SKP_SMLAWB( coefs_syn_Q24[ i - 1 ], coefs_syn_Q24[ i ], lambda_Q16 ); coefs_ana_Q24[ i - 1 ] = SKP_SMLAWB( coefs_ana_Q24[ i - 1 ], coefs_ana_Q24[ i ], lambda_Q16 ); } gain_syn_Q16 = SKP_INVERSE32_varQ( gain_syn_Q16, 32 ); gain_ana_Q16 = SKP_INVERSE32_varQ( gain_ana_Q16, 32 ); for( i = 0; i < order; i++ ) { coefs_syn_Q24[ i ] = SKP_SMULWW( gain_syn_Q16, coefs_syn_Q24[ i ] ); coefs_ana_Q24[ i ] = SKP_SMULWW( gain_ana_Q16, coefs_ana_Q24[ i ] ); } /* Apply bandwidth expansion */ chirp_Q16 = SKP_FIX_CONST( 0.99, 16 ) - SKP_DIV32_varQ( SKP_SMULWB( maxabs_Q24 - limit_Q24, SKP_SMLABB( SKP_FIX_CONST( 0.8, 10 ), SKP_FIX_CONST( 0.1, 10 ), iter ) ), SKP_MUL( maxabs_Q24, ind + 1 ), 22 ); SKP_Silk_bwexpander_32( coefs_syn_Q24, order, chirp_Q16 ); SKP_Silk_bwexpander_32( coefs_ana_Q24, order, chirp_Q16 ); /* Convert to monic warped coefficients */ lambda_Q16 = -lambda_Q16; for( i = order - 1; i > 0; i-- ) { coefs_syn_Q24[ i - 1 ] = SKP_SMLAWB( coefs_syn_Q24[ i - 1 ], coefs_syn_Q24[ i ], lambda_Q16 ); coefs_ana_Q24[ i - 1 ] = SKP_SMLAWB( coefs_ana_Q24[ i - 1 ], coefs_ana_Q24[ i ], lambda_Q16 ); } lambda_Q16 = -lambda_Q16; nom_Q16 = SKP_SMLAWB( SKP_FIX_CONST( 1.0, 16 ), -lambda_Q16, lambda_Q16 ); den_Q24 = SKP_SMLAWB( SKP_FIX_CONST( 1.0, 24 ), coefs_syn_Q24[ 0 ], lambda_Q16 ); gain_syn_Q16 = SKP_DIV32_varQ( nom_Q16, den_Q24, 24 ); den_Q24 = SKP_SMLAWB( SKP_FIX_CONST( 1.0, 24 ), coefs_ana_Q24[ 0 ], lambda_Q16 ); gain_ana_Q16 = SKP_DIV32_varQ( nom_Q16, den_Q24, 24 ); for( i = 0; i < order; i++ ) { coefs_syn_Q24[ i ] = SKP_SMULWW( gain_syn_Q16, coefs_syn_Q24[ i ] ); coefs_ana_Q24[ i ] = SKP_SMULWW( gain_ana_Q16, coefs_ana_Q24[ i ] ); } } SKP_assert( 0 ); }
/* Find pitch lags */ void silk_find_pitch_lags_FIX( silk_encoder_state_FIX *psEnc, /* I/O encoder state */ silk_encoder_control_FIX *psEncCtrl, /* I/O encoder control */ opus_int16 res[], /* O residual */ const opus_int16 x[] /* I Speech signal */ ) { opus_int buf_len, i, scale; opus_int32 thrhld_Q15, res_nrg; const opus_int16 *x_buf, *x_buf_ptr; opus_int16 Wsig[ FIND_PITCH_LPC_WIN_MAX ], *Wsig_ptr; opus_int32 auto_corr[ MAX_FIND_PITCH_LPC_ORDER + 1 ]; opus_int16 rc_Q15[ MAX_FIND_PITCH_LPC_ORDER ]; opus_int32 A_Q24[ MAX_FIND_PITCH_LPC_ORDER ]; opus_int16 A_Q12[ MAX_FIND_PITCH_LPC_ORDER ]; /******************************************/ /* Setup buffer lengths etc based on Fs */ /******************************************/ buf_len = psEnc->sCmn.la_pitch + psEnc->sCmn.frame_length + psEnc->sCmn.ltp_mem_length; /* Safty check */ SKP_assert( buf_len >= psEnc->sCmn.pitch_LPC_win_length ); x_buf = x - psEnc->sCmn.ltp_mem_length; /*************************************/ /* Estimate LPC AR coefficients */ /*************************************/ /* Calculate windowed signal */ /* First LA_LTP samples */ x_buf_ptr = x_buf + buf_len - psEnc->sCmn.pitch_LPC_win_length; Wsig_ptr = Wsig; silk_apply_sine_window( Wsig_ptr, x_buf_ptr, 1, psEnc->sCmn.la_pitch ); /* Middle un - windowed samples */ Wsig_ptr += psEnc->sCmn.la_pitch; x_buf_ptr += psEnc->sCmn.la_pitch; SKP_memcpy( Wsig_ptr, x_buf_ptr, ( psEnc->sCmn.pitch_LPC_win_length - SKP_LSHIFT( psEnc->sCmn.la_pitch, 1 ) ) * sizeof( opus_int16 ) ); /* Last LA_LTP samples */ Wsig_ptr += psEnc->sCmn.pitch_LPC_win_length - SKP_LSHIFT( psEnc->sCmn.la_pitch, 1 ); x_buf_ptr += psEnc->sCmn.pitch_LPC_win_length - SKP_LSHIFT( psEnc->sCmn.la_pitch, 1 ); silk_apply_sine_window( Wsig_ptr, x_buf_ptr, 2, psEnc->sCmn.la_pitch ); /* Calculate autocorrelation sequence */ silk_autocorr( auto_corr, &scale, Wsig, psEnc->sCmn.pitch_LPC_win_length, psEnc->sCmn.pitchEstimationLPCOrder + 1 ); /* Add white noise, as fraction of energy */ auto_corr[ 0 ] = SKP_SMLAWB( auto_corr[ 0 ], auto_corr[ 0 ], SILK_FIX_CONST( FIND_PITCH_WHITE_NOISE_FRACTION, 16 ) ) + 1; /* Calculate the reflection coefficients using schur */ res_nrg = silk_schur( rc_Q15, auto_corr, psEnc->sCmn.pitchEstimationLPCOrder ); /* Prediction gain */ psEncCtrl->predGain_Q16 = silk_DIV32_varQ( auto_corr[ 0 ], SKP_max_int( res_nrg, 1 ), 16 ); /* Convert reflection coefficients to prediction coefficients */ silk_k2a( A_Q24, rc_Q15, psEnc->sCmn.pitchEstimationLPCOrder ); /* Convert From 32 bit Q24 to 16 bit Q12 coefs */ for( i = 0; i < psEnc->sCmn.pitchEstimationLPCOrder; i++ ) { A_Q12[ i ] = ( opus_int16 )SKP_SAT16( SKP_RSHIFT( A_Q24[ i ], 12 ) ); } /* Do BWE */ silk_bwexpander( A_Q12, psEnc->sCmn.pitchEstimationLPCOrder, SILK_FIX_CONST( FIND_PITCH_BANDWITH_EXPANSION, 16 ) ); /*****************************************/ /* LPC analysis filtering */ /*****************************************/ silk_LPC_analysis_filter( res, x_buf, A_Q12, buf_len, psEnc->sCmn.pitchEstimationLPCOrder ); if( psEnc->sCmn.indices.signalType != TYPE_NO_VOICE_ACTIVITY && psEnc->sCmn.first_frame_after_reset == 0 ) { /* Threshold for pitch estimator */ thrhld_Q15 = SILK_FIX_CONST( 0.6, 15 ); thrhld_Q15 = SKP_SMLABB( thrhld_Q15, SILK_FIX_CONST( -0.004, 15 ), psEnc->sCmn.pitchEstimationLPCOrder ); thrhld_Q15 = SKP_SMLABB( thrhld_Q15, SILK_FIX_CONST( -0.1, 7 ), psEnc->sCmn.speech_activity_Q8 ); thrhld_Q15 = SKP_SMLABB( thrhld_Q15, SILK_FIX_CONST( -0.15, 15 ), SKP_RSHIFT( psEnc->sCmn.prevSignalType, 1 ) ); thrhld_Q15 = SKP_SMLAWB( thrhld_Q15, SILK_FIX_CONST( -0.1, 16 ), psEnc->sCmn.input_tilt_Q15 ); thrhld_Q15 = SKP_SAT16( thrhld_Q15 ); /*****************************************/ /* Call pitch estimator */ /*****************************************/ if( silk_pitch_analysis_core( res, psEncCtrl->pitchL, &psEnc->sCmn.indices.lagIndex, &psEnc->sCmn.indices.contourIndex, &psEnc->LTPCorr_Q15, psEnc->sCmn.prevLag, psEnc->sCmn.pitchEstimationThreshold_Q16, ( opus_int16 )thrhld_Q15, psEnc->sCmn.fs_kHz, psEnc->sCmn.pitchEstimationComplexity, psEnc->sCmn.nb_subfr ) == 0 ) { psEnc->sCmn.indices.signalType = TYPE_VOICED; } else { psEnc->sCmn.indices.signalType = TYPE_UNVOICED; } } else { SKP_memset( psEncCtrl->pitchL, 0, sizeof( psEncCtrl->pitchL ) ); psEnc->sCmn.indices.lagIndex = 0; psEnc->sCmn.indices.contourIndex = 0; psEnc->LTPCorr_Q15 = 0; } }