SKP_int SKP_Silk_init_encoder_FLP(
    SKP_Silk_encoder_state_FLP      *psEnc              /* I/O  Encoder state FLP                       */
) {
    SKP_int ret = 0;

    /* Clear the entire encoder state */
    SKP_memset( psEnc, 0, sizeof( SKP_Silk_encoder_state_FLP ) );

#if HIGH_PASS_INPUT
    psEnc->variable_HP_smth1 = SKP_Silk_log2( 70.0 );
    psEnc->variable_HP_smth2 = SKP_Silk_log2( 70.0 );
#endif

    /* Used to deactivate e.g. LSF interpolation and fluctuation reduction */
    psEnc->sCmn.first_frame_after_reset = 1;

    /* Initialize Silk VAD */
    ret += SKP_Silk_VAD_Init( &psEnc->sCmn.sVAD );

    /* Initialize NSQ */
    psEnc->sCmn.sNSQ.prev_inv_gain_Q16      = 65536;
    psEnc->sCmn.sNSQ_LBRR.prev_inv_gain_Q16 = 65536;

    return( ret );
}
/* High-pass filter with cutoff frequency adaptation based on pitch lag statistics */
void SKP_Silk_HP_variable_cutoff_FLP(
    SKP_Silk_encoder_state_FLP      *psEnc,             /* I/O  Encoder state FLP                       */
    SKP_Silk_encoder_control_FLP    *psEncCtrl,         /* I/O  Encoder control FLP                     */
          SKP_int16                 *out,               /* O    High-pass filtered output signal        */
    const SKP_int16                 *in                 /* I    Input signal                            */
)
{
    SKP_float pitch_freq_Hz, pitch_freq_log, quality, delta_freq, smth_coef, Fc, r;
    SKP_int32 B_Q28[ 3 ], A_Q28[ 2 ];

    /*********************************************/
    /* Estimate low end of pitch frequency range */
    /*********************************************/
    if( psEnc->sCmn.prev_sigtype == SIG_TYPE_VOICED ) {

        /* Difference, in log domain */
        pitch_freq_Hz  = 1e3f * psEnc->sCmn.fs_kHz / psEnc->sCmn.prevLag;
        pitch_freq_log = SKP_Silk_log2( pitch_freq_Hz );

        /* Adjustment based on quality */
        quality = psEncCtrl->input_quality_bands[ 0 ];
        pitch_freq_log -= quality * quality * ( pitch_freq_log - SKP_Silk_log2( VARIABLE_HP_MIN_FREQ ) );
        pitch_freq_log += 0.5f * ( 0.6f - quality );

        delta_freq = pitch_freq_log - psEnc->variable_HP_smth1;
        if( delta_freq < 0.0 ) {
            /* Less smoothing for decreasing pitch frequency, to track something close to the minimum */
            delta_freq *= 3.0f;
        }

        /* Limit delta, to reduce impact of outliers */
        delta_freq = SKP_LIMIT_float( delta_freq, -VARIABLE_HP_MAX_DELTA_FREQ, VARIABLE_HP_MAX_DELTA_FREQ );
    
        /* Update smoother */
        smth_coef = VARIABLE_HP_SMTH_COEF1 * psEnc->speech_activity;
        psEnc->variable_HP_smth1 += smth_coef * delta_freq;
    }

    /* Second smoother */
    psEnc->variable_HP_smth2 += VARIABLE_HP_SMTH_COEF2 * ( psEnc->variable_HP_smth1 - psEnc->variable_HP_smth2 );

    /* Convert from log scale to Hertz */
    psEncCtrl->pitch_freq_low_Hz = ( SKP_float )pow( 2.0f, psEnc->variable_HP_smth2 );

    /* Limit frequency range */
    psEncCtrl->pitch_freq_low_Hz = SKP_LIMIT_float( psEncCtrl->pitch_freq_low_Hz, VARIABLE_HP_MIN_FREQ, VARIABLE_HP_MAX_FREQ );

    /*******************************/
    /* Compute filter coefficients */
    /*******************************/
    /* Compute cut-off frequency, in radians */
    Fc = ( SKP_float )( 0.45f * 2.0f * 3.14159265359 * psEncCtrl->pitch_freq_low_Hz / ( 1e3f * psEnc->sCmn.fs_kHz ) );

    /* 2nd order ARMA coefficients */
    r = 1.0f - 0.92f * Fc;

    /* b = r * [1; -2; 1]; */
    /* a = [1; -2 * r * (1 - 0.5 * Fc^2); r^2]; */
    B_Q28[ 0 ] = SKP_float2int( ( 1 << 28 ) * r );
    B_Q28[ 1 ] = SKP_float2int( ( 1 << 28 ) * -2.0f * r );
    B_Q28[ 2 ] = B_Q28[ 0 ];
    A_Q28[ 0 ] = SKP_float2int( ( 1 << 28 ) * -2.0f * r * ( 1.0f - 0.5f * Fc * Fc ) );
    A_Q28[ 1 ] = SKP_float2int( ( 1 << 28 ) * r * r );

    /********************/
    /* High-pass filter */
    /********************/
    SKP_Silk_biquad_alt( in, B_Q28, A_Q28, psEnc->sCmn.In_HP_State, out, psEnc->sCmn.frame_length );
}