diff options
author | Koen Vos <koenvos@users.noreply.github.com> | 2016-06-02 21:19:16 +0800 |
---|---|---|
committer | Koen Vos <koenvos@users.noreply.github.com> | 2016-06-02 21:19:16 +0800 |
commit | c7deab77a95335312c2d4f66af0634d44bec2f37 (patch) | |
tree | 63d49b035bf9373ce4ae034d68043547a2c17a3e | |
parent | cce3d894215e16b6cc6abeb2cf194c771ac48a92 (diff) | |
download | opus-silk_lsf_quant_with_hysteresis.tar.gz |
bias in LSF quantization towards previously quantized LSFssilk_lsf_quant_with_hysteresis
-rw-r--r-- | silk/LPC_fit.c | 4 | ||||
-rw-r--r-- | silk/NLSF_del_dec_quant.c | 28 | ||||
-rw-r--r-- | silk/NLSF_encode.c | 311 | ||||
-rw-r--r-- | silk/main.h | 6 | ||||
-rw-r--r-- | silk/process_NLSFs.c | 2 | ||||
-rw-r--r-- | silk/tuning_parameters.h | 5 |
6 files changed, 205 insertions, 151 deletions
diff --git a/silk/LPC_fit.c b/silk/LPC_fit.c index cdea4f3a..ac68dedf 100644 --- a/silk/LPC_fit.c +++ b/silk/LPC_fit.c @@ -34,14 +34,14 @@ POSSIBILITY OF SUCH DAMAGE. /* Convert int32 coefficients to int16 coefs and make sure there's no wrap-around */ void silk_LPC_fit( opus_int16 *a_QOUT, /* O Output signal */ - opus_int32 *a_QIN, /* I/O Input signal */ + opus_int32 *a_QIN, /* I/O Input signal */ const opus_int QOUT, /* I Input Q domain */ const opus_int QIN, /* I Input Q domain */ const opus_int d /* I Filter order */ ) { opus_int i, k, idx = 0; - opus_int32 maxabs, absval, chirp_Q16; + opus_int32 maxabs, absval, chirp_Q16; /* Limit the maximum absolute value of the prediction coefficients, so that they'll fit in int16 */ for( i = 0; i < 10; i++ ) { diff --git a/silk/NLSF_del_dec_quant.c b/silk/NLSF_del_dec_quant.c index 3895749b..b541e1fc 100644 --- a/silk/NLSF_del_dec_quant.c +++ b/silk/NLSF_del_dec_quant.c @@ -32,8 +32,9 @@ POSSIBILITY OF SUCH DAMAGE. #include "main.h" /* Delayed-decision quantizer for NLSF residuals */ -opus_int32 silk_NLSF_del_dec_quant( /* O Returns RD value in Q25 */ - opus_int8 indices[], /* O Quantization indices [ order ] */ +void silk_NLSF_del_dec_quant(
+ opus_int32 RD_out_Q25[], /* O RD value in Q25 */ + opus_int8 indices[], /* O Quantization indices */ const opus_int16 x_Q10[], /* I Input [ order ] */ const opus_int16 w_Q5[], /* I Weights [ order ] */ const opus_uint8 pred_coef_Q8[], /* I Backward predictor coefs [ order ] */ @@ -47,7 +48,7 @@ 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_int32 RD_tmp_Q25, min_max_Q25, max_min_Q25, pred_coef_Q16; 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 ]; @@ -194,22 +195,7 @@ opus_int32 silk_NLSF_del_dec_quant( /* O Returns } } - /* last sample: find winner, copy indices and return RD value */ - ind_tmp = 0; - min_Q25 = silk_int32_MAX; - for( j = 0; j < 2 * NLSF_QUANT_DEL_DEC_STATES; j++ ) { - if( min_Q25 > RD_Q25[ j ] ) { - min_Q25 = RD_Q25[ j ]; - ind_tmp = j; - } - } - for( j = 0; j < order; j++ ) { - indices[ j ] = ind[ ind_tmp & ( NLSF_QUANT_DEL_DEC_STATES - 1 ) ][ j ]; - silk_assert( indices[ j ] >= -NLSF_QUANT_MAX_AMPLITUDE_EXT ); - silk_assert( indices[ j ] <= NLSF_QUANT_MAX_AMPLITUDE_EXT ); - } - indices[ 0 ] += silk_RSHIFT( ind_tmp, NLSF_QUANT_DEL_DEC_STATES_LOG2 ); - silk_assert( indices[ 0 ] <= NLSF_QUANT_MAX_AMPLITUDE_EXT ); - silk_assert( min_Q25 >= 0 ); - return min_Q25; + /* copy indices and RD values */ + silk_memcpy( indices, ind, NLSF_QUANT_DEL_DEC_STATES * MAX_LPC_ORDER * sizeof( opus_int8 ) ); + silk_memcpy( RD_out_Q25, RD_Q25, NLSF_QUANT_DEL_DEC_STATES * sizeof( opus_int32 ) ); } diff --git a/silk/NLSF_encode.c b/silk/NLSF_encode.c index 268b9a19..e0768ae5 100644 --- a/silk/NLSF_encode.c +++ b/silk/NLSF_encode.c @@ -1,124 +1,187 @@ -/*********************************************************************** -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. -***********************************************************************/ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include "main.h" -#include "stack_alloc.h" - -/***********************/ -/* NLSF vector encoder */ -/***********************/ -opus_int32 silk_NLSF_encode( /* O Returns RD value in Q25 */ - opus_int8 *NLSFIndices, /* I Codebook path vector [ LPC_ORDER + 1 ] */ - opus_int16 *pNLSF_Q15, /* I/O (Un)quantized NLSF vector [ LPC_ORDER ] */ - const silk_NLSF_CB_struct *psNLSF_CB, /* I Codebook object */ - const opus_int16 *pW_Q2, /* I NLSF weight vector [ LPC_ORDER ] */ - const opus_int NLSF_mu_Q20, /* I Rate weight for the RD optimization */ - const opus_int nSurvivors, /* I Max survivors after first stage */ - const opus_int signalType /* I Signal type: 0/1/2 */ -) -{ - opus_int i, s, ind1, bestIndex, prob_Q8, bits_q7; - opus_int32 W_tmp_Q9, ret; - VARDECL( opus_int32, err_Q24 ); - VARDECL( opus_int32, RD_Q25 ); - VARDECL( opus_int, tempIndices1 ); - VARDECL( opus_int8, tempIndices2 ); - opus_int16 res_Q10[ MAX_LPC_ORDER ]; - opus_int16 NLSF_tmp_Q15[ MAX_LPC_ORDER ]; - opus_int16 W_adj_Q5[ MAX_LPC_ORDER ]; - opus_uint8 pred_Q8[ MAX_LPC_ORDER ]; - opus_int16 ec_ix[ MAX_LPC_ORDER ]; - const opus_uint8 *pCB_element, *iCDF_ptr; - const opus_int16 *pCB_Wght_Q9; - SAVE_STACK; - - silk_assert( signalType >= 0 && signalType <= 2 ); - silk_assert( NLSF_mu_Q20 <= 32767 && NLSF_mu_Q20 >= 0 ); - - /* NLSF stabilization */ - silk_NLSF_stabilize( pNLSF_Q15, psNLSF_CB->deltaMin_Q15, psNLSF_CB->order ); - - /* First stage: VQ */ - ALLOC( err_Q24, psNLSF_CB->nVectors, opus_int32 ); - silk_NLSF_VQ( err_Q24, pNLSF_Q15, psNLSF_CB->CB1_NLSF_Q8, psNLSF_CB->CB1_Wght_Q9, psNLSF_CB->nVectors, psNLSF_CB->order ); - - /* Sort the quantization errors */ - ALLOC( tempIndices1, nSurvivors, opus_int ); - silk_insertion_sort_increasing( err_Q24, tempIndices1, psNLSF_CB->nVectors, nSurvivors ); - - ALLOC( RD_Q25, nSurvivors, opus_int32 ); - ALLOC( tempIndices2, nSurvivors * MAX_LPC_ORDER, opus_int8 ); - - /* Loop over survivors */ - for( s = 0; s < nSurvivors; s++ ) { - ind1 = tempIndices1[ s ]; - - /* Residual after first stage */ - pCB_element = &psNLSF_CB->CB1_NLSF_Q8[ ind1 * psNLSF_CB->order ]; - pCB_Wght_Q9 = &psNLSF_CB->CB1_Wght_Q9[ ind1 * psNLSF_CB->order ]; - for( i = 0; i < psNLSF_CB->order; i++ ) { - NLSF_tmp_Q15[ i ] = silk_LSHIFT16( (opus_int16)pCB_element[ i ], 7 ); - W_tmp_Q9 = pCB_Wght_Q9[ i ]; - res_Q10[ i ] = (opus_int16)silk_RSHIFT( silk_SMULBB( pNLSF_Q15[ i ] - NLSF_tmp_Q15[ i ], W_tmp_Q9 ), 14 ); - W_adj_Q5[ i ] = silk_DIV32_varQ( (opus_int32)pW_Q2[ i ], silk_SMULBB( W_tmp_Q9, W_tmp_Q9 ), 21 ); - } - - /* Unpack entropy table indices and predictor for current CB1 index */ - silk_NLSF_unpack( ec_ix, pred_Q8, psNLSF_CB, ind1 ); - - /* Trellis quantizer */ - RD_Q25[ s ] = silk_NLSF_del_dec_quant( &tempIndices2[ s * MAX_LPC_ORDER ], res_Q10, W_adj_Q5, pred_Q8, ec_ix, - psNLSF_CB->ec_Rates_Q5, psNLSF_CB->quantStepSize_Q16, psNLSF_CB->invQuantStepSize_Q6, NLSF_mu_Q20, psNLSF_CB->order ); - - /* Add rate for first stage */ - iCDF_ptr = &psNLSF_CB->CB1_iCDF[ ( signalType >> 1 ) * psNLSF_CB->nVectors ]; - if( ind1 == 0 ) { - prob_Q8 = 256 - iCDF_ptr[ ind1 ]; - } else { - prob_Q8 = iCDF_ptr[ ind1 - 1 ] - iCDF_ptr[ ind1 ]; - } - bits_q7 = ( 8 << 7 ) - silk_lin2log( prob_Q8 ); - RD_Q25[ s ] = silk_SMLABB( RD_Q25[ s ], bits_q7, silk_RSHIFT( NLSF_mu_Q20, 2 ) ); - } - - /* Find the lowest rate-distortion error */ - silk_insertion_sort_increasing( RD_Q25, &bestIndex, nSurvivors, 1 ); - - NLSFIndices[ 0 ] = (opus_int8)tempIndices1[ bestIndex ]; - silk_memcpy( &NLSFIndices[ 1 ], &tempIndices2[ bestIndex * MAX_LPC_ORDER ], psNLSF_CB->order * sizeof( opus_int8 ) ); - - /* Decode */ - silk_NLSF_decode( pNLSF_Q15, NLSFIndices, psNLSF_CB ); - - ret = RD_Q25[ 0 ]; - RESTORE_STACK; - return ret; -} +/***********************************************************************
+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.
+***********************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "main.h"
+#include "tuning_parameters.h"
+#include "stack_alloc.h"
+
+/***********************/
+/* NLSF vector encoder */
+/***********************/
+opus_int32 silk_NLSF_encode( /* O Returns RD value in Q25 */
+ opus_int8 *NLSFIndices, /* I Codebook path vector [ LPC_ORDER + 1 ] */
+ opus_int16 *pNLSF_Q15, /* I/O (Un)quantized NLSF vector [ LPC_ORDER ] */
+ const silk_NLSF_CB_struct *psNLSF_CB, /* I Codebook object */
+ const opus_int16 *pW_Q2, /* I NLSF weight vector [ LPC_ORDER ] */
+ const opus_int16 *pNLSF_Q15_prev, /* I Previous Quantized NLSFs[ LPC_ORDER ] */
+ const opus_int NLSF_mu_Q20, /* I Rate weight for the RD optimization */
+ const opus_int nSurvivors, /* I Max survivors after first stage */
+ const opus_int signalType /* I Signal type: 0/1/2 */
+)
+{
+ opus_int i, s, ind1, prob_Q8, bits_q7;
+ opus_int32 W_tmp_Q9, R_Q25, ret;
+ VARDECL( opus_int32, err_Q24 );
+ VARDECL( opus_int32, RD_Q25 );
+ VARDECL( opus_int, tempIndices1 );
+ VARDECL( opus_int8, tempIndices2 );
+ VARDECL( opus_int, tempIndices3 );
+ opus_int16 res_Q10[ MAX_LPC_ORDER ];
+ opus_int16 NLSF_tmp_Q15[ MAX_LPC_ORDER ];
+ opus_int16 W_adj_Q5[ MAX_LPC_ORDER ];
+ opus_uint8 pred_Q8[ MAX_LPC_ORDER ];
+ opus_int16 ec_ix[ MAX_LPC_ORDER ];
+ const opus_uint8 *pCB_element, *iCDF_ptr;
+ const opus_int16 *pCB_Wght_Q9;
+ SAVE_STACK;
+
+ silk_assert( signalType >= 0 && signalType <= 2 );
+ silk_assert( NLSF_mu_Q20 <= 32767 && NLSF_mu_Q20 >= 0 );
+
+ /* NLSF stabilization */
+ silk_NLSF_stabilize( pNLSF_Q15, psNLSF_CB->deltaMin_Q15, psNLSF_CB->order );
+
+ /* First stage: VQ */
+ ALLOC( err_Q24, psNLSF_CB->nVectors, opus_int32 );
+ silk_NLSF_VQ( err_Q24, pNLSF_Q15, psNLSF_CB->CB1_NLSF_Q8, psNLSF_CB->CB1_Wght_Q9, psNLSF_CB->nVectors, psNLSF_CB->order );
+
+ /* Sort the quantization errors */
+ ALLOC( tempIndices1, nSurvivors, opus_int );
+ silk_insertion_sort_increasing( err_Q24, tempIndices1, psNLSF_CB->nVectors, nSurvivors );
+
+ ALLOC( RD_Q25, nSurvivors * NLSF_QUANT_DEL_DEC_STATES, opus_int32 );
+ ALLOC( tempIndices2, nSurvivors * NLSF_QUANT_DEL_DEC_STATES * MAX_LPC_ORDER, opus_int8 );
+
+ /* Loop over survivors */
+ for( s = 0; s < nSurvivors; s++ ) {
+ ind1 = tempIndices1[ s ];
+
+ /* Residual after first stage */
+ pCB_element = &psNLSF_CB->CB1_NLSF_Q8[ ind1 * psNLSF_CB->order ];
+ pCB_Wght_Q9 = &psNLSF_CB->CB1_Wght_Q9[ ind1 * psNLSF_CB->order ];
+ for( i = 0; i < psNLSF_CB->order; i++ ) {
+ NLSF_tmp_Q15[ i ] = silk_LSHIFT16( (opus_int16)pCB_element[ i ], 7 );
+ W_tmp_Q9 = pCB_Wght_Q9[ i ];
+ res_Q10[ i ] = (opus_int16)silk_RSHIFT( silk_SMULBB( pNLSF_Q15[ i ] - NLSF_tmp_Q15[ i ], W_tmp_Q9 ), 14 );
+ W_adj_Q5[ i ] = silk_DIV32_varQ( (opus_int32)pW_Q2[ i ], silk_SMULBB( W_tmp_Q9, W_tmp_Q9 ), 21 );
+ }
+
+ /* Unpack entropy table indices and predictor for current CB1 index */
+ silk_NLSF_unpack( ec_ix, pred_Q8, psNLSF_CB, ind1 );
+
+ /* Trellis quantizer */
+ silk_NLSF_del_dec_quant( &RD_Q25[ s * NLSF_QUANT_DEL_DEC_STATES ], &tempIndices2[ s * NLSF_QUANT_DEL_DEC_STATES * MAX_LPC_ORDER ], res_Q10,
+ W_adj_Q5, pred_Q8, ec_ix, psNLSF_CB->ec_Rates_Q5, psNLSF_CB->quantStepSize_Q16, psNLSF_CB->invQuantStepSize_Q6, NLSF_mu_Q20, psNLSF_CB->order );
+
+ /* Add rate for first stage */
+ iCDF_ptr = &psNLSF_CB->CB1_iCDF[ ( signalType >> 1 ) * psNLSF_CB->nVectors ];
+ if( ind1 == 0 ) {
+ prob_Q8 = 256 - iCDF_ptr[ ind1 ];
+ } else {
+ prob_Q8 = iCDF_ptr[ ind1 - 1 ] - iCDF_ptr[ ind1 ];
+ }
+ bits_q7 = ( 8 << 7 ) - silk_lin2log( prob_Q8 );
+ R_Q25 = silk_SMULBB( bits_q7, silk_RSHIFT( NLSF_mu_Q20, 2 ) );
+ for( i = 0; i < NLSF_QUANT_DEL_DEC_STATES; i++ ) {
+ RD_Q25[ s * NLSF_QUANT_DEL_DEC_STATES + i ] = silk_ADD32( RD_Q25[ s * NLSF_QUANT_DEL_DEC_STATES + i ], R_Q25 );
+ }
+ }
+
+ /* Find the lowest rate-distortion error */
+ opus_int nSurvivors2 = nSurvivors;
+ ALLOC( tempIndices3, nSurvivors2, opus_int );
+ silk_insertion_sort_increasing( RD_Q25, tempIndices3, nSurvivors * NLSF_QUANT_DEL_DEC_STATES, nSurvivors2 );
+
+ /* Loop over final survivors and copy indices */
+ if( nSurvivors2 > 1 ) {
+ /* Bias quantizer towards previous quantized coefficients */
+ opus_int16 pNLSF_Q15_best[ MAX_LPC_ORDER ];
+ opus_int8 NLSFIndices_tmp[ MAX_LPC_ORDER + 1 ];
+ opus_int16 pNLSF_Q15_tmp[ MAX_LPC_ORDER ];
+ opus_int32 RD_Q25_best = silk_int32_MAX;
+ opus_int32 pNLSF_Q15_diff[ MAX_LPC_ORDER ], pNLSF_Q15_err[ MAX_LPC_ORDER ];
+ opus_int32 sum_sqrd_Q22_prev, sum_sqrd_Q22, inv_norm_Q16, inner_prod_Q26, adj_Q16;
+ opus_int64 acc;
+ acc = 0;
+ for( i = 0; i < psNLSF_CB->order; i++ ) {
+ pNLSF_Q15_diff[ i ] = pNLSF_Q15[ i ] - pNLSF_Q15_prev[ i ];
+ acc += (opus_int64)silk_MUL( pNLSF_Q15_diff[ i ], pNLSF_Q15_diff[ i ] ) * pW_Q2[ i ];
+ }
+ sum_sqrd_Q22_prev = (opus_int32)silk_RSHIFT64( acc, 10 );
+ silk_assert( sum_sqrd_Q22_prev >= 0 );
+ inv_norm_Q16 = silk_INVERSE32_varQ( silk_SQRT_APPROX(sum_sqrd_Q22_prev + 1), 24 );
+ for( i = 0; i < psNLSF_CB->order; i++ ) {
+ pNLSF_Q15_diff[ i ] = silk_SMULWW( inv_norm_Q16, pNLSF_Q15_diff[ i ] );
+ }
+ for( s = 0; s < nSurvivors2; s++ ) {
+ NLSFIndices_tmp[ 0 ] = (opus_int8)tempIndices1[ tempIndices3[ s ] >> NLSF_QUANT_DEL_DEC_STATES_LOG2 ];
+ silk_memcpy( &NLSFIndices_tmp[ 1 ], &tempIndices2[ tempIndices3[ s ] * MAX_LPC_ORDER ], psNLSF_CB->order * sizeof( opus_int8 ) );
+ silk_NLSF_decode( pNLSF_Q15_tmp, NLSFIndices_tmp, psNLSF_CB );
+ acc = 0;
+ for( i = 0; i < psNLSF_CB->order; i++ ) {
+ pNLSF_Q15_err[ i ] = pNLSF_Q15[ i ] - pNLSF_Q15_tmp[ i ];
+ acc += (opus_int64)silk_MUL( pNLSF_Q15_err[ i ], pNLSF_Q15_err[ i ] ) * pW_Q2[ i ];
+ }
+ sum_sqrd_Q22 = (opus_int32)silk_RSHIFT64( acc, 10 );
+ silk_assert( sum_sqrd_Q22 >= 0 );
+ inv_norm_Q16 = silk_INVERSE32_varQ( silk_SQRT_APPROX(sum_sqrd_Q22 + 1), 24 );
+
+ /* compute normalized inner product between quantization error and (difference between unquantized LSFs and previous quantized ones) */
+ inner_prod_Q26 = 0;
+ for( i = 0; i < psNLSF_CB->order; i++ ) {
+ pNLSF_Q15_err[ i ] = silk_SMULWW( inv_norm_Q16, pNLSF_Q15_err[ i ] );
+ inner_prod_Q26 += pNLSF_Q15_err[ i ] * pNLSF_Q15_diff[ i ] * pW_Q2[ i ];
+ }
+ if( sum_sqrd_Q22_prev < sum_sqrd_Q22 ) {
+ inner_prod_Q26 = ( (opus_int64)inner_prod_Q26 * sum_sqrd_Q22_prev ) / sum_sqrd_Q22;
+ }
+ /* reduce RD value if quantization error is towards previous quantized LSFs; increase on the other side */
+ adj_Q16 = silk_SMULWB( inner_prod_Q26, SILK_FIX_CONST(-LSF_QUANT_BIAS_TO_PREVIOUS, 6) );
+ RD_Q25[ s ] = silk_SMLAWW( RD_Q25[ s ], RD_Q25[ s ], adj_Q16 );
+
+ if( RD_Q25[ s ] <= RD_Q25_best ) {
+ RD_Q25_best = RD_Q25[ s ];
+ silk_memcpy( NLSFIndices, NLSFIndices_tmp, ( psNLSF_CB->order + 1 ) * sizeof( opus_int8 ) );
+ silk_memcpy( pNLSF_Q15_best, pNLSF_Q15_tmp, psNLSF_CB->order * sizeof( opus_int16 ) );
+ }
+ }
+ silk_memcpy( pNLSF_Q15, pNLSF_Q15_best, psNLSF_CB->order * sizeof( opus_int16 ) );
+ ret = RD_Q25_best;
+ } else {
+ NLSFIndices[ 0 ] = (opus_int8)tempIndices1[ tempIndices3[ 0 ] >> NLSF_QUANT_DEL_DEC_STATES_LOG2 ];
+ silk_memcpy( &NLSFIndices[ 1 ], &tempIndices2[ tempIndices3[ 0 ] * MAX_LPC_ORDER ], psNLSF_CB->order * sizeof( opus_int8 ) );
+ silk_NLSF_decode( pNLSF_Q15, NLSFIndices, psNLSF_CB );
+ ret = RD_Q25[ 0 ];
+ }
+
+ RESTORE_STACK;
+ return ret;
+}
diff --git a/silk/main.h b/silk/main.h index 94315b47..0587c0e3 100644 --- a/silk/main.h +++ b/silk/main.h @@ -332,6 +332,7 @@ opus_int32 silk_NLSF_encode( /* O Returns opus_int16 *pNLSF_Q15, /* I/O Quantized NLSF vector [ LPC_ORDER ] */ const silk_NLSF_CB_struct *psNLSF_CB, /* I Codebook object */ const opus_int16 *pW_QW, /* I NLSF weight vector [ LPC_ORDER ] */ + const opus_int16 *pNLSF_Q15_prev, /* I Prevoius quantized NLSFs [ LPC_ORDER ] */ const opus_int NLSF_mu_Q20, /* I Rate weight for the RD optimization */ const opus_int nSurvivors, /* I Max survivors after first stage */ const opus_int signalType /* I Signal type: 0/1/2 */ @@ -348,8 +349,9 @@ void silk_NLSF_VQ( ); /* Delayed-decision quantizer for NLSF residuals */ -opus_int32 silk_NLSF_del_dec_quant( /* O Returns RD value in Q25 */ - opus_int8 indices[], /* O Quantization indices [ order ] */ +void silk_NLSF_del_dec_quant( + opus_int32 RD_out_Q25[], /* O RD value in Q25 */ + opus_int8 indices[], /* O Quantization indices */ const opus_int16 x_Q10[], /* I Input [ order ] */ const opus_int16 w_Q5[], /* I Weights [ order ] */ const opus_uint8 pred_coef_Q8[], /* I Backward predictor coefs [ order ] */ diff --git a/silk/process_NLSFs.c b/silk/process_NLSFs.c index c27cf030..3ca2ddde 100644 --- a/silk/process_NLSFs.c +++ b/silk/process_NLSFs.c @@ -84,7 +84,7 @@ void silk_process_NLSFs( } } - silk_NLSF_encode( psEncC->indices.NLSFIndices, pNLSF_Q15, psEncC->psNLSF_CB, pNLSFW_QW, + silk_NLSF_encode( psEncC->indices.NLSFIndices, pNLSF_Q15, psEncC->psNLSF_CB, pNLSFW_QW, prev_NLSFq_Q15, NLSF_mu_Q20, psEncC->NLSF_MSVQ_Survivors, psEncC->indices.signalType ); /* Convert quantized NLSFs back to LPC coefficients */ diff --git a/silk/tuning_parameters.h b/silk/tuning_parameters.h index cbf68bac..22a2df1f 100644 --- a/silk/tuning_parameters.h +++ b/silk/tuning_parameters.h @@ -50,7 +50,7 @@ extern "C" /* Linear prediction */ /*********************/ -/* LPC analysis defines: regularization and bandwidth expansion */ +/* LPC analysis regularization */ #define FIND_LPC_COND_FAC 1e-5f /***********************/ @@ -128,6 +128,9 @@ extern "C" /* subframe smoothing coefficient for HarmBoost, HarmShapeGain, Tilt (lower -> more smoothing) */ #define SUBFR_SMTH_COEF 0.4f +/* bias in LSF quantization towards previous quantized LSFs (0.0...1.0) */ +#define LSF_QUANT_BIAS_TO_PREVIOUS 0.3f + /* parameters defining the R/D tradeoff in the residual quantizer */ #define LAMBDA_OFFSET 1.2f #define LAMBDA_SPEECH_ACT -0.2f |