/* Convert LSF parameters to AR prediction filter coefficients */ void SKP_Silk_NLSF2A_stable_FLP( SKP_float *pAR, /* O LPC coefficients [ LPC_order ] */ const SKP_float *pNLSF, /* I NLSF vector [ LPC_order ] */ const SKP_int LPC_order /* I LPC order */ ) { SKP_int i; SKP_int NLSF_fix[ MAX_LPC_ORDER ]; SKP_int16 a_fix_Q12[ MAX_LPC_ORDER ]; for( i = 0; i < LPC_order; i++ ) { NLSF_fix[ i ] = ( SKP_int )SKP_CHECK_FIT16( SKP_float2int( pNLSF[ i ] * 32768.0f ) ); } SKP_Silk_NLSF2A_stable( a_fix_Q12, NLSF_fix, LPC_order ); for( i = 0; i < LPC_order; i++ ) { pAR[ i ] = ( SKP_float )a_fix_Q12[ i ] / 4096.0f; } }
/* Updates CNG estimate, and applies the CNG when packet was lost */ void SKP_Silk_CNG( SKP_Silk_decoder_state *psDec, /* I/O Decoder state */ SKP_Silk_decoder_control *psDecCtrl, /* I/O Decoder control */ SKP_int16 signal[], /* I/O Signal */ SKP_int length /* I Length of residual */ ) { SKP_int i, subfr; SKP_int32 tmp_32, Gain_Q26, max_Gain_Q16; SKP_int16 LPC_buf[ MAX_LPC_ORDER ]; SKP_int16 CNG_sig[ MAX_FRAME_LENGTH ]; SKP_Silk_CNG_struct *psCNG; psCNG = &psDec->sCNG; if( psDec->fs_kHz != psCNG->fs_kHz ) { /* Reset state */ SKP_Silk_CNG_Reset( psDec ); psCNG->fs_kHz = psDec->fs_kHz; } if( psDec->lossCnt == 0 && psDec->vadFlag == NO_VOICE_ACTIVITY ) { /* Update CNG parameters */ /* Smoothing of LSF's */ for( i = 0; i < psDec->LPC_order; i++ ) { psCNG->CNG_smth_NLSF_Q15[ i ] += SKP_SMULWB( psDec->prevNLSF_Q15[ i ] - psCNG->CNG_smth_NLSF_Q15[ i ], CNG_NLSF_SMTH_Q16 ); } /* Find the subframe with the highest gain */ max_Gain_Q16 = 0; subfr = 0; for( i = 0; i < NB_SUBFR; i++ ) { if( psDecCtrl->Gains_Q16[ i ] > max_Gain_Q16 ) { max_Gain_Q16 = psDecCtrl->Gains_Q16[ i ]; subfr = i; } } /* Update CNG excitation buffer with excitation from this subframe */ SKP_memmove( &psCNG->CNG_exc_buf_Q10[ psDec->subfr_length ], psCNG->CNG_exc_buf_Q10, ( NB_SUBFR - 1 ) * psDec->subfr_length * sizeof( SKP_int32 ) ); SKP_memcpy( psCNG->CNG_exc_buf_Q10, &psDec->exc_Q10[ subfr * psDec->subfr_length ], psDec->subfr_length * sizeof( SKP_int32 ) ); /* Smooth gains */ for( i = 0; i < NB_SUBFR; i++ ) { psCNG->CNG_smth_Gain_Q16 += SKP_SMULWB( psDecCtrl->Gains_Q16[ i ] - psCNG->CNG_smth_Gain_Q16, CNG_GAIN_SMTH_Q16 ); } } /* Add CNG when packet is lost and / or when low speech activity */ if( psDec->lossCnt ) {//|| psDec->vadFlag == NO_VOICE_ACTIVITY ) { /* Generate CNG excitation */ SKP_Silk_CNG_exc( CNG_sig, psCNG->CNG_exc_buf_Q10, psCNG->CNG_smth_Gain_Q16, length, &psCNG->rand_seed ); /* Convert CNG NLSF to filter representation */ SKP_Silk_NLSF2A_stable( LPC_buf, psCNG->CNG_smth_NLSF_Q15, psDec->LPC_order ); Gain_Q26 = ( SKP_int32 )1 << 26; /* 1.0 */ /* Generate CNG signal, by synthesis filtering */ if( psDec->LPC_order == 16 ) { SKP_Silk_LPC_synthesis_order16( CNG_sig, LPC_buf, Gain_Q26, psCNG->CNG_synth_state, CNG_sig, length ); } else { SKP_Silk_LPC_synthesis_filter( CNG_sig, LPC_buf, Gain_Q26, psCNG->CNG_synth_state, CNG_sig, length, psDec->LPC_order ); } /* Mix with signal */ for( i = 0; i < length; i++ ) { tmp_32 = signal[ i ] + CNG_sig[ i ]; signal[ i ] = SKP_SAT16( tmp_32 ); } } else { SKP_memset( psCNG->CNG_synth_state, 0, psDec->LPC_order * sizeof( SKP_int32 ) ); } }
/* Finds LPC vector from correlations, and converts to NLSF */ void SKP_Silk_find_LPC_FIX( SKP_int NLSF_Q15[], /* O NLSFs */ SKP_int *interpIndex, /* O NLSF interpolation index, only used for NLSF interpolation */ const SKP_int prev_NLSFq_Q15[], /* I previous NLSFs, only used for NLSF interpolation */ const SKP_int useInterpolatedNLSFs, /* I Flag */ const SKP_int LPC_order, /* I LPC order */ const SKP_int16 x[], /* I Input signal */ const SKP_int subfr_length /* I Input signal subframe length including preceeding samples */ ) { SKP_int k; SKP_int32 a_Q16[ MAX_LPC_ORDER ]; SKP_int isInterpLower, shift; SKP_int16 S[ MAX_LPC_ORDER ]; SKP_int32 res_nrg0, res_nrg1; SKP_int rshift0, rshift1; /* Used only for LSF interpolation */ SKP_int32 a_tmp_Q16[ MAX_LPC_ORDER ], res_nrg_interp, res_nrg, res_tmp_nrg; SKP_int res_nrg_interp_Q, res_nrg_Q, res_tmp_nrg_Q; SKP_int16 a_tmp_Q12[ MAX_LPC_ORDER ]; SKP_int NLSF0_Q15[ MAX_LPC_ORDER ]; SKP_int16 LPC_res[ ( MAX_FRAME_LENGTH + NB_SUBFR * MAX_LPC_ORDER ) / 2 ]; /* Default: no interpolation */ *interpIndex = 4; /* Burg AR analysis for the full frame */ SKP_Silk_burg_modified( &res_nrg, &res_nrg_Q, a_Q16, x, subfr_length, NB_SUBFR, SKP_FIX_CONST( FIND_LPC_COND_FAC, 32 ), LPC_order ); SKP_Silk_bwexpander_32( a_Q16, LPC_order, SKP_FIX_CONST( FIND_LPC_CHIRP, 16 ) ); if( useInterpolatedNLSFs == 1 ) { /* Optimal solution for last 10 ms */ SKP_Silk_burg_modified( &res_tmp_nrg, &res_tmp_nrg_Q, a_tmp_Q16, x + ( NB_SUBFR >> 1 ) * subfr_length, subfr_length, ( NB_SUBFR >> 1 ), SKP_FIX_CONST( FIND_LPC_COND_FAC, 32 ), LPC_order ); SKP_Silk_bwexpander_32( a_tmp_Q16, LPC_order, SKP_FIX_CONST( FIND_LPC_CHIRP, 16 ) ); /* 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 */ shift = res_tmp_nrg_Q - res_nrg_Q; if( shift >= 0 ) { if( shift < 32 ) { res_nrg = res_nrg - SKP_RSHIFT( res_tmp_nrg, shift ); } } else { SKP_assert( shift > -32 ); res_nrg = SKP_RSHIFT( res_nrg, -shift ) - res_tmp_nrg; res_nrg_Q = res_tmp_nrg_Q; } /* Convert to NLSFs */ SKP_Silk_A2NLSF( NLSF_Q15, a_tmp_Q16, LPC_order ); /* Search over interpolation indices to find the one with lowest residual energy */ for( k = 3; k >= 0; k-- ) { /* Interpolate NLSFs for first half */ SKP_Silk_interpolate( NLSF0_Q15, prev_NLSFq_Q15, NLSF_Q15, k, LPC_order ); /* Convert to LPC for residual energy evaluation */ SKP_Silk_NLSF2A_stable( a_tmp_Q12, NLSF0_Q15, LPC_order ); /* Calculate residual energy with NLSF interpolation */ SKP_memset( S, 0, LPC_order * sizeof( SKP_int16 ) ); SKP_Silk_LPC_analysis_filter( x, a_tmp_Q12, S, LPC_res, 2 * subfr_length, LPC_order ); SKP_Silk_sum_sqr_shift( &res_nrg0, &rshift0, LPC_res + LPC_order, subfr_length - LPC_order ); SKP_Silk_sum_sqr_shift( &res_nrg1, &rshift1, LPC_res + LPC_order + subfr_length, subfr_length - LPC_order ); /* Add subframe energies from first half frame */ shift = rshift0 - rshift1; if( shift >= 0 ) { res_nrg1 = SKP_RSHIFT( res_nrg1, shift ); res_nrg_interp_Q = -rshift0; } else { res_nrg0 = SKP_RSHIFT( res_nrg0, -shift ); res_nrg_interp_Q = -rshift1; } res_nrg_interp = SKP_ADD32( res_nrg0, res_nrg1 ); /* Compare with first half energy without NLSF interpolation, or best interpolated value so far */ shift = res_nrg_interp_Q - res_nrg_Q; if( shift >= 0 ) { if( SKP_RSHIFT( res_nrg_interp, shift ) < res_nrg ) { isInterpLower = SKP_TRUE; } else { isInterpLower = SKP_FALSE; } } else { if( -shift < 32 ) { if( res_nrg_interp < SKP_RSHIFT( res_nrg, -shift ) ) { isInterpLower = SKP_TRUE; } else { isInterpLower = SKP_FALSE; } } else { isInterpLower = SKP_FALSE; } } /* Determine whether current interpolated NLSFs are best so far */ if( isInterpLower == SKP_TRUE ) { /* Interpolation has lower residual energy */ res_nrg = res_nrg_interp; res_nrg_Q = res_nrg_interp_Q; *interpIndex = k; } } }
/* Limit, stabilize, convert and quantize NLSFs. */ void SKP_Silk_process_NLSFs_FIX( SKP_Silk_encoder_state_FIX *psEnc, /* I/O Encoder state FIX */ SKP_Silk_encoder_control_FIX *psEncCtrl, /* I/O Encoder control FIX */ SKP_int *pNLSF_Q15 /* I/O Normalized LSFs (quant out) (0 - (2^15-1)) */ ) { SKP_int doInterpolate; SKP_int pNLSFW_Q6[ MAX_LPC_ORDER ]; SKP_int NLSF_mu_Q15, NLSF_mu_fluc_red_Q16; SKP_int32 i_sqr_Q15; const SKP_Silk_NLSF_CB_struct *psNLSF_CB; /* Used only for NLSF interpolation */ SKP_int pNLSF0_temp_Q15[ MAX_LPC_ORDER ]; SKP_int pNLSFW0_temp_Q6[ MAX_LPC_ORDER ]; SKP_int i; SKP_assert( psEnc->speech_activity_Q8 >= 0 ); SKP_assert( psEnc->speech_activity_Q8 <= 256 ); SKP_assert( psEncCtrl->sparseness_Q8 >= 0 ); SKP_assert( psEncCtrl->sparseness_Q8 <= 256 ); 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; */ NLSF_mu_Q15 = SKP_SMLAWB( 66, -8388, psEnc->speech_activity_Q8 ); NLSF_mu_fluc_red_Q16 = SKP_SMLAWB( 6554, -838848, psEnc->speech_activity_Q8 ); } else { /* NLSF_mu = 0.005f - 0.004f * psEnc->speech_activity; */ /* NLSF_mu_fluc_red = 0.2f - 0.1f * psEnc->speech_activity - 0.1f * psEncCtrl->sparseness; */ NLSF_mu_Q15 = SKP_SMLAWB( 164, -33554, psEnc->speech_activity_Q8 ); NLSF_mu_fluc_red_Q16 = SKP_SMLAWB( 13107, -1677696, psEnc->speech_activity_Q8 + psEncCtrl->sparseness_Q8 ); } SKP_assert( NLSF_mu_Q15 >= 0 ); SKP_assert( NLSF_mu_Q15 <= 164 ); SKP_assert( NLSF_mu_fluc_red_Q16 >= 0 ); SKP_assert( NLSF_mu_fluc_red_Q16 <= 13107 ); NLSF_mu_Q15 = SKP_max( NLSF_mu_Q15, 1 ); /* Calculate NLSF weights */ TIC(NLSF_weights_FIX) SKP_Silk_NLSF_VQ_weights_laroia( pNLSFW_Q6, pNLSF_Q15, psEnc->sCmn.predictLPCOrder ); TOC(NLSF_weights_FIX) /* 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 */ SKP_Silk_interpolate( pNLSF0_temp_Q15, psEnc->sPred.prev_NLSFq_Q15, pNLSF_Q15, psEncCtrl->sCmn.NLSFInterpCoef_Q2, psEnc->sCmn.predictLPCOrder ); /* Calculate first half NLSF weights for the interpolated NLSFs */ TIC(NLSF_weights_FIX) SKP_Silk_NLSF_VQ_weights_laroia( pNLSFW0_temp_Q6, pNLSF0_temp_Q15, psEnc->sCmn.predictLPCOrder ); TOC(NLSF_weights_FIX) /* Update NLSF weights with contribution from first half */ i_sqr_Q15 = SKP_LSHIFT( SKP_SMULBB( psEncCtrl->sCmn.NLSFInterpCoef_Q2, psEncCtrl->sCmn.NLSFInterpCoef_Q2 ), 11 ); for( i = 0; i < psEnc->sCmn.predictLPCOrder; i++ ) { pNLSFW_Q6[ i ] = SKP_SMLAWB( SKP_RSHIFT( pNLSFW_Q6[ i ], 1 ), pNLSFW0_temp_Q6[ i ], i_sqr_Q15 ); SKP_assert( pNLSFW_Q6[ i ] <= SKP_int16_MAX ); SKP_assert( pNLSFW_Q6[ i ] >= 1 ); } } /* Set pointer to the NLSF codebook for the current signal type and LPC order */ psNLSF_CB = psEnc->sCmn.psNLSF_CB[ psEncCtrl->sCmn.sigtype ]; /* Quantize NLSF parameters given the trained NLSF codebooks */ TIC(MSVQ_encode_FIX) SKP_Silk_NLSF_MSVQ_encode_FIX( psEncCtrl->sCmn.NLSFIndices, pNLSF_Q15, psNLSF_CB, psEnc->sPred.prev_NLSFq_Q15, pNLSFW_Q6, NLSF_mu_Q15, NLSF_mu_fluc_red_Q16, psEnc->sCmn.NLSF_MSVQ_Survivors, psEnc->sCmn.predictLPCOrder, psEnc->sCmn.first_frame_after_reset ); TOC(MSVQ_encode_FIX) /* Convert quantized NLSFs back to LPC coefficients */ SKP_Silk_NLSF2A_stable( psEncCtrl->PredCoef_Q12[ 1 ], pNLSF_Q15, psEnc->sCmn.predictLPCOrder ); if( doInterpolate ) { /* Calculate the interpolated, quantized LSF vector for the first half */ SKP_Silk_interpolate( pNLSF0_temp_Q15, psEnc->sPred.prev_NLSFq_Q15, pNLSF_Q15, psEncCtrl->sCmn.NLSFInterpCoef_Q2, psEnc->sCmn.predictLPCOrder ); /* Convert back to LPC coefficients */ SKP_Silk_NLSF2A_stable( psEncCtrl->PredCoef_Q12[ 0 ], pNLSF0_temp_Q15, psEnc->sCmn.predictLPCOrder ); } else { /* Copy LPC coefficients for first half from second half */ SKP_memcpy( psEncCtrl->PredCoef_Q12[ 0 ], psEncCtrl->PredCoef_Q12[ 1 ], psEnc->sCmn.predictLPCOrder * sizeof( SKP_int16 ) ); } }