/* High-pass filter with cutoff frequency adaptation based on pitch lag statistics */ void silk_HP_variable_cutoff(silk_encoder_state_Fxx state_Fxx[] /* I/O Encoder states */ ) { int quality_Q15; int32_t pitch_freq_Hz_Q16, pitch_freq_log_Q7, delta_freq_Q7; silk_encoder_state *psEncC1 = &state_Fxx[0].sCmn; /* Adaptive cutoff frequency: estimate low end of pitch frequency range */ if (psEncC1->prevSignalType == TYPE_VOICED) { /* difference, in log domain */ pitch_freq_Hz_Q16 = silk_DIV32_16(silk_LSHIFT (silk_MUL(psEncC1->fs_kHz, 1000), 16), psEncC1->prevLag); pitch_freq_log_Q7 = silk_lin2log(pitch_freq_Hz_Q16) - (16 << 7); /* adjustment based on quality */ quality_Q15 = psEncC1->input_quality_bands_Q15[0]; pitch_freq_log_Q7 = silk_SMLAWB(pitch_freq_log_Q7, silk_SMULWB(silk_LSHIFT(-quality_Q15, 2), quality_Q15), pitch_freq_log_Q7 - (silk_lin2log (SILK_FIX_CONST(VARIABLE_HP_MIN_CUTOFF_HZ, 16)) - (16 << 7))); /* delta_freq = pitch_freq_log - psEnc->variable_HP_smth1; */ delta_freq_Q7 = pitch_freq_log_Q7 - silk_RSHIFT(psEncC1->variable_HP_smth1_Q15, 8); if (delta_freq_Q7 < 0) { /* less smoothing for decreasing pitch frequency, to track something close to the minimum */ delta_freq_Q7 = silk_MUL(delta_freq_Q7, 3); } /* limit delta, to reduce impact of outliers in pitch estimation */ delta_freq_Q7 = silk_LIMIT_32(delta_freq_Q7, -SILK_FIX_CONST(VARIABLE_HP_MAX_DELTA_FREQ, 7), SILK_FIX_CONST(VARIABLE_HP_MAX_DELTA_FREQ, 7)); /* update smoother */ psEncC1->variable_HP_smth1_Q15 = silk_SMLAWB(psEncC1->variable_HP_smth1_Q15, silk_SMULBB(psEncC1->speech_activity_Q8, delta_freq_Q7), SILK_FIX_CONST(VARIABLE_HP_SMTH_COEF1, 16)); /* limit frequency range */ psEncC1->variable_HP_smth1_Q15 = silk_LIMIT_32(psEncC1->variable_HP_smth1_Q15, silk_LSHIFT(silk_lin2log (VARIABLE_HP_MIN_CUTOFF_HZ), 8), silk_LSHIFT(silk_lin2log (VARIABLE_HP_MAX_CUTOFF_HZ), 8)); } }
static inline opus_int silk_setup_LBRR( silk_encoder_state *psEncC, /* I/O */ const opus_int32 TargetRate_bps /* I */ ) { opus_int ret = SILK_NO_ERROR; opus_int32 LBRR_rate_thres_bps; psEncC->LBRR_enabled = 0; if( psEncC->useInBandFEC && psEncC->PacketLoss_perc > 0 ) { if( psEncC->fs_kHz == 8 ) { LBRR_rate_thres_bps = LBRR_NB_MIN_RATE_BPS; } else if( psEncC->fs_kHz == 12 ) { LBRR_rate_thres_bps = LBRR_MB_MIN_RATE_BPS; } else { LBRR_rate_thres_bps = LBRR_WB_MIN_RATE_BPS; } LBRR_rate_thres_bps = silk_SMULWB( silk_MUL( LBRR_rate_thres_bps, 125 - silk_min( psEncC->PacketLoss_perc, 25 ) ), SILK_FIX_CONST( 0.01, 16 ) ); if( TargetRate_bps > LBRR_rate_thres_bps ) { /* Set gain increase for coding LBRR excitation */ psEncC->LBRR_enabled = 1; psEncC->LBRR_GainIncreases = silk_max_int( 7 - silk_SMULWB( psEncC->PacketLoss_perc, SILK_FIX_CONST( 0.4, 16 ) ), 2 ); } } return ret; }
static OPUS_INLINE opus_int silk_setup_LBRR( silk_encoder_state *psEncC, /* I/O */ const opus_int32 TargetRate_bps /* I */ ) { opus_int LBRR_in_previous_packet, ret = SILK_NO_ERROR; opus_int32 LBRR_rate_thres_bps; LBRR_in_previous_packet = psEncC->LBRR_enabled; psEncC->LBRR_enabled = 0; if( psEncC->useInBandFEC && psEncC->PacketLoss_perc > 0 ) { if( psEncC->fs_kHz == 8 ) { LBRR_rate_thres_bps = LBRR_NB_MIN_RATE_BPS; } else if( psEncC->fs_kHz == 12 ) { LBRR_rate_thres_bps = LBRR_MB_MIN_RATE_BPS; } else { LBRR_rate_thres_bps = LBRR_WB_MIN_RATE_BPS; } LBRR_rate_thres_bps = silk_SMULWB( silk_MUL( LBRR_rate_thres_bps, 125 - silk_min( psEncC->PacketLoss_perc, 25 ) ), SILK_FIX_CONST( 0.01, 16 ) ); if( TargetRate_bps > LBRR_rate_thres_bps ) { /* Set gain increase for coding LBRR excitation */ if( LBRR_in_previous_packet == 0 ) { /* Previous packet did not have LBRR, and was therefore coded at a higher bitrate */ psEncC->LBRR_GainIncreases = 7; } else { psEncC->LBRR_GainIncreases = silk_max_int( 7 - silk_SMULWB( (opus_int32)psEncC->PacketLoss_perc, SILK_FIX_CONST( 0.4, 16 ) ), 2 ); } psEncC->LBRR_enabled = 1; } } return ret; }
opus_int silk_VAD_Init( /* O Return value, 0 if success */ silk_VAD_state *psSilk_VAD /* I/O Pointer to Silk VAD state */ ) { opus_int b, ret = 0; /* reset state memory */ silk_memset( psSilk_VAD, 0, sizeof( silk_VAD_state ) ); /* init noise levels */ /* Initialize array with approx pink noise levels (psd proportional to inverse of frequency) */ for( b = 0; b < VAD_N_BANDS; b++ ) { psSilk_VAD->NoiseLevelBias[ b ] = silk_max_32( silk_DIV32_16( VAD_NOISE_LEVELS_BIAS, b + 1 ), 1 ); } /* Initialize state */ for( b = 0; b < VAD_N_BANDS; b++ ) { psSilk_VAD->NL[ b ] = silk_MUL( 100, psSilk_VAD->NoiseLevelBias[ b ] ); psSilk_VAD->inv_NL[ b ] = silk_DIV32( silk_int32_MAX, psSilk_VAD->NL[ b ] ); } psSilk_VAD->counter = 15; /* init smoothed energy-to-noise ratio*/ for( b = 0; b < VAD_N_BANDS; b++ ) { psSilk_VAD->NrgRatioSmth_Q8[ b ] = 100 * 256; /* 100 * 256 --> 20 dB SNR */ } return( ret ); }
/* Convert input to a log scale */ opus_int32 silk_lin2log( const opus_int32 inLin /* I input in linear scale */ ) { opus_int32 lz, frac_Q7; silk_CLZ_FRAC( inLin, &lz, &frac_Q7 ); /* Piece-wise parabolic approximation */ return silk_LSHIFT( 31 - lz, 7 ) + silk_SMLAWB( frac_Q7, silk_MUL( frac_Q7, 128 - frac_Q7 ), 179 ); }
/* 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); }
/* Control SNR of redidual quantizer */ opus_int silk_control_SNR( silk_encoder_state *psEncC, /* I/O Pointer to Silk encoder state */ opus_int32 TargetRate_bps /* I Target max bitrate (bps) */ ) { opus_int k, ret = SILK_NO_ERROR; opus_int32 frac_Q6; const opus_int32 *rateTable; /* Set bitrate/coding quality */ TargetRate_bps = silk_LIMIT(TargetRate_bps, MIN_TARGET_RATE_BPS, MAX_TARGET_RATE_BPS); if (TargetRate_bps != psEncC->TargetRate_bps) { psEncC->TargetRate_bps = TargetRate_bps; /* If new TargetRate_bps, translate to SNR_dB value */ if (psEncC->fs_kHz == 8) { rateTable = silk_TargetRate_table_NB; } else if (psEncC->fs_kHz == 12) { rateTable = silk_TargetRate_table_MB; } else { rateTable = silk_TargetRate_table_WB; } /* Reduce bitrate for 10 ms modes in these calculations */ if (psEncC->nb_subfr == 2) { TargetRate_bps -= REDUCE_BITRATE_10_MS_BPS; } /* Find bitrate interval in table and interpolate */ for (k = 1; k < TARGET_RATE_TAB_SZ; k++) { if (TargetRate_bps <= rateTable[k]) { frac_Q6 = silk_DIV32(silk_LSHIFT(TargetRate_bps - rateTable[k - 1], 6), rateTable[k] - rateTable[k - 1]); psEncC->SNR_dB_Q7 = silk_LSHIFT(silk_SNR_table_Q1[k - 1], 6) + silk_MUL(frac_Q6, silk_SNR_table_Q1[k] - silk_SNR_table_Q1[ k - 1]); break; } } /* Reduce coding quality whenever LBRR is enabled, to free up some bits */ if (psEncC->LBRR_enabled) { psEncC->SNR_dB_Q7 = silk_SMLABB(psEncC->SNR_dB_Q7, 12 - psEncC->LBRR_GainIncreases, SILK_FIX_CONST(-0.25, 7)); } } return ret; }
/* 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 ] ); }
/* 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 ); } } }
/* Convert input to a linear scale */ opus_int32 silk_log2lin( const opus_int32 inLog_Q7 /* I input on log scale */ ) { opus_int32 out, frac_Q7; if( inLog_Q7 < 0 ) { return 0; } out = silk_LSHIFT( 1, silk_RSHIFT( inLog_Q7, 7 ) ); frac_Q7 = inLog_Q7 & 0x7F; if( inLog_Q7 < 2048 ) { /* Piece-wise parabolic approximation */ out = silk_ADD_RSHIFT32( out, silk_MUL( out, silk_SMLAWB( frac_Q7, silk_SMULBB( frac_Q7, 128 - frac_Q7 ), -174 ) ), 7 ); } else { /* Piece-wise parabolic approximation */ out = silk_MLA( out, silk_RSHIFT( out, 7 ), silk_SMLAWB( frac_Q7, silk_SMULBB( frac_Q7, 128 - frac_Q7 ), -174 ) ); } return out; }
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; } }
/* Residual energy: nrg = wxx - 2 * wXx * c + c' * wXX * c */ opus_int32 silk_residual_energy16_covar_FIX( const opus_int16 *c, /* I Prediction vector */ const opus_int32 *wXX, /* I Correlation matrix */ const opus_int32 *wXx, /* I Correlation vector */ opus_int32 wxx, /* I Signal energy */ opus_int D, /* I Dimension */ opus_int cQ /* I Q value for c vector 0 - 15 */ ) { opus_int i, j, lshifts, Qxtra; opus_int32 c_max, w_max, tmp, tmp2, nrg; opus_int cn[ MAX_MATRIX_SIZE ]; const opus_int32 *pRow; /* Safety checks */ silk_assert( D >= 0 ); silk_assert( D <= 16 ); silk_assert( cQ > 0 ); silk_assert( cQ < 16 ); lshifts = 16 - cQ; Qxtra = lshifts; c_max = 0; for( i = 0; i < D; i++ ) { c_max = silk_max_32( c_max, silk_abs( (opus_int32)c[ i ] ) ); } Qxtra = silk_min_int( Qxtra, silk_CLZ32( c_max ) - 17 ); w_max = silk_max_32( wXX[ 0 ], wXX[ D * D - 1 ] ); Qxtra = silk_min_int( Qxtra, silk_CLZ32( silk_MUL( D, silk_RSHIFT( silk_SMULWB( w_max, c_max ), 4 ) ) ) - 5 ); Qxtra = silk_max_int( Qxtra, 0 ); for( i = 0; i < D; i++ ) { cn[ i ] = silk_LSHIFT( ( opus_int )c[ i ], Qxtra ); silk_assert( silk_abs(cn[i]) <= ( silk_int16_MAX + 1 ) ); /* Check that silk_SMLAWB can be used */ } lshifts -= Qxtra; /* Compute wxx - 2 * wXx * c */ tmp = 0; for( i = 0; i < D; i++ ) { tmp = silk_SMLAWB( tmp, wXx[ i ], cn[ i ] ); } nrg = silk_RSHIFT( wxx, 1 + lshifts ) - tmp; /* Q: -lshifts - 1 */ /* Add c' * wXX * c, assuming wXX is symmetric */ tmp2 = 0; for( i = 0; i < D; i++ ) { tmp = 0; pRow = &wXX[ i * D ]; for( j = i + 1; j < D; j++ ) { tmp = silk_SMLAWB( tmp, pRow[ j ], cn[ j ] ); } tmp = silk_SMLAWB( tmp, silk_RSHIFT( pRow[ i ], 1 ), cn[ i ] ); tmp2 = silk_SMLAWB( tmp2, tmp, cn[ i ] ); } nrg = silk_ADD_LSHIFT32( nrg, tmp2, lshifts ); /* Q: -lshifts - 1 */ /* Keep one bit free always, because we add them for LSF interpolation */ if( nrg < 1 ) { nrg = 1; } else if( nrg > silk_RSHIFT( silk_int32_MAX, lshifts + 2 ) ) { nrg = silk_int32_MAX >> 1; } else {
/* 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; }
/* 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; } } }
int silk_encode_frame_FIX(silk_encoder_state_FIX * psEnc, /* I/O Pointer to Silk FIX encoder state */ int32_t * pnBytesOut, /* O Pointer to number of payload bytes; */ ec_enc * psRangeEnc, /* I/O compressor data structure */ int condCoding, /* I The type of conditional coding to use */ int maxBits, /* I If > 0: maximum number of output bits */ int useCBR /* I Flag to force constant-bitrate operation */ ) { silk_encoder_control_FIX sEncCtrl; int i, iter, maxIter, found_upper, found_lower, ret = 0; int16_t *x_frame; ec_enc sRangeEnc_copy, sRangeEnc_copy2; silk_nsq_state sNSQ_copy, sNSQ_copy2; int32_t seed_copy, nBits, nBits_lower, nBits_upper, gainMult_lower, gainMult_upper; int32_t gainsID, gainsID_lower, gainsID_upper; int16_t gainMult_Q8; int16_t ec_prevLagIndex_copy; int ec_prevSignalType_copy; int8_t LastGainIndex_copy2; /* This is totally unnecessary but many compilers (including gcc) are too dumb to realise it */ LastGainIndex_copy2 = nBits_lower = nBits_upper = gainMult_lower = gainMult_upper = 0; psEnc->sCmn.indices.Seed = psEnc->sCmn.frameCounter++ & 3; /**************************************************************/ /* Set up Input Pointers, and insert frame in input buffer */ /*************************************************************/ /* start of frame to encode */ x_frame = psEnc->x_buf + psEnc->sCmn.ltp_mem_length; /***************************************/ /* Ensure smooth bandwidth transitions */ /***************************************/ silk_LP_variable_cutoff(&psEnc->sCmn.sLP, psEnc->sCmn.inputBuf + 1, psEnc->sCmn.frame_length); /*******************************************/ /* Copy new frame to front of input buffer */ /*******************************************/ memcpy(x_frame + LA_SHAPE_MS * psEnc->sCmn.fs_kHz, psEnc->sCmn.inputBuf + 1, psEnc->sCmn.frame_length * sizeof(int16_t)); if (!psEnc->sCmn.prefillFlag) { int16_t *res_pitch_frame; int16_t res_pitch[psEnc->sCmn.la_pitch + psEnc->sCmn.frame_length + psEnc->sCmn.ltp_mem_length]; /* start of pitch LPC residual frame */ res_pitch_frame = res_pitch + psEnc->sCmn.ltp_mem_length; /*****************************************/ /* Find pitch lags, initial LPC analysis */ /*****************************************/ silk_find_pitch_lags_FIX(psEnc, &sEncCtrl, res_pitch, x_frame, psEnc->sCmn.arch); /************************/ /* Noise shape analysis */ /************************/ silk_noise_shape_analysis_FIX(psEnc, &sEncCtrl, res_pitch_frame, x_frame, psEnc->sCmn.arch); /***************************************************/ /* Find linear prediction coefficients (LPC + LTP) */ /***************************************************/ silk_find_pred_coefs_FIX(psEnc, &sEncCtrl, res_pitch, x_frame, condCoding); /****************************************/ /* Process gains */ /****************************************/ silk_process_gains_FIX(psEnc, &sEncCtrl, condCoding); /*****************************************/ /* Prefiltering for noise shaper */ /*****************************************/ int32_t xfw_Q3[psEnc->sCmn.frame_length]; silk_prefilter_FIX(psEnc, &sEncCtrl, xfw_Q3, x_frame); /****************************************/ /* Low Bitrate Redundant Encoding */ /****************************************/ silk_LBRR_encode_FIX(psEnc, &sEncCtrl, xfw_Q3, condCoding); /* Loop over quantizer and entropy coding to control bitrate */ maxIter = 6; gainMult_Q8 = SILK_FIX_CONST(1, 8); found_lower = 0; found_upper = 0; gainsID = silk_gains_ID(psEnc->sCmn.indices.GainsIndices, psEnc->sCmn.nb_subfr); gainsID_lower = -1; gainsID_upper = -1; /* Copy part of the input state */ memcpy(&sRangeEnc_copy, psRangeEnc, sizeof(ec_enc)); memcpy(&sNSQ_copy, &psEnc->sCmn.sNSQ, sizeof(silk_nsq_state)); seed_copy = psEnc->sCmn.indices.Seed; ec_prevLagIndex_copy = psEnc->sCmn.ec_prevLagIndex; ec_prevSignalType_copy = psEnc->sCmn.ec_prevSignalType; uint8_t ec_buf_copy[1275]; for (iter = 0;; iter++) { if (gainsID == gainsID_lower) { nBits = nBits_lower; } else if (gainsID == gainsID_upper) { nBits = nBits_upper; } else { /* Restore part of the input state */ if (iter > 0) { memcpy(psRangeEnc, &sRangeEnc_copy, sizeof(ec_enc)); memcpy(&psEnc->sCmn.sNSQ, &sNSQ_copy, sizeof(silk_nsq_state)); psEnc->sCmn.indices.Seed = seed_copy; psEnc->sCmn.ec_prevLagIndex = ec_prevLagIndex_copy; psEnc->sCmn.ec_prevSignalType = ec_prevSignalType_copy; } /*****************************************/ /* Noise shaping quantization */ /*****************************************/ if (psEnc->sCmn.nStatesDelayedDecision > 1 || psEnc->sCmn.warping_Q16 > 0) { silk_NSQ_del_dec(&psEnc->sCmn, &psEnc->sCmn.sNSQ, &psEnc->sCmn.indices, xfw_Q3, psEnc->sCmn.pulses, sEncCtrl. PredCoef_Q12[0], sEncCtrl.LTPCoef_Q14, sEncCtrl.AR2_Q13, sEncCtrl. HarmShapeGain_Q14, sEncCtrl.Tilt_Q14, sEncCtrl.LF_shp_Q14, sEncCtrl.Gains_Q16, sEncCtrl.pitchL, sEncCtrl.Lambda_Q10, sEncCtrl. LTP_scale_Q14); } else { silk_NSQ(&psEnc->sCmn, &psEnc->sCmn.sNSQ, &psEnc->sCmn.indices, xfw_Q3, psEnc->sCmn.pulses, sEncCtrl.PredCoef_Q12[0], sEncCtrl.LTPCoef_Q14, sEncCtrl.AR2_Q13, sEncCtrl.HarmShapeGain_Q14, sEncCtrl.Tilt_Q14, sEncCtrl.LF_shp_Q14, sEncCtrl.Gains_Q16, sEncCtrl.pitchL, sEncCtrl.Lambda_Q10, sEncCtrl.LTP_scale_Q14); } /****************************************/ /* Encode Parameters */ /****************************************/ silk_encode_indices(&psEnc->sCmn, psRangeEnc, psEnc->sCmn.nFramesEncoded, 0, condCoding); /****************************************/ /* Encode Excitation Signal */ /****************************************/ silk_encode_pulses(psRangeEnc, psEnc->sCmn.indices. signalType, psEnc->sCmn.indices. quantOffsetType, psEnc->sCmn.pulses, psEnc->sCmn.frame_length); nBits = ec_tell(psRangeEnc); if (useCBR == 0 && iter == 0 && nBits <= maxBits) { break; } } if (iter == maxIter) { if (found_lower && (gainsID == gainsID_lower || nBits > maxBits)) { /* Restore output state from earlier iteration that did meet the bitrate budget */ memcpy(psRangeEnc, &sRangeEnc_copy2, sizeof(ec_enc)); assert(sRangeEnc_copy2.offs <= 1275); memcpy(psRangeEnc->buf, ec_buf_copy, sRangeEnc_copy2.offs); memcpy(&psEnc->sCmn.sNSQ, &sNSQ_copy2, sizeof(silk_nsq_state)); psEnc->sShape.LastGainIndex = LastGainIndex_copy2; } break; } if (nBits > maxBits) { if (found_lower == 0 && iter >= 2) { /* Adjust the quantizer's rate/distortion tradeoff and discard previous "upper" results */ sEncCtrl.Lambda_Q10 = silk_ADD_RSHIFT32(sEncCtrl. Lambda_Q10, sEncCtrl. Lambda_Q10, 1); found_upper = 0; gainsID_upper = -1; } else { found_upper = 1; nBits_upper = nBits; gainMult_upper = gainMult_Q8; gainsID_upper = gainsID; } } else if (nBits < maxBits - 5) { found_lower = 1; nBits_lower = nBits; gainMult_lower = gainMult_Q8; if (gainsID != gainsID_lower) { gainsID_lower = gainsID; /* Copy part of the output state */ memcpy(&sRangeEnc_copy2, psRangeEnc, sizeof(ec_enc)); assert(psRangeEnc->offs <= 1275); memcpy(ec_buf_copy, psRangeEnc->buf, psRangeEnc->offs); memcpy(&sNSQ_copy2, &psEnc->sCmn.sNSQ, sizeof(silk_nsq_state)); LastGainIndex_copy2 = psEnc->sShape.LastGainIndex; } } else { /* Within 5 bits of budget: close enough */ break; } if ((found_lower & found_upper) == 0) { /* Adjust gain according to high-rate rate/distortion curve */ int32_t gain_factor_Q16; gain_factor_Q16 = silk_log2lin(silk_LSHIFT(nBits - maxBits, 7) / psEnc->sCmn.frame_length + SILK_FIX_CONST(16, 7)); gain_factor_Q16 = silk_min_32(gain_factor_Q16, SILK_FIX_CONST(2, 16)); if (nBits > maxBits) { gain_factor_Q16 = silk_max_32(gain_factor_Q16, SILK_FIX_CONST(1.3, 16)); } gainMult_Q8 = silk_SMULWB(gain_factor_Q16, gainMult_Q8); } else { /* Adjust gain by interpolating */ assert(nBits_upper != nBits_lower); gainMult_Q8 = gainMult_lower + silk_DIV32_16(silk_MUL (gainMult_upper - gainMult_lower, maxBits - nBits_lower), nBits_upper - nBits_lower); /* New gain multplier must be between 25% and 75% of old range (note that gainMult_upper < gainMult_lower) */ if (gainMult_Q8 > silk_ADD_RSHIFT32(gainMult_lower, gainMult_upper - gainMult_lower, 2)) { gainMult_Q8 = silk_ADD_RSHIFT32(gainMult_lower, gainMult_upper - gainMult_lower, 2); } else if (gainMult_Q8 < silk_SUB_RSHIFT32(gainMult_upper, gainMult_upper - gainMult_lower, 2)) { gainMult_Q8 = silk_SUB_RSHIFT32(gainMult_upper, gainMult_upper - gainMult_lower, 2); } } for (i = 0; i < psEnc->sCmn.nb_subfr; i++) { sEncCtrl.Gains_Q16[i] = silk_LSHIFT_SAT32(silk_SMULWB (sEncCtrl.GainsUnq_Q16[i], gainMult_Q8), 8); } /* Quantize gains */ psEnc->sShape.LastGainIndex = sEncCtrl.lastGainIndexPrev; silk_gains_quant(psEnc->sCmn.indices.GainsIndices, sEncCtrl.Gains_Q16, &psEnc->sShape.LastGainIndex, condCoding == CODE_CONDITIONALLY, psEnc->sCmn.nb_subfr); /* Unique identifier of gains vector */ gainsID = silk_gains_ID(psEnc->sCmn.indices.GainsIndices, psEnc->sCmn.nb_subfr); } } /* Update input buffer */ memmove(psEnc->x_buf, &psEnc->x_buf[psEnc->sCmn.frame_length], (psEnc->sCmn.ltp_mem_length + LA_SHAPE_MS * psEnc->sCmn.fs_kHz) * sizeof(int16_t)); /* Exit without entropy coding */ if (psEnc->sCmn.prefillFlag) { /* No payload */ *pnBytesOut = 0; return ret; } /* Parameters needed for next frame */ psEnc->sCmn.prevLag = sEncCtrl.pitchL[psEnc->sCmn.nb_subfr - 1]; psEnc->sCmn.prevSignalType = psEnc->sCmn.indices.signalType; /****************************************/ /* Finalize payload */ /****************************************/ psEnc->sCmn.first_frame_after_reset = 0; /* Payload size */ *pnBytesOut = silk_RSHIFT(ec_tell(psRangeEnc) + 7, 3); return ret; }
/* Decode parameters from payload */ void silk_decode_parameters(silk_decoder_state * psDec, /* I/O State */ silk_decoder_control * psDecCtrl, /* I/O Decoder control */ int condCoding /* I The type of conditional coding to use */ ) { int i, k, Ix; int16_t pNLSF_Q15[MAX_LPC_ORDER], pNLSF0_Q15[MAX_LPC_ORDER]; const int8_t *cbk_ptr_Q7; /* Dequant Gains */ silk_gains_dequant(psDecCtrl->Gains_Q16, psDec->indices.GainsIndices, &psDec->LastGainIndex, condCoding == CODE_CONDITIONALLY, psDec->nb_subfr); /****************/ /* Decode NLSFs */ /****************/ silk_NLSF_decode(pNLSF_Q15, psDec->indices.NLSFIndices, psDec->psNLSF_CB); /* Convert NLSF parameters to AR prediction filter coefficients */ silk_NLSF2A(psDecCtrl->PredCoef_Q12[1], pNLSF_Q15, psDec->LPC_order); /* If just reset, e.g., because internal Fs changed, do not allow interpolation */ /* improves the case of packet loss in the first frame after a switch */ if (psDec->first_frame_after_reset == 1) { psDec->indices.NLSFInterpCoef_Q2 = 4; } if (psDec->indices.NLSFInterpCoef_Q2 < 4) { /* Calculation of the interpolated NLSF0 vector from the interpolation factor, */ /* the previous NLSF1, and the current NLSF1 */ for (i = 0; i < psDec->LPC_order; i++) { pNLSF0_Q15[i] = psDec->prevNLSF_Q15[i] + silk_RSHIFT(silk_MUL (psDec->indices.NLSFInterpCoef_Q2, pNLSF_Q15[i] - psDec->prevNLSF_Q15[i]), 2); } /* Convert NLSF parameters to AR prediction filter coefficients */ silk_NLSF2A(psDecCtrl->PredCoef_Q12[0], pNLSF0_Q15, psDec->LPC_order); } else { /* Copy LPC coefficients for first half from second half */ memcpy(psDecCtrl->PredCoef_Q12[0], psDecCtrl->PredCoef_Q12[1], psDec->LPC_order * sizeof(int16_t)); } memcpy(psDec->prevNLSF_Q15, pNLSF_Q15, psDec->LPC_order * sizeof(int16_t)); /* After a packet loss do BWE of LPC coefs */ if (psDec->lossCnt) { silk_bwexpander(psDecCtrl->PredCoef_Q12[0], psDec->LPC_order, BWE_AFTER_LOSS_Q16); silk_bwexpander(psDecCtrl->PredCoef_Q12[1], psDec->LPC_order, BWE_AFTER_LOSS_Q16); } if (psDec->indices.signalType == TYPE_VOICED) { /*********************/ /* Decode pitch lags */ /*********************/ /* Decode pitch values */ silk_decode_pitch(psDec->indices.lagIndex, psDec->indices.contourIndex, psDecCtrl->pitchL, psDec->fs_kHz, psDec->nb_subfr); /* Decode Codebook Index */ cbk_ptr_Q7 = silk_LTP_vq_ptrs_Q7[psDec->indices.PERIndex]; /* set pointer to start of codebook */ for (k = 0; k < psDec->nb_subfr; k++) { Ix = psDec->indices.LTPIndex[k]; for (i = 0; i < LTP_ORDER; i++) { psDecCtrl->LTPCoef_Q14[k * LTP_ORDER + i] = silk_LSHIFT(cbk_ptr_Q7[Ix * LTP_ORDER + i], 7); } } /**********************/ /* Decode LTP scaling */ /**********************/ Ix = psDec->indices.LTP_scaleIndex; psDecCtrl->LTP_scale_Q14 = silk_LTPScales_table_Q14[Ix]; } else { memzero(psDecCtrl->pitchL, psDec->nb_subfr * sizeof(int)); memzero(psDecCtrl->LTPCoef_Q14, LTP_ORDER * psDec->nb_subfr * sizeof(int16_t)); psDec->indices.PERIndex = 0; psDecCtrl->LTP_scale_Q14 = 0; } }
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; }
/* amplitude of monic warped coefficients by using bandwidth expansion on the true coefficients */ static inline void limit_warped_coefs( opus_int32 *coefs_syn_Q24, opus_int32 *coefs_ana_Q24, opus_int lambda_Q16, opus_int32 limit_Q24, opus_int order ) { opus_int i, iter, ind = 0; opus_int32 tmp, maxabs_Q24, chirp_Q16, gain_syn_Q16, gain_ana_Q16; opus_int32 nom_Q16, den_Q24; /* Convert to monic coefficients */ lambda_Q16 = -lambda_Q16; for( i = order - 1; i > 0; i-- ) { coefs_syn_Q24[ i - 1 ] = silk_SMLAWB( coefs_syn_Q24[ i - 1 ], coefs_syn_Q24[ i ], lambda_Q16 ); coefs_ana_Q24[ i - 1 ] = silk_SMLAWB( coefs_ana_Q24[ i - 1 ], coefs_ana_Q24[ i ], lambda_Q16 ); } lambda_Q16 = -lambda_Q16; nom_Q16 = silk_SMLAWB( SILK_FIX_CONST( 1.0, 16 ), -lambda_Q16, lambda_Q16 ); den_Q24 = silk_SMLAWB( SILK_FIX_CONST( 1.0, 24 ), coefs_syn_Q24[ 0 ], lambda_Q16 ); gain_syn_Q16 = silk_DIV32_varQ( nom_Q16, den_Q24, 24 ); den_Q24 = silk_SMLAWB( SILK_FIX_CONST( 1.0, 24 ), coefs_ana_Q24[ 0 ], lambda_Q16 ); gain_ana_Q16 = silk_DIV32_varQ( nom_Q16, den_Q24, 24 ); for( i = 0; i < order; i++ ) { coefs_syn_Q24[ i ] = silk_SMULWW( gain_syn_Q16, coefs_syn_Q24[ i ] ); coefs_ana_Q24[ i ] = silk_SMULWW( gain_ana_Q16, coefs_ana_Q24[ i ] ); } for( iter = 0; iter < 10; iter++ ) { /* Find maximum absolute value */ maxabs_Q24 = -1; for( i = 0; i < order; i++ ) { tmp = silk_max( silk_abs_int32( coefs_syn_Q24[ i ] ), silk_abs_int32( coefs_ana_Q24[ i ] ) ); if( tmp > maxabs_Q24 ) { maxabs_Q24 = tmp; ind = i; } } if( maxabs_Q24 <= limit_Q24 ) { /* Coefficients are within range - done */ return; } /* Convert back to true warped coefficients */ for( i = 1; i < order; i++ ) { coefs_syn_Q24[ i - 1 ] = silk_SMLAWB( coefs_syn_Q24[ i - 1 ], coefs_syn_Q24[ i ], lambda_Q16 ); coefs_ana_Q24[ i - 1 ] = silk_SMLAWB( coefs_ana_Q24[ i - 1 ], coefs_ana_Q24[ i ], lambda_Q16 ); } gain_syn_Q16 = silk_INVERSE32_varQ( gain_syn_Q16, 32 ); gain_ana_Q16 = silk_INVERSE32_varQ( gain_ana_Q16, 32 ); for( i = 0; i < order; i++ ) { coefs_syn_Q24[ i ] = silk_SMULWW( gain_syn_Q16, coefs_syn_Q24[ i ] ); coefs_ana_Q24[ i ] = silk_SMULWW( gain_ana_Q16, coefs_ana_Q24[ i ] ); } /* Apply bandwidth expansion */ chirp_Q16 = SILK_FIX_CONST( 0.99, 16 ) - silk_DIV32_varQ( silk_SMULWB( maxabs_Q24 - limit_Q24, silk_SMLABB( SILK_FIX_CONST( 0.8, 10 ), SILK_FIX_CONST( 0.1, 10 ), iter ) ), silk_MUL( maxabs_Q24, ind + 1 ), 22 ); silk_bwexpander_32( coefs_syn_Q24, order, chirp_Q16 ); silk_bwexpander_32( coefs_ana_Q24, order, chirp_Q16 ); /* Convert to monic warped coefficients */ lambda_Q16 = -lambda_Q16; for( i = order - 1; i > 0; i-- ) { coefs_syn_Q24[ i - 1 ] = silk_SMLAWB( coefs_syn_Q24[ i - 1 ], coefs_syn_Q24[ i ], lambda_Q16 ); coefs_ana_Q24[ i - 1 ] = silk_SMLAWB( coefs_ana_Q24[ i - 1 ], coefs_ana_Q24[ i ], lambda_Q16 ); } lambda_Q16 = -lambda_Q16; nom_Q16 = silk_SMLAWB( SILK_FIX_CONST( 1.0, 16 ), -lambda_Q16, lambda_Q16 ); den_Q24 = silk_SMLAWB( SILK_FIX_CONST( 1.0, 24 ), coefs_syn_Q24[ 0 ], lambda_Q16 ); gain_syn_Q16 = silk_DIV32_varQ( nom_Q16, den_Q24, 24 ); den_Q24 = silk_SMLAWB( SILK_FIX_CONST( 1.0, 24 ), coefs_ana_Q24[ 0 ], lambda_Q16 ); gain_ana_Q16 = silk_DIV32_varQ( nom_Q16, den_Q24, 24 ); for( i = 0; i < order; i++ ) { coefs_syn_Q24[ i ] = silk_SMULWW( gain_syn_Q16, coefs_syn_Q24[ i ] ); coefs_ana_Q24[ i ] = silk_SMULWW( gain_ana_Q16, coefs_ana_Q24[ i ] ); } } silk_assert( 0 ); }
/* 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; }
/* Initialize/reset the resampler state for a given pair of input/output sampling rates */ opus_int silk_resampler_init( silk_resampler_state_struct *S, /* I/O Resampler state */ opus_int32 Fs_Hz_in, /* I Input sampling rate (Hz) */ opus_int32 Fs_Hz_out, /* I Output sampling rate (Hz) */ opus_int forEnc /* I If 1: encoder; if 0: decoder */ ) { opus_int up2x; /* Clear state */ silk_memset( S, 0, sizeof( silk_resampler_state_struct ) ); /* Input checking */ if( forEnc ) { if( ( Fs_Hz_in != 8000 && Fs_Hz_in != 12000 && Fs_Hz_in != 16000 && Fs_Hz_in != 24000 && Fs_Hz_in != 48000 ) || ( Fs_Hz_out != 8000 && Fs_Hz_out != 12000 && Fs_Hz_out != 16000 ) ) { silk_assert( 0 ); return -1; } S->inputDelay = delay_matrix_enc[ rateID( Fs_Hz_in ) ][ rateID( Fs_Hz_out ) ]; } else { if( ( Fs_Hz_in != 8000 && Fs_Hz_in != 12000 && Fs_Hz_in != 16000 ) || ( Fs_Hz_out != 8000 && Fs_Hz_out != 12000 && Fs_Hz_out != 16000 && Fs_Hz_out != 24000 && Fs_Hz_out != 48000 ) ) { silk_assert( 0 ); return -1; } S->inputDelay = delay_matrix_dec[ rateID( Fs_Hz_in ) ][ rateID( Fs_Hz_out ) ]; } S->Fs_in_kHz = silk_DIV32_16( Fs_Hz_in, 1000 ); S->Fs_out_kHz = silk_DIV32_16( Fs_Hz_out, 1000 ); /* Number of samples processed per batch */ S->batchSize = S->Fs_in_kHz * RESAMPLER_MAX_BATCH_SIZE_MS; /* Find resampler with the right sampling ratio */ up2x = 0; if( Fs_Hz_out > Fs_Hz_in ) { /* Upsample */ if( Fs_Hz_out == silk_MUL( Fs_Hz_in, 2 ) ) { /* Fs_out : Fs_in = 2 : 1 */ /* Special case: directly use 2x upsampler */ S->resampler_function = USE_silk_resampler_private_up2_HQ_wrapper; } else { /* Default resampler */ S->resampler_function = USE_silk_resampler_private_IIR_FIR; up2x = 1; } } else if ( Fs_Hz_out < Fs_Hz_in ) { /* Downsample */ S->resampler_function = USE_silk_resampler_private_down_FIR; if( silk_MUL( Fs_Hz_out, 4 ) == silk_MUL( Fs_Hz_in, 3 ) ) { /* Fs_out : Fs_in = 3 : 4 */ S->FIR_Fracs = 3; S->FIR_Order = RESAMPLER_DOWN_ORDER_FIR0; S->Coefs = silk_Resampler_3_4_COEFS; } else if( silk_MUL( Fs_Hz_out, 3 ) == silk_MUL( Fs_Hz_in, 2 ) ) { /* Fs_out : Fs_in = 2 : 3 */ S->FIR_Fracs = 2; S->FIR_Order = RESAMPLER_DOWN_ORDER_FIR0; S->Coefs = silk_Resampler_2_3_COEFS; } else if( silk_MUL( Fs_Hz_out, 2 ) == Fs_Hz_in ) { /* Fs_out : Fs_in = 1 : 2 */ S->FIR_Fracs = 1; S->FIR_Order = RESAMPLER_DOWN_ORDER_FIR1; S->Coefs = silk_Resampler_1_2_COEFS; } else if( silk_MUL( Fs_Hz_out, 3 ) == Fs_Hz_in ) { /* Fs_out : Fs_in = 1 : 3 */ S->FIR_Fracs = 1; S->FIR_Order = RESAMPLER_DOWN_ORDER_FIR2; S->Coefs = silk_Resampler_1_3_COEFS; } else if( silk_MUL( Fs_Hz_out, 4 ) == Fs_Hz_in ) { /* Fs_out : Fs_in = 1 : 4 */ S->FIR_Fracs = 1; S->FIR_Order = RESAMPLER_DOWN_ORDER_FIR2; S->Coefs = silk_Resampler_1_4_COEFS; } else if( silk_MUL( Fs_Hz_out, 6 ) == Fs_Hz_in ) { /* Fs_out : Fs_in = 1 : 6 */ S->FIR_Fracs = 1; S->FIR_Order = RESAMPLER_DOWN_ORDER_FIR2; S->Coefs = silk_Resampler_1_6_COEFS; } else { /* None available */ silk_assert( 0 ); return -1; } } else { /* Input and output sampling rates are equal: copy */ S->resampler_function = USE_silk_resampler_copy; } /* Ratio of input/output samples */ S->invRatio_Q16 = silk_LSHIFT32( silk_DIV32( silk_LSHIFT32( Fs_Hz_in, 14 + up2x ), Fs_Hz_out ), 2 ); /* Make sure the ratio is rounded up */ while( silk_SMULWW( S->invRatio_Q16, Fs_Hz_out ) < silk_LSHIFT32( Fs_Hz_in, up2x ) ) { S->invRatio_Q16++; } return 0; }
/* Initialize/reset the resampler state for a given pair of input/output sampling rates */ opus_int silk_resampler_init( silk_resampler_state_struct *S, /* I/O Resampler state */ opus_int32 Fs_Hz_in, /* I Input sampling rate (Hz) */ opus_int32 Fs_Hz_out /* I Output sampling rate (Hz) */ ) { opus_int32 up2 = 0, down2 = 0; /* Clear state */ silk_memset( S, 0, sizeof( silk_resampler_state_struct ) ); /* Input checking */ if( ( Fs_Hz_in != 8000 && Fs_Hz_in != 12000 && Fs_Hz_in != 16000 && Fs_Hz_in != 24000 && Fs_Hz_in != 48000 ) || ( Fs_Hz_out != 8000 && Fs_Hz_out != 12000 && Fs_Hz_out != 16000 && Fs_Hz_out != 24000 && Fs_Hz_out != 48000 ) ) { silk_assert( 0 ); return -1; } /* Number of samples processed per batch */ S->batchSize = silk_DIV32_16( Fs_Hz_in, 100 ); /* Find resampler with the right sampling ratio */ if( Fs_Hz_out > Fs_Hz_in ) { /* Upsample */ if( Fs_Hz_out == silk_MUL( Fs_Hz_in, 2 ) ) { /* Fs_out : Fs_in = 2 : 1 */ /* Special case: directly use 2x upsampler */ S->resampler_function = USE_silk_resampler_private_up2_HQ_wrapper; } else { /* Default resampler */ S->resampler_function = USE_silk_resampler_private_IIR_FIR; up2 = 1; } } else if ( Fs_Hz_out < Fs_Hz_in ) { /* Downsample */ if( silk_MUL( Fs_Hz_out, 4 ) == silk_MUL( Fs_Hz_in, 3 ) ) { /* Fs_out : Fs_in = 3 : 4 */ S->FIR_Fracs = 3; S->Coefs = silk_Resampler_3_4_COEFS; S->resampler_function = USE_silk_resampler_private_down_FIR; } else if( silk_MUL( Fs_Hz_out, 3 ) == silk_MUL( Fs_Hz_in, 2 ) ) { /* Fs_out : Fs_in = 2 : 3 */ S->FIR_Fracs = 2; S->Coefs = silk_Resampler_2_3_COEFS; S->resampler_function = USE_silk_resampler_private_down_FIR; } else if( silk_MUL( Fs_Hz_out, 2 ) == Fs_Hz_in ) { /* Fs_out : Fs_in = 1 : 2 */ S->FIR_Fracs = 1; S->Coefs = silk_Resampler_1_2_COEFS; S->resampler_function = USE_silk_resampler_private_down_FIR; } else if( silk_MUL( Fs_Hz_out, 3 ) == Fs_Hz_in ) { /* Fs_out : Fs_in = 1 : 3 */ S->FIR_Fracs = 1; S->Coefs = silk_Resampler_1_3_COEFS; S->resampler_function = USE_silk_resampler_private_down_FIR; } else if( silk_MUL( Fs_Hz_out, 4 ) == Fs_Hz_in ) { /* Fs_out : Fs_in = 1 : 4 */ S->FIR_Fracs = 1; down2 = 1; S->Coefs = silk_Resampler_1_2_COEFS; S->resampler_function = USE_silk_resampler_private_down_FIR; } else if( silk_MUL( Fs_Hz_out, 6 ) == Fs_Hz_in ) { /* Fs_out : Fs_in = 1 : 6 */ S->FIR_Fracs = 1; down2 = 1; S->Coefs = silk_Resampler_1_3_COEFS; S->resampler_function = USE_silk_resampler_private_down_FIR; } else { /* None available */ silk_assert( 0 ); return -1; } } else { /* Input and output sampling rates are equal: copy */ S->resampler_function = USE_silk_resampler_copy; } S->input2x = up2 | down2; /* Ratio of input/output samples */ S->invRatio_Q16 = silk_LSHIFT32( silk_DIV32( silk_LSHIFT32( Fs_Hz_in, 14 + up2 - down2 ), Fs_Hz_out ), 2 ); /* Make sure the ratio is rounded up */ while( silk_SMULWW( S->invRatio_Q16, silk_LSHIFT32( Fs_Hz_out, down2 ) ) < silk_LSHIFT32( Fs_Hz_in, up2 ) ) { S->invRatio_Q16++; } return 0; }