/* uses SMLAWB(), requiring armv5E and higher. */ SKP_int32 SKP_Silk_schur( /* O: Returns residual energy */ SKP_int16 *rc_Q15, /* O: reflection coefficients [order] Q15 */ const SKP_int32 *c, /* I: correlations [order+1] */ const SKP_int32 order /* I: prediction order */ ) { SKP_int k, n, lz; SKP_int32 C[ SKP_Silk_MAX_ORDER_LPC + 1 ][ 2 ]; SKP_int32 Ctmp1, Ctmp2, rc_tmp_Q15; /* Get number of leading zeros */ lz = SKP_Silk_CLZ32( c[ 0 ] ); /* Copy correlations and adjust level to Q30 */ if( lz < 2 ) { /* lz must be 1, so shift one to the right */ for( k = 0; k < order + 1; k++ ) { C[ k ][ 0 ] = C[ k ][ 1 ] = SKP_RSHIFT( c[ k ], 1 ); } } else if( lz > 2 ) { /* Shift to the left */ lz -= 2; for( k = 0; k < order + 1; k++ ) { C[ k ][ 0 ] = C[ k ][ 1 ] = SKP_LSHIFT( c[k], lz ); } } else { /* No need to shift */ for( k = 0; k < order + 1; k++ ) { C[ k ][ 0 ] = C[ k ][ 1 ] = c[ k ]; } } for( k = 0; k < order; k++ ) { /* Get reflection coefficient */ rc_tmp_Q15 = -SKP_DIV32_16( C[ k + 1 ][ 0 ], SKP_max_32( SKP_RSHIFT( C[ 0 ][ 1 ], 15 ), 1 ) ); /* Clip (shouldn't happen for properly conditioned inputs) */ rc_tmp_Q15 = SKP_SAT16( rc_tmp_Q15 ); /* Store */ rc_Q15[ k ] = (SKP_int16)rc_tmp_Q15; /* Update correlations */ for( n = 0; n < order - k; n++ ) { Ctmp1 = C[ n + k + 1 ][ 0 ]; Ctmp2 = C[ n ][ 1 ]; C[ n + k + 1 ][ 0 ] = SKP_SMLAWB( Ctmp1, SKP_LSHIFT( Ctmp2, 1 ), rc_tmp_Q15 ); C[ n ][ 1 ] = SKP_SMLAWB( Ctmp2, SKP_LSHIFT( Ctmp1, 1 ), rc_tmp_Q15 ); } } /* return residual energy */ return C[0][1]; }
/* Helper function, interpolates the filter taps */ SKP_INLINE void silk_LP_interpolate_filter_taps( SKP_int32 B_Q28[ TRANSITION_NB ], SKP_int32 A_Q28[ TRANSITION_NA ], const SKP_int ind, const SKP_int32 fac_Q16 ) { SKP_int nb, na; if( ind < TRANSITION_INT_NUM - 1 ) { if( fac_Q16 > 0 ) { if( fac_Q16 < 32768 ) { /* fac_Q16 is in range of a 16-bit int */ /* Piece-wise linear interpolation of B and A */ for( nb = 0; nb < TRANSITION_NB; nb++ ) { B_Q28[ nb ] = SKP_SMLAWB( silk_Transition_LP_B_Q28[ ind ][ nb ], silk_Transition_LP_B_Q28[ ind + 1 ][ nb ] - silk_Transition_LP_B_Q28[ ind ][ nb ], fac_Q16 ); } for( na = 0; na < TRANSITION_NA; na++ ) { A_Q28[ na ] = SKP_SMLAWB( silk_Transition_LP_A_Q28[ ind ][ na ], silk_Transition_LP_A_Q28[ ind + 1 ][ na ] - silk_Transition_LP_A_Q28[ ind ][ na ], fac_Q16 ); } } else { /* ( fac_Q16 - ( 1 << 16 ) ) is in range of a 16-bit int */ SKP_assert( fac_Q16 - ( 1 << 16 ) == SKP_SAT16( fac_Q16 - ( 1 << 16 ) ) ); /* Piece-wise linear interpolation of B and A */ for( nb = 0; nb < TRANSITION_NB; nb++ ) { B_Q28[ nb ] = SKP_SMLAWB( silk_Transition_LP_B_Q28[ ind + 1 ][ nb ], silk_Transition_LP_B_Q28[ ind + 1 ][ nb ] - silk_Transition_LP_B_Q28[ ind ][ nb ], fac_Q16 - ( 1 << 16 ) ); } for( na = 0; na < TRANSITION_NA; na++ ) { A_Q28[ na ] = SKP_SMLAWB( silk_Transition_LP_A_Q28[ ind + 1 ][ na ], silk_Transition_LP_A_Q28[ ind + 1 ][ na ] - silk_Transition_LP_A_Q28[ ind ][ na ], fac_Q16 - ( 1 << 16 ) ); } } } else { SKP_memcpy( B_Q28, silk_Transition_LP_B_Q28[ ind ], TRANSITION_NB * sizeof( SKP_int32 ) ); SKP_memcpy( A_Q28, silk_Transition_LP_A_Q28[ ind ], TRANSITION_NA * sizeof( SKP_int32 ) ); } } else { SKP_memcpy( B_Q28, silk_Transition_LP_B_Q28[ TRANSITION_INT_NUM - 1 ], TRANSITION_NB * sizeof( SKP_int32 ) ); SKP_memcpy( A_Q28, silk_Transition_LP_A_Q28[ TRANSITION_INT_NUM - 1 ], TRANSITION_NA * sizeof( SKP_int32 ) ); } }
/* Downsample by a factor 3, low quality */ void SKP_Silk_resampler_down3( SKP_int32 *S, /* I/O: State vector [ 8 ] */ SKP_int16 *out, /* O: Output signal [ floor(inLen/3) ] */ const SKP_int16 *in, /* I: Input signal [ inLen ] */ SKP_int32 inLen /* I: Number of input samples */ ) { SKP_int32 nSamplesIn, counter, res_Q6; SKP_int32 buf[ RESAMPLER_MAX_BATCH_SIZE_IN + ORDER_FIR ]; SKP_int32 *buf_ptr; /* Copy buffered samples to start of buffer */ SKP_memcpy( buf, S, ORDER_FIR * sizeof( SKP_int32 ) ); /* Iterate over blocks of frameSizeIn input samples */ while( 1 ) { nSamplesIn = SKP_min( inLen, RESAMPLER_MAX_BATCH_SIZE_IN ); /* Second-order AR filter (output in Q8) */ SKP_Silk_resampler_private_AR2( &S[ ORDER_FIR ], &buf[ ORDER_FIR ], in, SKP_Silk_Resampler_1_3_COEFS_LQ, nSamplesIn ); /* Interpolate filtered signal */ buf_ptr = buf; counter = nSamplesIn; while( counter > 2 ) { /* Inner product */ res_Q6 = SKP_SMULWB( SKP_ADD32( buf_ptr[ 0 ], buf_ptr[ 5 ] ), SKP_Silk_Resampler_1_3_COEFS_LQ[ 2 ] ); res_Q6 = SKP_SMLAWB( res_Q6, SKP_ADD32( buf_ptr[ 1 ], buf_ptr[ 4 ] ), SKP_Silk_Resampler_1_3_COEFS_LQ[ 3 ] ); res_Q6 = SKP_SMLAWB( res_Q6, SKP_ADD32( buf_ptr[ 2 ], buf_ptr[ 3 ] ), SKP_Silk_Resampler_1_3_COEFS_LQ[ 4 ] ); /* Scale down, saturate and store in output array */ *out++ = (SKP_int16)SKP_SAT16( SKP_RSHIFT_ROUND( res_Q6, 6 ) ); buf_ptr += 3; counter -= 3; } 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 ], ORDER_FIR * sizeof( SKP_int32 ) ); } else { break; } } /* Copy last part of filtered signal to the state for the next call */ SKP_memcpy( S, &buf[ nSamplesIn ], ORDER_FIR * sizeof( SKP_int32 ) ); }
/* Autocorrelations for a warped frequency axis */ void silk_warped_autocorrelation_FIX( opus_int32 *corr, /* O Result [order + 1] */ opus_int *scale, /* O Scaling of the correlation vector */ const opus_int16 *input, /* I Input data to correlate */ const opus_int warping_Q16, /* I Warping coefficient */ const opus_int length, /* I Length of input */ const opus_int order /* I Correlation order (even) */ ) { opus_int n, i, lsh; opus_int32 tmp1_QS, tmp2_QS; opus_int32 state_QS[ MAX_SHAPE_LPC_ORDER + 1 ] = { 0 }; opus_int64 corr_QC[ MAX_SHAPE_LPC_ORDER + 1 ] = { 0 }; /* Order must be even */ SKP_assert( ( order & 1 ) == 0 ); SKP_assert( 2 * QS - QC >= 0 ); /* Loop over samples */ for( n = 0; n < length; n++ ) { tmp1_QS = SKP_LSHIFT32( ( opus_int32 )input[ n ], QS ); /* Loop over allpass sections */ for( i = 0; i < order; i += 2 ) { /* Output of allpass section */ tmp2_QS = SKP_SMLAWB( state_QS[ i ], state_QS[ i + 1 ] - tmp1_QS, warping_Q16 ); state_QS[ i ] = tmp1_QS; corr_QC[ i ] += SKP_RSHIFT64( SKP_SMULL( tmp1_QS, state_QS[ 0 ] ), 2 * QS - QC ); /* Output of allpass section */ tmp1_QS = SKP_SMLAWB( state_QS[ i + 1 ], state_QS[ i + 2 ] - tmp2_QS, warping_Q16 ); state_QS[ i + 1 ] = tmp2_QS; corr_QC[ i + 1 ] += SKP_RSHIFT64( SKP_SMULL( tmp2_QS, state_QS[ 0 ] ), 2 * QS - QC ); } state_QS[ order ] = tmp1_QS; corr_QC[ order ] += SKP_RSHIFT64( SKP_SMULL( tmp1_QS, state_QS[ 0 ] ), 2 * QS - QC ); } lsh = silk_CLZ64( corr_QC[ 0 ] ) - 35; lsh = SKP_LIMIT( lsh, -12 - QC, 30 - QC ); *scale = -( QC + lsh ); SKP_assert( *scale >= -30 && *scale <= 12 ); if( lsh >= 0 ) { for( i = 0; i < order + 1; i++ ) { corr[ i ] = ( opus_int32 )SKP_CHECK_FIT32( SKP_LSHIFT64( corr_QC[ i ], lsh ) ); } } else { for( i = 0; i < order + 1; i++ ) { corr[ i ] = ( opus_int32 )SKP_CHECK_FIT32( SKP_RSHIFT64( corr_QC[ i ], -lsh ) ); } } SKP_assert( corr_QC[ 0 ] >= 0 ); // If breaking, decrease QC }
/* Convert adaptive Mid/Side representation to Left/Right stereo signal */ void silk_stereo_MS_to_LR( stereo_dec_state *state, /* I/O State */ opus_int16 x1[], /* I/O Left input signal, becomes mid signal */ opus_int16 x2[], /* I/O Right input signal, becomes side signal */ const opus_int32 pred_Q13[], /* I Predictors */ opus_int fs_kHz, /* I Samples rate (kHz) */ opus_int frame_length /* I Number of samples */ ) { opus_int n, denom_Q16, delta0_Q13, delta1_Q13; opus_int32 sum, diff, pred0_Q13, pred1_Q13; /* Buffering */ SKP_memcpy( x1, state->sMid, 2 * sizeof( opus_int16 ) ); SKP_memcpy( x2, state->sSide, 2 * sizeof( opus_int16 ) ); SKP_memcpy( state->sMid, &x1[ frame_length ], 2 * sizeof( opus_int16 ) ); SKP_memcpy( state->sSide, &x2[ frame_length ], 2 * sizeof( opus_int16 ) ); /* Interpolate predictors and add prediction to side channel */ pred0_Q13 = state->pred_prev_Q13[ 0 ]; pred1_Q13 = state->pred_prev_Q13[ 1 ]; denom_Q16 = SKP_DIV32_16( 1 << 16, STEREO_INTERP_LEN_MS * fs_kHz ); delta0_Q13 = SKP_RSHIFT_ROUND( SKP_SMULBB( pred_Q13[ 0 ] - state->pred_prev_Q13[ 0 ], denom_Q16 ), 16 ); delta1_Q13 = SKP_RSHIFT_ROUND( SKP_SMULBB( pred_Q13[ 1 ] - state->pred_prev_Q13[ 1 ], denom_Q16 ), 16 ); for( n = 0; n < STEREO_INTERP_LEN_MS * fs_kHz; n++ ) { pred0_Q13 += delta0_Q13; pred1_Q13 += delta1_Q13; sum = SKP_LSHIFT( SKP_ADD_LSHIFT( x1[ n ] + x1[ n + 2 ], x1[ n + 1 ], 1 ), 9 ); /* Q11 */ sum = SKP_SMLAWB( SKP_LSHIFT( ( opus_int32 )x2[ n + 1 ], 8 ), sum, pred0_Q13 ); /* Q8 */ sum = SKP_SMLAWB( sum, SKP_LSHIFT( ( opus_int32 )x1[ n + 1 ], 11 ), pred1_Q13 ); /* Q8 */ x2[ n + 1 ] = (opus_int16)SKP_SAT16( SKP_RSHIFT_ROUND( sum, 8 ) ); } pred0_Q13 = pred_Q13[ 0 ]; pred1_Q13 = pred_Q13[ 1 ]; for( n = STEREO_INTERP_LEN_MS * fs_kHz; n < frame_length; n++ ) { sum = SKP_LSHIFT( SKP_ADD_LSHIFT( x1[ n ] + x1[ n + 2 ], x1[ n + 1 ], 1 ), 9 ); /* Q11 */ sum = SKP_SMLAWB( SKP_LSHIFT( ( opus_int32 )x2[ n + 1 ], 8 ), sum, pred0_Q13 ); /* Q8 */ sum = SKP_SMLAWB( sum, SKP_LSHIFT( ( opus_int32 )x1[ n + 1 ], 11 ), pred1_Q13 ); /* Q8 */ x2[ n + 1 ] = (opus_int16)SKP_SAT16( SKP_RSHIFT_ROUND( sum, 8 ) ); } state->pred_prev_Q13[ 0 ] = pred_Q13[ 0 ]; state->pred_prev_Q13[ 1 ] = pred_Q13[ 1 ]; /* Convert to left/right signals */ for( n = 0; n < frame_length; n++ ) { sum = x1[ n + 1 ] + (opus_int32)x2[ n + 1 ]; diff = x1[ n + 1 ] - (opus_int32)x2[ n + 1 ]; x1[ n + 1 ] = (opus_int16)SKP_SAT16( sum ); x2[ n + 1 ] = (opus_int16)SKP_SAT16( diff ); } }
/* even order AR filter */ void SKP_Silk_LPC_synthesis_filter( const SKP_int16 *in, /* I: excitation signal */ const SKP_int16 *A_Q12, /* I: AR coefficients [Order], between -8_Q0 and 8_Q0 */ const SKP_int32 Gain_Q26, /* I: gain */ SKP_int32 *S, /* I/O: state vector [Order] */ SKP_int16 *out, /* O: output signal */ const SKP_int32 len, /* I: signal length */ const SKP_int Order /* I: filter order, must be even */ ) { SKP_int k, j, idx, Order_half = SKP_RSHIFT( Order, 1 ); SKP_int32 SA, SB, out32_Q10, out32; /* Order must be even */ SKP_assert( 2 * Order_half == Order ); /* S[] values are in Q14 */ for( k = 0; k < len; k++ ) { SA = S[ Order - 1 ]; out32_Q10 = 0; for( j = 0; j < ( Order_half - 1 ); j++ ) { idx = SKP_SMULBB( 2, j ) + 1; SB = S[ Order - 1 - idx ]; S[ Order - 1 - idx ] = SA; out32_Q10 = SKP_SMLAWB( out32_Q10, SA, A_Q12[ ( j << 1 ) ] ); out32_Q10 = SKP_SMLAWB( out32_Q10, SB, A_Q12[ ( j << 1 ) + 1 ] ); SA = S[ Order - 2 - idx ]; S[ Order - 2 - idx ] = SB; } /* unrolled loop: epilog */ SB = S[ 0 ]; S[ 0 ] = SA; out32_Q10 = SKP_SMLAWB( out32_Q10, SA, A_Q12[ Order - 2 ] ); out32_Q10 = SKP_SMLAWB( out32_Q10, SB, A_Q12[ Order - 1 ] ); /* apply gain to excitation signal and add to prediction */ out32_Q10 = SKP_ADD_SAT32( out32_Q10, SKP_SMULWB( Gain_Q26, in[ k ] ) ); /* scale to Q0 */ out32 = SKP_RSHIFT_ROUND( out32_Q10, 10 ); /* saturate output */ out[ k ] = ( SKP_int16 )SKP_SAT16( out32 ); /* move result into delay line */ S[ Order - 1 ] = SKP_LSHIFT_SAT32( out32_Q10, 4 ); } }
/* non-warped frequency scale. (So that it can be implemented with a minimum-phase monic filter.) */ SKP_INLINE SKP_int32 warped_gain( // gain in Q16 const SKP_int32 *coefs_Q24, SKP_int lambda_Q16, SKP_int order ) { SKP_int i; SKP_int32 gain_Q24; lambda_Q16 = -lambda_Q16; gain_Q24 = coefs_Q24[ order - 1 ]; for( i = order - 2; i >= 0; i-- ) { gain_Q24 = SKP_SMLAWB( coefs_Q24[ i ], gain_Q24, lambda_Q16 ); } gain_Q24 = SKP_SMLAWB( SKP_FIX_CONST( 1.0, 24 ), gain_Q24, -lambda_Q16 ); return SKP_INVERSE32_varQ( gain_Q24, 40 ); }
void SKP_Silk_resampler_private_ARMA4( SKP_int32 S[], /* I/O: State vector [ 4 ] */ SKP_int16 out[], /* O: Output signal */ const SKP_int16 in[], /* I: Input signal */ const SKP_int16 Coef[], /* I: ARMA coefficients [ 7 ] */ SKP_int32 len /* I: Signal length */ ) { SKP_int32 k; SKP_int32 in_Q8, out1_Q8, out2_Q8, X; for( k = 0; k < len; k++ ) { in_Q8 = SKP_LSHIFT32( (SKP_int32)in[ k ], 8 ); /* Outputs of first and second biquad */ out1_Q8 = SKP_ADD_LSHIFT32( in_Q8, S[ 0 ], 2 ); out2_Q8 = SKP_ADD_LSHIFT32( out1_Q8, S[ 2 ], 2 ); /* Update states, which are stored in Q6. Coefficients are in Q14 here */ X = SKP_SMLAWB( S[ 1 ], in_Q8, Coef[ 0 ] ); S[ 0 ] = SKP_SMLAWB( X, out1_Q8, Coef[ 2 ] ); X = SKP_SMLAWB( S[ 3 ], out1_Q8, Coef[ 1 ] ); S[ 2 ] = SKP_SMLAWB( X, out2_Q8, Coef[ 4 ] ); S[ 1 ] = SKP_SMLAWB( SKP_RSHIFT32( in_Q8, 2 ), out1_Q8, Coef[ 3 ] ); S[ 3 ] = SKP_SMLAWB( SKP_RSHIFT32( out1_Q8, 2 ), out2_Q8, Coef[ 5 ] ); /* Apply gain and store to output. The coefficient is in Q16 */ out[ k ] = (SKP_int16)SKP_SAT16( SKP_RSHIFT32( SKP_SMLAWB( 128, out2_Q8, Coef[ 6 ] ), 8 ) ); } }
/* Convert input to a log scale */ opus_int32 silk_lin2log( const opus_int32 inLin ) /* I: Input in linear scale */ { opus_int32 lz, frac_Q7; silk_CLZ_FRAC( inLin, &lz, &frac_Q7 ); /* Piece-wise parabolic approximation */ return SKP_LSHIFT( 31 - lz, 7 ) + SKP_SMLAWB( frac_Q7, SKP_MUL( frac_Q7, 128 - frac_Q7 ), 179 ); }
/* Compute weighted quantization errors for an LPC_order element input vector, over one codebook stage */ void SKP_Silk_NLSF_VQ_sum_error_FIX(int32_t * err_Q20, /* O Weighted quantization errors [N*K] */ const int *in_Q15, /* I Input vectors to be quantized [N*LPC_order] */ const int *w_Q6, /* I Weighting vectors [N*LPC_order] */ const int16_t * pCB_Q15, /* I Codebook vectors [K*LPC_order] */ const int N, /* I Number of input vectors */ const int K, /* I Number of codebook vectors */ const int LPC_order /* I Number of LPCs */ ) { int i, n, m; int32_t diff_Q15, sum_error, Wtmp_Q6; int32_t Wcpy_Q6[MAX_LPC_ORDER / 2]; const int16_t *cb_vec_Q15; assert(LPC_order <= 16); assert((LPC_order & 1) == 0); memzero(Wcpy_Q6, (MAX_LPC_ORDER / 2) * sizeof(int32_t)); /* Copy to local stack and pack two weights per int32 */ for (m = 0; m < SKP_RSHIFT(LPC_order, 1); m++) { Wcpy_Q6[m] = w_Q6[2 * m] | SKP_LSHIFT((int32_t) w_Q6[2 * m + 1], 16); } /* Loop over input vectors */ for (n = 0; n < N; n++) { /* Loop over codebook */ cb_vec_Q15 = pCB_Q15; for (i = 0; i < K; i++) { sum_error = 0; for (m = 0; m < LPC_order; m += 2) { /* Get two weights packed in an int32 */ Wtmp_Q6 = Wcpy_Q6[SKP_RSHIFT(m, 1)]; /* Compute weighted squared quantization error for index m */ diff_Q15 = in_Q15[m] - *cb_vec_Q15++; // range: [ -32767 : 32767 ] sum_error = SKP_SMLAWB(sum_error, SKP_SMULBB(diff_Q15, diff_Q15), Wtmp_Q6); /* Compute weighted squared quantization error for index m + 1 */ diff_Q15 = in_Q15[m + 1] - *cb_vec_Q15++; // range: [ -32767 : 32767 ] sum_error = SKP_SMLAWT(sum_error, SKP_SMULBB(diff_Q15, diff_Q15), Wtmp_Q6); } assert(sum_error >= 0); err_Q20[i] = sum_error; } err_Q20 += K; in_Q15 += LPC_order; } }
/* Convert input to a linear scale */ SKP_int32 silk_log2lin( const SKP_int32 inLog_Q7 ) /* I: Input on log scale */ { SKP_int32 out, frac_Q7; if( inLog_Q7 < 0 ) { return 0; } out = SKP_LSHIFT( 1, SKP_RSHIFT( inLog_Q7, 7 ) ); frac_Q7 = inLog_Q7 & 0x7F; if( inLog_Q7 < 2048 ) { /* Piece-wise parabolic approximation */ out = SKP_ADD_RSHIFT( out, SKP_MUL( out, SKP_SMLAWB( frac_Q7, SKP_MUL( frac_Q7, 128 - frac_Q7 ), -174 ) ), 7 ); } else { /* Piece-wise parabolic approximation */ out = SKP_MLA( out, SKP_RSHIFT( out, 7 ), SKP_SMLAWB( frac_Q7, SKP_MUL( frac_Q7, 128 - frac_Q7 ), -174 ) ); } return out; }
SKP_INLINE SKP_int16 *SKP_Silk_resampler_private_down_FIR_INTERPOL0( SKP_int16 *out, SKP_int32 *buf2, const SKP_int16 *FIR_Coefs, SKP_int32 max_index_Q16, SKP_int32 index_increment_Q16){ SKP_int32 index_Q16, res_Q6; SKP_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 + SKP_RSHIFT( index_Q16, 16 ); /* Inner product */ res_Q6 = SKP_SMULWB( SKP_ADD32( buf_ptr[ 0 ], buf_ptr[ 11 ] ), FIR_Coefs[ 0 ] ); res_Q6 = SKP_SMLAWB( res_Q6, SKP_ADD32( buf_ptr[ 1 ], buf_ptr[ 10 ] ), FIR_Coefs[ 1 ] ); res_Q6 = SKP_SMLAWB( res_Q6, SKP_ADD32( buf_ptr[ 2 ], buf_ptr[ 9 ] ), FIR_Coefs[ 2 ] ); res_Q6 = SKP_SMLAWB( res_Q6, SKP_ADD32( buf_ptr[ 3 ], buf_ptr[ 8 ] ), FIR_Coefs[ 3 ] ); res_Q6 = SKP_SMLAWB( res_Q6, SKP_ADD32( buf_ptr[ 4 ], buf_ptr[ 7 ] ), FIR_Coefs[ 4 ] ); res_Q6 = SKP_SMLAWB( res_Q6, SKP_ADD32( buf_ptr[ 5 ], buf_ptr[ 6 ] ), FIR_Coefs[ 5 ] ); /* Scale down, saturate and store in output array */ *out++ = (SKP_int16)SKP_SAT16( SKP_RSHIFT_ROUND( res_Q6, 6 ) ); } return out; }
/* 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; }
/* Second order ARMA filter, alternative implementation */ void SKP_Silk_biquad_alt( const SKP_int16 *in, /* I: Input signal */ const SKP_int32 *B_Q28, /* I: MA coefficients [3] */ const SKP_int32 *A_Q28, /* I: AR coefficients [2] */ SKP_int32 *S, /* I/O: State vector [2] */ SKP_int16 *out, /* O: Output signal */ const SKP_int32 len /* I: Signal length (must be even) */ ) { /* DIRECT FORM II TRANSPOSED (uses 2 element state vector) */ SKP_int k; SKP_int32 inval, A0_U_Q28, A0_L_Q28, A1_U_Q28, A1_L_Q28, out32_Q14; /* Negate A_Q28 values and split in two parts */ A0_L_Q28 = ( -A_Q28[ 0 ] ) & 0x00003FFF; /* lower part */ A0_U_Q28 = SKP_RSHIFT( -A_Q28[ 0 ], 14 ); /* upper part */ A1_L_Q28 = ( -A_Q28[ 1 ] ) & 0x00003FFF; /* lower part */ A1_U_Q28 = SKP_RSHIFT( -A_Q28[ 1 ], 14 ); /* upper part */ for( k = 0; k < len; k++ ) { /* S[ 0 ], S[ 1 ]: Q12 */ inval = in[ k ]; out32_Q14 = SKP_LSHIFT( SKP_SMLAWB( S[ 0 ], B_Q28[ 0 ], inval ), 2 ); S[ 0 ] = S[1] + SKP_RSHIFT_ROUND( SKP_SMULWB( out32_Q14, A0_L_Q28 ), 14 ); S[ 0 ] = SKP_SMLAWB( S[ 0 ], out32_Q14, A0_U_Q28 ); S[ 0 ] = SKP_SMLAWB( S[ 0 ], B_Q28[ 1 ], inval); S[ 1 ] = SKP_RSHIFT_ROUND( SKP_SMULWB( out32_Q14, A1_L_Q28 ), 14 ); S[ 1 ] = SKP_SMLAWB( S[ 1 ], out32_Q14, A1_U_Q28 ); S[ 1 ] = SKP_SMLAWB( S[ 1 ], B_Q28[ 2 ], inval ); /* Scale back to Q0 and saturate */ out[ k ] = (SKP_int16)SKP_SAT16( SKP_RSHIFT( out32_Q14 + (1<<14) - 1, 14 ) ); } }
/* Processing of gains */ void silk_process_gains_FIX( silk_encoder_state_FIX *psEnc, /* I/O Encoder state_FIX */ silk_encoder_control_FIX *psEncCtrl /* I/O Encoder control_FIX */ ) { silk_shape_state_FIX *psShapeSt = &psEnc->sShape; opus_int k; opus_int32 s_Q16, InvMaxSqrVal_Q16, gain, gain_squared, ResNrg, ResNrgPart, quant_offset_Q10; /* Gain reduction when LTP coding gain is high */ if( psEnc->sCmn.indices.signalType == TYPE_VOICED ) { /*s = -0.5f * SKP_sigmoid( 0.25f * ( psEncCtrl->LTPredCodGain - 12.0f ) ); */ s_Q16 = -silk_sigm_Q15( SKP_RSHIFT_ROUND( psEncCtrl->LTPredCodGain_Q7 - SILK_FIX_CONST( 12.0, 7 ), 4 ) ); for( k = 0; k < psEnc->sCmn.nb_subfr; k++ ) { psEncCtrl->Gains_Q16[ k ] = SKP_SMLAWB( psEncCtrl->Gains_Q16[ k ], psEncCtrl->Gains_Q16[ k ], s_Q16 ); } } /* Limit the quantized signal */ /* InvMaxSqrVal = pow( 2.0f, 0.33f * ( 21.0f - SNR_dB ) ) / subfr_length; */ InvMaxSqrVal_Q16 = SKP_DIV32_16( silk_log2lin( SKP_SMULWB( SILK_FIX_CONST( 21 + 16 / 0.33, 7 ) - psEnc->sCmn.SNR_dB_Q7, SILK_FIX_CONST( 0.33, 16 ) ) ), psEnc->sCmn.subfr_length ); for( k = 0; k < psEnc->sCmn.nb_subfr; k++ ) { /* Soft limit on ratio residual energy and squared gains */ ResNrg = psEncCtrl->ResNrg[ k ]; ResNrgPart = SKP_SMULWW( ResNrg, InvMaxSqrVal_Q16 ); if( psEncCtrl->ResNrgQ[ k ] > 0 ) { ResNrgPart = SKP_RSHIFT_ROUND( ResNrgPart, psEncCtrl->ResNrgQ[ k ] ); } else { if( ResNrgPart >= SKP_RSHIFT( SKP_int32_MAX, -psEncCtrl->ResNrgQ[ k ] ) ) { ResNrgPart = SKP_int32_MAX; } else { ResNrgPart = SKP_LSHIFT( ResNrgPart, -psEncCtrl->ResNrgQ[ k ] ); } } gain = psEncCtrl->Gains_Q16[ k ]; gain_squared = SKP_ADD_SAT32( ResNrgPart, SKP_SMMUL( gain, gain ) ); if( gain_squared < SKP_int16_MAX ) { /* recalculate with higher precision */ gain_squared = SKP_SMLAWW( SKP_LSHIFT( ResNrgPart, 16 ), gain, gain ); SKP_assert( gain_squared > 0 ); gain = silk_SQRT_APPROX( gain_squared ); /* Q8 */ gain = SKP_min( gain, SKP_int32_MAX >> 8 ); psEncCtrl->Gains_Q16[ k ] = SKP_LSHIFT_SAT32( gain, 8 ); /* Q16 */ } else {
/* Step up function, converts reflection coefficients to prediction coefficients */ void SKP_Silk_k2a( SKP_int32 *A_Q24, /* O: Prediction coefficients [order] Q24 */ const SKP_int16 *rc_Q15, /* I: Reflection coefficients [order] Q15 */ const SKP_int32 order /* I: Prediction order */ ) { SKP_int k, n; SKP_int32 Atmp[ SKP_Silk_MAX_ORDER_LPC ]; for( k = 0; k < order; k++ ) { for( n = 0; n < k; n++ ) { Atmp[ n ] = A_Q24[ n ]; } for( n = 0; n < k; n++ ) { A_Q24[ n ] = SKP_SMLAWB( A_Q24[ n ], SKP_LSHIFT( Atmp[ k - n - 1 ], 1 ), rc_Q15[ k ] ); } A_Q24[ k ] = -SKP_LSHIFT( (SKP_int32)rc_Q15[ k ], 9 ); } }
/* Second order AR filter with single delay elements */ void SKP_Silk_resampler_private_AR2( SKP_int32 S[], /* I/O: State vector [ 2 ] */ SKP_int32 out_Q8[], /* O: Output signal */ const SKP_int16 in[], /* I: Input signal */ const SKP_int16 A_Q14[], /* I: AR coefficients, Q14 */ SKP_int32 len /* I: Signal length */ ) { SKP_int32 k; SKP_int32 out32; for( k = 0; k < len; k++ ) { out32 = SKP_ADD_LSHIFT32( S[ 0 ], (SKP_int32)in[ k ], 8 ); out_Q8[ k ] = out32; out32 = SKP_LSHIFT( out32, 2 ); S[ 0 ] = SKP_SMLAWB( S[ 1 ], out32, A_Q14[ 0 ] ); S[ 1 ] = SKP_SMULWB( out32, A_Q14[ 1 ] ); } }
/* Upsample by a factor 4, Note: very low quality, only use with output sampling rates above 96 kHz. */ void SKP_Silk_resampler_private_up4( SKP_int32 *S, /* I/O: State vector [ 2 ] */ SKP_int16 *out, /* O: Output signal [ 4 * len ] */ const SKP_int16 *in, /* I: Input signal [ len ] */ SKP_int32 len /* I: Number of INPUT samples */ ) { SKP_int32 k; SKP_int32 in32, out32, Y, X; SKP_int16 out16; SKP_assert( SKP_Silk_resampler_up2_lq_0 > 0 ); SKP_assert( SKP_Silk_resampler_up2_lq_1 < 0 ); /* Internal variables and state are in Q10 format */ for( k = 0; k < len; k++ ) { /* Convert to Q10 */ in32 = SKP_LSHIFT( (SKP_int32)in[ k ], 10 ); /* All-pass section for even output sample */ Y = SKP_SUB32( in32, S[ 0 ] ); X = SKP_SMULWB( Y, SKP_Silk_resampler_up2_lq_0 ); out32 = SKP_ADD32( S[ 0 ], X ); S[ 0 ] = SKP_ADD32( in32, X ); /* Convert back to int16 and store to output */ out16 = (SKP_int16)SKP_SAT16( SKP_RSHIFT_ROUND( out32, 10 ) ); out[ 4 * k ] = out16; out[ 4 * k + 1 ] = out16; /* All-pass section for odd output sample */ Y = SKP_SUB32( in32, S[ 1 ] ); X = SKP_SMLAWB( Y, Y, SKP_Silk_resampler_up2_lq_1 ); out32 = SKP_ADD32( S[ 1 ], X ); S[ 1 ] = SKP_ADD32( in32, X ); /* Convert back to int16 and store to output */ out16 = (SKP_int16)SKP_SAT16( SKP_RSHIFT_ROUND( out32, 10 ) ); out[ 4 * k + 2 ] = out16; out[ 4 * k + 3 ] = out16; } }
/* Downsample by a factor 2, mediocre quality */ void SKP_Silk_resampler_down2( SKP_int32 *S, /* I/O: State vector [ 2 ] */ SKP_int16 *out, /* O: Output signal [ len ] */ const SKP_int16 *in, /* I: Input signal [ floor(len/2) ] */ SKP_int32 inLen /* I: Number of input samples */ ) { SKP_int32 k, len2 = SKP_RSHIFT32( inLen, 1 ); SKP_int32 in32, out32, Y, X; SKP_assert( SKP_Silk_resampler_down2_0 > 0 ); SKP_assert( SKP_Silk_resampler_down2_1 < 0 ); /* Internal variables and state are in Q10 format */ for( k = 0; k < len2; k++ ) { /* Convert to Q10 */ in32 = SKP_LSHIFT( (SKP_int32)in[ 2 * k ], 10 ); /* All-pass section for even input sample */ Y = SKP_SUB32( in32, S[ 0 ] ); X = SKP_SMLAWB( Y, Y, SKP_Silk_resampler_down2_1 ); out32 = SKP_ADD32( S[ 0 ], X ); S[ 0 ] = SKP_ADD32( in32, X ); /* Convert to Q10 */ in32 = SKP_LSHIFT( (SKP_int32)in[ 2 * k + 1 ], 10 ); /* All-pass section for odd input sample, and add to output of previous section */ Y = SKP_SUB32( in32, S[ 1 ] ); X = SKP_SMULWB( Y, SKP_Silk_resampler_down2_0 ); out32 = SKP_ADD32( out32, S[ 1 ] ); out32 = SKP_ADD32( out32, X ); S[ 1 ] = SKP_ADD32( in32, X ); /* Add, convert back to int16 and store to output */ out[ k ] = (SKP_int16)SKP_SAT16( SKP_RSHIFT_ROUND( out32, 11 ) ); } }
/* Predictive dequantizer for NLSF residuals */ void silk_NLSF_residual_dequant( /* O Returns RD value in Q30 */ opus_int16 x_Q10[], /* O Output [ order ] */ const opus_int8 indices[], /* I Quantization indices [ order ] */ const opus_uint8 pred_coef_Q8[], /* I Backward predictor coefs [ order ] */ const opus_int quant_step_size_Q16, /* I Quantization step size */ const opus_int16 order /* I Number of input values */ ) { opus_int i, out_Q10, pred_Q10; out_Q10 = 0; for( i = order-1; i >= 0; i-- ) { pred_Q10 = SKP_RSHIFT( SKP_SMULBB( out_Q10, (opus_int16)pred_coef_Q8[ i ] ), 8 ); out_Q10 = SKP_LSHIFT( indices[ i ], 10 ); if( out_Q10 > 0 ) { out_Q10 = SKP_SUB16( out_Q10, SILK_FIX_CONST( NLSF_QUANT_LEVEL_ADJ, 10 ) ); } else if( out_Q10 < 0 ) { out_Q10 = SKP_ADD16( out_Q10, SILK_FIX_CONST( NLSF_QUANT_LEVEL_ADJ, 10 ) ); } out_Q10 = SKP_SMLAWB( pred_Q10, out_Q10, quant_step_size_Q16 ); x_Q10[ i ] = out_Q10; } }
void SKP_Silk_warped_LPC_analysis_filter_FIX( SKP_int32 state[], /* I/O State [order + 1] */ SKP_int16 res[], /* O Residual signal [length] */ const SKP_int16 coef_Q13[], /* I Coefficients [order] */ const SKP_int16 input[], /* I Input signal [length] */ const SKP_int16 lambda_Q16, /* I Warping factor */ const SKP_int length, /* I Length of input signal */ const SKP_int order /* I Filter order (even) */ ) { SKP_int n, i; SKP_int32 acc_Q11, tmp1, tmp2; /* Order must be even */ SKP_assert( ( order & 1 ) == 0 ); for( n = 0; n < length; n++ ) { /* Output of lowpass section */ tmp2 = SKP_SMLAWB( state[ 0 ], state[ 1 ], lambda_Q16 ); state[ 0 ] = SKP_LSHIFT( input[ n ], 14 ); /* Output of allpass section */ tmp1 = SKP_SMLAWB( state[ 1 ], state[ 2 ] - tmp2, lambda_Q16 ); state[ 1 ] = tmp2; acc_Q11 = SKP_SMULWB( tmp2, coef_Q13[ 0 ] ); /* Loop over allpass sections */ for( i = 2; i < order; i += 2 ) { /* Output of allpass section */ tmp2 = SKP_SMLAWB( state[ i ], state[ i + 1 ] - tmp1, lambda_Q16 ); state[ i ] = tmp1; acc_Q11 = SKP_SMLAWB( acc_Q11, tmp1, coef_Q13[ i - 1 ] ); /* Output of allpass section */ tmp1 = SKP_SMLAWB( state[ i + 1 ], state[ i + 2 ] - tmp2, lambda_Q16 ); state[ i + 1 ] = tmp2; acc_Q11 = SKP_SMLAWB( acc_Q11, tmp2, coef_Q13[ i ] ); } state[ order ] = tmp1; acc_Q11 = SKP_SMLAWB( acc_Q11, tmp1, coef_Q13[ order - 1 ] ); res[ n ] = ( SKP_int16 )SKP_SAT16( ( SKP_int32 )input[ n ] - SKP_RSHIFT_ROUND( acc_Q11, 11 ) ); } }
/* Split signal into two decimated bands using first-order allpass filters */ void SKP_Silk_ana_filt_bank_1( const SKP_int16 *in, /* I: Input signal [N] */ SKP_int32 *S, /* I/O: State vector [2] */ SKP_int16 *outL, /* O: Low band [N/2] */ SKP_int16 *outH, /* O: High band [N/2] */ SKP_int32 *scratch, /* I: Scratch memory [3*N/2] */ // todo: remove - no longer used const SKP_int32 N /* I: Number of input samples */ ) { SKP_int k, N2 = SKP_RSHIFT( N, 1 ); SKP_int32 in32, X, Y, out_1, out_2; /* Internal variables and state are in Q10 format */ for( k = 0; k < N2; k++ ) { /* Convert to Q10 */ in32 = SKP_LSHIFT( (SKP_int32)in[ 2 * k ], 10 ); /* All-pass section for even input sample */ Y = SKP_SUB32( in32, S[ 0 ] ); X = SKP_SMLAWB( Y, Y, A_fb1_21[ 0 ] ); out_1 = SKP_ADD32( S[ 0 ], X ); S[ 0 ] = SKP_ADD32( in32, X ); /* Convert to Q10 */ in32 = SKP_LSHIFT( (SKP_int32)in[ 2 * k + 1 ], 10 ); /* All-pass section for odd input sample */ Y = SKP_SUB32( in32, S[ 1 ] ); X = SKP_SMULWB( Y, A_fb1_20[ 0 ] ); out_2 = SKP_ADD32( S[ 1 ], X ); S[ 1 ] = SKP_ADD32( in32, X ); /* Add/subtract, convert back to int16 and store to output */ outL[ k ] = (SKP_int16)SKP_SAT16( SKP_RSHIFT_ROUND( SKP_ADD32( out_2, out_1 ), 11 ) ); outH[ k ] = (SKP_int16)SKP_SAT16( SKP_RSHIFT_ROUND( SKP_SUB32( out_2, out_1 ), 11 ) ); } }
/* 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 ); }
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; }
/* High-pass filter with cutoff frequency adaptation based on pitch lag statistics */ void SKP_Silk_HP_variable_cutoff_FIX( SKP_Silk_encoder_state_FIX *psEnc, /* I/O Encoder state FIX */ SKP_Silk_encoder_control_FIX *psEncCtrl, /* I/O Encoder control FIX */ SKP_int16 *out, /* O high-pass filtered output signal */ const SKP_int16 *in /* I input signal */ ) { SKP_int quality_Q15; SKP_int32 B_Q28[ 3 ], A_Q28[ 2 ]; SKP_int32 Fc_Q19, r_Q28, r_Q22; SKP_int32 pitch_freq_Hz_Q16, pitch_freq_log_Q7, delta_freq_Q7; /*********************************************/ /* Estimate Low End of Pitch Frequency Range */ /*********************************************/ if( psEnc->sCmn.prev_sigtype == SIG_TYPE_VOICED ) { /* difference, in log domain */ pitch_freq_Hz_Q16 = SKP_DIV32_16( SKP_LSHIFT( SKP_MUL( psEnc->sCmn.fs_kHz, 1000 ), 16 ), psEnc->sCmn.prevLag ); pitch_freq_log_Q7 = SKP_Silk_lin2log( pitch_freq_Hz_Q16 ) - ( 16 << 7 ); //0x70 /* adjustment based on quality */ quality_Q15 = psEncCtrl->input_quality_bands_Q15[ 0 ]; pitch_freq_log_Q7 = SKP_SUB32( pitch_freq_log_Q7, SKP_SMULWB( SKP_SMULWB( SKP_LSHIFT( quality_Q15, 2 ), quality_Q15 ), pitch_freq_log_Q7 - SKP_LOG2_VARIABLE_HP_MIN_FREQ_Q7 ) ); pitch_freq_log_Q7 = SKP_ADD32( pitch_freq_log_Q7, SKP_RSHIFT( SKP_FIX_CONST( 0.6, 15 ) - quality_Q15, 9 ) ); //delta_freq = pitch_freq_log - psEnc->variable_HP_smth1; delta_freq_Q7 = pitch_freq_log_Q7 - SKP_RSHIFT( psEnc->variable_HP_smth1_Q15, 8 ); if( delta_freq_Q7 < 0 ) { /* less smoothing for decreasing pitch frequency, to track something close to the minimum */ delta_freq_Q7 = SKP_MUL( delta_freq_Q7, 3 ); } /* limit delta, to reduce impact of outliers */ delta_freq_Q7 = SKP_LIMIT_32( delta_freq_Q7, -SKP_FIX_CONST( VARIABLE_HP_MAX_DELTA_FREQ, 7 ), SKP_FIX_CONST( VARIABLE_HP_MAX_DELTA_FREQ, 7 ) ); /* update smoother */ psEnc->variable_HP_smth1_Q15 = SKP_SMLAWB( psEnc->variable_HP_smth1_Q15, SKP_MUL( SKP_LSHIFT( psEnc->speech_activity_Q8, 1 ), delta_freq_Q7 ), SKP_FIX_CONST( VARIABLE_HP_SMTH_COEF1, 16 ) ); } /* second smoother */ psEnc->variable_HP_smth2_Q15 = SKP_SMLAWB( psEnc->variable_HP_smth2_Q15, psEnc->variable_HP_smth1_Q15 - psEnc->variable_HP_smth2_Q15, SKP_FIX_CONST( VARIABLE_HP_SMTH_COEF2, 16 ) ); /* convert from log scale to Hertz */ psEncCtrl->pitch_freq_low_Hz = SKP_Silk_log2lin( SKP_RSHIFT( psEnc->variable_HP_smth2_Q15, 8 ) ); /* limit frequency range */ psEncCtrl->pitch_freq_low_Hz = SKP_LIMIT_32( psEncCtrl->pitch_freq_low_Hz, SKP_FIX_CONST( VARIABLE_HP_MIN_FREQ, 0 ), SKP_FIX_CONST( VARIABLE_HP_MAX_FREQ, 0 ) ); /********************************/ /* Compute Filter Coefficients */ /********************************/ /* compute cut-off frequency, in radians */ //Fc_num = (SKP_float)( 0.45f * 2.0f * 3.14159265359 * psEncCtrl->pitch_freq_low_Hz ); //Fc_denom = (SKP_float)( 1e3f * psEnc->sCmn.fs_kHz ); SKP_assert( psEncCtrl->pitch_freq_low_Hz <= SKP_int32_MAX / SKP_RADIANS_CONSTANT_Q19 ); Fc_Q19 = SKP_DIV32_16( SKP_SMULBB( SKP_RADIANS_CONSTANT_Q19, psEncCtrl->pitch_freq_low_Hz ), psEnc->sCmn.fs_kHz ); // range: 3704 - 27787, 11-15 bits SKP_assert( Fc_Q19 >= 3704 ); SKP_assert( Fc_Q19 <= 27787 ); r_Q28 = SKP_FIX_CONST( 1.0, 28 ) - SKP_MUL( SKP_FIX_CONST( 0.92, 9 ), Fc_Q19 ); SKP_assert( r_Q28 >= 255347779 ); SKP_assert( r_Q28 <= 266690872 ); /* b = r * [ 1; -2; 1 ]; */ /* a = [ 1; -2 * r * ( 1 - 0.5 * Fc^2 ); r^2 ]; */ B_Q28[ 0 ] = r_Q28; B_Q28[ 1 ] = SKP_LSHIFT( -r_Q28, 1 ); B_Q28[ 2 ] = r_Q28; // -r * ( 2 - Fc * Fc ); r_Q22 = SKP_RSHIFT( r_Q28, 6 ); A_Q28[ 0 ] = SKP_SMULWW( r_Q22, SKP_SMULWW( Fc_Q19, Fc_Q19 ) - SKP_FIX_CONST( 2.0, 22 ) ); A_Q28[ 1 ] = SKP_SMULWW( r_Q22, r_Q22 ); /********************************/ /* High-Pass Filter */ /********************************/ SKP_Silk_biquad_alt( in, B_Q28, A_Q28, psEnc->sCmn.In_HP_State, out, psEnc->sCmn.frame_length ); }
void SKP_Silk_noise_shape_analysis_FIX( SKP_Silk_encoder_state_FIX *psEnc, /* I/O Encoder state FIX */ SKP_Silk_encoder_control_FIX *psEncCtrl, /* I/O Encoder control FIX */ const SKP_int16 *pitch_res, /* I LPC residual from pitch analysis */ const SKP_int16 *x /* I Input signal [ frame_length + la_shape ] */ ) { SKP_Silk_shape_state_FIX *psShapeSt = &psEnc->sShape; SKP_int k, i, nSamples, Qnrg, b_Q14, warping_Q16, scale = 0; SKP_int32 SNR_adj_dB_Q7, HarmBoost_Q16, HarmShapeGain_Q16, Tilt_Q16, tmp32; SKP_int32 nrg, pre_nrg_Q30, log_energy_Q7, log_energy_prev_Q7, energy_variation_Q7; SKP_int32 delta_Q16, BWExp1_Q16, BWExp2_Q16, gain_mult_Q16, gain_add_Q16, strength_Q16, b_Q8; SKP_int32 auto_corr[ MAX_SHAPE_LPC_ORDER + 1 ]; SKP_int32 refl_coef_Q16[ MAX_SHAPE_LPC_ORDER ]; SKP_int32 AR1_Q24[ MAX_SHAPE_LPC_ORDER ]; SKP_int32 AR2_Q24[ MAX_SHAPE_LPC_ORDER ]; SKP_int16 x_windowed[ SHAPE_LPC_WIN_MAX ]; const SKP_int16 *x_ptr, *pitch_res_ptr; SKP_int32 sqrt_nrg[ NB_SUBFR ], Qnrg_vec[ NB_SUBFR ]; /* Point to start of first LPC analysis block */ x_ptr = x - psEnc->sCmn.la_shape; /****************/ /* CONTROL SNR */ /****************/ /* Reduce SNR_dB values if recent bitstream has exceeded TargetRate */ psEncCtrl->current_SNR_dB_Q7 = psEnc->SNR_dB_Q7 - SKP_SMULWB( SKP_LSHIFT( ( SKP_int32 )psEnc->BufferedInChannel_ms, 7 ), SKP_FIX_CONST( 0.05, 16 ) ); /* Reduce SNR_dB if inband FEC used */ if( psEnc->speech_activity_Q8 > SKP_FIX_CONST( LBRR_SPEECH_ACTIVITY_THRES, 8 ) ) { psEncCtrl->current_SNR_dB_Q7 -= SKP_RSHIFT( psEnc->inBandFEC_SNR_comp_Q8, 1 ); } /****************/ /* GAIN CONTROL */ /****************/ /* Input quality is the average of the quality in the lowest two VAD bands */ psEncCtrl->input_quality_Q14 = ( SKP_int )SKP_RSHIFT( ( SKP_int32 )psEncCtrl->input_quality_bands_Q15[ 0 ] + psEncCtrl->input_quality_bands_Q15[ 1 ], 2 ); /* Coding quality level, between 0.0_Q0 and 1.0_Q0, but in Q14 */ psEncCtrl->coding_quality_Q14 = SKP_RSHIFT( SKP_Silk_sigm_Q15( SKP_RSHIFT_ROUND( psEncCtrl->current_SNR_dB_Q7 - SKP_FIX_CONST( 18.0, 7 ), 4 ) ), 1 ); /* Reduce coding SNR during low speech activity */ b_Q8 = SKP_FIX_CONST( 1.0, 8 ) - psEnc->speech_activity_Q8; b_Q8 = SKP_SMULWB( SKP_LSHIFT( b_Q8, 8 ), b_Q8 ); SNR_adj_dB_Q7 = SKP_SMLAWB( psEncCtrl->current_SNR_dB_Q7, SKP_SMULBB( SKP_FIX_CONST( -BG_SNR_DECR_dB, 7 ) >> ( 4 + 1 ), b_Q8 ), // Q11 SKP_SMULWB( SKP_FIX_CONST( 1.0, 14 ) + psEncCtrl->input_quality_Q14, psEncCtrl->coding_quality_Q14 ) ); // Q12 if( psEncCtrl->sCmn.sigtype == SIG_TYPE_VOICED ) { /* Reduce gains for periodic signals */ SNR_adj_dB_Q7 = SKP_SMLAWB( SNR_adj_dB_Q7, SKP_FIX_CONST( HARM_SNR_INCR_dB, 8 ), psEnc->LTPCorr_Q15 ); } else { /* For unvoiced signals and low-quality input, adjust the quality slower than SNR_dB setting */ SNR_adj_dB_Q7 = SKP_SMLAWB( SNR_adj_dB_Q7, SKP_SMLAWB( SKP_FIX_CONST( 6.0, 9 ), -SKP_FIX_CONST( 0.4, 18 ), psEncCtrl->current_SNR_dB_Q7 ), SKP_FIX_CONST( 1.0, 14 ) - psEncCtrl->input_quality_Q14 ); } /*************************/ /* SPARSENESS PROCESSING */ /*************************/ /* Set quantizer offset */ if( psEncCtrl->sCmn.sigtype == SIG_TYPE_VOICED ) { /* Initally set to 0; may be overruled in process_gains(..) */ psEncCtrl->sCmn.QuantOffsetType = 0; psEncCtrl->sparseness_Q8 = 0; } else { /* Sparseness measure, based on relative fluctuations of energy per 2 milliseconds */ nSamples = SKP_LSHIFT( psEnc->sCmn.fs_kHz, 1 ); energy_variation_Q7 = 0; log_energy_prev_Q7 = 0; pitch_res_ptr = pitch_res; for( k = 0; k < FRAME_LENGTH_MS / 2; k++ ) { SKP_Silk_sum_sqr_shift( &nrg, &scale, pitch_res_ptr, nSamples ); nrg += SKP_RSHIFT( nSamples, scale ); // Q(-scale) log_energy_Q7 = SKP_Silk_lin2log( nrg ); if( k > 0 ) { energy_variation_Q7 += SKP_abs( log_energy_Q7 - log_energy_prev_Q7 ); } log_energy_prev_Q7 = log_energy_Q7; pitch_res_ptr += nSamples; } psEncCtrl->sparseness_Q8 = SKP_RSHIFT( SKP_Silk_sigm_Q15( SKP_SMULWB( energy_variation_Q7 - SKP_FIX_CONST( 5.0, 7 ), SKP_FIX_CONST( 0.1, 16 ) ) ), 7 ); /* Set quantization offset depending on sparseness measure */ if( psEncCtrl->sparseness_Q8 > SKP_FIX_CONST( SPARSENESS_THRESHOLD_QNT_OFFSET, 8 ) ) { psEncCtrl->sCmn.QuantOffsetType = 0; } else { psEncCtrl->sCmn.QuantOffsetType = 1; } /* Increase coding SNR for sparse signals */ SNR_adj_dB_Q7 = SKP_SMLAWB( SNR_adj_dB_Q7, SKP_FIX_CONST( SPARSE_SNR_INCR_dB, 15 ), psEncCtrl->sparseness_Q8 - SKP_FIX_CONST( 0.5, 8 ) ); } /*******************************/ /* Control bandwidth expansion */ /*******************************/ /* More BWE for signals with high prediction gain */ strength_Q16 = SKP_SMULWB( psEncCtrl->predGain_Q16, SKP_FIX_CONST( FIND_PITCH_WHITE_NOISE_FRACTION, 16 ) ); BWExp1_Q16 = BWExp2_Q16 = SKP_DIV32_varQ( SKP_FIX_CONST( BANDWIDTH_EXPANSION, 16 ), SKP_SMLAWW( SKP_FIX_CONST( 1.0, 16 ), strength_Q16, strength_Q16 ), 16 ); delta_Q16 = SKP_SMULWB( SKP_FIX_CONST( 1.0, 16 ) - SKP_SMULBB( 3, psEncCtrl->coding_quality_Q14 ), SKP_FIX_CONST( LOW_RATE_BANDWIDTH_EXPANSION_DELTA, 16 ) ); BWExp1_Q16 = SKP_SUB32( BWExp1_Q16, delta_Q16 ); BWExp2_Q16 = SKP_ADD32( BWExp2_Q16, delta_Q16 ); /* BWExp1 will be applied after BWExp2, so make it relative */ BWExp1_Q16 = SKP_DIV32_16( SKP_LSHIFT( BWExp1_Q16, 14 ), SKP_RSHIFT( BWExp2_Q16, 2 ) ); if( psEnc->sCmn.warping_Q16 > 0 ) { /* Slightly more warping in analysis will move quantization noise up in frequency, where it's better masked */ warping_Q16 = SKP_SMLAWB( psEnc->sCmn.warping_Q16, psEncCtrl->coding_quality_Q14, SKP_FIX_CONST( 0.01, 18 ) ); } else { warping_Q16 = 0; } /********************************************/ /* Compute noise shaping AR coefs and gains */ /********************************************/ for( k = 0; k < NB_SUBFR; k++ ) { /* Apply window: sine slope followed by flat part followed by cosine slope */ SKP_int shift, slope_part, flat_part; flat_part = psEnc->sCmn.fs_kHz * 5; slope_part = SKP_RSHIFT( psEnc->sCmn.shapeWinLength - flat_part, 1 ); SKP_Silk_apply_sine_window_new( x_windowed, x_ptr, 1, slope_part ); shift = slope_part; SKP_memcpy( x_windowed + shift, x_ptr + shift, flat_part * sizeof(SKP_int16) ); shift += flat_part; SKP_Silk_apply_sine_window_new( x_windowed + shift, x_ptr + shift, 2, slope_part ); /* Update pointer: next LPC analysis block */ x_ptr += psEnc->sCmn.subfr_length; if( psEnc->sCmn.warping_Q16 > 0 ) { /* Calculate warped auto correlation */ SKP_Silk_warped_autocorrelation_FIX( auto_corr, &scale, x_windowed, warping_Q16, psEnc->sCmn.shapeWinLength, psEnc->sCmn.shapingLPCOrder ); } else { /* Calculate regular auto correlation */ SKP_Silk_autocorr( auto_corr, &scale, x_windowed, psEnc->sCmn.shapeWinLength, psEnc->sCmn.shapingLPCOrder + 1 ); } /* Add white noise, as a fraction of energy */ auto_corr[0] = SKP_ADD32( auto_corr[0], SKP_max_32( SKP_SMULWB( SKP_RSHIFT( auto_corr[ 0 ], 4 ), SKP_FIX_CONST( SHAPE_WHITE_NOISE_FRACTION, 20 ) ), 1 ) ); /* Calculate the reflection coefficients using schur */ nrg = SKP_Silk_schur64( refl_coef_Q16, auto_corr, psEnc->sCmn.shapingLPCOrder ); SKP_assert( nrg >= 0 ); /* Convert reflection coefficients to prediction coefficients */ SKP_Silk_k2a_Q16( AR2_Q24, refl_coef_Q16, psEnc->sCmn.shapingLPCOrder ); Qnrg = -scale; // range: -12...30 SKP_assert( Qnrg >= -12 ); SKP_assert( Qnrg <= 30 ); /* Make sure that Qnrg is an even number */ if( Qnrg & 1 ) { Qnrg -= 1; nrg >>= 1; } tmp32 = SKP_Silk_SQRT_APPROX( nrg ); Qnrg >>= 1; // range: -6...15 sqrt_nrg[ k ] = tmp32; Qnrg_vec[ k ] = Qnrg; psEncCtrl->Gains_Q16[ k ] = SKP_LSHIFT_SAT32( tmp32, 16 - Qnrg ); if( psEnc->sCmn.warping_Q16 > 0 ) { /* Adjust gain for warping */ gain_mult_Q16 = warped_gain( AR2_Q24, warping_Q16, psEnc->sCmn.shapingLPCOrder ); SKP_assert( psEncCtrl->Gains_Q16[ k ] >= 0 ); psEncCtrl->Gains_Q16[ k ] = SKP_SMULWW( psEncCtrl->Gains_Q16[ k ], gain_mult_Q16 ); if( psEncCtrl->Gains_Q16[ k ] < 0 ) { psEncCtrl->Gains_Q16[ k ] = SKP_int32_MAX; } } /* Bandwidth expansion for synthesis filter shaping */ SKP_Silk_bwexpander_32( AR2_Q24, psEnc->sCmn.shapingLPCOrder, BWExp2_Q16 ); /* Compute noise shaping filter coefficients */ SKP_memcpy( AR1_Q24, AR2_Q24, psEnc->sCmn.shapingLPCOrder * sizeof( SKP_int32 ) ); /* Bandwidth expansion for analysis filter shaping */ SKP_assert( BWExp1_Q16 <= SKP_FIX_CONST( 1.0, 16 ) ); SKP_Silk_bwexpander_32( AR1_Q24, psEnc->sCmn.shapingLPCOrder, BWExp1_Q16 ); /* Ratio of prediction gains, in energy domain */ SKP_Silk_LPC_inverse_pred_gain_Q24( &pre_nrg_Q30, AR2_Q24, psEnc->sCmn.shapingLPCOrder ); SKP_Silk_LPC_inverse_pred_gain_Q24( &nrg, AR1_Q24, psEnc->sCmn.shapingLPCOrder ); //psEncCtrl->GainsPre[ k ] = 1.0f - 0.7f * ( 1.0f - pre_nrg / nrg ) = 0.3f + 0.7f * pre_nrg / nrg; pre_nrg_Q30 = SKP_LSHIFT32( SKP_SMULWB( pre_nrg_Q30, SKP_FIX_CONST( 0.7, 15 ) ), 1 ); psEncCtrl->GainsPre_Q14[ k ] = ( SKP_int ) SKP_FIX_CONST( 0.3, 14 ) + SKP_DIV32_varQ( pre_nrg_Q30, nrg, 14 ); /* Convert to monic warped prediction coefficients and limit absolute values */ limit_warped_coefs( AR2_Q24, AR1_Q24, warping_Q16, SKP_FIX_CONST( 3.999, 24 ), psEnc->sCmn.shapingLPCOrder ); /* Convert from Q24 to Q13 and store in int16 */ for( i = 0; i < psEnc->sCmn.shapingLPCOrder; i++ ) { psEncCtrl->AR1_Q13[ k * MAX_SHAPE_LPC_ORDER + i ] = (SKP_int16)SKP_SAT16( SKP_RSHIFT_ROUND( AR1_Q24[ i ], 11 ) ); psEncCtrl->AR2_Q13[ k * MAX_SHAPE_LPC_ORDER + i ] = (SKP_int16)SKP_SAT16( SKP_RSHIFT_ROUND( AR2_Q24[ i ], 11 ) ); } }
/* even order AR filter */ void SKP_Silk_LPC_synthesis_filter( const SKP_int16 *in, /* I: excitation signal */ const SKP_int16 *A_Q12, /* I: AR coefficients [Order], between -8_Q0 and 8_Q0 */ const SKP_int32 Gain_Q26, /* I: gain */ SKP_int32 *S, /* I/O: state vector [Order] */ SKP_int16 *out, /* O: output signal */ const SKP_int32 len, /* I: signal length */ const SKP_int Order /* I: filter order, must be even */ ) { SKP_int k, j, idx, Order_half = SKP_RSHIFT( Order, 1 ); SKP_int32 SA, SB, Atmp, A_align_Q12[SigProc_MAX_ORDER_LPC >> 1], out32_Q10, out32; /* 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 ); A_align_Q12[k] = (((SKP_int32)A_Q12[idx]) & 0x0000ffff) | SKP_LSHIFT( (SKP_int32)A_Q12[idx+1], 16 ); } /* S[] values are in Q14 */ for( k = 0; k < len; k++ ) { SA = S[Order-1]; out32_Q10 = 0; for( j=0;j<(Order_half-1); j++ ) { idx = SKP_SMULBB( 2, j ) + 1; /* multiply-add two prediction coefficients for each loop */ /* NOTE: the code below loads two int16 values in an int32, and multiplies each using the */ /* SMLAWB and SMLAWT 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 SMLAWB and SMLAWT instructions should solve the problem. */ Atmp = A_align_Q12[j]; SB = S[Order - 1 - idx]; S[Order - 1 - idx] = SA; out32_Q10 = SKP_SMLAWB( out32_Q10, SA, Atmp ); out32_Q10 = SKP_SMLAWT( out32_Q10, SB, Atmp ); SA = S[Order - 2 - idx]; S[Order - 2 - idx] = SB; } /* unrolled loop: epilog */ Atmp = A_align_Q12[Order_half-1]; SB = S[0]; S[0] = SA; out32_Q10 = SKP_SMLAWB( out32_Q10, SA, Atmp ); out32_Q10 = SKP_SMLAWT( out32_Q10, SB, Atmp ); /* apply gain to excitation signal and add to prediction */ out32_Q10 = SKP_ADD_SAT32( out32_Q10, SKP_SMULWB( Gain_Q26, in[k] ) ); /* scale to Q0 */ out32 = SKP_RSHIFT_ROUND( out32_Q10, 10 ); /* saturate output */ out[k] = (SKP_int16)SKP_SAT16( out32 ); /* move result into delay line */ S[Order - 1] = SKP_LSHIFT_SAT32( out32_Q10, 4 ); } }
void SKP_Silk_PLC_conceal( SKP_Silk_decoder_state *psDec, /* I/O Decoder state */ SKP_Silk_decoder_control *psDecCtrl, /* I/O Decoder control */ SKP_int16 signal[], /* O concealed signal */ SKP_int length /* I length of residual */ ) { SKP_int i, j, k; SKP_int16 *B_Q14, exc_buf[ MAX_FRAME_LENGTH ], *exc_buf_ptr; SKP_int16 rand_scale_Q14, A_Q12_tmp[ MAX_LPC_ORDER ]; SKP_int32 rand_seed, harm_Gain_Q15, rand_Gain_Q15; SKP_int lag, idx, shift1, shift2; SKP_int32 energy1, energy2, *rand_ptr, *pred_lag_ptr, Atmp; SKP_int32 sig_Q10[ MAX_FRAME_LENGTH ], *sig_Q10_ptr, LPC_exc_Q10, LPC_pred_Q10, LTP_pred_Q14; SKP_Silk_PLC_struct *psPLC; psPLC = &psDec->sPLC; /* Update LTP buffer */ SKP_memcpy( psDec->sLTP_Q16, &psDec->sLTP_Q16[ psDec->frame_length ], psDec->frame_length * sizeof( SKP_int32 ) ); /* LPC concealment. Apply BWE to previous LPC */ SKP_Silk_bwexpander( psPLC->prevLPC_Q12, psDec->LPC_order, BWE_COEF_Q16 ); /* Find random noise component */ /* Scale previous excitation signal */ exc_buf_ptr = exc_buf; for( k = ( NB_SUBFR >> 1 ); k < NB_SUBFR; k++ ) { for( i = 0; i < psDec->subfr_length; i++ ) { exc_buf_ptr[ i ] = ( SKP_int16 )SKP_RSHIFT( SKP_SMULWW( psDec->exc_Q10[ i + k * psDec->subfr_length ], psPLC->prevGain_Q16[ k ] ), 10 ); } exc_buf_ptr += psDec->subfr_length; } /* Find the subframe with lowest energy of the last two and use that as random noise generator */ SKP_Silk_sum_sqr_shift( &energy1, &shift1, exc_buf, psDec->subfr_length ); SKP_Silk_sum_sqr_shift( &energy2, &shift2, &exc_buf[ psDec->subfr_length ], psDec->subfr_length ); if( SKP_RSHIFT( energy1, shift2 ) < SKP_RSHIFT( energy1, shift2 ) ) { /* First sub-frame has lowest energy */ rand_ptr = &psDec->exc_Q10[ SKP_max_int( 0, 3 * psDec->subfr_length - RAND_BUF_SIZE ) ]; } else { /* Second sub-frame has lowest energy */ rand_ptr = &psDec->exc_Q10[ SKP_max_int( 0, psDec->frame_length - RAND_BUF_SIZE ) ]; } /* Setup Gain to random noise component */ B_Q14 = psPLC->LTPCoef_Q14; rand_scale_Q14 = psPLC->randScale_Q14; /* Setup attenuation gains */ harm_Gain_Q15 = HARM_ATT_Q15[ SKP_min_int( NB_ATT - 1, psDec->lossCnt ) ]; if( psDec->prev_sigtype == SIG_TYPE_VOICED ) { rand_Gain_Q15 = PLC_RAND_ATTENUATE_V_Q15[ SKP_min_int( NB_ATT - 1, psDec->lossCnt ) ]; } else { rand_Gain_Q15 = PLC_RAND_ATTENUATE_UV_Q15[ SKP_min_int( NB_ATT - 1, psDec->lossCnt ) ]; } /* First Lost frame */ if( psDec->lossCnt == 0 ) { rand_scale_Q14 = (1 << 14 ); /* Reduce random noise Gain for voiced frames */ if( psDec->prev_sigtype == SIG_TYPE_VOICED ) { for( i = 0; i < LTP_ORDER; i++ ) { rand_scale_Q14 -= B_Q14[ i ]; } rand_scale_Q14 = SKP_max_16( 3277, rand_scale_Q14 ); /* 0.2 */ rand_scale_Q14 = ( SKP_int16 )SKP_RSHIFT( SKP_SMULBB( rand_scale_Q14, psPLC->prevLTP_scale_Q14 ), 14 ); } /* Reduce random noise for unvoiced frames with high LPC gain */ if( psDec->prev_sigtype == SIG_TYPE_UNVOICED ) { SKP_int32 invGain_Q30, down_scale_Q30; SKP_Silk_LPC_inverse_pred_gain( &invGain_Q30, psPLC->prevLPC_Q12, psDec->LPC_order ); down_scale_Q30 = SKP_min_32( SKP_RSHIFT( ( 1 << 30 ), LOG2_INV_LPC_GAIN_HIGH_THRES ), invGain_Q30 ); down_scale_Q30 = SKP_max_32( SKP_RSHIFT( ( 1 << 30 ), LOG2_INV_LPC_GAIN_LOW_THRES ), down_scale_Q30 ); down_scale_Q30 = SKP_LSHIFT( down_scale_Q30, LOG2_INV_LPC_GAIN_HIGH_THRES ); rand_Gain_Q15 = SKP_RSHIFT( SKP_SMULWB( down_scale_Q30, rand_Gain_Q15 ), 14 ); } } rand_seed = psPLC->rand_seed; lag = SKP_RSHIFT_ROUND( psPLC->pitchL_Q8, 8 ); psDec->sLTP_buf_idx = psDec->frame_length; /***************************/ /* LTP synthesis filtering */ /***************************/ sig_Q10_ptr = sig_Q10; for( k = 0; k < NB_SUBFR; k++ ) { /* Setup pointer */ pred_lag_ptr = &psDec->sLTP_Q16[ psDec->sLTP_buf_idx - lag + LTP_ORDER / 2 ]; for( i = 0; i < psDec->subfr_length; i++ ) { rand_seed = SKP_RAND( rand_seed ); idx = SKP_RSHIFT( rand_seed, 25 ) & RAND_BUF_MASK; /* Unrolled loop */ LTP_pred_Q14 = SKP_SMULWB( pred_lag_ptr[ 0 ], B_Q14[ 0 ] ); LTP_pred_Q14 = SKP_SMLAWB( LTP_pred_Q14, pred_lag_ptr[ -1 ], B_Q14[ 1 ] ); LTP_pred_Q14 = SKP_SMLAWB( LTP_pred_Q14, pred_lag_ptr[ -2 ], B_Q14[ 2 ] ); LTP_pred_Q14 = SKP_SMLAWB( LTP_pred_Q14, pred_lag_ptr[ -3 ], B_Q14[ 3 ] ); LTP_pred_Q14 = SKP_SMLAWB( LTP_pred_Q14, pred_lag_ptr[ -4 ], B_Q14[ 4 ] ); pred_lag_ptr++; /* Generate LPC residual */ LPC_exc_Q10 = SKP_LSHIFT( SKP_SMULWB( rand_ptr[ idx ], rand_scale_Q14 ), 2 ); /* Random noise part */ LPC_exc_Q10 = SKP_ADD32( LPC_exc_Q10, SKP_RSHIFT_ROUND( LTP_pred_Q14, 4 ) ); /* Harmonic part */ /* Update states */ psDec->sLTP_Q16[ psDec->sLTP_buf_idx ] = SKP_LSHIFT( LPC_exc_Q10, 6 ); psDec->sLTP_buf_idx++; /* Save LPC residual */ sig_Q10_ptr[ i ] = LPC_exc_Q10; } sig_Q10_ptr += psDec->subfr_length; /* Gradually reduce LTP gain */ for( j = 0; j < LTP_ORDER; j++ ) { B_Q14[ j ] = SKP_RSHIFT( SKP_SMULBB( harm_Gain_Q15, B_Q14[ j ] ), 15 ); } /* Gradually reduce excitation gain */ rand_scale_Q14 = SKP_RSHIFT( SKP_SMULBB( rand_scale_Q14, rand_Gain_Q15 ), 15 ); /* Slowly increase pitch lag */ psPLC->pitchL_Q8 += SKP_SMULWB( psPLC->pitchL_Q8, PITCH_DRIFT_FAC_Q16 ); psPLC->pitchL_Q8 = SKP_min_32( psPLC->pitchL_Q8, SKP_LSHIFT( SKP_SMULBB( MAX_PITCH_LAG_MS, psDec->fs_kHz ), 8 ) ); lag = SKP_RSHIFT_ROUND( psPLC->pitchL_Q8, 8 ); } /***************************/ /* LPC synthesis filtering */ /***************************/ sig_Q10_ptr = sig_Q10; /* Preload LPC coeficients to array on stack. Gives small performance gain */ SKP_memcpy( A_Q12_tmp, psPLC->prevLPC_Q12, psDec->LPC_order * sizeof( SKP_int16 ) ); SKP_assert( psDec->LPC_order >= 10 ); /* check that unrolling works */ for( k = 0; k < NB_SUBFR; k++ ) { for( i = 0; i < psDec->subfr_length; i++ ){ /* unrolled */ Atmp = *( ( SKP_int32* )&A_Q12_tmp[ 0 ] ); /* read two coefficients at once */ LPC_pred_Q10 = SKP_SMULWB( psDec->sLPC_Q14[ MAX_LPC_ORDER + i - 1 ], Atmp ); LPC_pred_Q10 = SKP_SMLAWT( LPC_pred_Q10, psDec->sLPC_Q14[ MAX_LPC_ORDER + i - 2 ], Atmp ); Atmp = *( ( SKP_int32* )&A_Q12_tmp[ 2 ] ); LPC_pred_Q10 = SKP_SMLAWB( LPC_pred_Q10, psDec->sLPC_Q14[ MAX_LPC_ORDER + i - 3 ], Atmp ); LPC_pred_Q10 = SKP_SMLAWT( LPC_pred_Q10, psDec->sLPC_Q14[ MAX_LPC_ORDER + i - 4 ], Atmp ); Atmp = *( ( SKP_int32* )&A_Q12_tmp[ 4 ] ); LPC_pred_Q10 = SKP_SMLAWB( LPC_pred_Q10, psDec->sLPC_Q14[ MAX_LPC_ORDER + i - 5 ], Atmp ); LPC_pred_Q10 = SKP_SMLAWT( LPC_pred_Q10, psDec->sLPC_Q14[ MAX_LPC_ORDER + i - 6 ], Atmp ); Atmp = *( ( SKP_int32* )&A_Q12_tmp[ 6 ] ); LPC_pred_Q10 = SKP_SMLAWB( LPC_pred_Q10, psDec->sLPC_Q14[ MAX_LPC_ORDER + i - 7 ], Atmp ); LPC_pred_Q10 = SKP_SMLAWT( LPC_pred_Q10, psDec->sLPC_Q14[ MAX_LPC_ORDER + i - 8 ], Atmp ); Atmp = *( ( SKP_int32* )&A_Q12_tmp[ 8 ] ); LPC_pred_Q10 = SKP_SMLAWB( LPC_pred_Q10, psDec->sLPC_Q14[ MAX_LPC_ORDER + i - 9 ], Atmp ); LPC_pred_Q10 = SKP_SMLAWT( LPC_pred_Q10, psDec->sLPC_Q14[ MAX_LPC_ORDER + i - 10 ], Atmp ); for( j = 10 ; j < psDec->LPC_order ; j+=2 ) { Atmp = *( ( SKP_int32* )&A_Q12_tmp[ j ] ); LPC_pred_Q10 = SKP_SMLAWB( LPC_pred_Q10, psDec->sLPC_Q14[ MAX_LPC_ORDER + i - 1 - j ], Atmp ); LPC_pred_Q10 = SKP_SMLAWT( LPC_pred_Q10, psDec->sLPC_Q14[ MAX_LPC_ORDER + i - 2 - j ], Atmp ); } /* Add prediction to LPC residual */ sig_Q10_ptr[ i ] = SKP_ADD32( sig_Q10_ptr[ i ], LPC_pred_Q10 ); /* Update states */ psDec->sLPC_Q14[ MAX_LPC_ORDER + i ] = SKP_LSHIFT( sig_Q10_ptr[ i ], 4 ); } sig_Q10_ptr += psDec->subfr_length; /* Update LPC filter state */ SKP_memcpy( psDec->sLPC_Q14, &psDec->sLPC_Q14[ psDec->subfr_length ], MAX_LPC_ORDER * sizeof( SKP_int32 ) ); } /* Scale with Gain */ for( i = 0; i < psDec->frame_length; i++ ) { signal[ i ] = ( SKP_int16 )SKP_SAT16( SKP_RSHIFT_ROUND( SKP_SMULWW( sig_Q10[ i ], psPLC->prevGain_Q16[ NB_SUBFR - 1 ] ), 10 ) ); } /**************************************/ /* Update states */ /**************************************/ psPLC->rand_seed = rand_seed; psPLC->randScale_Q14 = rand_scale_Q14; for( i = 0; i < NB_SUBFR; i++ ) { psDecCtrl->pitchL[ i ] = lag; } }
void SKP_Silk_resampler_private_up2_HQ( SKP_int32 *S, /* I/O: Resampler state [ 6 ] */ SKP_int16 *out, /* O: Output signal [ 2 * len ] */ const SKP_int16 *in, /* I: Input signal [ len ] */ SKP_int32 len /* I: Number of INPUT samples */ ) { SKP_int32 k; SKP_int32 in32, out32_1, out32_2, Y, X; SKP_assert( SKP_Silk_resampler_up2_hq_0[ 0 ] > 0 ); SKP_assert( SKP_Silk_resampler_up2_hq_0[ 1 ] < 0 ); SKP_assert( SKP_Silk_resampler_up2_hq_1[ 0 ] > 0 ); SKP_assert( SKP_Silk_resampler_up2_hq_1[ 1 ] < 0 ); /* Internal variables and state are in Q10 format */ for( k = 0; k < len; k++ ) { /* Convert to Q10 */ in32 = SKP_LSHIFT( (SKP_int32)in[ k ], 10 ); /* First all-pass section for even output sample */ Y = SKP_SUB32( in32, S[ 0 ] ); X = SKP_SMULWB( Y, SKP_Silk_resampler_up2_hq_0[ 0 ] ); out32_1 = SKP_ADD32( S[ 0 ], X ); S[ 0 ] = SKP_ADD32( in32, X ); /* Second all-pass section for even output sample */ Y = SKP_SUB32( out32_1, S[ 1 ] ); X = SKP_SMLAWB( Y, Y, SKP_Silk_resampler_up2_hq_0[ 1 ] ); out32_2 = SKP_ADD32( S[ 1 ], X ); S[ 1 ] = SKP_ADD32( out32_1, X ); /* Biquad notch filter */ out32_2 = SKP_SMLAWB( out32_2, S[ 5 ], SKP_Silk_resampler_up2_hq_notch[ 2 ] ); out32_2 = SKP_SMLAWB( out32_2, S[ 4 ], SKP_Silk_resampler_up2_hq_notch[ 1 ] ); out32_1 = SKP_SMLAWB( out32_2, S[ 4 ], SKP_Silk_resampler_up2_hq_notch[ 0 ] ); S[ 5 ] = SKP_SUB32( out32_2, S[ 5 ] ); /* Apply gain in Q15, convert back to int16 and store to output */ out[ 2 * k ] = (SKP_int16)SKP_SAT16( SKP_RSHIFT32( SKP_SMLAWB( 256, out32_1, SKP_Silk_resampler_up2_hq_notch[ 3 ] ), 9 ) ); /* First all-pass section for odd output sample */ Y = SKP_SUB32( in32, S[ 2 ] ); X = SKP_SMULWB( Y, SKP_Silk_resampler_up2_hq_1[ 0 ] ); out32_1 = SKP_ADD32( S[ 2 ], X ); S[ 2 ] = SKP_ADD32( in32, X ); /* Second all-pass section for odd output sample */ Y = SKP_SUB32( out32_1, S[ 3 ] ); X = SKP_SMLAWB( Y, Y, SKP_Silk_resampler_up2_hq_1[ 1 ] ); out32_2 = SKP_ADD32( S[ 3 ], X ); S[ 3 ] = SKP_ADD32( out32_1, X ); /* Biquad notch filter */ out32_2 = SKP_SMLAWB( out32_2, S[ 4 ], SKP_Silk_resampler_up2_hq_notch[ 2 ] ); out32_2 = SKP_SMLAWB( out32_2, S[ 5 ], SKP_Silk_resampler_up2_hq_notch[ 1 ] ); out32_1 = SKP_SMLAWB( out32_2, S[ 5 ], SKP_Silk_resampler_up2_hq_notch[ 0 ] ); S[ 4 ] = SKP_SUB32( out32_2, S[ 4 ] ); /* Apply gain in Q15, convert back to int16 and store to output */ out[ 2 * k + 1 ] = (SKP_int16)SKP_SAT16( SKP_RSHIFT32( SKP_SMLAWB( 256, out32_1, SKP_Silk_resampler_up2_hq_notch[ 3 ] ), 9 ) ); } }
/* 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 ); }