/* Prefilter for finding Quantizer input signal */ static OPUS_INLINE void silk_prefilt_FIX( silk_prefilter_state_FIX *P, /* I/O state */ opus_int32 st_res_Q12[], /* I short term residual signal */ opus_int32 xw_Q3[], /* O prefiltered signal */ opus_int32 HarmShapeFIRPacked_Q12, /* I Harmonic shaping coeficients */ opus_int Tilt_Q14, /* I Tilt shaping coeficient */ opus_int32 LF_shp_Q14, /* I Low-frequancy shaping coeficients */ opus_int lag, /* I Lag for harmonic shaping */ opus_int length /* I Length of signals */ ) { opus_int i, idx, LTP_shp_buf_idx; opus_int32 n_LTP_Q12, n_Tilt_Q10, n_LF_Q10; opus_int32 sLF_MA_shp_Q12, sLF_AR_shp_Q12; opus_int16 *LTP_shp_buf; /* To speed up use temp variables instead of using the struct */ LTP_shp_buf = P->sLTP_shp; LTP_shp_buf_idx = P->sLTP_shp_buf_idx; sLF_AR_shp_Q12 = P->sLF_AR_shp_Q12; sLF_MA_shp_Q12 = P->sLF_MA_shp_Q12; for (i = 0; i < length; i++) { if (lag > 0) { /* unrolled loop */ silk_assert(HARM_SHAPE_FIR_TAPS == 3); idx = lag + LTP_shp_buf_idx; n_LTP_Q12 = silk_SMULBB(LTP_shp_buf[(idx - HARM_SHAPE_FIR_TAPS / 2 - 1) & LTP_MASK], HarmShapeFIRPacked_Q12); n_LTP_Q12 = silk_SMLABT(n_LTP_Q12, LTP_shp_buf[(idx - HARM_SHAPE_FIR_TAPS / 2) & LTP_MASK], HarmShapeFIRPacked_Q12); n_LTP_Q12 = silk_SMLABB(n_LTP_Q12, LTP_shp_buf[(idx - HARM_SHAPE_FIR_TAPS / 2 + 1) & LTP_MASK], HarmShapeFIRPacked_Q12); } else { n_LTP_Q12 = 0; } n_Tilt_Q10 = silk_SMULWB(sLF_AR_shp_Q12, Tilt_Q14); n_LF_Q10 = silk_SMLAWB(silk_SMULWT(sLF_AR_shp_Q12, LF_shp_Q14), sLF_MA_shp_Q12, LF_shp_Q14); sLF_AR_shp_Q12 = silk_SUB32(st_res_Q12[i], silk_LSHIFT(n_Tilt_Q10, 2)); sLF_MA_shp_Q12 = silk_SUB32(sLF_AR_shp_Q12, silk_LSHIFT(n_LF_Q10, 2)); LTP_shp_buf_idx = (LTP_shp_buf_idx - 1) & LTP_MASK; LTP_shp_buf[LTP_shp_buf_idx] = (opus_int16) silk_SAT16( silk_RSHIFT_ROUND(sLF_MA_shp_Q12, 12)); xw_Q3[i] = silk_RSHIFT_ROUND(silk_SUB32(sLF_MA_shp_Q12, n_LTP_Q12), 9); } /* Copy temp variable back to state */ P->sLF_AR_shp_Q12 = sLF_AR_shp_Q12; P->sLF_MA_shp_Q12 = sLF_MA_shp_Q12; P->sLTP_shp_buf_idx = LTP_shp_buf_idx; }
/* Convert adaptive Mid/Side representation to Left/Right stereo signal */ void silk_stereo_MS_to_LR( stereo_dec_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 */ const opus_int32 pred_Q13[], /* I Predictors */ opus_int fs_kHz, /* I Samples rate (kHz) */ opus_int frame_length /* I Number of samples */ ) { opus_int n, denom_Q16, delta0_Q13, delta1_Q13; opus_int32 sum, diff, pred0_Q13, pred1_Q13; /* Buffering */ silk_memcpy( x1, state->sMid, 2 * sizeof( opus_int16 ) ); silk_memcpy( x2, state->sSide, 2 * sizeof( opus_int16 ) ); silk_memcpy( state->sMid, &x1[ frame_length ], 2 * sizeof( opus_int16 ) ); silk_memcpy( state->sSide, &x2[ frame_length ], 2 * sizeof( opus_int16 ) ); /* Interpolate predictors and add prediction to side channel */ pred0_Q13 = state->pred_prev_Q13[ 0 ]; pred1_Q13 = state->pred_prev_Q13[ 1 ]; 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 ); for( n = 0; n < STEREO_INTERP_LEN_MS * fs_kHz; n++ ) { pred0_Q13 += delta0_Q13; pred1_Q13 += delta1_Q13; sum = silk_LSHIFT( silk_ADD_LSHIFT( x1[ n ] + x1[ n + 2 ], x1[ n + 1 ], 1 ), 9 ); /* Q11 */ sum = silk_SMLAWB( silk_LSHIFT( (opus_int32)x2[ n + 1 ], 8 ), sum, pred0_Q13 ); /* Q8 */ sum = silk_SMLAWB( sum, silk_LSHIFT( (opus_int32)x1[ 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 ]; for( n = STEREO_INTERP_LEN_MS * fs_kHz; n < frame_length; n++ ) { sum = silk_LSHIFT( silk_ADD_LSHIFT( x1[ n ] + x1[ n + 2 ], x1[ n + 1 ], 1 ), 9 ); /* Q11 */ sum = silk_SMLAWB( silk_LSHIFT( (opus_int32)x2[ n + 1 ], 8 ), sum, pred0_Q13 ); /* Q8 */ sum = silk_SMLAWB( sum, silk_LSHIFT( (opus_int32)x1[ n + 1 ], 11 ), pred1_Q13 ); /* Q8 */ x2[ n + 1 ] = (opus_int16)silk_SAT16( silk_RSHIFT_ROUND( sum, 8 ) ); } state->pred_prev_Q13[ 0 ] = pred_Q13[ 0 ]; state->pred_prev_Q13[ 1 ] = pred_Q13[ 1 ]; /* Convert to left/right signals */ for( n = 0; n < frame_length; n++ ) { sum = x1[ n + 1 ] + (opus_int32)x2[ n + 1 ]; diff = x1[ n + 1 ] - (opus_int32)x2[ n + 1 ]; x1[ n + 1 ] = (opus_int16)silk_SAT16( sum ); x2[ n + 1 ] = (opus_int16)silk_SAT16( diff ); } }
static OPUS_INLINE opus_int16 *silk_resampler_private_IIR_FIR_INTERPOL( opus_int16 *out, opus_int16 *buf, opus_int32 max_index_Q16, opus_int32 index_increment_Q16 ) { opus_int32 index_Q16, res_Q15; opus_int16 *buf_ptr; opus_int32 table_index; /* Interpolate upsampled signal and store in output array */ for( index_Q16 = 0; index_Q16 < max_index_Q16; index_Q16 += index_increment_Q16 ) { table_index = silk_SMULWB( index_Q16 & 0xFFFF, 12 ); buf_ptr = &buf[ index_Q16 >> 16 ]; res_Q15 = silk_SMULBB( buf_ptr[ 0 ], silk_resampler_frac_FIR_12[ table_index ][ 0 ] ); res_Q15 = silk_SMLABB( res_Q15, buf_ptr[ 1 ], silk_resampler_frac_FIR_12[ table_index ][ 1 ] ); res_Q15 = silk_SMLABB( res_Q15, buf_ptr[ 2 ], silk_resampler_frac_FIR_12[ table_index ][ 2 ] ); res_Q15 = silk_SMLABB( res_Q15, buf_ptr[ 3 ], silk_resampler_frac_FIR_12[ table_index ][ 3 ] ); res_Q15 = silk_SMLABB( res_Q15, buf_ptr[ 4 ], silk_resampler_frac_FIR_12[ 11 - table_index ][ 3 ] ); res_Q15 = silk_SMLABB( res_Q15, buf_ptr[ 5 ], silk_resampler_frac_FIR_12[ 11 - table_index ][ 2 ] ); res_Q15 = silk_SMLABB( res_Q15, buf_ptr[ 6 ], silk_resampler_frac_FIR_12[ 11 - table_index ][ 1 ] ); res_Q15 = silk_SMLABB( res_Q15, buf_ptr[ 7 ], silk_resampler_frac_FIR_12[ 11 - table_index ][ 0 ] ); *out++ = (opus_int16)silk_SAT16( silk_RSHIFT_ROUND( res_Q15, 15 ) ); } return out; }
/* Processing of gains */ void silk_process_gains_FIX( silk_encoder_state_FIX *psEnc, /* I/O Encoder state */ silk_encoder_control_FIX *psEncCtrl, /* I/O Encoder control */ opus_int condCoding /* I The type of conditional coding to use */ ) { silk_shape_state_FIX *psShapeSt = &psEnc->sShape; opus_int k; opus_int32 s_Q16, InvMaxSqrVal_Q16, gain, gain_squared, ResNrg, ResNrgPart, quant_offset_Q10; /* Gain reduction when LTP coding gain is high */ if( psEnc->sCmn.indices.signalType == TYPE_VOICED ) { /*s = -0.5f * silk_sigmoid( 0.25f * ( psEncCtrl->LTPredCodGain - 12.0f ) ); */ s_Q16 = -silk_sigm_Q15( silk_RSHIFT_ROUND( psEncCtrl->LTPredCodGain_Q7 - SILK_FIX_CONST( 12.0, 7 ), 4 ) ); for( k = 0; k < psEnc->sCmn.nb_subfr; k++ ) { psEncCtrl->Gains_Q16[ k ] = silk_SMLAWB( psEncCtrl->Gains_Q16[ k ], psEncCtrl->Gains_Q16[ k ], s_Q16 ); } } /* Limit the quantized signal */ /* InvMaxSqrVal = pow( 2.0f, 0.33f * ( 21.0f - SNR_dB ) ) / subfr_length; */ InvMaxSqrVal_Q16 = silk_DIV32_16( silk_log2lin( silk_SMULWB( SILK_FIX_CONST( 21 + 16 / 0.33, 7 ) - psEnc->sCmn.SNR_dB_Q7, SILK_FIX_CONST( 0.33, 16 ) ) ), psEnc->sCmn.subfr_length ); for( k = 0; k < psEnc->sCmn.nb_subfr; k++ ) { /* Soft limit on ratio residual energy and squared gains */ ResNrg = psEncCtrl->ResNrg[ k ]; ResNrgPart = silk_SMULWW( ResNrg, InvMaxSqrVal_Q16 ); if( psEncCtrl->ResNrgQ[ k ] > 0 ) { ResNrgPart = silk_RSHIFT_ROUND( ResNrgPart, psEncCtrl->ResNrgQ[ k ] ); } else { if( ResNrgPart >= silk_RSHIFT( silk_int32_MAX, -psEncCtrl->ResNrgQ[ k ] ) ) { ResNrgPart = silk_int32_MAX; } else { ResNrgPart = silk_LSHIFT( ResNrgPart, -psEncCtrl->ResNrgQ[ k ] ); } } gain = psEncCtrl->Gains_Q16[ k ]; gain_squared = silk_ADD_SAT32( ResNrgPart, silk_SMMUL( gain, gain ) ); if( gain_squared < silk_int16_MAX ) { /* recalculate with higher precision */ gain_squared = silk_SMLAWW( silk_LSHIFT( ResNrgPart, 16 ), gain, gain ); silk_assert( gain_squared > 0 ); gain = silk_SQRT_APPROX( gain_squared ); /* Q8 */ gain = silk_min( gain, silk_int32_MAX >> 8 ); psEncCtrl->Gains_Q16[ k ] = silk_LSHIFT_SAT32( gain, 8 ); /* Q16 */ } else {
/* Convert int32 coefficients to int16 coefs and make sure there's no wrap-around */ void silk_LPC_fit( opus_int16 *a_QOUT, /* O Output signal */ opus_int32 *a_QIN, /* I/O Input signal */ const opus_int QOUT, /* I Input Q domain */ const opus_int QIN, /* I Input Q domain */ const opus_int d /* I Filter order */ ) { opus_int i, k, idx = 0; opus_int32 maxabs, absval, chirp_Q16; /* Limit the maximum absolute value of the prediction coefficients, so that they'll fit in int16 */ for( i = 0; i < 10; i++ ) { /* Find maximum absolute value and its index */ maxabs = 0; for( k = 0; k < d; k++ ) { absval = silk_abs( a_QIN[k] ); if( absval > maxabs ) { maxabs = absval; idx = k; } } maxabs = silk_RSHIFT_ROUND( maxabs, QIN - QOUT ); if( maxabs > silk_int16_MAX ) { /* Reduce magnitude of prediction coefficients */ maxabs = silk_min( maxabs, 163838 ); /* ( silk_int32_MAX >> 14 ) + silk_int16_MAX = 163838 */ chirp_Q16 = SILK_FIX_CONST( 0.999, 16 ) - silk_DIV32( silk_LSHIFT( maxabs - silk_int16_MAX, 14 ), silk_RSHIFT32( silk_MUL( maxabs, idx + 1), 2 ) ); silk_bwexpander_32( a_QIN, d, chirp_Q16 ); } else { break; } } if( i == 10 ) { /* Reached the last iteration, clip the coefficients */ for( k = 0; k < d; k++ ) { a_QOUT[ k ] = (opus_int16)silk_SAT16( silk_RSHIFT_ROUND( a_QIN[ k ], QIN - QOUT ) ); a_QIN[ k ] = silk_LSHIFT( (opus_int32)a_QOUT[ k ], QIN - QOUT ); } } else { for( k = 0; k < d; k++ ) { a_QOUT[ k ] = (opus_int16)silk_RSHIFT_ROUND( a_QIN[ k ], QIN - QOUT ); } } }
/* Uses SMULL(), available on armv4 */ opus_int32 silk_schur64( /* O returns residual energy */ opus_int32 rc_Q16[], /* O Reflection coefficients [order] Q16 */ const opus_int32 c[], /* I Correlations [order+1] */ opus_int32 order /* I Prediction order */ ) { opus_int k, n; opus_int32 C[ SILK_MAX_ORDER_LPC + 1 ][ 2 ]; opus_int32 Ctmp1_Q30, Ctmp2_Q30, rc_tmp_Q31; silk_assert( order==6||order==8||order==10||order==12||order==14||order==16 ); /* Check for invalid input */ if( c[ 0 ] <= 0 ) { silk_memset( rc_Q16, 0, order * sizeof( opus_int32 ) ); return 0; } for( k = 0; k < order + 1; k++ ) { C[ k ][ 0 ] = C[ k ][ 1 ] = c[ k ]; } for( k = 0; k < order; k++ ) { /* Check that we won't be getting an unstable rc, otherwise stop here. */ if (silk_abs_int32(C[ k + 1 ][ 0 ]) >= C[ 0 ][ 1 ]) { if ( C[ k + 1 ][ 0 ] > 0 ) { rc_Q16[ k ] = -SILK_FIX_CONST( .99f, 16 ); } else { rc_Q16[ k ] = SILK_FIX_CONST( .99f, 16 ); } k++; break; } /* Get reflection coefficient: divide two Q30 values and get result in Q31 */ rc_tmp_Q31 = silk_DIV32_varQ( -C[ k + 1 ][ 0 ], C[ 0 ][ 1 ], 31 ); /* Save the output */ rc_Q16[ k ] = silk_RSHIFT_ROUND( rc_tmp_Q31, 15 ); /* Update correlations */ for( n = 0; n < order - k; n++ ) { Ctmp1_Q30 = C[ n + k + 1 ][ 0 ]; Ctmp2_Q30 = C[ n ][ 1 ]; /* Multiply and add the highest int32 */ C[ n + k + 1 ][ 0 ] = Ctmp1_Q30 + silk_SMMUL( silk_LSHIFT( Ctmp2_Q30, 1 ), rc_tmp_Q31 ); C[ n ][ 1 ] = Ctmp2_Q30 + silk_SMMUL( silk_LSHIFT( Ctmp1_Q30, 1 ), rc_tmp_Q31 ); } } for(; k < order; k++ ) { rc_Q16[ k ] = 0; } return silk_max_32( 1, C[ 0 ][ 1 ] ); }
void silk_fit_LTP( opus_int32 LTP_coefs_Q16[ LTP_ORDER ], opus_int16 LTP_coefs_Q14[ LTP_ORDER ] ) { opus_int i; for( i = 0; i < LTP_ORDER; i++ ) { LTP_coefs_Q14[ i ] = (opus_int16)silk_SAT16( silk_RSHIFT_ROUND( LTP_coefs_Q16[ i ], 2 ) ); } }
/* Chirp (bandwidth expand) LP AR filter */ void silk_bwexpander(int16_t * ar, /* I/O AR filter to be expanded (without leading 1) */ const int d, /* I Length of ar */ int32_t chirp_Q16 /* I Chirp factor (typically in the range 0 to 1) */ ) { int i; int32_t chirp_minus_one_Q16 = chirp_Q16 - 65536; /* NB: Dont use silk_SMULWB, instead of silk_RSHIFT_ROUND( silk_MUL(), 16 ), below. */ /* Bias in silk_SMULWB can lead to unstable filters */ for (i = 0; i < d - 1; i++) { ar[i] = (int16_t) silk_RSHIFT_ROUND(silk_MUL(chirp_Q16, ar[i]), 16); chirp_Q16 += silk_RSHIFT_ROUND(silk_MUL(chirp_Q16, chirp_minus_one_Q16), 16); } ar[d - 1] = (int16_t) silk_RSHIFT_ROUND(silk_MUL(chirp_Q16, ar[d - 1]), 16); }
/* Second order ARMA filter, alternative implementation */ void silk_biquad_alt(const int16_t * in, /* I input signal */ const int32_t * B_Q28, /* I MA coefficients [3] */ const int32_t * A_Q28, /* I AR coefficients [2] */ int32_t * S, /* I/O State vector [2] */ int16_t * out, /* O output signal */ const int32_t len, /* I signal length (must be even) */ int stride /* I Operate on interleaved signal if > 1 */ ) { /* DIRECT FORM II TRANSPOSED (uses 2 element state vector) */ int k; int32_t inval, A0_U_Q28, A0_L_Q28, A1_U_Q28, A1_L_Q28, out32_Q14; /* Negate A_Q28 values and split in two parts */ A0_L_Q28 = (-A_Q28[0]) & 0x00003FFF; /* lower part */ A0_U_Q28 = silk_RSHIFT(-A_Q28[0], 14); /* upper part */ A1_L_Q28 = (-A_Q28[1]) & 0x00003FFF; /* lower part */ A1_U_Q28 = silk_RSHIFT(-A_Q28[1], 14); /* upper part */ for (k = 0; k < len; k++) { /* S[ 0 ], S[ 1 ]: Q12 */ inval = in[k * stride]; out32_Q14 = silk_LSHIFT(silk_SMLAWB(S[0], B_Q28[0], inval), 2); S[0] = S[1] + silk_RSHIFT_ROUND(silk_SMULWB(out32_Q14, A0_L_Q28), 14); S[0] = silk_SMLAWB(S[0], out32_Q14, A0_U_Q28); S[0] = silk_SMLAWB(S[0], B_Q28[1], inval); S[1] = silk_RSHIFT_ROUND(silk_SMULWB(out32_Q14, A1_L_Q28), 14); S[1] = silk_SMLAWB(S[1], out32_Q14, A1_U_Q28); S[1] = silk_SMLAWB(S[1], B_Q28[2], inval); /* Scale back to Q0 and saturate */ out[k * stride] = (int16_t) silk_SAT16(silk_RSHIFT(out32_Q14 + (1 << 14) - 1, 14)); } }
static inline void silk_A2NLSF_init( const opus_int32 *a_Q16, opus_int32 *P, opus_int32 *Q, const opus_int dd ) { opus_int k; /* Convert filter coefs to even and odd polynomials */ P[dd] = silk_LSHIFT( 1, QPoly ); Q[dd] = silk_LSHIFT( 1, QPoly ); for( k = 0; k < dd; k++ ) { #if( QPoly < 16 ) P[ k ] = silk_RSHIFT_ROUND( -a_Q16[ dd - k - 1 ] - a_Q16[ dd + k ], 16 - QPoly ); /* QPoly */ Q[ k ] = silk_RSHIFT_ROUND( -a_Q16[ dd - k - 1 ] + a_Q16[ dd + k ], 16 - QPoly ); /* QPoly */ #elif( Qpoly == 16 ) P[ k ] = -a_Q16[ dd - k - 1 ] - a_Q16[ dd + k ]; /* QPoly*/ Q[ k ] = -a_Q16[ dd - k - 1 ] + a_Q16[ dd + k ]; /* QPoly*/ #else P[ k ] = silk_LSHIFT( -a_Q16[ dd - k - 1 ] - a_Q16[ dd + k ], QPoly - 16 ); /* QPoly */ Q[ k ] = silk_LSHIFT( -a_Q16[ dd - k - 1 ] + a_Q16[ dd + k ], QPoly - 16 ); /* QPoly */ #endif } /* Divide out zeros as we have that for even filter orders, */ /* z = 1 is always a root in Q, and */ /* z = -1 is always a root in P */ for( k = dd; k > 0; k-- ) { P[ k - 1 ] -= P[ k ]; Q[ k - 1 ] += Q[ k ]; } /* Transform polynomials from cos(n*f) to cos(f)^n */ silk_A2NLSF_trans_poly( P, dd ); silk_A2NLSF_trans_poly( Q, dd ); }
/* Split signal into two decimated bands using first-order allpass filters */ void silk_ana_filt_bank_1( const opus_int16 *in, /* I Input signal [N] */ opus_int32 *S, /* I/O State vector [2] */ opus_int16 *outL, /* O Low band [N/2] */ opus_int16 *outH, /* O High band [N/2] */ const opus_int32 N /* I Number of input samples */ ) { opus_int k, N2 = silk_RSHIFT( N, 1 ); opus_int32 in32, X, Y, out_1, out_2; /* Internal variables and state are in Q10 format */ for( k = 0; k < N2; k++ ) { /* Convert to Q10 */ in32 = silk_LSHIFT( (opus_int32)in[ 2 * k ], 10 ); /* All-pass section for even input sample */ Y = silk_SUB32( in32, S[ 0 ] ); X = silk_SMLAWB( Y, Y, A_fb1_21 ); out_1 = silk_ADD32( S[ 0 ], X ); S[ 0 ] = silk_ADD32( in32, X ); /* Convert to Q10 */ in32 = silk_LSHIFT( (opus_int32)in[ 2 * k + 1 ], 10 ); /* All-pass section for odd input sample, and add to output of previous section */ Y = silk_SUB32( in32, S[ 1 ] ); X = silk_SMULWB( Y, A_fb1_20 ); out_2 = silk_ADD32( S[ 1 ], X ); S[ 1 ] = silk_ADD32( in32, X ); /* Add/subtract, convert back to int16 and store to output */ outL[ k ] = (opus_int16)silk_SAT16( silk_RSHIFT_ROUND( silk_ADD32( out_2, out_1 ), 11 ) ); outH[ k ] = (opus_int16)silk_SAT16( silk_RSHIFT_ROUND( silk_SUB32( out_2, out_1 ), 11 ) ); } }
/* Chirp (bandwidth expand) LP AR filter */ void silk_bwexpander_32( opus_int32 *ar, /* I/O AR filter to be expanded (without leading 1) */ const opus_int d, /* I Length of ar */ opus_int32 chirp_Q16 /* I Chirp factor in Q16 */ ) { opus_int i; opus_int32 chirp_minus_one_Q16 = chirp_Q16 - 65536; for( i = 0; i < d - 1; i++ ) { ar[ i ] = silk_SMULWW( chirp_Q16, ar[ i ] ); chirp_Q16 += silk_RSHIFT_ROUND( silk_MUL( chirp_Q16, chirp_minus_one_Q16 ), 16 ); } ar[ d - 1 ] = silk_SMULWW( chirp_Q16, ar[ d - 1 ] ); }
void silk_LPC_analysis_filter( opus_int16 *out, /* O Output signal */ const opus_int16 *in, /* I Input signal */ const opus_int16 *B, /* I MA prediction coefficients, Q12 [order] */ const opus_int32 len, /* I Signal length */ const opus_int32 d /* I Filter order */ ) { opus_int ix, j; opus_int32 out32_Q12, out32; const opus_int16 *in_ptr; silk_assert( d >= 6 ); silk_assert( (d & 1) == 0 ); silk_assert( d <= len ); for( ix = d; ix < len; ix++ ) { in_ptr = &in[ ix - 1 ]; out32_Q12 = silk_SMULBB( in_ptr[ 0 ], B[ 0 ] ); /* Allowing wrap around so that two wraps can cancel each other. The rare cases where the result wraps around can only be triggered by invalid streams*/ out32_Q12 = silk_SMLABB_ovflw( out32_Q12, in_ptr[ -1 ], B[ 1 ] ); out32_Q12 = silk_SMLABB_ovflw( out32_Q12, in_ptr[ -2 ], B[ 2 ] ); out32_Q12 = silk_SMLABB_ovflw( out32_Q12, in_ptr[ -3 ], B[ 3 ] ); out32_Q12 = silk_SMLABB_ovflw( out32_Q12, in_ptr[ -4 ], B[ 4 ] ); out32_Q12 = silk_SMLABB_ovflw( out32_Q12, in_ptr[ -5 ], B[ 5 ] ); for( j = 6; j < d; j += 2 ) { out32_Q12 = silk_SMLABB_ovflw( out32_Q12, in_ptr[ -j ], B[ j ] ); out32_Q12 = silk_SMLABB_ovflw( out32_Q12, in_ptr[ -j - 1 ], B[ j + 1 ] ); } /* Subtract prediction */ out32_Q12 = silk_SUB32_ovflw( silk_LSHIFT( (opus_int32)in_ptr[ 1 ], 12 ), out32_Q12 ); /* Scale to Q0 */ out32 = silk_RSHIFT_ROUND( out32_Q12, 12 ); /* Saturate output */ out[ ix ] = (opus_int16)silk_SAT16( out32 ); } /* Set first d output samples to zero */ silk_memset( out, 0, d * sizeof( opus_int16 ) ); }
void silk_noise_shape_analysis_FIX( silk_encoder_state_FIX *psEnc, /* I/O Encoder state FIX */ silk_encoder_control_FIX *psEncCtrl, /* I/O Encoder control FIX */ const opus_int16 *pitch_res, /* I LPC residual from pitch analysis */ const opus_int16 *x, /* I Input signal [ frame_length + la_shape ] */ int arch /* I Run-time architecture */ ) { silk_shape_state_FIX *psShapeSt = &psEnc->sShape; opus_int k, i, nSamples, Qnrg, b_Q14, warping_Q16, scale = 0; opus_int32 SNR_adj_dB_Q7, HarmBoost_Q16, HarmShapeGain_Q16, Tilt_Q16, tmp32; opus_int32 nrg, pre_nrg_Q30, log_energy_Q7, log_energy_prev_Q7, energy_variation_Q7; opus_int32 delta_Q16, BWExp1_Q16, BWExp2_Q16, gain_mult_Q16, gain_add_Q16, strength_Q16, b_Q8; opus_int32 auto_corr[ MAX_SHAPE_LPC_ORDER + 1 ]; opus_int32 refl_coef_Q16[ MAX_SHAPE_LPC_ORDER ]; opus_int32 AR1_Q24[ MAX_SHAPE_LPC_ORDER ]; opus_int32 AR2_Q24[ MAX_SHAPE_LPC_ORDER ]; VARDECL( opus_int16, x_windowed ); const opus_int16 *x_ptr, *pitch_res_ptr; SAVE_STACK; /* Point to start of first LPC analysis block */ x_ptr = x - psEnc->sCmn.la_shape; /****************/ /* GAIN CONTROL */ /****************/ SNR_adj_dB_Q7 = psEnc->sCmn.SNR_dB_Q7; /* Input quality is the average of the quality in the lowest two VAD bands */ psEncCtrl->input_quality_Q14 = ( opus_int )silk_RSHIFT( (opus_int32)psEnc->sCmn.input_quality_bands_Q15[ 0 ] + psEnc->sCmn.input_quality_bands_Q15[ 1 ], 2 ); /* Coding quality level, between 0.0_Q0 and 1.0_Q0, but in Q14 */ psEncCtrl->coding_quality_Q14 = silk_RSHIFT( silk_sigm_Q15( silk_RSHIFT_ROUND( SNR_adj_dB_Q7 - SILK_FIX_CONST( 20.0, 7 ), 4 ) ), 1 ); /* Reduce coding SNR during low speech activity */ if( psEnc->sCmn.useCBR == 0 ) { b_Q8 = SILK_FIX_CONST( 1.0, 8 ) - psEnc->sCmn.speech_activity_Q8; b_Q8 = silk_SMULWB( silk_LSHIFT( b_Q8, 8 ), b_Q8 ); SNR_adj_dB_Q7 = silk_SMLAWB( SNR_adj_dB_Q7, silk_SMULBB( SILK_FIX_CONST( -BG_SNR_DECR_dB, 7 ) >> ( 4 + 1 ), b_Q8 ), /* Q11*/ silk_SMULWB( SILK_FIX_CONST( 1.0, 14 ) + psEncCtrl->input_quality_Q14, psEncCtrl->coding_quality_Q14 ) ); /* Q12*/ }
void silk_warped_LPC_analysis_filter_FIX( opus_int32 state[], /* I/O State [order + 1] */ opus_int32 res_Q2[], /* O Residual signal [length] */ const opus_int16 coef_Q13[], /* I Coefficients [order] */ const opus_int16 input[], /* I Input signal [length] */ const opus_int16 lambda_Q16, /* I Warping factor */ const opus_int length, /* I Length of input signal */ const opus_int order /* I Filter order (even) */ ) { opus_int n, i; opus_int32 acc_Q11, tmp1, tmp2; /* Order must be even */ silk_assert( ( order & 1 ) == 0 ); for( n = 0; n < length; n++ ) { /* Output of lowpass section */ tmp2 = silk_SMLAWB( state[ 0 ], state[ 1 ], lambda_Q16 ); state[ 0 ] = silk_LSHIFT( input[ n ], 14 ); /* Output of allpass section */ tmp1 = silk_SMLAWB( state[ 1 ], state[ 2 ] - tmp2, lambda_Q16 ); state[ 1 ] = tmp2; acc_Q11 = silk_RSHIFT( order, 1 ); acc_Q11 = silk_SMLAWB( acc_Q11, tmp2, coef_Q13[ 0 ] ); /* Loop over allpass sections */ for( i = 2; i < order; i += 2 ) { /* Output of allpass section */ tmp2 = silk_SMLAWB( state[ i ], state[ i + 1 ] - tmp1, lambda_Q16 ); state[ i ] = tmp1; acc_Q11 = silk_SMLAWB( acc_Q11, tmp1, coef_Q13[ i - 1 ] ); /* Output of allpass section */ tmp1 = silk_SMLAWB( state[ i + 1 ], state[ i + 2 ] - tmp2, lambda_Q16 ); state[ i + 1 ] = tmp2; acc_Q11 = silk_SMLAWB( acc_Q11, tmp2, coef_Q13[ i ] ); } state[ order ] = tmp1; acc_Q11 = silk_SMLAWB( acc_Q11, tmp1, coef_Q13[ order - 1 ] ); res_Q2[ n ] = silk_LSHIFT( (opus_int32)input[ n ], 2 ) - silk_RSHIFT_ROUND( acc_Q11, 9 ); } }
static inline opus_int16 *silk_resampler_private_down_FIR_INTERPOL( opus_int16 *out, opus_int32 *buf, const opus_int16 *FIR_Coefs, opus_int FIR_Order, opus_int FIR_Fracs, opus_int32 max_index_Q16, opus_int32 index_increment_Q16 ) { opus_int32 index_Q16, res_Q6; opus_int32 *buf_ptr; opus_int32 interpol_ind; const opus_int16 *interpol_ptr; switch( FIR_Order ) { case RESAMPLER_DOWN_ORDER_FIR0: for( index_Q16 = 0; index_Q16 < max_index_Q16; index_Q16 += index_increment_Q16 ) { /* Integer part gives pointer to buffered input */ buf_ptr = buf + silk_RSHIFT( index_Q16, 16 ); /* Fractional part gives interpolation coefficients */ interpol_ind = silk_SMULWB( index_Q16 & 0xFFFF, FIR_Fracs ); /* Inner product */ interpol_ptr = &FIR_Coefs[ RESAMPLER_DOWN_ORDER_FIR0 / 2 * interpol_ind ]; res_Q6 = silk_SMULWB( buf_ptr[ 0 ], interpol_ptr[ 0 ] ); res_Q6 = silk_SMLAWB( res_Q6, buf_ptr[ 1 ], interpol_ptr[ 1 ] ); res_Q6 = silk_SMLAWB( res_Q6, buf_ptr[ 2 ], interpol_ptr[ 2 ] ); res_Q6 = silk_SMLAWB( res_Q6, buf_ptr[ 3 ], interpol_ptr[ 3 ] ); res_Q6 = silk_SMLAWB( res_Q6, buf_ptr[ 4 ], interpol_ptr[ 4 ] ); res_Q6 = silk_SMLAWB( res_Q6, buf_ptr[ 5 ], interpol_ptr[ 5 ] ); res_Q6 = silk_SMLAWB( res_Q6, buf_ptr[ 6 ], interpol_ptr[ 6 ] ); res_Q6 = silk_SMLAWB( res_Q6, buf_ptr[ 7 ], interpol_ptr[ 7 ] ); res_Q6 = silk_SMLAWB( res_Q6, buf_ptr[ 8 ], interpol_ptr[ 8 ] ); interpol_ptr = &FIR_Coefs[ RESAMPLER_DOWN_ORDER_FIR0 / 2 * ( FIR_Fracs - 1 - interpol_ind ) ]; res_Q6 = silk_SMLAWB( res_Q6, buf_ptr[ 17 ], interpol_ptr[ 0 ] ); res_Q6 = silk_SMLAWB( res_Q6, buf_ptr[ 16 ], interpol_ptr[ 1 ] ); res_Q6 = silk_SMLAWB( res_Q6, buf_ptr[ 15 ], interpol_ptr[ 2 ] ); res_Q6 = silk_SMLAWB( res_Q6, buf_ptr[ 14 ], interpol_ptr[ 3 ] ); res_Q6 = silk_SMLAWB( res_Q6, buf_ptr[ 13 ], interpol_ptr[ 4 ] ); res_Q6 = silk_SMLAWB( res_Q6, buf_ptr[ 12 ], interpol_ptr[ 5 ] ); res_Q6 = silk_SMLAWB( res_Q6, buf_ptr[ 11 ], interpol_ptr[ 6 ] ); res_Q6 = silk_SMLAWB( res_Q6, buf_ptr[ 10 ], interpol_ptr[ 7 ] ); res_Q6 = silk_SMLAWB( res_Q6, buf_ptr[ 9 ], interpol_ptr[ 8 ] ); /* Scale down, saturate and store in output array */ *out++ = (opus_int16)silk_SAT16( silk_RSHIFT_ROUND( res_Q6, 6 ) ); } break; case RESAMPLER_DOWN_ORDER_FIR1: for( index_Q16 = 0; index_Q16 < max_index_Q16; index_Q16 += index_increment_Q16 ) { /* Integer part gives pointer to buffered input */ buf_ptr = buf + silk_RSHIFT( index_Q16, 16 ); /* Inner product */ res_Q6 = silk_SMULWB( silk_ADD32( buf_ptr[ 0 ], buf_ptr[ 23 ] ), FIR_Coefs[ 0 ] ); res_Q6 = silk_SMLAWB( res_Q6, silk_ADD32( buf_ptr[ 1 ], buf_ptr[ 22 ] ), FIR_Coefs[ 1 ] ); res_Q6 = silk_SMLAWB( res_Q6, silk_ADD32( buf_ptr[ 2 ], buf_ptr[ 21 ] ), FIR_Coefs[ 2 ] ); res_Q6 = silk_SMLAWB( res_Q6, silk_ADD32( buf_ptr[ 3 ], buf_ptr[ 20 ] ), FIR_Coefs[ 3 ] ); res_Q6 = silk_SMLAWB( res_Q6, silk_ADD32( buf_ptr[ 4 ], buf_ptr[ 19 ] ), FIR_Coefs[ 4 ] ); res_Q6 = silk_SMLAWB( res_Q6, silk_ADD32( buf_ptr[ 5 ], buf_ptr[ 18 ] ), FIR_Coefs[ 5 ] ); res_Q6 = silk_SMLAWB( res_Q6, silk_ADD32( buf_ptr[ 6 ], buf_ptr[ 17 ] ), FIR_Coefs[ 6 ] ); res_Q6 = silk_SMLAWB( res_Q6, silk_ADD32( buf_ptr[ 7 ], buf_ptr[ 16 ] ), FIR_Coefs[ 7 ] ); res_Q6 = silk_SMLAWB( res_Q6, silk_ADD32( buf_ptr[ 8 ], buf_ptr[ 15 ] ), FIR_Coefs[ 8 ] ); res_Q6 = silk_SMLAWB( res_Q6, silk_ADD32( buf_ptr[ 9 ], buf_ptr[ 14 ] ), FIR_Coefs[ 9 ] ); res_Q6 = silk_SMLAWB( res_Q6, silk_ADD32( buf_ptr[ 10 ], buf_ptr[ 13 ] ), FIR_Coefs[ 10 ] ); res_Q6 = silk_SMLAWB( res_Q6, silk_ADD32( buf_ptr[ 11 ], buf_ptr[ 12 ] ), FIR_Coefs[ 11 ] ); /* Scale down, saturate and store in output array */ *out++ = (opus_int16)silk_SAT16( silk_RSHIFT_ROUND( res_Q6, 6 ) ); } break; case RESAMPLER_DOWN_ORDER_FIR2: for( index_Q16 = 0; index_Q16 < max_index_Q16; index_Q16 += index_increment_Q16 ) { /* Integer part gives pointer to buffered input */ buf_ptr = buf + silk_RSHIFT( index_Q16, 16 ); /* Inner product */ res_Q6 = silk_SMULWB( silk_ADD32( buf_ptr[ 0 ], buf_ptr[ 35 ] ), FIR_Coefs[ 0 ] ); res_Q6 = silk_SMLAWB( res_Q6, silk_ADD32( buf_ptr[ 1 ], buf_ptr[ 34 ] ), FIR_Coefs[ 1 ] ); res_Q6 = silk_SMLAWB( res_Q6, silk_ADD32( buf_ptr[ 2 ], buf_ptr[ 33 ] ), FIR_Coefs[ 2 ] ); res_Q6 = silk_SMLAWB( res_Q6, silk_ADD32( buf_ptr[ 3 ], buf_ptr[ 32 ] ), FIR_Coefs[ 3 ] ); res_Q6 = silk_SMLAWB( res_Q6, silk_ADD32( buf_ptr[ 4 ], buf_ptr[ 31 ] ), FIR_Coefs[ 4 ] ); res_Q6 = silk_SMLAWB( res_Q6, silk_ADD32( buf_ptr[ 5 ], buf_ptr[ 30 ] ), FIR_Coefs[ 5 ] ); res_Q6 = silk_SMLAWB( res_Q6, silk_ADD32( buf_ptr[ 6 ], buf_ptr[ 29 ] ), FIR_Coefs[ 6 ] ); res_Q6 = silk_SMLAWB( res_Q6, silk_ADD32( buf_ptr[ 7 ], buf_ptr[ 28 ] ), FIR_Coefs[ 7 ] ); res_Q6 = silk_SMLAWB( res_Q6, silk_ADD32( buf_ptr[ 8 ], buf_ptr[ 27 ] ), FIR_Coefs[ 8 ] ); res_Q6 = silk_SMLAWB( res_Q6, silk_ADD32( buf_ptr[ 9 ], buf_ptr[ 26 ] ), FIR_Coefs[ 9 ] ); res_Q6 = silk_SMLAWB( res_Q6, silk_ADD32( buf_ptr[ 10 ], buf_ptr[ 25 ] ), FIR_Coefs[ 10 ] ); res_Q6 = silk_SMLAWB( res_Q6, silk_ADD32( buf_ptr[ 11 ], buf_ptr[ 24 ] ), FIR_Coefs[ 11 ] ); res_Q6 = silk_SMLAWB( res_Q6, silk_ADD32( buf_ptr[ 12 ], buf_ptr[ 23 ] ), FIR_Coefs[ 12 ] ); res_Q6 = silk_SMLAWB( res_Q6, silk_ADD32( buf_ptr[ 13 ], buf_ptr[ 22 ] ), FIR_Coefs[ 13 ] ); res_Q6 = silk_SMLAWB( res_Q6, silk_ADD32( buf_ptr[ 14 ], buf_ptr[ 21 ] ), FIR_Coefs[ 14 ] ); res_Q6 = silk_SMLAWB( res_Q6, silk_ADD32( buf_ptr[ 15 ], buf_ptr[ 20 ] ), FIR_Coefs[ 15 ] ); res_Q6 = silk_SMLAWB( res_Q6, silk_ADD32( buf_ptr[ 16 ], buf_ptr[ 19 ] ), FIR_Coefs[ 16 ] ); res_Q6 = silk_SMLAWB( res_Q6, silk_ADD32( buf_ptr[ 17 ], buf_ptr[ 18 ] ), FIR_Coefs[ 17 ] ); /* Scale down, saturate and store in output array */ *out++ = (opus_int16)silk_SAT16( silk_RSHIFT_ROUND( res_Q6, 6 ) ); } break; default: silk_assert( 0 ); } return out; }
static inline void silk_PLC_conceal( silk_decoder_state *psDec, /* I/O Decoder state */ silk_decoder_control *psDecCtrl, /* I/O Decoder control */ opus_int16 frame[] /* O LPC residual signal */ ) { opus_int i, j, k; opus_int lag, idx, sLTP_buf_idx, shift1, shift2; opus_int32 rand_seed, harm_Gain_Q15, rand_Gain_Q15, inv_gain_Q16, inv_gain_Q30; opus_int32 energy1, energy2, *rand_ptr, *pred_lag_ptr; opus_int32 LPC_exc_Q14, LPC_pred_Q10, LTP_pred_Q12; opus_int16 rand_scale_Q14; opus_int16 *B_Q14, *exc_buf_ptr; opus_int32 *sLPC_Q14_ptr; opus_int16 exc_buf[ 2 * MAX_SUB_FRAME_LENGTH ]; opus_int16 A_Q12[ MAX_LPC_ORDER ]; opus_int16 sLTP[ MAX_FRAME_LENGTH ]; opus_int32 sLTP_Q14[ 2 * MAX_FRAME_LENGTH ]; silk_PLC_struct *psPLC = &psDec->sPLC; if (psDec->first_frame_after_reset) silk_memset(psPLC->prevLPC_Q12, 0, MAX_LPC_ORDER*sizeof(psPLC->prevLPC_Q12[ 0 ])); /* Find random noise component */ /* Scale previous excitation signal */ exc_buf_ptr = exc_buf; for( k = 0; k < 2; k++ ) { for( i = 0; i < psPLC->subfr_length; i++ ) { exc_buf_ptr[ i ] = ( opus_int16 )silk_RSHIFT( silk_SMULWW( psDec->exc_Q10[ i + ( k + psPLC->nb_subfr - 2 ) * psPLC->subfr_length ], psPLC->prevGain_Q16[ k ] ), 10 ); } exc_buf_ptr += psPLC->subfr_length; } /* Find the subframe with lowest energy of the last two and use that as random noise generator */ silk_sum_sqr_shift( &energy1, &shift1, exc_buf, psPLC->subfr_length ); silk_sum_sqr_shift( &energy2, &shift2, &exc_buf[ psPLC->subfr_length ], psPLC->subfr_length ); if( silk_RSHIFT( energy1, shift2 ) < silk_RSHIFT( energy2, shift1 ) ) { /* First sub-frame has lowest energy */ rand_ptr = &psDec->exc_Q10[ silk_max_int( 0, ( psPLC->nb_subfr - 1 ) * psPLC->subfr_length - RAND_BUF_SIZE ) ]; } else { /* Second sub-frame has lowest energy */ rand_ptr = &psDec->exc_Q10[ silk_max_int( 0, psPLC->nb_subfr * psPLC->subfr_length - RAND_BUF_SIZE ) ]; } /* Setup Gain to random noise component */ B_Q14 = psPLC->LTPCoef_Q14; rand_scale_Q14 = psPLC->randScale_Q14; /* Setup attenuation gains */ harm_Gain_Q15 = HARM_ATT_Q15[ silk_min_int( NB_ATT - 1, psDec->lossCnt ) ]; if( psDec->prevSignalType == TYPE_VOICED ) { rand_Gain_Q15 = PLC_RAND_ATTENUATE_V_Q15[ silk_min_int( NB_ATT - 1, psDec->lossCnt ) ]; } else { rand_Gain_Q15 = PLC_RAND_ATTENUATE_UV_Q15[ silk_min_int( NB_ATT - 1, psDec->lossCnt ) ]; } /* LPC concealment. Apply BWE to previous LPC */ silk_bwexpander( psPLC->prevLPC_Q12, psDec->LPC_order, SILK_FIX_CONST( BWE_COEF, 16 ) ); /* Preload LPC coeficients to array on stack. Gives small performance gain */ silk_memcpy( A_Q12, psPLC->prevLPC_Q12, psDec->LPC_order * sizeof( opus_int16 ) ); /* First Lost frame */ if( psDec->lossCnt == 0 ) { rand_scale_Q14 = 1 << 14; /* Reduce random noise Gain for voiced frames */ if( psDec->prevSignalType == TYPE_VOICED ) { for( i = 0; i < LTP_ORDER; i++ ) { rand_scale_Q14 -= B_Q14[ i ]; } rand_scale_Q14 = silk_max_16( 3277, rand_scale_Q14 ); /* 0.2 */ rand_scale_Q14 = ( opus_int16 )silk_RSHIFT( silk_SMULBB( rand_scale_Q14, psPLC->prevLTP_scale_Q14 ), 14 ); } else { /* Reduce random noise for unvoiced frames with high LPC gain */ opus_int32 invGain_Q30, down_scale_Q30; silk_LPC_inverse_pred_gain( &invGain_Q30, psPLC->prevLPC_Q12, psDec->LPC_order ); down_scale_Q30 = silk_min_32( silk_RSHIFT( 1 << 30, LOG2_INV_LPC_GAIN_HIGH_THRES ), invGain_Q30 ); down_scale_Q30 = silk_max_32( silk_RSHIFT( 1 << 30, LOG2_INV_LPC_GAIN_LOW_THRES ), down_scale_Q30 ); down_scale_Q30 = silk_LSHIFT( down_scale_Q30, LOG2_INV_LPC_GAIN_HIGH_THRES ); rand_Gain_Q15 = silk_RSHIFT( silk_SMULWB( down_scale_Q30, rand_Gain_Q15 ), 14 ); } } rand_seed = psPLC->rand_seed; lag = silk_RSHIFT_ROUND( psPLC->pitchL_Q8, 8 ); sLTP_buf_idx = psDec->ltp_mem_length; /* Rewhiten LTP state */ idx = psDec->ltp_mem_length - lag - psDec->LPC_order - LTP_ORDER / 2; silk_assert( idx > 0 ); silk_LPC_analysis_filter( &sLTP[ idx ], &psDec->outBuf[ idx ], A_Q12, psDec->ltp_mem_length - idx, psDec->LPC_order ); /* Scale LTP state */ inv_gain_Q16 = silk_INVERSE32_varQ( psPLC->prevGain_Q16[ 1 ], 32 ); inv_gain_Q16 = silk_min( inv_gain_Q16, silk_int16_MAX ); inv_gain_Q30 = silk_LSHIFT( inv_gain_Q16, 14 ); for( i = idx + psDec->LPC_order; i < psDec->ltp_mem_length; i++ ) { sLTP_Q14[ i ] = silk_SMULWB( inv_gain_Q30, sLTP[ i ] ); } /***************************/ /* LTP synthesis filtering */ /***************************/ for( k = 0; k < psDec->nb_subfr; k++ ) { /* Setup pointer */ pred_lag_ptr = &sLTP_Q14[ sLTP_buf_idx - lag + LTP_ORDER / 2 ]; for( i = 0; i < psDec->subfr_length; i++ ) { /* Unrolled loop */ LTP_pred_Q12 = silk_SMULWB( pred_lag_ptr[ 0 ], B_Q14[ 0 ] ); LTP_pred_Q12 = silk_SMLAWB( LTP_pred_Q12, pred_lag_ptr[ -1 ], B_Q14[ 1 ] ); LTP_pred_Q12 = silk_SMLAWB( LTP_pred_Q12, pred_lag_ptr[ -2 ], B_Q14[ 2 ] ); LTP_pred_Q12 = silk_SMLAWB( LTP_pred_Q12, pred_lag_ptr[ -3 ], B_Q14[ 3 ] ); LTP_pred_Q12 = silk_SMLAWB( LTP_pred_Q12, pred_lag_ptr[ -4 ], B_Q14[ 4 ] ); pred_lag_ptr++; /* Generate LPC excitation */ rand_seed = silk_RAND( rand_seed ); idx = silk_RSHIFT( rand_seed, 25 ) & RAND_BUF_MASK; LPC_exc_Q14 = silk_LSHIFT32( silk_SMULWB( rand_ptr[ idx ], rand_scale_Q14 ), 6 ); /* Random noise part */ LPC_exc_Q14 = silk_ADD32( LPC_exc_Q14, silk_LSHIFT32( LTP_pred_Q12, 2 ) ); /* Harmonic part */ sLTP_Q14[ sLTP_buf_idx ] = LPC_exc_Q14; sLTP_buf_idx++; } /* Gradually reduce LTP gain */ for( j = 0; j < LTP_ORDER; j++ ) { B_Q14[ j ] = silk_RSHIFT( silk_SMULBB( harm_Gain_Q15, B_Q14[ j ] ), 15 ); } /* Gradually reduce excitation gain */ rand_scale_Q14 = silk_RSHIFT( silk_SMULBB( rand_scale_Q14, rand_Gain_Q15 ), 15 ); /* Slowly increase pitch lag */ psPLC->pitchL_Q8 = silk_SMLAWB( psPLC->pitchL_Q8, psPLC->pitchL_Q8, PITCH_DRIFT_FAC_Q16 ); psPLC->pitchL_Q8 = silk_min_32( psPLC->pitchL_Q8, silk_LSHIFT( silk_SMULBB( MAX_PITCH_LAG_MS, psDec->fs_kHz ), 8 ) ); lag = silk_RSHIFT_ROUND( psPLC->pitchL_Q8, 8 ); } /***************************/ /* LPC synthesis filtering */ /***************************/ sLPC_Q14_ptr = &sLTP_Q14[ psDec->ltp_mem_length - MAX_LPC_ORDER ]; /* Copy LPC state */ silk_memcpy( sLPC_Q14_ptr, psDec->sLPC_Q14_buf, MAX_LPC_ORDER * sizeof( opus_int32 ) ); silk_assert( psDec->LPC_order >= 10 ); /* check that unrolling works */ for( i = 0; i < psDec->frame_length; i++ ) { /* partly unrolled */ LPC_pred_Q10 = silk_SMULWB( sLPC_Q14_ptr[ MAX_LPC_ORDER + i - 1 ], A_Q12[ 0 ] ); LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, sLPC_Q14_ptr[ MAX_LPC_ORDER + i - 2 ], A_Q12[ 1 ] ); LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, sLPC_Q14_ptr[ MAX_LPC_ORDER + i - 3 ], A_Q12[ 2 ] ); LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, sLPC_Q14_ptr[ MAX_LPC_ORDER + i - 4 ], A_Q12[ 3 ] ); LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, sLPC_Q14_ptr[ MAX_LPC_ORDER + i - 5 ], A_Q12[ 4 ] ); LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, sLPC_Q14_ptr[ MAX_LPC_ORDER + i - 6 ], A_Q12[ 5 ] ); LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, sLPC_Q14_ptr[ MAX_LPC_ORDER + i - 7 ], A_Q12[ 6 ] ); LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, sLPC_Q14_ptr[ MAX_LPC_ORDER + i - 8 ], A_Q12[ 7 ] ); LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, sLPC_Q14_ptr[ MAX_LPC_ORDER + i - 9 ], A_Q12[ 8 ] ); LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, sLPC_Q14_ptr[ MAX_LPC_ORDER + i - 10 ], A_Q12[ 9 ] ); for( j = 10; j < psDec->LPC_order; j++ ) { LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, sLPC_Q14_ptr[ MAX_LPC_ORDER + i - j - 1 ], A_Q12[ j ] ); } /* Add prediction to LPC excitation */ sLPC_Q14_ptr[ MAX_LPC_ORDER + i ] = silk_ADD_LSHIFT32( sLPC_Q14_ptr[ MAX_LPC_ORDER + i ], LPC_pred_Q10, 4 ); /* Scale with Gain */ frame[ i ] = ( opus_int16 )silk_SAT16( silk_RSHIFT_ROUND( silk_SMULWW( sLPC_Q14_ptr[ MAX_LPC_ORDER + i ], psPLC->prevGain_Q16[ 1 ] ), 14 ) ); } /* Save LPC state */ silk_memcpy( psDec->sLPC_Q14_buf, &sLPC_Q14_ptr[ psDec->frame_length ], MAX_LPC_ORDER * sizeof( opus_int32 ) ); /**************************************/ /* Update states */ /**************************************/ psPLC->rand_seed = rand_seed; psPLC->randScale_Q14 = rand_scale_Q14; for( i = 0; i < MAX_NB_SUBFR; i++ ) { psDecCtrl->pitchL[ i ] = lag; } }
/* 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; }
void silk_prefilter_FIX( silk_encoder_state_FIX *psEnc, /* I/O Encoder state */ const silk_encoder_control_FIX *psEncCtrl, /* I Encoder control */ opus_int32 xw_Q3[], /* O Weighted signal */ const opus_int16 x[] /* I Speech signal */ ) { silk_prefilter_state_FIX *P = &psEnc->sPrefilt; opus_int j, k, lag; opus_int32 tmp_32; const opus_int16 *AR1_shp_Q13; const opus_int16 *px; opus_int32 *pxw_Q3; opus_int HarmShapeGain_Q12, Tilt_Q14; opus_int32 HarmShapeFIRPacked_Q12, LF_shp_Q14; VARDECL( opus_int32, x_filt_Q12 ); VARDECL( opus_int32, st_res_Q2 ); opus_int16 B_Q10[ 2 ]; SAVE_STACK; /* Set up pointers */ px = x; pxw_Q3 = xw_Q3; lag = P->lagPrev; ALLOC( x_filt_Q12, psEnc->sCmn.subfr_length, opus_int32 ); ALLOC( st_res_Q2, psEnc->sCmn.subfr_length, opus_int32 ); for( k = 0; k < psEnc->sCmn.nb_subfr; k++ ) { /* Update Variables that change per sub frame */ if( psEnc->sCmn.indices.signalType == TYPE_VOICED ) { lag = psEncCtrl->pitchL[ k ]; } /* Noise shape parameters */ HarmShapeGain_Q12 = silk_SMULWB( (opus_int32)psEncCtrl->HarmShapeGain_Q14[ k ], 16384 - psEncCtrl->HarmBoost_Q14[ k ] ); silk_assert( HarmShapeGain_Q12 >= 0 ); HarmShapeFIRPacked_Q12 = silk_RSHIFT( HarmShapeGain_Q12, 2 ); HarmShapeFIRPacked_Q12 |= silk_LSHIFT( (opus_int32)silk_RSHIFT( HarmShapeGain_Q12, 1 ), 16 ); Tilt_Q14 = psEncCtrl->Tilt_Q14[ k ]; LF_shp_Q14 = psEncCtrl->LF_shp_Q14[ k ]; AR1_shp_Q13 = &psEncCtrl->AR1_Q13[ k * MAX_SHAPE_LPC_ORDER ]; /* Short term FIR filtering*/ silk_warped_LPC_analysis_filter_FIX( P->sAR_shp, st_res_Q2, AR1_shp_Q13, px, psEnc->sCmn.warping_Q16, psEnc->sCmn.subfr_length, psEnc->sCmn.shapingLPCOrder ); /* Reduce (mainly) low frequencies during harmonic emphasis */ B_Q10[ 0 ] = silk_RSHIFT_ROUND( psEncCtrl->GainsPre_Q14[ k ], 4 ); tmp_32 = silk_SMLABB( SILK_FIX_CONST( INPUT_TILT, 26 ), psEncCtrl->HarmBoost_Q14[ k ], HarmShapeGain_Q12 ); /* Q26 */ tmp_32 = silk_SMLABB( tmp_32, psEncCtrl->coding_quality_Q14, SILK_FIX_CONST( HIGH_RATE_INPUT_TILT, 12 ) ); /* Q26 */ tmp_32 = silk_SMULWB( tmp_32, -psEncCtrl->GainsPre_Q14[ k ] ); /* Q24 */ tmp_32 = silk_RSHIFT_ROUND( tmp_32, 14 ); /* Q10 */ B_Q10[ 1 ]= silk_SAT16( tmp_32 ); x_filt_Q12[ 0 ] = silk_MLA( silk_MUL( st_res_Q2[ 0 ], B_Q10[ 0 ] ), P->sHarmHP_Q2, B_Q10[ 1 ] ); for( j = 1; j < psEnc->sCmn.subfr_length; j++ ) { x_filt_Q12[ j ] = silk_MLA( silk_MUL( st_res_Q2[ j ], B_Q10[ 0 ] ), st_res_Q2[ j - 1 ], B_Q10[ 1 ] ); } P->sHarmHP_Q2 = st_res_Q2[ psEnc->sCmn.subfr_length - 1 ]; silk_prefilt_FIX( P, x_filt_Q12, pxw_Q3, HarmShapeFIRPacked_Q12, Tilt_Q14, LF_shp_Q14, lag, psEnc->sCmn.subfr_length ); px += psEnc->sCmn.subfr_length; pxw_Q3 += psEnc->sCmn.subfr_length; } P->lagPrev = psEncCtrl->pitchL[ psEnc->sCmn.nb_subfr - 1 ]; RESTORE_STACK; }
void silk_find_LTP_FIX( opus_int16 b_Q14[ MAX_NB_SUBFR * LTP_ORDER ], /* O LTP coefs */ opus_int32 WLTP[ MAX_NB_SUBFR * LTP_ORDER * LTP_ORDER ], /* O Weight for LTP quantization */ opus_int *LTPredCodGain_Q7, /* O LTP coding gain */ const opus_int16 r_lpc[], /* I residual signal after LPC signal + state for first 10 ms */ const opus_int lag[ MAX_NB_SUBFR ], /* I LTP lags */ const opus_int32 Wght_Q15[ MAX_NB_SUBFR ], /* I weights */ const opus_int subfr_length, /* I subframe length */ const opus_int nb_subfr, /* I number of subframes */ const opus_int mem_offset, /* I number of samples in LTP memory */ opus_int corr_rshifts[ MAX_NB_SUBFR ] /* O right shifts applied to correlations */ ) { opus_int i, k, lshift; const opus_int16 *r_ptr, *lag_ptr; opus_int16 *b_Q14_ptr; opus_int32 regu; opus_int32 *WLTP_ptr; opus_int32 b_Q16[ LTP_ORDER ], delta_b_Q14[ LTP_ORDER ], d_Q14[ MAX_NB_SUBFR ], nrg[ MAX_NB_SUBFR ], g_Q26; opus_int32 w[ MAX_NB_SUBFR ], WLTP_max, max_abs_d_Q14, max_w_bits; opus_int32 temp32, denom32; opus_int extra_shifts; opus_int rr_shifts, maxRshifts, maxRshifts_wxtra, LZs; opus_int32 LPC_res_nrg, LPC_LTP_res_nrg, div_Q16; opus_int32 Rr[ LTP_ORDER ], rr[ MAX_NB_SUBFR ]; opus_int32 wd, m_Q12; b_Q14_ptr = b_Q14; WLTP_ptr = WLTP; r_ptr = &r_lpc[ mem_offset ]; for( k = 0; k < nb_subfr; k++ ) { lag_ptr = r_ptr - ( lag[ k ] + LTP_ORDER / 2 ); silk_sum_sqr_shift( &rr[ k ], &rr_shifts, r_ptr, subfr_length ); /* rr[ k ] in Q( -rr_shifts ) */ /* Assure headroom */ LZs = silk_CLZ32( rr[k] ); if( LZs < LTP_CORRS_HEAD_ROOM ) { rr[ k ] = silk_RSHIFT_ROUND( rr[ k ], LTP_CORRS_HEAD_ROOM - LZs ); rr_shifts += ( LTP_CORRS_HEAD_ROOM - LZs ); } corr_rshifts[ k ] = rr_shifts; silk_corrMatrix_FIX( lag_ptr, subfr_length, LTP_ORDER, LTP_CORRS_HEAD_ROOM, WLTP_ptr, &corr_rshifts[ k ] ); /* WLTP_fix_ptr in Q( -corr_rshifts[ k ] ) */ /* The correlation vector always has lower max abs value than rr and/or RR so head room is assured */ silk_corrVector_FIX( lag_ptr, r_ptr, subfr_length, LTP_ORDER, Rr, corr_rshifts[ k ] ); /* Rr_fix_ptr in Q( -corr_rshifts[ k ] ) */ if( corr_rshifts[ k ] > rr_shifts ) { rr[ k ] = silk_RSHIFT( rr[ k ], corr_rshifts[ k ] - rr_shifts ); /* rr[ k ] in Q( -corr_rshifts[ k ] ) */ } silk_assert( rr[ k ] >= 0 ); regu = 1; regu = silk_SMLAWB( regu, rr[ k ], SILK_FIX_CONST( LTP_DAMPING/3, 16 ) ); regu = silk_SMLAWB( regu, matrix_ptr( WLTP_ptr, 0, 0, LTP_ORDER ), SILK_FIX_CONST( LTP_DAMPING/3, 16 ) ); regu = silk_SMLAWB( regu, matrix_ptr( WLTP_ptr, LTP_ORDER-1, LTP_ORDER-1, LTP_ORDER ), SILK_FIX_CONST( LTP_DAMPING/3, 16 ) ); silk_regularize_correlations_FIX( WLTP_ptr, &rr[k], regu, LTP_ORDER ); silk_solve_LDL_FIX( WLTP_ptr, LTP_ORDER, Rr, b_Q16 ); /* WLTP_fix_ptr and Rr_fix_ptr both in Q(-corr_rshifts[k]) */ /* Limit and store in Q14 */ silk_fit_LTP( b_Q16, b_Q14_ptr ); /* Calculate residual energy */ nrg[ k ] = silk_residual_energy16_covar_FIX( b_Q14_ptr, WLTP_ptr, Rr, rr[ k ], LTP_ORDER, 14 ); /* nrg_fix in Q( -corr_rshifts[ k ] ) */ /* temp = Wght[ k ] / ( nrg[ k ] * Wght[ k ] + 0.01f * subfr_length ); */ extra_shifts = silk_min_int( corr_rshifts[ k ], LTP_CORRS_HEAD_ROOM ); denom32 = silk_LSHIFT_SAT32( silk_SMULWB( nrg[ k ], Wght_Q15[ k ] ), 1 + extra_shifts ) + /* Q( -corr_rshifts[ k ] + extra_shifts ) */ silk_RSHIFT( silk_SMULWB( subfr_length, 655 ), corr_rshifts[ k ] - extra_shifts ); /* Q( -corr_rshifts[ k ] + extra_shifts ) */ denom32 = silk_max( denom32, 1 ); silk_assert( ((opus_int64)Wght_Q15[ k ] << 16 ) < silk_int32_MAX ); /* Wght always < 0.5 in Q0 */ temp32 = silk_DIV32( silk_LSHIFT( (opus_int32)Wght_Q15[ k ], 16 ), denom32 ); /* Q( 15 + 16 + corr_rshifts[k] - extra_shifts ) */ temp32 = silk_RSHIFT( temp32, 31 + corr_rshifts[ k ] - extra_shifts - 26 ); /* Q26 */ /* Limit temp such that the below scaling never wraps around */ WLTP_max = 0; for( i = 0; i < LTP_ORDER * LTP_ORDER; i++ ) { WLTP_max = silk_max( WLTP_ptr[ i ], WLTP_max ); } lshift = silk_CLZ32( WLTP_max ) - 1 - 3; /* keep 3 bits free for vq_nearest_neighbor_fix */ silk_assert( 26 - 18 + lshift >= 0 ); if( 26 - 18 + lshift < 31 ) { temp32 = silk_min_32( temp32, silk_LSHIFT( (opus_int32)1, 26 - 18 + lshift ) ); } silk_scale_vector32_Q26_lshift_18( WLTP_ptr, temp32, LTP_ORDER * LTP_ORDER ); /* WLTP_ptr in Q( 18 - corr_rshifts[ k ] ) */ w[ k ] = matrix_ptr( WLTP_ptr, LTP_ORDER/2, LTP_ORDER/2, LTP_ORDER ); /* w in Q( 18 - corr_rshifts[ k ] ) */ silk_assert( w[k] >= 0 ); r_ptr += subfr_length; b_Q14_ptr += LTP_ORDER; WLTP_ptr += LTP_ORDER * LTP_ORDER; } maxRshifts = 0; for( k = 0; k < nb_subfr; k++ ) { maxRshifts = silk_max_int( corr_rshifts[ k ], maxRshifts ); } /* Compute LTP coding gain */ if( LTPredCodGain_Q7 != NULL ) { LPC_LTP_res_nrg = 0; LPC_res_nrg = 0; silk_assert( LTP_CORRS_HEAD_ROOM >= 2 ); /* Check that no overflow will happen when adding */ for( k = 0; k < nb_subfr; k++ ) { LPC_res_nrg = silk_ADD32( LPC_res_nrg, silk_RSHIFT( silk_ADD32( silk_SMULWB( rr[ k ], Wght_Q15[ k ] ), 1 ), 1 + ( maxRshifts - corr_rshifts[ k ] ) ) ); /* Q( -maxRshifts ) */ LPC_LTP_res_nrg = silk_ADD32( LPC_LTP_res_nrg, silk_RSHIFT( silk_ADD32( silk_SMULWB( nrg[ k ], Wght_Q15[ k ] ), 1 ), 1 + ( maxRshifts - corr_rshifts[ k ] ) ) ); /* Q( -maxRshifts ) */ } LPC_LTP_res_nrg = silk_max( LPC_LTP_res_nrg, 1 ); /* avoid division by zero */ div_Q16 = silk_DIV32_varQ( LPC_res_nrg, LPC_LTP_res_nrg, 16 ); *LTPredCodGain_Q7 = ( opus_int )silk_SMULBB( 3, silk_lin2log( div_Q16 ) - ( 16 << 7 ) ); silk_assert( *LTPredCodGain_Q7 == ( opus_int )silk_SAT16( silk_MUL( 3, silk_lin2log( div_Q16 ) - ( 16 << 7 ) ) ) ); } /* smoothing */ /* d = sum( B, 1 ); */ b_Q14_ptr = b_Q14; for( k = 0; k < nb_subfr; k++ ) { d_Q14[ k ] = 0; for( i = 0; i < LTP_ORDER; i++ ) { d_Q14[ k ] += b_Q14_ptr[ i ]; } b_Q14_ptr += LTP_ORDER; } /* m = ( w * d' ) / ( sum( w ) + 1e-3 ); */ /* Find maximum absolute value of d_Q14 and the bits used by w in Q0 */ max_abs_d_Q14 = 0; max_w_bits = 0; for( k = 0; k < nb_subfr; k++ ) { max_abs_d_Q14 = silk_max_32( max_abs_d_Q14, silk_abs( d_Q14[ k ] ) ); /* w[ k ] is in Q( 18 - corr_rshifts[ k ] ) */ /* Find bits needed in Q( 18 - maxRshifts ) */ max_w_bits = silk_max_32( max_w_bits, 32 - silk_CLZ32( w[ k ] ) + corr_rshifts[ k ] - maxRshifts ); } /* max_abs_d_Q14 = (5 << 15); worst case, i.e. LTP_ORDER * -silk_int16_MIN */ silk_assert( max_abs_d_Q14 <= ( 5 << 15 ) ); /* How many bits is needed for w*d' in Q( 18 - maxRshifts ) in the worst case, of all d_Q14's being equal to max_abs_d_Q14 */ extra_shifts = max_w_bits + 32 - silk_CLZ32( max_abs_d_Q14 ) - 14; /* Subtract what we got available; bits in output var plus maxRshifts */ extra_shifts -= ( 32 - 1 - 2 + maxRshifts ); /* Keep sign bit free as well as 2 bits for accumulation */ extra_shifts = silk_max_int( extra_shifts, 0 ); maxRshifts_wxtra = maxRshifts + extra_shifts; temp32 = silk_RSHIFT( 262, maxRshifts + extra_shifts ) + 1; /* 1e-3f in Q( 18 - (maxRshifts + extra_shifts) ) */ wd = 0; for( k = 0; k < nb_subfr; k++ ) { /* w has at least 2 bits of headroom so no overflow should happen */ temp32 = silk_ADD32( temp32, silk_RSHIFT( w[ k ], maxRshifts_wxtra - corr_rshifts[ k ] ) ); /* Q( 18 - maxRshifts_wxtra ) */ wd = silk_ADD32( wd, silk_LSHIFT( silk_SMULWW( silk_RSHIFT( w[ k ], maxRshifts_wxtra - corr_rshifts[ k ] ), d_Q14[ k ] ), 2 ) ); /* Q( 18 - maxRshifts_wxtra ) */ } m_Q12 = silk_DIV32_varQ( wd, temp32, 12 ); b_Q14_ptr = b_Q14; for( k = 0; k < nb_subfr; k++ ) { /* w_fix[ k ] from Q( 18 - corr_rshifts[ k ] ) to Q( 16 ) */ if( 2 - corr_rshifts[k] > 0 ) { temp32 = silk_RSHIFT( w[ k ], 2 - corr_rshifts[ k ] ); } else { temp32 = silk_LSHIFT_SAT32( w[ k ], corr_rshifts[ k ] - 2 ); } g_Q26 = silk_MUL( silk_DIV32( SILK_FIX_CONST( LTP_SMOOTHING, 26 ), silk_RSHIFT( SILK_FIX_CONST( LTP_SMOOTHING, 26 ), 10 ) + temp32 ), /* Q10 */ silk_LSHIFT_SAT32( silk_SUB_SAT32( (opus_int32)m_Q12, silk_RSHIFT( d_Q14[ k ], 2 ) ), 4 ) ); /* Q16 */ temp32 = 0; for( i = 0; i < LTP_ORDER; i++ ) { delta_b_Q14[ i ] = silk_max_16( b_Q14_ptr[ i ], 1638 ); /* 1638_Q14 = 0.1_Q0 */ temp32 += delta_b_Q14[ i ]; /* Q14 */ } temp32 = silk_DIV32( g_Q26, temp32 ); /* Q14 -> Q12 */ for( i = 0; i < LTP_ORDER; i++ ) { b_Q14_ptr[ i ] = silk_LIMIT_32( (opus_int32)b_Q14_ptr[ i ] + silk_SMULWB( silk_LSHIFT_SAT32( temp32, 4 ), delta_b_Q14[ i ] ), -16000, 28000 ); } b_Q14_ptr += LTP_ORDER; } }
/* Compute reflection coefficients from input signal */ void silk_burg_modified( opus_int32 *res_nrg, /* O Residual energy */ opus_int *res_nrg_Q, /* O Residual energy Q value */ opus_int32 A_Q16[], /* O Prediction coefficients (length order) */ const opus_int16 x[], /* I Input signal, length: nb_subfr * ( D + subfr_length ) */ const opus_int32 minInvGain_Q30, /* I Inverse of max prediction gain */ const opus_int subfr_length, /* I Input signal subframe length (incl. D preceding samples) */ const opus_int nb_subfr, /* I Number of subframes stacked in x */ const opus_int D /* I Order */ ) { opus_int k, n, s, lz, rshifts, rshifts_extra, reached_max_gain; opus_int32 C0, num, nrg, rc_Q31, invGain_Q30, Atmp_QA, Atmp1, tmp1, tmp2, x1, x2; const opus_int16 *x_ptr; opus_int32 C_first_row[ SILK_MAX_ORDER_LPC ]; opus_int32 C_last_row[ SILK_MAX_ORDER_LPC ]; opus_int32 Af_QA[ SILK_MAX_ORDER_LPC ]; opus_int32 CAf[ SILK_MAX_ORDER_LPC + 1 ]; opus_int32 CAb[ SILK_MAX_ORDER_LPC + 1 ]; silk_assert( subfr_length * nb_subfr <= MAX_FRAME_SIZE ); /* Compute autocorrelations, added over subframes */ silk_sum_sqr_shift( &C0, &rshifts, x, nb_subfr * subfr_length ); if( rshifts > MAX_RSHIFTS ) { C0 = silk_LSHIFT32( C0, rshifts - MAX_RSHIFTS ); silk_assert( C0 > 0 ); rshifts = MAX_RSHIFTS; } else { lz = silk_CLZ32( C0 ) - 1; rshifts_extra = N_BITS_HEAD_ROOM - lz; if( rshifts_extra > 0 ) { rshifts_extra = silk_min( rshifts_extra, MAX_RSHIFTS - rshifts ); C0 = silk_RSHIFT32( C0, rshifts_extra ); } else { rshifts_extra = silk_max( rshifts_extra, MIN_RSHIFTS - rshifts ); C0 = silk_LSHIFT32( C0, -rshifts_extra ); } rshifts += rshifts_extra; } CAb[ 0 ] = CAf[ 0 ] = C0 + silk_SMMUL( SILK_FIX_CONST( FIND_LPC_COND_FAC, 32 ), C0 ) + 1; /* Q(-rshifts) */ silk_memset( C_first_row, 0, SILK_MAX_ORDER_LPC * sizeof( opus_int32 ) ); if( rshifts > 0 ) { for( s = 0; s < nb_subfr; s++ ) { x_ptr = x + s * subfr_length; for( n = 1; n < D + 1; n++ ) { C_first_row[ n - 1 ] += (opus_int32)silk_RSHIFT64( silk_inner_prod16_aligned_64( x_ptr, x_ptr + n, subfr_length - n ), rshifts ); } } } else { for( s = 0; s < nb_subfr; s++ ) { x_ptr = x + s * subfr_length; for( n = 1; n < D + 1; n++ ) { C_first_row[ n - 1 ] += silk_LSHIFT32( silk_inner_prod_aligned( x_ptr, x_ptr + n, subfr_length - n ), -rshifts ); } } } silk_memcpy( C_last_row, C_first_row, SILK_MAX_ORDER_LPC * sizeof( opus_int32 ) ); /* Initialize */ CAb[ 0 ] = CAf[ 0 ] = C0 + silk_SMMUL( SILK_FIX_CONST( FIND_LPC_COND_FAC, 32 ), C0 ) + 1; /* Q(-rshifts) */ invGain_Q30 = (opus_int32)1 << 30; reached_max_gain = 0; for( n = 0; n < D; n++ ) { /* Update first row of correlation matrix (without first element) */ /* Update last row of correlation matrix (without last element, stored in reversed order) */ /* Update C * Af */ /* Update C * flipud(Af) (stored in reversed order) */ if( rshifts > -2 ) { for( s = 0; s < nb_subfr; s++ ) { x_ptr = x + s * subfr_length; x1 = -silk_LSHIFT32( (opus_int32)x_ptr[ n ], 16 - rshifts ); /* Q(16-rshifts) */ x2 = -silk_LSHIFT32( (opus_int32)x_ptr[ subfr_length - n - 1 ], 16 - rshifts ); /* Q(16-rshifts) */ tmp1 = silk_LSHIFT32( (opus_int32)x_ptr[ n ], QA - 16 ); /* Q(QA-16) */ tmp2 = silk_LSHIFT32( (opus_int32)x_ptr[ subfr_length - n - 1 ], QA - 16 ); /* Q(QA-16) */ for( k = 0; k < n; k++ ) { C_first_row[ k ] = silk_SMLAWB( C_first_row[ k ], x1, x_ptr[ n - k - 1 ] ); /* Q( -rshifts ) */ C_last_row[ k ] = silk_SMLAWB( C_last_row[ k ], x2, x_ptr[ subfr_length - n + k ] ); /* Q( -rshifts ) */ Atmp_QA = Af_QA[ k ]; tmp1 = silk_SMLAWB( tmp1, Atmp_QA, x_ptr[ n - k - 1 ] ); /* Q(QA-16) */ tmp2 = silk_SMLAWB( tmp2, Atmp_QA, x_ptr[ subfr_length - n + k ] ); /* Q(QA-16) */ } tmp1 = silk_LSHIFT32( -tmp1, 32 - QA - rshifts ); /* Q(16-rshifts) */ tmp2 = silk_LSHIFT32( -tmp2, 32 - QA - rshifts ); /* Q(16-rshifts) */ for( k = 0; k <= n; k++ ) { CAf[ k ] = silk_SMLAWB( CAf[ k ], tmp1, x_ptr[ n - k ] ); /* Q( -rshift ) */ CAb[ k ] = silk_SMLAWB( CAb[ k ], tmp2, x_ptr[ subfr_length - n + k - 1 ] ); /* Q( -rshift ) */ } } } else { for( s = 0; s < nb_subfr; s++ ) { x_ptr = x + s * subfr_length; x1 = -silk_LSHIFT32( (opus_int32)x_ptr[ n ], -rshifts ); /* Q( -rshifts ) */ x2 = -silk_LSHIFT32( (opus_int32)x_ptr[ subfr_length - n - 1 ], -rshifts ); /* Q( -rshifts ) */ tmp1 = silk_LSHIFT32( (opus_int32)x_ptr[ n ], 17 ); /* Q17 */ tmp2 = silk_LSHIFT32( (opus_int32)x_ptr[ subfr_length - n - 1 ], 17 ); /* Q17 */ for( k = 0; k < n; k++ ) { C_first_row[ k ] = silk_MLA( C_first_row[ k ], x1, x_ptr[ n - k - 1 ] ); /* Q( -rshifts ) */ C_last_row[ k ] = silk_MLA( C_last_row[ k ], x2, x_ptr[ subfr_length - n + k ] ); /* Q( -rshifts ) */ Atmp1 = silk_RSHIFT_ROUND( Af_QA[ k ], QA - 17 ); /* Q17 */ tmp1 = silk_MLA( tmp1, x_ptr[ n - k - 1 ], Atmp1 ); /* Q17 */ tmp2 = silk_MLA( tmp2, x_ptr[ subfr_length - n + k ], Atmp1 ); /* Q17 */ } tmp1 = -tmp1; /* Q17 */ tmp2 = -tmp2; /* Q17 */ for( k = 0; k <= n; k++ ) { CAf[ k ] = silk_SMLAWW( CAf[ k ], tmp1, silk_LSHIFT32( (opus_int32)x_ptr[ n - k ], -rshifts - 1 ) ); /* Q( -rshift ) */ CAb[ k ] = silk_SMLAWW( CAb[ k ], tmp2, silk_LSHIFT32( (opus_int32)x_ptr[ subfr_length - n + k - 1 ], -rshifts - 1 ) ); /* Q( -rshift ) */ } } } /* Calculate nominator and denominator for the next order reflection (parcor) coefficient */ tmp1 = C_first_row[ n ]; /* Q( -rshifts ) */ tmp2 = C_last_row[ n ]; /* Q( -rshifts ) */ num = 0; /* Q( -rshifts ) */ nrg = silk_ADD32( CAb[ 0 ], CAf[ 0 ] ); /* Q( 1-rshifts ) */ for( k = 0; k < n; k++ ) { Atmp_QA = Af_QA[ k ]; lz = silk_CLZ32( silk_abs( Atmp_QA ) ) - 1; lz = silk_min( 32 - QA, lz ); Atmp1 = silk_LSHIFT32( Atmp_QA, lz ); /* Q( QA + lz ) */ tmp1 = silk_ADD_LSHIFT32( tmp1, silk_SMMUL( C_last_row[ n - k - 1 ], Atmp1 ), 32 - QA - lz ); /* Q( -rshifts ) */ tmp2 = silk_ADD_LSHIFT32( tmp2, silk_SMMUL( C_first_row[ n - k - 1 ], Atmp1 ), 32 - QA - lz ); /* Q( -rshifts ) */ num = silk_ADD_LSHIFT32( num, silk_SMMUL( CAb[ n - k ], Atmp1 ), 32 - QA - lz ); /* Q( -rshifts ) */ nrg = silk_ADD_LSHIFT32( nrg, silk_SMMUL( silk_ADD32( CAb[ k + 1 ], CAf[ k + 1 ] ), Atmp1 ), 32 - QA - lz ); /* Q( 1-rshifts ) */ } CAf[ n + 1 ] = tmp1; /* Q( -rshifts ) */ CAb[ n + 1 ] = tmp2; /* Q( -rshifts ) */ num = silk_ADD32( num, tmp2 ); /* Q( -rshifts ) */ num = silk_LSHIFT32( -num, 1 ); /* Q( 1-rshifts ) */ /* Calculate the next order reflection (parcor) coefficient */ if( silk_abs( num ) < nrg ) { rc_Q31 = silk_DIV32_varQ( num, nrg, 31 ); } else { rc_Q31 = ( num > 0 ) ? silk_int32_MAX : silk_int32_MIN; } /* Update inverse prediction gain */ tmp1 = ( (opus_int32)1 << 30 ) - silk_SMMUL( rc_Q31, rc_Q31 ); tmp1 = silk_LSHIFT( silk_SMMUL( invGain_Q30, tmp1 ), 2 ); if( tmp1 <= minInvGain_Q30 ) { /* Max prediction gain exceeded; set reflection coefficient such that max prediction gain is exactly hit */ tmp2 = ( (opus_int32)1 << 30 ) - silk_DIV32_varQ( minInvGain_Q30, invGain_Q30, 30 ); /* Q30 */ rc_Q31 = silk_SQRT_APPROX( tmp2 ); /* Q15 */ /* Newton-Raphson iteration */ rc_Q31 = silk_RSHIFT32( rc_Q31 + silk_DIV32( tmp2, rc_Q31 ), 1 ); /* Q15 */ rc_Q31 = silk_LSHIFT32( rc_Q31, 16 ); /* Q31 */ if( num < 0 ) { /* Ensure adjusted reflection coefficients has the original sign */ rc_Q31 = -rc_Q31; } invGain_Q30 = minInvGain_Q30; reached_max_gain = 1; } else { invGain_Q30 = tmp1; } /* Update the AR coefficients */ for( k = 0; k < (n + 1) >> 1; k++ ) { tmp1 = Af_QA[ k ]; /* QA */ tmp2 = Af_QA[ n - k - 1 ]; /* QA */ Af_QA[ k ] = silk_ADD_LSHIFT32( tmp1, silk_SMMUL( tmp2, rc_Q31 ), 1 ); /* QA */ Af_QA[ n - k - 1 ] = silk_ADD_LSHIFT32( tmp2, silk_SMMUL( tmp1, rc_Q31 ), 1 ); /* QA */ } Af_QA[ n ] = silk_RSHIFT32( rc_Q31, 31 - QA ); /* QA */ if( reached_max_gain ) { /* Reached max prediction gain; set remaining coefficients to zero and exit loop */ for( k = n + 1; k < D; k++ ) { Af_QA[ k ] = 0; } break; } /* Update C * Af and C * Ab */ for( k = 0; k <= n + 1; k++ ) { tmp1 = CAf[ k ]; /* Q( -rshifts ) */ tmp2 = CAb[ n - k + 1 ]; /* Q( -rshifts ) */ CAf[ k ] = silk_ADD_LSHIFT32( tmp1, silk_SMMUL( tmp2, rc_Q31 ), 1 ); /* Q( -rshifts ) */ CAb[ n - k + 1 ] = silk_ADD_LSHIFT32( tmp2, silk_SMMUL( tmp1, rc_Q31 ), 1 ); /* Q( -rshifts ) */ } } if( reached_max_gain ) { for( k = 0; k < D; k++ ) { /* Scale coefficients */ A_Q16[ k ] = -silk_RSHIFT_ROUND( Af_QA[ k ], QA - 16 ); } /* Subtract energy of preceding samples from C0 */ if( rshifts > 0 ) { for( s = 0; s < nb_subfr; s++ ) { x_ptr = x + s * subfr_length; C0 -= (opus_int32)silk_RSHIFT64( silk_inner_prod16_aligned_64( x_ptr, x_ptr, D ), rshifts ); } } else { for( s = 0; s < nb_subfr; s++ ) { x_ptr = x + s * subfr_length; C0 -= silk_LSHIFT32( silk_inner_prod_aligned( x_ptr, x_ptr, D ), -rshifts ); } } /* Approximate residual energy */ *res_nrg = silk_LSHIFT( silk_SMMUL( invGain_Q30, C0 ), 2 ); *res_nrg_Q = -rshifts; } else { /* Return residual energy */ nrg = CAf[ 0 ]; /* Q( -rshifts ) */ tmp1 = (opus_int32)1 << 16; /* Q16 */ for( k = 0; k < D; k++ ) { Atmp1 = silk_RSHIFT_ROUND( Af_QA[ k ], QA - 16 ); /* Q16 */ nrg = silk_SMLAWW( nrg, CAf[ k + 1 ], Atmp1 ); /* Q( -rshifts ) */ tmp1 = silk_SMLAWW( tmp1, Atmp1, Atmp1 ); /* Q16 */ A_Q16[ k ] = -Atmp1; } *res_nrg = silk_SMLAWW( nrg, silk_SMMUL( FIND_LPC_COND_FAC, C0 ), -tmp1 ); /* Q( -rshifts ) */ *res_nrg_Q = -rshifts; } }
/* notch filter just above Nyquist. */ void silk_resampler_private_up2_HQ( opus_int32 *S, /* I/O Resampler state [ 6 ] */ opus_int16 *out, /* O Output signal [ 2 * len ] */ const opus_int16 *in, /* I Input signal [ len ] */ opus_int32 len /* I Number of input samples */ ) { opus_int32 k; opus_int32 in32, out32_1, out32_2, Y, X; silk_assert( silk_resampler_up2_hq_0[ 0 ] > 0 ); silk_assert( silk_resampler_up2_hq_0[ 1 ] > 0 ); silk_assert( silk_resampler_up2_hq_0[ 2 ] < 0 ); silk_assert( silk_resampler_up2_hq_1[ 0 ] > 0 ); silk_assert( silk_resampler_up2_hq_1[ 1 ] > 0 ); silk_assert( silk_resampler_up2_hq_1[ 2 ] < 0 ); /* Internal variables and state are in Q10 format */ for( k = 0; k < len; k++ ) { /* Convert to Q10 */ in32 = silk_LSHIFT( (opus_int32)in[ k ], 10 ); /* First all-pass section for even output sample */ Y = silk_SUB32( in32, S[ 0 ] ); X = silk_SMULWB( Y, silk_resampler_up2_hq_0[ 0 ] ); out32_1 = silk_ADD32( S[ 0 ], X ); S[ 0 ] = silk_ADD32( in32, X ); /* Second all-pass section for even output sample */ Y = silk_SUB32( out32_1, S[ 1 ] ); X = silk_SMULWB( Y, silk_resampler_up2_hq_0[ 1 ] ); out32_2 = silk_ADD32( S[ 1 ], X ); S[ 1 ] = silk_ADD32( out32_1, X ); /* Third all-pass section for even output sample */ Y = silk_SUB32( out32_2, S[ 2 ] ); X = silk_SMLAWB( Y, Y, silk_resampler_up2_hq_0[ 2 ] ); out32_1 = silk_ADD32( S[ 2 ], X ); S[ 2 ] = silk_ADD32( out32_2, X ); /* Apply gain in Q15, convert back to int16 and store to output */ out[ 2 * k ] = (opus_int16)silk_SAT16( silk_RSHIFT_ROUND( out32_1, 10 ) ); /* First all-pass section for odd output sample */ Y = silk_SUB32( in32, S[ 3 ] ); X = silk_SMULWB( Y, silk_resampler_up2_hq_1[ 0 ] ); out32_1 = silk_ADD32( S[ 3 ], X ); S[ 3 ] = silk_ADD32( in32, X ); /* Second all-pass section for odd output sample */ Y = silk_SUB32( out32_1, S[ 4 ] ); X = silk_SMULWB( Y, silk_resampler_up2_hq_1[ 1 ] ); out32_2 = silk_ADD32( S[ 4 ], X ); S[ 4 ] = silk_ADD32( out32_1, X ); /* Third all-pass section for odd output sample */ Y = silk_SUB32( out32_2, S[ 5 ] ); X = silk_SMLAWB( Y, Y, silk_resampler_up2_hq_1[ 2 ] ); out32_1 = silk_ADD32( S[ 5 ], X ); S[ 5 ] = silk_ADD32( out32_2, X ); /* Apply gain in Q15, convert back to int16 and store to output */ out[ 2 * k + 1 ] = (opus_int16)silk_SAT16( silk_RSHIFT_ROUND( out32_1, 10 ) ); } }
/* Downsample by a factor 2/3, low quality */ void silk_resampler_down2_3( opus_int32 *S, /* I/O State vector [ 6 ] */ opus_int16 *out, /* O Output signal [ floor(2*inLen/3) ] */ const opus_int16 *in, /* I Input signal [ inLen ] */ opus_int32 inLen /* I Number of input samples */ ) { opus_int32 nSamplesIn, counter, res_Q6; VARDECL( opus_int32, buf ); opus_int32 *buf_ptr; SAVE_STACK; ALLOC( buf, RESAMPLER_MAX_BATCH_SIZE_IN + ORDER_FIR, opus_int32 ); /* Copy buffered samples to start of buffer */ silk_memcpy( buf, S, ORDER_FIR * sizeof( opus_int32 ) ); /* Iterate over blocks of frameSizeIn input samples */ while( 1 ) { nSamplesIn = silk_min( inLen, RESAMPLER_MAX_BATCH_SIZE_IN ); /* Second-order AR filter (output in Q8) */ silk_resampler_private_AR2( &S[ ORDER_FIR ], &buf[ ORDER_FIR ], in, silk_Resampler_2_3_COEFS_LQ, nSamplesIn ); /* Interpolate filtered signal */ buf_ptr = buf; counter = nSamplesIn; while( counter > 2 ) { /* Inner product */ res_Q6 = silk_SMULWB( buf_ptr[ 0 ], silk_Resampler_2_3_COEFS_LQ[ 2 ] ); res_Q6 = silk_SMLAWB( res_Q6, buf_ptr[ 1 ], silk_Resampler_2_3_COEFS_LQ[ 3 ] ); res_Q6 = silk_SMLAWB( res_Q6, buf_ptr[ 2 ], silk_Resampler_2_3_COEFS_LQ[ 5 ] ); res_Q6 = silk_SMLAWB( res_Q6, buf_ptr[ 3 ], silk_Resampler_2_3_COEFS_LQ[ 4 ] ); /* Scale down, saturate and store in output array */ *out++ = (opus_int16)silk_SAT16( silk_RSHIFT_ROUND( res_Q6, 6 ) ); res_Q6 = silk_SMULWB( buf_ptr[ 1 ], silk_Resampler_2_3_COEFS_LQ[ 4 ] ); res_Q6 = silk_SMLAWB( res_Q6, buf_ptr[ 2 ], silk_Resampler_2_3_COEFS_LQ[ 5 ] ); res_Q6 = silk_SMLAWB( res_Q6, buf_ptr[ 3 ], silk_Resampler_2_3_COEFS_LQ[ 3 ] ); res_Q6 = silk_SMLAWB( res_Q6, buf_ptr[ 4 ], silk_Resampler_2_3_COEFS_LQ[ 2 ] ); /* Scale down, saturate and store in output array */ *out++ = (opus_int16)silk_SAT16( silk_RSHIFT_ROUND( res_Q6, 6 ) ); buf_ptr += 3; counter -= 3; } in += nSamplesIn; inLen -= nSamplesIn; if( inLen > 0 ) { /* More iterations to do; copy last part of filtered signal to beginning of buffer */ silk_memcpy( buf, &buf[ nSamplesIn ], ORDER_FIR * sizeof( opus_int32 ) ); } else { break; } } /* Copy last part of filtered signal to the state for the next call */ silk_memcpy( S, &buf[ nSamplesIn ], ORDER_FIR * sizeof( opus_int32 ) ); RESTORE_STACK; }
/* Compute reflection coefficients from input signal */ void silk_burg_modified_sse4_1( opus_int32 *res_nrg, /* O Residual energy */ opus_int *res_nrg_Q, /* O Residual energy Q value */ opus_int32 A_Q16[], /* O Prediction coefficients (length order) */ const opus_int16 x[], /* I Input signal, length: nb_subfr * (D + subfr_length) */ const opus_int32 minInvGain_Q30, /* I Inverse of max prediction gain */ const opus_int subfr_length, /* I Input signal subframe length (incl. D preceding samples) */ const opus_int nb_subfr, /* I Number of subframes stacked in x */ const opus_int D, /* I Order */ int arch /* I Run-time architecture */ ) { opus_int k, n, s, lz, rshifts, rshifts_extra, reached_max_gain; opus_int32 C0, num, nrg, rc_Q31, invGain_Q30, Atmp_QA, Atmp1, tmp1, tmp2, x1, x2; const opus_int16 *x_ptr; opus_int32 C_first_row[ SILK_MAX_ORDER_LPC ]; opus_int32 C_last_row[ SILK_MAX_ORDER_LPC ]; opus_int32 Af_QA[ SILK_MAX_ORDER_LPC ]; opus_int32 CAf[ SILK_MAX_ORDER_LPC + 1 ]; opus_int32 CAb[ SILK_MAX_ORDER_LPC + 1 ]; opus_int32 xcorr[ SILK_MAX_ORDER_LPC ]; __m128i FIRST_3210, LAST_3210, ATMP_3210, TMP1_3210, TMP2_3210, T1_3210, T2_3210, PTR_3210, SUBFR_3210, X1_3210, X2_3210; __m128i CONST1 = _mm_set1_epi32(1); silk_assert(subfr_length * nb_subfr <= MAX_FRAME_SIZE); /* Compute autocorrelations, added over subframes */ silk_sum_sqr_shift(&C0, &rshifts, x, nb_subfr * subfr_length); if(rshifts > MAX_RSHIFTS) { C0 = silk_LSHIFT32(C0, rshifts - MAX_RSHIFTS); silk_assert(C0 > 0); rshifts = MAX_RSHIFTS; } else { lz = silk_CLZ32(C0) - 1; rshifts_extra = N_BITS_HEAD_ROOM - lz; if(rshifts_extra > 0) { rshifts_extra = silk_min(rshifts_extra, MAX_RSHIFTS - rshifts); C0 = silk_RSHIFT32(C0, rshifts_extra); } else { rshifts_extra = silk_max(rshifts_extra, MIN_RSHIFTS - rshifts); C0 = silk_LSHIFT32(C0, -rshifts_extra); } rshifts += rshifts_extra; } CAb[ 0 ] = CAf[ 0 ] = C0 + silk_SMMUL(SILK_FIX_CONST(FIND_LPC_COND_FAC, 32), C0) + 1; /* Q(-rshifts) */ silk_memset(C_first_row, 0, SILK_MAX_ORDER_LPC * sizeof(opus_int32)); if(rshifts > 0) { for(s = 0; s < nb_subfr; s++) { x_ptr = x + s * subfr_length; for(n = 1; n < D + 1; n++) { C_first_row[ n - 1 ] += (opus_int32)silk_RSHIFT64( silk_inner_prod16_aligned_64(x_ptr, x_ptr + n, subfr_length - n, arch), rshifts); } } } else { for(s = 0; s < nb_subfr; s++) { int i; opus_int32 d; x_ptr = x + s * subfr_length; celt_pitch_xcorr(x_ptr, x_ptr + 1, xcorr, subfr_length - D, D, arch); for(n = 1; n < D + 1; n++) { for (i = n + subfr_length - D, d = 0; i < subfr_length; i++) d = MAC16_16(d, x_ptr[ i ], x_ptr[ i - n ]); xcorr[ n - 1 ] += d; } for(n = 1; n < D + 1; n++) { C_first_row[ n - 1 ] += silk_LSHIFT32(xcorr[ n - 1 ], -rshifts); } } } silk_memcpy(C_last_row, C_first_row, SILK_MAX_ORDER_LPC * sizeof(opus_int32)); /* Initialize */ CAb[ 0 ] = CAf[ 0 ] = C0 + silk_SMMUL(SILK_FIX_CONST(FIND_LPC_COND_FAC, 32), C0) + 1; /* Q(-rshifts) */ invGain_Q30 = (opus_int32)1 << 30; reached_max_gain = 0; for(n = 0; n < D; n++) { /* Update first row of correlation matrix (without first element) */ /* Update last row of correlation matrix (without last element, stored in reversed order) */ /* Update C * Af */ /* Update C * flipud(Af) (stored in reversed order) */ if(rshifts > -2) { for(s = 0; s < nb_subfr; s++) { x_ptr = x + s * subfr_length; x1 = -silk_LSHIFT32((opus_int32)x_ptr[ n ], 16 - rshifts); /* Q(16-rshifts) */ x2 = -silk_LSHIFT32((opus_int32)x_ptr[ subfr_length - n - 1 ], 16 - rshifts); /* Q(16-rshifts) */ tmp1 = silk_LSHIFT32((opus_int32)x_ptr[ n ], QA - 16); /* Q(QA-16) */ tmp2 = silk_LSHIFT32((opus_int32)x_ptr[ subfr_length - n - 1 ], QA - 16); /* Q(QA-16) */ for(k = 0; k < n; k++) { C_first_row[ k ] = silk_SMLAWB(C_first_row[ k ], x1, x_ptr[ n - k - 1 ] ); /* Q(-rshifts) */ C_last_row[ k ] = silk_SMLAWB(C_last_row[ k ], x2, x_ptr[ subfr_length - n + k ]); /* Q(-rshifts) */ Atmp_QA = Af_QA[ k ]; tmp1 = silk_SMLAWB(tmp1, Atmp_QA, x_ptr[ n - k - 1 ] ); /* Q(QA-16) */ tmp2 = silk_SMLAWB(tmp2, Atmp_QA, x_ptr[ subfr_length - n + k ]); /* Q(QA-16) */ } tmp1 = silk_LSHIFT32(-tmp1, 32 - QA - rshifts); /* Q(16-rshifts) */ tmp2 = silk_LSHIFT32(-tmp2, 32 - QA - rshifts); /* Q(16-rshifts) */ for(k = 0; k <= n; k++) { CAf[ k ] = silk_SMLAWB(CAf[ k ], tmp1, x_ptr[ n - k ] ); /* Q(-rshift) */ CAb[ k ] = silk_SMLAWB(CAb[ k ], tmp2, x_ptr[ subfr_length - n + k - 1 ]); /* Q(-rshift) */ } } } else { for(s = 0; s < nb_subfr; s++) { x_ptr = x + s * subfr_length; x1 = -silk_LSHIFT32((opus_int32)x_ptr[ n ], -rshifts); /* Q(-rshifts) */ x2 = -silk_LSHIFT32((opus_int32)x_ptr[ subfr_length - n - 1 ], -rshifts); /* Q(-rshifts) */ tmp1 = silk_LSHIFT32((opus_int32)x_ptr[ n ], 17); /* Q17 */ tmp2 = silk_LSHIFT32((opus_int32)x_ptr[ subfr_length - n - 1 ], 17); /* Q17 */ X1_3210 = _mm_set1_epi32(x1); X2_3210 = _mm_set1_epi32(x2); TMP1_3210 = _mm_setzero_si128(); TMP2_3210 = _mm_setzero_si128(); for(k = 0; k < n - 3; k += 4) { PTR_3210 = OP_CVTEPI16_EPI32_M64(&x_ptr[ n - k - 1 - 3 ]); SUBFR_3210 = OP_CVTEPI16_EPI32_M64(&x_ptr[ subfr_length - n + k ]); FIRST_3210 = _mm_loadu_si128((__m128i *)&C_first_row[ k ]); PTR_3210 = _mm_shuffle_epi32(PTR_3210, _MM_SHUFFLE(0, 1, 2, 3)); LAST_3210 = _mm_loadu_si128((__m128i *)&C_last_row[ k ]); ATMP_3210 = _mm_loadu_si128((__m128i *)&Af_QA[ k ]); T1_3210 = _mm_mullo_epi32(PTR_3210, X1_3210); T2_3210 = _mm_mullo_epi32(SUBFR_3210, X2_3210); ATMP_3210 = _mm_srai_epi32(ATMP_3210, 7); ATMP_3210 = _mm_add_epi32(ATMP_3210, CONST1); ATMP_3210 = _mm_srai_epi32(ATMP_3210, 1); FIRST_3210 = _mm_add_epi32(FIRST_3210, T1_3210); LAST_3210 = _mm_add_epi32(LAST_3210, T2_3210); PTR_3210 = _mm_mullo_epi32(ATMP_3210, PTR_3210); SUBFR_3210 = _mm_mullo_epi32(ATMP_3210, SUBFR_3210); _mm_storeu_si128((__m128i *)&C_first_row[ k ], FIRST_3210); _mm_storeu_si128((__m128i *)&C_last_row[ k ], LAST_3210); TMP1_3210 = _mm_add_epi32(TMP1_3210, PTR_3210); TMP2_3210 = _mm_add_epi32(TMP2_3210, SUBFR_3210); } TMP1_3210 = _mm_add_epi32(TMP1_3210, _mm_unpackhi_epi64(TMP1_3210, TMP1_3210)); TMP2_3210 = _mm_add_epi32(TMP2_3210, _mm_unpackhi_epi64(TMP2_3210, TMP2_3210)); TMP1_3210 = _mm_add_epi32(TMP1_3210, _mm_shufflelo_epi16(TMP1_3210, 0x0E)); TMP2_3210 = _mm_add_epi32(TMP2_3210, _mm_shufflelo_epi16(TMP2_3210, 0x0E)); tmp1 += _mm_cvtsi128_si32(TMP1_3210); tmp2 += _mm_cvtsi128_si32(TMP2_3210); for(; k < n; k++) { C_first_row[ k ] = silk_MLA(C_first_row[ k ], x1, x_ptr[ n - k - 1 ] ); /* Q(-rshifts) */ C_last_row[ k ] = silk_MLA(C_last_row[ k ], x2, x_ptr[ subfr_length - n + k ]); /* Q(-rshifts) */ Atmp1 = silk_RSHIFT_ROUND(Af_QA[ k ], QA - 17); /* Q17 */ tmp1 = silk_MLA(tmp1, x_ptr[ n - k - 1 ], Atmp1); /* Q17 */ tmp2 = silk_MLA(tmp2, x_ptr[ subfr_length - n + k ], Atmp1); /* Q17 */ } tmp1 = -tmp1; /* Q17 */ tmp2 = -tmp2; /* Q17 */ { __m128i xmm_tmp1, xmm_tmp2; __m128i xmm_x_ptr_n_k_x2x0, xmm_x_ptr_n_k_x3x1; __m128i xmm_x_ptr_sub_x2x0, xmm_x_ptr_sub_x3x1; xmm_tmp1 = _mm_set1_epi32(tmp1); xmm_tmp2 = _mm_set1_epi32(tmp2); for(k = 0; k <= n - 3; k += 4) { xmm_x_ptr_n_k_x2x0 = OP_CVTEPI16_EPI32_M64(&x_ptr[ n - k - 3 ]); xmm_x_ptr_sub_x2x0 = OP_CVTEPI16_EPI32_M64(&x_ptr[ subfr_length - n + k - 1 ]); xmm_x_ptr_n_k_x2x0 = _mm_shuffle_epi32(xmm_x_ptr_n_k_x2x0, _MM_SHUFFLE(0, 1, 2, 3)); xmm_x_ptr_n_k_x2x0 = _mm_slli_epi32(xmm_x_ptr_n_k_x2x0, -rshifts - 1); xmm_x_ptr_sub_x2x0 = _mm_slli_epi32(xmm_x_ptr_sub_x2x0, -rshifts - 1); /* equal shift right 4 bytes, xmm_x_ptr_n_k_x3x1 = _mm_srli_si128(xmm_x_ptr_n_k_x2x0, 4)*/ xmm_x_ptr_n_k_x3x1 = _mm_shuffle_epi32(xmm_x_ptr_n_k_x2x0, _MM_SHUFFLE(0, 3, 2, 1)); xmm_x_ptr_sub_x3x1 = _mm_shuffle_epi32(xmm_x_ptr_sub_x2x0, _MM_SHUFFLE(0, 3, 2, 1)); xmm_x_ptr_n_k_x2x0 = _mm_mul_epi32(xmm_x_ptr_n_k_x2x0, xmm_tmp1); xmm_x_ptr_n_k_x3x1 = _mm_mul_epi32(xmm_x_ptr_n_k_x3x1, xmm_tmp1); xmm_x_ptr_sub_x2x0 = _mm_mul_epi32(xmm_x_ptr_sub_x2x0, xmm_tmp2); xmm_x_ptr_sub_x3x1 = _mm_mul_epi32(xmm_x_ptr_sub_x3x1, xmm_tmp2); xmm_x_ptr_n_k_x2x0 = _mm_srli_epi64(xmm_x_ptr_n_k_x2x0, 16); xmm_x_ptr_n_k_x3x1 = _mm_slli_epi64(xmm_x_ptr_n_k_x3x1, 16); xmm_x_ptr_sub_x2x0 = _mm_srli_epi64(xmm_x_ptr_sub_x2x0, 16); xmm_x_ptr_sub_x3x1 = _mm_slli_epi64(xmm_x_ptr_sub_x3x1, 16); xmm_x_ptr_n_k_x2x0 = _mm_blend_epi16(xmm_x_ptr_n_k_x2x0, xmm_x_ptr_n_k_x3x1, 0xCC); xmm_x_ptr_sub_x2x0 = _mm_blend_epi16(xmm_x_ptr_sub_x2x0, xmm_x_ptr_sub_x3x1, 0xCC); X1_3210 = _mm_loadu_si128((__m128i *)&CAf[ k ]); PTR_3210 = _mm_loadu_si128((__m128i *)&CAb[ k ]); X1_3210 = _mm_add_epi32(X1_3210, xmm_x_ptr_n_k_x2x0); PTR_3210 = _mm_add_epi32(PTR_3210, xmm_x_ptr_sub_x2x0); _mm_storeu_si128((__m128i *)&CAf[ k ], X1_3210); _mm_storeu_si128((__m128i *)&CAb[ k ], PTR_3210); } for(; k <= n; k++) { CAf[ k ] = silk_SMLAWW(CAf[ k ], tmp1, silk_LSHIFT32((opus_int32)x_ptr[ n - k ], -rshifts - 1)); /* Q(-rshift) */ CAb[ k ] = silk_SMLAWW(CAb[ k ], tmp2, silk_LSHIFT32((opus_int32)x_ptr[ subfr_length - n + k - 1 ], -rshifts - 1)); /* Q(-rshift) */ } } } } /* Calculate nominator and denominator for the next order reflection (parcor) coefficient */ tmp1 = C_first_row[ n ]; /* Q(-rshifts) */ tmp2 = C_last_row[ n ]; /* Q(-rshifts) */ num = 0; /* Q(-rshifts) */ nrg = silk_ADD32(CAb[ 0 ], CAf[ 0 ]); /* Q(1-rshifts) */ for(k = 0; k < n; k++) { Atmp_QA = Af_QA[ k ]; lz = silk_CLZ32(silk_abs(Atmp_QA)) - 1; lz = silk_min(32 - QA, lz); Atmp1 = silk_LSHIFT32(Atmp_QA, lz); /* Q(QA + lz) */ tmp1 = silk_ADD_LSHIFT32(tmp1, silk_SMMUL(C_last_row[ n - k - 1 ], Atmp1), 32 - QA - lz); /* Q(-rshifts) */ tmp2 = silk_ADD_LSHIFT32(tmp2, silk_SMMUL(C_first_row[ n - k - 1 ], Atmp1), 32 - QA - lz); /* Q(-rshifts) */ num = silk_ADD_LSHIFT32(num, silk_SMMUL(CAb[ n - k ], Atmp1), 32 - QA - lz); /* Q(-rshifts) */ nrg = silk_ADD_LSHIFT32(nrg, silk_SMMUL(silk_ADD32(CAb[ k + 1 ], CAf[ k + 1 ]), Atmp1), 32 - QA - lz); /* Q(1-rshifts) */ } CAf[ n + 1 ] = tmp1; /* Q(-rshifts) */ CAb[ n + 1 ] = tmp2; /* Q(-rshifts) */ num = silk_ADD32(num, tmp2); /* Q(-rshifts) */ num = silk_LSHIFT32(-num, 1); /* Q(1-rshifts) */ /* Calculate the next order reflection (parcor) coefficient */ if(silk_abs(num) < nrg) { rc_Q31 = silk_DIV32_varQ(num, nrg, 31); } else { rc_Q31 = (num > 0) ? silk_int32_MAX : silk_int32_MIN; } /* Update inverse prediction gain */ tmp1 = ((opus_int32)1 << 30) - silk_SMMUL(rc_Q31, rc_Q31); tmp1 = silk_LSHIFT(silk_SMMUL(invGain_Q30, tmp1), 2); if(tmp1 <= minInvGain_Q30) { /* Max prediction gain exceeded; set reflection coefficient such that max prediction gain is exactly hit */ tmp2 = ((opus_int32)1 << 30) - silk_DIV32_varQ(minInvGain_Q30, invGain_Q30, 30); /* Q30 */ rc_Q31 = silk_SQRT_APPROX(tmp2); /* Q15 */ /* Newton-Raphson iteration */ rc_Q31 = silk_RSHIFT32(rc_Q31 + silk_DIV32(tmp2, rc_Q31), 1); /* Q15 */ rc_Q31 = silk_LSHIFT32(rc_Q31, 16); /* Q31 */ if(num < 0) { /* Ensure adjusted reflection coefficients has the original sign */ rc_Q31 = -rc_Q31; } invGain_Q30 = minInvGain_Q30; reached_max_gain = 1; } else { invGain_Q30 = tmp1; } /* Update the AR coefficients */ for(k = 0; k < (n + 1) >> 1; k++) { tmp1 = Af_QA[ k ]; /* QA */ tmp2 = Af_QA[ n - k - 1 ]; /* QA */ Af_QA[ k ] = silk_ADD_LSHIFT32(tmp1, silk_SMMUL(tmp2, rc_Q31), 1); /* QA */ Af_QA[ n - k - 1 ] = silk_ADD_LSHIFT32(tmp2, silk_SMMUL(tmp1, rc_Q31), 1); /* QA */ } Af_QA[ n ] = silk_RSHIFT32(rc_Q31, 31 - QA); /* QA */ if(reached_max_gain) { /* Reached max prediction gain; set remaining coefficients to zero and exit loop */ for(k = n + 1; k < D; k++) { Af_QA[ k ] = 0; } break; } /* Update C * Af and C * Ab */ for(k = 0; k <= n + 1; k++) { tmp1 = CAf[ k ]; /* Q(-rshifts) */ tmp2 = CAb[ n - k + 1 ]; /* Q(-rshifts) */ CAf[ k ] = silk_ADD_LSHIFT32(tmp1, silk_SMMUL(tmp2, rc_Q31), 1); /* Q(-rshifts) */ CAb[ n - k + 1 ] = silk_ADD_LSHIFT32(tmp2, silk_SMMUL(tmp1, rc_Q31), 1); /* Q(-rshifts) */ } } if(reached_max_gain) { for(k = 0; k < D; k++) { /* Scale coefficients */ A_Q16[ k ] = -silk_RSHIFT_ROUND(Af_QA[ k ], QA - 16); } /* Subtract energy of preceding samples from C0 */ if(rshifts > 0) { for(s = 0; s < nb_subfr; s++) { x_ptr = x + s * subfr_length; C0 -= (opus_int32)silk_RSHIFT64(silk_inner_prod16_aligned_64(x_ptr, x_ptr, D, arch), rshifts); } } else { for(s = 0; s < nb_subfr; s++) { x_ptr = x + s * subfr_length; C0 -= silk_LSHIFT32(silk_inner_prod_aligned(x_ptr, x_ptr, D, arch), -rshifts); } } /* Approximate residual energy */ *res_nrg = silk_LSHIFT(silk_SMMUL(invGain_Q30, C0), 2); *res_nrg_Q = -rshifts; } else { /* Return residual energy */ nrg = CAf[ 0 ]; /* Q(-rshifts) */ tmp1 = (opus_int32)1 << 16; /* Q16 */ for(k = 0; k < D; k++) { Atmp1 = silk_RSHIFT_ROUND(Af_QA[ k ], QA - 16); /* Q16 */ nrg = silk_SMLAWW(nrg, CAf[ k + 1 ], Atmp1); /* Q(-rshifts) */ tmp1 = silk_SMLAWW(tmp1, Atmp1, Atmp1); /* Q16 */ A_Q16[ k ] = -Atmp1; } *res_nrg = silk_SMLAWW(nrg, silk_SMMUL(SILK_FIX_CONST(FIND_LPC_COND_FAC, 32), C0), -tmp1);/* Q(-rshifts) */ *res_nrg_Q = -rshifts; } }
/* If not all roots are found, the a_Q16 coefficients are bandwidth expanded until convergence. */ void silk_A2NLSF( opus_int16 *NLSF, /* O Normalized Line Spectral Frequencies in Q15 (0..2^15-1) [d] */ opus_int32 *a_Q16, /* I/O Monic whitening filter coefficients in Q16 [d] */ const opus_int d /* I Filter order (must be even) */ ) { opus_int i, k, m, dd, root_ix, ffrac; opus_int32 xlo, xhi, xmid; opus_int32 ylo, yhi, ymid, thr; opus_int32 nom, den; opus_int32 P[ SILK_MAX_ORDER_LPC / 2 + 1 ]; opus_int32 Q[ SILK_MAX_ORDER_LPC / 2 + 1 ]; opus_int32 *PQ[ 2 ]; opus_int32 *p; /* Store pointers to array */ PQ[ 0 ] = P; PQ[ 1 ] = Q; dd = silk_RSHIFT( d, 1 ); silk_A2NLSF_init( a_Q16, P, Q, dd ); /* Find roots, alternating between P and Q */ p = P; /* Pointer to polynomial */ xlo = silk_LSFCosTab_FIX_Q12[ 0 ]; /* Q12*/ ylo = silk_A2NLSF_eval_poly( p, xlo, dd ); if( ylo < 0 ) { /* Set the first NLSF to zero and move on to the next */ NLSF[ 0 ] = 0; p = Q; /* Pointer to polynomial */ ylo = silk_A2NLSF_eval_poly( p, xlo, dd ); root_ix = 1; /* Index of current root */ } else { root_ix = 0; /* Index of current root */ } k = 1; /* Loop counter */ i = 0; /* Counter for bandwidth expansions applied */ thr = 0; while( 1 ) { /* Evaluate polynomial */ xhi = silk_LSFCosTab_FIX_Q12[ k ]; /* Q12 */ yhi = silk_A2NLSF_eval_poly( p, xhi, dd ); /* Detect zero crossing */ if( ( ylo <= 0 && yhi >= thr ) || ( ylo >= 0 && yhi <= -thr ) ) { if( yhi == 0 ) { /* If the root lies exactly at the end of the current */ /* interval, look for the next root in the next interval */ thr = 1; } else { thr = 0; } /* Binary division */ ffrac = -256; for( m = 0; m < BIN_DIV_STEPS_A2NLSF_FIX; m++ ) { /* Evaluate polynomial */ xmid = silk_RSHIFT_ROUND( xlo + xhi, 1 ); ymid = silk_A2NLSF_eval_poly( p, xmid, dd ); /* Detect zero crossing */ if( ( ylo <= 0 && ymid >= 0 ) || ( ylo >= 0 && ymid <= 0 ) ) { /* Reduce frequency */ xhi = xmid; yhi = ymid; } else { /* Increase frequency */ xlo = xmid; ylo = ymid; ffrac = silk_ADD_RSHIFT( ffrac, 128, m ); } } /* Interpolate */ if( silk_abs( ylo ) < 65536 ) { /* Avoid dividing by zero */ den = ylo - yhi; nom = silk_LSHIFT( ylo, 8 - BIN_DIV_STEPS_A2NLSF_FIX ) + silk_RSHIFT( den, 1 ); if( den != 0 ) { ffrac += silk_DIV32( nom, den ); } } else { /* No risk of dividing by zero because abs(ylo - yhi) >= abs(ylo) >= 65536 */ ffrac += silk_DIV32( ylo, silk_RSHIFT( ylo - yhi, 8 - BIN_DIV_STEPS_A2NLSF_FIX ) ); } NLSF[ root_ix ] = (opus_int16)silk_min_32( silk_LSHIFT( (opus_int32)k, 8 ) + ffrac, silk_int16_MAX ); silk_assert( NLSF[ root_ix ] >= 0 ); root_ix++; /* Next root */ if( root_ix >= d ) { /* Found all roots */ break; } /* Alternate pointer to polynomial */ p = PQ[ root_ix & 1 ]; /* Evaluate polynomial */ xlo = silk_LSFCosTab_FIX_Q12[ k - 1 ]; /* Q12*/ ylo = silk_LSHIFT( 1 - ( root_ix & 2 ), 12 ); } else { /* Increment loop counter */ k++; xlo = xhi; ylo = yhi; thr = 0; if( k > LSF_COS_TAB_SZ_FIX ) { i++; if( i > MAX_ITERATIONS_A2NLSF_FIX ) { /* Set NLSFs to white spectrum and exit */ NLSF[ 0 ] = (opus_int16)silk_DIV32_16( 1 << 15, d + 1 ); for( k = 1; k < d; k++ ) { NLSF[ k ] = (opus_int16)silk_SMULBB( k + 1, NLSF[ 0 ] ); } return; } /* Error: Apply progressively more bandwidth expansion and run again */ silk_bwexpander_32( a_Q16, d, 65536 - silk_SMULBB( 10 + i, i ) ); /* 10_Q16 = 0.00015*/ silk_A2NLSF_init( a_Q16, P, Q, dd ); p = P; /* Pointer to polynomial */ xlo = silk_LSFCosTab_FIX_Q12[ 0 ]; /* Q12*/ ylo = silk_A2NLSF_eval_poly( p, xlo, dd ); if( ylo < 0 ) { /* Set the first NLSF to zero and move on to the next */ NLSF[ 0 ] = 0; p = Q; /* Pointer to polynomial */ ylo = silk_A2NLSF_eval_poly( p, xlo, dd ); root_ix = 1; /* Index of current root */ } else { root_ix = 0; /* Index of current root */ } k = 1; /* Reset loop counter */ } } } }
/* compute whitening filter coefficients from normalized line spectral frequencies */ void silk_NLSF2A( opus_int16 *a_Q12, /* O monic whitening filter coefficients in Q12, [ d ] */ const opus_int16 *NLSF, /* I normalized line spectral frequencies in Q15, [ d ] */ const opus_int d /* I filter order (should be even) */ ) { /* This ordering was found to maximize quality. It improves numerical accuracy of silk_NLSF2A_find_poly() compared to "standard" ordering. */ static const unsigned char ordering16[16] = { 0, 15, 8, 7, 4, 11, 12, 3, 2, 13, 10, 5, 6, 9, 14, 1 }; static const unsigned char ordering10[10] = { 0, 9, 6, 3, 4, 5, 8, 1, 2, 7 }; const unsigned char *ordering; opus_int k, i, dd; opus_int32 cos_LSF_QA[ SILK_MAX_ORDER_LPC ]; opus_int32 P[ SILK_MAX_ORDER_LPC / 2 + 1 ], Q[ SILK_MAX_ORDER_LPC / 2 + 1 ]; opus_int32 Ptmp, Qtmp, f_int, f_frac, cos_val, delta; opus_int32 a32_QA1[ SILK_MAX_ORDER_LPC ]; opus_int32 maxabs, absval, idx=0, sc_Q16; silk_assert( LSF_COS_TAB_SZ_FIX == 128 ); silk_assert( d==10||d==16 ); /* convert LSFs to 2*cos(LSF), using piecewise linear curve from table */ ordering = d == 16 ? ordering16 : ordering10; for( k = 0; k < d; k++ ) { silk_assert(NLSF[k] >= 0 ); /* f_int on a scale 0-127 (rounded down) */ f_int = silk_RSHIFT( NLSF[k], 15 - 7 ); /* f_frac, range: 0..255 */ f_frac = NLSF[k] - silk_LSHIFT( f_int, 15 - 7 ); silk_assert(f_int >= 0); silk_assert(f_int < LSF_COS_TAB_SZ_FIX ); /* Read start and end value from table */ cos_val = silk_LSFCosTab_FIX_Q12[ f_int ]; /* Q12 */ delta = silk_LSFCosTab_FIX_Q12[ f_int + 1 ] - cos_val; /* Q12, with a range of 0..200 */ /* Linear interpolation */ cos_LSF_QA[ordering[k]] = silk_RSHIFT_ROUND( silk_LSHIFT( cos_val, 8 ) + silk_MUL( delta, f_frac ), 20 - QA ); /* QA */ } dd = silk_RSHIFT( d, 1 ); /* generate even and odd polynomials using convolution */ silk_NLSF2A_find_poly( P, &cos_LSF_QA[ 0 ], dd ); silk_NLSF2A_find_poly( Q, &cos_LSF_QA[ 1 ], dd ); /* convert even and odd polynomials to opus_int32 Q12 filter coefs */ for( k = 0; k < dd; k++ ) { Ptmp = P[ k+1 ] + P[ k ]; Qtmp = Q[ k+1 ] - Q[ k ]; /* the Ptmp and Qtmp values at this stage need to fit in int32 */ a32_QA1[ k ] = -Qtmp - Ptmp; /* QA+1 */ a32_QA1[ d-k-1 ] = Qtmp - Ptmp; /* QA+1 */ } /* Limit the maximum absolute value of the prediction coefficients, so that they'll fit in int16 */ for( i = 0; i < 10; i++ ) { /* Find maximum absolute value and its index */ maxabs = 0; for( k = 0; k < d; k++ ) { absval = silk_abs( a32_QA1[k] ); if( absval > maxabs ) { maxabs = absval; idx = k; } } maxabs = silk_RSHIFT_ROUND( maxabs, QA + 1 - 12 ); /* QA+1 -> Q12 */ if( maxabs > silk_int16_MAX ) { /* Reduce magnitude of prediction coefficients */ maxabs = silk_min( maxabs, 163838 ); /* ( silk_int32_MAX >> 14 ) + silk_int16_MAX = 163838 */ sc_Q16 = SILK_FIX_CONST( 0.999, 16 ) - silk_DIV32( silk_LSHIFT( maxabs - silk_int16_MAX, 14 ), silk_RSHIFT32( silk_MUL( maxabs, idx + 1), 2 ) ); silk_bwexpander_32( a32_QA1, d, sc_Q16 ); } else { break; } } if( i == 10 ) { /* Reached the last iteration, clip the coefficients */ for( k = 0; k < d; k++ ) { a_Q12[ k ] = (opus_int16)silk_SAT16( silk_RSHIFT_ROUND( a32_QA1[ k ], QA + 1 - 12 ) ); /* QA+1 -> Q12 */ a32_QA1[ k ] = silk_LSHIFT( (opus_int32)a_Q12[ k ], QA + 1 - 12 ); } } else { for( k = 0; k < d; k++ ) { a_Q12[ k ] = (opus_int16)silk_RSHIFT_ROUND( a32_QA1[ k ], QA + 1 - 12 ); /* QA+1 -> Q12 */ } } for( i = 0; i < MAX_LPC_STABILIZE_ITERATIONS; i++ ) { if( silk_LPC_inverse_pred_gain( a_Q12, d ) < SILK_FIX_CONST( 1.0 / MAX_PREDICTION_POWER_GAIN, 30 ) ) { /* Prediction coefficients are (too close to) unstable; apply bandwidth expansion */ /* on the unscaled coefficients, convert to Q12 and measure again */ silk_bwexpander_32( a32_QA1, d, 65536 - silk_LSHIFT( 2, i ) ); for( k = 0; k < d; k++ ) { a_Q12[ k ] = (opus_int16)silk_RSHIFT_ROUND( a32_QA1[ k ], QA + 1 - 12 ); /* QA+1 -> Q12 */ } } else { break; } } }
/* 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 Min distance vector, 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 */ silk_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 += silk_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 -= silk_RSHIFT( NDeltaMin_Q15[I], 1 ); /* Move apart, sorted by value, keeping the same center frequency */ center_freq_Q15 = (opus_int16)silk_LIMIT_32( silk_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 - silk_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] = silk_max_int( NLSF_Q15[0], NDeltaMin_Q15[0] ); /* Keep delta_min distance between the NLSFs */ for( i = 1; i < L; i++ ) NLSF_Q15[i] = silk_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] = silk_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] = silk_min_int( NLSF_Q15[i], NLSF_Q15[i+1] - NDeltaMin_Q15[i+1] ); } }
/* Compute reflection coefficients from input signal */ void silk_burg_modified( opus_int32 *res_nrg, /* O Residual energy */ opus_int *res_nrg_Q, /* O Residual energy Q value */ opus_int32 A_Q16[], /* O Prediction coefficients (length order) */ const opus_int16 x[], /* I Input signal, length: nb_subfr * ( D + subfr_length ) */ const opus_int subfr_length, /* I Input signal subframe length (incl. D preceeding samples) */ const opus_int nb_subfr, /* I Number of subframes stacked in x */ const opus_int32 WhiteNoiseFrac_Q32, /* I Fraction added to zero-lag autocorrelation */ const opus_int D /* I Order */ ) { opus_int k, n, s, lz, rshifts, rshifts_extra; opus_int32 C0, num, nrg, rc_Q31, Atmp_QA, Atmp1, tmp1, tmp2, x1, x2; const opus_int16 *x_ptr; opus_int32 C_first_row[ SILK_MAX_ORDER_LPC ]; opus_int32 C_last_row[ SILK_MAX_ORDER_LPC ]; opus_int32 Af_QA[ SILK_MAX_ORDER_LPC ]; opus_int32 CAf[ SILK_MAX_ORDER_LPC + 1 ]; opus_int32 CAb[ SILK_MAX_ORDER_LPC + 1 ]; silk_assert( subfr_length * nb_subfr <= MAX_FRAME_SIZE ); silk_assert( nb_subfr <= MAX_NB_SUBFR ); /* Compute autocorrelations, added over subframes */ silk_sum_sqr_shift( &C0, &rshifts, x, nb_subfr * subfr_length ); if( rshifts > MAX_RSHIFTS ) { C0 = silk_LSHIFT32( C0, rshifts - MAX_RSHIFTS ); silk_assert( C0 > 0 ); rshifts = MAX_RSHIFTS; } else { lz = silk_CLZ32( C0 ) - 1; rshifts_extra = N_BITS_HEAD_ROOM - lz; if( rshifts_extra > 0 ) { rshifts_extra = silk_min( rshifts_extra, MAX_RSHIFTS - rshifts ); C0 = silk_RSHIFT32( C0, rshifts_extra ); } else { rshifts_extra = silk_max( rshifts_extra, MIN_RSHIFTS - rshifts ); C0 = silk_LSHIFT32( C0, -rshifts_extra ); } rshifts += rshifts_extra; } silk_memset( C_first_row, 0, SILK_MAX_ORDER_LPC * sizeof( opus_int32 ) ); if( rshifts > 0 ) { for( s = 0; s < nb_subfr; s++ ) { x_ptr = x + s * subfr_length; for( n = 1; n < D + 1; n++ ) { C_first_row[ n - 1 ] += (opus_int32)silk_RSHIFT64( silk_inner_prod16_aligned_64( x_ptr, x_ptr + n, subfr_length - n ), rshifts ); } } } else { for( s = 0; s < nb_subfr; s++ ) { x_ptr = x + s * subfr_length; for( n = 1; n < D + 1; n++ ) { C_first_row[ n - 1 ] += silk_LSHIFT32( silk_inner_prod_aligned( x_ptr, x_ptr + n, subfr_length - n ), -rshifts ); } } } silk_memcpy( C_last_row, C_first_row, SILK_MAX_ORDER_LPC * sizeof( opus_int32 ) ); /* Initialize */ CAb[ 0 ] = CAf[ 0 ] = C0 + silk_SMMUL( WhiteNoiseFrac_Q32, C0 ) + 1; /* Q(-rshifts)*/ for( n = 0; n < D; n++ ) { /* Update first row of correlation matrix (without first element) */ /* Update last row of correlation matrix (without last element, stored in reversed order) */ /* Update C * Af */ /* Update C * flipud(Af) (stored in reversed order) */ if( rshifts > -2 ) { for( s = 0; s < nb_subfr; s++ ) { x_ptr = x + s * subfr_length; x1 = -silk_LSHIFT32( (opus_int32)x_ptr[ n ], 16 - rshifts ); /* Q(16-rshifts)*/ x2 = -silk_LSHIFT32( (opus_int32)x_ptr[ subfr_length - n - 1 ], 16 - rshifts ); /* Q(16-rshifts)*/ tmp1 = silk_LSHIFT32( (opus_int32)x_ptr[ n ], QA - 16 ); /* Q(QA-16)*/ tmp2 = silk_LSHIFT32( (opus_int32)x_ptr[ subfr_length - n - 1 ], QA - 16 ); /* Q(QA-16)*/ for( k = 0; k < n; k++ ) { C_first_row[ k ] = silk_SMLAWB( C_first_row[ k ], x1, x_ptr[ n - k - 1 ] ); /* Q( -rshifts )*/ C_last_row[ k ] = silk_SMLAWB( C_last_row[ k ], x2, x_ptr[ subfr_length - n + k ] ); /* Q( -rshifts )*/ Atmp_QA = Af_QA[ k ]; tmp1 = silk_SMLAWB( tmp1, Atmp_QA, x_ptr[ n - k - 1 ] ); /* Q(QA-16)*/ tmp2 = silk_SMLAWB( tmp2, Atmp_QA, x_ptr[ subfr_length - n + k ] ); /* Q(QA-16)*/ } tmp1 = silk_LSHIFT32( -tmp1, 32 - QA - rshifts ); /* Q(16-rshifts)*/ tmp2 = silk_LSHIFT32( -tmp2, 32 - QA - rshifts ); /* Q(16-rshifts)*/ for( k = 0; k <= n; k++ ) { CAf[ k ] = silk_SMLAWB( CAf[ k ], tmp1, x_ptr[ n - k ] ); /* Q( -rshift )*/ CAb[ k ] = silk_SMLAWB( CAb[ k ], tmp2, x_ptr[ subfr_length - n + k - 1 ] ); /* Q( -rshift )*/ } } } else { for( s = 0; s < nb_subfr; s++ ) { x_ptr = x + s * subfr_length; x1 = -silk_LSHIFT32( (opus_int32)x_ptr[ n ], -rshifts ); /* Q( -rshifts )*/ x2 = -silk_LSHIFT32( (opus_int32)x_ptr[ subfr_length - n - 1 ], -rshifts ); /* Q( -rshifts )*/ tmp1 = silk_LSHIFT32( (opus_int32)x_ptr[ n ], 17 ); /* Q17*/ tmp2 = silk_LSHIFT32( (opus_int32)x_ptr[ subfr_length - n - 1 ], 17 ); /* Q17*/ for( k = 0; k < n; k++ ) { C_first_row[ k ] = silk_MLA( C_first_row[ k ], x1, x_ptr[ n - k - 1 ] ); /* Q( -rshifts )*/ C_last_row[ k ] = silk_MLA( C_last_row[ k ], x2, x_ptr[ subfr_length - n + k ] ); /* Q( -rshifts )*/ Atmp1 = silk_RSHIFT_ROUND( Af_QA[ k ], QA - 17 ); /* Q17*/ tmp1 = silk_MLA( tmp1, x_ptr[ n - k - 1 ], Atmp1 ); /* Q17*/ tmp2 = silk_MLA( tmp2, x_ptr[ subfr_length - n + k ], Atmp1 ); /* Q17*/ } tmp1 = -tmp1; /* Q17*/ tmp2 = -tmp2; /* Q17*/ for( k = 0; k <= n; k++ ) { CAf[ k ] = silk_SMLAWW( CAf[ k ], tmp1, silk_LSHIFT32( (opus_int32)x_ptr[ n - k ], -rshifts - 1 ) ); /* Q( -rshift )*/ CAb[ k ] = silk_SMLAWW( CAb[ k ], tmp2, silk_LSHIFT32( (opus_int32)x_ptr[ subfr_length - n + k - 1 ], -rshifts - 1 ) ); /* Q( -rshift )*/ } } } /* Calculate nominator and denominator for the next order reflection (parcor) coefficient */ tmp1 = C_first_row[ n ]; /* Q( -rshifts )*/ tmp2 = C_last_row[ n ]; /* Q( -rshifts )*/ num = 0; /* Q( -rshifts )*/ nrg = silk_ADD32( CAb[ 0 ], CAf[ 0 ] ); /* Q( 1-rshifts )*/ for( k = 0; k < n; k++ ) { Atmp_QA = Af_QA[ k ]; lz = silk_CLZ32( silk_abs( Atmp_QA ) ) - 1; lz = silk_min( 32 - QA, lz ); Atmp1 = silk_LSHIFT32( Atmp_QA, lz ); /* Q( QA + lz )*/ tmp1 = silk_ADD_LSHIFT32( tmp1, silk_SMMUL( C_last_row[ n - k - 1 ], Atmp1 ), 32 - QA - lz ); /* Q( -rshifts )*/ tmp2 = silk_ADD_LSHIFT32( tmp2, silk_SMMUL( C_first_row[ n - k - 1 ], Atmp1 ), 32 - QA - lz ); /* Q( -rshifts )*/ num = silk_ADD_LSHIFT32( num, silk_SMMUL( CAb[ n - k ], Atmp1 ), 32 - QA - lz ); /* Q( -rshifts )*/ nrg = silk_ADD_LSHIFT32( nrg, silk_SMMUL( silk_ADD32( CAb[ k + 1 ], CAf[ k + 1 ] ), Atmp1 ), 32 - QA - lz ); /* Q( 1-rshifts )*/ } CAf[ n + 1 ] = tmp1; /* Q( -rshifts )*/ CAb[ n + 1 ] = tmp2; /* Q( -rshifts )*/ num = silk_ADD32( num, tmp2 ); /* Q( -rshifts )*/ num = silk_LSHIFT32( -num, 1 ); /* Q( 1-rshifts )*/ /* Calculate the next order reflection (parcor) coefficient */ if( silk_abs( num ) < nrg ) { rc_Q31 = silk_DIV32_varQ( num, nrg, 31 ); } else { /* Negative energy or ratio too high; set remaining coefficients to zero and exit loop */ silk_memset( &Af_QA[ n ], 0, ( D - n ) * sizeof( opus_int32 ) ); silk_assert( 0 ); break; } /* Update the AR coefficients */ for( k = 0; k < (n + 1) >> 1; k++ ) { tmp1 = Af_QA[ k ]; /* QA*/ tmp2 = Af_QA[ n - k - 1 ]; /* QA*/ Af_QA[ k ] = silk_ADD_LSHIFT32( tmp1, silk_SMMUL( tmp2, rc_Q31 ), 1 ); /* QA*/ Af_QA[ n - k - 1 ] = silk_ADD_LSHIFT32( tmp2, silk_SMMUL( tmp1, rc_Q31 ), 1 ); /* QA*/ } Af_QA[ n ] = silk_RSHIFT32( rc_Q31, 31 - QA ); /* QA*/ /* Update C * Af and C * Ab */ for( k = 0; k <= n + 1; k++ ) { tmp1 = CAf[ k ]; /* Q( -rshifts )*/ tmp2 = CAb[ n - k + 1 ]; /* Q( -rshifts )*/ CAf[ k ] = silk_ADD_LSHIFT32( tmp1, silk_SMMUL( tmp2, rc_Q31 ), 1 ); /* Q( -rshifts )*/ CAb[ n - k + 1 ] = silk_ADD_LSHIFT32( tmp2, silk_SMMUL( tmp1, rc_Q31 ), 1 ); /* Q( -rshifts )*/ } } /* Return residual energy */ nrg = CAf[ 0 ]; /* Q( -rshifts )*/ tmp1 = 1 << 16; /* Q16*/ for( k = 0; k < D; k++ ) { Atmp1 = silk_RSHIFT_ROUND( Af_QA[ k ], QA - 16 ); /* Q16*/ nrg = silk_SMLAWW( nrg, CAf[ k + 1 ], Atmp1 ); /* Q( -rshifts )*/ tmp1 = silk_SMLAWW( tmp1, Atmp1, Atmp1 ); /* Q16*/ A_Q16[ k ] = -Atmp1; } *res_nrg = silk_SMLAWW( nrg, silk_SMMUL( WhiteNoiseFrac_Q32, C0 ), -tmp1 ); /* Q( -rshifts )*/ *res_nrg_Q = -rshifts; }
static OPUS_INLINE void silk_PLC_conceal( silk_decoder_state *psDec, /* I/O Decoder state */ silk_decoder_control *psDecCtrl, /* I/O Decoder control */ opus_int16 frame[], /* O LPC residual signal */ int arch /* I Run-time architecture */ ) { opus_int i, j, k; opus_int lag, idx, sLTP_buf_idx, shift1, shift2; opus_int32 rand_seed, harm_Gain_Q15, rand_Gain_Q15, inv_gain_Q30; opus_int32 energy1, energy2, *rand_ptr, *pred_lag_ptr; opus_int32 LPC_pred_Q10, LTP_pred_Q12; opus_int16 rand_scale_Q14; opus_int16 *B_Q14; opus_int32 *sLPC_Q14_ptr; opus_int16 A_Q12[ MAX_LPC_ORDER ]; #ifdef SMALL_FOOTPRINT opus_int16 *sLTP; #else VARDECL( opus_int16, sLTP ); #endif VARDECL( opus_int32, sLTP_Q14 ); silk_PLC_struct *psPLC = &psDec->sPLC; opus_int32 prevGain_Q10[2]; SAVE_STACK; ALLOC( sLTP_Q14, psDec->ltp_mem_length + psDec->frame_length, opus_int32 ); #ifdef SMALL_FOOTPRINT /* Ugly hack that breaks aliasing rules to save stack: put sLTP at the very end of sLTP_Q14. */ sLTP = ((opus_int16*)&sLTP_Q14[psDec->ltp_mem_length + psDec->frame_length])-psDec->ltp_mem_length; #else ALLOC( sLTP, psDec->ltp_mem_length, opus_int16 ); #endif prevGain_Q10[0] = silk_RSHIFT( psPLC->prevGain_Q16[ 0 ], 6); prevGain_Q10[1] = silk_RSHIFT( psPLC->prevGain_Q16[ 1 ], 6); if( psDec->first_frame_after_reset ) { silk_memset( psPLC->prevLPC_Q12, 0, sizeof( psPLC->prevLPC_Q12 ) ); } silk_PLC_energy(&energy1, &shift1, &energy2, &shift2, psDec->exc_Q14, prevGain_Q10, psDec->subfr_length, psDec->nb_subfr); if( silk_RSHIFT( energy1, shift2 ) < silk_RSHIFT( energy2, shift1 ) ) { /* First sub-frame has lowest energy */ rand_ptr = &psDec->exc_Q14[ silk_max_int( 0, ( psPLC->nb_subfr - 1 ) * psPLC->subfr_length - RAND_BUF_SIZE ) ]; } else { /* Second sub-frame has lowest energy */ rand_ptr = &psDec->exc_Q14[ silk_max_int( 0, psPLC->nb_subfr * psPLC->subfr_length - RAND_BUF_SIZE ) ]; } /* Set up Gain to random noise component */ B_Q14 = psPLC->LTPCoef_Q14; rand_scale_Q14 = psPLC->randScale_Q14; /* Set up attenuation gains */ harm_Gain_Q15 = HARM_ATT_Q15[ silk_min_int( NB_ATT - 1, psDec->lossCnt ) ]; if( psDec->prevSignalType == TYPE_VOICED ) { rand_Gain_Q15 = PLC_RAND_ATTENUATE_V_Q15[ silk_min_int( NB_ATT - 1, psDec->lossCnt ) ]; } else { rand_Gain_Q15 = PLC_RAND_ATTENUATE_UV_Q15[ silk_min_int( NB_ATT - 1, psDec->lossCnt ) ]; } /* LPC concealment. Apply BWE to previous LPC */ silk_bwexpander( psPLC->prevLPC_Q12, psDec->LPC_order, SILK_FIX_CONST( BWE_COEF, 16 ) ); /* Preload LPC coeficients to array on stack. Gives small performance gain */ silk_memcpy( A_Q12, psPLC->prevLPC_Q12, psDec->LPC_order * sizeof( opus_int16 ) ); /* First Lost frame */ if( psDec->lossCnt == 0 ) { rand_scale_Q14 = 1 << 14; /* Reduce random noise Gain for voiced frames */ if( psDec->prevSignalType == TYPE_VOICED ) { for( i = 0; i < LTP_ORDER; i++ ) { rand_scale_Q14 -= B_Q14[ i ]; } rand_scale_Q14 = silk_max_16( 3277, rand_scale_Q14 ); /* 0.2 */ rand_scale_Q14 = (opus_int16)silk_RSHIFT( silk_SMULBB( rand_scale_Q14, psPLC->prevLTP_scale_Q14 ), 14 ); } else { /* Reduce random noise for unvoiced frames with high LPC gain */ opus_int32 invGain_Q30, down_scale_Q30; invGain_Q30 = silk_LPC_inverse_pred_gain( psPLC->prevLPC_Q12, psDec->LPC_order, arch ); down_scale_Q30 = silk_min_32( silk_RSHIFT( (opus_int32)1 << 30, LOG2_INV_LPC_GAIN_HIGH_THRES ), invGain_Q30 ); down_scale_Q30 = silk_max_32( silk_RSHIFT( (opus_int32)1 << 30, LOG2_INV_LPC_GAIN_LOW_THRES ), down_scale_Q30 ); down_scale_Q30 = silk_LSHIFT( down_scale_Q30, LOG2_INV_LPC_GAIN_HIGH_THRES ); rand_Gain_Q15 = silk_RSHIFT( silk_SMULWB( down_scale_Q30, rand_Gain_Q15 ), 14 ); } } rand_seed = psPLC->rand_seed; lag = silk_RSHIFT_ROUND( psPLC->pitchL_Q8, 8 ); sLTP_buf_idx = psDec->ltp_mem_length; /* Rewhiten LTP state */ idx = psDec->ltp_mem_length - lag - psDec->LPC_order - LTP_ORDER / 2; silk_assert( idx > 0 ); silk_LPC_analysis_filter( &sLTP[ idx ], &psDec->outBuf[ idx ], A_Q12, psDec->ltp_mem_length - idx, psDec->LPC_order, arch ); /* Scale LTP state */ inv_gain_Q30 = silk_INVERSE32_varQ( psPLC->prevGain_Q16[ 1 ], 46 ); inv_gain_Q30 = silk_min( inv_gain_Q30, silk_int32_MAX >> 1 ); for( i = idx + psDec->LPC_order; i < psDec->ltp_mem_length; i++ ) { sLTP_Q14[ i ] = silk_SMULWB( inv_gain_Q30, sLTP[ i ] ); } /***************************/ /* LTP synthesis filtering */ /***************************/ for( k = 0; k < psDec->nb_subfr; k++ ) { /* Set up pointer */ pred_lag_ptr = &sLTP_Q14[ sLTP_buf_idx - lag + LTP_ORDER / 2 ]; for( i = 0; i < psDec->subfr_length; i++ ) { /* Unrolled loop */ /* Avoids introducing a bias because silk_SMLAWB() always rounds to -inf */ LTP_pred_Q12 = 2; LTP_pred_Q12 = silk_SMLAWB( LTP_pred_Q12, pred_lag_ptr[ 0 ], B_Q14[ 0 ] ); LTP_pred_Q12 = silk_SMLAWB( LTP_pred_Q12, pred_lag_ptr[ -1 ], B_Q14[ 1 ] ); LTP_pred_Q12 = silk_SMLAWB( LTP_pred_Q12, pred_lag_ptr[ -2 ], B_Q14[ 2 ] ); LTP_pred_Q12 = silk_SMLAWB( LTP_pred_Q12, pred_lag_ptr[ -3 ], B_Q14[ 3 ] ); LTP_pred_Q12 = silk_SMLAWB( LTP_pred_Q12, pred_lag_ptr[ -4 ], B_Q14[ 4 ] ); pred_lag_ptr++; /* Generate LPC excitation */ rand_seed = silk_RAND( rand_seed ); idx = silk_RSHIFT( rand_seed, 25 ) & RAND_BUF_MASK; sLTP_Q14[ sLTP_buf_idx ] = silk_LSHIFT32( silk_SMLAWB( LTP_pred_Q12, rand_ptr[ idx ], rand_scale_Q14 ), 2 ); sLTP_buf_idx++; } /* Gradually reduce LTP gain */ for( j = 0; j < LTP_ORDER; j++ ) { B_Q14[ j ] = silk_RSHIFT( silk_SMULBB( harm_Gain_Q15, B_Q14[ j ] ), 15 ); } if ( psDec->indices.signalType != TYPE_NO_VOICE_ACTIVITY ) { /* Gradually reduce excitation gain */ rand_scale_Q14 = silk_RSHIFT( silk_SMULBB( rand_scale_Q14, rand_Gain_Q15 ), 15 ); } /* Slowly increase pitch lag */ psPLC->pitchL_Q8 = silk_SMLAWB( psPLC->pitchL_Q8, psPLC->pitchL_Q8, PITCH_DRIFT_FAC_Q16 ); psPLC->pitchL_Q8 = silk_min_32( psPLC->pitchL_Q8, silk_LSHIFT( silk_SMULBB( MAX_PITCH_LAG_MS, psDec->fs_kHz ), 8 ) ); lag = silk_RSHIFT_ROUND( psPLC->pitchL_Q8, 8 ); } /***************************/ /* LPC synthesis filtering */ /***************************/ sLPC_Q14_ptr = &sLTP_Q14[ psDec->ltp_mem_length - MAX_LPC_ORDER ]; /* Copy LPC state */ silk_memcpy( sLPC_Q14_ptr, psDec->sLPC_Q14_buf, MAX_LPC_ORDER * sizeof( opus_int32 ) ); silk_assert( psDec->LPC_order >= 10 ); /* check that unrolling works */ for( i = 0; i < psDec->frame_length; i++ ) { /* partly unrolled */ /* Avoids introducing a bias because silk_SMLAWB() always rounds to -inf */ LPC_pred_Q10 = silk_RSHIFT( psDec->LPC_order, 1 ); LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, sLPC_Q14_ptr[ MAX_LPC_ORDER + i - 1 ], A_Q12[ 0 ] ); LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, sLPC_Q14_ptr[ MAX_LPC_ORDER + i - 2 ], A_Q12[ 1 ] ); LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, sLPC_Q14_ptr[ MAX_LPC_ORDER + i - 3 ], A_Q12[ 2 ] ); LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, sLPC_Q14_ptr[ MAX_LPC_ORDER + i - 4 ], A_Q12[ 3 ] ); LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, sLPC_Q14_ptr[ MAX_LPC_ORDER + i - 5 ], A_Q12[ 4 ] ); LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, sLPC_Q14_ptr[ MAX_LPC_ORDER + i - 6 ], A_Q12[ 5 ] ); LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, sLPC_Q14_ptr[ MAX_LPC_ORDER + i - 7 ], A_Q12[ 6 ] ); LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, sLPC_Q14_ptr[ MAX_LPC_ORDER + i - 8 ], A_Q12[ 7 ] ); LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, sLPC_Q14_ptr[ MAX_LPC_ORDER + i - 9 ], A_Q12[ 8 ] ); LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, sLPC_Q14_ptr[ MAX_LPC_ORDER + i - 10 ], A_Q12[ 9 ] ); for( j = 10; j < psDec->LPC_order; j++ ) { LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, sLPC_Q14_ptr[ MAX_LPC_ORDER + i - j - 1 ], A_Q12[ j ] ); } /* Add prediction to LPC excitation */ sLPC_Q14_ptr[ MAX_LPC_ORDER + i ] = silk_ADD_SAT32( sLPC_Q14_ptr[ MAX_LPC_ORDER + i ], silk_LSHIFT_SAT32( LPC_pred_Q10, 4 )); /* Scale with Gain */ frame[ i ] = (opus_int16)silk_SAT16( silk_SAT16( silk_RSHIFT_ROUND( silk_SMULWW( sLPC_Q14_ptr[ MAX_LPC_ORDER + i ], prevGain_Q10[ 1 ] ), 8 ) ) ); } /* Save LPC state */ silk_memcpy( psDec->sLPC_Q14_buf, &sLPC_Q14_ptr[ psDec->frame_length ], MAX_LPC_ORDER * sizeof( opus_int32 ) ); /**************************************/ /* Update states */ /**************************************/ psPLC->rand_seed = rand_seed; psPLC->randScale_Q14 = rand_scale_Q14; for( i = 0; i < MAX_NB_SUBFR; i++ ) { psDecCtrl->pitchL[ i ] = lag; } RESTORE_STACK; }
/* 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; }