Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/xiph/opus.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKoen Vos <koen.vos@skype.net>2011-12-13 23:47:31 +0400
committerJean-Marc Valin <jmvalin@jmvalin.ca>2011-12-13 23:47:31 +0400
commitbf75c8ec4d0dded188bc7793de6da56c7ff0be1c (patch)
treec21bb05faf0a203b73e8f8aae90fc63dac27625d /silk/float
parent6619a736376221f2782cecff55d051c3ecfc2ff7 (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.c17
-rw-r--r--silk/float/LTP_scale_ctrl_FLP.c11
-rw-r--r--silk/float/SigProc_FLP.h5
-rw-r--r--silk/float/burg_modified_FLP.c78
-rw-r--r--silk/float/encode_frame_FLP.c6
-rw-r--r--silk/float/find_LPC_FLP.c65
-rw-r--r--silk/float/find_pitch_lags_FLP.c2
-rw-r--r--silk/float/find_pred_coefs_FLP.c15
-rw-r--r--silk/float/main_FLP.h9
-rw-r--r--silk/float/noise_shape_analysis_FLP.c6
-rw-r--r--silk/float/pitch_analysis_core_FLP.c6
-rw-r--r--silk/float/prefilter_FLP.c2
-rw-r--r--silk/float/process_gains_FLP.c2
-rw-r--r--silk/float/structs_FLP.h4
-rw-r--r--silk/float/wrappers_FLP.c14
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 );
}
}