/* Can handle slowly varying filter coefficients */ void SKP_Silk_biquad( const SKP_int16 *in, /* I: input signal */ const SKP_int16 *B, /* I: MA coefficients, Q13 [3] */ const SKP_int16 *A, /* I: AR coefficients, Q13 [2] */ SKP_int32 *S, /* I/O: state vector [2] */ SKP_int16 *out, /* O: output signal */ const SKP_int32 len /* I: signal length */ ) { SKP_int k, in16; SKP_int32 A0_neg, A1_neg, S0, S1, out32, tmp32; S0 = S[ 0 ]; S1 = S[ 1 ]; A0_neg = -A[ 0 ]; A1_neg = -A[ 1 ]; for( k = 0; k < len; k++ ) { /* S[ 0 ], S[ 1 ]: Q13 */ in16 = in[ k ]; out32 = SKP_SMLABB( S0, in16, B[ 0 ] ); S0 = SKP_SMLABB( S1, in16, B[ 1 ] ); S0 += SKP_LSHIFT( SKP_SMULWB( out32, A0_neg ), 3 ); S1 = SKP_LSHIFT( SKP_SMULWB( out32, A1_neg ), 3 ); S1 = SKP_SMLABB( S1, in16, B[ 2 ] ); tmp32 = SKP_RSHIFT_ROUND( out32, 13 ) + 1; out[ k ] = (SKP_int16)SKP_SAT16( tmp32 ); } S[ 0 ] = S0; S[ 1 ] = S1; }
/* helper function for NLSF2A(..) */ static inline void SKP_Silk_NLSF2A_find_poly(int32_t * out, /* o intermediate polynomial, Q20 */ const int32_t * cLSF, /* i vector of interleaved 2*cos(LSFs), Q20 */ int dd /* i polynomial order (= 1/2 * filter order) */ ) { int k, n; int32_t ftmp; out[0] = SKP_LSHIFT(1, 20); out[1] = -cLSF[0]; for (k = 1; k < dd; k++) { ftmp = cLSF[2 * k]; // Q20 out[k + 1] = SKP_LSHIFT(out[k - 1], 1) - (int32_t) SKP_RSHIFT_ROUND64(SKP_SMULL(ftmp, out [k]), 20); for (n = k; n > 1; n--) { out[n] += out[n - 2] - (int32_t) SKP_RSHIFT_ROUND64(SKP_SMULL(ftmp, out[n - 1]), 20); } out[1] -= ftmp; } }
/* Split signal into two decimated bands using first-order allpass filters */ void SKP_Silk_ana_filt_bank_1(const int16_t * in, /* I: Input signal [N] */ int32_t * S, /* I/O: State vector [2] */ int16_t * outL, /* O: Low band [N/2] */ int16_t * outH, /* O: High band [N/2] */ int32_t * scratch, /* I: Scratch memory [3*N/2] */ const int32_t N /* I: Number of input samples */ ) { int k, N2 = SKP_RSHIFT(N, 1); int32_t out_tmp; /* De-interleave three allpass inputs, and convert Q15 -> Q25 */ for (k = 0; k < N2; k++) { scratch[k + N] = SKP_LSHIFT((int32_t) in[2 * k], 10); scratch[k + N2] = SKP_LSHIFT((int32_t) in[2 * k + 1], 10); } /* Allpass filters */ SKP_Silk_allpass_int(scratch + N2, S + 0, A_fb1_20[0], scratch, N2); SKP_Silk_allpass_int(scratch + N, S + 1, A_fb1_21[0], scratch + N2, N2); /* Add and subtract two allpass outputs to create bands */ for (k = 0; k < N2; k++) { out_tmp = scratch[k] + scratch[k + N2]; outL[k] = (int16_t) SKP_SAT16(SKP_RSHIFT_ROUND(out_tmp, 11)); out_tmp = scratch[k] - scratch[k + N2]; outH[k] = (int16_t) SKP_SAT16(SKP_RSHIFT_ROUND(out_tmp, 11)); } }
/* Downsample by a factor 2, coarsest */ void SKP_Silk_resample_1_2_coarsest( const SKP_int16 *in, /* I: 16 kHz signal [2*len] */ SKP_int32 *S, /* I/O: State vector [2] */ SKP_int16 *out, /* O: 8 kHz signal [len] */ SKP_int32 *scratch, /* I: Scratch memory [3*len] */ const SKP_int32 len /* I: Number of OUTPUT samples*/ ) { SKP_int32 k, idx; /* De-interleave allpass inputs, and convert Q15 -> Q25 */ for( k = 0; k < len; k++ ) { idx = SKP_LSHIFT( k, 1 ); scratch[ k ] = SKP_LSHIFT( (SKP_int32)in[ idx ], 10 ); scratch[ k + len ] = SKP_LSHIFT( (SKP_int32)in[ idx + 1 ], 10 ); } idx = SKP_LSHIFT( len, 1 ); /* Allpass filters */ SKP_Silk_allpass_int( scratch, S, A21cst[ 0 ], scratch + idx, len ); SKP_Silk_allpass_int( scratch + len, S + 1, A20cst[ 0 ], scratch, len ); /* Add two allpass outputs */ for( k = 0; k < len; k++ ) { out[ k ] = (SKP_int16)SKP_SAT16( SKP_RSHIFT_ROUND( scratch[ k ] + scratch[ k + idx ], 11 ) ); } }
/* Upsample by a factor 2, coarser */ void SKP_Silk_resample_2_1_coarse( const SKP_int16 *in, /* I: 8 kHz signal [len] */ SKP_int32 *S, /* I/O: State vector [4] */ SKP_int16 *out, /* O: 16 kHz signal [2*len] */ SKP_int32 *scratch, /* I: Scratch memory [3*len] */ const SKP_int32 len /* I: Number of INPUT samples */ ) { SKP_int32 k, idx; /* Coefficients for coarser 2-fold resampling */ const SKP_int16 A20c[ 2 ] = { 2119, 16663 }; const SKP_int16 A21c[ 2 ] = { 8050, 26861 }; /* Convert Q15 -> Q25 */ for( k = 0; k < len; k++ ) { scratch[ k ] = SKP_LSHIFT( (SKP_int32)in[ k ], 10 ); } idx = SKP_LSHIFT( len, 1 ); /* Allpass filters */ SKP_Silk_allpass_int( scratch, S, A20c[ 0 ], scratch + idx, len ); SKP_Silk_allpass_int( scratch + idx, S + 1, A20c[ 1 ], scratch + len, len ); SKP_Silk_allpass_int( scratch, S + 2, A21c[ 0 ], scratch + idx, len ); SKP_Silk_allpass_int( scratch + idx, S + 3, A21c[ 1 ], scratch, len ); /* Interleave two allpass outputs */ for( k = 0; k < len; k++ ) { idx = SKP_LSHIFT( k, 1 ); out[ idx ] = (SKP_int16)SKP_SAT16( SKP_RSHIFT_ROUND( scratch[ k + len ], 10 ) ); out[ idx + 1 ] = (SKP_int16)SKP_SAT16( SKP_RSHIFT_ROUND( scratch[ k ], 10 ) ); } }
void SKP_Silk_MA_Prediction_Q13( const SKP_int16 *in, /* I: input signal */ const SKP_int16 *B, /* I: MA prediction coefficients, Q13 [order] */ SKP_int32 *S, /* I/O: state vector [order] */ SKP_int16 *out, /* O: output signal */ SKP_int32 len, /* I: signal length */ SKP_int32 order /* I: filter order */ ) { SKP_int k, in16; SKP_int32 out32; switch(order) { case 8: for( k = 0; k < len; k++ ) { in16 = in[ k ]; out32 = SKP_LSHIFT( in16, 13 ) - S[ 0 ]; out32 = SKP_RSHIFT_ROUND( out32, 13 ); FILTER_LOOP_ORDER_8(S, B, in16); out[ k ] = (SKP_int16) SKP_SAT16(out32); } break; case 10: for( k = 0; k < len; k++ ) { in16 = in[ k ]; out32 = SKP_LSHIFT( in16, 13 ) - S[ 0 ]; out32 = SKP_RSHIFT_ROUND( out32, 13 ); FILTER_LOOP_ORDER_10(S, B, in16); out[ k ] = (SKP_int16) SKP_SAT16(out32); } break; case 12: for( k = 0; k < len; k++ ) { in16 = in[ k ]; out32 = SKP_LSHIFT( in16, 13 ) - S[ 0 ]; out32 = SKP_RSHIFT_ROUND( out32, 13 ); FILTER_LOOP_ORDER_12(S, B, in16); out[ k ] = (SKP_int16) SKP_SAT16(out32); } break; case 16: for( k = 0; k < len; k++ ) { in16 = in[ k ]; out32 = SKP_LSHIFT( in16, 13 ) - S[ 0 ]; out32 = SKP_RSHIFT_ROUND( out32, 13 ); FILTER_LOOP_ORDER_16(S, B, in16); out[ k ] = (SKP_int16) SKP_SAT16(out32); } break; default: for( k = 0; k < len; k++ ) { in16 = in[ k ]; out32 = SKP_LSHIFT( in16, 13 ) - S[ 0 ]; out32 = SKP_RSHIFT_ROUND( out32, 13 ); FILTER_LOOP_ORDER_ANY(S, B, in16, order); out[ k ] = (SKP_int16) SKP_SAT16(out32); } } }
/* Inverse filter of SKP_Silk_LPC_synthesis_filter */ void SKP_Silk_LPC_analysis_filter( const SKP_int16 *in, /* I: Input signal */ const SKP_int16 *B, /* I: MA prediction coefficients, Q12 [order] */ SKP_int16 *S, /* I/O: State vector [order] */ SKP_int16 *out, /* O: Output signal */ const SKP_int32 len, /* I: Signal length */ const SKP_int32 Order /* I: Filter order */ ) { SKP_int k, j, idx, Order_half = SKP_RSHIFT( Order, 1 ); SKP_int32 Btmp, B_align_Q12[ SigProc_MAX_ORDER_LPC >> 1 ], out32_Q12, out32; SKP_int16 SA, SB; /* Order must be even */ SKP_assert( 2 * Order_half == Order ); /* Combine two A_Q12 values and ensure 32-bit alignment */ for( k = 0; k < Order_half; k++ ) { idx = SKP_SMULBB( 2, k ); B_align_Q12[ k ] = ( ( (SKP_int32)B[ idx ] ) & 0x0000ffff ) | SKP_LSHIFT( (SKP_int32)B[ idx + 1 ], 16 ); } /* S[] values are in Q0 */ for( k = 0; k < len; k++ ) { SA = S[ 0 ]; out32_Q12 = 0; for( j = 0; j < ( Order_half - 1 ); j++ ) { idx = SKP_SMULBB( 2, j ) + 1; /* Multiply-add two prediction coefficients for each loop */ Btmp = B_align_Q12[ j ]; SB = S[ idx ]; S[ idx ] = SA; out32_Q12 = SKP_SMLABB( out32_Q12, SA, Btmp ); out32_Q12 = SKP_SMLABT( out32_Q12, SB, Btmp ); SA = S[ idx + 1 ]; S[ idx + 1 ] = SB; } /* Unrolled loop: epilog */ Btmp = B_align_Q12[ Order_half - 1 ]; SB = S[ Order - 1 ]; S[ Order - 1 ] = SA; out32_Q12 = SKP_SMLABB( out32_Q12, SA, Btmp ); out32_Q12 = SKP_SMLABT( out32_Q12, SB, Btmp ); /* Subtract prediction */ out32_Q12 = SKP_SUB_SAT32( SKP_LSHIFT( (SKP_int32)in[ k ], 12 ), out32_Q12 ); /* Scale to Q0 */ out32 = SKP_RSHIFT_ROUND( out32_Q12, 12 ); /* Saturate output */ out[ k ] = (SKP_int16)SKP_SAT16( out32 ); /* Move input line */ S[ 0 ] = in[ k ]; } }
/* every other sample of window is linearly interpolated, for speed */ void SKP_Silk_apply_sine_window( SKP_int16 px_win[], /* O Pointer to windowed signal */ const SKP_int16 px[], /* I Pointer to input signal */ const SKP_int win_type, /* I Selects a window type */ const SKP_int length /* I Window length, multiple of 4 */ ) { SKP_int k; SKP_int32 f_Q16, c_Q20, S0_Q16, S1_Q16; /* Length must be multiple of 4 */ SKP_assert( ( length & 3 ) == 0 ); /* Input pointer must be 4-byte aligned */ SKP_assert( ( (SKP_int64)px & 3 ) == 0 ); if( win_type == 0 ) { f_Q16 = SKP_DIV32_16( 411775, length + 1 ); // 411775 = 2 * 65536 * pi } else { f_Q16 = SKP_DIV32_16( 205887, length + 1 ); // 205887 = 65536 * pi } /* factor used for cosine approximation */ c_Q20 = -SKP_RSHIFT( SKP_MUL( f_Q16, f_Q16 ), 12 ); /* c_Q20 becomes too large if length is too small */ SKP_assert( c_Q20 >= -32768 ); /* initialize state */ if( win_type < 2 ) { /* start from 0 */ S0_Q16 = 0; /* approximation of sin(f) */ S1_Q16 = f_Q16; } else { /* start from 1 */ S0_Q16 = ( 1 << 16 ); /* approximation of cos(f) */ S1_Q16 = ( 1 << 16 ) + SKP_RSHIFT( c_Q20, 5 ); } /* Uses the recursive equation: sin(n*f) = 2 * cos(f) * sin((n-1)*f) - sin((n-2)*f) */ /* 4 samples at a time */ for( k = 0; k < length; k += 4 ) { px_win[ k ] = (SKP_int16)SKP_SMULWB( SKP_RSHIFT( S0_Q16 + S1_Q16, 1 ), px[ k ] ); px_win[ k + 1 ] = (SKP_int16)SKP_SMULWB( S1_Q16, px[ k + 1] ); S0_Q16 = SKP_RSHIFT( SKP_MUL( c_Q20, S1_Q16 ), 20 ) + SKP_LSHIFT( S1_Q16, 1 ) - S0_Q16 + 1; S0_Q16 = SKP_min( S0_Q16, ( 1 << 16 ) ); px_win[ k + 2 ] = (SKP_int16)SKP_SMULWB( SKP_RSHIFT( S0_Q16 + S1_Q16, 1 ), px[ k + 2] ); px_win[ k + 3 ] = (SKP_int16)SKP_SMULWB( S0_Q16, px[ k + 3 ] ); S1_Q16 = SKP_RSHIFT( SKP_MUL( c_Q20, S0_Q16 ), 20 ) + SKP_LSHIFT( S0_Q16, 1 ) - S1_Q16; S1_Q16 = SKP_min( S1_Q16, ( 1 << 16 ) ); } }
/* uses SMLAWB(), requiring armv5E and higher. */ SKP_int32 SKP_Silk_schur( /* O: Returns residual energy */ SKP_int16 *rc_Q15, /* O: reflection coefficients [order] Q15 */ const SKP_int32 *c, /* I: correlations [order+1] */ const SKP_int32 order /* I: prediction order */ ) { SKP_int k, n, lz; SKP_int32 C[ SKP_Silk_MAX_ORDER_LPC + 1 ][ 2 ]; SKP_int32 Ctmp1, Ctmp2, rc_tmp_Q15; /* Get number of leading zeros */ lz = SKP_Silk_CLZ32( c[ 0 ] ); /* Copy correlations and adjust level to Q30 */ if( lz < 2 ) { /* lz must be 1, so shift one to the right */ for( k = 0; k < order + 1; k++ ) { C[ k ][ 0 ] = C[ k ][ 1 ] = SKP_RSHIFT( c[ k ], 1 ); } } else if( lz > 2 ) { /* Shift to the left */ lz -= 2; for( k = 0; k < order + 1; k++ ) { C[ k ][ 0 ] = C[ k ][ 1 ] = SKP_LSHIFT( c[k], lz ); } } else { /* No need to shift */ for( k = 0; k < order + 1; k++ ) { C[ k ][ 0 ] = C[ k ][ 1 ] = c[ k ]; } } for( k = 0; k < order; k++ ) { /* Get reflection coefficient */ rc_tmp_Q15 = -SKP_DIV32_16( C[ k + 1 ][ 0 ], SKP_max_32( SKP_RSHIFT( C[ 0 ][ 1 ], 15 ), 1 ) ); /* Clip (shouldn't happen for properly conditioned inputs) */ rc_tmp_Q15 = SKP_SAT16( rc_tmp_Q15 ); /* Store */ rc_Q15[ k ] = (SKP_int16)rc_tmp_Q15; /* Update correlations */ for( n = 0; n < order - k; n++ ) { Ctmp1 = C[ n + k + 1 ][ 0 ]; Ctmp2 = C[ n ][ 1 ]; C[ n + k + 1 ][ 0 ] = SKP_SMLAWB( Ctmp1, SKP_LSHIFT( Ctmp2, 1 ), rc_tmp_Q15 ); C[ n ][ 1 ] = SKP_SMLAWB( Ctmp2, SKP_LSHIFT( Ctmp1, 1 ), rc_tmp_Q15 ); } } /* return residual energy */ return C[0][1]; }
/* Variable order MA prediction error filter */ void SKP_Silk_MA_Prediction( const SKP_int16 *in, /* I: Input signal */ const SKP_int16 *B, /* I: MA prediction coefficients, Q12 [order] */ SKP_int32 *S, /* I/O: State vector [order] */ SKP_int16 *out, /* O: Output signal */ const SKP_int32 len, /* I: Signal length */ const SKP_int32 order /* I: Filter order */ ) { SKP_int k, d, in16; SKP_int32 out32; SKP_int32 B32; if( ( order & 1 ) == 0 && (SKP_int32)( (SKP_int_ptr_size)B & 3 ) == 0 ) { /* Even order and 4-byte aligned coefficient array */ /* NOTE: the code below loads two int16 values in an int32, and multiplies each using the */ /* SMLABB and SMLABT instructions. On a big-endian CPU the two int16 variables would be */ /* loaded in reverse order and the code will give the wrong result. In that case swapping */ /* the SMLABB and SMLABT instructions should solve the problem. */ for( k = 0; k < len; k++ ) { in16 = in[ k ]; out32 = SKP_LSHIFT( in16, 12 ) - S[ 0 ]; out32 = SKP_RSHIFT_ROUND( out32, 12 ); for( d = 0; d < order - 2; d += 2 ) { B32 = *( (SKP_int32*)&B[ d ] ); /* read two coefficients at once */ S[ d ] = SKP_SMLABB_ovflw( S[ d + 1 ], in16, B32 ); S[ d + 1 ] = SKP_SMLABT_ovflw( S[ d + 2 ], in16, B32 ); } B32 = *( (SKP_int32*)&B[ d ] ); /* read two coefficients at once */ S[ order - 2 ] = SKP_SMLABB_ovflw( S[ order - 1 ], in16, B32 ); S[ order - 1 ] = SKP_SMULBT( in16, B32 ); /* Limit */ out[ k ] = (SKP_int16)SKP_SAT16( out32 ); } } else { /* Odd order or not 4-byte aligned coefficient array */ for( k = 0; k < len; k++ ) { in16 = in[ k ]; out32 = SKP_LSHIFT( in16, 12 ) - S[ 0 ]; out32 = SKP_RSHIFT_ROUND( out32, 12 ); for( d = 0; d < order - 1; d++ ) { S[ d ] = SKP_SMLABB_ovflw( S[ d + 1 ], in16, B[ d ] ); } S[ order - 1 ] = SKP_SMULBB( in16, B[ order - 1 ] ); /* Limit */ out[ k ] = (SKP_int16)SKP_SAT16( out32 ); } } }
/* SKP_Silk_prefilter. Prefilter for finding Quantizer input signal */ SKP_INLINE void SKP_Silk_prefilt_FIX( SKP_Silk_prefilter_state_FIX *P, /* I/O state */ SKP_int32 st_res_Q12[], /* I short term residual signal */ SKP_int16 xw[], /* O prefiltered signal */ SKP_int32 HarmShapeFIRPacked_Q12, /* I Harmonic shaping coeficients */ SKP_int Tilt_Q14, /* I Tilt shaping coeficient */ SKP_int32 LF_shp_Q14, /* I Low-frequancy shaping coeficients*/ SKP_int lag, /* I Lag for harmonic shaping */ SKP_int length /* I Length of signals */ ) { SKP_int i, idx, LTP_shp_buf_idx; SKP_int32 n_LTP_Q12, n_Tilt_Q10, n_LF_Q10; SKP_int32 sLF_MA_shp_Q12, sLF_AR_shp_Q12; SKP_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 */ SKP_assert( HARM_SHAPE_FIR_TAPS == 3 ); idx = lag + LTP_shp_buf_idx; n_LTP_Q12 = SKP_SMULBB( LTP_shp_buf[ ( idx - HARM_SHAPE_FIR_TAPS / 2 - 1) & LTP_MASK ], HarmShapeFIRPacked_Q12 ); n_LTP_Q12 = SKP_SMLABT( n_LTP_Q12, LTP_shp_buf[ ( idx - HARM_SHAPE_FIR_TAPS / 2 ) & LTP_MASK ], HarmShapeFIRPacked_Q12 ); n_LTP_Q12 = SKP_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 = SKP_SMULWB( sLF_AR_shp_Q12, Tilt_Q14 ); n_LF_Q10 = SKP_SMLAWB( SKP_SMULWT( sLF_AR_shp_Q12, LF_shp_Q14 ), sLF_MA_shp_Q12, LF_shp_Q14 ); sLF_AR_shp_Q12 = SKP_SUB32( st_res_Q12[ i ], SKP_LSHIFT( n_Tilt_Q10, 2 ) ); sLF_MA_shp_Q12 = SKP_SUB32( sLF_AR_shp_Q12, SKP_LSHIFT( n_LF_Q10, 2 ) ); LTP_shp_buf_idx = ( LTP_shp_buf_idx - 1 ) & LTP_MASK; LTP_shp_buf[ LTP_shp_buf_idx ] = ( SKP_int16 )SKP_SAT16( SKP_RSHIFT_ROUND( sLF_MA_shp_Q12, 12 ) ); xw[i] = ( SKP_int16 )SKP_SAT16( SKP_RSHIFT_ROUND( SKP_SUB32( sLF_MA_shp_Q12, n_LTP_Q12 ), 12 ) ); } /* 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; }
/* Gains scalar dequantization, uniform on log scale */ void SKP_Silk_gains_dequant( SKP_int32 gain_Q16[ MAX_NB_SUBFR ], /* O quantized gains */ const SKP_int8 ind[ MAX_NB_SUBFR ], /* I gain indices */ SKP_int8 *prev_ind, /* I/O last index in previous frame */ const SKP_int conditional, /* I first gain is delta coded if 1 */ const SKP_int nb_subfr /* I number of subframes */ ) { SKP_int k, ind_tmp, double_step_size_threshold; for( k = 0; k < nb_subfr; k++ ) { if( k == 0 && conditional == 0 ) { *prev_ind = ind[ k ]; } else { /* Delta index */ ind_tmp = ind[ k ] + MIN_DELTA_GAIN_QUANT; /* Accumulate deltas */ double_step_size_threshold = 2 * MAX_DELTA_GAIN_QUANT - N_LEVELS_QGAIN + *prev_ind; if( ind_tmp > double_step_size_threshold ) { *prev_ind += SKP_LSHIFT( ind_tmp, 1 ) - double_step_size_threshold; } else { *prev_ind += ind_tmp; } } /* Convert to linear scale and scale */ gain_Q16[ k ] = SKP_Silk_log2lin( SKP_min_32( SKP_SMULWB( INV_SCALE_Q16, *prev_ind ) + OFFSET, 3967 ) ); /* 3967 = 31 in Q7 */ } }
/* Variable order MA prediction error filter. Inverse filter of SKP_Silk_LPC_synthesis_filter. The inlined assembly makes it over 30% faster than the generic C. */ void SKP_Silk_LPC_analysis_filter( const SKP_int16 *in, /* I: Input signal */ const SKP_int16 *B, /* I: MA prediction coefficients, Q12 [order] */ SKP_int16 *S, /* I/O: State vector [order] */ SKP_int16 *out, /* O: Output signal */ const SKP_int32 len, /* I: Signal length */ const SKP_int32 Order /* I: Filter order */ ) { SKP_int k; SKP_int32 out32_Q12, out32; /* Order must be even */ SKP_assert( 2 * Order_half == Order ); /* S[] values are in Q0 */ for( k = 0; k < len; k++ ) { LPC_ANALYSYS(out32_Q12, S, B, Order); /* Subtract prediction */ out32_Q12 = SKP_SUB_SAT32( SKP_LSHIFT( (SKP_int32)in[ k ], 12 ), out32_Q12 ); /* Scale to Q0 */ out32 = SKP_RSHIFT_ROUND( out32_Q12, 12 ); out[ k ] = (SKP_int16)SKP_SAT16( out32 ); /* Move input line */ S[ 0 ] = in[ k ]; } }
void SKP_Silk_VAD_GetNoiseLevels( const SKP_int32 pX[ VAD_N_BANDS ], /* I subband energies */ SKP_Silk_VAD_state *psSilk_VAD /* I/O Pointer to Silk VAD state */ ) { SKP_int k; SKP_int32 nl, nrg, inv_nrg; SKP_int coef, min_coef; /* Initially faster smoothing */ if( psSilk_VAD->counter < 1000 ) { /* 1000 = 20 sec */ min_coef = SKP_DIV32_16( SKP_int16_MAX, SKP_RSHIFT( psSilk_VAD->counter, 4 ) + 1 ); } else { min_coef = 0; } for( k = 0; k < VAD_N_BANDS; k++ ) { /* Get old noise level estimate for current band */ nl = psSilk_VAD->NL[ k ]; SKP_assert( nl >= 0 ); /* Add bias */ nrg = SKP_ADD_POS_SAT32( pX[ k ], psSilk_VAD->NoiseLevelBias[ k ] ); SKP_assert( nrg > 0 ); /* Invert energies */ inv_nrg = SKP_DIV32( SKP_int32_MAX, nrg ); SKP_assert( inv_nrg >= 0 ); /* Less update when subband energy is high */ if( nrg > SKP_LSHIFT( nl, 3 ) ) { coef = VAD_NOISE_LEVEL_SMOOTH_COEF_Q16 >> 3; } else if( nrg < nl ) {
/* Resamples by a factor 3/1 */ void SKP_Silk_resample_3_1( SKP_int16 *out, /* O: Fs_high signal [inLen*3] */ SKP_int32 *S, /* I/O: State vector [7] */ const SKP_int16 *in, /* I: Fs_low signal [inLen] */ const SKP_int32 inLen /* I: Input length */ ) { SKP_int k, LSubFrameIn, LSubFrameOut; SKP_int32 out_tmp, idx, inLenTmp = inLen; SKP_int32 scratch00[ IN_SUBFR_LEN_RESAMPLE_3_1 ]; SKP_int32 scratch0[ 3 * IN_SUBFR_LEN_RESAMPLE_3_1 ]; SKP_int32 scratch1[ 3 * IN_SUBFR_LEN_RESAMPLE_3_1 ]; /* Coefficients for 3-fold resampling */ const SKP_int16 A30[ 2 ] = { 1773, 17818 }; const SKP_int16 A31[ 2 ] = { 4942, 25677 }; const SKP_int16 A32[ 2 ] = { 11786, 29304 }; while( inLenTmp > 0 ) { LSubFrameIn = SKP_min_int( IN_SUBFR_LEN_RESAMPLE_3_1, inLenTmp ); LSubFrameOut = SKP_SMULBB( 3, LSubFrameIn ); /* Convert Q15 -> Q25 */ for( k = 0; k < LSubFrameIn; k++ ) { scratch00[k] = SKP_LSHIFT( (SKP_int32)in[ k ], 10 ); } /* Allpass filtering */ /* Scratch size: 2 * 3* LSubFrame * sizeof(SKP_int32) */ SKP_Silk_allpass_int( scratch00, S + 1, A30[ 0 ], scratch1, LSubFrameIn ); SKP_Silk_allpass_int( scratch1, S + 2, A30[ 1 ], scratch0, LSubFrameIn ); SKP_Silk_allpass_int( scratch00, S + 3, A31[ 0 ], scratch1, LSubFrameIn ); SKP_Silk_allpass_int( scratch1, S + 4, A31[ 1 ], scratch0 + IN_SUBFR_LEN_RESAMPLE_3_1, LSubFrameIn ); SKP_Silk_allpass_int( scratch00, S + 5, A32[ 0 ], scratch1, LSubFrameIn ); SKP_Silk_allpass_int( scratch1, S + 6, A32[ 1 ], scratch0 + 2 * IN_SUBFR_LEN_RESAMPLE_3_1, LSubFrameIn ); /* Interleave three allpass outputs */ for( k = 0; k < LSubFrameIn; k++ ) { idx = SKP_SMULBB( 3, k ); scratch1[ idx ] = scratch0[ k ]; scratch1[ idx + 1 ] = scratch0[ k + IN_SUBFR_LEN_RESAMPLE_3_1 ]; scratch1[ idx + 2 ] = scratch0[ k + 2 * IN_SUBFR_LEN_RESAMPLE_3_1 ]; } /* Low-pass filtering */ SKP_Silk_lowpass_int( scratch1, S, scratch0, LSubFrameOut ); /* Saturate and convert to SKP_int16 */ for( k = 0; k < LSubFrameOut; k++ ) { out_tmp = scratch0[ k ]; out[ k ] = (SKP_int16) SKP_SAT16( SKP_RSHIFT_ROUND( out_tmp, 10 ) ); } in += LSubFrameIn; inLenTmp -= LSubFrameIn; out += LSubFrameOut; } }
void SKP_Silk_LBRR_embed( SKP_Silk_encoder_state *psEncC, /* I/O Encoder state */ ec_enc *psRangeEnc /* I/O Compressor data structure */ ) { SKP_int i; SKP_int32 LBRR_symbol; /* Encode LBRR flags */ LBRR_symbol = 0; for( i = 0; i < psEncC->nFramesPerPacket; i++ ) { LBRR_symbol |= SKP_LSHIFT( psEncC->LBRR_flags[ i ], i ); } psEncC->LBRR_flag = LBRR_symbol > 0 ? 1 : 0; if( LBRR_symbol && psEncC->nFramesPerPacket > 1 ) { ec_enc_icdf( psRangeEnc, LBRR_symbol - 1, SKP_Silk_LBRR_flags_iCDF_ptr[ psEncC->nFramesPerPacket - 2 ], 8 ); } /* Code indices and excitation signals */ for( i = 0; i < psEncC->nFramesPerPacket; i++ ) { if( psEncC->LBRR_flags[ i ] ) { SKP_Silk_encode_indices( psEncC, psRangeEnc, i, 1 ); SKP_Silk_encode_pulses( psRangeEnc, psEncC->indices_LBRR[i].signalType, psEncC->indices_LBRR[i].quantOffsetType, psEncC->pulses_LBRR[ i ], psEncC->frame_length ); } } }
/* Variable order MA prediction error filter */ void SKP_Silk_MA_Prediction( const SKP_int16 *in, /* I: Input signal */ const SKP_int16 *B, /* I: MA prediction coefficients, Q12 [order] */ SKP_int32 *S, /* I/O: State vector [order] */ SKP_int16 *out, /* O: Output signal */ const SKP_int32 len, /* I: Signal length */ const SKP_int32 order /* I: Filter order */ ) { SKP_int k, d, in16; SKP_int32 out32; for( k = 0; k < len; k++ ) { in16 = in[ k ]; out32 = SKP_LSHIFT( in16, 12 ) - S[ 0 ]; out32 = SKP_RSHIFT_ROUND( out32, 12 ); for( d = 0; d < order - 1; d++ ) { S[ d ] = SKP_SMLABB_ovflw( S[ d + 1 ], in16, B[ d ] ); } S[ order - 1 ] = SKP_SMULBB( in16, B[ order - 1 ] ); /* Limit */ out[ k ] = (SKP_int16)SKP_SAT16( out32 ); } }
/* Decodes signs of excitation */ void SKP_Silk_decode_signs(SKP_Silk_range_coder_state * sRC, /* I/O Range coder state */ int q[], /* I/O pulse signal */ const int length, /* I length of output */ const int sigtype, /* I Signal type */ const int QuantOffsetType, /* I Quantization offset type */ const int RateLevelIndex /* I Rate Level Index */ ) { int i; int data; const uint16_t *cdf; i = SKP_SMULBB(N_RATE_LEVELS - 1, SKP_LSHIFT(sigtype, 1) + QuantOffsetType) + RateLevelIndex; cdf = SKP_Silk_sign_CDF[i]; for (i = 0; i < length; i++) { if (q[i] > 0) { SKP_Silk_range_decoder(&data, sRC, cdf, 1); /* attach sign */ /* implementation with shift, subtraction, multiplication */ q[i] *= SKP_dec_map(data); } } }
/* Encodes signs of excitation */ void SKP_Silk_encode_signs( SKP_Silk_range_coder_state *sRC, /* I/O Range coder state */ const SKP_int8 q[], /* I Pulse signal */ const SKP_int length, /* I Length of input */ const SKP_int sigtype, /* I Signal type */ const SKP_int QuantOffsetType, /* I Quantization offset type */ const SKP_int RateLevelIndex /* I Rate level index */ ) { SKP_int i; SKP_int inData; SKP_uint16 cdf[ 3 ]; i = SKP_SMULBB( N_RATE_LEVELS - 1, SKP_LSHIFT( sigtype, 1 ) + QuantOffsetType ) + RateLevelIndex; cdf[ 0 ] = 0; cdf[ 1 ] = SKP_Silk_sign_CDF[ i ]; cdf[ 2 ] = 65535; for( i = 0; i < length; i++ ) { if( q[ i ] != 0 ) { inData = SKP_enc_map( q[ i ] ); /* - = 0, + = 1 */ SKP_Silk_range_encoder( sRC, inData, cdf ); } } }
/* Processing of gains */ void silk_process_gains_FIX( silk_encoder_state_FIX *psEnc, /* I/O Encoder state_FIX */ silk_encoder_control_FIX *psEncCtrl /* I/O Encoder control_FIX */ ) { 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 * SKP_sigmoid( 0.25f * ( psEncCtrl->LTPredCodGain - 12.0f ) ); */ s_Q16 = -silk_sigm_Q15( SKP_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 ] = SKP_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 = SKP_DIV32_16( silk_log2lin( SKP_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 = SKP_SMULWW( ResNrg, InvMaxSqrVal_Q16 ); if( psEncCtrl->ResNrgQ[ k ] > 0 ) { ResNrgPart = SKP_RSHIFT_ROUND( ResNrgPart, psEncCtrl->ResNrgQ[ k ] ); } else { if( ResNrgPart >= SKP_RSHIFT( SKP_int32_MAX, -psEncCtrl->ResNrgQ[ k ] ) ) { ResNrgPart = SKP_int32_MAX; } else { ResNrgPart = SKP_LSHIFT( ResNrgPart, -psEncCtrl->ResNrgQ[ k ] ); } } gain = psEncCtrl->Gains_Q16[ k ]; gain_squared = SKP_ADD_SAT32( ResNrgPart, SKP_SMMUL( gain, gain ) ); if( gain_squared < SKP_int16_MAX ) { /* recalculate with higher precision */ gain_squared = SKP_SMLAWW( SKP_LSHIFT( ResNrgPart, 16 ), gain, gain ); SKP_assert( gain_squared > 0 ); gain = silk_SQRT_APPROX( gain_squared ); /* Q8 */ gain = SKP_min( gain, SKP_int32_MAX >> 8 ); psEncCtrl->Gains_Q16[ k ] = SKP_LSHIFT_SAT32( gain, 8 ); /* Q16 */ } else {
/* 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 SKP_LSHIFT( 31 - lz, 7 ) + SKP_SMLAWB( frac_Q7, SKP_MUL( frac_Q7, 128 - frac_Q7 ), 179 ); }
/* Compute weighted quantization errors for an LPC_order element input vector, over one codebook stage */ void SKP_Silk_NLSF_VQ_sum_error_FIX(int32_t * err_Q20, /* O Weighted quantization errors [N*K] */ const int *in_Q15, /* I Input vectors to be quantized [N*LPC_order] */ const int *w_Q6, /* I Weighting vectors [N*LPC_order] */ const int16_t * pCB_Q15, /* I Codebook vectors [K*LPC_order] */ const int N, /* I Number of input vectors */ const int K, /* I Number of codebook vectors */ const int LPC_order /* I Number of LPCs */ ) { int i, n, m; int32_t diff_Q15, sum_error, Wtmp_Q6; int32_t Wcpy_Q6[MAX_LPC_ORDER / 2]; const int16_t *cb_vec_Q15; assert(LPC_order <= 16); assert((LPC_order & 1) == 0); memzero(Wcpy_Q6, (MAX_LPC_ORDER / 2) * sizeof(int32_t)); /* Copy to local stack and pack two weights per int32 */ for (m = 0; m < SKP_RSHIFT(LPC_order, 1); m++) { Wcpy_Q6[m] = w_Q6[2 * m] | SKP_LSHIFT((int32_t) w_Q6[2 * m + 1], 16); } /* Loop over input vectors */ for (n = 0; n < N; n++) { /* Loop over codebook */ cb_vec_Q15 = pCB_Q15; for (i = 0; i < K; i++) { sum_error = 0; for (m = 0; m < LPC_order; m += 2) { /* Get two weights packed in an int32 */ Wtmp_Q6 = Wcpy_Q6[SKP_RSHIFT(m, 1)]; /* Compute weighted squared quantization error for index m */ diff_Q15 = in_Q15[m] - *cb_vec_Q15++; // range: [ -32767 : 32767 ] sum_error = SKP_SMLAWB(sum_error, SKP_SMULBB(diff_Q15, diff_Q15), Wtmp_Q6); /* Compute weighted squared quantization error for index m + 1 */ diff_Q15 = in_Q15[m + 1] - *cb_vec_Q15++; // range: [ -32767 : 32767 ] sum_error = SKP_SMLAWT(sum_error, SKP_SMULBB(diff_Q15, diff_Q15), Wtmp_Q6); } assert(sum_error >= 0); err_Q20[i] = sum_error; } err_Q20 += K; in_Q15 += LPC_order; } }
/* Step up function, converts reflection coefficients to prediction coefficients */ void SKP_Silk_k2a( SKP_int32 *A_Q24, /* O: Prediction coefficients [order] Q24 */ const SKP_int16 *rc_Q15, /* I: Reflection coefficients [order] Q15 */ const SKP_int32 order /* I: Prediction order */ ) { SKP_int k, n; SKP_int32 Atmp[ SKP_Silk_MAX_ORDER_LPC ]; for( k = 0; k < order; k++ ) { for( n = 0; n < k; n++ ) { Atmp[ n ] = A_Q24[ n ]; } for( n = 0; n < k; n++ ) { A_Q24[ n ] = SKP_SMLAWB( A_Q24[ n ], SKP_LSHIFT( Atmp[ k - n - 1 ], 1 ), rc_Q15[ k ] ); } A_Q24[ k ] = -SKP_LSHIFT( (SKP_int32)rc_Q15[ k ], 9 ); } }
/* Glues concealed frames with new good recieved frames */ void SKP_Silk_PLC_glue_frames( SKP_Silk_decoder_state *psDec, /* I/O decoder state */ SKP_Silk_decoder_control *psDecCtrl, /* I/O Decoder control */ SKP_int16 signal[], /* I/O signal */ SKP_int length /* I length of residual */ ) { SKP_int i, energy_shift; SKP_int32 energy; SKP_Silk_PLC_struct *psPLC; psPLC = &psDec->sPLC; if( psDec->lossCnt ) { /* Calculate energy in concealed residual */ SKP_Silk_sum_sqr_shift( &psPLC->conc_energy, &psPLC->conc_energy_shift, signal, length ); psPLC->last_frame_lost = 1; } else { if( psDec->sPLC.last_frame_lost ) { /* Calculate residual in decoded signal if last frame was lost */ SKP_Silk_sum_sqr_shift( &energy, &energy_shift, signal, length ); /* Normalize energies */ if( energy_shift > psPLC->conc_energy_shift ) { psPLC->conc_energy = SKP_RSHIFT( psPLC->conc_energy, energy_shift - psPLC->conc_energy_shift ); } else if( energy_shift < psPLC->conc_energy_shift ) { energy = SKP_RSHIFT( energy, psPLC->conc_energy_shift - energy_shift ); } /* Fade in the energy difference */ if( energy > psPLC->conc_energy ) { SKP_int32 frac_Q24, LZ; SKP_int32 gain_Q12, slope_Q12; LZ = SKP_Silk_CLZ32( psPLC->conc_energy ); LZ = LZ - 1; psPLC->conc_energy = SKP_LSHIFT( psPLC->conc_energy, LZ ); energy = SKP_RSHIFT( energy, SKP_max_32( 24 - LZ, 0 ) ); frac_Q24 = SKP_DIV32( psPLC->conc_energy, SKP_max( energy, 1 ) ); gain_Q12 = SKP_Silk_SQRT_APPROX( frac_Q24 ); slope_Q12 = SKP_DIV32_16( ( 1 << 12 ) - gain_Q12, length ); for( i = 0; i < length; i++ ) { signal[ i ] = SKP_RSHIFT( SKP_MUL( gain_Q12, signal[ i ] ), 12 ); gain_Q12 += slope_Q12; gain_Q12 = SKP_min( gain_Q12, ( 1 << 12 ) ); } } } psPLC->last_frame_lost = 0; } }
void SKP_Silk_shell_insertion_sort_increasing( SKP_int32 *a, /* I/O: Unsorted / Sorted vector */ SKP_int *index, /* O: Index vector for the sorted elements */ const SKP_int L, /* I: Vector length */ const SKP_int K /* I: Number of correctly sorted positions */ ) { SKP_int32 value, inc_Q16_tmp; SKP_int i, j, inc, idx; /* Safety checks */ SKP_assert( K > 0 ); SKP_assert( L > 0 ); SKP_assert( L >= K ); /* Calculate initial step size */ inc_Q16_tmp = SKP_LSHIFT( (SKP_int32)L, 15 ); inc = SKP_RSHIFT( inc_Q16_tmp, 16 ); /* Write start indices in index vector */ for( i = 0; i < K; i++ ) { index[ i ] = i; } /* Shell sort first values */ while( inc > 0 ) { for( i = inc; i < K; i++ ) { value = a[ i ]; idx = index[ i ]; for( j = i - inc; ( j >= 0 ) && ( value < a[ j ] ); j -= inc ) { a[ j + inc ] = a[ j ]; /* Shift value */ index[ j + inc ] = index[ j ]; /* Shift index */ } a[ j + inc ] = value; /* Write value */ index[ j + inc ] = idx; /* Write index */ } inc_Q16_tmp = SKP_SMULWB( inc_Q16_tmp, 29789 ); // 29789_Q16 = 2.2^(-1)_Q0 inc = SKP_RSHIFT_ROUND( inc_Q16_tmp, 16 ); } /* If less than L values are asked for, check the remaining values, */ /* but only spend CPU to ensure that the K first values are correct */ /* Insertion sort remaining values */ for( i = K; i < L; i++ ) { value = a[ i ]; if( value < a[ K - 1 ] ) { for( j = K - 2; ( j >= 0 ) && ( value < a[ j ] ); j-- ) { a[ j + 1 ] = a[ j ]; /* Shift value */ index[ j + 1 ] = index[ j ]; /* Shift index */ } a[ j + 1 ] = value; /* Write value */ index[ j + 1 ] = i; /* Write index */ } } }
/* Compute autocorrelation */ void SKP_Silk_autocorr( SKP_int32 *results, /* O Result (length correlationCount) */ SKP_int *scale, /* O Scaling of the correlation vector */ const SKP_int16 *inputData, /* I Input data to correlate */ const SKP_int inputDataSize, /* I Length of input */ const SKP_int correlationCount /* I Number of correlation taps to compute */ ) { SKP_int i, lz, nRightShifts, corrCount; SKP_int64 corr64; corrCount = SKP_min_int( inputDataSize, correlationCount ); /* compute energy (zero-lag correlation) */ corr64 = SKP_Silk_inner_prod16_aligned_64( inputData, inputData, inputDataSize ); /* deal with all-zero input data */ corr64 += 1; /* number of leading zeros */ lz = SKP_Silk_CLZ64( corr64 ); /* scaling: number of right shifts applied to correlations */ nRightShifts = 35 - lz; *scale = nRightShifts; if( nRightShifts <= 0 ) { results[ 0 ] = SKP_LSHIFT( (SKP_int32)SKP_CHECK_FIT32( corr64 ), -nRightShifts ); /* compute remaining correlations based on int32 inner product */ for( i = 1; i < corrCount; i++ ) { results[ i ] = SKP_LSHIFT( SKP_Silk_inner_prod_aligned( inputData, inputData + i, inputDataSize - i ), -nRightShifts ); } } else { results[ 0 ] = (SKP_int32)SKP_CHECK_FIT32( SKP_RSHIFT64( corr64, nRightShifts ) ); /* compute remaining correlations based on int64 inner product */ for( i = 1; i < corrCount; i++ ) { results[ i ] = (SKP_int32)SKP_CHECK_FIT32( SKP_RSHIFT64( SKP_Silk_inner_prod16_aligned_64( inputData, inputData + i, inputDataSize - i ), nRightShifts ) ); } } }
/* Control SNR of redidual quantizer */ SKP_int silk_control_SNR( silk_encoder_state *psEncC, /* I/O Pointer to Silk encoder state */ SKP_int32 TargetRate_bps /* I Target max bitrate (bps) */ ) { SKP_int k, ret = SILK_NO_ERROR; SKP_int32 frac_Q6; const SKP_int32 *rateTable; /* Set bitrate/coding quality */ TargetRate_bps = SKP_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 = SKP_DIV32( SKP_LSHIFT( TargetRate_bps - rateTable[ k - 1 ], 6 ), rateTable[ k ] - rateTable[ k - 1 ] ); psEncC->SNR_dB_Q7 = SKP_LSHIFT( silk_SNR_table_Q1[ k - 1 ], 6 ) + SKP_MUL( frac_Q6, silk_SNR_table_Q1[ k ] - silk_SNR_table_Q1[ k - 1 ] ); break; } } } return ret; }
/* Uses SMULL(), available on armv4 */ SKP_int32 SKP_Silk_schur64( /* O: Returns residual energy */ SKP_int32 rc_Q16[], /* O: Reflection coefficients [order] Q16 */ const SKP_int32 c[], /* I: Correlations [order+1] */ SKP_int32 order /* I: Prediction order */ ) { SKP_int k, n; SKP_int32 C[ SKP_Silk_MAX_ORDER_LPC + 1 ][ 2 ]; SKP_int32 Ctmp1_Q30, Ctmp2_Q30, rc_tmp_Q31; /* Check for invalid input */ if( c[ 0 ] <= 0 ) { SKP_memset( rc_Q16, 0, order * sizeof( SKP_int32 ) ); return 0; } for( k = 0; k < order + 1; k++ ) { C[ k ][ 0 ] = C[ k ][ 1 ] = c[ k ]; } for( k = 0; k < order; k++ ) { /* Get reflection coefficient: divide two Q30 values and get result in Q31 */ rc_tmp_Q31 = SKP_DIV32_varQ( -C[ k + 1 ][ 0 ], C[ 0 ][ 1 ], 31 ); /* Save the output */ rc_Q16[ k ] = SKP_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 + SKP_SMMUL( SKP_LSHIFT( Ctmp2_Q30, 1 ), rc_tmp_Q31 ); C[ n ][ 1 ] = Ctmp2_Q30 + SKP_SMMUL( SKP_LSHIFT( Ctmp1_Q30, 1 ), rc_tmp_Q31 ); } } return( C[ 0 ][ 1 ] ); }
void SKP_Silk_noise_shape_analysis_FIX( SKP_Silk_encoder_state_FIX *psEnc, /* I/O Encoder state FIX */ SKP_Silk_encoder_control_FIX *psEncCtrl, /* I/O Encoder control FIX */ const SKP_int16 *pitch_res, /* I LPC residual from pitch analysis */ const SKP_int16 *x /* I Input signal [ frame_length + la_shape ] */ ) { SKP_Silk_shape_state_FIX *psShapeSt = &psEnc->sShape; SKP_int k, i, nSamples, Qnrg, b_Q14, warping_Q16, scale = 0; SKP_int32 SNR_adj_dB_Q7, HarmBoost_Q16, HarmShapeGain_Q16, Tilt_Q16, tmp32; SKP_int32 nrg, pre_nrg_Q30, log_energy_Q7, log_energy_prev_Q7, energy_variation_Q7; SKP_int32 delta_Q16, BWExp1_Q16, BWExp2_Q16, gain_mult_Q16, gain_add_Q16, strength_Q16, b_Q8; SKP_int32 auto_corr[ MAX_SHAPE_LPC_ORDER + 1 ]; SKP_int32 refl_coef_Q16[ MAX_SHAPE_LPC_ORDER ]; SKP_int32 AR1_Q24[ MAX_SHAPE_LPC_ORDER ]; SKP_int32 AR2_Q24[ MAX_SHAPE_LPC_ORDER ]; SKP_int16 x_windowed[ SHAPE_LPC_WIN_MAX ]; SKP_int32 sqrt_nrg[ MAX_NB_SUBFR ], Qnrg_vec[ MAX_NB_SUBFR ]; const SKP_int16 *x_ptr, *pitch_res_ptr; /* Point to start of first LPC analysis block */ x_ptr = x - psEnc->sCmn.la_shape; /****************/ /* CONTROL SNR */ /****************/ /* Reduce SNR_dB values if recent bitstream has exceeded TargetRate */ psEncCtrl->current_SNR_dB_Q7 = psEnc->SNR_dB_Q7 - SKP_SMULBB( psEnc->BufferedInChannel_ms, SKP_FIX_CONST( 0.1, 7 ) ); /* Reduce SNR_dB because of any inband FEC used */ psEncCtrl->current_SNR_dB_Q7 -= psEnc->inBandFEC_SNR_comp_Q7; /****************/ /* GAIN CONTROL */ /****************/ /* Input quality is the average of the quality in the lowest two VAD bands */ psEncCtrl->input_quality_Q14 = ( SKP_int )SKP_RSHIFT( ( SKP_int32 )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 = SKP_RSHIFT( SKP_Silk_sigm_Q15( SKP_RSHIFT_ROUND( psEncCtrl->current_SNR_dB_Q7 - SKP_FIX_CONST( 18.0, 7 ), 4 ) ), 1 ); /* Reduce coding SNR during low speech activity */ SNR_adj_dB_Q7 = psEncCtrl->current_SNR_dB_Q7; if( psEnc->sCmn.useCBR == 0 ) { b_Q8 = SKP_FIX_CONST( 1.0, 8 ) - psEnc->sCmn.speech_activity_Q8; b_Q8 = SKP_SMULWB( SKP_LSHIFT( b_Q8, 8 ), b_Q8 ); SNR_adj_dB_Q7 = SKP_SMLAWB( SNR_adj_dB_Q7, SKP_SMULBB( SKP_FIX_CONST( -BG_SNR_DECR_dB, 7 ) >> ( 4 + 1 ), b_Q8 ), // Q11 SKP_SMULWB( SKP_FIX_CONST( 1.0, 14 ) + psEncCtrl->input_quality_Q14, psEncCtrl->coding_quality_Q14 ) ); // Q12 }
/* Gain scalar quantization with hysteresis, uniform on log scale */ void SKP_Silk_gains_quant( SKP_int8 ind[ MAX_NB_SUBFR ], /* O gain indices */ SKP_int32 gain_Q16[ MAX_NB_SUBFR ], /* I/O gains (quantized out) */ SKP_int8 *prev_ind, /* I/O last index in previous frame */ const SKP_int conditional, /* I first gain is delta coded if 1 */ const SKP_int nb_subfr /* I number of subframes */ ) { SKP_int k, double_step_size_threshold; for( k = 0; k < nb_subfr; k++ ) { /* Add half of previous quantization error, convert to log scale, scale, floor() */ ind[ k ] = SKP_SMULWB( SCALE_Q16, SKP_Silk_lin2log( gain_Q16[ k ] ) - OFFSET ); /* Round towards previous quantized gain (hysteresis) */ if( ind[ k ] < *prev_ind ) { ind[ k ]++; } ind[ k ] = SKP_max_int( ind[ k ], 0 ); /* Compute delta indices and limit */ if( k == 0 && conditional == 0 ) { /* Full index */ ind[ k ] = SKP_LIMIT_int( ind[ k ], *prev_ind + MIN_DELTA_GAIN_QUANT, N_LEVELS_QGAIN - 1 ); *prev_ind = ind[ k ]; } else { /* Delta index */ ind[ k ] = ind[ k ] - *prev_ind; /* Double the quantization step size for large gain increases, so that the max gain level can be reached */ double_step_size_threshold = 2 * MAX_DELTA_GAIN_QUANT - N_LEVELS_QGAIN + *prev_ind; if( ind[ k ] > double_step_size_threshold ) { ind[ k ] = double_step_size_threshold + SKP_RSHIFT( ind[ k ] - double_step_size_threshold + 1, 1 ); } ind[ k ] = SKP_LIMIT_int( ind[ k ], MIN_DELTA_GAIN_QUANT, MAX_DELTA_GAIN_QUANT ); /* Accumulate deltas */ if( ind[ k ] > double_step_size_threshold ) { *prev_ind += SKP_LSHIFT( ind[ k ], 1 ) - double_step_size_threshold; } else { *prev_ind += ind[ k ]; } /* Shift to make non-negative */ ind[ k ] -= MIN_DELTA_GAIN_QUANT; } /* Convert to linear scale and scale */ gain_Q16[ k ] = SKP_Silk_log2lin( SKP_min_32( SKP_SMULWB( INV_SCALE_Q16, *prev_ind ) + OFFSET, 3967 ) ); /* 3967 = 31 in Q7 */ } }