Commit 54518c87 authored by Koen Vos's avatar Koen Vos Committed by Jean-Marc Valin
Browse files

Last part of the LPC work stabilization work discussed at the last meeting

Also adds the encoder part of commit ee8adbe7 as well as a few
minor cleanups.
parent a26b2be2
......@@ -40,7 +40,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
/* Number of binary divisions, when not in low complexity mode */
#define BIN_DIV_STEPS_A2NLSF_FIX 3 /* must be no higher than 16 - log2( LSF_COS_TAB_SZ_FIX ) */
#define QPoly 16
#define MAX_ITERATIONS_A2NLSF_FIX 30
/* Helper function for A2NLSF(..) */
......@@ -61,8 +60,8 @@ static inline void silk_A2NLSF_trans_poly(
}
/* Helper function for A2NLSF(..) */
/* Polynomial evaluation */
static inline opus_int32 silk_A2NLSF_eval_poly( /* return the polynomial evaluation, in QPoly */
opus_int32 *p, /* I Polynomial, QPoly */
static inline opus_int32 silk_A2NLSF_eval_poly( /* return the polynomial evaluation, in Q16 */
opus_int32 *p, /* I Polynomial, Q16 */
const opus_int32 x, /* I Evaluation point, Q12 */
const opus_int dd /* I Order */
)
......@@ -70,10 +69,10 @@ static inline opus_int32 silk_A2NLSF_eval_poly( /* return the polynomial evaluat
opus_int n;
opus_int32 x_Q16, y32;
y32 = p[ dd ]; /* QPoly */
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 ); /* QPoly */
y32 = silk_SMLAWW( p[ n ], y32, x_Q16 ); /* Q16 */
}
return y32;
}
......@@ -88,19 +87,11 @@ static inline void silk_A2NLSF_init(
opus_int k;
/* Convert filter coefs to even and odd polynomials */
P[dd] = silk_LSHIFT( 1, QPoly );
Q[dd] = silk_LSHIFT( 1, QPoly );
P[dd] = silk_LSHIFT( 1, 16 );
Q[dd] = silk_LSHIFT( 1, 16 );
for( k = 0; k < dd; k++ ) {
#if( QPoly < 16 )
P[ k ] = silk_RSHIFT_ROUND( -a_Q16[ dd - k - 1 ] - a_Q16[ dd + k ], 16 - QPoly ); /* QPoly */
Q[ k ] = silk_RSHIFT_ROUND( -a_Q16[ dd - k - 1 ] + a_Q16[ dd + k ], 16 - QPoly ); /* QPoly */
#elif( Qpoly == 16 )
P[ k ] = -a_Q16[ dd - k - 1 ] - a_Q16[ dd + k ]; /* QPoly*/
Q[ k ] = -a_Q16[ dd - k - 1 ] + a_Q16[ dd + k ]; /* QPoly*/
#else
P[ k ] = silk_LSHIFT( -a_Q16[ dd - k - 1 ] - a_Q16[ dd + k ], QPoly - 16 ); /* QPoly */
Q[ k ] = silk_LSHIFT( -a_Q16[ dd - k - 1 ] + a_Q16[ dd + k ], QPoly - 16 ); /* QPoly */
#endif
P[ k ] = -a_Q16[ dd - k - 1 ] - a_Q16[ dd + k ]; /* Q16 */
Q[ k ] = -a_Q16[ dd - k - 1 ] + a_Q16[ dd + k ]; /* Q16 */
}
/* Divide out zeros as we have that for even filter orders, */
......
......@@ -137,7 +137,7 @@ void silk_NLSF2A(
idx = k;
}
}
maxabs = silk_RSHIFT_ROUND( maxabs, QA + 1 - 12 ); /* QA+1 -> Q12 */
maxabs = silk_RSHIFT_ROUND( maxabs, QA + 1 - 12 ); /* QA+1 -> Q12 */
if( maxabs > silk_int16_MAX ) {
/* Reduce magnitude of prediction coefficients */
......@@ -153,33 +153,26 @@ void silk_NLSF2A(
if( i == 10 ) {
/* Reached the last iteration, clip the coefficients */
for( k = 0; k < d; k++ ) {
a_Q12[ k ] = (opus_int16)silk_SAT16( silk_RSHIFT_ROUND( a32_QA1[ k ], QA + 1 - 12 ) ); /* QA+1 -> Q12 */
a_Q12[ k ] = (opus_int16)silk_SAT16( silk_RSHIFT_ROUND( a32_QA1[ k ], QA + 1 - 12 ) ); /* QA+1 -> Q12 */
a32_QA1[ k ] = silk_LSHIFT( (opus_int32)a_Q12[ k ], QA + 1 - 12 );
}
} else {
for( k = 0; k < d; k++ ) {
a_Q12[ k ] = (opus_int16)silk_RSHIFT_ROUND( a32_QA1[ k ], QA + 1 - 12 ); /* QA+1 -> Q12 */
a_Q12[ k ] = (opus_int16)silk_RSHIFT_ROUND( a32_QA1[ k ], QA + 1 - 12 ); /* QA+1 -> Q12 */
}
}
for( i = 1; i <= MAX_LPC_STABILIZE_ITERATIONS; i++ ) {
for( i = 0; i < MAX_LPC_STABILIZE_ITERATIONS; i++ ) {
if( silk_LPC_inverse_pred_gain( a_Q12, d ) < SILK_FIX_CONST( 1.0 / MAX_PREDICTION_POWER_GAIN, 30 ) ) {
/* Prediction coefficients are (too close to) unstable; apply bandwidth expansion */
/* on the unscaled coefficients, convert to Q12 and measure again */
silk_bwexpander_32( a32_QA1, d, 65536 - silk_SMULBB( 9 + i, i ) ); /* 10_Q16 = 0.00015 */
silk_bwexpander_32( a32_QA1, d, 65536 - silk_LSHIFT( 2, i ) );
for( k = 0; k < d; k++ ) {
a_Q12[ k ] = (opus_int16)silk_RSHIFT_ROUND( a32_QA1[ k ], QA + 1 - 12 ); /* QA+1 -> Q12 */
a_Q12[ k ] = (opus_int16)silk_RSHIFT_ROUND( a32_QA1[ k ], QA + 1 - 12 ); /* QA+1 -> Q12 */
}
} else {
break;
}
}
if( i > MAX_LPC_STABILIZE_ITERATIONS ) {
/* Reached the last iteration, set coefficients to zero */
for( k = 0; k < d; k++ ) {
a_Q12[ k ] = 0;
}
}
}
......@@ -83,7 +83,7 @@ void silk_NLSF_decode(
/* Unpack entropy table indices and predictor for current CB1 index */
silk_NLSF_unpack( ec_ix, pred_Q8, psNLSF_CB, NLSFIndices[ 0 ] );
/* Trellis dequantizer */
/* Predictive residual dequantizer */
silk_NLSF_residual_dequant( res_Q10, &NLSFIndices[ 1 ], pred_Q8, psNLSF_CB->quantStepSize_Q16, psNLSF_CB->order );
/* Weights from codebook vector */
......
......@@ -33,7 +33,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
/* Unpack predictor values and indices for entropy coding tables */
void silk_NLSF_unpack(
opus_int16 ec_ix[], /* O Indices to entropy tales [ LPC_ORDER ] */
opus_int16 ec_ix[], /* O Indices to entropy tables [ LPC_ORDER ] */
opus_uint8 pred_Q8[], /* O LSF predictor [ LPC_ORDER ] */
const silk_NLSF_CB_struct *psNLSF_CB, /* I Codebook object */
const opus_int CB1_index /* I Index of vector in first LSF codebook */
......
......@@ -190,7 +190,7 @@ static inline void silk_noise_shape_quantizer(
opus_int i, j;
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 dither, exc_Q14, LPC_exc_Q14, xq_Q14, Gain_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;
......@@ -205,9 +205,6 @@ static inline void silk_noise_shape_quantizer(
/* Generate dither */
NSQ->rand_seed = silk_RAND( NSQ->rand_seed );
/* dither = rand_seed < 0 ? 0xFFFFFFFF : 0; */
dither = silk_RSHIFT( NSQ->rand_seed, 31 );
/* Short-term prediction */
silk_assert( predictLPCOrder == 10 || predictLPCOrder == 16 );
/* Avoids introducing a bias because silk_SMLAWB() always rounds to -inf */
......@@ -292,7 +289,9 @@ static inline void silk_noise_shape_quantizer(
r_Q10 = silk_SUB32( x_sc_Q10[ i ], tmp1 ); /* residual error Q10 */
/* Flip sign depending on dither */
r_Q10 = r_Q10 ^ dither;
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 */
......@@ -333,7 +332,10 @@ static inline void silk_noise_shape_quantizer(
pulses[ i ] = (opus_int8)silk_RSHIFT_ROUND( q1_Q10, 10 );
/* Excitation */
exc_Q14 = silk_LSHIFT( q1_Q10, 4 ) ^ dither;
exc_Q14 = silk_LSHIFT( q1_Q10, 4 );
if ( NSQ->rand_seed < 0 ) {
exc_Q14 = -exc_Q14;
}
/* Add predictions */
LPC_exc_Q14 = silk_ADD_LSHIFT32( exc_Q14, LTP_pred_Q13, 1 );
......
......@@ -325,7 +325,7 @@ static inline void silk_noise_shape_quantizer_del_dec(
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, dither, exc_Q14, LPC_exc_Q14, xq_Q14, Gain_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 ];
......@@ -378,9 +378,6 @@ static inline void silk_noise_shape_quantizer_del_dec(
/* Generate dither */
psDD->Seed = silk_RAND( psDD->Seed );
/* dither = rand_seed < 0 ? 0xFFFFFFFF : 0; */
dither = silk_RSHIFT( psDD->Seed, 31 );
/* Pointer used in short term prediction and shaping */
psLPC_Q14 = &psDD->sLPC_Q14[ NSQ_LPC_BUF_LENGTH - 1 + i ];
/* Short-term prediction */
......@@ -448,7 +445,9 @@ static inline void silk_noise_shape_quantizer_del_dec(
r_Q10 = silk_SUB32( x_Q10[ i ], tmp1 ); /* residual error Q10 */
/* Flip sign depending on dither */
r_Q10 = r_Q10 ^ 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 */
......@@ -497,7 +496,10 @@ static inline void silk_noise_shape_quantizer_del_dec(
/* Update states for best quantization */
/* Quantized excitation */
exc_Q14 = silk_LSHIFT32( psSS[ 0 ].Q_Q10, 4 ) ^ dither;
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 );
......@@ -513,7 +515,11 @@ static inline void silk_noise_shape_quantizer_del_dec(
/* Update states for second best quantization */
/* Quantized excitation */
exc_Q14 = silk_LSHIFT32( psSS[ 1 ].Q_Q10, 4 ) ^ dither;
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 );
......
......@@ -72,8 +72,9 @@ void silk_decode_core(
psDec->exc_Q14[ i ] += QUANT_LEVEL_ADJUST_Q10 << 4;
}
psDec->exc_Q14[ i ] += offset_Q10 << 4;
if ( rand_seed < 0 )
if( rand_seed < 0 ) {
psDec->exc_Q14[ i ] = -psDec->exc_Q14[ i ];
}
rand_seed = silk_ADD32_ovflw( rand_seed, pulses[ i ] );
}
......
......@@ -130,7 +130,7 @@ extern "C"
#define QUANT_LEVEL_ADJUST_Q10 80
/* Maximum numbers of iterations used to stabilize an LPC vector */
#define MAX_LPC_STABILIZE_ITERATIONS 15
#define MAX_LPC_STABILIZE_ITERATIONS 16
#define MAX_PREDICTION_POWER_GAIN 1e4f
#define MAX_PREDICTION_POWER_GAIN_AFTER_RESET 1e2f
......
......@@ -331,7 +331,7 @@ opus_int32 silk_NLSF_del_dec_quant( /* O Returns
/* Unpack predictor values and indices for entropy coding tables */
void silk_NLSF_unpack(
opus_int16 ec_ix[], /* O Indices to entropy tales [ LPC_ORDER ] */
opus_int16 ec_ix[], /* O Indices to entropy tables [ LPC_ORDER ] */
opus_uint8 pred_Q8[], /* O LSF predictor [ LPC_ORDER ] */
const silk_NLSF_CB_struct *psNLSF_CB, /* I Codebook object */
const opus_int CB1_index /* I Index of vector in first LSF codebook */
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment