/* High-pass filter with cutoff frequency adaptation based on pitch lag statistics */ void silk_HP_variable_cutoff(silk_encoder_state_Fxx state_Fxx[] /* I/O Encoder states */ ) { int quality_Q15; int32_t pitch_freq_Hz_Q16, pitch_freq_log_Q7, delta_freq_Q7; silk_encoder_state *psEncC1 = &state_Fxx[0].sCmn; /* Adaptive cutoff frequency: estimate low end of pitch frequency range */ if (psEncC1->prevSignalType == TYPE_VOICED) { /* difference, in log domain */ pitch_freq_Hz_Q16 = silk_DIV32_16(silk_LSHIFT (silk_MUL(psEncC1->fs_kHz, 1000), 16), psEncC1->prevLag); pitch_freq_log_Q7 = silk_lin2log(pitch_freq_Hz_Q16) - (16 << 7); /* adjustment based on quality */ quality_Q15 = psEncC1->input_quality_bands_Q15[0]; pitch_freq_log_Q7 = silk_SMLAWB(pitch_freq_log_Q7, silk_SMULWB(silk_LSHIFT(-quality_Q15, 2), quality_Q15), pitch_freq_log_Q7 - (silk_lin2log (SILK_FIX_CONST(VARIABLE_HP_MIN_CUTOFF_HZ, 16)) - (16 << 7))); /* delta_freq = pitch_freq_log - psEnc->variable_HP_smth1; */ delta_freq_Q7 = pitch_freq_log_Q7 - silk_RSHIFT(psEncC1->variable_HP_smth1_Q15, 8); if (delta_freq_Q7 < 0) { /* less smoothing for decreasing pitch frequency, to track something close to the minimum */ delta_freq_Q7 = silk_MUL(delta_freq_Q7, 3); } /* limit delta, to reduce impact of outliers in pitch estimation */ delta_freq_Q7 = silk_LIMIT_32(delta_freq_Q7, -SILK_FIX_CONST(VARIABLE_HP_MAX_DELTA_FREQ, 7), SILK_FIX_CONST(VARIABLE_HP_MAX_DELTA_FREQ, 7)); /* update smoother */ psEncC1->variable_HP_smth1_Q15 = silk_SMLAWB(psEncC1->variable_HP_smth1_Q15, silk_SMULBB(psEncC1->speech_activity_Q8, delta_freq_Q7), SILK_FIX_CONST(VARIABLE_HP_SMTH_COEF1, 16)); /* limit frequency range */ psEncC1->variable_HP_smth1_Q15 = silk_LIMIT_32(psEncC1->variable_HP_smth1_Q15, silk_LSHIFT(silk_lin2log (VARIABLE_HP_MIN_CUTOFF_HZ), 8), silk_LSHIFT(silk_lin2log (VARIABLE_HP_MAX_CUTOFF_HZ), 8)); } }
/* Uses SMULL(), available on armv4 */ opus_int32 silk_schur64( /* O returns residual energy */ opus_int32 rc_Q16[], /* O Reflection coefficients [order] Q16 */ const opus_int32 c[], /* I Correlations [order+1] */ opus_int32 order /* I Prediction order */ ) { opus_int k, n; opus_int32 C[ SILK_MAX_ORDER_LPC + 1 ][ 2 ]; opus_int32 Ctmp1_Q30, Ctmp2_Q30, rc_tmp_Q31; silk_assert( order==6||order==8||order==10||order==12||order==14||order==16 ); /* Check for invalid input */ if( c[ 0 ] <= 0 ) { silk_memset( rc_Q16, 0, order * sizeof( opus_int32 ) ); return 0; } for( k = 0; k < order + 1; k++ ) { C[ k ][ 0 ] = C[ k ][ 1 ] = c[ k ]; } for( k = 0; k < order; k++ ) { /* Check that we won't be getting an unstable rc, otherwise stop here. */ if (silk_abs_int32(C[ k + 1 ][ 0 ]) >= C[ 0 ][ 1 ]) { if ( C[ k + 1 ][ 0 ] > 0 ) { rc_Q16[ k ] = -SILK_FIX_CONST( .99f, 16 ); } else { rc_Q16[ k ] = SILK_FIX_CONST( .99f, 16 ); } k++; break; } /* Get reflection coefficient: divide two Q30 values and get result in Q31 */ rc_tmp_Q31 = silk_DIV32_varQ( -C[ k + 1 ][ 0 ], C[ 0 ][ 1 ], 31 ); /* Save the output */ rc_Q16[ k ] = silk_RSHIFT_ROUND( rc_tmp_Q31, 15 ); /* Update correlations */ for( n = 0; n < order - k; n++ ) { Ctmp1_Q30 = C[ n + k + 1 ][ 0 ]; Ctmp2_Q30 = C[ n ][ 1 ]; /* Multiply and add the highest int32 */ C[ n + k + 1 ][ 0 ] = Ctmp1_Q30 + silk_SMMUL( silk_LSHIFT( Ctmp2_Q30, 1 ), rc_tmp_Q31 ); C[ n ][ 1 ] = Ctmp2_Q30 + silk_SMMUL( silk_LSHIFT( Ctmp1_Q30, 1 ), rc_tmp_Q31 ); } } for(; k < order; k++ ) { rc_Q16[ k ] = 0; } return silk_max_32( 1, C[ 0 ][ 1 ] ); }
void silk_PLC_Reset( silk_decoder_state *psDec /* I/O Decoder state */ ) { psDec->sPLC.pitchL_Q8 = silk_LSHIFT( psDec->frame_length, 8 - 1 ); psDec->sPLC.prevGain_Q16[ 0 ] = SILK_FIX_CONST( 1, 16 ); psDec->sPLC.prevGain_Q16[ 1 ] = SILK_FIX_CONST( 1, 16 ); psDec->sPLC.subfr_length = 20; psDec->sPLC.nb_subfr = 2; }
void silk_encode_do_VAD_FLP( silk_encoder_state_FLP *psEnc /* I/O Encoder state FLP */ ) { /****************************/ /* Voice Activity Detection */ /****************************/ silk_VAD_GetSA_Q8( &psEnc->sCmn, psEnc->sCmn.inputBuf + 1 ); /**************************************************/ /* Convert speech activity into VAD and DTX flags */ /**************************************************/ if( psEnc->sCmn.speech_activity_Q8 < SILK_FIX_CONST( SPEECH_ACTIVITY_DTX_THRES, 8 ) ) { psEnc->sCmn.indices.signalType = TYPE_NO_VOICE_ACTIVITY; psEnc->sCmn.noSpeechCounter++; if( psEnc->sCmn.noSpeechCounter < NB_SPEECH_FRAMES_BEFORE_DTX ) { psEnc->sCmn.inDTX = 0; } else if( psEnc->sCmn.noSpeechCounter > MAX_CONSECUTIVE_DTX + NB_SPEECH_FRAMES_BEFORE_DTX ) { psEnc->sCmn.noSpeechCounter = NB_SPEECH_FRAMES_BEFORE_DTX; psEnc->sCmn.inDTX = 0; } psEnc->sCmn.VAD_flags[ psEnc->sCmn.nFramesEncoded ] = 0; } else { psEnc->sCmn.noSpeechCounter = 0; psEnc->sCmn.inDTX = 0; psEnc->sCmn.indices.signalType = TYPE_UNVOICED; psEnc->sCmn.VAD_flags[ psEnc->sCmn.nFramesEncoded ] = 1; } }
/* Decode mid/side predictors */ void silk_stereo_decode_pred( ec_dec *psRangeDec, /* I/O Compressor data structure */ opus_int32 pred_Q13[] /* O Predictors */ ) { opus_int n, ix[ 2 ][ 3 ]; opus_int32 low_Q13, step_Q13; /* Entropy decoding */ n = ec_dec_icdf( psRangeDec, silk_stereo_pred_joint_iCDF, 8 ); ix[ 0 ][ 2 ] = silk_DIV32_16( n, 5 ); ix[ 1 ][ 2 ] = n - 5 * ix[ 0 ][ 2 ]; for( n = 0; n < 2; n++ ) { ix[ n ][ 0 ] = ec_dec_icdf( psRangeDec, silk_uniform3_iCDF, 8 ); ix[ n ][ 1 ] = ec_dec_icdf( psRangeDec, silk_uniform5_iCDF, 8 ); } /* Dequantize */ for( n = 0; n < 2; n++ ) { ix[ n ][ 0 ] += 3 * ix[ n ][ 2 ]; low_Q13 = silk_stereo_pred_quant_Q13[ ix[ n ][ 0 ] ]; step_Q13 = silk_SMULWB( silk_stereo_pred_quant_Q13[ ix[ n ][ 0 ] + 1 ] - low_Q13, SILK_FIX_CONST( 0.5 / STEREO_QUANT_SUB_STEPS, 16 ) ); pred_Q13[ n ] = silk_SMLABB( low_Q13, step_Q13, 2 * ix[ n ][ 1 ] + 1 ); } /* Subtract second from first predictor (helps when actually applying these) */ pred_Q13[ 0 ] -= pred_Q13[ 1 ]; }
/* Processing of gains */ void silk_process_gains_FIX( silk_encoder_state_FIX *psEnc, /* I/O Encoder state */ silk_encoder_control_FIX *psEncCtrl, /* I/O Encoder control */ opus_int condCoding /* I The type of conditional coding to use */ ) { silk_shape_state_FIX *psShapeSt = &psEnc->sShape; opus_int k; opus_int32 s_Q16, InvMaxSqrVal_Q16, gain, gain_squared, ResNrg, ResNrgPart, quant_offset_Q10; /* Gain reduction when LTP coding gain is high */ if( psEnc->sCmn.indices.signalType == TYPE_VOICED ) { /*s = -0.5f * silk_sigmoid( 0.25f * ( psEncCtrl->LTPredCodGain - 12.0f ) ); */ s_Q16 = -silk_sigm_Q15( silk_RSHIFT_ROUND( psEncCtrl->LTPredCodGain_Q7 - SILK_FIX_CONST( 12.0, 7 ), 4 ) ); for( k = 0; k < psEnc->sCmn.nb_subfr; k++ ) { psEncCtrl->Gains_Q16[ k ] = silk_SMLAWB( psEncCtrl->Gains_Q16[ k ], psEncCtrl->Gains_Q16[ k ], s_Q16 ); } } /* Limit the quantized signal */ /* InvMaxSqrVal = pow( 2.0f, 0.33f * ( 21.0f - SNR_dB ) ) / subfr_length; */ InvMaxSqrVal_Q16 = silk_DIV32_16( silk_log2lin( silk_SMULWB( SILK_FIX_CONST( 21 + 16 / 0.33, 7 ) - psEnc->sCmn.SNR_dB_Q7, SILK_FIX_CONST( 0.33, 16 ) ) ), psEnc->sCmn.subfr_length ); for( k = 0; k < psEnc->sCmn.nb_subfr; k++ ) { /* Soft limit on ratio residual energy and squared gains */ ResNrg = psEncCtrl->ResNrg[ k ]; ResNrgPart = silk_SMULWW( ResNrg, InvMaxSqrVal_Q16 ); if( psEncCtrl->ResNrgQ[ k ] > 0 ) { ResNrgPart = silk_RSHIFT_ROUND( ResNrgPart, psEncCtrl->ResNrgQ[ k ] ); } else { if( ResNrgPart >= silk_RSHIFT( silk_int32_MAX, -psEncCtrl->ResNrgQ[ k ] ) ) { ResNrgPart = silk_int32_MAX; } else { ResNrgPart = silk_LSHIFT( ResNrgPart, -psEncCtrl->ResNrgQ[ k ] ); } } gain = psEncCtrl->Gains_Q16[ k ]; gain_squared = silk_ADD_SAT32( ResNrgPart, silk_SMMUL( gain, gain ) ); if( gain_squared < silk_int16_MAX ) { /* recalculate with higher precision */ gain_squared = silk_SMLAWW( silk_LSHIFT( ResNrgPart, 16 ), gain, gain ); silk_assert( gain_squared > 0 ); gain = silk_SQRT_APPROX( gain_squared ); /* Q8 */ gain = silk_min( gain, silk_int32_MAX >> 8 ); psEncCtrl->Gains_Q16[ k ] = silk_LSHIFT_SAT32( gain, 8 ); /* Q16 */ } else {
void silk_noise_shape_analysis_FIX( silk_encoder_state_FIX *psEnc, /* I/O Encoder state FIX */ silk_encoder_control_FIX *psEncCtrl, /* I/O Encoder control FIX */ const opus_int16 *pitch_res, /* I LPC residual from pitch analysis */ const opus_int16 *x, /* I Input signal [ frame_length + la_shape ] */ int arch /* I Run-time architecture */ ) { silk_shape_state_FIX *psShapeSt = &psEnc->sShape; opus_int k, i, nSamples, Qnrg, b_Q14, warping_Q16, scale = 0; opus_int32 SNR_adj_dB_Q7, HarmBoost_Q16, HarmShapeGain_Q16, Tilt_Q16, tmp32; opus_int32 nrg, pre_nrg_Q30, log_energy_Q7, log_energy_prev_Q7, energy_variation_Q7; opus_int32 delta_Q16, BWExp1_Q16, BWExp2_Q16, gain_mult_Q16, gain_add_Q16, strength_Q16, b_Q8; opus_int32 auto_corr[ MAX_SHAPE_LPC_ORDER + 1 ]; opus_int32 refl_coef_Q16[ MAX_SHAPE_LPC_ORDER ]; opus_int32 AR1_Q24[ MAX_SHAPE_LPC_ORDER ]; opus_int32 AR2_Q24[ MAX_SHAPE_LPC_ORDER ]; VARDECL( opus_int16, x_windowed ); const opus_int16 *x_ptr, *pitch_res_ptr; SAVE_STACK; /* Point to start of first LPC analysis block */ x_ptr = x - psEnc->sCmn.la_shape; /****************/ /* GAIN CONTROL */ /****************/ SNR_adj_dB_Q7 = psEnc->sCmn.SNR_dB_Q7; /* Input quality is the average of the quality in the lowest two VAD bands */ psEncCtrl->input_quality_Q14 = ( opus_int )silk_RSHIFT( (opus_int32)psEnc->sCmn.input_quality_bands_Q15[ 0 ] + psEnc->sCmn.input_quality_bands_Q15[ 1 ], 2 ); /* Coding quality level, between 0.0_Q0 and 1.0_Q0, but in Q14 */ psEncCtrl->coding_quality_Q14 = silk_RSHIFT( silk_sigm_Q15( silk_RSHIFT_ROUND( SNR_adj_dB_Q7 - SILK_FIX_CONST( 20.0, 7 ), 4 ) ), 1 ); /* Reduce coding SNR during low speech activity */ if( psEnc->sCmn.useCBR == 0 ) { b_Q8 = SILK_FIX_CONST( 1.0, 8 ) - psEnc->sCmn.speech_activity_Q8; b_Q8 = silk_SMULWB( silk_LSHIFT( b_Q8, 8 ), b_Q8 ); SNR_adj_dB_Q7 = silk_SMLAWB( SNR_adj_dB_Q7, silk_SMULBB( SILK_FIX_CONST( -BG_SNR_DECR_dB, 7 ) >> ( 4 + 1 ), b_Q8 ), /* Q11*/ silk_SMULWB( SILK_FIX_CONST( 1.0, 14 ) + psEncCtrl->input_quality_Q14, psEncCtrl->coding_quality_Q14 ) ); /* Q12*/ }
/* Low-Bitrate Redundancy (LBRR) encoding. Reuse all parameters but encode excitation at lower bitrate */ static OPUS_INLINE void silk_LBRR_encode_FIX( silk_encoder_state_FIX *psEnc, /* I/O Pointer to Silk FIX encoder state */ silk_encoder_control_FIX *psEncCtrl, /* I/O Pointer to Silk FIX encoder control struct */ const opus_int32 xfw_Q3[], /* I Input signal */ opus_int condCoding /* I The type of conditional coding used so far for this frame */ ) { opus_int32 TempGains_Q16[ MAX_NB_SUBFR ]; SideInfoIndices *psIndices_LBRR = &psEnc->sCmn.indices_LBRR[ psEnc->sCmn.nFramesEncoded ]; silk_nsq_state sNSQ_LBRR; /*******************************************/ /* Control use of inband LBRR */ /*******************************************/ if( psEnc->sCmn.LBRR_enabled && psEnc->sCmn.speech_activity_Q8 > SILK_FIX_CONST( LBRR_SPEECH_ACTIVITY_THRES, 8 ) ) { psEnc->sCmn.LBRR_flags[ psEnc->sCmn.nFramesEncoded ] = 1; /* Copy noise shaping quantizer state and quantization indices from regular encoding */ silk_memcpy( &sNSQ_LBRR, &psEnc->sCmn.sNSQ, sizeof( silk_nsq_state ) ); silk_memcpy( psIndices_LBRR, &psEnc->sCmn.indices, sizeof( SideInfoIndices ) ); /* Save original gains */ silk_memcpy( TempGains_Q16, psEncCtrl->Gains_Q16, psEnc->sCmn.nb_subfr * sizeof( opus_int32 ) ); if( psEnc->sCmn.nFramesEncoded == 0 || psEnc->sCmn.LBRR_flags[ psEnc->sCmn.nFramesEncoded - 1 ] == 0 ) { /* First frame in packet or previous frame not LBRR coded */ psEnc->sCmn.LBRRprevLastGainIndex = psEnc->sShape.LastGainIndex; /* Increase Gains to get target LBRR rate */ psIndices_LBRR->GainsIndices[ 0 ] = psIndices_LBRR->GainsIndices[ 0 ] + psEnc->sCmn.LBRR_GainIncreases; psIndices_LBRR->GainsIndices[ 0 ] = silk_min_int( psIndices_LBRR->GainsIndices[ 0 ], N_LEVELS_QGAIN - 1 ); } /* Decode to get gains in sync with decoder */ /* Overwrite unquantized gains with quantized gains */ silk_gains_dequant( psEncCtrl->Gains_Q16, psIndices_LBRR->GainsIndices, &psEnc->sCmn.LBRRprevLastGainIndex, condCoding == CODE_CONDITIONALLY, psEnc->sCmn.nb_subfr ); /*****************************************/ /* Noise shaping quantization */ /*****************************************/ if( psEnc->sCmn.nStatesDelayedDecision > 1 || psEnc->sCmn.warping_Q16 > 0 ) { silk_NSQ_del_dec( &psEnc->sCmn, &sNSQ_LBRR, psIndices_LBRR, xfw_Q3, psEnc->sCmn.pulses_LBRR[ psEnc->sCmn.nFramesEncoded ], psEncCtrl->PredCoef_Q12[ 0 ], psEncCtrl->LTPCoef_Q14, psEncCtrl->AR2_Q13, psEncCtrl->HarmShapeGain_Q14, psEncCtrl->Tilt_Q14, psEncCtrl->LF_shp_Q14, psEncCtrl->Gains_Q16, psEncCtrl->pitchL, psEncCtrl->Lambda_Q10, psEncCtrl->LTP_scale_Q14 ); } else { silk_NSQ( &psEnc->sCmn, &sNSQ_LBRR, psIndices_LBRR, xfw_Q3, psEnc->sCmn.pulses_LBRR[ psEnc->sCmn.nFramesEncoded ], psEncCtrl->PredCoef_Q12[ 0 ], psEncCtrl->LTPCoef_Q14, psEncCtrl->AR2_Q13, psEncCtrl->HarmShapeGain_Q14, psEncCtrl->Tilt_Q14, psEncCtrl->LF_shp_Q14, psEncCtrl->Gains_Q16, psEncCtrl->pitchL, psEncCtrl->Lambda_Q10, psEncCtrl->LTP_scale_Q14 ); } /* Restore original gains */ silk_memcpy( psEncCtrl->Gains_Q16, TempGains_Q16, psEnc->sCmn.nb_subfr * sizeof( opus_int32 ) ); } }
/* Low-Bitrate Redundancy (LBRR) encoding. Reuse all parameters but encode excitation at lower bitrate */ static void silk_LBRR_encode_FLP( silk_encoder_state_FLP *psEnc, /* I/O Encoder state FLP */ silk_encoder_control_FLP *psEncCtrl, /* I/O Encoder control FLP */ const silk_float xfw[], /* I Input signal */ opus_int condCoding /* I The type of conditional coding used so far for this frame */ ) { opus_int k; opus_int32 Gains_Q16[ MAX_NB_SUBFR ]; silk_float TempGains[ MAX_NB_SUBFR ]; SideInfoIndices *psIndices_LBRR = &psEnc->sCmn.indices_LBRR[ psEnc->sCmn.nFramesEncoded ]; silk_nsq_state sNSQ_LBRR; /*******************************************/ /* Control use of inband LBRR */ /*******************************************/ if( psEnc->sCmn.LBRR_enabled && psEnc->sCmn.speech_activity_Q8 > SILK_FIX_CONST( LBRR_SPEECH_ACTIVITY_THRES, 8 ) ) { psEnc->sCmn.LBRR_flags[ psEnc->sCmn.nFramesEncoded ] = 1; /* Copy noise shaping quantizer state and quantization indices from regular encoding */ silk_memcpy( &sNSQ_LBRR, &psEnc->sCmn.sNSQ, sizeof( silk_nsq_state ) ); silk_memcpy( psIndices_LBRR, &psEnc->sCmn.indices, sizeof( SideInfoIndices ) ); /* Save original gains */ silk_memcpy( TempGains, psEncCtrl->Gains, psEnc->sCmn.nb_subfr * sizeof( silk_float ) ); if( psEnc->sCmn.nFramesEncoded == 0 || psEnc->sCmn.LBRR_flags[ psEnc->sCmn.nFramesEncoded - 1 ] == 0 ) { /* First frame in packet or previous frame not LBRR coded */ psEnc->sCmn.LBRRprevLastGainIndex = psEnc->sShape.LastGainIndex; /* Increase Gains to get target LBRR rate */ psIndices_LBRR->GainsIndices[ 0 ] += psEnc->sCmn.LBRR_GainIncreases; psIndices_LBRR->GainsIndices[ 0 ] = silk_min_int( psIndices_LBRR->GainsIndices[ 0 ], N_LEVELS_QGAIN - 1 ); } /* Decode to get gains in sync with decoder */ silk_gains_dequant( Gains_Q16, psIndices_LBRR->GainsIndices, &psEnc->sCmn.LBRRprevLastGainIndex, condCoding == CODE_CONDITIONALLY, psEnc->sCmn.nb_subfr ); /* Overwrite unquantized gains with quantized gains and convert back to Q0 from Q16 */ for( k = 0; k < psEnc->sCmn.nb_subfr; k++ ) { psEncCtrl->Gains[ k ] = Gains_Q16[ k ] * ( 1.0f / 65536.0f ); } /*****************************************/ /* Noise shaping quantization */ /*****************************************/ silk_NSQ_wrapper_FLP( psEnc, psEncCtrl, psIndices_LBRR, &sNSQ_LBRR, psEnc->sCmn.pulses_LBRR[ psEnc->sCmn.nFramesEncoded ], xfw ); /* Restore original gains */ silk_memcpy( psEncCtrl->Gains, TempGains, psEnc->sCmn.nb_subfr * sizeof( silk_float ) ); } }
/* Predictive dequantizer for NLSF residuals */ static OPUS_INLINE void silk_NLSF_residual_dequant( /* O Returns RD value in Q30 */ opus_int16 x_Q10[], /* O Output [ order ] */ const opus_int8 indices[], /* I Quantization indices [ order ] */ const opus_uint8 pred_coef_Q8[], /* I Backward predictor coefs [ order ] */ const opus_int quant_step_size_Q16, /* I Quantization step size */ const opus_int16 order /* I Number of input values */ ) { opus_int i, out_Q10, pred_Q10; out_Q10 = 0; for( i = order-1; i >= 0; i-- ) { pred_Q10 = silk_RSHIFT( silk_SMULBB( out_Q10, (opus_int16)pred_coef_Q8[ i ] ), 8 ); out_Q10 = silk_LSHIFT( indices[ i ], 10 ); if( out_Q10 > 0 ) { out_Q10 = silk_SUB16( out_Q10, SILK_FIX_CONST( NLSF_QUANT_LEVEL_ADJ, 10 ) ); } else if( out_Q10 < 0 ) { out_Q10 = silk_ADD16( out_Q10, SILK_FIX_CONST( NLSF_QUANT_LEVEL_ADJ, 10 ) ); } out_Q10 = silk_SMLAWB( pred_Q10, (opus_int32)out_Q10, quant_step_size_Q16 ); x_Q10[ i ] = out_Q10; } }
/* Control SNR of redidual quantizer */ opus_int silk_control_SNR( silk_encoder_state *psEncC, /* I/O Pointer to Silk encoder state */ opus_int32 TargetRate_bps /* I Target max bitrate (bps) */ ) { opus_int k, ret = SILK_NO_ERROR; opus_int32 frac_Q6; const opus_int32 *rateTable; /* Set bitrate/coding quality */ TargetRate_bps = silk_LIMIT(TargetRate_bps, MIN_TARGET_RATE_BPS, MAX_TARGET_RATE_BPS); if (TargetRate_bps != psEncC->TargetRate_bps) { psEncC->TargetRate_bps = TargetRate_bps; /* If new TargetRate_bps, translate to SNR_dB value */ if (psEncC->fs_kHz == 8) { rateTable = silk_TargetRate_table_NB; } else if (psEncC->fs_kHz == 12) { rateTable = silk_TargetRate_table_MB; } else { rateTable = silk_TargetRate_table_WB; } /* Reduce bitrate for 10 ms modes in these calculations */ if (psEncC->nb_subfr == 2) { TargetRate_bps -= REDUCE_BITRATE_10_MS_BPS; } /* Find bitrate interval in table and interpolate */ for (k = 1; k < TARGET_RATE_TAB_SZ; k++) { if (TargetRate_bps <= rateTable[k]) { frac_Q6 = silk_DIV32(silk_LSHIFT(TargetRate_bps - rateTable[k - 1], 6), rateTable[k] - rateTable[k - 1]); psEncC->SNR_dB_Q7 = silk_LSHIFT(silk_SNR_table_Q1[k - 1], 6) + silk_MUL(frac_Q6, silk_SNR_table_Q1[k] - silk_SNR_table_Q1[ k - 1]); break; } } /* Reduce coding quality whenever LBRR is enabled, to free up some bits */ if (psEncC->LBRR_enabled) { psEncC->SNR_dB_Q7 = silk_SMLABB(psEncC->SNR_dB_Q7, 12 - psEncC->LBRR_GainIncreases, SILK_FIX_CONST(-0.25, 7)); } } return ret; }
/* coefficient in an array of coefficients, for monic filters. */ static inline opus_int32 warped_gain( /* gain in Q16*/ const opus_int32 *coefs_Q24, opus_int lambda_Q16, opus_int order ) { opus_int i; opus_int32 gain_Q24; lambda_Q16 = -lambda_Q16; gain_Q24 = coefs_Q24[ order - 1 ]; for( i = order - 2; i >= 0; i-- ) { gain_Q24 = silk_SMLAWB( coefs_Q24[ i ], gain_Q24, lambda_Q16 ); } gain_Q24 = silk_SMLAWB( SILK_FIX_CONST( 1.0, 24 ), gain_Q24, -lambda_Q16 ); return silk_INVERSE32_varQ( gain_Q24, 40 ); }
/* Convert int32 coefficients to int16 coefs and make sure there's no wrap-around */ void silk_LPC_fit( opus_int16 *a_QOUT, /* O Output signal */ opus_int32 *a_QIN, /* I/O Input signal */ const opus_int QOUT, /* I Input Q domain */ const opus_int QIN, /* I Input Q domain */ const opus_int d /* I Filter order */ ) { opus_int i, k, idx = 0; opus_int32 maxabs, absval, chirp_Q16; /* Limit the maximum absolute value of the prediction coefficients, so that they'll fit in int16 */ for( i = 0; i < 10; i++ ) { /* Find maximum absolute value and its index */ maxabs = 0; for( k = 0; k < d; k++ ) { absval = silk_abs( a_QIN[k] ); if( absval > maxabs ) { maxabs = absval; idx = k; } } maxabs = silk_RSHIFT_ROUND( maxabs, QIN - QOUT ); if( maxabs > silk_int16_MAX ) { /* Reduce magnitude of prediction coefficients */ maxabs = silk_min( maxabs, 163838 ); /* ( silk_int32_MAX >> 14 ) + silk_int16_MAX = 163838 */ chirp_Q16 = SILK_FIX_CONST( 0.999, 16 ) - silk_DIV32( silk_LSHIFT( maxabs - silk_int16_MAX, 14 ), silk_RSHIFT32( silk_MUL( maxabs, idx + 1), 2 ) ); silk_bwexpander_32( a_QIN, d, chirp_Q16 ); } else { break; } } if( i == 10 ) { /* Reached the last iteration, clip the coefficients */ for( k = 0; k < d; k++ ) { a_QOUT[ k ] = (opus_int16)silk_SAT16( silk_RSHIFT_ROUND( a_QIN[ k ], QIN - QOUT ) ); a_QIN[ k ] = silk_LSHIFT( (opus_int32)a_QOUT[ k ], QIN - QOUT ); } } else { for( k = 0; k < d; k++ ) { a_QOUT[ k ] = (opus_int16)silk_RSHIFT_ROUND( a_QIN[ k ], QIN - QOUT ); } } }
/* Calculation of LTP state scaling */ void silk_LTP_scale_ctrl_FIX( silk_encoder_state_FIX *psEnc, /* I/O encoder state */ silk_encoder_control_FIX *psEncCtrl, /* I/O encoder control */ opus_int condCoding /* I The type of conditional coding to use */ ) { opus_int round_loss; if( condCoding == CODE_INDEPENDENTLY ) { /* Only scale if first frame in packet */ round_loss = psEnc->sCmn.PacketLoss_perc + psEnc->sCmn.nFramesPerPacket; psEnc->sCmn.indices.LTP_scaleIndex = (opus_int8)silk_LIMIT( silk_SMULWB( silk_SMULBB( round_loss, psEncCtrl->LTPredCodGain_Q7 ), SILK_FIX_CONST( 0.1, 9 ) ), 0, 2 ); } else { /* Default is minimum scaling */ psEnc->sCmn.indices.LTP_scaleIndex = 0; } psEncCtrl->LTP_scale_Q14 = silk_LTPScales_table_Q14[ psEnc->sCmn.indices.LTP_scaleIndex ]; }
opus_int silk_init_encoder( silk_encoder_state_Fxx *psEnc /* I/O Pointer to Silk FIX encoder state */ ) { opus_int ret = 0; /* Clear the entire encoder state */ silk_memset( psEnc, 0, sizeof( silk_encoder_state_Fxx ) ); psEnc->sCmn.variable_HP_smth1_Q15 = silk_LSHIFT( silk_lin2log( SILK_FIX_CONST( VARIABLE_HP_MIN_CUTOFF_HZ, 16 ) ) - ( 16 << 7 ), 8 ); psEnc->sCmn.variable_HP_smth2_Q15 = psEnc->sCmn.variable_HP_smth1_Q15; /* Used to deactivate LSF interpolation, pitch prediction */ psEnc->sCmn.first_frame_after_reset = 1; /* Initialize Silk VAD */ ret += silk_VAD_Init( &psEnc->sCmn.sVAD ); return ret; }
/* Quantize mid/side predictors */ void silk_stereo_quant_pred( opus_int32 pred_Q13[], /* I/O Predictors (out: quantized) */ opus_int8 ix[ 2 ][ 3 ] /* O Quantization indices */ ) { opus_int i, j, n; opus_int32 low_Q13, step_Q13, lvl_Q13, err_min_Q13, err_Q13, quant_pred_Q13 = 0; /* Quantize */ for( n = 0; n < 2; n++ ) { /* Brute-force search over quantization levels */ err_min_Q13 = silk_int32_MAX; for( i = 0; i < STEREO_QUANT_TAB_SIZE - 1; i++ ) { low_Q13 = silk_stereo_pred_quant_Q13[ i ]; step_Q13 = silk_SMULWB( silk_stereo_pred_quant_Q13[ i + 1 ] - low_Q13, SILK_FIX_CONST( 0.5 / STEREO_QUANT_SUB_STEPS, 16 ) ); for( j = 0; j < STEREO_QUANT_SUB_STEPS; j++ ) { lvl_Q13 = silk_SMLABB( low_Q13, step_Q13, 2 * j + 1 ); err_Q13 = silk_abs( pred_Q13[ n ] - lvl_Q13 ); if( err_Q13 < err_min_Q13 ) { err_min_Q13 = err_Q13; quant_pred_Q13 = lvl_Q13; ix[ n ][ 0 ] = i; ix[ n ][ 1 ] = j; } else { /* Error increasing, so we're past the optimum */ goto done; } } } done: ix[ n ][ 2 ] = silk_DIV32_16( ix[ n ][ 0 ], 3 ); ix[ n ][ 0 ] -= ix[ n ][ 2 ] * 3; pred_Q13[ n ] = quant_pred_Q13; } /* Subtract second from first predictor (helps when actually applying these) */ pred_Q13[ 0 ] -= pred_Q13[ 1 ]; }
void silk_encode_do_VAD_FIX( silk_encoder_state_FIX *psEnc, /* I/O Pointer to Silk FIX encoder state */ opus_int activity /* I Decision of Opus voice activity detector */ ) { const opus_int activity_threshold = SILK_FIX_CONST( SPEECH_ACTIVITY_DTX_THRES, 8 ); /****************************/ /* Voice Activity Detection */ /****************************/ silk_VAD_GetSA_Q8( &psEnc->sCmn, psEnc->sCmn.inputBuf + 1, psEnc->sCmn.arch ); /* If Opus VAD is inactive and Silk VAD is active: lower Silk VAD to just under the threshold */ if( activity == VAD_NO_ACTIVITY && psEnc->sCmn.speech_activity_Q8 >= activity_threshold ) { psEnc->sCmn.speech_activity_Q8 = activity_threshold - 1; } /**************************************************/ /* Convert speech activity into VAD and DTX flags */ /**************************************************/ if( psEnc->sCmn.speech_activity_Q8 < activity_threshold ) { psEnc->sCmn.indices.signalType = TYPE_NO_VOICE_ACTIVITY; psEnc->sCmn.noSpeechCounter++; if( psEnc->sCmn.noSpeechCounter <= NB_SPEECH_FRAMES_BEFORE_DTX ) { psEnc->sCmn.inDTX = 0; } else if( psEnc->sCmn.noSpeechCounter > MAX_CONSECUTIVE_DTX + NB_SPEECH_FRAMES_BEFORE_DTX ) { psEnc->sCmn.noSpeechCounter = NB_SPEECH_FRAMES_BEFORE_DTX; psEnc->sCmn.inDTX = 0; } psEnc->sCmn.VAD_flags[ psEnc->sCmn.nFramesEncoded ] = 0; } else { psEnc->sCmn.noSpeechCounter = 0; psEnc->sCmn.inDTX = 0; psEnc->sCmn.indices.signalType = TYPE_UNVOICED; psEnc->sCmn.VAD_flags[ psEnc->sCmn.nFramesEncoded ] = 1; } }
static inline opus_int silk_setup_LBRR( silk_encoder_state *psEncC, /* I/O */ const opus_int32 TargetRate_bps /* I */ ) { opus_int ret = SILK_NO_ERROR; opus_int32 LBRR_rate_thres_bps; psEncC->LBRR_enabled = 0; if( psEncC->useInBandFEC && psEncC->PacketLoss_perc > 0 ) { if( psEncC->fs_kHz == 8 ) { LBRR_rate_thres_bps = LBRR_NB_MIN_RATE_BPS; } else if( psEncC->fs_kHz == 12 ) { LBRR_rate_thres_bps = LBRR_MB_MIN_RATE_BPS; } else { LBRR_rate_thres_bps = LBRR_WB_MIN_RATE_BPS; } LBRR_rate_thres_bps = silk_SMULWB( silk_MUL( LBRR_rate_thres_bps, 125 - silk_min( psEncC->PacketLoss_perc, 25 ) ), SILK_FIX_CONST( 0.01, 16 ) ); if( TargetRate_bps > LBRR_rate_thres_bps ) { /* Set gain increase for coding LBRR excitation */ psEncC->LBRR_enabled = 1; psEncC->LBRR_GainIncreases = silk_max_int( 7 - silk_SMULWB( psEncC->PacketLoss_perc, SILK_FIX_CONST( 0.4, 16 ) ), 2 ); } } return ret; }
opus_int silk_setup_complexity( silk_encoder_state *psEncC, /* I/O */ opus_int Complexity /* I */ ) { opus_int ret = 0; /* Set encoding complexity */ silk_assert( Complexity >= 0 && Complexity <= 10 ); if( Complexity < 2 ) { psEncC->pitchEstimationComplexity = SILK_PE_MIN_COMPLEX; psEncC->pitchEstimationThreshold_Q16 = SILK_FIX_CONST( 0.8, 16 ); psEncC->pitchEstimationLPCOrder = 6; psEncC->shapingLPCOrder = 8; psEncC->la_shape = 3 * psEncC->fs_kHz; psEncC->nStatesDelayedDecision = 1; psEncC->useInterpolatedNLSFs = 0; psEncC->LTPQuantLowComplexity = 1; psEncC->NLSF_MSVQ_Survivors = 2; psEncC->warping_Q16 = 0; } else if( Complexity < 4 ) { psEncC->pitchEstimationComplexity = SILK_PE_MID_COMPLEX; psEncC->pitchEstimationThreshold_Q16 = SILK_FIX_CONST( 0.76, 16 ); psEncC->pitchEstimationLPCOrder = 8; psEncC->shapingLPCOrder = 10; psEncC->la_shape = 5 * psEncC->fs_kHz; psEncC->nStatesDelayedDecision = 1; psEncC->useInterpolatedNLSFs = 0; psEncC->LTPQuantLowComplexity = 0; psEncC->NLSF_MSVQ_Survivors = 4; psEncC->warping_Q16 = 0; } else if( Complexity < 6 ) { psEncC->pitchEstimationComplexity = SILK_PE_MID_COMPLEX; psEncC->pitchEstimationThreshold_Q16 = SILK_FIX_CONST( 0.74, 16 ); psEncC->pitchEstimationLPCOrder = 10; psEncC->shapingLPCOrder = 12; psEncC->la_shape = 5 * psEncC->fs_kHz; psEncC->nStatesDelayedDecision = 2; psEncC->useInterpolatedNLSFs = 1; psEncC->LTPQuantLowComplexity = 0; psEncC->NLSF_MSVQ_Survivors = 8; psEncC->warping_Q16 = psEncC->fs_kHz * SILK_FIX_CONST( WARPING_MULTIPLIER, 16 ); } else if( Complexity < 8 ) { psEncC->pitchEstimationComplexity = SILK_PE_MID_COMPLEX; psEncC->pitchEstimationThreshold_Q16 = SILK_FIX_CONST( 0.72, 16 ); psEncC->pitchEstimationLPCOrder = 12; psEncC->shapingLPCOrder = 14; psEncC->la_shape = 5 * psEncC->fs_kHz; psEncC->nStatesDelayedDecision = 3; psEncC->useInterpolatedNLSFs = 1; psEncC->LTPQuantLowComplexity = 0; psEncC->NLSF_MSVQ_Survivors = 16; psEncC->warping_Q16 = psEncC->fs_kHz * SILK_FIX_CONST( WARPING_MULTIPLIER, 16 ); } else { psEncC->pitchEstimationComplexity = SILK_PE_MAX_COMPLEX; psEncC->pitchEstimationThreshold_Q16 = SILK_FIX_CONST( 0.7, 16 ); psEncC->pitchEstimationLPCOrder = 16; psEncC->shapingLPCOrder = 16; psEncC->la_shape = 5 * psEncC->fs_kHz; psEncC->nStatesDelayedDecision = MAX_DEL_DEC_STATES; psEncC->useInterpolatedNLSFs = 1; psEncC->LTPQuantLowComplexity = 0; psEncC->NLSF_MSVQ_Survivors = 32; psEncC->warping_Q16 = psEncC->fs_kHz * SILK_FIX_CONST( WARPING_MULTIPLIER, 16 ); } /* Do not allow higher pitch estimation LPC order than predict LPC order */ psEncC->pitchEstimationLPCOrder = silk_min_int( psEncC->pitchEstimationLPCOrder, psEncC->predictLPCOrder ); psEncC->shapeWinLength = SUB_FRAME_LENGTH_MS * psEncC->fs_kHz + 2 * psEncC->la_shape; psEncC->Complexity = Complexity; silk_assert( psEncC->pitchEstimationLPCOrder <= MAX_FIND_PITCH_LPC_ORDER ); silk_assert( psEncC->shapingLPCOrder <= MAX_SHAPE_LPC_ORDER ); silk_assert( psEncC->nStatesDelayedDecision <= MAX_DEL_DEC_STATES ); silk_assert( psEncC->warping_Q16 <= 32767 ); silk_assert( psEncC->la_shape <= LA_SHAPE_MAX ); silk_assert( psEncC->shapeWinLength <= SHAPE_LPC_WIN_MAX ); silk_assert( psEncC->NLSF_MSVQ_Survivors <= NLSF_VQ_MAX_SURVIVORS ); return ret; }
opus_int silk_setup_fs( silk_encoder_state_Fxx *psEnc, /* I/O */ opus_int fs_kHz, /* I */ opus_int PacketSize_ms /* I */ ) { opus_int ret = SILK_NO_ERROR; /* Set packet size */ if( PacketSize_ms != psEnc->sCmn.PacketSize_ms ) { if( ( PacketSize_ms != 10 ) && ( PacketSize_ms != 20 ) && ( PacketSize_ms != 40 ) && ( PacketSize_ms != 60 ) ) { ret = SILK_ENC_PACKET_SIZE_NOT_SUPPORTED; } if( PacketSize_ms <= 10 ) { psEnc->sCmn.nFramesPerPacket = 1; psEnc->sCmn.nb_subfr = PacketSize_ms == 10 ? 2 : 1; psEnc->sCmn.frame_length = silk_SMULBB( PacketSize_ms, fs_kHz ); psEnc->sCmn.pitch_LPC_win_length = silk_SMULBB( FIND_PITCH_LPC_WIN_MS_2_SF, fs_kHz ); if( psEnc->sCmn.fs_kHz == 8 ) { psEnc->sCmn.pitch_contour_iCDF = silk_pitch_contour_10_ms_NB_iCDF; } else { psEnc->sCmn.pitch_contour_iCDF = silk_pitch_contour_10_ms_iCDF; } } else { psEnc->sCmn.nFramesPerPacket = silk_DIV32_16( PacketSize_ms, MAX_FRAME_LENGTH_MS ); psEnc->sCmn.nb_subfr = MAX_NB_SUBFR; psEnc->sCmn.frame_length = silk_SMULBB( 20, fs_kHz ); psEnc->sCmn.pitch_LPC_win_length = silk_SMULBB( FIND_PITCH_LPC_WIN_MS, fs_kHz ); if( psEnc->sCmn.fs_kHz == 8 ) { psEnc->sCmn.pitch_contour_iCDF = silk_pitch_contour_NB_iCDF; } else { psEnc->sCmn.pitch_contour_iCDF = silk_pitch_contour_iCDF; } } psEnc->sCmn.PacketSize_ms = PacketSize_ms; psEnc->sCmn.TargetRate_bps = 0; /* trigger new SNR computation */ } /* Set internal sampling frequency */ silk_assert( fs_kHz == 8 || fs_kHz == 12 || fs_kHz == 16 ); silk_assert( psEnc->sCmn.nb_subfr == 2 || psEnc->sCmn.nb_subfr == 4 ); if( psEnc->sCmn.fs_kHz != fs_kHz ) { /* reset part of the state */ silk_memset( &psEnc->sShape, 0, sizeof( psEnc->sShape ) ); silk_memset( &psEnc->sPrefilt, 0, sizeof( psEnc->sPrefilt ) ); silk_memset( &psEnc->sCmn.sNSQ, 0, sizeof( psEnc->sCmn.sNSQ ) ); silk_memset( psEnc->sCmn.prev_NLSFq_Q15, 0, sizeof( psEnc->sCmn.prev_NLSFq_Q15 ) ); silk_memset( &psEnc->sCmn.sLP.In_LP_State, 0, sizeof( psEnc->sCmn.sLP.In_LP_State ) ); psEnc->sCmn.inputBufIx = 0; psEnc->sCmn.nFramesEncoded = 0; psEnc->sCmn.TargetRate_bps = 0; /* trigger new SNR computation */ /* Initialize non-zero parameters */ psEnc->sCmn.prevLag = 100; psEnc->sCmn.first_frame_after_reset = 1; psEnc->sPrefilt.lagPrev = 100; psEnc->sShape.LastGainIndex = 10; psEnc->sCmn.sNSQ.lagPrev = 100; psEnc->sCmn.sNSQ.prev_gain_Q16 = 65536; psEnc->sCmn.prevSignalType = TYPE_NO_VOICE_ACTIVITY; psEnc->sCmn.fs_kHz = fs_kHz; if( psEnc->sCmn.fs_kHz == 8 ) { if( psEnc->sCmn.nb_subfr == MAX_NB_SUBFR ) { psEnc->sCmn.pitch_contour_iCDF = silk_pitch_contour_NB_iCDF; } else { psEnc->sCmn.pitch_contour_iCDF = silk_pitch_contour_10_ms_NB_iCDF; } } else { if( psEnc->sCmn.nb_subfr == MAX_NB_SUBFR ) { psEnc->sCmn.pitch_contour_iCDF = silk_pitch_contour_iCDF; } else { psEnc->sCmn.pitch_contour_iCDF = silk_pitch_contour_10_ms_iCDF; } } if( psEnc->sCmn.fs_kHz == 8 || psEnc->sCmn.fs_kHz == 12 ) { psEnc->sCmn.predictLPCOrder = MIN_LPC_ORDER; psEnc->sCmn.psNLSF_CB = &silk_NLSF_CB_NB_MB; } else { psEnc->sCmn.predictLPCOrder = MAX_LPC_ORDER; psEnc->sCmn.psNLSF_CB = &silk_NLSF_CB_WB; } psEnc->sCmn.subfr_length = SUB_FRAME_LENGTH_MS * fs_kHz; psEnc->sCmn.frame_length = silk_SMULBB( psEnc->sCmn.subfr_length, psEnc->sCmn.nb_subfr ); psEnc->sCmn.ltp_mem_length = silk_SMULBB( LTP_MEM_LENGTH_MS, fs_kHz ); psEnc->sCmn.la_pitch = silk_SMULBB( LA_PITCH_MS, fs_kHz ); psEnc->sCmn.max_pitch_lag = silk_SMULBB( 18, fs_kHz ); if( psEnc->sCmn.nb_subfr == MAX_NB_SUBFR ) { psEnc->sCmn.pitch_LPC_win_length = silk_SMULBB( FIND_PITCH_LPC_WIN_MS, fs_kHz ); } else { psEnc->sCmn.pitch_LPC_win_length = silk_SMULBB( FIND_PITCH_LPC_WIN_MS_2_SF, fs_kHz ); } if( psEnc->sCmn.fs_kHz == 16 ) { psEnc->sCmn.mu_LTP_Q9 = SILK_FIX_CONST( MU_LTP_QUANT_WB, 9 ); psEnc->sCmn.pitch_lag_low_bits_iCDF = silk_uniform8_iCDF; } else if( psEnc->sCmn.fs_kHz == 12 ) { psEnc->sCmn.mu_LTP_Q9 = SILK_FIX_CONST( MU_LTP_QUANT_MB, 9 ); psEnc->sCmn.pitch_lag_low_bits_iCDF = silk_uniform6_iCDF; } else { psEnc->sCmn.mu_LTP_Q9 = SILK_FIX_CONST( MU_LTP_QUANT_NB, 9 ); psEnc->sCmn.pitch_lag_low_bits_iCDF = silk_uniform4_iCDF; } } /* Check that settings are valid */ silk_assert( ( psEnc->sCmn.subfr_length * psEnc->sCmn.nb_subfr ) == psEnc->sCmn.frame_length ); return ret; }
}; static const opus_uint8 silk_NLSF_PRED_WB_Q8[ 30 ] = { 175, 148, 160, 176, 178, 173, 174, 164, 177, 174, 196, 182, 198, 192, 182, 68, 62, 66, 60, 72, 117, 85, 90, 118, 136, 151, 142, 160, 142, 155 }; static const opus_int16 silk_NLSF_DELTA_MIN_WB_Q15[ 17 ] = { 100, 3, 40, 3, 3, 3, 5, 14, 14, 10, 11, 3, 8, 9, 7, 3, 347 }; const silk_NLSF_CB_struct silk_NLSF_CB_WB = { 32, 16, SILK_FIX_CONST( 0.15, 16 ), SILK_FIX_CONST( 1.0 / 0.15, 6 ), silk_NLSF_CB1_WB_Q8, silk_NLSF_CB1_iCDF_WB, silk_NLSF_PRED_WB_Q8, silk_NLSF_CB2_SELECT_WB, silk_NLSF_CB2_iCDF_WB, silk_NLSF_CB2_BITS_WB_Q5, silk_NLSF_DELTA_MIN_WB_Q15, };
/* amplitude of monic warped coefficients by using bandwidth expansion on the true coefficients */ static inline void limit_warped_coefs( opus_int32 *coefs_syn_Q24, opus_int32 *coefs_ana_Q24, opus_int lambda_Q16, opus_int32 limit_Q24, opus_int order ) { opus_int i, iter, ind = 0; opus_int32 tmp, maxabs_Q24, chirp_Q16, gain_syn_Q16, gain_ana_Q16; opus_int32 nom_Q16, den_Q24; /* Convert to monic coefficients */ lambda_Q16 = -lambda_Q16; for( i = order - 1; i > 0; i-- ) { coefs_syn_Q24[ i - 1 ] = silk_SMLAWB( coefs_syn_Q24[ i - 1 ], coefs_syn_Q24[ i ], lambda_Q16 ); coefs_ana_Q24[ i - 1 ] = silk_SMLAWB( coefs_ana_Q24[ i - 1 ], coefs_ana_Q24[ i ], lambda_Q16 ); } lambda_Q16 = -lambda_Q16; nom_Q16 = silk_SMLAWB( SILK_FIX_CONST( 1.0, 16 ), -lambda_Q16, lambda_Q16 ); den_Q24 = silk_SMLAWB( SILK_FIX_CONST( 1.0, 24 ), coefs_syn_Q24[ 0 ], lambda_Q16 ); gain_syn_Q16 = silk_DIV32_varQ( nom_Q16, den_Q24, 24 ); den_Q24 = silk_SMLAWB( SILK_FIX_CONST( 1.0, 24 ), coefs_ana_Q24[ 0 ], lambda_Q16 ); gain_ana_Q16 = silk_DIV32_varQ( nom_Q16, den_Q24, 24 ); for( i = 0; i < order; i++ ) { coefs_syn_Q24[ i ] = silk_SMULWW( gain_syn_Q16, coefs_syn_Q24[ i ] ); coefs_ana_Q24[ i ] = silk_SMULWW( gain_ana_Q16, coefs_ana_Q24[ i ] ); } for( iter = 0; iter < 10; iter++ ) { /* Find maximum absolute value */ maxabs_Q24 = -1; for( i = 0; i < order; i++ ) { tmp = silk_max( silk_abs_int32( coefs_syn_Q24[ i ] ), silk_abs_int32( coefs_ana_Q24[ i ] ) ); if( tmp > maxabs_Q24 ) { maxabs_Q24 = tmp; ind = i; } } if( maxabs_Q24 <= limit_Q24 ) { /* Coefficients are within range - done */ return; } /* Convert back to true warped coefficients */ for( i = 1; i < order; i++ ) { coefs_syn_Q24[ i - 1 ] = silk_SMLAWB( coefs_syn_Q24[ i - 1 ], coefs_syn_Q24[ i ], lambda_Q16 ); coefs_ana_Q24[ i - 1 ] = silk_SMLAWB( coefs_ana_Q24[ i - 1 ], coefs_ana_Q24[ i ], lambda_Q16 ); } gain_syn_Q16 = silk_INVERSE32_varQ( gain_syn_Q16, 32 ); gain_ana_Q16 = silk_INVERSE32_varQ( gain_ana_Q16, 32 ); for( i = 0; i < order; i++ ) { coefs_syn_Q24[ i ] = silk_SMULWW( gain_syn_Q16, coefs_syn_Q24[ i ] ); coefs_ana_Q24[ i ] = silk_SMULWW( gain_ana_Q16, coefs_ana_Q24[ i ] ); } /* Apply bandwidth expansion */ chirp_Q16 = SILK_FIX_CONST( 0.99, 16 ) - silk_DIV32_varQ( silk_SMULWB( maxabs_Q24 - limit_Q24, silk_SMLABB( SILK_FIX_CONST( 0.8, 10 ), SILK_FIX_CONST( 0.1, 10 ), iter ) ), silk_MUL( maxabs_Q24, ind + 1 ), 22 ); silk_bwexpander_32( coefs_syn_Q24, order, chirp_Q16 ); silk_bwexpander_32( coefs_ana_Q24, order, chirp_Q16 ); /* Convert to monic warped coefficients */ lambda_Q16 = -lambda_Q16; for( i = order - 1; i > 0; i-- ) { coefs_syn_Q24[ i - 1 ] = silk_SMLAWB( coefs_syn_Q24[ i - 1 ], coefs_syn_Q24[ i ], lambda_Q16 ); coefs_ana_Q24[ i - 1 ] = silk_SMLAWB( coefs_ana_Q24[ i - 1 ], coefs_ana_Q24[ i ], lambda_Q16 ); } lambda_Q16 = -lambda_Q16; nom_Q16 = silk_SMLAWB( SILK_FIX_CONST( 1.0, 16 ), -lambda_Q16, lambda_Q16 ); den_Q24 = silk_SMLAWB( SILK_FIX_CONST( 1.0, 24 ), coefs_syn_Q24[ 0 ], lambda_Q16 ); gain_syn_Q16 = silk_DIV32_varQ( nom_Q16, den_Q24, 24 ); den_Q24 = silk_SMLAWB( SILK_FIX_CONST( 1.0, 24 ), coefs_ana_Q24[ 0 ], lambda_Q16 ); gain_ana_Q16 = silk_DIV32_varQ( nom_Q16, den_Q24, 24 ); for( i = 0; i < order; i++ ) { coefs_syn_Q24[ i ] = silk_SMULWW( gain_syn_Q16, coefs_syn_Q24[ i ] ); coefs_ana_Q24[ i ] = silk_SMULWW( gain_ana_Q16, coefs_ana_Q24[ i ] ); } } silk_assert( 0 ); }
/* uses SMLAWB(), requiring armv5E and higher. */ opus_int32 silk_schur( /* O Returns residual energy */ opus_int16 *rc_Q15, /* O reflection coefficients [order] Q15 */ const opus_int32 *c, /* I correlations [order+1] */ const opus_int32 order /* I prediction order */ ) { opus_int k, n, lz; opus_int32 C[ SILK_MAX_ORDER_LPC + 1 ][ 2 ]; opus_int32 Ctmp1, Ctmp2, rc_tmp_Q15; silk_assert( order==6||order==8||order==10||order==12||order==14||order==16 ); /* Get number of leading zeros */ lz = silk_CLZ32( c[ 0 ] ); /* Copy correlations and adjust level to Q30 */ if( lz < 2 ) { /* lz must be 1, so shift one to the right */ for( k = 0; k < order + 1; k++ ) { C[ k ][ 0 ] = C[ k ][ 1 ] = silk_RSHIFT( c[ k ], 1 ); } } else if( lz > 2 ) { /* Shift to the left */ lz -= 2; for( k = 0; k < order + 1; k++ ) { C[ k ][ 0 ] = C[ k ][ 1 ] = silk_LSHIFT( c[ k ], lz ); } } else { /* No need to shift */ for( k = 0; k < order + 1; k++ ) { C[ k ][ 0 ] = C[ k ][ 1 ] = c[ k ]; } } for( k = 0; k < order; k++ ) { /* Check that we won't be getting an unstable rc, otherwise stop here. */ if (silk_abs_int32(C[ k + 1 ][ 0 ]) >= C[ 0 ][ 1 ]) { if ( C[ k + 1 ][ 0 ] > 0 ) { rc_Q15[ k ] = -SILK_FIX_CONST( .99f, 15 ); } else { rc_Q15[ k ] = SILK_FIX_CONST( .99f, 15 ); } k++; break; } /* Get reflection coefficient */ rc_tmp_Q15 = -silk_DIV32_16( C[ k + 1 ][ 0 ], silk_max_32( silk_RSHIFT( C[ 0 ][ 1 ], 15 ), 1 ) ); /* Clip (shouldn't happen for properly conditioned inputs) */ rc_tmp_Q15 = silk_SAT16( rc_tmp_Q15 ); /* Store */ rc_Q15[ k ] = (opus_int16)rc_tmp_Q15; /* Update correlations */ for( n = 0; n < order - k; n++ ) { Ctmp1 = C[ n + k + 1 ][ 0 ]; Ctmp2 = C[ n ][ 1 ]; C[ n + k + 1 ][ 0 ] = silk_SMLAWB( Ctmp1, silk_LSHIFT( Ctmp2, 1 ), rc_tmp_Q15 ); C[ n ][ 1 ] = silk_SMLAWB( Ctmp2, silk_LSHIFT( Ctmp1, 1 ), rc_tmp_Q15 ); } } for(; k < order; k++ ) { rc_Q15[ k ] = 0; } /* return residual energy */ return silk_max_32( 1, C[ 0 ][ 1 ] ); }
void silk_find_LTP_FIX( opus_int16 b_Q14[ MAX_NB_SUBFR * LTP_ORDER ], /* O LTP coefs */ opus_int32 WLTP[ MAX_NB_SUBFR * LTP_ORDER * LTP_ORDER ], /* O Weight for LTP quantization */ opus_int *LTPredCodGain_Q7, /* O LTP coding gain */ const opus_int16 r_lpc[], /* I residual signal after LPC signal + state for first 10 ms */ const opus_int lag[ MAX_NB_SUBFR ], /* I LTP lags */ const opus_int32 Wght_Q15[ 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 corr_rshifts[ MAX_NB_SUBFR ] /* O right shifts applied to correlations */ ) { opus_int i, k, lshift; const opus_int16 *r_ptr, *lag_ptr; opus_int16 *b_Q14_ptr; opus_int32 regu; opus_int32 *WLTP_ptr; opus_int32 b_Q16[ LTP_ORDER ], delta_b_Q14[ LTP_ORDER ], d_Q14[ MAX_NB_SUBFR ], nrg[ MAX_NB_SUBFR ], g_Q26; opus_int32 w[ MAX_NB_SUBFR ], WLTP_max, max_abs_d_Q14, max_w_bits; opus_int32 temp32, denom32; opus_int extra_shifts; opus_int rr_shifts, maxRshifts, maxRshifts_wxtra, LZs; opus_int32 LPC_res_nrg, LPC_LTP_res_nrg, div_Q16; opus_int32 Rr[ LTP_ORDER ], rr[ MAX_NB_SUBFR ]; opus_int32 wd, m_Q12; b_Q14_ptr = b_Q14; 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_sum_sqr_shift( &rr[ k ], &rr_shifts, r_ptr, subfr_length ); /* rr[ k ] in Q( -rr_shifts ) */ /* Assure headroom */ LZs = silk_CLZ32( rr[k] ); if( LZs < LTP_CORRS_HEAD_ROOM ) { rr[ k ] = silk_RSHIFT_ROUND( rr[ k ], LTP_CORRS_HEAD_ROOM - LZs ); rr_shifts += ( LTP_CORRS_HEAD_ROOM - LZs ); } corr_rshifts[ k ] = rr_shifts; silk_corrMatrix_FIX( lag_ptr, subfr_length, LTP_ORDER, LTP_CORRS_HEAD_ROOM, WLTP_ptr, &corr_rshifts[ k ] ); /* WLTP_fix_ptr in Q( -corr_rshifts[ k ] ) */ /* The correlation vector always has lower max abs value than rr and/or RR so head room is assured */ silk_corrVector_FIX( lag_ptr, r_ptr, subfr_length, LTP_ORDER, Rr, corr_rshifts[ k ] ); /* Rr_fix_ptr in Q( -corr_rshifts[ k ] ) */ if( corr_rshifts[ k ] > rr_shifts ) { rr[ k ] = silk_RSHIFT( rr[ k ], corr_rshifts[ k ] - rr_shifts ); /* rr[ k ] in Q( -corr_rshifts[ k ] ) */ } silk_assert( rr[ k ] >= 0 ); regu = 1; regu = silk_SMLAWB( regu, rr[ k ], SILK_FIX_CONST( LTP_DAMPING/3, 16 ) ); regu = silk_SMLAWB( regu, matrix_ptr( WLTP_ptr, 0, 0, LTP_ORDER ), SILK_FIX_CONST( LTP_DAMPING/3, 16 ) ); regu = silk_SMLAWB( regu, matrix_ptr( WLTP_ptr, LTP_ORDER-1, LTP_ORDER-1, LTP_ORDER ), SILK_FIX_CONST( LTP_DAMPING/3, 16 ) ); silk_regularize_correlations_FIX( WLTP_ptr, &rr[k], regu, LTP_ORDER ); silk_solve_LDL_FIX( WLTP_ptr, LTP_ORDER, Rr, b_Q16 ); /* WLTP_fix_ptr and Rr_fix_ptr both in Q(-corr_rshifts[k]) */ /* Limit and store in Q14 */ silk_fit_LTP( b_Q16, b_Q14_ptr ); /* Calculate residual energy */ nrg[ k ] = silk_residual_energy16_covar_FIX( b_Q14_ptr, WLTP_ptr, Rr, rr[ k ], LTP_ORDER, 14 ); /* nrg_fix in Q( -corr_rshifts[ k ] ) */ /* temp = Wght[ k ] / ( nrg[ k ] * Wght[ k ] + 0.01f * subfr_length ); */ extra_shifts = silk_min_int( corr_rshifts[ k ], LTP_CORRS_HEAD_ROOM ); denom32 = silk_LSHIFT_SAT32( silk_SMULWB( nrg[ k ], Wght_Q15[ k ] ), 1 + extra_shifts ) + /* Q( -corr_rshifts[ k ] + extra_shifts ) */ silk_RSHIFT( silk_SMULWB( subfr_length, 655 ), corr_rshifts[ k ] - extra_shifts ); /* Q( -corr_rshifts[ k ] + extra_shifts ) */ denom32 = silk_max( denom32, 1 ); silk_assert( ((opus_int64)Wght_Q15[ k ] << 16 ) < silk_int32_MAX ); /* Wght always < 0.5 in Q0 */ temp32 = silk_DIV32( silk_LSHIFT( (opus_int32)Wght_Q15[ k ], 16 ), denom32 ); /* Q( 15 + 16 + corr_rshifts[k] - extra_shifts ) */ temp32 = silk_RSHIFT( temp32, 31 + corr_rshifts[ k ] - extra_shifts - 26 ); /* Q26 */ /* Limit temp such that the below scaling never wraps around */ WLTP_max = 0; for( i = 0; i < LTP_ORDER * LTP_ORDER; i++ ) { WLTP_max = silk_max( WLTP_ptr[ i ], WLTP_max ); } lshift = silk_CLZ32( WLTP_max ) - 1 - 3; /* keep 3 bits free for vq_nearest_neighbor_fix */ silk_assert( 26 - 18 + lshift >= 0 ); if( 26 - 18 + lshift < 31 ) { temp32 = silk_min_32( temp32, silk_LSHIFT( (opus_int32)1, 26 - 18 + lshift ) ); } silk_scale_vector32_Q26_lshift_18( WLTP_ptr, temp32, LTP_ORDER * LTP_ORDER ); /* WLTP_ptr in Q( 18 - corr_rshifts[ k ] ) */ w[ k ] = matrix_ptr( WLTP_ptr, LTP_ORDER/2, LTP_ORDER/2, LTP_ORDER ); /* w in Q( 18 - corr_rshifts[ k ] ) */ silk_assert( w[k] >= 0 ); r_ptr += subfr_length; b_Q14_ptr += LTP_ORDER; WLTP_ptr += LTP_ORDER * LTP_ORDER; } maxRshifts = 0; for( k = 0; k < nb_subfr; k++ ) { maxRshifts = silk_max_int( corr_rshifts[ k ], maxRshifts ); } /* Compute LTP coding gain */ if( LTPredCodGain_Q7 != NULL ) { LPC_LTP_res_nrg = 0; LPC_res_nrg = 0; silk_assert( LTP_CORRS_HEAD_ROOM >= 2 ); /* Check that no overflow will happen when adding */ for( k = 0; k < nb_subfr; k++ ) { LPC_res_nrg = silk_ADD32( LPC_res_nrg, silk_RSHIFT( silk_ADD32( silk_SMULWB( rr[ k ], Wght_Q15[ k ] ), 1 ), 1 + ( maxRshifts - corr_rshifts[ k ] ) ) ); /* Q( -maxRshifts ) */ LPC_LTP_res_nrg = silk_ADD32( LPC_LTP_res_nrg, silk_RSHIFT( silk_ADD32( silk_SMULWB( nrg[ k ], Wght_Q15[ k ] ), 1 ), 1 + ( maxRshifts - corr_rshifts[ k ] ) ) ); /* Q( -maxRshifts ) */ } LPC_LTP_res_nrg = silk_max( LPC_LTP_res_nrg, 1 ); /* avoid division by zero */ div_Q16 = silk_DIV32_varQ( LPC_res_nrg, LPC_LTP_res_nrg, 16 ); *LTPredCodGain_Q7 = ( opus_int )silk_SMULBB( 3, silk_lin2log( div_Q16 ) - ( 16 << 7 ) ); silk_assert( *LTPredCodGain_Q7 == ( opus_int )silk_SAT16( silk_MUL( 3, silk_lin2log( div_Q16 ) - ( 16 << 7 ) ) ) ); } /* smoothing */ /* d = sum( B, 1 ); */ b_Q14_ptr = b_Q14; for( k = 0; k < nb_subfr; k++ ) { d_Q14[ k ] = 0; for( i = 0; i < LTP_ORDER; i++ ) { d_Q14[ k ] += b_Q14_ptr[ i ]; } b_Q14_ptr += LTP_ORDER; } /* m = ( w * d' ) / ( sum( w ) + 1e-3 ); */ /* Find maximum absolute value of d_Q14 and the bits used by w in Q0 */ max_abs_d_Q14 = 0; max_w_bits = 0; for( k = 0; k < nb_subfr; k++ ) { max_abs_d_Q14 = silk_max_32( max_abs_d_Q14, silk_abs( d_Q14[ k ] ) ); /* w[ k ] is in Q( 18 - corr_rshifts[ k ] ) */ /* Find bits needed in Q( 18 - maxRshifts ) */ max_w_bits = silk_max_32( max_w_bits, 32 - silk_CLZ32( w[ k ] ) + corr_rshifts[ k ] - maxRshifts ); } /* max_abs_d_Q14 = (5 << 15); worst case, i.e. LTP_ORDER * -silk_int16_MIN */ silk_assert( max_abs_d_Q14 <= ( 5 << 15 ) ); /* How many bits is needed for w*d' in Q( 18 - maxRshifts ) in the worst case, of all d_Q14's being equal to max_abs_d_Q14 */ extra_shifts = max_w_bits + 32 - silk_CLZ32( max_abs_d_Q14 ) - 14; /* Subtract what we got available; bits in output var plus maxRshifts */ extra_shifts -= ( 32 - 1 - 2 + maxRshifts ); /* Keep sign bit free as well as 2 bits for accumulation */ extra_shifts = silk_max_int( extra_shifts, 0 ); maxRshifts_wxtra = maxRshifts + extra_shifts; temp32 = silk_RSHIFT( 262, maxRshifts + extra_shifts ) + 1; /* 1e-3f in Q( 18 - (maxRshifts + extra_shifts) ) */ wd = 0; for( k = 0; k < nb_subfr; k++ ) { /* w has at least 2 bits of headroom so no overflow should happen */ temp32 = silk_ADD32( temp32, silk_RSHIFT( w[ k ], maxRshifts_wxtra - corr_rshifts[ k ] ) ); /* Q( 18 - maxRshifts_wxtra ) */ wd = silk_ADD32( wd, silk_LSHIFT( silk_SMULWW( silk_RSHIFT( w[ k ], maxRshifts_wxtra - corr_rshifts[ k ] ), d_Q14[ k ] ), 2 ) ); /* Q( 18 - maxRshifts_wxtra ) */ } m_Q12 = silk_DIV32_varQ( wd, temp32, 12 ); b_Q14_ptr = b_Q14; for( k = 0; k < nb_subfr; k++ ) { /* w_fix[ k ] from Q( 18 - corr_rshifts[ k ] ) to Q( 16 ) */ if( 2 - corr_rshifts[k] > 0 ) { temp32 = silk_RSHIFT( w[ k ], 2 - corr_rshifts[ k ] ); } else { temp32 = silk_LSHIFT_SAT32( w[ k ], corr_rshifts[ k ] - 2 ); } g_Q26 = silk_MUL( silk_DIV32( SILK_FIX_CONST( LTP_SMOOTHING, 26 ), silk_RSHIFT( SILK_FIX_CONST( LTP_SMOOTHING, 26 ), 10 ) + temp32 ), /* Q10 */ silk_LSHIFT_SAT32( silk_SUB_SAT32( (opus_int32)m_Q12, silk_RSHIFT( d_Q14[ k ], 2 ) ), 4 ) ); /* Q16 */ temp32 = 0; for( i = 0; i < LTP_ORDER; i++ ) { delta_b_Q14[ i ] = silk_max_16( b_Q14_ptr[ i ], 1638 ); /* 1638_Q14 = 0.1_Q0 */ temp32 += delta_b_Q14[ i ]; /* Q14 */ } temp32 = silk_DIV32( g_Q26, temp32 ); /* Q14 -> Q12 */ for( i = 0; i < LTP_ORDER; i++ ) { b_Q14_ptr[ i ] = silk_LIMIT_32( (opus_int32)b_Q14_ptr[ i ] + silk_SMULWB( silk_LSHIFT_SAT32( temp32, 4 ), delta_b_Q14[ i ] ), -16000, 28000 ); } b_Q14_ptr += LTP_ORDER; } }
static OPUS_INLINE void silk_LDL_factorize_FIX( opus_int32 *A, /* I/O Pointer to Symetric Square Matrix */ opus_int M, /* I Size of Matrix */ opus_int32 *L_Q16, /* I/O Pointer to Square Upper triangular Matrix */ inv_D_t *inv_D /* I/O Pointer to vector holding inverted diagonal elements of D */ ) { opus_int i, j, k, status, loop_count; const opus_int32 *ptr1, *ptr2; opus_int32 diag_min_value, tmp_32, err; opus_int32 v_Q0[ MAX_MATRIX_SIZE ], D_Q0[ MAX_MATRIX_SIZE ]; opus_int32 one_div_diag_Q36, one_div_diag_Q40, one_div_diag_Q48; silk_assert( M <= MAX_MATRIX_SIZE ); status = 1; diag_min_value = silk_max_32( silk_SMMUL( silk_ADD_SAT32( A[ 0 ], A[ silk_SMULBB( M, M ) - 1 ] ), SILK_FIX_CONST( FIND_LTP_COND_FAC, 31 ) ), 1 << 9 ); for( loop_count = 0; loop_count < M && status == 1; loop_count++ ) { status = 0; for( j = 0; j < M; j++ ) { ptr1 = matrix_adr( L_Q16, j, 0, M ); tmp_32 = 0; for( i = 0; i < j; i++ ) { v_Q0[ i ] = silk_SMULWW( D_Q0[ i ], ptr1[ i ] ); /* Q0 */ tmp_32 = silk_SMLAWW( tmp_32, v_Q0[ i ], ptr1[ i ] ); /* Q0 */ } tmp_32 = silk_SUB32( matrix_ptr( A, j, j, M ), tmp_32 ); if( tmp_32 < diag_min_value ) { tmp_32 = silk_SUB32( silk_SMULBB( loop_count + 1, diag_min_value ), tmp_32 ); /* Matrix not positive semi-definite, or ill conditioned */ for( i = 0; i < M; i++ ) { matrix_ptr( A, i, i, M ) = silk_ADD32( matrix_ptr( A, i, i, M ), tmp_32 ); } status = 1; break; } D_Q0[ j ] = tmp_32; /* always < max(Correlation) */ /* two-step division */ one_div_diag_Q36 = silk_INVERSE32_varQ( tmp_32, 36 ); /* Q36 */ one_div_diag_Q40 = silk_LSHIFT( one_div_diag_Q36, 4 ); /* Q40 */ err = silk_SUB32( (opus_int32)1 << 24, silk_SMULWW( tmp_32, one_div_diag_Q40 ) ); /* Q24 */ one_div_diag_Q48 = silk_SMULWW( err, one_div_diag_Q40 ); /* Q48 */ /* Save 1/Ds */ inv_D[ j ].Q36_part = one_div_diag_Q36; inv_D[ j ].Q48_part = one_div_diag_Q48; matrix_ptr( L_Q16, j, j, M ) = 65536; /* 1.0 in Q16 */ ptr1 = matrix_adr( A, j, 0, M ); ptr2 = matrix_adr( L_Q16, j + 1, 0, M ); for( i = j + 1; i < M; i++ ) { tmp_32 = 0; for( k = 0; k < j; k++ ) { tmp_32 = silk_SMLAWW( tmp_32, v_Q0[ k ], ptr2[ k ] ); /* Q0 */ } tmp_32 = silk_SUB32( ptr1[ i ], tmp_32 ); /* always < max(Correlation) */ /* tmp_32 / D_Q0[j] : Divide to Q16 */ matrix_ptr( L_Q16, i, j, M ) = silk_ADD32( silk_SMMUL( tmp_32, one_div_diag_Q48 ), silk_RSHIFT( silk_SMULWW( tmp_32, one_div_diag_Q36 ), 4 ) ); /* go to next column */ ptr2 += M; } } } silk_assert( status == 0 ); }
/* Limit, stabilize, convert and quantize NLSFs */ void silk_process_NLSFs( silk_encoder_state *psEncC, /* I/O Encoder state */ opus_int16 PredCoef_Q12[ 2 ][ MAX_LPC_ORDER ], /* O Prediction coefficients */ opus_int16 pNLSF_Q15[ MAX_LPC_ORDER ], /* I/O Normalized LSFs (quant out) (0 - (2^15-1)) */ const opus_int16 prev_NLSFq_Q15[ MAX_LPC_ORDER ] /* I Previous Normalized LSFs (0 - (2^15-1)) */ ) { opus_int i, doInterpolate; opus_int NLSF_mu_Q20; opus_int32 i_sqr_Q15; opus_int16 pNLSF0_temp_Q15[ MAX_LPC_ORDER ]; opus_int16 pNLSFW_QW[ MAX_LPC_ORDER ]; opus_int16 pNLSFW0_temp_QW[ MAX_LPC_ORDER ]; silk_assert(psEncC->speech_activity_Q8 >= 0); silk_assert(psEncC->speech_activity_Q8 <= SILK_FIX_CONST(1.0, 8)); silk_assert(psEncC->useInterpolatedNLSFs == 1 || psEncC->indices.NLSFInterpCoef_Q2 == (1 << 2)); /***********************/ /* Calculate mu values */ /***********************/ /* NLSF_mu = 0.003 - 0.0015 * psEnc->speech_activity; */ NLSF_mu_Q20 = silk_SMLAWB(SILK_FIX_CONST(0.003, 20), SILK_FIX_CONST(-0.001, 28), psEncC->speech_activity_Q8); if(psEncC->nb_subfr == 2) { /* Multiply by 1.5 for 10 ms packets */ NLSF_mu_Q20 = silk_ADD_RSHIFT(NLSF_mu_Q20, NLSF_mu_Q20, 1); } silk_assert(NLSF_mu_Q20 > 0); silk_assert(NLSF_mu_Q20 <= SILK_FIX_CONST(0.005, 20)); /* Calculate NLSF weights */ silk_NLSF_VQ_weights_laroia(pNLSFW_QW, pNLSF_Q15, psEncC->predictLPCOrder); /* Update NLSF weights for interpolated NLSFs */ doInterpolate = (psEncC->useInterpolatedNLSFs == 1) && (psEncC->indices.NLSFInterpCoef_Q2 < 4); if(doInterpolate) { /* Calculate the interpolated NLSF vector for the first half */ silk_interpolate(pNLSF0_temp_Q15, prev_NLSFq_Q15, pNLSF_Q15, psEncC->indices.NLSFInterpCoef_Q2, psEncC->predictLPCOrder); /* Calculate first half NLSF weights for the interpolated NLSFs */ silk_NLSF_VQ_weights_laroia(pNLSFW0_temp_QW, pNLSF0_temp_Q15, psEncC->predictLPCOrder); /* Update NLSF weights with contribution from first half */ i_sqr_Q15 = silk_LSHIFT(silk_SMULBB(psEncC->indices.NLSFInterpCoef_Q2, psEncC->indices.NLSFInterpCoef_Q2), 11); for(i = 0; i < psEncC->predictLPCOrder; i++) { pNLSFW_QW[ i ] = silk_SMLAWB(silk_RSHIFT(pNLSFW_QW[ i ], 1), (opus_int32)pNLSFW0_temp_QW[ i ], i_sqr_Q15); silk_assert(pNLSFW_QW[ i ] >= 1); } } silk_NLSF_encode(psEncC->indices.NLSFIndices, pNLSF_Q15, psEncC->psNLSF_CB, pNLSFW_QW, NLSF_mu_Q20, psEncC->NLSF_MSVQ_Survivors, psEncC->indices.signalType); /* Convert quantized NLSFs back to LPC coefficients */ silk_NLSF2A(PredCoef_Q12[ 1 ], pNLSF_Q15, psEncC->predictLPCOrder); if(doInterpolate) { /* Calculate the interpolated, quantized LSF vector for the first half */ silk_interpolate(pNLSF0_temp_Q15, prev_NLSFq_Q15, pNLSF_Q15, psEncC->indices.NLSFInterpCoef_Q2, psEncC->predictLPCOrder); /* Convert back to LPC coefficients */ silk_NLSF2A(PredCoef_Q12[ 0 ], pNLSF0_temp_Q15, psEncC->predictLPCOrder); } else { /* Copy LPC coefficients for first half from second half */ silk_memcpy(PredCoef_Q12[ 0 ], PredCoef_Q12[ 1 ], psEncC->predictLPCOrder * sizeof(opus_int16)); } }
void silk_prefilter_FIX( silk_encoder_state_FIX *psEnc, /* I/O Encoder state */ const silk_encoder_control_FIX *psEncCtrl, /* I Encoder control */ opus_int32 xw_Q3[], /* O Weighted signal */ const opus_int16 x[] /* I Speech signal */ ) { silk_prefilter_state_FIX *P = &psEnc->sPrefilt; opus_int j, k, lag; opus_int32 tmp_32; const opus_int16 *AR1_shp_Q13; const opus_int16 *px; opus_int32 *pxw_Q3; opus_int HarmShapeGain_Q12, Tilt_Q14; opus_int32 HarmShapeFIRPacked_Q12, LF_shp_Q14; VARDECL( opus_int32, x_filt_Q12 ); VARDECL( opus_int32, st_res_Q2 ); opus_int16 B_Q10[ 2 ]; SAVE_STACK; /* Set up pointers */ px = x; pxw_Q3 = xw_Q3; lag = P->lagPrev; ALLOC( x_filt_Q12, psEnc->sCmn.subfr_length, opus_int32 ); ALLOC( st_res_Q2, psEnc->sCmn.subfr_length, opus_int32 ); for( k = 0; k < psEnc->sCmn.nb_subfr; k++ ) { /* Update Variables that change per sub frame */ if( psEnc->sCmn.indices.signalType == TYPE_VOICED ) { lag = psEncCtrl->pitchL[ k ]; } /* Noise shape parameters */ HarmShapeGain_Q12 = silk_SMULWB( (opus_int32)psEncCtrl->HarmShapeGain_Q14[ k ], 16384 - psEncCtrl->HarmBoost_Q14[ k ] ); silk_assert( HarmShapeGain_Q12 >= 0 ); HarmShapeFIRPacked_Q12 = silk_RSHIFT( HarmShapeGain_Q12, 2 ); HarmShapeFIRPacked_Q12 |= silk_LSHIFT( (opus_int32)silk_RSHIFT( HarmShapeGain_Q12, 1 ), 16 ); Tilt_Q14 = psEncCtrl->Tilt_Q14[ k ]; LF_shp_Q14 = psEncCtrl->LF_shp_Q14[ k ]; AR1_shp_Q13 = &psEncCtrl->AR1_Q13[ k * MAX_SHAPE_LPC_ORDER ]; /* Short term FIR filtering*/ silk_warped_LPC_analysis_filter_FIX( P->sAR_shp, st_res_Q2, AR1_shp_Q13, px, psEnc->sCmn.warping_Q16, psEnc->sCmn.subfr_length, psEnc->sCmn.shapingLPCOrder ); /* Reduce (mainly) low frequencies during harmonic emphasis */ B_Q10[ 0 ] = silk_RSHIFT_ROUND( psEncCtrl->GainsPre_Q14[ k ], 4 ); tmp_32 = silk_SMLABB( SILK_FIX_CONST( INPUT_TILT, 26 ), psEncCtrl->HarmBoost_Q14[ k ], HarmShapeGain_Q12 ); /* Q26 */ tmp_32 = silk_SMLABB( tmp_32, psEncCtrl->coding_quality_Q14, SILK_FIX_CONST( HIGH_RATE_INPUT_TILT, 12 ) ); /* Q26 */ tmp_32 = silk_SMULWB( tmp_32, -psEncCtrl->GainsPre_Q14[ k ] ); /* Q24 */ tmp_32 = silk_RSHIFT_ROUND( tmp_32, 14 ); /* Q10 */ B_Q10[ 1 ]= silk_SAT16( tmp_32 ); x_filt_Q12[ 0 ] = silk_MLA( silk_MUL( st_res_Q2[ 0 ], B_Q10[ 0 ] ), P->sHarmHP_Q2, B_Q10[ 1 ] ); for( j = 1; j < psEnc->sCmn.subfr_length; j++ ) { x_filt_Q12[ j ] = silk_MLA( silk_MUL( st_res_Q2[ j ], B_Q10[ 0 ] ), st_res_Q2[ j - 1 ], B_Q10[ 1 ] ); } P->sHarmHP_Q2 = st_res_Q2[ psEnc->sCmn.subfr_length - 1 ]; silk_prefilt_FIX( P, x_filt_Q12, pxw_Q3, HarmShapeFIRPacked_Q12, Tilt_Q14, LF_shp_Q14, lag, psEnc->sCmn.subfr_length ); px += psEnc->sCmn.subfr_length; pxw_Q3 += psEnc->sCmn.subfr_length; } P->lagPrev = psEncCtrl->pitchL[ psEnc->sCmn.nb_subfr - 1 ]; RESTORE_STACK; }
static OPUS_INLINE void silk_PLC_conceal( silk_decoder_state *psDec, /* I/O Decoder state */ silk_decoder_control *psDecCtrl, /* I/O Decoder control */ opus_int16 frame[], /* O LPC residual signal */ int arch /* I Run-time architecture */ ) { opus_int i, j, k; opus_int lag, idx, sLTP_buf_idx, shift1, shift2; opus_int32 rand_seed, harm_Gain_Q15, rand_Gain_Q15, inv_gain_Q30; opus_int32 energy1, energy2, *rand_ptr, *pred_lag_ptr; opus_int32 LPC_pred_Q10, LTP_pred_Q12; opus_int16 rand_scale_Q14; opus_int16 *B_Q14; opus_int32 *sLPC_Q14_ptr; opus_int16 A_Q12[ MAX_LPC_ORDER ]; #ifdef SMALL_FOOTPRINT opus_int16 *sLTP; #else VARDECL( opus_int16, sLTP ); #endif VARDECL( opus_int32, sLTP_Q14 ); silk_PLC_struct *psPLC = &psDec->sPLC; opus_int32 prevGain_Q10[2]; SAVE_STACK; ALLOC( sLTP_Q14, psDec->ltp_mem_length + psDec->frame_length, opus_int32 ); #ifdef SMALL_FOOTPRINT /* Ugly hack that breaks aliasing rules to save stack: put sLTP at the very end of sLTP_Q14. */ sLTP = ((opus_int16*)&sLTP_Q14[psDec->ltp_mem_length + psDec->frame_length])-psDec->ltp_mem_length; #else ALLOC( sLTP, psDec->ltp_mem_length, opus_int16 ); #endif prevGain_Q10[0] = silk_RSHIFT( psPLC->prevGain_Q16[ 0 ], 6); prevGain_Q10[1] = silk_RSHIFT( psPLC->prevGain_Q16[ 1 ], 6); if( psDec->first_frame_after_reset ) { silk_memset( psPLC->prevLPC_Q12, 0, sizeof( psPLC->prevLPC_Q12 ) ); } silk_PLC_energy(&energy1, &shift1, &energy2, &shift2, psDec->exc_Q14, prevGain_Q10, psDec->subfr_length, psDec->nb_subfr); if( silk_RSHIFT( energy1, shift2 ) < silk_RSHIFT( energy2, shift1 ) ) { /* First sub-frame has lowest energy */ rand_ptr = &psDec->exc_Q14[ silk_max_int( 0, ( psPLC->nb_subfr - 1 ) * psPLC->subfr_length - RAND_BUF_SIZE ) ]; } else { /* Second sub-frame has lowest energy */ rand_ptr = &psDec->exc_Q14[ silk_max_int( 0, psPLC->nb_subfr * psPLC->subfr_length - RAND_BUF_SIZE ) ]; } /* Set up Gain to random noise component */ B_Q14 = psPLC->LTPCoef_Q14; rand_scale_Q14 = psPLC->randScale_Q14; /* Set up attenuation gains */ harm_Gain_Q15 = HARM_ATT_Q15[ silk_min_int( NB_ATT - 1, psDec->lossCnt ) ]; if( psDec->prevSignalType == TYPE_VOICED ) { rand_Gain_Q15 = PLC_RAND_ATTENUATE_V_Q15[ silk_min_int( NB_ATT - 1, psDec->lossCnt ) ]; } else { rand_Gain_Q15 = PLC_RAND_ATTENUATE_UV_Q15[ silk_min_int( NB_ATT - 1, psDec->lossCnt ) ]; } /* LPC concealment. Apply BWE to previous LPC */ silk_bwexpander( psPLC->prevLPC_Q12, psDec->LPC_order, SILK_FIX_CONST( BWE_COEF, 16 ) ); /* Preload LPC coeficients to array on stack. Gives small performance gain */ silk_memcpy( A_Q12, psPLC->prevLPC_Q12, psDec->LPC_order * sizeof( opus_int16 ) ); /* First Lost frame */ if( psDec->lossCnt == 0 ) { rand_scale_Q14 = 1 << 14; /* Reduce random noise Gain for voiced frames */ if( psDec->prevSignalType == TYPE_VOICED ) { for( i = 0; i < LTP_ORDER; i++ ) { rand_scale_Q14 -= B_Q14[ i ]; } rand_scale_Q14 = silk_max_16( 3277, rand_scale_Q14 ); /* 0.2 */ rand_scale_Q14 = (opus_int16)silk_RSHIFT( silk_SMULBB( rand_scale_Q14, psPLC->prevLTP_scale_Q14 ), 14 ); } else { /* Reduce random noise for unvoiced frames with high LPC gain */ opus_int32 invGain_Q30, down_scale_Q30; invGain_Q30 = silk_LPC_inverse_pred_gain( psPLC->prevLPC_Q12, psDec->LPC_order, arch ); down_scale_Q30 = silk_min_32( silk_RSHIFT( (opus_int32)1 << 30, LOG2_INV_LPC_GAIN_HIGH_THRES ), invGain_Q30 ); down_scale_Q30 = silk_max_32( silk_RSHIFT( (opus_int32)1 << 30, LOG2_INV_LPC_GAIN_LOW_THRES ), down_scale_Q30 ); down_scale_Q30 = silk_LSHIFT( down_scale_Q30, LOG2_INV_LPC_GAIN_HIGH_THRES ); rand_Gain_Q15 = silk_RSHIFT( silk_SMULWB( down_scale_Q30, rand_Gain_Q15 ), 14 ); } } rand_seed = psPLC->rand_seed; lag = silk_RSHIFT_ROUND( psPLC->pitchL_Q8, 8 ); sLTP_buf_idx = psDec->ltp_mem_length; /* Rewhiten LTP state */ idx = psDec->ltp_mem_length - lag - psDec->LPC_order - LTP_ORDER / 2; silk_assert( idx > 0 ); silk_LPC_analysis_filter( &sLTP[ idx ], &psDec->outBuf[ idx ], A_Q12, psDec->ltp_mem_length - idx, psDec->LPC_order, arch ); /* Scale LTP state */ inv_gain_Q30 = silk_INVERSE32_varQ( psPLC->prevGain_Q16[ 1 ], 46 ); inv_gain_Q30 = silk_min( inv_gain_Q30, silk_int32_MAX >> 1 ); for( i = idx + psDec->LPC_order; i < psDec->ltp_mem_length; i++ ) { sLTP_Q14[ i ] = silk_SMULWB( inv_gain_Q30, sLTP[ i ] ); } /***************************/ /* LTP synthesis filtering */ /***************************/ for( k = 0; k < psDec->nb_subfr; k++ ) { /* Set up pointer */ pred_lag_ptr = &sLTP_Q14[ sLTP_buf_idx - lag + LTP_ORDER / 2 ]; for( i = 0; i < psDec->subfr_length; i++ ) { /* Unrolled loop */ /* Avoids introducing a bias because silk_SMLAWB() always rounds to -inf */ LTP_pred_Q12 = 2; LTP_pred_Q12 = silk_SMLAWB( LTP_pred_Q12, pred_lag_ptr[ 0 ], B_Q14[ 0 ] ); LTP_pred_Q12 = silk_SMLAWB( LTP_pred_Q12, pred_lag_ptr[ -1 ], B_Q14[ 1 ] ); LTP_pred_Q12 = silk_SMLAWB( LTP_pred_Q12, pred_lag_ptr[ -2 ], B_Q14[ 2 ] ); LTP_pred_Q12 = silk_SMLAWB( LTP_pred_Q12, pred_lag_ptr[ -3 ], B_Q14[ 3 ] ); LTP_pred_Q12 = silk_SMLAWB( LTP_pred_Q12, pred_lag_ptr[ -4 ], B_Q14[ 4 ] ); pred_lag_ptr++; /* Generate LPC excitation */ rand_seed = silk_RAND( rand_seed ); idx = silk_RSHIFT( rand_seed, 25 ) & RAND_BUF_MASK; sLTP_Q14[ sLTP_buf_idx ] = silk_LSHIFT32( silk_SMLAWB( LTP_pred_Q12, rand_ptr[ idx ], rand_scale_Q14 ), 2 ); sLTP_buf_idx++; } /* Gradually reduce LTP gain */ for( j = 0; j < LTP_ORDER; j++ ) { B_Q14[ j ] = silk_RSHIFT( silk_SMULBB( harm_Gain_Q15, B_Q14[ j ] ), 15 ); } if ( psDec->indices.signalType != TYPE_NO_VOICE_ACTIVITY ) { /* Gradually reduce excitation gain */ rand_scale_Q14 = silk_RSHIFT( silk_SMULBB( rand_scale_Q14, rand_Gain_Q15 ), 15 ); } /* Slowly increase pitch lag */ psPLC->pitchL_Q8 = silk_SMLAWB( psPLC->pitchL_Q8, psPLC->pitchL_Q8, PITCH_DRIFT_FAC_Q16 ); psPLC->pitchL_Q8 = silk_min_32( psPLC->pitchL_Q8, silk_LSHIFT( silk_SMULBB( MAX_PITCH_LAG_MS, psDec->fs_kHz ), 8 ) ); lag = silk_RSHIFT_ROUND( psPLC->pitchL_Q8, 8 ); } /***************************/ /* LPC synthesis filtering */ /***************************/ sLPC_Q14_ptr = &sLTP_Q14[ psDec->ltp_mem_length - MAX_LPC_ORDER ]; /* Copy LPC state */ silk_memcpy( sLPC_Q14_ptr, psDec->sLPC_Q14_buf, MAX_LPC_ORDER * sizeof( opus_int32 ) ); silk_assert( psDec->LPC_order >= 10 ); /* check that unrolling works */ for( i = 0; i < psDec->frame_length; i++ ) { /* partly unrolled */ /* Avoids introducing a bias because silk_SMLAWB() always rounds to -inf */ LPC_pred_Q10 = silk_RSHIFT( psDec->LPC_order, 1 ); LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, sLPC_Q14_ptr[ MAX_LPC_ORDER + i - 1 ], A_Q12[ 0 ] ); LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, sLPC_Q14_ptr[ MAX_LPC_ORDER + i - 2 ], A_Q12[ 1 ] ); LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, sLPC_Q14_ptr[ MAX_LPC_ORDER + i - 3 ], A_Q12[ 2 ] ); LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, sLPC_Q14_ptr[ MAX_LPC_ORDER + i - 4 ], A_Q12[ 3 ] ); LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, sLPC_Q14_ptr[ MAX_LPC_ORDER + i - 5 ], A_Q12[ 4 ] ); LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, sLPC_Q14_ptr[ MAX_LPC_ORDER + i - 6 ], A_Q12[ 5 ] ); LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, sLPC_Q14_ptr[ MAX_LPC_ORDER + i - 7 ], A_Q12[ 6 ] ); LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, sLPC_Q14_ptr[ MAX_LPC_ORDER + i - 8 ], A_Q12[ 7 ] ); LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, sLPC_Q14_ptr[ MAX_LPC_ORDER + i - 9 ], A_Q12[ 8 ] ); LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, sLPC_Q14_ptr[ MAX_LPC_ORDER + i - 10 ], A_Q12[ 9 ] ); for( j = 10; j < psDec->LPC_order; j++ ) { LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, sLPC_Q14_ptr[ MAX_LPC_ORDER + i - j - 1 ], A_Q12[ j ] ); } /* Add prediction to LPC excitation */ sLPC_Q14_ptr[ MAX_LPC_ORDER + i ] = silk_ADD_SAT32( sLPC_Q14_ptr[ MAX_LPC_ORDER + i ], silk_LSHIFT_SAT32( LPC_pred_Q10, 4 )); /* Scale with Gain */ frame[ i ] = (opus_int16)silk_SAT16( silk_SAT16( silk_RSHIFT_ROUND( silk_SMULWW( sLPC_Q14_ptr[ MAX_LPC_ORDER + i ], prevGain_Q10[ 1 ] ), 8 ) ) ); } /* Save LPC state */ silk_memcpy( psDec->sLPC_Q14_buf, &sLPC_Q14_ptr[ psDec->frame_length ], MAX_LPC_ORDER * sizeof( opus_int32 ) ); /**************************************/ /* Update states */ /**************************************/ psPLC->rand_seed = rand_seed; psPLC->randScale_Q14 = rand_scale_Q14; for( i = 0; i < MAX_NB_SUBFR; i++ ) { psDecCtrl->pitchL[ i ] = lag; } RESTORE_STACK; }
static inline void silk_PLC_conceal( silk_decoder_state *psDec, /* I/O Decoder state */ silk_decoder_control *psDecCtrl, /* I/O Decoder control */ opus_int16 frame[] /* O LPC residual signal */ ) { opus_int i, j, k; opus_int lag, idx, sLTP_buf_idx, shift1, shift2; opus_int32 rand_seed, harm_Gain_Q15, rand_Gain_Q15, inv_gain_Q16, inv_gain_Q30; opus_int32 energy1, energy2, *rand_ptr, *pred_lag_ptr; opus_int32 LPC_exc_Q14, LPC_pred_Q10, LTP_pred_Q12; opus_int16 rand_scale_Q14; opus_int16 *B_Q14, *exc_buf_ptr; opus_int32 *sLPC_Q14_ptr; opus_int16 exc_buf[ 2 * MAX_SUB_FRAME_LENGTH ]; opus_int16 A_Q12[ MAX_LPC_ORDER ]; opus_int16 sLTP[ MAX_FRAME_LENGTH ]; opus_int32 sLTP_Q14[ 2 * MAX_FRAME_LENGTH ]; silk_PLC_struct *psPLC = &psDec->sPLC; if (psDec->first_frame_after_reset) silk_memset(psPLC->prevLPC_Q12, 0, MAX_LPC_ORDER*sizeof(psPLC->prevLPC_Q12[ 0 ])); /* Find random noise component */ /* Scale previous excitation signal */ exc_buf_ptr = exc_buf; for( k = 0; k < 2; k++ ) { for( i = 0; i < psPLC->subfr_length; i++ ) { exc_buf_ptr[ i ] = ( opus_int16 )silk_RSHIFT( silk_SMULWW( psDec->exc_Q10[ i + ( k + psPLC->nb_subfr - 2 ) * psPLC->subfr_length ], psPLC->prevGain_Q16[ k ] ), 10 ); } exc_buf_ptr += psPLC->subfr_length; } /* Find the subframe with lowest energy of the last two and use that as random noise generator */ silk_sum_sqr_shift( &energy1, &shift1, exc_buf, psPLC->subfr_length ); silk_sum_sqr_shift( &energy2, &shift2, &exc_buf[ psPLC->subfr_length ], psPLC->subfr_length ); if( silk_RSHIFT( energy1, shift2 ) < silk_RSHIFT( energy2, shift1 ) ) { /* First sub-frame has lowest energy */ rand_ptr = &psDec->exc_Q10[ silk_max_int( 0, ( psPLC->nb_subfr - 1 ) * psPLC->subfr_length - RAND_BUF_SIZE ) ]; } else { /* Second sub-frame has lowest energy */ rand_ptr = &psDec->exc_Q10[ silk_max_int( 0, psPLC->nb_subfr * psPLC->subfr_length - RAND_BUF_SIZE ) ]; } /* Setup Gain to random noise component */ B_Q14 = psPLC->LTPCoef_Q14; rand_scale_Q14 = psPLC->randScale_Q14; /* Setup attenuation gains */ harm_Gain_Q15 = HARM_ATT_Q15[ silk_min_int( NB_ATT - 1, psDec->lossCnt ) ]; if( psDec->prevSignalType == TYPE_VOICED ) { rand_Gain_Q15 = PLC_RAND_ATTENUATE_V_Q15[ silk_min_int( NB_ATT - 1, psDec->lossCnt ) ]; } else { rand_Gain_Q15 = PLC_RAND_ATTENUATE_UV_Q15[ silk_min_int( NB_ATT - 1, psDec->lossCnt ) ]; } /* LPC concealment. Apply BWE to previous LPC */ silk_bwexpander( psPLC->prevLPC_Q12, psDec->LPC_order, SILK_FIX_CONST( BWE_COEF, 16 ) ); /* Preload LPC coeficients to array on stack. Gives small performance gain */ silk_memcpy( A_Q12, psPLC->prevLPC_Q12, psDec->LPC_order * sizeof( opus_int16 ) ); /* First Lost frame */ if( psDec->lossCnt == 0 ) { rand_scale_Q14 = 1 << 14; /* Reduce random noise Gain for voiced frames */ if( psDec->prevSignalType == TYPE_VOICED ) { for( i = 0; i < LTP_ORDER; i++ ) { rand_scale_Q14 -= B_Q14[ i ]; } rand_scale_Q14 = silk_max_16( 3277, rand_scale_Q14 ); /* 0.2 */ rand_scale_Q14 = ( opus_int16 )silk_RSHIFT( silk_SMULBB( rand_scale_Q14, psPLC->prevLTP_scale_Q14 ), 14 ); } else { /* Reduce random noise for unvoiced frames with high LPC gain */ opus_int32 invGain_Q30, down_scale_Q30; silk_LPC_inverse_pred_gain( &invGain_Q30, psPLC->prevLPC_Q12, psDec->LPC_order ); down_scale_Q30 = silk_min_32( silk_RSHIFT( 1 << 30, LOG2_INV_LPC_GAIN_HIGH_THRES ), invGain_Q30 ); down_scale_Q30 = silk_max_32( silk_RSHIFT( 1 << 30, LOG2_INV_LPC_GAIN_LOW_THRES ), down_scale_Q30 ); down_scale_Q30 = silk_LSHIFT( down_scale_Q30, LOG2_INV_LPC_GAIN_HIGH_THRES ); rand_Gain_Q15 = silk_RSHIFT( silk_SMULWB( down_scale_Q30, rand_Gain_Q15 ), 14 ); } } rand_seed = psPLC->rand_seed; lag = silk_RSHIFT_ROUND( psPLC->pitchL_Q8, 8 ); sLTP_buf_idx = psDec->ltp_mem_length; /* Rewhiten LTP state */ idx = psDec->ltp_mem_length - lag - psDec->LPC_order - LTP_ORDER / 2; silk_assert( idx > 0 ); silk_LPC_analysis_filter( &sLTP[ idx ], &psDec->outBuf[ idx ], A_Q12, psDec->ltp_mem_length - idx, psDec->LPC_order ); /* Scale LTP state */ inv_gain_Q16 = silk_INVERSE32_varQ( psPLC->prevGain_Q16[ 1 ], 32 ); inv_gain_Q16 = silk_min( inv_gain_Q16, silk_int16_MAX ); inv_gain_Q30 = silk_LSHIFT( inv_gain_Q16, 14 ); for( i = idx + psDec->LPC_order; i < psDec->ltp_mem_length; i++ ) { sLTP_Q14[ i ] = silk_SMULWB( inv_gain_Q30, sLTP[ i ] ); } /***************************/ /* LTP synthesis filtering */ /***************************/ for( k = 0; k < psDec->nb_subfr; k++ ) { /* Setup pointer */ pred_lag_ptr = &sLTP_Q14[ sLTP_buf_idx - lag + LTP_ORDER / 2 ]; for( i = 0; i < psDec->subfr_length; i++ ) { /* Unrolled loop */ LTP_pred_Q12 = silk_SMULWB( pred_lag_ptr[ 0 ], B_Q14[ 0 ] ); LTP_pred_Q12 = silk_SMLAWB( LTP_pred_Q12, pred_lag_ptr[ -1 ], B_Q14[ 1 ] ); LTP_pred_Q12 = silk_SMLAWB( LTP_pred_Q12, pred_lag_ptr[ -2 ], B_Q14[ 2 ] ); LTP_pred_Q12 = silk_SMLAWB( LTP_pred_Q12, pred_lag_ptr[ -3 ], B_Q14[ 3 ] ); LTP_pred_Q12 = silk_SMLAWB( LTP_pred_Q12, pred_lag_ptr[ -4 ], B_Q14[ 4 ] ); pred_lag_ptr++; /* Generate LPC excitation */ rand_seed = silk_RAND( rand_seed ); idx = silk_RSHIFT( rand_seed, 25 ) & RAND_BUF_MASK; LPC_exc_Q14 = silk_LSHIFT32( silk_SMULWB( rand_ptr[ idx ], rand_scale_Q14 ), 6 ); /* Random noise part */ LPC_exc_Q14 = silk_ADD32( LPC_exc_Q14, silk_LSHIFT32( LTP_pred_Q12, 2 ) ); /* Harmonic part */ sLTP_Q14[ sLTP_buf_idx ] = LPC_exc_Q14; sLTP_buf_idx++; } /* Gradually reduce LTP gain */ for( j = 0; j < LTP_ORDER; j++ ) { B_Q14[ j ] = silk_RSHIFT( silk_SMULBB( harm_Gain_Q15, B_Q14[ j ] ), 15 ); } /* Gradually reduce excitation gain */ rand_scale_Q14 = silk_RSHIFT( silk_SMULBB( rand_scale_Q14, rand_Gain_Q15 ), 15 ); /* Slowly increase pitch lag */ psPLC->pitchL_Q8 = silk_SMLAWB( psPLC->pitchL_Q8, psPLC->pitchL_Q8, PITCH_DRIFT_FAC_Q16 ); psPLC->pitchL_Q8 = silk_min_32( psPLC->pitchL_Q8, silk_LSHIFT( silk_SMULBB( MAX_PITCH_LAG_MS, psDec->fs_kHz ), 8 ) ); lag = silk_RSHIFT_ROUND( psPLC->pitchL_Q8, 8 ); } /***************************/ /* LPC synthesis filtering */ /***************************/ sLPC_Q14_ptr = &sLTP_Q14[ psDec->ltp_mem_length - MAX_LPC_ORDER ]; /* Copy LPC state */ silk_memcpy( sLPC_Q14_ptr, psDec->sLPC_Q14_buf, MAX_LPC_ORDER * sizeof( opus_int32 ) ); silk_assert( psDec->LPC_order >= 10 ); /* check that unrolling works */ for( i = 0; i < psDec->frame_length; i++ ) { /* partly unrolled */ LPC_pred_Q10 = silk_SMULWB( sLPC_Q14_ptr[ MAX_LPC_ORDER + i - 1 ], A_Q12[ 0 ] ); LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, sLPC_Q14_ptr[ MAX_LPC_ORDER + i - 2 ], A_Q12[ 1 ] ); LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, sLPC_Q14_ptr[ MAX_LPC_ORDER + i - 3 ], A_Q12[ 2 ] ); LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, sLPC_Q14_ptr[ MAX_LPC_ORDER + i - 4 ], A_Q12[ 3 ] ); LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, sLPC_Q14_ptr[ MAX_LPC_ORDER + i - 5 ], A_Q12[ 4 ] ); LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, sLPC_Q14_ptr[ MAX_LPC_ORDER + i - 6 ], A_Q12[ 5 ] ); LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, sLPC_Q14_ptr[ MAX_LPC_ORDER + i - 7 ], A_Q12[ 6 ] ); LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, sLPC_Q14_ptr[ MAX_LPC_ORDER + i - 8 ], A_Q12[ 7 ] ); LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, sLPC_Q14_ptr[ MAX_LPC_ORDER + i - 9 ], A_Q12[ 8 ] ); LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, sLPC_Q14_ptr[ MAX_LPC_ORDER + i - 10 ], A_Q12[ 9 ] ); for( j = 10; j < psDec->LPC_order; j++ ) { LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, sLPC_Q14_ptr[ MAX_LPC_ORDER + i - j - 1 ], A_Q12[ j ] ); } /* Add prediction to LPC excitation */ sLPC_Q14_ptr[ MAX_LPC_ORDER + i ] = silk_ADD_LSHIFT32( sLPC_Q14_ptr[ MAX_LPC_ORDER + i ], LPC_pred_Q10, 4 ); /* Scale with Gain */ frame[ i ] = ( opus_int16 )silk_SAT16( silk_RSHIFT_ROUND( silk_SMULWW( sLPC_Q14_ptr[ MAX_LPC_ORDER + i ], psPLC->prevGain_Q16[ 1 ] ), 14 ) ); } /* Save LPC state */ silk_memcpy( psDec->sLPC_Q14_buf, &sLPC_Q14_ptr[ psDec->frame_length ], MAX_LPC_ORDER * sizeof( opus_int32 ) ); /**************************************/ /* Update states */ /**************************************/ psPLC->rand_seed = rand_seed; psPLC->randScale_Q14 = rand_scale_Q14; for( i = 0; i < MAX_NB_SUBFR; i++ ) { psDecCtrl->pitchL[ i ] = lag; } }
71, 48, 58, 130, 255, 255, 255, 166, 110, 73, 57, 62, 104, 210, 255, 255, 251, 123, 65, 55, 68, 100, 171, 255 }; const opus_uint8 silk_NLSF_PRED_NB_MB_Q8[ 18 ] = { 179, 138, 140, 148, 151, 149, 153, 151, 163, 116, 67, 82, 59, 92, 72, 100, 89, 92 }; const opus_int16 silk_NLSF_DELTA_MIN_NB_MB_Q15[ 11 ] = { 250, 3, 6, 3, 3, 3, 4, 3, 3, 3, 461 }; const silk_NLSF_CB_struct silk_NLSF_CB_NB_MB = { 32, 10, SILK_FIX_CONST( 0.18, 16 ), SILK_FIX_CONST( 1.0 / 0.18, 6 ), silk_NLSF_CB1_NB_MB_Q8, silk_NLSF_CB1_iCDF_NB_MB, silk_NLSF_PRED_NB_MB_Q8, silk_NLSF_CB2_SELECT_NB_MB, silk_NLSF_CB2_iCDF_NB_MB, silk_NLSF_CB2_BITS_NB_MB_Q5, silk_NLSF_DELTA_MIN_NB_MB_Q15, };