Update opus from 1.1 to 1.1.4

Define FLOAT_APPROX in Makefile and misc/msvc12/quake3.vcxproj.
This commit is contained in:
Zack Middleton committed 2017-05-23 11:47:26 -05:00
1 parent 67bfe8f8d6
commit 853110d5d4
146 files changed
+11917 -2109

No files matched your search

+17 -2
View File
@@ -71,8 +71,23 @@ static OPUS_INLINE opus_int32 silk_A2NLSF_eval_poly( /* return the polynomial ev
y32 = p[ dd ]; /* Q16 */
x_Q16 = silk_LSHIFT( x, 4 );
for( n = dd - 1; n >= 0; n-- ) {
y32 = silk_SMLAWW( p[ n ], y32, x_Q16 ); /* Q16 */
if ( opus_likely( 8 == dd ) )
{
y32 = silk_SMLAWW( p[ 7 ], y32, x_Q16 );
y32 = silk_SMLAWW( p[ 6 ], y32, x_Q16 );
y32 = silk_SMLAWW( p[ 5 ], y32, x_Q16 );
y32 = silk_SMLAWW( p[ 4 ], y32, x_Q16 );
y32 = silk_SMLAWW( p[ 3 ], y32, x_Q16 );
y32 = silk_SMLAWW( p[ 2 ], y32, x_Q16 );
y32 = silk_SMLAWW( p[ 1 ], y32, x_Q16 );
y32 = silk_SMLAWW( p[ 0 ], y32, x_Q16 );
}
else
{
for( n = dd - 1; n >= 0; n-- ) {
y32 = silk_SMLAWW( p[ n ], y32, x_Q16 ); /* Q16 */
}
}
return y32;
}
+2 -1
View File
@@ -111,7 +111,8 @@ opus_int silk_Decode( /* O Returns error co
opus_int newPacketFlag, /* I Indicates first decoder call for this packet */
ec_dec *psRangeDec, /* I/O Compressor data structure */
opus_int16 *samplesOut, /* O Decoded output speech vector */
opus_int32 *nSamplesOut /* O Number of samples decoded */
opus_int32 *nSamplesOut, /* O Number of samples decoded */
int arch /* I Run-time architecture */
);
#if 0
+42 -30
View File
@@ -34,9 +34,8 @@ POSSIBILITY OF SUCH DAMAGE.
/* Generates excitation for CNG LPC synthesis */
static OPUS_INLINE void silk_CNG_exc(
opus_int32 residual_Q10[], /* O CNG residual signal Q10 */
opus_int32 exc_Q14[], /* O CNG excitation signal Q10 */
opus_int32 exc_buf_Q14[], /* I Random samples buffer Q10 */
opus_int32 Gain_Q16, /* I Gain to apply */
opus_int length, /* I Length */
opus_int32 *rand_seed /* I/O Seed to random index generator */
)
@@ -55,7 +54,7 @@ static OPUS_INLINE void silk_CNG_exc(
idx = (opus_int)( silk_RSHIFT( seed, 24 ) & exc_mask );
silk_assert( idx >= 0 );
silk_assert( idx <= CNG_BUF_MASK_MAX );
residual_Q10[ i ] = (opus_int16)silk_SAT16( silk_SMULWW( exc_buf_Q14[ idx ], Gain_Q16 >> 4 ) );
exc_Q14[ i ] = exc_buf_Q14[ idx ];
}
*rand_seed = seed;
}
@@ -85,7 +84,7 @@ void silk_CNG(
)
{
opus_int i, subfr;
opus_int32 sum_Q6, max_Gain_Q16;
opus_int32 LPC_pred_Q10, max_Gain_Q16, gain_Q16, gain_Q10;
opus_int16 A_Q12[ MAX_LPC_ORDER ];
silk_CNG_struct *psCNG = &psDec->sCNG;
SAVE_STACK;
@@ -124,47 +123,60 @@ void silk_CNG(
/* Add CNG when packet is lost or during DTX */
if( psDec->lossCnt ) {
VARDECL( opus_int32, CNG_sig_Q10 );
ALLOC( CNG_sig_Q10, length + MAX_LPC_ORDER, opus_int32 );
VARDECL( opus_int32, CNG_sig_Q14 );
ALLOC( CNG_sig_Q14, length + MAX_LPC_ORDER, opus_int32 );
/* Generate CNG excitation */
silk_CNG_exc( CNG_sig_Q10 + MAX_LPC_ORDER, psCNG->CNG_exc_buf_Q14, psCNG->CNG_smth_Gain_Q16, length, &psCNG->rand_seed );
gain_Q16 = silk_SMULWW( psDec->sPLC.randScale_Q14, psDec->sPLC.prevGain_Q16[1] );
if( gain_Q16 >= (1 << 21) || psCNG->CNG_smth_Gain_Q16 > (1 << 23) ) {
gain_Q16 = silk_SMULTT( gain_Q16, gain_Q16 );
gain_Q16 = silk_SUB_LSHIFT32(silk_SMULTT( psCNG->CNG_smth_Gain_Q16, psCNG->CNG_smth_Gain_Q16 ), gain_Q16, 5 );
gain_Q16 = silk_LSHIFT32( silk_SQRT_APPROX( gain_Q16 ), 16 );
} else {
gain_Q16 = silk_SMULWW( gain_Q16, gain_Q16 );
gain_Q16 = silk_SUB_LSHIFT32(silk_SMULWW( psCNG->CNG_smth_Gain_Q16, psCNG->CNG_smth_Gain_Q16 ), gain_Q16, 5 );
gain_Q16 = silk_LSHIFT32( silk_SQRT_APPROX( gain_Q16 ), 8 );
}
gain_Q10 = silk_RSHIFT( gain_Q16, 6 );
silk_CNG_exc( CNG_sig_Q14 + MAX_LPC_ORDER, psCNG->CNG_exc_buf_Q14, length, &psCNG->rand_seed );
/* Convert CNG NLSF to filter representation */
silk_NLSF2A( A_Q12, psCNG->CNG_smth_NLSF_Q15, psDec->LPC_order );
/* Generate CNG signal, by synthesis filtering */
silk_memcpy( CNG_sig_Q10, psCNG->CNG_synth_state, MAX_LPC_ORDER * sizeof( opus_int32 ) );
silk_memcpy( CNG_sig_Q14, psCNG->CNG_synth_state, MAX_LPC_ORDER * sizeof( opus_int32 ) );
for( i = 0; i < length; i++ ) {
silk_assert( psDec->LPC_order == 10 || psDec->LPC_order == 16 );
/* Avoids introducing a bias because silk_SMLAWB() always rounds to -inf */
sum_Q6 = silk_RSHIFT( psDec->LPC_order, 1 );
sum_Q6 = silk_SMLAWB( sum_Q6, CNG_sig_Q10[ MAX_LPC_ORDER + i - 1 ], A_Q12[ 0 ] );
sum_Q6 = silk_SMLAWB( sum_Q6, CNG_sig_Q10[ MAX_LPC_ORDER + i - 2 ], A_Q12[ 1 ] );
sum_Q6 = silk_SMLAWB( sum_Q6, CNG_sig_Q10[ MAX_LPC_ORDER + i - 3 ], A_Q12[ 2 ] );
sum_Q6 = silk_SMLAWB( sum_Q6, CNG_sig_Q10[ MAX_LPC_ORDER + i - 4 ], A_Q12[ 3 ] );
sum_Q6 = silk_SMLAWB( sum_Q6, CNG_sig_Q10[ MAX_LPC_ORDER + i - 5 ], A_Q12[ 4 ] );
sum_Q6 = silk_SMLAWB( sum_Q6, CNG_sig_Q10[ MAX_LPC_ORDER + i - 6 ], A_Q12[ 5 ] );
sum_Q6 = silk_SMLAWB( sum_Q6, CNG_sig_Q10[ MAX_LPC_ORDER + i - 7 ], A_Q12[ 6 ] );
sum_Q6 = silk_SMLAWB( sum_Q6, CNG_sig_Q10[ MAX_LPC_ORDER + i - 8 ], A_Q12[ 7 ] );
sum_Q6 = silk_SMLAWB( sum_Q6, CNG_sig_Q10[ MAX_LPC_ORDER + i - 9 ], A_Q12[ 8 ] );
sum_Q6 = silk_SMLAWB( sum_Q6, CNG_sig_Q10[ MAX_LPC_ORDER + i - 10 ], A_Q12[ 9 ] );
LPC_pred_Q10 = silk_RSHIFT( psDec->LPC_order, 1 );
LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, CNG_sig_Q14[ MAX_LPC_ORDER + i - 1 ], A_Q12[ 0 ] );
LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, CNG_sig_Q14[ MAX_LPC_ORDER + i - 2 ], A_Q12[ 1 ] );
LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, CNG_sig_Q14[ MAX_LPC_ORDER + i - 3 ], A_Q12[ 2 ] );
LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, CNG_sig_Q14[ MAX_LPC_ORDER + i - 4 ], A_Q12[ 3 ] );
LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, CNG_sig_Q14[ MAX_LPC_ORDER + i - 5 ], A_Q12[ 4 ] );
LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, CNG_sig_Q14[ MAX_LPC_ORDER + i - 6 ], A_Q12[ 5 ] );
LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, CNG_sig_Q14[ MAX_LPC_ORDER + i - 7 ], A_Q12[ 6 ] );
LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, CNG_sig_Q14[ MAX_LPC_ORDER + i - 8 ], A_Q12[ 7 ] );
LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, CNG_sig_Q14[ MAX_LPC_ORDER + i - 9 ], A_Q12[ 8 ] );
LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, CNG_sig_Q14[ MAX_LPC_ORDER + i - 10 ], A_Q12[ 9 ] );
if( psDec->LPC_order == 16 ) {
sum_Q6 = silk_SMLAWB( sum_Q6, CNG_sig_Q10[ MAX_LPC_ORDER + i - 11 ], A_Q12[ 10 ] );
sum_Q6 = silk_SMLAWB( sum_Q6, CNG_sig_Q10[ MAX_LPC_ORDER + i - 12 ], A_Q12[ 11 ] );
sum_Q6 = silk_SMLAWB( sum_Q6, CNG_sig_Q10[ MAX_LPC_ORDER + i - 13 ], A_Q12[ 12 ] );
sum_Q6 = silk_SMLAWB( sum_Q6, CNG_sig_Q10[ MAX_LPC_ORDER + i - 14 ], A_Q12[ 13 ] );
sum_Q6 = silk_SMLAWB( sum_Q6, CNG_sig_Q10[ MAX_LPC_ORDER + i - 15 ], A_Q12[ 14 ] );
sum_Q6 = silk_SMLAWB( sum_Q6, CNG_sig_Q10[ MAX_LPC_ORDER + i - 16 ], A_Q12[ 15 ] );
LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, CNG_sig_Q14[ MAX_LPC_ORDER + i - 11 ], A_Q12[ 10 ] );
LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, CNG_sig_Q14[ MAX_LPC_ORDER + i - 12 ], A_Q12[ 11 ] );
LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, CNG_sig_Q14[ MAX_LPC_ORDER + i - 13 ], A_Q12[ 12 ] );
LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, CNG_sig_Q14[ MAX_LPC_ORDER + i - 14 ], A_Q12[ 13 ] );
LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, CNG_sig_Q14[ MAX_LPC_ORDER + i - 15 ], A_Q12[ 14 ] );
LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, CNG_sig_Q14[ MAX_LPC_ORDER + i - 16 ], A_Q12[ 15 ] );
}
/* Update states */
CNG_sig_Q10[ MAX_LPC_ORDER + i ] = silk_ADD_LSHIFT( CNG_sig_Q10[ MAX_LPC_ORDER + i ], sum_Q6, 4 );
frame[ i ] = silk_ADD_SAT16( frame[ i ], silk_RSHIFT_ROUND( sum_Q6, 6 ) );
CNG_sig_Q14[ MAX_LPC_ORDER + i ] = silk_ADD_LSHIFT( CNG_sig_Q14[ MAX_LPC_ORDER + i ], LPC_pred_Q10, 4 );
/* Scale with Gain and add to input signal */
frame[ i ] = (opus_int16)silk_ADD_SAT16( frame[ i ], silk_SAT16( silk_RSHIFT_ROUND( silk_SMULWW( CNG_sig_Q14[ MAX_LPC_ORDER + i ], gain_Q10 ), 8 ) ) );
}
silk_memcpy( psCNG->CNG_synth_state, &CNG_sig_Q10[ length ], MAX_LPC_ORDER * sizeof( opus_int32 ) );
silk_memcpy( psCNG->CNG_synth_state, &CNG_sig_Q14[ length ], MAX_LPC_ORDER * sizeof( opus_int32 ) );
} else {
silk_memset( psCNG->CNG_synth_state, 0, psDec->LPC_order * sizeof( opus_int32 ) );
}
+4 -2
View File
@@ -44,7 +44,8 @@ void silk_LPC_analysis_filter(
const opus_int16 *in, /* I Input signal */
const opus_int16 *B, /* I MA prediction coefficients, Q12 [order] */
const opus_int32 len, /* I Signal length */
const opus_int32 d /* I Filter order */
const opus_int32 d, /* I Filter order */
int arch /* I Run-time architecture */
)
{
opus_int j;
@@ -69,11 +70,12 @@ void silk_LPC_analysis_filter(
for (j=0;j<d;j++) {
mem[ j ] = in[ d - j - 1 ];
}
celt_fir( in + d, num, out + d, len - d, d, mem );
celt_fir( in + d, num, out + d, len - d, d, mem, arch );
for ( j = 0; j < d; j++ ) {
out[ j ] = 0;
}
#else
(void)arch;
for( ix = d; ix < len; ix++ ) {
in_ptr = &in[ ix - 1 ];
+30 -20
View File
@@ -46,8 +46,9 @@ opus_int32 silk_NLSF_del_dec_quant( /* O Returns
)
{
opus_int i, j, nStates, ind_tmp, ind_min_max, ind_max_min, in_Q10, res_Q10;
opus_int pred_Q10, diff_Q10, out0_Q10, out1_Q10, rate0_Q5, rate1_Q5;
opus_int32 RD_tmp_Q25, min_Q25, min_max_Q25, max_min_Q25, pred_coef_Q16;
opus_int pred_Q10, diff_Q10, rate0_Q5, rate1_Q5;
opus_int16 out0_Q10, out1_Q10;
opus_int32 RD_tmp_Q25, min_Q25, min_max_Q25, max_min_Q25;
opus_int ind_sort[ NLSF_QUANT_DEL_DEC_STATES ];
opus_int8 ind[ NLSF_QUANT_DEL_DEC_STATES ][ MAX_LPC_ORDER ];
opus_int16 prev_out_Q10[ 2 * NLSF_QUANT_DEL_DEC_STATES ];
@@ -56,6 +57,28 @@ opus_int32 silk_NLSF_del_dec_quant( /* O Returns
opus_int32 RD_max_Q25[ NLSF_QUANT_DEL_DEC_STATES ];
const opus_uint8 *rates_Q5;
opus_int out0_Q10_table[2 * NLSF_QUANT_MAX_AMPLITUDE_EXT];
opus_int out1_Q10_table[2 * NLSF_QUANT_MAX_AMPLITUDE_EXT];
for (i = -NLSF_QUANT_MAX_AMPLITUDE_EXT; i <= NLSF_QUANT_MAX_AMPLITUDE_EXT-1; i++)
{
out0_Q10 = silk_LSHIFT( i, 10 );
out1_Q10 = silk_ADD16( out0_Q10, 1024 );
if( i > 0 ) {
out0_Q10 = silk_SUB16( out0_Q10, SILK_FIX_CONST( NLSF_QUANT_LEVEL_ADJ, 10 ) );
out1_Q10 = silk_SUB16( out1_Q10, SILK_FIX_CONST( NLSF_QUANT_LEVEL_ADJ, 10 ) );
} else if( i == 0 ) {
out1_Q10 = silk_SUB16( out1_Q10, SILK_FIX_CONST( NLSF_QUANT_LEVEL_ADJ, 10 ) );
} else if( i == -1 ) {
out0_Q10 = silk_ADD16( out0_Q10, SILK_FIX_CONST( NLSF_QUANT_LEVEL_ADJ, 10 ) );
} else {
out0_Q10 = silk_ADD16( out0_Q10, SILK_FIX_CONST( NLSF_QUANT_LEVEL_ADJ, 10 ) );
out1_Q10 = silk_ADD16( out1_Q10, SILK_FIX_CONST( NLSF_QUANT_LEVEL_ADJ, 10 ) );
}
out0_Q10_table[ i + NLSF_QUANT_MAX_AMPLITUDE_EXT ] = silk_RSHIFT( silk_SMULBB( out0_Q10, quant_step_size_Q16 ), 16 );
out1_Q10_table[ i + NLSF_QUANT_MAX_AMPLITUDE_EXT ] = silk_RSHIFT( silk_SMULBB( out1_Q10, quant_step_size_Q16 ), 16 );
}
silk_assert( (NLSF_QUANT_DEL_DEC_STATES & (NLSF_QUANT_DEL_DEC_STATES-1)) == 0 ); /* must be power of two */
nStates = 1;
@@ -63,31 +86,18 @@ opus_int32 silk_NLSF_del_dec_quant( /* O Returns
prev_out_Q10[ 0 ] = 0;
for( i = order - 1; ; i-- ) {
rates_Q5 = &ec_rates_Q5[ ec_ix[ i ] ];
pred_coef_Q16 = silk_LSHIFT( (opus_int32)pred_coef_Q8[ i ], 8 );
in_Q10 = x_Q10[ i ];
for( j = 0; j < nStates; j++ ) {
pred_Q10 = silk_SMULWB( pred_coef_Q16, prev_out_Q10[ j ] );
pred_Q10 = silk_RSHIFT( silk_SMULBB( (opus_int16)pred_coef_Q8[ i ], prev_out_Q10[ j ] ), 8 );
res_Q10 = silk_SUB16( in_Q10, pred_Q10 );
ind_tmp = silk_SMULWB( (opus_int32)inv_quant_step_size_Q6, res_Q10 );
ind_tmp = silk_RSHIFT( silk_SMULBB( inv_quant_step_size_Q6, res_Q10 ), 16 );
ind_tmp = silk_LIMIT( ind_tmp, -NLSF_QUANT_MAX_AMPLITUDE_EXT, NLSF_QUANT_MAX_AMPLITUDE_EXT-1 );
ind[ j ][ i ] = (opus_int8)ind_tmp;
/* compute outputs for ind_tmp and ind_tmp + 1 */
out0_Q10 = silk_LSHIFT( ind_tmp, 10 );
out1_Q10 = silk_ADD16( out0_Q10, 1024 );
if( ind_tmp > 0 ) {
out0_Q10 = silk_SUB16( out0_Q10, SILK_FIX_CONST( NLSF_QUANT_LEVEL_ADJ, 10 ) );
out1_Q10 = silk_SUB16( out1_Q10, SILK_FIX_CONST( NLSF_QUANT_LEVEL_ADJ, 10 ) );
} else if( ind_tmp == 0 ) {
out1_Q10 = silk_SUB16( out1_Q10, SILK_FIX_CONST( NLSF_QUANT_LEVEL_ADJ, 10 ) );
} else if( ind_tmp == -1 ) {
out0_Q10 = silk_ADD16( out0_Q10, SILK_FIX_CONST( NLSF_QUANT_LEVEL_ADJ, 10 ) );
} else {
out0_Q10 = silk_ADD16( out0_Q10, SILK_FIX_CONST( NLSF_QUANT_LEVEL_ADJ, 10 ) );
out1_Q10 = silk_ADD16( out1_Q10, SILK_FIX_CONST( NLSF_QUANT_LEVEL_ADJ, 10 ) );
}
out0_Q10 = silk_SMULWB( (opus_int32)out0_Q10, quant_step_size_Q16 );
out1_Q10 = silk_SMULWB( (opus_int32)out1_Q10, quant_step_size_Q16 );
out0_Q10 = out0_Q10_table[ ind_tmp + NLSF_QUANT_MAX_AMPLITUDE_EXT ];
out1_Q10 = out1_Q10_table[ ind_tmp + NLSF_QUANT_MAX_AMPLITUDE_EXT ];
out0_Q10 = silk_ADD16( out0_Q10, pred_Q10 );
out1_Q10 = silk_ADD16( out1_Q10, pred_Q10 );
prev_out_Q10[ j ] = out0_Q10;
+3 -2
View File
@@ -46,7 +46,7 @@ opus_int32 silk_NLSF_encode( /* O Returns
)
{
opus_int i, s, ind1, bestIndex, prob_Q8, bits_q7;
opus_int32 W_tmp_Q9;
opus_int32 W_tmp_Q9, ret;
VARDECL( opus_int32, err_Q26 );
VARDECL( opus_int32, RD_Q25 );
VARDECL( opus_int, tempIndices1 );
@@ -131,6 +131,7 @@ opus_int32 silk_NLSF_encode( /* O Returns
/* Decode */
silk_NLSF_decode( pNLSF_Q15, NLSFIndices, psNLSF_CB );
ret = RD_Q25[ 0 ];
RESTORE_STACK;
return RD_Q25[ 0 ];
return ret;
}
+1 -1
View File
@@ -130,7 +130,7 @@ void silk_NLSF_stabilize(
/* Keep delta_min distance between the NLSFs */
for( i = 1; i < L; i++ )
NLSF_Q15[i] = silk_max_int( NLSF_Q15[i], NLSF_Q15[i-1] + NDeltaMin_Q15[i] );
NLSF_Q15[i] = silk_max_int( NLSF_Q15[i], silk_ADD_SAT16( NLSF_Q15[i-1], NDeltaMin_Q15[i] ) );
/* Last NLSF should be no higher than 1 - NDeltaMin[L] */
NLSF_Q15[L-1] = silk_min_int( NLSF_Q15[L-1], (1<<15) - NDeltaMin_Q15[L] );
+27 -44
View File
@@ -31,6 +31,8 @@ POSSIBILITY OF SUCH DAMAGE.
#include "main.h"
#include "stack_alloc.h"
#include "NSQ.h"
static OPUS_INLINE void silk_nsq_scale_states(
const silk_encoder_state *psEncC, /* I Encoder State */
@@ -46,6 +48,7 @@ static OPUS_INLINE void silk_nsq_scale_states(
const opus_int signal_type /* I Signal type */
);
#if !defined(OPUS_X86_MAY_HAVE_SSE4_1)
static OPUS_INLINE void silk_noise_shape_quantizer(
silk_nsq_state *NSQ, /* I/O NSQ state */
opus_int signalType, /* I Signal type */
@@ -65,10 +68,13 @@ static OPUS_INLINE void silk_noise_shape_quantizer(
opus_int offset_Q10, /* I */
opus_int length, /* I Input length */
opus_int shapingLPCOrder, /* I Noise shaping AR filter order */
opus_int predictLPCOrder /* I Prediction filter order */
opus_int predictLPCOrder, /* I Prediction filter order */
int arch /* I Architecture */
);
#endif
void silk_NSQ(
void silk_NSQ_c
(
const silk_encoder_state *psEncC, /* I/O Encoder State */
silk_nsq_state *NSQ, /* I/O NSQ state */
SideInfoIndices *psIndices, /* I/O Quantization Indices */
@@ -141,7 +147,7 @@ void silk_NSQ(
silk_assert( start_idx > 0 );
silk_LPC_analysis_filter( &sLTP[ start_idx ], &NSQ->xq[ start_idx + k * psEncC->subfr_length ],
A_Q12, psEncC->ltp_mem_length - start_idx, psEncC->predictLPCOrder );
A_Q12, psEncC->ltp_mem_length - start_idx, psEncC->predictLPCOrder, psEncC->arch );
NSQ->rewhite_flag = 1;
NSQ->sLTP_buf_idx = psEncC->ltp_mem_length;
@@ -152,7 +158,7 @@ void silk_NSQ(
silk_noise_shape_quantizer( NSQ, psIndices->signalType, x_sc_Q10, pulses, pxq, sLTP_Q15, A_Q12, B_Q14,
AR_shp_Q13, lag, HarmShapeFIRPacked_Q14, Tilt_Q14[ k ], LF_shp_Q14[ k ], Gains_Q16[ k ], Lambda_Q10,
offset_Q10, psEncC->subfr_length, psEncC->shapingLPCOrder, psEncC->predictLPCOrder );
offset_Q10, psEncC->subfr_length, psEncC->shapingLPCOrder, psEncC->predictLPCOrder, psEncC->arch );
x_Q3 += psEncC->subfr_length;
pulses += psEncC->subfr_length;
@@ -172,7 +178,11 @@ void silk_NSQ(
/***********************************/
/* silk_noise_shape_quantizer */
/***********************************/
static OPUS_INLINE void silk_noise_shape_quantizer(
#if !defined(OPUS_X86_MAY_HAVE_SSE4_1)
static OPUS_INLINE
#endif
void silk_noise_shape_quantizer(
silk_nsq_state *NSQ, /* I/O NSQ state */
opus_int signalType, /* I Signal type */
const opus_int32 x_sc_Q10[], /* I */
@@ -191,15 +201,19 @@ static OPUS_INLINE void silk_noise_shape_quantizer(
opus_int offset_Q10, /* I */
opus_int length, /* I Input length */
opus_int shapingLPCOrder, /* I Noise shaping AR filter order */
opus_int predictLPCOrder /* I Prediction filter order */
opus_int predictLPCOrder, /* I Prediction filter order */
int arch /* I Architecture */
)
{
opus_int i, j;
opus_int i;
opus_int32 LTP_pred_Q13, LPC_pred_Q10, n_AR_Q12, n_LTP_Q13;
opus_int32 n_LF_Q12, r_Q10, rr_Q10, q1_Q0, q1_Q10, q2_Q10, rd1_Q20, rd2_Q20;
opus_int32 exc_Q14, LPC_exc_Q14, xq_Q14, Gain_Q10;
opus_int32 tmp1, tmp2, sLF_AR_shp_Q14;
opus_int32 *psLPC_Q14, *shp_lag_ptr, *pred_lag_ptr;
#ifdef silk_short_prediction_create_arch_coef
opus_int32 a_Q12_arch[MAX_LPC_ORDER];
#endif
shp_lag_ptr = &NSQ->sLTP_shp_Q14[ NSQ->sLTP_shp_buf_idx - lag + HARM_SHAPE_FIR_TAPS / 2 ];
pred_lag_ptr = &sLTP_Q15[ NSQ->sLTP_buf_idx - lag + LTP_ORDER / 2 ];
@@ -208,32 +222,16 @@ static OPUS_INLINE void silk_noise_shape_quantizer(
/* Set up short term AR state */
psLPC_Q14 = &NSQ->sLPC_Q14[ NSQ_LPC_BUF_LENGTH - 1 ];
#ifdef silk_short_prediction_create_arch_coef
silk_short_prediction_create_arch_coef(a_Q12_arch, a_Q12, predictLPCOrder);
#endif
for( i = 0; i < length; i++ ) {
/* Generate dither */
NSQ->rand_seed = silk_RAND( NSQ->rand_seed );
/* Short-term prediction */
silk_assert( predictLPCOrder == 10 || predictLPCOrder == 16 );
/* Avoids introducing a bias because silk_SMLAWB() always rounds to -inf */
LPC_pred_Q10 = silk_RSHIFT( predictLPCOrder, 1 );
LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, psLPC_Q14[ 0 ], a_Q12[ 0 ] );
LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, psLPC_Q14[ -1 ], a_Q12[ 1 ] );
LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, psLPC_Q14[ -2 ], a_Q12[ 2 ] );
LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, psLPC_Q14[ -3 ], a_Q12[ 3 ] );
LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, psLPC_Q14[ -4 ], a_Q12[ 4 ] );
LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, psLPC_Q14[ -5 ], a_Q12[ 5 ] );
LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, psLPC_Q14[ -6 ], a_Q12[ 6 ] );
LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, psLPC_Q14[ -7 ], a_Q12[ 7 ] );
LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, psLPC_Q14[ -8 ], a_Q12[ 8 ] );
LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, psLPC_Q14[ -9 ], a_Q12[ 9 ] );
if( predictLPCOrder == 16 ) {
LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, psLPC_Q14[ -10 ], a_Q12[ 10 ] );
LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, psLPC_Q14[ -11 ], a_Q12[ 11 ] );
LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, psLPC_Q14[ -12 ], a_Q12[ 12 ] );
LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, psLPC_Q14[ -13 ], a_Q12[ 13 ] );
LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, psLPC_Q14[ -14 ], a_Q12[ 14 ] );
LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, psLPC_Q14[ -15 ], a_Q12[ 15 ] );
}
LPC_pred_Q10 = silk_noise_shape_quantizer_short_prediction(psLPC_Q14, a_Q12, a_Q12_arch, predictLPCOrder, arch);
/* Long-term prediction */
if( signalType == TYPE_VOICED ) {
@@ -252,23 +250,8 @@ static OPUS_INLINE void silk_noise_shape_quantizer(
/* Noise shape feedback */
silk_assert( ( shapingLPCOrder & 1 ) == 0 ); /* check that order is even */
tmp2 = psLPC_Q14[ 0 ];
tmp1 = NSQ->sAR2_Q14[ 0 ];
NSQ->sAR2_Q14[ 0 ] = tmp2;
n_AR_Q12 = silk_RSHIFT( shapingLPCOrder, 1 );
n_AR_Q12 = silk_SMLAWB( n_AR_Q12, tmp2, AR_shp_Q13[ 0 ] );
for( j = 2; j < shapingLPCOrder; j += 2 ) {
tmp2 = NSQ->sAR2_Q14[ j - 1 ];
NSQ->sAR2_Q14[ j - 1 ] = tmp1;
n_AR_Q12 = silk_SMLAWB( n_AR_Q12, tmp1, AR_shp_Q13[ j - 1 ] );
tmp1 = NSQ->sAR2_Q14[ j + 0 ];
NSQ->sAR2_Q14[ j + 0 ] = tmp2;
n_AR_Q12 = silk_SMLAWB( n_AR_Q12, tmp2, AR_shp_Q13[ j ] );
}
NSQ->sAR2_Q14[ shapingLPCOrder - 1 ] = tmp1;
n_AR_Q12 = silk_SMLAWB( n_AR_Q12, tmp1, AR_shp_Q13[ shapingLPCOrder - 1 ] );
n_AR_Q12 = silk_NSQ_noise_shape_feedback_loop(psLPC_Q14, NSQ->sAR2_Q14, AR_shp_Q13, shapingLPCOrder, arch);
n_AR_Q12 = silk_LSHIFT32( n_AR_Q12, 1 ); /* Q11 -> Q12 */
n_AR_Q12 = silk_SMLAWB( n_AR_Q12, NSQ->sLF_AR_shp_Q14, Tilt_Q14 );
n_LF_Q12 = silk_SMULWB( NSQ->sLTP_shp_Q14[ NSQ->sLTP_shp_buf_idx - 1 ], LF_shp_Q14 );
+101
View File
@@ -0,0 +1,101 @@
/***********************************************************************
Copyright (c) 2014 Vidyo.
Copyright (c) 2006-2011, Skype Limited. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
- Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
- Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
- Neither the name of Internet Society, IETF or IETF Trust, nor the
names of specific contributors, may be used to endorse or promote
products derived from this software without specific prior written
permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
***********************************************************************/
#ifndef SILK_NSQ_H
#define SILK_NSQ_H
#include "SigProc_FIX.h"
#undef silk_short_prediction_create_arch_coef
static OPUS_INLINE opus_int32 silk_noise_shape_quantizer_short_prediction_c(const opus_int32 *buf32, const opus_int16 *coef16, opus_int order)
{
opus_int32 out;
silk_assert( order == 10 || order == 16 );
/* Avoids introducing a bias because silk_SMLAWB() always rounds to -inf */
out = silk_RSHIFT( order, 1 );
out = silk_SMLAWB( out, buf32[ 0 ], coef16[ 0 ] );
out = silk_SMLAWB( out, buf32[ -1 ], coef16[ 1 ] );
out = silk_SMLAWB( out, buf32[ -2 ], coef16[ 2 ] );
out = silk_SMLAWB( out, buf32[ -3 ], coef16[ 3 ] );
out = silk_SMLAWB( out, buf32[ -4 ], coef16[ 4 ] );
out = silk_SMLAWB( out, buf32[ -5 ], coef16[ 5 ] );
out = silk_SMLAWB( out, buf32[ -6 ], coef16[ 6 ] );
out = silk_SMLAWB( out, buf32[ -7 ], coef16[ 7 ] );
out = silk_SMLAWB( out, buf32[ -8 ], coef16[ 8 ] );
out = silk_SMLAWB( out, buf32[ -9 ], coef16[ 9 ] );
if( order == 16 )
{
out = silk_SMLAWB( out, buf32[ -10 ], coef16[ 10 ] );
out = silk_SMLAWB( out, buf32[ -11 ], coef16[ 11 ] );
out = silk_SMLAWB( out, buf32[ -12 ], coef16[ 12 ] );
out = silk_SMLAWB( out, buf32[ -13 ], coef16[ 13 ] );
out = silk_SMLAWB( out, buf32[ -14 ], coef16[ 14 ] );
out = silk_SMLAWB( out, buf32[ -15 ], coef16[ 15 ] );
}
return out;
}
#define silk_noise_shape_quantizer_short_prediction(in, coef, coefRev, order, arch) ((void)arch,silk_noise_shape_quantizer_short_prediction_c(in, coef, order))
static OPUS_INLINE opus_int32 silk_NSQ_noise_shape_feedback_loop_c(const opus_int32 *data0, opus_int32 *data1, const opus_int16 *coef, opus_int order)
{
opus_int32 out;
opus_int32 tmp1, tmp2;
opus_int j;
tmp2 = data0[0];
tmp1 = data1[0];
data1[0] = tmp2;
out = silk_RSHIFT(order, 1);
out = silk_SMLAWB(out, tmp2, coef[0]);
for (j = 2; j < order; j += 2) {
tmp2 = data1[j - 1];
data1[j - 1] = tmp1;
out = silk_SMLAWB(out, tmp1, coef[j - 1]);
tmp1 = data1[j + 0];
data1[j + 0] = tmp2;
out = silk_SMLAWB(out, tmp2, coef[j]);
}
data1[order - 1] = tmp1;
out = silk_SMLAWB(out, tmp1, coef[order - 1]);
/* Q11 -> Q12 */
out = silk_LSHIFT32( out, 1 );
return out;
}
#define silk_NSQ_noise_shape_feedback_loop(data0, data1, coef, order, arch) ((void)arch,silk_NSQ_noise_shape_feedback_loop_c(data0, data1, coef, order))
#if defined(OPUS_ARM_MAY_HAVE_NEON_INTR)
#include "arm/NSQ_neon.h"
#endif
#endif /* SILK_NSQ_H */
+23 -26
View File
@@ -31,6 +31,8 @@ POSSIBILITY OF SUCH DAMAGE.
#include "main.h"
#include "stack_alloc.h"
#include "NSQ.h"
typedef struct {
opus_int32 sLPC_Q14[ MAX_SUB_FRAME_LENGTH + NSQ_LPC_BUF_LENGTH ];
@@ -57,6 +59,9 @@ typedef struct {
typedef NSQ_sample_struct NSQ_sample_pair[ 2 ];
#if defined(MIPSr1_ASM)
#include "mips/NSQ_del_dec_mipsr1.h"
#endif
static OPUS_INLINE void silk_nsq_del_dec_scale_states(
const silk_encoder_state *psEncC, /* I Encoder State */
silk_nsq_state *NSQ, /* I/O NSQ state */
@@ -103,10 +108,11 @@ static OPUS_INLINE void silk_noise_shape_quantizer_del_dec(
opus_int warping_Q16, /* I */
opus_int nStatesDelayedDecision, /* I Number of states in decision tree */
opus_int *smpl_buf_idx, /* I Index to newest samples in buffers */
opus_int decisionDelay /* I */
opus_int decisionDelay, /* I */
int arch /* I */
);
void silk_NSQ_del_dec(
void silk_NSQ_del_dec_c(
const silk_encoder_state *psEncC, /* I/O Encoder State */
silk_nsq_state *NSQ, /* I/O NSQ state */
SideInfoIndices *psIndices, /* I/O Quantization Indices */
@@ -244,7 +250,7 @@ void silk_NSQ_del_dec(
silk_assert( start_idx > 0 );
silk_LPC_analysis_filter( &sLTP[ start_idx ], &NSQ->xq[ start_idx + k * psEncC->subfr_length ],
A_Q12, psEncC->ltp_mem_length - start_idx, psEncC->predictLPCOrder );
A_Q12, psEncC->ltp_mem_length - start_idx, psEncC->predictLPCOrder, psEncC->arch );
NSQ->sLTP_buf_idx = psEncC->ltp_mem_length;
NSQ->rewhite_flag = 1;
@@ -257,7 +263,7 @@ void silk_NSQ_del_dec(
silk_noise_shape_quantizer_del_dec( NSQ, psDelDec, psIndices->signalType, x_sc_Q10, pulses, pxq, sLTP_Q15,
delayedGain_Q10, A_Q12, B_Q14, AR_shp_Q13, lag, HarmShapeFIRPacked_Q14, Tilt_Q14[ k ], LF_shp_Q14[ k ],
Gains_Q16[ k ], Lambda_Q10, offset_Q10, psEncC->subfr_length, subfr++, psEncC->shapingLPCOrder,
psEncC->predictLPCOrder, psEncC->warping_Q16, psEncC->nStatesDelayedDecision, &smpl_buf_idx, decisionDelay );
psEncC->predictLPCOrder, psEncC->warping_Q16, psEncC->nStatesDelayedDecision, &smpl_buf_idx, decisionDelay, psEncC->arch );
x_Q3 += psEncC->subfr_length;
pulses += psEncC->subfr_length;
@@ -303,6 +309,7 @@ void silk_NSQ_del_dec(
/******************************************/
/* Noise shape quantizer for one subframe */
/******************************************/
#ifndef OVERRIDE_silk_noise_shape_quantizer_del_dec
static OPUS_INLINE void silk_noise_shape_quantizer_del_dec(
silk_nsq_state *NSQ, /* I/O NSQ state */
NSQ_del_dec_struct psDelDec[], /* I/O Delayed decision states */
@@ -329,7 +336,8 @@ static OPUS_INLINE void silk_noise_shape_quantizer_del_dec(
opus_int warping_Q16, /* I */
opus_int nStatesDelayedDecision, /* I Number of states in decision tree */
opus_int *smpl_buf_idx, /* I Index to newest samples in buffers */
opus_int decisionDelay /* I */
opus_int decisionDelay, /* I */
int arch /* I */
)
{
opus_int i, j, k, Winner_ind, RDmin_ind, RDmax_ind, last_smple_idx;
@@ -339,6 +347,10 @@ static OPUS_INLINE void silk_noise_shape_quantizer_del_dec(
opus_int32 q1_Q0, q1_Q10, q2_Q10, exc_Q14, LPC_exc_Q14, xq_Q14, Gain_Q10;
opus_int32 tmp1, tmp2, sLF_AR_shp_Q14;
opus_int32 *pred_lag_ptr, *shp_lag_ptr, *psLPC_Q14;
#ifdef silk_short_prediction_create_arch_coef
opus_int32 a_Q12_arch[MAX_LPC_ORDER];
#endif
VARDECL( NSQ_sample_pair, psSampleState );
NSQ_del_dec_struct *psDD;
NSQ_sample_struct *psSS;
@@ -351,6 +363,10 @@ static OPUS_INLINE void silk_noise_shape_quantizer_del_dec(
pred_lag_ptr = &sLTP_Q15[ NSQ->sLTP_buf_idx - lag + LTP_ORDER / 2 ];
Gain_Q10 = silk_RSHIFT( Gain_Q16, 6 );
#ifdef silk_short_prediction_create_arch_coef
silk_short_prediction_create_arch_coef(a_Q12_arch, a_Q12, predictLPCOrder);
#endif
for( i = 0; i < length; i++ ) {
/* Perform common calculations used in all states */
@@ -394,27 +410,7 @@ static OPUS_INLINE void silk_noise_shape_quantizer_del_dec(
/* Pointer used in short term prediction and shaping */
psLPC_Q14 = &psDD->sLPC_Q14[ NSQ_LPC_BUF_LENGTH - 1 + i ];
/* Short-term prediction */
silk_assert( predictLPCOrder == 10 || predictLPCOrder == 16 );
/* Avoids introducing a bias because silk_SMLAWB() always rounds to -inf */
LPC_pred_Q14 = silk_RSHIFT( predictLPCOrder, 1 );
LPC_pred_Q14 = silk_SMLAWB( LPC_pred_Q14, psLPC_Q14[ 0 ], a_Q12[ 0 ] );
LPC_pred_Q14 = silk_SMLAWB( LPC_pred_Q14, psLPC_Q14[ -1 ], a_Q12[ 1 ] );
LPC_pred_Q14 = silk_SMLAWB( LPC_pred_Q14, psLPC_Q14[ -2 ], a_Q12[ 2 ] );
LPC_pred_Q14 = silk_SMLAWB( LPC_pred_Q14, psLPC_Q14[ -3 ], a_Q12[ 3 ] );
LPC_pred_Q14 = silk_SMLAWB( LPC_pred_Q14, psLPC_Q14[ -4 ], a_Q12[ 4 ] );
LPC_pred_Q14 = silk_SMLAWB( LPC_pred_Q14, psLPC_Q14[ -5 ], a_Q12[ 5 ] );
LPC_pred_Q14 = silk_SMLAWB( LPC_pred_Q14, psLPC_Q14[ -6 ], a_Q12[ 6 ] );
LPC_pred_Q14 = silk_SMLAWB( LPC_pred_Q14, psLPC_Q14[ -7 ], a_Q12[ 7 ] );
LPC_pred_Q14 = silk_SMLAWB( LPC_pred_Q14, psLPC_Q14[ -8 ], a_Q12[ 8 ] );
LPC_pred_Q14 = silk_SMLAWB( LPC_pred_Q14, psLPC_Q14[ -9 ], a_Q12[ 9 ] );
if( predictLPCOrder == 16 ) {
LPC_pred_Q14 = silk_SMLAWB( LPC_pred_Q14, psLPC_Q14[ -10 ], a_Q12[ 10 ] );
LPC_pred_Q14 = silk_SMLAWB( LPC_pred_Q14, psLPC_Q14[ -11 ], a_Q12[ 11 ] );
LPC_pred_Q14 = silk_SMLAWB( LPC_pred_Q14, psLPC_Q14[ -12 ], a_Q12[ 12 ] );
LPC_pred_Q14 = silk_SMLAWB( LPC_pred_Q14, psLPC_Q14[ -13 ], a_Q12[ 13 ] );
LPC_pred_Q14 = silk_SMLAWB( LPC_pred_Q14, psLPC_Q14[ -14 ], a_Q12[ 14 ] );
LPC_pred_Q14 = silk_SMLAWB( LPC_pred_Q14, psLPC_Q14[ -15 ], a_Q12[ 15 ] );
}
LPC_pred_Q14 = silk_noise_shape_quantizer_short_prediction(psLPC_Q14, a_Q12, a_Q12_arch, predictLPCOrder, arch);
LPC_pred_Q14 = silk_LSHIFT( LPC_pred_Q14, 4 ); /* Q10 -> Q14 */
/* Noise shape feedback */
@@ -629,6 +625,7 @@ static OPUS_INLINE void silk_noise_shape_quantizer_del_dec(
}
RESTORE_STACK;
}
#endif /* OVERRIDE_silk_noise_shape_quantizer_del_dec */
static OPUS_INLINE void silk_nsq_del_dec_scale_states(
const silk_encoder_state *psEncC, /* I Encoder State */
+46 -23
View File
@@ -46,7 +46,8 @@ static OPUS_INLINE void silk_PLC_update(
static OPUS_INLINE void silk_PLC_conceal(
silk_decoder_state *psDec, /* I/O Decoder state */
silk_decoder_control *psDecCtrl, /* I/O Decoder control */
opus_int16 frame[] /* O LPC residual signal */
opus_int16 frame[], /* O LPC residual signal */
int arch /* I Run-time architecture */
);
@@ -65,7 +66,8 @@ void silk_PLC(
silk_decoder_state *psDec, /* I/O Decoder state */
silk_decoder_control *psDecCtrl, /* I/O Decoder control */
opus_int16 frame[], /* I/O signal */
opus_int lost /* I Loss flag */
opus_int lost, /* I Loss flag */
int arch /* I Run-time architecture */
)
{
/* PLC control function */
@@ -78,7 +80,7 @@ void silk_PLC(
/****************************/
/* Generate Signal */
/****************************/
silk_PLC_conceal( psDec, psDecCtrl, frame );
silk_PLC_conceal( psDec, psDecCtrl, frame, arch );
psDec->lossCnt++;
} else {
@@ -165,10 +167,35 @@ static OPUS_INLINE void silk_PLC_update(
psPLC->nb_subfr = psDec->nb_subfr;
}
static OPUS_INLINE void silk_PLC_energy(opus_int32 *energy1, opus_int *shift1, opus_int32 *energy2, opus_int *shift2,
const opus_int32 *exc_Q14, const opus_int32 *prevGain_Q10, int subfr_length, int nb_subfr)
{
int i, k;
VARDECL( opus_int16, exc_buf );
opus_int16 *exc_buf_ptr;
SAVE_STACK;
ALLOC( exc_buf, 2*subfr_length, opus_int16 );
/* Find random noise component */
/* Scale previous excitation signal */
exc_buf_ptr = exc_buf;
for( k = 0; k < 2; k++ ) {
for( i = 0; i < subfr_length; i++ ) {
exc_buf_ptr[ i ] = (opus_int16)silk_SAT16( silk_RSHIFT(
silk_SMULWW( exc_Q14[ i + ( k + nb_subfr - 2 ) * subfr_length ], prevGain_Q10[ k ] ), 8 ) );
}
exc_buf_ptr += subfr_length;
}
/* Find the subframe with lowest energy of the last two and use that as random noise generator */
silk_sum_sqr_shift( energy1, shift1, exc_buf, subfr_length );
silk_sum_sqr_shift( energy2, shift2, &exc_buf[ subfr_length ], subfr_length );
RESTORE_STACK;
}
static OPUS_INLINE void silk_PLC_conceal(
silk_decoder_state *psDec, /* I/O Decoder state */
silk_decoder_control *psDecCtrl, /* I/O Decoder control */
opus_int16 frame[] /* O LPC residual signal */
opus_int16 frame[], /* O LPC residual signal */
int arch /* I Run-time architecture */
)
{
opus_int i, j, k;
@@ -177,19 +204,26 @@ static OPUS_INLINE void silk_PLC_conceal(
opus_int32 energy1, energy2, *rand_ptr, *pred_lag_ptr;
opus_int32 LPC_pred_Q10, LTP_pred_Q12;
opus_int16 rand_scale_Q14;
opus_int16 *B_Q14, *exc_buf_ptr;
opus_int16 *B_Q14;
opus_int32 *sLPC_Q14_ptr;
VARDECL( opus_int16, exc_buf );
opus_int16 A_Q12[ MAX_LPC_ORDER ];
#ifdef SMALL_FOOTPRINT
opus_int16 *sLTP;
#else
VARDECL( opus_int16, sLTP );
#endif
VARDECL( opus_int32, sLTP_Q14 );
silk_PLC_struct *psPLC = &psDec->sPLC;
opus_int32 prevGain_Q10[2];
SAVE_STACK;
ALLOC( exc_buf, 2*psPLC->subfr_length, opus_int16 );
ALLOC( sLTP, psDec->ltp_mem_length, opus_int16 );
ALLOC( sLTP_Q14, psDec->ltp_mem_length + psDec->frame_length, opus_int32 );
#ifdef SMALL_FOOTPRINT
/* Ugly hack that breaks aliasing rules to save stack: put sLTP at the very end of sLTP_Q14. */
sLTP = ((opus_int16*)&sLTP_Q14[psDec->ltp_mem_length + psDec->frame_length])-psDec->ltp_mem_length;
#else
ALLOC( sLTP, psDec->ltp_mem_length, opus_int16 );
#endif
prevGain_Q10[0] = silk_RSHIFT( psPLC->prevGain_Q16[ 0 ], 6);
prevGain_Q10[1] = silk_RSHIFT( psPLC->prevGain_Q16[ 1 ], 6);
@@ -198,19 +232,7 @@ static OPUS_INLINE void silk_PLC_conceal(
silk_memset( psPLC->prevLPC_Q12, 0, sizeof( psPLC->prevLPC_Q12 ) );
}
/* Find random noise component */
/* Scale previous excitation signal */
exc_buf_ptr = exc_buf;
for( k = 0; k < 2; k++ ) {
for( i = 0; i < psPLC->subfr_length; i++ ) {
exc_buf_ptr[ i ] = (opus_int16)silk_SAT16( silk_RSHIFT(
silk_SMULWW( psDec->exc_Q14[ i + ( k + psPLC->nb_subfr - 2 ) * psPLC->subfr_length ], prevGain_Q10[ k ] ), 8 ) );
}
exc_buf_ptr += psPLC->subfr_length;
}
/* Find the subframe with lowest energy of the last two and use that as random noise generator */
silk_sum_sqr_shift( &energy1, &shift1, exc_buf, psPLC->subfr_length );
silk_sum_sqr_shift( &energy2, &shift2, &exc_buf[ psPLC->subfr_length ], psPLC->subfr_length );
silk_PLC_energy(&energy1, &shift1, &energy2, &shift2, psDec->exc_Q14, prevGain_Q10, psDec->subfr_length, psDec->nb_subfr);
if( silk_RSHIFT( energy1, shift2 ) < silk_RSHIFT( energy2, shift1 ) ) {
/* First sub-frame has lowest energy */
@@ -270,7 +292,7 @@ static OPUS_INLINE void silk_PLC_conceal(
/* Rewhiten LTP state */
idx = psDec->ltp_mem_length - lag - psDec->LPC_order - LTP_ORDER / 2;
silk_assert( idx > 0 );
silk_LPC_analysis_filter( &sLTP[ idx ], &psDec->outBuf[ idx ], A_Q12, psDec->ltp_mem_length - idx, psDec->LPC_order );
silk_LPC_analysis_filter( &sLTP[ idx ], &psDec->outBuf[ idx ], A_Q12, psDec->ltp_mem_length - idx, psDec->LPC_order, arch );
/* Scale LTP state */
inv_gain_Q30 = silk_INVERSE32_varQ( psPLC->prevGain_Q16[ 1 ], 46 );
inv_gain_Q30 = silk_min( inv_gain_Q30, silk_int32_MAX >> 1 );
@@ -343,7 +365,8 @@ static OPUS_INLINE void silk_PLC_conceal(
}
/* Add prediction to LPC excitation */
sLPC_Q14_ptr[ MAX_LPC_ORDER + i ] = silk_ADD_LSHIFT32( sLPC_Q14_ptr[ MAX_LPC_ORDER + i ], LPC_pred_Q10, 4 );
sLPC_Q14_ptr[ MAX_LPC_ORDER + i ] = silk_ADD_SAT32( sLPC_Q14_ptr[ MAX_LPC_ORDER + i ],
silk_LSHIFT_SAT32( LPC_pred_Q10, 4 ));
/* Scale with Gain */
frame[ i ] = (opus_int16)silk_SAT16( silk_SAT16( silk_RSHIFT_ROUND( silk_SMULWW( sLPC_Q14_ptr[ MAX_LPC_ORDER + i ], prevGain_Q10[ 1 ] ), 8 ) ) );
+2 -1
View File
@@ -48,7 +48,8 @@ void silk_PLC(
silk_decoder_state *psDec, /* I/O Decoder state */
silk_decoder_control *psDecCtrl, /* I/O Decoder control */
opus_int16 frame[], /* I/O signal */
opus_int lost /* I Loss flag */
opus_int lost, /* I Loss flag */
int arch /* I Run-time architecture */
);
void silk_PLC_glue_frames(
+25 -4
View File
@@ -41,7 +41,11 @@ extern "C"
#include "typedef.h"
#include "resampler_structs.h"
#include "macros.h"
#include "cpu_support.h"
#if defined(OPUS_X86_MAY_HAVE_SSE4_1)
#include "x86/SigProc_FIX_sse.h"
#endif
/********************************************************************/
/* SIGNAL PROCESSING FUNCTIONS */
@@ -108,7 +112,8 @@ void silk_LPC_analysis_filter(
const opus_int16 *in, /* I Input signal */
const opus_int16 *B, /* I MA prediction coefficients, Q12 [order] */
const opus_int32 len, /* I Signal length */
const opus_int32 d /* I Filter order */
const opus_int32 d, /* I Filter order */
int arch /* I Run-time architecture */
);
/* Chirp (bandwidth expand) LP AR filter */
@@ -303,7 +308,7 @@ void silk_NLSF_VQ_weights_laroia(
);
/* Compute reflection coefficients from input signal */
void silk_burg_modified(
void silk_burg_modified_c(
opus_int32 *res_nrg, /* O Residual energy */
opus_int *res_nrg_Q, /* O Residual energy Q value */
opus_int32 A_Q16[], /* O Prediction coefficients (length order) */
@@ -335,12 +340,15 @@ void silk_scale_vector32_Q26_lshift_18(
/********************************************************************/
/* return sum( inVec1[i] * inVec2[i] ) */
opus_int32 silk_inner_prod_aligned(
const opus_int16 *const inVec1, /* I input vector 1 */
const opus_int16 *const inVec2, /* I input vector 2 */
const opus_int len /* I vector lengths */
const opus_int len, /* I vector lengths */
int arch /* I Run-time architecture */
);
opus_int32 silk_inner_prod_aligned_scale(
const opus_int16 *const inVec1, /* I input vector 1 */
const opus_int16 *const inVec2, /* I input vector 2 */
@@ -348,7 +356,7 @@ opus_int32 silk_inner_prod_aligned_scale(
const opus_int len /* I vector lengths */
);
opus_int64 silk_inner_prod16_aligned_64(
opus_int64 silk_inner_prod16_aligned_64_c(
const opus_int16 *inVec1, /* I input vector 1 */
const opus_int16 *inVec2, /* I input vector 2 */
const opus_int len /* I vector lengths */
@@ -575,6 +583,14 @@ static OPUS_INLINE opus_int64 silk_max_64(opus_int64 a, opus_int64 b)
/* the following seems faster on x86 */
#define silk_SMMUL(a32, b32) (opus_int32)silk_RSHIFT64(silk_SMULL((a32), (b32)), 32)
#if !defined(OPUS_X86_MAY_HAVE_SSE4_1)
#define silk_burg_modified(res_nrg, res_nrg_Q, A_Q16, x, minInvGain_Q30, subfr_length, nb_subfr, D, arch) \
((void)(arch), silk_burg_modified_c(res_nrg, res_nrg_Q, A_Q16, x, minInvGain_Q30, subfr_length, nb_subfr, D, arch))
#define silk_inner_prod16_aligned_64(inVec1, inVec2, len, arch) \
((void)(arch),silk_inner_prod16_aligned_64_c(inVec1, inVec2, len))
#endif
#include "Inlines.h"
#include "MacroCount.h"
#include "MacroDebug.h"
@@ -587,6 +603,11 @@ static OPUS_INLINE opus_int64 silk_max_64(opus_int64 a, opus_int64 b)
#include "arm/SigProc_FIX_armv5e.h"
#endif
#if defined(MIPSr1_ASM)
#include "mips/sigproc_fix_mipsr1.h"
#endif
#ifdef __cplusplus
}
#endif
+7 -2
View File
@@ -33,10 +33,12 @@ POSSIBILITY OF SUCH DAMAGE.
#include "stack_alloc.h"
/* Silk VAD noise level estimation */
# if !defined(OPUS_X86_MAY_HAVE_SSE4_1)
static OPUS_INLINE void silk_VAD_GetNoiseLevels(
const opus_int32 pX[ VAD_N_BANDS ], /* I subband energies */
silk_VAD_state *psSilk_VAD /* I/O Pointer to Silk VAD state */
);
#endif
/**********************************/
/* Initialization of the Silk VAD */
@@ -77,7 +79,7 @@ static const opus_int32 tiltWeights[ VAD_N_BANDS ] = { 30000, 6000, -12000, -120
/***************************************/
/* Get the speech activity level in Q8 */
/***************************************/
opus_int silk_VAD_GetSA_Q8( /* O Return value, 0 if success */
opus_int silk_VAD_GetSA_Q8_c( /* O Return value, 0 if success */
silk_encoder_state *psEncC, /* I/O Encoder state */
const opus_int16 pIn[] /* I PCM input */
)
@@ -296,7 +298,10 @@ opus_int silk_VAD_GetSA_Q8( /* O Return v
/**************************/
/* Noise level estimation */
/**************************/
static OPUS_INLINE void silk_VAD_GetNoiseLevels(
# if !defined(OPUS_X86_MAY_HAVE_SSE4_1)
static OPUS_INLINE
#endif
void silk_VAD_GetNoiseLevels(
const opus_int32 pX[ VAD_N_BANDS ], /* I subband energies */
silk_VAD_state *psSilk_VAD /* I/O Pointer to Silk VAD state */
)
+5 -5
View File
@@ -32,7 +32,7 @@ POSSIBILITY OF SUCH DAMAGE.
#include "main.h"
/* Entropy constrained matrix-weighted VQ, hard-coded to 5-element vectors, for a single input data vector */
void silk_VQ_WMat_EC(
void silk_VQ_WMat_EC_c(
opus_int8 *ind, /* O index of best codebook vector */
opus_int32 *rate_dist_Q14, /* O best weighted quant error + mu * rate */
opus_int *gain_Q7, /* O sum of absolute LTP coefficients */
@@ -55,7 +55,7 @@ void silk_VQ_WMat_EC(
*rate_dist_Q14 = silk_int32_MAX;
cb_row_Q7 = cb_Q7;
for( k = 0; k < L; k++ ) {
gain_tmp_Q7 = cb_gain_Q7[k];
gain_tmp_Q7 = cb_gain_Q7[k];
diff_Q14[ 0 ] = in_Q14[ 0 ] - silk_LSHIFT( cb_row_Q7[ 0 ], 7 );
diff_Q14[ 1 ] = in_Q14[ 1 ] - silk_LSHIFT( cb_row_Q7[ 1 ], 7 );
@@ -66,8 +66,8 @@ void silk_VQ_WMat_EC(
/* Weighted rate */
sum1_Q14 = silk_SMULBB( mu_Q9, cl_Q5[ k ] );
/* Penalty for too large gain */
sum1_Q14 = silk_ADD_LSHIFT32( sum1_Q14, silk_max( silk_SUB32( gain_tmp_Q7, max_gain_Q7 ), 0 ), 10 );
/* Penalty for too large gain */
sum1_Q14 = silk_ADD_LSHIFT32( sum1_Q14, silk_max( silk_SUB32( gain_tmp_Q7, max_gain_Q7 ), 0 ), 10 );
silk_assert( sum1_Q14 >= 0 );
@@ -111,7 +111,7 @@ void silk_VQ_WMat_EC(
if( sum1_Q14 < *rate_dist_Q14 ) {
*rate_dist_Q14 = sum1_Q14;
*ind = (opus_int8)k;
*gain_Q7 = gain_tmp_Q7;
*gain_Q7 = gain_tmp_Q7;
}
/* Go to next cbk vector */
+112
View File
@@ -0,0 +1,112 @@
/***********************************************************************
Copyright (C) 2014 Vidyo
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
- Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
- Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
- Neither the name of Internet Society, IETF or IETF Trust, nor the
names of specific contributors, may be used to endorse or promote
products derived from this software without specific prior written
permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
***********************************************************************/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <arm_neon.h>
#include "main.h"
#include "stack_alloc.h"
#include "NSQ.h"
#include "celt/cpu_support.h"
#include "celt/arm/armcpu.h"
opus_int32 silk_noise_shape_quantizer_short_prediction_neon(const opus_int32 *buf32, const opus_int32 *coef32, opus_int order)
{
int32x4_t coef0 = vld1q_s32(coef32);
int32x4_t coef1 = vld1q_s32(coef32 + 4);
int32x4_t coef2 = vld1q_s32(coef32 + 8);
int32x4_t coef3 = vld1q_s32(coef32 + 12);
int32x4_t a0 = vld1q_s32(buf32 - 15);
int32x4_t a1 = vld1q_s32(buf32 - 11);
int32x4_t a2 = vld1q_s32(buf32 - 7);
int32x4_t a3 = vld1q_s32(buf32 - 3);
int32x4_t b0 = vqdmulhq_s32(coef0, a0);
int32x4_t b1 = vqdmulhq_s32(coef1, a1);
int32x4_t b2 = vqdmulhq_s32(coef2, a2);
int32x4_t b3 = vqdmulhq_s32(coef3, a3);
int32x4_t c0 = vaddq_s32(b0, b1);
int32x4_t c1 = vaddq_s32(b2, b3);
int32x4_t d = vaddq_s32(c0, c1);
int64x2_t e = vpaddlq_s32(d);
int64x1_t f = vadd_s64(vget_low_s64(e), vget_high_s64(e));
opus_int32 out = vget_lane_s32(vreinterpret_s32_s64(f), 0);
out += silk_RSHIFT( order, 1 );
return out;
}
opus_int32 silk_NSQ_noise_shape_feedback_loop_neon(const opus_int32 *data0, opus_int32 *data1, const opus_int16 *coef, opus_int order)
{
opus_int32 out;
if (order == 8)
{
int32x4_t a00 = vdupq_n_s32(data0[0]);
int32x4_t a01 = vld1q_s32(data1); /* data1[0] ... [3] */
int32x4_t a0 = vextq_s32 (a00, a01, 3); /* data0[0] data1[0] ...[2] */
int32x4_t a1 = vld1q_s32(data1 + 3); /* data1[3] ... [6] */
/*TODO: Convert these once in advance instead of once per sample, like
silk_noise_shape_quantizer_short_prediction_neon() does.*/
int16x8_t coef16 = vld1q_s16(coef);
int32x4_t coef0 = vmovl_s16(vget_low_s16(coef16));
int32x4_t coef1 = vmovl_s16(vget_high_s16(coef16));
/*This is not bit-exact with the C version, since we do not drop the
lower 16 bits of each multiply, but wait until the end to truncate
precision. This is an encoder-specific calculation (and unlike
silk_noise_shape_quantizer_short_prediction_neon(), is not meant to
simulate what the decoder will do). We still could use vqdmulhq_s32()
like silk_noise_shape_quantizer_short_prediction_neon() and save
half the multiplies, but the speed difference is not large, since we
then need two extra adds.*/
int64x2_t b0 = vmull_s32(vget_low_s32(a0), vget_low_s32(coef0));
int64x2_t b1 = vmlal_s32(b0, vget_high_s32(a0), vget_high_s32(coef0));
int64x2_t b2 = vmlal_s32(b1, vget_low_s32(a1), vget_low_s32(coef1));
int64x2_t b3 = vmlal_s32(b2, vget_high_s32(a1), vget_high_s32(coef1));
int64x1_t c = vadd_s64(vget_low_s64(b3), vget_high_s64(b3));
int64x1_t cS = vrshr_n_s64(c, 15);
int32x2_t d = vreinterpret_s32_s64(cS);
out = vget_lane_s32(d, 0);
vst1q_s32(data1, a0);
vst1q_s32(data1 + 4, a1);
return out;
}
return silk_NSQ_noise_shape_feedback_loop_c(data0, data1, coef, order);
}
+113
View File
@@ -0,0 +1,113 @@
/***********************************************************************
Copyright (C) 2014 Vidyo
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
- Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
- Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
- Neither the name of Internet Society, IETF or IETF Trust, nor the
names of specific contributors, may be used to endorse or promote
products derived from this software without specific prior written
permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
***********************************************************************/
#ifndef SILK_NSQ_NEON_H
#define SILK_NSQ_NEON_H
#include "cpu_support.h"
#undef silk_short_prediction_create_arch_coef
/* For vectorized calc, reverse a_Q12 coefs, convert to 32-bit, and shift for vqdmulhq_s32. */
static OPUS_INLINE void silk_short_prediction_create_arch_coef_neon(opus_int32 *out, const opus_int16 *in, opus_int order)
{
out[15] = in[0] << 15;
out[14] = in[1] << 15;
out[13] = in[2] << 15;
out[12] = in[3] << 15;
out[11] = in[4] << 15;
out[10] = in[5] << 15;
out[9] = in[6] << 15;
out[8] = in[7] << 15;
out[7] = in[8] << 15;
out[6] = in[9] << 15;
if (order == 16)
{
out[5] = in[10] << 15;
out[4] = in[11] << 15;
out[3] = in[12] << 15;
out[2] = in[13] << 15;
out[1] = in[14] << 15;
out[0] = in[15] << 15;
}
else
{
out[5] = 0;
out[4] = 0;
out[3] = 0;
out[2] = 0;
out[1] = 0;
out[0] = 0;
}
}
#if defined(OPUS_ARM_PRESUME_NEON_INTR)
#define silk_short_prediction_create_arch_coef(out, in, order) \
(silk_short_prediction_create_arch_coef_neon(out, in, order))
#elif defined(OPUS_HAVE_RTCD) && defined(OPUS_ARM_MAY_HAVE_NEON_INTR)
#define silk_short_prediction_create_arch_coef(out, in, order) \
do { if (arch == OPUS_ARCH_ARM_NEON) { silk_short_prediction_create_arch_coef_neon(out, in, order); } } while (0)
#endif
opus_int32 silk_noise_shape_quantizer_short_prediction_neon(const opus_int32 *buf32, const opus_int32 *coef32, opus_int order);
opus_int32 silk_NSQ_noise_shape_feedback_loop_neon(const opus_int32 *data0, opus_int32 *data1, const opus_int16 *coef, opus_int order);
#if defined(OPUS_ARM_PRESUME_NEON_INTR)
#undef silk_noise_shape_quantizer_short_prediction
#define silk_noise_shape_quantizer_short_prediction(in, coef, coefRev, order, arch) \
((void)arch,silk_noise_shape_quantizer_short_prediction_neon(in, coefRev, order))
#undef silk_NSQ_noise_shape_feedback_loop
#define silk_NSQ_noise_shape_feedback_loop(data0, data1, coef, order, arch) ((void)arch,silk_NSQ_noise_shape_feedback_loop_neon(data0, data1, coef, order))
#elif defined(OPUS_HAVE_RTCD) && defined(OPUS_ARM_MAY_HAVE_NEON_INTR)
/* silk_noise_shape_quantizer_short_prediction implementations take different parameters based on arch
(coef vs. coefRev) so can't use the usual IMPL table implementation */
#undef silk_noise_shape_quantizer_short_prediction
#define silk_noise_shape_quantizer_short_prediction(in, coef, coefRev, order, arch) \
(arch == OPUS_ARCH_ARM_NEON ? \
silk_noise_shape_quantizer_short_prediction_neon(in, coefRev, order) : \
silk_noise_shape_quantizer_short_prediction_c(in, coef, order))
extern opus_int32
(*const SILK_NSQ_NOISE_SHAPE_FEEDBACK_LOOP_IMPL[OPUS_ARCHMASK+1])(
const opus_int32 *data0, opus_int32 *data1, const opus_int16 *coef,
opus_int order);
#undef silk_NSQ_noise_shape_feedback_loop
#define silk_NSQ_noise_shape_feedback_loop(data0, data1, coef, order, arch) \
(SILK_NSQ_NOISE_SHAPE_FEEDBACK_LOOP_IMPL[(arch)&OPUS_ARCHMASK](data0, data1, \
coef, order))
#endif
#endif /* SILK_NSQ_NEON_H */
+55
View File
@@ -0,0 +1,55 @@
/***********************************************************************
Copyright (C) 2014 Vidyo
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
- Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
- Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
- Neither the name of Internet Society, IETF or IETF Trust, nor the
names of specific contributors, may be used to endorse or promote
products derived from this software without specific prior written
permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
***********************************************************************/
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include "NSQ.h"
#if defined(OPUS_HAVE_RTCD)
# if (defined(OPUS_ARM_MAY_HAVE_NEON_INTR) && \
!defined(OPUS_ARM_PRESUME_NEON_INTR))
/*There is no table for silk_noise_shape_quantizer_short_prediction because the
NEON version takes different parameters than the C version.
Instead RTCD is done via if statements at the call sites.
See NSQ_neon.h for details.*/
opus_int32
(*const SILK_NSQ_NOISE_SHAPE_FEEDBACK_LOOP_IMPL[OPUS_ARCHMASK+1])(
const opus_int32 *data0, opus_int32 *data1, const opus_int16 *coef,
opus_int order) = {
silk_NSQ_noise_shape_feedback_loop_c, /* ARMv4 */
silk_NSQ_noise_shape_feedback_loop_c, /* EDSP */
silk_NSQ_noise_shape_feedback_loop_c, /* Media */
silk_NSQ_noise_shape_feedback_loop_neon, /* NEON */
};
# endif
#endif /* OPUS_HAVE_RTCD */
+39
View File
@@ -0,0 +1,39 @@
/***********************************************************************
Copyright (C) 2015 Vidyo
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
- Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
- Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
- Neither the name of Internet Society, IETF or IETF Trust, nor the
names of specific contributors, may be used to endorse or promote
products derived from this software without specific prior written
permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
***********************************************************************/
#ifndef SILK_MACROS_ARM64_H
#define SILK_MACROS_ARM64_H
#include <arm_neon.h>
#undef silk_ADD_SAT32
#define silk_ADD_SAT32(a, b) (vqadds_s32((a), (b)))
#undef silk_SUB_SAT32
#define silk_SUB_SAT32(a, b) (vqsubs_s32((a), (b)))
#endif /* SILK_MACROS_ARM64_H */
+2 -2
View File
@@ -74,7 +74,7 @@ void silk_encode_signs(
/* Decodes signs of excitation */
void silk_decode_signs(
ec_dec *psRangeDec, /* I/O Compressor data structure */
opus_int pulses[], /* I/O pulse signal */
opus_int16 pulses[], /* I/O pulse signal */
opus_int length, /* I length of input */
const opus_int signalType, /* I Signal type */
const opus_int quantOffsetType, /* I Quantization offset type */
@@ -83,7 +83,7 @@ void silk_decode_signs(
{
opus_int i, j, p;
opus_uint8 icdf[ 2 ];
opus_int *q_ptr;
opus_int16 *q_ptr;
const opus_uint8 *icdf_ptr;
icdf[ 1 ] = 0;
-5
View File
@@ -70,11 +70,6 @@ opus_int silk_control_SNR(
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;
+8 -2
View File
@@ -397,9 +397,10 @@ static OPUS_INLINE opus_int silk_setup_LBRR(
const opus_int32 TargetRate_bps /* I */
)
{
opus_int ret = SILK_NO_ERROR;
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 ) {
@@ -413,8 +414,13 @@ static OPUS_INLINE opus_int silk_setup_LBRR(
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;
psEncC->LBRR_GainIncreases = silk_max_int( 7 - silk_SMULWB( (opus_int32)psEncC->PacketLoss_perc, SILK_FIX_CONST( 0.4, 16 ) ), 2 );
}
}
+32 -10
View File
@@ -31,6 +31,7 @@ POSSIBILITY OF SUCH DAMAGE.
#include "API.h"
#include "main.h"
#include "stack_alloc.h"
#include "os_support.h"
/************************/
/* Decoder Super Struct */
@@ -84,13 +85,15 @@ opus_int silk_Decode( /* O Returns error co
opus_int newPacketFlag, /* I Indicates first decoder call for this packet */
ec_dec *psRangeDec, /* I/O Compressor data structure */
opus_int16 *samplesOut, /* O Decoded output speech vector */
opus_int32 *nSamplesOut /* O Number of samples decoded */
opus_int32 *nSamplesOut, /* O Number of samples decoded */
int arch /* I Run-time architecture */
)
{
opus_int i, n, decode_only_middle = 0, ret = SILK_NO_ERROR;
opus_int32 nSamplesOutDec, LBRR_symbol;
opus_int16 *samplesOut1_tmp[ 2 ];
VARDECL( opus_int16, samplesOut1_tmp_storage );
VARDECL( opus_int16, samplesOut1_tmp_storage1 );
VARDECL( opus_int16, samplesOut1_tmp_storage2 );
VARDECL( opus_int16, samplesOut2_tmp );
opus_int32 MS_pred_Q13[ 2 ] = { 0 };
opus_int16 *resample_out_ptr;
@@ -98,6 +101,7 @@ opus_int silk_Decode( /* O Returns error co
silk_decoder_state *channel_state = psDec->channel_state;
opus_int has_side;
opus_int stereo_to_mono;
int delay_stack_alloc;
SAVE_STACK;
silk_assert( decControl->nChannelsInternal == 1 || decControl->nChannelsInternal == 2 );
@@ -196,7 +200,7 @@ opus_int silk_Decode( /* O Returns error co
for( i = 0; i < channel_state[ 0 ].nFramesPerPacket; i++ ) {
for( n = 0; n < decControl->nChannelsInternal; n++ ) {
if( channel_state[ n ].LBRR_flags[ i ] ) {
opus_int pulses[ MAX_FRAME_LENGTH ];
opus_int16 pulses[ MAX_FRAME_LENGTH ];
opus_int condCoding;
if( decControl->nChannelsInternal == 2 && n == 0 ) {
@@ -251,13 +255,22 @@ opus_int silk_Decode( /* O Returns error co
psDec->channel_state[ 1 ].first_frame_after_reset = 1;
}
ALLOC( samplesOut1_tmp_storage,
decControl->nChannelsInternal*(
channel_state[ 0 ].frame_length + 2 ),
/* Check if the temp buffer fits into the output PCM buffer. If it fits,
we can delay allocating the temp buffer until after the SILK peak stack
usage. We need to use a < and not a <= because of the two extra samples. */
delay_stack_alloc = decControl->internalSampleRate*decControl->nChannelsInternal
< decControl->API_sampleRate*decControl->nChannelsAPI;
ALLOC( samplesOut1_tmp_storage1, delay_stack_alloc ? ALLOC_NONE
: decControl->nChannelsInternal*(channel_state[ 0 ].frame_length + 2 ),
opus_int16 );
samplesOut1_tmp[ 0 ] = samplesOut1_tmp_storage;
samplesOut1_tmp[ 1 ] = samplesOut1_tmp_storage
+ channel_state[ 0 ].frame_length + 2;
if ( delay_stack_alloc )
{
samplesOut1_tmp[ 0 ] = samplesOut;
samplesOut1_tmp[ 1 ] = samplesOut + channel_state[ 0 ].frame_length + 2;
} else {
samplesOut1_tmp[ 0 ] = samplesOut1_tmp_storage1;
samplesOut1_tmp[ 1 ] = samplesOut1_tmp_storage1 + channel_state[ 0 ].frame_length + 2;
}
if( lostFlag == FLAG_DECODE_NORMAL ) {
has_side = !decode_only_middle;
@@ -284,7 +297,7 @@ opus_int silk_Decode( /* O Returns error co
} else {
condCoding = CODE_CONDITIONALLY;
}
ret += silk_decode_frame( &channel_state[ n ], psRangeDec, &samplesOut1_tmp[ n ][ 2 ], &nSamplesOutDec, lostFlag, condCoding);
ret += silk_decode_frame( &channel_state[ n ], psRangeDec, &samplesOut1_tmp[ n ][ 2 ], &nSamplesOutDec, lostFlag, condCoding, arch);
} else {
silk_memset( &samplesOut1_tmp[ n ][ 2 ], 0, nSamplesOutDec * sizeof( opus_int16 ) );
}
@@ -312,6 +325,15 @@ opus_int silk_Decode( /* O Returns error co
resample_out_ptr = samplesOut;
}
ALLOC( samplesOut1_tmp_storage2, delay_stack_alloc
? decControl->nChannelsInternal*(channel_state[ 0 ].frame_length + 2 )
: ALLOC_NONE,
opus_int16 );
if ( delay_stack_alloc ) {
OPUS_COPY(samplesOut1_tmp_storage2, samplesOut, decControl->nChannelsInternal*(channel_state[ 0 ].frame_length + 2));
samplesOut1_tmp[ 0 ] = samplesOut1_tmp_storage2;
samplesOut1_tmp[ 1 ] = samplesOut1_tmp_storage2 + channel_state[ 0 ].frame_length + 2;
}
for( n = 0; n < silk_min( decControl->nChannelsAPI, decControl->nChannelsInternal ); n++ ) {
/* Resample decoded signal to API_sampleRate */
+4 -3
View File
@@ -39,7 +39,8 @@ void silk_decode_core(
silk_decoder_state *psDec, /* I/O Decoder state */
silk_decoder_control *psDecCtrl, /* I Decoder control */
opus_int16 xq[], /* O Decoded speech */
const opus_int pulses[ MAX_FRAME_LENGTH ] /* I Pulse signal */
const opus_int16 pulses[ MAX_FRAME_LENGTH ], /* I Pulse signal */
int arch /* I Run-time architecture */
)
{
opus_int i, k, lag = 0, start_idx, sLTP_buf_idx, NLSF_interpolation_flag, signalType;
@@ -147,7 +148,7 @@ void silk_decode_core(
}
silk_LPC_analysis_filter( &sLTP[ start_idx ], &psDec->outBuf[ start_idx + k * psDec->subfr_length ],
A_Q12, psDec->ltp_mem_length - start_idx, psDec->LPC_order );
A_Q12, psDec->ltp_mem_length - start_idx, psDec->LPC_order, arch );
/* After rewhitening the LTP state is unscaled */
if( k == 0 ) {
@@ -218,7 +219,7 @@ void silk_decode_core(
}
/* Add prediction to LPC excitation */
sLPC_Q14[ MAX_LPC_ORDER + i ] = silk_ADD_LSHIFT32( pres_Q14[ i ], LPC_pred_Q10, 4 );
sLPC_Q14[ MAX_LPC_ORDER + i ] = silk_ADD_SAT32( pres_Q14[ i ], silk_LSHIFT_SAT32( LPC_pred_Q10, 4 ) );
/* Scale with gain */
pxq[ i ] = (opus_int16)silk_SAT16( silk_RSHIFT_ROUND( silk_SMULWW( sLPC_Q14[ MAX_LPC_ORDER + i ], Gain_Q10 ), 8 ) );
+13 -12
View File
@@ -42,18 +42,16 @@ opus_int silk_decode_frame(
opus_int16 pOut[], /* O Pointer to output speech frame */
opus_int32 *pN, /* O Pointer to size of output frame */
opus_int lostFlag, /* I 0: no loss, 1 loss, 2 decode fec */
opus_int condCoding /* I The type of conditional coding to use */
opus_int condCoding, /* I The type of conditional coding to use */
int arch /* I Run-time architecture */
)
{
VARDECL( silk_decoder_control, psDecCtrl );
opus_int L, mv_len, ret = 0;
VARDECL( opus_int, pulses );
SAVE_STACK;
L = psDec->frame_length;
ALLOC( psDecCtrl, 1, silk_decoder_control );
ALLOC( pulses, (L + SHELL_CODEC_FRAME_LENGTH - 1) &
~(SHELL_CODEC_FRAME_LENGTH - 1), opus_int );
psDecCtrl->LTP_scale_Q14 = 0;
/* Safety checks */
@@ -62,6 +60,9 @@ opus_int silk_decode_frame(
if( lostFlag == FLAG_DECODE_NORMAL ||
( lostFlag == FLAG_DECODE_LBRR && psDec->LBRR_flags[ psDec->nFramesDecoded ] == 1 ) )
{
VARDECL( opus_int16, pulses );
ALLOC( pulses, (L + SHELL_CODEC_FRAME_LENGTH - 1) &
~(SHELL_CODEC_FRAME_LENGTH - 1), opus_int16 );
/*********************************************/
/* Decode quantization indices of side info */
/*********************************************/
@@ -81,12 +82,12 @@ opus_int silk_decode_frame(
/********************************************************/
/* Run inverse NSQ */
/********************************************************/
silk_decode_core( psDec, psDecCtrl, pOut, pulses );
silk_decode_core( psDec, psDecCtrl, pOut, pulses, arch );
/********************************************************/
/* Update PLC state */
/********************************************************/
silk_PLC( psDec, psDecCtrl, pOut, 0 );
silk_PLC( psDec, psDecCtrl, pOut, 0, arch );
psDec->lossCnt = 0;
psDec->prevSignalType = psDec->indices.signalType;
@@ -96,7 +97,7 @@ opus_int silk_decode_frame(
psDec->first_frame_after_reset = 0;
} else {
/* Handle packet loss by extrapolation */
silk_PLC( psDec, psDecCtrl, pOut, 1 );
silk_PLC( psDec, psDecCtrl, pOut, 1, arch );
}
/*************************/
@@ -107,16 +108,16 @@ opus_int silk_decode_frame(
silk_memmove( psDec->outBuf, &psDec->outBuf[ psDec->frame_length ], mv_len * sizeof(opus_int16) );
silk_memcpy( &psDec->outBuf[ mv_len ], pOut, psDec->frame_length * sizeof( opus_int16 ) );
/****************************************************************/
/* Ensure smooth connection of extrapolated and good frames */
/****************************************************************/
silk_PLC_glue_frames( psDec, pOut, L );
/************************************************/
/* Comfort noise generation / estimation */
/************************************************/
silk_CNG( psDec, psDecCtrl, pOut, L );
/****************************************************************/
/* Ensure smooth connection of extrapolated and good frames */
/****************************************************************/
silk_PLC_glue_frames( psDec, pOut, L );
/* Update some decoder state variables */
psDec->lagPrev = psDecCtrl->pitchL[ psDec->nb_subfr - 1 ];
+5 -5
View File
@@ -36,7 +36,7 @@ POSSIBILITY OF SUCH DAMAGE.
/*********************************************/
void silk_decode_pulses(
ec_dec *psRangeDec, /* I/O Compressor data structure */
opus_int pulses[], /* O Excitation signal */
opus_int16 pulses[], /* O Excitation signal */
const opus_int signalType, /* I Sigtype */
const opus_int quantOffsetType, /* I quantOffsetType */
const opus_int frame_length /* I Frame length */
@@ -44,7 +44,7 @@ void silk_decode_pulses(
{
opus_int i, j, k, iter, abs_q, nLS, RateLevelIndex;
opus_int sum_pulses[ MAX_NB_SHELL_BLOCKS ], nLshifts[ MAX_NB_SHELL_BLOCKS ];
opus_int *pulses_ptr;
opus_int16 *pulses_ptr;
const opus_uint8 *cdf_ptr;
/*********************/
@@ -69,9 +69,9 @@ void silk_decode_pulses(
sum_pulses[ i ] = ec_dec_icdf( psRangeDec, cdf_ptr, 8 );
/* LSB indication */
while( sum_pulses[ i ] == MAX_PULSES + 1 ) {
while( sum_pulses[ i ] == SILK_MAX_PULSES + 1 ) {
nLshifts[ i ]++;
/* When we've already got 10 LSBs, we shift the table to not allow (MAX_PULSES + 1) */
/* When we've already got 10 LSBs, we shift the table to not allow (SILK_MAX_PULSES + 1) */
sum_pulses[ i ] = ec_dec_icdf( psRangeDec,
silk_pulses_per_block_iCDF[ N_RATE_LEVELS - 1] + ( nLshifts[ i ] == 10 ), 8 );
}
@@ -84,7 +84,7 @@ void silk_decode_pulses(
if( sum_pulses[ i ] > 0 ) {
silk_shell_decoder( &pulses[ silk_SMULBB( i, SHELL_CODEC_FRAME_LENGTH ) ], psRangeDec, sum_pulses[ i ] );
} else {
silk_memset( &pulses[ silk_SMULBB( i, SHELL_CODEC_FRAME_LENGTH ) ], 0, SHELL_CODEC_FRAME_LENGTH * sizeof( opus_int ) );
silk_memset( &pulses[ silk_SMULBB( i, SHELL_CODEC_FRAME_LENGTH ) ], 0, SHELL_CODEC_FRAME_LENGTH * sizeof( pulses[0] ) );
}
}
+1 -1
View File
@@ -169,7 +169,7 @@ extern "C"
#define N_RATE_LEVELS 10
/* Maximum sum of pulses per shell coding frame */
#define MAX_PULSES 16
#define SILK_MAX_PULSES 16
#define MAX_MATRIX_SIZE MAX_LPC_ORDER /* Max of LPC Order and LTP order */
+12 -5
View File
@@ -165,7 +165,7 @@ opus_int silk_Encode( /* O Returns error co
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 ) ) {
if( ( ret = check_control_input( encControl ) ) != 0 ) {
silk_assert( 0 );
RESTORE_STACK;
return ret;
@@ -376,26 +376,33 @@ opus_int silk_Encode( /* O Returns error co
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 half of the bits already used */
/* Subtract bits used for LBRR */
if( !prefillFlag ) {
nBits -= ec_tell( psRangeEnc ) >> 1;
nBits -= psEnc->nBitsUsedLBRR;
}
/* Divide by number of uncoded frames left in packet */
nBits = silk_DIV32_16( nBits, psEnc->state_Fxx[ 0 ].sCmn.nFramesPerPacket - psEnc->state_Fxx[ 0 ].sCmn.nFramesEncoded );
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 packets */
/* 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 );
+3 -3
View File
@@ -142,7 +142,7 @@ void silk_encode_pulses(
sumBits_Q5 = silk_rate_levels_BITS_Q5[ signalType >> 1 ][ k ];
for( i = 0; i < iter; i++ ) {
if( nRshifts[ i ] > 0 ) {
sumBits_Q5 += nBits_ptr[ MAX_PULSES + 1 ];
sumBits_Q5 += nBits_ptr[ SILK_MAX_PULSES + 1 ];
} else {
sumBits_Q5 += nBits_ptr[ sum_pulses[ i ] ];
}
@@ -162,9 +162,9 @@ void silk_encode_pulses(
if( nRshifts[ i ] == 0 ) {
ec_enc_icdf( psRangeEnc, sum_pulses[ i ], cdf_ptr, 8 );
} else {
ec_enc_icdf( psRangeEnc, MAX_PULSES + 1, cdf_ptr, 8 );
ec_enc_icdf( psRangeEnc, SILK_MAX_PULSES + 1, cdf_ptr, 8 );
for( k = 0; k < nRshifts[ i ] - 1; k++ ) {
ec_enc_icdf( psRangeEnc, MAX_PULSES + 1, silk_pulses_per_block_iCDF[ N_RATE_LEVELS - 1 ], 8 );
ec_enc_icdf( psRangeEnc, SILK_MAX_PULSES + 1, silk_pulses_per_block_iCDF[ N_RATE_LEVELS - 1 ], 8 );
}
ec_enc_icdf( psRangeEnc, sum_pulses[ i ], silk_pulses_per_block_iCDF[ N_RATE_LEVELS - 1 ], 8 );
}
+1 -1
View File
@@ -47,7 +47,7 @@ void silk_encode_do_VAD_FLP(
/****************************/
/* Voice Activity Detection */
/****************************/
silk_VAD_GetSA_Q8( &psEnc->sCmn, psEnc->sCmn.inputBuf + 1 );
silk_VAD_GetSA_Q8( &psEnc->sCmn, psEnc->sCmn.inputBuf + 1, psEnc->sCmn.arch );
/**************************************************/
/* Convert speech activity into VAD and DTX flags */
+1 -1
View File
@@ -99,6 +99,6 @@ void silk_find_LPC_FLP(
silk_A2NLSF_FLP( NLSF_Q15, a, psEncC->predictLPCOrder );
}
silk_assert( psEncC->indices.NLSFInterpCoef_Q2 == 4 ||
silk_assert( psEncC->indices.NLSFInterpCoef_Q2 == 4 ||
( psEncC->useInterpolatedNLSFs && !psEncC->first_frame_after_reset && psEncC->nb_subfr == MAX_NB_SUBFR ) );
}
@@ -67,7 +67,8 @@ void silk_find_pred_coefs_FLP(
/* Quantize LTP gain parameters */
silk_quant_LTP_gains_FLP( psEncCtrl->LTPCoef, psEnc->sCmn.indices.LTPIndex, &psEnc->sCmn.indices.PERIndex,
&psEnc->sCmn.sum_log_gain_Q7, WLTP, psEnc->sCmn.mu_LTP_Q9, psEnc->sCmn.LTPQuantLowComplexity, psEnc->sCmn.nb_subfr );
&psEnc->sCmn.sum_log_gain_Q7, WLTP, psEnc->sCmn.mu_LTP_Q9, psEnc->sCmn.LTPQuantLowComplexity, psEnc->sCmn.nb_subfr,
psEnc->sCmn.arch );
/* Control LTP scaling */
silk_LTP_scale_ctrl_FLP( psEnc, psEncCtrl, condCoding );
@@ -90,13 +91,13 @@ void silk_find_pred_coefs_FLP(
}
silk_memset( psEncCtrl->LTPCoef, 0, psEnc->sCmn.nb_subfr * LTP_ORDER * sizeof( silk_float ) );
psEncCtrl->LTPredCodGain = 0.0f;
psEnc->sCmn.sum_log_gain_Q7 = 0;
psEnc->sCmn.sum_log_gain_Q7 = 0;
}
/* Limit on total predictive coding gain */
if( psEnc->sCmn.first_frame_after_reset ) {
minInvGain = 1.0f / MAX_PREDICTION_POWER_GAIN_AFTER_RESET;
} else {
} else {
minInvGain = (silk_float)pow( 2, psEncCtrl->LTPredCodGain / 3 ) / MAX_PREDICTION_POWER_GAIN;
minInvGain /= 0.25f + 0.75f * psEncCtrl->coding_quality;
}
+2 -1
View File
@@ -205,7 +205,8 @@ void silk_quant_LTP_gains_FLP(
const silk_float W[ MAX_NB_SUBFR * LTP_ORDER * LTP_ORDER ], /* I Error weights */
const opus_int mu_Q10, /* I Mu value (R/D tradeoff) */
const opus_int lowComplexity, /* I Flag for low complexity */
const opus_int nb_subfr /* I number of subframes */
const opus_int nb_subfr, /* I number of subframes */
int arch /* I Run-time architecture */
);
/* Residual energy: nrg = wxx - 2 * wXx * c + c' * wXX * c */
@@ -182,8 +182,8 @@ opus_int silk_pitch_analysis_core_FLP( /* O Voicing estimate: 0 voiced,
/* Calculate first vector products before loop */
cross_corr = xcorr[ max_lag_4kHz - min_lag_4kHz ];
normalizer = silk_energy_FLP( target_ptr, sf_length_8kHz ) +
silk_energy_FLP( basis_ptr, sf_length_8kHz ) +
normalizer = silk_energy_FLP( target_ptr, sf_length_8kHz ) +
silk_energy_FLP( basis_ptr, sf_length_8kHz ) +
sf_length_8kHz * 4000.0f;
C[ 0 ][ min_lag_4kHz ] += (silk_float)( 2 * cross_corr / normalizer );
+1
View File
@@ -115,6 +115,7 @@ typedef struct {
typedef struct {
silk_encoder_state_FLP state_Fxx[ ENCODER_NUM_CHANNELS ];
stereo_enc_state sStereo;
opus_int32 nBitsUsedLBRR;
opus_int32 nBitsExceeded;
opus_int nChannelsAPI;
opus_int nChannelsInternal;
+5 -4
View File
@@ -161,10 +161,10 @@ void silk_NSQ_wrapper_FLP(
/* Call NSQ */
if( psEnc->sCmn.nStatesDelayedDecision > 1 || psEnc->sCmn.warping_Q16 > 0 ) {
silk_NSQ_del_dec( &psEnc->sCmn, psNSQ, psIndices, x_Q3, pulses, PredCoef_Q12[ 0 ], LTPCoef_Q14,
AR2_Q13, HarmShapeGain_Q14, Tilt_Q14, LF_shp_Q14, Gains_Q16, psEncCtrl->pitchL, Lambda_Q10, LTP_scale_Q14 );
AR2_Q13, HarmShapeGain_Q14, Tilt_Q14, LF_shp_Q14, Gains_Q16, psEncCtrl->pitchL, Lambda_Q10, LTP_scale_Q14, psEnc->sCmn.arch );
} else {
silk_NSQ( &psEnc->sCmn, psNSQ, psIndices, x_Q3, pulses, PredCoef_Q12[ 0 ], LTPCoef_Q14,
AR2_Q13, HarmShapeGain_Q14, Tilt_Q14, LF_shp_Q14, Gains_Q16, psEncCtrl->pitchL, Lambda_Q10, LTP_scale_Q14 );
AR2_Q13, HarmShapeGain_Q14, Tilt_Q14, LF_shp_Q14, Gains_Q16, psEncCtrl->pitchL, Lambda_Q10, LTP_scale_Q14, psEnc->sCmn.arch );
}
}
@@ -179,7 +179,8 @@ void silk_quant_LTP_gains_FLP(
const silk_float W[ MAX_NB_SUBFR * LTP_ORDER * LTP_ORDER ], /* I Error weights */
const opus_int mu_Q10, /* I Mu value (R/D tradeoff) */
const opus_int lowComplexity, /* I Flag for low complexity */
const opus_int nb_subfr /* I number of subframes */
const opus_int nb_subfr, /* I number of subframes */
int arch /* I Run-time architecture */
)
{
opus_int i;
@@ -193,7 +194,7 @@ void silk_quant_LTP_gains_FLP(
W_Q18[ i ] = (opus_int32)silk_float2int( W[ i ] * 262144.0f );
}
silk_quant_LTP_gains( B_Q14, cbk_index, periodicity_index, sum_log_gain_Q7, W_Q18, mu_Q10, lowComplexity, nb_subfr );
silk_quant_LTP_gains( B_Q14, cbk_index, periodicity_index, sum_log_gain_Q7, W_Q18, mu_Q10, lowComplexity, nb_subfr, arch );
for( i = 0; i < nb_subfr * LTP_ORDER; i++ ) {
B[ i ] = (silk_float)B_Q14[ i ] * ( 1.0f / 16384.0f );
+3 -3
View File
@@ -33,7 +33,7 @@ POSSIBILITY OF SUCH DAMAGE.
/* Approximation of 2^() (very close inverse of silk_lin2log()) */
/* Convert input to a linear scale */
opus_int32 silk_log2lin(
opus_int32 silk_log2lin(
const opus_int32 inLog_Q7 /* I input on log scale */
)
{
@@ -42,8 +42,8 @@ opus_int32 silk_log2lin(
if( inLog_Q7 < 0 ) {
return 0;
} else if ( inLog_Q7 >= 3967 ) {
return silk_int32_MAX;
}
return silk_int32_MAX;
}
out = silk_LSHIFT( 1, silk_RSHIFT( inLog_Q7, 7 ) );
frac_Q7 = inLog_Q7 & 0x7F;
+45 -1
View File
@@ -34,20 +34,45 @@ POSSIBILITY OF SUCH DAMAGE.
#include "opus_types.h"
#include "opus_defines.h"
#include "arch.h"
#if OPUS_GNUC_PREREQ(3, 0)
#define opus_likely(x) (__builtin_expect(!!(x), 1))
#define opus_unlikely(x) (__builtin_expect(!!(x), 0))
#else
#define opus_likely(x) (!!(x))
#define opus_unlikely(x) (!!(x))
#endif
/* This is an OPUS_INLINE header file for general platform. */
/* (a32 * (opus_int32)((opus_int16)(b32))) >> 16 output have to be 32bit int */
#if OPUS_FAST_INT64
#define silk_SMULWB(a32, b32) ((opus_int32)(((a32) * (opus_int64)((opus_int16)(b32))) >> 16))
#else
#define silk_SMULWB(a32, b32) ((((a32) >> 16) * (opus_int32)((opus_int16)(b32))) + ((((a32) & 0x0000FFFF) * (opus_int32)((opus_int16)(b32))) >> 16))
#endif
/* a32 + (b32 * (opus_int32)((opus_int16)(c32))) >> 16 output have to be 32bit int */
#if OPUS_FAST_INT64
#define silk_SMLAWB(a32, b32, c32) ((opus_int32)((a32) + (((b32) * (opus_int64)((opus_int16)(c32))) >> 16)))
#else
#define silk_SMLAWB(a32, b32, c32) ((a32) + ((((b32) >> 16) * (opus_int32)((opus_int16)(c32))) + ((((b32) & 0x0000FFFF) * (opus_int32)((opus_int16)(c32))) >> 16)))
#endif
/* (a32 * (b32 >> 16)) >> 16 */
#if OPUS_FAST_INT64
#define silk_SMULWT(a32, b32) ((opus_int32)(((a32) * (opus_int64)((b32) >> 16)) >> 16))
#else
#define silk_SMULWT(a32, b32) (((a32) >> 16) * ((b32) >> 16) + ((((a32) & 0x0000FFFF) * ((b32) >> 16)) >> 16))
#endif
/* a32 + (b32 * (c32 >> 16)) >> 16 */
#if OPUS_FAST_INT64
#define silk_SMLAWT(a32, b32, c32) ((opus_int32)((a32) + (((b32) * ((opus_int64)(c32) >> 16)) >> 16)))
#else
#define silk_SMLAWT(a32, b32, c32) ((a32) + (((b32) >> 16) * ((c32) >> 16)) + ((((b32) & 0x0000FFFF) * ((c32) >> 16)) >> 16))
#endif
/* (opus_int32)((opus_int16)(a3))) * (opus_int32)((opus_int16)(b32)) output have to be 32bit int */
#define silk_SMULBB(a32, b32) ((opus_int32)((opus_int16)(a32)) * (opus_int32)((opus_int16)(b32)))
@@ -65,10 +90,18 @@ POSSIBILITY OF SUCH DAMAGE.
#define silk_SMLAL(a64, b32, c32) (silk_ADD64((a64), ((opus_int64)(b32) * (opus_int64)(c32))))
/* (a32 * b32) >> 16 */
#if OPUS_FAST_INT64
#define silk_SMULWW(a32, b32) ((opus_int32)(((opus_int64)(a32) * (b32)) >> 16))
#else
#define silk_SMULWW(a32, b32) silk_MLA(silk_SMULWB((a32), (b32)), (a32), silk_RSHIFT_ROUND((b32), 16))
#endif
/* a32 + ((b32 * c32) >> 16) */
#if OPUS_FAST_INT64
#define silk_SMLAWW(a32, b32, c32) ((opus_int32)((a32) + (((opus_int64)(b32) * (c32)) >> 16)))
#else
#define silk_SMLAWW(a32, b32, c32) silk_MLA(silk_SMLAWB((a32), (b32), (c32)), (b32), silk_RSHIFT_ROUND((c32), 16))
#endif
/* add/subtract with output saturated */
#define silk_ADD_SAT32(a, b) ((((opus_uint32)(a) + (opus_uint32)(b)) & 0x80000000) == 0 ? \
@@ -79,17 +112,24 @@ POSSIBILITY OF SUCH DAMAGE.
(( (a) & ((b)^0x80000000) & 0x80000000) ? silk_int32_MIN : (a)-(b)) : \
((((a)^0x80000000) & (b) & 0x80000000) ? silk_int32_MAX : (a)-(b)) )
#include "ecintrin.h"
#if defined(MIPSr1_ASM)
#include "mips/macros_mipsr1.h"
#endif
#include "ecintrin.h"
#ifndef OVERRIDE_silk_CLZ16
static OPUS_INLINE opus_int32 silk_CLZ16(opus_int16 in16)
{
return 32 - EC_ILOG(in16<<16|0x8000);
}
#endif
#ifndef OVERRIDE_silk_CLZ32
static OPUS_INLINE opus_int32 silk_CLZ32(opus_int32 in32)
{
return in32 ? 32 - EC_ILOG(in32) : 32;
}
#endif
/* Row based */
#define matrix_ptr(Matrix_base_adr, row, column, N) \
@@ -111,5 +151,9 @@ static OPUS_INLINE opus_int32 silk_CLZ32(opus_int32 in32)
#include "arm/macros_armv5e.h"
#endif
#ifdef OPUS_ARM_PRESUME_AARCH64_NEON_INTR
#include "arm/macros_arm64.h"
#endif
#endif /* SILK_MACROS_H */
+44 -11
View File
@@ -38,6 +38,10 @@ POSSIBILITY OF SUCH DAMAGE.
#include "entenc.h"
#include "entdec.h"
#if defined(OPUS_X86_MAY_HAVE_SSE4_1)
#include "x86/main_sse.h"
#endif
/* Convert Left/Right stereo signal to adaptive Mid/Side representation */
void silk_stereo_LR_to_MS(
stereo_enc_state *state, /* I/O State */
@@ -116,7 +120,7 @@ void silk_encode_signs(
/* Decodes signs of excitation */
void silk_decode_signs(
ec_dec *psRangeDec, /* I/O Compressor data structure */
opus_int pulses[], /* I/O pulse signal */
opus_int16 pulses[], /* I/O pulse signal */
opus_int length, /* I length of input */
const opus_int signalType, /* I Signal type */
const opus_int quantOffsetType, /* I Quantization offset type */
@@ -161,7 +165,7 @@ void silk_shell_encoder(
/* Shell decoder, operates on one shell code frame of 16 pulses */
void silk_shell_decoder(
opus_int *pulses0, /* O data: nonnegative pulse amplitudes */
opus_int16 *pulses0, /* O data: nonnegative pulse amplitudes */
ec_dec *psRangeDec, /* I/O Compressor data structure */
const opus_int pulses4 /* I number of pulses per pulse-subframe */
);
@@ -204,15 +208,16 @@ void silk_quant_LTP_gains(
opus_int16 B_Q14[ MAX_NB_SUBFR * LTP_ORDER ], /* I/O (un)quantized LTP gains */
opus_int8 cbk_index[ MAX_NB_SUBFR ], /* O Codebook Index */
opus_int8 *periodicity_index, /* O Periodicity Index */
opus_int32 *sum_gain_dB_Q7, /* I/O Cumulative max prediction gain */
opus_int32 *sum_gain_dB_Q7, /* I/O Cumulative max prediction gain */
const opus_int32 W_Q18[ MAX_NB_SUBFR*LTP_ORDER*LTP_ORDER ], /* I Error Weights in Q18 */
opus_int mu_Q9, /* I Mu value (R/D tradeoff) */
opus_int lowComplexity, /* I Flag for low complexity */
const opus_int nb_subfr /* I number of subframes */
const opus_int nb_subfr, /* I number of subframes */
int arch /* I Run-time architecture */
);
/* Entropy constrained matrix-weighted VQ, for a single input data vector */
void silk_VQ_WMat_EC(
void silk_VQ_WMat_EC_c(
opus_int8 *ind, /* O index of best codebook vector */
opus_int32 *rate_dist_Q14, /* O best weighted quant error + mu * rate */
opus_int *gain_Q7, /* O sum of absolute LTP coefficients */
@@ -226,10 +231,18 @@ void silk_VQ_WMat_EC(
opus_int L /* I number of vectors in codebook */
);
#if !defined(OVERRIDE_silk_VQ_WMat_EC)
#define silk_VQ_WMat_EC(ind, rate_dist_Q14, gain_Q7, in_Q14, W_Q18, cb_Q7, cb_gain_Q7, cl_Q5, \
mu_Q9, max_gain_Q7, L, arch) \
((void)(arch),silk_VQ_WMat_EC_c(ind, rate_dist_Q14, gain_Q7, in_Q14, W_Q18, cb_Q7, cb_gain_Q7, cl_Q5, \
mu_Q9, max_gain_Q7, L))
#endif
/************************************/
/* Noise shaping quantization (NSQ) */
/************************************/
void silk_NSQ(
void silk_NSQ_c(
const silk_encoder_state *psEncC, /* I/O Encoder State */
silk_nsq_state *NSQ, /* I/O NSQ state */
SideInfoIndices *psIndices, /* I/O Quantization Indices */
@@ -247,8 +260,15 @@ void silk_NSQ(
const opus_int LTP_scale_Q14 /* I LTP state scaling */
);
#if !defined(OVERRIDE_silk_NSQ)
#define silk_NSQ(psEncC, NSQ, psIndices, x_Q3, pulses, PredCoef_Q12, LTPCoef_Q14, AR2_Q13, \
HarmShapeGain_Q14, Tilt_Q14, LF_shp_Q14, Gains_Q16, pitchL, Lambda_Q10, LTP_scale_Q14, arch) \
((void)(arch),silk_NSQ_c(psEncC, NSQ, psIndices, x_Q3, pulses, PredCoef_Q12, LTPCoef_Q14, AR2_Q13, \
HarmShapeGain_Q14, Tilt_Q14, LF_shp_Q14, Gains_Q16, pitchL, Lambda_Q10, LTP_scale_Q14))
#endif
/* Noise shaping using delayed decision */
void silk_NSQ_del_dec(
void silk_NSQ_del_dec_c(
const silk_encoder_state *psEncC, /* I/O Encoder State */
silk_nsq_state *NSQ, /* I/O NSQ state */
SideInfoIndices *psIndices, /* I/O Quantization Indices */
@@ -266,6 +286,13 @@ void silk_NSQ_del_dec(
const opus_int LTP_scale_Q14 /* I LTP state scaling */
);
#if !defined(OVERRIDE_silk_NSQ_del_dec)
#define silk_NSQ_del_dec(psEncC, NSQ, psIndices, x_Q3, pulses, PredCoef_Q12, LTPCoef_Q14, AR2_Q13, \
HarmShapeGain_Q14, Tilt_Q14, LF_shp_Q14, Gains_Q16, pitchL, Lambda_Q10, LTP_scale_Q14, arch) \
((void)(arch),silk_NSQ_del_dec_c(psEncC, NSQ, psIndices, x_Q3, pulses, PredCoef_Q12, LTPCoef_Q14, AR2_Q13, \
HarmShapeGain_Q14, Tilt_Q14, LF_shp_Q14, Gains_Q16, pitchL, Lambda_Q10, LTP_scale_Q14))
#endif
/************/
/* Silk VAD */
/************/
@@ -275,11 +302,15 @@ opus_int silk_VAD_Init( /* O Return v
);
/* Get speech activity level in Q8 */
opus_int silk_VAD_GetSA_Q8( /* O Return value, 0 if success */
opus_int silk_VAD_GetSA_Q8_c( /* O Return value, 0 if success */
silk_encoder_state *psEncC, /* I/O Encoder state */
const opus_int16 pIn[] /* I PCM input */
);
#if !defined(OVERRIDE_silk_VAD_GetSA_Q8)
#define silk_VAD_GetSA_Q8(psEnC, pIn, arch) ((void)(arch),silk_VAD_GetSA_Q8_c(psEnC, pIn))
#endif
/* Low-pass filter with variable cutoff frequency based on */
/* piece-wise linear interpolation between elliptic filters */
/* Start by setting transition_frame_no = 1; */
@@ -373,7 +404,8 @@ opus_int silk_decode_frame(
opus_int16 pOut[], /* O Pointer to output speech frame */
opus_int32 *pN, /* O Pointer to size of output frame */
opus_int lostFlag, /* I 0: no loss, 1 loss, 2 decode fec */
opus_int condCoding /* I The type of conditional coding to use */
opus_int condCoding, /* I The type of conditional coding to use */
int arch /* I Run-time architecture */
);
/* Decode indices from bitstream */
@@ -397,13 +429,14 @@ void silk_decode_core(
silk_decoder_state *psDec, /* I/O Decoder state */
silk_decoder_control *psDecCtrl, /* I Decoder control */
opus_int16 xq[], /* O Decoded speech */
const opus_int pulses[ MAX_FRAME_LENGTH ] /* I Pulse signal */
const opus_int16 pulses[ MAX_FRAME_LENGTH ], /* I Pulse signal */
int arch /* I Run-time architecture */
);
/* Decode quantization indices of excitation (Shell coding) */
void silk_decode_pulses(
ec_dec *psRangeDec, /* I/O Compressor data structure */
opus_int pulses[], /* O Excitation signal */
opus_int16 pulses[], /* O Excitation signal */
const opus_int signalType, /* I Sigtype */
const opus_int quantOffsetType, /* I quantOffsetType */
const opus_int frame_length /* I Frame length */
@@ -0,0 +1,409 @@
/***********************************************************************
Copyright (c) 2006-2011, Skype Limited. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
- Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
- Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
- Neither the name of Internet Society, IETF or IETF Trust, nor the
names of specific contributors, may be used to endorse or promote
products derived from this software without specific prior written
permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
***********************************************************************/
#ifndef __NSQ_DEL_DEC_MIPSR1_H__
#define __NSQ_DEL_DEC_MIPSR1_H__
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include "main.h"
#include "stack_alloc.h"
#define OVERRIDE_silk_noise_shape_quantizer_del_dec
static inline void silk_noise_shape_quantizer_del_dec(
silk_nsq_state *NSQ, /* I/O NSQ state */
NSQ_del_dec_struct psDelDec[], /* I/O Delayed decision states */
opus_int signalType, /* I Signal type */
const opus_int32 x_Q10[], /* I */
opus_int8 pulses[], /* O */
opus_int16 xq[], /* O */
opus_int32 sLTP_Q15[], /* I/O LTP filter state */
opus_int32 delayedGain_Q10[], /* I/O Gain delay buffer */
const opus_int16 a_Q12[], /* I Short term prediction coefs */
const opus_int16 b_Q14[], /* I Long term prediction coefs */
const opus_int16 AR_shp_Q13[], /* I Noise shaping coefs */
opus_int lag, /* I Pitch lag */
opus_int32 HarmShapeFIRPacked_Q14, /* I */
opus_int Tilt_Q14, /* I Spectral tilt */
opus_int32 LF_shp_Q14, /* I */
opus_int32 Gain_Q16, /* I */
opus_int Lambda_Q10, /* I */
opus_int offset_Q10, /* I */
opus_int length, /* I Input length */
opus_int subfr, /* I Subframe number */
opus_int shapingLPCOrder, /* I Shaping LPC filter order */
opus_int predictLPCOrder, /* I Prediction filter order */
opus_int warping_Q16, /* I */
opus_int nStatesDelayedDecision, /* I Number of states in decision tree */
opus_int *smpl_buf_idx, /* I Index to newest samples in buffers */
opus_int decisionDelay, /* I */
int arch /* I */
)
{
opus_int i, j, k, Winner_ind, RDmin_ind, RDmax_ind, last_smple_idx;
opus_int32 Winner_rand_state;
opus_int32 LTP_pred_Q14, LPC_pred_Q14, n_AR_Q14, n_LTP_Q14;
opus_int32 n_LF_Q14, r_Q10, rr_Q10, rd1_Q10, rd2_Q10, RDmin_Q10, RDmax_Q10;
opus_int32 q1_Q0, q1_Q10, q2_Q10, exc_Q14, LPC_exc_Q14, xq_Q14, Gain_Q10;
opus_int32 tmp1, tmp2, sLF_AR_shp_Q14;
opus_int32 *pred_lag_ptr, *shp_lag_ptr, *psLPC_Q14;
NSQ_sample_struct psSampleState[ MAX_DEL_DEC_STATES ][ 2 ];
NSQ_del_dec_struct *psDD;
NSQ_sample_struct *psSS;
opus_int16 b_Q14_0, b_Q14_1, b_Q14_2, b_Q14_3, b_Q14_4;
opus_int16 a_Q12_0, a_Q12_1, a_Q12_2, a_Q12_3, a_Q12_4, a_Q12_5, a_Q12_6;
opus_int16 a_Q12_7, a_Q12_8, a_Q12_9, a_Q12_10, a_Q12_11, a_Q12_12, a_Q12_13;
opus_int16 a_Q12_14, a_Q12_15;
opus_int32 cur, prev, next;
/*Unused.*/
(void)arch;
//Intialize b_Q14 variables
b_Q14_0 = b_Q14[ 0 ];
b_Q14_1 = b_Q14[ 1 ];
b_Q14_2 = b_Q14[ 2 ];
b_Q14_3 = b_Q14[ 3 ];
b_Q14_4 = b_Q14[ 4 ];
//Intialize a_Q12 variables
a_Q12_0 = a_Q12[0];
a_Q12_1 = a_Q12[1];
a_Q12_2 = a_Q12[2];
a_Q12_3 = a_Q12[3];
a_Q12_4 = a_Q12[4];
a_Q12_5 = a_Q12[5];
a_Q12_6 = a_Q12[6];
a_Q12_7 = a_Q12[7];
a_Q12_8 = a_Q12[8];
a_Q12_9 = a_Q12[9];
a_Q12_10 = a_Q12[10];
a_Q12_11 = a_Q12[11];
a_Q12_12 = a_Q12[12];
a_Q12_13 = a_Q12[13];
a_Q12_14 = a_Q12[14];
a_Q12_15 = a_Q12[15];
long long temp64;
silk_assert( nStatesDelayedDecision > 0 );
shp_lag_ptr = &NSQ->sLTP_shp_Q14[ NSQ->sLTP_shp_buf_idx - lag + HARM_SHAPE_FIR_TAPS / 2 ];
pred_lag_ptr = &sLTP_Q15[ NSQ->sLTP_buf_idx - lag + LTP_ORDER / 2 ];
Gain_Q10 = silk_RSHIFT( Gain_Q16, 6 );
for( i = 0; i < length; i++ ) {
/* Perform common calculations used in all states */
/* Long-term prediction */
if( signalType == TYPE_VOICED ) {
/* Unrolled loop */
/* Avoids introducing a bias because silk_SMLAWB() always rounds to -inf */
temp64 = __builtin_mips_mult(pred_lag_ptr[ 0 ], b_Q14_0 );
temp64 = __builtin_mips_madd( temp64, pred_lag_ptr[ -1 ], b_Q14_1 );
temp64 = __builtin_mips_madd( temp64, pred_lag_ptr[ -2 ], b_Q14_2 );
temp64 = __builtin_mips_madd( temp64, pred_lag_ptr[ -3 ], b_Q14_3 );
temp64 = __builtin_mips_madd( temp64, pred_lag_ptr[ -4 ], b_Q14_4 );
temp64 += 32768;
LTP_pred_Q14 = __builtin_mips_extr_w(temp64, 16);
LTP_pred_Q14 = silk_LSHIFT( LTP_pred_Q14, 1 ); /* Q13 -> Q14 */
pred_lag_ptr++;
} else {
LTP_pred_Q14 = 0;
}
/* Long-term shaping */
if( lag > 0 ) {
/* Symmetric, packed FIR coefficients */
n_LTP_Q14 = silk_SMULWB( silk_ADD32( shp_lag_ptr[ 0 ], shp_lag_ptr[ -2 ] ), HarmShapeFIRPacked_Q14 );
n_LTP_Q14 = silk_SMLAWT( n_LTP_Q14, shp_lag_ptr[ -1 ], HarmShapeFIRPacked_Q14 );
n_LTP_Q14 = silk_SUB_LSHIFT32( LTP_pred_Q14, n_LTP_Q14, 2 ); /* Q12 -> Q14 */
shp_lag_ptr++;
} else {
n_LTP_Q14 = 0;
}
for( k = 0; k < nStatesDelayedDecision; k++ ) {
/* Delayed decision state */
psDD = &psDelDec[ k ];
/* Sample state */
psSS = psSampleState[ k ];
/* Generate dither */
psDD->Seed = silk_RAND( psDD->Seed );
/* Pointer used in short term prediction and shaping */
psLPC_Q14 = &psDD->sLPC_Q14[ NSQ_LPC_BUF_LENGTH - 1 + i ];
/* Short-term prediction */
silk_assert( predictLPCOrder == 10 || predictLPCOrder == 16 );
temp64 = __builtin_mips_mult(psLPC_Q14[ 0 ], a_Q12_0 );
temp64 = __builtin_mips_madd( temp64, psLPC_Q14[ -1 ], a_Q12_1 );
temp64 = __builtin_mips_madd( temp64, psLPC_Q14[ -2 ], a_Q12_2 );
temp64 = __builtin_mips_madd( temp64, psLPC_Q14[ -3 ], a_Q12_3 );
temp64 = __builtin_mips_madd( temp64, psLPC_Q14[ -4 ], a_Q12_4 );
temp64 = __builtin_mips_madd( temp64, psLPC_Q14[ -5 ], a_Q12_5 );
temp64 = __builtin_mips_madd( temp64, psLPC_Q14[ -6 ], a_Q12_6 );
temp64 = __builtin_mips_madd( temp64, psLPC_Q14[ -7 ], a_Q12_7 );
temp64 = __builtin_mips_madd( temp64, psLPC_Q14[ -8 ], a_Q12_8 );
temp64 = __builtin_mips_madd( temp64, psLPC_Q14[ -9 ], a_Q12_9 );
if( predictLPCOrder == 16 ) {
temp64 = __builtin_mips_madd( temp64, psLPC_Q14[ -10 ], a_Q12_10 );
temp64 = __builtin_mips_madd( temp64, psLPC_Q14[ -11 ], a_Q12_11 );
temp64 = __builtin_mips_madd( temp64, psLPC_Q14[ -12 ], a_Q12_12 );
temp64 = __builtin_mips_madd( temp64, psLPC_Q14[ -13 ], a_Q12_13 );
temp64 = __builtin_mips_madd( temp64, psLPC_Q14[ -14 ], a_Q12_14 );
temp64 = __builtin_mips_madd( temp64, psLPC_Q14[ -15 ], a_Q12_15 );
}
temp64 += 32768;
LPC_pred_Q14 = __builtin_mips_extr_w(temp64, 16);
LPC_pred_Q14 = silk_LSHIFT( LPC_pred_Q14, 4 ); /* Q10 -> Q14 */
/* Noise shape feedback */
silk_assert( ( shapingLPCOrder & 1 ) == 0 ); /* check that order is even */
/* Output of lowpass section */
tmp2 = silk_SMLAWB( psLPC_Q14[ 0 ], psDD->sAR2_Q14[ 0 ], warping_Q16 );
/* Output of allpass section */
tmp1 = silk_SMLAWB( psDD->sAR2_Q14[ 0 ], psDD->sAR2_Q14[ 1 ] - tmp2, warping_Q16 );
psDD->sAR2_Q14[ 0 ] = tmp2;
temp64 = __builtin_mips_mult(tmp2, AR_shp_Q13[ 0 ] );
prev = psDD->sAR2_Q14[ 1 ];
/* Loop over allpass sections */
for( j = 2; j < shapingLPCOrder; j += 2 ) {
cur = psDD->sAR2_Q14[ j ];
next = psDD->sAR2_Q14[ j+1 ];
/* Output of allpass section */
tmp2 = silk_SMLAWB( prev, cur - tmp1, warping_Q16 );
psDD->sAR2_Q14[ j - 1 ] = tmp1;
temp64 = __builtin_mips_madd( temp64, tmp1, AR_shp_Q13[ j - 1 ] );
temp64 = __builtin_mips_madd( temp64, tmp2, AR_shp_Q13[ j ] );
/* Output of allpass section */
tmp1 = silk_SMLAWB( cur, next - tmp2, warping_Q16 );
psDD->sAR2_Q14[ j + 0 ] = tmp2;
prev = next;
}
psDD->sAR2_Q14[ shapingLPCOrder - 1 ] = tmp1;
temp64 = __builtin_mips_madd( temp64, tmp1, AR_shp_Q13[ shapingLPCOrder - 1 ] );
temp64 += 32768;
n_AR_Q14 = __builtin_mips_extr_w(temp64, 16);
n_AR_Q14 = silk_LSHIFT( n_AR_Q14, 1 ); /* Q11 -> Q12 */
n_AR_Q14 = silk_SMLAWB( n_AR_Q14, psDD->LF_AR_Q14, Tilt_Q14 ); /* Q12 */
n_AR_Q14 = silk_LSHIFT( n_AR_Q14, 2 ); /* Q12 -> Q14 */
n_LF_Q14 = silk_SMULWB( psDD->Shape_Q14[ *smpl_buf_idx ], LF_shp_Q14 ); /* Q12 */
n_LF_Q14 = silk_SMLAWT( n_LF_Q14, psDD->LF_AR_Q14, LF_shp_Q14 ); /* Q12 */
n_LF_Q14 = silk_LSHIFT( n_LF_Q14, 2 ); /* Q12 -> Q14 */
/* Input minus prediction plus noise feedback */
/* r = x[ i ] - LTP_pred - LPC_pred + n_AR + n_Tilt + n_LF + n_LTP */
tmp1 = silk_ADD32( n_AR_Q14, n_LF_Q14 ); /* Q14 */
tmp2 = silk_ADD32( n_LTP_Q14, LPC_pred_Q14 ); /* Q13 */
tmp1 = silk_SUB32( tmp2, tmp1 ); /* Q13 */
tmp1 = silk_RSHIFT_ROUND( tmp1, 4 ); /* Q10 */
r_Q10 = silk_SUB32( x_Q10[ i ], tmp1 ); /* residual error Q10 */
/* Flip sign depending on dither */
if ( psDD->Seed < 0 ) {
r_Q10 = -r_Q10;
}
r_Q10 = silk_LIMIT_32( r_Q10, -(31 << 10), 30 << 10 );
/* Find two quantization level candidates and measure their rate-distortion */
q1_Q10 = silk_SUB32( r_Q10, offset_Q10 );
q1_Q0 = silk_RSHIFT( q1_Q10, 10 );
if( q1_Q0 > 0 ) {
q1_Q10 = silk_SUB32( silk_LSHIFT( q1_Q0, 10 ), QUANT_LEVEL_ADJUST_Q10 );
q1_Q10 = silk_ADD32( q1_Q10, offset_Q10 );
q2_Q10 = silk_ADD32( q1_Q10, 1024 );
rd1_Q10 = silk_SMULBB( q1_Q10, Lambda_Q10 );
rd2_Q10 = silk_SMULBB( q2_Q10, Lambda_Q10 );
} else if( q1_Q0 == 0 ) {
q1_Q10 = offset_Q10;
q2_Q10 = silk_ADD32( q1_Q10, 1024 - QUANT_LEVEL_ADJUST_Q10 );
rd1_Q10 = silk_SMULBB( q1_Q10, Lambda_Q10 );
rd2_Q10 = silk_SMULBB( q2_Q10, Lambda_Q10 );
} else if( q1_Q0 == -1 ) {
q2_Q10 = offset_Q10;
q1_Q10 = silk_SUB32( q2_Q10, 1024 - QUANT_LEVEL_ADJUST_Q10 );
rd1_Q10 = silk_SMULBB( -q1_Q10, Lambda_Q10 );
rd2_Q10 = silk_SMULBB( q2_Q10, Lambda_Q10 );
} else { /* q1_Q0 < -1 */
q1_Q10 = silk_ADD32( silk_LSHIFT( q1_Q0, 10 ), QUANT_LEVEL_ADJUST_Q10 );
q1_Q10 = silk_ADD32( q1_Q10, offset_Q10 );
q2_Q10 = silk_ADD32( q1_Q10, 1024 );
rd1_Q10 = silk_SMULBB( -q1_Q10, Lambda_Q10 );
rd2_Q10 = silk_SMULBB( -q2_Q10, Lambda_Q10 );
}
rr_Q10 = silk_SUB32( r_Q10, q1_Q10 );
rd1_Q10 = silk_RSHIFT( silk_SMLABB( rd1_Q10, rr_Q10, rr_Q10 ), 10 );
rr_Q10 = silk_SUB32( r_Q10, q2_Q10 );
rd2_Q10 = silk_RSHIFT( silk_SMLABB( rd2_Q10, rr_Q10, rr_Q10 ), 10 );
if( rd1_Q10 < rd2_Q10 ) {
psSS[ 0 ].RD_Q10 = silk_ADD32( psDD->RD_Q10, rd1_Q10 );
psSS[ 1 ].RD_Q10 = silk_ADD32( psDD->RD_Q10, rd2_Q10 );
psSS[ 0 ].Q_Q10 = q1_Q10;
psSS[ 1 ].Q_Q10 = q2_Q10;
} else {
psSS[ 0 ].RD_Q10 = silk_ADD32( psDD->RD_Q10, rd2_Q10 );
psSS[ 1 ].RD_Q10 = silk_ADD32( psDD->RD_Q10, rd1_Q10 );
psSS[ 0 ].Q_Q10 = q2_Q10;
psSS[ 1 ].Q_Q10 = q1_Q10;
}
/* Update states for best quantization */
/* Quantized excitation */
exc_Q14 = silk_LSHIFT32( psSS[ 0 ].Q_Q10, 4 );
if ( psDD->Seed < 0 ) {
exc_Q14 = -exc_Q14;
}
/* Add predictions */
LPC_exc_Q14 = silk_ADD32( exc_Q14, LTP_pred_Q14 );
xq_Q14 = silk_ADD32( LPC_exc_Q14, LPC_pred_Q14 );
/* Update states */
sLF_AR_shp_Q14 = silk_SUB32( xq_Q14, n_AR_Q14 );
psSS[ 0 ].sLTP_shp_Q14 = silk_SUB32( sLF_AR_shp_Q14, n_LF_Q14 );
psSS[ 0 ].LF_AR_Q14 = sLF_AR_shp_Q14;
psSS[ 0 ].LPC_exc_Q14 = LPC_exc_Q14;
psSS[ 0 ].xq_Q14 = xq_Q14;
/* Update states for second best quantization */
/* Quantized excitation */
exc_Q14 = silk_LSHIFT32( psSS[ 1 ].Q_Q10, 4 );
if ( psDD->Seed < 0 ) {
exc_Q14 = -exc_Q14;
}
/* Add predictions */
LPC_exc_Q14 = silk_ADD32( exc_Q14, LTP_pred_Q14 );
xq_Q14 = silk_ADD32( LPC_exc_Q14, LPC_pred_Q14 );
/* Update states */
sLF_AR_shp_Q14 = silk_SUB32( xq_Q14, n_AR_Q14 );
psSS[ 1 ].sLTP_shp_Q14 = silk_SUB32( sLF_AR_shp_Q14, n_LF_Q14 );
psSS[ 1 ].LF_AR_Q14 = sLF_AR_shp_Q14;
psSS[ 1 ].LPC_exc_Q14 = LPC_exc_Q14;
psSS[ 1 ].xq_Q14 = xq_Q14;
}
*smpl_buf_idx = ( *smpl_buf_idx - 1 ) & DECISION_DELAY_MASK; /* Index to newest samples */
last_smple_idx = ( *smpl_buf_idx + decisionDelay ) & DECISION_DELAY_MASK; /* Index to decisionDelay old samples */
/* Find winner */
RDmin_Q10 = psSampleState[ 0 ][ 0 ].RD_Q10;
Winner_ind = 0;
for( k = 1; k < nStatesDelayedDecision; k++ ) {
if( psSampleState[ k ][ 0 ].RD_Q10 < RDmin_Q10 ) {
RDmin_Q10 = psSampleState[ k ][ 0 ].RD_Q10;
Winner_ind = k;
}
}
/* Increase RD values of expired states */
Winner_rand_state = psDelDec[ Winner_ind ].RandState[ last_smple_idx ];
for( k = 0; k < nStatesDelayedDecision; k++ ) {
if( psDelDec[ k ].RandState[ last_smple_idx ] != Winner_rand_state ) {
psSampleState[ k ][ 0 ].RD_Q10 = silk_ADD32( psSampleState[ k ][ 0 ].RD_Q10, silk_int32_MAX >> 4 );
psSampleState[ k ][ 1 ].RD_Q10 = silk_ADD32( psSampleState[ k ][ 1 ].RD_Q10, silk_int32_MAX >> 4 );
silk_assert( psSampleState[ k ][ 0 ].RD_Q10 >= 0 );
}
}
/* Find worst in first set and best in second set */
RDmax_Q10 = psSampleState[ 0 ][ 0 ].RD_Q10;
RDmin_Q10 = psSampleState[ 0 ][ 1 ].RD_Q10;
RDmax_ind = 0;
RDmin_ind = 0;
for( k = 1; k < nStatesDelayedDecision; k++ ) {
/* find worst in first set */
if( psSampleState[ k ][ 0 ].RD_Q10 > RDmax_Q10 ) {
RDmax_Q10 = psSampleState[ k ][ 0 ].RD_Q10;
RDmax_ind = k;
}
/* find best in second set */
if( psSampleState[ k ][ 1 ].RD_Q10 < RDmin_Q10 ) {
RDmin_Q10 = psSampleState[ k ][ 1 ].RD_Q10;
RDmin_ind = k;
}
}
/* Replace a state if best from second set outperforms worst in first set */
if( RDmin_Q10 < RDmax_Q10 ) {
silk_memcpy( ( (opus_int32 *)&psDelDec[ RDmax_ind ] ) + i,
( (opus_int32 *)&psDelDec[ RDmin_ind ] ) + i, sizeof( NSQ_del_dec_struct ) - i * sizeof( opus_int32) );
silk_memcpy( &psSampleState[ RDmax_ind ][ 0 ], &psSampleState[ RDmin_ind ][ 1 ], sizeof( NSQ_sample_struct ) );
}
/* Write samples from winner to output and long-term filter states */
psDD = &psDelDec[ Winner_ind ];
if( subfr > 0 || i >= decisionDelay ) {
pulses[ i - decisionDelay ] = (opus_int8)silk_RSHIFT_ROUND( psDD->Q_Q10[ last_smple_idx ], 10 );
xq[ i - decisionDelay ] = (opus_int16)silk_SAT16( silk_RSHIFT_ROUND(
silk_SMULWW( psDD->Xq_Q14[ last_smple_idx ], delayedGain_Q10[ last_smple_idx ] ), 8 ) );
NSQ->sLTP_shp_Q14[ NSQ->sLTP_shp_buf_idx - decisionDelay ] = psDD->Shape_Q14[ last_smple_idx ];
sLTP_Q15[ NSQ->sLTP_buf_idx - decisionDelay ] = psDD->Pred_Q15[ last_smple_idx ];
}
NSQ->sLTP_shp_buf_idx++;
NSQ->sLTP_buf_idx++;
/* Update states */
for( k = 0; k < nStatesDelayedDecision; k++ ) {
psDD = &psDelDec[ k ];
psSS = &psSampleState[ k ][ 0 ];
psDD->LF_AR_Q14 = psSS->LF_AR_Q14;
psDD->sLPC_Q14[ NSQ_LPC_BUF_LENGTH + i ] = psSS->xq_Q14;
psDD->Xq_Q14[ *smpl_buf_idx ] = psSS->xq_Q14;
psDD->Q_Q10[ *smpl_buf_idx ] = psSS->Q_Q10;
psDD->Pred_Q15[ *smpl_buf_idx ] = silk_LSHIFT32( psSS->LPC_exc_Q14, 1 );
psDD->Shape_Q14[ *smpl_buf_idx ] = psSS->sLTP_shp_Q14;
psDD->Seed = silk_ADD32_ovflw( psDD->Seed, silk_RSHIFT_ROUND( psSS->Q_Q10, 10 ) );
psDD->RandState[ *smpl_buf_idx ] = psDD->Seed;
psDD->RD_Q10 = psSS->RD_Q10;
}
delayedGain_Q10[ *smpl_buf_idx ] = Gain_Q10;
}
/* Update LPC states */
for( k = 0; k < nStatesDelayedDecision; k++ ) {
psDD = &psDelDec[ k ];
silk_memcpy( psDD->sLPC_Q14, &psDD->sLPC_Q14[ length ], NSQ_LPC_BUF_LENGTH * sizeof( opus_int32 ) );
}
}
#endif /* __NSQ_DEL_DEC_MIPSR1_H__ */
+92
View File
@@ -0,0 +1,92 @@
/***********************************************************************
Copyright (c) 2006-2011, Skype Limited. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
- Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
- Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
- Neither the name of Internet Society, IETF or IETF Trust, nor the
names of specific contributors, may be used to endorse or promote
products derived from this software without specific prior written
permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
***********************************************************************/
#ifndef __SILK_MACROS_MIPSR1_H__
#define __SILK_MACROS_MIPSR1_H__
#define mips_clz(x) __builtin_clz(x)
#undef silk_SMULWB
static inline int silk_SMULWB(int a, int b)
{
long long ac;
int c;
ac = __builtin_mips_mult(a, (opus_int32)(opus_int16)b);
c = __builtin_mips_extr_w(ac, 16);
return c;
}
#undef silk_SMLAWB
#define silk_SMLAWB(a32, b32, c32) ((a32) + silk_SMULWB(b32, c32))
#undef silk_SMULWW
static inline int silk_SMULWW(int a, int b)
{
long long ac;
int c;
ac = __builtin_mips_mult(a, b);
c = __builtin_mips_extr_w(ac, 16);
return c;
}
#undef silk_SMLAWW
static inline int silk_SMLAWW(int a, int b, int c)
{
long long ac;
int res;
ac = __builtin_mips_mult(b, c);
res = __builtin_mips_extr_w(ac, 16);
res += a;
return res;
}
#define OVERRIDE_silk_CLZ16
static inline opus_int32 silk_CLZ16(opus_int16 in16)
{
int re32;
opus_int32 in32 = (opus_int32 )in16;
re32 = mips_clz(in32);
re32-=16;
return re32;
}
#define OVERRIDE_silk_CLZ32
static inline opus_int32 silk_CLZ32(opus_int32 in32)
{
int re32;
re32 = mips_clz(in32);
return re32;
}
#endif /* __SILK_MACROS_MIPSR1_H__ */
@@ -0,0 +1,65 @@
/***********************************************************************
Copyright (c) 2006-2011, Skype Limited. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
- Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
- Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
- Neither the name of Internet Society, IETF or IETF Trust, nor the
names of specific contributors, may be used to endorse or promote
products derived from this software without specific prior written
permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
***********************************************************************/
#ifndef SILK_SIGPROC_FIX_MIPSR1_H
#define SILK_SIGPROC_FIX_MIPSR1_H
#ifdef __cplusplus
extern "C"
{
#endif
#undef silk_SAT16
static inline short int silk_SAT16(int a)
{
int c;
c = __builtin_mips_shll_s_w(a, 16);
c = c>>16;
return c;
}
#undef silk_LSHIFT_SAT32
static inline int silk_LSHIFT_SAT32(int a, int shift)
{
int r;
r = __builtin_mips_shll_s_w(a, shift);
return r;
}
#undef silk_RSHIFT_ROUND
static inline int silk_RSHIFT_ROUND(int a, int shift)
{
int r;
r = __builtin_mips_shra_r_w(a, shift);
return r;
}
#endif /* SILK_SIGPROC_FIX_MIPSR1_H */
+4 -2
View File
@@ -41,7 +41,7 @@ void silk_process_NLSFs(
{
opus_int i, doInterpolate;
opus_int NLSF_mu_Q20;
opus_int32 i_sqr_Q15;
opus_int16 i_sqr_Q15;
opus_int16 pNLSF0_temp_Q15[ MAX_LPC_ORDER ];
opus_int16 pNLSFW_QW[ MAX_LPC_ORDER ];
opus_int16 pNLSFW0_temp_QW[ MAX_LPC_ORDER ];
@@ -79,7 +79,8 @@ void silk_process_NLSFs(
/* Update NLSF weights with contribution from first half */
i_sqr_Q15 = silk_LSHIFT( silk_SMULBB( psEncC->indices.NLSFInterpCoef_Q2, psEncC->indices.NLSFInterpCoef_Q2 ), 11 );
for( i = 0; i < psEncC->predictLPCOrder; i++ ) {
pNLSFW_QW[ i ] = silk_SMLAWB( silk_RSHIFT( pNLSFW_QW[ i ], 1 ), (opus_int32)pNLSFW0_temp_QW[ i ], i_sqr_Q15 );
pNLSFW_QW[ i ] = silk_ADD16( silk_RSHIFT( pNLSFW_QW[ i ], 1 ), silk_RSHIFT(
silk_SMULBB( pNLSFW0_temp_QW[ i ], i_sqr_Q15 ), 16) );
silk_assert( pNLSFW_QW[ i ] >= 1 );
}
}
@@ -100,6 +101,7 @@ void silk_process_NLSFs(
} else {
/* Copy LPC coefficients for first half from second half */
silk_assert( psEncC->predictLPCOrder <= MAX_LPC_ORDER );
silk_memcpy( PredCoef_Q12[ 0 ], PredCoef_Q12[ 1 ], psEncC->predictLPCOrder * sizeof( opus_int16 ) );
}
}
+13 -12
View File
@@ -36,11 +36,12 @@ void silk_quant_LTP_gains(
opus_int16 B_Q14[ MAX_NB_SUBFR * LTP_ORDER ], /* I/O (un)quantized LTP gains */
opus_int8 cbk_index[ MAX_NB_SUBFR ], /* O Codebook Index */
opus_int8 *periodicity_index, /* O Periodicity Index */
opus_int32 *sum_log_gain_Q7, /* I/O Cumulative max prediction gain */
opus_int32 *sum_log_gain_Q7, /* I/O Cumulative max prediction gain */
const opus_int32 W_Q18[ MAX_NB_SUBFR*LTP_ORDER*LTP_ORDER ], /* I Error Weights in Q18 */
opus_int mu_Q9, /* I Mu value (R/D tradeoff) */
opus_int lowComplexity, /* I Flag for low complexity */
const opus_int nb_subfr /* I number of subframes */
const opus_int nb_subfr, /* I number of subframes */
int arch /* I Run-time architecture */
)
{
opus_int j, k, cbk_size;
@@ -51,7 +52,7 @@ void silk_quant_LTP_gains(
const opus_int16 *b_Q14_ptr;
const opus_int32 *W_Q18_ptr;
opus_int32 rate_dist_Q14_subfr, rate_dist_Q14, min_rate_dist_Q14;
opus_int32 sum_log_gain_tmp_Q7, best_sum_log_gain_Q7, max_gain_Q7, gain_Q7;
opus_int32 sum_log_gain_tmp_Q7, best_sum_log_gain_Q7, max_gain_Q7, gain_Q7;
/***************************************************/
/* iterate over different codebooks with different */
@@ -74,23 +75,24 @@ void silk_quant_LTP_gains(
b_Q14_ptr = B_Q14;
rate_dist_Q14 = 0;
sum_log_gain_tmp_Q7 = *sum_log_gain_Q7;
sum_log_gain_tmp_Q7 = *sum_log_gain_Q7;
for( j = 0; j < nb_subfr; j++ ) {
max_gain_Q7 = silk_log2lin( ( SILK_FIX_CONST( MAX_SUM_LOG_GAIN_DB / 6.0, 7 ) - sum_log_gain_tmp_Q7 )
+ SILK_FIX_CONST( 7, 7 ) ) - gain_safety;
max_gain_Q7 = silk_log2lin( ( SILK_FIX_CONST( MAX_SUM_LOG_GAIN_DB / 6.0, 7 ) - sum_log_gain_tmp_Q7 )
+ SILK_FIX_CONST( 7, 7 ) ) - gain_safety;
silk_VQ_WMat_EC(
&temp_idx[ j ], /* O index of best codebook vector */
&rate_dist_Q14_subfr, /* O best weighted quantization error + mu * rate */
&gain_Q7, /* O sum of absolute LTP coefficients */
&gain_Q7, /* O sum of absolute LTP coefficients */
b_Q14_ptr, /* I input vector to be quantized */
W_Q18_ptr, /* I weighting matrix */
cbk_ptr_Q7, /* I codebook */
cbk_gain_ptr_Q7, /* I codebook effective gains */
cl_ptr_Q5, /* I code length for each codebook vector */
mu_Q9, /* I tradeoff between weighted error and rate */
max_gain_Q7, /* I maximum sum of absolute LTP coefficients */
cbk_size /* I number of vectors in codebook */
max_gain_Q7, /* I maximum sum of absolute LTP coefficients */
cbk_size, /* I number of vectors in codebook */
arch /* I Run-time architecture */
);
rate_dist_Q14 = silk_ADD_POS_SAT32( rate_dist_Q14, rate_dist_Q14_subfr );
@@ -108,7 +110,7 @@ void silk_quant_LTP_gains(
min_rate_dist_Q14 = rate_dist_Q14;
*periodicity_index = (opus_int8)k;
silk_memcpy( cbk_index, temp_idx, nb_subfr * sizeof( opus_int8 ) );
best_sum_log_gain_Q7 = sum_log_gain_tmp_Q7;
best_sum_log_gain_Q7 = sum_log_gain_tmp_Q7;
}
/* Break early in low-complexity mode if rate distortion is below threshold */
@@ -123,6 +125,5 @@ void silk_quant_LTP_gains(
B_Q14[ j * LTP_ORDER + k ] = silk_LSHIFT( cbk_ptr_Q7[ cbk_index[ j ] * LTP_ORDER + k ], 7 );
}
}
*sum_log_gain_Q7 = best_sum_log_gain_Q7;
*sum_log_gain_Q7 = best_sum_log_gain_Q7;
}
+27 -27
View File
@@ -41,36 +41,36 @@ POSSIBILITY OF SUCH DAMAGE.
/* Tables with IIR and FIR coefficients for fractional downsamplers (123 Words) */
silk_DWORD_ALIGN const opus_int16 silk_Resampler_3_4_COEFS[ 2 + 3 * RESAMPLER_DOWN_ORDER_FIR0 / 2 ] = {
-20694, -13867,
-49, 64, 17, -157, 353, -496, 163, 11047, 22205,
-39, 6, 91, -170, 186, 23, -896, 6336, 19928,
-19, -36, 102, -89, -24, 328, -951, 2568, 15909,
-20694, -13867,
-49, 64, 17, -157, 353, -496, 163, 11047, 22205,
-39, 6, 91, -170, 186, 23, -896, 6336, 19928,
-19, -36, 102, -89, -24, 328, -951, 2568, 15909,
};
silk_DWORD_ALIGN const opus_int16 silk_Resampler_2_3_COEFS[ 2 + 2 * RESAMPLER_DOWN_ORDER_FIR0 / 2 ] = {
-14457, -14019,
64, 128, -122, 36, 310, -768, 584, 9267, 17733,
12, 128, 18, -142, 288, -117, -865, 4123, 14459,
-14457, -14019,
64, 128, -122, 36, 310, -768, 584, 9267, 17733,
12, 128, 18, -142, 288, -117, -865, 4123, 14459,
};
silk_DWORD_ALIGN const opus_int16 silk_Resampler_1_2_COEFS[ 2 + RESAMPLER_DOWN_ORDER_FIR1 / 2 ] = {
616, -14323,
-10, 39, 58, -46, -84, 120, 184, -315, -541, 1284, 5380, 9024,
616, -14323,
-10, 39, 58, -46, -84, 120, 184, -315, -541, 1284, 5380, 9024,
};
silk_DWORD_ALIGN const opus_int16 silk_Resampler_1_3_COEFS[ 2 + RESAMPLER_DOWN_ORDER_FIR2 / 2 ] = {
16102, -15162,
-13, 0, 20, 26, 5, -31, -43, -4, 65, 90, 7, -157, -248, -44, 593, 1583, 2612, 3271,
16102, -15162,
-13, 0, 20, 26, 5, -31, -43, -4, 65, 90, 7, -157, -248, -44, 593, 1583, 2612, 3271,
};
silk_DWORD_ALIGN const opus_int16 silk_Resampler_1_4_COEFS[ 2 + RESAMPLER_DOWN_ORDER_FIR2 / 2 ] = {
22500, -15099,
3, -14, -20, -15, 2, 25, 37, 25, -16, -71, -107, -79, 50, 292, 623, 982, 1288, 1464,
22500, -15099,
3, -14, -20, -15, 2, 25, 37, 25, -16, -71, -107, -79, 50, 292, 623, 982, 1288, 1464,
};
silk_DWORD_ALIGN const opus_int16 silk_Resampler_1_6_COEFS[ 2 + RESAMPLER_DOWN_ORDER_FIR2 / 2 ] = {
27540, -15257,
17, 12, 8, 1, -10, -22, -30, -32, -22, 3, 44, 100, 168, 243, 317, 381, 429, 455,
27540, -15257,
17, 12, 8, 1, -10, -22, -30, -32, -22, 3, 44, 100, 168, 243, 317, 381, 429, 455,
};
silk_DWORD_ALIGN const opus_int16 silk_Resampler_2_3_COEFS_LQ[ 2 + 2 * 2 ] = {
@@ -81,16 +81,16 @@ silk_DWORD_ALIGN const opus_int16 silk_Resampler_2_3_COEFS_LQ[ 2 + 2 * 2 ] = {
/* Table with interplation fractions of 1/24, 3/24, 5/24, ... , 23/24 : 23/24 (46 Words) */
silk_DWORD_ALIGN const opus_int16 silk_resampler_frac_FIR_12[ 12 ][ RESAMPLER_ORDER_FIR_12 / 2 ] = {
{ 189, -600, 617, 30567 },
{ 117, -159, -1070, 29704 },
{ 52, 221, -2392, 28276 },
{ -4, 529, -3350, 26341 },
{ -48, 758, -3956, 23973 },
{ -80, 905, -4235, 21254 },
{ -99, 972, -4222, 18278 },
{ -107, 967, -3957, 15143 },
{ -103, 896, -3487, 11950 },
{ -91, 773, -2865, 8798 },
{ -71, 611, -2143, 5784 },
{ -46, 425, -1375, 2996 },
{ 189, -600, 617, 30567 },
{ 117, -159, -1070, 29704 },
{ 52, 221, -2392, 28276 },
{ -4, 529, -3350, 26341 },
{ -48, 758, -3956, 23973 },
{ -80, 905, -4235, 21254 },
{ -99, 972, -4222, 18278 },
{ -107, 967, -3957, 15143 },
{ -103, 896, -3487, 11950 },
{ -91, 773, -2865, 8798 },
{ -71, 611, -2143, 5784 },
{ -46, 425, -1375, 2996 },
};
+4 -4
View File
@@ -58,8 +58,8 @@ static OPUS_INLINE void encode_split(
}
static OPUS_INLINE void decode_split(
opus_int *p_child1, /* O pulse amplitude of first child subframe */
opus_int *p_child2, /* O pulse amplitude of second child subframe */
opus_int16 *p_child1, /* O pulse amplitude of first child subframe */
opus_int16 *p_child2, /* O pulse amplitude of second child subframe */
ec_dec *psRangeDec, /* I/O Compressor data structure */
const opus_int p, /* I pulse amplitude of current subframe */
const opus_uint8 *shell_table /* I table of shell cdfs */
@@ -117,12 +117,12 @@ void silk_shell_encoder(
/* Shell decoder, operates on one shell code frame of 16 pulses */
void silk_shell_decoder(
opus_int *pulses0, /* O data: nonnegative pulse amplitudes */
opus_int16 *pulses0, /* O data: nonnegative pulse amplitudes */
ec_dec *psRangeDec, /* I/O Compressor data structure */
const opus_int pulses4 /* I number of pulses per pulse-subframe */
)
{
opus_int pulses3[ 2 ], pulses2[ 4 ], pulses1[ 8 ];
opus_int16 pulses3[ 2 ], pulses2[ 4 ], pulses1[ 8 ];
/* this function operates on one shell code frame of 16 pulses */
silk_assert( SHELL_CODEC_FRAME_LENGTH == 16 );
+1 -1
View File
@@ -33,7 +33,7 @@ POSSIBILITY OF SUCH DAMAGE.
/* Best case: O(n) for an already sorted array */
/* Worst case: O(n^2) for an inversely sorted array */
/* */
/* Shell short: http://en.wikipedia.org/wiki/Shell_sort */
/* Shell short: https://en.wikipedia.org/wiki/Shell_sort */
#include "SigProc_FIX.h"
+4 -4
View File
@@ -77,7 +77,7 @@ void silk_stereo_LR_to_MS(
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 );
sum = silk_RSHIFT_ROUND( silk_ADD_LSHIFT( mid[ n ] + (opus_int32)mid[ n + 2 ], mid[ n + 1 ], 1 ), 2 );
LP_mid[ n ] = sum;
HP_mid[ n ] = mid[ n + 1 ] - sum;
}
@@ -86,7 +86,7 @@ void silk_stereo_LR_to_MS(
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 );
sum = silk_RSHIFT_ROUND( silk_ADD_LSHIFT( side[ n ] + (opus_int32)side[ n + 2 ], side[ n + 1 ], 1 ), 2 );
LP_side[ n ] = sum;
HP_side[ n ] = side[ n + 1 ] - sum;
}
@@ -207,7 +207,7 @@ void silk_stereo_LR_to_MS(
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_LSHIFT( silk_ADD_LSHIFT( mid[ n ] + (opus_int32)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 ) );
@@ -217,7 +217,7 @@ void silk_stereo_LR_to_MS(
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_LSHIFT( silk_ADD_LSHIFT( mid[ n ] + (opus_int32)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 ) );
+1 -1
View File
@@ -171,7 +171,7 @@ typedef struct {
opus_int32 pitchEstimationThreshold_Q16; /* Threshold for pitch estimator */
opus_int LTPQuantLowComplexity; /* Flag for low complexity LTP quantization */
opus_int mu_LTP_Q9; /* Rate-distortion tradeoff in LTP quantization */
opus_int32 sum_log_gain_Q7; /* Cumulative max prediction gain */
opus_int32 sum_log_gain_Q7; /* Cumulative max prediction gain */
opus_int NLSF_MSVQ_Survivors; /* Number of survivors in NLSF MSVQ */
opus_int first_frame_after_reset; /* Flag for deactivating NLSF interpolation, pitch prediction */
opus_int controlled_since_last_payload; /* Flag for ensuring codec_control only runs once per packet */
+1
View File
@@ -53,6 +53,7 @@ void silk_sum_sqr_shift(
/* Scale down */
nrg = (opus_int32)silk_RSHIFT_uint( (opus_uint32)nrg, 2 );
shft = 2;
i+=2;
break;
}
}
+3 -3
View File
@@ -47,8 +47,8 @@ extern const opus_uint8 silk_pitch_contour_NB_iCDF[ 11 ];
extern const opus_uint8 silk_pitch_contour_10_ms_iCDF[ 12 ]; /* 12 */
extern const opus_uint8 silk_pitch_contour_10_ms_NB_iCDF[ 3 ]; /* 3 */
extern const opus_uint8 silk_pulses_per_block_iCDF[ N_RATE_LEVELS ][ MAX_PULSES + 2 ]; /* 180 */
extern const opus_uint8 silk_pulses_per_block_BITS_Q5[ N_RATE_LEVELS - 1 ][ MAX_PULSES + 2 ]; /* 162 */
extern const opus_uint8 silk_pulses_per_block_iCDF[ N_RATE_LEVELS ][ SILK_MAX_PULSES + 2 ]; /* 180 */
extern const opus_uint8 silk_pulses_per_block_BITS_Q5[ N_RATE_LEVELS - 1 ][ SILK_MAX_PULSES + 2 ]; /* 162 */
extern const opus_uint8 silk_rate_levels_iCDF[ 2 ][ N_RATE_LEVELS - 1 ]; /* 18 */
extern const opus_uint8 silk_rate_levels_BITS_Q5[ 2 ][ N_RATE_LEVELS - 1 ]; /* 18 */
@@ -59,7 +59,7 @@ extern const opus_uint8 silk_shell_code_table0[ 152 ];
extern const opus_uint8 silk_shell_code_table1[ 152 ]; /* 152 */
extern const opus_uint8 silk_shell_code_table2[ 152 ]; /* 152 */
extern const opus_uint8 silk_shell_code_table3[ 152 ]; /* 152 */
extern const opus_uint8 silk_shell_code_table_offsets[ MAX_PULSES + 1 ]; /* 17 */
extern const opus_uint8 silk_shell_code_table_offsets[ SILK_MAX_PULSES + 1 ]; /* 17 */
extern const opus_uint8 silk_lsb_iCDF[ 2 ]; /* 2 */
+1 -1
View File
@@ -64,7 +64,7 @@ extern "C"
#define MU_LTP_QUANT_WB 0.02f
/* Max cumulative LTP gain */
#define MAX_SUM_LOG_GAIN_DB 250.0f
#define MAX_SUM_LOG_GAIN_DB 250.0f
/***********************/
/* High pass filtering */
+857
View File
@@ -0,0 +1,857 @@
/* Copyright (c) 2014, Cisco Systems, INC
Written by XiangMingZhu WeiZhou MinPeng YanWang
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
- Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
- Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <xmmintrin.h>
#include <emmintrin.h>
#include <smmintrin.h>
#include "main.h"
#include "celt/x86/x86cpu.h"
#include "stack_alloc.h"
typedef struct {
opus_int32 sLPC_Q14[ MAX_SUB_FRAME_LENGTH + NSQ_LPC_BUF_LENGTH ];
opus_int32 RandState[ DECISION_DELAY ];
opus_int32 Q_Q10[ DECISION_DELAY ];
opus_int32 Xq_Q14[ DECISION_DELAY ];
opus_int32 Pred_Q15[ DECISION_DELAY ];
opus_int32 Shape_Q14[ DECISION_DELAY ];
opus_int32 sAR2_Q14[ MAX_SHAPE_LPC_ORDER ];
opus_int32 LF_AR_Q14;
opus_int32 Seed;
opus_int32 SeedInit;
opus_int32 RD_Q10;
} NSQ_del_dec_struct;
typedef struct {
opus_int32 Q_Q10;
opus_int32 RD_Q10;
opus_int32 xq_Q14;
opus_int32 LF_AR_Q14;
opus_int32 sLTP_shp_Q14;
opus_int32 LPC_exc_Q14;
} NSQ_sample_struct;
typedef NSQ_sample_struct NSQ_sample_pair[ 2 ];
static OPUS_INLINE void silk_nsq_del_dec_scale_states_sse4_1(
const silk_encoder_state *psEncC, /* I Encoder State */
silk_nsq_state *NSQ, /* I/O NSQ state */
NSQ_del_dec_struct psDelDec[], /* I/O Delayed decision states */
const opus_int32 x_Q3[], /* I Input in Q3 */
opus_int32 x_sc_Q10[], /* O Input scaled with 1/Gain in Q10 */
const opus_int16 sLTP[], /* I Re-whitened LTP state in Q0 */
opus_int32 sLTP_Q15[], /* O LTP state matching scaled input */
opus_int subfr, /* I Subframe number */
opus_int nStatesDelayedDecision, /* I Number of del dec states */
const opus_int LTP_scale_Q14, /* I LTP state scaling */
const opus_int32 Gains_Q16[ MAX_NB_SUBFR ], /* I */
const opus_int pitchL[ MAX_NB_SUBFR ], /* I Pitch lag */
const opus_int signal_type, /* I Signal type */
const opus_int decisionDelay /* I Decision delay */
);
/******************************************/
/* Noise shape quantizer for one subframe */
/******************************************/
static OPUS_INLINE void silk_noise_shape_quantizer_del_dec_sse4_1(
silk_nsq_state *NSQ, /* I/O NSQ state */
NSQ_del_dec_struct psDelDec[], /* I/O Delayed decision states */
opus_int signalType, /* I Signal type */
const opus_int32 x_Q10[], /* I */
opus_int8 pulses[], /* O */
opus_int16 xq[], /* O */
opus_int32 sLTP_Q15[], /* I/O LTP filter state */
opus_int32 delayedGain_Q10[], /* I/O Gain delay buffer */
const opus_int16 a_Q12[], /* I Short term prediction coefs */
const opus_int16 b_Q14[], /* I Long term prediction coefs */
const opus_int16 AR_shp_Q13[], /* I Noise shaping coefs */
opus_int lag, /* I Pitch lag */
opus_int32 HarmShapeFIRPacked_Q14, /* I */
opus_int Tilt_Q14, /* I Spectral tilt */
opus_int32 LF_shp_Q14, /* I */
opus_int32 Gain_Q16, /* I */
opus_int Lambda_Q10, /* I */
opus_int offset_Q10, /* I */
opus_int length, /* I Input length */
opus_int subfr, /* I Subframe number */
opus_int shapingLPCOrder, /* I Shaping LPC filter order */
opus_int predictLPCOrder, /* I Prediction filter order */
opus_int warping_Q16, /* I */
opus_int nStatesDelayedDecision, /* I Number of states in decision tree */
opus_int *smpl_buf_idx, /* I Index to newest samples in buffers */
opus_int decisionDelay /* I */
);
void silk_NSQ_del_dec_sse4_1(
const silk_encoder_state *psEncC, /* I/O Encoder State */
silk_nsq_state *NSQ, /* I/O NSQ state */
SideInfoIndices *psIndices, /* I/O Quantization Indices */
const opus_int32 x_Q3[], /* I Prefiltered input signal */
opus_int8 pulses[], /* O Quantized pulse signal */
const opus_int16 PredCoef_Q12[ 2 * MAX_LPC_ORDER ], /* I Short term prediction coefs */
const opus_int16 LTPCoef_Q14[ LTP_ORDER * MAX_NB_SUBFR ], /* I Long term prediction coefs */
const opus_int16 AR2_Q13[ MAX_NB_SUBFR * MAX_SHAPE_LPC_ORDER ], /* I Noise shaping coefs */
const opus_int HarmShapeGain_Q14[ MAX_NB_SUBFR ], /* I Long term shaping coefs */
const opus_int Tilt_Q14[ MAX_NB_SUBFR ], /* I Spectral tilt */
const opus_int32 LF_shp_Q14[ MAX_NB_SUBFR ], /* I Low frequency shaping coefs */
const opus_int32 Gains_Q16[ MAX_NB_SUBFR ], /* I Quantization step sizes */
const opus_int pitchL[ MAX_NB_SUBFR ], /* I Pitch lags */
const opus_int Lambda_Q10, /* I Rate/distortion tradeoff */
const opus_int LTP_scale_Q14 /* I LTP state scaling */
)
{
opus_int i, k, lag, start_idx, LSF_interpolation_flag, Winner_ind, subfr;
opus_int last_smple_idx, smpl_buf_idx, decisionDelay;
const opus_int16 *A_Q12, *B_Q14, *AR_shp_Q13;
opus_int16 *pxq;
VARDECL( opus_int32, sLTP_Q15 );
VARDECL( opus_int16, sLTP );
opus_int32 HarmShapeFIRPacked_Q14;
opus_int offset_Q10;
opus_int32 RDmin_Q10, Gain_Q10;
VARDECL( opus_int32, x_sc_Q10 );
VARDECL( opus_int32, delayedGain_Q10 );
VARDECL( NSQ_del_dec_struct, psDelDec );
NSQ_del_dec_struct *psDD;
SAVE_STACK;
/* Set unvoiced lag to the previous one, overwrite later for voiced */
lag = NSQ->lagPrev;
silk_assert( NSQ->prev_gain_Q16 != 0 );
/* Initialize delayed decision states */
ALLOC( psDelDec, psEncC->nStatesDelayedDecision, NSQ_del_dec_struct );
silk_memset( psDelDec, 0, psEncC->nStatesDelayedDecision * sizeof( NSQ_del_dec_struct ) );
for( k = 0; k < psEncC->nStatesDelayedDecision; k++ ) {
psDD = &psDelDec[ k ];
psDD->Seed = ( k + psIndices->Seed ) & 3;
psDD->SeedInit = psDD->Seed;
psDD->RD_Q10 = 0;
psDD->LF_AR_Q14 = NSQ->sLF_AR_shp_Q14;
psDD->Shape_Q14[ 0 ] = NSQ->sLTP_shp_Q14[ psEncC->ltp_mem_length - 1 ];
silk_memcpy( psDD->sLPC_Q14, NSQ->sLPC_Q14, NSQ_LPC_BUF_LENGTH * sizeof( opus_int32 ) );
silk_memcpy( psDD->sAR2_Q14, NSQ->sAR2_Q14, sizeof( NSQ->sAR2_Q14 ) );
}
offset_Q10 = silk_Quantization_Offsets_Q10[ psIndices->signalType >> 1 ][ psIndices->quantOffsetType ];
smpl_buf_idx = 0; /* index of oldest samples */
decisionDelay = silk_min_int( DECISION_DELAY, psEncC->subfr_length );
/* For voiced frames limit the decision delay to lower than the pitch lag */
if( psIndices->signalType == TYPE_VOICED ) {
for( k = 0; k < psEncC->nb_subfr; k++ ) {
decisionDelay = silk_min_int( decisionDelay, pitchL[ k ] - LTP_ORDER / 2 - 1 );
}
} else {
if( lag > 0 ) {
decisionDelay = silk_min_int( decisionDelay, lag - LTP_ORDER / 2 - 1 );
}
}
if( psIndices->NLSFInterpCoef_Q2 == 4 ) {
LSF_interpolation_flag = 0;
} else {
LSF_interpolation_flag = 1;
}
ALLOC( sLTP_Q15,
psEncC->ltp_mem_length + psEncC->frame_length, opus_int32 );
ALLOC( sLTP, psEncC->ltp_mem_length + psEncC->frame_length, opus_int16 );
ALLOC( x_sc_Q10, psEncC->subfr_length, opus_int32 );
ALLOC( delayedGain_Q10, DECISION_DELAY, opus_int32 );
/* Set up pointers to start of sub frame */
pxq = &NSQ->xq[ psEncC->ltp_mem_length ];
NSQ->sLTP_shp_buf_idx = psEncC->ltp_mem_length;
NSQ->sLTP_buf_idx = psEncC->ltp_mem_length;
subfr = 0;
for( k = 0; k < psEncC->nb_subfr; k++ ) {
A_Q12 = &PredCoef_Q12[ ( ( k >> 1 ) | ( 1 - LSF_interpolation_flag ) ) * MAX_LPC_ORDER ];
B_Q14 = &LTPCoef_Q14[ k * LTP_ORDER ];
AR_shp_Q13 = &AR2_Q13[ k * MAX_SHAPE_LPC_ORDER ];
/* Noise shape parameters */
silk_assert( HarmShapeGain_Q14[ k ] >= 0 );
HarmShapeFIRPacked_Q14 = silk_RSHIFT( HarmShapeGain_Q14[ k ], 2 );
HarmShapeFIRPacked_Q14 |= silk_LSHIFT( (opus_int32)silk_RSHIFT( HarmShapeGain_Q14[ k ], 1 ), 16 );
NSQ->rewhite_flag = 0;
if( psIndices->signalType == TYPE_VOICED ) {
/* Voiced */
lag = pitchL[ k ];
/* Re-whitening */
if( ( k & ( 3 - silk_LSHIFT( LSF_interpolation_flag, 1 ) ) ) == 0 ) {
if( k == 2 ) {
/* RESET DELAYED DECISIONS */
/* Find winner */
RDmin_Q10 = psDelDec[ 0 ].RD_Q10;
Winner_ind = 0;
for( i = 1; i < psEncC->nStatesDelayedDecision; i++ ) {
if( psDelDec[ i ].RD_Q10 < RDmin_Q10 ) {
RDmin_Q10 = psDelDec[ i ].RD_Q10;
Winner_ind = i;
}
}
for( i = 0; i < psEncC->nStatesDelayedDecision; i++ ) {
if( i != Winner_ind ) {
psDelDec[ i ].RD_Q10 += ( silk_int32_MAX >> 4 );
silk_assert( psDelDec[ i ].RD_Q10 >= 0 );
}
}
/* Copy final part of signals from winner state to output and long-term filter states */
psDD = &psDelDec[ Winner_ind ];
last_smple_idx = smpl_buf_idx + decisionDelay;
for( i = 0; i < decisionDelay; i++ ) {
last_smple_idx = ( last_smple_idx - 1 ) & DECISION_DELAY_MASK;
pulses[ i - decisionDelay ] = (opus_int8)silk_RSHIFT_ROUND( psDD->Q_Q10[ last_smple_idx ], 10 );
pxq[ i - decisionDelay ] = (opus_int16)silk_SAT16( silk_RSHIFT_ROUND(
silk_SMULWW( psDD->Xq_Q14[ last_smple_idx ], Gains_Q16[ 1 ] ), 14 ) );
NSQ->sLTP_shp_Q14[ NSQ->sLTP_shp_buf_idx - decisionDelay + i ] = psDD->Shape_Q14[ last_smple_idx ];
}
subfr = 0;
}
/* Rewhiten with new A coefs */
start_idx = psEncC->ltp_mem_length - lag - psEncC->predictLPCOrder - LTP_ORDER / 2;
silk_assert( start_idx > 0 );
silk_LPC_analysis_filter( &sLTP[ start_idx ], &NSQ->xq[ start_idx + k * psEncC->subfr_length ],
A_Q12, psEncC->ltp_mem_length - start_idx, psEncC->predictLPCOrder, psEncC->arch );
NSQ->sLTP_buf_idx = psEncC->ltp_mem_length;
NSQ->rewhite_flag = 1;
}
}
silk_nsq_del_dec_scale_states_sse4_1( psEncC, NSQ, psDelDec, x_Q3, x_sc_Q10, sLTP, sLTP_Q15, k,
psEncC->nStatesDelayedDecision, LTP_scale_Q14, Gains_Q16, pitchL, psIndices->signalType, decisionDelay );
silk_noise_shape_quantizer_del_dec_sse4_1( NSQ, psDelDec, psIndices->signalType, x_sc_Q10, pulses, pxq, sLTP_Q15,
delayedGain_Q10, A_Q12, B_Q14, AR_shp_Q13, lag, HarmShapeFIRPacked_Q14, Tilt_Q14[ k ], LF_shp_Q14[ k ],
Gains_Q16[ k ], Lambda_Q10, offset_Q10, psEncC->subfr_length, subfr++, psEncC->shapingLPCOrder,
psEncC->predictLPCOrder, psEncC->warping_Q16, psEncC->nStatesDelayedDecision, &smpl_buf_idx, decisionDelay );
x_Q3 += psEncC->subfr_length;
pulses += psEncC->subfr_length;
pxq += psEncC->subfr_length;
}
/* Find winner */
RDmin_Q10 = psDelDec[ 0 ].RD_Q10;
Winner_ind = 0;
for( k = 1; k < psEncC->nStatesDelayedDecision; k++ ) {
if( psDelDec[ k ].RD_Q10 < RDmin_Q10 ) {
RDmin_Q10 = psDelDec[ k ].RD_Q10;
Winner_ind = k;
}
}
/* Copy final part of signals from winner state to output and long-term filter states */
psDD = &psDelDec[ Winner_ind ];
psIndices->Seed = psDD->SeedInit;
last_smple_idx = smpl_buf_idx + decisionDelay;
Gain_Q10 = silk_RSHIFT32( Gains_Q16[ psEncC->nb_subfr - 1 ], 6 );
for( i = 0; i < decisionDelay; i++ ) {
last_smple_idx = ( last_smple_idx - 1 ) & DECISION_DELAY_MASK;
pulses[ i - decisionDelay ] = (opus_int8)silk_RSHIFT_ROUND( psDD->Q_Q10[ last_smple_idx ], 10 );
pxq[ i - decisionDelay ] = (opus_int16)silk_SAT16( silk_RSHIFT_ROUND(
silk_SMULWW( psDD->Xq_Q14[ last_smple_idx ], Gain_Q10 ), 8 ) );
NSQ->sLTP_shp_Q14[ NSQ->sLTP_shp_buf_idx - decisionDelay + i ] = psDD->Shape_Q14[ last_smple_idx ];
}
silk_memcpy( NSQ->sLPC_Q14, &psDD->sLPC_Q14[ psEncC->subfr_length ], NSQ_LPC_BUF_LENGTH * sizeof( opus_int32 ) );
silk_memcpy( NSQ->sAR2_Q14, psDD->sAR2_Q14, sizeof( psDD->sAR2_Q14 ) );
/* Update states */
NSQ->sLF_AR_shp_Q14 = psDD->LF_AR_Q14;
NSQ->lagPrev = pitchL[ psEncC->nb_subfr - 1 ];
/* Save quantized speech signal */
/* DEBUG_STORE_DATA( enc.pcm, &NSQ->xq[psEncC->ltp_mem_length], psEncC->frame_length * sizeof( opus_int16 ) ) */
silk_memmove( NSQ->xq, &NSQ->xq[ psEncC->frame_length ], psEncC->ltp_mem_length * sizeof( opus_int16 ) );
silk_memmove( NSQ->sLTP_shp_Q14, &NSQ->sLTP_shp_Q14[ psEncC->frame_length ], psEncC->ltp_mem_length * sizeof( opus_int32 ) );
RESTORE_STACK;
}
/******************************************/
/* Noise shape quantizer for one subframe */
/******************************************/
static OPUS_INLINE void silk_noise_shape_quantizer_del_dec_sse4_1(
silk_nsq_state *NSQ, /* I/O NSQ state */
NSQ_del_dec_struct psDelDec[], /* I/O Delayed decision states */
opus_int signalType, /* I Signal type */
const opus_int32 x_Q10[], /* I */
opus_int8 pulses[], /* O */
opus_int16 xq[], /* O */
opus_int32 sLTP_Q15[], /* I/O LTP filter state */
opus_int32 delayedGain_Q10[], /* I/O Gain delay buffer */
const opus_int16 a_Q12[], /* I Short term prediction coefs */
const opus_int16 b_Q14[], /* I Long term prediction coefs */
const opus_int16 AR_shp_Q13[], /* I Noise shaping coefs */
opus_int lag, /* I Pitch lag */
opus_int32 HarmShapeFIRPacked_Q14, /* I */
opus_int Tilt_Q14, /* I Spectral tilt */
opus_int32 LF_shp_Q14, /* I */
opus_int32 Gain_Q16, /* I */
opus_int Lambda_Q10, /* I */
opus_int offset_Q10, /* I */
opus_int length, /* I Input length */
opus_int subfr, /* I Subframe number */
opus_int shapingLPCOrder, /* I Shaping LPC filter order */
opus_int predictLPCOrder, /* I Prediction filter order */
opus_int warping_Q16, /* I */
opus_int nStatesDelayedDecision, /* I Number of states in decision tree */
opus_int *smpl_buf_idx, /* I Index to newest samples in buffers */
opus_int decisionDelay /* I */
)
{
opus_int i, j, k, Winner_ind, RDmin_ind, RDmax_ind, last_smple_idx;
opus_int32 Winner_rand_state;
opus_int32 LTP_pred_Q14, LPC_pred_Q14, n_AR_Q14, n_LTP_Q14;
opus_int32 n_LF_Q14, r_Q10, rr_Q10, rd1_Q10, rd2_Q10, RDmin_Q10, RDmax_Q10;
opus_int32 q1_Q0, q1_Q10, q2_Q10, exc_Q14, LPC_exc_Q14, xq_Q14, Gain_Q10;
opus_int32 tmp1, tmp2, sLF_AR_shp_Q14;
opus_int32 *pred_lag_ptr, *shp_lag_ptr, *psLPC_Q14;
VARDECL( NSQ_sample_pair, psSampleState );
NSQ_del_dec_struct *psDD;
NSQ_sample_struct *psSS;
__m128i a_Q12_0123, a_Q12_4567, a_Q12_89AB, a_Q12_CDEF;
__m128i b_Q12_0123, b_sr_Q12_0123;
SAVE_STACK;
silk_assert( nStatesDelayedDecision > 0 );
ALLOC( psSampleState, nStatesDelayedDecision, NSQ_sample_pair );
shp_lag_ptr = &NSQ->sLTP_shp_Q14[ NSQ->sLTP_shp_buf_idx - lag + HARM_SHAPE_FIR_TAPS / 2 ];
pred_lag_ptr = &sLTP_Q15[ NSQ->sLTP_buf_idx - lag + LTP_ORDER / 2 ];
Gain_Q10 = silk_RSHIFT( Gain_Q16, 6 );
a_Q12_0123 = OP_CVTEPI16_EPI32_M64( a_Q12 );
a_Q12_4567 = OP_CVTEPI16_EPI32_M64( a_Q12 + 4 );
if( opus_likely( predictLPCOrder == 16 ) ) {
a_Q12_89AB = OP_CVTEPI16_EPI32_M64( a_Q12 + 8 );
a_Q12_CDEF = OP_CVTEPI16_EPI32_M64( a_Q12 + 12 );
}
if( signalType == TYPE_VOICED ){
b_Q12_0123 = OP_CVTEPI16_EPI32_M64( b_Q14 );
b_sr_Q12_0123 = _mm_shuffle_epi32( b_Q12_0123, _MM_SHUFFLE( 0, 3, 2, 1 ) ); /* equal shift right 4 bytes */
}
for( i = 0; i < length; i++ ) {
/* Perform common calculations used in all states */
/* Long-term prediction */
if( signalType == TYPE_VOICED ) {
/* Unrolled loop */
/* Avoids introducing a bias because silk_SMLAWB() always rounds to -inf */
LTP_pred_Q14 = 2;
{
__m128i tmpa, tmpb, pred_lag_ptr_tmp;
pred_lag_ptr_tmp = _mm_loadu_si128( (__m128i *)(&pred_lag_ptr[ -3 ] ) );
pred_lag_ptr_tmp = _mm_shuffle_epi32( pred_lag_ptr_tmp, 0x1B );
tmpa = _mm_mul_epi32( pred_lag_ptr_tmp, b_Q12_0123 );
tmpa = _mm_srli_si128( tmpa, 2 );
pred_lag_ptr_tmp = _mm_shuffle_epi32( pred_lag_ptr_tmp, _MM_SHUFFLE( 0, 3, 2, 1 ) );/* equal shift right 4 bytes */
pred_lag_ptr_tmp = _mm_mul_epi32( pred_lag_ptr_tmp, b_sr_Q12_0123 );
pred_lag_ptr_tmp = _mm_srli_si128( pred_lag_ptr_tmp, 2 );
pred_lag_ptr_tmp = _mm_add_epi32( pred_lag_ptr_tmp, tmpa );
tmpb = _mm_shuffle_epi32( pred_lag_ptr_tmp, _MM_SHUFFLE( 0, 0, 3, 2 ) );/* equal shift right 8 bytes */
pred_lag_ptr_tmp = _mm_add_epi32( pred_lag_ptr_tmp, tmpb );
LTP_pred_Q14 += _mm_cvtsi128_si32( pred_lag_ptr_tmp );
LTP_pred_Q14 = silk_SMLAWB( LTP_pred_Q14, pred_lag_ptr[ -4 ], b_Q14[ 4 ] );
LTP_pred_Q14 = silk_LSHIFT( LTP_pred_Q14, 1 ); /* Q13 -> Q14 */
pred_lag_ptr++;
}
} else {
LTP_pred_Q14 = 0;
}
/* Long-term shaping */
if( lag > 0 ) {
/* Symmetric, packed FIR coefficients */
n_LTP_Q14 = silk_SMULWB( silk_ADD32( shp_lag_ptr[ 0 ], shp_lag_ptr[ -2 ] ), HarmShapeFIRPacked_Q14 );
n_LTP_Q14 = silk_SMLAWT( n_LTP_Q14, shp_lag_ptr[ -1 ], HarmShapeFIRPacked_Q14 );
n_LTP_Q14 = silk_SUB_LSHIFT32( LTP_pred_Q14, n_LTP_Q14, 2 ); /* Q12 -> Q14 */
shp_lag_ptr++;
} else {
n_LTP_Q14 = 0;
}
{
__m128i tmpa, tmpb, psLPC_Q14_tmp, a_Q12_tmp;
for( k = 0; k < nStatesDelayedDecision; k++ ) {
/* Delayed decision state */
psDD = &psDelDec[ k ];
/* Sample state */
psSS = psSampleState[ k ];
/* Generate dither */
psDD->Seed = silk_RAND( psDD->Seed );
/* Pointer used in short term prediction and shaping */
psLPC_Q14 = &psDD->sLPC_Q14[ NSQ_LPC_BUF_LENGTH - 1 + i ];
/* Short-term prediction */
silk_assert( predictLPCOrder == 10 || predictLPCOrder == 16 );
/* Avoids introducing a bias because silk_SMLAWB() always rounds to -inf */
LPC_pred_Q14 = silk_RSHIFT( predictLPCOrder, 1 );
tmpb = _mm_setzero_si128();
/* step 1 */
psLPC_Q14_tmp = _mm_loadu_si128( (__m128i *)(&psLPC_Q14[ -3 ] ) ); /* -3, -2 , -1, 0 */
psLPC_Q14_tmp = _mm_shuffle_epi32( psLPC_Q14_tmp, 0x1B ); /* 0, -1, -2, -3 */
tmpa = _mm_mul_epi32( psLPC_Q14_tmp, a_Q12_0123 ); /* 0, -1, -2, -3 * 0123 -> 0*0, 2*-2 */
tmpa = _mm_srli_epi64( tmpa, 16 );
tmpb = _mm_add_epi32( tmpb, tmpa );
psLPC_Q14_tmp = _mm_shuffle_epi32( psLPC_Q14_tmp, _MM_SHUFFLE( 0, 3, 2, 1 ) ); /* equal shift right 4 bytes */
a_Q12_tmp = _mm_shuffle_epi32( a_Q12_0123, _MM_SHUFFLE(0, 3, 2, 1 ) ); /* equal shift right 4 bytes */
psLPC_Q14_tmp = _mm_mul_epi32( psLPC_Q14_tmp, a_Q12_tmp ); /* 1*-1, 3*-3 */
psLPC_Q14_tmp = _mm_srli_epi64( psLPC_Q14_tmp, 16 );
tmpb = _mm_add_epi32( tmpb, psLPC_Q14_tmp );
/* step 2 */
psLPC_Q14_tmp = _mm_loadu_si128( (__m128i *)(&psLPC_Q14[ -7 ] ) );
psLPC_Q14_tmp = _mm_shuffle_epi32( psLPC_Q14_tmp, 0x1B );
tmpa = _mm_mul_epi32( psLPC_Q14_tmp, a_Q12_4567 );
tmpa = _mm_srli_epi64( tmpa, 16 );
tmpb = _mm_add_epi32( tmpb, tmpa );
psLPC_Q14_tmp = _mm_shuffle_epi32( psLPC_Q14_tmp, _MM_SHUFFLE( 0, 3, 2, 1 ) ); /* equal shift right 4 bytes */
a_Q12_tmp = _mm_shuffle_epi32( a_Q12_4567, _MM_SHUFFLE(0, 3, 2, 1 ) ); /* equal shift right 4 bytes */
psLPC_Q14_tmp = _mm_mul_epi32( psLPC_Q14_tmp, a_Q12_tmp );
psLPC_Q14_tmp = _mm_srli_epi64( psLPC_Q14_tmp, 16 );
tmpb = _mm_add_epi32( tmpb, psLPC_Q14_tmp );
if ( opus_likely( predictLPCOrder == 16 ) )
{
/* step 3 */
psLPC_Q14_tmp = _mm_loadu_si128( (__m128i *)(&psLPC_Q14[ -11 ] ) );
psLPC_Q14_tmp = _mm_shuffle_epi32( psLPC_Q14_tmp, 0x1B );
tmpa = _mm_mul_epi32( psLPC_Q14_tmp, a_Q12_89AB );
tmpa = _mm_srli_epi64( tmpa, 16 );
tmpb = _mm_add_epi32( tmpb, tmpa );
psLPC_Q14_tmp = _mm_shuffle_epi32( psLPC_Q14_tmp, _MM_SHUFFLE( 0, 3, 2, 1 ) ); /* equal shift right 4 bytes */
a_Q12_tmp = _mm_shuffle_epi32( a_Q12_89AB, _MM_SHUFFLE(0, 3, 2, 1 ) );/* equal shift right 4 bytes */
psLPC_Q14_tmp = _mm_mul_epi32( psLPC_Q14_tmp, a_Q12_tmp );
psLPC_Q14_tmp = _mm_srli_epi64( psLPC_Q14_tmp, 16 );
tmpb = _mm_add_epi32( tmpb, psLPC_Q14_tmp );
/* setp 4 */
psLPC_Q14_tmp = _mm_loadu_si128( (__m128i *)(&psLPC_Q14[ -15 ] ) );
psLPC_Q14_tmp = _mm_shuffle_epi32( psLPC_Q14_tmp, 0x1B );
tmpa = _mm_mul_epi32( psLPC_Q14_tmp, a_Q12_CDEF );
tmpa = _mm_srli_epi64( tmpa, 16 );
tmpb = _mm_add_epi32( tmpb, tmpa );
psLPC_Q14_tmp = _mm_shuffle_epi32( psLPC_Q14_tmp, _MM_SHUFFLE( 0, 3, 2, 1 ) ); /* equal shift right 4 bytes */
a_Q12_tmp = _mm_shuffle_epi32( a_Q12_CDEF, _MM_SHUFFLE(0, 3, 2, 1 ) ); /* equal shift right 4 bytes */
psLPC_Q14_tmp = _mm_mul_epi32( psLPC_Q14_tmp, a_Q12_tmp );
psLPC_Q14_tmp = _mm_srli_epi64( psLPC_Q14_tmp, 16 );
tmpb = _mm_add_epi32( tmpb, psLPC_Q14_tmp );
/* add at last */
/* equal shift right 8 bytes*/
tmpa = _mm_shuffle_epi32( tmpb, _MM_SHUFFLE( 0, 0, 3, 2 ) );
tmpb = _mm_add_epi32( tmpb, tmpa );
LPC_pred_Q14 += _mm_cvtsi128_si32( tmpb );
}
else
{
/* add at last */
tmpa = _mm_shuffle_epi32( tmpb, _MM_SHUFFLE( 0, 0, 3, 2 ) ); /* equal shift right 8 bytes*/
tmpb = _mm_add_epi32( tmpb, tmpa );
LPC_pred_Q14 += _mm_cvtsi128_si32( tmpb );
LPC_pred_Q14 = silk_SMLAWB( LPC_pred_Q14, psLPC_Q14[ -8 ], a_Q12[ 8 ] );
LPC_pred_Q14 = silk_SMLAWB( LPC_pred_Q14, psLPC_Q14[ -9 ], a_Q12[ 9 ] );
}
LPC_pred_Q14 = silk_LSHIFT( LPC_pred_Q14, 4 ); /* Q10 -> Q14 */
/* Noise shape feedback */
silk_assert( ( shapingLPCOrder & 1 ) == 0 ); /* check that order is even */
/* Output of lowpass section */
tmp2 = silk_SMLAWB( psLPC_Q14[ 0 ], psDD->sAR2_Q14[ 0 ], warping_Q16 );
/* Output of allpass section */
tmp1 = silk_SMLAWB( psDD->sAR2_Q14[ 0 ], psDD->sAR2_Q14[ 1 ] - tmp2, warping_Q16 );
psDD->sAR2_Q14[ 0 ] = tmp2;
n_AR_Q14 = silk_RSHIFT( shapingLPCOrder, 1 );
n_AR_Q14 = silk_SMLAWB( n_AR_Q14, tmp2, AR_shp_Q13[ 0 ] );
/* Loop over allpass sections */
for( j = 2; j < shapingLPCOrder; j += 2 ) {
/* Output of allpass section */
tmp2 = silk_SMLAWB( psDD->sAR2_Q14[ j - 1 ], psDD->sAR2_Q14[ j + 0 ] - tmp1, warping_Q16 );
psDD->sAR2_Q14[ j - 1 ] = tmp1;
n_AR_Q14 = silk_SMLAWB( n_AR_Q14, tmp1, AR_shp_Q13[ j - 1 ] );
/* Output of allpass section */
tmp1 = silk_SMLAWB( psDD->sAR2_Q14[ j + 0 ], psDD->sAR2_Q14[ j + 1 ] - tmp2, warping_Q16 );
psDD->sAR2_Q14[ j + 0 ] = tmp2;
n_AR_Q14 = silk_SMLAWB( n_AR_Q14, tmp2, AR_shp_Q13[ j ] );
}
psDD->sAR2_Q14[ shapingLPCOrder - 1 ] = tmp1;
n_AR_Q14 = silk_SMLAWB( n_AR_Q14, tmp1, AR_shp_Q13[ shapingLPCOrder - 1 ] );
n_AR_Q14 = silk_LSHIFT( n_AR_Q14, 1 ); /* Q11 -> Q12 */
n_AR_Q14 = silk_SMLAWB( n_AR_Q14, psDD->LF_AR_Q14, Tilt_Q14 ); /* Q12 */
n_AR_Q14 = silk_LSHIFT( n_AR_Q14, 2 ); /* Q12 -> Q14 */
n_LF_Q14 = silk_SMULWB( psDD->Shape_Q14[ *smpl_buf_idx ], LF_shp_Q14 ); /* Q12 */
n_LF_Q14 = silk_SMLAWT( n_LF_Q14, psDD->LF_AR_Q14, LF_shp_Q14 ); /* Q12 */
n_LF_Q14 = silk_LSHIFT( n_LF_Q14, 2 ); /* Q12 -> Q14 */
/* Input minus prediction plus noise feedback */
/* r = x[ i ] - LTP_pred - LPC_pred + n_AR + n_Tilt + n_LF + n_LTP */
tmp1 = silk_ADD32( n_AR_Q14, n_LF_Q14 ); /* Q14 */
tmp2 = silk_ADD32( n_LTP_Q14, LPC_pred_Q14 ); /* Q13 */
tmp1 = silk_SUB32( tmp2, tmp1 ); /* Q13 */
tmp1 = silk_RSHIFT_ROUND( tmp1, 4 ); /* Q10 */
r_Q10 = silk_SUB32( x_Q10[ i ], tmp1 ); /* residual error Q10 */
/* Flip sign depending on dither */
if ( psDD->Seed < 0 ) {
r_Q10 = -r_Q10;
}
r_Q10 = silk_LIMIT_32( r_Q10, -(31 << 10), 30 << 10 );
/* Find two quantization level candidates and measure their rate-distortion */
q1_Q10 = silk_SUB32( r_Q10, offset_Q10 );
q1_Q0 = silk_RSHIFT( q1_Q10, 10 );
if( q1_Q0 > 0 ) {
q1_Q10 = silk_SUB32( silk_LSHIFT( q1_Q0, 10 ), QUANT_LEVEL_ADJUST_Q10 );
q1_Q10 = silk_ADD32( q1_Q10, offset_Q10 );
q2_Q10 = silk_ADD32( q1_Q10, 1024 );
rd1_Q10 = silk_SMULBB( q1_Q10, Lambda_Q10 );
rd2_Q10 = silk_SMULBB( q2_Q10, Lambda_Q10 );
} else if( q1_Q0 == 0 ) {
q1_Q10 = offset_Q10;
q2_Q10 = silk_ADD32( q1_Q10, 1024 - QUANT_LEVEL_ADJUST_Q10 );
rd1_Q10 = silk_SMULBB( q1_Q10, Lambda_Q10 );
rd2_Q10 = silk_SMULBB( q2_Q10, Lambda_Q10 );
} else if( q1_Q0 == -1 ) {
q2_Q10 = offset_Q10;
q1_Q10 = silk_SUB32( q2_Q10, 1024 - QUANT_LEVEL_ADJUST_Q10 );
rd1_Q10 = silk_SMULBB( -q1_Q10, Lambda_Q10 );
rd2_Q10 = silk_SMULBB( q2_Q10, Lambda_Q10 );
} else { /* q1_Q0 < -1 */
q1_Q10 = silk_ADD32( silk_LSHIFT( q1_Q0, 10 ), QUANT_LEVEL_ADJUST_Q10 );
q1_Q10 = silk_ADD32( q1_Q10, offset_Q10 );
q2_Q10 = silk_ADD32( q1_Q10, 1024 );
rd1_Q10 = silk_SMULBB( -q1_Q10, Lambda_Q10 );
rd2_Q10 = silk_SMULBB( -q2_Q10, Lambda_Q10 );
}
rr_Q10 = silk_SUB32( r_Q10, q1_Q10 );
rd1_Q10 = silk_RSHIFT( silk_SMLABB( rd1_Q10, rr_Q10, rr_Q10 ), 10 );
rr_Q10 = silk_SUB32( r_Q10, q2_Q10 );
rd2_Q10 = silk_RSHIFT( silk_SMLABB( rd2_Q10, rr_Q10, rr_Q10 ), 10 );
if( rd1_Q10 < rd2_Q10 ) {
psSS[ 0 ].RD_Q10 = silk_ADD32( psDD->RD_Q10, rd1_Q10 );
psSS[ 1 ].RD_Q10 = silk_ADD32( psDD->RD_Q10, rd2_Q10 );
psSS[ 0 ].Q_Q10 = q1_Q10;
psSS[ 1 ].Q_Q10 = q2_Q10;
} else {
psSS[ 0 ].RD_Q10 = silk_ADD32( psDD->RD_Q10, rd2_Q10 );
psSS[ 1 ].RD_Q10 = silk_ADD32( psDD->RD_Q10, rd1_Q10 );
psSS[ 0 ].Q_Q10 = q2_Q10;
psSS[ 1 ].Q_Q10 = q1_Q10;
}
/* Update states for best quantization */
/* Quantized excitation */
exc_Q14 = silk_LSHIFT32( psSS[ 0 ].Q_Q10, 4 );
if ( psDD->Seed < 0 ) {
exc_Q14 = -exc_Q14;
}
/* Add predictions */
LPC_exc_Q14 = silk_ADD32( exc_Q14, LTP_pred_Q14 );
xq_Q14 = silk_ADD32( LPC_exc_Q14, LPC_pred_Q14 );
/* Update states */
sLF_AR_shp_Q14 = silk_SUB32( xq_Q14, n_AR_Q14 );
psSS[ 0 ].sLTP_shp_Q14 = silk_SUB32( sLF_AR_shp_Q14, n_LF_Q14 );
psSS[ 0 ].LF_AR_Q14 = sLF_AR_shp_Q14;
psSS[ 0 ].LPC_exc_Q14 = LPC_exc_Q14;
psSS[ 0 ].xq_Q14 = xq_Q14;
/* Update states for second best quantization */
/* Quantized excitation */
exc_Q14 = silk_LSHIFT32( psSS[ 1 ].Q_Q10, 4 );
if ( psDD->Seed < 0 ) {
exc_Q14 = -exc_Q14;
}
/* Add predictions */
LPC_exc_Q14 = silk_ADD32( exc_Q14, LTP_pred_Q14 );
xq_Q14 = silk_ADD32( LPC_exc_Q14, LPC_pred_Q14 );
/* Update states */
sLF_AR_shp_Q14 = silk_SUB32( xq_Q14, n_AR_Q14 );
psSS[ 1 ].sLTP_shp_Q14 = silk_SUB32( sLF_AR_shp_Q14, n_LF_Q14 );
psSS[ 1 ].LF_AR_Q14 = sLF_AR_shp_Q14;
psSS[ 1 ].LPC_exc_Q14 = LPC_exc_Q14;
psSS[ 1 ].xq_Q14 = xq_Q14;
}
}
*smpl_buf_idx = ( *smpl_buf_idx - 1 ) & DECISION_DELAY_MASK; /* Index to newest samples */
last_smple_idx = ( *smpl_buf_idx + decisionDelay ) & DECISION_DELAY_MASK; /* Index to decisionDelay old samples */
/* Find winner */
RDmin_Q10 = psSampleState[ 0 ][ 0 ].RD_Q10;
Winner_ind = 0;
for( k = 1; k < nStatesDelayedDecision; k++ ) {
if( psSampleState[ k ][ 0 ].RD_Q10 < RDmin_Q10 ) {
RDmin_Q10 = psSampleState[ k ][ 0 ].RD_Q10;
Winner_ind = k;
}
}
/* Increase RD values of expired states */
Winner_rand_state = psDelDec[ Winner_ind ].RandState[ last_smple_idx ];
for( k = 0; k < nStatesDelayedDecision; k++ ) {
if( psDelDec[ k ].RandState[ last_smple_idx ] != Winner_rand_state ) {
psSampleState[ k ][ 0 ].RD_Q10 = silk_ADD32( psSampleState[ k ][ 0 ].RD_Q10, silk_int32_MAX >> 4 );
psSampleState[ k ][ 1 ].RD_Q10 = silk_ADD32( psSampleState[ k ][ 1 ].RD_Q10, silk_int32_MAX >> 4 );
silk_assert( psSampleState[ k ][ 0 ].RD_Q10 >= 0 );
}
}
/* Find worst in first set and best in second set */
RDmax_Q10 = psSampleState[ 0 ][ 0 ].RD_Q10;
RDmin_Q10 = psSampleState[ 0 ][ 1 ].RD_Q10;
RDmax_ind = 0;
RDmin_ind = 0;
for( k = 1; k < nStatesDelayedDecision; k++ ) {
/* find worst in first set */
if( psSampleState[ k ][ 0 ].RD_Q10 > RDmax_Q10 ) {
RDmax_Q10 = psSampleState[ k ][ 0 ].RD_Q10;
RDmax_ind = k;
}
/* find best in second set */
if( psSampleState[ k ][ 1 ].RD_Q10 < RDmin_Q10 ) {
RDmin_Q10 = psSampleState[ k ][ 1 ].RD_Q10;
RDmin_ind = k;
}
}
/* Replace a state if best from second set outperforms worst in first set */
if( RDmin_Q10 < RDmax_Q10 ) {
silk_memcpy( ( (opus_int32 *)&psDelDec[ RDmax_ind ] ) + i,
( (opus_int32 *)&psDelDec[ RDmin_ind ] ) + i, sizeof( NSQ_del_dec_struct ) - i * sizeof( opus_int32) );
silk_memcpy( &psSampleState[ RDmax_ind ][ 0 ], &psSampleState[ RDmin_ind ][ 1 ], sizeof( NSQ_sample_struct ) );
}
/* Write samples from winner to output and long-term filter states */
psDD = &psDelDec[ Winner_ind ];
if( subfr > 0 || i >= decisionDelay ) {
pulses[ i - decisionDelay ] = (opus_int8)silk_RSHIFT_ROUND( psDD->Q_Q10[ last_smple_idx ], 10 );
xq[ i - decisionDelay ] = (opus_int16)silk_SAT16( silk_RSHIFT_ROUND(
silk_SMULWW( psDD->Xq_Q14[ last_smple_idx ], delayedGain_Q10[ last_smple_idx ] ), 8 ) );
NSQ->sLTP_shp_Q14[ NSQ->sLTP_shp_buf_idx - decisionDelay ] = psDD->Shape_Q14[ last_smple_idx ];
sLTP_Q15[ NSQ->sLTP_buf_idx - decisionDelay ] = psDD->Pred_Q15[ last_smple_idx ];
}
NSQ->sLTP_shp_buf_idx++;
NSQ->sLTP_buf_idx++;
/* Update states */
for( k = 0; k < nStatesDelayedDecision; k++ ) {
psDD = &psDelDec[ k ];
psSS = &psSampleState[ k ][ 0 ];
psDD->LF_AR_Q14 = psSS->LF_AR_Q14;
psDD->sLPC_Q14[ NSQ_LPC_BUF_LENGTH + i ] = psSS->xq_Q14;
psDD->Xq_Q14[ *smpl_buf_idx ] = psSS->xq_Q14;
psDD->Q_Q10[ *smpl_buf_idx ] = psSS->Q_Q10;
psDD->Pred_Q15[ *smpl_buf_idx ] = silk_LSHIFT32( psSS->LPC_exc_Q14, 1 );
psDD->Shape_Q14[ *smpl_buf_idx ] = psSS->sLTP_shp_Q14;
psDD->Seed = silk_ADD32_ovflw( psDD->Seed, silk_RSHIFT_ROUND( psSS->Q_Q10, 10 ) );
psDD->RandState[ *smpl_buf_idx ] = psDD->Seed;
psDD->RD_Q10 = psSS->RD_Q10;
}
delayedGain_Q10[ *smpl_buf_idx ] = Gain_Q10;
}
/* Update LPC states */
for( k = 0; k < nStatesDelayedDecision; k++ ) {
psDD = &psDelDec[ k ];
silk_memcpy( psDD->sLPC_Q14, &psDD->sLPC_Q14[ length ], NSQ_LPC_BUF_LENGTH * sizeof( opus_int32 ) );
}
RESTORE_STACK;
}
static OPUS_INLINE void silk_nsq_del_dec_scale_states_sse4_1(
const silk_encoder_state *psEncC, /* I Encoder State */
silk_nsq_state *NSQ, /* I/O NSQ state */
NSQ_del_dec_struct psDelDec[], /* I/O Delayed decision states */
const opus_int32 x_Q3[], /* I Input in Q3 */
opus_int32 x_sc_Q10[], /* O Input scaled with 1/Gain in Q10 */
const opus_int16 sLTP[], /* I Re-whitened LTP state in Q0 */
opus_int32 sLTP_Q15[], /* O LTP state matching scaled input */
opus_int subfr, /* I Subframe number */
opus_int nStatesDelayedDecision, /* I Number of del dec states */
const opus_int LTP_scale_Q14, /* I LTP state scaling */
const opus_int32 Gains_Q16[ MAX_NB_SUBFR ], /* I */
const opus_int pitchL[ MAX_NB_SUBFR ], /* I Pitch lag */
const opus_int signal_type, /* I Signal type */
const opus_int decisionDelay /* I Decision delay */
)
{
opus_int i, k, lag;
opus_int32 gain_adj_Q16, inv_gain_Q31, inv_gain_Q23;
NSQ_del_dec_struct *psDD;
__m128i xmm_inv_gain_Q23, xmm_x_Q3_x2x0, xmm_x_Q3_x3x1;
lag = pitchL[ subfr ];
inv_gain_Q31 = silk_INVERSE32_varQ( silk_max( Gains_Q16[ subfr ], 1 ), 47 );
silk_assert( inv_gain_Q31 != 0 );
/* Calculate gain adjustment factor */
if( Gains_Q16[ subfr ] != NSQ->prev_gain_Q16 ) {
gain_adj_Q16 = silk_DIV32_varQ( NSQ->prev_gain_Q16, Gains_Q16[ subfr ], 16 );
} else {
gain_adj_Q16 = (opus_int32)1 << 16;
}
/* Scale input */
inv_gain_Q23 = silk_RSHIFT_ROUND( inv_gain_Q31, 8 );
/* prepare inv_gain_Q23 in packed 4 32-bits */
xmm_inv_gain_Q23 = _mm_set1_epi32(inv_gain_Q23);
for( i = 0; i < psEncC->subfr_length - 3; i += 4 ) {
xmm_x_Q3_x2x0 = _mm_loadu_si128( (__m128i *)(&(x_Q3[ i ] ) ) );
/* equal shift right 4 bytes*/
xmm_x_Q3_x3x1 = _mm_shuffle_epi32( xmm_x_Q3_x2x0, _MM_SHUFFLE( 0, 3, 2, 1 ) );
xmm_x_Q3_x2x0 = _mm_mul_epi32( xmm_x_Q3_x2x0, xmm_inv_gain_Q23 );
xmm_x_Q3_x3x1 = _mm_mul_epi32( xmm_x_Q3_x3x1, xmm_inv_gain_Q23 );
xmm_x_Q3_x2x0 = _mm_srli_epi64( xmm_x_Q3_x2x0, 16 );
xmm_x_Q3_x3x1 = _mm_slli_epi64( xmm_x_Q3_x3x1, 16 );
xmm_x_Q3_x2x0 = _mm_blend_epi16( xmm_x_Q3_x2x0, xmm_x_Q3_x3x1, 0xCC );
_mm_storeu_si128( (__m128i *)(&(x_sc_Q10[ i ])), xmm_x_Q3_x2x0 );
}
for( ; i < psEncC->subfr_length; i++ ) {
x_sc_Q10[ i ] = silk_SMULWW( x_Q3[ i ], inv_gain_Q23 );
}
/* Save inverse gain */
NSQ->prev_gain_Q16 = Gains_Q16[ subfr ];
/* After rewhitening the LTP state is un-scaled, so scale with inv_gain_Q16 */
if( NSQ->rewhite_flag ) {
if( subfr == 0 ) {
/* Do LTP downscaling */
inv_gain_Q31 = silk_LSHIFT( silk_SMULWB( inv_gain_Q31, LTP_scale_Q14 ), 2 );
}
for( i = NSQ->sLTP_buf_idx - lag - LTP_ORDER / 2; i < NSQ->sLTP_buf_idx; i++ ) {
silk_assert( i < MAX_FRAME_LENGTH );
sLTP_Q15[ i ] = silk_SMULWB( inv_gain_Q31, sLTP[ i ] );
}
}
/* Adjust for changing gain */
if( gain_adj_Q16 != (opus_int32)1 << 16 ) {
/* Scale long-term shaping state */
{
__m128i xmm_gain_adj_Q16, xmm_sLTP_shp_Q14_x2x0, xmm_sLTP_shp_Q14_x3x1;
/* prepare gain_adj_Q16 in packed 4 32-bits */
xmm_gain_adj_Q16 = _mm_set1_epi32( gain_adj_Q16 );
for( i = NSQ->sLTP_shp_buf_idx - psEncC->ltp_mem_length; i < NSQ->sLTP_shp_buf_idx - 3; i += 4 )
{
xmm_sLTP_shp_Q14_x2x0 = _mm_loadu_si128( (__m128i *)(&(NSQ->sLTP_shp_Q14[ i ] ) ) );
/* equal shift right 4 bytes*/
xmm_sLTP_shp_Q14_x3x1 = _mm_shuffle_epi32( xmm_sLTP_shp_Q14_x2x0, _MM_SHUFFLE( 0, 3, 2, 1 ) );
xmm_sLTP_shp_Q14_x2x0 = _mm_mul_epi32( xmm_sLTP_shp_Q14_x2x0, xmm_gain_adj_Q16 );
xmm_sLTP_shp_Q14_x3x1 = _mm_mul_epi32( xmm_sLTP_shp_Q14_x3x1, xmm_gain_adj_Q16 );
xmm_sLTP_shp_Q14_x2x0 = _mm_srli_epi64( xmm_sLTP_shp_Q14_x2x0, 16 );
xmm_sLTP_shp_Q14_x3x1 = _mm_slli_epi64( xmm_sLTP_shp_Q14_x3x1, 16 );
xmm_sLTP_shp_Q14_x2x0 = _mm_blend_epi16( xmm_sLTP_shp_Q14_x2x0, xmm_sLTP_shp_Q14_x3x1, 0xCC );
_mm_storeu_si128( (__m128i *)(&(NSQ->sLTP_shp_Q14[ i ] ) ), xmm_sLTP_shp_Q14_x2x0 );
}
for( ; i < NSQ->sLTP_shp_buf_idx; i++ ) {
NSQ->sLTP_shp_Q14[ i ] = silk_SMULWW( gain_adj_Q16, NSQ->sLTP_shp_Q14[ i ] );
}
/* Scale long-term prediction state */
if( signal_type == TYPE_VOICED && NSQ->rewhite_flag == 0 ) {
for( i = NSQ->sLTP_buf_idx - lag - LTP_ORDER / 2; i < NSQ->sLTP_buf_idx - decisionDelay; i++ ) {
sLTP_Q15[ i ] = silk_SMULWW( gain_adj_Q16, sLTP_Q15[ i ] );
}
}
for( k = 0; k < nStatesDelayedDecision; k++ ) {
psDD = &psDelDec[ k ];
/* Scale scalar states */
psDD->LF_AR_Q14 = silk_SMULWW( gain_adj_Q16, psDD->LF_AR_Q14 );
/* Scale short-term prediction and shaping states */
for( i = 0; i < NSQ_LPC_BUF_LENGTH; i++ ) {
psDD->sLPC_Q14[ i ] = silk_SMULWW( gain_adj_Q16, psDD->sLPC_Q14[ i ] );
}
for( i = 0; i < MAX_SHAPE_LPC_ORDER; i++ ) {
psDD->sAR2_Q14[ i ] = silk_SMULWW( gain_adj_Q16, psDD->sAR2_Q14[ i ] );
}
for( i = 0; i < DECISION_DELAY; i++ ) {
psDD->Pred_Q15[ i ] = silk_SMULWW( gain_adj_Q16, psDD->Pred_Q15[ i ] );
psDD->Shape_Q14[ i ] = silk_SMULWW( gain_adj_Q16, psDD->Shape_Q14[ i ] );
}
}
}
}
}
+720
View File
@@ -0,0 +1,720 @@
/* Copyright (c) 2014, Cisco Systems, INC
Written by XiangMingZhu WeiZhou MinPeng YanWang
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
- Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
- Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <xmmintrin.h>
#include <emmintrin.h>
#include <smmintrin.h>
#include "main.h"
#include "celt/x86/x86cpu.h"
#include "stack_alloc.h"
static OPUS_INLINE void silk_nsq_scale_states_sse4_1(
const silk_encoder_state *psEncC, /* I Encoder State */
silk_nsq_state *NSQ, /* I/O NSQ state */
const opus_int32 x_Q3[], /* I input in Q3 */
opus_int32 x_sc_Q10[], /* O input scaled with 1/Gain */
const opus_int16 sLTP[], /* I re-whitened LTP state in Q0 */
opus_int32 sLTP_Q15[], /* O LTP state matching scaled input */
opus_int subfr, /* I subframe number */
const opus_int LTP_scale_Q14, /* I */
const opus_int32 Gains_Q16[ MAX_NB_SUBFR ], /* I */
const opus_int pitchL[ MAX_NB_SUBFR ], /* I Pitch lag */
const opus_int signal_type /* I Signal type */
);
static OPUS_INLINE void silk_noise_shape_quantizer_10_16_sse4_1(
silk_nsq_state *NSQ, /* I/O NSQ state */
opus_int signalType, /* I Signal type */
const opus_int32 x_sc_Q10[], /* I */
opus_int8 pulses[], /* O */
opus_int16 xq[], /* O */
opus_int32 sLTP_Q15[], /* I/O LTP state */
const opus_int16 a_Q12[], /* I Short term prediction coefs */
const opus_int16 b_Q14[], /* I Long term prediction coefs */
const opus_int16 AR_shp_Q13[], /* I Noise shaping AR coefs */
opus_int lag, /* I Pitch lag */
opus_int32 HarmShapeFIRPacked_Q14, /* I */
opus_int Tilt_Q14, /* I Spectral tilt */
opus_int32 LF_shp_Q14, /* I */
opus_int32 Gain_Q16, /* I */
opus_int offset_Q10, /* I */
opus_int length, /* I Input length */
opus_int32 table[][4] /* I */
);
void silk_NSQ_sse4_1(
const silk_encoder_state *psEncC, /* I/O Encoder State */
silk_nsq_state *NSQ, /* I/O NSQ state */
SideInfoIndices *psIndices, /* I/O Quantization Indices */
const opus_int32 x_Q3[], /* I Prefiltered input signal */
opus_int8 pulses[], /* O Quantized pulse signal */
const opus_int16 PredCoef_Q12[ 2 * MAX_LPC_ORDER ], /* I Short term prediction coefs */
const opus_int16 LTPCoef_Q14[ LTP_ORDER * MAX_NB_SUBFR ], /* I Long term prediction coefs */
const opus_int16 AR2_Q13[ MAX_NB_SUBFR * MAX_SHAPE_LPC_ORDER ], /* I Noise shaping coefs */
const opus_int HarmShapeGain_Q14[ MAX_NB_SUBFR ], /* I Long term shaping coefs */
const opus_int Tilt_Q14[ MAX_NB_SUBFR ], /* I Spectral tilt */
const opus_int32 LF_shp_Q14[ MAX_NB_SUBFR ], /* I Low frequency shaping coefs */
const opus_int32 Gains_Q16[ MAX_NB_SUBFR ], /* I Quantization step sizes */
const opus_int pitchL[ MAX_NB_SUBFR ], /* I Pitch lags */
const opus_int Lambda_Q10, /* I Rate/distortion tradeoff */
const opus_int LTP_scale_Q14 /* I LTP state scaling */
)
{
opus_int k, lag, start_idx, LSF_interpolation_flag;
const opus_int16 *A_Q12, *B_Q14, *AR_shp_Q13;
opus_int16 *pxq;
VARDECL( opus_int32, sLTP_Q15 );
VARDECL( opus_int16, sLTP );
opus_int32 HarmShapeFIRPacked_Q14;
opus_int offset_Q10;
VARDECL( opus_int32, x_sc_Q10 );
opus_int32 table[ 64 ][ 4 ];
opus_int32 tmp1;
opus_int32 q1_Q10, q2_Q10, rd1_Q20, rd2_Q20;
SAVE_STACK;
NSQ->rand_seed = psIndices->Seed;
/* Set unvoiced lag to the previous one, overwrite later for voiced */
lag = NSQ->lagPrev;
silk_assert( NSQ->prev_gain_Q16 != 0 );
offset_Q10 = silk_Quantization_Offsets_Q10[ psIndices->signalType >> 1 ][ psIndices->quantOffsetType ];
/* 0 */
q1_Q10 = offset_Q10;
q2_Q10 = offset_Q10 + ( 1024 - QUANT_LEVEL_ADJUST_Q10 );
rd1_Q20 = q1_Q10 * Lambda_Q10;
rd2_Q20 = q2_Q10 * Lambda_Q10;
table[ 32 ][ 0 ] = q1_Q10;
table[ 32 ][ 1 ] = q2_Q10;
table[ 32 ][ 2 ] = 2 * (q1_Q10 - q2_Q10);
table[ 32 ][ 3 ] = (rd1_Q20 - rd2_Q20) + (q1_Q10 * q1_Q10 - q2_Q10 * q2_Q10);
/* -1 */
q1_Q10 = offset_Q10 - ( 1024 - QUANT_LEVEL_ADJUST_Q10 );
q2_Q10 = offset_Q10;
rd1_Q20 = - q1_Q10 * Lambda_Q10;
rd2_Q20 = q2_Q10 * Lambda_Q10;
table[ 31 ][ 0 ] = q1_Q10;
table[ 31 ][ 1 ] = q2_Q10;
table[ 31 ][ 2 ] = 2 * (q1_Q10 - q2_Q10);
table[ 31 ][ 3 ] = (rd1_Q20 - rd2_Q20) + (q1_Q10 * q1_Q10 - q2_Q10 * q2_Q10);
/* > 0 */
for (k = 1; k <= 31; k++)
{
tmp1 = offset_Q10 + silk_LSHIFT( k, 10 );
q1_Q10 = tmp1 - QUANT_LEVEL_ADJUST_Q10;
q2_Q10 = tmp1 - QUANT_LEVEL_ADJUST_Q10 + 1024;
rd1_Q20 = q1_Q10 * Lambda_Q10;
rd2_Q20 = q2_Q10 * Lambda_Q10;
table[ 32 + k ][ 0 ] = q1_Q10;
table[ 32 + k ][ 1 ] = q2_Q10;
table[ 32 + k ][ 2 ] = 2 * (q1_Q10 - q2_Q10);
table[ 32 + k ][ 3 ] = (rd1_Q20 - rd2_Q20) + (q1_Q10 * q1_Q10 - q2_Q10 * q2_Q10);
}
/* < -1 */
for (k = -32; k <= -2; k++)
{
tmp1 = offset_Q10 + silk_LSHIFT( k, 10 );
q1_Q10 = tmp1 + QUANT_LEVEL_ADJUST_Q10;
q2_Q10 = tmp1 + QUANT_LEVEL_ADJUST_Q10 + 1024;
rd1_Q20 = - q1_Q10 * Lambda_Q10;
rd2_Q20 = - q2_Q10 * Lambda_Q10;
table[ 32 + k ][ 0 ] = q1_Q10;
table[ 32 + k ][ 1 ] = q2_Q10;
table[ 32 + k ][ 2 ] = 2 * (q1_Q10 - q2_Q10);
table[ 32 + k ][ 3 ] = (rd1_Q20 - rd2_Q20) + (q1_Q10 * q1_Q10 - q2_Q10 * q2_Q10);
}
if( psIndices->NLSFInterpCoef_Q2 == 4 ) {
LSF_interpolation_flag = 0;
} else {
LSF_interpolation_flag = 1;
}
ALLOC( sLTP_Q15,
psEncC->ltp_mem_length + psEncC->frame_length, opus_int32 );
ALLOC( sLTP, psEncC->ltp_mem_length + psEncC->frame_length, opus_int16 );
ALLOC( x_sc_Q10, psEncC->subfr_length, opus_int32 );
/* Set up pointers to start of sub frame */
NSQ->sLTP_shp_buf_idx = psEncC->ltp_mem_length;
NSQ->sLTP_buf_idx = psEncC->ltp_mem_length;
pxq = &NSQ->xq[ psEncC->ltp_mem_length ];
for( k = 0; k < psEncC->nb_subfr; k++ ) {
A_Q12 = &PredCoef_Q12[ (( k >> 1 ) | ( 1 - LSF_interpolation_flag )) * MAX_LPC_ORDER ];
B_Q14 = &LTPCoef_Q14[ k * LTP_ORDER ];
AR_shp_Q13 = &AR2_Q13[ k * MAX_SHAPE_LPC_ORDER ];
/* Noise shape parameters */
silk_assert( HarmShapeGain_Q14[ k ] >= 0 );
HarmShapeFIRPacked_Q14 = silk_RSHIFT( HarmShapeGain_Q14[ k ], 2 );
HarmShapeFIRPacked_Q14 |= silk_LSHIFT( (opus_int32)silk_RSHIFT( HarmShapeGain_Q14[ k ], 1 ), 16 );
NSQ->rewhite_flag = 0;
if( psIndices->signalType == TYPE_VOICED ) {
/* Voiced */
lag = pitchL[ k ];
/* Re-whitening */
if( ( k & ( 3 - silk_LSHIFT( LSF_interpolation_flag, 1 ) ) ) == 0 ) {
/* Rewhiten with new A coefs */
start_idx = psEncC->ltp_mem_length - lag - psEncC->predictLPCOrder - LTP_ORDER / 2;
silk_assert( start_idx > 0 );
silk_LPC_analysis_filter( &sLTP[ start_idx ], &NSQ->xq[ start_idx + k * psEncC->subfr_length ],
A_Q12, psEncC->ltp_mem_length - start_idx, psEncC->predictLPCOrder, psEncC->arch );
NSQ->rewhite_flag = 1;
NSQ->sLTP_buf_idx = psEncC->ltp_mem_length;
}
}
silk_nsq_scale_states_sse4_1( psEncC, NSQ, x_Q3, x_sc_Q10, sLTP, sLTP_Q15, k, LTP_scale_Q14, Gains_Q16, pitchL, psIndices->signalType );
if ( opus_likely( ( 10 == psEncC->shapingLPCOrder ) && ( 16 == psEncC->predictLPCOrder) ) )
{
silk_noise_shape_quantizer_10_16_sse4_1( NSQ, psIndices->signalType, x_sc_Q10, pulses, pxq, sLTP_Q15, A_Q12, B_Q14,
AR_shp_Q13, lag, HarmShapeFIRPacked_Q14, Tilt_Q14[ k ], LF_shp_Q14[ k ], Gains_Q16[ k ],
offset_Q10, psEncC->subfr_length, &(table[32]) );
}
else
{
silk_noise_shape_quantizer( NSQ, psIndices->signalType, x_sc_Q10, pulses, pxq, sLTP_Q15, A_Q12, B_Q14,
AR_shp_Q13, lag, HarmShapeFIRPacked_Q14, Tilt_Q14[ k ], LF_shp_Q14[ k ], Gains_Q16[ k ], Lambda_Q10,
offset_Q10, psEncC->subfr_length, psEncC->shapingLPCOrder, psEncC->predictLPCOrder, psEncC->arch );
}
x_Q3 += psEncC->subfr_length;
pulses += psEncC->subfr_length;
pxq += psEncC->subfr_length;
}
/* Update lagPrev for next frame */
NSQ->lagPrev = pitchL[ psEncC->nb_subfr - 1 ];
/* Save quantized speech and noise shaping signals */
/* DEBUG_STORE_DATA( enc.pcm, &NSQ->xq[ psEncC->ltp_mem_length ], psEncC->frame_length * sizeof( opus_int16 ) ) */
silk_memmove( NSQ->xq, &NSQ->xq[ psEncC->frame_length ], psEncC->ltp_mem_length * sizeof( opus_int16 ) );
silk_memmove( NSQ->sLTP_shp_Q14, &NSQ->sLTP_shp_Q14[ psEncC->frame_length ], psEncC->ltp_mem_length * sizeof( opus_int32 ) );
RESTORE_STACK;
}
/***********************************/
/* silk_noise_shape_quantizer_10_16 */
/***********************************/
static OPUS_INLINE void silk_noise_shape_quantizer_10_16_sse4_1(
silk_nsq_state *NSQ, /* I/O NSQ state */
opus_int signalType, /* I Signal type */
const opus_int32 x_sc_Q10[], /* I */
opus_int8 pulses[], /* O */
opus_int16 xq[], /* O */
opus_int32 sLTP_Q15[], /* I/O LTP state */
const opus_int16 a_Q12[], /* I Short term prediction coefs */
const opus_int16 b_Q14[], /* I Long term prediction coefs */
const opus_int16 AR_shp_Q13[], /* I Noise shaping AR coefs */
opus_int lag, /* I Pitch lag */
opus_int32 HarmShapeFIRPacked_Q14, /* I */
opus_int Tilt_Q14, /* I Spectral tilt */
opus_int32 LF_shp_Q14, /* I */
opus_int32 Gain_Q16, /* I */
opus_int offset_Q10, /* I */
opus_int length, /* I Input length */
opus_int32 table[][4] /* I */
)
{
opus_int i;
opus_int32 LTP_pred_Q13, LPC_pred_Q10, n_AR_Q12, n_LTP_Q13;
opus_int32 n_LF_Q12, r_Q10, q1_Q0, q1_Q10, q2_Q10;
opus_int32 exc_Q14, LPC_exc_Q14, xq_Q14, Gain_Q10;
opus_int32 tmp1, tmp2, sLF_AR_shp_Q14;
opus_int32 *psLPC_Q14, *shp_lag_ptr, *pred_lag_ptr;
__m128i xmm_tempa, xmm_tempb;
__m128i xmm_one;
__m128i psLPC_Q14_hi_01234567, psLPC_Q14_hi_89ABCDEF;
__m128i psLPC_Q14_lo_01234567, psLPC_Q14_lo_89ABCDEF;
__m128i a_Q12_01234567, a_Q12_89ABCDEF;
__m128i sAR2_Q14_hi_76543210, sAR2_Q14_lo_76543210;
__m128i AR_shp_Q13_76543210;
shp_lag_ptr = &NSQ->sLTP_shp_Q14[ NSQ->sLTP_shp_buf_idx - lag + HARM_SHAPE_FIR_TAPS / 2 ];
pred_lag_ptr = &sLTP_Q15[ NSQ->sLTP_buf_idx - lag + LTP_ORDER / 2 ];
Gain_Q10 = silk_RSHIFT( Gain_Q16, 6 );
/* Set up short term AR state */
psLPC_Q14 = &NSQ->sLPC_Q14[ NSQ_LPC_BUF_LENGTH - 1 ];
sLF_AR_shp_Q14 = NSQ->sLF_AR_shp_Q14;
xq_Q14 = psLPC_Q14[ 0 ];
LTP_pred_Q13 = 0;
/* load a_Q12 */
xmm_one = _mm_set_epi8( 1, 0, 3, 2, 5, 4, 7, 6, 9, 8, 11, 10, 13, 12, 15, 14 );
/* load a_Q12[0] - a_Q12[7] */
a_Q12_01234567 = _mm_loadu_si128( (__m128i *)(&a_Q12[ 0 ] ) );
/* load a_Q12[ 8 ] - a_Q12[ 15 ] */
a_Q12_89ABCDEF = _mm_loadu_si128( (__m128i *)(&a_Q12[ 8 ] ) );
a_Q12_01234567 = _mm_shuffle_epi8( a_Q12_01234567, xmm_one );
a_Q12_89ABCDEF = _mm_shuffle_epi8( a_Q12_89ABCDEF, xmm_one );
/* load AR_shp_Q13 */
AR_shp_Q13_76543210 = _mm_loadu_si128( (__m128i *)(&AR_shp_Q13[0] ) );
/* load psLPC_Q14 */
xmm_one = _mm_set_epi8(15, 14, 11, 10, 7, 6, 3, 2, 13, 12, 9, 8, 5, 4, 1, 0 );
xmm_tempa = _mm_loadu_si128( (__m128i *)(&psLPC_Q14[-16]) );
xmm_tempb = _mm_loadu_si128( (__m128i *)(&psLPC_Q14[-12]) );
xmm_tempa = _mm_shuffle_epi8( xmm_tempa, xmm_one );
xmm_tempb = _mm_shuffle_epi8( xmm_tempb, xmm_one );
psLPC_Q14_hi_89ABCDEF = _mm_unpackhi_epi64( xmm_tempa, xmm_tempb );
psLPC_Q14_lo_89ABCDEF = _mm_unpacklo_epi64( xmm_tempa, xmm_tempb );
xmm_tempa = _mm_loadu_si128( (__m128i *)(&psLPC_Q14[ -8 ]) );
xmm_tempb = _mm_loadu_si128( (__m128i *)(&psLPC_Q14[ -4 ]) );
xmm_tempa = _mm_shuffle_epi8( xmm_tempa, xmm_one );
xmm_tempb = _mm_shuffle_epi8( xmm_tempb, xmm_one );
psLPC_Q14_hi_01234567 = _mm_unpackhi_epi64( xmm_tempa, xmm_tempb );
psLPC_Q14_lo_01234567 = _mm_unpacklo_epi64( xmm_tempa, xmm_tempb );
/* load sAR2_Q14 */
xmm_tempa = _mm_loadu_si128( (__m128i *)(&(NSQ->sAR2_Q14[ 0 ]) ) );
xmm_tempb = _mm_loadu_si128( (__m128i *)(&(NSQ->sAR2_Q14[ 4 ]) ) );
xmm_tempa = _mm_shuffle_epi8( xmm_tempa, xmm_one );
xmm_tempb = _mm_shuffle_epi8( xmm_tempb, xmm_one );
sAR2_Q14_hi_76543210 = _mm_unpackhi_epi64( xmm_tempa, xmm_tempb );
sAR2_Q14_lo_76543210 = _mm_unpacklo_epi64( xmm_tempa, xmm_tempb );
/* prepare 1 in 8 * 16bit */
xmm_one = _mm_set1_epi16(1);
for( i = 0; i < length; i++ )
{
/* Short-term prediction */
__m128i xmm_hi_07, xmm_hi_8F, xmm_lo_07, xmm_lo_8F;
/* Avoids introducing a bias because silk_SMLAWB() always rounds to -inf */
LPC_pred_Q10 = 8; /* silk_RSHIFT( predictLPCOrder, 1 ); */
/* shift psLPC_Q14 */
psLPC_Q14_hi_89ABCDEF = _mm_alignr_epi8( psLPC_Q14_hi_01234567, psLPC_Q14_hi_89ABCDEF, 2 );
psLPC_Q14_lo_89ABCDEF = _mm_alignr_epi8( psLPC_Q14_lo_01234567, psLPC_Q14_lo_89ABCDEF, 2 );
psLPC_Q14_hi_01234567 = _mm_srli_si128( psLPC_Q14_hi_01234567, 2 );
psLPC_Q14_lo_01234567 = _mm_srli_si128( psLPC_Q14_lo_01234567, 2 );
psLPC_Q14_hi_01234567 = _mm_insert_epi16( psLPC_Q14_hi_01234567, (xq_Q14 >> 16), 7 );
psLPC_Q14_lo_01234567 = _mm_insert_epi16( psLPC_Q14_lo_01234567, (xq_Q14), 7 );
/* high part, use pmaddwd, results in 4 32-bit */
xmm_hi_07 = _mm_madd_epi16( psLPC_Q14_hi_01234567, a_Q12_01234567 );
xmm_hi_8F = _mm_madd_epi16( psLPC_Q14_hi_89ABCDEF, a_Q12_89ABCDEF );
/* low part, use pmulhw, results in 8 16-bit, note we need simulate unsigned * signed, _mm_srai_epi16(psLPC_Q14_lo_01234567, 15) */
xmm_tempa = _mm_cmpgt_epi16( _mm_setzero_si128(), psLPC_Q14_lo_01234567 );
xmm_tempb = _mm_cmpgt_epi16( _mm_setzero_si128(), psLPC_Q14_lo_89ABCDEF );
xmm_tempa = _mm_and_si128( xmm_tempa, a_Q12_01234567 );
xmm_tempb = _mm_and_si128( xmm_tempb, a_Q12_89ABCDEF );
xmm_lo_07 = _mm_mulhi_epi16( psLPC_Q14_lo_01234567, a_Q12_01234567 );
xmm_lo_8F = _mm_mulhi_epi16( psLPC_Q14_lo_89ABCDEF, a_Q12_89ABCDEF );
xmm_lo_07 = _mm_add_epi16( xmm_lo_07, xmm_tempa );
xmm_lo_8F = _mm_add_epi16( xmm_lo_8F, xmm_tempb );
xmm_lo_07 = _mm_madd_epi16( xmm_lo_07, xmm_one );
xmm_lo_8F = _mm_madd_epi16( xmm_lo_8F, xmm_one );
/* accumulate */
xmm_hi_07 = _mm_add_epi32( xmm_hi_07, xmm_hi_8F );
xmm_lo_07 = _mm_add_epi32( xmm_lo_07, xmm_lo_8F );
xmm_hi_07 = _mm_add_epi32( xmm_hi_07, xmm_lo_07 );
xmm_hi_07 = _mm_add_epi32( xmm_hi_07, _mm_unpackhi_epi64(xmm_hi_07, xmm_hi_07 ) );
xmm_hi_07 = _mm_add_epi32( xmm_hi_07, _mm_shufflelo_epi16(xmm_hi_07, 0x0E ) );
LPC_pred_Q10 += _mm_cvtsi128_si32( xmm_hi_07 );
/* Long-term prediction */
if ( opus_likely( signalType == TYPE_VOICED ) ) {
/* Unrolled loop */
/* Avoids introducing a bias because silk_SMLAWB() always rounds to -inf */
LTP_pred_Q13 = 2;
{
__m128i b_Q14_3210, b_Q14_0123, pred_lag_ptr_0123;
b_Q14_3210 = OP_CVTEPI16_EPI32_M64( b_Q14 );
b_Q14_0123 = _mm_shuffle_epi32( b_Q14_3210, 0x1B );
/* loaded: [0] [-1] [-2] [-3] */
pred_lag_ptr_0123 = _mm_loadu_si128( (__m128i *)(&pred_lag_ptr[ -3 ] ) );
/* shuffle to [-3] [-2] [-1] [0] and to new xmm */
xmm_tempa = _mm_shuffle_epi32( pred_lag_ptr_0123, 0x1B );
/*64-bit multiply, a[2] * b[-2], a[0] * b[0] */
xmm_tempa = _mm_mul_epi32( xmm_tempa, b_Q14_3210 );
/* right shift 2 bytes (16 bits), zero extended */
xmm_tempa = _mm_srli_si128( xmm_tempa, 2 );
/* a[1] * b[-1], a[3] * b[-3] */
pred_lag_ptr_0123 = _mm_mul_epi32( pred_lag_ptr_0123, b_Q14_0123 );
pred_lag_ptr_0123 = _mm_srli_si128( pred_lag_ptr_0123, 2 );
pred_lag_ptr_0123 = _mm_add_epi32( pred_lag_ptr_0123, xmm_tempa );
/* equal shift right 8 bytes*/
xmm_tempa = _mm_shuffle_epi32( pred_lag_ptr_0123, _MM_SHUFFLE( 0, 0, 3, 2 ) );
xmm_tempa = _mm_add_epi32( xmm_tempa, pred_lag_ptr_0123 );
LTP_pred_Q13 += _mm_cvtsi128_si32( xmm_tempa );
LTP_pred_Q13 = silk_SMLAWB( LTP_pred_Q13, pred_lag_ptr[ -4 ], b_Q14[ 4 ] );
pred_lag_ptr++;
}
}
/* Noise shape feedback */
NSQ->sAR2_Q14[ 9 ] = NSQ->sAR2_Q14[ 8 ];
NSQ->sAR2_Q14[ 8 ] = _mm_cvtsi128_si32( _mm_srli_si128(_mm_unpackhi_epi16( sAR2_Q14_lo_76543210, sAR2_Q14_hi_76543210 ), 12 ) );
sAR2_Q14_hi_76543210 = _mm_slli_si128( sAR2_Q14_hi_76543210, 2 );
sAR2_Q14_lo_76543210 = _mm_slli_si128( sAR2_Q14_lo_76543210, 2 );
sAR2_Q14_hi_76543210 = _mm_insert_epi16( sAR2_Q14_hi_76543210, (xq_Q14 >> 16), 0 );
sAR2_Q14_lo_76543210 = _mm_insert_epi16( sAR2_Q14_lo_76543210, (xq_Q14), 0 );
/* high part, use pmaddwd, results in 4 32-bit */
xmm_hi_07 = _mm_madd_epi16( sAR2_Q14_hi_76543210, AR_shp_Q13_76543210 );
/* low part, use pmulhw, results in 8 16-bit, note we need simulate unsigned * signed,_mm_srai_epi16(sAR2_Q14_lo_76543210, 15) */
xmm_tempa = _mm_cmpgt_epi16( _mm_setzero_si128(), sAR2_Q14_lo_76543210 );
xmm_tempa = _mm_and_si128( xmm_tempa, AR_shp_Q13_76543210 );
xmm_lo_07 = _mm_mulhi_epi16( sAR2_Q14_lo_76543210, AR_shp_Q13_76543210 );
xmm_lo_07 = _mm_add_epi16( xmm_lo_07, xmm_tempa );
xmm_lo_07 = _mm_madd_epi16( xmm_lo_07, xmm_one );
/* accumulate */
xmm_hi_07 = _mm_add_epi32( xmm_hi_07, xmm_lo_07 );
xmm_hi_07 = _mm_add_epi32( xmm_hi_07, _mm_unpackhi_epi64(xmm_hi_07, xmm_hi_07 ) );
xmm_hi_07 = _mm_add_epi32( xmm_hi_07, _mm_shufflelo_epi16(xmm_hi_07, 0x0E ) );
n_AR_Q12 = 5 + _mm_cvtsi128_si32( xmm_hi_07 );
n_AR_Q12 = silk_SMLAWB( n_AR_Q12, NSQ->sAR2_Q14[ 8 ], AR_shp_Q13[ 8 ] );
n_AR_Q12 = silk_SMLAWB( n_AR_Q12, NSQ->sAR2_Q14[ 9 ], AR_shp_Q13[ 9 ] );
n_AR_Q12 = silk_LSHIFT32( n_AR_Q12, 1 ); /* Q11 -> Q12 */
n_AR_Q12 = silk_SMLAWB( n_AR_Q12, sLF_AR_shp_Q14, Tilt_Q14 );
n_LF_Q12 = silk_SMULWB( NSQ->sLTP_shp_Q14[ NSQ->sLTP_shp_buf_idx - 1 ], LF_shp_Q14 );
n_LF_Q12 = silk_SMLAWT( n_LF_Q12, sLF_AR_shp_Q14, LF_shp_Q14 );
silk_assert( lag > 0 || signalType != TYPE_VOICED );
/* Combine prediction and noise shaping signals */
tmp1 = silk_SUB32( silk_LSHIFT32( LPC_pred_Q10, 2 ), n_AR_Q12 ); /* Q12 */
tmp1 = silk_SUB32( tmp1, n_LF_Q12 ); /* Q12 */
if( lag > 0 ) {
/* Symmetric, packed FIR coefficients */
n_LTP_Q13 = silk_SMULWB( silk_ADD32( shp_lag_ptr[ 0 ], shp_lag_ptr[ -2 ] ), HarmShapeFIRPacked_Q14 );
n_LTP_Q13 = silk_SMLAWT( n_LTP_Q13, shp_lag_ptr[ -1 ], HarmShapeFIRPacked_Q14 );
n_LTP_Q13 = silk_LSHIFT( n_LTP_Q13, 1 );
shp_lag_ptr++;
tmp2 = silk_SUB32( LTP_pred_Q13, n_LTP_Q13 ); /* Q13 */
tmp1 = silk_ADD_LSHIFT32( tmp2, tmp1, 1 ); /* Q13 */
tmp1 = silk_RSHIFT_ROUND( tmp1, 3 ); /* Q10 */
} else {
tmp1 = silk_RSHIFT_ROUND( tmp1, 2 ); /* Q10 */
}
r_Q10 = silk_SUB32( x_sc_Q10[ i ], tmp1 ); /* residual error Q10 */
/* Generate dither */
NSQ->rand_seed = silk_RAND( NSQ->rand_seed );
/* Flip sign depending on dither */
tmp2 = -r_Q10;
if ( NSQ->rand_seed < 0 ) r_Q10 = tmp2;
r_Q10 = silk_LIMIT_32( r_Q10, -(31 << 10), 30 << 10 );
/* Find two quantization level candidates and measure their rate-distortion */
q1_Q10 = silk_SUB32( r_Q10, offset_Q10 );
q1_Q0 = silk_RSHIFT( q1_Q10, 10 );
q1_Q10 = table[q1_Q0][0];
q2_Q10 = table[q1_Q0][1];
if (r_Q10 * table[q1_Q0][2] - table[q1_Q0][3] < 0)
{
q1_Q10 = q2_Q10;
}
pulses[ i ] = (opus_int8)silk_RSHIFT_ROUND( q1_Q10, 10 );
/* Excitation */
exc_Q14 = silk_LSHIFT( q1_Q10, 4 );
tmp2 = -exc_Q14;
if ( NSQ->rand_seed < 0 ) exc_Q14 = tmp2;
/* Add predictions */
LPC_exc_Q14 = silk_ADD_LSHIFT32( exc_Q14, LTP_pred_Q13, 1 );
xq_Q14 = silk_ADD_LSHIFT32( LPC_exc_Q14, LPC_pred_Q10, 4 );
/* Update states */
psLPC_Q14++;
*psLPC_Q14 = xq_Q14;
sLF_AR_shp_Q14 = silk_SUB_LSHIFT32( xq_Q14, n_AR_Q12, 2 );
NSQ->sLTP_shp_Q14[ NSQ->sLTP_shp_buf_idx ] = silk_SUB_LSHIFT32( sLF_AR_shp_Q14, n_LF_Q12, 2 );
sLTP_Q15[ NSQ->sLTP_buf_idx ] = silk_LSHIFT( LPC_exc_Q14, 1 );
NSQ->sLTP_shp_buf_idx++;
NSQ->sLTP_buf_idx++;
/* Make dither dependent on quantized signal */
NSQ->rand_seed = silk_ADD32_ovflw( NSQ->rand_seed, pulses[ i ] );
}
NSQ->sLF_AR_shp_Q14 = sLF_AR_shp_Q14;
/* Scale XQ back to normal level before saving */
psLPC_Q14 = &NSQ->sLPC_Q14[ NSQ_LPC_BUF_LENGTH ];
/* write back sAR2_Q14 */
xmm_tempa = _mm_unpackhi_epi16( sAR2_Q14_lo_76543210, sAR2_Q14_hi_76543210 );
xmm_tempb = _mm_unpacklo_epi16( sAR2_Q14_lo_76543210, sAR2_Q14_hi_76543210 );
_mm_storeu_si128( (__m128i *)(&NSQ->sAR2_Q14[ 4 ]), xmm_tempa );
_mm_storeu_si128( (__m128i *)(&NSQ->sAR2_Q14[ 0 ]), xmm_tempb );
/* xq[ i ] = (opus_int16)silk_SAT16( silk_RSHIFT_ROUND( silk_SMULWW( psLPC_Q14[ i ], Gain_Q10 ), 8 ) ); */
{
__m128i xmm_Gain_Q10;
__m128i xmm_xq_Q14_3210, xmm_xq_Q14_x3x1, xmm_xq_Q14_7654, xmm_xq_Q14_x7x5;
/* prepare (1 << 7) in packed 4 32-bits */
xmm_tempa = _mm_set1_epi32( (1 << 7) );
/* prepare Gain_Q10 in packed 4 32-bits */
xmm_Gain_Q10 = _mm_set1_epi32( Gain_Q10 );
/* process xq */
for (i = 0; i < length - 7; i += 8)
{
xmm_xq_Q14_3210 = _mm_loadu_si128( (__m128i *)(&(psLPC_Q14[ i + 0 ] ) ) );
xmm_xq_Q14_7654 = _mm_loadu_si128( (__m128i *)(&(psLPC_Q14[ i + 4 ] ) ) );
/* equal shift right 4 bytes*/
xmm_xq_Q14_x3x1 = _mm_shuffle_epi32( xmm_xq_Q14_3210, _MM_SHUFFLE( 0, 3, 2, 1 ) );
/* equal shift right 4 bytes*/
xmm_xq_Q14_x7x5 = _mm_shuffle_epi32( xmm_xq_Q14_7654, _MM_SHUFFLE( 0, 3, 2, 1 ) );
xmm_xq_Q14_3210 = _mm_mul_epi32( xmm_xq_Q14_3210, xmm_Gain_Q10 );
xmm_xq_Q14_x3x1 = _mm_mul_epi32( xmm_xq_Q14_x3x1, xmm_Gain_Q10 );
xmm_xq_Q14_7654 = _mm_mul_epi32( xmm_xq_Q14_7654, xmm_Gain_Q10 );
xmm_xq_Q14_x7x5 = _mm_mul_epi32( xmm_xq_Q14_x7x5, xmm_Gain_Q10 );
xmm_xq_Q14_3210 = _mm_srli_epi64( xmm_xq_Q14_3210, 16 );
xmm_xq_Q14_x3x1 = _mm_slli_epi64( xmm_xq_Q14_x3x1, 16 );
xmm_xq_Q14_7654 = _mm_srli_epi64( xmm_xq_Q14_7654, 16 );
xmm_xq_Q14_x7x5 = _mm_slli_epi64( xmm_xq_Q14_x7x5, 16 );
xmm_xq_Q14_3210 = _mm_blend_epi16( xmm_xq_Q14_3210, xmm_xq_Q14_x3x1, 0xCC );
xmm_xq_Q14_7654 = _mm_blend_epi16( xmm_xq_Q14_7654, xmm_xq_Q14_x7x5, 0xCC );
/* silk_RSHIFT_ROUND(xq, 8) */
xmm_xq_Q14_3210 = _mm_add_epi32( xmm_xq_Q14_3210, xmm_tempa );
xmm_xq_Q14_7654 = _mm_add_epi32( xmm_xq_Q14_7654, xmm_tempa );
xmm_xq_Q14_3210 = _mm_srai_epi32( xmm_xq_Q14_3210, 8 );
xmm_xq_Q14_7654 = _mm_srai_epi32( xmm_xq_Q14_7654, 8 );
/* silk_SAT16 */
xmm_xq_Q14_3210 = _mm_packs_epi32( xmm_xq_Q14_3210, xmm_xq_Q14_7654 );
/* save to xq */
_mm_storeu_si128( (__m128i *)(&xq[ i ] ), xmm_xq_Q14_3210 );
}
}
for ( ; i < length; i++)
{
xq[i] = (opus_int16)silk_SAT16( silk_RSHIFT_ROUND( silk_SMULWW( psLPC_Q14[ i ], Gain_Q10 ), 8 ) );
}
/* Update LPC synth buffer */
silk_memcpy( NSQ->sLPC_Q14, &NSQ->sLPC_Q14[ length ], NSQ_LPC_BUF_LENGTH * sizeof( opus_int32 ) );
}
static OPUS_INLINE void silk_nsq_scale_states_sse4_1(
const silk_encoder_state *psEncC, /* I Encoder State */
silk_nsq_state *NSQ, /* I/O NSQ state */
const opus_int32 x_Q3[], /* I input in Q3 */
opus_int32 x_sc_Q10[], /* O input scaled with 1/Gain */
const opus_int16 sLTP[], /* I re-whitened LTP state in Q0 */
opus_int32 sLTP_Q15[], /* O LTP state matching scaled input */
opus_int subfr, /* I subframe number */
const opus_int LTP_scale_Q14, /* I */
const opus_int32 Gains_Q16[ MAX_NB_SUBFR ], /* I */
const opus_int pitchL[ MAX_NB_SUBFR ], /* I Pitch lag */
const opus_int signal_type /* I Signal type */
)
{
opus_int i, lag;
opus_int32 gain_adj_Q16, inv_gain_Q31, inv_gain_Q23;
__m128i xmm_inv_gain_Q23, xmm_x_Q3_x2x0, xmm_x_Q3_x3x1;
lag = pitchL[ subfr ];
inv_gain_Q31 = silk_INVERSE32_varQ( silk_max( Gains_Q16[ subfr ], 1 ), 47 );
silk_assert( inv_gain_Q31 != 0 );
/* Calculate gain adjustment factor */
if( Gains_Q16[ subfr ] != NSQ->prev_gain_Q16 ) {
gain_adj_Q16 = silk_DIV32_varQ( NSQ->prev_gain_Q16, Gains_Q16[ subfr ], 16 );
} else {
gain_adj_Q16 = (opus_int32)1 << 16;
}
/* Scale input */
inv_gain_Q23 = silk_RSHIFT_ROUND( inv_gain_Q31, 8 );
/* prepare inv_gain_Q23 in packed 4 32-bits */
xmm_inv_gain_Q23 = _mm_set1_epi32(inv_gain_Q23);
for( i = 0; i < psEncC->subfr_length - 3; i += 4 ) {
xmm_x_Q3_x2x0 = _mm_loadu_si128( (__m128i *)(&(x_Q3[ i ] ) ) );
/* equal shift right 4 bytes*/
xmm_x_Q3_x3x1 = _mm_shuffle_epi32( xmm_x_Q3_x2x0, _MM_SHUFFLE( 0, 3, 2, 1 ) );
xmm_x_Q3_x2x0 = _mm_mul_epi32( xmm_x_Q3_x2x0, xmm_inv_gain_Q23 );
xmm_x_Q3_x3x1 = _mm_mul_epi32( xmm_x_Q3_x3x1, xmm_inv_gain_Q23 );
xmm_x_Q3_x2x0 = _mm_srli_epi64( xmm_x_Q3_x2x0, 16 );
xmm_x_Q3_x3x1 = _mm_slli_epi64( xmm_x_Q3_x3x1, 16 );
xmm_x_Q3_x2x0 = _mm_blend_epi16( xmm_x_Q3_x2x0, xmm_x_Q3_x3x1, 0xCC );
_mm_storeu_si128( (__m128i *)(&(x_sc_Q10[ i ] ) ), xmm_x_Q3_x2x0 );
}
for( ; i < psEncC->subfr_length; i++ ) {
x_sc_Q10[ i ] = silk_SMULWW( x_Q3[ i ], inv_gain_Q23 );
}
/* Save inverse gain */
NSQ->prev_gain_Q16 = Gains_Q16[ subfr ];
/* After rewhitening the LTP state is un-scaled, so scale with inv_gain_Q16 */
if( NSQ->rewhite_flag ) {
if( subfr == 0 ) {
/* Do LTP downscaling */
inv_gain_Q31 = silk_LSHIFT( silk_SMULWB( inv_gain_Q31, LTP_scale_Q14 ), 2 );
}
for( i = NSQ->sLTP_buf_idx - lag - LTP_ORDER / 2; i < NSQ->sLTP_buf_idx; i++ ) {
silk_assert( i < MAX_FRAME_LENGTH );
sLTP_Q15[ i ] = silk_SMULWB( inv_gain_Q31, sLTP[ i ] );
}
}
/* Adjust for changing gain */
if( gain_adj_Q16 != (opus_int32)1 << 16 ) {
/* Scale long-term shaping state */
__m128i xmm_gain_adj_Q16, xmm_sLTP_shp_Q14_x2x0, xmm_sLTP_shp_Q14_x3x1;
/* prepare gain_adj_Q16 in packed 4 32-bits */
xmm_gain_adj_Q16 = _mm_set1_epi32(gain_adj_Q16);
for( i = NSQ->sLTP_shp_buf_idx - psEncC->ltp_mem_length; i < NSQ->sLTP_shp_buf_idx - 3; i += 4 )
{
xmm_sLTP_shp_Q14_x2x0 = _mm_loadu_si128( (__m128i *)(&(NSQ->sLTP_shp_Q14[ i ] ) ) );
/* equal shift right 4 bytes*/
xmm_sLTP_shp_Q14_x3x1 = _mm_shuffle_epi32( xmm_sLTP_shp_Q14_x2x0, _MM_SHUFFLE( 0, 3, 2, 1 ) );
xmm_sLTP_shp_Q14_x2x0 = _mm_mul_epi32( xmm_sLTP_shp_Q14_x2x0, xmm_gain_adj_Q16 );
xmm_sLTP_shp_Q14_x3x1 = _mm_mul_epi32( xmm_sLTP_shp_Q14_x3x1, xmm_gain_adj_Q16 );
xmm_sLTP_shp_Q14_x2x0 = _mm_srli_epi64( xmm_sLTP_shp_Q14_x2x0, 16 );
xmm_sLTP_shp_Q14_x3x1 = _mm_slli_epi64( xmm_sLTP_shp_Q14_x3x1, 16 );
xmm_sLTP_shp_Q14_x2x0 = _mm_blend_epi16( xmm_sLTP_shp_Q14_x2x0, xmm_sLTP_shp_Q14_x3x1, 0xCC );
_mm_storeu_si128( (__m128i *)(&(NSQ->sLTP_shp_Q14[ i ] ) ), xmm_sLTP_shp_Q14_x2x0 );
}
for( ; i < NSQ->sLTP_shp_buf_idx; i++ ) {
NSQ->sLTP_shp_Q14[ i ] = silk_SMULWW( gain_adj_Q16, NSQ->sLTP_shp_Q14[ i ] );
}
/* Scale long-term prediction state */
if( signal_type == TYPE_VOICED && NSQ->rewhite_flag == 0 ) {
for( i = NSQ->sLTP_buf_idx - lag - LTP_ORDER / 2; i < NSQ->sLTP_buf_idx; i++ ) {
sLTP_Q15[ i ] = silk_SMULWW( gain_adj_Q16, sLTP_Q15[ i ] );
}
}
NSQ->sLF_AR_shp_Q14 = silk_SMULWW( gain_adj_Q16, NSQ->sLF_AR_shp_Q14 );
/* Scale short-term prediction and shaping states */
for( i = 0; i < NSQ_LPC_BUF_LENGTH; i++ ) {
NSQ->sLPC_Q14[ i ] = silk_SMULWW( gain_adj_Q16, NSQ->sLPC_Q14[ i ] );
}
for( i = 0; i < MAX_SHAPE_LPC_ORDER; i++ ) {
NSQ->sAR2_Q14[ i ] = silk_SMULWW( gain_adj_Q16, NSQ->sAR2_Q14[ i ] );
}
}
}
+94
View File
@@ -0,0 +1,94 @@
/* Copyright (c) 2014, Cisco Systems, INC
Written by XiangMingZhu WeiZhou MinPeng YanWang
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
- Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
- Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef SIGPROC_FIX_SSE_H
#define SIGPROC_FIX_SSE_H
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#if defined(OPUS_X86_MAY_HAVE_SSE4_1)
void silk_burg_modified_sse4_1(
opus_int32 *res_nrg, /* O Residual energy */
opus_int *res_nrg_Q, /* O Residual energy Q value */
opus_int32 A_Q16[], /* O Prediction coefficients (length order) */
const opus_int16 x[], /* I Input signal, length: nb_subfr * ( D + subfr_length ) */
const opus_int32 minInvGain_Q30, /* I Inverse of max prediction gain */
const opus_int subfr_length, /* I Input signal subframe length (incl. D preceding samples) */
const opus_int nb_subfr, /* I Number of subframes stacked in x */
const opus_int D, /* I Order */
int arch /* I Run-time architecture */
);
#if defined(OPUS_X86_PRESUME_SSE4_1)
#define silk_burg_modified(res_nrg, res_nrg_Q, A_Q16, x, minInvGain_Q30, subfr_length, nb_subfr, D, arch) \
((void)(arch), silk_burg_modified_sse4_1(res_nrg, res_nrg_Q, A_Q16, x, minInvGain_Q30, subfr_length, nb_subfr, D, arch))
#else
extern void (*const SILK_BURG_MODIFIED_IMPL[OPUS_ARCHMASK + 1])(
opus_int32 *res_nrg, /* O Residual energy */
opus_int *res_nrg_Q, /* O Residual energy Q value */
opus_int32 A_Q16[], /* O Prediction coefficients (length order) */
const opus_int16 x[], /* I Input signal, length: nb_subfr * ( D + subfr_length ) */
const opus_int32 minInvGain_Q30, /* I Inverse of max prediction gain */
const opus_int subfr_length, /* I Input signal subframe length (incl. D preceding samples) */
const opus_int nb_subfr, /* I Number of subframes stacked in x */
const opus_int D, /* I Order */
int arch /* I Run-time architecture */);
# define silk_burg_modified(res_nrg, res_nrg_Q, A_Q16, x, minInvGain_Q30, subfr_length, nb_subfr, D, arch) \
((*SILK_BURG_MODIFIED_IMPL[(arch) & OPUS_ARCHMASK])(res_nrg, res_nrg_Q, A_Q16, x, minInvGain_Q30, subfr_length, nb_subfr, D, arch))
#endif
opus_int64 silk_inner_prod16_aligned_64_sse4_1(
const opus_int16 *inVec1,
const opus_int16 *inVec2,
const opus_int len
);
#if defined(OPUS_X86_PRESUME_SSE4_1)
#define silk_inner_prod16_aligned_64(inVec1, inVec2, len, arch) \
((void)(arch),silk_inner_prod16_aligned_64_sse4_1(inVec1, inVec2, len))
#else
extern opus_int64 (*const SILK_INNER_PROD16_ALIGNED_64_IMPL[OPUS_ARCHMASK + 1])(
const opus_int16 *inVec1,
const opus_int16 *inVec2,
const opus_int len);
# define silk_inner_prod16_aligned_64(inVec1, inVec2, len, arch) \
((*SILK_INNER_PROD16_ALIGNED_64_IMPL[(arch) & OPUS_ARCHMASK])(inVec1, inVec2, len))
#endif
#endif
#endif
+277
View File
@@ -0,0 +1,277 @@
/* Copyright (c) 2014, Cisco Systems, INC
Written by XiangMingZhu WeiZhou MinPeng YanWang
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
- Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
- Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <xmmintrin.h>
#include <emmintrin.h>
#include <smmintrin.h>
#include "main.h"
#include "stack_alloc.h"
/* Weighting factors for tilt measure */
static const opus_int32 tiltWeights[ VAD_N_BANDS ] = { 30000, 6000, -12000, -12000 };
/***************************************/
/* Get the speech activity level in Q8 */
/***************************************/
opus_int silk_VAD_GetSA_Q8_sse4_1( /* O Return value, 0 if success */
silk_encoder_state *psEncC, /* I/O Encoder state */
const opus_int16 pIn[] /* I PCM input */
)
{
opus_int SA_Q15, pSNR_dB_Q7, input_tilt;
opus_int decimated_framelength1, decimated_framelength2;
opus_int decimated_framelength;
opus_int dec_subframe_length, dec_subframe_offset, SNR_Q7, i, b, s;
opus_int32 sumSquared, smooth_coef_Q16;
opus_int16 HPstateTmp;
VARDECL( opus_int16, X );
opus_int32 Xnrg[ VAD_N_BANDS ];
opus_int32 NrgToNoiseRatio_Q8[ VAD_N_BANDS ];
opus_int32 speech_nrg, x_tmp;
opus_int X_offset[ VAD_N_BANDS ];
opus_int ret = 0;
silk_VAD_state *psSilk_VAD = &psEncC->sVAD;
SAVE_STACK;
/* Safety checks */
silk_assert( VAD_N_BANDS == 4 );
silk_assert( MAX_FRAME_LENGTH >= psEncC->frame_length );
silk_assert( psEncC->frame_length <= 512 );
silk_assert( psEncC->frame_length == 8 * silk_RSHIFT( psEncC->frame_length, 3 ) );
/***********************/
/* Filter and Decimate */
/***********************/
decimated_framelength1 = silk_RSHIFT( psEncC->frame_length, 1 );
decimated_framelength2 = silk_RSHIFT( psEncC->frame_length, 2 );
decimated_framelength = silk_RSHIFT( psEncC->frame_length, 3 );
/* Decimate into 4 bands:
0 L 3L L 3L 5L
- -- - -- --
8 8 2 4 4
[0-1 kHz| temp. |1-2 kHz| 2-4 kHz | 4-8 kHz |
They're arranged to allow the minimal ( frame_length / 4 ) extra
scratch space during the downsampling process */
X_offset[ 0 ] = 0;
X_offset[ 1 ] = decimated_framelength + decimated_framelength2;
X_offset[ 2 ] = X_offset[ 1 ] + decimated_framelength;
X_offset[ 3 ] = X_offset[ 2 ] + decimated_framelength2;
ALLOC( X, X_offset[ 3 ] + decimated_framelength1, opus_int16 );
/* 0-8 kHz to 0-4 kHz and 4-8 kHz */
silk_ana_filt_bank_1( pIn, &psSilk_VAD->AnaState[ 0 ],
X, &X[ X_offset[ 3 ] ], psEncC->frame_length );
/* 0-4 kHz to 0-2 kHz and 2-4 kHz */
silk_ana_filt_bank_1( X, &psSilk_VAD->AnaState1[ 0 ],
X, &X[ X_offset[ 2 ] ], decimated_framelength1 );
/* 0-2 kHz to 0-1 kHz and 1-2 kHz */
silk_ana_filt_bank_1( X, &psSilk_VAD->AnaState2[ 0 ],
X, &X[ X_offset[ 1 ] ], decimated_framelength2 );
/*********************************************/
/* HP filter on lowest band (differentiator) */
/*********************************************/
X[ decimated_framelength - 1 ] = silk_RSHIFT( X[ decimated_framelength - 1 ], 1 );
HPstateTmp = X[ decimated_framelength - 1 ];
for( i = decimated_framelength - 1; i > 0; i-- ) {
X[ i - 1 ] = silk_RSHIFT( X[ i - 1 ], 1 );
X[ i ] -= X[ i - 1 ];
}
X[ 0 ] -= psSilk_VAD->HPstate;
psSilk_VAD->HPstate = HPstateTmp;
/*************************************/
/* Calculate the energy in each band */
/*************************************/
for( b = 0; b < VAD_N_BANDS; b++ ) {
/* Find the decimated framelength in the non-uniformly divided bands */
decimated_framelength = silk_RSHIFT( psEncC->frame_length, silk_min_int( VAD_N_BANDS - b, VAD_N_BANDS - 1 ) );
/* Split length into subframe lengths */
dec_subframe_length = silk_RSHIFT( decimated_framelength, VAD_INTERNAL_SUBFRAMES_LOG2 );
dec_subframe_offset = 0;
/* Compute energy per sub-frame */
/* initialize with summed energy of last subframe */
Xnrg[ b ] = psSilk_VAD->XnrgSubfr[ b ];
for( s = 0; s < VAD_INTERNAL_SUBFRAMES; s++ ) {
__m128i xmm_X, xmm_acc;
sumSquared = 0;
xmm_acc = _mm_setzero_si128();
for( i = 0; i < dec_subframe_length - 7; i += 8 )
{
xmm_X = _mm_loadu_si128( (__m128i *)&(X[ X_offset[ b ] + i + dec_subframe_offset ] ) );
xmm_X = _mm_srai_epi16( xmm_X, 3 );
xmm_X = _mm_madd_epi16( xmm_X, xmm_X );
xmm_acc = _mm_add_epi32( xmm_acc, xmm_X );
}
xmm_acc = _mm_add_epi32( xmm_acc, _mm_unpackhi_epi64( xmm_acc, xmm_acc ) );
xmm_acc = _mm_add_epi32( xmm_acc, _mm_shufflelo_epi16( xmm_acc, 0x0E ) );
sumSquared += _mm_cvtsi128_si32( xmm_acc );
for( ; i < dec_subframe_length; i++ ) {
/* The energy will be less than dec_subframe_length * ( silk_int16_MIN / 8 ) ^ 2. */
/* Therefore we can accumulate with no risk of overflow (unless dec_subframe_length > 128) */
x_tmp = silk_RSHIFT(
X[ X_offset[ b ] + i + dec_subframe_offset ], 3 );
sumSquared = silk_SMLABB( sumSquared, x_tmp, x_tmp );
/* Safety check */
silk_assert( sumSquared >= 0 );
}
/* Add/saturate summed energy of current subframe */
if( s < VAD_INTERNAL_SUBFRAMES - 1 ) {
Xnrg[ b ] = silk_ADD_POS_SAT32( Xnrg[ b ], sumSquared );
} else {
/* Look-ahead subframe */
Xnrg[ b ] = silk_ADD_POS_SAT32( Xnrg[ b ], silk_RSHIFT( sumSquared, 1 ) );
}
dec_subframe_offset += dec_subframe_length;
}
psSilk_VAD->XnrgSubfr[ b ] = sumSquared;
}
/********************/
/* Noise estimation */
/********************/
silk_VAD_GetNoiseLevels( &Xnrg[ 0 ], psSilk_VAD );
/***********************************************/
/* Signal-plus-noise to noise ratio estimation */
/***********************************************/
sumSquared = 0;
input_tilt = 0;
for( b = 0; b < VAD_N_BANDS; b++ ) {
speech_nrg = Xnrg[ b ] - psSilk_VAD->NL[ b ];
if( speech_nrg > 0 ) {
/* Divide, with sufficient resolution */
if( ( Xnrg[ b ] & 0xFF800000 ) == 0 ) {
NrgToNoiseRatio_Q8[ b ] = silk_DIV32( silk_LSHIFT( Xnrg[ b ], 8 ), psSilk_VAD->NL[ b ] + 1 );
} else {
NrgToNoiseRatio_Q8[ b ] = silk_DIV32( Xnrg[ b ], silk_RSHIFT( psSilk_VAD->NL[ b ], 8 ) + 1 );
}
/* Convert to log domain */
SNR_Q7 = silk_lin2log( NrgToNoiseRatio_Q8[ b ] ) - 8 * 128;
/* Sum-of-squares */
sumSquared = silk_SMLABB( sumSquared, SNR_Q7, SNR_Q7 ); /* Q14 */
/* Tilt measure */
if( speech_nrg < ( (opus_int32)1 << 20 ) ) {
/* Scale down SNR value for small subband speech energies */
SNR_Q7 = silk_SMULWB( silk_LSHIFT( silk_SQRT_APPROX( speech_nrg ), 6 ), SNR_Q7 );
}
input_tilt = silk_SMLAWB( input_tilt, tiltWeights[ b ], SNR_Q7 );
} else {
NrgToNoiseRatio_Q8[ b ] = 256;
}
}
/* Mean-of-squares */
sumSquared = silk_DIV32_16( sumSquared, VAD_N_BANDS ); /* Q14 */
/* Root-mean-square approximation, scale to dBs, and write to output pointer */
pSNR_dB_Q7 = (opus_int16)( 3 * silk_SQRT_APPROX( sumSquared ) ); /* Q7 */
/*********************************/
/* Speech Probability Estimation */
/*********************************/
SA_Q15 = silk_sigm_Q15( silk_SMULWB( VAD_SNR_FACTOR_Q16, pSNR_dB_Q7 ) - VAD_NEGATIVE_OFFSET_Q5 );
/**************************/
/* Frequency Tilt Measure */
/**************************/
psEncC->input_tilt_Q15 = silk_LSHIFT( silk_sigm_Q15( input_tilt ) - 16384, 1 );
/**************************************************/
/* Scale the sigmoid output based on power levels */
/**************************************************/
speech_nrg = 0;
for( b = 0; b < VAD_N_BANDS; b++ ) {
/* Accumulate signal-without-noise energies, higher frequency bands have more weight */
speech_nrg += ( b + 1 ) * silk_RSHIFT( Xnrg[ b ] - psSilk_VAD->NL[ b ], 4 );
}
/* Power scaling */
if( speech_nrg <= 0 ) {
SA_Q15 = silk_RSHIFT( SA_Q15, 1 );
} else if( speech_nrg < 32768 ) {
if( psEncC->frame_length == 10 * psEncC->fs_kHz ) {
speech_nrg = silk_LSHIFT_SAT32( speech_nrg, 16 );
} else {
speech_nrg = silk_LSHIFT_SAT32( speech_nrg, 15 );
}
/* square-root */
speech_nrg = silk_SQRT_APPROX( speech_nrg );
SA_Q15 = silk_SMULWB( 32768 + speech_nrg, SA_Q15 );
}
/* Copy the resulting speech activity in Q8 */
psEncC->speech_activity_Q8 = silk_min_int( silk_RSHIFT( SA_Q15, 7 ), silk_uint8_MAX );
/***********************************/
/* Energy Level and SNR estimation */
/***********************************/
/* Smoothing coefficient */
smooth_coef_Q16 = silk_SMULWB( VAD_SNR_SMOOTH_COEF_Q18, silk_SMULWB( (opus_int32)SA_Q15, SA_Q15 ) );
if( psEncC->frame_length == 10 * psEncC->fs_kHz ) {
smooth_coef_Q16 >>= 1;
}
for( b = 0; b < VAD_N_BANDS; b++ ) {
/* compute smoothed energy-to-noise ratio per band */
psSilk_VAD->NrgRatioSmth_Q8[ b ] = silk_SMLAWB( psSilk_VAD->NrgRatioSmth_Q8[ b ],
NrgToNoiseRatio_Q8[ b ] - psSilk_VAD->NrgRatioSmth_Q8[ b ], smooth_coef_Q16 );
/* signal to noise ratio in dB per band */
SNR_Q7 = 3 * ( silk_lin2log( psSilk_VAD->NrgRatioSmth_Q8[b] ) - 8 * 128 );
/* quality = sigmoid( 0.25 * ( SNR_dB - 16 ) ); */
psEncC->input_quality_bands_Q15[ b ] = silk_sigm_Q15( silk_RSHIFT( SNR_Q7 - 16 * 128, 4 ) );
}
RESTORE_STACK;
return( ret );
}
+142
View File
@@ -0,0 +1,142 @@
/* Copyright (c) 2014, Cisco Systems, INC
Written by XiangMingZhu WeiZhou MinPeng YanWang
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
- Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
- Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <xmmintrin.h>
#include <emmintrin.h>
#include <smmintrin.h>
#include "main.h"
#include "celt/x86/x86cpu.h"
/* Entropy constrained matrix-weighted VQ, hard-coded to 5-element vectors, for a single input data vector */
void silk_VQ_WMat_EC_sse4_1(
opus_int8 *ind, /* O index of best codebook vector */
opus_int32 *rate_dist_Q14, /* O best weighted quant error + mu * rate */
opus_int *gain_Q7, /* O sum of absolute LTP coefficients */
const opus_int16 *in_Q14, /* I input vector to be quantized */
const opus_int32 *W_Q18, /* I weighting matrix */
const opus_int8 *cb_Q7, /* I codebook */
const opus_uint8 *cb_gain_Q7, /* I codebook effective gain */
const opus_uint8 *cl_Q5, /* I code length for each codebook vector */
const opus_int mu_Q9, /* I tradeoff betw. weighted error and rate */
const opus_int32 max_gain_Q7, /* I maximum sum of absolute LTP coefficients */
opus_int L /* I number of vectors in codebook */
)
{
opus_int k, gain_tmp_Q7;
const opus_int8 *cb_row_Q7;
opus_int16 diff_Q14[ 5 ];
opus_int32 sum1_Q14, sum2_Q16;
__m128i C_tmp1, C_tmp2, C_tmp3, C_tmp4, C_tmp5;
/* Loop over codebook */
*rate_dist_Q14 = silk_int32_MAX;
cb_row_Q7 = cb_Q7;
for( k = 0; k < L; k++ ) {
gain_tmp_Q7 = cb_gain_Q7[k];
diff_Q14[ 0 ] = in_Q14[ 0 ] - silk_LSHIFT( cb_row_Q7[ 0 ], 7 );
C_tmp1 = OP_CVTEPI16_EPI32_M64( &in_Q14[ 1 ] );
C_tmp2 = OP_CVTEPI8_EPI32_M32( &cb_row_Q7[ 1 ] );
C_tmp2 = _mm_slli_epi32( C_tmp2, 7 );
C_tmp1 = _mm_sub_epi32( C_tmp1, C_tmp2 );
diff_Q14[ 1 ] = _mm_extract_epi16( C_tmp1, 0 );
diff_Q14[ 2 ] = _mm_extract_epi16( C_tmp1, 2 );
diff_Q14[ 3 ] = _mm_extract_epi16( C_tmp1, 4 );
diff_Q14[ 4 ] = _mm_extract_epi16( C_tmp1, 6 );
/* Weighted rate */
sum1_Q14 = silk_SMULBB( mu_Q9, cl_Q5[ k ] );
/* Penalty for too large gain */
sum1_Q14 = silk_ADD_LSHIFT32( sum1_Q14, silk_max( silk_SUB32( gain_tmp_Q7, max_gain_Q7 ), 0 ), 10 );
silk_assert( sum1_Q14 >= 0 );
/* first row of W_Q18 */
C_tmp3 = _mm_loadu_si128( (__m128i *)(&W_Q18[ 1 ] ) );
C_tmp4 = _mm_mul_epi32( C_tmp3, C_tmp1 );
C_tmp4 = _mm_srli_si128( C_tmp4, 2 );
C_tmp1 = _mm_shuffle_epi32( C_tmp1, _MM_SHUFFLE( 0, 3, 2, 1 ) ); /* shift right 4 bytes */
C_tmp3 = _mm_shuffle_epi32( C_tmp3, _MM_SHUFFLE( 0, 3, 2, 1 ) ); /* shift right 4 bytes */
C_tmp5 = _mm_mul_epi32( C_tmp3, C_tmp1 );
C_tmp5 = _mm_srli_si128( C_tmp5, 2 );
C_tmp5 = _mm_add_epi32( C_tmp4, C_tmp5 );
C_tmp5 = _mm_slli_epi32( C_tmp5, 1 );
C_tmp5 = _mm_add_epi32( C_tmp5, _mm_shuffle_epi32( C_tmp5, _MM_SHUFFLE( 0, 0, 0, 2 ) ) );
sum2_Q16 = _mm_cvtsi128_si32( C_tmp5 );
sum2_Q16 = silk_SMLAWB( sum2_Q16, W_Q18[ 0 ], diff_Q14[ 0 ] );
sum1_Q14 = silk_SMLAWB( sum1_Q14, sum2_Q16, diff_Q14[ 0 ] );
/* second row of W_Q18 */
sum2_Q16 = silk_SMULWB( W_Q18[ 7 ], diff_Q14[ 2 ] );
sum2_Q16 = silk_SMLAWB( sum2_Q16, W_Q18[ 8 ], diff_Q14[ 3 ] );
sum2_Q16 = silk_SMLAWB( sum2_Q16, W_Q18[ 9 ], diff_Q14[ 4 ] );
sum2_Q16 = silk_LSHIFT( sum2_Q16, 1 );
sum2_Q16 = silk_SMLAWB( sum2_Q16, W_Q18[ 6 ], diff_Q14[ 1 ] );
sum1_Q14 = silk_SMLAWB( sum1_Q14, sum2_Q16, diff_Q14[ 1 ] );
/* third row of W_Q18 */
sum2_Q16 = silk_SMULWB( W_Q18[ 13 ], diff_Q14[ 3 ] );
sum2_Q16 = silk_SMLAWB( sum2_Q16, W_Q18[ 14 ], diff_Q14[ 4 ] );
sum2_Q16 = silk_LSHIFT( sum2_Q16, 1 );
sum2_Q16 = silk_SMLAWB( sum2_Q16, W_Q18[ 12 ], diff_Q14[ 2 ] );
sum1_Q14 = silk_SMLAWB( sum1_Q14, sum2_Q16, diff_Q14[ 2 ] );
/* fourth row of W_Q18 */
sum2_Q16 = silk_SMULWB( W_Q18[ 19 ], diff_Q14[ 4 ] );
sum2_Q16 = silk_LSHIFT( sum2_Q16, 1 );
sum2_Q16 = silk_SMLAWB( sum2_Q16, W_Q18[ 18 ], diff_Q14[ 3 ] );
sum1_Q14 = silk_SMLAWB( sum1_Q14, sum2_Q16, diff_Q14[ 3 ] );
/* last row of W_Q18 */
sum2_Q16 = silk_SMULWB( W_Q18[ 24 ], diff_Q14[ 4 ] );
sum1_Q14 = silk_SMLAWB( sum1_Q14, sum2_Q16, diff_Q14[ 4 ] );
silk_assert( sum1_Q14 >= 0 );
/* find best */
if( sum1_Q14 < *rate_dist_Q14 ) {
*rate_dist_Q14 = sum1_Q14;
*ind = (opus_int8)k;
*gain_Q7 = gain_tmp_Q7;
}
/* Go to next cbk vector */
cb_row_Q7 += LTP_ORDER;
}
}
+277
View File
@@ -0,0 +1,277 @@
/* Copyright (c) 2014, Cisco Systems, INC
Written by XiangMingZhu WeiZhou MinPeng YanWang
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
- Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
- Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef MAIN_SSE_H
#define MAIN_SSE_H
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
# if defined(OPUS_X86_MAY_HAVE_SSE4_1)
# define OVERRIDE_silk_VQ_WMat_EC
void silk_VQ_WMat_EC_sse4_1(
opus_int8 *ind, /* O index of best codebook vector */
opus_int32 *rate_dist_Q14, /* O best weighted quant error + mu * rate */
opus_int *gain_Q7, /* O sum of absolute LTP coefficients */
const opus_int16 *in_Q14, /* I input vector to be quantized */
const opus_int32 *W_Q18, /* I weighting matrix */
const opus_int8 *cb_Q7, /* I codebook */
const opus_uint8 *cb_gain_Q7, /* I codebook effective gain */
const opus_uint8 *cl_Q5, /* I code length for each codebook vector */
const opus_int mu_Q9, /* I tradeoff betw. weighted error and rate */
const opus_int32 max_gain_Q7, /* I maximum sum of absolute LTP coefficients */
opus_int L /* I number of vectors in codebook */
);
#if defined OPUS_X86_PRESUME_SSE4_1
#define silk_VQ_WMat_EC(ind, rate_dist_Q14, gain_Q7, in_Q14, W_Q18, cb_Q7, cb_gain_Q7, cl_Q5, \
mu_Q9, max_gain_Q7, L, arch) \
((void)(arch),silk_VQ_WMat_EC_sse4_1(ind, rate_dist_Q14, gain_Q7, in_Q14, W_Q18, cb_Q7, cb_gain_Q7, cl_Q5, \
mu_Q9, max_gain_Q7, L))
#else
extern void (*const SILK_VQ_WMAT_EC_IMPL[OPUS_ARCHMASK + 1])(
opus_int8 *ind, /* O index of best codebook vector */
opus_int32 *rate_dist_Q14, /* O best weighted quant error + mu * rate */
opus_int *gain_Q7, /* O sum of absolute LTP coefficients */
const opus_int16 *in_Q14, /* I input vector to be quantized */
const opus_int32 *W_Q18, /* I weighting matrix */
const opus_int8 *cb_Q7, /* I codebook */
const opus_uint8 *cb_gain_Q7, /* I codebook effective gain */
const opus_uint8 *cl_Q5, /* I code length for each codebook vector */
const opus_int mu_Q9, /* I tradeoff betw. weighted error and rate */
const opus_int32 max_gain_Q7, /* I maximum sum of absolute LTP coefficients */
opus_int L /* I number of vectors in codebook */
);
# define silk_VQ_WMat_EC(ind, rate_dist_Q14, gain_Q7, in_Q14, W_Q18, cb_Q7, cb_gain_Q7, cl_Q5, \
mu_Q9, max_gain_Q7, L, arch) \
((*SILK_VQ_WMAT_EC_IMPL[(arch) & OPUS_ARCHMASK])(ind, rate_dist_Q14, gain_Q7, in_Q14, W_Q18, cb_Q7, cb_gain_Q7, cl_Q5, \
mu_Q9, max_gain_Q7, L))
#endif
# define OVERRIDE_silk_NSQ
void silk_NSQ_sse4_1(
const silk_encoder_state *psEncC, /* I/O Encoder State */
silk_nsq_state *NSQ, /* I/O NSQ state */
SideInfoIndices *psIndices, /* I/O Quantization Indices */
const opus_int32 x_Q3[], /* I Prefiltered input signal */
opus_int8 pulses[], /* O Quantized pulse signal */
const opus_int16 PredCoef_Q12[ 2 * MAX_LPC_ORDER ], /* I Short term prediction coefs */
const opus_int16 LTPCoef_Q14[ LTP_ORDER * MAX_NB_SUBFR ], /* I Long term prediction coefs */
const opus_int16 AR2_Q13[ MAX_NB_SUBFR * MAX_SHAPE_LPC_ORDER ], /* I Noise shaping coefs */
const opus_int HarmShapeGain_Q14[ MAX_NB_SUBFR ], /* I Long term shaping coefs */
const opus_int Tilt_Q14[ MAX_NB_SUBFR ], /* I Spectral tilt */
const opus_int32 LF_shp_Q14[ MAX_NB_SUBFR ], /* I Low frequency shaping coefs */
const opus_int32 Gains_Q16[ MAX_NB_SUBFR ], /* I Quantization step sizes */
const opus_int pitchL[ MAX_NB_SUBFR ], /* I Pitch lags */
const opus_int Lambda_Q10, /* I Rate/distortion tradeoff */
const opus_int LTP_scale_Q14 /* I LTP state scaling */
);
#if defined OPUS_X86_PRESUME_SSE4_1
#define silk_NSQ(psEncC, NSQ, psIndices, x_Q3, pulses, PredCoef_Q12, LTPCoef_Q14, AR2_Q13, \
HarmShapeGain_Q14, Tilt_Q14, LF_shp_Q14, Gains_Q16, pitchL, Lambda_Q10, LTP_scale_Q14, arch) \
((void)(arch),silk_NSQ_sse4_1(psEncC, NSQ, psIndices, x_Q3, pulses, PredCoef_Q12, LTPCoef_Q14, AR2_Q13, \
HarmShapeGain_Q14, Tilt_Q14, LF_shp_Q14, Gains_Q16, pitchL, Lambda_Q10, LTP_scale_Q14))
#else
extern void (*const SILK_NSQ_IMPL[OPUS_ARCHMASK + 1])(
const silk_encoder_state *psEncC, /* I/O Encoder State */
silk_nsq_state *NSQ, /* I/O NSQ state */
SideInfoIndices *psIndices, /* I/O Quantization Indices */
const opus_int32 x_Q3[], /* I Prefiltered input signal */
opus_int8 pulses[], /* O Quantized pulse signal */
const opus_int16 PredCoef_Q12[ 2 * MAX_LPC_ORDER ], /* I Short term prediction coefs */
const opus_int16 LTPCoef_Q14[ LTP_ORDER * MAX_NB_SUBFR ], /* I Long term prediction coefs */
const opus_int16 AR2_Q13[ MAX_NB_SUBFR * MAX_SHAPE_LPC_ORDER ], /* I Noise shaping coefs */
const opus_int HarmShapeGain_Q14[ MAX_NB_SUBFR ], /* I Long term shaping coefs */
const opus_int Tilt_Q14[ MAX_NB_SUBFR ], /* I Spectral tilt */
const opus_int32 LF_shp_Q14[ MAX_NB_SUBFR ], /* I Low frequency shaping coefs */
const opus_int32 Gains_Q16[ MAX_NB_SUBFR ], /* I Quantization step sizes */
const opus_int pitchL[ MAX_NB_SUBFR ], /* I Pitch lags */
const opus_int Lambda_Q10, /* I Rate/distortion tradeoff */
const opus_int LTP_scale_Q14 /* I LTP state scaling */
);
# define silk_NSQ(psEncC, NSQ, psIndices, x_Q3, pulses, PredCoef_Q12, LTPCoef_Q14, AR2_Q13, \
HarmShapeGain_Q14, Tilt_Q14, LF_shp_Q14, Gains_Q16, pitchL, Lambda_Q10, LTP_scale_Q14, arch) \
((*SILK_NSQ_IMPL[(arch) & OPUS_ARCHMASK])(psEncC, NSQ, psIndices, x_Q3, pulses, PredCoef_Q12, LTPCoef_Q14, AR2_Q13, \
HarmShapeGain_Q14, Tilt_Q14, LF_shp_Q14, Gains_Q16, pitchL, Lambda_Q10, LTP_scale_Q14))
#endif
# define OVERRIDE_silk_NSQ_del_dec
void silk_NSQ_del_dec_sse4_1(
const silk_encoder_state *psEncC, /* I/O Encoder State */
silk_nsq_state *NSQ, /* I/O NSQ state */
SideInfoIndices *psIndices, /* I/O Quantization Indices */
const opus_int32 x_Q3[], /* I Prefiltered input signal */
opus_int8 pulses[], /* O Quantized pulse signal */
const opus_int16 PredCoef_Q12[ 2 * MAX_LPC_ORDER ], /* I Short term prediction coefs */
const opus_int16 LTPCoef_Q14[ LTP_ORDER * MAX_NB_SUBFR ], /* I Long term prediction coefs */
const opus_int16 AR2_Q13[ MAX_NB_SUBFR * MAX_SHAPE_LPC_ORDER ], /* I Noise shaping coefs */
const opus_int HarmShapeGain_Q14[ MAX_NB_SUBFR ], /* I Long term shaping coefs */
const opus_int Tilt_Q14[ MAX_NB_SUBFR ], /* I Spectral tilt */
const opus_int32 LF_shp_Q14[ MAX_NB_SUBFR ], /* I Low frequency shaping coefs */
const opus_int32 Gains_Q16[ MAX_NB_SUBFR ], /* I Quantization step sizes */
const opus_int pitchL[ MAX_NB_SUBFR ], /* I Pitch lags */
const opus_int Lambda_Q10, /* I Rate/distortion tradeoff */
const opus_int LTP_scale_Q14 /* I LTP state scaling */
);
#if defined OPUS_X86_PRESUME_SSE4_1
#define silk_NSQ_del_dec(psEncC, NSQ, psIndices, x_Q3, pulses, PredCoef_Q12, LTPCoef_Q14, AR2_Q13, \
HarmShapeGain_Q14, Tilt_Q14, LF_shp_Q14, Gains_Q16, pitchL, Lambda_Q10, LTP_scale_Q14, arch) \
((void)(arch),silk_NSQ_del_dec_sse4_1(psEncC, NSQ, psIndices, x_Q3, pulses, PredCoef_Q12, LTPCoef_Q14, AR2_Q13, \
HarmShapeGain_Q14, Tilt_Q14, LF_shp_Q14, Gains_Q16, pitchL, Lambda_Q10, LTP_scale_Q14))
#else
extern void (*const SILK_NSQ_DEL_DEC_IMPL[OPUS_ARCHMASK + 1])(
const silk_encoder_state *psEncC, /* I/O Encoder State */
silk_nsq_state *NSQ, /* I/O NSQ state */
SideInfoIndices *psIndices, /* I/O Quantization Indices */
const opus_int32 x_Q3[], /* I Prefiltered input signal */
opus_int8 pulses[], /* O Quantized pulse signal */
const opus_int16 PredCoef_Q12[ 2 * MAX_LPC_ORDER ], /* I Short term prediction coefs */
const opus_int16 LTPCoef_Q14[ LTP_ORDER * MAX_NB_SUBFR ], /* I Long term prediction coefs */
const opus_int16 AR2_Q13[ MAX_NB_SUBFR * MAX_SHAPE_LPC_ORDER ], /* I Noise shaping coefs */
const opus_int HarmShapeGain_Q14[ MAX_NB_SUBFR ], /* I Long term shaping coefs */
const opus_int Tilt_Q14[ MAX_NB_SUBFR ], /* I Spectral tilt */
const opus_int32 LF_shp_Q14[ MAX_NB_SUBFR ], /* I Low frequency shaping coefs */
const opus_int32 Gains_Q16[ MAX_NB_SUBFR ], /* I Quantization step sizes */
const opus_int pitchL[ MAX_NB_SUBFR ], /* I Pitch lags */
const opus_int Lambda_Q10, /* I Rate/distortion tradeoff */
const opus_int LTP_scale_Q14 /* I LTP state scaling */
);
# define silk_NSQ_del_dec(psEncC, NSQ, psIndices, x_Q3, pulses, PredCoef_Q12, LTPCoef_Q14, AR2_Q13, \
HarmShapeGain_Q14, Tilt_Q14, LF_shp_Q14, Gains_Q16, pitchL, Lambda_Q10, LTP_scale_Q14, arch) \
((*SILK_NSQ_DEL_DEC_IMPL[(arch) & OPUS_ARCHMASK])(psEncC, NSQ, psIndices, x_Q3, pulses, PredCoef_Q12, LTPCoef_Q14, AR2_Q13, \
HarmShapeGain_Q14, Tilt_Q14, LF_shp_Q14, Gains_Q16, pitchL, Lambda_Q10, LTP_scale_Q14))
#endif
void silk_noise_shape_quantizer(
silk_nsq_state *NSQ, /* I/O NSQ state */
opus_int signalType, /* I Signal type */
const opus_int32 x_sc_Q10[], /* I */
opus_int8 pulses[], /* O */
opus_int16 xq[], /* O */
opus_int32 sLTP_Q15[], /* I/O LTP state */
const opus_int16 a_Q12[], /* I Short term prediction coefs */
const opus_int16 b_Q14[], /* I Long term prediction coefs */
const opus_int16 AR_shp_Q13[], /* I Noise shaping AR coefs */
opus_int lag, /* I Pitch lag */
opus_int32 HarmShapeFIRPacked_Q14, /* I */
opus_int Tilt_Q14, /* I Spectral tilt */
opus_int32 LF_shp_Q14, /* I */
opus_int32 Gain_Q16, /* I */
opus_int Lambda_Q10, /* I */
opus_int offset_Q10, /* I */
opus_int length, /* I Input length */
opus_int shapingLPCOrder, /* I Noise shaping AR filter order */
opus_int predictLPCOrder, /* I Prediction filter order */
int arch /* I Architecture */
);
/**************************/
/* Noise level estimation */
/**************************/
void silk_VAD_GetNoiseLevels(
const opus_int32 pX[ VAD_N_BANDS ], /* I subband energies */
silk_VAD_state *psSilk_VAD /* I/O Pointer to Silk VAD state */
);
# define OVERRIDE_silk_VAD_GetSA_Q8
opus_int silk_VAD_GetSA_Q8_sse4_1(
silk_encoder_state *psEnC,
const opus_int16 pIn[]
);
#if defined(OPUS_X86_PRESUME_SSE4_1)
#define silk_VAD_GetSA_Q8(psEnC, pIn, arch) ((void)(arch),silk_VAD_GetSA_Q8_sse4_1(psEnC, pIn))
#else
# define silk_VAD_GetSA_Q8(psEnC, pIn, arch) \
((*SILK_VAD_GETSA_Q8_IMPL[(arch) & OPUS_ARCHMASK])(psEnC, pIn))
extern opus_int (*const SILK_VAD_GETSA_Q8_IMPL[OPUS_ARCHMASK + 1])(
silk_encoder_state *psEnC,
const opus_int16 pIn[]);
# define OVERRIDE_silk_warped_LPC_analysis_filter_FIX
#endif
void silk_warped_LPC_analysis_filter_FIX_sse4_1(
opus_int32 state[], /* I/O State [order + 1] */
opus_int32 res_Q2[], /* O Residual signal [length] */
const opus_int16 coef_Q13[], /* I Coefficients [order] */
const opus_int16 input[], /* I Input signal [length] */
const opus_int16 lambda_Q16, /* I Warping factor */
const opus_int length, /* I Length of input signal */
const opus_int order /* I Filter order (even) */
);
#if defined(OPUS_X86_PRESUME_SSE4_1)
#define silk_warped_LPC_analysis_filter_FIX(state, res_Q2, coef_Q13, input, lambda_Q16, length, order, arch) \
((void)(arch),silk_warped_LPC_analysis_filter_FIX_c(state, res_Q2, coef_Q13, input, lambda_Q16, length, order))
#else
extern void (*const SILK_WARPED_LPC_ANALYSIS_FILTER_FIX_IMPL[OPUS_ARCHMASK + 1])(
opus_int32 state[], /* I/O State [order + 1] */
opus_int32 res_Q2[], /* O Residual signal [length] */
const opus_int16 coef_Q13[], /* I Coefficients [order] */
const opus_int16 input[], /* I Input signal [length] */
const opus_int16 lambda_Q16, /* I Warping factor */
const opus_int length, /* I Length of input signal */
const opus_int order /* I Filter order (even) */
);
# define silk_warped_LPC_analysis_filter_FIX(state, res_Q2, coef_Q13, input, lambda_Q16, length, order, arch) \
((*SILK_WARPED_LPC_ANALYSIS_FILTER_FIX_IMPL[(arch) & OPUS_ARCHMASK])(state, res_Q2, coef_Q13, input, lambda_Q16, length, order))
#endif
# endif
#endif
+174
View File
@@ -0,0 +1,174 @@
/* Copyright (c) 2014, Cisco Systems, INC
Written by XiangMingZhu WeiZhou MinPeng YanWang
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
- Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
- Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#if defined(HAVE_CONFIG_H)
#include "config.h"
#endif
#include "celt/x86/x86cpu.h"
#include "structs.h"
#include "SigProc_FIX.h"
#include "pitch.h"
#include "main.h"
#if !defined(OPUS_X86_PRESUME_SSE4_1)
#if defined(FIXED_POINT)
#include "fixed/main_FIX.h"
opus_int64 (*const SILK_INNER_PROD16_ALIGNED_64_IMPL[ OPUS_ARCHMASK + 1 ] )(
const opus_int16 *inVec1,
const opus_int16 *inVec2,
const opus_int len
) = {
silk_inner_prod16_aligned_64_c, /* non-sse */
silk_inner_prod16_aligned_64_c,
silk_inner_prod16_aligned_64_c,
MAY_HAVE_SSE4_1( silk_inner_prod16_aligned_64 ), /* sse4.1 */
MAY_HAVE_SSE4_1( silk_inner_prod16_aligned_64 ) /* avx */
};
#endif
opus_int (*const SILK_VAD_GETSA_Q8_IMPL[ OPUS_ARCHMASK + 1 ] )(
silk_encoder_state *psEncC,
const opus_int16 pIn[]
) = {
silk_VAD_GetSA_Q8_c, /* non-sse */
silk_VAD_GetSA_Q8_c,
silk_VAD_GetSA_Q8_c,
MAY_HAVE_SSE4_1( silk_VAD_GetSA_Q8 ), /* sse4.1 */
MAY_HAVE_SSE4_1( silk_VAD_GetSA_Q8 ) /* avx */
};
void (*const SILK_NSQ_IMPL[ OPUS_ARCHMASK + 1 ] )(
const silk_encoder_state *psEncC, /* I/O Encoder State */
silk_nsq_state *NSQ, /* I/O NSQ state */
SideInfoIndices *psIndices, /* I/O Quantization Indices */
const opus_int32 x_Q3[], /* I Prefiltered input signal */
opus_int8 pulses[], /* O Quantized pulse signal */
const opus_int16 PredCoef_Q12[ 2 * MAX_LPC_ORDER ], /* I Short term prediction coefs */
const opus_int16 LTPCoef_Q14[ LTP_ORDER * MAX_NB_SUBFR ], /* I Long term prediction coefs */
const opus_int16 AR2_Q13[ MAX_NB_SUBFR * MAX_SHAPE_LPC_ORDER ], /* I Noise shaping coefs */
const opus_int HarmShapeGain_Q14[ MAX_NB_SUBFR ], /* I Long term shaping coefs */
const opus_int Tilt_Q14[ MAX_NB_SUBFR ], /* I Spectral tilt */
const opus_int32 LF_shp_Q14[ MAX_NB_SUBFR ], /* I Low frequency shaping coefs */
const opus_int32 Gains_Q16[ MAX_NB_SUBFR ], /* I Quantization step sizes */
const opus_int pitchL[ MAX_NB_SUBFR ], /* I Pitch lags */
const opus_int Lambda_Q10, /* I Rate/distortion tradeoff */
const opus_int LTP_scale_Q14 /* I LTP state scaling */
) = {
silk_NSQ_c, /* non-sse */
silk_NSQ_c,
silk_NSQ_c,
MAY_HAVE_SSE4_1( silk_NSQ ), /* sse4.1 */
MAY_HAVE_SSE4_1( silk_NSQ ) /* avx */
};
void (*const SILK_VQ_WMAT_EC_IMPL[ OPUS_ARCHMASK + 1 ] )(
opus_int8 *ind, /* O index of best codebook vector */
opus_int32 *rate_dist_Q14, /* O best weighted quant error + mu * rate */
opus_int *gain_Q7, /* O sum of absolute LTP coefficients */
const opus_int16 *in_Q14, /* I input vector to be quantized */
const opus_int32 *W_Q18, /* I weighting matrix */
const opus_int8 *cb_Q7, /* I codebook */
const opus_uint8 *cb_gain_Q7, /* I codebook effective gain */
const opus_uint8 *cl_Q5, /* I code length for each codebook vector */
const opus_int mu_Q9, /* I tradeoff betw. weighted error and rate */
const opus_int32 max_gain_Q7, /* I maximum sum of absolute LTP coefficients */
opus_int L /* I number of vectors in codebook */
) = {
silk_VQ_WMat_EC_c, /* non-sse */
silk_VQ_WMat_EC_c,
silk_VQ_WMat_EC_c,
MAY_HAVE_SSE4_1( silk_VQ_WMat_EC ), /* sse4.1 */
MAY_HAVE_SSE4_1( silk_VQ_WMat_EC ) /* avx */
};
void (*const SILK_NSQ_DEL_DEC_IMPL[ OPUS_ARCHMASK + 1 ] )(
const silk_encoder_state *psEncC, /* I/O Encoder State */
silk_nsq_state *NSQ, /* I/O NSQ state */
SideInfoIndices *psIndices, /* I/O Quantization Indices */
const opus_int32 x_Q3[], /* I Prefiltered input signal */
opus_int8 pulses[], /* O Quantized pulse signal */
const opus_int16 PredCoef_Q12[ 2 * MAX_LPC_ORDER ], /* I Short term prediction coefs */
const opus_int16 LTPCoef_Q14[ LTP_ORDER * MAX_NB_SUBFR ], /* I Long term prediction coefs */
const opus_int16 AR2_Q13[ MAX_NB_SUBFR * MAX_SHAPE_LPC_ORDER ], /* I Noise shaping coefs */
const opus_int HarmShapeGain_Q14[ MAX_NB_SUBFR ], /* I Long term shaping coefs */
const opus_int Tilt_Q14[ MAX_NB_SUBFR ], /* I Spectral tilt */
const opus_int32 LF_shp_Q14[ MAX_NB_SUBFR ], /* I Low frequency shaping coefs */
const opus_int32 Gains_Q16[ MAX_NB_SUBFR ], /* I Quantization step sizes */
const opus_int pitchL[ MAX_NB_SUBFR ], /* I Pitch lags */
const opus_int Lambda_Q10, /* I Rate/distortion tradeoff */
const opus_int LTP_scale_Q14 /* I LTP state scaling */
) = {
silk_NSQ_del_dec_c, /* non-sse */
silk_NSQ_del_dec_c,
silk_NSQ_del_dec_c,
MAY_HAVE_SSE4_1( silk_NSQ_del_dec ), /* sse4.1 */
MAY_HAVE_SSE4_1( silk_NSQ_del_dec ) /* avx */
};
#if defined(FIXED_POINT)
void (*const SILK_WARPED_LPC_ANALYSIS_FILTER_FIX_IMPL[ OPUS_ARCHMASK + 1 ] )(
opus_int32 state[], /* I/O State [order + 1] */
opus_int32 res_Q2[], /* O Residual signal [length] */
const opus_int16 coef_Q13[], /* I Coefficients [order] */
const opus_int16 input[], /* I Input signal [length] */
const opus_int16 lambda_Q16, /* I Warping factor */
const opus_int length, /* I Length of input signal */
const opus_int order /* I Filter order (even) */
) = {
silk_warped_LPC_analysis_filter_FIX_c, /* non-sse */
silk_warped_LPC_analysis_filter_FIX_c,
silk_warped_LPC_analysis_filter_FIX_c,
MAY_HAVE_SSE4_1( silk_warped_LPC_analysis_filter_FIX ), /* sse4.1 */
MAY_HAVE_SSE4_1( silk_warped_LPC_analysis_filter_FIX ) /* avx */
};
void (*const SILK_BURG_MODIFIED_IMPL[ OPUS_ARCHMASK + 1 ] )(
opus_int32 *res_nrg, /* O Residual energy */
opus_int *res_nrg_Q, /* O Residual energy Q value */
opus_int32 A_Q16[], /* O Prediction coefficients (length order) */
const opus_int16 x[], /* I Input signal, length: nb_subfr * ( D + subfr_length ) */
const opus_int32 minInvGain_Q30, /* I Inverse of max prediction gain */
const opus_int subfr_length, /* I Input signal subframe length (incl. D preceding samples) */
const opus_int nb_subfr, /* I Number of subframes stacked in x */
const opus_int D, /* I Order */
int arch /* I Run-time architecture */
) = {
silk_burg_modified_c, /* non-sse */
silk_burg_modified_c,
silk_burg_modified_c,
MAY_HAVE_SSE4_1( silk_burg_modified ), /* sse4.1 */
MAY_HAVE_SSE4_1( silk_burg_modified ) /* avx */
};
#endif
#endif