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 );
    }

}