aboutsummaryrefslogtreecommitdiff
path: root/silk/NSQ.c
diff options
context:
space:
mode:
Diffstat (limited to 'silk/NSQ.c')
-rw-r--r--silk/NSQ.c66
1 files changed, 37 insertions, 29 deletions
diff --git a/silk/NSQ.c b/silk/NSQ.c
index 43e3fee7..617a19fe 100644
--- a/silk/NSQ.c
+++ b/silk/NSQ.c
@@ -37,7 +37,7 @@ POSSIBILITY OF SUCH DAMAGE.
static OPUS_INLINE void silk_nsq_scale_states(
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 */
+ const opus_int16 x16[], /* I input */
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 */
@@ -75,14 +75,14 @@ static OPUS_INLINE void silk_noise_shape_quantizer(
void silk_NSQ_c
(
- const silk_encoder_state *psEncC, /* I/O Encoder State */
+ const silk_encoder_state *psEncC, /* I 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 */
+ const opus_int16 x16[], /* I Input */
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_int16 AR_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 */
@@ -117,8 +117,7 @@ void silk_NSQ_c
LSF_interpolation_flag = 1;
}
- ALLOC( sLTP_Q15,
- psEncC->ltp_mem_length + psEncC->frame_length, opus_int32 );
+ 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 */
@@ -128,7 +127,7 @@ void silk_NSQ_c
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 ];
+ AR_shp_Q13 = &AR_Q13[ k * MAX_SHAPE_LPC_ORDER ];
/* Noise shape parameters */
silk_assert( HarmShapeGain_Q14[ k ] >= 0 );
@@ -154,13 +153,13 @@ void silk_NSQ_c
}
}
- silk_nsq_scale_states( psEncC, NSQ, x_Q3, x_sc_Q10, sLTP, sLTP_Q15, k, LTP_scale_Q14, Gains_Q16, pitchL, psIndices->signalType );
+ silk_nsq_scale_states( psEncC, NSQ, x16, x_sc_Q10, sLTP, sLTP_Q15, k, LTP_scale_Q14, Gains_Q16, pitchL, psIndices->signalType );
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;
+ x16 += psEncC->subfr_length;
pulses += psEncC->subfr_length;
pxq += psEncC->subfr_length;
}
@@ -169,7 +168,6 @@ void silk_NSQ_c
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;
@@ -250,7 +248,7 @@ void silk_noise_shape_quantizer(
/* Noise shape feedback */
silk_assert( ( shapingLPCOrder & 1 ) == 0 ); /* check that order is even */
- n_AR_Q12 = silk_NSQ_noise_shape_feedback_loop(psLPC_Q14, NSQ->sAR2_Q14, AR_shp_Q13, shapingLPCOrder, arch);
+ n_AR_Q12 = silk_NSQ_noise_shape_feedback_loop(&NSQ->sDiff_shp_Q14, NSQ->sAR2_Q14, AR_shp_Q13, shapingLPCOrder, arch);
n_AR_Q12 = silk_SMLAWB( n_AR_Q12, NSQ->sLF_AR_shp_Q14, Tilt_Q14 );
@@ -279,14 +277,27 @@ void silk_noise_shape_quantizer(
r_Q10 = silk_SUB32( x_sc_Q10[ i ], tmp1 ); /* residual error Q10 */
/* Flip sign depending on dither */
- if ( NSQ->rand_seed < 0 ) {
- r_Q10 = -r_Q10;
+ if( NSQ->rand_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 (Lambda_Q10 > 2048) {
+ /* For aggressive RDO, the bias becomes more than one pulse. */
+ int rdo_offset = Lambda_Q10/2 - 512;
+ if (q1_Q10 > rdo_offset) {
+ q1_Q0 = silk_RSHIFT( q1_Q10 - rdo_offset, 10 );
+ } else if (q1_Q10 < -rdo_offset) {
+ q1_Q0 = silk_RSHIFT( q1_Q10 + rdo_offset, 10 );
+ } else if (q1_Q10 < 0) {
+ q1_Q0 = -1;
+ } else {
+ q1_Q0 = 0;
+ }
+ }
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 );
@@ -337,7 +348,8 @@ void silk_noise_shape_quantizer(
/* Update states */
psLPC_Q14++;
*psLPC_Q14 = xq_Q14;
- sLF_AR_shp_Q14 = silk_SUB_LSHIFT32( xq_Q14, n_AR_Q12, 2 );
+ NSQ->sDiff_shp_Q14 = silk_SUB_LSHIFT32( xq_Q14, x_sc_Q10[ i ], 4 );
+ sLF_AR_shp_Q14 = silk_SUB_LSHIFT32( NSQ->sDiff_shp_Q14, n_AR_Q12, 2 );
NSQ->sLF_AR_shp_Q14 = sLF_AR_shp_Q14;
NSQ->sLTP_shp_Q14[ NSQ->sLTP_shp_buf_idx ] = silk_SUB_LSHIFT32( sLF_AR_shp_Q14, n_LF_Q12, 2 );
@@ -356,7 +368,7 @@ void silk_noise_shape_quantizer(
static OPUS_INLINE void silk_nsq_scale_states(
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 */
+ const opus_int16 x16[], /* I input */
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 */
@@ -368,28 +380,18 @@ static OPUS_INLINE void silk_nsq_scale_states(
)
{
opus_int i, lag;
- opus_int32 gain_adj_Q16, inv_gain_Q31, inv_gain_Q23;
+ opus_int32 gain_adj_Q16, inv_gain_Q31, inv_gain_Q26;
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 );
+ inv_gain_Q26 = silk_RSHIFT_ROUND( inv_gain_Q31, 5 );
for( i = 0; i < psEncC->subfr_length; i++ ) {
- x_sc_Q10[ i ] = silk_SMULWW( x_Q3[ i ], inv_gain_Q23 );
+ x_sc_Q10[ i ] = silk_SMULWW( x16[ i ], inv_gain_Q26 );
}
- /* 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 ) {
@@ -403,7 +405,9 @@ static OPUS_INLINE void silk_nsq_scale_states(
}
/* Adjust for changing gain */
- if( gain_adj_Q16 != (opus_int32)1 << 16 ) {
+ if( Gains_Q16[ subfr ] != NSQ->prev_gain_Q16 ) {
+ gain_adj_Q16 = silk_DIV32_varQ( NSQ->prev_gain_Q16, Gains_Q16[ subfr ], 16 );
+
/* Scale long-term shaping state */
for( i = NSQ->sLTP_shp_buf_idx - psEncC->ltp_mem_length; i < NSQ->sLTP_shp_buf_idx; i++ ) {
NSQ->sLTP_shp_Q14[ i ] = silk_SMULWW( gain_adj_Q16, NSQ->sLTP_shp_Q14[ i ] );
@@ -417,6 +421,7 @@ static OPUS_INLINE void silk_nsq_scale_states(
}
NSQ->sLF_AR_shp_Q14 = silk_SMULWW( gain_adj_Q16, NSQ->sLF_AR_shp_Q14 );
+ NSQ->sDiff_shp_Q14 = silk_SMULWW( gain_adj_Q16, NSQ->sDiff_shp_Q14 );
/* Scale short-term prediction and shaping states */
for( i = 0; i < NSQ_LPC_BUF_LENGTH; i++ ) {
@@ -425,5 +430,8 @@ static OPUS_INLINE void silk_nsq_scale_states(
for( i = 0; i < MAX_SHAPE_LPC_ORDER; i++ ) {
NSQ->sAR2_Q14[ i ] = silk_SMULWW( gain_adj_Q16, NSQ->sAR2_Q14[ i ] );
}
+
+ /* Save inverse gain */
+ NSQ->prev_gain_Q16 = Gains_Q16[ subfr ];
}
}