/* Find least-squares prediction gain for one signal based on another and quantize it */ int32_t silk_stereo_find_predictor( /* O Returns predictor in Q13 */ int32_t * ratio_Q14, /* O Ratio of residual and mid energies */ const int16_t x[], /* I Basis signal */ const int16_t y[], /* I Target signal */ int32_t mid_res_amp_Q0[], /* I/O Smoothed mid, residual norms */ int length, /* I Number of samples */ int smooth_coef_Q16 /* I Smoothing coefficient */ ) { int scale, scale1, scale2; int32_t nrgx, nrgy, corr, pred_Q13, pred2_Q10; /* Find predictor */ silk_sum_sqr_shift(&nrgx, &scale1, x, length); silk_sum_sqr_shift(&nrgy, &scale2, y, length); scale = silk_max_int(scale1, scale2); scale = scale + (scale & 1); /* make even */ nrgy = silk_RSHIFT32(nrgy, scale - scale2); nrgx = silk_RSHIFT32(nrgx, scale - scale1); nrgx = silk_max_int(nrgx, 1); corr = silk_inner_prod_aligned_scale(x, y, scale, length); pred_Q13 = silk_DIV32_varQ(corr, nrgx, 13); pred_Q13 = silk_LIMIT(pred_Q13, -(1 << 14), 1 << 14); pred2_Q10 = silk_SMULWB(pred_Q13, pred_Q13); /* Faster update for signals with large prediction parameters */ smooth_coef_Q16 = (int) silk_max_int(smooth_coef_Q16, silk_abs(pred2_Q10)); /* Smoothed mid and residual norms */ assert(smooth_coef_Q16 < 32768); scale = silk_RSHIFT(scale, 1); mid_res_amp_Q0[0] = silk_SMLAWB(mid_res_amp_Q0[0], silk_LSHIFT(silk_SQRT_APPROX(nrgx), scale) - mid_res_amp_Q0[0], smooth_coef_Q16); /* Residual energy = nrgy - 2 * pred * corr + pred^2 * nrgx */ nrgy = silk_SUB_LSHIFT32(nrgy, silk_SMULWB(corr, pred_Q13), 3 + 1); nrgy = silk_ADD_LSHIFT32(nrgy, silk_SMULWB(nrgx, pred2_Q10), 6); mid_res_amp_Q0[1] = silk_SMLAWB(mid_res_amp_Q0[1], silk_LSHIFT(silk_SQRT_APPROX(nrgy), scale) - mid_res_amp_Q0[1], smooth_coef_Q16); /* Ratio of smoothed residual and mid norms */ *ratio_Q14 = silk_DIV32_varQ(mid_res_amp_Q0[1], silk_max(mid_res_amp_Q0[0], 1), 14); *ratio_Q14 = silk_LIMIT(*ratio_Q14, 0, 32767); return pred_Q13; }
void silk_NLSF_decode( opus_int16 *pNLSF_Q15, /* O Quantized NLSF vector [ LPC_ORDER ] */ opus_int8 *NLSFIndices, /* I Codebook path vector [ LPC_ORDER + 1 ] */ const silk_NLSF_CB_struct *psNLSF_CB /* I Codebook object */ ) { opus_int i; opus_uint8 pred_Q8[ MAX_LPC_ORDER ]; opus_int16 ec_ix[ MAX_LPC_ORDER ]; opus_int16 res_Q10[ MAX_LPC_ORDER ]; opus_int32 NLSF_Q15_tmp; const opus_uint8 *pCB_element; const opus_int16 *pCB_Wght_Q9; /* Unpack entropy table indices and predictor for current CB1 index */ silk_NLSF_unpack( ec_ix, pred_Q8, psNLSF_CB, NLSFIndices[ 0 ] ); /* Predictive residual dequantizer */ silk_NLSF_residual_dequant( res_Q10, &NLSFIndices[ 1 ], pred_Q8, psNLSF_CB->quantStepSize_Q16, psNLSF_CB->order ); /* Apply inverse square-rooted weights to first stage and add to output */ pCB_element = &psNLSF_CB->CB1_NLSF_Q8[ NLSFIndices[ 0 ] * psNLSF_CB->order ]; pCB_Wght_Q9 = &psNLSF_CB->CB1_Wght_Q9[ NLSFIndices[ 0 ] * psNLSF_CB->order ]; for( i = 0; i < psNLSF_CB->order; i++ ) { NLSF_Q15_tmp = silk_ADD_LSHIFT32( silk_DIV32_16( silk_LSHIFT( (opus_int32)res_Q10[ i ], 14 ), pCB_Wght_Q9[ i ] ), (opus_int16)pCB_element[ i ], 7 ); pNLSF_Q15[ i ] = (opus_int16)silk_LIMIT( NLSF_Q15_tmp, 0, 32767 ); } /* NLSF stabilization */ silk_NLSF_stabilize( pNLSF_Q15, psNLSF_CB->deltaMin_Q15, psNLSF_CB->order ); }
/* Autocorrelations for a warped frequency axis */ void silk_warped_autocorrelation_FIX( opus_int32 *corr, /* O Result [order + 1] */ opus_int *scale, /* O Scaling of the correlation vector */ const opus_int16 *input, /* I Input data to correlate */ const opus_int warping_Q16, /* I Warping coefficient */ const opus_int length, /* I Length of input */ const opus_int order /* I Correlation order (even) */ ) { opus_int n, i, lsh; opus_int32 tmp1_QS, tmp2_QS; opus_int32 state_QS[ MAX_SHAPE_LPC_ORDER + 1 ] = { 0 }; opus_int64 corr_QC[ MAX_SHAPE_LPC_ORDER + 1 ] = { 0 }; /* Order must be even */ silk_assert( ( order & 1 ) == 0 ); silk_assert( 2 * QS - QC >= 0 ); /* Loop over samples */ for( n = 0; n < length; n++ ) { tmp1_QS = silk_LSHIFT32( (opus_int32)input[ n ], QS ); /* Loop over allpass sections */ for( i = 0; i < order; i += 2 ) { /* Output of allpass section */ tmp2_QS = silk_SMLAWB( state_QS[ i ], state_QS[ i + 1 ] - tmp1_QS, warping_Q16 ); state_QS[ i ] = tmp1_QS; corr_QC[ i ] += silk_RSHIFT64( silk_SMULL( tmp1_QS, state_QS[ 0 ] ), 2 * QS - QC ); /* Output of allpass section */ tmp1_QS = silk_SMLAWB( state_QS[ i + 1 ], state_QS[ i + 2 ] - tmp2_QS, warping_Q16 ); state_QS[ i + 1 ] = tmp2_QS; corr_QC[ i + 1 ] += silk_RSHIFT64( silk_SMULL( tmp2_QS, state_QS[ 0 ] ), 2 * QS - QC ); } state_QS[ order ] = tmp1_QS; corr_QC[ order ] += silk_RSHIFT64( silk_SMULL( tmp1_QS, state_QS[ 0 ] ), 2 * QS - QC ); } lsh = silk_CLZ64( corr_QC[ 0 ] ) - 35; lsh = silk_LIMIT( lsh, -12 - QC, 30 - QC ); *scale = -( QC + lsh ); silk_assert( *scale >= -30 && *scale <= 12 ); if( lsh >= 0 ) { for( i = 0; i < order + 1; i++ ) { corr[ i ] = (opus_int32)silk_CHECK_FIT32( silk_LSHIFT64( corr_QC[ i ], lsh ) ); } } else { for( i = 0; i < order + 1; i++ ) { corr[ i ] = (opus_int32)silk_CHECK_FIT32( silk_RSHIFT64( corr_QC[ i ], -lsh ) ); } } silk_assert( corr_QC[ 0 ] >= 0 ); /* If breaking, decrease QC*/ }
/* Control SNR of redidual quantizer */ opus_int silk_control_SNR( silk_encoder_state *psEncC, /* I/O Pointer to Silk encoder state */ opus_int32 TargetRate_bps /* I Target max bitrate (bps) */ ) { opus_int k, ret = SILK_NO_ERROR; opus_int32 frac_Q6; const opus_int32 *rateTable; /* Set bitrate/coding quality */ TargetRate_bps = silk_LIMIT(TargetRate_bps, MIN_TARGET_RATE_BPS, MAX_TARGET_RATE_BPS); if (TargetRate_bps != psEncC->TargetRate_bps) { psEncC->TargetRate_bps = TargetRate_bps; /* If new TargetRate_bps, translate to SNR_dB value */ if (psEncC->fs_kHz == 8) { rateTable = silk_TargetRate_table_NB; } else if (psEncC->fs_kHz == 12) { rateTable = silk_TargetRate_table_MB; } else { rateTable = silk_TargetRate_table_WB; } /* Reduce bitrate for 10 ms modes in these calculations */ if (psEncC->nb_subfr == 2) { TargetRate_bps -= REDUCE_BITRATE_10_MS_BPS; } /* Find bitrate interval in table and interpolate */ for (k = 1; k < TARGET_RATE_TAB_SZ; k++) { if (TargetRate_bps <= rateTable[k]) { frac_Q6 = silk_DIV32(silk_LSHIFT(TargetRate_bps - rateTable[k - 1], 6), rateTable[k] - rateTable[k - 1]); psEncC->SNR_dB_Q7 = silk_LSHIFT(silk_SNR_table_Q1[k - 1], 6) + silk_MUL(frac_Q6, silk_SNR_table_Q1[k] - silk_SNR_table_Q1[ k - 1]); break; } } /* Reduce coding quality whenever LBRR is enabled, to free up some bits */ if (psEncC->LBRR_enabled) { psEncC->SNR_dB_Q7 = silk_SMLABB(psEncC->SNR_dB_Q7, 12 - psEncC->LBRR_GainIncreases, SILK_FIX_CONST(-0.25, 7)); } } return ret; }
/* Calculation of LTP state scaling */ void silk_LTP_scale_ctrl_FIX( silk_encoder_state_FIX *psEnc, /* I/O encoder state */ silk_encoder_control_FIX *psEncCtrl, /* I/O encoder control */ opus_int condCoding /* I The type of conditional coding to use */ ) { opus_int round_loss; if( condCoding == CODE_INDEPENDENTLY ) { /* Only scale if first frame in packet */ round_loss = psEnc->sCmn.PacketLoss_perc + psEnc->sCmn.nFramesPerPacket; psEnc->sCmn.indices.LTP_scaleIndex = (opus_int8)silk_LIMIT( silk_SMULWB( silk_SMULBB( round_loss, psEncCtrl->LTPredCodGain_Q7 ), SILK_FIX_CONST( 0.1, 9 ) ), 0, 2 ); } else { /* Default is minimum scaling */ psEnc->sCmn.indices.LTP_scaleIndex = 0; } psEncCtrl->LTP_scale_Q14 = silk_LTPScales_table_Q14[ psEnc->sCmn.indices.LTP_scaleIndex ]; }
void silk_NLSF_decode( opus_int16 *pNLSF_Q15, /* O Quantized NLSF vector [ LPC_ORDER ] */ opus_int8 *NLSFIndices, /* I Codebook path vector [ LPC_ORDER + 1 ] */ const silk_NLSF_CB_struct *psNLSF_CB /* I Codebook object */ ) { opus_int i; opus_uint8 pred_Q8[ MAX_LPC_ORDER ]; opus_int16 ec_ix[ MAX_LPC_ORDER ]; opus_int16 res_Q10[ MAX_LPC_ORDER ]; opus_int16 W_tmp_QW[ MAX_LPC_ORDER ]; opus_int32 W_tmp_Q9, NLSF_Q15_tmp; const opus_uint8 *pCB_element; /* Decode first stage */ pCB_element = &psNLSF_CB->CB1_NLSF_Q8[ NLSFIndices[ 0 ] * psNLSF_CB->order ]; for( i = 0; i < psNLSF_CB->order; i++ ) { pNLSF_Q15[ i ] = silk_LSHIFT( (opus_int16)pCB_element[ i ], 7 ); } /* Unpack entropy table indices and predictor for current CB1 index */ silk_NLSF_unpack( ec_ix, pred_Q8, psNLSF_CB, NLSFIndices[ 0 ] ); /* Predictive residual dequantizer */ silk_NLSF_residual_dequant( res_Q10, &NLSFIndices[ 1 ], pred_Q8, psNLSF_CB->quantStepSize_Q16, psNLSF_CB->order ); /* Weights from codebook vector */ silk_NLSF_VQ_weights_laroia( W_tmp_QW, pNLSF_Q15, psNLSF_CB->order ); /* Apply inverse square-rooted weights and add to output */ for( i = 0; i < psNLSF_CB->order; i++ ) { W_tmp_Q9 = silk_SQRT_APPROX( silk_LSHIFT( (opus_int32)W_tmp_QW[ i ], 18 - NLSF_W_Q ) ); NLSF_Q15_tmp = silk_ADD32( pNLSF_Q15[ i ], silk_DIV32_16( silk_LSHIFT( (opus_int32)res_Q10[ i ], 14 ), W_tmp_Q9 ) ); pNLSF_Q15[ i ] = (opus_int16)silk_LIMIT( NLSF_Q15_tmp, 0, 32767 ); } /* NLSF stabilization */ silk_NLSF_stabilize( pNLSF_Q15, psNLSF_CB->deltaMin_Q15, psNLSF_CB->order ); }
/* Deactivate by setting psEncC->mode = 0; */ void silk_LP_variable_cutoff( silk_LP_state *psLP, /* I/O LP filter state */ opus_int16 *frame, /* I/O Low-pass filtered output signal */ const opus_int frame_length /* I Frame length */ ) { opus_int32 B_Q28[ TRANSITION_NB ], A_Q28[ TRANSITION_NA ], fac_Q16 = 0; opus_int ind = 0; silk_assert( psLP->transition_frame_no >= 0 && psLP->transition_frame_no <= TRANSITION_FRAMES ); /* Run filter if needed */ if( psLP->mode != 0 ) { /* Calculate index and interpolation factor for interpolation */ #if( TRANSITION_INT_STEPS == 64 ) fac_Q16 = silk_LSHIFT( TRANSITION_FRAMES - psLP->transition_frame_no, 16 - 6 ); #else fac_Q16 = silk_DIV32_16( silk_LSHIFT( TRANSITION_FRAMES - psLP->transition_frame_no, 16 ), TRANSITION_FRAMES ); #endif ind = silk_RSHIFT( fac_Q16, 16 ); fac_Q16 -= silk_LSHIFT( ind, 16 ); silk_assert( ind >= 0 ); silk_assert( ind < TRANSITION_INT_NUM ); /* Interpolate filter coefficients */ silk_LP_interpolate_filter_taps( B_Q28, A_Q28, ind, fac_Q16 ); /* Update transition frame number for next frame */ psLP->transition_frame_no = silk_LIMIT( psLP->transition_frame_no + psLP->mode, 0, TRANSITION_FRAMES ); /* ARMA low-pass filtering */ silk_assert( TRANSITION_NB == 3 && TRANSITION_NA == 2 ); silk_biquad_alt( frame, B_Q28, A_Q28, psLP->In_LP_State, frame, frame_length, 1); } }
/* Delayed-decision quantizer for NLSF residuals */ opus_int32 silk_NLSF_del_dec_quant( /* O Returns RD value in Q25 */ opus_int8 indices[], /* O Quantization indices [ order ] */ const opus_int16 x_Q10[], /* I Input [ order ] */ const opus_int16 w_Q5[], /* I Weights [ order ] */ const opus_uint8 pred_coef_Q8[], /* I Backward predictor coefs [ order ] */ const opus_int16 ec_ix[], /* I Indices to entropy coding tables [ order ] */ const opus_uint8 ec_rates_Q5[], /* I Rates [] */ const opus_int quant_step_size_Q16, /* I Quantization step size */ const opus_int16 inv_quant_step_size_Q6, /* I Inverse quantization step size */ const opus_int32 mu_Q20, /* I R/D tradeoff */ const opus_int16 order /* I Number of input values */ ) { opus_int i, j, nStates, ind_tmp, ind_min_max, ind_max_min, in_Q10, res_Q10; opus_int pred_Q10, diff_Q10, out0_Q10, out1_Q10, rate0_Q5, rate1_Q5; opus_int32 RD_tmp_Q25, min_Q25, min_max_Q25, max_min_Q25, pred_coef_Q16; opus_int ind_sort[ NLSF_QUANT_DEL_DEC_STATES ]; opus_int8 ind[ NLSF_QUANT_DEL_DEC_STATES ][ MAX_LPC_ORDER ]; opus_int16 prev_out_Q10[ 2 * NLSF_QUANT_DEL_DEC_STATES ]; opus_int32 RD_Q25[ 2 * NLSF_QUANT_DEL_DEC_STATES ]; opus_int32 RD_min_Q25[ NLSF_QUANT_DEL_DEC_STATES ]; opus_int32 RD_max_Q25[ NLSF_QUANT_DEL_DEC_STATES ]; const opus_uint8 *rates_Q5; silk_assert( (NLSF_QUANT_DEL_DEC_STATES & (NLSF_QUANT_DEL_DEC_STATES-1)) == 0 ); /* must be power of two */ nStates = 1; RD_Q25[ 0 ] = 0; prev_out_Q10[ 0 ] = 0; for( i = order - 1; ; i-- ) { rates_Q5 = &ec_rates_Q5[ ec_ix[ i ] ]; pred_coef_Q16 = silk_LSHIFT( (opus_int32)pred_coef_Q8[ i ], 8 ); in_Q10 = x_Q10[ i ]; for( j = 0; j < nStates; j++ ) { pred_Q10 = silk_SMULWB( pred_coef_Q16, prev_out_Q10[ j ] ); res_Q10 = silk_SUB16( in_Q10, pred_Q10 ); ind_tmp = silk_SMULWB( inv_quant_step_size_Q6, res_Q10 ); ind_tmp = silk_LIMIT( ind_tmp, -NLSF_QUANT_MAX_AMPLITUDE_EXT, NLSF_QUANT_MAX_AMPLITUDE_EXT-1 ); ind[ j ][ i ] = (opus_int8)ind_tmp; /* compute outputs for ind_tmp and ind_tmp + 1 */ out0_Q10 = silk_LSHIFT( ind_tmp, 10 ); out1_Q10 = silk_ADD16( out0_Q10, 1024 ); if( ind_tmp > 0 ) { out0_Q10 = silk_SUB16( out0_Q10, SILK_FIX_CONST( NLSF_QUANT_LEVEL_ADJ, 10 ) ); out1_Q10 = silk_SUB16( out1_Q10, SILK_FIX_CONST( NLSF_QUANT_LEVEL_ADJ, 10 ) ); } else if( ind_tmp == 0 ) { out1_Q10 = silk_SUB16( out1_Q10, SILK_FIX_CONST( NLSF_QUANT_LEVEL_ADJ, 10 ) ); } else if( ind_tmp == -1 ) { out0_Q10 = silk_ADD16( out0_Q10, SILK_FIX_CONST( NLSF_QUANT_LEVEL_ADJ, 10 ) ); } else { out0_Q10 = silk_ADD16( out0_Q10, SILK_FIX_CONST( NLSF_QUANT_LEVEL_ADJ, 10 ) ); out1_Q10 = silk_ADD16( out1_Q10, SILK_FIX_CONST( NLSF_QUANT_LEVEL_ADJ, 10 ) ); } out0_Q10 = silk_SMULWB( out0_Q10, quant_step_size_Q16 ); out1_Q10 = silk_SMULWB( out1_Q10, quant_step_size_Q16 ); out0_Q10 = silk_ADD16( out0_Q10, pred_Q10 ); out1_Q10 = silk_ADD16( out1_Q10, pred_Q10 ); prev_out_Q10[ j ] = out0_Q10; prev_out_Q10[ j + nStates ] = out1_Q10; /* compute RD for ind_tmp and ind_tmp + 1 */ if( ind_tmp + 1 >= NLSF_QUANT_MAX_AMPLITUDE ) { if( ind_tmp + 1 == NLSF_QUANT_MAX_AMPLITUDE ) { rate0_Q5 = rates_Q5[ ind_tmp + NLSF_QUANT_MAX_AMPLITUDE ]; rate1_Q5 = 280; } else { rate0_Q5 = silk_SMLABB( 280 - 43 * NLSF_QUANT_MAX_AMPLITUDE, 43, ind_tmp ); rate1_Q5 = silk_ADD16( rate0_Q5, 43 ); } } else if( ind_tmp <= -NLSF_QUANT_MAX_AMPLITUDE ) { if( ind_tmp == -NLSF_QUANT_MAX_AMPLITUDE ) { rate0_Q5 = 280; rate1_Q5 = rates_Q5[ ind_tmp + 1 + NLSF_QUANT_MAX_AMPLITUDE ]; } else { rate0_Q5 = silk_SMLABB( 280 - 43 * NLSF_QUANT_MAX_AMPLITUDE, -43, ind_tmp ); rate1_Q5 = silk_SUB16( rate0_Q5, 43 ); } } else { rate0_Q5 = rates_Q5[ ind_tmp + NLSF_QUANT_MAX_AMPLITUDE ]; rate1_Q5 = rates_Q5[ ind_tmp + 1 + NLSF_QUANT_MAX_AMPLITUDE ]; } RD_tmp_Q25 = RD_Q25[ j ]; diff_Q10 = silk_SUB16( in_Q10, out0_Q10 ); RD_Q25[ j ] = silk_SMLABB( silk_MLA( RD_tmp_Q25, silk_SMULBB( diff_Q10, diff_Q10 ), w_Q5[ i ] ), mu_Q20, rate0_Q5 ); diff_Q10 = silk_SUB16( in_Q10, out1_Q10 ); RD_Q25[ j + nStates ] = silk_SMLABB( silk_MLA( RD_tmp_Q25, silk_SMULBB( diff_Q10, diff_Q10 ), w_Q5[ i ] ), mu_Q20, rate1_Q5 ); } if( nStates < NLSF_QUANT_DEL_DEC_STATES ) { /* double number of states and copy */ for( j = 0; j < nStates; j++ ) { ind[ j + nStates ][ i ] = ind[ j ][ i ] + 1; } nStates = silk_LSHIFT( nStates, 1 ); for( j = nStates; j < NLSF_QUANT_DEL_DEC_STATES; j++ ) { ind[ j ][ i ] = ind[ j - nStates ][ i ]; } } else if( i > 0 ) { /* sort lower and upper half of RD_Q25, pairwise */ for( j = 0; j < NLSF_QUANT_DEL_DEC_STATES; j++ ) { if( RD_Q25[ j ] > RD_Q25[ j + NLSF_QUANT_DEL_DEC_STATES ] ) { RD_max_Q25[ j ] = RD_Q25[ j ]; RD_min_Q25[ j ] = RD_Q25[ j + NLSF_QUANT_DEL_DEC_STATES ]; RD_Q25[ j ] = RD_min_Q25[ j ]; RD_Q25[ j + NLSF_QUANT_DEL_DEC_STATES ] = RD_max_Q25[ j ]; /* swap prev_out values */ out0_Q10 = prev_out_Q10[ j ]; prev_out_Q10[ j ] = prev_out_Q10[ j + NLSF_QUANT_DEL_DEC_STATES ]; prev_out_Q10[ j + NLSF_QUANT_DEL_DEC_STATES ] = out0_Q10; ind_sort[ j ] = j + NLSF_QUANT_DEL_DEC_STATES; } else { RD_min_Q25[ j ] = RD_Q25[ j ]; RD_max_Q25[ j ] = RD_Q25[ j + NLSF_QUANT_DEL_DEC_STATES ]; ind_sort[ j ] = j; } } /* compare the highest RD values of the winning half with the lowest one in the losing half, and copy if necessary */ /* afterwards ind_sort[] will contain the indices of the NLSF_QUANT_DEL_DEC_STATES winning RD values */ while( 1 ) { min_max_Q25 = silk_int32_MAX; max_min_Q25 = 0; ind_min_max = 0; ind_max_min = 0; for( j = 0; j < NLSF_QUANT_DEL_DEC_STATES; j++ ) { if( min_max_Q25 > RD_max_Q25[ j ] ) { min_max_Q25 = RD_max_Q25[ j ]; ind_min_max = j; } if( max_min_Q25 < RD_min_Q25[ j ] ) { max_min_Q25 = RD_min_Q25[ j ]; ind_max_min = j; } } if( min_max_Q25 >= max_min_Q25 ) { break; } /* copy ind_min_max to ind_max_min */ ind_sort[ ind_max_min ] = ind_sort[ ind_min_max ] ^ NLSF_QUANT_DEL_DEC_STATES; RD_Q25[ ind_max_min ] = RD_Q25[ ind_min_max + NLSF_QUANT_DEL_DEC_STATES ]; prev_out_Q10[ ind_max_min ] = prev_out_Q10[ ind_min_max + NLSF_QUANT_DEL_DEC_STATES ]; RD_min_Q25[ ind_max_min ] = 0; RD_max_Q25[ ind_min_max ] = silk_int32_MAX; silk_memcpy( ind[ ind_max_min ], ind[ ind_min_max ], MAX_LPC_ORDER * sizeof( opus_int8 ) ); } /* increment index if it comes from the upper half */ for( j = 0; j < NLSF_QUANT_DEL_DEC_STATES; j++ ) { ind[ j ][ i ] += silk_RSHIFT( ind_sort[ j ], NLSF_QUANT_DEL_DEC_STATES_LOG2 ); } } else { /* i == 0 */ break; } } /* last sample: find winner, copy indices and return RD value */ ind_tmp = 0; min_Q25 = silk_int32_MAX; for( j = 0; j < 2 * NLSF_QUANT_DEL_DEC_STATES; j++ ) { if( min_Q25 > RD_Q25[ j ] ) { min_Q25 = RD_Q25[ j ]; ind_tmp = j; } } for( j = 0; j < order; j++ ) { indices[ j ] = ind[ ind_tmp & ( NLSF_QUANT_DEL_DEC_STATES - 1 ) ][ j ]; silk_assert( indices[ j ] >= -NLSF_QUANT_MAX_AMPLITUDE_EXT ); silk_assert( indices[ j ] <= NLSF_QUANT_MAX_AMPLITUDE_EXT ); } indices[ 0 ] += silk_RSHIFT( ind_tmp, NLSF_QUANT_DEL_DEC_STATES_LOG2 ); silk_assert( indices[ 0 ] <= NLSF_QUANT_MAX_AMPLITUDE_EXT ); silk_assert( min_Q25 >= 0 ); return min_Q25; }
void silk_warped_autocorrelation_FIX_neon( opus_int32 *corr, /* O Result [order + 1] */ opus_int *scale, /* O Scaling of the correlation vector */ const opus_int16 *input, /* I Input data to correlate */ const opus_int warping_Q16, /* I Warping coefficient */ const opus_int length, /* I Length of input */ const opus_int order /* I Correlation order (even) */ ) { if( ( MAX_SHAPE_LPC_ORDER > 24 ) || ( order < 6 ) ) { silk_warped_autocorrelation_FIX_c( corr, scale, input, warping_Q16, length, order ); } else { opus_int n, i, lsh; opus_int64 corr_QC[ MAX_SHAPE_LPC_ORDER + 1 ] = { 0 }; /* In reverse order */ opus_int64 corr_QC_orderT; int64x2_t lsh_s64x2; const opus_int orderT = ( order + 3 ) & ~3; opus_int64 *corr_QCT; opus_int32 *input_QS; VARDECL( opus_int32, input_QST ); VARDECL( opus_int32, state ); SAVE_STACK; /* Order must be even */ silk_assert( ( order & 1 ) == 0 ); silk_assert( 2 * QS - QC >= 0 ); ALLOC( input_QST, length + 2 * MAX_SHAPE_LPC_ORDER, opus_int32 ); input_QS = input_QST; /* input_QS has zero paddings in the beginning and end. */ vst1q_s32( input_QS, vdupq_n_s32( 0 ) ); input_QS += 4; vst1q_s32( input_QS, vdupq_n_s32( 0 ) ); input_QS += 4; vst1q_s32( input_QS, vdupq_n_s32( 0 ) ); input_QS += 4; vst1q_s32( input_QS, vdupq_n_s32( 0 ) ); input_QS += 4; vst1q_s32( input_QS, vdupq_n_s32( 0 ) ); input_QS += 4; vst1q_s32( input_QS, vdupq_n_s32( 0 ) ); input_QS += 4; /* Loop over samples */ for( n = 0; n < length - 7; n += 8, input_QS += 8 ) { const int16x8_t t0_s16x4 = vld1q_s16( input + n ); vst1q_s32( input_QS + 0, vshll_n_s16( vget_low_s16( t0_s16x4 ), QS ) ); vst1q_s32( input_QS + 4, vshll_n_s16( vget_high_s16( t0_s16x4 ), QS ) ); } for( ; n < length; n++, input_QS++ ) { input_QS[ 0 ] = silk_LSHIFT32( (opus_int32)input[ n ], QS ); } vst1q_s32( input_QS, vdupq_n_s32( 0 ) ); input_QS += 4; vst1q_s32( input_QS, vdupq_n_s32( 0 ) ); input_QS += 4; vst1q_s32( input_QS, vdupq_n_s32( 0 ) ); input_QS += 4; vst1q_s32( input_QS, vdupq_n_s32( 0 ) ); input_QS += 4; vst1q_s32( input_QS, vdupq_n_s32( 0 ) ); input_QS += 4; vst1q_s32( input_QS, vdupq_n_s32( 0 ) ); input_QS = input_QST + MAX_SHAPE_LPC_ORDER - orderT; /* The following loop runs ( length + order ) times, with ( order ) extra epilogues. */ /* The zero paddings in input_QS guarantee corr_QC's correctness even with the extra epilogues. */ /* The values of state_QS will be polluted by the extra epilogues, however they are temporary values. */ /* Keep the C code here to help understand the intrinsics optimization. */ /* { opus_int32 state_QS[ 2 ][ MAX_SHAPE_LPC_ORDER + 1 ] = { 0 }; opus_int32 *state_QST[ 3 ]; state_QST[ 0 ] = state_QS[ 0 ]; state_QST[ 1 ] = state_QS[ 1 ]; for( n = 0; n < length + order; n++, input_QS++ ) { state_QST[ 0 ][ orderT ] = input_QS[ orderT ]; for( i = 0; i < orderT; i++ ) { corr_QC[ i ] += silk_RSHIFT64( silk_SMULL( state_QST[ 0 ][ i ], input_QS[ i ] ), 2 * QS - QC ); state_QST[ 1 ][ i ] = silk_SMLAWB( state_QST[ 1 ][ i + 1 ], state_QST[ 0 ][ i ] - state_QST[ 0 ][ i + 1 ], warping_Q16 ); } state_QST[ 2 ] = state_QST[ 0 ]; state_QST[ 0 ] = state_QST[ 1 ]; state_QST[ 1 ] = state_QST[ 2 ]; } } */ { const int32x4_t warping_Q16_s32x4 = vdupq_n_s32( warping_Q16 << 15 ); const opus_int32 *in = input_QS + orderT; opus_int o = orderT; int32x4_t state_QS_s32x4[ 3 ][ 2 ]; ALLOC( state, length + orderT, opus_int32 ); state_QS_s32x4[ 2 ][ 1 ] = vdupq_n_s32( 0 ); /* Calculate 8 taps of all inputs in each loop. */ do { state_QS_s32x4[ 0 ][ 0 ] = state_QS_s32x4[ 0 ][ 1 ] = state_QS_s32x4[ 1 ][ 0 ] = state_QS_s32x4[ 1 ][ 1 ] = vdupq_n_s32( 0 ); n = 0; do { calc_corr( input_QS + n, corr_QC, o - 8, state_QS_s32x4[ 0 ][ 0 ] ); calc_corr( input_QS + n, corr_QC, o - 4, state_QS_s32x4[ 0 ][ 1 ] ); state_QS_s32x4[ 2 ][ 1 ] = vld1q_s32( in + n ); vst1q_lane_s32( state + n, state_QS_s32x4[ 0 ][ 0 ], 0 ); state_QS_s32x4[ 2 ][ 0 ] = vextq_s32( state_QS_s32x4[ 0 ][ 0 ], state_QS_s32x4[ 0 ][ 1 ], 1 ); state_QS_s32x4[ 2 ][ 1 ] = vextq_s32( state_QS_s32x4[ 0 ][ 1 ], state_QS_s32x4[ 2 ][ 1 ], 1 ); state_QS_s32x4[ 0 ][ 0 ] = calc_state( state_QS_s32x4[ 0 ][ 0 ], state_QS_s32x4[ 2 ][ 0 ], state_QS_s32x4[ 1 ][ 0 ], warping_Q16_s32x4 ); state_QS_s32x4[ 0 ][ 1 ] = calc_state( state_QS_s32x4[ 0 ][ 1 ], state_QS_s32x4[ 2 ][ 1 ], state_QS_s32x4[ 1 ][ 1 ], warping_Q16_s32x4 ); state_QS_s32x4[ 1 ][ 0 ] = state_QS_s32x4[ 2 ][ 0 ]; state_QS_s32x4[ 1 ][ 1 ] = state_QS_s32x4[ 2 ][ 1 ]; } while( ++n < ( length + order ) ); in = state; o -= 8; } while( o > 4 ); if( o ) { /* Calculate the last 4 taps of all inputs. */ opus_int32 *stateT = state; silk_assert( o == 4 ); state_QS_s32x4[ 0 ][ 0 ] = state_QS_s32x4[ 1 ][ 0 ] = vdupq_n_s32( 0 ); n = length + order; do { calc_corr( input_QS, corr_QC, 0, state_QS_s32x4[ 0 ][ 0 ] ); state_QS_s32x4[ 2 ][ 0 ] = vld1q_s32( stateT ); vst1q_lane_s32( stateT, state_QS_s32x4[ 0 ][ 0 ], 0 ); state_QS_s32x4[ 2 ][ 0 ] = vextq_s32( state_QS_s32x4[ 0 ][ 0 ], state_QS_s32x4[ 2 ][ 0 ], 1 ); state_QS_s32x4[ 0 ][ 0 ] = calc_state( state_QS_s32x4[ 0 ][ 0 ], state_QS_s32x4[ 2 ][ 0 ], state_QS_s32x4[ 1 ][ 0 ], warping_Q16_s32x4 ); state_QS_s32x4[ 1 ][ 0 ] = state_QS_s32x4[ 2 ][ 0 ]; input_QS++; stateT++; } while( --n ); } } { const opus_int16 *inputT = input; int32x4_t t_s32x4; int64x1_t t_s64x1; int64x2_t t_s64x2 = vdupq_n_s64( 0 ); for( n = 0; n <= length - 8; n += 8 ) { int16x8_t input_s16x8 = vld1q_s16( inputT ); t_s32x4 = vmull_s16( vget_low_s16( input_s16x8 ), vget_low_s16( input_s16x8 ) ); t_s32x4 = vmlal_s16( t_s32x4, vget_high_s16( input_s16x8 ), vget_high_s16( input_s16x8 ) ); t_s64x2 = vaddw_s32( t_s64x2, vget_low_s32( t_s32x4 ) ); t_s64x2 = vaddw_s32( t_s64x2, vget_high_s32( t_s32x4 ) ); inputT += 8; } t_s64x1 = vadd_s64( vget_low_s64( t_s64x2 ), vget_high_s64( t_s64x2 ) ); corr_QC_orderT = vget_lane_s64( t_s64x1, 0 ); for( ; n < length; n++ ) { corr_QC_orderT += silk_SMULL( input[ n ], input[ n ] ); } corr_QC_orderT = silk_LSHIFT64( corr_QC_orderT, QC ); corr_QC[ orderT ] = corr_QC_orderT; } corr_QCT = corr_QC + orderT - order; lsh = silk_CLZ64( corr_QC_orderT ) - 35; lsh = silk_LIMIT( lsh, -12 - QC, 30 - QC ); *scale = -( QC + lsh ); silk_assert( *scale >= -30 && *scale <= 12 ); lsh_s64x2 = vdupq_n_s64( lsh ); for( i = 0; i <= order - 3; i += 4 ) { int32x4_t corr_s32x4; int64x2_t corr_QC0_s64x2, corr_QC1_s64x2; corr_QC0_s64x2 = vld1q_s64( corr_QCT + i ); corr_QC1_s64x2 = vld1q_s64( corr_QCT + i + 2 ); corr_QC0_s64x2 = vshlq_s64( corr_QC0_s64x2, lsh_s64x2 ); corr_QC1_s64x2 = vshlq_s64( corr_QC1_s64x2, lsh_s64x2 ); corr_s32x4 = vcombine_s32( vmovn_s64( corr_QC1_s64x2 ), vmovn_s64( corr_QC0_s64x2 ) ); corr_s32x4 = vrev64q_s32( corr_s32x4 ); vst1q_s32( corr + order - i - 3, corr_s32x4 ); } if( lsh >= 0 ) { for( ; i < order + 1; i++ ) { corr[ order - i ] = (opus_int32)silk_CHECK_FIT32( silk_LSHIFT64( corr_QCT[ i ], lsh ) ); } } else { for( ; i < order + 1; i++ ) { corr[ order - i ] = (opus_int32)silk_CHECK_FIT32( silk_RSHIFT64( corr_QCT[ i ], -lsh ) ); } } silk_assert( corr_QCT[ order ] >= 0 ); /* If breaking, decrease QC*/ RESTORE_STACK; } #ifdef OPUS_CHECK_ASM { opus_int32 corr_c[ MAX_SHAPE_LPC_ORDER + 1 ]; opus_int scale_c; silk_warped_autocorrelation_FIX_c( corr_c, &scale_c, input, warping_Q16, length, order ); silk_assert( !memcmp( corr_c, corr, sizeof( corr_c[ 0 ] ) * ( order + 1 ) ) ); silk_assert( scale_c == *scale ); } #endif }
/* encControl->payloadSize_ms is set to */ opus_int silk_Encode( /* O Returns error code */ void *encState, /* I/O State */ silk_EncControlStruct *encControl, /* I Control status */ const opus_int16 *samplesIn, /* I Speech sample input vector */ opus_int nSamplesIn, /* I Number of samples in input vector */ ec_enc *psRangeEnc, /* I/O Compressor data structure */ opus_int32 *nBytesOut, /* I/O Number of bytes in payload (input: Max bytes) */ const opus_int prefillFlag /* I Flag to indicate prefilling buffers no coding */ ) { opus_int n, i, nBits, flags, tmp_payloadSize_ms = 0, tmp_complexity = 0, ret = 0; opus_int nSamplesToBuffer, nSamplesToBufferMax, nBlocksOf10ms; opus_int nSamplesFromInput = 0, nSamplesFromInputMax; opus_int speech_act_thr_for_switch_Q8; opus_int32 TargetRate_bps, MStargetRates_bps[ 2 ], channelRate_bps, LBRR_symbol, sum; silk_encoder *psEnc = ( silk_encoder * )encState; VARDECL( opus_int16, buf ); opus_int transition, curr_block, tot_blocks; SAVE_STACK; if (encControl->reducedDependency) { psEnc->state_Fxx[0].sCmn.first_frame_after_reset = 1; psEnc->state_Fxx[1].sCmn.first_frame_after_reset = 1; } psEnc->state_Fxx[ 0 ].sCmn.nFramesEncoded = psEnc->state_Fxx[ 1 ].sCmn.nFramesEncoded = 0; /* Check values in encoder control structure */ if( ( ret = check_control_input( encControl ) ) != 0 ) { silk_assert( 0 ); RESTORE_STACK; return ret; } encControl->switchReady = 0; if( encControl->nChannelsInternal > psEnc->nChannelsInternal ) { /* Mono -> Stereo transition: init state of second channel and stereo state */ ret += silk_init_encoder( &psEnc->state_Fxx[ 1 ], psEnc->state_Fxx[ 0 ].sCmn.arch ); silk_memset( psEnc->sStereo.pred_prev_Q13, 0, sizeof( psEnc->sStereo.pred_prev_Q13 ) ); silk_memset( psEnc->sStereo.sSide, 0, sizeof( psEnc->sStereo.sSide ) ); psEnc->sStereo.mid_side_amp_Q0[ 0 ] = 0; psEnc->sStereo.mid_side_amp_Q0[ 1 ] = 1; psEnc->sStereo.mid_side_amp_Q0[ 2 ] = 0; psEnc->sStereo.mid_side_amp_Q0[ 3 ] = 1; psEnc->sStereo.width_prev_Q14 = 0; psEnc->sStereo.smth_width_Q14 = SILK_FIX_CONST( 1, 14 ); if( psEnc->nChannelsAPI == 2 ) { silk_memcpy( &psEnc->state_Fxx[ 1 ].sCmn.resampler_state, &psEnc->state_Fxx[ 0 ].sCmn.resampler_state, sizeof( silk_resampler_state_struct ) ); silk_memcpy( &psEnc->state_Fxx[ 1 ].sCmn.In_HP_State, &psEnc->state_Fxx[ 0 ].sCmn.In_HP_State, sizeof( psEnc->state_Fxx[ 1 ].sCmn.In_HP_State ) ); } } transition = (encControl->payloadSize_ms != psEnc->state_Fxx[ 0 ].sCmn.PacketSize_ms) || (psEnc->nChannelsInternal != encControl->nChannelsInternal); psEnc->nChannelsAPI = encControl->nChannelsAPI; psEnc->nChannelsInternal = encControl->nChannelsInternal; nBlocksOf10ms = silk_DIV32( 100 * nSamplesIn, encControl->API_sampleRate ); tot_blocks = ( nBlocksOf10ms > 1 ) ? nBlocksOf10ms >> 1 : 1; curr_block = 0; if( prefillFlag ) { /* Only accept input length of 10 ms */ if( nBlocksOf10ms != 1 ) { silk_assert( 0 ); RESTORE_STACK; return SILK_ENC_INPUT_INVALID_NO_OF_SAMPLES; } /* Reset Encoder */ for( n = 0; n < encControl->nChannelsInternal; n++ ) { ret = silk_init_encoder( &psEnc->state_Fxx[ n ], psEnc->state_Fxx[ n ].sCmn.arch ); silk_assert( !ret ); } tmp_payloadSize_ms = encControl->payloadSize_ms; encControl->payloadSize_ms = 10; tmp_complexity = encControl->complexity; encControl->complexity = 0; for( n = 0; n < encControl->nChannelsInternal; n++ ) { psEnc->state_Fxx[ n ].sCmn.controlled_since_last_payload = 0; psEnc->state_Fxx[ n ].sCmn.prefillFlag = 1; } } else { /* Only accept input lengths that are a multiple of 10 ms */ if( nBlocksOf10ms * encControl->API_sampleRate != 100 * nSamplesIn || nSamplesIn < 0 ) { silk_assert( 0 ); RESTORE_STACK; return SILK_ENC_INPUT_INVALID_NO_OF_SAMPLES; } /* Make sure no more than one packet can be produced */ if( 1000 * (opus_int32)nSamplesIn > encControl->payloadSize_ms * encControl->API_sampleRate ) { silk_assert( 0 ); RESTORE_STACK; return SILK_ENC_INPUT_INVALID_NO_OF_SAMPLES; } } TargetRate_bps = silk_RSHIFT32( encControl->bitRate, encControl->nChannelsInternal - 1 ); for( n = 0; n < encControl->nChannelsInternal; n++ ) { /* Force the side channel to the same rate as the mid */ opus_int force_fs_kHz = (n==1) ? psEnc->state_Fxx[0].sCmn.fs_kHz : 0; if( ( ret = silk_control_encoder( &psEnc->state_Fxx[ n ], encControl, TargetRate_bps, psEnc->allowBandwidthSwitch, n, force_fs_kHz ) ) != 0 ) { silk_assert( 0 ); RESTORE_STACK; return ret; } if( psEnc->state_Fxx[n].sCmn.first_frame_after_reset || transition ) { for( i = 0; i < psEnc->state_Fxx[ 0 ].sCmn.nFramesPerPacket; i++ ) { psEnc->state_Fxx[ n ].sCmn.LBRR_flags[ i ] = 0; } } psEnc->state_Fxx[ n ].sCmn.inDTX = psEnc->state_Fxx[ n ].sCmn.useDTX; } silk_assert( encControl->nChannelsInternal == 1 || psEnc->state_Fxx[ 0 ].sCmn.fs_kHz == psEnc->state_Fxx[ 1 ].sCmn.fs_kHz ); /* Input buffering/resampling and encoding */ nSamplesToBufferMax = 10 * nBlocksOf10ms * psEnc->state_Fxx[ 0 ].sCmn.fs_kHz; nSamplesFromInputMax = silk_DIV32_16( nSamplesToBufferMax * psEnc->state_Fxx[ 0 ].sCmn.API_fs_Hz, psEnc->state_Fxx[ 0 ].sCmn.fs_kHz * 1000 ); ALLOC( buf, nSamplesFromInputMax, opus_int16 ); while( 1 ) { nSamplesToBuffer = psEnc->state_Fxx[ 0 ].sCmn.frame_length - psEnc->state_Fxx[ 0 ].sCmn.inputBufIx; nSamplesToBuffer = silk_min( nSamplesToBuffer, nSamplesToBufferMax ); nSamplesFromInput = silk_DIV32_16( nSamplesToBuffer * psEnc->state_Fxx[ 0 ].sCmn.API_fs_Hz, psEnc->state_Fxx[ 0 ].sCmn.fs_kHz * 1000 ); /* Resample and write to buffer */ if( encControl->nChannelsAPI == 2 && encControl->nChannelsInternal == 2 ) { opus_int id = psEnc->state_Fxx[ 0 ].sCmn.nFramesEncoded; for( n = 0; n < nSamplesFromInput; n++ ) { buf[ n ] = samplesIn[ 2 * n ]; } /* Making sure to start both resamplers from the same state when switching from mono to stereo */ if( psEnc->nPrevChannelsInternal == 1 && id==0 ) { silk_memcpy( &psEnc->state_Fxx[ 1 ].sCmn.resampler_state, &psEnc->state_Fxx[ 0 ].sCmn.resampler_state, sizeof(psEnc->state_Fxx[ 1 ].sCmn.resampler_state)); } ret += silk_resampler( &psEnc->state_Fxx[ 0 ].sCmn.resampler_state, &psEnc->state_Fxx[ 0 ].sCmn.inputBuf[ psEnc->state_Fxx[ 0 ].sCmn.inputBufIx + 2 ], buf, nSamplesFromInput ); psEnc->state_Fxx[ 0 ].sCmn.inputBufIx += nSamplesToBuffer; nSamplesToBuffer = psEnc->state_Fxx[ 1 ].sCmn.frame_length - psEnc->state_Fxx[ 1 ].sCmn.inputBufIx; nSamplesToBuffer = silk_min( nSamplesToBuffer, 10 * nBlocksOf10ms * psEnc->state_Fxx[ 1 ].sCmn.fs_kHz ); for( n = 0; n < nSamplesFromInput; n++ ) { buf[ n ] = samplesIn[ 2 * n + 1 ]; } ret += silk_resampler( &psEnc->state_Fxx[ 1 ].sCmn.resampler_state, &psEnc->state_Fxx[ 1 ].sCmn.inputBuf[ psEnc->state_Fxx[ 1 ].sCmn.inputBufIx + 2 ], buf, nSamplesFromInput ); psEnc->state_Fxx[ 1 ].sCmn.inputBufIx += nSamplesToBuffer; } else if( encControl->nChannelsAPI == 2 && encControl->nChannelsInternal == 1 ) { /* Combine left and right channels before resampling */ for( n = 0; n < nSamplesFromInput; n++ ) { sum = samplesIn[ 2 * n ] + samplesIn[ 2 * n + 1 ]; buf[ n ] = (opus_int16)silk_RSHIFT_ROUND( sum, 1 ); } ret += silk_resampler( &psEnc->state_Fxx[ 0 ].sCmn.resampler_state, &psEnc->state_Fxx[ 0 ].sCmn.inputBuf[ psEnc->state_Fxx[ 0 ].sCmn.inputBufIx + 2 ], buf, nSamplesFromInput ); /* On the first mono frame, average the results for the two resampler states */ if( psEnc->nPrevChannelsInternal == 2 && psEnc->state_Fxx[ 0 ].sCmn.nFramesEncoded == 0 ) { ret += silk_resampler( &psEnc->state_Fxx[ 1 ].sCmn.resampler_state, &psEnc->state_Fxx[ 1 ].sCmn.inputBuf[ psEnc->state_Fxx[ 1 ].sCmn.inputBufIx + 2 ], buf, nSamplesFromInput ); for( n = 0; n < psEnc->state_Fxx[ 0 ].sCmn.frame_length; n++ ) { psEnc->state_Fxx[ 0 ].sCmn.inputBuf[ psEnc->state_Fxx[ 0 ].sCmn.inputBufIx+n+2 ] = silk_RSHIFT(psEnc->state_Fxx[ 0 ].sCmn.inputBuf[ psEnc->state_Fxx[ 0 ].sCmn.inputBufIx+n+2 ] + psEnc->state_Fxx[ 1 ].sCmn.inputBuf[ psEnc->state_Fxx[ 1 ].sCmn.inputBufIx+n+2 ], 1); } } psEnc->state_Fxx[ 0 ].sCmn.inputBufIx += nSamplesToBuffer; } else { silk_assert( encControl->nChannelsAPI == 1 && encControl->nChannelsInternal == 1 ); silk_memcpy(buf, samplesIn, nSamplesFromInput*sizeof(opus_int16)); ret += silk_resampler( &psEnc->state_Fxx[ 0 ].sCmn.resampler_state, &psEnc->state_Fxx[ 0 ].sCmn.inputBuf[ psEnc->state_Fxx[ 0 ].sCmn.inputBufIx + 2 ], buf, nSamplesFromInput ); psEnc->state_Fxx[ 0 ].sCmn.inputBufIx += nSamplesToBuffer; } samplesIn += nSamplesFromInput * encControl->nChannelsAPI; nSamplesIn -= nSamplesFromInput; /* Default */ psEnc->allowBandwidthSwitch = 0; /* Silk encoder */ if( psEnc->state_Fxx[ 0 ].sCmn.inputBufIx >= psEnc->state_Fxx[ 0 ].sCmn.frame_length ) { /* Enough data in input buffer, so encode */ silk_assert( psEnc->state_Fxx[ 0 ].sCmn.inputBufIx == psEnc->state_Fxx[ 0 ].sCmn.frame_length ); silk_assert( encControl->nChannelsInternal == 1 || psEnc->state_Fxx[ 1 ].sCmn.inputBufIx == psEnc->state_Fxx[ 1 ].sCmn.frame_length ); /* Deal with LBRR data */ if( psEnc->state_Fxx[ 0 ].sCmn.nFramesEncoded == 0 && !prefillFlag ) { /* Create space at start of payload for VAD and FEC flags */ opus_uint8 iCDF[ 2 ] = { 0, 0 }; iCDF[ 0 ] = 256 - silk_RSHIFT( 256, ( psEnc->state_Fxx[ 0 ].sCmn.nFramesPerPacket + 1 ) * encControl->nChannelsInternal ); ec_enc_icdf( psRangeEnc, 0, iCDF, 8 ); /* Encode any LBRR data from previous packet */ /* Encode LBRR flags */ for( n = 0; n < encControl->nChannelsInternal; n++ ) { LBRR_symbol = 0; for( i = 0; i < psEnc->state_Fxx[ n ].sCmn.nFramesPerPacket; i++ ) { LBRR_symbol |= silk_LSHIFT( psEnc->state_Fxx[ n ].sCmn.LBRR_flags[ i ], i ); } psEnc->state_Fxx[ n ].sCmn.LBRR_flag = LBRR_symbol > 0 ? 1 : 0; if( LBRR_symbol && psEnc->state_Fxx[ n ].sCmn.nFramesPerPacket > 1 ) { ec_enc_icdf( psRangeEnc, LBRR_symbol - 1, silk_LBRR_flags_iCDF_ptr[ psEnc->state_Fxx[ n ].sCmn.nFramesPerPacket - 2 ], 8 ); } } /* Code LBRR indices and excitation signals */ for( i = 0; i < psEnc->state_Fxx[ 0 ].sCmn.nFramesPerPacket; i++ ) { for( n = 0; n < encControl->nChannelsInternal; n++ ) { if( psEnc->state_Fxx[ n ].sCmn.LBRR_flags[ i ] ) { opus_int condCoding; if( encControl->nChannelsInternal == 2 && n == 0 ) { silk_stereo_encode_pred( psRangeEnc, psEnc->sStereo.predIx[ i ] ); /* For LBRR data there's no need to code the mid-only flag if the side-channel LBRR flag is set */ if( psEnc->state_Fxx[ 1 ].sCmn.LBRR_flags[ i ] == 0 ) { silk_stereo_encode_mid_only( psRangeEnc, psEnc->sStereo.mid_only_flags[ i ] ); } } /* Use conditional coding if previous frame available */ if( i > 0 && psEnc->state_Fxx[ n ].sCmn.LBRR_flags[ i - 1 ] ) { condCoding = CODE_CONDITIONALLY; } else { condCoding = CODE_INDEPENDENTLY; } silk_encode_indices( &psEnc->state_Fxx[ n ].sCmn, psRangeEnc, i, 1, condCoding ); silk_encode_pulses( psRangeEnc, psEnc->state_Fxx[ n ].sCmn.indices_LBRR[i].signalType, psEnc->state_Fxx[ n ].sCmn.indices_LBRR[i].quantOffsetType, psEnc->state_Fxx[ n ].sCmn.pulses_LBRR[ i ], psEnc->state_Fxx[ n ].sCmn.frame_length ); } } } /* Reset LBRR flags */ for( n = 0; n < encControl->nChannelsInternal; n++ ) { silk_memset( psEnc->state_Fxx[ n ].sCmn.LBRR_flags, 0, sizeof( psEnc->state_Fxx[ n ].sCmn.LBRR_flags ) ); } psEnc->nBitsUsedLBRR = ec_tell( psRangeEnc ); } silk_HP_variable_cutoff( psEnc->state_Fxx ); /* Total target bits for packet */ nBits = silk_DIV32_16( silk_MUL( encControl->bitRate, encControl->payloadSize_ms ), 1000 ); /* Subtract bits used for LBRR */ if( !prefillFlag ) { nBits -= psEnc->nBitsUsedLBRR; } /* Divide by number of uncoded frames left in packet */ nBits = silk_DIV32_16( nBits, psEnc->state_Fxx[ 0 ].sCmn.nFramesPerPacket ); /* Convert to bits/second */ if( encControl->payloadSize_ms == 10 ) { TargetRate_bps = silk_SMULBB( nBits, 100 ); } else { TargetRate_bps = silk_SMULBB( nBits, 50 ); } /* Subtract fraction of bits in excess of target in previous frames and packets */ TargetRate_bps -= silk_DIV32_16( silk_MUL( psEnc->nBitsExceeded, 1000 ), BITRESERVOIR_DECAY_TIME_MS ); if( !prefillFlag && psEnc->state_Fxx[ 0 ].sCmn.nFramesEncoded > 0 ) { /* Compare actual vs target bits so far in this packet */ opus_int32 bitsBalance = ec_tell( psRangeEnc ) - psEnc->nBitsUsedLBRR - nBits * psEnc->state_Fxx[ 0 ].sCmn.nFramesEncoded; TargetRate_bps -= silk_DIV32_16( silk_MUL( bitsBalance, 1000 ), BITRESERVOIR_DECAY_TIME_MS ); } /* Never exceed input bitrate */ TargetRate_bps = silk_LIMIT( TargetRate_bps, encControl->bitRate, 5000 ); /* Convert Left/Right to Mid/Side */ if( encControl->nChannelsInternal == 2 ) { silk_stereo_LR_to_MS( &psEnc->sStereo, &psEnc->state_Fxx[ 0 ].sCmn.inputBuf[ 2 ], &psEnc->state_Fxx[ 1 ].sCmn.inputBuf[ 2 ], psEnc->sStereo.predIx[ psEnc->state_Fxx[ 0 ].sCmn.nFramesEncoded ], &psEnc->sStereo.mid_only_flags[ psEnc->state_Fxx[ 0 ].sCmn.nFramesEncoded ], MStargetRates_bps, TargetRate_bps, psEnc->state_Fxx[ 0 ].sCmn.speech_activity_Q8, encControl->toMono, psEnc->state_Fxx[ 0 ].sCmn.fs_kHz, psEnc->state_Fxx[ 0 ].sCmn.frame_length ); if( psEnc->sStereo.mid_only_flags[ psEnc->state_Fxx[ 0 ].sCmn.nFramesEncoded ] == 0 ) { /* Reset side channel encoder memory for first frame with side coding */ if( psEnc->prev_decode_only_middle == 1 ) { silk_memset( &psEnc->state_Fxx[ 1 ].sShape, 0, sizeof( psEnc->state_Fxx[ 1 ].sShape ) ); silk_memset( &psEnc->state_Fxx[ 1 ].sPrefilt, 0, sizeof( psEnc->state_Fxx[ 1 ].sPrefilt ) ); silk_memset( &psEnc->state_Fxx[ 1 ].sCmn.sNSQ, 0, sizeof( psEnc->state_Fxx[ 1 ].sCmn.sNSQ ) ); silk_memset( psEnc->state_Fxx[ 1 ].sCmn.prev_NLSFq_Q15, 0, sizeof( psEnc->state_Fxx[ 1 ].sCmn.prev_NLSFq_Q15 ) ); silk_memset( &psEnc->state_Fxx[ 1 ].sCmn.sLP.In_LP_State, 0, sizeof( psEnc->state_Fxx[ 1 ].sCmn.sLP.In_LP_State ) ); psEnc->state_Fxx[ 1 ].sCmn.prevLag = 100; psEnc->state_Fxx[ 1 ].sCmn.sNSQ.lagPrev = 100; psEnc->state_Fxx[ 1 ].sShape.LastGainIndex = 10; psEnc->state_Fxx[ 1 ].sCmn.prevSignalType = TYPE_NO_VOICE_ACTIVITY; psEnc->state_Fxx[ 1 ].sCmn.sNSQ.prev_gain_Q16 = 65536; psEnc->state_Fxx[ 1 ].sCmn.first_frame_after_reset = 1; } silk_encode_do_VAD_Fxx( &psEnc->state_Fxx[ 1 ] ); } else { psEnc->state_Fxx[ 1 ].sCmn.VAD_flags[ psEnc->state_Fxx[ 0 ].sCmn.nFramesEncoded ] = 0; } if( !prefillFlag ) { silk_stereo_encode_pred( psRangeEnc, psEnc->sStereo.predIx[ psEnc->state_Fxx[ 0 ].sCmn.nFramesEncoded ] ); if( psEnc->state_Fxx[ 1 ].sCmn.VAD_flags[ psEnc->state_Fxx[ 0 ].sCmn.nFramesEncoded ] == 0 ) { silk_stereo_encode_mid_only( psRangeEnc, psEnc->sStereo.mid_only_flags[ psEnc->state_Fxx[ 0 ].sCmn.nFramesEncoded ] ); } } } else { /* Buffering */ silk_memcpy( psEnc->state_Fxx[ 0 ].sCmn.inputBuf, psEnc->sStereo.sMid, 2 * sizeof( opus_int16 ) ); silk_memcpy( psEnc->sStereo.sMid, &psEnc->state_Fxx[ 0 ].sCmn.inputBuf[ psEnc->state_Fxx[ 0 ].sCmn.frame_length ], 2 * sizeof( opus_int16 ) ); } silk_encode_do_VAD_Fxx( &psEnc->state_Fxx[ 0 ] ); /* Encode */ for( n = 0; n < encControl->nChannelsInternal; n++ ) { opus_int maxBits, useCBR; /* Handling rate constraints */ maxBits = encControl->maxBits; if( tot_blocks == 2 && curr_block == 0 ) { maxBits = maxBits * 3 / 5; } else if( tot_blocks == 3 ) { if( curr_block == 0 ) { maxBits = maxBits * 2 / 5; } else if( curr_block == 1 ) { maxBits = maxBits * 3 / 4; } } useCBR = encControl->useCBR && curr_block == tot_blocks - 1; if( encControl->nChannelsInternal == 1 ) { channelRate_bps = TargetRate_bps; } else { channelRate_bps = MStargetRates_bps[ n ]; if( n == 0 && MStargetRates_bps[ 1 ] > 0 ) { useCBR = 0; /* Give mid up to 1/2 of the max bits for that frame */ maxBits -= encControl->maxBits / ( tot_blocks * 2 ); } } if( channelRate_bps > 0 ) { opus_int condCoding; silk_control_SNR( &psEnc->state_Fxx[ n ].sCmn, channelRate_bps ); /* Use independent coding if no previous frame available */ if( psEnc->state_Fxx[ 0 ].sCmn.nFramesEncoded - n <= 0 ) { condCoding = CODE_INDEPENDENTLY; } else if( n > 0 && psEnc->prev_decode_only_middle ) { /* If we skipped a side frame in this packet, we don't need LTP scaling; the LTP state is well-defined. */ condCoding = CODE_INDEPENDENTLY_NO_LTP_SCALING; } else { condCoding = CODE_CONDITIONALLY; } if( ( ret = silk_encode_frame_Fxx( &psEnc->state_Fxx[ n ], nBytesOut, psRangeEnc, condCoding, maxBits, useCBR ) ) != 0 ) { silk_assert( 0 ); } } psEnc->state_Fxx[ n ].sCmn.controlled_since_last_payload = 0; psEnc->state_Fxx[ n ].sCmn.inputBufIx = 0; psEnc->state_Fxx[ n ].sCmn.nFramesEncoded++; } psEnc->prev_decode_only_middle = psEnc->sStereo.mid_only_flags[ psEnc->state_Fxx[ 0 ].sCmn.nFramesEncoded - 1 ]; /* Insert VAD and FEC flags at beginning of bitstream */ if( *nBytesOut > 0 && psEnc->state_Fxx[ 0 ].sCmn.nFramesEncoded == psEnc->state_Fxx[ 0 ].sCmn.nFramesPerPacket) { flags = 0; for( n = 0; n < encControl->nChannelsInternal; n++ ) { for( i = 0; i < psEnc->state_Fxx[ n ].sCmn.nFramesPerPacket; i++ ) { flags = silk_LSHIFT( flags, 1 ); flags |= psEnc->state_Fxx[ n ].sCmn.VAD_flags[ i ]; } flags = silk_LSHIFT( flags, 1 ); flags |= psEnc->state_Fxx[ n ].sCmn.LBRR_flag; } if( !prefillFlag ) { ec_enc_patch_initial_bits( psRangeEnc, flags, ( psEnc->state_Fxx[ 0 ].sCmn.nFramesPerPacket + 1 ) * encControl->nChannelsInternal ); } /* Return zero bytes if all channels DTXed */ if( psEnc->state_Fxx[ 0 ].sCmn.inDTX && ( encControl->nChannelsInternal == 1 || psEnc->state_Fxx[ 1 ].sCmn.inDTX ) ) { *nBytesOut = 0; } psEnc->nBitsExceeded += *nBytesOut * 8; psEnc->nBitsExceeded -= silk_DIV32_16( silk_MUL( encControl->bitRate, encControl->payloadSize_ms ), 1000 ); psEnc->nBitsExceeded = silk_LIMIT( psEnc->nBitsExceeded, 0, 10000 ); /* Update flag indicating if bandwidth switching is allowed */ speech_act_thr_for_switch_Q8 = (opus_int) silk_SMLAWB( SILK_FIX_CONST( SPEECH_ACTIVITY_DTX_THRES, 8 ), SILK_FIX_CONST( ( 1 - SPEECH_ACTIVITY_DTX_THRES ) / MAX_BANDWIDTH_SWITCH_DELAY_MS, 16 + 8 ), psEnc->timeSinceSwitchAllowed_ms ); if( psEnc->state_Fxx[ 0 ].sCmn.speech_activity_Q8 < speech_act_thr_for_switch_Q8 ) { psEnc->allowBandwidthSwitch = 1; psEnc->timeSinceSwitchAllowed_ms = 0; } else { psEnc->allowBandwidthSwitch = 0; psEnc->timeSinceSwitchAllowed_ms += encControl->payloadSize_ms; } } if( nSamplesIn == 0 ) { break; } } else { break; } curr_block++; } psEnc->nPrevChannelsInternal = encControl->nChannelsInternal; encControl->allowBandwidthSwitch = psEnc->allowBandwidthSwitch; encControl->inWBmodeWithoutVariableLP = psEnc->state_Fxx[ 0 ].sCmn.fs_kHz == 16 && psEnc->state_Fxx[ 0 ].sCmn.sLP.mode == 0; encControl->internalSampleRate = silk_SMULBB( psEnc->state_Fxx[ 0 ].sCmn.fs_kHz, 1000 ); encControl->stereoWidth_Q14 = encControl->toMono ? 0 : psEnc->sStereo.smth_width_Q14; if( prefillFlag ) { encControl->payloadSize_ms = tmp_payloadSize_ms; encControl->complexity = tmp_complexity; for( n = 0; n < encControl->nChannelsInternal; n++ ) { psEnc->state_Fxx[ n ].sCmn.controlled_since_last_payload = 0; psEnc->state_Fxx[ n ].sCmn.prefillFlag = 0; } } RESTORE_STACK; return ret; }
/* Convert Left/Right stereo signal to adaptive Mid/Side representation */ void silk_stereo_LR_to_MS( stereo_enc_state *state, /* I/O State */ opus_int16 x1[], /* I/O Left input signal, becomes mid signal */ opus_int16 x2[], /* I/O Right input signal, becomes side signal */ opus_int8 ix[ 2 ][ 3 ], /* O Quantization indices */ opus_int8 *mid_only_flag, /* O Flag: only mid signal coded */ opus_int32 mid_side_rates_bps[], /* O Bitrates for mid and side signals */ opus_int32 total_rate_bps, /* I Total bitrate */ opus_int prev_speech_act_Q8, /* I Speech activity level in previous frame */ opus_int toMono, /* I Last frame before a stereo->mono transition */ opus_int fs_kHz, /* I Sample rate (kHz) */ opus_int frame_length /* I Number of samples */ ) { opus_int n, is10msFrame, denom_Q16, delta0_Q13, delta1_Q13; opus_int32 sum, diff, smooth_coef_Q16, pred_Q13[ 2 ], pred0_Q13, pred1_Q13; opus_int32 LP_ratio_Q14, HP_ratio_Q14, frac_Q16, frac_3_Q16, min_mid_rate_bps, width_Q14, w_Q24, deltaw_Q24; VARDECL( opus_int16, side ); VARDECL( opus_int16, LP_mid ); VARDECL( opus_int16, HP_mid ); VARDECL( opus_int16, LP_side ); VARDECL( opus_int16, HP_side ); opus_int16 *mid = &x1[ -2 ]; SAVE_STACK; ALLOC( side, frame_length + 2, opus_int16 ); /* Convert to basic mid/side signals */ for( n = 0; n < frame_length + 2; n++ ) { sum = x1[ n - 2 ] + (opus_int32)x2[ n - 2 ]; diff = x1[ n - 2 ] - (opus_int32)x2[ n - 2 ]; mid[ n ] = (opus_int16)silk_RSHIFT_ROUND( sum, 1 ); side[ n ] = (opus_int16)silk_SAT16( silk_RSHIFT_ROUND( diff, 1 ) ); } /* Buffering */ silk_memcpy( mid, state->sMid, 2 * sizeof( opus_int16 ) ); silk_memcpy( side, state->sSide, 2 * sizeof( opus_int16 ) ); silk_memcpy( state->sMid, &mid[ frame_length ], 2 * sizeof( opus_int16 ) ); silk_memcpy( state->sSide, &side[ frame_length ], 2 * sizeof( opus_int16 ) ); /* LP and HP filter mid signal */ ALLOC( LP_mid, frame_length, opus_int16 ); ALLOC( HP_mid, frame_length, opus_int16 ); for( n = 0; n < frame_length; n++ ) { sum = silk_RSHIFT_ROUND( silk_ADD_LSHIFT( mid[ n ] + mid[ n + 2 ], mid[ n + 1 ], 1 ), 2 ); LP_mid[ n ] = sum; HP_mid[ n ] = mid[ n + 1 ] - sum; } /* LP and HP filter side signal */ ALLOC( LP_side, frame_length, opus_int16 ); ALLOC( HP_side, frame_length, opus_int16 ); for( n = 0; n < frame_length; n++ ) { sum = silk_RSHIFT_ROUND( silk_ADD_LSHIFT( side[ n ] + side[ n + 2 ], side[ n + 1 ], 1 ), 2 ); LP_side[ n ] = sum; HP_side[ n ] = side[ n + 1 ] - sum; } /* Find energies and predictors */ is10msFrame = frame_length == 10 * fs_kHz; smooth_coef_Q16 = is10msFrame ? SILK_FIX_CONST( STEREO_RATIO_SMOOTH_COEF / 2, 16 ) : SILK_FIX_CONST( STEREO_RATIO_SMOOTH_COEF, 16 ); smooth_coef_Q16 = silk_SMULWB( silk_SMULBB( prev_speech_act_Q8, prev_speech_act_Q8 ), smooth_coef_Q16 ); pred_Q13[ 0 ] = silk_stereo_find_predictor( &LP_ratio_Q14, LP_mid, LP_side, &state->mid_side_amp_Q0[ 0 ], frame_length, smooth_coef_Q16 ); pred_Q13[ 1 ] = silk_stereo_find_predictor( &HP_ratio_Q14, HP_mid, HP_side, &state->mid_side_amp_Q0[ 2 ], frame_length, smooth_coef_Q16 ); /* Ratio of the norms of residual and mid signals */ frac_Q16 = silk_SMLABB( HP_ratio_Q14, LP_ratio_Q14, 3 ); frac_Q16 = silk_min( frac_Q16, SILK_FIX_CONST( 1, 16 ) ); /* Determine bitrate distribution between mid and side, and possibly reduce stereo width */ total_rate_bps -= is10msFrame ? 1200 : 600; /* Subtract approximate bitrate for coding stereo parameters */ if( total_rate_bps < 1 ) { total_rate_bps = 1; } min_mid_rate_bps = silk_SMLABB( 2000, fs_kHz, 900 ); silk_assert( min_mid_rate_bps < 32767 ); /* Default bitrate distribution: 8 parts for Mid and (5+3*frac) parts for Side. so: mid_rate = ( 8 / ( 13 + 3 * frac ) ) * total_ rate */ frac_3_Q16 = silk_MUL( 3, frac_Q16 ); mid_side_rates_bps[ 0 ] = silk_DIV32_varQ( total_rate_bps, SILK_FIX_CONST( 8 + 5, 16 ) + frac_3_Q16, 16+3 ); /* If Mid bitrate below minimum, reduce stereo width */ if( mid_side_rates_bps[ 0 ] < min_mid_rate_bps ) { mid_side_rates_bps[ 0 ] = min_mid_rate_bps; mid_side_rates_bps[ 1 ] = total_rate_bps - mid_side_rates_bps[ 0 ]; /* width = 4 * ( 2 * side_rate - min_rate ) / ( ( 1 + 3 * frac ) * min_rate ) */ width_Q14 = silk_DIV32_varQ( silk_LSHIFT( mid_side_rates_bps[ 1 ], 1 ) - min_mid_rate_bps, silk_SMULWB( SILK_FIX_CONST( 1, 16 ) + frac_3_Q16, min_mid_rate_bps ), 14+2 ); width_Q14 = silk_LIMIT( width_Q14, 0, SILK_FIX_CONST( 1, 14 ) ); } else { mid_side_rates_bps[ 1 ] = total_rate_bps - mid_side_rates_bps[ 0 ]; width_Q14 = SILK_FIX_CONST( 1, 14 ); } /* Smoother */ state->smth_width_Q14 = (opus_int16)silk_SMLAWB( state->smth_width_Q14, width_Q14 - state->smth_width_Q14, smooth_coef_Q16 ); /* At very low bitrates or for inputs that are nearly amplitude panned, switch to panned-mono coding */ *mid_only_flag = 0; if( toMono ) { /* Last frame before stereo->mono transition; collapse stereo width */ width_Q14 = 0; pred_Q13[ 0 ] = 0; pred_Q13[ 1 ] = 0; silk_stereo_quant_pred( pred_Q13, ix ); } else if( state->width_prev_Q14 == 0 && ( 8 * total_rate_bps < 13 * min_mid_rate_bps || silk_SMULWB( frac_Q16, state->smth_width_Q14 ) < SILK_FIX_CONST( 0.05, 14 ) ) ) { /* Code as panned-mono; previous frame already had zero width */ /* Scale down and quantize predictors */ pred_Q13[ 0 ] = silk_RSHIFT( silk_SMULBB( state->smth_width_Q14, pred_Q13[ 0 ] ), 14 ); pred_Q13[ 1 ] = silk_RSHIFT( silk_SMULBB( state->smth_width_Q14, pred_Q13[ 1 ] ), 14 ); silk_stereo_quant_pred( pred_Q13, ix ); /* Collapse stereo width */ width_Q14 = 0; pred_Q13[ 0 ] = 0; pred_Q13[ 1 ] = 0; mid_side_rates_bps[ 0 ] = total_rate_bps; mid_side_rates_bps[ 1 ] = 0; *mid_only_flag = 1; } else if( state->width_prev_Q14 != 0 && ( 8 * total_rate_bps < 11 * min_mid_rate_bps || silk_SMULWB( frac_Q16, state->smth_width_Q14 ) < SILK_FIX_CONST( 0.02, 14 ) ) ) { /* Transition to zero-width stereo */ /* Scale down and quantize predictors */ pred_Q13[ 0 ] = silk_RSHIFT( silk_SMULBB( state->smth_width_Q14, pred_Q13[ 0 ] ), 14 ); pred_Q13[ 1 ] = silk_RSHIFT( silk_SMULBB( state->smth_width_Q14, pred_Q13[ 1 ] ), 14 ); silk_stereo_quant_pred( pred_Q13, ix ); /* Collapse stereo width */ width_Q14 = 0; pred_Q13[ 0 ] = 0; pred_Q13[ 1 ] = 0; } else if( state->smth_width_Q14 > SILK_FIX_CONST( 0.95, 14 ) ) { /* Full-width stereo coding */ silk_stereo_quant_pred( pred_Q13, ix ); width_Q14 = SILK_FIX_CONST( 1, 14 ); } else { /* Reduced-width stereo coding; scale down and quantize predictors */ pred_Q13[ 0 ] = silk_RSHIFT( silk_SMULBB( state->smth_width_Q14, pred_Q13[ 0 ] ), 14 ); pred_Q13[ 1 ] = silk_RSHIFT( silk_SMULBB( state->smth_width_Q14, pred_Q13[ 1 ] ), 14 ); silk_stereo_quant_pred( pred_Q13, ix ); width_Q14 = state->smth_width_Q14; } /* Make sure to keep on encoding until the tapered output has been transmitted */ if( *mid_only_flag == 1 ) { state->silent_side_len += frame_length - STEREO_INTERP_LEN_MS * fs_kHz; if( state->silent_side_len < LA_SHAPE_MS * fs_kHz ) { *mid_only_flag = 0; } else { /* Limit to avoid wrapping around */ state->silent_side_len = 10000; } } else { state->silent_side_len = 0; } if( *mid_only_flag == 0 && mid_side_rates_bps[ 1 ] < 1 ) { mid_side_rates_bps[ 1 ] = 1; mid_side_rates_bps[ 0 ] = silk_max_int( 1, total_rate_bps - mid_side_rates_bps[ 1 ]); } /* Interpolate predictors and subtract prediction from side channel */ pred0_Q13 = -state->pred_prev_Q13[ 0 ]; pred1_Q13 = -state->pred_prev_Q13[ 1 ]; w_Q24 = silk_LSHIFT( state->width_prev_Q14, 10 ); denom_Q16 = silk_DIV32_16( (opus_int32)1 << 16, STEREO_INTERP_LEN_MS * fs_kHz ); delta0_Q13 = -silk_RSHIFT_ROUND( silk_SMULBB( pred_Q13[ 0 ] - state->pred_prev_Q13[ 0 ], denom_Q16 ), 16 ); delta1_Q13 = -silk_RSHIFT_ROUND( silk_SMULBB( pred_Q13[ 1 ] - state->pred_prev_Q13[ 1 ], denom_Q16 ), 16 ); deltaw_Q24 = silk_LSHIFT( silk_SMULWB( width_Q14 - state->width_prev_Q14, denom_Q16 ), 10 ); for( n = 0; n < STEREO_INTERP_LEN_MS * fs_kHz; n++ ) { pred0_Q13 += delta0_Q13; pred1_Q13 += delta1_Q13; w_Q24 += deltaw_Q24; sum = silk_LSHIFT( silk_ADD_LSHIFT( mid[ n ] + mid[ n + 2 ], mid[ n + 1 ], 1 ), 9 ); /* Q11 */ sum = silk_SMLAWB( silk_SMULWB( w_Q24, side[ n + 1 ] ), sum, pred0_Q13 ); /* Q8 */ sum = silk_SMLAWB( sum, silk_LSHIFT( (opus_int32)mid[ n + 1 ], 11 ), pred1_Q13 ); /* Q8 */ x2[ n - 1 ] = (opus_int16)silk_SAT16( silk_RSHIFT_ROUND( sum, 8 ) ); } pred0_Q13 = -pred_Q13[ 0 ]; pred1_Q13 = -pred_Q13[ 1 ]; w_Q24 = silk_LSHIFT( width_Q14, 10 ); for( n = STEREO_INTERP_LEN_MS * fs_kHz; n < frame_length; n++ ) { sum = silk_LSHIFT( silk_ADD_LSHIFT( mid[ n ] + mid[ n + 2 ], mid[ n + 1 ], 1 ), 9 ); /* Q11 */ sum = silk_SMLAWB( silk_SMULWB( w_Q24, side[ n + 1 ] ), sum, pred0_Q13 ); /* Q8 */ sum = silk_SMLAWB( sum, silk_LSHIFT( (opus_int32)mid[ n + 1 ], 11 ), pred1_Q13 ); /* Q8 */ x2[ n - 1 ] = (opus_int16)silk_SAT16( silk_RSHIFT_ROUND( sum, 8 ) ); } state->pred_prev_Q13[ 0 ] = (opus_int16)pred_Q13[ 0 ]; state->pred_prev_Q13[ 1 ] = (opus_int16)pred_Q13[ 1 ]; state->width_prev_Q14 = (opus_int16)width_Q14; RESTORE_STACK; }