/* Limit, stabilize, convert and quantize NLSFs */ void SKP_Silk_process_NLSFs_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 *pNLSF /* I/O NLSFs (quantized output) */ ) { SKP_int doInterpolate; SKP_float pNLSFW[ MAX_LPC_ORDER ]; SKP_float NLSF_mu, NLSF_mu_fluc_red, i_sqr, NLSF_interpolation_factor = 0.0f; const SKP_Silk_NLSF_CB_FLP *psNLSF_CB_FLP; /* Used only for NLSF interpolation */ SKP_float pNLSF0_temp[ MAX_LPC_ORDER ]; SKP_float pNLSFW0_temp[ MAX_LPC_ORDER ]; SKP_int i; SKP_assert( psEncCtrl->sCmn.sigtype == SIG_TYPE_VOICED || psEncCtrl->sCmn.sigtype == SIG_TYPE_UNVOICED ); /***********************/ /* Calculate mu values */ /***********************/ if( psEncCtrl->sCmn.sigtype == SIG_TYPE_VOICED ) { NLSF_mu = 0.002f - 0.001f * psEnc->speech_activity; NLSF_mu_fluc_red = 0.1f - 0.05f * psEnc->speech_activity; } else { NLSF_mu = 0.005f - 0.004f * psEnc->speech_activity; NLSF_mu_fluc_red = 0.2f - 0.1f * ( psEnc->speech_activity + psEncCtrl->sparseness ); } /* Calculate NLSF weights */ SKP_Silk_NLSF_VQ_weights_laroia_FLP( pNLSFW, pNLSF, psEnc->sCmn.predictLPCOrder ); /* Update NLSF weights for interpolated NLSFs */ doInterpolate = ( psEnc->sCmn.useInterpolatedNLSFs == 1 ) && ( psEncCtrl->sCmn.NLSFInterpCoef_Q2 < ( 1 << 2 ) ); if( doInterpolate ) { /* Calculate the interpolated NLSF vector for the first half */ NLSF_interpolation_factor = 0.25f * psEncCtrl->sCmn.NLSFInterpCoef_Q2; SKP_Silk_interpolate_wrapper_FLP( pNLSF0_temp, psEnc->sPred.prev_NLSFq, pNLSF, NLSF_interpolation_factor, psEnc->sCmn.predictLPCOrder ); /* Calculate first half NLSF weights for the interpolated NLSFs */ SKP_Silk_NLSF_VQ_weights_laroia_FLP( pNLSFW0_temp, pNLSF0_temp, psEnc->sCmn.predictLPCOrder ); /* Update NLSF weights with contribution from first half */ i_sqr = NLSF_interpolation_factor * NLSF_interpolation_factor; for( i = 0; i < psEnc->sCmn.predictLPCOrder; i++ ) { pNLSFW[ i ] = 0.5f * ( pNLSFW[ i ] + i_sqr * pNLSFW0_temp[ i ] ); } } /* Set pointer to the NLSF codebook for the current signal type and LPC order */ psNLSF_CB_FLP = psEnc->psNLSF_CB_FLP[ psEncCtrl->sCmn.sigtype ]; /* Quantize NLSF parameters given the trained NLSF codebooks */ SKP_Silk_NLSF_MSVQ_encode_FLP( psEncCtrl->sCmn.NLSFIndices, pNLSF, psNLSF_CB_FLP, psEnc->sPred.prev_NLSFq, pNLSFW, NLSF_mu, NLSF_mu_fluc_red, psEnc->sCmn.NLSF_MSVQ_Survivors, psEnc->sCmn.predictLPCOrder, psEnc->sCmn.first_frame_after_reset ); /* Convert quantized NLSFs back to LPC coefficients */ SKP_Silk_NLSF2A_stable_FLP( psEncCtrl->PredCoef[ 1 ], pNLSF, psEnc->sCmn.predictLPCOrder ); if( doInterpolate ) { /* Calculate the interpolated, quantized NLSF vector for the first half */ SKP_Silk_interpolate_wrapper_FLP( pNLSF0_temp, psEnc->sPred.prev_NLSFq, pNLSF, NLSF_interpolation_factor, psEnc->sCmn.predictLPCOrder ); /* Convert back to LPC coefficients */ SKP_Silk_NLSF2A_stable_FLP( psEncCtrl->PredCoef[ 0 ], pNLSF0_temp, psEnc->sCmn.predictLPCOrder ); } else { /* Copy LPC coefficients for first half from second half */ SKP_memcpy( psEncCtrl->PredCoef[ 0 ], psEncCtrl->PredCoef[ 1 ], psEnc->sCmn.predictLPCOrder * sizeof( SKP_float ) ); } }
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 ); } }