diff options
author | Koen Vos <koen.vos@skype.net> | 2011-12-13 23:47:31 +0400 |
---|---|---|
committer | Jean-Marc Valin <jmvalin@jmvalin.ca> | 2011-12-13 23:47:31 +0400 |
commit | bf75c8ec4d0dded188bc7793de6da56c7ff0be1c (patch) | |
tree | c21bb05faf0a203b73e8f8aae90fc63dac27625d /silk/float | |
parent | 6619a736376221f2782cecff55d051c3ecfc2ff7 (diff) |
SILK fixes following last codec WG meeting
decoder:
- fixed incorrect scaling of filter states for the smallest quantization
step sizes
- NLSF2A now limits the prediction gain of LPC filters
encoder:
- increased damping of LTP coefficients in LTP analysis
- increased white noise fraction in noise shaping LPC analysis
- introduced maximum total prediction gain. Used by Burg's method to
exit early if prediction gain is exceeded. This improves packet
loss robustness and numerical robustness in Burg's method
- Prefiltered signal is now in int32 Q10 domain, from int16 Q0
- Increased max number of iterations in CBR gain control loop from 5 to 6
- Removed useless code from LTP scaling control
- Optimization: smarter LPC loop unrolling
- Switched default win32 compile mode to be floating-point
resampler:
- made resampler have constant delay of 0.75 ms; removed delay
compensation from silk code.
- removed obsolete table entries (~850 Bytes)
- increased downsampling filter order from 16 to 18/24/36 (depending on
frequency ratio)
- reoptimized filter coefficients
Diffstat (limited to 'silk/float')
-rw-r--r-- | silk/float/LPC_inv_pred_gain_FLP.c | 17 | ||||
-rw-r--r-- | silk/float/LTP_scale_ctrl_FLP.c | 11 | ||||
-rw-r--r-- | silk/float/SigProc_FLP.h | 5 | ||||
-rw-r--r-- | silk/float/burg_modified_FLP.c | 78 | ||||
-rw-r--r-- | silk/float/encode_frame_FLP.c | 6 | ||||
-rw-r--r-- | silk/float/find_LPC_FLP.c | 65 | ||||
-rw-r--r-- | silk/float/find_pitch_lags_FLP.c | 2 | ||||
-rw-r--r-- | silk/float/find_pred_coefs_FLP.c | 15 | ||||
-rw-r--r-- | silk/float/main_FLP.h | 9 | ||||
-rw-r--r-- | silk/float/noise_shape_analysis_FLP.c | 6 | ||||
-rw-r--r-- | silk/float/pitch_analysis_core_FLP.c | 6 | ||||
-rw-r--r-- | silk/float/prefilter_FLP.c | 2 | ||||
-rw-r--r-- | silk/float/process_gains_FLP.c | 2 | ||||
-rw-r--r-- | silk/float/structs_FLP.h | 4 | ||||
-rw-r--r-- | silk/float/wrappers_FLP.c | 14 |
15 files changed, 131 insertions, 111 deletions
diff --git a/silk/float/LPC_inv_pred_gain_FLP.c b/silk/float/LPC_inv_pred_gain_FLP.c index d7a5d87e..59ed7d4c 100644 --- a/silk/float/LPC_inv_pred_gain_FLP.c +++ b/silk/float/LPC_inv_pred_gain_FLP.c @@ -37,29 +37,28 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. /* compute inverse of LPC prediction gain, and */ /* test if LPC coefficients are stable (all poles within unit circle) */ /* this code is based on silk_a2k_FLP() */ -opus_int silk_LPC_inverse_pred_gain_FLP( /* O returns 1 if unstable, otherwise 0 */ - silk_float *invGain, /* O inverse prediction gain, energy domain */ +silk_float silk_LPC_inverse_pred_gain_FLP( /* O return inverse prediction gain, energy domain */ const silk_float *A, /* I prediction coefficients [order] */ opus_int32 order /* I prediction order */ ) { opus_int k, n; - double rc, rc_mult1, rc_mult2; + double invGain, rc, rc_mult1, rc_mult2; silk_float Atmp[ 2 ][ SILK_MAX_ORDER_LPC ]; silk_float *Aold, *Anew; Anew = Atmp[ order & 1 ]; silk_memcpy( Anew, A, order * sizeof(silk_float) ); - *invGain = 1.0f; + invGain = 1.0; for( k = order - 1; k > 0; k-- ) { rc = -Anew[ k ]; if( rc > RC_THRESHOLD || rc < -RC_THRESHOLD ) { - return 1; + return 0.0f; } rc_mult1 = 1.0f - rc * rc; rc_mult2 = 1.0f / rc_mult1; - *invGain *= (silk_float)rc_mult1; + invGain *= rc_mult1; /* swap pointers */ Aold = Anew; Anew = Atmp[ k & 1 ]; @@ -69,9 +68,9 @@ opus_int silk_LPC_inverse_pred_gain_FLP( /* O returns 1 if unstable, other } rc = -Anew[ 0 ]; if( rc > RC_THRESHOLD || rc < -RC_THRESHOLD ) { - return 1; + return 0.0f; } rc_mult1 = 1.0f - rc * rc; - *invGain *= (silk_float)rc_mult1; - return 0; + invGain *= rc_mult1; + return (silk_float)invGain; } diff --git a/silk/float/LTP_scale_ctrl_FLP.c b/silk/float/LTP_scale_ctrl_FLP.c index ebfdbf49..2354ebe9 100644 --- a/silk/float/LTP_scale_ctrl_FLP.c +++ b/silk/float/LTP_scale_ctrl_FLP.c @@ -39,19 +39,14 @@ void silk_LTP_scale_ctrl_FLP( { opus_int round_loss; - /* 1st order high-pass filter */ - /*g_HP(n) = g(n) - 0.5 * g(n-1) + 0.5 * g_HP(n-1);*/ - psEnc->HPLTPredCodGain = silk_max_float( psEncCtrl->LTPredCodGain - 0.5f * psEnc->prevLTPredCodGain, 0.0f ) - + 0.5f * psEnc->HPLTPredCodGain; - psEnc->prevLTPredCodGain = psEncCtrl->LTPredCodGain; - - /* Only scale if first frame in packet */ if( condCoding == CODE_INDEPENDENTLY ) { + /* Only scale if first frame in packet */ round_loss = psEnc->sCmn.PacketLoss_perc + psEnc->sCmn.nFramesPerPacket; - psEnc->sCmn.indices.LTP_scaleIndex = (opus_int8)silk_LIMIT( round_loss * psEnc->HPLTPredCodGain * 0.1f, 0.0f, 2.0f ); + psEnc->sCmn.indices.LTP_scaleIndex = (opus_int8)silk_LIMIT( round_loss * psEncCtrl->LTPredCodGain * 0.1f, 0.0f, 2.0f ); } else { /* Default is minimum scaling */ psEnc->sCmn.indices.LTP_scaleIndex = 0; } + psEncCtrl->LTP_scale = (silk_float)silk_LTPScales_table_Q14[ psEnc->sCmn.indices.LTP_scaleIndex ] / 16384.0f; } diff --git a/silk/float/SigProc_FLP.h b/silk/float/SigProc_FLP.h index 7b2ba089..0d70ca1b 100644 --- a/silk/float/SigProc_FLP.h +++ b/silk/float/SigProc_FLP.h @@ -50,8 +50,7 @@ void silk_bwexpander_FLP( /* compute inverse of LPC prediction gain, and */ /* test if LPC coefficients are stable (all poles within unit circle) */ /* this code is based on silk_FLP_a2k() */ -opus_int silk_LPC_inverse_pred_gain_FLP( /* O returns 1 if unstable, otherwise 0 */ - silk_float *invGain, /* O inverse prediction gain, energy domain */ +silk_float silk_LPC_inverse_pred_gain_FLP( /* O return inverse prediction gain, energy domain */ const silk_float *A, /* I prediction coefficients [order] */ opus_int32 order /* I prediction order */ ); @@ -108,9 +107,9 @@ void silk_insertion_sort_decreasing_FLP( silk_float silk_burg_modified_FLP( /* O returns residual energy */ silk_float A[], /* O prediction coefficients (length order) */ const silk_float x[], /* I input signal, length: nb_subfr*(D+L_sub) */ + const silk_float minInvGain, /* I minimum inverse prediction gain */ const opus_int subfr_length, /* I input signal subframe length (incl. D preceeding samples) */ const opus_int nb_subfr, /* I number of subframes stacked in x */ - const silk_float WhiteNoiseFrac, /* I fraction added to zero-lag autocorrelation */ const opus_int D /* I order */ ); diff --git a/silk/float/burg_modified_FLP.c b/silk/float/burg_modified_FLP.c index b5862a54..2f6edfae 100644 --- a/silk/float/burg_modified_FLP.c +++ b/silk/float/burg_modified_FLP.c @@ -30,29 +30,29 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #endif #include "SigProc_FLP.h" +#include "tuning_parameters.h" +#include "define.h" #define MAX_FRAME_SIZE 384 /* subfr_length * nb_subfr = ( 0.005 * 16000 + 16 ) * 4 = 384*/ -#define MAX_NB_SUBFR 4 /* Compute reflection coefficients from input signal */ silk_float silk_burg_modified_FLP( /* O returns residual energy */ silk_float A[], /* O prediction coefficients (length order) */ const silk_float x[], /* I input signal, length: nb_subfr*(D+L_sub) */ + const silk_float minInvGain, /* I minimum inverse prediction gain */ const opus_int subfr_length, /* I input signal subframe length (incl. D preceeding samples) */ const opus_int nb_subfr, /* I number of subframes stacked in x */ - const silk_float WhiteNoiseFrac, /* I fraction added to zero-lag autocorrelation */ const opus_int D /* I order */ ) { - opus_int k, n, s; - double C0, num, nrg_f, nrg_b, rc, Atmp, tmp1, tmp2; + opus_int k, n, s, reached_max_gain; + double C0, invGain, num, nrg_f, nrg_b, rc, Atmp, tmp1, tmp2; const silk_float *x_ptr; - double C_first_row[ SILK_MAX_ORDER_LPC ], C_last_row[ SILK_MAX_ORDER_LPC ]; - double CAf[ SILK_MAX_ORDER_LPC + 1 ], CAb[ SILK_MAX_ORDER_LPC + 1 ]; - double Af[ SILK_MAX_ORDER_LPC ]; + double C_first_row[ SILK_MAX_ORDER_LPC ], C_last_row[ SILK_MAX_ORDER_LPC ]; + double CAf[ SILK_MAX_ORDER_LPC + 1 ], CAb[ SILK_MAX_ORDER_LPC + 1 ]; + double Af[ SILK_MAX_ORDER_LPC ]; silk_assert( subfr_length * nb_subfr <= MAX_FRAME_SIZE ); - silk_assert( nb_subfr <= MAX_NB_SUBFR ); /* Compute autocorrelations, added over subframes */ C0 = silk_energy_FLP( x, nb_subfr * subfr_length ); @@ -66,8 +66,9 @@ silk_float silk_burg_modified_FLP( /* O returns residual energy silk_memcpy( C_last_row, C_first_row, SILK_MAX_ORDER_LPC * sizeof( double ) ); /* Initialize */ - CAb[ 0 ] = CAf[ 0 ] = C0 + WhiteNoiseFrac * C0 + 1e-9f; - + CAb[ 0 ] = CAf[ 0 ] = C0 + FIND_LPC_COND_FAC * C0 + 1e-9f; + invGain = 1.0f; + reached_max_gain = 0; for( n = 0; n < D; n++ ) { /* Update first row of correlation matrix (without first element) */ /* Update last row of correlation matrix (without last element, stored in reversed order) */ @@ -93,7 +94,7 @@ silk_float silk_burg_modified_FLP( /* O returns residual energy tmp2 = C_last_row[ n ]; for( k = 0; k < n; k++ ) { Atmp = Af[ k ]; - tmp1 += C_last_row[ n - k - 1 ] * Atmp; + tmp1 += C_last_row[ n - k - 1 ] * Atmp; tmp2 += C_first_row[ n - k - 1 ] * Atmp; } CAf[ n + 1 ] = tmp1; @@ -116,6 +117,21 @@ silk_float silk_burg_modified_FLP( /* O returns residual energy rc = -2.0 * num / ( nrg_f + nrg_b ); silk_assert( rc > -1.0 && rc < 1.0 ); + /* Update inverse prediction gain */ + tmp1 = invGain * ( 1.0 - rc * rc ); + if( tmp1 <= minInvGain ) { + /* Max prediction gain exceeded; set reflection coefficient such that max prediction gain is exactly hit */ + rc = sqrt( 1.0 - minInvGain / invGain ); + if( num > 0 ) { + /* Ensure adjusted reflection coefficients has the original sign */ + rc = -rc; + } + invGain = minInvGain; + reached_max_gain = 1; + } else { + invGain = tmp1; + } + /* Update the AR coefficients */ for( k = 0; k < (n + 1) >> 1; k++ ) { tmp1 = Af[ k ]; @@ -125,6 +141,14 @@ silk_float silk_burg_modified_FLP( /* O returns residual energy } Af[ n ] = rc; + if( reached_max_gain ) { + /* Reached max prediction gain; set remaining coefficients to zero and exit loop */ + for( k = n + 1; k < D; k++ ) { + Af[ k ] = 0.0; + } + break; + } + /* Update C * Af and C * Ab */ for( k = 0; k <= n + 1; k++ ) { tmp1 = CAf[ k ]; @@ -133,16 +157,30 @@ silk_float silk_burg_modified_FLP( /* O returns residual energy } } - /* Return residual energy */ - nrg_f = CAf[ 0 ]; - tmp1 = 1.0; - for( k = 0; k < D; k++ ) { - Atmp = Af[ k ]; - nrg_f += CAf[ k + 1 ] * Atmp; - tmp1 += Atmp * Atmp; - A[ k ] = (silk_float)(-Atmp); + if( reached_max_gain ) { + /* Convert to silk_float */ + for( k = 0; k < D; k++ ) { + A[ k ] = (silk_float)( -Af[ k ] ); + } + /* Subtract energy of preceeding samples from C0 */ + for( s = 0; s < nb_subfr; s++ ) { + C0 -= silk_energy_FLP( x + s * subfr_length, D ); + } + /* Approximate residual energy */ + nrg_f = C0 * invGain; + } else { + /* Compute residual energy and store coefficients as silk_float */ + nrg_f = CAf[ 0 ]; + tmp1 = 1.0; + for( k = 0; k < D; k++ ) { + Atmp = Af[ k ]; + nrg_f += CAf[ k + 1 ] * Atmp; + tmp1 += Atmp * Atmp; + A[ k ] = (silk_float)(-Atmp); + } + nrg_f -= FIND_LPC_COND_FAC * C0 * tmp1; } - nrg_f -= WhiteNoiseFrac * C0 * tmp1; + /* Return residual energy */ return (silk_float)nrg_f; } diff --git a/silk/float/encode_frame_FLP.c b/silk/float/encode_frame_FLP.c index faae848c..facb4104 100644 --- a/silk/float/encode_frame_FLP.c +++ b/silk/float/encode_frame_FLP.c @@ -104,8 +104,8 @@ opus_int silk_encode_frame_FLP( psEnc->sCmn.indices.Seed = psEnc->sCmn.frameCounter++ & 3; /**************************************************************/ - /* Setup Input Pointers, and insert frame in input buffer */ - /*************************************************************/ + /* Set up Input Pointers, and insert frame in input buffer */ + /**************************************************************/ /* pointers aligned with start of frame to encode */ x_frame = psEnc->x_buf + psEnc->sCmn.ltp_mem_length; /* start of frame to encode */ res_pitch_frame = res_pitch + psEnc->sCmn.ltp_mem_length; /* start of pitch LPC residual frame */ @@ -157,7 +157,7 @@ opus_int silk_encode_frame_FLP( silk_LBRR_encode_FLP( psEnc, &sEncCtrl, xfw, condCoding ); /* Loop over quantizer and entroy coding to control bitrate */ - maxIter = 5; + maxIter = 6; gainMult_Q8 = SILK_FIX_CONST( 1, 8 ); found_lower = 0; found_upper = 0; diff --git a/silk/float/find_LPC_FLP.c b/silk/float/find_LPC_FLP.c index 23de2e73..940a8c0a 100644 --- a/silk/float/find_LPC_FLP.c +++ b/silk/float/find_LPC_FLP.c @@ -29,73 +29,63 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "config.h" #endif +#include "define.h" #include "main_FLP.h" #include "tuning_parameters.h" +/* LPC analysis */ void silk_find_LPC_FLP( + silk_encoder_state *psEncC, /* I/O Encoder state */ opus_int16 NLSF_Q15[], /* O NLSFs */ - opus_int8 *interpIndex, /* O NLSF interp. index for NLSF interp. */ - const opus_int16 prev_NLSFq_Q15[], /* I Previous NLSFs, for NLSF interpolation */ - const opus_int useInterpNLSFs, /* I Flag */ - const opus_int firstFrameAfterReset, /* I Flag */ - const opus_int LPC_order, /* I LPC order */ const silk_float x[], /* I Input signal */ - const opus_int subfr_length, /* I Subframe length incl preceeding samples */ - const opus_int nb_subfr /* I Number of subframes */ + const silk_float minInvGain /* I Inverse of max prediction gain */ ) { - opus_int k; - silk_float a[ MAX_LPC_ORDER ]; + opus_int k, subfr_length; + silk_float a[ MAX_LPC_ORDER ]; /* Used only for NLSF interpolation */ - double res_nrg, res_nrg_2nd, res_nrg_interp; - opus_int16 NLSF0_Q15[ MAX_LPC_ORDER ]; - silk_float a_tmp[ MAX_LPC_ORDER ]; - silk_float LPC_res[ ( MAX_FRAME_LENGTH + MAX_NB_SUBFR * MAX_LPC_ORDER ) / 2 ]; + silk_float res_nrg, res_nrg_2nd, res_nrg_interp; + opus_int16 NLSF0_Q15[ MAX_LPC_ORDER ]; + silk_float a_tmp[ MAX_LPC_ORDER ]; + silk_float LPC_res[ MAX_FRAME_LENGTH + MAX_NB_SUBFR * MAX_LPC_ORDER ]; + + subfr_length = psEncC->subfr_length + psEncC->predictLPCOrder; /* Default: No interpolation */ - *interpIndex = 4; + psEncC->indices.NLSFInterpCoef_Q2 = 4; /* Burg AR analysis for the full frame */ - res_nrg = silk_burg_modified_FLP( a, x, subfr_length, nb_subfr, FIND_LPC_COND_FAC, LPC_order ); - - if( firstFrameAfterReset ) { - silk_bwexpander_FLP( a, LPC_order, FIND_LPC_CHIRP_FIRST_FRAME ); - } else { - silk_bwexpander_FLP( a_tmp, LPC_order, FIND_LPC_CHIRP ); - } + res_nrg = silk_burg_modified_FLP( a, x, minInvGain, subfr_length, psEncC->nb_subfr, psEncC->predictLPCOrder ); - if( useInterpNLSFs && !firstFrameAfterReset && nb_subfr == MAX_NB_SUBFR ) { + if( psEncC->useInterpolatedNLSFs && !psEncC->first_frame_after_reset && psEncC->nb_subfr == MAX_NB_SUBFR ) { /* Optimal solution for last 10 ms; subtract residual energy here, as that's easier than */ /* adding it to the residual energy of the first 10 ms in each iteration of the search below */ - res_nrg -= silk_burg_modified_FLP( a_tmp, x + ( MAX_NB_SUBFR / 2 ) * subfr_length, - subfr_length, MAX_NB_SUBFR / 2, FIND_LPC_COND_FAC, LPC_order ); - - silk_bwexpander_FLP( a_tmp, LPC_order, FIND_LPC_CHIRP ); + res_nrg -= silk_burg_modified_FLP( a_tmp, x + ( MAX_NB_SUBFR / 2 ) * subfr_length, minInvGain, subfr_length, MAX_NB_SUBFR / 2, psEncC->predictLPCOrder ); /* Convert to NLSFs */ - silk_A2NLSF_FLP( NLSF_Q15, a_tmp, LPC_order ); + silk_A2NLSF_FLP( NLSF_Q15, a_tmp, psEncC->predictLPCOrder ); /* Search over interpolation indices to find the one with lowest residual energy */ res_nrg_2nd = silk_float_MAX; for( k = 3; k >= 0; k-- ) { /* Interpolate NLSFs for first half */ - silk_interpolate( NLSF0_Q15, prev_NLSFq_Q15, NLSF_Q15, k, LPC_order ); + silk_interpolate( NLSF0_Q15, psEncC->prev_NLSFq_Q15, NLSF_Q15, k, psEncC->predictLPCOrder ); /* Convert to LPC for residual energy evaluation */ - silk_NLSF2A_FLP( a_tmp, NLSF0_Q15, LPC_order ); + silk_NLSF2A_FLP( a_tmp, NLSF0_Q15, psEncC->predictLPCOrder ); /* Calculate residual energy with LSF interpolation */ - silk_LPC_analysis_filter_FLP( LPC_res, a_tmp, x, 2 * subfr_length, LPC_order ); - res_nrg_interp = - silk_energy_FLP( LPC_res + LPC_order, subfr_length - LPC_order ) + - silk_energy_FLP( LPC_res + LPC_order + subfr_length, subfr_length - LPC_order ); + silk_LPC_analysis_filter_FLP( LPC_res, a_tmp, x, 2 * subfr_length, psEncC->predictLPCOrder ); + res_nrg_interp = (silk_float)( + silk_energy_FLP( LPC_res + psEncC->predictLPCOrder, subfr_length - psEncC->predictLPCOrder ) + + silk_energy_FLP( LPC_res + psEncC->predictLPCOrder + subfr_length, subfr_length - psEncC->predictLPCOrder ) ); /* Determine whether current interpolated NLSFs are best so far */ if( res_nrg_interp < res_nrg ) { /* Interpolation has lower residual energy */ res_nrg = res_nrg_interp; - *interpIndex = (opus_int8)k; + psEncC->indices.NLSFInterpCoef_Q2 = (opus_int8)k; } else if( res_nrg_interp > res_nrg_2nd ) { /* No reason to continue iterating - residual energies will continue to climb */ break; @@ -104,10 +94,11 @@ void silk_find_LPC_FLP( } } - if( *interpIndex == 4 ) { + if( psEncC->indices.NLSFInterpCoef_Q2 == 4 ) { /* NLSF interpolation is currently inactive, calculate NLSFs from full frame AR coefficients */ - silk_A2NLSF_FLP( NLSF_Q15, a, LPC_order ); + silk_A2NLSF_FLP( NLSF_Q15, a, psEncC->predictLPCOrder ); } - silk_assert( *interpIndex == 4 || ( useInterpNLSFs && !firstFrameAfterReset && nb_subfr == MAX_NB_SUBFR ) ); + silk_assert( psEncC->indices.NLSFInterpCoef_Q2 == 4 || + ( psEncC->useInterpolatedNLSFs && !psEncC->first_frame_after_reset && psEncC->nb_subfr == MAX_NB_SUBFR ) ); } diff --git a/silk/float/find_pitch_lags_FLP.c b/silk/float/find_pitch_lags_FLP.c index 43f7ff94..c037138f 100644 --- a/silk/float/find_pitch_lags_FLP.c +++ b/silk/float/find_pitch_lags_FLP.c @@ -50,7 +50,7 @@ void silk_find_pitch_lags_FLP( silk_float *Wsig_ptr; /******************************************/ - /* Setup buffer lengths etc based on Fs */ + /* Set up buffer lengths etc based on Fs */ /******************************************/ buf_len = psEnc->sCmn.la_pitch + psEnc->sCmn.frame_length + psEnc->sCmn.ltp_mem_length; diff --git a/silk/float/find_pred_coefs_FLP.c b/silk/float/find_pred_coefs_FLP.c index 03500c2c..71866778 100644 --- a/silk/float/find_pred_coefs_FLP.c +++ b/silk/float/find_pred_coefs_FLP.c @@ -46,6 +46,7 @@ void silk_find_pred_coefs_FLP( opus_int16 NLSF_Q15[ MAX_LPC_ORDER ]; const silk_float *x_ptr; silk_float *x_pre_ptr, LPC_in_pre[ MAX_NB_SUBFR * MAX_LPC_ORDER + MAX_FRAME_LENGTH ]; + silk_float minInvGain; /* Weighting for weighted least squares */ for( i = 0; i < psEnc->sCmn.nb_subfr; i++ ) { @@ -74,7 +75,6 @@ void silk_find_pred_coefs_FLP( /* Create LTP residual */ silk_LTP_analysis_filter_FLP( LPC_in_pre, x - psEnc->sCmn.predictLPCOrder, psEncCtrl->LTPCoef, psEncCtrl->pitchL, invGains, psEnc->sCmn.subfr_length, psEnc->sCmn.nb_subfr, psEnc->sCmn.predictLPCOrder ); - } else { /************/ /* UNVOICED */ @@ -88,15 +88,20 @@ void silk_find_pred_coefs_FLP( x_pre_ptr += psEnc->sCmn.subfr_length + psEnc->sCmn.predictLPCOrder; x_ptr += psEnc->sCmn.subfr_length; } - silk_memset( psEncCtrl->LTPCoef, 0, psEnc->sCmn.nb_subfr * LTP_ORDER * sizeof( silk_float ) ); psEncCtrl->LTPredCodGain = 0.0f; } + /* Limit on total predictive coding gain */ + if( psEnc->sCmn.first_frame_after_reset ) { + minInvGain = 1.0f / MAX_PREDICTION_POWER_GAIN_AFTER_RESET; + } else { + minInvGain = (silk_float)powf( 2, psEncCtrl->LTPredCodGain / 3 ) / MAX_PREDICTION_POWER_GAIN; + minInvGain /= 0.1f + 0.9f * psEncCtrl->coding_quality; + } + /* LPC_in_pre contains the LTP-filtered input for voiced, and the unfiltered input for unvoiced */ - silk_find_LPC_FLP( NLSF_Q15, &psEnc->sCmn.indices.NLSFInterpCoef_Q2, psEnc->sCmn.prev_NLSFq_Q15, - psEnc->sCmn.useInterpolatedNLSFs, psEnc->sCmn.first_frame_after_reset, psEnc->sCmn.predictLPCOrder, - LPC_in_pre, psEnc->sCmn.subfr_length + psEnc->sCmn.predictLPCOrder, psEnc->sCmn.nb_subfr ); + silk_find_LPC_FLP( &psEnc->sCmn, NLSF_Q15, LPC_in_pre, minInvGain ); /* Quantize LSFs */ silk_process_NLSFs_FLP( &psEnc->sCmn, psEncCtrl->PredCoef, NLSF_Q15, psEnc->sCmn.prev_NLSFq_Q15 ); diff --git a/silk/float/main_FLP.h b/silk/float/main_FLP.h index d2889009..5107921b 100644 --- a/silk/float/main_FLP.h +++ b/silk/float/main_FLP.h @@ -143,15 +143,10 @@ void silk_find_pred_coefs_FLP( /* LPC analysis */ void silk_find_LPC_FLP( + silk_encoder_state *psEncC, /* I/O Encoder state */ opus_int16 NLSF_Q15[], /* O NLSFs */ - opus_int8 *interpIndex, /* O NLSF interp. index for NLSF interp. */ - const opus_int16 prev_NLSFq_Q15[], /* I Previous NLSFs, for NLSF interpolation */ - const opus_int useInterpNLSFs, /* I Flag */ - const opus_int firstFrameAfterReset, /* I Flag */ - const opus_int LPC_order, /* I LPC order */ const silk_float x[], /* I Input signal */ - const opus_int subfr_length, /* I Subframe length incl preceeding samples */ - const opus_int nb_subfr /* I Number of subframes */ + const silk_float minInvGain /* I Prediction gain from LTP (dB) */ ); /* LTP analysis */ diff --git a/silk/float/noise_shape_analysis_FLP.c b/silk/float/noise_shape_analysis_FLP.c index e19ff70a..d1f1a69c 100644 --- a/silk/float/noise_shape_analysis_FLP.c +++ b/silk/float/noise_shape_analysis_FLP.c @@ -151,7 +151,7 @@ void silk_noise_shape_analysis_FLP( psEncCtrl->input_quality = 0.5f * ( psEnc->sCmn.input_quality_bands_Q15[ 0 ] + psEnc->sCmn.input_quality_bands_Q15[ 1 ] ) * ( 1.0f / 32768.0f ); /* Coding quality level, between 0.0 and 1.0 */ - psEncCtrl->coding_quality = silk_sigmoid( 0.25f * ( SNR_adj_dB - 18.0f ) ); + psEncCtrl->coding_quality = silk_sigmoid( 0.25f * ( SNR_adj_dB - 20.0f ) ); if( psEnc->sCmn.useCBR == 0 ) { /* Reduce coding SNR during low speech activity */ @@ -274,8 +274,8 @@ void silk_noise_shape_analysis_FLP( silk_bwexpander_FLP( &psEncCtrl->AR1[ k * MAX_SHAPE_LPC_ORDER ], psEnc->sCmn.shapingLPCOrder, BWExp1 ); /* Ratio of prediction gains, in energy domain */ - silk_LPC_inverse_pred_gain_FLP( &pre_nrg, &psEncCtrl->AR2[ k * MAX_SHAPE_LPC_ORDER ], psEnc->sCmn.shapingLPCOrder ); - silk_LPC_inverse_pred_gain_FLP( &nrg, &psEncCtrl->AR1[ k * MAX_SHAPE_LPC_ORDER ], psEnc->sCmn.shapingLPCOrder ); + pre_nrg = silk_LPC_inverse_pred_gain_FLP( &psEncCtrl->AR2[ k * MAX_SHAPE_LPC_ORDER ], psEnc->sCmn.shapingLPCOrder ); + nrg = silk_LPC_inverse_pred_gain_FLP( &psEncCtrl->AR1[ k * MAX_SHAPE_LPC_ORDER ], psEnc->sCmn.shapingLPCOrder ); psEncCtrl->GainsPre[ k ] = 1.0f - 0.7f * ( 1.0f - pre_nrg / nrg ); /* Convert to monic warped prediction coefficients and limit absolute values */ diff --git a/silk/float/pitch_analysis_core_FLP.c b/silk/float/pitch_analysis_core_FLP.c index c7980035..5546d09b 100644 --- a/silk/float/pitch_analysis_core_FLP.c +++ b/silk/float/pitch_analysis_core_FLP.c @@ -115,7 +115,7 @@ opus_int silk_pitch_analysis_core_FLP( /* O Voicing estimate: 0 voiced, silk_assert( search_thres1 >= 0.0f && search_thres1 <= 1.0f ); silk_assert( search_thres2 >= 0.0f && search_thres2 <= 1.0f ); - /* Setup frame lengths max / min lag for the sampling frequency */ + /* Set up frame lengths max / min lag for the sampling frequency */ frame_length = ( PE_LTP_MEM_LENGTH_MS + nb_subfr * PE_SUBFR_LENGTH_MS ) * Fs_kHz; frame_length_4kHz = ( PE_LTP_MEM_LENGTH_MS + nb_subfr * PE_SUBFR_LENGTH_MS ) * 4; frame_length_8kHz = ( PE_LTP_MEM_LENGTH_MS + nb_subfr * PE_SUBFR_LENGTH_MS ) * 8; @@ -322,7 +322,7 @@ opus_int silk_pitch_analysis_core_FLP( /* O Voicing estimate: 0 voiced, prevLag_log2 = 0; } - /* Setup stage 2 codebook based on number of subframes */ + /* Set up stage 2 codebook based on number of subframes */ if( nb_subfr == PE_MAX_NB_SUBFR ) { cbk_size = PE_NB_CBKS_STAGE2_EXT; Lag_CB_ptr = &silk_CB_lags_stage2[ 0 ][ 0 ]; @@ -419,7 +419,7 @@ opus_int silk_pitch_analysis_core_FLP( /* O Voicing estimate: 0 voiced, silk_assert( lag == silk_SAT16( lag ) ); contour_bias = PE_FLATCONTOUR_BIAS / lag; - /* Setup cbk parameters acording to complexity setting and frame length */ + /* Set up cbk parameters acording to complexity setting and frame length */ if( nb_subfr == PE_MAX_NB_SUBFR ) { nb_cbk_search = (opus_int)silk_nb_cbk_searchs_stage3[ complexity ]; cbk_size = PE_NB_CBKS_STAGE3_MAX; diff --git a/silk/float/prefilter_FLP.c b/silk/float/prefilter_FLP.c index 3dcf7b53..79ebf65f 100644 --- a/silk/float/prefilter_FLP.c +++ b/silk/float/prefilter_FLP.c @@ -108,7 +108,7 @@ void silk_prefilter_FLP( silk_float HarmShapeFIR[ 3 ]; silk_float st_res[ MAX_SUB_FRAME_LENGTH + MAX_LPC_ORDER ]; - /* Setup pointers */ + /* Set up pointers */ px = x; pxw = xw; lag = P->lagPrev; diff --git a/silk/float/process_gains_FLP.c b/silk/float/process_gains_FLP.c index 020f847b..edac122e 100644 --- a/silk/float/process_gains_FLP.c +++ b/silk/float/process_gains_FLP.c @@ -64,7 +64,7 @@ void silk_process_gains_FLP( /* Prepare gains for noise shaping quantization */ for( k = 0; k < psEnc->sCmn.nb_subfr; k++ ) { - pGains_Q16[ k ] = ( opus_int32 ) ( psEncCtrl->Gains[ k ] * 65536.0f ); + pGains_Q16[ k ] = (opus_int32)( psEncCtrl->Gains[ k ] * 65536.0f ); } /* Save unquantized gains and gain Index */ diff --git a/silk/float/structs_FLP.h b/silk/float/structs_FLP.h index f56a972a..b879fd17 100644 --- a/silk/float/structs_FLP.h +++ b/silk/float/structs_FLP.h @@ -72,10 +72,6 @@ typedef struct { /* Buffer for find pitch and noise shape analysis */ silk_float x_buf[ 2 * MAX_FRAME_LENGTH + LA_SHAPE_MAX ];/* Buffer for find pitch and noise shape analysis */ silk_float LTPCorr; /* Normalized correlation from pitch lag estimator */ - - /* Parameters for LTP scaling control */ - silk_float prevLTPredCodGain; - silk_float HPLTPredCodGain; } silk_encoder_state_FLP; /************************/ diff --git a/silk/float/wrappers_FLP.c b/silk/float/wrappers_FLP.c index 9fd91477..ad9c2a59 100644 --- a/silk/float/wrappers_FLP.c +++ b/silk/float/wrappers_FLP.c @@ -102,7 +102,7 @@ void silk_NSQ_wrapper_FLP( ) { opus_int i, j; - opus_int16 x_16[ MAX_FRAME_LENGTH ]; + opus_int32 x_Q10[ MAX_FRAME_LENGTH ]; opus_int32 Gains_Q16[ MAX_NB_SUBFR ]; silk_DWORD_ALIGN opus_int16 PredCoef_Q12[ 2 ][ MAX_LPC_ORDER ]; opus_int16 LTPCoef_Q14[ LTP_ORDER * MAX_NB_SUBFR ]; @@ -133,12 +133,12 @@ void silk_NSQ_wrapper_FLP( /* prediction and coding parameters */ for( i = 0; i < psEnc->sCmn.nb_subfr * LTP_ORDER; i++ ) { - LTPCoef_Q14[ i ] = ( opus_int16 )silk_float2int( psEncCtrl->LTPCoef[ i ] * 16384.0f ); + LTPCoef_Q14[ i ] = (opus_int16)silk_float2int( psEncCtrl->LTPCoef[ i ] * 16384.0f ); } for( j = 0; j < 2; j++ ) { for( i = 0; i < psEnc->sCmn.predictLPCOrder; i++ ) { - PredCoef_Q12[ j ][ i ] = ( opus_int16 )silk_float2int( psEncCtrl->PredCoef[ j ][ i ] * 4096.0f ); + PredCoef_Q12[ j ][ i ] = (opus_int16)silk_float2int( psEncCtrl->PredCoef[ j ][ i ] * 4096.0f ); } } @@ -154,14 +154,16 @@ void silk_NSQ_wrapper_FLP( } /* Convert input to fix */ - silk_float2short_array( x_16, x, psEnc->sCmn.frame_length ); + for( i = 0; i < psEnc->sCmn.frame_length; i++ ) { + x_Q10[ i ] = silk_float2int( 1024.0 * x[ i ] ); + } /* Call NSQ */ if( psEnc->sCmn.nStatesDelayedDecision > 1 || psEnc->sCmn.warping_Q16 > 0 ) { - silk_NSQ_del_dec( &psEnc->sCmn, psNSQ, psIndices, x_16, pulses, PredCoef_Q12[ 0 ], LTPCoef_Q14, + silk_NSQ_del_dec( &psEnc->sCmn, psNSQ, psIndices, x_Q10, pulses, PredCoef_Q12[ 0 ], LTPCoef_Q14, AR2_Q13, HarmShapeGain_Q14, Tilt_Q14, LF_shp_Q14, Gains_Q16, psEncCtrl->pitchL, Lambda_Q10, LTP_scale_Q14 ); } else { - silk_NSQ( &psEnc->sCmn, psNSQ, psIndices, x_16, pulses, PredCoef_Q12[ 0 ], LTPCoef_Q14, + silk_NSQ( &psEnc->sCmn, psNSQ, psIndices, x_Q10, pulses, PredCoef_Q12[ 0 ], LTPCoef_Q14, AR2_Q13, HarmShapeGain_Q14, Tilt_Q14, LF_shp_Q14, Gains_Q16, psEncCtrl->pitchL, Lambda_Q10, LTP_scale_Q14 ); } } |