/* Resample with a 2x downsampler (optional), a 2nd order AR filter followed by FIR interpolation */ void SKP_Silk_resampler_private_down_FIR( void *SS, /* I/O: Resampler state */ SKP_int16 out[], /* O: Output signal */ const SKP_int16 in[], /* I: Input signal */ SKP_int32 inLen /* I: Number of input samples */ ) { SKP_Silk_resampler_state_struct *S = (SKP_Silk_resampler_state_struct *)SS; SKP_int32 nSamplesIn, interpol_ind; SKP_int32 max_index_Q16, index_Q16, index_increment_Q16, res_Q6; SKP_int16 buf1[ RESAMPLER_MAX_BATCH_SIZE_IN / 2 ]; SKP_int32 buf2[ RESAMPLER_MAX_BATCH_SIZE_IN + RESAMPLER_DOWN_ORDER_FIR ]; SKP_int32 *buf_ptr; const SKP_int16 *interpol_ptr, *FIR_Coefs; /* Copy buffered samples to start of buffer */ SKP_memcpy( buf2, S->sFIR, RESAMPLER_DOWN_ORDER_FIR * sizeof( SKP_int32 ) ); FIR_Coefs = &S->Coefs[ 2 ]; /* Iterate over blocks of frameSizeIn input samples */ index_increment_Q16 = S->invRatio_Q16; while( 1 ) { nSamplesIn = SKP_min( inLen, S->batchSize ); if( S->input2x == 1 ) { /* Downsample 2x */ SKP_Silk_resampler_down2( S->sDown2, buf1, in, nSamplesIn ); nSamplesIn = SKP_RSHIFT32( nSamplesIn, 1 ); /* Second-order AR filter (output in Q8) */ SKP_Silk_resampler_private_AR2( S->sIIR, &buf2[ RESAMPLER_DOWN_ORDER_FIR ], buf1, S->Coefs, nSamplesIn ); } else { /* Second-order AR filter (output in Q8) */ SKP_Silk_resampler_private_AR2( S->sIIR, &buf2[ RESAMPLER_DOWN_ORDER_FIR ], in, S->Coefs, nSamplesIn ); } max_index_Q16 = SKP_LSHIFT32( nSamplesIn, 16 ); /* Interpolate filtered signal */ if( S->FIR_Fracs == 1 ) { for( index_Q16 = 0; index_Q16 < max_index_Q16; index_Q16 += index_increment_Q16 ) { /* Integer part gives pointer to buffered input */ buf_ptr = buf2 + SKP_RSHIFT( index_Q16, 16 ); /* Inner product */ res_Q6 = SKP_SMULWB( SKP_ADD32( buf_ptr[ 0 ], buf_ptr[ 11 ] ), FIR_Coefs[ 0 ] ); res_Q6 = SKP_SMLAWB( res_Q6, SKP_ADD32( buf_ptr[ 1 ], buf_ptr[ 10 ] ), FIR_Coefs[ 1 ] ); res_Q6 = SKP_SMLAWB( res_Q6, SKP_ADD32( buf_ptr[ 2 ], buf_ptr[ 9 ] ), FIR_Coefs[ 2 ] ); res_Q6 = SKP_SMLAWB( res_Q6, SKP_ADD32( buf_ptr[ 3 ], buf_ptr[ 8 ] ), FIR_Coefs[ 3 ] ); res_Q6 = SKP_SMLAWB( res_Q6, SKP_ADD32( buf_ptr[ 4 ], buf_ptr[ 7 ] ), FIR_Coefs[ 4 ] ); res_Q6 = SKP_SMLAWB( res_Q6, SKP_ADD32( buf_ptr[ 5 ], buf_ptr[ 6 ] ), FIR_Coefs[ 5 ] ); /* Scale down, saturate and store in output array */ *out++ = (SKP_int16)SKP_SAT16( SKP_RSHIFT_ROUND( res_Q6, 6 ) ); } } else { for( index_Q16 = 0; index_Q16 < max_index_Q16; index_Q16 += index_increment_Q16 ) { /* Integer part gives pointer to buffered input */ buf_ptr = buf2 + SKP_RSHIFT( index_Q16, 16 ); /* Fractional part gives interpolation coefficients */ interpol_ind = SKP_SMULWB( index_Q16 & 0xFFFF, S->FIR_Fracs ); /* Inner product */ interpol_ptr = &FIR_Coefs[ RESAMPLER_DOWN_ORDER_FIR / 2 * interpol_ind ]; res_Q6 = SKP_SMULWB( buf_ptr[ 0 ], interpol_ptr[ 0 ] ); res_Q6 = SKP_SMLAWB( res_Q6, buf_ptr[ 1 ], interpol_ptr[ 1 ] ); res_Q6 = SKP_SMLAWB( res_Q6, buf_ptr[ 2 ], interpol_ptr[ 2 ] ); res_Q6 = SKP_SMLAWB( res_Q6, buf_ptr[ 3 ], interpol_ptr[ 3 ] ); res_Q6 = SKP_SMLAWB( res_Q6, buf_ptr[ 4 ], interpol_ptr[ 4 ] ); res_Q6 = SKP_SMLAWB( res_Q6, buf_ptr[ 5 ], interpol_ptr[ 5 ] ); interpol_ptr = &FIR_Coefs[ RESAMPLER_DOWN_ORDER_FIR / 2 * ( S->FIR_Fracs - 1 - interpol_ind ) ]; res_Q6 = SKP_SMLAWB( res_Q6, buf_ptr[ 11 ], interpol_ptr[ 0 ] ); res_Q6 = SKP_SMLAWB( res_Q6, buf_ptr[ 10 ], interpol_ptr[ 1 ] ); res_Q6 = SKP_SMLAWB( res_Q6, buf_ptr[ 9 ], interpol_ptr[ 2 ] ); res_Q6 = SKP_SMLAWB( res_Q6, buf_ptr[ 8 ], interpol_ptr[ 3 ] ); res_Q6 = SKP_SMLAWB( res_Q6, buf_ptr[ 7 ], interpol_ptr[ 4 ] ); res_Q6 = SKP_SMLAWB( res_Q6, buf_ptr[ 6 ], interpol_ptr[ 5 ] ); /* Scale down, saturate and store in output array */ *out++ = (SKP_int16)SKP_SAT16( SKP_RSHIFT_ROUND( res_Q6, 6 ) ); } } in += nSamplesIn << S->input2x; inLen -= nSamplesIn << S->input2x; if( inLen > S->input2x ) { /* More iterations to do; copy last part of filtered signal to beginning of buffer */ SKP_memcpy( buf2, &buf2[ nSamplesIn ], RESAMPLER_DOWN_ORDER_FIR * sizeof( SKP_int32 ) ); } else { break; } } /* Copy last part of filtered signal to the state for the next call */ SKP_memcpy( S->sFIR, &buf2[ nSamplesIn ], RESAMPLER_DOWN_ORDER_FIR * sizeof( SKP_int32 ) ); }
void SKP_Silk_PLC_conceal( SKP_Silk_decoder_state *psDec, /* I/O Decoder state */ SKP_Silk_decoder_control *psDecCtrl, /* I/O Decoder control */ SKP_int16 signal[], /* O concealed signal */ SKP_int length /* I length of residual */ ) { SKP_int i, j, k; SKP_int16 *B_Q14, exc_buf[ MAX_FRAME_LENGTH ], *exc_buf_ptr; SKP_int16 rand_scale_Q14; union { SKP_int16 as_int16[ MAX_LPC_ORDER ]; SKP_int32 as_int32[ MAX_LPC_ORDER / 2 ]; } A_Q12_tmp; SKP_int32 rand_seed, harm_Gain_Q15, rand_Gain_Q15; SKP_int lag, idx, sLTP_buf_idx, shift1, shift2; SKP_int32 energy1, energy2, *rand_ptr, *pred_lag_ptr; SKP_int32 sig_Q10[ MAX_FRAME_LENGTH ], *sig_Q10_ptr, LPC_exc_Q10, LPC_pred_Q10, LTP_pred_Q14; SKP_Silk_PLC_struct *psPLC; psPLC = &psDec->sPLC; /* Update LTP buffer */ SKP_memcpy( psDec->sLTP_Q16, &psDec->sLTP_Q16[ psDec->frame_length ], psDec->frame_length * sizeof( SKP_int32 ) ); /* LPC concealment. Apply BWE to previous LPC */ SKP_Silk_bwexpander( psPLC->prevLPC_Q12, psDec->LPC_order, BWE_COEF_Q16 ); /* Find random noise component */ /* Scale previous excitation signal */ exc_buf_ptr = exc_buf; for( k = ( NB_SUBFR >> 1 ); k < NB_SUBFR; k++ ) { for( i = 0; i < psDec->subfr_length; i++ ) { exc_buf_ptr[ i ] = ( SKP_int16 )SKP_RSHIFT( SKP_SMULWW( psDec->exc_Q10[ i + k * psDec->subfr_length ], psPLC->prevGain_Q16[ k ] ), 10 ); } exc_buf_ptr += psDec->subfr_length; } /* Find the subframe with lowest energy of the last two and use that as random noise generator */ SKP_Silk_sum_sqr_shift( &energy1, &shift1, exc_buf, psDec->subfr_length ); SKP_Silk_sum_sqr_shift( &energy2, &shift2, &exc_buf[ psDec->subfr_length ], psDec->subfr_length ); if( SKP_RSHIFT( energy1, shift2 ) < SKP_RSHIFT( energy2, shift1 ) ) { /* First sub-frame has lowest energy */ rand_ptr = &psDec->exc_Q10[ SKP_max_int( 0, 3 * psDec->subfr_length - RAND_BUF_SIZE ) ]; } else { /* Second sub-frame has lowest energy */ rand_ptr = &psDec->exc_Q10[ SKP_max_int( 0, psDec->frame_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[ SKP_min_int( NB_ATT - 1, psDec->lossCnt ) ]; if( psDec->prev_sigtype == SIG_TYPE_VOICED ) { rand_Gain_Q15 = PLC_RAND_ATTENUATE_V_Q15[ SKP_min_int( NB_ATT - 1, psDec->lossCnt ) ]; } else { rand_Gain_Q15 = PLC_RAND_ATTENUATE_UV_Q15[ SKP_min_int( NB_ATT - 1, psDec->lossCnt ) ]; } /* First Lost frame */ if( psDec->lossCnt == 0 ) { rand_scale_Q14 = (1 << 14 ); /* Reduce random noise Gain for voiced frames */ if( psDec->prev_sigtype == SIG_TYPE_VOICED ) { for( i = 0; i < LTP_ORDER; i++ ) { rand_scale_Q14 -= B_Q14[ i ]; } rand_scale_Q14 = SKP_max_16( 3277, rand_scale_Q14 ); /* 0.2 */ rand_scale_Q14 = ( SKP_int16 )SKP_RSHIFT( SKP_SMULBB( rand_scale_Q14, psPLC->prevLTP_scale_Q14 ), 14 ); } /* Reduce random noise for unvoiced frames with high LPC gain */ if( psDec->prev_sigtype == SIG_TYPE_UNVOICED ) { SKP_int32 invGain_Q30, down_scale_Q30; SKP_Silk_LPC_inverse_pred_gain( &invGain_Q30, psPLC->prevLPC_Q12, psDec->LPC_order ); down_scale_Q30 = SKP_min_32( SKP_RSHIFT( ( 1 << 30 ), LOG2_INV_LPC_GAIN_HIGH_THRES ), invGain_Q30 ); down_scale_Q30 = SKP_max_32( SKP_RSHIFT( ( 1 << 30 ), LOG2_INV_LPC_GAIN_LOW_THRES ), down_scale_Q30 ); down_scale_Q30 = SKP_LSHIFT( down_scale_Q30, LOG2_INV_LPC_GAIN_HIGH_THRES ); rand_Gain_Q15 = SKP_RSHIFT( SKP_SMULWB( down_scale_Q30, rand_Gain_Q15 ), 14 ); } } rand_seed = psPLC->rand_seed; lag = SKP_RSHIFT_ROUND( psPLC->pitchL_Q8, 8 ); sLTP_buf_idx = psDec->frame_length; /***************************/ /* LTP synthesis filtering */ /***************************/ sig_Q10_ptr = sig_Q10; for( k = 0; k < NB_SUBFR; k++ ) { /* Setup pointer */ pred_lag_ptr = &psDec->sLTP_Q16[ sLTP_buf_idx - lag + LTP_ORDER / 2 ]; for( i = 0; i < psDec->subfr_length; i++ ) { rand_seed = SKP_RAND( rand_seed ); idx = SKP_RSHIFT( rand_seed, 25 ) & RAND_BUF_MASK; /* Unrolled loop */ LTP_pred_Q14 = SKP_SMULWB( pred_lag_ptr[ 0 ], B_Q14[ 0 ] ); LTP_pred_Q14 = SKP_SMLAWB( LTP_pred_Q14, pred_lag_ptr[ -1 ], B_Q14[ 1 ] ); LTP_pred_Q14 = SKP_SMLAWB( LTP_pred_Q14, pred_lag_ptr[ -2 ], B_Q14[ 2 ] ); LTP_pred_Q14 = SKP_SMLAWB( LTP_pred_Q14, pred_lag_ptr[ -3 ], B_Q14[ 3 ] ); LTP_pred_Q14 = SKP_SMLAWB( LTP_pred_Q14, pred_lag_ptr[ -4 ], B_Q14[ 4 ] ); pred_lag_ptr++; /* Generate LPC residual */ LPC_exc_Q10 = SKP_LSHIFT( SKP_SMULWB( rand_ptr[ idx ], rand_scale_Q14 ), 2 ); /* Random noise part */ LPC_exc_Q10 = SKP_ADD32( LPC_exc_Q10, SKP_RSHIFT_ROUND( LTP_pred_Q14, 4 ) ); /* Harmonic part */ /* Update states */ psDec->sLTP_Q16[ sLTP_buf_idx ] = SKP_LSHIFT( LPC_exc_Q10, 6 ); sLTP_buf_idx++; /* Save LPC residual */ sig_Q10_ptr[ i ] = LPC_exc_Q10; } sig_Q10_ptr += psDec->subfr_length; /* Gradually reduce LTP gain */ for( j = 0; j < LTP_ORDER; j++ ) { B_Q14[ j ] = SKP_RSHIFT( SKP_SMULBB( harm_Gain_Q15, B_Q14[ j ] ), 15 ); } /* Gradually reduce excitation gain */ rand_scale_Q14 = SKP_RSHIFT( SKP_SMULBB( rand_scale_Q14, rand_Gain_Q15 ), 15 ); /* Slowly increase pitch lag */ psPLC->pitchL_Q8 += SKP_SMULWB( psPLC->pitchL_Q8, PITCH_DRIFT_FAC_Q16 ); psPLC->pitchL_Q8 = SKP_min_32( psPLC->pitchL_Q8, SKP_LSHIFT( SKP_SMULBB( MAX_PITCH_LAG_MS, psDec->fs_kHz ), 8 ) ); lag = SKP_RSHIFT_ROUND( psPLC->pitchL_Q8, 8 ); } /***************************/ /* LPC synthesis filtering */ /***************************/ sig_Q10_ptr = sig_Q10; /* Preload LPC coeficients to array on stack. Gives small performance gain */ SKP_memcpy( A_Q12_tmp.as_int16, psPLC->prevLPC_Q12, psDec->LPC_order * sizeof( SKP_int16 ) ); SKP_assert( psDec->LPC_order >= 10 ); /* check that unrolling works */ for( k = 0; k < NB_SUBFR; k++ ) { for( i = 0; i < psDec->subfr_length; i++ ){ /* partly unrolled */ LPC_pred_Q10 = SKP_SMULWB( psDec->sLPC_Q14[ MAX_LPC_ORDER + i - 1 ], A_Q12_tmp.as_int16[ 0 ] ); LPC_pred_Q10 = SKP_SMLAWB( LPC_pred_Q10, psDec->sLPC_Q14[ MAX_LPC_ORDER + i - 2 ], A_Q12_tmp.as_int16[ 1 ] ); LPC_pred_Q10 = SKP_SMLAWB( LPC_pred_Q10, psDec->sLPC_Q14[ MAX_LPC_ORDER + i - 3 ], A_Q12_tmp.as_int16[ 2 ] ); LPC_pred_Q10 = SKP_SMLAWB( LPC_pred_Q10, psDec->sLPC_Q14[ MAX_LPC_ORDER + i - 4 ], A_Q12_tmp.as_int16[ 3 ] ); LPC_pred_Q10 = SKP_SMLAWB( LPC_pred_Q10, psDec->sLPC_Q14[ MAX_LPC_ORDER + i - 5 ], A_Q12_tmp.as_int16[ 4 ] ); LPC_pred_Q10 = SKP_SMLAWB( LPC_pred_Q10, psDec->sLPC_Q14[ MAX_LPC_ORDER + i - 6 ], A_Q12_tmp.as_int16[ 5 ] ); LPC_pred_Q10 = SKP_SMLAWB( LPC_pred_Q10, psDec->sLPC_Q14[ MAX_LPC_ORDER + i - 7 ], A_Q12_tmp.as_int16[ 6 ] ); LPC_pred_Q10 = SKP_SMLAWB( LPC_pred_Q10, psDec->sLPC_Q14[ MAX_LPC_ORDER + i - 8 ], A_Q12_tmp.as_int16[ 7 ] ); LPC_pred_Q10 = SKP_SMLAWB( LPC_pred_Q10, psDec->sLPC_Q14[ MAX_LPC_ORDER + i - 9 ], A_Q12_tmp.as_int16[ 8 ] ); LPC_pred_Q10 = SKP_SMLAWB( LPC_pred_Q10, psDec->sLPC_Q14[ MAX_LPC_ORDER + i - 10 ], A_Q12_tmp.as_int16[ 9 ] ); for( j = 10; j < psDec->LPC_order; j++ ) { LPC_pred_Q10 = SKP_SMLAWB( LPC_pred_Q10, psDec->sLPC_Q14[ MAX_LPC_ORDER + i - j - 1 ], A_Q12_tmp.as_int16[ j ] ); } /* Add prediction to LPC residual */ sig_Q10_ptr[ i ] = SKP_ADD32( sig_Q10_ptr[ i ], LPC_pred_Q10 ); /* Update states */ psDec->sLPC_Q14[ MAX_LPC_ORDER + i ] = SKP_LSHIFT( sig_Q10_ptr[ i ], 4 ); } sig_Q10_ptr += psDec->subfr_length; /* Update LPC filter state */ SKP_memcpy( psDec->sLPC_Q14, &psDec->sLPC_Q14[ psDec->subfr_length ], MAX_LPC_ORDER * sizeof( SKP_int32 ) ); } /* Scale with Gain */ for( i = 0; i < psDec->frame_length; i++ ) { signal[ i ] = ( SKP_int16 )SKP_SAT16( SKP_RSHIFT_ROUND( SKP_SMULWW( sig_Q10[ i ], psPLC->prevGain_Q16[ NB_SUBFR - 1 ] ), 10 ) ); } /**************************************/ /* Update states */ /**************************************/ psPLC->rand_seed = rand_seed; psPLC->randScale_Q14 = rand_scale_Q14; for( i = 0; i < NB_SUBFR; i++ ) { psDecCtrl->pitchL[ i ] = lag; } }
void SKP_Silk_PLC_update( SKP_Silk_decoder_state *psDec, /* (I/O) Decoder state */ SKP_Silk_decoder_control *psDecCtrl, /* (I/O) Decoder control */ SKP_int16 signal[], SKP_int length ) { SKP_int32 LTP_Gain_Q14, temp_LTP_Gain_Q14; SKP_int i, j; SKP_Silk_PLC_struct *psPLC; psPLC = &psDec->sPLC; /* Update parameters used in case of packet loss */ psDec->prev_sigtype = psDecCtrl->sigtype; LTP_Gain_Q14 = 0; if( psDecCtrl->sigtype == SIG_TYPE_VOICED ) { /* Find the parameters for the last subframe which contains a pitch pulse */ for( j = 0; j * psDec->subfr_length < psDecCtrl->pitchL[ NB_SUBFR - 1 ]; j++ ) { temp_LTP_Gain_Q14 = 0; for( i = 0; i < LTP_ORDER; i++ ) { temp_LTP_Gain_Q14 += psDecCtrl->LTPCoef_Q14[ ( NB_SUBFR - 1 - j ) * LTP_ORDER + i ]; } if( temp_LTP_Gain_Q14 > LTP_Gain_Q14 ) { LTP_Gain_Q14 = temp_LTP_Gain_Q14; SKP_memcpy( psPLC->LTPCoef_Q14, &psDecCtrl->LTPCoef_Q14[ SKP_SMULBB( NB_SUBFR - 1 - j, LTP_ORDER ) ], LTP_ORDER * sizeof( SKP_int16 ) ); psPLC->pitchL_Q8 = SKP_LSHIFT( psDecCtrl->pitchL[ NB_SUBFR - 1 - j ], 8 ); } } #if USE_SINGLE_TAP SKP_memset( psPLC->LTPCoef_Q14, 0, LTP_ORDER * sizeof( SKP_int16 ) ); psPLC->LTPCoef_Q14[ LTP_ORDER / 2 ] = LTP_Gain_Q14; #endif /* Limit LT coefs */ if( LTP_Gain_Q14 < V_PITCH_GAIN_START_MIN_Q14 ) { SKP_int scale_Q10; SKP_int32 tmp; tmp = SKP_LSHIFT( V_PITCH_GAIN_START_MIN_Q14, 10 ); scale_Q10 = SKP_DIV32( tmp, SKP_max( LTP_Gain_Q14, 1 ) ); for( i = 0; i < LTP_ORDER; i++ ) { psPLC->LTPCoef_Q14[ i ] = SKP_RSHIFT( SKP_SMULBB( psPLC->LTPCoef_Q14[ i ], scale_Q10 ), 10 ); } } else if( LTP_Gain_Q14 > V_PITCH_GAIN_START_MAX_Q14 ) { SKP_int scale_Q14; SKP_int32 tmp; tmp = SKP_LSHIFT( V_PITCH_GAIN_START_MAX_Q14, 14 ); scale_Q14 = SKP_DIV32( tmp, SKP_max( LTP_Gain_Q14, 1 ) ); for( i = 0; i < LTP_ORDER; i++ ) { psPLC->LTPCoef_Q14[ i ] = SKP_RSHIFT( SKP_SMULBB( psPLC->LTPCoef_Q14[ i ], scale_Q14 ), 14 ); } } } else { psPLC->pitchL_Q8 = SKP_LSHIFT( SKP_SMULBB( psDec->fs_kHz, 18 ), 8 ); SKP_memset( psPLC->LTPCoef_Q14, 0, LTP_ORDER * sizeof( SKP_int16 )); } /* Save LPC coeficients */ SKP_memcpy( psPLC->prevLPC_Q12, psDecCtrl->PredCoef_Q12[ 1 ], psDec->LPC_order * sizeof( SKP_int16 ) ); psPLC->prevLTP_scale_Q14 = psDecCtrl->LTP_scale_Q14; /* Save Gains */ SKP_memcpy( psPLC->prevGain_Q16, psDecCtrl->Gains_Q16, NB_SUBFR * sizeof( SKP_int32 ) ); }
void SKP_Silk_NLSF_MSVQ_encode_FLP( SKP_int *NLSFIndices, /* O Codebook path vector [ CB_STAGES ] */ SKP_float *pNLSF, /* I/O Quantized NLSF vector [ LPC_ORDER ] */ const SKP_Silk_NLSF_CB_FLP *psNLSF_CB_FLP, /* I Codebook object */ const SKP_float *pNLSF_q_prev, /* I Prev. quantized NLSF vector [LPC_ORDER] */ const SKP_float *pW, /* I NLSF weight vector [ LPC_ORDER ] */ const SKP_float NLSF_mu, /* I Rate weight for the RD optimization */ const SKP_float NLSF_mu_fluc_red, /* 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, prev_survivors, min_survivors, input_index, cb_index, bestIndex; SKP_float se, wsse, rateDistThreshold, bestRateDist; #if( LOW_COMPLEXITY_ONLY == 1 ) SKP_float pRateDist[ NLSF_MSVQ_TREE_SEARCH_MAX_VECTORS_EVALUATED_LC_MODE ]; SKP_float pRate[ MAX_NLSF_MSVQ_SURVIVORS_LC_MODE ]; SKP_float pRate_new[ 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_float pRes[ MAX_NLSF_MSVQ_SURVIVORS_LC_MODE * MAX_LPC_ORDER ]; SKP_float pRes_new[ MAX_NLSF_MSVQ_SURVIVORS_LC_MODE * MAX_LPC_ORDER ]; #else SKP_float pRateDist[ NLSF_MSVQ_TREE_SEARCH_MAX_VECTORS_EVALUATED ]; SKP_float pRate[ MAX_NLSF_MSVQ_SURVIVORS ]; SKP_float pRate_new[ 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_float pRes[ MAX_NLSF_MSVQ_SURVIVORS * MAX_LPC_ORDER ]; SKP_float pRes_new[ MAX_NLSF_MSVQ_SURVIVORS * MAX_LPC_ORDER ]; #endif const SKP_float *pConstFloat; SKP_float *pFloat; const SKP_int *pConstInt; SKP_int *pInt; const SKP_float *pCB_element; const SKP_Silk_NLSF_CBS_FLP *pCurrentCBStage; #ifdef USE_UNQUANTIZED_LSFS SKP_float NLSF_orig[ MAX_LPC_ORDER ]; SKP_memcpy( NLSF_orig, pNLSF, LPC_order * sizeof( SKP_float ) ); #endif SKP_assert( NLSF_MSVQ_Survivors <= MAX_NLSF_MSVQ_SURVIVORS ); SKP_assert( ( LOW_COMPLEXITY_ONLY == 0 ) || ( NLSF_MSVQ_Survivors <= MAX_NLSF_MSVQ_SURVIVORS_LC_MODE ) ); cur_survivors = NLSF_MSVQ_Survivors; /****************************************************/ /* Tree search for the multi-stage vector quantizer */ /****************************************************/ /* Clear accumulated rates */ SKP_memset( pRate, 0, NLSF_MSVQ_Survivors * sizeof( SKP_float ) ); /* Copy NLSFs into residual signal vector */ SKP_memcpy( pRes, pNLSF, LPC_order * sizeof( SKP_float ) ); /* Set first stage values */ prev_survivors = 1; /* Minimum number of survivors */ min_survivors = NLSF_MSVQ_Survivors / 2; /* Loop over all stages */ for( s = 0; s < psNLSF_CB_FLP->nStages; s++ ) { /* Set a pointer to the current stage codebook */ pCurrentCBStage = &psNLSF_CB_FLP->CBStages[ s ]; /* Calculate the number of survivors in the current stage */ cur_survivors = SKP_min_32( NLSF_MSVQ_Survivors, 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_FLP->nStages - 1 ) { cur_survivors = 1; } #endif /* Nearest neighbor clustering for multiple input data vectors */ SKP_Silk_NLSF_VQ_rate_distortion_FLP( pRateDist, pCurrentCBStage, pRes, pW, pRate, NLSF_mu, prev_survivors, LPC_order ); /* Sort the rate-distortion errors */ SKP_Silk_insertion_sort_increasing_FLP( pRateDist, pTempIndices, prev_survivors * pCurrentCBStage->nVectors, cur_survivors ); /* Discard survivors with rate-distortion values too far above the best one */ rateDistThreshold = ( 1.0f + NLSF_MSVQ_Survivors * NLSF_MSVQ_SURV_MAX_REL_RD ) * pRateDist[ 0 ]; while( pRateDist[ cur_survivors - 1 ] > rateDistThreshold && cur_survivors > min_survivors ) { 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 = pTempIndices[ k ] / pCurrentCBStage->nVectors; cb_index = pTempIndices[ k ] - 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' */ pConstFloat = &pRes[ input_index * LPC_order ]; pCB_element = &pCurrentCBStage->CB[ cb_index * LPC_order ]; pFloat = &pRes_new[ k * LPC_order ]; for( i = 0; i < LPC_order; i++ ) { pFloat[ i ] = pConstFloat[ i ] - pCB_element[ i ]; } /* Update accumulated rate for stage 1 to the current */ pRate_new[ k ] = pRate[ input_index ] + pCurrentCBStage->Rates[ cb_index ]; /* Copy paths from previous matrix, starting with the best path */ pConstInt = &pPath[ input_index * psNLSF_CB_FLP->nStages ]; pInt = &pPath_new[ k * psNLSF_CB_FLP->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_FLP->nStages - 1 ) { /* Copy NLSF residual matrix for next stage */ SKP_memcpy(pRes, pRes_new, cur_survivors * LPC_order * sizeof( SKP_float ) ); /* Copy rate vector for next stage */ SKP_memcpy(pRate, pRate_new, cur_survivors * sizeof( SKP_float ) ); /* Copy best path matrix for next stage */ SKP_memcpy(pPath, pPath_new, cur_survivors * psNLSF_CB_FLP->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 = SKP_float_MAX; for( s = 0; s < cur_survivors; s++ ) { /* Decode survivor to compare with previous quantized NLSF vector */ SKP_Silk_NLSF_MSVQ_decode_FLP( pNLSF, psNLSF_CB_FLP, &pPath_new[ s * psNLSF_CB_FLP->nStages ], LPC_order ); /* Compare decoded NLSF vector with the previously quantized vector */ wsse = 0; for( i = 0; i < LPC_order; i += 2 ) { /* Compute weighted squared quantization error for index i */ se = pNLSF[ i ] - pNLSF_q_prev[ i ]; wsse += pW[ i ] * se * se; /* Compute weighted squared quantization error for index i + 1 */ se = pNLSF[ i + 1 ] - pNLSF_q_prev[ i + 1 ]; wsse += pW[ i + 1 ] * se * se; } /* Add the fluctuation reduction penalty to the rate distortion error */ wsse = pRateDist[s] + wsse * NLSF_mu_fluc_red; /* Keep index of best survivor */ if( wsse < bestRateDist ) { bestRateDist = wsse; bestIndex = s; } } } #endif /* Copy best path to output argument */ SKP_memcpy( NLSFIndices, &pPath_new[ bestIndex * psNLSF_CB_FLP->nStages ], psNLSF_CB_FLP->nStages * sizeof( SKP_int ) ); /* Decode and stabilize the best survivor */ SKP_Silk_NLSF_MSVQ_decode_FLP( pNLSF, psNLSF_CB_FLP, NLSFIndices, LPC_order ); #ifdef USE_UNQUANTIZED_LSFS SKP_memcpy( pNLSF, NLSF_orig, LPC_order * sizeof( SKP_float ) ); #endif }
void SKP_Silk_prefilter_FIX( SKP_Silk_encoder_state_FIX *psEnc, /* I/O Encoder state FIX */ const SKP_Silk_encoder_control_FIX *psEncCtrl, /* I Encoder control FIX */ SKP_int16 xw[], /* O Weighted signal */ const SKP_int16 x[] /* I Speech signal */ ) { SKP_Silk_prefilter_state_FIX *P = &psEnc->sPrefilt; SKP_int j, k, lag; SKP_int32 tmp_32; const SKP_int16 *AR1_shp_Q13; const SKP_int16 *px; SKP_int16 *pxw; SKP_int HarmShapeGain_Q12, Tilt_Q14; SKP_int32 HarmShapeFIRPacked_Q12, LF_shp_Q14; SKP_int32 x_filt_Q12[ MAX_FRAME_LENGTH / NB_SUBFR ]; SKP_int16 st_res[ ( MAX_FRAME_LENGTH / NB_SUBFR ) + MAX_SHAPE_LPC_ORDER ]; #if !defined(_SYSTEM_IS_BIG_ENDIAN) SKP_int32 B_Q12; #else SKP_int16 B_Q12[ 2 ]; #endif /* Setup pointers */ px = x; pxw = xw; lag = P->lagPrev; for( k = 0; k < NB_SUBFR; k++ ) { /* Update Variables that change per sub frame */ if( psEncCtrl->sCmn.sigtype == SIG_TYPE_VOICED ) { lag = psEncCtrl->sCmn.pitchL[ k ]; } /* Noise shape parameters */ HarmShapeGain_Q12 = SKP_SMULWB( psEncCtrl->HarmShapeGain_Q14[ k ], 16384 - psEncCtrl->HarmBoost_Q14[ k ] ); SKP_assert( HarmShapeGain_Q12 >= 0 ); HarmShapeFIRPacked_Q12 = SKP_RSHIFT( HarmShapeGain_Q12, 2 ); HarmShapeFIRPacked_Q12 |= SKP_LSHIFT( ( SKP_int32 )SKP_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*/ SKP_Silk_warped_LPC_analysis_filter_FIX( P->sAR_shp, st_res, AR1_shp_Q13, px, psEnc->sCmn.warping_Q16, psEnc->sCmn.subfr_length, psEnc->sCmn.shapingLPCOrder ); /* reduce (mainly) low frequencies during harmonic emphasis */ #if !defined(_SYSTEM_IS_BIG_ENDIAN) /* NOTE: the code below loads two int16 values in an int32, and multiplies each using the */ /* SMLABB and SMLABT instructions. On a big-endian CPU the two int16 variables would be */ /* loaded in reverse order and the code will give the wrong result. In that case swapping */ /* the SMLABB and SMLABT instructions should solve the problem. */ B_Q12 = SKP_RSHIFT_ROUND( psEncCtrl->GainsPre_Q14[ k ], 2 ); tmp_32 = SKP_SMLABB( SKP_FIX_CONST( INPUT_TILT, 26 ), psEncCtrl->HarmBoost_Q14[ k ], HarmShapeGain_Q12 ); /* Q26 */ tmp_32 = SKP_SMLABB( tmp_32, psEncCtrl->coding_quality_Q14, SKP_FIX_CONST( HIGH_RATE_INPUT_TILT, 12 ) ); /* Q26 */ tmp_32 = SKP_SMULWB( tmp_32, -psEncCtrl->GainsPre_Q14[ k ] ); /* Q24 */ tmp_32 = SKP_RSHIFT_ROUND( tmp_32, 12 ); /* Q12 */ B_Q12 |= SKP_LSHIFT( SKP_SAT16( tmp_32 ), 16 ); x_filt_Q12[ 0 ] = SKP_SMLABT( SKP_SMULBB( st_res[ 0 ], B_Q12 ), P->sHarmHP, B_Q12 ); for( j = 1; j < psEnc->sCmn.subfr_length; j++ ) { x_filt_Q12[ j ] = SKP_SMLABT( SKP_SMULBB( st_res[ j ], B_Q12 ), st_res[ j - 1 ], B_Q12 ); } #else B_Q12[ 0 ] = SKP_RSHIFT_ROUND( psEncCtrl->GainsPre_Q14[ k ], 2 ); tmp_32 = SKP_SMLABB( SKP_FIX_CONST( INPUT_TILT, 26 ), psEncCtrl->HarmBoost_Q14[ k ], HarmShapeGain_Q12 ); /* Q26 */ tmp_32 = SKP_SMLABB( tmp_32, psEncCtrl->coding_quality_Q14, SKP_FIX_CONST( HIGH_RATE_INPUT_TILT, 12 ) ); /* Q26 */ tmp_32 = SKP_SMULWB( tmp_32, -psEncCtrl->GainsPre_Q14[ k ] ); /* Q24 */ tmp_32 = SKP_RSHIFT_ROUND( tmp_32, 12 ); /* Q12 */ B_Q12[ 1 ]= SKP_SAT16( tmp_32 ); x_filt_Q12[ 0 ] = SKP_SMLABB( SKP_SMULBB( st_res[ 0 ], B_Q12[ 0 ] ), P->sHarmHP, B_Q12[ 1 ] ); for( j = 1; j < psEnc->sCmn.subfr_length; j++ ) { x_filt_Q12[ j ] = SKP_SMLABB( SKP_SMULBB( st_res[ j ], B_Q12[ 0 ] ), st_res[ j - 1 ], B_Q12[ 1 ] ); } #endif P->sHarmHP = st_res[ psEnc->sCmn.subfr_length - 1 ]; SKP_Silk_prefilt_FIX( P, x_filt_Q12, pxw, HarmShapeFIRPacked_Q12, Tilt_Q14, LF_shp_Q14, lag, psEnc->sCmn.subfr_length ); px += psEnc->sCmn.subfr_length; pxw += psEnc->sCmn.subfr_length; } P->lagPrev = psEncCtrl->sCmn.pitchL[ NB_SUBFR - 1 ]; }
/* Find pitch lags */ void silk_find_pitch_lags_FIX( silk_encoder_state_FIX *psEnc, /* I/O encoder state */ silk_encoder_control_FIX *psEncCtrl, /* I/O encoder control */ opus_int16 res[], /* O residual */ const opus_int16 x[] /* I Speech signal */ ) { opus_int buf_len, i, scale; opus_int32 thrhld_Q15, res_nrg; const opus_int16 *x_buf, *x_buf_ptr; opus_int16 Wsig[ FIND_PITCH_LPC_WIN_MAX ], *Wsig_ptr; opus_int32 auto_corr[ MAX_FIND_PITCH_LPC_ORDER + 1 ]; opus_int16 rc_Q15[ MAX_FIND_PITCH_LPC_ORDER ]; opus_int32 A_Q24[ MAX_FIND_PITCH_LPC_ORDER ]; opus_int16 A_Q12[ MAX_FIND_PITCH_LPC_ORDER ]; /******************************************/ /* Setup buffer lengths etc based on Fs */ /******************************************/ buf_len = psEnc->sCmn.la_pitch + psEnc->sCmn.frame_length + psEnc->sCmn.ltp_mem_length; /* Safty check */ SKP_assert( buf_len >= psEnc->sCmn.pitch_LPC_win_length ); x_buf = x - psEnc->sCmn.ltp_mem_length; /*************************************/ /* Estimate LPC AR coefficients */ /*************************************/ /* Calculate windowed signal */ /* First LA_LTP samples */ x_buf_ptr = x_buf + buf_len - psEnc->sCmn.pitch_LPC_win_length; Wsig_ptr = Wsig; silk_apply_sine_window( Wsig_ptr, x_buf_ptr, 1, psEnc->sCmn.la_pitch ); /* Middle un - windowed samples */ Wsig_ptr += psEnc->sCmn.la_pitch; x_buf_ptr += psEnc->sCmn.la_pitch; SKP_memcpy( Wsig_ptr, x_buf_ptr, ( psEnc->sCmn.pitch_LPC_win_length - SKP_LSHIFT( psEnc->sCmn.la_pitch, 1 ) ) * sizeof( opus_int16 ) ); /* Last LA_LTP samples */ Wsig_ptr += psEnc->sCmn.pitch_LPC_win_length - SKP_LSHIFT( psEnc->sCmn.la_pitch, 1 ); x_buf_ptr += psEnc->sCmn.pitch_LPC_win_length - SKP_LSHIFT( psEnc->sCmn.la_pitch, 1 ); silk_apply_sine_window( Wsig_ptr, x_buf_ptr, 2, psEnc->sCmn.la_pitch ); /* Calculate autocorrelation sequence */ silk_autocorr( auto_corr, &scale, Wsig, psEnc->sCmn.pitch_LPC_win_length, psEnc->sCmn.pitchEstimationLPCOrder + 1 ); /* Add white noise, as fraction of energy */ auto_corr[ 0 ] = SKP_SMLAWB( auto_corr[ 0 ], auto_corr[ 0 ], SILK_FIX_CONST( FIND_PITCH_WHITE_NOISE_FRACTION, 16 ) ) + 1; /* Calculate the reflection coefficients using schur */ res_nrg = silk_schur( rc_Q15, auto_corr, psEnc->sCmn.pitchEstimationLPCOrder ); /* Prediction gain */ psEncCtrl->predGain_Q16 = silk_DIV32_varQ( auto_corr[ 0 ], SKP_max_int( res_nrg, 1 ), 16 ); /* Convert reflection coefficients to prediction coefficients */ silk_k2a( A_Q24, rc_Q15, psEnc->sCmn.pitchEstimationLPCOrder ); /* Convert From 32 bit Q24 to 16 bit Q12 coefs */ for( i = 0; i < psEnc->sCmn.pitchEstimationLPCOrder; i++ ) { A_Q12[ i ] = ( opus_int16 )SKP_SAT16( SKP_RSHIFT( A_Q24[ i ], 12 ) ); } /* Do BWE */ silk_bwexpander( A_Q12, psEnc->sCmn.pitchEstimationLPCOrder, SILK_FIX_CONST( FIND_PITCH_BANDWITH_EXPANSION, 16 ) ); /*****************************************/ /* LPC analysis filtering */ /*****************************************/ silk_LPC_analysis_filter( res, x_buf, A_Q12, buf_len, psEnc->sCmn.pitchEstimationLPCOrder ); if( psEnc->sCmn.indices.signalType != TYPE_NO_VOICE_ACTIVITY && psEnc->sCmn.first_frame_after_reset == 0 ) { /* Threshold for pitch estimator */ thrhld_Q15 = SILK_FIX_CONST( 0.6, 15 ); thrhld_Q15 = SKP_SMLABB( thrhld_Q15, SILK_FIX_CONST( -0.004, 15 ), psEnc->sCmn.pitchEstimationLPCOrder ); thrhld_Q15 = SKP_SMLABB( thrhld_Q15, SILK_FIX_CONST( -0.1, 7 ), psEnc->sCmn.speech_activity_Q8 ); thrhld_Q15 = SKP_SMLABB( thrhld_Q15, SILK_FIX_CONST( -0.15, 15 ), SKP_RSHIFT( psEnc->sCmn.prevSignalType, 1 ) ); thrhld_Q15 = SKP_SMLAWB( thrhld_Q15, SILK_FIX_CONST( -0.1, 16 ), psEnc->sCmn.input_tilt_Q15 ); thrhld_Q15 = SKP_SAT16( thrhld_Q15 ); /*****************************************/ /* Call pitch estimator */ /*****************************************/ if( silk_pitch_analysis_core( res, psEncCtrl->pitchL, &psEnc->sCmn.indices.lagIndex, &psEnc->sCmn.indices.contourIndex, &psEnc->LTPCorr_Q15, psEnc->sCmn.prevLag, psEnc->sCmn.pitchEstimationThreshold_Q16, ( opus_int16 )thrhld_Q15, psEnc->sCmn.fs_kHz, psEnc->sCmn.pitchEstimationComplexity, psEnc->sCmn.nb_subfr ) == 0 ) { psEnc->sCmn.indices.signalType = TYPE_VOICED; } else { psEnc->sCmn.indices.signalType = TYPE_UNVOICED; } } else { SKP_memset( psEncCtrl->pitchL, 0, sizeof( psEncCtrl->pitchL ) ); psEnc->sCmn.indices.lagIndex = 0; psEnc->sCmn.indices.contourIndex = 0; psEnc->LTPCorr_Q15 = 0; } }
SKP_int SKP_Silk_decode_frame( SKP_Silk_decoder_state *psDec, /* I/O Pointer to Silk decoder state */ ec_dec *psRangeDec, /* I/O Compressor data structure */ SKP_int16 pOut[], /* O Pointer to output speech frame */ SKP_int32 *pN, /* O Pointer to size of output frame */ const SKP_int nBytes, /* I Payload length */ SKP_int lostFlag /* I 0: no loss, 1 loss, 2 decode fec */ ) { SKP_Silk_decoder_control sDecCtrl; SKP_int i, L, mv_len, ret = 0; SKP_int8 flags; SKP_int32 LBRR_symbol; SKP_int pulses[ MAX_FRAME_LENGTH ]; TIC(DECODE_FRAME) L = psDec->frame_length; sDecCtrl.LTP_scale_Q14 = 0; /* Safety checks */ SKP_assert( L > 0 && L <= MAX_FRAME_LENGTH ); /********************************************/ /* Decode Frame if packet is not lost */ /********************************************/ if( lostFlag != PACKET_LOST && psDec->nFramesDecoded == 0 ) { /* First decoder call for this payload */ /* Decode VAD flags and LBRR flag */ flags = SKP_RSHIFT( psRangeDec->buf[ 0 ], 7 - psDec->nFramesPerPacket ) & ( SKP_LSHIFT( 1, psDec->nFramesPerPacket + 1 ) - 1 ); psDec->LBRR_flag = flags & 1; for( i = psDec->nFramesPerPacket - 1; i >= 0 ; i-- ) { flags = SKP_RSHIFT( flags, 1 ); psDec->VAD_flags[ i ] = flags & 1; } for( i = 0; i < psDec->nFramesPerPacket + 1; i++ ) { ec_dec_icdf( psRangeDec, SKP_Silk_uniform2_iCDF, 8 ); } /* Decode LBRR flags */ SKP_memset( psDec->LBRR_flags, 0, sizeof( psDec->LBRR_flags ) ); if( psDec->LBRR_flag ) { if( psDec->nFramesPerPacket == 1 ) { psDec->LBRR_flags[ 0 ] = 1; } else { LBRR_symbol = ec_dec_icdf( psRangeDec, SKP_Silk_LBRR_flags_iCDF_ptr[ psDec->nFramesPerPacket - 2 ], 8 ) + 1; for( i = 0; i < psDec->nFramesPerPacket; i++ ) { psDec->LBRR_flags[ i ] = SKP_RSHIFT( LBRR_symbol, i ) & 1; } } } if( lostFlag == DECODE_NORMAL ) { /* Regular decoding: skip all LBRR data */ for( i = 0; i < psDec->nFramesPerPacket; i++ ) { if( psDec->LBRR_flags[ i ] ) { SKP_Silk_decode_indices( psDec, psRangeDec, i, 1 ); SKP_Silk_decode_pulses( psRangeDec, pulses, psDec->indices.signalType, psDec->indices.quantOffsetType, psDec->frame_length ); } } } } if( lostFlag == DECODE_LBRR && psDec->LBRR_flags[ psDec->nFramesDecoded ] == 0 ) { /* Treat absent LBRR data as lost frame */ lostFlag = PACKET_LOST; psDec->nFramesDecoded++; } if( lostFlag != PACKET_LOST ) { /*********************************************/ /* Decode quantization indices of side info */ /*********************************************/ TIC(decode_indices) SKP_Silk_decode_indices( psDec, psRangeDec, psDec->nFramesDecoded, lostFlag ); TOC(decode_indices) /*********************************************/ /* Decode quantization indices of excitation */ /*********************************************/ TIC(decode_pulses) SKP_Silk_decode_pulses( psRangeDec, pulses, psDec->indices.signalType, psDec->indices.quantOffsetType, psDec->frame_length ); TOC(decode_pulses) /********************************************/ /* Decode parameters and pulse signal */ /********************************************/ TIC(decode_params) SKP_Silk_decode_parameters( psDec, &sDecCtrl ); TOC(decode_params) /* Update length. Sampling frequency may have changed */ L = psDec->frame_length; /********************************************************/ /* Run inverse NSQ */ /********************************************************/ TIC(decode_core) SKP_Silk_decode_core( psDec, &sDecCtrl, pOut, pulses ); TOC(decode_core) /********************************************************/ /* Update PLC state */ /********************************************************/ SKP_Silk_PLC( psDec, &sDecCtrl, pOut, L, 0 ); psDec->lossCnt = 0; psDec->prevSignalType = psDec->indices.signalType; SKP_assert( psDec->prevSignalType >= 0 && psDec->prevSignalType <= 2 ); /* A frame has been decoded without errors */ psDec->first_frame_after_reset = 0; psDec->nFramesDecoded++; } else { /* Handle packet loss by extrapolation */ SKP_Silk_PLC( psDec, &sDecCtrl, pOut, L, 1 ); } /*************************/ /* Update output buffer. */ /*************************/ SKP_assert( psDec->ltp_mem_length >= psDec->frame_length ); mv_len = psDec->ltp_mem_length - psDec->frame_length; SKP_memmove( psDec->outBuf, &psDec->outBuf[ psDec->frame_length ], mv_len * sizeof(SKP_int16) ); SKP_memcpy( &psDec->outBuf[ mv_len ], pOut, psDec->frame_length * sizeof( SKP_int16 ) ); /****************************************************************/ /* Ensure smooth connection of extrapolated and good frames */ /****************************************************************/ SKP_Silk_PLC_glue_frames( psDec, &sDecCtrl, pOut, L ); /************************************************/ /* Comfort noise generation / estimation */ /************************************************/ SKP_Silk_CNG( psDec, &sDecCtrl, pOut, L ); /********************************************/ /* HP filter output */ /********************************************/ TIC(HP_out) SKP_Silk_biquad_alt( pOut, psDec->HP_B, psDec->HP_A, psDec->HPState, pOut, L ); TOC(HP_out) /* Update some decoder state variables */ psDec->lagPrev = sDecCtrl.pitchL[ psDec->nb_subfr - 1 ]; /********************************************/ /* set output frame length */ /********************************************/ *pN = ( SKP_int16 )L; TOC(DECODE_FRAME) return ret; }
/* Resamples input data with a factor 2/3 */ void SKP_Silk_resample_2_3_coarsest( SKP_int16 *out, /* O: Output signal */ SKP_int16 *S, /* I/O: Resampler state [ SigProc_Resample_2_3_coarsest_NUM_FIR_COEFS - 1 ] */ const SKP_int16 *in, /* I: Input signal */ const SKP_int frameLenIn, /* I: Number of input samples */ SKP_int16 *scratch /* I: Scratch memory [ frameLenIn + SigProc_Resample_2_3_coarsest_NUM_FIR_COEFS - 1 ] */ ) { SKP_int32 n, ind, interpol_ind, tmp, index_Q16; SKP_int16 *in_ptr; SKP_int frameLenOut; const SKP_int16 *interpol_ptr; /* Copy buffered samples to start of scratch */ SKP_memcpy( scratch, S, ( SigProc_Resample_2_3_coarsest_NUM_FIR_COEFS - 1 ) * sizeof( SKP_int16 ) ); /* Then append by the input signal */ SKP_memcpy( &scratch[ SigProc_Resample_2_3_coarsest_NUM_FIR_COEFS - 1 ], in, frameLenIn * sizeof( SKP_int16 ) ); frameLenOut = SKP_SMULWB( SKP_LSHIFT( (SKP_int32)frameLenIn, 1 ), 21846 ); // 21846_Q15 = (2/3)_Q0 rounded _up_ index_Q16 = 0; SKP_assert( frameLenIn == ( ( frameLenOut * 3 ) / 2 ) ); /* Interpolate */ for( n = frameLenOut; n > 0; n-- ) { /* Integer part */ ind = SKP_RSHIFT( index_Q16, 16 ); /* Pointer to buffered input */ in_ptr = scratch + ind; /* Fractional part */ interpol_ind = ( SKP_SMULWB( index_Q16, SigProc_Resample_2_3_coarsest_NUM_INTERPOLATORS ) & ( SigProc_Resample_2_3_coarsest_NUM_INTERPOLATORS - 1 ) ); /* Pointer to FIR taps */ interpol_ptr = SigProc_Resample_2_3_coarsest_INTERPOL[ interpol_ind ]; /* Interpolate: Hardcoded for 10 FIR taps */ SKP_assert( SigProc_Resample_2_3_coarsest_NUM_FIR_COEFS == 10 ); tmp = SKP_SMULBB( interpol_ptr[ 0 ], in_ptr[ 0 ] ); tmp = SKP_SMLABB( tmp, interpol_ptr[ 1 ], in_ptr[ 1 ] ); tmp = SKP_SMLABB( tmp, interpol_ptr[ 2 ], in_ptr[ 2 ] ); tmp = SKP_SMLABB( tmp, interpol_ptr[ 3 ], in_ptr[ 3 ] ); tmp = SKP_SMLABB( tmp, interpol_ptr[ 4 ], in_ptr[ 4 ] ); tmp = SKP_SMLABB( tmp, interpol_ptr[ 5 ], in_ptr[ 5 ] ); tmp = SKP_SMLABB( tmp, interpol_ptr[ 6 ], in_ptr[ 6 ] ); tmp = SKP_SMLABB( tmp, interpol_ptr[ 7 ], in_ptr[ 7 ] ); tmp = SKP_SMLABB( tmp, interpol_ptr[ 8 ], in_ptr[ 8 ] ); tmp = SKP_SMLABB( tmp, interpol_ptr[ 9 ], in_ptr[ 9 ] ); /* Round, saturate and store to output array */ *out++ = (SKP_int16)SKP_SAT16( SKP_RSHIFT_ROUND( tmp, 15 ) ); /* Update index */ index_Q16 += ( ( 1 << 16 ) + ( 1 << 15 ) ); // (3/2)_Q0; } /* Move last part of input signal to the sample buffer to prepare for the next call */ SKP_memcpy( S, &in[ frameLenIn - ( SigProc_Resample_2_3_coarsest_NUM_FIR_COEFS - 1 ) ], ( SigProc_Resample_2_3_coarsest_NUM_FIR_COEFS - 1 ) * sizeof( SKP_int16 ) ); }
/* Deactivate by setting psEncC->transition_frame_no = 0; */ void SKP_Silk_LP_variable_cutoff( SKP_Silk_LP_state *psLP, /* I/O LP filter state */ SKP_int16 *out, /* O Low-pass filtered output signal */ const SKP_int16 *in, /* I Input signal */ const SKP_int frame_length /* I Frame length */ ) { SKP_int32 B_Q28[ TRANSITION_NB ], A_Q28[ TRANSITION_NA ], fac_Q16 = 0; SKP_int ind = 0; SKP_assert( psLP->transition_frame_no >= 0 ); SKP_assert( ( ( ( psLP->transition_frame_no <= TRANSITION_FRAMES_DOWN ) && ( psLP->mode == 0 ) ) || ( ( psLP->transition_frame_no <= TRANSITION_FRAMES_UP ) && ( psLP->mode == 1 ) ) ) ); /* Interpolate filter coefficients if needed */ if( psLP->transition_frame_no > 0 ) { if( psLP->mode == 0 ) { if( psLP->transition_frame_no < TRANSITION_FRAMES_DOWN ) { /* Calculate index and interpolation factor for interpolation */ #if( TRANSITION_INT_STEPS_DOWN == 32 ) fac_Q16 = SKP_LSHIFT( psLP->transition_frame_no, 16 - 5 ); #else fac_Q16 = SKP_DIV32_16( SKP_LSHIFT( psLP->transition_frame_no, 16 ), TRANSITION_INT_STEPS_DOWN ); #endif ind = SKP_RSHIFT( fac_Q16, 16 ); fac_Q16 -= SKP_LSHIFT( ind, 16 ); SKP_assert( ind >= 0 ); SKP_assert( ind < TRANSITION_INT_NUM ); /* Interpolate filter coefficients */ SKP_Silk_LP_interpolate_filter_taps( B_Q28, A_Q28, ind, fac_Q16 ); /* Increment transition frame number for next frame */ psLP->transition_frame_no++; } else if( psLP->transition_frame_no == TRANSITION_FRAMES_DOWN ) { /* End of transition phase */ SKP_Silk_LP_interpolate_filter_taps( B_Q28, A_Q28, TRANSITION_INT_NUM - 1, 0 ); } } else if( psLP->mode == 1 ) { if( psLP->transition_frame_no < TRANSITION_FRAMES_UP ) { /* Calculate index and interpolation factor for interpolation */ #if( TRANSITION_INT_STEPS_UP == 64 ) fac_Q16 = SKP_LSHIFT( TRANSITION_FRAMES_UP - psLP->transition_frame_no, 16 - 6 ); #else fac_Q16 = SKP_DIV32_16( SKP_LSHIFT( TRANSITION_FRAMES_UP - psLP->transition_frame_no, 16 ), TRANSITION_INT_STEPS_UP ); #endif ind = SKP_RSHIFT( fac_Q16, 16 ); fac_Q16 -= SKP_LSHIFT( ind, 16 ); SKP_assert( ind >= 0 ); SKP_assert( ind < TRANSITION_INT_NUM ); /* Interpolate filter coefficients */ SKP_Silk_LP_interpolate_filter_taps( B_Q28, A_Q28, ind, fac_Q16 ); /* Increment transition frame number for next frame */ psLP->transition_frame_no++; } else if( psLP->transition_frame_no == TRANSITION_FRAMES_UP ) { /* End of transition phase */ SKP_Silk_LP_interpolate_filter_taps( B_Q28, A_Q28, 0, 0 ); } } } if( psLP->transition_frame_no > 0 ) { /* ARMA low-pass filtering */ SKP_assert( TRANSITION_NB == 3 && TRANSITION_NA == 2 ); SKP_Silk_biquad_alt( in, B_Q28, A_Q28, psLP->In_LP_State, out, frame_length ); } else { /* Instead of using the filter, copy input directly to output */ SKP_memcpy( out, in, frame_length * sizeof( SKP_int16 ) ); } }
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 ); }
/* Encode quantization indices of excitation */ void SKP_Silk_encode_pulses( ec_enc *psRangeEnc, /* I/O compressor data structure */ const SKP_int signalType, /* I Sigtype */ const SKP_int quantOffsetType, /* I quantOffsetType */ SKP_int8 pulses[], /* I quantization indices */ const SKP_int frame_length /* I Frame length */ ) { SKP_int i, k, j, iter, bit, nLS, scale_down, RateLevelIndex = 0; SKP_int32 abs_q, minSumBits_Q5, sumBits_Q5; SKP_int abs_pulses[ MAX_FRAME_LENGTH ]; SKP_int sum_pulses[ MAX_NB_SHELL_BLOCKS ]; SKP_int nRshifts[ MAX_NB_SHELL_BLOCKS ]; SKP_int pulses_comb[ 8 ]; SKP_int *abs_pulses_ptr; const SKP_int8 *pulses_ptr; const SKP_uint8 *cdf_ptr; const SKP_uint8 *nBits_ptr; SKP_memset( pulses_comb, 0, 8 * sizeof( SKP_int ) ); // Fixing Valgrind reported problem /****************************/ /* Prepare for shell coding */ /****************************/ /* Calculate number of shell blocks */ SKP_assert( 1 << LOG2_SHELL_CODEC_FRAME_LENGTH == SHELL_CODEC_FRAME_LENGTH ); iter = SKP_RSHIFT( frame_length, LOG2_SHELL_CODEC_FRAME_LENGTH ); if( iter * SHELL_CODEC_FRAME_LENGTH < frame_length ){ SKP_assert( frame_length == 12 * 10 ); /* Make sure only happens for 10 ms @ 12 kHz */ iter++; SKP_memset( &pulses[ frame_length ], 0, SHELL_CODEC_FRAME_LENGTH * sizeof(SKP_int8)); } /* Take the absolute value of the pulses */ for( i = 0; i < iter * SHELL_CODEC_FRAME_LENGTH; i+=4 ) { abs_pulses[i+0] = ( SKP_int )SKP_abs( pulses[ i + 0 ] ); abs_pulses[i+1] = ( SKP_int )SKP_abs( pulses[ i + 1 ] ); abs_pulses[i+2] = ( SKP_int )SKP_abs( pulses[ i + 2 ] ); abs_pulses[i+3] = ( SKP_int )SKP_abs( pulses[ i + 3 ] ); } /* Calc sum pulses per shell code frame */ abs_pulses_ptr = abs_pulses; for( i = 0; i < iter; i++ ) { nRshifts[ i ] = 0; while( 1 ) { /* 1+1 -> 2 */ scale_down = combine_and_check( pulses_comb, abs_pulses_ptr, SKP_Silk_max_pulses_table[ 0 ], 8 ); /* 2+2 -> 4 */ scale_down += combine_and_check( pulses_comb, pulses_comb, SKP_Silk_max_pulses_table[ 1 ], 4 ); /* 4+4 -> 8 */ scale_down += combine_and_check( pulses_comb, pulses_comb, SKP_Silk_max_pulses_table[ 2 ], 2 ); /* 8+8 -> 16 */ scale_down += combine_and_check( &sum_pulses[ i ], pulses_comb, SKP_Silk_max_pulses_table[ 3 ], 1 ); if( scale_down ) { /* We need to downscale the quantization signal */ nRshifts[ i ]++; for( k = 0; k < SHELL_CODEC_FRAME_LENGTH; k++ ) { abs_pulses_ptr[ k ] = SKP_RSHIFT( abs_pulses_ptr[ k ], 1 ); } } else { /* Jump out of while(1) loop and go to next shell coding frame */ break; } } abs_pulses_ptr += SHELL_CODEC_FRAME_LENGTH; } /**************/ /* Rate level */ /**************/ /* find rate level that leads to fewest bits for coding of pulses per block info */ minSumBits_Q5 = SKP_int32_MAX; for( k = 0; k < N_RATE_LEVELS - 1; k++ ) { nBits_ptr = SKP_Silk_pulses_per_block_BITS_Q5[ k ]; sumBits_Q5 = SKP_Silk_rate_levels_BITS_Q5[ signalType >> 1 ][ k ]; for( i = 0; i < iter; i++ ) { if( nRshifts[ i ] > 0 ) { sumBits_Q5 += nBits_ptr[ MAX_PULSES + 1 ]; } else { sumBits_Q5 += nBits_ptr[ sum_pulses[ i ] ]; } } if( sumBits_Q5 < minSumBits_Q5 ) { minSumBits_Q5 = sumBits_Q5; RateLevelIndex = k; } } ec_enc_icdf( psRangeEnc, RateLevelIndex, SKP_Silk_rate_levels_iCDF[ signalType >> 1 ], 8 ); /***************************************************/ /* Sum-Weighted-Pulses Encoding */ /***************************************************/ cdf_ptr = SKP_Silk_pulses_per_block_iCDF[ RateLevelIndex ]; for( i = 0; i < iter; i++ ) { if( nRshifts[ i ] == 0 ) { ec_enc_icdf( psRangeEnc, sum_pulses[ i ], cdf_ptr, 8 ); } else { ec_enc_icdf( psRangeEnc, MAX_PULSES + 1, cdf_ptr, 8 ); for( k = 0; k < nRshifts[ i ] - 1; k++ ) { ec_enc_icdf( psRangeEnc, MAX_PULSES + 1, SKP_Silk_pulses_per_block_iCDF[ N_RATE_LEVELS - 1 ], 8 ); } ec_enc_icdf( psRangeEnc, sum_pulses[ i ], SKP_Silk_pulses_per_block_iCDF[ N_RATE_LEVELS - 1 ], 8 ); } } /******************/ /* Shell Encoding */ /******************/ for( i = 0; i < iter; i++ ) { if( sum_pulses[ i ] > 0 ) { SKP_Silk_shell_encoder( psRangeEnc, &abs_pulses[ i * SHELL_CODEC_FRAME_LENGTH ] ); } } /****************/ /* LSB Encoding */ /****************/ for( i = 0; i < iter; i++ ) { if( nRshifts[ i ] > 0 ) { pulses_ptr = &pulses[ i * SHELL_CODEC_FRAME_LENGTH ]; nLS = nRshifts[ i ] - 1; for( k = 0; k < SHELL_CODEC_FRAME_LENGTH; k++ ) { abs_q = (SKP_int8)SKP_abs( pulses_ptr[ k ] ); for( j = nLS; j > 0; j-- ) { bit = SKP_RSHIFT( abs_q, j ) & 1; ec_enc_icdf( psRangeEnc, bit, SKP_Silk_lsb_iCDF, 8 ); } bit = abs_q & 1; ec_enc_icdf( psRangeEnc, bit, SKP_Silk_lsb_iCDF, 8 ); } } } #if! USE_CELT_PVQ /****************/ /* Encode signs */ /****************/ SKP_Silk_encode_signs( psRangeEnc, pulses, frame_length, signalType, quantOffsetType, sum_pulses ); #endif }
/* Encode side-information parameters to payload */ void silk_encode_indices( silk_encoder_state *psEncC, /* I/O Encoder state */ ec_enc *psRangeEnc, /* I/O Compressor data structure */ opus_int FrameIndex, /* I Frame number */ opus_int encode_LBRR /* I Flag indicating LBRR data is being encoded */ ) { opus_int i, k, condCoding, typeOffset; opus_int encode_absolute_lagIndex, delta_lagIndex; opus_int16 ec_ix[ MAX_LPC_ORDER ]; opus_uint8 pred_Q8[ MAX_LPC_ORDER ]; const SideInfoIndices *psIndices; #if SAVE_ALL_INTERNAL_DATA opus_int nBytes_lagIndex, nBytes_contourIndex, nBytes_LTP; opus_int nBytes_after, nBytes_before; #endif /* Use conditional coding if previous frame available */ if( FrameIndex > 0 && ( encode_LBRR == 0 || psEncC->LBRR_flags[ FrameIndex - 1 ] == 1 ) ) { condCoding = 1; } else { condCoding = 0; } if( encode_LBRR ) { psIndices = &psEncC->indices_LBRR[ FrameIndex ]; } else { psIndices = &psEncC->indices; } /*******************************************/ /* Encode signal type and quantizer offset */ /*******************************************/ typeOffset = 2 * psIndices->signalType + psIndices->quantOffsetType; SKP_assert( typeOffset >= 0 && typeOffset < 6 ); SKP_assert( encode_LBRR == 0 || typeOffset >= 2 ); if( encode_LBRR || typeOffset >= 2 ) { ec_enc_icdf( psRangeEnc, typeOffset - 2, silk_type_offset_VAD_iCDF, 8 ); } else { ec_enc_icdf( psRangeEnc, typeOffset, silk_type_offset_no_VAD_iCDF, 8 ); } /****************/ /* Encode gains */ /****************/ #ifdef SAVE_ALL_INTERNAL_DATA nBytes_before = SKP_RSHIFT( ec_tell( psRangeEnc ) + 7, 3 ); #endif /* first subframe */ if( condCoding ) { /* conditional coding */ SKP_assert( psIndices->GainsIndices[ 0 ] >= 0 && psIndices->GainsIndices[ 0 ] < MAX_DELTA_GAIN_QUANT - MIN_DELTA_GAIN_QUANT + 1 ); ec_enc_icdf( psRangeEnc, psIndices->GainsIndices[ 0 ], silk_delta_gain_iCDF, 8 ); } else { /* independent coding, in two stages: MSB bits followed by 3 LSBs */ SKP_assert( psIndices->GainsIndices[ 0 ] >= 0 && psIndices->GainsIndices[ 0 ] < N_LEVELS_QGAIN ); ec_enc_icdf( psRangeEnc, SKP_RSHIFT( psIndices->GainsIndices[ 0 ], 3 ), silk_gain_iCDF[ psIndices->signalType ], 8 ); ec_enc_icdf( psRangeEnc, psIndices->GainsIndices[ 0 ] & 7, silk_uniform8_iCDF, 8 ); } /* remaining subframes */ for( i = 1; i < psEncC->nb_subfr; i++ ) { SKP_assert( psIndices->GainsIndices[ i ] >= 0 && psIndices->GainsIndices[ i ] < MAX_DELTA_GAIN_QUANT - MIN_DELTA_GAIN_QUANT + 1 ); ec_enc_icdf( psRangeEnc, psIndices->GainsIndices[ i ], silk_delta_gain_iCDF, 8 ); } #ifdef SAVE_ALL_INTERNAL_DATA nBytes_after = SKP_RSHIFT( ec_tell( psRangeEnc ) + 7, 3 ); nBytes_after -= nBytes_before; // bytes just added DEBUG_STORE_DATA( nBytes_gains.dat, &nBytes_after, sizeof( opus_int ) ); #endif /****************/ /* Encode NLSFs */ /****************/ #ifdef SAVE_ALL_INTERNAL_DATA nBytes_before = SKP_RSHIFT( ec_tell( psRangeEnc ) + 7, 3 ); #endif ec_enc_icdf( psRangeEnc, psIndices->NLSFIndices[ 0 ], &psEncC->psNLSF_CB->CB1_iCDF[ ( psIndices->signalType >> 1 ) * psEncC->psNLSF_CB->nVectors ], 8 ); silk_NLSF_unpack( ec_ix, pred_Q8, psEncC->psNLSF_CB, psIndices->NLSFIndices[ 0 ] ); SKP_assert( psEncC->psNLSF_CB->order == psEncC->predictLPCOrder ); for( i = 0; i < psEncC->psNLSF_CB->order; i++ ) { if( psIndices->NLSFIndices[ i+1 ] >= NLSF_QUANT_MAX_AMPLITUDE ) { ec_enc_icdf( psRangeEnc, 2 * NLSF_QUANT_MAX_AMPLITUDE, &psEncC->psNLSF_CB->ec_iCDF[ ec_ix[ i ] ], 8 ); ec_enc_icdf( psRangeEnc, psIndices->NLSFIndices[ i+1 ] - NLSF_QUANT_MAX_AMPLITUDE, silk_NLSF_EXT_iCDF, 8 ); } else if( psIndices->NLSFIndices[ i+1 ] <= -NLSF_QUANT_MAX_AMPLITUDE ) { ec_enc_icdf( psRangeEnc, 0, &psEncC->psNLSF_CB->ec_iCDF[ ec_ix[ i ] ], 8 ); ec_enc_icdf( psRangeEnc, -psIndices->NLSFIndices[ i+1 ] - NLSF_QUANT_MAX_AMPLITUDE, silk_NLSF_EXT_iCDF, 8 ); } else { ec_enc_icdf( psRangeEnc, psIndices->NLSFIndices[ i+1 ] + NLSF_QUANT_MAX_AMPLITUDE, &psEncC->psNLSF_CB->ec_iCDF[ ec_ix[ i ] ], 8 ); } } /* Encode NLSF interpolation factor */ if( psEncC->nb_subfr == MAX_NB_SUBFR ) { SKP_assert( psEncC->useInterpolatedNLSFs == 1 || psIndices->NLSFInterpCoef_Q2 == ( 1 << 2 ) ); SKP_assert( psIndices->NLSFInterpCoef_Q2 >= 0 && psIndices->NLSFInterpCoef_Q2 < 5 ); ec_enc_icdf( psRangeEnc, psIndices->NLSFInterpCoef_Q2, silk_NLSF_interpolation_factor_iCDF, 8 ); } #ifdef SAVE_ALL_INTERNAL_DATA DEBUG_STORE_DATA( lsf_interpol.dat, &psIndices->NLSFInterpCoef_Q2, sizeof(int) ); nBytes_after = SKP_RSHIFT( ec_tell( psRangeEnc ) + 7, 3 ); nBytes_after -= nBytes_before; // bytes just added DEBUG_STORE_DATA( nBytes_LSF.dat, &nBytes_after, sizeof( opus_int ) ); #endif if( psIndices->signalType == TYPE_VOICED ) { /*********************/ /* Encode pitch lags */ /*********************/ #ifdef SAVE_ALL_INTERNAL_DATA nBytes_before = SKP_RSHIFT( ec_tell( psRangeEnc ) + 7, 3 ); #endif /* lag index */ encode_absolute_lagIndex = 1; if( condCoding && psEncC->ec_prevSignalType == TYPE_VOICED ) { /* Delta Encoding */ delta_lagIndex = psIndices->lagIndex - psEncC->ec_prevLagIndex; if( delta_lagIndex < -8 || delta_lagIndex > 11 ) { delta_lagIndex = 0; } else { delta_lagIndex = delta_lagIndex + 9; encode_absolute_lagIndex = 0; /* Only use delta */ } SKP_assert( delta_lagIndex >= 0 && delta_lagIndex < 21 ); ec_enc_icdf( psRangeEnc, delta_lagIndex, silk_pitch_delta_iCDF, 8 ); } if( encode_absolute_lagIndex ) { /* Absolute encoding */ opus_int32 pitch_high_bits, pitch_low_bits; pitch_high_bits = SKP_DIV32_16( psIndices->lagIndex, SKP_RSHIFT( psEncC->fs_kHz, 1 ) ); pitch_low_bits = psIndices->lagIndex - SKP_SMULBB( pitch_high_bits, SKP_RSHIFT( psEncC->fs_kHz, 1 ) ); SKP_assert( pitch_low_bits < psEncC->fs_kHz / 2 ); SKP_assert( pitch_high_bits < 32 ); ec_enc_icdf( psRangeEnc, pitch_high_bits, silk_pitch_lag_iCDF, 8 ); ec_enc_icdf( psRangeEnc, pitch_low_bits, psEncC->pitch_lag_low_bits_iCDF, 8 ); } psEncC->ec_prevLagIndex = psIndices->lagIndex; #ifdef SAVE_ALL_INTERNAL_DATA nBytes_after = SKP_RSHIFT( ec_tell( psRangeEnc ) + 7, 3 ); nBytes_lagIndex = nBytes_after - nBytes_before; // bytes just added #endif #ifdef SAVE_ALL_INTERNAL_DATA nBytes_before = SKP_RSHIFT( ec_tell( psRangeEnc ) + 7, 3 ); #endif /* Countour index */ SKP_assert( psIndices->contourIndex >= 0 ); SKP_assert( ( psIndices->contourIndex < 34 && psEncC->fs_kHz > 8 && psEncC->nb_subfr == 4 ) || ( psIndices->contourIndex < 11 && psEncC->fs_kHz == 8 && psEncC->nb_subfr == 4 ) || ( psIndices->contourIndex < 12 && psEncC->fs_kHz > 8 && psEncC->nb_subfr == 2 ) || ( psIndices->contourIndex < 3 && psEncC->fs_kHz == 8 && psEncC->nb_subfr == 2 ) ); ec_enc_icdf( psRangeEnc, psIndices->contourIndex, psEncC->pitch_contour_iCDF, 8 ); #ifdef SAVE_ALL_INTERNAL_DATA nBytes_after = SKP_RSHIFT( ec_tell( psRangeEnc ) + 7, 3 ); nBytes_contourIndex = nBytes_after - nBytes_before; // bytes just added #endif /********************/ /* Encode LTP gains */ /********************/ #ifdef SAVE_ALL_INTERNAL_DATA nBytes_before = SKP_RSHIFT( ec_tell( psRangeEnc ) + 7, 3 ); #endif /* PERIndex value */ SKP_assert( psIndices->PERIndex >= 0 && psIndices->PERIndex < 3 ); ec_enc_icdf( psRangeEnc, psIndices->PERIndex, silk_LTP_per_index_iCDF, 8 ); /* Codebook Indices */ for( k = 0; k < psEncC->nb_subfr; k++ ) { SKP_assert( psIndices->LTPIndex[ k ] >= 0 && psIndices->LTPIndex[ k ] < ( 8 << psIndices->PERIndex ) ); ec_enc_icdf( psRangeEnc, psIndices->LTPIndex[ k ], silk_LTP_gain_iCDF_ptrs[ psIndices->PERIndex ], 8 ); } /**********************/ /* Encode LTP scaling */ /**********************/ if( !condCoding ) { SKP_assert( psIndices->LTP_scaleIndex >= 0 && psIndices->LTP_scaleIndex < 3 ); ec_enc_icdf( psRangeEnc, psIndices->LTP_scaleIndex, silk_LTPscale_iCDF, 8 ); } SKP_assert( !condCoding || psIndices->LTP_scaleIndex == 0 ); #ifdef SAVE_ALL_INTERNAL_DATA nBytes_after = SKP_RSHIFT( ec_tell( psRangeEnc ) + 7, 3 ); nBytes_LTP = nBytes_after - nBytes_before; // bytes just added #endif } #ifdef SAVE_ALL_INTERNAL_DATA else { // Unvoiced speech nBytes_lagIndex = 0; nBytes_contourIndex = 0; nBytes_LTP = 0; } DEBUG_STORE_DATA( nBytes_lagIndex.dat, &nBytes_lagIndex, sizeof( opus_int ) ); DEBUG_STORE_DATA( nBytes_contourIndex.dat, &nBytes_contourIndex, sizeof( opus_int ) ); DEBUG_STORE_DATA( nBytes_LTP.dat, &nBytes_LTP, sizeof( opus_int ) ); #endif psEncC->ec_prevSignalType = psIndices->signalType; #ifdef SAVE_ALL_INTERNAL_DATA nBytes_before = SKP_RSHIFT( ec_tell( psRangeEnc ) + 7, 3 ); #endif /***************/ /* Encode seed */ /***************/ SKP_assert( psIndices->Seed >= 0 && psIndices->Seed < 4 ); ec_enc_icdf( psRangeEnc, psIndices->Seed, silk_uniform4_iCDF, 8 ); }
void SKP_Silk_find_pred_coefs_FIX(SKP_Silk_encoder_state_FIX * psEnc, /* I/O encoder state */ SKP_Silk_encoder_control_FIX * psEncCtrl, /* I/O encoder control */ const int16_t res_pitch[] /* I Residual from pitch analysis */ ) { int i; int32_t WLTP[NB_SUBFR * LTP_ORDER * LTP_ORDER]; int32_t invGains_Q16[NB_SUBFR], local_gains_Qx[NB_SUBFR], Wght_Q15[NB_SUBFR]; int NLSF_Q15[MAX_LPC_ORDER]; const int16_t *x_ptr; int16_t *x_pre_ptr, LPC_in_pre[NB_SUBFR * MAX_LPC_ORDER + MAX_FRAME_LENGTH]; int32_t tmp, min_gain_Q16; #if !VARQ int LZ; #endif int LTP_corrs_rshift[NB_SUBFR]; /* weighting for weighted least squares */ min_gain_Q16 = int32_t_MAX >> 6; for (i = 0; i < NB_SUBFR; i++) { min_gain_Q16 = SKP_min(min_gain_Q16, psEncCtrl->Gains_Q16[i]); } #if !VARQ LZ = SKP_Silk_CLZ32(min_gain_Q16) - 1; LZ = SKP_LIMIT(LZ, 0, 16); min_gain_Q16 = SKP_RSHIFT(min_gain_Q16, 2); /* Ensure that maximum invGains_Q16 is within range of a 16 bit int */ #endif for (i = 0; i < NB_SUBFR; i++) { /* Divide to Q16 */ assert(psEncCtrl->Gains_Q16[i] > 0); #if VARQ /* Invert and normalize gains, and ensure that maximum invGains_Q16 is within range of a 16 bit int */ invGains_Q16[i] = SKP_DIV32_varQ(min_gain_Q16, psEncCtrl->Gains_Q16[i], 16 - 2); #else invGains_Q16[i] = SKP_DIV32(SKP_LSHIFT(min_gain_Q16, LZ), SKP_RSHIFT(psEncCtrl->Gains_Q16[i], 16 - LZ)); #endif /* Ensure Wght_Q15 a minimum value 1 */ invGains_Q16[i] = SKP_max(invGains_Q16[i], 363); /* Square the inverted gains */ assert(invGains_Q16[i] == SKP_SAT16(invGains_Q16[i])); tmp = SKP_SMULWB(invGains_Q16[i], invGains_Q16[i]); Wght_Q15[i] = SKP_RSHIFT(tmp, 1); /* Invert the inverted and normalized gains */ local_gains_Qx[i] = SKP_DIV32((1 << (16 + Qx)), invGains_Q16[i]); } if (psEncCtrl->sCmn.sigtype == SIG_TYPE_VOICED) { /**********/ /* VOICED */ /**********/ assert(psEnc->sCmn.frame_length - psEnc->sCmn.predictLPCOrder >= psEncCtrl->sCmn.pitchL[0] + LTP_ORDER / 2); /* LTP analysis */ SKP_Silk_find_LTP_FIX(psEncCtrl->LTPCoef_Q14, WLTP, &psEncCtrl->LTPredCodGain_Q7, res_pitch, res_pitch + SKP_RSHIFT(psEnc->sCmn.frame_length, 1), psEncCtrl->sCmn.pitchL, Wght_Q15, psEnc->sCmn.subfr_length, psEnc->sCmn.frame_length, LTP_corrs_rshift); /* Quantize LTP gain parameters */ SKP_Silk_quant_LTP_gains_FIX(psEncCtrl->LTPCoef_Q14, psEncCtrl->sCmn.LTPIndex, &psEncCtrl->sCmn.PERIndex, WLTP, psEnc->mu_LTP_Q8, psEnc->sCmn.LTPQuantLowComplexity); /* Control LTP scaling */ SKP_Silk_LTP_scale_ctrl_FIX(psEnc, psEncCtrl); /* Create LTP residual */ SKP_Silk_LTP_analysis_filter_FIX(LPC_in_pre, psEnc->x_buf + psEnc->sCmn.frame_length - psEnc->sCmn.predictLPCOrder, psEncCtrl->LTPCoef_Q14, psEncCtrl->sCmn.pitchL, invGains_Q16, 16, psEnc->sCmn.subfr_length, psEnc->sCmn.predictLPCOrder); } else { /************/ /* UNVOICED */ /************/ /* Create signal with prepended subframes, scaled by inverse gains */ x_ptr = psEnc->x_buf + psEnc->sCmn.frame_length - psEnc->sCmn.predictLPCOrder; x_pre_ptr = LPC_in_pre; for (i = 0; i < NB_SUBFR; i++) { SKP_Silk_scale_copy_vector16(x_pre_ptr, x_ptr, invGains_Q16[i], psEnc->sCmn.subfr_length + psEnc->sCmn. predictLPCOrder); x_pre_ptr += psEnc->sCmn.subfr_length + psEnc->sCmn.predictLPCOrder; x_ptr += psEnc->sCmn.subfr_length; } SKP_memset(psEncCtrl->LTPCoef_Q14, 0, NB_SUBFR * LTP_ORDER * sizeof(int16_t)); psEncCtrl->LTPredCodGain_Q7 = 0; } /* LPC_in_pre contains the LTP-filtered input for voiced, and the unfiltered input for unvoiced */ TIC(FIND_LPC) SKP_Silk_find_LPC_FIX(NLSF_Q15, &psEncCtrl->sCmn.NLSFInterpCoef_Q2, psEnc->sPred.prev_NLSFq_Q15, psEnc->sCmn.useInterpolatedNLSFs * (1 - psEnc-> sCmn. first_frame_after_reset), psEnc->sCmn.predictLPCOrder, LPC_in_pre, psEnc->sCmn.subfr_length + psEnc->sCmn.predictLPCOrder); TOC(FIND_LPC) /* Quantize LSFs */ TIC(PROCESS_LSFS) SKP_Silk_process_NLSFs_FIX(psEnc, psEncCtrl, NLSF_Q15); TOC(PROCESS_LSFS) /* Calculate residual energy using quantized LPC coefficients */ SKP_Silk_residual_energy_FIX(psEncCtrl->ResNrg, psEncCtrl->ResNrgQ, LPC_in_pre, (const int16_t(*)[])psEncCtrl->PredCoef_Q12, local_gains_Qx, Qx, psEnc->sCmn.subfr_length, psEnc->sCmn.predictLPCOrder); /* Copy to prediction struct for use in next frame for fluctuation reduction */ SKP_memcpy(psEnc->sPred.prev_NLSFq_Q15, NLSF_Q15, psEnc->sCmn.predictLPCOrder * sizeof(int)); }
/* Control encoder SNR */ SKP_int SKP_Silk_control_encoder_FIX( SKP_Silk_encoder_state_FIX *psEnc, /* I/O Pointer to Silk encoder state */ const SKP_int API_fs_kHz, /* I External (API) sampling rate (kHz) */ const SKP_int PacketSize_ms, /* I Packet length (ms) */ SKP_int32 TargetRate_bps, /* I Target max bitrate (bps) (used if SNR_dB == 0) */ const SKP_int PacketLoss_perc, /* I Packet loss rate (in percent) */ const SKP_int INBandFec_enabled, /* I Enable (1) / disable (0) inband FEC */ const SKP_int DTX_enabled, /* I Enable / disable DTX */ const SKP_int InputFramesize_ms, /* I Inputframe in ms */ const SKP_int Complexity /* I Complexity (0->low; 1->medium; 2->high) */ ) { SKP_int32 LBRRRate_thres_bps; SKP_int k, fs_kHz, ret = 0; SKP_int32 frac_Q6; const SKP_int32 *rateTable; /* State machine for the SWB/WB switching */ fs_kHz = psEnc->sCmn.fs_kHz; /* Only switch during low speech activity, when no frames are sitting in the payload buffer */ if( API_fs_kHz == 8 || fs_kHz == 0 || API_fs_kHz < fs_kHz ) { // Switching is not possible, encoder just initialized, or internal mode higher than external fs_kHz = API_fs_kHz; } else { /* Resample all valid data in x_buf. Resampling the last part gets rid of a click, 5ms after switching */ /* this is because the same state is used when downsampling in API.c and is then up to date */ /* the click immidiatly after switching is most of the time still there */ if( psEnc->sCmn.fs_kHz == 24 ) { /* Accumulate the difference between the target rate and limit */ if( psEnc->sCmn.fs_kHz_changed == 0 ) { psEnc->sCmn.bitrateDiff += SKP_MUL( InputFramesize_ms, TargetRate_bps - SWB2WB_BITRATE_BPS_INITIAL ); } else { psEnc->sCmn.bitrateDiff += SKP_MUL( InputFramesize_ms, TargetRate_bps - SWB2WB_BITRATE_BPS ); } psEnc->sCmn.bitrateDiff = SKP_min( psEnc->sCmn.bitrateDiff, 0 ); /* Check if we should switch from 24 to 16 kHz */ #if SWITCH_TRANSITION_FILTERING if( ( psEnc->sCmn.sLP.transition_frame_no == 0 ) && /* Transition phase not active */ ( psEnc->sCmn.bitrateDiff <= -ACCUM_BITS_DIFF_THRESHOLD || psEnc->sCmn.sSWBdetect.WB_detected == 1 ) && ( psEnc->speech_activity_Q8 < 128 && psEnc->sCmn.nFramesInPayloadBuf == 0 ) ) { psEnc->sCmn.sLP.transition_frame_no = 1; /* Begin transition phase */ psEnc->sCmn.sLP.mode = 0; /* Switch down */ } if( ( psEnc->sCmn.sLP.transition_frame_no >= TRANSITION_FRAMES_DOWN ) && ( psEnc->sCmn.sLP.mode == 0 ) && /* Transition phase complete, ready to switch */ #else if( ( psEnc->sCmn.bitrateDiff <= -ACCUM_BITS_DIFF_THRESHOLD || psEnc->sCmn.sSWBdetect.WB_detected == 1 ) && #endif ( psEnc->speech_activity_Q8 < 128 && psEnc->sCmn.nFramesInPayloadBuf == 0 ) ) { SKP_int16 x_buf[ 2 * MAX_FRAME_LENGTH + LA_SHAPE_MAX ]; SKP_int16 x_bufout[ 2 * MAX_FRAME_LENGTH + LA_SHAPE_MAX ]; psEnc->sCmn.bitrateDiff = 0; fs_kHz = 16; SKP_memcpy( x_buf, psEnc->x_buf, ( 2 * MAX_FRAME_LENGTH + LA_SHAPE_MAX ) * sizeof( SKP_int16 ) ); SKP_memset( psEnc->sCmn.resample24To16state, 0, sizeof( psEnc->sCmn.resample24To16state ) ); #if LOW_COMPLEXITY_ONLY { SKP_int16 scratch[ ( 2 * MAX_FRAME_LENGTH + LA_SHAPE_MAX ) + SigProc_Resample_2_3_coarse_NUM_FIR_COEFS - 1 ]; SKP_Silk_resample_2_3_coarse( &x_bufout[ 0 ], psEnc->sCmn.resample24To16state, &x_buf[ 0 ], SKP_LSHIFT( psEnc->sCmn.frame_length, 1 ) + psEnc->sCmn.la_shape, (SKP_int16*)scratch ); } #else SKP_Silk_resample_2_3( &x_bufout[ 0 ], psEnc->sCmn.resample24To16state, &x_buf[ 0 ], SKP_LSHIFT( psEnc->sCmn.frame_length, 1 ) + psEnc->sCmn.la_shape ); #endif /* set the first frame to zero, no performance difference was noticed though */ SKP_memset( x_bufout, 0, 320 * sizeof( SKP_int16 ) ); SKP_memcpy( psEnc->x_buf, x_bufout, ( 2 * MAX_FRAME_LENGTH + LA_SHAPE_MAX ) * sizeof( SKP_int16 ) ); #if SWITCH_TRANSITION_FILTERING psEnc->sCmn.sLP.transition_frame_no = 0; /* Transition phase complete */ #endif } } else if( psEnc->sCmn.fs_kHz == 16 ) { /* Check if we should switch from 16 to 24 kHz */ #if SWITCH_TRANSITION_FILTERING if( ( psEnc->sCmn.sLP.transition_frame_no == 0 ) && /* No transition phase running, ready to switch */ #else if( #endif ( API_fs_kHz > psEnc->sCmn.fs_kHz && TargetRate_bps >= WB2SWB_BITRATE_BPS && psEnc->sCmn.sSWBdetect.WB_detected == 0 ) && ( psEnc->speech_activity_Q8 < 128 && psEnc->sCmn.nFramesInPayloadBuf == 0 ) ) { SKP_int16 x_buf[ 2 * MAX_FRAME_LENGTH + LA_SHAPE_MAX ]; SKP_int16 x_bufout[ 3 * ( 2 * MAX_FRAME_LENGTH + LA_SHAPE_MAX ) / 2 ]; SKP_int32 resample16To24state[ 11 ]; psEnc->sCmn.bitrateDiff = 0; fs_kHz = 24; SKP_memcpy( x_buf, psEnc->x_buf, ( 2 * MAX_FRAME_LENGTH + LA_SHAPE_MAX ) * sizeof( SKP_int16 ) ); SKP_memset( resample16To24state, 0, sizeof(resample16To24state) ); SKP_Silk_resample_3_2( &x_bufout[ 0 ], resample16To24state, &x_buf[ 0 ], SKP_LSHIFT( psEnc->sCmn.frame_length, 1 ) + psEnc->sCmn.la_shape ); /* set the first frame to zero, no performance difference was noticed though */ SKP_memset( x_bufout, 0, 480 * sizeof( SKP_int16 ) ); SKP_memcpy( psEnc->x_buf, x_bufout, ( 2 * MAX_FRAME_LENGTH + LA_SHAPE_MAX ) * sizeof( SKP_int16 ) ); #if SWITCH_TRANSITION_FILTERING psEnc->sCmn.sLP.mode = 1; /* Switch up */ #endif } else { /* accumulate the difference between the target rate and limit */ psEnc->sCmn.bitrateDiff += SKP_MUL( InputFramesize_ms, TargetRate_bps - WB2MB_BITRATE_BPS ); psEnc->sCmn.bitrateDiff = SKP_min( psEnc->sCmn.bitrateDiff, 0 ); /* Check if we should switch from 16 to 12 kHz */ #if SWITCH_TRANSITION_FILTERING if( ( psEnc->sCmn.sLP.transition_frame_no == 0 ) && /* Transition phase not active */ ( psEnc->sCmn.bitrateDiff <= -ACCUM_BITS_DIFF_THRESHOLD ) && ( psEnc->speech_activity_Q8 < 128 && psEnc->sCmn.nFramesInPayloadBuf == 0 ) ) { psEnc->sCmn.sLP.transition_frame_no = 1; /* Begin transition phase */ psEnc->sCmn.sLP.mode = 0; /* Switch down */ } if( ( psEnc->sCmn.sLP.transition_frame_no >= TRANSITION_FRAMES_DOWN ) && ( psEnc->sCmn.sLP.mode == 0 ) && /* Transition phase complete, ready to switch */ #else if( ( psEnc->sCmn.bitrateDiff <= -ACCUM_BITS_DIFF_THRESHOLD ) && #endif ( psEnc->speech_activity_Q8 < 128 && psEnc->sCmn.nFramesInPayloadBuf == 0 ) ) { SKP_int16 x_buf[ 2 * MAX_FRAME_LENGTH + LA_SHAPE_MAX ]; SKP_memcpy( x_buf, psEnc->x_buf, ( 2 * MAX_FRAME_LENGTH + LA_SHAPE_MAX ) * sizeof( SKP_int16 ) ); psEnc->sCmn.bitrateDiff = 0; fs_kHz = 12; if( API_fs_kHz == 24 ) { /* Intermediate upsampling of x_bufFIX from 16 to 24 kHz */ SKP_int16 x_buf24[ 3 * ( 2 * MAX_FRAME_LENGTH + LA_SHAPE_MAX ) / 2 ]; SKP_int32 scratch[ 3 * ( 2 * MAX_FRAME_LENGTH + LA_SHAPE_MAX ) ]; SKP_int32 resample16To24state[ 11 ]; SKP_memset( resample16To24state, 0, sizeof( resample16To24state ) ); SKP_Silk_resample_3_2( &x_buf24[ 0 ], resample16To24state, &x_buf[ 0 ], SKP_LSHIFT( psEnc->sCmn.frame_length, 1 ) + psEnc->sCmn.la_shape ); /* Update the state of the resampler used in API.c, from 24 to 12 kHz */ SKP_memset( psEnc->sCmn.resample24To12state, 0, sizeof( psEnc->sCmn.resample24To12state ) ); SKP_Silk_resample_1_2_coarse( &x_buf24[ 0 ], psEnc->sCmn.resample24To12state, &x_buf[ 0 ], scratch, SKP_RSHIFT( SKP_SMULBB( 3, SKP_LSHIFT( psEnc->sCmn.frame_length, 1 ) + psEnc->sCmn.la_shape ), 2 ) ); /* set the first frame to zero, no performance difference was noticed though */ SKP_memset( x_buf, 0, 240 * sizeof( SKP_int16 ) ); SKP_memcpy( psEnc->x_buf, x_buf, ( 2 * MAX_FRAME_LENGTH + LA_SHAPE_MAX ) * sizeof( SKP_int16 ) ); } else if( API_fs_kHz == 16 ) { SKP_int16 x_bufout[ 3 * ( 2 * MAX_FRAME_LENGTH + LA_SHAPE_MAX ) / 4 ]; SKP_memset( psEnc->sCmn.resample16To12state, 0, sizeof( psEnc->sCmn.resample16To12state ) ); SKP_Silk_resample_3_4( &x_bufout[ 0 ], psEnc->sCmn.resample16To12state, &x_buf[ 0 ], SKP_LSHIFT( psEnc->sCmn.frame_length, 1 ) + psEnc->sCmn.la_shape ); /* set the first frame to zero, no performance difference was noticed though */ SKP_memset( x_bufout, 0, 240 * sizeof( SKP_int16 ) ); SKP_memcpy( psEnc->x_buf, x_bufout, ( 2 * MAX_FRAME_LENGTH + LA_SHAPE_MAX ) * sizeof( SKP_int16 ) ); } #if SWITCH_TRANSITION_FILTERING psEnc->sCmn.sLP.transition_frame_no = 0; /* Transition phase complete */ #endif } } } else if( psEnc->sCmn.fs_kHz == 12 ) {
/* High-pass filter with cutoff frequency adaptation based on pitch lag statistics */ void SKP_Silk_HP_variable_cutoff_FIX( SKP_Silk_encoder_state_FIX *psEnc, /* I/O Encoder state FIX */ SKP_Silk_encoder_control_FIX *psEncCtrl, /* I/O Encoder control FIX */ SKP_int16 *out, /* O high-pass filtered output signal */ const SKP_int16 *in /* I input signal */ ) { SKP_int quality_Q15; SKP_int32 B_Q28[ 3 ], A_Q28[ 2 ]; SKP_int32 Fc_Q19, r_Q28, r_Q22; SKP_int32 pitch_freq_Hz_Q16, pitch_freq_log_Q7, delta_freq_Q7; /*********************************************/ /* Estimate Low End of Pitch Frequency Range */ /*********************************************/ if( psEnc->sCmn.prev_sigtype == SIG_TYPE_VOICED ) { /* difference, in log domain */ pitch_freq_Hz_Q16 = SKP_DIV32_16( SKP_LSHIFT( SKP_MUL( psEnc->sCmn.fs_kHz, 1000 ), 16 ), psEnc->sCmn.prevLag ); pitch_freq_log_Q7 = SKP_Silk_lin2log( pitch_freq_Hz_Q16 ) - ( 16 << 7 ); //0x70 /* adjustment based on quality */ quality_Q15 = psEncCtrl->input_quality_bands_Q15[ 0 ]; pitch_freq_log_Q7 = SKP_SUB32( pitch_freq_log_Q7, SKP_SMULWB( SKP_SMULWB( SKP_LSHIFT( quality_Q15, 2 ), quality_Q15 ), pitch_freq_log_Q7 - SKP_LOG2_VARIABLE_HP_MIN_FREQ_Q7 ) ); pitch_freq_log_Q7 = SKP_ADD32( pitch_freq_log_Q7, SKP_RSHIFT( 19661 - quality_Q15, 9 ) ); // 19661_Q15 = 0.6_Q0 //delta_freq = pitch_freq_log - psEnc->variable_HP_smth1; delta_freq_Q7 = pitch_freq_log_Q7 - SKP_RSHIFT( psEnc->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 = SKP_MUL( delta_freq_Q7, 3 ); } /* limit delta, to reduce impact of outliers */ delta_freq_Q7 = SKP_LIMIT_32( delta_freq_Q7, -VARIABLE_HP_MAX_DELTA_FREQ_Q7, VARIABLE_HP_MAX_DELTA_FREQ_Q7 ); /* update smoother */ psEnc->variable_HP_smth1_Q15 = SKP_SMLAWB( psEnc->variable_HP_smth1_Q15, SKP_MUL( SKP_LSHIFT( psEnc->speech_activity_Q8, 1 ), delta_freq_Q7 ), VARIABLE_HP_SMTH_COEF1_Q16 ); } /* second smoother */ psEnc->variable_HP_smth2_Q15 = SKP_SMLAWB( psEnc->variable_HP_smth2_Q15, psEnc->variable_HP_smth1_Q15 - psEnc->variable_HP_smth2_Q15, VARIABLE_HP_SMTH_COEF2_Q16 ); /* convert from log scale to Hertz */ psEncCtrl->pitch_freq_low_Hz = SKP_Silk_log2lin( SKP_RSHIFT( psEnc->variable_HP_smth2_Q15, 8 ) ); //pow( 2.0, psEnc->variable_HP_smth2 ); /* limit frequency range */ psEncCtrl->pitch_freq_low_Hz = SKP_LIMIT_32( psEncCtrl->pitch_freq_low_Hz, VARIABLE_HP_MIN_FREQ_Q0, VARIABLE_HP_MAX_FREQ_Q0 ); /********************************/ /* Compute Filter Coefficients */ /********************************/ /* compute cut-off frequency, in radians */ //Fc_num = (SKP_float)( 0.45f * 2.0f * 3.14159265359 * psEncCtrl->pitch_freq_low_Hz ); //Fc_denom = (SKP_float)( 1e3f * psEnc->sCmn.fs_kHz ); SKP_assert( psEncCtrl->pitch_freq_low_Hz <= SKP_int32_MAX / SKP_RADIANS_CONSTANT_Q19 ); Fc_Q19 = SKP_DIV32_16( SKP_SMULBB( SKP_RADIANS_CONSTANT_Q19, psEncCtrl->pitch_freq_low_Hz ), psEnc->sCmn.fs_kHz ); // range: 3704 - 27787, 11-15 bits SKP_assert( Fc_Q19 >= 3704 ); SKP_assert( Fc_Q19 <= 27787 ); r_Q28 = ( 1 << 28 ) - SKP_MUL( 471, Fc_Q19 ); // 471_Q9 = 0.92_Q0, range: 255347779 to 266690872, 27-28 bits SKP_assert( r_Q28 >= 255347779 ); SKP_assert( r_Q28 <= 266690872 ); /* b = r * [ 1; -2; 1 ]; */ /* a = [ 1; -2 * r * ( 1 - 0.5 * Fc^2 ); r^2 ]; */ B_Q28[ 0 ] = r_Q28; B_Q28[ 1 ] = SKP_LSHIFT( -r_Q28, 1 ); B_Q28[ 2 ] = r_Q28; // -r * ( 2 - Fc * Fc ); r_Q22 = SKP_RSHIFT( r_Q28, 6 ); A_Q28[ 0 ] = SKP_SMULWW( r_Q22, SKP_SMULWW( Fc_Q19, Fc_Q19 ) - ( 2 << 22 ) ); A_Q28[ 1 ] = SKP_SMULWW( r_Q22, r_Q22 ); /********************************/ /* High-Pass Filter */ /********************************/ SKP_Silk_biquad_alt( in, B_Q28, A_Q28, psEnc->sCmn.In_HP_State, out, psEnc->sCmn.frame_length ); }
/* Helper function, that interpolates the filter taps */ SKP_INLINE void SKP_Silk_LP_interpolate_filter_taps( SKP_int32 B_Q28[ TRANSITION_NB ], SKP_int32 A_Q28[ TRANSITION_NA ], const SKP_int ind, const SKP_int32 fac_Q16 ) { SKP_int nb, na; if( ind < TRANSITION_INT_NUM - 1 ) { if( fac_Q16 > 0 ) { if( fac_Q16 == SKP_SAT16( fac_Q16 ) ) { /* fac_Q16 is in range of a 16-bit int */ /* Piece-wise linear interpolation of B and A */ for( nb = 0; nb < TRANSITION_NB; nb++ ) { B_Q28[ nb ] = SKP_SMLAWB( SKP_Silk_Transition_LP_B_Q28[ ind ][ nb ], SKP_Silk_Transition_LP_B_Q28[ ind + 1 ][ nb ] - SKP_Silk_Transition_LP_B_Q28[ ind ][ nb ], fac_Q16 ); } for( na = 0; na < TRANSITION_NA; na++ ) { A_Q28[ na ] = SKP_SMLAWB( SKP_Silk_Transition_LP_A_Q28[ ind ][ na ], SKP_Silk_Transition_LP_A_Q28[ ind + 1 ][ na ] - SKP_Silk_Transition_LP_A_Q28[ ind ][ na ], fac_Q16 ); } } else if( fac_Q16 == ( 1 << 15 ) ) { /* Neither fac_Q16 nor ( ( 1 << 16 ) - fac_Q16 ) is in range of a 16-bit int */ /* Piece-wise linear interpolation of B and A */ for( nb = 0; nb < TRANSITION_NB; nb++ ) { B_Q28[ nb ] = SKP_RSHIFT( SKP_Silk_Transition_LP_B_Q28[ ind ][ nb ] + SKP_Silk_Transition_LP_B_Q28[ ind + 1 ][ nb ], 1 ); } for( na = 0; na < TRANSITION_NA; na++ ) { A_Q28[ na ] = SKP_RSHIFT( SKP_Silk_Transition_LP_A_Q28[ ind ][ na ] + SKP_Silk_Transition_LP_A_Q28[ ind + 1 ][ na ], 1 ); } } else { /* ( ( 1 << 16 ) - fac_Q16 ) is in range of a 16-bit int */ SKP_assert( ( ( 1 << 16 ) - fac_Q16 ) == SKP_SAT16( ( ( 1 << 16 ) - fac_Q16) ) ); /* Piece-wise linear interpolation of B and A */ for( nb = 0; nb < TRANSITION_NB; nb++ ) { B_Q28[ nb ] = SKP_SMLAWB( SKP_Silk_Transition_LP_B_Q28[ ind + 1 ][ nb ], SKP_Silk_Transition_LP_B_Q28[ ind ][ nb ] - SKP_Silk_Transition_LP_B_Q28[ ind + 1 ][ nb ], ( 1 << 16 ) - fac_Q16 ); } for( na = 0; na < TRANSITION_NA; na++ ) { A_Q28[ na ] = SKP_SMLAWB( SKP_Silk_Transition_LP_A_Q28[ ind + 1 ][ na ], SKP_Silk_Transition_LP_A_Q28[ ind ][ na ] - SKP_Silk_Transition_LP_A_Q28[ ind + 1 ][ na ], ( 1 << 16 ) - fac_Q16 ); } } } else { SKP_memcpy( B_Q28, SKP_Silk_Transition_LP_B_Q28[ ind ], TRANSITION_NB * sizeof( SKP_int32 ) ); SKP_memcpy( A_Q28, SKP_Silk_Transition_LP_A_Q28[ ind ], TRANSITION_NA * sizeof( SKP_int32 ) ); } } else { SKP_memcpy( B_Q28, SKP_Silk_Transition_LP_B_Q28[ TRANSITION_INT_NUM - 1 ], TRANSITION_NB * sizeof( SKP_int32 ) ); SKP_memcpy( A_Q28, SKP_Silk_Transition_LP_A_Q28[ TRANSITION_INT_NUM - 1 ], TRANSITION_NA * sizeof( SKP_int32 ) ); } }
SKP_INLINE void SKP_Silk_LDL_factorize_FIX( SKP_int32 *A, /* I Pointer to Symetric Square Matrix */ SKP_int M, /* I Size of Matrix */ SKP_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 */ ) { SKP_int i, j, k, status, loop_count; const SKP_int32 *ptr1, *ptr2; SKP_int32 diag_min_value, tmp_32, err; SKP_int32 v_Q0[ MAX_MATRIX_SIZE ], D_Q0[ MAX_MATRIX_SIZE ]; SKP_int32 one_div_diag_Q36, one_div_diag_Q40, one_div_diag_Q48; SKP_assert( M <= MAX_MATRIX_SIZE ); status = 1; diag_min_value = SKP_max_32( SKP_SMMUL( SKP_ADD_SAT32( A[ 0 ], A[ SKP_SMULBB( M, M ) - 1 ] ), SKP_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 ] = SKP_SMULWW( D_Q0[ i ], ptr1[ i ] ); /* Q0 */ tmp_32 = SKP_SMLAWW( tmp_32, v_Q0[ i ], ptr1[ i ] ); /* Q0 */ } tmp_32 = SKP_SUB32( matrix_ptr( A, j, j, M ), tmp_32 ); if( tmp_32 < diag_min_value ) { tmp_32 = SKP_SUB32( SKP_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 ) = SKP_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 = SKP_INVERSE32_varQ( tmp_32, 36 ); /* Q36 */ one_div_diag_Q40 = SKP_LSHIFT( one_div_diag_Q36, 4 ); /* Q40 */ err = SKP_SUB32( 1 << 24, SKP_SMULWW( tmp_32, one_div_diag_Q40 ) ); /* Q24 */ one_div_diag_Q48 = SKP_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 = SKP_SMLAWW( tmp_32, v_Q0[ k ], ptr2[ k ] ); /* Q0 */ } tmp_32 = SKP_SUB32( ptr1[ i ], tmp_32 ); /* always < max(Correlation) */ /* tmp_32 / D_Q0[j] : Divide to Q16 */ matrix_ptr( L_Q16, i, j, M ) = SKP_ADD32( SKP_SMMUL( tmp_32, one_div_diag_Q48 ), SKP_RSHIFT( SKP_SMULWW( tmp_32, one_div_diag_Q36 ), 4 ) ); /* go to next column */ ptr2 += M; } } } SKP_assert( status == 0 ); }
void SKP_Silk_noise_shape_analysis_FIX( SKP_Silk_encoder_state_FIX *psEnc, /* I/O Encoder state FIX */ SKP_Silk_encoder_control_FIX *psEncCtrl, /* I/O Encoder control FIX */ const SKP_int16 *pitch_res, /* I LPC residual from pitch analysis */ const SKP_int16 *x /* I Input signal [ frame_length + la_shape ] */ ) { SKP_Silk_shape_state_FIX *psShapeSt = &psEnc->sShape; SKP_int k, i, nSamples, Qnrg, b_Q14, warping_Q16, scale = 0; SKP_int32 SNR_adj_dB_Q7, HarmBoost_Q16, HarmShapeGain_Q16, Tilt_Q16, tmp32; SKP_int32 nrg, pre_nrg_Q30, log_energy_Q7, log_energy_prev_Q7, energy_variation_Q7; SKP_int32 delta_Q16, BWExp1_Q16, BWExp2_Q16, gain_mult_Q16, gain_add_Q16, strength_Q16, b_Q8; SKP_int32 auto_corr[ MAX_SHAPE_LPC_ORDER + 1 ]; SKP_int32 refl_coef_Q16[ MAX_SHAPE_LPC_ORDER ]; SKP_int32 AR1_Q24[ MAX_SHAPE_LPC_ORDER ]; SKP_int32 AR2_Q24[ MAX_SHAPE_LPC_ORDER ]; SKP_int16 x_windowed[ SHAPE_LPC_WIN_MAX ]; const SKP_int16 *x_ptr, *pitch_res_ptr; SKP_int32 sqrt_nrg[ NB_SUBFR ], Qnrg_vec[ NB_SUBFR ]; /* Point to start of first LPC analysis block */ x_ptr = x - psEnc->sCmn.la_shape; /****************/ /* CONTROL SNR */ /****************/ /* Reduce SNR_dB values if recent bitstream has exceeded TargetRate */ psEncCtrl->current_SNR_dB_Q7 = psEnc->SNR_dB_Q7 - SKP_SMULWB( SKP_LSHIFT( ( SKP_int32 )psEnc->BufferedInChannel_ms, 7 ), SKP_FIX_CONST( 0.05, 16 ) ); /* Reduce SNR_dB if inband FEC used */ if( psEnc->speech_activity_Q8 > SKP_FIX_CONST( LBRR_SPEECH_ACTIVITY_THRES, 8 ) ) { psEncCtrl->current_SNR_dB_Q7 -= SKP_RSHIFT( psEnc->inBandFEC_SNR_comp_Q8, 1 ); } /****************/ /* GAIN CONTROL */ /****************/ /* Input quality is the average of the quality in the lowest two VAD bands */ psEncCtrl->input_quality_Q14 = ( SKP_int )SKP_RSHIFT( ( SKP_int32 )psEncCtrl->input_quality_bands_Q15[ 0 ] + psEncCtrl->input_quality_bands_Q15[ 1 ], 2 ); /* Coding quality level, between 0.0_Q0 and 1.0_Q0, but in Q14 */ psEncCtrl->coding_quality_Q14 = SKP_RSHIFT( SKP_Silk_sigm_Q15( SKP_RSHIFT_ROUND( psEncCtrl->current_SNR_dB_Q7 - SKP_FIX_CONST( 18.0, 7 ), 4 ) ), 1 ); /* Reduce coding SNR during low speech activity */ b_Q8 = SKP_FIX_CONST( 1.0, 8 ) - psEnc->speech_activity_Q8; b_Q8 = SKP_SMULWB( SKP_LSHIFT( b_Q8, 8 ), b_Q8 ); SNR_adj_dB_Q7 = SKP_SMLAWB( psEncCtrl->current_SNR_dB_Q7, SKP_SMULBB( SKP_FIX_CONST( -BG_SNR_DECR_dB, 7 ) >> ( 4 + 1 ), b_Q8 ), // Q11 SKP_SMULWB( SKP_FIX_CONST( 1.0, 14 ) + psEncCtrl->input_quality_Q14, psEncCtrl->coding_quality_Q14 ) ); // Q12 if( psEncCtrl->sCmn.sigtype == SIG_TYPE_VOICED ) { /* Reduce gains for periodic signals */ SNR_adj_dB_Q7 = SKP_SMLAWB( SNR_adj_dB_Q7, SKP_FIX_CONST( HARM_SNR_INCR_dB, 8 ), psEnc->LTPCorr_Q15 ); } else { /* For unvoiced signals and low-quality input, adjust the quality slower than SNR_dB setting */ SNR_adj_dB_Q7 = SKP_SMLAWB( SNR_adj_dB_Q7, SKP_SMLAWB( SKP_FIX_CONST( 6.0, 9 ), -SKP_FIX_CONST( 0.4, 18 ), psEncCtrl->current_SNR_dB_Q7 ), SKP_FIX_CONST( 1.0, 14 ) - psEncCtrl->input_quality_Q14 ); } /*************************/ /* SPARSENESS PROCESSING */ /*************************/ /* Set quantizer offset */ if( psEncCtrl->sCmn.sigtype == SIG_TYPE_VOICED ) { /* Initally set to 0; may be overruled in process_gains(..) */ psEncCtrl->sCmn.QuantOffsetType = 0; psEncCtrl->sparseness_Q8 = 0; } else { /* Sparseness measure, based on relative fluctuations of energy per 2 milliseconds */ nSamples = SKP_LSHIFT( psEnc->sCmn.fs_kHz, 1 ); energy_variation_Q7 = 0; log_energy_prev_Q7 = 0; pitch_res_ptr = pitch_res; for( k = 0; k < FRAME_LENGTH_MS / 2; k++ ) { SKP_Silk_sum_sqr_shift( &nrg, &scale, pitch_res_ptr, nSamples ); nrg += SKP_RSHIFT( nSamples, scale ); // Q(-scale) log_energy_Q7 = SKP_Silk_lin2log( nrg ); if( k > 0 ) { energy_variation_Q7 += SKP_abs( log_energy_Q7 - log_energy_prev_Q7 ); } log_energy_prev_Q7 = log_energy_Q7; pitch_res_ptr += nSamples; } psEncCtrl->sparseness_Q8 = SKP_RSHIFT( SKP_Silk_sigm_Q15( SKP_SMULWB( energy_variation_Q7 - SKP_FIX_CONST( 5.0, 7 ), SKP_FIX_CONST( 0.1, 16 ) ) ), 7 ); /* Set quantization offset depending on sparseness measure */ if( psEncCtrl->sparseness_Q8 > SKP_FIX_CONST( SPARSENESS_THRESHOLD_QNT_OFFSET, 8 ) ) { psEncCtrl->sCmn.QuantOffsetType = 0; } else { psEncCtrl->sCmn.QuantOffsetType = 1; } /* Increase coding SNR for sparse signals */ SNR_adj_dB_Q7 = SKP_SMLAWB( SNR_adj_dB_Q7, SKP_FIX_CONST( SPARSE_SNR_INCR_dB, 15 ), psEncCtrl->sparseness_Q8 - SKP_FIX_CONST( 0.5, 8 ) ); } /*******************************/ /* Control bandwidth expansion */ /*******************************/ /* More BWE for signals with high prediction gain */ strength_Q16 = SKP_SMULWB( psEncCtrl->predGain_Q16, SKP_FIX_CONST( FIND_PITCH_WHITE_NOISE_FRACTION, 16 ) ); BWExp1_Q16 = BWExp2_Q16 = SKP_DIV32_varQ( SKP_FIX_CONST( BANDWIDTH_EXPANSION, 16 ), SKP_SMLAWW( SKP_FIX_CONST( 1.0, 16 ), strength_Q16, strength_Q16 ), 16 ); delta_Q16 = SKP_SMULWB( SKP_FIX_CONST( 1.0, 16 ) - SKP_SMULBB( 3, psEncCtrl->coding_quality_Q14 ), SKP_FIX_CONST( LOW_RATE_BANDWIDTH_EXPANSION_DELTA, 16 ) ); BWExp1_Q16 = SKP_SUB32( BWExp1_Q16, delta_Q16 ); BWExp2_Q16 = SKP_ADD32( BWExp2_Q16, delta_Q16 ); /* BWExp1 will be applied after BWExp2, so make it relative */ BWExp1_Q16 = SKP_DIV32_16( SKP_LSHIFT( BWExp1_Q16, 14 ), SKP_RSHIFT( BWExp2_Q16, 2 ) ); if( psEnc->sCmn.warping_Q16 > 0 ) { /* Slightly more warping in analysis will move quantization noise up in frequency, where it's better masked */ warping_Q16 = SKP_SMLAWB( psEnc->sCmn.warping_Q16, psEncCtrl->coding_quality_Q14, SKP_FIX_CONST( 0.01, 18 ) ); } else { warping_Q16 = 0; } /********************************************/ /* Compute noise shaping AR coefs and gains */ /********************************************/ for( k = 0; k < NB_SUBFR; k++ ) { /* Apply window: sine slope followed by flat part followed by cosine slope */ SKP_int shift, slope_part, flat_part; flat_part = psEnc->sCmn.fs_kHz * 5; slope_part = SKP_RSHIFT( psEnc->sCmn.shapeWinLength - flat_part, 1 ); SKP_Silk_apply_sine_window_new( x_windowed, x_ptr, 1, slope_part ); shift = slope_part; SKP_memcpy( x_windowed + shift, x_ptr + shift, flat_part * sizeof(SKP_int16) ); shift += flat_part; SKP_Silk_apply_sine_window_new( x_windowed + shift, x_ptr + shift, 2, slope_part ); /* Update pointer: next LPC analysis block */ x_ptr += psEnc->sCmn.subfr_length; if( psEnc->sCmn.warping_Q16 > 0 ) { /* Calculate warped auto correlation */ SKP_Silk_warped_autocorrelation_FIX( auto_corr, &scale, x_windowed, warping_Q16, psEnc->sCmn.shapeWinLength, psEnc->sCmn.shapingLPCOrder ); } else { /* Calculate regular auto correlation */ SKP_Silk_autocorr( auto_corr, &scale, x_windowed, psEnc->sCmn.shapeWinLength, psEnc->sCmn.shapingLPCOrder + 1 ); } /* Add white noise, as a fraction of energy */ auto_corr[0] = SKP_ADD32( auto_corr[0], SKP_max_32( SKP_SMULWB( SKP_RSHIFT( auto_corr[ 0 ], 4 ), SKP_FIX_CONST( SHAPE_WHITE_NOISE_FRACTION, 20 ) ), 1 ) ); /* Calculate the reflection coefficients using schur */ nrg = SKP_Silk_schur64( refl_coef_Q16, auto_corr, psEnc->sCmn.shapingLPCOrder ); SKP_assert( nrg >= 0 ); /* Convert reflection coefficients to prediction coefficients */ SKP_Silk_k2a_Q16( AR2_Q24, refl_coef_Q16, psEnc->sCmn.shapingLPCOrder ); Qnrg = -scale; // range: -12...30 SKP_assert( Qnrg >= -12 ); SKP_assert( Qnrg <= 30 ); /* Make sure that Qnrg is an even number */ if( Qnrg & 1 ) { Qnrg -= 1; nrg >>= 1; } tmp32 = SKP_Silk_SQRT_APPROX( nrg ); Qnrg >>= 1; // range: -6...15 sqrt_nrg[ k ] = tmp32; Qnrg_vec[ k ] = Qnrg; psEncCtrl->Gains_Q16[ k ] = SKP_LSHIFT_SAT32( tmp32, 16 - Qnrg ); if( psEnc->sCmn.warping_Q16 > 0 ) { /* Adjust gain for warping */ gain_mult_Q16 = warped_gain( AR2_Q24, warping_Q16, psEnc->sCmn.shapingLPCOrder ); SKP_assert( psEncCtrl->Gains_Q16[ k ] >= 0 ); psEncCtrl->Gains_Q16[ k ] = SKP_SMULWW( psEncCtrl->Gains_Q16[ k ], gain_mult_Q16 ); if( psEncCtrl->Gains_Q16[ k ] < 0 ) { psEncCtrl->Gains_Q16[ k ] = SKP_int32_MAX; } } /* Bandwidth expansion for synthesis filter shaping */ SKP_Silk_bwexpander_32( AR2_Q24, psEnc->sCmn.shapingLPCOrder, BWExp2_Q16 ); /* Compute noise shaping filter coefficients */ SKP_memcpy( AR1_Q24, AR2_Q24, psEnc->sCmn.shapingLPCOrder * sizeof( SKP_int32 ) ); /* Bandwidth expansion for analysis filter shaping */ SKP_assert( BWExp1_Q16 <= SKP_FIX_CONST( 1.0, 16 ) ); SKP_Silk_bwexpander_32( AR1_Q24, psEnc->sCmn.shapingLPCOrder, BWExp1_Q16 ); /* Ratio of prediction gains, in energy domain */ SKP_Silk_LPC_inverse_pred_gain_Q24( &pre_nrg_Q30, AR2_Q24, psEnc->sCmn.shapingLPCOrder ); SKP_Silk_LPC_inverse_pred_gain_Q24( &nrg, AR1_Q24, psEnc->sCmn.shapingLPCOrder ); //psEncCtrl->GainsPre[ k ] = 1.0f - 0.7f * ( 1.0f - pre_nrg / nrg ) = 0.3f + 0.7f * pre_nrg / nrg; pre_nrg_Q30 = SKP_LSHIFT32( SKP_SMULWB( pre_nrg_Q30, SKP_FIX_CONST( 0.7, 15 ) ), 1 ); psEncCtrl->GainsPre_Q14[ k ] = ( SKP_int ) SKP_FIX_CONST( 0.3, 14 ) + SKP_DIV32_varQ( pre_nrg_Q30, nrg, 14 ); /* Convert to monic warped prediction coefficients and limit absolute values */ limit_warped_coefs( AR2_Q24, AR1_Q24, warping_Q16, SKP_FIX_CONST( 3.999, 24 ), psEnc->sCmn.shapingLPCOrder ); /* Convert from Q24 to Q13 and store in int16 */ for( i = 0; i < psEnc->sCmn.shapingLPCOrder; i++ ) { psEncCtrl->AR1_Q13[ k * MAX_SHAPE_LPC_ORDER + i ] = (SKP_int16)SKP_SAT16( SKP_RSHIFT_ROUND( AR1_Q24[ i ], 11 ) ); psEncCtrl->AR2_Q13[ k * MAX_SHAPE_LPC_ORDER + i ] = (SKP_int16)SKP_SAT16( SKP_RSHIFT_ROUND( AR2_Q24[ i ], 11 ) ); } }
void SKP_Silk_noise_shape_analysis_FIX( SKP_Silk_encoder_state_FIX *psEnc, /* I/O Encoder state FIX */ SKP_Silk_encoder_control_FIX *psEncCtrl, /* I/O Encoder control FIX */ const SKP_int16 *pitch_res, /* I LPC residual from pitch analysis */ const SKP_int16 *x /* I Input signal [ 2 * frame_length + la_shape ]*/ ) { SKP_Silk_shape_state_FIX *psShapeSt = &psEnc->sShape; SKP_int k, nSamples, lz, Qnrg, b_Q14, scale = 0, sz; SKP_int32 SNR_adj_dB_Q7, HarmBoost_Q16, HarmShapeGain_Q16, Tilt_Q16, tmp32; SKP_int32 nrg, pre_nrg_Q30, log_energy_Q7, log_energy_prev_Q7, energy_variation_Q7; SKP_int32 delta_Q16, BWExp1_Q16, BWExp2_Q16, gain_mult_Q16, gain_add_Q16, strength_Q16, b_Q8; SKP_int32 auto_corr[ SHAPE_LPC_ORDER_MAX + 1 ]; SKP_int32 refl_coef_Q16[ SHAPE_LPC_ORDER_MAX ]; SKP_int32 AR_Q24[ SHAPE_LPC_ORDER_MAX ]; SKP_int16 x_windowed[ SHAPE_LPC_WIN_MAX ]; const SKP_int16 *x_ptr, *pitch_res_ptr; SKP_int32 sqrt_nrg[ NB_SUBFR ], Qnrg_vec[ NB_SUBFR ]; /* Point to start of first LPC analysis block */ x_ptr = x + psEnc->sCmn.la_shape - SKP_SMULBB( SHAPE_LPC_WIN_MS, psEnc->sCmn.fs_kHz ) + psEnc->sCmn.frame_length / NB_SUBFR; /****************/ /* CONTROL SNR */ /****************/ /* Reduce SNR_dB values if recent bitstream has exceeded TargetRate */ psEncCtrl->current_SNR_dB_Q7 = psEnc->SNR_dB_Q7 - SKP_SMULWB( SKP_LSHIFT( ( SKP_int32 )psEnc->BufferedInChannel_ms, 7 ), 3277 ); /* Reduce SNR_dB if inband FEC used */ if( psEnc->speech_activity_Q8 > LBRR_SPEECH_ACTIVITY_THRES_Q8 ) { psEncCtrl->current_SNR_dB_Q7 -= SKP_RSHIFT( psEnc->inBandFEC_SNR_comp_Q8, 1 ); } /****************/ /* GAIN CONTROL */ /****************/ /* Input quality is the average of the quality in the lowest two VAD bands */ psEncCtrl->input_quality_Q14 = ( SKP_int )SKP_RSHIFT( ( SKP_int32 )psEncCtrl->input_quality_bands_Q15[ 0 ] + psEncCtrl->input_quality_bands_Q15[ 1 ], 2 ); /* Coding quality level, between 0.0_Q0 and 1.0_Q0, but in Q14 */ psEncCtrl->coding_quality_Q14 = SKP_RSHIFT( SKP_Silk_sigm_Q15( SKP_RSHIFT_ROUND( psEncCtrl->current_SNR_dB_Q7 - ( 18 << 7 ), 4 ) ), 1 ); /* Reduce coding SNR during low speech activity */ b_Q8 = ( 1 << 8 ) - psEnc->speech_activity_Q8; b_Q8 = SKP_SMULWB( SKP_LSHIFT( b_Q8, 8 ), b_Q8 ); SNR_adj_dB_Q7 = SKP_SMLAWB( psEncCtrl->current_SNR_dB_Q7, SKP_SMULBB( -BG_SNR_DECR_dB_Q7 >> ( 4 + 1 ), b_Q8 ), // Q11 SKP_SMULWB( ( 1 << 14 ) + psEncCtrl->input_quality_Q14, psEncCtrl->coding_quality_Q14 ) ); // Q12 if( psEncCtrl->sCmn.sigtype == SIG_TYPE_VOICED ) { /* Reduce gains for periodic signals */ SNR_adj_dB_Q7 = SKP_SMLAWB( SNR_adj_dB_Q7, HARM_SNR_INCR_dB_Q7 << 1, psEnc->LTPCorr_Q15 ); } else { /* For unvoiced signals and low-quality input, adjust the quality slower than SNR_dB setting */ SNR_adj_dB_Q7 = SKP_SMLAWB( SNR_adj_dB_Q7, SKP_SMLAWB( 6 << ( 7 + 2 ), -104856, psEncCtrl->current_SNR_dB_Q7 ), //-104856_Q18 = -0.4_Q0, Q9 ( 1 << 14 ) - psEncCtrl->input_quality_Q14 ); // Q14 } /*************************/ /* SPARSENESS PROCESSING */ /*************************/ /* Set quantizer offset */ if( psEncCtrl->sCmn.sigtype == SIG_TYPE_VOICED ) { /* Initally set to 0; may be overruled in process_gains(..) */ psEncCtrl->sCmn.QuantOffsetType = 0; psEncCtrl->sparseness_Q8 = 0; } else { /* Sparseness measure, based on relative fluctuations of energy per 2 milliseconds */ nSamples = SKP_LSHIFT( psEnc->sCmn.fs_kHz, 1 ); energy_variation_Q7 = 0; log_energy_prev_Q7 = 0; pitch_res_ptr = pitch_res; for( k = 0; k < FRAME_LENGTH_MS / 2; k++ ) { SKP_Silk_sum_sqr_shift( &nrg, &scale, pitch_res_ptr, nSamples ); nrg += SKP_RSHIFT( nSamples, scale ); // Q(-scale) log_energy_Q7 = SKP_Silk_lin2log( nrg ); if( k > 0 ) { energy_variation_Q7 += SKP_abs( log_energy_Q7 - log_energy_prev_Q7 ); } log_energy_prev_Q7 = log_energy_Q7; pitch_res_ptr += nSamples; } psEncCtrl->sparseness_Q8 = SKP_RSHIFT( SKP_Silk_sigm_Q15( SKP_SMULWB( energy_variation_Q7 - ( 5 << 7 ), 6554 ) ), 7 ); // 6554_Q16 = 0.1_Q0 /* Set quantization offset depending on sparseness measure */ if( psEncCtrl->sparseness_Q8 > SPARSENESS_THRESHOLD_QNT_OFFSET_Q8 ) { psEncCtrl->sCmn.QuantOffsetType = 0; } else { psEncCtrl->sCmn.QuantOffsetType = 1; } /* Increase coding SNR for sparse signals */ SNR_adj_dB_Q7 = SKP_SMLAWB( SNR_adj_dB_Q7, SPARSE_SNR_INCR_dB_Q7 << 8, psEncCtrl->sparseness_Q8 - ( 1 << 7 ) ); } /*******************************/ /* Control bandwidth expansion */ /*******************************/ delta_Q16 = SKP_SMULWB( ( 1 << 16 ) - SKP_SMULBB( 3, psEncCtrl->coding_quality_Q14 ), LOW_RATE_BANDWIDTH_EXPANSION_DELTA_Q16 ); BWExp1_Q16 = BANDWIDTH_EXPANSION_Q16 - delta_Q16; BWExp2_Q16 = BANDWIDTH_EXPANSION_Q16 + delta_Q16; if( psEnc->sCmn.fs_kHz == 24 ) { /* Less bandwidth expansion for super wideband */ BWExp1_Q16 = ( 1 << 16 ) - SKP_SMULWB( SWB_BANDWIDTH_EXPANSION_REDUCTION_Q16, ( 1 << 16 ) - BWExp1_Q16 ); BWExp2_Q16 = ( 1 << 16 ) - SKP_SMULWB( SWB_BANDWIDTH_EXPANSION_REDUCTION_Q16, ( 1 << 16 ) - BWExp2_Q16 ); } /* BWExp1 will be applied after BWExp2, so make it relative */ BWExp1_Q16 = SKP_DIV32_16( SKP_LSHIFT( BWExp1_Q16, 14 ), SKP_RSHIFT( BWExp2_Q16, 2 ) ); /********************************************/ /* Compute noise shaping AR coefs and gains */ /********************************************/ sz = ( SKP_int )SKP_SMULBB( SHAPE_LPC_WIN_MS, psEnc->sCmn.fs_kHz ); for( k = 0; k < NB_SUBFR; k++ ) { /* Apply window */ SKP_Silk_apply_sine_window( x_windowed, x_ptr, 0, SHAPE_LPC_WIN_MS * psEnc->sCmn.fs_kHz ); /* Update pointer: next LPC analysis block */ x_ptr += psEnc->sCmn.frame_length / NB_SUBFR; /* Calculate auto correlation */ SKP_Silk_autocorr( auto_corr, &scale, x_windowed, sz, psEnc->sCmn.shapingLPCOrder + 1 ); /* Add white noise, as a fraction of energy */ auto_corr[0] = SKP_ADD32( auto_corr[0], SKP_max_32( SKP_SMULWB( SKP_RSHIFT( auto_corr[ 0 ], 4 ), SHAPE_WHITE_NOISE_FRACTION_Q20 ), 1 ) ); /* Calculate the reflection coefficients using schur */ nrg = SKP_Silk_schur64( refl_coef_Q16, auto_corr, psEnc->sCmn.shapingLPCOrder ); /* Convert reflection coefficients to prediction coefficients */ SKP_Silk_k2a_Q16( AR_Q24, refl_coef_Q16, psEnc->sCmn.shapingLPCOrder ); /* Bandwidth expansion for synthesis filter shaping */ SKP_Silk_bwexpander_32( AR_Q24, psEnc->sCmn.shapingLPCOrder, BWExp2_Q16 ); /* Make sure to fit in Q13 SKP_int16 */ SKP_Silk_LPC_fit( &psEncCtrl->AR2_Q13[ k * SHAPE_LPC_ORDER_MAX ], AR_Q24, 13, psEnc->sCmn.shapingLPCOrder ); /* Compute noise shaping filter coefficients */ SKP_memcpy( &psEncCtrl->AR1_Q13[ k * SHAPE_LPC_ORDER_MAX ], &psEncCtrl->AR2_Q13[ k * SHAPE_LPC_ORDER_MAX ], psEnc->sCmn.shapingLPCOrder * sizeof( SKP_int16 ) ); /* Bandwidth expansion for analysis filter shaping */ SKP_assert( BWExp1_Q16 <= ( 1 << 16 ) ); // If ever breaking, use LPC_stabilize() in these cases to stay within range SKP_Silk_bwexpander( &psEncCtrl->AR1_Q13[ k * SHAPE_LPC_ORDER_MAX ], psEnc->sCmn.shapingLPCOrder, BWExp1_Q16 ); /* Increase residual energy */ nrg = SKP_SMLAWB( nrg, SKP_RSHIFT( auto_corr[ 0 ], 8 ), SHAPE_MIN_ENERGY_RATIO_Q24 ); Qnrg = -scale; // range: -12...30 SKP_assert( Qnrg >= -12 ); SKP_assert( Qnrg <= 30 ); /* Make sure that Qnrg is an even number */ if( Qnrg & 1 ) { Qnrg -= 1; nrg >>= 1; } tmp32 = SKP_Silk_SQRT_APPROX( nrg ); Qnrg >>= 1; // range: -6...15 sqrt_nrg[ k ] = tmp32; Qnrg_vec[ k ] = Qnrg; psEncCtrl->Gains_Q16[ k ] = SKP_LSHIFT_SAT32( tmp32, 16 - Qnrg ); /* Ratio of prediction gains, in energy domain */ SKP_Silk_LPC_inverse_pred_gain_Q13( &pre_nrg_Q30, &psEncCtrl->AR2_Q13[ k * SHAPE_LPC_ORDER_MAX ], psEnc->sCmn.shapingLPCOrder ); SKP_Silk_LPC_inverse_pred_gain_Q13( &nrg, &psEncCtrl->AR1_Q13[ k * SHAPE_LPC_ORDER_MAX ], psEnc->sCmn.shapingLPCOrder ); lz = SKP_min_32( SKP_Silk_CLZ32( pre_nrg_Q30 ) - 1, 19 ); pre_nrg_Q30 = SKP_DIV32( SKP_LSHIFT( pre_nrg_Q30, lz ), SKP_RSHIFT( nrg, 20 - lz ) + 1 ); // Q20 pre_nrg_Q30 = SKP_RSHIFT( SKP_LSHIFT_SAT32( pre_nrg_Q30, 9 ), 1 ); /* Q28 */ psEncCtrl->GainsPre_Q14[ k ] = ( SKP_int )SKP_Silk_SQRT_APPROX( pre_nrg_Q30 ); }
/* Encode quantization indices of excitation */ void SKP_Silk_encode_pulses( SKP_Silk_range_coder_state *psRC, /* I/O Range coder state */ const SKP_int sigtype, /* I Sigtype */ const SKP_int QuantOffsetType,/* I QuantOffsetType */ const SKP_int8 q[], /* I quantization indices */ const SKP_int frame_length /* I Frame length */ ) { SKP_int i, k, j, iter, bit, nLS, scale_down, RateLevelIndex = 0; SKP_int32 abs_q, minSumBits_Q6, sumBits_Q6; SKP_int abs_pulses[ MAX_FRAME_LENGTH ]; SKP_int sum_pulses[ MAX_NB_SHELL_BLOCKS ]; SKP_int nRshifts[ MAX_NB_SHELL_BLOCKS ]; SKP_int pulses_comb[ 8 ]; SKP_int *abs_pulses_ptr; const SKP_int8 *pulses_ptr; const SKP_uint16 *cdf_ptr; const SKP_int16 *nBits_ptr; SKP_memset( pulses_comb, 0, 8 * sizeof( SKP_int ) ); // Fixing Valgrind reported problem /****************************/ /* Prepare for shell coding */ /****************************/ /* Calculate number of shell blocks */ iter = frame_length / SHELL_CODEC_FRAME_LENGTH; /* Take the absolute value of the pulses */ for( i = 0; i < frame_length; i+=4 ) { abs_pulses[i+0] = ( SKP_int )SKP_abs( q[ i + 0 ] ); abs_pulses[i+1] = ( SKP_int )SKP_abs( q[ i + 1 ] ); abs_pulses[i+2] = ( SKP_int )SKP_abs( q[ i + 2 ] ); abs_pulses[i+3] = ( SKP_int )SKP_abs( q[ i + 3 ] ); } /* Calc sum pulses per shell code frame */ abs_pulses_ptr = abs_pulses; for( i = 0; i < iter; i++ ) { nRshifts[ i ] = 0; while( 1 ) { /* 1+1 -> 2 */ scale_down = combine_and_check( pulses_comb, abs_pulses_ptr, SKP_Silk_max_pulses_table[ 0 ], 8 ); /* 2+2 -> 4 */ scale_down += combine_and_check( pulses_comb, pulses_comb, SKP_Silk_max_pulses_table[ 1 ], 4 ); /* 4+4 -> 8 */ scale_down += combine_and_check( pulses_comb, pulses_comb, SKP_Silk_max_pulses_table[ 2 ], 2 ); /* 8+8 -> 16 */ sum_pulses[ i ] = pulses_comb[ 0 ] + pulses_comb[ 1 ]; if( sum_pulses[ i ] > SKP_Silk_max_pulses_table[ 3 ] ) { scale_down++; } if( scale_down ) { /* We need to down scale the quantization signal */ nRshifts[ i ]++; for( k = 0; k < SHELL_CODEC_FRAME_LENGTH; k++ ) { abs_pulses_ptr[ k ] = SKP_RSHIFT( abs_pulses_ptr[ k ], 1 ); } } else { /* Jump out of while(1) loop and go to next shell coding frame */ break; } } abs_pulses_ptr += SHELL_CODEC_FRAME_LENGTH; } /**************/ /* Rate level */ /**************/ /* find rate level that leads to fewest bits for coding of pulses per block info */ minSumBits_Q6 = SKP_int32_MAX; for( k = 0; k < N_RATE_LEVELS - 1; k++ ) { nBits_ptr = SKP_Silk_pulses_per_block_BITS_Q6[ k ]; sumBits_Q6 = SKP_Silk_rate_levels_BITS_Q6[sigtype][ k ]; for( i = 0; i < iter; i++ ) { if( nRshifts[ i ] > 0 ) { sumBits_Q6 += nBits_ptr[ MAX_PULSES + 1 ]; } else { sumBits_Q6 += nBits_ptr[ sum_pulses[ i ] ]; } } if( sumBits_Q6 < minSumBits_Q6 ) { minSumBits_Q6 = sumBits_Q6; RateLevelIndex = k; } } SKP_Silk_range_encoder( psRC, RateLevelIndex, SKP_Silk_rate_levels_CDF[ sigtype ] ); /***************************************************/ /* Sum-Weighted-Pulses Encoding */ /***************************************************/ cdf_ptr = SKP_Silk_pulses_per_block_CDF[ RateLevelIndex ]; for( i = 0; i < iter; i++ ) { if( nRshifts[ i ] == 0 ) { SKP_Silk_range_encoder( psRC, sum_pulses[ i ], cdf_ptr ); } else { SKP_Silk_range_encoder( psRC, MAX_PULSES + 1, cdf_ptr ); for( k = 0; k < nRshifts[ i ] - 1; k++ ) { SKP_Silk_range_encoder( psRC, MAX_PULSES + 1, SKP_Silk_pulses_per_block_CDF[ N_RATE_LEVELS - 1 ] ); } SKP_Silk_range_encoder( psRC, sum_pulses[ i ], SKP_Silk_pulses_per_block_CDF[ N_RATE_LEVELS - 1 ] ); } } /******************/ /* Shell Encoding */ /******************/ for( i = 0; i < iter; i++ ) { if( sum_pulses[ i ] > 0 ) { SKP_Silk_shell_encoder( psRC, &abs_pulses[ i * SHELL_CODEC_FRAME_LENGTH ] ); } } /****************/ /* LSB Encoding */ /****************/ for( i = 0; i < iter; i++ ) { if( nRshifts[ i ] > 0 ) { pulses_ptr = &q[ i * SHELL_CODEC_FRAME_LENGTH ]; nLS = nRshifts[ i ] - 1; for( k = 0; k < SHELL_CODEC_FRAME_LENGTH; k++ ) { abs_q = (SKP_int8)SKP_abs( pulses_ptr[ k ] ); for( j = nLS; j > 0; j-- ) { bit = SKP_RSHIFT( abs_q, j ) & 1; SKP_Silk_range_encoder( psRC, bit, SKP_Silk_lsb_CDF ); } bit = abs_q & 1; SKP_Silk_range_encoder( psRC, bit, SKP_Silk_lsb_CDF ); } } } /****************/ /* Encode signs */ /****************/ SKP_Silk_encode_signs( psRC, q, frame_length, sigtype, QuantOffsetType, RateLevelIndex ); }
void SKP_Silk_prefilter_FIX( SKP_Silk_encoder_state_FIX *psEnc, /* I/O Encoder state FIX */ const SKP_Silk_encoder_control_FIX *psEncCtrl, /* I Encoder control FIX */ SKP_int16 xw[], /* O Weighted signal */ const SKP_int16 x[] /* I Speech signal */ ) { SKP_Silk_prefilter_state_FIX *P = &psEnc->sPrefilt; SKP_int j, k, lag; SKP_int32 tmp_32; const SKP_int16 *AR1_shp_Q13; const SKP_int16 *px; SKP_int16 *pxw; SKP_int HarmShapeGain_Q12, Tilt_Q14; SKP_int32 HarmShapeFIRPacked_Q12, LF_shp_Q14; SKP_int32 x_filt_Q12[ MAX_FRAME_LENGTH / NB_SUBFR ]; SKP_int16 st_res[ ( MAX_FRAME_LENGTH / NB_SUBFR ) + MAX_SHAPE_LPC_ORDER ]; SKP_int16 B_Q12[ 2 ]; /* Setup pointers */ px = x; pxw = xw; lag = P->lagPrev; for( k = 0; k < NB_SUBFR; k++ ) { /* Update Variables that change per sub frame */ if( psEncCtrl->sCmn.sigtype == SIG_TYPE_VOICED ) { lag = psEncCtrl->sCmn.pitchL[ k ]; } /* Noise shape parameters */ HarmShapeGain_Q12 = SKP_SMULWB( psEncCtrl->HarmShapeGain_Q14[ k ], 16384 - psEncCtrl->HarmBoost_Q14[ k ] ); SKP_assert( HarmShapeGain_Q12 >= 0 ); HarmShapeFIRPacked_Q12 = SKP_RSHIFT( HarmShapeGain_Q12, 2 ); HarmShapeFIRPacked_Q12 |= SKP_LSHIFT( ( SKP_int32 )SKP_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*/ SKP_Silk_warped_LPC_analysis_filter_FIX( P->sAR_shp, st_res, AR1_shp_Q13, px, psEnc->sCmn.warping_Q16, psEnc->sCmn.subfr_length, psEnc->sCmn.shapingLPCOrder ); /* reduce (mainly) low frequencies during harmonic emphasis */ B_Q12[ 0 ] = SKP_RSHIFT_ROUND( psEncCtrl->GainsPre_Q14[ k ], 2 ); tmp_32 = SKP_SMLABB( SKP_FIX_CONST( INPUT_TILT, 26 ), psEncCtrl->HarmBoost_Q14[ k ], HarmShapeGain_Q12 ); /* Q26 */ tmp_32 = SKP_SMLABB( tmp_32, psEncCtrl->coding_quality_Q14, SKP_FIX_CONST( HIGH_RATE_INPUT_TILT, 12 ) ); /* Q26 */ tmp_32 = SKP_SMULWB( tmp_32, -psEncCtrl->GainsPre_Q14[ k ] ); /* Q24 */ tmp_32 = SKP_RSHIFT_ROUND( tmp_32, 12 ); /* Q12 */ B_Q12[ 1 ]= SKP_SAT16( tmp_32 ); x_filt_Q12[ 0 ] = SKP_SMLABB( SKP_SMULBB( st_res[ 0 ], B_Q12[ 0 ] ), P->sHarmHP, B_Q12[ 1 ] ); for( j = 1; j < psEnc->sCmn.subfr_length; j++ ) { x_filt_Q12[ j ] = SKP_SMLABB( SKP_SMULBB( st_res[ j ], B_Q12[ 0 ] ), st_res[ j - 1 ], B_Q12[ 1 ] ); } P->sHarmHP = st_res[ psEnc->sCmn.subfr_length - 1 ]; SKP_Silk_prefilt_FIX( P, x_filt_Q12, pxw, HarmShapeFIRPacked_Q12, Tilt_Q14, LF_shp_Q14, lag, psEnc->sCmn.subfr_length ); px += psEnc->sCmn.subfr_length; pxw += psEnc->sCmn.subfr_length; } P->lagPrev = psEncCtrl->sCmn.pitchL[ NB_SUBFR - 1 ]; }
/* Decode indices from payload */ void SKP_Silk_decode_indices( SKP_Silk_decoder_state *psDec, /* I/O State */ ec_dec *psRangeDec, /* I/O Compressor data structure */ SKP_int FrameIndex, /* I Frame number */ SKP_int decode_LBRR /* I Flag indicating LBRR data is being decoded */ ) { SKP_int i, k, Ix, condCoding; SKP_int decode_absolute_lagIndex, delta_lagIndex; SKP_int16 ec_ix[ MAX_LPC_ORDER ]; SKP_uint8 pred_Q8[ MAX_LPC_ORDER ]; if( FrameIndex > 0 && ( decode_LBRR == 0 || psDec->LBRR_flags[ FrameIndex - 1 ] == 1 ) ) { condCoding = 1; } else { condCoding = 0; } /*******************************************/ /* Decode signal type and quantizer offset */ /*******************************************/ if( decode_LBRR || psDec->VAD_flags[ FrameIndex ] ) { Ix = ec_dec_icdf( psRangeDec, SKP_Silk_type_offset_VAD_iCDF, 8 ) + 2; } else { Ix = ec_dec_icdf( psRangeDec, SKP_Silk_type_offset_no_VAD_iCDF, 8 ); } psDec->indices.signalType = (SKP_int8)SKP_RSHIFT( Ix, 1 ); psDec->indices.quantOffsetType = (SKP_int8)( Ix & 1 ); /****************/ /* Decode gains */ /****************/ /* first subframe */ if( condCoding ) { /* conditional coding */ psDec->indices.GainsIndices[ 0 ] = (SKP_int8)ec_dec_icdf( psRangeDec, SKP_Silk_delta_gain_iCDF, 8 ); } else { /* independent coding, in two stages: MSB bits followed by 3 LSBs */ psDec->indices.GainsIndices[ 0 ] = (SKP_int8)SKP_LSHIFT( ec_dec_icdf( psRangeDec, SKP_Silk_gain_iCDF[ psDec->indices.signalType ], 8 ), 3 ); psDec->indices.GainsIndices[ 0 ] += (SKP_int8)ec_dec_icdf( psRangeDec, SKP_Silk_uniform8_iCDF, 8 ); } /* remaining subframes */ for( i = 1; i < psDec->nb_subfr; i++ ) { psDec->indices.GainsIndices[ i ] = (SKP_int8)ec_dec_icdf( psRangeDec, SKP_Silk_delta_gain_iCDF, 8 ); } /**********************/ /* Decode LSF Indices */ /**********************/ psDec->indices.NLSFIndices[ 0 ] = (SKP_int8)ec_dec_icdf( psRangeDec, &psDec->psNLSF_CB->CB1_iCDF[ ( psDec->indices.signalType >> 1 ) * psDec->psNLSF_CB->nVectors ], 8 ); SKP_Silk_NLSF_unpack( ec_ix, pred_Q8, psDec->psNLSF_CB, psDec->indices.NLSFIndices[ 0 ] ); SKP_assert( psDec->psNLSF_CB->order == psDec->LPC_order ); for( i = 0; i < psDec->psNLSF_CB->order; i++ ) { Ix = ec_dec_icdf( psRangeDec, &psDec->psNLSF_CB->ec_iCDF[ ec_ix[ i ] ], 8 ); if( Ix == 0 ) { Ix -= ec_dec_icdf( psRangeDec, SKP_Silk_NLSF_EXT_iCDF, 8 ); } else if( Ix == 2 * NLSF_QUANT_MAX_AMPLITUDE ) { Ix += ec_dec_icdf( psRangeDec, SKP_Silk_NLSF_EXT_iCDF, 8 ); } psDec->indices.NLSFIndices[ i+1 ] = (SKP_int8)( Ix - NLSF_QUANT_MAX_AMPLITUDE ); } /* Decode LSF interpolation factor */ if( psDec->nb_subfr == MAX_NB_SUBFR ) { psDec->indices.NLSFInterpCoef_Q2 = (SKP_int8)ec_dec_icdf( psRangeDec, SKP_Silk_NLSF_interpolation_factor_iCDF, 8 ); } else { psDec->indices.NLSFInterpCoef_Q2 = 4; } if( psDec->indices.signalType == TYPE_VOICED ) { /*********************/ /* Decode pitch lags */ /*********************/ /* Get lag index */ decode_absolute_lagIndex = 1; if( condCoding && psDec->ec_prevSignalType == TYPE_VOICED ) { /* Decode Delta index */ delta_lagIndex = (SKP_int16)ec_dec_icdf( psRangeDec, SKP_Silk_pitch_delta_iCDF, 8 ); if( delta_lagIndex > 0 ) { delta_lagIndex = delta_lagIndex - 9; psDec->indices.lagIndex = (SKP_int16)( psDec->ec_prevLagIndex + delta_lagIndex ); decode_absolute_lagIndex = 0; } } if( decode_absolute_lagIndex ) { /* Absolute decoding */ psDec->indices.lagIndex = (SKP_int16)ec_dec_icdf( psRangeDec, SKP_Silk_pitch_lag_iCDF, 8 ) * SKP_RSHIFT( psDec->fs_kHz, 1 ); psDec->indices.lagIndex += (SKP_int16)ec_dec_icdf( psRangeDec, psDec->pitch_lag_low_bits_iCDF, 8 ); } psDec->ec_prevLagIndex = psDec->indices.lagIndex; /* Get countour index */ psDec->indices.contourIndex = (SKP_int8)ec_dec_icdf( psRangeDec, psDec->pitch_contour_iCDF, 8 ); /********************/ /* Decode LTP gains */ /********************/ /* Decode PERIndex value */ psDec->indices.PERIndex = (SKP_int8)ec_dec_icdf( psRangeDec, SKP_Silk_LTP_per_index_iCDF, 8 ); for( k = 0; k < psDec->nb_subfr; k++ ) { psDec->indices.LTPIndex[ k ] = (SKP_int8)ec_dec_icdf( psRangeDec, SKP_Silk_LTP_gain_iCDF_ptrs[ psDec->indices.PERIndex ], 8 ); } /**********************/ /* Decode LTP scaling */ /**********************/ if( !condCoding ) { psDec->indices.LTP_scaleIndex = (SKP_int8)ec_dec_icdf( psRangeDec, SKP_Silk_LTPscale_iCDF, 8 ); } else { psDec->indices.LTP_scaleIndex = 0; } } psDec->ec_prevSignalType = psDec->indices.signalType; /***************/ /* Decode seed */ /***************/ psDec->indices.Seed = (SKP_int8)ec_dec_icdf( psRangeDec, SKP_Silk_uniform4_iCDF, 8 ); }
/* Decode parameters from payload */ void silk_decode_parameters( silk_decoder_state *psDec, /* I/O State */ silk_decoder_control *psDecCtrl /* I/O Decoder control */ ) { SKP_int i, k, Ix; SKP_int16 pNLSF_Q15[ MAX_LPC_ORDER ], pNLSF0_Q15[ MAX_LPC_ORDER ]; const SKP_int8 *cbk_ptr_Q7; /* Dequant Gains */ silk_gains_dequant( psDecCtrl->Gains_Q16, psDec->indices.GainsIndices, &psDec->LastGainIndex, psDec->nFramesDecoded, psDec->nb_subfr ); /****************/ /* Decode NLSFs */ /****************/ silk_NLSF_decode( pNLSF_Q15, psDec->indices.NLSFIndices, psDec->psNLSF_CB ); /* Convert NLSF parameters to AR prediction filter coefficients */ silk_NLSF2A_stable( psDecCtrl->PredCoef_Q12[ 1 ], pNLSF_Q15, psDec->LPC_order ); /* If just reset, e.g., because internal Fs changed, do not allow interpolation */ /* improves the case of packet loss in the first frame after a switch */ if( psDec->first_frame_after_reset == 1 ) { psDec->indices.NLSFInterpCoef_Q2 = 4; } if( psDec->indices.NLSFInterpCoef_Q2 < 4 ) { /* Calculation of the interpolated NLSF0 vector from the interpolation factor, */ /* the previous NLSF1, and the current NLSF1 */ for( i = 0; i < psDec->LPC_order; i++ ) { pNLSF0_Q15[ i ] = psDec->prevNLSF_Q15[ i ] + SKP_RSHIFT( SKP_MUL( psDec->indices.NLSFInterpCoef_Q2, pNLSF_Q15[ i ] - psDec->prevNLSF_Q15[ i ] ), 2 ); } /* Convert NLSF parameters to AR prediction filter coefficients */ silk_NLSF2A_stable( psDecCtrl->PredCoef_Q12[ 0 ], pNLSF0_Q15, psDec->LPC_order ); } else { /* Copy LPC coefficients for first half from second half */ SKP_memcpy( psDecCtrl->PredCoef_Q12[ 0 ], psDecCtrl->PredCoef_Q12[ 1 ], psDec->LPC_order * sizeof( SKP_int16 ) ); } SKP_memcpy( psDec->prevNLSF_Q15, pNLSF_Q15, psDec->LPC_order * sizeof( SKP_int16 ) ); /* After a packet loss do BWE of LPC coefs */ if( psDec->lossCnt ) { silk_bwexpander( psDecCtrl->PredCoef_Q12[ 0 ], psDec->LPC_order, BWE_AFTER_LOSS_Q16 ); silk_bwexpander( psDecCtrl->PredCoef_Q12[ 1 ], psDec->LPC_order, BWE_AFTER_LOSS_Q16 ); } if( psDec->indices.signalType == TYPE_VOICED ) { /*********************/ /* Decode pitch lags */ /*********************/ /* Decode pitch values */ silk_decode_pitch( psDec->indices.lagIndex, psDec->indices.contourIndex, psDecCtrl->pitchL, psDec->fs_kHz, psDec->nb_subfr ); /* Decode Codebook Index */ cbk_ptr_Q7 = silk_LTP_vq_ptrs_Q7[ psDec->indices.PERIndex ]; /* set pointer to start of codebook */ for( k = 0; k < psDec->nb_subfr; k++ ) { Ix = psDec->indices.LTPIndex[ k ]; for( i = 0; i < LTP_ORDER; i++ ) { psDecCtrl->LTPCoef_Q14[ k * LTP_ORDER + i ] = SKP_LSHIFT( cbk_ptr_Q7[ Ix * LTP_ORDER + i ], 7 ); } } /**********************/ /* Decode LTP scaling */ /**********************/ Ix = psDec->indices.LTP_scaleIndex; psDecCtrl->LTP_scale_Q14 = silk_LTPScales_table_Q14[ Ix ]; } else { SKP_memset( psDecCtrl->pitchL, 0, psDec->nb_subfr * sizeof( SKP_int ) ); SKP_memset( psDecCtrl->LTPCoef_Q14, 0, LTP_ORDER * psDec->nb_subfr * sizeof( SKP_int16 ) ); psDec->indices.PERIndex = 0; psDecCtrl->LTP_scale_Q14 = 0; } }
/* even order AR filter */ void SKP_Silk_LPC_synthesis_filter( const SKP_int16 *in, /* I: excitation signal */ const SKP_int16 *A_Q12, /* I: AR coefficients [Order], between -8_Q0 and 8_Q0 */ const SKP_int32 Gain_Q26, /* I: gain */ SKP_int32 *S, /* I/O: state vector [Order] */ SKP_int16 *out, /* O: output signal */ const SKP_int32 len, /* I: signal length */ const SKP_int Order /* I: filter order, must be even */ ) { SKP_int k, j, idx, Order_half = SKP_RSHIFT( Order, 1 ); SKP_int32 SA, SB, out32_Q10, out32; #if !defined(_SYSTEM_IS_BIG_ENDIAN) SKP_int32 Atmp, A_align_Q12[ SKP_Silk_MAX_ORDER_LPC >> 1 ]; /* combine two A_Q12 values and ensure 32-bit alignment */ for( k = 0; k < Order_half; k++ ) { idx = SKP_SMULBB( 2, k ); A_align_Q12[ k ] = ( ( ( SKP_int32 )A_Q12[ idx ] ) & 0x0000ffff ) | SKP_LSHIFT( ( SKP_int32 )A_Q12[ idx + 1 ], 16 ); } #endif /* Order must be even */ SKP_assert( 2 * Order_half == Order ); /* S[] values are in Q14 */ for( k = 0; k < len; k++ ) { SA = S[ Order - 1 ]; out32_Q10 = 0; for( j = 0; j < ( Order_half - 1 ); j++ ) { idx = SKP_SMULBB( 2, j ) + 1; #if !defined(_SYSTEM_IS_BIG_ENDIAN) /* multiply-add two prediction coefficients for each loop */ /* NOTE: the code below loads two int16 values in an int32, and multiplies each using the */ /* SMLAWB and SMLAWT instructions. On a big-endian CPU the two int16 variables would be */ /* loaded in reverse order and the code will give the wrong result. In that case swapping */ /* the SMLAWB and SMLAWT instructions should solve the problem. */ Atmp = A_align_Q12[ j ]; SB = S[ Order - 1 - idx ]; S[ Order - 1 - idx ] = SA; out32_Q10 = SKP_SMLAWB( out32_Q10, SA, Atmp ); out32_Q10 = SKP_SMLAWT( out32_Q10, SB, Atmp ); SA = S[ Order - 2 - idx ]; S[ Order - 2 - idx ] = SB; #else SB = S[ Order - 1 - idx ]; S[ Order - 1 - idx ] = SA; out32_Q10 = SKP_SMLAWB( out32_Q10, SA, A_Q12[ ( j << 1 ) ] ); out32_Q10 = SKP_SMLAWB( out32_Q10, SB, A_Q12[ ( j << 1 ) + 1 ] ); SA = S[ Order - 2 - idx ]; S[ Order - 2 - idx ] = SB; #endif } #if !defined(_SYSTEM_IS_BIG_ENDIAN) /* unrolled loop: epilog */ Atmp = A_align_Q12[ Order_half - 1 ]; SB = S[ 0 ]; S[ 0 ] = SA; out32_Q10 = SKP_SMLAWB( out32_Q10, SA, Atmp ); out32_Q10 = SKP_SMLAWT( out32_Q10, SB, Atmp ); #else /* unrolled loop: epilog */ SB = S[ 0 ]; S[ 0 ] = SA; out32_Q10 = SKP_SMLAWB( out32_Q10, SA, A_Q12[ Order - 2 ] ); out32_Q10 = SKP_SMLAWB( out32_Q10, SB, A_Q12[ Order - 1 ] ); #endif /* apply gain to excitation signal and add to prediction */ out32_Q10 = SKP_ADD_SAT32( out32_Q10, SKP_SMULWB( Gain_Q26, in[ k ] ) ); /* scale to Q0 */ out32 = SKP_RSHIFT_ROUND( out32_Q10, 10 ); /* saturate output */ out[ k ] = ( SKP_int16 )SKP_SAT16( out32 ); /* move result into delay line */ S[ Order - 1 ] = SKP_LSHIFT_SAT32( out32_Q10, 4 ); } }
/* Finds LPC vector from correlations, and converts to NLSF */ void SKP_Silk_find_LPC_FIX( SKP_int NLSF_Q15[], /* O NLSFs */ SKP_int *interpIndex, /* O NLSF interpolation index, only used for NLSF interpolation */ const SKP_int prev_NLSFq_Q15[], /* I previous NLSFs, only used for NLSF interpolation */ const SKP_int useInterpolatedNLSFs, /* I Flag */ const SKP_int LPC_order, /* I LPC order */ const SKP_int16 x[], /* I Input signal */ const SKP_int subfr_length /* I Input signal subframe length including preceeding samples */ ) { SKP_int k; SKP_int32 a_Q16[ MAX_LPC_ORDER ]; SKP_int isInterpLower, shift; SKP_int16 S[ MAX_LPC_ORDER ]; SKP_int32 res_nrg0, res_nrg1; SKP_int rshift0, rshift1; /* Used only for LSF interpolation */ SKP_int32 a_tmp_Q16[ MAX_LPC_ORDER ], res_nrg_interp, res_nrg, res_tmp_nrg; SKP_int res_nrg_interp_Q, res_nrg_Q, res_tmp_nrg_Q; SKP_int16 a_tmp_Q12[ MAX_LPC_ORDER ]; SKP_int NLSF0_Q15[ MAX_LPC_ORDER ]; SKP_int16 LPC_res[ ( MAX_FRAME_LENGTH + NB_SUBFR * MAX_LPC_ORDER ) / 2 ]; /* Default: no interpolation */ *interpIndex = 4; /* Burg AR analysis for the full frame */ SKP_Silk_burg_modified( &res_nrg, &res_nrg_Q, a_Q16, x, subfr_length, NB_SUBFR, SKP_FIX_CONST( FIND_LPC_COND_FAC, 32 ), LPC_order ); SKP_Silk_bwexpander_32( a_Q16, LPC_order, SKP_FIX_CONST( FIND_LPC_CHIRP, 16 ) ); if( useInterpolatedNLSFs == 1 ) { /* Optimal solution for last 10 ms */ SKP_Silk_burg_modified( &res_tmp_nrg, &res_tmp_nrg_Q, a_tmp_Q16, x + ( NB_SUBFR >> 1 ) * subfr_length, subfr_length, ( NB_SUBFR >> 1 ), SKP_FIX_CONST( FIND_LPC_COND_FAC, 32 ), LPC_order ); SKP_Silk_bwexpander_32( a_tmp_Q16, LPC_order, SKP_FIX_CONST( FIND_LPC_CHIRP, 16 ) ); /* subtract residual energy here, as that's easier than adding it to the */ /* residual energy of the first 10 ms in each iteration of the search below */ shift = res_tmp_nrg_Q - res_nrg_Q; if( shift >= 0 ) { if( shift < 32 ) { res_nrg = res_nrg - SKP_RSHIFT( res_tmp_nrg, shift ); } } else { SKP_assert( shift > -32 ); res_nrg = SKP_RSHIFT( res_nrg, -shift ) - res_tmp_nrg; res_nrg_Q = res_tmp_nrg_Q; } /* Convert to NLSFs */ SKP_Silk_A2NLSF( NLSF_Q15, a_tmp_Q16, LPC_order ); /* Search over interpolation indices to find the one with lowest residual energy */ for( k = 3; k >= 0; k-- ) { /* Interpolate NLSFs for first half */ SKP_Silk_interpolate( NLSF0_Q15, prev_NLSFq_Q15, NLSF_Q15, k, LPC_order ); /* Convert to LPC for residual energy evaluation */ SKP_Silk_NLSF2A_stable( a_tmp_Q12, NLSF0_Q15, LPC_order ); /* Calculate residual energy with NLSF interpolation */ SKP_memset( S, 0, LPC_order * sizeof( SKP_int16 ) ); SKP_Silk_LPC_analysis_filter( x, a_tmp_Q12, S, LPC_res, 2 * subfr_length, LPC_order ); SKP_Silk_sum_sqr_shift( &res_nrg0, &rshift0, LPC_res + LPC_order, subfr_length - LPC_order ); SKP_Silk_sum_sqr_shift( &res_nrg1, &rshift1, LPC_res + LPC_order + subfr_length, subfr_length - LPC_order ); /* Add subframe energies from first half frame */ shift = rshift0 - rshift1; if( shift >= 0 ) { res_nrg1 = SKP_RSHIFT( res_nrg1, shift ); res_nrg_interp_Q = -rshift0; } else { res_nrg0 = SKP_RSHIFT( res_nrg0, -shift ); res_nrg_interp_Q = -rshift1; } res_nrg_interp = SKP_ADD32( res_nrg0, res_nrg1 ); /* Compare with first half energy without NLSF interpolation, or best interpolated value so far */ shift = res_nrg_interp_Q - res_nrg_Q; if( shift >= 0 ) { if( SKP_RSHIFT( res_nrg_interp, shift ) < res_nrg ) { isInterpLower = SKP_TRUE; } else { isInterpLower = SKP_FALSE; } } else { if( -shift < 32 ) { if( res_nrg_interp < SKP_RSHIFT( res_nrg, -shift ) ) { isInterpLower = SKP_TRUE; } else { isInterpLower = SKP_FALSE; } } else { isInterpLower = SKP_FALSE; } } /* Determine whether current interpolated NLSFs are best so far */ if( isInterpLower == SKP_TRUE ) { /* Interpolation has lower residual energy */ res_nrg = res_nrg_interp; res_nrg_Q = res_nrg_interp_Q; *interpIndex = k; } } }
/* NLSF stabilizer, for a single input data vector */ void silk_NLSF_stabilize( opus_int16 *NLSF_Q15, /* I/O: Unstable/stabilized normalized LSF vector in Q15 [L] */ const opus_int16 *NDeltaMin_Q15, /* I: Normalized delta min vector in Q15, NDeltaMin_Q15[L] must be >= 1 [L+1] */ const opus_int L /* I: Number of NLSF parameters in the input vector */ ) { opus_int i, I=0, k, loops; opus_int16 center_freq_Q15; opus_int32 diff_Q15, min_diff_Q15, min_center_Q15, max_center_Q15; /* This is necessary to ensure an output within range of a opus_int16 */ SKP_assert( NDeltaMin_Q15[L] >= 1 ); for( loops = 0; loops < MAX_LOOPS; loops++ ) { /**************************/ /* Find smallest distance */ /**************************/ /* First element */ min_diff_Q15 = NLSF_Q15[0] - NDeltaMin_Q15[0]; I = 0; /* Middle elements */ for( i = 1; i <= L-1; i++ ) { diff_Q15 = NLSF_Q15[i] - ( NLSF_Q15[i-1] + NDeltaMin_Q15[i] ); if( diff_Q15 < min_diff_Q15 ) { min_diff_Q15 = diff_Q15; I = i; } } /* Last element */ diff_Q15 = ( 1 << 15 ) - ( NLSF_Q15[L-1] + NDeltaMin_Q15[L] ); if( diff_Q15 < min_diff_Q15 ) { min_diff_Q15 = diff_Q15; I = L; } /***************************************************/ /* Now check if the smallest distance non-negative */ /***************************************************/ if (min_diff_Q15 >= 0) { return; } if( I == 0 ) { /* Move away from lower limit */ NLSF_Q15[0] = NDeltaMin_Q15[0]; } else if( I == L) { /* Move away from higher limit */ NLSF_Q15[L-1] = ( 1 << 15 ) - NDeltaMin_Q15[L]; } else { /* Find the lower extreme for the location of the current center frequency */ min_center_Q15 = 0; for( k = 0; k < I; k++ ) { min_center_Q15 += NDeltaMin_Q15[k]; } min_center_Q15 += SKP_RSHIFT( NDeltaMin_Q15[I], 1 ); /* Find the upper extreme for the location of the current center frequency */ max_center_Q15 = 1 << 15; for( k = L; k > I; k-- ) { max_center_Q15 -= NDeltaMin_Q15[k]; } max_center_Q15 -= SKP_RSHIFT( NDeltaMin_Q15[I], 1 ); /* Move apart, sorted by value, keeping the same center frequency */ center_freq_Q15 = (opus_int16)SKP_LIMIT_32( SKP_RSHIFT_ROUND( (opus_int32)NLSF_Q15[I-1] + (opus_int32)NLSF_Q15[I], 1 ), min_center_Q15, max_center_Q15 ); NLSF_Q15[I-1] = center_freq_Q15 - SKP_RSHIFT( NDeltaMin_Q15[I], 1 ); NLSF_Q15[I] = NLSF_Q15[I-1] + NDeltaMin_Q15[I]; } } /* Safe and simple fall back method, which is less ideal than the above */ if( loops == MAX_LOOPS ) { /* Insertion sort (fast for already almost sorted arrays): */ /* Best case: O(n) for an already sorted array */ /* Worst case: O(n^2) for an inversely sorted array */ silk_insertion_sort_increasing_all_values_int16( &NLSF_Q15[0], L ); /* First NLSF should be no less than NDeltaMin[0] */ NLSF_Q15[0] = SKP_max_int( NLSF_Q15[0], NDeltaMin_Q15[0] ); /* Keep delta_min distance between the NLSFs */ for( i = 1; i < L; i++ ) NLSF_Q15[i] = SKP_max_int( NLSF_Q15[i], NLSF_Q15[i-1] + NDeltaMin_Q15[i] ); /* Last NLSF should be no higher than 1 - NDeltaMin[L] */ NLSF_Q15[L-1] = SKP_min_int( NLSF_Q15[L-1], (1<<15) - NDeltaMin_Q15[L] ); /* Keep NDeltaMin distance between the NLSFs */ for( i = L-2; i >= 0; i-- ) NLSF_Q15[i] = SKP_min_int( NLSF_Q15[i], NLSF_Q15[i+1] - NDeltaMin_Q15[i+1] ); } }
void SKP_Silk_PLC_Reset( SKP_Silk_decoder_state *psDec /* I/O Decoder state */ ) { psDec->sPLC.pitchL_Q8 = SKP_RSHIFT( psDec->frame_length, 1 ); }
SKP_int SKP_Silk_VAD_GetSA_Q8( /* O Return value, 0 if success */ SKP_Silk_VAD_state *psSilk_VAD, /* I/O Silk VAD state */ SKP_int *pSA_Q8, /* O Speech activity level in Q8 */ SKP_int *pSNR_dB_Q7, /* O SNR for current frame in Q7 */ SKP_int pQuality_Q15[ VAD_N_BANDS ], /* O Smoothed SNR for each band */ SKP_int *pTilt_Q15, /* O current frame's frequency tilt */ const SKP_int16 pIn[], /* I PCM input [framelength] */ const SKP_int framelength /* I Input frame length */ ) { SKP_int SA_Q15, input_tilt; SKP_int32 scratch[ 3 * MAX_FRAME_LENGTH / 2 ]; 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; /* Safety checks */ SKP_assert( VAD_N_BANDS == 4 ); SKP_assert( MAX_FRAME_LENGTH >= framelength ); SKP_assert( framelength <= 512 ); /***********************/ /* 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 ], &scratch[ 0 ], framelength ); /* 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 ], &scratch[ 0 ], SKP_RSHIFT( framelength, 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 ], &scratch[ 0 ], SKP_RSHIFT( framelength, 2 ) ); /*********************************************/ /* HP filter on lowest band (differentiator) */ /*********************************************/ decimated_framelength = SKP_RSHIFT( framelength, 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( framelength, 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 */ /**************************/ *pTilt_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 ) { /* square-root */ speech_nrg = SKP_Silk_SQRT_APPROX( SKP_LSHIFT( speech_nrg, 15 ) ); SA_Q15 = SKP_SMULWB( 32768 + speech_nrg, SA_Q15 ); } /* Copy the resulting speech activity in Q8 to *pSA_Q8 */ *pSA_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 ) ); for( b = 0; b < VAD_N_BANDS; b++ ) { /* compute smoothed energy-to-noise ratio per band */ psSilk_VAD->NrgRatioSmth_Q8[ b ] = SKP_SMLAWB( psSilk_VAD->NrgRatioSmth_Q8[ b ], NrgToNoiseRatio_Q8[ b ] - psSilk_VAD->NrgRatioSmth_Q8[ b ], smooth_coef_Q16 ); /* signal to noise ratio in dB per band */ SNR_Q7 = 3 * ( SKP_Silk_lin2log( psSilk_VAD->NrgRatioSmth_Q8[b] ) - 8 * 128 ); /* quality = sigmoid( 0.25 * ( SNR_dB - 16 ) ); */ pQuality_Q15[ b ] = SKP_Silk_sigm_Q15( SKP_RSHIFT( SNR_Q7 - 16 * 128, 4 ) ); } return( ret ); }
/* Processing of gains */ void SKP_Silk_process_gains_FIX( SKP_Silk_encoder_state_FIX *psEnc, /* I/O Encoder state_FIX */ SKP_Silk_encoder_control_FIX *psEncCtrl /* I/O Encoder control_FIX */ ) { SKP_Silk_shape_state_FIX *psShapeSt = &psEnc->sShape; SKP_int k; SKP_int32 s_Q16, InvMaxSqrVal_Q16, gain, gain_squared, ResNrg, ResNrgPart; /* Gain reduction when LTP coding gain is high */ if( psEncCtrl->sCmn.sigtype == SIG_TYPE_VOICED ) { /*s = -0.5f * SKP_sigmoid( 0.25f * ( psEncCtrl->LTPredCodGain - 12.0f ) ); */ s_Q16 = -SKP_Silk_sigm_Q15( SKP_RSHIFT_ROUND( psEncCtrl->LTPredCodGain_Q7 - (12 << 7), 4 ) ); for( k = 0; k < NB_SUBFR; k++ ) { psEncCtrl->Gains_Q16[ k ] = SKP_SMLAWB( psEncCtrl->Gains_Q16[ k ], psEncCtrl->Gains_Q16[ k ], s_Q16 ); } } /* Limit the quantized signal */ /* 69 = 21.0f + 16/0.33 */ InvMaxSqrVal_Q16 = SKP_DIV32_16( SKP_Silk_log2lin( SKP_SMULWB( (69 << 7) - psEncCtrl->current_SNR_dB_Q7, SKP_FIX_CONST( 0.33, 16 )) ), psEnc->sCmn.subfr_length ); for( k = 0; k < NB_SUBFR; k++ ) { /* Soft limit on ratio residual energy and squared gains */ ResNrg = psEncCtrl->ResNrg[ k ]; ResNrgPart = SKP_SMULWW( ResNrg, InvMaxSqrVal_Q16 ); if( psEncCtrl->ResNrgQ[ k ] > 0 ) { if( psEncCtrl->ResNrgQ[ k ] < 32 ) { ResNrgPart = SKP_RSHIFT_ROUND( ResNrgPart, psEncCtrl->ResNrgQ[ k ] ); } else { ResNrgPart = 0; } } else if( psEncCtrl->ResNrgQ[k] != 0 ) { if( ResNrgPart > SKP_RSHIFT( SKP_int32_MAX, -psEncCtrl->ResNrgQ[ k ] ) ) { ResNrgPart = SKP_int32_MAX; } else { ResNrgPart = SKP_LSHIFT( ResNrgPart, -psEncCtrl->ResNrgQ[ k ] ); } } gain = psEncCtrl->Gains_Q16[ k ]; gain_squared = SKP_ADD_SAT32( ResNrgPart, SKP_SMMUL( gain, gain ) ); if( gain_squared < SKP_int16_MAX ) { /* recalculate with higher precision */ gain_squared = SKP_SMLAWW( SKP_LSHIFT( ResNrgPart, 16 ), gain, gain ); SKP_assert( gain_squared > 0 ); gain = SKP_Silk_SQRT_APPROX( gain_squared ); /* Q8 */ psEncCtrl->Gains_Q16[ k ] = SKP_LSHIFT_SAT32( gain, 8 ); /* Q16 */ } else { gain = SKP_Silk_SQRT_APPROX( gain_squared ); /* Q0 */ psEncCtrl->Gains_Q16[ k ] = SKP_LSHIFT_SAT32( gain, 16 ); /* Q16 */ } } /* Noise shaping quantization */ SKP_Silk_gains_quant( psEncCtrl->sCmn.GainsIndices, psEncCtrl->Gains_Q16, &psShapeSt->LastGainIndex, psEnc->sCmn.nFramesInPayloadBuf ); /* Set quantizer offset for voiced signals. Larger offset when LTP coding gain is low or tilt is high (ie low-pass) */ if( psEncCtrl->sCmn.sigtype == SIG_TYPE_VOICED ) { if( psEncCtrl->LTPredCodGain_Q7 + SKP_RSHIFT( psEncCtrl->input_tilt_Q15, 8 ) > ( 1 << 7 ) ) { psEncCtrl->sCmn.QuantOffsetType = 0; } else { psEncCtrl->sCmn.QuantOffsetType = 1; } } /* Quantizer boundary adjustment */ if( psEncCtrl->sCmn.sigtype == SIG_TYPE_VOICED ) { psEncCtrl->Lambda_Q10 = SKP_FIX_CONST( 1.3, 10 ) - SKP_SMULWB( SKP_FIX_CONST( 0.5, 18 ), psEnc->speech_activity_Q8 ) - SKP_SMULWB( SKP_FIX_CONST( 0.3, 12 ), psEncCtrl->input_quality_Q14 ) + SKP_SMULBB( SKP_FIX_CONST( 0.2, 10 ), psEncCtrl->sCmn.QuantOffsetType ) - SKP_SMULWB( SKP_FIX_CONST( 0.1, 12 ), psEncCtrl->coding_quality_Q14 ); } else { psEncCtrl->Lambda_Q10 = SKP_FIX_CONST( 1.3, 10 ) - SKP_SMULWB( SKP_FIX_CONST( 0.5, 18 ), psEnc->speech_activity_Q8 ) - SKP_SMULWB( SKP_FIX_CONST( 0.4, 12 ), psEncCtrl->input_quality_Q14 ) + SKP_SMULBB( SKP_FIX_CONST( 0.4, 10 ), psEncCtrl->sCmn.QuantOffsetType ) - SKP_SMULWB( SKP_FIX_CONST( 0.1, 12 ), psEncCtrl->coding_quality_Q14 ); } SKP_assert( psEncCtrl->Lambda_Q10 >= 0 ); SKP_assert( psEncCtrl->Lambda_Q10 < SKP_FIX_CONST( 2, 10 ) ); }
/* Limit, stabilize, convert and quantize NLSFs. */ void SKP_Silk_process_NLSFs_FIX( SKP_Silk_encoder_state_FIX *psEnc, /* I/O Encoder state FIX */ SKP_Silk_encoder_control_FIX *psEncCtrl, /* I/O Encoder control FIX */ SKP_int *pNLSF_Q15 /* I/O Normalized LSFs (quant out) (0 - (2^15-1)) */ ) { SKP_int doInterpolate; SKP_int pNLSFW_Q6[ MAX_LPC_ORDER ]; SKP_int NLSF_mu_Q15, NLSF_mu_fluc_red_Q16; SKP_int32 i_sqr_Q15; const SKP_Silk_NLSF_CB_struct *psNLSF_CB; /* Used only for NLSF interpolation */ SKP_int pNLSF0_temp_Q15[ MAX_LPC_ORDER ]; SKP_int pNLSFW0_temp_Q6[ MAX_LPC_ORDER ]; SKP_int i; SKP_assert( psEnc->speech_activity_Q8 >= 0 ); SKP_assert( psEnc->speech_activity_Q8 <= 256 ); SKP_assert( psEncCtrl->sparseness_Q8 >= 0 ); SKP_assert( psEncCtrl->sparseness_Q8 <= 256 ); SKP_assert( psEncCtrl->sCmn.sigtype == SIG_TYPE_VOICED || psEncCtrl->sCmn.sigtype == SIG_TYPE_UNVOICED ); /***********************/ /* Calculate mu values */ /***********************/ if( psEncCtrl->sCmn.sigtype == SIG_TYPE_VOICED ) { /* NLSF_mu = 0.002f - 0.001f * psEnc->speech_activity; */ /* NLSF_mu_fluc_red = 0.1f - 0.05f * psEnc->speech_activity; */ NLSF_mu_Q15 = SKP_SMLAWB( 66, -8388, psEnc->speech_activity_Q8 ); NLSF_mu_fluc_red_Q16 = SKP_SMLAWB( 6554, -838848, psEnc->speech_activity_Q8 ); } else { /* NLSF_mu = 0.005f - 0.004f * psEnc->speech_activity; */ /* NLSF_mu_fluc_red = 0.2f - 0.1f * psEnc->speech_activity - 0.1f * psEncCtrl->sparseness; */ NLSF_mu_Q15 = SKP_SMLAWB( 164, -33554, psEnc->speech_activity_Q8 ); NLSF_mu_fluc_red_Q16 = SKP_SMLAWB( 13107, -1677696, psEnc->speech_activity_Q8 + psEncCtrl->sparseness_Q8 ); } SKP_assert( NLSF_mu_Q15 >= 0 ); SKP_assert( NLSF_mu_Q15 <= 164 ); SKP_assert( NLSF_mu_fluc_red_Q16 >= 0 ); SKP_assert( NLSF_mu_fluc_red_Q16 <= 13107 ); NLSF_mu_Q15 = SKP_max( NLSF_mu_Q15, 1 ); /* Calculate NLSF weights */ TIC(NLSF_weights_FIX) SKP_Silk_NLSF_VQ_weights_laroia( pNLSFW_Q6, pNLSF_Q15, psEnc->sCmn.predictLPCOrder ); TOC(NLSF_weights_FIX) /* Update NLSF weights for interpolated NLSFs */ doInterpolate = ( psEnc->sCmn.useInterpolatedNLSFs == 1 ) && ( psEncCtrl->sCmn.NLSFInterpCoef_Q2 < ( 1 << 2 ) ); if( doInterpolate ) { /* Calculate the interpolated NLSF vector for the first half */ SKP_Silk_interpolate( pNLSF0_temp_Q15, psEnc->sPred.prev_NLSFq_Q15, pNLSF_Q15, psEncCtrl->sCmn.NLSFInterpCoef_Q2, psEnc->sCmn.predictLPCOrder ); /* Calculate first half NLSF weights for the interpolated NLSFs */ TIC(NLSF_weights_FIX) SKP_Silk_NLSF_VQ_weights_laroia( pNLSFW0_temp_Q6, pNLSF0_temp_Q15, psEnc->sCmn.predictLPCOrder ); TOC(NLSF_weights_FIX) /* Update NLSF weights with contribution from first half */ i_sqr_Q15 = SKP_LSHIFT( SKP_SMULBB( psEncCtrl->sCmn.NLSFInterpCoef_Q2, psEncCtrl->sCmn.NLSFInterpCoef_Q2 ), 11 ); for( i = 0; i < psEnc->sCmn.predictLPCOrder; i++ ) { pNLSFW_Q6[ i ] = SKP_SMLAWB( SKP_RSHIFT( pNLSFW_Q6[ i ], 1 ), pNLSFW0_temp_Q6[ i ], i_sqr_Q15 ); SKP_assert( pNLSFW_Q6[ i ] <= SKP_int16_MAX ); SKP_assert( pNLSFW_Q6[ i ] >= 1 ); } } /* Set pointer to the NLSF codebook for the current signal type and LPC order */ psNLSF_CB = psEnc->sCmn.psNLSF_CB[ psEncCtrl->sCmn.sigtype ]; /* Quantize NLSF parameters given the trained NLSF codebooks */ TIC(MSVQ_encode_FIX) SKP_Silk_NLSF_MSVQ_encode_FIX( psEncCtrl->sCmn.NLSFIndices, pNLSF_Q15, psNLSF_CB, psEnc->sPred.prev_NLSFq_Q15, pNLSFW_Q6, NLSF_mu_Q15, NLSF_mu_fluc_red_Q16, psEnc->sCmn.NLSF_MSVQ_Survivors, psEnc->sCmn.predictLPCOrder, psEnc->sCmn.first_frame_after_reset ); TOC(MSVQ_encode_FIX) /* Convert quantized NLSFs back to LPC coefficients */ SKP_Silk_NLSF2A_stable( psEncCtrl->PredCoef_Q12[ 1 ], pNLSF_Q15, psEnc->sCmn.predictLPCOrder ); if( doInterpolate ) { /* Calculate the interpolated, quantized LSF vector for the first half */ SKP_Silk_interpolate( pNLSF0_temp_Q15, psEnc->sPred.prev_NLSFq_Q15, pNLSF_Q15, psEncCtrl->sCmn.NLSFInterpCoef_Q2, psEnc->sCmn.predictLPCOrder ); /* Convert back to LPC coefficients */ SKP_Silk_NLSF2A_stable( psEncCtrl->PredCoef_Q12[ 0 ], pNLSF0_temp_Q15, psEnc->sCmn.predictLPCOrder ); } else { /* Copy LPC coefficients for first half from second half */ SKP_memcpy( psEncCtrl->PredCoef_Q12[ 0 ], psEncCtrl->PredCoef_Q12[ 1 ], psEnc->sCmn.predictLPCOrder * sizeof( SKP_int16 ) ); } }