Beispiel #1
0
/* Solve the normal equations using the Levinson-Durbin recursion */
silk_float silk_levinsondurbin_FLP(	/* O    prediction error energy                                     */
    silk_float A[],	/* O    prediction coefficients    [order]                          */
    const silk_float corr[],	/* I    input auto-correlations [order + 1]                         */
    const int order	/* I    prediction order                                            */
)
{
    int i, mHalf, m;
    silk_float min_nrg, nrg, t, km, Atmp1, Atmp2;

    min_nrg = 1e-12f * corr[0] + 1e-9f;
    nrg = corr[0];
    nrg = silk_max_float(min_nrg, nrg);
    A[0] = corr[1] / nrg;
    nrg -= A[0] * corr[1];
    nrg = silk_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 = silk_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;
}
Beispiel #2
0
silk_float silk_schur_FLP(	/* O    returns residual energy                                     */
				 silk_float refl_coef[],	/* O    reflection coefficients (length order)                      */
				 const silk_float auto_corr[],	/* I    autocorrelation sequence (length order+1)                   */
				 int order	/* I    order                                                       */
    )
{
	int k, n;
	silk_float C[SILK_MAX_ORDER_LPC + 1][2];
	silk_float Ctmp1, Ctmp2, rc_tmp;

	assert(order == 6 || order == 8 || order == 10 || order == 12
		    || order == 14 || order == 16);

	/* 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] / silk_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];
}
Beispiel #3
0
silk_float silk_schur_FLP(                  /* O    returns residual energy                                     */
    silk_float          refl_coef[],        /* O    reflection coefficients (length order)                      */
    const silk_float    auto_corr[],        /* I    autocorrelation sequence (length order+1)                   */
    opus_int            order               /* I    order                                                       */
)
{
    opus_int   k, n;
    double C[ SILK_MAX_ORDER_LPC + 1 ][ 2 ];
    double Ctmp1, Ctmp2, rc_tmp;

    celt_assert( order >= 0 && order <= SILK_MAX_ORDER_LPC );

    /* Copy correlations */
    k = 0;
    do {
        C[ k ][ 0 ] = C[ k ][ 1 ] = auto_corr[ k ];
    } while( ++k <= order );

    for( k = 0; k < order; k++ ) {
        /* Get reflection coefficient */
        rc_tmp = -C[ k + 1 ][ 0 ] / silk_max_float( C[ 0 ][ 1 ], 1e-9f );

        /* Save the output */
        refl_coef[ k ] = (silk_float)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 (silk_float)C[ 0 ][ 1 ];
}
Beispiel #4
0
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                         */
    silk_float                      res[],                              /* O    Residual                                    */
    const silk_float                x[],                                /* I    Speech signal                               */
    int                             arch                                /* I    Run-time architecture                       */
)
{
    opus_int   buf_len;
    silk_float thrhld, res_nrg;
    const silk_float *x_buf_ptr, *x_buf;
    silk_float auto_corr[ MAX_FIND_PITCH_LPC_ORDER + 1 ];
    silk_float A[         MAX_FIND_PITCH_LPC_ORDER ];
    silk_float refl_coef[ MAX_FIND_PITCH_LPC_ORDER ];
    silk_float Wsig[      FIND_PITCH_LPC_WIN_MAX ];
    silk_float *Wsig_ptr;

    /******************************************/
    /* Set up buffer lengths etc based on Fs  */
    /******************************************/
    buf_len = psEnc->sCmn.la_pitch + psEnc->sCmn.frame_length + psEnc->sCmn.ltp_mem_length;

    /* Safety check */
    silk_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;
    silk_memcpy( Wsig_ptr, x_buf_ptr, ( psEnc->sCmn.pitch_LPC_win_length - ( psEnc->sCmn.la_pitch << 1 ) ) * sizeof( silk_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 ] / silk_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_BANDWIDTH_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, arch ) == 0 )
        {
            psEnc->sCmn.indices.signalType = TYPE_VOICED;
        } else {
            psEnc->sCmn.indices.signalType = TYPE_UNVOICED;
        }
    } else {
Beispiel #5
0
void silk_find_LTP_FLP(
    silk_float                      b[ MAX_NB_SUBFR * LTP_ORDER ],      /* O    LTP coefs                                   */
    silk_float                      WLTP[ MAX_NB_SUBFR * LTP_ORDER * LTP_ORDER ], /* O    Weight for LTP quantization       */
    silk_float                      *LTPredCodGain,                     /* O    LTP coding gain                             */
    const silk_float                r_lpc[],                            /* I    LPC residual                                */
    const opus_int                  lag[  MAX_NB_SUBFR ],               /* I    LTP lags                                    */
    const silk_float                Wght[ MAX_NB_SUBFR ],               /* I    Weights                                     */
    const opus_int                  subfr_length,                       /* I    Subframe length                             */
    const opus_int                  nb_subfr,                           /* I    number of subframes                         */
    const opus_int                  mem_offset                          /* I    Number of samples in LTP memory             */
)
{
    opus_int   i, k;
    silk_float *b_ptr, temp, *WLTP_ptr;
    silk_float LPC_res_nrg, LPC_LTP_res_nrg;
    silk_float d[ MAX_NB_SUBFR ], m, g, delta_b[ LTP_ORDER ];
    silk_float w[ MAX_NB_SUBFR ], nrg[ MAX_NB_SUBFR ], regu;
    silk_float Rr[ LTP_ORDER ], rr[ MAX_NB_SUBFR ];
    const silk_float *r_ptr, *lag_ptr;

    b_ptr    = b;
    WLTP_ptr = WLTP;
    r_ptr    = &r_lpc[ mem_offset ];
    for( k = 0; k < nb_subfr; k++ ) {
        lag_ptr = r_ptr - ( lag[ k ] + LTP_ORDER / 2 );

        silk_corrMatrix_FLP( lag_ptr, subfr_length, LTP_ORDER, WLTP_ptr );
        silk_corrVector_FLP( lag_ptr, r_ptr, subfr_length, LTP_ORDER, Rr );

        rr[ k ] = ( silk_float )silk_energy_FLP( r_ptr, subfr_length );
        regu = 1.0f + rr[ k ] +
            matrix_ptr( WLTP_ptr, 0, 0, LTP_ORDER ) +
            matrix_ptr( WLTP_ptr, LTP_ORDER-1, LTP_ORDER-1, LTP_ORDER );
        regu *= LTP_DAMPING / 3;
        silk_regularize_correlations_FLP( WLTP_ptr, &rr[ k ], regu, LTP_ORDER );
        silk_solve_LDL_FLP( WLTP_ptr, LTP_ORDER, Rr, b_ptr );

        /* Calculate residual energy */
        nrg[ k ] = silk_residual_energy_covar_FLP( b_ptr, WLTP_ptr, Rr, rr[ k ], LTP_ORDER );

        temp = Wght[ k ] / ( nrg[ k ] * Wght[ k ] + 0.01f * subfr_length );
        silk_scale_vector_FLP( WLTP_ptr, temp, LTP_ORDER * LTP_ORDER );
        w[ k ] = matrix_ptr( WLTP_ptr, LTP_ORDER / 2, LTP_ORDER / 2, LTP_ORDER );

        r_ptr    += subfr_length;
        b_ptr    += LTP_ORDER;
        WLTP_ptr += LTP_ORDER * LTP_ORDER;
    }

    /* Compute LTP coding gain */
    if( LTPredCodGain != NULL ) {
        LPC_LTP_res_nrg = 1e-6f;
        LPC_res_nrg     = 0.0f;
        for( k = 0; k < nb_subfr; k++ ) {
            LPC_res_nrg     += rr[  k ] * Wght[ k ];
            LPC_LTP_res_nrg += nrg[ k ] * Wght[ k ];
        }

        silk_assert( LPC_LTP_res_nrg > 0 );
        *LTPredCodGain = 3.0f * silk_log2( LPC_res_nrg / LPC_LTP_res_nrg );
    }

    /* Smoothing */
    /* d = sum( B, 1 ); */
    b_ptr = b;
    for( k = 0; k < nb_subfr; k++ ) {
        d[ k ] = 0;
        for( i = 0; i < LTP_ORDER; i++ ) {
            d[ k ] += b_ptr[ i ];
        }
        b_ptr += LTP_ORDER;
    }
    /* m = ( w * d' ) / ( sum( w ) + 1e-3 ); */
    temp = 1e-3f;
    for( k = 0; k < nb_subfr; k++ ) {
        temp += w[ k ];
    }
    m = 0;
    for( k = 0; k < nb_subfr; k++ ) {
        m += d[ k ] * w[ k ];
    }
    m = m / temp;

    b_ptr = b;
    for( k = 0; k < nb_subfr; k++ ) {
        g = LTP_SMOOTHING / ( LTP_SMOOTHING + w[ k ] ) * ( m - d[ k ] );
        temp = 0;
        for( i = 0; i < LTP_ORDER; i++ ) {
            delta_b[ i ] = silk_max_float( b_ptr[ i ], 0.1f );
            temp += delta_b[ i ];
        }
        temp = g / temp;
        for( i = 0; i < LTP_ORDER; i++ ) {
            b_ptr[ i ] = b_ptr[ i ] + delta_b[ i ] * temp;
        }
        b_ptr += LTP_ORDER;
    }
}