/* Laroia low complexity NLSF weights */ void SKP_Silk_NLSF_VQ_weights_laroia_FLP( SKP_float *pXW, /* 0: Pointer to input vector weights [D x 1] */ const SKP_float *pX, /* I: Pointer to input vector [D x 1] */ const SKP_int D /* I: Input vector dimension */ ) { SKP_int k; SKP_float tmp1, tmp2; /* Safety checks */ SKP_assert( D > 0 ); SKP_assert( ( D & 1 ) == 0 ); /* First value */ tmp1 = 1.0f / SKP_max_float( pX[ 0 ], MIN_NDELTA ); tmp2 = 1.0f / SKP_max_float( pX[ 1 ] - pX[ 0 ], MIN_NDELTA ); pXW[ 0 ] = tmp1 + tmp2; /* Main loop */ for( k = 1; k < D - 1; k += 2 ) { tmp1 = 1.0f / SKP_max_float( pX[ k + 1 ] - pX[ k ], MIN_NDELTA ); pXW[ k ] = tmp1 + tmp2; tmp2 = 1.0f / SKP_max_float( pX[ k + 2 ] - pX[ k + 1 ], MIN_NDELTA ); pXW[ k + 1 ] = tmp1 + tmp2; } /* Last value */ tmp1 = 1.0f / SKP_max_float( 1.0f - pX[ D - 1 ], MIN_NDELTA ); pXW[ D - 1 ] = tmp1 + tmp2; }
SKP_float SKP_Silk_schur_FLP( /* O returns residual energy */ SKP_float refl_coef[], /* O reflection coefficients (length order) */ const SKP_float auto_corr[], /* I autotcorrelation sequence (length order+1) */ SKP_int order /* I order */ ) { SKP_int k, n; SKP_float C[SKP_Silk_MAX_ORDER_LPC + 1][2]; SKP_float Ctmp1, Ctmp2, rc_tmp; /* copy correlations */ for( k = 0; k < order+1; k++ ){ C[k][0] = C[k][1] = auto_corr[k]; } for( k = 0; k < order; k++ ) { /* get reflection coefficient */ rc_tmp = -C[k + 1][0] / SKP_max_float( C[0][1], 1e-9f ); /* save the output */ refl_coef[k] = rc_tmp; /* update correlations */ for( n = 0; n < order - k; n++ ){ Ctmp1 = C[n + k + 1][0]; Ctmp2 = C[n][1]; C[n + k + 1][0] = Ctmp1 + Ctmp2 * rc_tmp; C[n][1] = Ctmp2 + Ctmp1 * rc_tmp; } } /* return residual energy */ return C[0][1]; }
/* Solve the normal equations using the Levinson-Durbin recursion */ SKP_float silk_levinsondurbin_FLP( /* O prediction error energy */ SKP_float A[], /* O prediction coefficients [order] */ const SKP_float corr[], /* I input auto-correlations [order + 1] */ const SKP_int order /* I prediction order */ ) { SKP_int i, mHalf, m; SKP_float min_nrg, nrg, t, km, Atmp1, Atmp2; min_nrg = 1e-12f * corr[ 0 ] + 1e-9f; nrg = corr[ 0 ]; nrg = SKP_max_float(min_nrg, nrg); A[ 0 ] = corr[ 1 ] / nrg; nrg -= A[ 0 ] * corr[ 1 ]; nrg = SKP_max_float(min_nrg, nrg); for( m = 1; m < order; m++ ) { t = corr[ m + 1 ]; for( i = 0; i < m; i++ ) { t -= A[ i ] * corr[ m - i ]; } /* reflection coefficient */ km = t / nrg; /* residual energy */ nrg -= km * t; nrg = SKP_max_float(min_nrg, nrg); mHalf = m >> 1; for( i = 0; i < mHalf; i++ ) { Atmp1 = A[ i ]; Atmp2 = A[ m - i - 1 ]; A[ m - i - 1 ] -= km * Atmp1; A[ i ] -= km * Atmp2; } if( m & 1 ) { A[ mHalf ] -= km * A[ mHalf ]; } A[ m ] = km; } /* return the residual energy */ return nrg; }
void silk_LTP_scale_ctrl_FLP( silk_encoder_state_FLP *psEnc, /* I/O Encoder state FLP */ silk_encoder_control_FLP *psEncCtrl /* I/O Encoder control FLP */ ) { opus_int round_loss; /* 1st order high-pass filter */ //g_HP(n) = g(n) - 0.5 * g(n-1) + 0.5 * g_HP(n-1); psEnc->HPLTPredCodGain = SKP_max_float( psEncCtrl->LTPredCodGain - 0.5 * psEnc->prevLTPredCodGain, 0.0f ) + 0.5f * psEnc->HPLTPredCodGain; psEnc->prevLTPredCodGain = psEncCtrl->LTPredCodGain; /* Only scale if first frame in packet */ if( psEnc->sCmn.nFramesEncoded == 0 ) { round_loss = psEnc->sCmn.PacketLoss_perc + psEnc->sCmn.nFramesPerPacket; psEnc->sCmn.indices.LTP_scaleIndex = (opus_int8)SKP_LIMIT( round_loss * psEnc->HPLTPredCodGain * 0.1f, 0.0f, 2.0f ); } else { /* Default is minimum scaling */ psEnc->sCmn.indices.LTP_scaleIndex = 0; } psEncCtrl->LTP_scale = (SKP_float)silk_LTPScales_table_Q14[ psEnc->sCmn.indices.LTP_scaleIndex ] / 16384.0f; }
void silk_find_pitch_lags_FLP( silk_encoder_state_FLP *psEnc, /* I/O Encoder state FLP */ silk_encoder_control_FLP *psEncCtrl, /* I/O Encoder control FLP */ SKP_float res[], /* O Residual */ const SKP_float x[] /* I Speech signal */ ) { opus_int buf_len; SKP_float thrhld, res_nrg; const SKP_float *x_buf_ptr, *x_buf; SKP_float auto_corr[ MAX_FIND_PITCH_LPC_ORDER + 1 ]; SKP_float A[ MAX_FIND_PITCH_LPC_ORDER ]; SKP_float refl_coef[ MAX_FIND_PITCH_LPC_ORDER ]; SKP_float Wsig[ FIND_PITCH_LPC_WIN_MAX ]; SKP_float *Wsig_ptr; /******************************************/ /* 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 coeficients */ /******************************************/ /* 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_FLP( Wsig_ptr, x_buf_ptr, 1, psEnc->sCmn.la_pitch ); /* Middle non-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 - ( psEnc->sCmn.la_pitch << 1 ) ) * sizeof( SKP_float ) ); /* Last LA_LTP samples */ Wsig_ptr += psEnc->sCmn.pitch_LPC_win_length - ( psEnc->sCmn.la_pitch << 1 ); x_buf_ptr += psEnc->sCmn.pitch_LPC_win_length - ( psEnc->sCmn.la_pitch << 1 ); silk_apply_sine_window_FLP( Wsig_ptr, x_buf_ptr, 2, psEnc->sCmn.la_pitch ); /* Calculate autocorrelation sequence */ silk_autocorrelation_FLP( auto_corr, Wsig, psEnc->sCmn.pitch_LPC_win_length, psEnc->sCmn.pitchEstimationLPCOrder + 1 ); /* Add white noise, as a fraction of the energy */ auto_corr[ 0 ] += auto_corr[ 0 ] * FIND_PITCH_WHITE_NOISE_FRACTION + 1; /* Calculate the reflection coefficients using Schur */ res_nrg = silk_schur_FLP( refl_coef, auto_corr, psEnc->sCmn.pitchEstimationLPCOrder ); /* Prediction gain */ psEncCtrl->predGain = auto_corr[ 0 ] / SKP_max_float( res_nrg, 1.0f ); /* Convert reflection coefficients to prediction coefficients */ silk_k2a_FLP( A, refl_coef, psEnc->sCmn.pitchEstimationLPCOrder ); /* Bandwidth expansion */ silk_bwexpander_FLP( A, psEnc->sCmn.pitchEstimationLPCOrder, FIND_PITCH_BANDWITH_EXPANSION ); /*****************************************/ /* LPC analysis filtering */ /*****************************************/ silk_LPC_analysis_filter_FLP( res, A, x_buf, 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 = 0.6f; thrhld -= 0.004f * psEnc->sCmn.pitchEstimationLPCOrder; thrhld -= 0.1f * psEnc->sCmn.speech_activity_Q8 * ( 1.0f / 256.0f ); thrhld -= 0.15f * (psEnc->sCmn.prevSignalType >> 1); thrhld -= 0.1f * psEnc->sCmn.input_tilt_Q15 * ( 1.0f / 32768.0f ); /*****************************************/ /* Call Pitch estimator */ /*****************************************/ if( silk_pitch_analysis_core_FLP( res, psEncCtrl->pitchL, &psEnc->sCmn.indices.lagIndex, &psEnc->sCmn.indices.contourIndex, &psEnc->LTPCorr, psEnc->sCmn.prevLag, psEnc->sCmn.pitchEstimationThreshold_Q16 / 65536.0f, thrhld, 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 {