void SKP_Silk_VAD_GetNoiseLevels( const SKP_int32 pX[ VAD_N_BANDS ], /* I subband energies */ SKP_Silk_VAD_state *psSilk_VAD /* I/O Pointer to Silk VAD state */ ) { SKP_int k; SKP_int32 nl, nrg, inv_nrg; SKP_int coef, min_coef; /* Initially faster smoothing */ if( psSilk_VAD->counter < 1000 ) { /* 1000 = 20 sec */ min_coef = SKP_DIV32_16( SKP_int16_MAX, SKP_RSHIFT( psSilk_VAD->counter, 4 ) + 1 ); } else { min_coef = 0; } for( k = 0; k < VAD_N_BANDS; k++ ) { /* Get old noise level estimate for current band */ nl = psSilk_VAD->NL[ k ]; SKP_assert( nl >= 0 ); /* Add bias */ nrg = SKP_ADD_POS_SAT32( pX[ k ], psSilk_VAD->NoiseLevelBias[ k ] ); SKP_assert( nrg > 0 ); /* Invert energies */ inv_nrg = SKP_DIV32( SKP_int32_MAX, nrg ); SKP_assert( inv_nrg >= 0 ); /* Less update when subband energy is high */ if( nrg > SKP_LSHIFT( nl, 3 ) ) { coef = VAD_NOISE_LEVEL_SMOOTH_COEF_Q16 >> 3; } else if( nrg < nl ) {
SKP_int SKP_Silk_VAD_GetSA_Q8( /* O Return value, 0 if success */ SKP_Silk_encoder_state *psEncC, /* I/O Encoder state */ const SKP_int16 pIn[] /* I PCM input */ ) { SKP_int SA_Q15, pSNR_dB_Q7, input_tilt; SKP_int decimated_framelength, dec_subframe_length, dec_subframe_offset, SNR_Q7, i, b, s; SKP_int32 sumSquared, smooth_coef_Q16; SKP_int16 HPstateTmp; SKP_int16 X[ VAD_N_BANDS ][ MAX_FRAME_LENGTH / 2 ]; SKP_int32 Xnrg[ VAD_N_BANDS ]; SKP_int32 NrgToNoiseRatio_Q8[ VAD_N_BANDS ]; SKP_int32 speech_nrg, x_tmp; SKP_int ret = 0; SKP_Silk_VAD_state *psSilk_VAD = &psEncC->sVAD; /* Safety checks */ SKP_assert( VAD_N_BANDS == 4 ); SKP_assert( MAX_FRAME_LENGTH >= psEncC->frame_length ); SKP_assert( psEncC->frame_length <= 512 ); SKP_assert( psEncC->frame_length == 8 * SKP_RSHIFT( psEncC->frame_length, 3 ) ); /***********************/ /* Filter and Decimate */ /***********************/ /* 0-8 kHz to 0-4 kHz and 4-8 kHz */ SKP_Silk_ana_filt_bank_1( pIn, &psSilk_VAD->AnaState[ 0 ], &X[ 0 ][ 0 ], &X[ 3 ][ 0 ], psEncC->frame_length ); /* 0-4 kHz to 0-2 kHz and 2-4 kHz */ SKP_Silk_ana_filt_bank_1( &X[ 0 ][ 0 ], &psSilk_VAD->AnaState1[ 0 ], &X[ 0 ][ 0 ], &X[ 2 ][ 0 ], SKP_RSHIFT( psEncC->frame_length, 1 ) ); /* 0-2 kHz to 0-1 kHz and 1-2 kHz */ SKP_Silk_ana_filt_bank_1( &X[ 0 ][ 0 ], &psSilk_VAD->AnaState2[ 0 ], &X[ 0 ][ 0 ], &X[ 1 ][ 0 ], SKP_RSHIFT( psEncC->frame_length, 2 ) ); /*********************************************/ /* HP filter on lowest band (differentiator) */ /*********************************************/ decimated_framelength = SKP_RSHIFT( psEncC->frame_length, 3 ); X[ 0 ][ decimated_framelength - 1 ] = SKP_RSHIFT( X[ 0 ][ decimated_framelength - 1 ], 1 ); HPstateTmp = X[ 0 ][ decimated_framelength - 1 ]; for( i = decimated_framelength - 1; i > 0; i-- ) { X[ 0 ][ i - 1 ] = SKP_RSHIFT( X[ 0 ][ i - 1 ], 1 ); X[ 0 ][ i ] -= X[ 0 ][ i - 1 ]; } X[ 0 ][ 0 ] -= psSilk_VAD->HPstate; psSilk_VAD->HPstate = HPstateTmp; /*************************************/ /* Calculate the energy in each band */ /*************************************/ for( b = 0; b < VAD_N_BANDS; b++ ) { /* Find the decimated framelength in the non-uniformly divided bands */ decimated_framelength = SKP_RSHIFT( psEncC->frame_length, SKP_min_int( VAD_N_BANDS - b, VAD_N_BANDS - 1 ) ); /* Split length into subframe lengths */ dec_subframe_length = SKP_RSHIFT( decimated_framelength, VAD_INTERNAL_SUBFRAMES_LOG2 ); dec_subframe_offset = 0; /* Compute energy per sub-frame */ /* initialize with summed energy of last subframe */ Xnrg[ b ] = psSilk_VAD->XnrgSubfr[ b ]; for( s = 0; s < VAD_INTERNAL_SUBFRAMES; s++ ) { sumSquared = 0; for( i = 0; i < dec_subframe_length; i++ ) { /* The energy will be less than dec_subframe_length * ( SKP_int16_MIN / 8 ) ^ 2. */ /* Therefore we can accumulate with no risk of overflow (unless dec_subframe_length > 128) */ x_tmp = SKP_RSHIFT( X[ b ][ i + dec_subframe_offset ], 3 ); sumSquared = SKP_SMLABB( sumSquared, x_tmp, x_tmp ); /* Safety check */ SKP_assert( sumSquared >= 0 ); } /* Add/saturate summed energy of current subframe */ if( s < VAD_INTERNAL_SUBFRAMES - 1 ) { Xnrg[ b ] = SKP_ADD_POS_SAT32( Xnrg[ b ], sumSquared ); } else { /* Look-ahead subframe */ Xnrg[ b ] = SKP_ADD_POS_SAT32( Xnrg[ b ], SKP_RSHIFT( sumSquared, 1 ) ); } dec_subframe_offset += dec_subframe_length; } psSilk_VAD->XnrgSubfr[ b ] = sumSquared; } /********************/ /* Noise estimation */ /********************/ SKP_Silk_VAD_GetNoiseLevels( &Xnrg[ 0 ], psSilk_VAD ); /***********************************************/ /* Signal-plus-noise to noise ratio estimation */ /***********************************************/ sumSquared = 0; input_tilt = 0; for( b = 0; b < VAD_N_BANDS; b++ ) { speech_nrg = Xnrg[ b ] - psSilk_VAD->NL[ b ]; if( speech_nrg > 0 ) { /* Divide, with sufficient resolution */ if( ( Xnrg[ b ] & 0xFF800000 ) == 0 ) { NrgToNoiseRatio_Q8[ b ] = SKP_DIV32( SKP_LSHIFT( Xnrg[ b ], 8 ), psSilk_VAD->NL[ b ] + 1 ); } else { NrgToNoiseRatio_Q8[ b ] = SKP_DIV32( Xnrg[ b ], SKP_RSHIFT( psSilk_VAD->NL[ b ], 8 ) + 1 ); } /* Convert to log domain */ SNR_Q7 = SKP_Silk_lin2log( NrgToNoiseRatio_Q8[ b ] ) - 8 * 128; /* Sum-of-squares */ sumSquared = SKP_SMLABB( sumSquared, SNR_Q7, SNR_Q7 ); /* Q14 */ /* Tilt measure */ if( speech_nrg < ( 1 << 20 ) ) { /* Scale down SNR value for small subband speech energies */ SNR_Q7 = SKP_SMULWB( SKP_LSHIFT( SKP_Silk_SQRT_APPROX( speech_nrg ), 6 ), SNR_Q7 ); } input_tilt = SKP_SMLAWB( input_tilt, tiltWeights[ b ], SNR_Q7 ); } else { NrgToNoiseRatio_Q8[ b ] = 256; } } /* Mean-of-squares */ sumSquared = SKP_DIV32_16( sumSquared, VAD_N_BANDS ); /* Q14 */ /* Root-mean-square approximation, scale to dBs, and write to output pointer */ pSNR_dB_Q7 = ( SKP_int16 )( 3 * SKP_Silk_SQRT_APPROX( sumSquared ) ); /* Q7 */ /*********************************/ /* Speech Probability Estimation */ /*********************************/ SA_Q15 = SKP_Silk_sigm_Q15( SKP_SMULWB( VAD_SNR_FACTOR_Q16, pSNR_dB_Q7 ) - VAD_NEGATIVE_OFFSET_Q5 ); /**************************/ /* Frequency Tilt Measure */ /**************************/ psEncC->input_tilt_Q15 = SKP_LSHIFT( SKP_Silk_sigm_Q15( input_tilt ) - 16384, 1 ); /**************************************************/ /* Scale the sigmoid output based on power levels */ /**************************************************/ speech_nrg = 0; for( b = 0; b < VAD_N_BANDS; b++ ) { /* Accumulate signal-without-noise energies, higher frequency bands have more weight */ speech_nrg += ( b + 1 ) * SKP_RSHIFT( Xnrg[ b ] - psSilk_VAD->NL[ b ], 4 ); } /* Power scaling */ if( speech_nrg <= 0 ) { SA_Q15 = SKP_RSHIFT( SA_Q15, 1 ); } else if( speech_nrg < 32768 ) { if( psEncC->frame_length == 10 * psEncC->fs_kHz ) { speech_nrg = SKP_LSHIFT_SAT32( speech_nrg, 16 ); } else { speech_nrg = SKP_LSHIFT_SAT32( speech_nrg, 15 ); } /* square-root */ speech_nrg = SKP_Silk_SQRT_APPROX( speech_nrg ); SA_Q15 = SKP_SMULWB( 32768 + speech_nrg, SA_Q15 ); } /* Copy the resulting speech activity in Q8 */ psEncC->speech_activity_Q8 = SKP_min_int( SKP_RSHIFT( SA_Q15, 7 ), SKP_uint8_MAX ); /***********************************/ /* Energy Level and SNR estimation */ /***********************************/ /* Smoothing coefficient */ smooth_coef_Q16 = SKP_SMULWB( VAD_SNR_SMOOTH_COEF_Q18, SKP_SMULWB( SA_Q15, SA_Q15 ) ); if( psEncC->frame_length == 10 * psEncC->fs_kHz ) { smooth_coef_Q16 >>= 1; }
void SKP_Silk_quant_LTP_gains_FIX( SKP_int16 B_Q14[], /* I/O (un)quantized LTP gains */ SKP_int cbk_index[], /* O Codebook Index */ SKP_int *periodicity_index, /* O Periodicity Index */ const SKP_int32 W_Q18[], /* I Error Weights in Q18 */ SKP_int mu_Q8, /* I Mu value (R/D tradeoff) */ SKP_int lowComplexity /* I Flag for low complexity */ ) { SKP_int j, k, temp_idx[ NB_SUBFR ], cbk_size; const SKP_uint16 *cdf_ptr; const SKP_int16 *cl_ptr; const SKP_int16 *cbk_ptr_Q14; const SKP_int16 *b_Q14_ptr; const SKP_int32 *W_Q18_ptr; SKP_int32 rate_dist_subfr, rate_dist, min_rate_dist; /***************************************************/ /* iterate over different codebooks with different */ /* rates/distortions, and choose best */ /***************************************************/ min_rate_dist = SKP_int32_MAX; for( k = 0; k < 3; k++ ) { cdf_ptr = SKP_Silk_LTP_gain_CDF_ptrs[ k ]; cl_ptr = SKP_Silk_LTP_gain_BITS_Q6_ptrs[ k ]; cbk_ptr_Q14 = SKP_Silk_LTP_vq_ptrs_Q14[ k ]; cbk_size = SKP_Silk_LTP_vq_sizes[ k ]; /* Setup pointer to first subframe */ W_Q18_ptr = W_Q18; b_Q14_ptr = B_Q14; rate_dist = 0; for( j = 0; j < NB_SUBFR; j++ ) { SKP_Silk_VQ_WMat_EC_FIX( &temp_idx[ j ], /* O index of best codebook vector */ &rate_dist_subfr, /* O best weighted quantization error + mu * rate */ b_Q14_ptr, /* I input vector to be quantized */ W_Q18_ptr, /* I weighting matrix */ cbk_ptr_Q14, /* I codebook */ cl_ptr, /* I code length for each codebook vector */ mu_Q8, /* I tradeoff between weighted error and rate */ cbk_size /* I number of vectors in codebook */ ); rate_dist = SKP_ADD_POS_SAT32( rate_dist, rate_dist_subfr ); b_Q14_ptr += LTP_ORDER; W_Q18_ptr += LTP_ORDER * LTP_ORDER; } /* Avoid never finding a codebook */ rate_dist = SKP_min( SKP_int32_MAX - 1, rate_dist ); if( rate_dist < min_rate_dist ) { min_rate_dist = rate_dist; SKP_memcpy( cbk_index, temp_idx, NB_SUBFR * sizeof( SKP_int ) ); *periodicity_index = k; } /* Break early in low-complexity mode if rate distortion is below threshold */ if( lowComplexity && ( rate_dist < SKP_Silk_LTP_gain_middle_avg_RD_Q14 ) ) { break; } } cbk_ptr_Q14 = SKP_Silk_LTP_vq_ptrs_Q14[ *periodicity_index ]; for( j = 0; j < NB_SUBFR; j++ ) { for( k = 0; k < LTP_ORDER; k++ ) { B_Q14[ j * LTP_ORDER + k ] = cbk_ptr_Q14[ SKP_MLA( k, cbk_index[ j ], LTP_ORDER ) ]; } } }
SKP_int SKP_Silk_encode_frame_FLP( SKP_Silk_encoder_state_FLP *psEnc, /* I/O Encoder state FLP */ SKP_uint8 *pCode, /* O Payload */ SKP_int16 *pnBytesOut, /* I/O Number of payload bytes; */ /* input: max length; output: used */ const SKP_int16 *pIn /* I Input speech frame */ ) { SKP_Silk_encoder_control_FLP sEncCtrl; SKP_int k, nBytes, ret = 0; SKP_float *x_frame, *res_pitch_frame; SKP_int16 pIn_HP[ MAX_FRAME_LENGTH ]; SKP_int16 pIn_HP_LP[ MAX_FRAME_LENGTH ]; SKP_float xfw[ MAX_FRAME_LENGTH ]; SKP_float res_pitch[ 2 * MAX_FRAME_LENGTH + LA_PITCH_MAX ]; SKP_int LBRR_idx, frame_terminator; /* Low bitrate redundancy parameters */ SKP_uint8 LBRRpayload[ MAX_ARITHM_BYTES ]; SKP_int16 nBytesLBRR; const SKP_uint16 *FrameTermination_CDF; sEncCtrl.sCmn.Seed = psEnc->sCmn.frameCounter++ & 3; /**************************************************************/ /* Setup Input Pointers, and insert frame in input buffer */ /*************************************************************/ /* pointers aligned with start of frame to encode */ x_frame = psEnc->x_buf + psEnc->sCmn.frame_length; // start of frame to encode res_pitch_frame = res_pitch + psEnc->sCmn.frame_length; // start of pitch LPC residual frame /****************************/ /* Voice Activity Detection */ /****************************/ SKP_Silk_VAD_FLP( psEnc, &sEncCtrl, pIn ); /*******************************************/ /* High-pass filtering of the input signal */ /*******************************************/ #if HIGH_PASS_INPUT /* Variable high-pass filter */ SKP_Silk_HP_variable_cutoff_FLP( psEnc, &sEncCtrl, pIn_HP, pIn ); #else SKP_memcpy( pIn_HP, pIn, psEnc->sCmn.frame_length * sizeof( SKP_int16 ) ); #endif #if SWITCH_TRANSITION_FILTERING /* Ensure smooth bandwidth transitions */ SKP_Silk_LP_variable_cutoff( &psEnc->sCmn.sLP, pIn_HP_LP, pIn_HP, psEnc->sCmn.frame_length ); #else SKP_memcpy( pIn_HP_LP, pIn_HP, psEnc->sCmn.frame_length * sizeof( SKP_int16 ) ); #endif /*******************************************/ /* Copy new frame to front of input buffer */ /*******************************************/ SKP_short2float_array( x_frame + LA_SHAPE_MS * psEnc->sCmn.fs_kHz, pIn_HP_LP, psEnc->sCmn.frame_length ); /* Add tiny signal to avoid high CPU load from denormalized floating point numbers */ for( k = 0; k < 8; k++ ) { x_frame[ LA_SHAPE_MS * psEnc->sCmn.fs_kHz + k * ( psEnc->sCmn.frame_length >> 3 ) ] += ( 1 - ( k & 2 ) ) * 1e-6f; } /*****************************************/ /* Find pitch lags, initial LPC analysis */ /*****************************************/ SKP_Silk_find_pitch_lags_FLP( psEnc, &sEncCtrl, res_pitch, x_frame ); /************************/ /* Noise shape analysis */ /************************/ SKP_Silk_noise_shape_analysis_FLP( psEnc, &sEncCtrl, res_pitch_frame, x_frame ); /*****************************************/ /* Prefiltering for noise shaper */ /*****************************************/ SKP_Silk_prefilter_FLP( psEnc, &sEncCtrl, xfw, x_frame ); /***************************************************/ /* Find linear prediction coefficients (LPC + LTP) */ /***************************************************/ SKP_Silk_find_pred_coefs_FLP( psEnc, &sEncCtrl, res_pitch ); /****************************************/ /* Process gains */ /****************************************/ SKP_Silk_process_gains_FLP( psEnc, &sEncCtrl ); /****************************************/ /* Low Bitrate Redundant Encoding */ /****************************************/ nBytesLBRR = MAX_ARITHM_BYTES; SKP_Silk_LBRR_encode_FLP( psEnc, &sEncCtrl, LBRRpayload, &nBytesLBRR, xfw ); /*****************************************/ /* Noise shaping quantization */ /*****************************************/ SKP_Silk_NSQ_wrapper_FLP( psEnc, &sEncCtrl, xfw, psEnc->sCmn.q, 0 ); /**************************************************/ /* Convert speech activity into VAD and DTX flags */ /**************************************************/ if( psEnc->speech_activity < SPEECH_ACTIVITY_DTX_THRES ) { psEnc->sCmn.vadFlag = NO_VOICE_ACTIVITY; psEnc->sCmn.noSpeechCounter++; if( psEnc->sCmn.noSpeechCounter > NO_SPEECH_FRAMES_BEFORE_DTX ) { psEnc->sCmn.inDTX = 1; } if( psEnc->sCmn.noSpeechCounter > MAX_CONSECUTIVE_DTX + NO_SPEECH_FRAMES_BEFORE_DTX ) { psEnc->sCmn.noSpeechCounter = NO_SPEECH_FRAMES_BEFORE_DTX; psEnc->sCmn.inDTX = 0; } } else { psEnc->sCmn.noSpeechCounter = 0; psEnc->sCmn.inDTX = 0; psEnc->sCmn.vadFlag = VOICE_ACTIVITY; } /****************************************/ /* Initialize range coder */ /****************************************/ if( psEnc->sCmn.nFramesInPayloadBuf == 0 ) { SKP_Silk_range_enc_init( &psEnc->sCmn.sRC ); psEnc->sCmn.nBytesInPayloadBuf = 0; } /****************************************/ /* Encode Parameters */ /****************************************/ SKP_Silk_encode_parameters( &psEnc->sCmn, &sEncCtrl.sCmn, &psEnc->sCmn.sRC, psEnc->sCmn.q ); FrameTermination_CDF = SKP_Silk_FrameTermination_CDF; /****************************************/ /* Update Buffers and State */ /****************************************/ /* Update input buffer */ SKP_memmove( psEnc->x_buf, &psEnc->x_buf[ psEnc->sCmn.frame_length ], ( psEnc->sCmn.frame_length + LA_SHAPE_MS * psEnc->sCmn.fs_kHz ) * sizeof( SKP_float ) ); /* Parameters needed for next frame */ psEnc->sCmn.prev_sigtype = sEncCtrl.sCmn.sigtype; psEnc->sCmn.prevLag = sEncCtrl.sCmn.pitchL[ NB_SUBFR - 1]; psEnc->sCmn.first_frame_after_reset = 0; if( psEnc->sCmn.sRC.error ) { /* Encoder returned error: Clear payload buffer */ psEnc->sCmn.nFramesInPayloadBuf = 0; } else { psEnc->sCmn.nFramesInPayloadBuf++; } /****************************************/ /* Finalize payload and copy to output */ /****************************************/ if( psEnc->sCmn.nFramesInPayloadBuf * FRAME_LENGTH_MS >= psEnc->sCmn.PacketSize_ms ) { LBRR_idx = ( psEnc->sCmn.oldest_LBRR_idx + 1 ) & LBRR_IDX_MASK; /* Check if FEC information should be added */ frame_terminator = SKP_SILK_LAST_FRAME; if( psEnc->sCmn.LBRR_buffer[ LBRR_idx ].usage == SKP_SILK_ADD_LBRR_TO_PLUS1 ) { frame_terminator = SKP_SILK_LBRR_VER1; } if( psEnc->sCmn.LBRR_buffer[ psEnc->sCmn.oldest_LBRR_idx ].usage == SKP_SILK_ADD_LBRR_TO_PLUS2 ) { frame_terminator = SKP_SILK_LBRR_VER2; LBRR_idx = psEnc->sCmn.oldest_LBRR_idx; } /* Add the frame termination info to stream */ SKP_Silk_range_encoder( &psEnc->sCmn.sRC, frame_terminator, FrameTermination_CDF ); /* Payload length so far */ SKP_Silk_range_coder_get_length( &psEnc->sCmn.sRC, &nBytes ); /* Check that there is enough space in external output buffer, and move data */ if( *pnBytesOut >= nBytes ) { SKP_Silk_range_enc_wrap_up( &psEnc->sCmn.sRC ); SKP_memcpy( pCode, psEnc->sCmn.sRC.buffer, nBytes * sizeof( SKP_uint8 ) ); if( frame_terminator > SKP_SILK_MORE_FRAMES && *pnBytesOut >= nBytes + psEnc->sCmn.LBRR_buffer[ LBRR_idx ].nBytes ) { /* Get old packet and add to payload. */ SKP_memcpy( &pCode[ nBytes ], psEnc->sCmn.LBRR_buffer[ LBRR_idx ].payload, psEnc->sCmn.LBRR_buffer[ LBRR_idx ].nBytes * sizeof( SKP_uint8 ) ); nBytes += psEnc->sCmn.LBRR_buffer[ LBRR_idx ].nBytes; } *pnBytesOut = nBytes; /* Update FEC buffer */ SKP_memcpy( psEnc->sCmn.LBRR_buffer[ psEnc->sCmn.oldest_LBRR_idx ].payload, LBRRpayload, nBytesLBRR * sizeof( SKP_uint8 ) ); psEnc->sCmn.LBRR_buffer[ psEnc->sCmn.oldest_LBRR_idx ].nBytes = nBytesLBRR; /* The line below describes how FEC should be used */ psEnc->sCmn.LBRR_buffer[ psEnc->sCmn.oldest_LBRR_idx ].usage = sEncCtrl.sCmn.LBRR_usage; psEnc->sCmn.oldest_LBRR_idx = ( ( psEnc->sCmn.oldest_LBRR_idx + 1 ) & LBRR_IDX_MASK ); } else { /* Not enough space: Payload will be discarded */ *pnBytesOut = 0; nBytes = 0; ret = SKP_SILK_ENC_PAYLOAD_BUF_TOO_SHORT; } /* Reset the number of frames in payload buffer */ psEnc->sCmn.nFramesInPayloadBuf = 0; } else { /* No payload this time */ *pnBytesOut = 0; /* Encode that more frames follows */ frame_terminator = SKP_SILK_MORE_FRAMES; SKP_Silk_range_encoder( &psEnc->sCmn.sRC, frame_terminator, FrameTermination_CDF ); /* Payload length so far */ SKP_Silk_range_coder_get_length( &psEnc->sCmn.sRC, &nBytes ); } /* Check for arithmetic coder errors */ if( psEnc->sCmn.sRC.error ) { ret = SKP_SILK_ENC_INTERNAL_ERROR; } /* Simulate number of ms buffered in channel because of exceeding TargetRate */ psEnc->BufferedInChannel_ms += ( 8.0f * 1000.0f * ( nBytes - psEnc->sCmn.nBytesInPayloadBuf ) ) / psEnc->sCmn.TargetRate_bps; psEnc->BufferedInChannel_ms -= FRAME_LENGTH_MS; psEnc->BufferedInChannel_ms = SKP_LIMIT_float( psEnc->BufferedInChannel_ms, 0.0f, 100.0f ); psEnc->sCmn.nBytesInPayloadBuf = nBytes; if( psEnc->speech_activity > WB_DETECT_ACTIVE_SPEECH_LEVEL_THRES ) { psEnc->sCmn.sSWBdetect.ActiveSpeech_ms = SKP_ADD_POS_SAT32( psEnc->sCmn.sSWBdetect.ActiveSpeech_ms, FRAME_LENGTH_MS ); } return( ret ); }
int SKP_Silk_encode_frame_FIX(SKP_Silk_encoder_state_FIX * psEnc, /* I/O Pointer to Silk FIX encoder state */ uint8_t * pCode, /* O Pointer to payload */ int16_t * pnBytesOut, /* I/O Pointer to number of payload bytes */ /* input: max length; output: used */ const int16_t * pIn /* I Pointer to input speech frame */ ) { SKP_Silk_encoder_control_FIX sEncCtrl; int i, nBytes, ret = 0; int16_t *x_frame, *res_pitch_frame; int16_t xfw[MAX_FRAME_LENGTH]; int16_t pIn_HP[MAX_FRAME_LENGTH]; int16_t res_pitch[2 * MAX_FRAME_LENGTH + LA_PITCH_MAX]; int LBRR_idx, frame_terminator, SNR_dB_Q7; const uint16_t *FrameTermination_CDF; /* Low bitrate redundancy parameters */ uint8_t LBRRpayload[MAX_ARITHM_BYTES]; int16_t nBytesLBRR; //int32_t Seed[ MAX_LAYERS ]; sEncCtrl.sCmn.Seed = psEnc->sCmn.frameCounter++ & 3; /**************************************************************/ /* Setup Input Pointers, and insert frame in input buffer */ /*************************************************************/ x_frame = psEnc->x_buf + psEnc->sCmn.frame_length; /* start of frame to encode */ res_pitch_frame = res_pitch + psEnc->sCmn.frame_length; /* start of pitch LPC residual frame */ /****************************/ /* Voice Activity Detection */ /****************************/ ret = SKP_Silk_VAD_GetSA_Q8(&psEnc->sCmn.sVAD, &psEnc->speech_activity_Q8, &SNR_dB_Q7, sEncCtrl.input_quality_bands_Q15, &sEncCtrl.input_tilt_Q15, pIn, psEnc->sCmn.frame_length); /*******************************************/ /* High-pass filtering of the input signal */ /*******************************************/ #if HIGH_PASS_INPUT /* Variable high-pass filter */ SKP_Silk_HP_variable_cutoff_FIX(psEnc, &sEncCtrl, pIn_HP, pIn); #else SKP_memcpy(pIn_HP, pIn, psEnc->sCmn.frame_length * sizeof(int16_t)); #endif #if SWITCH_TRANSITION_FILTERING /* Ensure smooth bandwidth transitions */ SKP_Silk_LP_variable_cutoff(&psEnc->sCmn.sLP, x_frame + psEnc->sCmn.la_shape, pIn_HP, psEnc->sCmn.frame_length); #else SKP_memcpy(x_frame + psEnc->sCmn.la_shape, pIn_HP, psEnc->sCmn.frame_length * sizeof(int16_t)); #endif /*****************************************/ /* Find pitch lags, initial LPC analysis */ /*****************************************/ SKP_Silk_find_pitch_lags_FIX(psEnc, &sEncCtrl, res_pitch, x_frame); /************************/ /* Noise shape analysis */ /************************/ SKP_Silk_noise_shape_analysis_FIX(psEnc, &sEncCtrl, res_pitch_frame, x_frame); /*****************************************/ /* Prefiltering for noise shaper */ /*****************************************/ SKP_Silk_prefilter_FIX(psEnc, &sEncCtrl, xfw, x_frame); /***************************************************/ /* Find linear prediction coefficients (LPC + LTP) */ /***************************************************/ SKP_Silk_find_pred_coefs_FIX(psEnc, &sEncCtrl, res_pitch); /****************************************/ /* Process gains */ /****************************************/ SKP_Silk_process_gains_FIX(psEnc, &sEncCtrl); psEnc->sCmn.sigtype[psEnc->sCmn.nFramesInPayloadBuf] = sEncCtrl.sCmn.sigtype; psEnc->sCmn.QuantOffsetType[psEnc->sCmn.nFramesInPayloadBuf] = sEncCtrl.sCmn.QuantOffsetType; /****************************************/ /* Low Bitrate Redundant Encoding */ /****************************************/ nBytesLBRR = MAX_ARITHM_BYTES; SKP_Silk_LBRR_encode_FIX(psEnc, &sEncCtrl, LBRRpayload, &nBytesLBRR, xfw); /*****************************************/ /* Noise shaping quantization */ /*****************************************/ psEnc->NoiseShapingQuantizer(&psEnc->sCmn, &sEncCtrl.sCmn, &psEnc->sNSQ, xfw, &psEnc->sCmn.q[psEnc->sCmn. nFramesInPayloadBuf * psEnc->sCmn.frame_length], sEncCtrl.sCmn.NLSFInterpCoef_Q2, sEncCtrl.PredCoef_Q12[0], sEncCtrl.LTPCoef_Q14, sEncCtrl.AR2_Q13, sEncCtrl.HarmShapeGain_Q14, sEncCtrl.Tilt_Q14, sEncCtrl.LF_shp_Q14, sEncCtrl.Gains_Q16, sEncCtrl.Lambda_Q10, sEncCtrl.LTP_scale_Q14); /**************************************************/ /* Convert speech activity into VAD and DTX flags */ /**************************************************/ if (psEnc->speech_activity_Q8 < SPEECH_ACTIVITY_DTX_THRES_Q8) { psEnc->sCmn.vadFlag = NO_VOICE_ACTIVITY; psEnc->sCmn.noSpeechCounter++; if (psEnc->sCmn.noSpeechCounter > NO_SPEECH_FRAMES_BEFORE_DTX) { psEnc->sCmn.inDTX = 1; } if (psEnc->sCmn.noSpeechCounter > MAX_CONSECUTIVE_DTX) { psEnc->sCmn.noSpeechCounter = 0; psEnc->sCmn.inDTX = 0; } } else { psEnc->sCmn.noSpeechCounter = 0; psEnc->sCmn.inDTX = 0; psEnc->sCmn.vadFlag = VOICE_ACTIVITY; } /****************************************/ /* Initialize arithmetic coder */ /****************************************/ if (psEnc->sCmn.nFramesInPayloadBuf == 0) { SKP_Silk_range_enc_init(&psEnc->sCmn.sRC); psEnc->sCmn.nBytesInPayloadBuf = 0; } /****************************************/ /* Encode Parameters */ /****************************************/ if (psEnc->sCmn.bitstream_v == BIT_STREAM_V4) { SKP_Silk_encode_parameters_v4(&psEnc->sCmn, &sEncCtrl.sCmn, &psEnc->sCmn.sRC); FrameTermination_CDF = SKP_Silk_FrameTermination_v4_CDF; } else { SKP_Silk_encode_parameters(&psEnc->sCmn, &sEncCtrl.sCmn, &psEnc->sCmn.sRC, &psEnc->sCmn.q[psEnc->sCmn. nFramesInPayloadBuf * psEnc->sCmn. frame_length]); FrameTermination_CDF = SKP_Silk_FrameTermination_CDF; } /****************************************/ /* Update Buffers and State */ /****************************************/ /* Update Input buffer */ SKP_memmove(psEnc->x_buf, &psEnc->x_buf[psEnc->sCmn.frame_length], (psEnc->sCmn.frame_length + psEnc->sCmn.la_shape) * sizeof(int16_t)); /* parameters needed for next frame */ psEnc->sCmn.prev_sigtype = sEncCtrl.sCmn.sigtype; psEnc->sCmn.prevLag = sEncCtrl.sCmn.pitchL[NB_SUBFR - 1]; psEnc->sCmn.first_frame_after_reset = 0; if (psEnc->sCmn.sRC.error) { /* encoder returned error: clear payload buffer */ psEnc->sCmn.nFramesInPayloadBuf = 0; } else { psEnc->sCmn.nFramesInPayloadBuf++; } /****************************************/ /* finalize payload and copy to output */ /****************************************/ if (psEnc->sCmn.nFramesInPayloadBuf * FRAME_LENGTH_MS >= psEnc->sCmn.PacketSize_ms) { LBRR_idx = (psEnc->sCmn.oldest_LBRR_idx + 1) & LBRR_IDX_MASK; /* Check if FEC information should be added */ frame_terminator = SKP_SILK_LAST_FRAME; if (psEnc->sCmn.LBRR_buffer[LBRR_idx].usage == SKP_SILK_ADD_LBRR_TO_PLUS1) { frame_terminator = SKP_SILK_LBRR_VER1; } if (psEnc->sCmn.LBRR_buffer[psEnc->sCmn.oldest_LBRR_idx]. usage == SKP_SILK_ADD_LBRR_TO_PLUS2) { frame_terminator = SKP_SILK_LBRR_VER2; LBRR_idx = psEnc->sCmn.oldest_LBRR_idx; } /* Add the frame termination info to stream */ SKP_Silk_range_encoder(&psEnc->sCmn.sRC, frame_terminator, FrameTermination_CDF); if (psEnc->sCmn.bitstream_v == BIT_STREAM_V4) { /* Code excitation signal */ for (i = 0; i < psEnc->sCmn.nFramesInPayloadBuf; i++) { SKP_Silk_encode_pulses(&psEnc->sCmn.sRC, psEnc->sCmn.sigtype[i], psEnc->sCmn. QuantOffsetType[i], &psEnc->sCmn.q[i * psEnc-> sCmn. frame_length], psEnc->sCmn. frame_length); } } /* payload length so far */ SKP_Silk_range_coder_get_length(&psEnc->sCmn.sRC, &nBytes); /* check that there is enough space in external output buffer, and move data */ if (*pnBytesOut >= nBytes) { SKP_Silk_range_enc_wrap_up(&psEnc->sCmn.sRC); SKP_memcpy(pCode, psEnc->sCmn.sRC.buffer, nBytes * sizeof(uint8_t)); if (frame_terminator > SKP_SILK_MORE_FRAMES && *pnBytesOut >= nBytes + psEnc->sCmn.LBRR_buffer[LBRR_idx].nBytes) { /* Get old packet and add to payload. */ SKP_memcpy(&pCode[nBytes], psEnc->sCmn.LBRR_buffer[LBRR_idx]. payload, psEnc->sCmn.LBRR_buffer[LBRR_idx]. nBytes * sizeof(uint8_t)); nBytes += psEnc->sCmn.LBRR_buffer[LBRR_idx].nBytes; } *pnBytesOut = nBytes; /* Update FEC buffer */ SKP_memcpy(psEnc->sCmn. LBRR_buffer[psEnc->sCmn.oldest_LBRR_idx]. payload, LBRRpayload, nBytesLBRR * sizeof(uint8_t)); psEnc->sCmn.LBRR_buffer[psEnc->sCmn.oldest_LBRR_idx]. nBytes = nBytesLBRR; /* This line tells describes how FEC should be used */ psEnc->sCmn.LBRR_buffer[psEnc->sCmn.oldest_LBRR_idx]. usage = sEncCtrl.sCmn.LBRR_usage; psEnc->sCmn.oldest_LBRR_idx = (psEnc->sCmn.oldest_LBRR_idx + 1) & LBRR_IDX_MASK; /* Reset number of frames in payload buffer */ psEnc->sCmn.nFramesInPayloadBuf = 0; } else { /* Not enough space: Payload will be discarded */ *pnBytesOut = 0; nBytes = 0; psEnc->sCmn.nFramesInPayloadBuf = 0; ret = SKP_SILK_ENC_PAYLOAD_BUF_TOO_SHORT; } } else { /* no payload for you this time */ *pnBytesOut = 0; /* Encode that more frames follows */ frame_terminator = SKP_SILK_MORE_FRAMES; SKP_Silk_range_encoder(&psEnc->sCmn.sRC, frame_terminator, FrameTermination_CDF); /* payload length so far */ SKP_Silk_range_coder_get_length(&psEnc->sCmn.sRC, &nBytes); if (psEnc->sCmn.bitstream_v == BIT_STREAM_V4) { /* Take into account the q signal that isnt in the bitstream yet */ nBytes += SKP_Silk_pulses_to_bytes(&psEnc->sCmn, &psEnc->sCmn. q[(psEnc->sCmn. nFramesInPayloadBuf - 1) * psEnc->sCmn. frame_length]); } } /* Check for arithmetic coder errors */ if (psEnc->sCmn.sRC.error) { ret = SKP_SILK_ENC_INTERNAL_ERROR; } /* simulate number of ms buffered in channel because of exceeding TargetRate */ assert((8 * 1000 * ((int64_t) nBytes - (int64_t) psEnc->sCmn.nBytesInPayloadBuf)) == SKP_SAT32(8 * 1000 * ((int64_t) nBytes - (int64_t) psEnc->sCmn.nBytesInPayloadBuf))); assert(psEnc->sCmn.TargetRate_bps > 0); psEnc->BufferedInChannel_ms += SKP_DIV32(8 * 1000 * (nBytes - psEnc->sCmn.nBytesInPayloadBuf), psEnc->sCmn.TargetRate_bps); psEnc->BufferedInChannel_ms -= FRAME_LENGTH_MS; psEnc->BufferedInChannel_ms = SKP_LIMIT(psEnc->BufferedInChannel_ms, 0, 100); psEnc->sCmn.nBytesInPayloadBuf = nBytes; if (psEnc->speech_activity_Q8 > WB_DETECT_ACTIVE_SPEECH_LEVEL_THRES_Q8) { psEnc->sCmn.sSWBdetect.ActiveSpeech_ms = SKP_ADD_POS_SAT32(psEnc->sCmn.sSWBdetect.ActiveSpeech_ms, FRAME_LENGTH_MS); } return (ret); }
void SKP_Silk_NLSF_MSVQ_encode_FIX( SKP_int *NLSFIndices, /* O Codebook path vector [ CB_STAGES ] */ SKP_int *pNLSF_Q15, /* I/O Quantized NLSF vector [ LPC_ORDER ] */ const SKP_Silk_NLSF_CB_struct *psNLSF_CB, /* I Codebook object */ const SKP_int *pNLSF_q_Q15_prev, /* I Prev. quantized NLSF vector [LPC_ORDER] */ const SKP_int *pW_Q6, /* I NLSF weight vector [ LPC_ORDER ] */ const SKP_int NLSF_mu_Q15, /* I Rate weight for the RD optimization */ const SKP_int NLSF_mu_fluc_red_Q16, /* I Fluctuation reduction error weight */ const SKP_int NLSF_MSVQ_Survivors, /* I Max survivors from each stage */ const SKP_int LPC_order, /* I LPC order */ const SKP_int deactivate_fluc_red /* I Deactivate fluctuation reduction */ ) { SKP_int i, s, k, cur_survivors = 0, prev_survivors, input_index, cb_index, bestIndex; SKP_int32 rateDistThreshold_Q18; SKP_int pNLSF_in_Q15[ MAX_LPC_ORDER ]; #if( NLSF_MSVQ_FLUCTUATION_REDUCTION == 1 ) SKP_int32 se_Q15, wsse_Q20, bestRateDist_Q20; #endif #if( LOW_COMPLEXITY_ONLY == 1 ) SKP_int32 pRateDist_Q18[ NLSF_MSVQ_TREE_SEARCH_MAX_VECTORS_EVALUATED_LC_MODE ]; SKP_int32 pRate_Q5[ MAX_NLSF_MSVQ_SURVIVORS_LC_MODE ]; SKP_int32 pRate_new_Q5[ MAX_NLSF_MSVQ_SURVIVORS_LC_MODE ]; SKP_int pTempIndices[ MAX_NLSF_MSVQ_SURVIVORS_LC_MODE ]; SKP_int pPath[ MAX_NLSF_MSVQ_SURVIVORS_LC_MODE * NLSF_MSVQ_MAX_CB_STAGES ]; SKP_int pPath_new[ MAX_NLSF_MSVQ_SURVIVORS_LC_MODE * NLSF_MSVQ_MAX_CB_STAGES ]; SKP_int pRes_Q15[ MAX_NLSF_MSVQ_SURVIVORS_LC_MODE * MAX_LPC_ORDER ]; SKP_int pRes_new_Q15[ MAX_NLSF_MSVQ_SURVIVORS_LC_MODE * MAX_LPC_ORDER ]; #else SKP_int32 pRateDist_Q18[ NLSF_MSVQ_TREE_SEARCH_MAX_VECTORS_EVALUATED ]; SKP_int32 pRate_Q5[ MAX_NLSF_MSVQ_SURVIVORS ]; SKP_int32 pRate_new_Q5[ MAX_NLSF_MSVQ_SURVIVORS ]; SKP_int pTempIndices[ MAX_NLSF_MSVQ_SURVIVORS ]; SKP_int pPath[ MAX_NLSF_MSVQ_SURVIVORS * NLSF_MSVQ_MAX_CB_STAGES ]; SKP_int pPath_new[ MAX_NLSF_MSVQ_SURVIVORS * NLSF_MSVQ_MAX_CB_STAGES ]; SKP_int pRes_Q15[ MAX_NLSF_MSVQ_SURVIVORS * MAX_LPC_ORDER ]; SKP_int pRes_new_Q15[ MAX_NLSF_MSVQ_SURVIVORS * MAX_LPC_ORDER ]; #endif const SKP_int *pConstInt; SKP_int *pInt; const SKP_int16 *pCB_element; const SKP_Silk_NLSF_CBS *pCurrentCBStage; SKP_assert( NLSF_MSVQ_Survivors <= MAX_NLSF_MSVQ_SURVIVORS ); SKP_assert( ( LOW_COMPLEXITY_ONLY == 0 ) || ( NLSF_MSVQ_Survivors <= MAX_NLSF_MSVQ_SURVIVORS_LC_MODE ) ); /* Copy the input vector */ SKP_memcpy( pNLSF_in_Q15, pNLSF_Q15, LPC_order * sizeof( SKP_int ) ); /****************************************************/ /* Tree search for the multi-stage vector quantizer */ /****************************************************/ /* Clear accumulated rates */ SKP_memset( pRate_Q5, 0, NLSF_MSVQ_Survivors * sizeof( SKP_int32 ) ); /* Copy NLSFs into residual signal vector */ for( i = 0; i < LPC_order; i++ ) { pRes_Q15[ i ] = pNLSF_Q15[ i ]; } /* Set first stage values */ prev_survivors = 1; /* Loop over all stages */ for( s = 0; s < psNLSF_CB->nStages; s++ ) { /* Set a pointer to the current stage codebook */ pCurrentCBStage = &psNLSF_CB->CBStages[ s ]; /* Calculate the number of survivors in the current stage */ cur_survivors = SKP_min_32( NLSF_MSVQ_Survivors, SKP_SMULBB( prev_survivors, pCurrentCBStage->nVectors ) ); #if( NLSF_MSVQ_FLUCTUATION_REDUCTION == 0 ) /* Find a single best survivor in the last stage, if we */ /* do not need candidates for fluctuation reduction */ if( s == psNLSF_CB->nStages - 1 ) { cur_survivors = 1; } #endif /* Nearest neighbor clustering for multiple input data vectors */ SKP_Silk_NLSF_VQ_rate_distortion_FIX( pRateDist_Q18, pCurrentCBStage, pRes_Q15, pW_Q6, pRate_Q5, NLSF_mu_Q15, prev_survivors, LPC_order ); /* Sort the rate-distortion errors */ SKP_Silk_insertion_sort_increasing( pRateDist_Q18, pTempIndices, prev_survivors * pCurrentCBStage->nVectors, cur_survivors ); /* Discard survivors with rate-distortion values too far above the best one */ if( pRateDist_Q18[ 0 ] < SKP_int32_MAX / NLSF_MSVQ_SURV_MAX_REL_RD ) { rateDistThreshold_Q18 = SKP_MUL( NLSF_MSVQ_SURV_MAX_REL_RD, pRateDist_Q18[ 0 ] ); while( pRateDist_Q18[ cur_survivors - 1 ] > rateDistThreshold_Q18 && cur_survivors > 1 ) { cur_survivors--; } } /* Update accumulated codebook contributions for the 'cur_survivors' best codebook indices */ for( k = 0; k < cur_survivors; k++ ) { if( s > 0 ) { /* Find the indices of the input and the codebook vector */ if( pCurrentCBStage->nVectors == 8 ) { input_index = SKP_RSHIFT( pTempIndices[ k ], 3 ); cb_index = pTempIndices[ k ] & 7; } else { input_index = SKP_DIV32_16( pTempIndices[ k ], pCurrentCBStage->nVectors ); cb_index = pTempIndices[ k ] - SKP_SMULBB( input_index, pCurrentCBStage->nVectors ); } } else { /* Find the indices of the input and the codebook vector */ input_index = 0; cb_index = pTempIndices[ k ]; } /* Subtract new contribution from the previous residual vector for each of 'cur_survivors' */ pConstInt = &pRes_Q15[ SKP_SMULBB( input_index, LPC_order ) ]; pCB_element = &pCurrentCBStage->CB_NLSF_Q15[ SKP_SMULBB( cb_index, LPC_order ) ]; pInt = &pRes_new_Q15[ SKP_SMULBB( k, LPC_order ) ]; for( i = 0; i < LPC_order; i++ ) { pInt[ i ] = pConstInt[ i ] - ( SKP_int )pCB_element[ i ]; } /* Update accumulated rate for stage 1 to the current */ pRate_new_Q5[ k ] = pRate_Q5[ input_index ] + pCurrentCBStage->Rates_Q5[ cb_index ]; /* Copy paths from previous matrix, starting with the best path */ pConstInt = &pPath[ SKP_SMULBB( input_index, psNLSF_CB->nStages ) ]; pInt = &pPath_new[ SKP_SMULBB( k, psNLSF_CB->nStages ) ]; for( i = 0; i < s; i++ ) { pInt[ i ] = pConstInt[ i ]; } /* Write the current stage indices for the 'cur_survivors' to the best path matrix */ pInt[ s ] = cb_index; } if( s < psNLSF_CB->nStages - 1 ) { /* Copy NLSF residual matrix for next stage */ SKP_memcpy( pRes_Q15, pRes_new_Q15, SKP_SMULBB( cur_survivors, LPC_order ) * sizeof( SKP_int ) ); /* Copy rate vector for next stage */ SKP_memcpy( pRate_Q5, pRate_new_Q5, cur_survivors * sizeof( SKP_int32 ) ); /* Copy best path matrix for next stage */ SKP_memcpy( pPath, pPath_new, SKP_SMULBB( cur_survivors, psNLSF_CB->nStages ) * sizeof( SKP_int ) ); } prev_survivors = cur_survivors; } /* (Preliminary) index of the best survivor, later to be decoded */ bestIndex = 0; #if( NLSF_MSVQ_FLUCTUATION_REDUCTION == 1 ) /******************************/ /* NLSF fluctuation reduction */ /******************************/ if( deactivate_fluc_red != 1 ) { /* Search among all survivors, now taking also weighted fluctuation errors into account */ bestRateDist_Q20 = SKP_int32_MAX; for( s = 0; s < cur_survivors; s++ ) { /* Decode survivor to compare with previous quantized NLSF vector */ SKP_Silk_NLSF_MSVQ_decode( pNLSF_Q15, psNLSF_CB, &pPath_new[ SKP_SMULBB( s, psNLSF_CB->nStages ) ], LPC_order ); /* Compare decoded NLSF vector with the previously quantized vector */ wsse_Q20 = 0; for( i = 0; i < LPC_order; i += 2 ) { /* Compute weighted squared quantization error for index i */ se_Q15 = pNLSF_Q15[ i ] - pNLSF_q_Q15_prev[ i ]; // range: [ -32767 : 32767 ] wsse_Q20 = SKP_SMLAWB( wsse_Q20, SKP_SMULBB( se_Q15, se_Q15 ), pW_Q6[ i ] ); /* Compute weighted squared quantization error for index i + 1 */ se_Q15 = pNLSF_Q15[ i + 1 ] - pNLSF_q_Q15_prev[ i + 1 ]; // range: [ -32767 : 32767 ] wsse_Q20 = SKP_SMLAWB( wsse_Q20, SKP_SMULBB( se_Q15, se_Q15 ), pW_Q6[ i + 1 ] ); } SKP_assert( wsse_Q20 >= 0 ); /* Add the fluctuation reduction penalty to the rate distortion error */ wsse_Q20 = SKP_ADD_POS_SAT32( pRateDist_Q18[ s ], SKP_SMULWB( wsse_Q20, NLSF_mu_fluc_red_Q16 ) ); /* Keep index of best survivor */ if( wsse_Q20 < bestRateDist_Q20 ) { bestRateDist_Q20 = wsse_Q20; bestIndex = s; } } } #endif /* Copy best path to output argument */ SKP_memcpy( NLSFIndices, &pPath_new[ SKP_SMULBB( bestIndex, psNLSF_CB->nStages ) ], psNLSF_CB->nStages * sizeof( SKP_int ) ); /* Decode and stabilize the best survivor */ SKP_Silk_NLSF_MSVQ_decode( pNLSF_Q15, psNLSF_CB, NLSFIndices, LPC_order ); }