void SKP_Silk_find_pitch_lags_FLP( SKP_Silk_encoder_state_FLP *psEnc, /* I/O Encoder state FLP */ SKP_Silk_encoder_control_FLP *psEncCtrl, /* I/O Encoder control FLP */ SKP_float res[], /* O Residual */ const SKP_float x[] /* I Speech signal */ ) { SKP_Silk_predict_state_FLP *psPredSt = &psEnc->sPred; SKP_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 = 2 * psEnc->sCmn.frame_length + psEnc->sCmn.la_pitch; /* 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_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, ( psPredSt->pitch_LPC_win_length - ( psEnc->sCmn.la_pitch << 1 ) ) * sizeof( SKP_float ) ); /* Last LA_LTP samples */ Wsig_ptr += psPredSt->pitch_LPC_win_length - ( psEnc->sCmn.la_pitch << 1 ); x_buf_ptr += psPredSt->pitch_LPC_win_length - ( psEnc->sCmn.la_pitch << 1 ); SKP_Silk_apply_sine_window_FLP( Wsig_ptr, x_buf_ptr, 2, psEnc->sCmn.la_pitch ); /* Calculate autocorrelation sequence */ SKP_Silk_autocorrelation_FLP( auto_corr, Wsig, psPredSt->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; /* Calculate the reflection coefficients using Schur */ res_nrg = SKP_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 */ SKP_Silk_k2a_FLP( A, refl_coef, psEnc->sCmn.pitchEstimationLPCOrder ); /* Bandwidth expansion */ SKP_Silk_bwexpander_FLP( A, psEnc->sCmn.pitchEstimationLPCOrder, FIND_PITCH_BANDWITH_EXPANSION ); /*****************************************/ /* LPC analysis filtering */ /*****************************************/ SKP_Silk_LPC_analysis_filter_FLP( res, A, x_buf, buf_len, psEnc->sCmn.pitchEstimationLPCOrder ); SKP_memset( res, 0, psEnc->sCmn.pitchEstimationLPCOrder * sizeof( SKP_float ) ); /* Threshold for pitch estimator */ thrhld = 0.45f; thrhld -= 0.004f * psEnc->sCmn.pitchEstimationLPCOrder; thrhld -= 0.1f * psEnc->speech_activity; thrhld += 0.15f * psEnc->sCmn.prev_sigtype; thrhld -= 0.1f * psEncCtrl->input_tilt; /*****************************************/ /* Call Pitch estimator */ /*****************************************/ psEncCtrl->sCmn.sigtype = SKP_Silk_pitch_analysis_core_FLP( res, psEncCtrl->sCmn.pitchL, &psEncCtrl->sCmn.lagIndex, &psEncCtrl->sCmn.contourIndex, &psEnc->LTPCorr, psEnc->sCmn.prevLag, psEnc->sCmn.pitchEstimationThreshold_Q16 / 65536.0f, thrhld, psEnc->sCmn.fs_kHz, psEnc->sCmn.pitchEstimationComplexity ); }
void SKP_Silk_find_LPC_FLP( SKP_float NLSF[], /* O NLSFs */ SKP_int *interpIndex, /* O NLSF interp. index for NLSF interp. */ const SKP_float prev_NLSFq[], /* I Previous NLSFs, for NLSF interpolation */ const SKP_int useInterpNLSFs, /* I Flag */ const SKP_int LPC_order, /* I LPC order */ const SKP_float x[], /* I Input signal */ const SKP_int subfr_length /* I Subframe length incl preceeding samples */ ) { SKP_int k; SKP_float a[ MAX_LPC_ORDER ]; /* Used only for NLSF interpolation */ double res_nrg, res_nrg_2nd, res_nrg_interp; SKP_float a_tmp[ MAX_LPC_ORDER ], NLSF0[ MAX_LPC_ORDER ]; SKP_float LPC_res[ ( MAX_FRAME_LENGTH + NB_SUBFR * MAX_LPC_ORDER ) / 2 ]; /* Default: No interpolation */ *interpIndex = 4; /* Burg AR analysis for the full frame */ res_nrg = SKP_Silk_burg_modified_FLP( a, x, subfr_length, NB_SUBFR, FIND_LPC_COND_FAC, LPC_order ); SKP_Silk_bwexpander_FLP( a, LPC_order, FIND_LPC_CHIRP ); if( useInterpNLSFs == 1 ) { /* Optimal solution for last 10 ms; subtract residual energy here, as that's easier than */ /* adding it to the residual energy of the first 10 ms in each iteration of the search below */ res_nrg -= SKP_Silk_burg_modified_FLP( a_tmp, x + ( NB_SUBFR / 2 ) * subfr_length, subfr_length, NB_SUBFR / 2, FIND_LPC_COND_FAC, LPC_order ); SKP_Silk_bwexpander_FLP( a_tmp, LPC_order, FIND_LPC_CHIRP ); /* Convert to NLSFs */ SKP_Silk_A2NLSF_FLP( NLSF, a_tmp, LPC_order ); /* Search over interpolation indices to find the one with lowest residual energy */ res_nrg_2nd = SKP_float_MAX; for( k = 3; k >= 0; k-- ) { /* Interpolate NLSFs for first half */ SKP_Silk_interpolate_wrapper_FLP( NLSF0, prev_NLSFq, NLSF, 0.25f * k, LPC_order ); /* Convert to LPC for residual energy evaluation */ SKP_Silk_NLSF2A_stable_FLP( a_tmp, NLSF0, LPC_order ); /* Calculate residual energy with LSF interpolation */ SKP_Silk_LPC_analysis_filter_FLP( LPC_res, a_tmp, x, 2 * subfr_length, LPC_order ); res_nrg_interp = SKP_Silk_energy_FLP( LPC_res + LPC_order, subfr_length - LPC_order ) + SKP_Silk_energy_FLP( LPC_res + LPC_order + subfr_length, subfr_length - LPC_order ); /* Determine whether current interpolated NLSFs are best so far */ if( res_nrg_interp < res_nrg ) { /* Interpolation has lower residual energy */ res_nrg = res_nrg_interp; *interpIndex = k; } else if( res_nrg_interp > res_nrg_2nd ) { /* No reason to continue iterating - residual energies will continue to climb */ break; } res_nrg_2nd = res_nrg_interp; } } if( *interpIndex == 4 ) { /* NLSF interpolation is currently inactive, calculate NLSFs from full frame AR coefficients */ SKP_Silk_A2NLSF_FLP( NLSF, a, LPC_order ); } }