From ae2311455b1bb5e0415a11d8add55e56bf0e9880 Mon Sep 17 00:00:00 2001 From: Gregory Maxwell <greg@xiph.org> Date: Sat, 30 Jul 2011 08:18:48 -0400 Subject: [PATCH] Convert all CRLF in the SILK code, tabs to spaces, and trailing whitespace. --- silk/fixed/silk_LTP_analysis_filter_FIX.c | 162 +- silk/fixed/silk_LTP_scale_ctrl_FIX.c | 104 +- silk/fixed/silk_corrMatrix_FIX.c | 304 ++-- silk/fixed/silk_encode_frame_FIX.c | 602 +++---- silk/fixed/silk_find_LPC_FIX.c | 314 ++-- silk/fixed/silk_find_LTP_FIX.c | 482 +++--- silk/fixed/silk_find_pitch_lags_FIX.c | 266 +-- silk/fixed/silk_find_pred_coefs_FIX.c | 254 +-- silk/fixed/silk_main_FIX.h | 508 +++--- silk/fixed/silk_noise_shape_analysis_FIX.c | 874 +++++----- silk/fixed/silk_prefilter_FIX.c | 402 ++--- silk/fixed/silk_process_gains_FIX.c | 216 +-- silk/fixed/silk_regularize_correlations_FIX.c | 86 +- silk/fixed/silk_residual_energy16_FIX.c | 198 +-- silk/fixed/silk_residual_energy_FIX.c | 174 +- silk/fixed/silk_solve_LS_FIX.c | 482 +++--- silk/fixed/silk_structs_FIX.h | 264 +-- silk/fixed/silk_warped_autocorrelation_FIX.c | 168 +- silk/float/silk_LPC_analysis_filter_FLP.c | 572 +++---- silk/float/silk_LPC_inv_pred_gain_FLP.c | 146 +- silk/float/silk_LTP_analysis_filter_FLP.c | 142 +- silk/float/silk_LTP_scale_ctrl_FLP.c | 104 +- silk/float/silk_SigProc_FLP.h | 438 ++--- silk/float/silk_apply_sine_window_FLP.c | 154 +- silk/float/silk_autocorrelation_FLP.c | 96 +- silk/float/silk_burg_modified_FLP.c | 288 ++-- silk/float/silk_bwexpander_FLP.c | 94 +- silk/float/silk_corrMatrix_FLP.c | 178 +- silk/float/silk_encode_frame_FLP.c | 542 +++--- silk/float/silk_energy_FLP.c | 112 +- silk/float/silk_find_LPC_FLP.c | 218 +-- silk/float/silk_find_LTP_FLP.c | 256 +-- silk/float/silk_find_pitch_lags_FLP.c | 254 +-- silk/float/silk_find_pred_coefs_FLP.c | 226 +-- silk/float/silk_inner_product_FLP.c | 112 +- silk/float/silk_k2a_FLP.c | 98 +- silk/float/silk_levinsondurbin_FLP.c | 154 +- silk/float/silk_main_FLP.h | 652 ++++---- silk/float/silk_noise_shape_analysis_FLP.c | 718 ++++---- silk/float/silk_pitch_analysis_core_FLP.c | 1264 +++++++------- silk/float/silk_prefilter_FLP.c | 404 ++--- silk/float/silk_process_gains_FLP.c | 188 +-- silk/float/silk_regularize_correlations_FLP.c | 86 +- silk/float/silk_residual_energy_FLP.c | 226 +-- silk/float/silk_scale_copy_vector_FLP.c | 106 +- silk/float/silk_scale_vector_FLP.c | 104 +- silk/float/silk_schur_FLP.c | 128 +- silk/float/silk_solve_LS_FLP.c | 406 ++--- silk/float/silk_sort_FLP.c | 158 +- silk/float/silk_structs_FLP.h | 258 +-- silk/float/silk_warped_autocorrelation_FLP.c | 138 +- silk/float/silk_wrappers_FLP.c | 388 ++--- silk/silk_A2NLSF.c | 560 +++---- silk/silk_API.h | 276 +-- silk/silk_CNG.c | 312 ++-- silk/silk_HP_variable_cutoff.c | 250 +-- silk/silk_Inlines.h | 370 ++-- silk/silk_LPC_analysis_filter.c | 158 +- silk/silk_LPC_inv_pred_gain.c | 292 ++-- silk/silk_LP_variable_cutoff.c | 264 +-- silk/silk_MacroCount.h | 1438 ++++++++-------- silk/silk_MacroDebug.h | 1118 ++++++------- silk/silk_NLSF2A.c | 342 ++-- silk/silk_NLSF_VQ.c | 128 +- silk/silk_NLSF_VQ_weights_laroia.c | 152 +- silk/silk_NLSF_decode.c | 194 +-- silk/silk_NLSF_del_dec_quant.c | 402 ++--- silk/silk_NLSF_encode.c | 366 ++-- silk/silk_NLSF_stabilize.c | 276 +-- silk/silk_NLSF_unpack.c | 102 +- silk/silk_NSQ.c | 854 +++++----- silk/silk_NSQ_del_dec.c | 1360 +++++++-------- silk/silk_PLC.c | 782 ++++----- silk/silk_PLC.h | 158 +- silk/silk_SigProc_FIX.h | 1234 +++++++------- silk/silk_VAD.c | 642 +++---- silk/silk_VQ_WMat_EC.c | 214 +-- silk/silk_ana_filt_bank_1.c | 142 +- silk/silk_apply_sine_window.c | 194 +-- silk/silk_array_maxabs.c | 120 +- silk/silk_autocorr.c | 144 +- silk/silk_biquad_alt.c | 146 +- silk/silk_burg_modified.c | 436 ++--- silk/silk_bwexpander.c | 94 +- silk/silk_bwexpander_32.c | 92 +- silk/silk_check_control_input.c | 204 +-- silk/silk_code_signs.c | 222 +-- silk/silk_control.h | 252 +-- silk/silk_control_SNR.c | 154 +- silk/silk_control_audio_bandwidth.c | 212 +-- silk/silk_control_codec.c | 842 +++++----- silk/silk_create_init_destroy.c | 106 +- silk/silk_debug.c | 332 ++-- silk/silk_debug.h | 622 +++---- silk/silk_dec_API.c | 594 +++---- silk/silk_decode_core.c | 448 ++--- silk/silk_decode_frame.c | 267 ++- silk/silk_decode_indices.c | 306 ++-- silk/silk_decode_parameters.c | 222 +-- silk/silk_decode_pitch.c | 144 +- silk/silk_decode_pulses.c | 218 +-- silk/silk_decoder_set_fs.c | 186 +-- silk/silk_define.h | 474 +++--- silk/silk_enc_API.c | 824 ++++----- silk/silk_encode_indices.c | 492 +++--- silk/silk_encode_pulses.c | 390 ++--- silk/silk_errors.h | 196 +-- silk/silk_gain_quant.c | 238 +-- silk/silk_init_encoder.c | 122 +- silk/silk_inner_prod_aligned.c | 154 +- silk/silk_interpolate.c | 94 +- silk/silk_k2a.c | 98 +- silk/silk_k2a_Q16.c | 98 +- silk/silk_lin2log.c | 80 +- silk/silk_log2lin.c | 100 +- silk/silk_macros.h | 264 +-- silk/silk_main.h | 892 +++++----- silk/silk_pitch_analysis_core.c | 1488 ++++++++--------- silk/silk_pitch_est_defines.h | 174 +- silk/silk_pitch_est_tables.c | 190 +-- silk/silk_process_NLSFs.c | 206 +-- silk/silk_quant_LTP_gains.c | 214 +-- silk/silk_resampler.c | 628 +++---- silk/silk_resampler_down2.c | 140 +- silk/silk_resampler_down2_3.c | 188 +-- silk/silk_resampler_down3.c | 170 +- silk/silk_resampler_private.h | 242 +-- silk/silk_resampler_private_AR2.c | 102 +- silk/silk_resampler_private_ARMA4.c | 142 +- silk/silk_resampler_private_IIR_FIR.c | 194 +-- silk/silk_resampler_private_copy.c | 80 +- silk/silk_resampler_private_down4.c | 138 +- silk/silk_resampler_private_down_FIR.c | 316 ++-- silk/silk_resampler_private_up2_HQ.c | 218 +-- silk/silk_resampler_private_up4.c | 146 +- silk/silk_resampler_rom.c | 516 +++--- silk/silk_resampler_rom.h | 158 +- silk/silk_resampler_structs.h | 140 +- silk/silk_resampler_up2.c | 134 +- silk/silk_scale_copy_vector16.c | 90 +- silk/silk_scale_vector.c | 84 +- silk/silk_schur.c | 172 +- silk/silk_schur64.c | 142 +- silk/silk_shell_coder.c | 294 ++-- silk/silk_sigm_Q15.c | 140 +- silk/silk_sort.c | 294 ++-- silk/silk_stereo_LR_to_MS.c | 354 ++-- silk/silk_stereo_MS_to_LR.c | 162 +- silk/silk_stereo_decode_pred.c | 126 +- silk/silk_stereo_encode_pred.c | 102 +- silk/silk_stereo_find_predictor.c | 138 +- silk/silk_stereo_quant_pred.c | 140 +- silk/silk_structs.h | 654 ++++---- silk/silk_sum_sqr_shift.c | 162 +- silk/silk_table_LSF_cos.c | 132 +- silk/silk_tables.h | 240 +-- silk/silk_tables_LTP.c | 536 +++--- silk/silk_tables_NLSF_CB_NB_MB.c | 310 ++-- silk/silk_tables_NLSF_CB_WB.c | 388 ++--- silk/silk_tables_gain.c | 118 +- silk/silk_tables_other.c | 268 +-- silk/silk_tables_pitch_lag.c | 130 +- silk/silk_tables_pulses_per_block.c | 518 +++--- silk/silk_tuning_parameters.h | 340 ++-- silk/silk_typedef.h | 178 +- 165 files changed, 25431 insertions(+), 25432 deletions(-) diff --git a/silk/fixed/silk_LTP_analysis_filter_FIX.c b/silk/fixed/silk_LTP_analysis_filter_FIX.c index e4664deee..9c46ab600 100644 --- a/silk/fixed/silk_LTP_analysis_filter_FIX.c +++ b/silk/fixed/silk_LTP_analysis_filter_FIX.c @@ -1,81 +1,81 @@ -/*********************************************************************** -Copyright (c) 2006-2011, Skype Limited. All rights reserved. -Redistribution and use in source and binary forms, with or without -modification, (subject to the limitations in the disclaimer below) -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 Skype Limited, nor the names of specific -contributors, may be used to endorse or promote products derived from -this software without specific prior written permission. -NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED -BY THIS LICENSE. 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. -***********************************************************************/ - -#include "silk_main_FIX.h" - -void silk_LTP_analysis_filter_FIX( - opus_int16 *LTP_res, /* O: LTP residual signal of length MAX_NB_SUBFR * ( pre_length + subfr_length ) */ - const opus_int16 *x, /* I: Pointer to input signal with at least max( pitchL ) preceeding samples */ - const opus_int16 LTPCoef_Q14[ LTP_ORDER * MAX_NB_SUBFR ],/* I: LTP_ORDER LTP coefficients for each MAX_NB_SUBFR subframe */ - const opus_int pitchL[ MAX_NB_SUBFR ], /* I: Pitch lag, one for each subframe */ - const opus_int32 invGains_Q16[ MAX_NB_SUBFR ], /* I: Inverse quantization gains, one for each subframe */ - const opus_int subfr_length, /* I: Length of each subframe */ - const opus_int nb_subfr, /* I: Number of subframes */ - const opus_int pre_length /* I: Length of the preceeding samples starting at &x[0] for each subframe */ -) -{ - const opus_int16 *x_ptr, *x_lag_ptr; - opus_int16 Btmp_Q14[ LTP_ORDER ]; - opus_int16 *LTP_res_ptr; - opus_int k, i, j; - opus_int32 LTP_est; - - x_ptr = x; - LTP_res_ptr = LTP_res; - for( k = 0; k < nb_subfr; k++ ) { - - x_lag_ptr = x_ptr - pitchL[ k ]; - for( i = 0; i < LTP_ORDER; i++ ) { - Btmp_Q14[ i ] = LTPCoef_Q14[ k * LTP_ORDER + i ]; - } - - /* LTP analysis FIR filter */ - for( i = 0; i < subfr_length + pre_length; i++ ) { - LTP_res_ptr[ i ] = x_ptr[ i ]; - - /* Long-term prediction */ - LTP_est = SKP_SMULBB( x_lag_ptr[ LTP_ORDER / 2 ], Btmp_Q14[ 0 ] ); - for( j = 1; j < LTP_ORDER; j++ ) { - LTP_est = SKP_SMLABB_ovflw( LTP_est, x_lag_ptr[ LTP_ORDER / 2 - j ], Btmp_Q14[ j ] ); - } - LTP_est = SKP_RSHIFT_ROUND( LTP_est, 14 ); // round and -> Q0 - - /* Subtract long-term prediction */ - LTP_res_ptr[ i ] = ( opus_int16 )SKP_SAT16( ( opus_int32 )x_ptr[ i ] - LTP_est ); - - /* Scale residual */ - LTP_res_ptr[ i ] = SKP_SMULWB( invGains_Q16[ k ], LTP_res_ptr[ i ] ); - - x_lag_ptr++; - } - - /* Update pointers */ - LTP_res_ptr += subfr_length + pre_length; - x_ptr += subfr_length; - } -} - +/*********************************************************************** +Copyright (c) 2006-2011, Skype Limited. All rights reserved. +Redistribution and use in source and binary forms, with or without +modification, (subject to the limitations in the disclaimer below) +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 Skype Limited, nor the names of specific +contributors, may be used to endorse or promote products derived from +this software without specific prior written permission. +NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED +BY THIS LICENSE. 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. +***********************************************************************/ + +#include "silk_main_FIX.h" + +void silk_LTP_analysis_filter_FIX( + opus_int16 *LTP_res, /* O: LTP residual signal of length MAX_NB_SUBFR * ( pre_length + subfr_length ) */ + const opus_int16 *x, /* I: Pointer to input signal with at least max( pitchL ) preceeding samples */ + const opus_int16 LTPCoef_Q14[ LTP_ORDER * MAX_NB_SUBFR ],/* I: LTP_ORDER LTP coefficients for each MAX_NB_SUBFR subframe */ + const opus_int pitchL[ MAX_NB_SUBFR ], /* I: Pitch lag, one for each subframe */ + const opus_int32 invGains_Q16[ MAX_NB_SUBFR ], /* I: Inverse quantization gains, one for each subframe */ + const opus_int subfr_length, /* I: Length of each subframe */ + const opus_int nb_subfr, /* I: Number of subframes */ + const opus_int pre_length /* I: Length of the preceeding samples starting at &x[0] for each subframe */ +) +{ + const opus_int16 *x_ptr, *x_lag_ptr; + opus_int16 Btmp_Q14[ LTP_ORDER ]; + opus_int16 *LTP_res_ptr; + opus_int k, i, j; + opus_int32 LTP_est; + + x_ptr = x; + LTP_res_ptr = LTP_res; + for( k = 0; k < nb_subfr; k++ ) { + + x_lag_ptr = x_ptr - pitchL[ k ]; + for( i = 0; i < LTP_ORDER; i++ ) { + Btmp_Q14[ i ] = LTPCoef_Q14[ k * LTP_ORDER + i ]; + } + + /* LTP analysis FIR filter */ + for( i = 0; i < subfr_length + pre_length; i++ ) { + LTP_res_ptr[ i ] = x_ptr[ i ]; + + /* Long-term prediction */ + LTP_est = SKP_SMULBB( x_lag_ptr[ LTP_ORDER / 2 ], Btmp_Q14[ 0 ] ); + for( j = 1; j < LTP_ORDER; j++ ) { + LTP_est = SKP_SMLABB_ovflw( LTP_est, x_lag_ptr[ LTP_ORDER / 2 - j ], Btmp_Q14[ j ] ); + } + LTP_est = SKP_RSHIFT_ROUND( LTP_est, 14 ); // round and -> Q0 + + /* Subtract long-term prediction */ + LTP_res_ptr[ i ] = ( opus_int16 )SKP_SAT16( ( opus_int32 )x_ptr[ i ] - LTP_est ); + + /* Scale residual */ + LTP_res_ptr[ i ] = SKP_SMULWB( invGains_Q16[ k ], LTP_res_ptr[ i ] ); + + x_lag_ptr++; + } + + /* Update pointers */ + LTP_res_ptr += subfr_length + pre_length; + x_ptr += subfr_length; + } +} + diff --git a/silk/fixed/silk_LTP_scale_ctrl_FIX.c b/silk/fixed/silk_LTP_scale_ctrl_FIX.c index d3535c717..3043d8a34 100644 --- a/silk/fixed/silk_LTP_scale_ctrl_FIX.c +++ b/silk/fixed/silk_LTP_scale_ctrl_FIX.c @@ -1,52 +1,52 @@ -/*********************************************************************** -Copyright (c) 2006-2011, Skype Limited. All rights reserved. -Redistribution and use in source and binary forms, with or without -modification, (subject to the limitations in the disclaimer below) -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 Skype Limited, nor the names of specific -contributors, may be used to endorse or promote products derived from -this software without specific prior written permission. -NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED -BY THIS LICENSE. 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. -***********************************************************************/ - -#include "silk_main_FIX.h" - -void silk_LTP_scale_ctrl_FIX( - silk_encoder_state_FIX *psEnc, /* I/O encoder state FIX */ - silk_encoder_control_FIX *psEncCtrl /* I/O encoder control FIX */ -) -{ - opus_int round_loss; - - /* 1st order high-pass filter */ - psEnc->HPLTPredCodGain_Q7 = SKP_max_int( psEncCtrl->LTPredCodGain_Q7 - SKP_RSHIFT( psEnc->prevLTPredCodGain_Q7, 1 ), 0 ) - + SKP_RSHIFT( psEnc->HPLTPredCodGain_Q7, 1 ); - psEnc->prevLTPredCodGain_Q7 = psEncCtrl->LTPredCodGain_Q7; - - /* Only scale if first frame in packet */ - if( psEnc->sCmn.nFramesEncoded == 0 ) { - round_loss = psEnc->sCmn.PacketLoss_perc + psEnc->sCmn.nFramesPerPacket - 1; - psEnc->sCmn.indices.LTP_scaleIndex = (opus_int8)SKP_LIMIT( - SKP_SMULWB( SKP_SMULBB( round_loss, psEnc->HPLTPredCodGain_Q7 ), SILK_FIX_CONST( 0.1, 9 ) ), 0, 2 ); - } else { - /* Default is minimum scaling */ - psEnc->sCmn.indices.LTP_scaleIndex = 0; - } - psEncCtrl->LTP_scale_Q14 = silk_LTPScales_table_Q14[ psEnc->sCmn.indices.LTP_scaleIndex ]; -} +/*********************************************************************** +Copyright (c) 2006-2011, Skype Limited. All rights reserved. +Redistribution and use in source and binary forms, with or without +modification, (subject to the limitations in the disclaimer below) +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 Skype Limited, nor the names of specific +contributors, may be used to endorse or promote products derived from +this software without specific prior written permission. +NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED +BY THIS LICENSE. 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. +***********************************************************************/ + +#include "silk_main_FIX.h" + +void silk_LTP_scale_ctrl_FIX( + silk_encoder_state_FIX *psEnc, /* I/O encoder state FIX */ + silk_encoder_control_FIX *psEncCtrl /* I/O encoder control FIX */ +) +{ + opus_int round_loss; + + /* 1st order high-pass filter */ + psEnc->HPLTPredCodGain_Q7 = SKP_max_int( psEncCtrl->LTPredCodGain_Q7 - SKP_RSHIFT( psEnc->prevLTPredCodGain_Q7, 1 ), 0 ) + + SKP_RSHIFT( psEnc->HPLTPredCodGain_Q7, 1 ); + psEnc->prevLTPredCodGain_Q7 = psEncCtrl->LTPredCodGain_Q7; + + /* Only scale if first frame in packet */ + if( psEnc->sCmn.nFramesEncoded == 0 ) { + round_loss = psEnc->sCmn.PacketLoss_perc + psEnc->sCmn.nFramesPerPacket - 1; + psEnc->sCmn.indices.LTP_scaleIndex = (opus_int8)SKP_LIMIT( + SKP_SMULWB( SKP_SMULBB( round_loss, psEnc->HPLTPredCodGain_Q7 ), SILK_FIX_CONST( 0.1, 9 ) ), 0, 2 ); + } else { + /* Default is minimum scaling */ + psEnc->sCmn.indices.LTP_scaleIndex = 0; + } + psEncCtrl->LTP_scale_Q14 = silk_LTPScales_table_Q14[ psEnc->sCmn.indices.LTP_scaleIndex ]; +} diff --git a/silk/fixed/silk_corrMatrix_FIX.c b/silk/fixed/silk_corrMatrix_FIX.c index 619546f0c..6bf4fd929 100644 --- a/silk/fixed/silk_corrMatrix_FIX.c +++ b/silk/fixed/silk_corrMatrix_FIX.c @@ -1,152 +1,152 @@ -/*********************************************************************** -Copyright (c) 2006-2011, Skype Limited. All rights reserved. -Redistribution and use in source and binary forms, with or without -modification, (subject to the limitations in the disclaimer below) -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 Skype Limited, nor the names of specific -contributors, may be used to endorse or promote products derived from -this software without specific prior written permission. -NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED -BY THIS LICENSE. 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. -***********************************************************************/ - -/********************************************************************** - * Correlation Matrix Computations for LS estimate. - **********************************************************************/ - -#include "silk_main_FIX.h" - -/* Calculates correlation vector X'*t */ -void silk_corrVector_FIX( - const opus_int16 *x, /* I x vector [L + order - 1] used to form data matrix X */ - const opus_int16 *t, /* I target vector [L] */ - const opus_int L, /* I Length of vectors */ - const opus_int order, /* I Max lag for correlation */ - opus_int32 *Xt, /* O Pointer to X'*t correlation vector [order] */ - const opus_int rshifts /* I Right shifts of correlations */ -) -{ - opus_int lag, i; - const opus_int16 *ptr1, *ptr2; - opus_int32 inner_prod; - - ptr1 = &x[ order - 1 ]; /* Points to first sample of column 0 of X: X[:,0] */ - ptr2 = t; - /* Calculate X'*t */ - if( rshifts > 0 ) { - /* Right shifting used */ - for( lag = 0; lag < order; lag++ ) { - inner_prod = 0; - for( i = 0; i < L; i++ ) { - inner_prod += SKP_RSHIFT32( SKP_SMULBB( ptr1[ i ], ptr2[i] ), rshifts ); - } - Xt[ lag ] = inner_prod; /* X[:,lag]'*t */ - ptr1--; /* Go to next column of X */ - } - } else { - SKP_assert( rshifts == 0 ); - for( lag = 0; lag < order; lag++ ) { - Xt[ lag ] = silk_inner_prod_aligned( ptr1, ptr2, L ); /* X[:,lag]'*t */ - ptr1--; /* Go to next column of X */ - } - } -} - -/* Calculates correlation matrix X'*X */ -void silk_corrMatrix_FIX( - const opus_int16 *x, /* I x vector [L + order - 1] used to form data matrix X */ - const opus_int L, /* I Length of vectors */ - const opus_int order, /* I Max lag for correlation */ - const opus_int head_room, /* I Desired headroom */ - opus_int32 *XX, /* O Pointer to X'*X correlation matrix [ order x order ]*/ - opus_int *rshifts /* I/O Right shifts of correlations */ -) -{ - opus_int i, j, lag, rshifts_local, head_room_rshifts; - opus_int32 energy; - const opus_int16 *ptr1, *ptr2; - - /* Calculate energy to find shift used to fit in 32 bits */ - silk_sum_sqr_shift( &energy, &rshifts_local, x, L + order - 1 ); - /* Add shifts to get the desired head room */ - head_room_rshifts = SKP_max( head_room - silk_CLZ32( energy ), 0 ); - - energy = SKP_RSHIFT32( energy, head_room_rshifts ); - rshifts_local += head_room_rshifts; - - /* Calculate energy of first column (0) of X: X[:,0]'*X[:,0] */ - /* Remove contribution of first order - 1 samples */ - for( i = 0; i < order - 1; i++ ) { - energy -= SKP_RSHIFT32( SKP_SMULBB( x[ i ], x[ i ] ), rshifts_local ); - } - if( rshifts_local < *rshifts ) { - /* Adjust energy */ - energy = SKP_RSHIFT32( energy, *rshifts - rshifts_local ); - rshifts_local = *rshifts; - } - - /* Calculate energy of remaining columns of X: X[:,j]'*X[:,j] */ - /* Fill out the diagonal of the correlation matrix */ - matrix_ptr( XX, 0, 0, order ) = energy; - ptr1 = &x[ order - 1 ]; /* First sample of column 0 of X */ - for( j = 1; j < order; j++ ) { - energy = SKP_SUB32( energy, SKP_RSHIFT32( SKP_SMULBB( ptr1[ L - j ], ptr1[ L - j ] ), rshifts_local ) ); - energy = SKP_ADD32( energy, SKP_RSHIFT32( SKP_SMULBB( ptr1[ -j ], ptr1[ -j ] ), rshifts_local ) ); - matrix_ptr( XX, j, j, order ) = energy; - } - - ptr2 = &x[ order - 2 ]; /* First sample of column 1 of X */ - /* Calculate the remaining elements of the correlation matrix */ - if( rshifts_local > 0 ) { - /* Right shifting used */ - for( lag = 1; lag < order; lag++ ) { - /* Inner product of column 0 and column lag: X[:,0]'*X[:,lag] */ - energy = 0; - for( i = 0; i < L; i++ ) { - energy += SKP_RSHIFT32( SKP_SMULBB( ptr1[ i ], ptr2[i] ), rshifts_local ); - } - /* Calculate remaining off diagonal: X[:,j]'*X[:,j + lag] */ - matrix_ptr( XX, lag, 0, order ) = energy; - matrix_ptr( XX, 0, lag, order ) = energy; - for( j = 1; j < ( order - lag ); j++ ) { - energy = SKP_SUB32( energy, SKP_RSHIFT32( SKP_SMULBB( ptr1[ L - j ], ptr2[ L - j ] ), rshifts_local ) ); - energy = SKP_ADD32( energy, SKP_RSHIFT32( SKP_SMULBB( ptr1[ -j ], ptr2[ -j ] ), rshifts_local ) ); - matrix_ptr( XX, lag + j, j, order ) = energy; - matrix_ptr( XX, j, lag + j, order ) = energy; - } - ptr2--; /* Update pointer to first sample of next column (lag) in X */ - } - } else { - for( lag = 1; lag < order; lag++ ) { - /* Inner product of column 0 and column lag: X[:,0]'*X[:,lag] */ - energy = silk_inner_prod_aligned( ptr1, ptr2, L ); - matrix_ptr( XX, lag, 0, order ) = energy; - matrix_ptr( XX, 0, lag, order ) = energy; - /* Calculate remaining off diagonal: X[:,j]'*X[:,j + lag] */ - for( j = 1; j < ( order - lag ); j++ ) { - energy = SKP_SUB32( energy, SKP_SMULBB( ptr1[ L - j ], ptr2[ L - j ] ) ); - energy = SKP_SMLABB( energy, ptr1[ -j ], ptr2[ -j ] ); - matrix_ptr( XX, lag + j, j, order ) = energy; - matrix_ptr( XX, j, lag + j, order ) = energy; - } - ptr2--;/* Update pointer to first sample of next column (lag) in X */ - } - } - *rshifts = rshifts_local; -} - +/*********************************************************************** +Copyright (c) 2006-2011, Skype Limited. All rights reserved. +Redistribution and use in source and binary forms, with or without +modification, (subject to the limitations in the disclaimer below) +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 Skype Limited, nor the names of specific +contributors, may be used to endorse or promote products derived from +this software without specific prior written permission. +NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED +BY THIS LICENSE. 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. +***********************************************************************/ + +/********************************************************************** + * Correlation Matrix Computations for LS estimate. + **********************************************************************/ + +#include "silk_main_FIX.h" + +/* Calculates correlation vector X'*t */ +void silk_corrVector_FIX( + const opus_int16 *x, /* I x vector [L + order - 1] used to form data matrix X */ + const opus_int16 *t, /* I target vector [L] */ + const opus_int L, /* I Length of vectors */ + const opus_int order, /* I Max lag for correlation */ + opus_int32 *Xt, /* O Pointer to X'*t correlation vector [order] */ + const opus_int rshifts /* I Right shifts of correlations */ +) +{ + opus_int lag, i; + const opus_int16 *ptr1, *ptr2; + opus_int32 inner_prod; + + ptr1 = &x[ order - 1 ]; /* Points to first sample of column 0 of X: X[:,0] */ + ptr2 = t; + /* Calculate X'*t */ + if( rshifts > 0 ) { + /* Right shifting used */ + for( lag = 0; lag < order; lag++ ) { + inner_prod = 0; + for( i = 0; i < L; i++ ) { + inner_prod += SKP_RSHIFT32( SKP_SMULBB( ptr1[ i ], ptr2[i] ), rshifts ); + } + Xt[ lag ] = inner_prod; /* X[:,lag]'*t */ + ptr1--; /* Go to next column of X */ + } + } else { + SKP_assert( rshifts == 0 ); + for( lag = 0; lag < order; lag++ ) { + Xt[ lag ] = silk_inner_prod_aligned( ptr1, ptr2, L ); /* X[:,lag]'*t */ + ptr1--; /* Go to next column of X */ + } + } +} + +/* Calculates correlation matrix X'*X */ +void silk_corrMatrix_FIX( + const opus_int16 *x, /* I x vector [L + order - 1] used to form data matrix X */ + const opus_int L, /* I Length of vectors */ + const opus_int order, /* I Max lag for correlation */ + const opus_int head_room, /* I Desired headroom */ + opus_int32 *XX, /* O Pointer to X'*X correlation matrix [ order x order ]*/ + opus_int *rshifts /* I/O Right shifts of correlations */ +) +{ + opus_int i, j, lag, rshifts_local, head_room_rshifts; + opus_int32 energy; + const opus_int16 *ptr1, *ptr2; + + /* Calculate energy to find shift used to fit in 32 bits */ + silk_sum_sqr_shift( &energy, &rshifts_local, x, L + order - 1 ); + /* Add shifts to get the desired head room */ + head_room_rshifts = SKP_max( head_room - silk_CLZ32( energy ), 0 ); + + energy = SKP_RSHIFT32( energy, head_room_rshifts ); + rshifts_local += head_room_rshifts; + + /* Calculate energy of first column (0) of X: X[:,0]'*X[:,0] */ + /* Remove contribution of first order - 1 samples */ + for( i = 0; i < order - 1; i++ ) { + energy -= SKP_RSHIFT32( SKP_SMULBB( x[ i ], x[ i ] ), rshifts_local ); + } + if( rshifts_local < *rshifts ) { + /* Adjust energy */ + energy = SKP_RSHIFT32( energy, *rshifts - rshifts_local ); + rshifts_local = *rshifts; + } + + /* Calculate energy of remaining columns of X: X[:,j]'*X[:,j] */ + /* Fill out the diagonal of the correlation matrix */ + matrix_ptr( XX, 0, 0, order ) = energy; + ptr1 = &x[ order - 1 ]; /* First sample of column 0 of X */ + for( j = 1; j < order; j++ ) { + energy = SKP_SUB32( energy, SKP_RSHIFT32( SKP_SMULBB( ptr1[ L - j ], ptr1[ L - j ] ), rshifts_local ) ); + energy = SKP_ADD32( energy, SKP_RSHIFT32( SKP_SMULBB( ptr1[ -j ], ptr1[ -j ] ), rshifts_local ) ); + matrix_ptr( XX, j, j, order ) = energy; + } + + ptr2 = &x[ order - 2 ]; /* First sample of column 1 of X */ + /* Calculate the remaining elements of the correlation matrix */ + if( rshifts_local > 0 ) { + /* Right shifting used */ + for( lag = 1; lag < order; lag++ ) { + /* Inner product of column 0 and column lag: X[:,0]'*X[:,lag] */ + energy = 0; + for( i = 0; i < L; i++ ) { + energy += SKP_RSHIFT32( SKP_SMULBB( ptr1[ i ], ptr2[i] ), rshifts_local ); + } + /* Calculate remaining off diagonal: X[:,j]'*X[:,j + lag] */ + matrix_ptr( XX, lag, 0, order ) = energy; + matrix_ptr( XX, 0, lag, order ) = energy; + for( j = 1; j < ( order - lag ); j++ ) { + energy = SKP_SUB32( energy, SKP_RSHIFT32( SKP_SMULBB( ptr1[ L - j ], ptr2[ L - j ] ), rshifts_local ) ); + energy = SKP_ADD32( energy, SKP_RSHIFT32( SKP_SMULBB( ptr1[ -j ], ptr2[ -j ] ), rshifts_local ) ); + matrix_ptr( XX, lag + j, j, order ) = energy; + matrix_ptr( XX, j, lag + j, order ) = energy; + } + ptr2--; /* Update pointer to first sample of next column (lag) in X */ + } + } else { + for( lag = 1; lag < order; lag++ ) { + /* Inner product of column 0 and column lag: X[:,0]'*X[:,lag] */ + energy = silk_inner_prod_aligned( ptr1, ptr2, L ); + matrix_ptr( XX, lag, 0, order ) = energy; + matrix_ptr( XX, 0, lag, order ) = energy; + /* Calculate remaining off diagonal: X[:,j]'*X[:,j + lag] */ + for( j = 1; j < ( order - lag ); j++ ) { + energy = SKP_SUB32( energy, SKP_SMULBB( ptr1[ L - j ], ptr2[ L - j ] ) ); + energy = SKP_SMLABB( energy, ptr1[ -j ], ptr2[ -j ] ); + matrix_ptr( XX, lag + j, j, order ) = energy; + matrix_ptr( XX, j, lag + j, order ) = energy; + } + ptr2--;/* Update pointer to first sample of next column (lag) in X */ + } + } + *rshifts = rshifts_local; +} + diff --git a/silk/fixed/silk_encode_frame_FIX.c b/silk/fixed/silk_encode_frame_FIX.c index ea05aa7f0..eb1710f85 100644 --- a/silk/fixed/silk_encode_frame_FIX.c +++ b/silk/fixed/silk_encode_frame_FIX.c @@ -1,301 +1,301 @@ -/*********************************************************************** -Copyright (c) 2006-2011, Skype Limited. All rights reserved. -Redistribution and use in source and binary forms, with or without -modification, (subject to the limitations in the disclaimer below) -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 Skype Limited, nor the names of specific -contributors, may be used to endorse or promote products derived from -this software without specific prior written permission. -NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED -BY THIS LICENSE. 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. -***********************************************************************/ - -#include "silk_main_FIX.h" -#include "silk_tuning_parameters.h" - -/****************/ -/* Encode frame */ -/****************/ -opus_int silk_encode_frame_FIX( - silk_encoder_state_FIX *psEnc, /* I/O Encoder state FIX */ - opus_int32 *pnBytesOut, /* O Number of payload bytes */ - ec_enc *psRangeEnc /* I/O compressor data structure */ -) -{ - silk_encoder_control_FIX sEncCtrl; - opus_int ret = 0; - opus_int16 *x_frame, *res_pitch_frame; - opus_int16 xfw[ MAX_FRAME_LENGTH ]; - opus_int16 res_pitch[ 2 * MAX_FRAME_LENGTH + LA_PITCH_MAX ]; - -TIC(ENCODE_FRAME) - - psEnc->sCmn.indices.Seed = psEnc->sCmn.frameCounter++ & 3; - - /**************************************************************/ - /* Setup 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 */ - - /****************************/ - /* Voice Activity Detection */ - /****************************/ -TIC(VAD) - ret = silk_VAD_GetSA_Q8( &psEnc->sCmn, psEnc->sCmn.inputBuf - 1 ); -TOC(VAD) - - /**************************************************/ - /* Convert speech activity into VAD and DTX flags */ - /**************************************************/ - if( psEnc->sCmn.nFramesEncoded == 0 ) { - psEnc->sCmn.inDTX = psEnc->sCmn.useDTX; - } - if( psEnc->sCmn.speech_activity_Q8 < SILK_FIX_CONST( SPEECH_ACTIVITY_DTX_THRES, 8 ) ) { - psEnc->sCmn.indices.signalType = TYPE_NO_VOICE_ACTIVITY; - psEnc->sCmn.noSpeechCounter++; - if( psEnc->sCmn.noSpeechCounter < NB_SPEECH_FRAMES_BEFORE_DTX ) { - psEnc->sCmn.inDTX = 0; - } else if( psEnc->sCmn.noSpeechCounter > MAX_CONSECUTIVE_DTX + NB_SPEECH_FRAMES_BEFORE_DTX ) { - psEnc->sCmn.noSpeechCounter = NB_SPEECH_FRAMES_BEFORE_DTX; - psEnc->sCmn.inDTX = 0; - } - psEnc->sCmn.VAD_flags[ psEnc->sCmn.nFramesEncoded ] = 0; - } else { - psEnc->sCmn.noSpeechCounter = 0; - psEnc->sCmn.inDTX = 0; - psEnc->sCmn.indices.signalType = TYPE_UNVOICED; - psEnc->sCmn.VAD_flags[ psEnc->sCmn.nFramesEncoded ] = 1; - } - - /***************************************/ - /* Ensure smooth bandwidth transitions */ - /***************************************/ - silk_LP_variable_cutoff( &psEnc->sCmn.sLP, psEnc->sCmn.inputBuf - 1, psEnc->sCmn.frame_length ); - - /*******************************************/ - /* Copy new frame to front of input buffer */ - /*******************************************/ - SKP_memcpy( x_frame + LA_SHAPE_MS * psEnc->sCmn.fs_kHz, psEnc->sCmn.inputBuf - 1, psEnc->sCmn.frame_length * sizeof( opus_int16 ) ); - - /*****************************************/ - /* Find pitch lags, initial LPC analysis */ - /*****************************************/ -TIC(FIND_PITCH) - silk_find_pitch_lags_FIX( psEnc, &sEncCtrl, res_pitch, x_frame ); -TOC(FIND_PITCH) - - /************************/ - /* Noise shape analysis */ - /************************/ -TIC(NOISE_SHAPE_ANALYSIS) - silk_noise_shape_analysis_FIX( psEnc, &sEncCtrl, res_pitch_frame, x_frame ); -TOC(NOISE_SHAPE_ANALYSIS) - - /***************************************************/ - /* Find linear prediction coefficients (LPC + LTP) */ - /***************************************************/ -TIC(FIND_PRED_COEF) - silk_find_pred_coefs_FIX( psEnc, &sEncCtrl, res_pitch, x_frame ); -TOC(FIND_PRED_COEF) - - /****************************************/ - /* Process gains */ - /****************************************/ -TIC(PROCESS_GAINS) - silk_process_gains_FIX( psEnc, &sEncCtrl ); -TOC(PROCESS_GAINS) - - /*****************************************/ - /* Prefiltering for noise shaper */ - /*****************************************/ -TIC(PREFILTER) - silk_prefilter_FIX( psEnc, &sEncCtrl, xfw, x_frame ); -TOC(PREFILTER) - - /****************************************/ - /* Low Bitrate Redundant Encoding */ - /****************************************/ -TIC(LBRR) - silk_LBRR_encode_FIX( psEnc, &sEncCtrl, xfw ); -TOC(LBRR) - - /*****************************************/ - /* Noise shaping quantization */ - /*****************************************/ -TIC(NSQ) - if( psEnc->sCmn.nStatesDelayedDecision > 1 || psEnc->sCmn.warping_Q16 > 0 ) { - silk_NSQ_del_dec( &psEnc->sCmn, &psEnc->sCmn.sNSQ, &psEnc->sCmn.indices, xfw, psEnc->sCmn.pulses, - sEncCtrl.PredCoef_Q12[ 0 ], sEncCtrl.LTPCoef_Q14, sEncCtrl.AR2_Q13, sEncCtrl.HarmShapeGain_Q14, - sEncCtrl.Tilt_Q14, sEncCtrl.LF_shp_Q14, sEncCtrl.Gains_Q16, sEncCtrl.pitchL, sEncCtrl.Lambda_Q10, sEncCtrl.LTP_scale_Q14 ); - } else { - silk_NSQ( &psEnc->sCmn, &psEnc->sCmn.sNSQ, &psEnc->sCmn.indices, xfw, psEnc->sCmn.pulses, - sEncCtrl.PredCoef_Q12[ 0 ], sEncCtrl.LTPCoef_Q14, sEncCtrl.AR2_Q13, sEncCtrl.HarmShapeGain_Q14, - sEncCtrl.Tilt_Q14, sEncCtrl.LF_shp_Q14, sEncCtrl.Gains_Q16, sEncCtrl.pitchL, sEncCtrl.Lambda_Q10, sEncCtrl.LTP_scale_Q14 ); - } -TOC(NSQ) - - /* Update input buffer */ - SKP_memmove( psEnc->x_buf, &psEnc->x_buf[ psEnc->sCmn.frame_length ], - ( psEnc->sCmn.ltp_mem_length + LA_SHAPE_MS * psEnc->sCmn.fs_kHz ) * sizeof( opus_int16 ) ); - - /* Parameters needed for next frame */ - psEnc->sCmn.prevLag = sEncCtrl.pitchL[ psEnc->sCmn.nb_subfr - 1 ]; - psEnc->sCmn.prevSignalType = psEnc->sCmn.indices.signalType; - - /* Exit without entropy coding */ - if( psEnc->sCmn.prefillFlag ) { - /* No payload */ - *pnBytesOut = 0; - return ret; - } - - /****************************************/ - /* Encode Parameters */ - /****************************************/ -TIC(ENCODE_PARAMS) - silk_encode_indices( &psEnc->sCmn, psRangeEnc, psEnc->sCmn.nFramesEncoded, 0 ); -TOC(ENCODE_PARAMS) - - /****************************************/ - /* Encode Excitation Signal */ - /****************************************/ -TIC(ENCODE_PULSES) - silk_encode_pulses( psRangeEnc, psEnc->sCmn.indices.signalType, psEnc->sCmn.indices.quantOffsetType, - psEnc->sCmn.pulses, psEnc->sCmn.frame_length ); -TOC(ENCODE_PULSES) - - /****************************************/ - /* Finalize payload */ - /****************************************/ - psEnc->sCmn.first_frame_after_reset = 0; - if( ++psEnc->sCmn.nFramesEncoded >= psEnc->sCmn.nFramesPerPacket ) { - /* Payload size */ - *pnBytesOut = SKP_RSHIFT( ec_tell( psRangeEnc ) + 7, 3 ); - - /* Reset the number of frames in payload buffer */ - psEnc->sCmn.nFramesEncoded = 0; - } else { - /* No payload this time */ - *pnBytesOut = 0; - } -TOC(ENCODE_FRAME) - -#ifdef SAVE_ALL_INTERNAL_DATA - { - SKP_float tmp[ MAX_NB_SUBFR * LTP_ORDER ]; - int i; - DEBUG_STORE_DATA( xf.dat, x_frame + LA_SHAPE_MS * psEnc->sCmn.fs_kHz, psEnc->sCmn.frame_length * sizeof( opus_int16 ) ); - DEBUG_STORE_DATA( xfw.dat, xfw, psEnc->sCmn.frame_length * sizeof( opus_int16 ) ); - DEBUG_STORE_DATA( pitchL.dat, sEncCtrl.pitchL, psEnc->sCmn.nb_subfr * sizeof( opus_int ) ); - for( i = 0; i < psEnc->sCmn.nb_subfr * LTP_ORDER; i++ ) { - tmp[ i ] = (SKP_float)sEncCtrl.LTPCoef_Q14[ i ] / 16384.0f; - } - DEBUG_STORE_DATA( pitchG_quantized.dat, tmp, psEnc->sCmn.nb_subfr * LTP_ORDER * sizeof( SKP_float ) ); - for( i = 0; i <psEnc->sCmn.predictLPCOrder; i++ ) { - tmp[ i ] = (SKP_float)sEncCtrl.PredCoef_Q12[ 1 ][ i ] / 4096.0f; - } - DEBUG_STORE_DATA( PredCoef.dat, tmp, psEnc->sCmn.predictLPCOrder * sizeof( SKP_float ) ); - - tmp[ 0 ] = (SKP_float)sEncCtrl.LTPredCodGain_Q7 / 128.0f; - DEBUG_STORE_DATA( LTPredCodGain.dat, tmp, sizeof( SKP_float ) ); - tmp[ 0 ] = (SKP_float)psEnc->LTPCorr_Q15 / 32768.0f; - DEBUG_STORE_DATA( LTPcorr.dat, tmp, sizeof( SKP_float ) ); - tmp[ 0 ] = (SKP_float)psEnc->sCmn.input_tilt_Q15 / 32768.0f; - DEBUG_STORE_DATA( tilt.dat, tmp, sizeof( SKP_float ) ); - for( i = 0; i < psEnc->sCmn.nb_subfr; i++ ) { - tmp[ i ] = (SKP_float)sEncCtrl.Gains_Q16[ i ] / 65536.0f; - } - DEBUG_STORE_DATA( gains.dat, tmp, psEnc->sCmn.nb_subfr * sizeof( SKP_float ) ); - DEBUG_STORE_DATA( gains_indices.dat, &psEnc->sCmn.indices.GainsIndices, psEnc->sCmn.nb_subfr * sizeof( opus_int ) ); - tmp[ 0 ] = (SKP_float)sEncCtrl.current_SNR_dB_Q7 / 128.0f; - DEBUG_STORE_DATA( current_SNR_db.dat, tmp, sizeof( SKP_float ) ); - DEBUG_STORE_DATA( quantOffsetType.dat, &psEnc->sCmn.indices.quantOffsetType, sizeof( opus_int ) ); - tmp[ 0 ] = (SKP_float)psEnc->sCmn.speech_activity_Q8 / 256.0f; - DEBUG_STORE_DATA( speech_activity.dat, tmp, sizeof( SKP_float ) ); - for( i = 0; i < VAD_N_BANDS; i++ ) { - tmp[ i ] = (SKP_float)psEnc->sCmn.input_quality_bands_Q15[ i ] / 32768.0f; - } - DEBUG_STORE_DATA( input_quality_bands.dat, tmp, VAD_N_BANDS * sizeof( SKP_float ) ); - DEBUG_STORE_DATA( signalType.dat, &psEnc->sCmn.indices.signalType, sizeof( opus_int8) ); - DEBUG_STORE_DATA( lag_index.dat, &psEnc->sCmn.indices.lagIndex, sizeof( opus_int16 ) ); - DEBUG_STORE_DATA( contour_index.dat, &psEnc->sCmn.indices.contourIndex, sizeof( opus_int8 ) ); - DEBUG_STORE_DATA( per_index.dat, &psEnc->sCmn.indices.PERIndex, sizeof( opus_int8) ); - } -#endif - return ret; -} - -/* Low-Bitrate Redundancy (LBRR) encoding. Reuse all parameters but encode excitation at lower bitrate */ -void silk_LBRR_encode_FIX( - silk_encoder_state_FIX *psEnc, /* I/O Pointer to Silk FIX encoder state */ - silk_encoder_control_FIX *psEncCtrl, /* I/O Pointer to Silk FIX encoder control struct */ - const opus_int16 xfw[] /* I Input signal */ -) -{ - opus_int32 TempGains_Q16[ MAX_NB_SUBFR ]; - SideInfoIndices *psIndices_LBRR = &psEnc->sCmn.indices_LBRR[ psEnc->sCmn.nFramesEncoded ]; - silk_nsq_state sNSQ_LBRR; - - /*******************************************/ - /* Control use of inband LBRR */ - /*******************************************/ - if( psEnc->sCmn.LBRR_enabled && psEnc->sCmn.speech_activity_Q8 > SILK_FIX_CONST( LBRR_SPEECH_ACTIVITY_THRES, 8 ) ) { - psEnc->sCmn.LBRR_flags[ psEnc->sCmn.nFramesEncoded ] = 1; - - /* Copy noise shaping quantizer state and quantization indices from regular encoding */ - SKP_memcpy( &sNSQ_LBRR, &psEnc->sCmn.sNSQ, sizeof( silk_nsq_state ) ); - SKP_memcpy( psIndices_LBRR, &psEnc->sCmn.indices, sizeof( SideInfoIndices ) ); - - /* Save original gains */ - SKP_memcpy( TempGains_Q16, psEncCtrl->Gains_Q16, psEnc->sCmn.nb_subfr * sizeof( opus_int32 ) ); - - if( psEnc->sCmn.nFramesEncoded == 0 || psEnc->sCmn.LBRR_flags[ psEnc->sCmn.nFramesEncoded - 1 ] == 0 ) { - /* First frame in packet or previous frame not LBRR coded */ - psEnc->sCmn.LBRRprevLastGainIndex = psEnc->sShape.LastGainIndex; - - /* Increase Gains to get target LBRR rate */ - psIndices_LBRR->GainsIndices[ 0 ] = psIndices_LBRR->GainsIndices[ 0 ] + psEnc->sCmn.LBRR_GainIncreases; - psIndices_LBRR->GainsIndices[ 0 ] = SKP_min_int( psIndices_LBRR->GainsIndices[ 0 ], N_LEVELS_QGAIN - 1 ); - } - - /* Decode to get gains in sync with decoder */ - /* Overwrite unquantized gains with quantized gains */ - silk_gains_dequant( psEncCtrl->Gains_Q16, psIndices_LBRR->GainsIndices, - &psEnc->sCmn.LBRRprevLastGainIndex, psEnc->sCmn.nFramesEncoded, psEnc->sCmn.nb_subfr ); - - /*****************************************/ - /* Noise shaping quantization */ - /*****************************************/ - if( psEnc->sCmn.nStatesDelayedDecision > 1 || psEnc->sCmn.warping_Q16 > 0 ) { - silk_NSQ_del_dec( &psEnc->sCmn, &sNSQ_LBRR, psIndices_LBRR, xfw, - psEnc->sCmn.pulses_LBRR[ psEnc->sCmn.nFramesEncoded ], psEncCtrl->PredCoef_Q12[ 0 ], psEncCtrl->LTPCoef_Q14, - psEncCtrl->AR2_Q13, psEncCtrl->HarmShapeGain_Q14, psEncCtrl->Tilt_Q14, psEncCtrl->LF_shp_Q14, - psEncCtrl->Gains_Q16, psEncCtrl->pitchL, psEncCtrl->Lambda_Q10, psEncCtrl->LTP_scale_Q14 ); - } else { - silk_NSQ( &psEnc->sCmn, &sNSQ_LBRR, psIndices_LBRR, xfw, - psEnc->sCmn.pulses_LBRR[ psEnc->sCmn.nFramesEncoded ], psEncCtrl->PredCoef_Q12[ 0 ], psEncCtrl->LTPCoef_Q14, - psEncCtrl->AR2_Q13, psEncCtrl->HarmShapeGain_Q14, psEncCtrl->Tilt_Q14, psEncCtrl->LF_shp_Q14, - psEncCtrl->Gains_Q16, psEncCtrl->pitchL, psEncCtrl->Lambda_Q10, psEncCtrl->LTP_scale_Q14 ); - } - - /* Restore original gains */ - SKP_memcpy( psEncCtrl->Gains_Q16, TempGains_Q16, psEnc->sCmn.nb_subfr * sizeof( opus_int32 ) ); - } -} +/*********************************************************************** +Copyright (c) 2006-2011, Skype Limited. All rights reserved. +Redistribution and use in source and binary forms, with or without +modification, (subject to the limitations in the disclaimer below) +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 Skype Limited, nor the names of specific +contributors, may be used to endorse or promote products derived from +this software without specific prior written permission. +NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED +BY THIS LICENSE. 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. +***********************************************************************/ + +#include "silk_main_FIX.h" +#include "silk_tuning_parameters.h" + +/****************/ +/* Encode frame */ +/****************/ +opus_int silk_encode_frame_FIX( + silk_encoder_state_FIX *psEnc, /* I/O Encoder state FIX */ + opus_int32 *pnBytesOut, /* O Number of payload bytes */ + ec_enc *psRangeEnc /* I/O compressor data structure */ +) +{ + silk_encoder_control_FIX sEncCtrl; + opus_int ret = 0; + opus_int16 *x_frame, *res_pitch_frame; + opus_int16 xfw[ MAX_FRAME_LENGTH ]; + opus_int16 res_pitch[ 2 * MAX_FRAME_LENGTH + LA_PITCH_MAX ]; + +TIC(ENCODE_FRAME) + + psEnc->sCmn.indices.Seed = psEnc->sCmn.frameCounter++ & 3; + + /**************************************************************/ + /* Setup 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 */ + + /****************************/ + /* Voice Activity Detection */ + /****************************/ +TIC(VAD) + ret = silk_VAD_GetSA_Q8( &psEnc->sCmn, psEnc->sCmn.inputBuf - 1 ); +TOC(VAD) + + /**************************************************/ + /* Convert speech activity into VAD and DTX flags */ + /**************************************************/ + if( psEnc->sCmn.nFramesEncoded == 0 ) { + psEnc->sCmn.inDTX = psEnc->sCmn.useDTX; + } + if( psEnc->sCmn.speech_activity_Q8 < SILK_FIX_CONST( SPEECH_ACTIVITY_DTX_THRES, 8 ) ) { + psEnc->sCmn.indices.signalType = TYPE_NO_VOICE_ACTIVITY; + psEnc->sCmn.noSpeechCounter++; + if( psEnc->sCmn.noSpeechCounter < NB_SPEECH_FRAMES_BEFORE_DTX ) { + psEnc->sCmn.inDTX = 0; + } else if( psEnc->sCmn.noSpeechCounter > MAX_CONSECUTIVE_DTX + NB_SPEECH_FRAMES_BEFORE_DTX ) { + psEnc->sCmn.noSpeechCounter = NB_SPEECH_FRAMES_BEFORE_DTX; + psEnc->sCmn.inDTX = 0; + } + psEnc->sCmn.VAD_flags[ psEnc->sCmn.nFramesEncoded ] = 0; + } else { + psEnc->sCmn.noSpeechCounter = 0; + psEnc->sCmn.inDTX = 0; + psEnc->sCmn.indices.signalType = TYPE_UNVOICED; + psEnc->sCmn.VAD_flags[ psEnc->sCmn.nFramesEncoded ] = 1; + } + + /***************************************/ + /* Ensure smooth bandwidth transitions */ + /***************************************/ + silk_LP_variable_cutoff( &psEnc->sCmn.sLP, psEnc->sCmn.inputBuf - 1, psEnc->sCmn.frame_length ); + + /*******************************************/ + /* Copy new frame to front of input buffer */ + /*******************************************/ + SKP_memcpy( x_frame + LA_SHAPE_MS * psEnc->sCmn.fs_kHz, psEnc->sCmn.inputBuf - 1, psEnc->sCmn.frame_length * sizeof( opus_int16 ) ); + + /*****************************************/ + /* Find pitch lags, initial LPC analysis */ + /*****************************************/ +TIC(FIND_PITCH) + silk_find_pitch_lags_FIX( psEnc, &sEncCtrl, res_pitch, x_frame ); +TOC(FIND_PITCH) + + /************************/ + /* Noise shape analysis */ + /************************/ +TIC(NOISE_SHAPE_ANALYSIS) + silk_noise_shape_analysis_FIX( psEnc, &sEncCtrl, res_pitch_frame, x_frame ); +TOC(NOISE_SHAPE_ANALYSIS) + + /***************************************************/ + /* Find linear prediction coefficients (LPC + LTP) */ + /***************************************************/ +TIC(FIND_PRED_COEF) + silk_find_pred_coefs_FIX( psEnc, &sEncCtrl, res_pitch, x_frame ); +TOC(FIND_PRED_COEF) + + /****************************************/ + /* Process gains */ + /****************************************/ +TIC(PROCESS_GAINS) + silk_process_gains_FIX( psEnc, &sEncCtrl ); +TOC(PROCESS_GAINS) + + /*****************************************/ + /* Prefiltering for noise shaper */ + /*****************************************/ +TIC(PREFILTER) + silk_prefilter_FIX( psEnc, &sEncCtrl, xfw, x_frame ); +TOC(PREFILTER) + + /****************************************/ + /* Low Bitrate Redundant Encoding */ + /****************************************/ +TIC(LBRR) + silk_LBRR_encode_FIX( psEnc, &sEncCtrl, xfw ); +TOC(LBRR) + + /*****************************************/ + /* Noise shaping quantization */ + /*****************************************/ +TIC(NSQ) + if( psEnc->sCmn.nStatesDelayedDecision > 1 || psEnc->sCmn.warping_Q16 > 0 ) { + silk_NSQ_del_dec( &psEnc->sCmn, &psEnc->sCmn.sNSQ, &psEnc->sCmn.indices, xfw, psEnc->sCmn.pulses, + sEncCtrl.PredCoef_Q12[ 0 ], sEncCtrl.LTPCoef_Q14, sEncCtrl.AR2_Q13, sEncCtrl.HarmShapeGain_Q14, + sEncCtrl.Tilt_Q14, sEncCtrl.LF_shp_Q14, sEncCtrl.Gains_Q16, sEncCtrl.pitchL, sEncCtrl.Lambda_Q10, sEncCtrl.LTP_scale_Q14 ); + } else { + silk_NSQ( &psEnc->sCmn, &psEnc->sCmn.sNSQ, &psEnc->sCmn.indices, xfw, psEnc->sCmn.pulses, + sEncCtrl.PredCoef_Q12[ 0 ], sEncCtrl.LTPCoef_Q14, sEncCtrl.AR2_Q13, sEncCtrl.HarmShapeGain_Q14, + sEncCtrl.Tilt_Q14, sEncCtrl.LF_shp_Q14, sEncCtrl.Gains_Q16, sEncCtrl.pitchL, sEncCtrl.Lambda_Q10, sEncCtrl.LTP_scale_Q14 ); + } +TOC(NSQ) + + /* Update input buffer */ + SKP_memmove( psEnc->x_buf, &psEnc->x_buf[ psEnc->sCmn.frame_length ], + ( psEnc->sCmn.ltp_mem_length + LA_SHAPE_MS * psEnc->sCmn.fs_kHz ) * sizeof( opus_int16 ) ); + + /* Parameters needed for next frame */ + psEnc->sCmn.prevLag = sEncCtrl.pitchL[ psEnc->sCmn.nb_subfr - 1 ]; + psEnc->sCmn.prevSignalType = psEnc->sCmn.indices.signalType; + + /* Exit without entropy coding */ + if( psEnc->sCmn.prefillFlag ) { + /* No payload */ + *pnBytesOut = 0; + return ret; + } + + /****************************************/ + /* Encode Parameters */ + /****************************************/ +TIC(ENCODE_PARAMS) + silk_encode_indices( &psEnc->sCmn, psRangeEnc, psEnc->sCmn.nFramesEncoded, 0 ); +TOC(ENCODE_PARAMS) + + /****************************************/ + /* Encode Excitation Signal */ + /****************************************/ +TIC(ENCODE_PULSES) + silk_encode_pulses( psRangeEnc, psEnc->sCmn.indices.signalType, psEnc->sCmn.indices.quantOffsetType, + psEnc->sCmn.pulses, psEnc->sCmn.frame_length ); +TOC(ENCODE_PULSES) + + /****************************************/ + /* Finalize payload */ + /****************************************/ + psEnc->sCmn.first_frame_after_reset = 0; + if( ++psEnc->sCmn.nFramesEncoded >= psEnc->sCmn.nFramesPerPacket ) { + /* Payload size */ + *pnBytesOut = SKP_RSHIFT( ec_tell( psRangeEnc ) + 7, 3 ); + + /* Reset the number of frames in payload buffer */ + psEnc->sCmn.nFramesEncoded = 0; + } else { + /* No payload this time */ + *pnBytesOut = 0; + } +TOC(ENCODE_FRAME) + +#ifdef SAVE_ALL_INTERNAL_DATA + { + SKP_float tmp[ MAX_NB_SUBFR * LTP_ORDER ]; + int i; + DEBUG_STORE_DATA( xf.dat, x_frame + LA_SHAPE_MS * psEnc->sCmn.fs_kHz, psEnc->sCmn.frame_length * sizeof( opus_int16 ) ); + DEBUG_STORE_DATA( xfw.dat, xfw, psEnc->sCmn.frame_length * sizeof( opus_int16 ) ); + DEBUG_STORE_DATA( pitchL.dat, sEncCtrl.pitchL, psEnc->sCmn.nb_subfr * sizeof( opus_int ) ); + for( i = 0; i < psEnc->sCmn.nb_subfr * LTP_ORDER; i++ ) { + tmp[ i ] = (SKP_float)sEncCtrl.LTPCoef_Q14[ i ] / 16384.0f; + } + DEBUG_STORE_DATA( pitchG_quantized.dat, tmp, psEnc->sCmn.nb_subfr * LTP_ORDER * sizeof( SKP_float ) ); + for( i = 0; i <psEnc->sCmn.predictLPCOrder; i++ ) { + tmp[ i ] = (SKP_float)sEncCtrl.PredCoef_Q12[ 1 ][ i ] / 4096.0f; + } + DEBUG_STORE_DATA( PredCoef.dat, tmp, psEnc->sCmn.predictLPCOrder * sizeof( SKP_float ) ); + + tmp[ 0 ] = (SKP_float)sEncCtrl.LTPredCodGain_Q7 / 128.0f; + DEBUG_STORE_DATA( LTPredCodGain.dat, tmp, sizeof( SKP_float ) ); + tmp[ 0 ] = (SKP_float)psEnc->LTPCorr_Q15 / 32768.0f; + DEBUG_STORE_DATA( LTPcorr.dat, tmp, sizeof( SKP_float ) ); + tmp[ 0 ] = (SKP_float)psEnc->sCmn.input_tilt_Q15 / 32768.0f; + DEBUG_STORE_DATA( tilt.dat, tmp, sizeof( SKP_float ) ); + for( i = 0; i < psEnc->sCmn.nb_subfr; i++ ) { + tmp[ i ] = (SKP_float)sEncCtrl.Gains_Q16[ i ] / 65536.0f; + } + DEBUG_STORE_DATA( gains.dat, tmp, psEnc->sCmn.nb_subfr * sizeof( SKP_float ) ); + DEBUG_STORE_DATA( gains_indices.dat, &psEnc->sCmn.indices.GainsIndices, psEnc->sCmn.nb_subfr * sizeof( opus_int ) ); + tmp[ 0 ] = (SKP_float)sEncCtrl.current_SNR_dB_Q7 / 128.0f; + DEBUG_STORE_DATA( current_SNR_db.dat, tmp, sizeof( SKP_float ) ); + DEBUG_STORE_DATA( quantOffsetType.dat, &psEnc->sCmn.indices.quantOffsetType, sizeof( opus_int ) ); + tmp[ 0 ] = (SKP_float)psEnc->sCmn.speech_activity_Q8 / 256.0f; + DEBUG_STORE_DATA( speech_activity.dat, tmp, sizeof( SKP_float ) ); + for( i = 0; i < VAD_N_BANDS; i++ ) { + tmp[ i ] = (SKP_float)psEnc->sCmn.input_quality_bands_Q15[ i ] / 32768.0f; + } + DEBUG_STORE_DATA( input_quality_bands.dat, tmp, VAD_N_BANDS * sizeof( SKP_float ) ); + DEBUG_STORE_DATA( signalType.dat, &psEnc->sCmn.indices.signalType, sizeof( opus_int8) ); + DEBUG_STORE_DATA( lag_index.dat, &psEnc->sCmn.indices.lagIndex, sizeof( opus_int16 ) ); + DEBUG_STORE_DATA( contour_index.dat, &psEnc->sCmn.indices.contourIndex, sizeof( opus_int8 ) ); + DEBUG_STORE_DATA( per_index.dat, &psEnc->sCmn.indices.PERIndex, sizeof( opus_int8) ); + } +#endif + return ret; +} + +/* Low-Bitrate Redundancy (LBRR) encoding. Reuse all parameters but encode excitation at lower bitrate */ +void silk_LBRR_encode_FIX( + silk_encoder_state_FIX *psEnc, /* I/O Pointer to Silk FIX encoder state */ + silk_encoder_control_FIX *psEncCtrl, /* I/O Pointer to Silk FIX encoder control struct */ + const opus_int16 xfw[] /* I Input signal */ +) +{ + opus_int32 TempGains_Q16[ MAX_NB_SUBFR ]; + SideInfoIndices *psIndices_LBRR = &psEnc->sCmn.indices_LBRR[ psEnc->sCmn.nFramesEncoded ]; + silk_nsq_state sNSQ_LBRR; + + /*******************************************/ + /* Control use of inband LBRR */ + /*******************************************/ + if( psEnc->sCmn.LBRR_enabled && psEnc->sCmn.speech_activity_Q8 > SILK_FIX_CONST( LBRR_SPEECH_ACTIVITY_THRES, 8 ) ) { + psEnc->sCmn.LBRR_flags[ psEnc->sCmn.nFramesEncoded ] = 1; + + /* Copy noise shaping quantizer state and quantization indices from regular encoding */ + SKP_memcpy( &sNSQ_LBRR, &psEnc->sCmn.sNSQ, sizeof( silk_nsq_state ) ); + SKP_memcpy( psIndices_LBRR, &psEnc->sCmn.indices, sizeof( SideInfoIndices ) ); + + /* Save original gains */ + SKP_memcpy( TempGains_Q16, psEncCtrl->Gains_Q16, psEnc->sCmn.nb_subfr * sizeof( opus_int32 ) ); + + if( psEnc->sCmn.nFramesEncoded == 0 || psEnc->sCmn.LBRR_flags[ psEnc->sCmn.nFramesEncoded - 1 ] == 0 ) { + /* First frame in packet or previous frame not LBRR coded */ + psEnc->sCmn.LBRRprevLastGainIndex = psEnc->sShape.LastGainIndex; + + /* Increase Gains to get target LBRR rate */ + psIndices_LBRR->GainsIndices[ 0 ] = psIndices_LBRR->GainsIndices[ 0 ] + psEnc->sCmn.LBRR_GainIncreases; + psIndices_LBRR->GainsIndices[ 0 ] = SKP_min_int( psIndices_LBRR->GainsIndices[ 0 ], N_LEVELS_QGAIN - 1 ); + } + + /* Decode to get gains in sync with decoder */ + /* Overwrite unquantized gains with quantized gains */ + silk_gains_dequant( psEncCtrl->Gains_Q16, psIndices_LBRR->GainsIndices, + &psEnc->sCmn.LBRRprevLastGainIndex, psEnc->sCmn.nFramesEncoded, psEnc->sCmn.nb_subfr ); + + /*****************************************/ + /* Noise shaping quantization */ + /*****************************************/ + if( psEnc->sCmn.nStatesDelayedDecision > 1 || psEnc->sCmn.warping_Q16 > 0 ) { + silk_NSQ_del_dec( &psEnc->sCmn, &sNSQ_LBRR, psIndices_LBRR, xfw, + psEnc->sCmn.pulses_LBRR[ psEnc->sCmn.nFramesEncoded ], psEncCtrl->PredCoef_Q12[ 0 ], psEncCtrl->LTPCoef_Q14, + psEncCtrl->AR2_Q13, psEncCtrl->HarmShapeGain_Q14, psEncCtrl->Tilt_Q14, psEncCtrl->LF_shp_Q14, + psEncCtrl->Gains_Q16, psEncCtrl->pitchL, psEncCtrl->Lambda_Q10, psEncCtrl->LTP_scale_Q14 ); + } else { + silk_NSQ( &psEnc->sCmn, &sNSQ_LBRR, psIndices_LBRR, xfw, + psEnc->sCmn.pulses_LBRR[ psEnc->sCmn.nFramesEncoded ], psEncCtrl->PredCoef_Q12[ 0 ], psEncCtrl->LTPCoef_Q14, + psEncCtrl->AR2_Q13, psEncCtrl->HarmShapeGain_Q14, psEncCtrl->Tilt_Q14, psEncCtrl->LF_shp_Q14, + psEncCtrl->Gains_Q16, psEncCtrl->pitchL, psEncCtrl->Lambda_Q10, psEncCtrl->LTP_scale_Q14 ); + } + + /* Restore original gains */ + SKP_memcpy( psEncCtrl->Gains_Q16, TempGains_Q16, psEnc->sCmn.nb_subfr * sizeof( opus_int32 ) ); + } +} diff --git a/silk/fixed/silk_find_LPC_FIX.c b/silk/fixed/silk_find_LPC_FIX.c index f1a0434f9..02a4318ea 100644 --- a/silk/fixed/silk_find_LPC_FIX.c +++ b/silk/fixed/silk_find_LPC_FIX.c @@ -1,157 +1,157 @@ -/*********************************************************************** -Copyright (c) 2006-2011, Skype Limited. All rights reserved. -Redistribution and use in source and binary forms, with or without -modification, (subject to the limitations in the disclaimer below) -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 Skype Limited, nor the names of specific -contributors, may be used to endorse or promote products derived from -this software without specific prior written permission. -NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED -BY THIS LICENSE. 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. -***********************************************************************/ - -#include "silk_main_FIX.h" -#include "silk_tuning_parameters.h" - -/* Finds LPC vector from correlations, and converts to NLSF */ -void silk_find_LPC_FIX( - opus_int16 NLSF_Q15[], /* O NLSFs */ - opus_int8 *interpIndex, /* O NLSF interpolation index, only used for NLSF interpolation */ - const opus_int16 prev_NLSFq_Q15[], /* I previous NLSFs, only used for NLSF interpolation */ - const opus_int useInterpNLSFs, /* I Flag */ - const opus_int firstFrameAfterReset, /* I Flag */ - const opus_int LPC_order, /* I LPC order */ - const opus_int16 x[], /* I Input signal */ - const opus_int subfr_length, /* I Input signal subframe length including preceeding samples */ - const opus_int nb_subfr /* I: Number of subframes */ -) -{ - opus_int k; - opus_int32 a_Q16[ MAX_LPC_ORDER ]; - opus_int isInterpLower, shift; - opus_int32 res_nrg0, res_nrg1; - opus_int rshift0, rshift1; - - /* Used only for LSF interpolation */ - opus_int32 a_tmp_Q16[ MAX_LPC_ORDER ], res_nrg_interp, res_nrg, res_tmp_nrg, res_nrg_2nd; - opus_int res_nrg_interp_Q, res_nrg_Q, res_tmp_nrg_Q, res_nrg_2nd_Q; - opus_int16 a_tmp_Q12[ MAX_LPC_ORDER ]; - opus_int16 NLSF0_Q15[ MAX_LPC_ORDER ]; - opus_int16 LPC_res[ ( MAX_FRAME_LENGTH + MAX_NB_SUBFR * MAX_LPC_ORDER ) / 2 ]; - - /* Default: no interpolation */ - *interpIndex = 4; - - /* Burg AR analysis for the full frame */ - silk_burg_modified( &res_nrg, &res_nrg_Q, a_Q16, x, subfr_length, nb_subfr, SILK_FIX_CONST( FIND_LPC_COND_FAC, 32 ), LPC_order ); - - if( firstFrameAfterReset ) { - silk_bwexpander_32( a_Q16, LPC_order, SILK_FIX_CONST( FIND_LPC_CHIRP_FIRST_FRAME, 16 ) ); - } else { - silk_bwexpander_32( a_Q16, LPC_order, SILK_FIX_CONST( FIND_LPC_CHIRP, 16 ) ); - } - - if( useInterpNLSFs && !firstFrameAfterReset && nb_subfr == MAX_NB_SUBFR ) { - - /* Optimal solution for last 10 ms */ - silk_burg_modified( &res_tmp_nrg, &res_tmp_nrg_Q, a_tmp_Q16, x + ( MAX_NB_SUBFR >> 1 ) * subfr_length, - subfr_length, ( MAX_NB_SUBFR >> 1 ), SILK_FIX_CONST( FIND_LPC_COND_FAC, 32 ), LPC_order ); - - silk_bwexpander_32( a_tmp_Q16, LPC_order, SILK_FIX_CONST( FIND_LPC_CHIRP, 16 ) ); - - /* 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 */ - shift = res_tmp_nrg_Q - res_nrg_Q; - if( shift >= 0 ) { - if( shift < 32 ) { - res_nrg = res_nrg - SKP_RSHIFT( res_tmp_nrg, shift ); - } - } else { - SKP_assert( shift > -32 ); - res_nrg = SKP_RSHIFT( res_nrg, -shift ) - res_tmp_nrg; - res_nrg_Q = res_tmp_nrg_Q; - } - - /* Convert to NLSFs */ - silk_A2NLSF( NLSF_Q15, a_tmp_Q16, LPC_order ); - - /* Search over interpolation indices to find the one with lowest residual energy */ - res_nrg_2nd = SKP_int32_MAX; - for( k = 3; k >= 0; k-- ) { - /* Interpolate NLSFs for first half */ - silk_interpolate( NLSF0_Q15, prev_NLSFq_Q15, NLSF_Q15, k, LPC_order ); - - /* Convert to LPC for residual energy evaluation */ - silk_NLSF2A( a_tmp_Q12, NLSF0_Q15, LPC_order ); - - /* Calculate residual energy with NLSF interpolation */ - silk_LPC_analysis_filter( LPC_res, x, a_tmp_Q12, 2 * subfr_length, LPC_order ); - - silk_sum_sqr_shift( &res_nrg0, &rshift0, LPC_res + LPC_order, subfr_length - LPC_order ); - silk_sum_sqr_shift( &res_nrg1, &rshift1, LPC_res + LPC_order + subfr_length, subfr_length - LPC_order ); - - /* Add subframe energies from first half frame */ - shift = rshift0 - rshift1; - if( shift >= 0 ) { - res_nrg1 = SKP_RSHIFT( res_nrg1, shift ); - res_nrg_interp_Q = -rshift0; - } else { - res_nrg0 = SKP_RSHIFT( res_nrg0, -shift ); - res_nrg_interp_Q = -rshift1; - } - res_nrg_interp = SKP_ADD32( res_nrg0, res_nrg1 ); - - /* Compare with first half energy without NLSF interpolation, or best interpolated value so far */ - shift = res_nrg_interp_Q - res_nrg_Q; - if( shift >= 0 ) { - if( SKP_RSHIFT( res_nrg_interp, shift ) < res_nrg ) { - isInterpLower = SKP_TRUE; - } else { - isInterpLower = SKP_FALSE; - } - } else { - if( -shift < 32 ) { - if( res_nrg_interp < SKP_RSHIFT( res_nrg, -shift ) ) { - isInterpLower = SKP_TRUE; - } else { - isInterpLower = SKP_FALSE; - } - } else { - isInterpLower = SKP_FALSE; - } - } - - /* Determine whether current interpolated NLSFs are best so far */ - if( isInterpLower == SKP_TRUE ) { - /* Interpolation has lower residual energy */ - res_nrg = res_nrg_interp; - res_nrg_Q = res_nrg_interp_Q; - *interpIndex = (opus_int8)k; - } - res_nrg_2nd = res_nrg_interp; - res_nrg_2nd_Q = res_nrg_interp_Q; - } - } - - if( *interpIndex == 4 ) { - /* NLSF interpolation is currently inactive, calculate NLSFs from full frame AR coefficients */ - silk_A2NLSF( NLSF_Q15, a_Q16, LPC_order ); - } - - SKP_assert( *interpIndex == 4 || ( useInterpNLSFs && !firstFrameAfterReset && nb_subfr == MAX_NB_SUBFR ) ); -} +/*********************************************************************** +Copyright (c) 2006-2011, Skype Limited. All rights reserved. +Redistribution and use in source and binary forms, with or without +modification, (subject to the limitations in the disclaimer below) +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 Skype Limited, nor the names of specific +contributors, may be used to endorse or promote products derived from +this software without specific prior written permission. +NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED +BY THIS LICENSE. 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. +***********************************************************************/ + +#include "silk_main_FIX.h" +#include "silk_tuning_parameters.h" + +/* Finds LPC vector from correlations, and converts to NLSF */ +void silk_find_LPC_FIX( + opus_int16 NLSF_Q15[], /* O NLSFs */ + opus_int8 *interpIndex, /* O NLSF interpolation index, only used for NLSF interpolation */ + const opus_int16 prev_NLSFq_Q15[], /* I previous NLSFs, only used for NLSF interpolation */ + const opus_int useInterpNLSFs, /* I Flag */ + const opus_int firstFrameAfterReset, /* I Flag */ + const opus_int LPC_order, /* I LPC order */ + const opus_int16 x[], /* I Input signal */ + const opus_int subfr_length, /* I Input signal subframe length including preceeding samples */ + const opus_int nb_subfr /* I: Number of subframes */ +) +{ + opus_int k; + opus_int32 a_Q16[ MAX_LPC_ORDER ]; + opus_int isInterpLower, shift; + opus_int32 res_nrg0, res_nrg1; + opus_int rshift0, rshift1; + + /* Used only for LSF interpolation */ + opus_int32 a_tmp_Q16[ MAX_LPC_ORDER ], res_nrg_interp, res_nrg, res_tmp_nrg, res_nrg_2nd; + opus_int res_nrg_interp_Q, res_nrg_Q, res_tmp_nrg_Q, res_nrg_2nd_Q; + opus_int16 a_tmp_Q12[ MAX_LPC_ORDER ]; + opus_int16 NLSF0_Q15[ MAX_LPC_ORDER ]; + opus_int16 LPC_res[ ( MAX_FRAME_LENGTH + MAX_NB_SUBFR * MAX_LPC_ORDER ) / 2 ]; + + /* Default: no interpolation */ + *interpIndex = 4; + + /* Burg AR analysis for the full frame */ + silk_burg_modified( &res_nrg, &res_nrg_Q, a_Q16, x, subfr_length, nb_subfr, SILK_FIX_CONST( FIND_LPC_COND_FAC, 32 ), LPC_order ); + + if( firstFrameAfterReset ) { + silk_bwexpander_32( a_Q16, LPC_order, SILK_FIX_CONST( FIND_LPC_CHIRP_FIRST_FRAME, 16 ) ); + } else { + silk_bwexpander_32( a_Q16, LPC_order, SILK_FIX_CONST( FIND_LPC_CHIRP, 16 ) ); + } + + if( useInterpNLSFs && !firstFrameAfterReset && nb_subfr == MAX_NB_SUBFR ) { + + /* Optimal solution for last 10 ms */ + silk_burg_modified( &res_tmp_nrg, &res_tmp_nrg_Q, a_tmp_Q16, x + ( MAX_NB_SUBFR >> 1 ) * subfr_length, + subfr_length, ( MAX_NB_SUBFR >> 1 ), SILK_FIX_CONST( FIND_LPC_COND_FAC, 32 ), LPC_order ); + + silk_bwexpander_32( a_tmp_Q16, LPC_order, SILK_FIX_CONST( FIND_LPC_CHIRP, 16 ) ); + + /* 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 */ + shift = res_tmp_nrg_Q - res_nrg_Q; + if( shift >= 0 ) { + if( shift < 32 ) { + res_nrg = res_nrg - SKP_RSHIFT( res_tmp_nrg, shift ); + } + } else { + SKP_assert( shift > -32 ); + res_nrg = SKP_RSHIFT( res_nrg, -shift ) - res_tmp_nrg; + res_nrg_Q = res_tmp_nrg_Q; + } + + /* Convert to NLSFs */ + silk_A2NLSF( NLSF_Q15, a_tmp_Q16, LPC_order ); + + /* Search over interpolation indices to find the one with lowest residual energy */ + res_nrg_2nd = SKP_int32_MAX; + for( k = 3; k >= 0; k-- ) { + /* Interpolate NLSFs for first half */ + silk_interpolate( NLSF0_Q15, prev_NLSFq_Q15, NLSF_Q15, k, LPC_order ); + + /* Convert to LPC for residual energy evaluation */ + silk_NLSF2A( a_tmp_Q12, NLSF0_Q15, LPC_order ); + + /* Calculate residual energy with NLSF interpolation */ + silk_LPC_analysis_filter( LPC_res, x, a_tmp_Q12, 2 * subfr_length, LPC_order ); + + silk_sum_sqr_shift( &res_nrg0, &rshift0, LPC_res + LPC_order, subfr_length - LPC_order ); + silk_sum_sqr_shift( &res_nrg1, &rshift1, LPC_res + LPC_order + subfr_length, subfr_length - LPC_order ); + + /* Add subframe energies from first half frame */ + shift = rshift0 - rshift1; + if( shift >= 0 ) { + res_nrg1 = SKP_RSHIFT( res_nrg1, shift ); + res_nrg_interp_Q = -rshift0; + } else { + res_nrg0 = SKP_RSHIFT( res_nrg0, -shift ); + res_nrg_interp_Q = -rshift1; + } + res_nrg_interp = SKP_ADD32( res_nrg0, res_nrg1 ); + + /* Compare with first half energy without NLSF interpolation, or best interpolated value so far */ + shift = res_nrg_interp_Q - res_nrg_Q; + if( shift >= 0 ) { + if( SKP_RSHIFT( res_nrg_interp, shift ) < res_nrg ) { + isInterpLower = SKP_TRUE; + } else { + isInterpLower = SKP_FALSE; + } + } else { + if( -shift < 32 ) { + if( res_nrg_interp < SKP_RSHIFT( res_nrg, -shift ) ) { + isInterpLower = SKP_TRUE; + } else { + isInterpLower = SKP_FALSE; + } + } else { + isInterpLower = SKP_FALSE; + } + } + + /* Determine whether current interpolated NLSFs are best so far */ + if( isInterpLower == SKP_TRUE ) { + /* Interpolation has lower residual energy */ + res_nrg = res_nrg_interp; + res_nrg_Q = res_nrg_interp_Q; + *interpIndex = (opus_int8)k; + } + res_nrg_2nd = res_nrg_interp; + res_nrg_2nd_Q = res_nrg_interp_Q; + } + } + + if( *interpIndex == 4 ) { + /* NLSF interpolation is currently inactive, calculate NLSFs from full frame AR coefficients */ + silk_A2NLSF( NLSF_Q15, a_Q16, LPC_order ); + } + + SKP_assert( *interpIndex == 4 || ( useInterpNLSFs && !firstFrameAfterReset && nb_subfr == MAX_NB_SUBFR ) ); +} diff --git a/silk/fixed/silk_find_LTP_FIX.c b/silk/fixed/silk_find_LTP_FIX.c index e88dda4da..657462d94 100644 --- a/silk/fixed/silk_find_LTP_FIX.c +++ b/silk/fixed/silk_find_LTP_FIX.c @@ -1,241 +1,241 @@ -/*********************************************************************** -Copyright (c) 2006-2011, Skype Limited. All rights reserved. -Redistribution and use in source and binary forms, with or without -modification, (subject to the limitations in the disclaimer below) -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 Skype Limited, nor the names of specific -contributors, may be used to endorse or promote products derived from -this software without specific prior written permission. -NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED -BY THIS LICENSE. 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. -***********************************************************************/ - -#include "silk_main_FIX.h" -#include "silk_tuning_parameters.h" - -/* Head room for correlations */ -#define LTP_CORRS_HEAD_ROOM 2 - -void silk_fit_LTP( - opus_int32 LTP_coefs_Q16[ LTP_ORDER ], - opus_int16 LTP_coefs_Q14[ LTP_ORDER ] -); - -void silk_find_LTP_FIX( - opus_int16 b_Q14[ MAX_NB_SUBFR * LTP_ORDER ], /* O LTP coefs */ - opus_int32 WLTP[ MAX_NB_SUBFR * LTP_ORDER * LTP_ORDER ], /* O Weight for LTP quantization */ - opus_int *LTPredCodGain_Q7, /* O LTP coding gain */ - const opus_int16 r_lpc[] , /* I residual signal after LPC signal + state for first 10 ms */ - const opus_int lag[ MAX_NB_SUBFR ], /* I LTP lags */ - const opus_int32 Wght_Q15[ MAX_NB_SUBFR ], /* I weights */ - const opus_int subfr_length, /* I subframe length */ - const opus_int nb_subfr, /* I number of subframes */ - const opus_int mem_offset, /* I number of samples in LTP memory */ - opus_int corr_rshifts[ MAX_NB_SUBFR ] /* O right shifts applied to correlations */ -) -{ - opus_int i, k, lshift; - const opus_int16 *r_ptr, *lag_ptr; - opus_int16 *b_Q14_ptr; - - opus_int32 regu; - opus_int32 *WLTP_ptr; - opus_int32 b_Q16[ LTP_ORDER ], delta_b_Q14[ LTP_ORDER ], d_Q14[ MAX_NB_SUBFR ], nrg[ MAX_NB_SUBFR ], g_Q26; - opus_int32 w[ MAX_NB_SUBFR ], WLTP_max, max_abs_d_Q14, max_w_bits; - - opus_int32 temp32, denom32; - opus_int extra_shifts; - opus_int rr_shifts, maxRshifts, maxRshifts_wxtra, LZs; - opus_int32 LPC_res_nrg, LPC_LTP_res_nrg, div_Q16; - opus_int32 Rr[ LTP_ORDER ], rr[ MAX_NB_SUBFR ]; - opus_int32 wd, m_Q12; - - b_Q14_ptr = b_Q14; - WLTP_ptr = WLTP; - r_ptr = &r_lpc[ mem_offset ]; - for( k = 0; k < nb_subfr; k++ ) { - lag_ptr = r_ptr - ( lag[ k ] + LTP_ORDER / 2 ); - - silk_sum_sqr_shift( &rr[ k ], &rr_shifts, r_ptr, subfr_length ); /* rr[ k ] in Q( -rr_shifts ) */ - - /* Assure headroom */ - LZs = silk_CLZ32( rr[k] ); - if( LZs < LTP_CORRS_HEAD_ROOM ) { - rr[ k ] = SKP_RSHIFT_ROUND( rr[ k ], LTP_CORRS_HEAD_ROOM - LZs ); - rr_shifts += ( LTP_CORRS_HEAD_ROOM - LZs ); - } - corr_rshifts[ k ] = rr_shifts; - silk_corrMatrix_FIX( lag_ptr, subfr_length, LTP_ORDER, LTP_CORRS_HEAD_ROOM, WLTP_ptr, &corr_rshifts[ k ] ); /* WLTP_fix_ptr in Q( -corr_rshifts[ k ] ) */ - - /* The correlation vector always has lower max abs value than rr and/or RR so head room is assured */ - silk_corrVector_FIX( lag_ptr, r_ptr, subfr_length, LTP_ORDER, Rr, corr_rshifts[ k ] ); /* Rr_fix_ptr in Q( -corr_rshifts[ k ] ) */ - if( corr_rshifts[ k ] > rr_shifts ) { - rr[ k ] = SKP_RSHIFT( rr[ k ], corr_rshifts[ k ] - rr_shifts ); /* rr[ k ] in Q( -corr_rshifts[ k ] ) */ - } - SKP_assert( rr[ k ] >= 0 ); - - regu = 1; - regu = SKP_SMLAWB( regu, rr[ k ], SILK_FIX_CONST( LTP_DAMPING/3, 16 ) ); - regu = SKP_SMLAWB( regu, matrix_ptr( WLTP_ptr, 0, 0, LTP_ORDER ), SILK_FIX_CONST( LTP_DAMPING/3, 16 ) ); - regu = SKP_SMLAWB( regu, matrix_ptr( WLTP_ptr, LTP_ORDER-1, LTP_ORDER-1, LTP_ORDER ), SILK_FIX_CONST( LTP_DAMPING/3, 16 ) ); - silk_regularize_correlations_FIX( WLTP_ptr, &rr[k], regu, LTP_ORDER ); - - silk_solve_LDL_FIX( WLTP_ptr, LTP_ORDER, Rr, b_Q16 ); /* WLTP_fix_ptr and Rr_fix_ptr both in Q(-corr_rshifts[k]) */ - - /* Limit and store in Q14 */ - silk_fit_LTP( b_Q16, b_Q14_ptr ); - - /* Calculate residual energy */ - nrg[ k ] = silk_residual_energy16_covar_FIX( b_Q14_ptr, WLTP_ptr, Rr, rr[ k ], LTP_ORDER, 14 ); /* nrg_fix in Q( -corr_rshifts[ k ] ) */ - - /* temp = Wght[ k ] / ( nrg[ k ] * Wght[ k ] + 0.01f * subfr_length ); */ - extra_shifts = SKP_min_int( corr_rshifts[ k ], LTP_CORRS_HEAD_ROOM ); - denom32 = SKP_LSHIFT_SAT32( SKP_SMULWB( nrg[ k ], Wght_Q15[ k ] ), 1 + extra_shifts ) + /* Q( -corr_rshifts[ k ] + extra_shifts ) */ - SKP_RSHIFT( SKP_SMULWB( subfr_length, 655 ), corr_rshifts[ k ] - extra_shifts ); /* Q( -corr_rshifts[ k ] + extra_shifts ) */ - denom32 = SKP_max( denom32, 1 ); - SKP_assert( ((opus_int64)Wght_Q15[ k ] << 16 ) < SKP_int32_MAX ); /* Wght always < 0.5 in Q0 */ - temp32 = SKP_DIV32( SKP_LSHIFT( ( opus_int32 )Wght_Q15[ k ], 16 ), denom32 ); /* Q( 15 + 16 + corr_rshifts[k] - extra_shifts ) */ - temp32 = SKP_RSHIFT( temp32, 31 + corr_rshifts[ k ] - extra_shifts - 26 ); /* Q26 */ - - /* Limit temp such that the below scaling never wraps around */ - WLTP_max = 0; - for( i = 0; i < LTP_ORDER * LTP_ORDER; i++ ) { - WLTP_max = SKP_max( WLTP_ptr[ i ], WLTP_max ); - } - lshift = silk_CLZ32( WLTP_max ) - 1 - 3; /* keep 3 bits free for vq_nearest_neighbor_fix */ - SKP_assert( 26 - 18 + lshift >= 0 ); - if( 26 - 18 + lshift < 31 ) { - temp32 = SKP_min_32( temp32, SKP_LSHIFT( ( opus_int32 )1, 26 - 18 + lshift ) ); - } - - silk_scale_vector32_Q26_lshift_18( WLTP_ptr, temp32, LTP_ORDER * LTP_ORDER ); /* WLTP_ptr in Q( 18 - corr_rshifts[ k ] ) */ - - w[ k ] = matrix_ptr( WLTP_ptr, LTP_ORDER/2, LTP_ORDER/2, LTP_ORDER ); /* w in Q( 18 - corr_rshifts[ k ] ) */ - SKP_assert( w[k] >= 0 ); - - r_ptr += subfr_length; - b_Q14_ptr += LTP_ORDER; - WLTP_ptr += LTP_ORDER * LTP_ORDER; - } - - maxRshifts = 0; - for( k = 0; k < nb_subfr; k++ ) { - maxRshifts = SKP_max_int( corr_rshifts[ k ], maxRshifts ); - } - - /* Compute LTP coding gain */ - if( LTPredCodGain_Q7 != NULL ) { - LPC_LTP_res_nrg = 0; - LPC_res_nrg = 0; - SKP_assert( LTP_CORRS_HEAD_ROOM >= 2 ); /* Check that no overflow will happen when adding */ - for( k = 0; k < nb_subfr; k++ ) { - LPC_res_nrg = SKP_ADD32( LPC_res_nrg, SKP_RSHIFT( SKP_ADD32( SKP_SMULWB( rr[ k ], Wght_Q15[ k ] ), 1 ), 1 + ( maxRshifts - corr_rshifts[ k ] ) ) ); /* Q( -maxRshifts ) */ - LPC_LTP_res_nrg = SKP_ADD32( LPC_LTP_res_nrg, SKP_RSHIFT( SKP_ADD32( SKP_SMULWB( nrg[ k ], Wght_Q15[ k ] ), 1 ), 1 + ( maxRshifts - corr_rshifts[ k ] ) ) ); /* Q( -maxRshifts ) */ - } - LPC_LTP_res_nrg = SKP_max( LPC_LTP_res_nrg, 1 ); /* avoid division by zero */ - - div_Q16 = silk_DIV32_varQ( LPC_res_nrg, LPC_LTP_res_nrg, 16 ); - *LTPredCodGain_Q7 = ( opus_int )SKP_SMULBB( 3, silk_lin2log( div_Q16 ) - ( 16 << 7 ) ); - - SKP_assert( *LTPredCodGain_Q7 == ( opus_int )SKP_SAT16( SKP_MUL( 3, silk_lin2log( div_Q16 ) - ( 16 << 7 ) ) ) ); - } - - /* smoothing */ - /* d = sum( B, 1 ); */ - b_Q14_ptr = b_Q14; - for( k = 0; k < nb_subfr; k++ ) { - d_Q14[ k ] = 0; - for( i = 0; i < LTP_ORDER; i++ ) { - d_Q14[ k ] += b_Q14_ptr[ i ]; - } - b_Q14_ptr += LTP_ORDER; - } - - /* m = ( w * d' ) / ( sum( w ) + 1e-3 ); */ - - /* Find maximum absolute value of d_Q14 and the bits used by w in Q0 */ - max_abs_d_Q14 = 0; - max_w_bits = 0; - for( k = 0; k < nb_subfr; k++ ) { - max_abs_d_Q14 = SKP_max_32( max_abs_d_Q14, SKP_abs( d_Q14[ k ] ) ); - /* w[ k ] is in Q( 18 - corr_rshifts[ k ] ) */ - /* Find bits needed in Q( 18 - maxRshifts ) */ - max_w_bits = SKP_max_32( max_w_bits, 32 - silk_CLZ32( w[ k ] ) + corr_rshifts[ k ] - maxRshifts ); - } - - /* max_abs_d_Q14 = (5 << 15); worst case, i.e. LTP_ORDER * -SKP_int16_MIN */ - SKP_assert( max_abs_d_Q14 <= ( 5 << 15 ) ); - - /* How many bits is needed for w*d' in Q( 18 - maxRshifts ) in the worst case, of all d_Q14's being equal to max_abs_d_Q14 */ - extra_shifts = max_w_bits + 32 - silk_CLZ32( max_abs_d_Q14 ) - 14; - - /* Subtract what we got available; bits in output var plus maxRshifts */ - extra_shifts -= ( 32 - 1 - 2 + maxRshifts ); /* Keep sign bit free as well as 2 bits for accumulation */ - extra_shifts = SKP_max_int( extra_shifts, 0 ); - - maxRshifts_wxtra = maxRshifts + extra_shifts; - - temp32 = SKP_RSHIFT( 262, maxRshifts + extra_shifts ) + 1; /* 1e-3f in Q( 18 - (maxRshifts + extra_shifts) ) */ - wd = 0; - for( k = 0; k < nb_subfr; k++ ) { - /* w has at least 2 bits of headroom so no overflow should happen */ - temp32 = SKP_ADD32( temp32, SKP_RSHIFT( w[ k ], maxRshifts_wxtra - corr_rshifts[ k ] ) ); /* Q( 18 - maxRshifts_wxtra ) */ - wd = SKP_ADD32( wd, SKP_LSHIFT( SKP_SMULWW( SKP_RSHIFT( w[ k ], maxRshifts_wxtra - corr_rshifts[ k ] ), d_Q14[ k ] ), 2 ) ); /* Q( 18 - maxRshifts_wxtra ) */ - } - m_Q12 = silk_DIV32_varQ( wd, temp32, 12 ); - - b_Q14_ptr = b_Q14; - for( k = 0; k < nb_subfr; k++ ) { - /* w_fix[ k ] from Q( 18 - corr_rshifts[ k ] ) to Q( 16 ) */ - if( 2 - corr_rshifts[k] > 0 ) { - temp32 = SKP_RSHIFT( w[ k ], 2 - corr_rshifts[ k ] ); - } else { - temp32 = SKP_LSHIFT_SAT32( w[ k ], corr_rshifts[ k ] - 2 ); - } - - g_Q26 = SKP_MUL( - SKP_DIV32( - SILK_FIX_CONST( LTP_SMOOTHING, 26 ), - SKP_RSHIFT( SILK_FIX_CONST( LTP_SMOOTHING, 26 ), 10 ) + temp32 ), /* Q10 */ - SKP_LSHIFT_SAT32( SKP_SUB_SAT32( ( opus_int32 )m_Q12, SKP_RSHIFT( d_Q14[ k ], 2 ) ), 4 ) ); /* Q16 */ - - temp32 = 0; - for( i = 0; i < LTP_ORDER; i++ ) { - delta_b_Q14[ i ] = SKP_max_16( b_Q14_ptr[ i ], 1638 ); /* 1638_Q14 = 0.1_Q0 */ - temp32 += delta_b_Q14[ i ]; /* Q14 */ - } - temp32 = SKP_DIV32( g_Q26, temp32 ); /* Q14->Q12 */ - for( i = 0; i < LTP_ORDER; i++ ) { - b_Q14_ptr[ i ] = SKP_LIMIT_32( ( opus_int32 )b_Q14_ptr[ i ] + SKP_SMULWB( SKP_LSHIFT_SAT32( temp32, 4 ), delta_b_Q14[ i ] ), -16000, 28000 ); - } - b_Q14_ptr += LTP_ORDER; - } -TOC(find_LTP_FIX) -} - -void silk_fit_LTP( - opus_int32 LTP_coefs_Q16[ LTP_ORDER ], - opus_int16 LTP_coefs_Q14[ LTP_ORDER ] -) -{ - opus_int i; - - for( i = 0; i < LTP_ORDER; i++ ) { - LTP_coefs_Q14[ i ] = ( opus_int16 )SKP_SAT16( SKP_RSHIFT_ROUND( LTP_coefs_Q16[ i ], 2 ) ); - } -} +/*********************************************************************** +Copyright (c) 2006-2011, Skype Limited. All rights reserved. +Redistribution and use in source and binary forms, with or without +modification, (subject to the limitations in the disclaimer below) +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 Skype Limited, nor the names of specific +contributors, may be used to endorse or promote products derived from +this software without specific prior written permission. +NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED +BY THIS LICENSE. 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. +***********************************************************************/ + +#include "silk_main_FIX.h" +#include "silk_tuning_parameters.h" + +/* Head room for correlations */ +#define LTP_CORRS_HEAD_ROOM 2 + +void silk_fit_LTP( + opus_int32 LTP_coefs_Q16[ LTP_ORDER ], + opus_int16 LTP_coefs_Q14[ LTP_ORDER ] +); + +void silk_find_LTP_FIX( + opus_int16 b_Q14[ MAX_NB_SUBFR * LTP_ORDER ], /* O LTP coefs */ + opus_int32 WLTP[ MAX_NB_SUBFR * LTP_ORDER * LTP_ORDER ], /* O Weight for LTP quantization */ + opus_int *LTPredCodGain_Q7, /* O LTP coding gain */ + const opus_int16 r_lpc[] , /* I residual signal after LPC signal + state for first 10 ms */ + const opus_int lag[ MAX_NB_SUBFR ], /* I LTP lags */ + const opus_int32 Wght_Q15[ MAX_NB_SUBFR ], /* I weights */ + const opus_int subfr_length, /* I subframe length */ + const opus_int nb_subfr, /* I number of subframes */ + const opus_int mem_offset, /* I number of samples in LTP memory */ + opus_int corr_rshifts[ MAX_NB_SUBFR ] /* O right shifts applied to correlations */ +) +{ + opus_int i, k, lshift; + const opus_int16 *r_ptr, *lag_ptr; + opus_int16 *b_Q14_ptr; + + opus_int32 regu; + opus_int32 *WLTP_ptr; + opus_int32 b_Q16[ LTP_ORDER ], delta_b_Q14[ LTP_ORDER ], d_Q14[ MAX_NB_SUBFR ], nrg[ MAX_NB_SUBFR ], g_Q26; + opus_int32 w[ MAX_NB_SUBFR ], WLTP_max, max_abs_d_Q14, max_w_bits; + + opus_int32 temp32, denom32; + opus_int extra_shifts; + opus_int rr_shifts, maxRshifts, maxRshifts_wxtra, LZs; + opus_int32 LPC_res_nrg, LPC_LTP_res_nrg, div_Q16; + opus_int32 Rr[ LTP_ORDER ], rr[ MAX_NB_SUBFR ]; + opus_int32 wd, m_Q12; + + b_Q14_ptr = b_Q14; + WLTP_ptr = WLTP; + r_ptr = &r_lpc[ mem_offset ]; + for( k = 0; k < nb_subfr; k++ ) { + lag_ptr = r_ptr - ( lag[ k ] + LTP_ORDER / 2 ); + + silk_sum_sqr_shift( &rr[ k ], &rr_shifts, r_ptr, subfr_length ); /* rr[ k ] in Q( -rr_shifts ) */ + + /* Assure headroom */ + LZs = silk_CLZ32( rr[k] ); + if( LZs < LTP_CORRS_HEAD_ROOM ) { + rr[ k ] = SKP_RSHIFT_ROUND( rr[ k ], LTP_CORRS_HEAD_ROOM - LZs ); + rr_shifts += ( LTP_CORRS_HEAD_ROOM - LZs ); + } + corr_rshifts[ k ] = rr_shifts; + silk_corrMatrix_FIX( lag_ptr, subfr_length, LTP_ORDER, LTP_CORRS_HEAD_ROOM, WLTP_ptr, &corr_rshifts[ k ] ); /* WLTP_fix_ptr in Q( -corr_rshifts[ k ] ) */ + + /* The correlation vector always has lower max abs value than rr and/or RR so head room is assured */ + silk_corrVector_FIX( lag_ptr, r_ptr, subfr_length, LTP_ORDER, Rr, corr_rshifts[ k ] ); /* Rr_fix_ptr in Q( -corr_rshifts[ k ] ) */ + if( corr_rshifts[ k ] > rr_shifts ) { + rr[ k ] = SKP_RSHIFT( rr[ k ], corr_rshifts[ k ] - rr_shifts ); /* rr[ k ] in Q( -corr_rshifts[ k ] ) */ + } + SKP_assert( rr[ k ] >= 0 ); + + regu = 1; + regu = SKP_SMLAWB( regu, rr[ k ], SILK_FIX_CONST( LTP_DAMPING/3, 16 ) ); + regu = SKP_SMLAWB( regu, matrix_ptr( WLTP_ptr, 0, 0, LTP_ORDER ), SILK_FIX_CONST( LTP_DAMPING/3, 16 ) ); + regu = SKP_SMLAWB( regu, matrix_ptr( WLTP_ptr, LTP_ORDER-1, LTP_ORDER-1, LTP_ORDER ), SILK_FIX_CONST( LTP_DAMPING/3, 16 ) ); + silk_regularize_correlations_FIX( WLTP_ptr, &rr[k], regu, LTP_ORDER ); + + silk_solve_LDL_FIX( WLTP_ptr, LTP_ORDER, Rr, b_Q16 ); /* WLTP_fix_ptr and Rr_fix_ptr both in Q(-corr_rshifts[k]) */ + + /* Limit and store in Q14 */ + silk_fit_LTP( b_Q16, b_Q14_ptr ); + + /* Calculate residual energy */ + nrg[ k ] = silk_residual_energy16_covar_FIX( b_Q14_ptr, WLTP_ptr, Rr, rr[ k ], LTP_ORDER, 14 ); /* nrg_fix in Q( -corr_rshifts[ k ] ) */ + + /* temp = Wght[ k ] / ( nrg[ k ] * Wght[ k ] + 0.01f * subfr_length ); */ + extra_shifts = SKP_min_int( corr_rshifts[ k ], LTP_CORRS_HEAD_ROOM ); + denom32 = SKP_LSHIFT_SAT32( SKP_SMULWB( nrg[ k ], Wght_Q15[ k ] ), 1 + extra_shifts ) + /* Q( -corr_rshifts[ k ] + extra_shifts ) */ + SKP_RSHIFT( SKP_SMULWB( subfr_length, 655 ), corr_rshifts[ k ] - extra_shifts ); /* Q( -corr_rshifts[ k ] + extra_shifts ) */ + denom32 = SKP_max( denom32, 1 ); + SKP_assert( ((opus_int64)Wght_Q15[ k ] << 16 ) < SKP_int32_MAX ); /* Wght always < 0.5 in Q0 */ + temp32 = SKP_DIV32( SKP_LSHIFT( ( opus_int32 )Wght_Q15[ k ], 16 ), denom32 ); /* Q( 15 + 16 + corr_rshifts[k] - extra_shifts ) */ + temp32 = SKP_RSHIFT( temp32, 31 + corr_rshifts[ k ] - extra_shifts - 26 ); /* Q26 */ + + /* Limit temp such that the below scaling never wraps around */ + WLTP_max = 0; + for( i = 0; i < LTP_ORDER * LTP_ORDER; i++ ) { + WLTP_max = SKP_max( WLTP_ptr[ i ], WLTP_max ); + } + lshift = silk_CLZ32( WLTP_max ) - 1 - 3; /* keep 3 bits free for vq_nearest_neighbor_fix */ + SKP_assert( 26 - 18 + lshift >= 0 ); + if( 26 - 18 + lshift < 31 ) { + temp32 = SKP_min_32( temp32, SKP_LSHIFT( ( opus_int32 )1, 26 - 18 + lshift ) ); + } + + silk_scale_vector32_Q26_lshift_18( WLTP_ptr, temp32, LTP_ORDER * LTP_ORDER ); /* WLTP_ptr in Q( 18 - corr_rshifts[ k ] ) */ + + w[ k ] = matrix_ptr( WLTP_ptr, LTP_ORDER/2, LTP_ORDER/2, LTP_ORDER ); /* w in Q( 18 - corr_rshifts[ k ] ) */ + SKP_assert( w[k] >= 0 ); + + r_ptr += subfr_length; + b_Q14_ptr += LTP_ORDER; + WLTP_ptr += LTP_ORDER * LTP_ORDER; + } + + maxRshifts = 0; + for( k = 0; k < nb_subfr; k++ ) { + maxRshifts = SKP_max_int( corr_rshifts[ k ], maxRshifts ); + } + + /* Compute LTP coding gain */ + if( LTPredCodGain_Q7 != NULL ) { + LPC_LTP_res_nrg = 0; + LPC_res_nrg = 0; + SKP_assert( LTP_CORRS_HEAD_ROOM >= 2 ); /* Check that no overflow will happen when adding */ + for( k = 0; k < nb_subfr; k++ ) { + LPC_res_nrg = SKP_ADD32( LPC_res_nrg, SKP_RSHIFT( SKP_ADD32( SKP_SMULWB( rr[ k ], Wght_Q15[ k ] ), 1 ), 1 + ( maxRshifts - corr_rshifts[ k ] ) ) ); /* Q( -maxRshifts ) */ + LPC_LTP_res_nrg = SKP_ADD32( LPC_LTP_res_nrg, SKP_RSHIFT( SKP_ADD32( SKP_SMULWB( nrg[ k ], Wght_Q15[ k ] ), 1 ), 1 + ( maxRshifts - corr_rshifts[ k ] ) ) ); /* Q( -maxRshifts ) */ + } + LPC_LTP_res_nrg = SKP_max( LPC_LTP_res_nrg, 1 ); /* avoid division by zero */ + + div_Q16 = silk_DIV32_varQ( LPC_res_nrg, LPC_LTP_res_nrg, 16 ); + *LTPredCodGain_Q7 = ( opus_int )SKP_SMULBB( 3, silk_lin2log( div_Q16 ) - ( 16 << 7 ) ); + + SKP_assert( *LTPredCodGain_Q7 == ( opus_int )SKP_SAT16( SKP_MUL( 3, silk_lin2log( div_Q16 ) - ( 16 << 7 ) ) ) ); + } + + /* smoothing */ + /* d = sum( B, 1 ); */ + b_Q14_ptr = b_Q14; + for( k = 0; k < nb_subfr; k++ ) { + d_Q14[ k ] = 0; + for( i = 0; i < LTP_ORDER; i++ ) { + d_Q14[ k ] += b_Q14_ptr[ i ]; + } + b_Q14_ptr += LTP_ORDER; + } + + /* m = ( w * d' ) / ( sum( w ) + 1e-3 ); */ + + /* Find maximum absolute value of d_Q14 and the bits used by w in Q0 */ + max_abs_d_Q14 = 0; + max_w_bits = 0; + for( k = 0; k < nb_subfr; k++ ) { + max_abs_d_Q14 = SKP_max_32( max_abs_d_Q14, SKP_abs( d_Q14[ k ] ) ); + /* w[ k ] is in Q( 18 - corr_rshifts[ k ] ) */ + /* Find bits needed in Q( 18 - maxRshifts ) */ + max_w_bits = SKP_max_32( max_w_bits, 32 - silk_CLZ32( w[ k ] ) + corr_rshifts[ k ] - maxRshifts ); + } + + /* max_abs_d_Q14 = (5 << 15); worst case, i.e. LTP_ORDER * -SKP_int16_MIN */ + SKP_assert( max_abs_d_Q14 <= ( 5 << 15 ) ); + + /* How many bits is needed for w*d' in Q( 18 - maxRshifts ) in the worst case, of all d_Q14's being equal to max_abs_d_Q14 */ + extra_shifts = max_w_bits + 32 - silk_CLZ32( max_abs_d_Q14 ) - 14; + + /* Subtract what we got available; bits in output var plus maxRshifts */ + extra_shifts -= ( 32 - 1 - 2 + maxRshifts ); /* Keep sign bit free as well as 2 bits for accumulation */ + extra_shifts = SKP_max_int( extra_shifts, 0 ); + + maxRshifts_wxtra = maxRshifts + extra_shifts; + + temp32 = SKP_RSHIFT( 262, maxRshifts + extra_shifts ) + 1; /* 1e-3f in Q( 18 - (maxRshifts + extra_shifts) ) */ + wd = 0; + for( k = 0; k < nb_subfr; k++ ) { + /* w has at least 2 bits of headroom so no overflow should happen */ + temp32 = SKP_ADD32( temp32, SKP_RSHIFT( w[ k ], maxRshifts_wxtra - corr_rshifts[ k ] ) ); /* Q( 18 - maxRshifts_wxtra ) */ + wd = SKP_ADD32( wd, SKP_LSHIFT( SKP_SMULWW( SKP_RSHIFT( w[ k ], maxRshifts_wxtra - corr_rshifts[ k ] ), d_Q14[ k ] ), 2 ) ); /* Q( 18 - maxRshifts_wxtra ) */ + } + m_Q12 = silk_DIV32_varQ( wd, temp32, 12 ); + + b_Q14_ptr = b_Q14; + for( k = 0; k < nb_subfr; k++ ) { + /* w_fix[ k ] from Q( 18 - corr_rshifts[ k ] ) to Q( 16 ) */ + if( 2 - corr_rshifts[k] > 0 ) { + temp32 = SKP_RSHIFT( w[ k ], 2 - corr_rshifts[ k ] ); + } else { + temp32 = SKP_LSHIFT_SAT32( w[ k ], corr_rshifts[ k ] - 2 ); + } + + g_Q26 = SKP_MUL( + SKP_DIV32( + SILK_FIX_CONST( LTP_SMOOTHING, 26 ), + SKP_RSHIFT( SILK_FIX_CONST( LTP_SMOOTHING, 26 ), 10 ) + temp32 ), /* Q10 */ + SKP_LSHIFT_SAT32( SKP_SUB_SAT32( ( opus_int32 )m_Q12, SKP_RSHIFT( d_Q14[ k ], 2 ) ), 4 ) ); /* Q16 */ + + temp32 = 0; + for( i = 0; i < LTP_ORDER; i++ ) { + delta_b_Q14[ i ] = SKP_max_16( b_Q14_ptr[ i ], 1638 ); /* 1638_Q14 = 0.1_Q0 */ + temp32 += delta_b_Q14[ i ]; /* Q14 */ + } + temp32 = SKP_DIV32( g_Q26, temp32 ); /* Q14->Q12 */ + for( i = 0; i < LTP_ORDER; i++ ) { + b_Q14_ptr[ i ] = SKP_LIMIT_32( ( opus_int32 )b_Q14_ptr[ i ] + SKP_SMULWB( SKP_LSHIFT_SAT32( temp32, 4 ), delta_b_Q14[ i ] ), -16000, 28000 ); + } + b_Q14_ptr += LTP_ORDER; + } +TOC(find_LTP_FIX) +} + +void silk_fit_LTP( + opus_int32 LTP_coefs_Q16[ LTP_ORDER ], + opus_int16 LTP_coefs_Q14[ LTP_ORDER ] +) +{ + opus_int i; + + for( i = 0; i < LTP_ORDER; i++ ) { + LTP_coefs_Q14[ i ] = ( opus_int16 )SKP_SAT16( SKP_RSHIFT_ROUND( LTP_coefs_Q16[ i ], 2 ) ); + } +} diff --git a/silk/fixed/silk_find_pitch_lags_FIX.c b/silk/fixed/silk_find_pitch_lags_FIX.c index 866f1d78c..5bda555b1 100644 --- a/silk/fixed/silk_find_pitch_lags_FIX.c +++ b/silk/fixed/silk_find_pitch_lags_FIX.c @@ -1,133 +1,133 @@ -/*********************************************************************** -Copyright (c) 2006-2011, Skype Limited. All rights reserved. -Redistribution and use in source and binary forms, with or without -modification, (subject to the limitations in the disclaimer below) -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 Skype Limited, nor the names of specific -contributors, may be used to endorse or promote products derived from -this software without specific prior written permission. -NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED -BY THIS LICENSE. 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. -***********************************************************************/ - -#include "silk_main_FIX.h" -#include "silk_tuning_parameters.h" - -/* Find pitch lags */ -void silk_find_pitch_lags_FIX( - silk_encoder_state_FIX *psEnc, /* I/O encoder state */ - silk_encoder_control_FIX *psEncCtrl, /* I/O encoder control */ - opus_int16 res[], /* O residual */ - const opus_int16 x[] /* I Speech signal */ -) -{ - opus_int buf_len, i, scale; - opus_int32 thrhld_Q15, res_nrg; - const opus_int16 *x_buf, *x_buf_ptr; - opus_int16 Wsig[ FIND_PITCH_LPC_WIN_MAX ], *Wsig_ptr; - opus_int32 auto_corr[ MAX_FIND_PITCH_LPC_ORDER + 1 ]; - opus_int16 rc_Q15[ MAX_FIND_PITCH_LPC_ORDER ]; - opus_int32 A_Q24[ MAX_FIND_PITCH_LPC_ORDER ]; - opus_int16 A_Q12[ MAX_FIND_PITCH_LPC_ORDER ]; - - /******************************************/ - /* Setup buffer lengths etc based on Fs */ - /******************************************/ - buf_len = psEnc->sCmn.la_pitch + psEnc->sCmn.frame_length + psEnc->sCmn.ltp_mem_length; - - /* Safty check */ - SKP_assert( buf_len >= psEnc->sCmn.pitch_LPC_win_length ); - - x_buf = x - psEnc->sCmn.ltp_mem_length; - - /*************************************/ - /* Estimate LPC AR coefficients */ - /*************************************/ - - /* Calculate windowed signal */ - - /* First LA_LTP samples */ - x_buf_ptr = x_buf + buf_len - psEnc->sCmn.pitch_LPC_win_length; - Wsig_ptr = Wsig; - silk_apply_sine_window( Wsig_ptr, x_buf_ptr, 1, psEnc->sCmn.la_pitch ); - - /* Middle un - windowed samples */ - Wsig_ptr += psEnc->sCmn.la_pitch; - x_buf_ptr += psEnc->sCmn.la_pitch; - SKP_memcpy( Wsig_ptr, x_buf_ptr, ( psEnc->sCmn.pitch_LPC_win_length - SKP_LSHIFT( psEnc->sCmn.la_pitch, 1 ) ) * sizeof( opus_int16 ) ); - - /* Last LA_LTP samples */ - Wsig_ptr += psEnc->sCmn.pitch_LPC_win_length - SKP_LSHIFT( psEnc->sCmn.la_pitch, 1 ); - x_buf_ptr += psEnc->sCmn.pitch_LPC_win_length - SKP_LSHIFT( psEnc->sCmn.la_pitch, 1 ); - silk_apply_sine_window( Wsig_ptr, x_buf_ptr, 2, psEnc->sCmn.la_pitch ); - - /* Calculate autocorrelation sequence */ - silk_autocorr( auto_corr, &scale, Wsig, psEnc->sCmn.pitch_LPC_win_length, psEnc->sCmn.pitchEstimationLPCOrder + 1 ); - - /* Add white noise, as fraction of energy */ - auto_corr[ 0 ] = SKP_SMLAWB( auto_corr[ 0 ], auto_corr[ 0 ], SILK_FIX_CONST( FIND_PITCH_WHITE_NOISE_FRACTION, 16 ) ) + 1; - - /* Calculate the reflection coefficients using schur */ - res_nrg = silk_schur( rc_Q15, auto_corr, psEnc->sCmn.pitchEstimationLPCOrder ); - - /* Prediction gain */ - psEncCtrl->predGain_Q16 = silk_DIV32_varQ( auto_corr[ 0 ], SKP_max_int( res_nrg, 1 ), 16 ); - - /* Convert reflection coefficients to prediction coefficients */ - silk_k2a( A_Q24, rc_Q15, psEnc->sCmn.pitchEstimationLPCOrder ); - - /* Convert From 32 bit Q24 to 16 bit Q12 coefs */ - for( i = 0; i < psEnc->sCmn.pitchEstimationLPCOrder; i++ ) { - A_Q12[ i ] = ( opus_int16 )SKP_SAT16( SKP_RSHIFT( A_Q24[ i ], 12 ) ); - } - - /* Do BWE */ - silk_bwexpander( A_Q12, psEnc->sCmn.pitchEstimationLPCOrder, SILK_FIX_CONST( FIND_PITCH_BANDWITH_EXPANSION, 16 ) ); - - /*****************************************/ - /* LPC analysis filtering */ - /*****************************************/ - silk_LPC_analysis_filter( res, x_buf, A_Q12, buf_len, psEnc->sCmn.pitchEstimationLPCOrder ); - - if( psEnc->sCmn.indices.signalType != TYPE_NO_VOICE_ACTIVITY && psEnc->sCmn.first_frame_after_reset == 0 ) { - /* Threshold for pitch estimator */ - thrhld_Q15 = SILK_FIX_CONST( 0.6, 15 ); - thrhld_Q15 = SKP_SMLABB( thrhld_Q15, SILK_FIX_CONST( -0.004, 15 ), psEnc->sCmn.pitchEstimationLPCOrder ); - thrhld_Q15 = SKP_SMLABB( thrhld_Q15, SILK_FIX_CONST( -0.1, 7 ), psEnc->sCmn.speech_activity_Q8 ); - thrhld_Q15 = SKP_SMLABB( thrhld_Q15, SILK_FIX_CONST( -0.15, 15 ), SKP_RSHIFT( psEnc->sCmn.prevSignalType, 1 ) ); - thrhld_Q15 = SKP_SMLAWB( thrhld_Q15, SILK_FIX_CONST( -0.1, 16 ), psEnc->sCmn.input_tilt_Q15 ); - thrhld_Q15 = SKP_SAT16( thrhld_Q15 ); - - /*****************************************/ - /* Call pitch estimator */ - /*****************************************/ - if( silk_pitch_analysis_core( res, psEncCtrl->pitchL, &psEnc->sCmn.indices.lagIndex, &psEnc->sCmn.indices.contourIndex, - &psEnc->LTPCorr_Q15, psEnc->sCmn.prevLag, psEnc->sCmn.pitchEstimationThreshold_Q16, - ( opus_int16 )thrhld_Q15, psEnc->sCmn.fs_kHz, psEnc->sCmn.pitchEstimationComplexity, psEnc->sCmn.nb_subfr ) == 0 ) - { - psEnc->sCmn.indices.signalType = TYPE_VOICED; - } else { - psEnc->sCmn.indices.signalType = TYPE_UNVOICED; - } - } else { - SKP_memset( psEncCtrl->pitchL, 0, sizeof( psEncCtrl->pitchL ) ); - psEnc->sCmn.indices.lagIndex = 0; - psEnc->sCmn.indices.contourIndex = 0; - psEnc->LTPCorr_Q15 = 0; - } -} +/*********************************************************************** +Copyright (c) 2006-2011, Skype Limited. All rights reserved. +Redistribution and use in source and binary forms, with or without +modification, (subject to the limitations in the disclaimer below) +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 Skype Limited, nor the names of specific +contributors, may be used to endorse or promote products derived from +this software without specific prior written permission. +NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED +BY THIS LICENSE. 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. +***********************************************************************/ + +#include "silk_main_FIX.h" +#include "silk_tuning_parameters.h" + +/* Find pitch lags */ +void silk_find_pitch_lags_FIX( + silk_encoder_state_FIX *psEnc, /* I/O encoder state */ + silk_encoder_control_FIX *psEncCtrl, /* I/O encoder control */ + opus_int16 res[], /* O residual */ + const opus_int16 x[] /* I Speech signal */ +) +{ + opus_int buf_len, i, scale; + opus_int32 thrhld_Q15, res_nrg; + const opus_int16 *x_buf, *x_buf_ptr; + opus_int16 Wsig[ FIND_PITCH_LPC_WIN_MAX ], *Wsig_ptr; + opus_int32 auto_corr[ MAX_FIND_PITCH_LPC_ORDER + 1 ]; + opus_int16 rc_Q15[ MAX_FIND_PITCH_LPC_ORDER ]; + opus_int32 A_Q24[ MAX_FIND_PITCH_LPC_ORDER ]; + opus_int16 A_Q12[ MAX_FIND_PITCH_LPC_ORDER ]; + + /******************************************/ + /* Setup buffer lengths etc based on Fs */ + /******************************************/ + buf_len = psEnc->sCmn.la_pitch + psEnc->sCmn.frame_length + psEnc->sCmn.ltp_mem_length; + + /* Safty check */ + SKP_assert( buf_len >= psEnc->sCmn.pitch_LPC_win_length ); + + x_buf = x - psEnc->sCmn.ltp_mem_length; + + /*************************************/ + /* Estimate LPC AR coefficients */ + /*************************************/ + + /* Calculate windowed signal */ + + /* First LA_LTP samples */ + x_buf_ptr = x_buf + buf_len - psEnc->sCmn.pitch_LPC_win_length; + Wsig_ptr = Wsig; + silk_apply_sine_window( Wsig_ptr, x_buf_ptr, 1, psEnc->sCmn.la_pitch ); + + /* Middle un - windowed samples */ + Wsig_ptr += psEnc->sCmn.la_pitch; + x_buf_ptr += psEnc->sCmn.la_pitch; + SKP_memcpy( Wsig_ptr, x_buf_ptr, ( psEnc->sCmn.pitch_LPC_win_length - SKP_LSHIFT( psEnc->sCmn.la_pitch, 1 ) ) * sizeof( opus_int16 ) ); + + /* Last LA_LTP samples */ + Wsig_ptr += psEnc->sCmn.pitch_LPC_win_length - SKP_LSHIFT( psEnc->sCmn.la_pitch, 1 ); + x_buf_ptr += psEnc->sCmn.pitch_LPC_win_length - SKP_LSHIFT( psEnc->sCmn.la_pitch, 1 ); + silk_apply_sine_window( Wsig_ptr, x_buf_ptr, 2, psEnc->sCmn.la_pitch ); + + /* Calculate autocorrelation sequence */ + silk_autocorr( auto_corr, &scale, Wsig, psEnc->sCmn.pitch_LPC_win_length, psEnc->sCmn.pitchEstimationLPCOrder + 1 ); + + /* Add white noise, as fraction of energy */ + auto_corr[ 0 ] = SKP_SMLAWB( auto_corr[ 0 ], auto_corr[ 0 ], SILK_FIX_CONST( FIND_PITCH_WHITE_NOISE_FRACTION, 16 ) ) + 1; + + /* Calculate the reflection coefficients using schur */ + res_nrg = silk_schur( rc_Q15, auto_corr, psEnc->sCmn.pitchEstimationLPCOrder ); + + /* Prediction gain */ + psEncCtrl->predGain_Q16 = silk_DIV32_varQ( auto_corr[ 0 ], SKP_max_int( res_nrg, 1 ), 16 ); + + /* Convert reflection coefficients to prediction coefficients */ + silk_k2a( A_Q24, rc_Q15, psEnc->sCmn.pitchEstimationLPCOrder ); + + /* Convert From 32 bit Q24 to 16 bit Q12 coefs */ + for( i = 0; i < psEnc->sCmn.pitchEstimationLPCOrder; i++ ) { + A_Q12[ i ] = ( opus_int16 )SKP_SAT16( SKP_RSHIFT( A_Q24[ i ], 12 ) ); + } + + /* Do BWE */ + silk_bwexpander( A_Q12, psEnc->sCmn.pitchEstimationLPCOrder, SILK_FIX_CONST( FIND_PITCH_BANDWITH_EXPANSION, 16 ) ); + + /*****************************************/ + /* LPC analysis filtering */ + /*****************************************/ + silk_LPC_analysis_filter( res, x_buf, A_Q12, buf_len, psEnc->sCmn.pitchEstimationLPCOrder ); + + if( psEnc->sCmn.indices.signalType != TYPE_NO_VOICE_ACTIVITY && psEnc->sCmn.first_frame_after_reset == 0 ) { + /* Threshold for pitch estimator */ + thrhld_Q15 = SILK_FIX_CONST( 0.6, 15 ); + thrhld_Q15 = SKP_SMLABB( thrhld_Q15, SILK_FIX_CONST( -0.004, 15 ), psEnc->sCmn.pitchEstimationLPCOrder ); + thrhld_Q15 = SKP_SMLABB( thrhld_Q15, SILK_FIX_CONST( -0.1, 7 ), psEnc->sCmn.speech_activity_Q8 ); + thrhld_Q15 = SKP_SMLABB( thrhld_Q15, SILK_FIX_CONST( -0.15, 15 ), SKP_RSHIFT( psEnc->sCmn.prevSignalType, 1 ) ); + thrhld_Q15 = SKP_SMLAWB( thrhld_Q15, SILK_FIX_CONST( -0.1, 16 ), psEnc->sCmn.input_tilt_Q15 ); + thrhld_Q15 = SKP_SAT16( thrhld_Q15 ); + + /*****************************************/ + /* Call pitch estimator */ + /*****************************************/ + if( silk_pitch_analysis_core( res, psEncCtrl->pitchL, &psEnc->sCmn.indices.lagIndex, &psEnc->sCmn.indices.contourIndex, + &psEnc->LTPCorr_Q15, psEnc->sCmn.prevLag, psEnc->sCmn.pitchEstimationThreshold_Q16, + ( opus_int16 )thrhld_Q15, psEnc->sCmn.fs_kHz, psEnc->sCmn.pitchEstimationComplexity, psEnc->sCmn.nb_subfr ) == 0 ) + { + psEnc->sCmn.indices.signalType = TYPE_VOICED; + } else { + psEnc->sCmn.indices.signalType = TYPE_UNVOICED; + } + } else { + SKP_memset( psEncCtrl->pitchL, 0, sizeof( psEncCtrl->pitchL ) ); + psEnc->sCmn.indices.lagIndex = 0; + psEnc->sCmn.indices.contourIndex = 0; + psEnc->LTPCorr_Q15 = 0; + } +} diff --git a/silk/fixed/silk_find_pred_coefs_FIX.c b/silk/fixed/silk_find_pred_coefs_FIX.c index ae95372d3..657195344 100644 --- a/silk/fixed/silk_find_pred_coefs_FIX.c +++ b/silk/fixed/silk_find_pred_coefs_FIX.c @@ -1,127 +1,127 @@ -/*********************************************************************** -Copyright (c) 2006-2011, Skype Limited. All rights reserved. -Redistribution and use in source and binary forms, with or without -modification, (subject to the limitations in the disclaimer below) -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 Skype Limited, nor the names of specific -contributors, may be used to endorse or promote products derived from -this software without specific prior written permission. -NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED -BY THIS LICENSE. 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. -***********************************************************************/ - -#include "silk_main_FIX.h" - -void silk_find_pred_coefs_FIX( - silk_encoder_state_FIX *psEnc, /* I/O encoder state */ - silk_encoder_control_FIX *psEncCtrl, /* I/O encoder control */ - const opus_int16 res_pitch[], /* I Residual from pitch analysis */ - const opus_int16 x[] /* I Speech signal */ -) -{ - opus_int i; - opus_int32 WLTP[ MAX_NB_SUBFR * LTP_ORDER * LTP_ORDER ]; - opus_int32 invGains_Q16[ MAX_NB_SUBFR ], local_gains[ MAX_NB_SUBFR ], Wght_Q15[ MAX_NB_SUBFR ]; - opus_int16 NLSF_Q15[ MAX_LPC_ORDER ]; - const opus_int16 *x_ptr; - opus_int16 *x_pre_ptr, LPC_in_pre[ MAX_NB_SUBFR * MAX_LPC_ORDER + MAX_FRAME_LENGTH ]; - opus_int32 tmp, min_gain_Q16; - opus_int LTP_corrs_rshift[ MAX_NB_SUBFR ]; - - /* weighting for weighted least squares */ - min_gain_Q16 = SKP_int32_MAX >> 6; - for( i = 0; i < psEnc->sCmn.nb_subfr; i++ ) { - min_gain_Q16 = SKP_min( min_gain_Q16, psEncCtrl->Gains_Q16[ i ] ); - } - for( i = 0; i < psEnc->sCmn.nb_subfr; i++ ) { - /* Divide to Q16 */ - SKP_assert( psEncCtrl->Gains_Q16[ i ] > 0 ); - /* Invert and normalize gains, and ensure that maximum invGains_Q16 is within range of a 16 bit int */ - invGains_Q16[ i ] = silk_DIV32_varQ( min_gain_Q16, psEncCtrl->Gains_Q16[ i ], 16 - 2 ); - - /* Ensure Wght_Q15 a minimum value 1 */ - invGains_Q16[ i ] = SKP_max( invGains_Q16[ i ], 363 ); - - /* Square the inverted gains */ - SKP_assert( invGains_Q16[ i ] == SKP_SAT16( invGains_Q16[ i ] ) ); - tmp = SKP_SMULWB( invGains_Q16[ i ], invGains_Q16[ i ] ); - Wght_Q15[ i ] = SKP_RSHIFT( tmp, 1 ); - - /* Invert the inverted and normalized gains */ - local_gains[ i ] = SKP_DIV32( ( 1 << 16 ), invGains_Q16[ i ] ); - } - - if( psEnc->sCmn.indices.signalType == TYPE_VOICED ) { - /**********/ - /* VOICED */ - /**********/ - SKP_assert( psEnc->sCmn.ltp_mem_length - psEnc->sCmn.predictLPCOrder >= psEncCtrl->pitchL[ 0 ] + LTP_ORDER / 2 ); - - /* LTP analysis */ - silk_find_LTP_FIX( psEncCtrl->LTPCoef_Q14, WLTP, &psEncCtrl->LTPredCodGain_Q7, - res_pitch, psEncCtrl->pitchL, Wght_Q15, psEnc->sCmn.subfr_length, - psEnc->sCmn.nb_subfr, psEnc->sCmn.ltp_mem_length, LTP_corrs_rshift ); - - /* Quantize LTP gain parameters */ - silk_quant_LTP_gains( psEncCtrl->LTPCoef_Q14, psEnc->sCmn.indices.LTPIndex, &psEnc->sCmn.indices.PERIndex, - WLTP, psEnc->sCmn.mu_LTP_Q9, psEnc->sCmn.LTPQuantLowComplexity, psEnc->sCmn.nb_subfr); - - /* Control LTP scaling */ - silk_LTP_scale_ctrl_FIX( psEnc, psEncCtrl ); - - /* Create LTP residual */ - silk_LTP_analysis_filter_FIX( LPC_in_pre, x - psEnc->sCmn.predictLPCOrder, psEncCtrl->LTPCoef_Q14, - psEncCtrl->pitchL, invGains_Q16, psEnc->sCmn.subfr_length, psEnc->sCmn.nb_subfr, psEnc->sCmn.predictLPCOrder ); - - } else { - /************/ - /* UNVOICED */ - /************/ - /* Create signal with prepended subframes, scaled by inverse gains */ - x_ptr = x - psEnc->sCmn.predictLPCOrder; - x_pre_ptr = LPC_in_pre; - for( i = 0; i < psEnc->sCmn.nb_subfr; i++ ) { - silk_scale_copy_vector16( x_pre_ptr, x_ptr, invGains_Q16[ i ], - psEnc->sCmn.subfr_length + psEnc->sCmn.predictLPCOrder ); - x_pre_ptr += psEnc->sCmn.subfr_length + psEnc->sCmn.predictLPCOrder; - x_ptr += psEnc->sCmn.subfr_length; - } - - SKP_memset( psEncCtrl->LTPCoef_Q14, 0, psEnc->sCmn.nb_subfr * LTP_ORDER * sizeof( opus_int16 ) ); - psEncCtrl->LTPredCodGain_Q7 = 0; - } - - /* LPC_in_pre contains the LTP-filtered input for voiced, and the unfiltered input for unvoiced */ - TIC(FIND_LPC) - silk_find_LPC_FIX( 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 ); - TOC(FIND_LPC) - - /* Quantize LSFs */ - TIC(PROCESS_LSFS) - silk_process_NLSFs( &psEnc->sCmn, psEncCtrl->PredCoef_Q12, NLSF_Q15, psEnc->sCmn.prev_NLSFq_Q15 ); - TOC(PROCESS_LSFS) - - /* Calculate residual energy using quantized LPC coefficients */ - silk_residual_energy_FIX( psEncCtrl->ResNrg, psEncCtrl->ResNrgQ, LPC_in_pre, psEncCtrl->PredCoef_Q12, local_gains, - psEnc->sCmn.subfr_length, psEnc->sCmn.nb_subfr, psEnc->sCmn.predictLPCOrder ); - - /* Copy to prediction struct for use in next frame for fluctuation reduction */ - SKP_memcpy( psEnc->sCmn.prev_NLSFq_Q15, NLSF_Q15, sizeof( psEnc->sCmn.prev_NLSFq_Q15 ) ); -} +/*********************************************************************** +Copyright (c) 2006-2011, Skype Limited. All rights reserved. +Redistribution and use in source and binary forms, with or without +modification, (subject to the limitations in the disclaimer below) +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 Skype Limited, nor the names of specific +contributors, may be used to endorse or promote products derived from +this software without specific prior written permission. +NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED +BY THIS LICENSE. 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. +***********************************************************************/ + +#include "silk_main_FIX.h" + +void silk_find_pred_coefs_FIX( + silk_encoder_state_FIX *psEnc, /* I/O encoder state */ + silk_encoder_control_FIX *psEncCtrl, /* I/O encoder control */ + const opus_int16 res_pitch[], /* I Residual from pitch analysis */ + const opus_int16 x[] /* I Speech signal */ +) +{ + opus_int i; + opus_int32 WLTP[ MAX_NB_SUBFR * LTP_ORDER * LTP_ORDER ]; + opus_int32 invGains_Q16[ MAX_NB_SUBFR ], local_gains[ MAX_NB_SUBFR ], Wght_Q15[ MAX_NB_SUBFR ]; + opus_int16 NLSF_Q15[ MAX_LPC_ORDER ]; + const opus_int16 *x_ptr; + opus_int16 *x_pre_ptr, LPC_in_pre[ MAX_NB_SUBFR * MAX_LPC_ORDER + MAX_FRAME_LENGTH ]; + opus_int32 tmp, min_gain_Q16; + opus_int LTP_corrs_rshift[ MAX_NB_SUBFR ]; + + /* weighting for weighted least squares */ + min_gain_Q16 = SKP_int32_MAX >> 6; + for( i = 0; i < psEnc->sCmn.nb_subfr; i++ ) { + min_gain_Q16 = SKP_min( min_gain_Q16, psEncCtrl->Gains_Q16[ i ] ); + } + for( i = 0; i < psEnc->sCmn.nb_subfr; i++ ) { + /* Divide to Q16 */ + SKP_assert( psEncCtrl->Gains_Q16[ i ] > 0 ); + /* Invert and normalize gains, and ensure that maximum invGains_Q16 is within range of a 16 bit int */ + invGains_Q16[ i ] = silk_DIV32_varQ( min_gain_Q16, psEncCtrl->Gains_Q16[ i ], 16 - 2 ); + + /* Ensure Wght_Q15 a minimum value 1 */ + invGains_Q16[ i ] = SKP_max( invGains_Q16[ i ], 363 ); + + /* Square the inverted gains */ + SKP_assert( invGains_Q16[ i ] == SKP_SAT16( invGains_Q16[ i ] ) ); + tmp = SKP_SMULWB( invGains_Q16[ i ], invGains_Q16[ i ] ); + Wght_Q15[ i ] = SKP_RSHIFT( tmp, 1 ); + + /* Invert the inverted and normalized gains */ + local_gains[ i ] = SKP_DIV32( ( 1 << 16 ), invGains_Q16[ i ] ); + } + + if( psEnc->sCmn.indices.signalType == TYPE_VOICED ) { + /**********/ + /* VOICED */ + /**********/ + SKP_assert( psEnc->sCmn.ltp_mem_length - psEnc->sCmn.predictLPCOrder >= psEncCtrl->pitchL[ 0 ] + LTP_ORDER / 2 ); + + /* LTP analysis */ + silk_find_LTP_FIX( psEncCtrl->LTPCoef_Q14, WLTP, &psEncCtrl->LTPredCodGain_Q7, + res_pitch, psEncCtrl->pitchL, Wght_Q15, psEnc->sCmn.subfr_length, + psEnc->sCmn.nb_subfr, psEnc->sCmn.ltp_mem_length, LTP_corrs_rshift ); + + /* Quantize LTP gain parameters */ + silk_quant_LTP_gains( psEncCtrl->LTPCoef_Q14, psEnc->sCmn.indices.LTPIndex, &psEnc->sCmn.indices.PERIndex, + WLTP, psEnc->sCmn.mu_LTP_Q9, psEnc->sCmn.LTPQuantLowComplexity, psEnc->sCmn.nb_subfr); + + /* Control LTP scaling */ + silk_LTP_scale_ctrl_FIX( psEnc, psEncCtrl ); + + /* Create LTP residual */ + silk_LTP_analysis_filter_FIX( LPC_in_pre, x - psEnc->sCmn.predictLPCOrder, psEncCtrl->LTPCoef_Q14, + psEncCtrl->pitchL, invGains_Q16, psEnc->sCmn.subfr_length, psEnc->sCmn.nb_subfr, psEnc->sCmn.predictLPCOrder ); + + } else { + /************/ + /* UNVOICED */ + /************/ + /* Create signal with prepended subframes, scaled by inverse gains */ + x_ptr = x - psEnc->sCmn.predictLPCOrder; + x_pre_ptr = LPC_in_pre; + for( i = 0; i < psEnc->sCmn.nb_subfr; i++ ) { + silk_scale_copy_vector16( x_pre_ptr, x_ptr, invGains_Q16[ i ], + psEnc->sCmn.subfr_length + psEnc->sCmn.predictLPCOrder ); + x_pre_ptr += psEnc->sCmn.subfr_length + psEnc->sCmn.predictLPCOrder; + x_ptr += psEnc->sCmn.subfr_length; + } + + SKP_memset( psEncCtrl->LTPCoef_Q14, 0, psEnc->sCmn.nb_subfr * LTP_ORDER * sizeof( opus_int16 ) ); + psEncCtrl->LTPredCodGain_Q7 = 0; + } + + /* LPC_in_pre contains the LTP-filtered input for voiced, and the unfiltered input for unvoiced */ + TIC(FIND_LPC) + silk_find_LPC_FIX( 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 ); + TOC(FIND_LPC) + + /* Quantize LSFs */ + TIC(PROCESS_LSFS) + silk_process_NLSFs( &psEnc->sCmn, psEncCtrl->PredCoef_Q12, NLSF_Q15, psEnc->sCmn.prev_NLSFq_Q15 ); + TOC(PROCESS_LSFS) + + /* Calculate residual energy using quantized LPC coefficients */ + silk_residual_energy_FIX( psEncCtrl->ResNrg, psEncCtrl->ResNrgQ, LPC_in_pre, psEncCtrl->PredCoef_Q12, local_gains, + psEnc->sCmn.subfr_length, psEnc->sCmn.nb_subfr, psEnc->sCmn.predictLPCOrder ); + + /* Copy to prediction struct for use in next frame for fluctuation reduction */ + SKP_memcpy( psEnc->sCmn.prev_NLSFq_Q15, NLSF_Q15, sizeof( psEnc->sCmn.prev_NLSFq_Q15 ) ); +} diff --git a/silk/fixed/silk_main_FIX.h b/silk/fixed/silk_main_FIX.h index fb31ae6be..88a9a4afe 100644 --- a/silk/fixed/silk_main_FIX.h +++ b/silk/fixed/silk_main_FIX.h @@ -1,254 +1,254 @@ -/*********************************************************************** -Copyright (c) 2006-2011, Skype Limited. All rights reserved. -Redistribution and use in source and binary forms, with or without -modification, (subject to the limitations in the disclaimer below) -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 Skype Limited, nor the names of specific -contributors, may be used to endorse or promote products derived from -this software without specific prior written permission. -NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED -BY THIS LICENSE. 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. -***********************************************************************/ - -#ifndef SILK_MAIN_FIX_H -#define SILK_MAIN_FIX_H - -#include "silk_SigProc_FIX.h" -#include "silk_structs_FIX.h" -#include "silk_control.h" -#include "silk_main.h" -#include "silk_PLC.h" -#include "silk_debug.h" -#include "entenc.h" - -#ifndef FORCE_CPP_BUILD -#ifdef __cplusplus -extern "C" -{ -#endif -#endif - -#define silk_encoder_state_Fxx silk_encoder_state_FIX -#define silk_encode_frame_Fxx silk_encode_frame_FIX - -/*********************/ -/* Encoder Functions */ -/*********************/ - -/* High-pass filter with cutoff frequency adaptation based on pitch lag statistics */ -void silk_HP_variable_cutoff( - silk_encoder_state_Fxx state_Fxx[], /* I/O Encoder states */ - const opus_int nChannels /* I Number of channels */ -); - -/* Encoder main function */ -opus_int silk_encode_frame_FIX( - silk_encoder_state_FIX *psEnc, /* I/O Pointer to Silk FIX encoder state */ - opus_int32 *pnBytesOut, /* O Pointer to number of payload bytes; */ - ec_enc *psRangeEnc /* I/O compressor data structure */ -); - -/* Low Bitrate Redundancy (LBRR) encoding. Reuse all parameters but encode with lower bitrate */ -void silk_LBRR_encode_FIX( - silk_encoder_state_FIX *psEnc, /* I/O Pointer to Silk FIX encoder state */ - silk_encoder_control_FIX *psEncCtrl, /* I/O Pointer to Silk FIX encoder control struct */ - const opus_int16 xfw[] /* I Input signal */ -); - -/* Initializes the Silk encoder state */ -opus_int silk_init_encoder( - silk_encoder_state_FIX *psEnc /* I/O Pointer to Silk FIX encoder state */ -); - -/* Control the Silk encoder */ -opus_int silk_control_encoder( - silk_encoder_state_FIX *psEnc, /* I/O Pointer to Silk encoder state */ - silk_EncControlStruct *encControl, /* I: Control structure */ - const opus_int32 TargetRate_bps, /* I Target max bitrate (bps) */ - const opus_int allow_bw_switch, /* I Flag to allow switching audio bandwidth */ - const opus_int channelNb /* I Channel number */ -); - -/****************/ -/* Prefiltering */ -/****************/ -void silk_prefilter_FIX( - silk_encoder_state_FIX *psEnc, /* I/O Encoder state */ - const silk_encoder_control_FIX *psEncCtrl, /* I Encoder control */ - opus_int16 xw[], /* O Weighted signal */ - const opus_int16 x[] /* I Speech signal */ -); - -/**************************/ -/* Noise shaping analysis */ -/**************************/ -/* Compute noise shaping coefficients and initial gain values */ -void silk_noise_shape_analysis_FIX( - silk_encoder_state_FIX *psEnc, /* I/O Encoder state FIX */ - silk_encoder_control_FIX *psEncCtrl, /* I/O Encoder control FIX */ - const opus_int16 *pitch_res, /* I LPC residual from pitch analysis */ - const opus_int16 *x /* I Input signal [ frame_length + la_shape ] */ -); - -/* Autocorrelations for a warped frequency axis */ -void silk_warped_autocorrelation_FIX( - opus_int32 *corr, /* O Result [order + 1] */ - opus_int *scale, /* O Scaling of the correlation vector */ - const opus_int16 *input, /* I Input data to correlate */ - const opus_int warping_Q16, /* I Warping coefficient */ - const opus_int length, /* I Length of input */ - const opus_int order /* I Correlation order (even) */ -); - -/* Calculation of LTP state scaling */ -void silk_LTP_scale_ctrl_FIX( - silk_encoder_state_FIX *psEnc, /* I/O encoder state */ - silk_encoder_control_FIX *psEncCtrl /* I/O encoder control */ -); - -/**********************************************/ -/* Prediction Analysis */ -/**********************************************/ -/* Find pitch lags */ -void silk_find_pitch_lags_FIX( - silk_encoder_state_FIX *psEnc, /* I/O encoder state */ - silk_encoder_control_FIX *psEncCtrl, /* I/O encoder control */ - opus_int16 res[], /* O residual */ - const opus_int16 x[] /* I Speech signal */ -); - -/* Find LPC and LTP coefficients */ -void silk_find_pred_coefs_FIX( - silk_encoder_state_FIX *psEnc, /* I/O encoder state */ - silk_encoder_control_FIX *psEncCtrl, /* I/O encoder control */ - const opus_int16 res_pitch[], /* I Residual from pitch analysis */ - const opus_int16 x[] /* I Speech signal */ -); - -/* LPC analysis */ -void silk_find_LPC_FIX( - opus_int16 NLSF_Q15[], /* O NLSFs */ - opus_int8 *interpIndex, /* O NLSF interpolation index, only used for NLSF interpolation */ - const opus_int16 prev_NLSFq_Q15[], /* I previous NLSFs, only used for NLSF interpolation */ - const opus_int useInterpNLSFs, /* I Flag */ - const opus_int firstFrameAfterReset, /* I Flag */ - const opus_int LPC_order, /* I LPC order */ - const opus_int16 x[], /* I Input signal */ - const opus_int subfr_length, /* I Input signal subframe length including preceeding samples */ - const opus_int nb_subfr /* I: Number of subframes */ -); - -/* LTP analysis */ -void silk_find_LTP_FIX( - opus_int16 b_Q14[ MAX_NB_SUBFR * LTP_ORDER ], /* O LTP coefs */ - opus_int32 WLTP[ MAX_NB_SUBFR * LTP_ORDER * LTP_ORDER ], /* O Weight for LTP quantization */ - opus_int *LTPredCodGain_Q7, /* O LTP coding gain */ - const opus_int16 r_lpc[], /* I residual signal after LPC signal + state for first 10 ms */ - const opus_int lag[ MAX_NB_SUBFR ], /* I LTP lags */ - const opus_int32 Wght_Q15[ MAX_NB_SUBFR ], /* I weights */ - const opus_int subfr_length, /* I subframe length */ - const opus_int nb_subfr, /* I number of subframes */ - const opus_int mem_offset, /* I number of samples in LTP memory */ - opus_int corr_rshifts[ MAX_NB_SUBFR ] /* O right shifts applied to correlations */ -); - -void silk_LTP_analysis_filter_FIX( - opus_int16 *LTP_res, /* O: LTP residual signal of length MAX_NB_SUBFR * ( pre_length + subfr_length ) */ - const opus_int16 *x, /* I: Pointer to input signal with at least max( pitchL ) preceeding samples */ - const opus_int16 LTPCoef_Q14[ LTP_ORDER * MAX_NB_SUBFR ],/* I: LTP_ORDER LTP coefficients for each MAX_NB_SUBFR subframe */ - const opus_int pitchL[ MAX_NB_SUBFR ], /* I: Pitch lag, one for each subframe */ - const opus_int32 invGains_Q16[ MAX_NB_SUBFR ], /* I: Inverse quantization gains, one for each subframe */ - const opus_int subfr_length, /* I: Length of each subframe */ - const opus_int nb_subfr, /* I: Number of subframes */ - const opus_int pre_length /* I: Length of the preceeding samples starting at &x[0] for each subframe */ -); - -/* Calculates residual energies of input subframes where all subframes have LPC_order */ -/* of preceeding samples */ -void silk_residual_energy_FIX( - opus_int32 nrgs[ MAX_NB_SUBFR ], /* O Residual energy per subframe */ - opus_int nrgsQ[ MAX_NB_SUBFR ], /* O Q value per subframe */ - const opus_int16 x[], /* I Input signal */ - opus_int16 a_Q12[ 2 ][ MAX_LPC_ORDER ], /* I AR coefs for each frame half */ - const opus_int32 gains[ MAX_NB_SUBFR ], /* I Quantization gains */ - const opus_int subfr_length, /* I Subframe length */ - const opus_int nb_subfr, /* I Number of subframes */ - const opus_int LPC_order /* I LPC order */ -); - -/* Residual energy: nrg = wxx - 2 * wXx * c + c' * wXX * c */ -opus_int32 silk_residual_energy16_covar_FIX( - const opus_int16 *c, /* I Prediction vector */ - const opus_int32 *wXX, /* I Correlation matrix */ - const opus_int32 *wXx, /* I Correlation vector */ - opus_int32 wxx, /* I Signal energy */ - opus_int D, /* I Dimension */ - opus_int cQ /* I Q value for c vector 0 - 15 */ -); - -/* Processing of gains */ -void silk_process_gains_FIX( - silk_encoder_state_FIX *psEnc, /* I/O Encoder state */ - silk_encoder_control_FIX *psEncCtrl /* I/O Encoder control */ -); - -/******************/ -/* Linear Algebra */ -/******************/ -/* Calculates correlation matrix X'*X */ -void silk_corrMatrix_FIX( - const opus_int16 *x, /* I x vector [L + order - 1] used to form data matrix X */ - const opus_int L, /* I Length of vectors */ - const opus_int order, /* I Max lag for correlation */ - const opus_int head_room, /* I Desired headroom */ - opus_int32 *XX, /* O Pointer to X'*X correlation matrix [ order x order ]*/ - opus_int *rshifts /* I/O Right shifts of correlations */ -); - -/* Calculates correlation vector X'*t */ -void silk_corrVector_FIX( - const opus_int16 *x, /* I x vector [L + order - 1] used to form data matrix X */ - const opus_int16 *t, /* I Target vector [L] */ - const opus_int L, /* I Length of vectors */ - const opus_int order, /* I Max lag for correlation */ - opus_int32 *Xt, /* O Pointer to X'*t correlation vector [order] */ - const opus_int rshifts /* I Right shifts of correlations */ -); - -/* Add noise to matrix diagonal */ -void silk_regularize_correlations_FIX( - opus_int32 *XX, /* I/O Correlation matrices */ - opus_int32 *xx, /* I/O Correlation values */ - opus_int32 noise, /* I Noise to add */ - opus_int D /* I Dimension of XX */ -); - -/* Solves Ax = b, assuming A is symmetric */ -void silk_solve_LDL_FIX( - opus_int32 *A, /* I Pointer to symetric square matrix A */ - opus_int M, /* I Size of matrix */ - const opus_int32 *b, /* I Pointer to b vector */ - opus_int32 *x_Q16 /* O Pointer to x solution vector */ -); - -#ifndef FORCE_CPP_BUILD -#ifdef __cplusplus -} -#endif /* __cplusplus */ -#endif /* FORCE_CPP_BUILD */ -#endif /* SILK_MAIN_FIX_H */ +/*********************************************************************** +Copyright (c) 2006-2011, Skype Limited. All rights reserved. +Redistribution and use in source and binary forms, with or without +modification, (subject to the limitations in the disclaimer below) +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 Skype Limited, nor the names of specific +contributors, may be used to endorse or promote products derived from +this software without specific prior written permission. +NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED +BY THIS LICENSE. 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. +***********************************************************************/ + +#ifndef SILK_MAIN_FIX_H +#define SILK_MAIN_FIX_H + +#include "silk_SigProc_FIX.h" +#include "silk_structs_FIX.h" +#include "silk_control.h" +#include "silk_main.h" +#include "silk_PLC.h" +#include "silk_debug.h" +#include "entenc.h" + +#ifndef FORCE_CPP_BUILD +#ifdef __cplusplus +extern "C" +{ +#endif +#endif + +#define silk_encoder_state_Fxx silk_encoder_state_FIX +#define silk_encode_frame_Fxx silk_encode_frame_FIX + +/*********************/ +/* Encoder Functions */ +/*********************/ + +/* High-pass filter with cutoff frequency adaptation based on pitch lag statistics */ +void silk_HP_variable_cutoff( + silk_encoder_state_Fxx state_Fxx[], /* I/O Encoder states */ + const opus_int nChannels /* I Number of channels */ +); + +/* Encoder main function */ +opus_int silk_encode_frame_FIX( + silk_encoder_state_FIX *psEnc, /* I/O Pointer to Silk FIX encoder state */ + opus_int32 *pnBytesOut, /* O Pointer to number of payload bytes; */ + ec_enc *psRangeEnc /* I/O compressor data structure */ +); + +/* Low Bitrate Redundancy (LBRR) encoding. Reuse all parameters but encode with lower bitrate */ +void silk_LBRR_encode_FIX( + silk_encoder_state_FIX *psEnc, /* I/O Pointer to Silk FIX encoder state */ + silk_encoder_control_FIX *psEncCtrl, /* I/O Pointer to Silk FIX encoder control struct */ + const opus_int16 xfw[] /* I Input signal */ +); + +/* Initializes the Silk encoder state */ +opus_int silk_init_encoder( + silk_encoder_state_FIX *psEnc /* I/O Pointer to Silk FIX encoder state */ +); + +/* Control the Silk encoder */ +opus_int silk_control_encoder( + silk_encoder_state_FIX *psEnc, /* I/O Pointer to Silk encoder state */ + silk_EncControlStruct *encControl, /* I: Control structure */ + const opus_int32 TargetRate_bps, /* I Target max bitrate (bps) */ + const opus_int allow_bw_switch, /* I Flag to allow switching audio bandwidth */ + const opus_int channelNb /* I Channel number */ +); + +/****************/ +/* Prefiltering */ +/****************/ +void silk_prefilter_FIX( + silk_encoder_state_FIX *psEnc, /* I/O Encoder state */ + const silk_encoder_control_FIX *psEncCtrl, /* I Encoder control */ + opus_int16 xw[], /* O Weighted signal */ + const opus_int16 x[] /* I Speech signal */ +); + +/**************************/ +/* Noise shaping analysis */ +/**************************/ +/* Compute noise shaping coefficients and initial gain values */ +void silk_noise_shape_analysis_FIX( + silk_encoder_state_FIX *psEnc, /* I/O Encoder state FIX */ + silk_encoder_control_FIX *psEncCtrl, /* I/O Encoder control FIX */ + const opus_int16 *pitch_res, /* I LPC residual from pitch analysis */ + const opus_int16 *x /* I Input signal [ frame_length + la_shape ] */ +); + +/* Autocorrelations for a warped frequency axis */ +void silk_warped_autocorrelation_FIX( + opus_int32 *corr, /* O Result [order + 1] */ + opus_int *scale, /* O Scaling of the correlation vector */ + const opus_int16 *input, /* I Input data to correlate */ + const opus_int warping_Q16, /* I Warping coefficient */ + const opus_int length, /* I Length of input */ + const opus_int order /* I Correlation order (even) */ +); + +/* Calculation of LTP state scaling */ +void silk_LTP_scale_ctrl_FIX( + silk_encoder_state_FIX *psEnc, /* I/O encoder state */ + silk_encoder_control_FIX *psEncCtrl /* I/O encoder control */ +); + +/**********************************************/ +/* Prediction Analysis */ +/**********************************************/ +/* Find pitch lags */ +void silk_find_pitch_lags_FIX( + silk_encoder_state_FIX *psEnc, /* I/O encoder state */ + silk_encoder_control_FIX *psEncCtrl, /* I/O encoder control */ + opus_int16 res[], /* O residual */ + const opus_int16 x[] /* I Speech signal */ +); + +/* Find LPC and LTP coefficients */ +void silk_find_pred_coefs_FIX( + silk_encoder_state_FIX *psEnc, /* I/O encoder state */ + silk_encoder_control_FIX *psEncCtrl, /* I/O encoder control */ + const opus_int16 res_pitch[], /* I Residual from pitch analysis */ + const opus_int16 x[] /* I Speech signal */ +); + +/* LPC analysis */ +void silk_find_LPC_FIX( + opus_int16 NLSF_Q15[], /* O NLSFs */ + opus_int8 *interpIndex, /* O NLSF interpolation index, only used for NLSF interpolation */ + const opus_int16 prev_NLSFq_Q15[], /* I previous NLSFs, only used for NLSF interpolation */ + const opus_int useInterpNLSFs, /* I Flag */ + const opus_int firstFrameAfterReset, /* I Flag */ + const opus_int LPC_order, /* I LPC order */ + const opus_int16 x[], /* I Input signal */ + const opus_int subfr_length, /* I Input signal subframe length including preceeding samples */ + const opus_int nb_subfr /* I: Number of subframes */ +); + +/* LTP analysis */ +void silk_find_LTP_FIX( + opus_int16 b_Q14[ MAX_NB_SUBFR * LTP_ORDER ], /* O LTP coefs */ + opus_int32 WLTP[ MAX_NB_SUBFR * LTP_ORDER * LTP_ORDER ], /* O Weight for LTP quantization */ + opus_int *LTPredCodGain_Q7, /* O LTP coding gain */ + const opus_int16 r_lpc[], /* I residual signal after LPC signal + state for first 10 ms */ + const opus_int lag[ MAX_NB_SUBFR ], /* I LTP lags */ + const opus_int32 Wght_Q15[ MAX_NB_SUBFR ], /* I weights */ + const opus_int subfr_length, /* I subframe length */ + const opus_int nb_subfr, /* I number of subframes */ + const opus_int mem_offset, /* I number of samples in LTP memory */ + opus_int corr_rshifts[ MAX_NB_SUBFR ] /* O right shifts applied to correlations */ +); + +void silk_LTP_analysis_filter_FIX( + opus_int16 *LTP_res, /* O: LTP residual signal of length MAX_NB_SUBFR * ( pre_length + subfr_length ) */ + const opus_int16 *x, /* I: Pointer to input signal with at least max( pitchL ) preceeding samples */ + const opus_int16 LTPCoef_Q14[ LTP_ORDER * MAX_NB_SUBFR ],/* I: LTP_ORDER LTP coefficients for each MAX_NB_SUBFR subframe */ + const opus_int pitchL[ MAX_NB_SUBFR ], /* I: Pitch lag, one for each subframe */ + const opus_int32 invGains_Q16[ MAX_NB_SUBFR ], /* I: Inverse quantization gains, one for each subframe */ + const opus_int subfr_length, /* I: Length of each subframe */ + const opus_int nb_subfr, /* I: Number of subframes */ + const opus_int pre_length /* I: Length of the preceeding samples starting at &x[0] for each subframe */ +); + +/* Calculates residual energies of input subframes where all subframes have LPC_order */ +/* of preceeding samples */ +void silk_residual_energy_FIX( + opus_int32 nrgs[ MAX_NB_SUBFR ], /* O Residual energy per subframe */ + opus_int nrgsQ[ MAX_NB_SUBFR ], /* O Q value per subframe */ + const opus_int16 x[], /* I Input signal */ + opus_int16 a_Q12[ 2 ][ MAX_LPC_ORDER ], /* I AR coefs for each frame half */ + const opus_int32 gains[ MAX_NB_SUBFR ], /* I Quantization gains */ + const opus_int subfr_length, /* I Subframe length */ + const opus_int nb_subfr, /* I Number of subframes */ + const opus_int LPC_order /* I LPC order */ +); + +/* Residual energy: nrg = wxx - 2 * wXx * c + c' * wXX * c */ +opus_int32 silk_residual_energy16_covar_FIX( + const opus_int16 *c, /* I Prediction vector */ + const opus_int32 *wXX, /* I Correlation matrix */ + const opus_int32 *wXx, /* I Correlation vector */ + opus_int32 wxx, /* I Signal energy */ + opus_int D, /* I Dimension */ + opus_int cQ /* I Q value for c vector 0 - 15 */ +); + +/* Processing of gains */ +void silk_process_gains_FIX( + silk_encoder_state_FIX *psEnc, /* I/O Encoder state */ + silk_encoder_control_FIX *psEncCtrl /* I/O Encoder control */ +); + +/******************/ +/* Linear Algebra */ +/******************/ +/* Calculates correlation matrix X'*X */ +void silk_corrMatrix_FIX( + const opus_int16 *x, /* I x vector [L + order - 1] used to form data matrix X */ + const opus_int L, /* I Length of vectors */ + const opus_int order, /* I Max lag for correlation */ + const opus_int head_room, /* I Desired headroom */ + opus_int32 *XX, /* O Pointer to X'*X correlation matrix [ order x order ]*/ + opus_int *rshifts /* I/O Right shifts of correlations */ +); + +/* Calculates correlation vector X'*t */ +void silk_corrVector_FIX( + const opus_int16 *x, /* I x vector [L + order - 1] used to form data matrix X */ + const opus_int16 *t, /* I Target vector [L] */ + const opus_int L, /* I Length of vectors */ + const opus_int order, /* I Max lag for correlation */ + opus_int32 *Xt, /* O Pointer to X'*t correlation vector [order] */ + const opus_int rshifts /* I Right shifts of correlations */ +); + +/* Add noise to matrix diagonal */ +void silk_regularize_correlations_FIX( + opus_int32 *XX, /* I/O Correlation matrices */ + opus_int32 *xx, /* I/O Correlation values */ + opus_int32 noise, /* I Noise to add */ + opus_int D /* I Dimension of XX */ +); + +/* Solves Ax = b, assuming A is symmetric */ +void silk_solve_LDL_FIX( + opus_int32 *A, /* I Pointer to symetric square matrix A */ + opus_int M, /* I Size of matrix */ + const opus_int32 *b, /* I Pointer to b vector */ + opus_int32 *x_Q16 /* O Pointer to x solution vector */ +); + +#ifndef FORCE_CPP_BUILD +#ifdef __cplusplus +} +#endif /* __cplusplus */ +#endif /* FORCE_CPP_BUILD */ +#endif /* SILK_MAIN_FIX_H */ diff --git a/silk/fixed/silk_noise_shape_analysis_FIX.c b/silk/fixed/silk_noise_shape_analysis_FIX.c index fb2bcc92e..1ce1ea66c 100644 --- a/silk/fixed/silk_noise_shape_analysis_FIX.c +++ b/silk/fixed/silk_noise_shape_analysis_FIX.c @@ -1,437 +1,437 @@ -/*********************************************************************** -Copyright (c) 2006-2011, Skype Limited. All rights reserved. -Redistribution and use in source and binary forms, with or without -modification, (subject to the limitations in the disclaimer below) -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 Skype Limited, nor the names of specific -contributors, may be used to endorse or promote products derived from -this software without specific prior written permission. -NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED -BY THIS LICENSE. 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. -***********************************************************************/ - -#include "silk_main_FIX.h" -#include "silk_tuning_parameters.h" - -/* Compute gain to make warped filter coefficients have a zero mean log frequency response on a */ -/* non-warped frequency scale. (So that it can be implemented with a minimum-phase monic filter.) */ -SKP_INLINE opus_int32 warped_gain( // gain in Q16 - const opus_int32 *coefs_Q24, - opus_int lambda_Q16, - opus_int order -) { - opus_int i; - opus_int32 gain_Q24; - - lambda_Q16 = -lambda_Q16; - gain_Q24 = coefs_Q24[ order - 1 ]; - for( i = order - 2; i >= 0; i-- ) { - gain_Q24 = SKP_SMLAWB( coefs_Q24[ i ], gain_Q24, lambda_Q16 ); - } - gain_Q24 = SKP_SMLAWB( SILK_FIX_CONST( 1.0, 24 ), gain_Q24, -lambda_Q16 ); - return silk_INVERSE32_varQ( gain_Q24, 40 ); -} - -/* Convert warped filter coefficients to monic pseudo-warped coefficients and limit maximum */ -/* amplitude of monic warped coefficients by using bandwidth expansion on the true coefficients */ -SKP_INLINE void limit_warped_coefs( - opus_int32 *coefs_syn_Q24, - opus_int32 *coefs_ana_Q24, - opus_int lambda_Q16, - opus_int32 limit_Q24, - opus_int order -) { - opus_int i, iter, ind = 0; - opus_int32 tmp, maxabs_Q24, chirp_Q16, gain_syn_Q16, gain_ana_Q16; - opus_int32 nom_Q16, den_Q24; - - /* Convert to monic coefficients */ - lambda_Q16 = -lambda_Q16; - for( i = order - 1; i > 0; i-- ) { - coefs_syn_Q24[ i - 1 ] = SKP_SMLAWB( coefs_syn_Q24[ i - 1 ], coefs_syn_Q24[ i ], lambda_Q16 ); - coefs_ana_Q24[ i - 1 ] = SKP_SMLAWB( coefs_ana_Q24[ i - 1 ], coefs_ana_Q24[ i ], lambda_Q16 ); - } - lambda_Q16 = -lambda_Q16; - nom_Q16 = SKP_SMLAWB( SILK_FIX_CONST( 1.0, 16 ), -lambda_Q16, lambda_Q16 ); - den_Q24 = SKP_SMLAWB( SILK_FIX_CONST( 1.0, 24 ), coefs_syn_Q24[ 0 ], lambda_Q16 ); - gain_syn_Q16 = silk_DIV32_varQ( nom_Q16, den_Q24, 24 ); - den_Q24 = SKP_SMLAWB( SILK_FIX_CONST( 1.0, 24 ), coefs_ana_Q24[ 0 ], lambda_Q16 ); - gain_ana_Q16 = silk_DIV32_varQ( nom_Q16, den_Q24, 24 ); - for( i = 0; i < order; i++ ) { - coefs_syn_Q24[ i ] = SKP_SMULWW( gain_syn_Q16, coefs_syn_Q24[ i ] ); - coefs_ana_Q24[ i ] = SKP_SMULWW( gain_ana_Q16, coefs_ana_Q24[ i ] ); - } - - for( iter = 0; iter < 10; iter++ ) { - /* Find maximum absolute value */ - maxabs_Q24 = -1; - for( i = 0; i < order; i++ ) { - tmp = SKP_max( SKP_abs_int32( coefs_syn_Q24[ i ] ), SKP_abs_int32( coefs_ana_Q24[ i ] ) ); - if( tmp > maxabs_Q24 ) { - maxabs_Q24 = tmp; - ind = i; - } - } - if( maxabs_Q24 <= limit_Q24 ) { - /* Coefficients are within range - done */ - return; - } - - /* Convert back to true warped coefficients */ - for( i = 1; i < order; i++ ) { - coefs_syn_Q24[ i - 1 ] = SKP_SMLAWB( coefs_syn_Q24[ i - 1 ], coefs_syn_Q24[ i ], lambda_Q16 ); - coefs_ana_Q24[ i - 1 ] = SKP_SMLAWB( coefs_ana_Q24[ i - 1 ], coefs_ana_Q24[ i ], lambda_Q16 ); - } - gain_syn_Q16 = silk_INVERSE32_varQ( gain_syn_Q16, 32 ); - gain_ana_Q16 = silk_INVERSE32_varQ( gain_ana_Q16, 32 ); - for( i = 0; i < order; i++ ) { - coefs_syn_Q24[ i ] = SKP_SMULWW( gain_syn_Q16, coefs_syn_Q24[ i ] ); - coefs_ana_Q24[ i ] = SKP_SMULWW( gain_ana_Q16, coefs_ana_Q24[ i ] ); - } - - /* Apply bandwidth expansion */ - chirp_Q16 = SILK_FIX_CONST( 0.99, 16 ) - silk_DIV32_varQ( - SKP_SMULWB( maxabs_Q24 - limit_Q24, SKP_SMLABB( SILK_FIX_CONST( 0.8, 10 ), SILK_FIX_CONST( 0.1, 10 ), iter ) ), - SKP_MUL( maxabs_Q24, ind + 1 ), 22 ); - silk_bwexpander_32( coefs_syn_Q24, order, chirp_Q16 ); - silk_bwexpander_32( coefs_ana_Q24, order, chirp_Q16 ); - - /* Convert to monic warped coefficients */ - lambda_Q16 = -lambda_Q16; - for( i = order - 1; i > 0; i-- ) { - coefs_syn_Q24[ i - 1 ] = SKP_SMLAWB( coefs_syn_Q24[ i - 1 ], coefs_syn_Q24[ i ], lambda_Q16 ); - coefs_ana_Q24[ i - 1 ] = SKP_SMLAWB( coefs_ana_Q24[ i - 1 ], coefs_ana_Q24[ i ], lambda_Q16 ); - } - lambda_Q16 = -lambda_Q16; - nom_Q16 = SKP_SMLAWB( SILK_FIX_CONST( 1.0, 16 ), -lambda_Q16, lambda_Q16 ); - den_Q24 = SKP_SMLAWB( SILK_FIX_CONST( 1.0, 24 ), coefs_syn_Q24[ 0 ], lambda_Q16 ); - gain_syn_Q16 = silk_DIV32_varQ( nom_Q16, den_Q24, 24 ); - den_Q24 = SKP_SMLAWB( SILK_FIX_CONST( 1.0, 24 ), coefs_ana_Q24[ 0 ], lambda_Q16 ); - gain_ana_Q16 = silk_DIV32_varQ( nom_Q16, den_Q24, 24 ); - for( i = 0; i < order; i++ ) { - coefs_syn_Q24[ i ] = SKP_SMULWW( gain_syn_Q16, coefs_syn_Q24[ i ] ); - coefs_ana_Q24[ i ] = SKP_SMULWW( gain_ana_Q16, coefs_ana_Q24[ i ] ); - } - } - SKP_assert( 0 ); -} - -/**************************************************************/ -/* Compute noise shaping coefficients and initial gain values */ -/**************************************************************/ -void silk_noise_shape_analysis_FIX( - silk_encoder_state_FIX *psEnc, /* I/O Encoder state FIX */ - silk_encoder_control_FIX *psEncCtrl, /* I/O Encoder control FIX */ - const opus_int16 *pitch_res, /* I LPC residual from pitch analysis */ - const opus_int16 *x /* I Input signal [ frame_length + la_shape ] */ -) -{ - silk_shape_state_FIX *psShapeSt = &psEnc->sShape; - opus_int k, i, nSamples, Qnrg, b_Q14, warping_Q16, scale = 0; - opus_int32 SNR_adj_dB_Q7, HarmBoost_Q16, HarmShapeGain_Q16, Tilt_Q16, tmp32; - opus_int32 nrg, pre_nrg_Q30, log_energy_Q7, log_energy_prev_Q7, energy_variation_Q7; - opus_int32 delta_Q16, BWExp1_Q16, BWExp2_Q16, gain_mult_Q16, gain_add_Q16, strength_Q16, b_Q8; - opus_int32 auto_corr[ MAX_SHAPE_LPC_ORDER + 1 ]; - opus_int32 refl_coef_Q16[ MAX_SHAPE_LPC_ORDER ]; - opus_int32 AR1_Q24[ MAX_SHAPE_LPC_ORDER ]; - opus_int32 AR2_Q24[ MAX_SHAPE_LPC_ORDER ]; - opus_int16 x_windowed[ SHAPE_LPC_WIN_MAX ]; - opus_int32 sqrt_nrg[ MAX_NB_SUBFR ], Qnrg_vec[ MAX_NB_SUBFR ]; - const opus_int16 *x_ptr, *pitch_res_ptr; - - /* Point to start of first LPC analysis block */ - x_ptr = x - psEnc->sCmn.la_shape; - - /****************/ - /* GAIN CONTROL */ - /****************/ - SNR_adj_dB_Q7 = psEnc->sCmn.SNR_dB_Q7; - - /* Input quality is the average of the quality in the lowest two VAD bands */ - psEncCtrl->input_quality_Q14 = ( opus_int )SKP_RSHIFT( ( opus_int32 )psEnc->sCmn.input_quality_bands_Q15[ 0 ] - + psEnc->sCmn.input_quality_bands_Q15[ 1 ], 2 ); - - /* Coding quality level, between 0.0_Q0 and 1.0_Q0, but in Q14 */ - psEncCtrl->coding_quality_Q14 = SKP_RSHIFT( silk_sigm_Q15( SKP_RSHIFT_ROUND( SNR_adj_dB_Q7 - - SILK_FIX_CONST( 18.0, 7 ), 4 ) ), 1 ); - - /* Reduce coding SNR during low speech activity */ - if( psEnc->sCmn.useCBR == 0 ) { - b_Q8 = SILK_FIX_CONST( 1.0, 8 ) - psEnc->sCmn.speech_activity_Q8; - b_Q8 = SKP_SMULWB( SKP_LSHIFT( b_Q8, 8 ), b_Q8 ); - SNR_adj_dB_Q7 = SKP_SMLAWB( SNR_adj_dB_Q7, - SKP_SMULBB( SILK_FIX_CONST( -BG_SNR_DECR_dB, 7 ) >> ( 4 + 1 ), b_Q8 ), // Q11 - SKP_SMULWB( SILK_FIX_CONST( 1.0, 14 ) + psEncCtrl->input_quality_Q14, psEncCtrl->coding_quality_Q14 ) ); // Q12 - } - - if( psEnc->sCmn.indices.signalType == TYPE_VOICED ) { - /* Reduce gains for periodic signals */ - SNR_adj_dB_Q7 = SKP_SMLAWB( SNR_adj_dB_Q7, SILK_FIX_CONST( HARM_SNR_INCR_dB, 8 ), psEnc->LTPCorr_Q15 ); - } else { - /* For unvoiced signals and low-quality input, adjust the quality slower than SNR_dB setting */ - SNR_adj_dB_Q7 = SKP_SMLAWB( SNR_adj_dB_Q7, - SKP_SMLAWB( SILK_FIX_CONST( 6.0, 9 ), -SILK_FIX_CONST( 0.4, 18 ), psEnc->sCmn.SNR_dB_Q7 ), - SILK_FIX_CONST( 1.0, 14 ) - psEncCtrl->input_quality_Q14 ); - } - - /*************************/ - /* SPARSENESS PROCESSING */ - /*************************/ - /* Set quantizer offset */ - if( psEnc->sCmn.indices.signalType == TYPE_VOICED ) { - /* Initally set to 0; may be overruled in process_gains(..) */ - psEnc->sCmn.indices.quantOffsetType = 0; - psEncCtrl->sparseness_Q8 = 0; - } else { - /* Sparseness measure, based on relative fluctuations of energy per 2 milliseconds */ - nSamples = SKP_LSHIFT( psEnc->sCmn.fs_kHz, 1 ); - energy_variation_Q7 = 0; - log_energy_prev_Q7 = 0; - pitch_res_ptr = pitch_res; - for( k = 0; k < SKP_SMULBB( SUB_FRAME_LENGTH_MS, psEnc->sCmn.nb_subfr ) / 2; k++ ) { - silk_sum_sqr_shift( &nrg, &scale, pitch_res_ptr, nSamples ); - nrg += SKP_RSHIFT( nSamples, scale ); // Q(-scale) - - log_energy_Q7 = silk_lin2log( nrg ); - if( k > 0 ) { - energy_variation_Q7 += SKP_abs( log_energy_Q7 - log_energy_prev_Q7 ); - } - log_energy_prev_Q7 = log_energy_Q7; - pitch_res_ptr += nSamples; - } - - psEncCtrl->sparseness_Q8 = SKP_RSHIFT( silk_sigm_Q15( SKP_SMULWB( energy_variation_Q7 - - SILK_FIX_CONST( 5.0, 7 ), SILK_FIX_CONST( 0.1, 16 ) ) ), 7 ); - - /* Set quantization offset depending on sparseness measure */ - if( psEncCtrl->sparseness_Q8 > SILK_FIX_CONST( SPARSENESS_THRESHOLD_QNT_OFFSET, 8 ) ) { - psEnc->sCmn.indices.quantOffsetType = 0; - } else { - psEnc->sCmn.indices.quantOffsetType = 1; - } - - /* Increase coding SNR for sparse signals */ - SNR_adj_dB_Q7 = SKP_SMLAWB( SNR_adj_dB_Q7, SILK_FIX_CONST( SPARSE_SNR_INCR_dB, 15 ), psEncCtrl->sparseness_Q8 - SILK_FIX_CONST( 0.5, 8 ) ); - } - - /*******************************/ - /* Control bandwidth expansion */ - /*******************************/ - /* More BWE for signals with high prediction gain */ - strength_Q16 = SKP_SMULWB( psEncCtrl->predGain_Q16, SILK_FIX_CONST( FIND_PITCH_WHITE_NOISE_FRACTION, 16 ) ); - BWExp1_Q16 = BWExp2_Q16 = silk_DIV32_varQ( SILK_FIX_CONST( BANDWIDTH_EXPANSION, 16 ), - SKP_SMLAWW( SILK_FIX_CONST( 1.0, 16 ), strength_Q16, strength_Q16 ), 16 ); - delta_Q16 = SKP_SMULWB( SILK_FIX_CONST( 1.0, 16 ) - SKP_SMULBB( 3, psEncCtrl->coding_quality_Q14 ), - SILK_FIX_CONST( LOW_RATE_BANDWIDTH_EXPANSION_DELTA, 16 ) ); - BWExp1_Q16 = SKP_SUB32( BWExp1_Q16, delta_Q16 ); - BWExp2_Q16 = SKP_ADD32( BWExp2_Q16, delta_Q16 ); - /* BWExp1 will be applied after BWExp2, so make it relative */ - BWExp1_Q16 = SKP_DIV32_16( SKP_LSHIFT( BWExp1_Q16, 14 ), SKP_RSHIFT( BWExp2_Q16, 2 ) ); - - if( psEnc->sCmn.warping_Q16 > 0 ) { - /* Slightly more warping in analysis will move quantization noise up in frequency, where it's better masked */ - warping_Q16 = SKP_SMLAWB( psEnc->sCmn.warping_Q16, psEncCtrl->coding_quality_Q14, SILK_FIX_CONST( 0.01, 18 ) ); - } else { - warping_Q16 = 0; - } - - /********************************************/ - /* Compute noise shaping AR coefs and gains */ - /********************************************/ - for( k = 0; k < psEnc->sCmn.nb_subfr; k++ ) { - /* Apply window: sine slope followed by flat part followed by cosine slope */ - opus_int shift, slope_part, flat_part; - flat_part = psEnc->sCmn.fs_kHz * 3; - slope_part = SKP_RSHIFT( psEnc->sCmn.shapeWinLength - flat_part, 1 ); - - silk_apply_sine_window( x_windowed, x_ptr, 1, slope_part ); - shift = slope_part; - SKP_memcpy( x_windowed + shift, x_ptr + shift, flat_part * sizeof(opus_int16) ); - shift += flat_part; - silk_apply_sine_window( x_windowed + shift, x_ptr + shift, 2, slope_part ); - - /* Update pointer: next LPC analysis block */ - x_ptr += psEnc->sCmn.subfr_length; - - if( psEnc->sCmn.warping_Q16 > 0 ) { - /* Calculate warped auto correlation */ - silk_warped_autocorrelation_FIX( auto_corr, &scale, x_windowed, warping_Q16, psEnc->sCmn.shapeWinLength, psEnc->sCmn.shapingLPCOrder ); - } else { - /* Calculate regular auto correlation */ - silk_autocorr( auto_corr, &scale, x_windowed, psEnc->sCmn.shapeWinLength, psEnc->sCmn.shapingLPCOrder + 1 ); - } - - /* Add white noise, as a fraction of energy */ - auto_corr[0] = SKP_ADD32( auto_corr[0], SKP_max_32( SKP_SMULWB( SKP_RSHIFT( auto_corr[ 0 ], 4 ), - SILK_FIX_CONST( SHAPE_WHITE_NOISE_FRACTION, 20 ) ), 1 ) ); - - /* Calculate the reflection coefficients using schur */ - nrg = silk_schur64( refl_coef_Q16, auto_corr, psEnc->sCmn.shapingLPCOrder ); - SKP_assert( nrg >= 0 ); - - /* Convert reflection coefficients to prediction coefficients */ - silk_k2a_Q16( AR2_Q24, refl_coef_Q16, psEnc->sCmn.shapingLPCOrder ); - - Qnrg = -scale; // range: -12...30 - SKP_assert( Qnrg >= -12 ); - SKP_assert( Qnrg <= 30 ); - - /* Make sure that Qnrg is an even number */ - if( Qnrg & 1 ) { - Qnrg -= 1; - nrg >>= 1; - } - - tmp32 = silk_SQRT_APPROX( nrg ); - Qnrg >>= 1; // range: -6...15 - - sqrt_nrg[ k ] = tmp32; - Qnrg_vec[ k ] = Qnrg; - - psEncCtrl->Gains_Q16[ k ] = SKP_LSHIFT_SAT32( tmp32, 16 - Qnrg ); - - if( psEnc->sCmn.warping_Q16 > 0 ) { - /* Adjust gain for warping */ - gain_mult_Q16 = warped_gain( AR2_Q24, warping_Q16, psEnc->sCmn.shapingLPCOrder ); - SKP_assert( psEncCtrl->Gains_Q16[ k ] >= 0 ); - psEncCtrl->Gains_Q16[ k ] = SKP_SMULWW( psEncCtrl->Gains_Q16[ k ], gain_mult_Q16 ); - if( psEncCtrl->Gains_Q16[ k ] < 0 ) { - psEncCtrl->Gains_Q16[ k ] = SKP_int32_MAX; - } - } - - /* Bandwidth expansion for synthesis filter shaping */ - silk_bwexpander_32( AR2_Q24, psEnc->sCmn.shapingLPCOrder, BWExp2_Q16 ); - - /* Compute noise shaping filter coefficients */ - SKP_memcpy( AR1_Q24, AR2_Q24, psEnc->sCmn.shapingLPCOrder * sizeof( opus_int32 ) ); - - /* Bandwidth expansion for analysis filter shaping */ - SKP_assert( BWExp1_Q16 <= SILK_FIX_CONST( 1.0, 16 ) ); - silk_bwexpander_32( AR1_Q24, psEnc->sCmn.shapingLPCOrder, BWExp1_Q16 ); - - /* Ratio of prediction gains, in energy domain */ - silk_LPC_inverse_pred_gain_Q24( &pre_nrg_Q30, AR2_Q24, psEnc->sCmn.shapingLPCOrder ); - silk_LPC_inverse_pred_gain_Q24( &nrg, AR1_Q24, psEnc->sCmn.shapingLPCOrder ); - - //psEncCtrl->GainsPre[ k ] = 1.0f - 0.7f * ( 1.0f - pre_nrg / nrg ) = 0.3f + 0.7f * pre_nrg / nrg; - pre_nrg_Q30 = SKP_LSHIFT32( SKP_SMULWB( pre_nrg_Q30, SILK_FIX_CONST( 0.7, 15 ) ), 1 ); - psEncCtrl->GainsPre_Q14[ k ] = ( opus_int ) SILK_FIX_CONST( 0.3, 14 ) + silk_DIV32_varQ( pre_nrg_Q30, nrg, 14 ); - - /* Convert to monic warped prediction coefficients and limit absolute values */ - limit_warped_coefs( AR2_Q24, AR1_Q24, warping_Q16, SILK_FIX_CONST( 3.999, 24 ), psEnc->sCmn.shapingLPCOrder ); - - /* Convert from Q24 to Q13 and store in int16 */ - for( i = 0; i < psEnc->sCmn.shapingLPCOrder; i++ ) { - psEncCtrl->AR1_Q13[ k * MAX_SHAPE_LPC_ORDER + i ] = (opus_int16)SKP_SAT16( SKP_RSHIFT_ROUND( AR1_Q24[ i ], 11 ) ); - psEncCtrl->AR2_Q13[ k * MAX_SHAPE_LPC_ORDER + i ] = (opus_int16)SKP_SAT16( SKP_RSHIFT_ROUND( AR2_Q24[ i ], 11 ) ); - } - } - - /*****************/ - /* Gain tweaking */ - /*****************/ - /* Increase gains during low speech activity and put lower limit on gains */ - gain_mult_Q16 = silk_log2lin( -SKP_SMLAWB( -SILK_FIX_CONST( 16.0, 7 ), SNR_adj_dB_Q7, SILK_FIX_CONST( 0.16, 16 ) ) ); - gain_add_Q16 = silk_log2lin( SKP_SMLAWB( SILK_FIX_CONST( 16.0, 7 ), SILK_FIX_CONST( MIN_QGAIN_DB, 7 ), SILK_FIX_CONST( 0.16, 16 ) ) ); - SKP_assert( gain_mult_Q16 > 0 ); - for( k = 0; k < psEnc->sCmn.nb_subfr; k++ ) { - psEncCtrl->Gains_Q16[ k ] = SKP_SMULWW( psEncCtrl->Gains_Q16[ k ], gain_mult_Q16 ); - SKP_assert( psEncCtrl->Gains_Q16[ k ] >= 0 ); - psEncCtrl->Gains_Q16[ k ] = SKP_ADD_POS_SAT32( psEncCtrl->Gains_Q16[ k ], gain_add_Q16 ); - } - - gain_mult_Q16 = SILK_FIX_CONST( 1.0, 16 ) + SKP_RSHIFT_ROUND( SKP_MLA( SILK_FIX_CONST( INPUT_TILT, 26 ), - psEncCtrl->coding_quality_Q14, SILK_FIX_CONST( HIGH_RATE_INPUT_TILT, 12 ) ), 10 ); - for( k = 0; k < psEnc->sCmn.nb_subfr; k++ ) { - psEncCtrl->GainsPre_Q14[ k ] = SKP_SMULWB( gain_mult_Q16, psEncCtrl->GainsPre_Q14[ k ] ); - } - - /************************************************/ - /* Control low-frequency shaping and noise tilt */ - /************************************************/ - /* Less low frequency shaping for noisy inputs */ - strength_Q16 = SKP_MUL( SILK_FIX_CONST( LOW_FREQ_SHAPING, 4 ), SKP_SMLAWB( SILK_FIX_CONST( 1.0, 12 ), - SILK_FIX_CONST( LOW_QUALITY_LOW_FREQ_SHAPING_DECR, 13 ), psEnc->sCmn.input_quality_bands_Q15[ 0 ] - SILK_FIX_CONST( 1.0, 15 ) ) ); - strength_Q16 = SKP_RSHIFT( SKP_MUL( strength_Q16, psEnc->sCmn.speech_activity_Q8 ), 8 ); - if( psEnc->sCmn.indices.signalType == TYPE_VOICED ) { - /* Reduce low frequencies quantization noise for periodic signals, depending on pitch lag */ - /*f = 400; freqz([1, -0.98 + 2e-4 * f], [1, -0.97 + 7e-4 * f], 2^12, Fs); axis([0, 1000, -10, 1])*/ - opus_int fs_kHz_inv = SKP_DIV32_16( SILK_FIX_CONST( 0.2, 14 ), psEnc->sCmn.fs_kHz ); - for( k = 0; k < psEnc->sCmn.nb_subfr; k++ ) { - b_Q14 = fs_kHz_inv + SKP_DIV32_16( SILK_FIX_CONST( 3.0, 14 ), psEncCtrl->pitchL[ k ] ); - /* Pack two coefficients in one int32 */ - psEncCtrl->LF_shp_Q14[ k ] = SKP_LSHIFT( SILK_FIX_CONST( 1.0, 14 ) - b_Q14 - SKP_SMULWB( strength_Q16, b_Q14 ), 16 ); - psEncCtrl->LF_shp_Q14[ k ] |= (opus_uint16)( b_Q14 - SILK_FIX_CONST( 1.0, 14 ) ); - } - SKP_assert( SILK_FIX_CONST( HARM_HP_NOISE_COEF, 24 ) < SILK_FIX_CONST( 0.5, 24 ) ); // Guarantees that second argument to SMULWB() is within range of an opus_int16 - Tilt_Q16 = - SILK_FIX_CONST( HP_NOISE_COEF, 16 ) - - SKP_SMULWB( SILK_FIX_CONST( 1.0, 16 ) - SILK_FIX_CONST( HP_NOISE_COEF, 16 ), - SKP_SMULWB( SILK_FIX_CONST( HARM_HP_NOISE_COEF, 24 ), psEnc->sCmn.speech_activity_Q8 ) ); - } else { - b_Q14 = SKP_DIV32_16( 21299, psEnc->sCmn.fs_kHz ); // 1.3_Q0 = 21299_Q14 - /* Pack two coefficients in one int32 */ - psEncCtrl->LF_shp_Q14[ 0 ] = SKP_LSHIFT( SILK_FIX_CONST( 1.0, 14 ) - b_Q14 - - SKP_SMULWB( strength_Q16, SKP_SMULWB( SILK_FIX_CONST( 0.6, 16 ), b_Q14 ) ), 16 ); - psEncCtrl->LF_shp_Q14[ 0 ] |= (opus_uint16)( b_Q14 - SILK_FIX_CONST( 1.0, 14 ) ); - for( k = 1; k < psEnc->sCmn.nb_subfr; k++ ) { - psEncCtrl->LF_shp_Q14[ k ] = psEncCtrl->LF_shp_Q14[ 0 ]; - } - Tilt_Q16 = -SILK_FIX_CONST( HP_NOISE_COEF, 16 ); - } - - /****************************/ - /* HARMONIC SHAPING CONTROL */ - /****************************/ - /* Control boosting of harmonic frequencies */ - HarmBoost_Q16 = SKP_SMULWB( SKP_SMULWB( SILK_FIX_CONST( 1.0, 17 ) - SKP_LSHIFT( psEncCtrl->coding_quality_Q14, 3 ), - psEnc->LTPCorr_Q15 ), SILK_FIX_CONST( LOW_RATE_HARMONIC_BOOST, 16 ) ); - - /* More harmonic boost for noisy input signals */ - HarmBoost_Q16 = SKP_SMLAWB( HarmBoost_Q16, - SILK_FIX_CONST( 1.0, 16 ) - SKP_LSHIFT( psEncCtrl->input_quality_Q14, 2 ), SILK_FIX_CONST( LOW_INPUT_QUALITY_HARMONIC_BOOST, 16 ) ); - - if( USE_HARM_SHAPING && psEnc->sCmn.indices.signalType == TYPE_VOICED ) { - /* More harmonic noise shaping for high bitrates or noisy input */ - HarmShapeGain_Q16 = SKP_SMLAWB( SILK_FIX_CONST( HARMONIC_SHAPING, 16 ), - SILK_FIX_CONST( 1.0, 16 ) - SKP_SMULWB( SILK_FIX_CONST( 1.0, 18 ) - SKP_LSHIFT( psEncCtrl->coding_quality_Q14, 4 ), - psEncCtrl->input_quality_Q14 ), SILK_FIX_CONST( HIGH_RATE_OR_LOW_QUALITY_HARMONIC_SHAPING, 16 ) ); - - /* Less harmonic noise shaping for less periodic signals */ - HarmShapeGain_Q16 = SKP_SMULWB( SKP_LSHIFT( HarmShapeGain_Q16, 1 ), - silk_SQRT_APPROX( SKP_LSHIFT( psEnc->LTPCorr_Q15, 15 ) ) ); - } else { - HarmShapeGain_Q16 = 0; - } - - /*************************/ - /* Smooth over subframes */ - /*************************/ - for( k = 0; k < MAX_NB_SUBFR; k++ ) { - psShapeSt->HarmBoost_smth_Q16 = - SKP_SMLAWB( psShapeSt->HarmBoost_smth_Q16, HarmBoost_Q16 - psShapeSt->HarmBoost_smth_Q16, SILK_FIX_CONST( SUBFR_SMTH_COEF, 16 ) ); - psShapeSt->HarmShapeGain_smth_Q16 = - SKP_SMLAWB( psShapeSt->HarmShapeGain_smth_Q16, HarmShapeGain_Q16 - psShapeSt->HarmShapeGain_smth_Q16, SILK_FIX_CONST( SUBFR_SMTH_COEF, 16 ) ); - psShapeSt->Tilt_smth_Q16 = - SKP_SMLAWB( psShapeSt->Tilt_smth_Q16, Tilt_Q16 - psShapeSt->Tilt_smth_Q16, SILK_FIX_CONST( SUBFR_SMTH_COEF, 16 ) ); - - psEncCtrl->HarmBoost_Q14[ k ] = ( opus_int )SKP_RSHIFT_ROUND( psShapeSt->HarmBoost_smth_Q16, 2 ); - psEncCtrl->HarmShapeGain_Q14[ k ] = ( opus_int )SKP_RSHIFT_ROUND( psShapeSt->HarmShapeGain_smth_Q16, 2 ); - psEncCtrl->Tilt_Q14[ k ] = ( opus_int )SKP_RSHIFT_ROUND( psShapeSt->Tilt_smth_Q16, 2 ); - } -} +/*********************************************************************** +Copyright (c) 2006-2011, Skype Limited. All rights reserved. +Redistribution and use in source and binary forms, with or without +modification, (subject to the limitations in the disclaimer below) +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 Skype Limited, nor the names of specific +contributors, may be used to endorse or promote products derived from +this software without specific prior written permission. +NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED +BY THIS LICENSE. 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. +***********************************************************************/ + +#include "silk_main_FIX.h" +#include "silk_tuning_parameters.h" + +/* Compute gain to make warped filter coefficients have a zero mean log frequency response on a */ +/* non-warped frequency scale. (So that it can be implemented with a minimum-phase monic filter.) */ +SKP_INLINE opus_int32 warped_gain( // gain in Q16 + const opus_int32 *coefs_Q24, + opus_int lambda_Q16, + opus_int order +) { + opus_int i; + opus_int32 gain_Q24; + + lambda_Q16 = -lambda_Q16; + gain_Q24 = coefs_Q24[ order - 1 ]; + for( i = order - 2; i >= 0; i-- ) { + gain_Q24 = SKP_SMLAWB( coefs_Q24[ i ], gain_Q24, lambda_Q16 ); + } + gain_Q24 = SKP_SMLAWB( SILK_FIX_CONST( 1.0, 24 ), gain_Q24, -lambda_Q16 ); + return silk_INVERSE32_varQ( gain_Q24, 40 ); +} + +/* Convert warped filter coefficients to monic pseudo-warped coefficients and limit maximum */ +/* amplitude of monic warped coefficients by using bandwidth expansion on the true coefficients */ +SKP_INLINE void limit_warped_coefs( + opus_int32 *coefs_syn_Q24, + opus_int32 *coefs_ana_Q24, + opus_int lambda_Q16, + opus_int32 limit_Q24, + opus_int order +) { + opus_int i, iter, ind = 0; + opus_int32 tmp, maxabs_Q24, chirp_Q16, gain_syn_Q16, gain_ana_Q16; + opus_int32 nom_Q16, den_Q24; + + /* Convert to monic coefficients */ + lambda_Q16 = -lambda_Q16; + for( i = order - 1; i > 0; i-- ) { + coefs_syn_Q24[ i - 1 ] = SKP_SMLAWB( coefs_syn_Q24[ i - 1 ], coefs_syn_Q24[ i ], lambda_Q16 ); + coefs_ana_Q24[ i - 1 ] = SKP_SMLAWB( coefs_ana_Q24[ i - 1 ], coefs_ana_Q24[ i ], lambda_Q16 ); + } + lambda_Q16 = -lambda_Q16; + nom_Q16 = SKP_SMLAWB( SILK_FIX_CONST( 1.0, 16 ), -lambda_Q16, lambda_Q16 ); + den_Q24 = SKP_SMLAWB( SILK_FIX_CONST( 1.0, 24 ), coefs_syn_Q24[ 0 ], lambda_Q16 ); + gain_syn_Q16 = silk_DIV32_varQ( nom_Q16, den_Q24, 24 ); + den_Q24 = SKP_SMLAWB( SILK_FIX_CONST( 1.0, 24 ), coefs_ana_Q24[ 0 ], lambda_Q16 ); + gain_ana_Q16 = silk_DIV32_varQ( nom_Q16, den_Q24, 24 ); + for( i = 0; i < order; i++ ) { + coefs_syn_Q24[ i ] = SKP_SMULWW( gain_syn_Q16, coefs_syn_Q24[ i ] ); + coefs_ana_Q24[ i ] = SKP_SMULWW( gain_ana_Q16, coefs_ana_Q24[ i ] ); + } + + for( iter = 0; iter < 10; iter++ ) { + /* Find maximum absolute value */ + maxabs_Q24 = -1; + for( i = 0; i < order; i++ ) { + tmp = SKP_max( SKP_abs_int32( coefs_syn_Q24[ i ] ), SKP_abs_int32( coefs_ana_Q24[ i ] ) ); + if( tmp > maxabs_Q24 ) { + maxabs_Q24 = tmp; + ind = i; + } + } + if( maxabs_Q24 <= limit_Q24 ) { + /* Coefficients are within range - done */ + return; + } + + /* Convert back to true warped coefficients */ + for( i = 1; i < order; i++ ) { + coefs_syn_Q24[ i - 1 ] = SKP_SMLAWB( coefs_syn_Q24[ i - 1 ], coefs_syn_Q24[ i ], lambda_Q16 ); + coefs_ana_Q24[ i - 1 ] = SKP_SMLAWB( coefs_ana_Q24[ i - 1 ], coefs_ana_Q24[ i ], lambda_Q16 ); + } + gain_syn_Q16 = silk_INVERSE32_varQ( gain_syn_Q16, 32 ); + gain_ana_Q16 = silk_INVERSE32_varQ( gain_ana_Q16, 32 ); + for( i = 0; i < order; i++ ) { + coefs_syn_Q24[ i ] = SKP_SMULWW( gain_syn_Q16, coefs_syn_Q24[ i ] ); + coefs_ana_Q24[ i ] = SKP_SMULWW( gain_ana_Q16, coefs_ana_Q24[ i ] ); + } + + /* Apply bandwidth expansion */ + chirp_Q16 = SILK_FIX_CONST( 0.99, 16 ) - silk_DIV32_varQ( + SKP_SMULWB( maxabs_Q24 - limit_Q24, SKP_SMLABB( SILK_FIX_CONST( 0.8, 10 ), SILK_FIX_CONST( 0.1, 10 ), iter ) ), + SKP_MUL( maxabs_Q24, ind + 1 ), 22 ); + silk_bwexpander_32( coefs_syn_Q24, order, chirp_Q16 ); + silk_bwexpander_32( coefs_ana_Q24, order, chirp_Q16 ); + + /* Convert to monic warped coefficients */ + lambda_Q16 = -lambda_Q16; + for( i = order - 1; i > 0; i-- ) { + coefs_syn_Q24[ i - 1 ] = SKP_SMLAWB( coefs_syn_Q24[ i - 1 ], coefs_syn_Q24[ i ], lambda_Q16 ); + coefs_ana_Q24[ i - 1 ] = SKP_SMLAWB( coefs_ana_Q24[ i - 1 ], coefs_ana_Q24[ i ], lambda_Q16 ); + } + lambda_Q16 = -lambda_Q16; + nom_Q16 = SKP_SMLAWB( SILK_FIX_CONST( 1.0, 16 ), -lambda_Q16, lambda_Q16 ); + den_Q24 = SKP_SMLAWB( SILK_FIX_CONST( 1.0, 24 ), coefs_syn_Q24[ 0 ], lambda_Q16 ); + gain_syn_Q16 = silk_DIV32_varQ( nom_Q16, den_Q24, 24 ); + den_Q24 = SKP_SMLAWB( SILK_FIX_CONST( 1.0, 24 ), coefs_ana_Q24[ 0 ], lambda_Q16 ); + gain_ana_Q16 = silk_DIV32_varQ( nom_Q16, den_Q24, 24 ); + for( i = 0; i < order; i++ ) { + coefs_syn_Q24[ i ] = SKP_SMULWW( gain_syn_Q16, coefs_syn_Q24[ i ] ); + coefs_ana_Q24[ i ] = SKP_SMULWW( gain_ana_Q16, coefs_ana_Q24[ i ] ); + } + } + SKP_assert( 0 ); +} + +/**************************************************************/ +/* Compute noise shaping coefficients and initial gain values */ +/**************************************************************/ +void silk_noise_shape_analysis_FIX( + silk_encoder_state_FIX *psEnc, /* I/O Encoder state FIX */ + silk_encoder_control_FIX *psEncCtrl, /* I/O Encoder control FIX */ + const opus_int16 *pitch_res, /* I LPC residual from pitch analysis */ + const opus_int16 *x /* I Input signal [ frame_length + la_shape ] */ +) +{ + silk_shape_state_FIX *psShapeSt = &psEnc->sShape; + opus_int k, i, nSamples, Qnrg, b_Q14, warping_Q16, scale = 0; + opus_int32 SNR_adj_dB_Q7, HarmBoost_Q16, HarmShapeGain_Q16, Tilt_Q16, tmp32; + opus_int32 nrg, pre_nrg_Q30, log_energy_Q7, log_energy_prev_Q7, energy_variation_Q7; + opus_int32 delta_Q16, BWExp1_Q16, BWExp2_Q16, gain_mult_Q16, gain_add_Q16, strength_Q16, b_Q8; + opus_int32 auto_corr[ MAX_SHAPE_LPC_ORDER + 1 ]; + opus_int32 refl_coef_Q16[ MAX_SHAPE_LPC_ORDER ]; + opus_int32 AR1_Q24[ MAX_SHAPE_LPC_ORDER ]; + opus_int32 AR2_Q24[ MAX_SHAPE_LPC_ORDER ]; + opus_int16 x_windowed[ SHAPE_LPC_WIN_MAX ]; + opus_int32 sqrt_nrg[ MAX_NB_SUBFR ], Qnrg_vec[ MAX_NB_SUBFR ]; + const opus_int16 *x_ptr, *pitch_res_ptr; + + /* Point to start of first LPC analysis block */ + x_ptr = x - psEnc->sCmn.la_shape; + + /****************/ + /* GAIN CONTROL */ + /****************/ + SNR_adj_dB_Q7 = psEnc->sCmn.SNR_dB_Q7; + + /* Input quality is the average of the quality in the lowest two VAD bands */ + psEncCtrl->input_quality_Q14 = ( opus_int )SKP_RSHIFT( ( opus_int32 )psEnc->sCmn.input_quality_bands_Q15[ 0 ] + + psEnc->sCmn.input_quality_bands_Q15[ 1 ], 2 ); + + /* Coding quality level, between 0.0_Q0 and 1.0_Q0, but in Q14 */ + psEncCtrl->coding_quality_Q14 = SKP_RSHIFT( silk_sigm_Q15( SKP_RSHIFT_ROUND( SNR_adj_dB_Q7 - + SILK_FIX_CONST( 18.0, 7 ), 4 ) ), 1 ); + + /* Reduce coding SNR during low speech activity */ + if( psEnc->sCmn.useCBR == 0 ) { + b_Q8 = SILK_FIX_CONST( 1.0, 8 ) - psEnc->sCmn.speech_activity_Q8; + b_Q8 = SKP_SMULWB( SKP_LSHIFT( b_Q8, 8 ), b_Q8 ); + SNR_adj_dB_Q7 = SKP_SMLAWB( SNR_adj_dB_Q7, + SKP_SMULBB( SILK_FIX_CONST( -BG_SNR_DECR_dB, 7 ) >> ( 4 + 1 ), b_Q8 ), // Q11 + SKP_SMULWB( SILK_FIX_CONST( 1.0, 14 ) + psEncCtrl->input_quality_Q14, psEncCtrl->coding_quality_Q14 ) ); // Q12 + } + + if( psEnc->sCmn.indices.signalType == TYPE_VOICED ) { + /* Reduce gains for periodic signals */ + SNR_adj_dB_Q7 = SKP_SMLAWB( SNR_adj_dB_Q7, SILK_FIX_CONST( HARM_SNR_INCR_dB, 8 ), psEnc->LTPCorr_Q15 ); + } else { + /* For unvoiced signals and low-quality input, adjust the quality slower than SNR_dB setting */ + SNR_adj_dB_Q7 = SKP_SMLAWB( SNR_adj_dB_Q7, + SKP_SMLAWB( SILK_FIX_CONST( 6.0, 9 ), -SILK_FIX_CONST( 0.4, 18 ), psEnc->sCmn.SNR_dB_Q7 ), + SILK_FIX_CONST( 1.0, 14 ) - psEncCtrl->input_quality_Q14 ); + } + + /*************************/ + /* SPARSENESS PROCESSING */ + /*************************/ + /* Set quantizer offset */ + if( psEnc->sCmn.indices.signalType == TYPE_VOICED ) { + /* Initally set to 0; may be overruled in process_gains(..) */ + psEnc->sCmn.indices.quantOffsetType = 0; + psEncCtrl->sparseness_Q8 = 0; + } else { + /* Sparseness measure, based on relative fluctuations of energy per 2 milliseconds */ + nSamples = SKP_LSHIFT( psEnc->sCmn.fs_kHz, 1 ); + energy_variation_Q7 = 0; + log_energy_prev_Q7 = 0; + pitch_res_ptr = pitch_res; + for( k = 0; k < SKP_SMULBB( SUB_FRAME_LENGTH_MS, psEnc->sCmn.nb_subfr ) / 2; k++ ) { + silk_sum_sqr_shift( &nrg, &scale, pitch_res_ptr, nSamples ); + nrg += SKP_RSHIFT( nSamples, scale ); // Q(-scale) + + log_energy_Q7 = silk_lin2log( nrg ); + if( k > 0 ) { + energy_variation_Q7 += SKP_abs( log_energy_Q7 - log_energy_prev_Q7 ); + } + log_energy_prev_Q7 = log_energy_Q7; + pitch_res_ptr += nSamples; + } + + psEncCtrl->sparseness_Q8 = SKP_RSHIFT( silk_sigm_Q15( SKP_SMULWB( energy_variation_Q7 - + SILK_FIX_CONST( 5.0, 7 ), SILK_FIX_CONST( 0.1, 16 ) ) ), 7 ); + + /* Set quantization offset depending on sparseness measure */ + if( psEncCtrl->sparseness_Q8 > SILK_FIX_CONST( SPARSENESS_THRESHOLD_QNT_OFFSET, 8 ) ) { + psEnc->sCmn.indices.quantOffsetType = 0; + } else { + psEnc->sCmn.indices.quantOffsetType = 1; + } + + /* Increase coding SNR for sparse signals */ + SNR_adj_dB_Q7 = SKP_SMLAWB( SNR_adj_dB_Q7, SILK_FIX_CONST( SPARSE_SNR_INCR_dB, 15 ), psEncCtrl->sparseness_Q8 - SILK_FIX_CONST( 0.5, 8 ) ); + } + + /*******************************/ + /* Control bandwidth expansion */ + /*******************************/ + /* More BWE for signals with high prediction gain */ + strength_Q16 = SKP_SMULWB( psEncCtrl->predGain_Q16, SILK_FIX_CONST( FIND_PITCH_WHITE_NOISE_FRACTION, 16 ) ); + BWExp1_Q16 = BWExp2_Q16 = silk_DIV32_varQ( SILK_FIX_CONST( BANDWIDTH_EXPANSION, 16 ), + SKP_SMLAWW( SILK_FIX_CONST( 1.0, 16 ), strength_Q16, strength_Q16 ), 16 ); + delta_Q16 = SKP_SMULWB( SILK_FIX_CONST( 1.0, 16 ) - SKP_SMULBB( 3, psEncCtrl->coding_quality_Q14 ), + SILK_FIX_CONST( LOW_RATE_BANDWIDTH_EXPANSION_DELTA, 16 ) ); + BWExp1_Q16 = SKP_SUB32( BWExp1_Q16, delta_Q16 ); + BWExp2_Q16 = SKP_ADD32( BWExp2_Q16, delta_Q16 ); + /* BWExp1 will be applied after BWExp2, so make it relative */ + BWExp1_Q16 = SKP_DIV32_16( SKP_LSHIFT( BWExp1_Q16, 14 ), SKP_RSHIFT( BWExp2_Q16, 2 ) ); + + if( psEnc->sCmn.warping_Q16 > 0 ) { + /* Slightly more warping in analysis will move quantization noise up in frequency, where it's better masked */ + warping_Q16 = SKP_SMLAWB( psEnc->sCmn.warping_Q16, psEncCtrl->coding_quality_Q14, SILK_FIX_CONST( 0.01, 18 ) ); + } else { + warping_Q16 = 0; + } + + /********************************************/ + /* Compute noise shaping AR coefs and gains */ + /********************************************/ + for( k = 0; k < psEnc->sCmn.nb_subfr; k++ ) { + /* Apply window: sine slope followed by flat part followed by cosine slope */ + opus_int shift, slope_part, flat_part; + flat_part = psEnc->sCmn.fs_kHz * 3; + slope_part = SKP_RSHIFT( psEnc->sCmn.shapeWinLength - flat_part, 1 ); + + silk_apply_sine_window( x_windowed, x_ptr, 1, slope_part ); + shift = slope_part; + SKP_memcpy( x_windowed + shift, x_ptr + shift, flat_part * sizeof(opus_int16) ); + shift += flat_part; + silk_apply_sine_window( x_windowed + shift, x_ptr + shift, 2, slope_part ); + + /* Update pointer: next LPC analysis block */ + x_ptr += psEnc->sCmn.subfr_length; + + if( psEnc->sCmn.warping_Q16 > 0 ) { + /* Calculate warped auto correlation */ + silk_warped_autocorrelation_FIX( auto_corr, &scale, x_windowed, warping_Q16, psEnc->sCmn.shapeWinLength, psEnc->sCmn.shapingLPCOrder ); + } else { + /* Calculate regular auto correlation */ + silk_autocorr( auto_corr, &scale, x_windowed, psEnc->sCmn.shapeWinLength, psEnc->sCmn.shapingLPCOrder + 1 ); + } + + /* Add white noise, as a fraction of energy */ + auto_corr[0] = SKP_ADD32( auto_corr[0], SKP_max_32( SKP_SMULWB( SKP_RSHIFT( auto_corr[ 0 ], 4 ), + SILK_FIX_CONST( SHAPE_WHITE_NOISE_FRACTION, 20 ) ), 1 ) ); + + /* Calculate the reflection coefficients using schur */ + nrg = silk_schur64( refl_coef_Q16, auto_corr, psEnc->sCmn.shapingLPCOrder ); + SKP_assert( nrg >= 0 ); + + /* Convert reflection coefficients to prediction coefficients */ + silk_k2a_Q16( AR2_Q24, refl_coef_Q16, psEnc->sCmn.shapingLPCOrder ); + + Qnrg = -scale; // range: -12...30 + SKP_assert( Qnrg >= -12 ); + SKP_assert( Qnrg <= 30 ); + + /* Make sure that Qnrg is an even number */ + if( Qnrg & 1 ) { + Qnrg -= 1; + nrg >>= 1; + } + + tmp32 = silk_SQRT_APPROX( nrg ); + Qnrg >>= 1; // range: -6...15 + + sqrt_nrg[ k ] = tmp32; + Qnrg_vec[ k ] = Qnrg; + + psEncCtrl->Gains_Q16[ k ] = SKP_LSHIFT_SAT32( tmp32, 16 - Qnrg ); + + if( psEnc->sCmn.warping_Q16 > 0 ) { + /* Adjust gain for warping */ + gain_mult_Q16 = warped_gain( AR2_Q24, warping_Q16, psEnc->sCmn.shapingLPCOrder ); + SKP_assert( psEncCtrl->Gains_Q16[ k ] >= 0 ); + psEncCtrl->Gains_Q16[ k ] = SKP_SMULWW( psEncCtrl->Gains_Q16[ k ], gain_mult_Q16 ); + if( psEncCtrl->Gains_Q16[ k ] < 0 ) { + psEncCtrl->Gains_Q16[ k ] = SKP_int32_MAX; + } + } + + /* Bandwidth expansion for synthesis filter shaping */ + silk_bwexpander_32( AR2_Q24, psEnc->sCmn.shapingLPCOrder, BWExp2_Q16 ); + + /* Compute noise shaping filter coefficients */ + SKP_memcpy( AR1_Q24, AR2_Q24, psEnc->sCmn.shapingLPCOrder * sizeof( opus_int32 ) ); + + /* Bandwidth expansion for analysis filter shaping */ + SKP_assert( BWExp1_Q16 <= SILK_FIX_CONST( 1.0, 16 ) ); + silk_bwexpander_32( AR1_Q24, psEnc->sCmn.shapingLPCOrder, BWExp1_Q16 ); + + /* Ratio of prediction gains, in energy domain */ + silk_LPC_inverse_pred_gain_Q24( &pre_nrg_Q30, AR2_Q24, psEnc->sCmn.shapingLPCOrder ); + silk_LPC_inverse_pred_gain_Q24( &nrg, AR1_Q24, psEnc->sCmn.shapingLPCOrder ); + + //psEncCtrl->GainsPre[ k ] = 1.0f - 0.7f * ( 1.0f - pre_nrg / nrg ) = 0.3f + 0.7f * pre_nrg / nrg; + pre_nrg_Q30 = SKP_LSHIFT32( SKP_SMULWB( pre_nrg_Q30, SILK_FIX_CONST( 0.7, 15 ) ), 1 ); + psEncCtrl->GainsPre_Q14[ k ] = ( opus_int ) SILK_FIX_CONST( 0.3, 14 ) + silk_DIV32_varQ( pre_nrg_Q30, nrg, 14 ); + + /* Convert to monic warped prediction coefficients and limit absolute values */ + limit_warped_coefs( AR2_Q24, AR1_Q24, warping_Q16, SILK_FIX_CONST( 3.999, 24 ), psEnc->sCmn.shapingLPCOrder ); + + /* Convert from Q24 to Q13 and store in int16 */ + for( i = 0; i < psEnc->sCmn.shapingLPCOrder; i++ ) { + psEncCtrl->AR1_Q13[ k * MAX_SHAPE_LPC_ORDER + i ] = (opus_int16)SKP_SAT16( SKP_RSHIFT_ROUND( AR1_Q24[ i ], 11 ) ); + psEncCtrl->AR2_Q13[ k * MAX_SHAPE_LPC_ORDER + i ] = (opus_int16)SKP_SAT16( SKP_RSHIFT_ROUND( AR2_Q24[ i ], 11 ) ); + } + } + + /*****************/ + /* Gain tweaking */ + /*****************/ + /* Increase gains during low speech activity and put lower limit on gains */ + gain_mult_Q16 = silk_log2lin( -SKP_SMLAWB( -SILK_FIX_CONST( 16.0, 7 ), SNR_adj_dB_Q7, SILK_FIX_CONST( 0.16, 16 ) ) ); + gain_add_Q16 = silk_log2lin( SKP_SMLAWB( SILK_FIX_CONST( 16.0, 7 ), SILK_FIX_CONST( MIN_QGAIN_DB, 7 ), SILK_FIX_CONST( 0.16, 16 ) ) ); + SKP_assert( gain_mult_Q16 > 0 ); + for( k = 0; k < psEnc->sCmn.nb_subfr; k++ ) { + psEncCtrl->Gains_Q16[ k ] = SKP_SMULWW( psEncCtrl->Gains_Q16[ k ], gain_mult_Q16 ); + SKP_assert( psEncCtrl->Gains_Q16[ k ] >= 0 ); + psEncCtrl->Gains_Q16[ k ] = SKP_ADD_POS_SAT32( psEncCtrl->Gains_Q16[ k ], gain_add_Q16 ); + } + + gain_mult_Q16 = SILK_FIX_CONST( 1.0, 16 ) + SKP_RSHIFT_ROUND( SKP_MLA( SILK_FIX_CONST( INPUT_TILT, 26 ), + psEncCtrl->coding_quality_Q14, SILK_FIX_CONST( HIGH_RATE_INPUT_TILT, 12 ) ), 10 ); + for( k = 0; k < psEnc->sCmn.nb_subfr; k++ ) { + psEncCtrl->GainsPre_Q14[ k ] = SKP_SMULWB( gain_mult_Q16, psEncCtrl->GainsPre_Q14[ k ] ); + } + + /************************************************/ + /* Control low-frequency shaping and noise tilt */ + /************************************************/ + /* Less low frequency shaping for noisy inputs */ + strength_Q16 = SKP_MUL( SILK_FIX_CONST( LOW_FREQ_SHAPING, 4 ), SKP_SMLAWB( SILK_FIX_CONST( 1.0, 12 ), + SILK_FIX_CONST( LOW_QUALITY_LOW_FREQ_SHAPING_DECR, 13 ), psEnc->sCmn.input_quality_bands_Q15[ 0 ] - SILK_FIX_CONST( 1.0, 15 ) ) ); + strength_Q16 = SKP_RSHIFT( SKP_MUL( strength_Q16, psEnc->sCmn.speech_activity_Q8 ), 8 ); + if( psEnc->sCmn.indices.signalType == TYPE_VOICED ) { + /* Reduce low frequencies quantization noise for periodic signals, depending on pitch lag */ + /*f = 400; freqz([1, -0.98 + 2e-4 * f], [1, -0.97 + 7e-4 * f], 2^12, Fs); axis([0, 1000, -10, 1])*/ + opus_int fs_kHz_inv = SKP_DIV32_16( SILK_FIX_CONST( 0.2, 14 ), psEnc->sCmn.fs_kHz ); + for( k = 0; k < psEnc->sCmn.nb_subfr; k++ ) { + b_Q14 = fs_kHz_inv + SKP_DIV32_16( SILK_FIX_CONST( 3.0, 14 ), psEncCtrl->pitchL[ k ] ); + /* Pack two coefficients in one int32 */ + psEncCtrl->LF_shp_Q14[ k ] = SKP_LSHIFT( SILK_FIX_CONST( 1.0, 14 ) - b_Q14 - SKP_SMULWB( strength_Q16, b_Q14 ), 16 ); + psEncCtrl->LF_shp_Q14[ k ] |= (opus_uint16)( b_Q14 - SILK_FIX_CONST( 1.0, 14 ) ); + } + SKP_assert( SILK_FIX_CONST( HARM_HP_NOISE_COEF, 24 ) < SILK_FIX_CONST( 0.5, 24 ) ); // Guarantees that second argument to SMULWB() is within range of an opus_int16 + Tilt_Q16 = - SILK_FIX_CONST( HP_NOISE_COEF, 16 ) - + SKP_SMULWB( SILK_FIX_CONST( 1.0, 16 ) - SILK_FIX_CONST( HP_NOISE_COEF, 16 ), + SKP_SMULWB( SILK_FIX_CONST( HARM_HP_NOISE_COEF, 24 ), psEnc->sCmn.speech_activity_Q8 ) ); + } else { + b_Q14 = SKP_DIV32_16( 21299, psEnc->sCmn.fs_kHz ); // 1.3_Q0 = 21299_Q14 + /* Pack two coefficients in one int32 */ + psEncCtrl->LF_shp_Q14[ 0 ] = SKP_LSHIFT( SILK_FIX_CONST( 1.0, 14 ) - b_Q14 - + SKP_SMULWB( strength_Q16, SKP_SMULWB( SILK_FIX_CONST( 0.6, 16 ), b_Q14 ) ), 16 ); + psEncCtrl->LF_shp_Q14[ 0 ] |= (opus_uint16)( b_Q14 - SILK_FIX_CONST( 1.0, 14 ) ); + for( k = 1; k < psEnc->sCmn.nb_subfr; k++ ) { + psEncCtrl->LF_shp_Q14[ k ] = psEncCtrl->LF_shp_Q14[ 0 ]; + } + Tilt_Q16 = -SILK_FIX_CONST( HP_NOISE_COEF, 16 ); + } + + /****************************/ + /* HARMONIC SHAPING CONTROL */ + /****************************/ + /* Control boosting of harmonic frequencies */ + HarmBoost_Q16 = SKP_SMULWB( SKP_SMULWB( SILK_FIX_CONST( 1.0, 17 ) - SKP_LSHIFT( psEncCtrl->coding_quality_Q14, 3 ), + psEnc->LTPCorr_Q15 ), SILK_FIX_CONST( LOW_RATE_HARMONIC_BOOST, 16 ) ); + + /* More harmonic boost for noisy input signals */ + HarmBoost_Q16 = SKP_SMLAWB( HarmBoost_Q16, + SILK_FIX_CONST( 1.0, 16 ) - SKP_LSHIFT( psEncCtrl->input_quality_Q14, 2 ), SILK_FIX_CONST( LOW_INPUT_QUALITY_HARMONIC_BOOST, 16 ) ); + + if( USE_HARM_SHAPING && psEnc->sCmn.indices.signalType == TYPE_VOICED ) { + /* More harmonic noise shaping for high bitrates or noisy input */ + HarmShapeGain_Q16 = SKP_SMLAWB( SILK_FIX_CONST( HARMONIC_SHAPING, 16 ), + SILK_FIX_CONST( 1.0, 16 ) - SKP_SMULWB( SILK_FIX_CONST( 1.0, 18 ) - SKP_LSHIFT( psEncCtrl->coding_quality_Q14, 4 ), + psEncCtrl->input_quality_Q14 ), SILK_FIX_CONST( HIGH_RATE_OR_LOW_QUALITY_HARMONIC_SHAPING, 16 ) ); + + /* Less harmonic noise shaping for less periodic signals */ + HarmShapeGain_Q16 = SKP_SMULWB( SKP_LSHIFT( HarmShapeGain_Q16, 1 ), + silk_SQRT_APPROX( SKP_LSHIFT( psEnc->LTPCorr_Q15, 15 ) ) ); + } else { + HarmShapeGain_Q16 = 0; + } + + /*************************/ + /* Smooth over subframes */ + /*************************/ + for( k = 0; k < MAX_NB_SUBFR; k++ ) { + psShapeSt->HarmBoost_smth_Q16 = + SKP_SMLAWB( psShapeSt->HarmBoost_smth_Q16, HarmBoost_Q16 - psShapeSt->HarmBoost_smth_Q16, SILK_FIX_CONST( SUBFR_SMTH_COEF, 16 ) ); + psShapeSt->HarmShapeGain_smth_Q16 = + SKP_SMLAWB( psShapeSt->HarmShapeGain_smth_Q16, HarmShapeGain_Q16 - psShapeSt->HarmShapeGain_smth_Q16, SILK_FIX_CONST( SUBFR_SMTH_COEF, 16 ) ); + psShapeSt->Tilt_smth_Q16 = + SKP_SMLAWB( psShapeSt->Tilt_smth_Q16, Tilt_Q16 - psShapeSt->Tilt_smth_Q16, SILK_FIX_CONST( SUBFR_SMTH_COEF, 16 ) ); + + psEncCtrl->HarmBoost_Q14[ k ] = ( opus_int )SKP_RSHIFT_ROUND( psShapeSt->HarmBoost_smth_Q16, 2 ); + psEncCtrl->HarmShapeGain_Q14[ k ] = ( opus_int )SKP_RSHIFT_ROUND( psShapeSt->HarmShapeGain_smth_Q16, 2 ); + psEncCtrl->Tilt_Q14[ k ] = ( opus_int )SKP_RSHIFT_ROUND( psShapeSt->Tilt_smth_Q16, 2 ); + } +} diff --git a/silk/fixed/silk_prefilter_FIX.c b/silk/fixed/silk_prefilter_FIX.c index 368aeda09..fd4746b8a 100644 --- a/silk/fixed/silk_prefilter_FIX.c +++ b/silk/fixed/silk_prefilter_FIX.c @@ -1,201 +1,201 @@ -/*********************************************************************** -Copyright (c) 2006-2011, Skype Limited. All rights reserved. -Redistribution and use in source and binary forms, with or without -modification, (subject to the limitations in the disclaimer below) -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 Skype Limited, nor the names of specific -contributors, may be used to endorse or promote products derived from -this software without specific prior written permission. -NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED -BY THIS LICENSE. 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. -***********************************************************************/ - -#include "silk_main_FIX.h" -#include "silk_tuning_parameters.h" - -/* silk_prefilter. Prefilter for finding Quantizer input signal */ -SKP_INLINE void silk_prefilt_FIX( - silk_prefilter_state_FIX *P, /* I/O state */ - opus_int32 st_res_Q12[], /* I short term residual signal */ - opus_int16 xw[], /* O prefiltered signal */ - opus_int32 HarmShapeFIRPacked_Q12, /* I Harmonic shaping coeficients */ - opus_int Tilt_Q14, /* I Tilt shaping coeficient */ - opus_int32 LF_shp_Q14, /* I Low-frequancy shaping coeficients*/ - opus_int lag, /* I Lag for harmonic shaping */ - opus_int length /* I Length of signals */ -); - -void silk_warped_LPC_analysis_filter_FIX( - opus_int32 state[], /* I/O State [order + 1] */ - opus_int16 res[], /* O Residual signal [length] */ - const opus_int16 coef_Q13[], /* I Coefficients [order] */ - const opus_int16 input[], /* I Input signal [length] */ - const opus_int16 lambda_Q16, /* I Warping factor */ - const opus_int length, /* I Length of input signal */ - const opus_int order /* I Filter order (even) */ -) -{ - opus_int n, i; - opus_int32 acc_Q11, tmp1, tmp2; - - /* Order must be even */ - SKP_assert( ( order & 1 ) == 0 ); - - for( n = 0; n < length; n++ ) { - /* Output of lowpass section */ - tmp2 = SKP_SMLAWB( state[ 0 ], state[ 1 ], lambda_Q16 ); - state[ 0 ] = SKP_LSHIFT( input[ n ], 14 ); - /* Output of allpass section */ - tmp1 = SKP_SMLAWB( state[ 1 ], state[ 2 ] - tmp2, lambda_Q16 ); - state[ 1 ] = tmp2; - acc_Q11 = SKP_SMULWB( tmp2, coef_Q13[ 0 ] ); - /* Loop over allpass sections */ - for( i = 2; i < order; i += 2 ) { - /* Output of allpass section */ - tmp2 = SKP_SMLAWB( state[ i ], state[ i + 1 ] - tmp1, lambda_Q16 ); - state[ i ] = tmp1; - acc_Q11 = SKP_SMLAWB( acc_Q11, tmp1, coef_Q13[ i - 1 ] ); - /* Output of allpass section */ - tmp1 = SKP_SMLAWB( state[ i + 1 ], state[ i + 2 ] - tmp2, lambda_Q16 ); - state[ i + 1 ] = tmp2; - acc_Q11 = SKP_SMLAWB( acc_Q11, tmp2, coef_Q13[ i ] ); - } - state[ order ] = tmp1; - acc_Q11 = SKP_SMLAWB( acc_Q11, tmp1, coef_Q13[ order - 1 ] ); - res[ n ] = ( opus_int16 )SKP_SAT16( ( opus_int32 )input[ n ] - SKP_RSHIFT_ROUND( acc_Q11, 11 ) ); - } -} - -void silk_prefilter_FIX( - silk_encoder_state_FIX *psEnc, /* I/O Encoder state FIX */ - const silk_encoder_control_FIX *psEncCtrl, /* I Encoder control FIX */ - opus_int16 xw[], /* O Weighted signal */ - const opus_int16 x[] /* I Speech signal */ -) -{ - silk_prefilter_state_FIX *P = &psEnc->sPrefilt; - opus_int j, k, lag; - opus_int32 tmp_32; - const opus_int16 *AR1_shp_Q13; - const opus_int16 *px; - opus_int16 *pxw; - opus_int HarmShapeGain_Q12, Tilt_Q14; - opus_int32 HarmShapeFIRPacked_Q12, LF_shp_Q14; - opus_int32 x_filt_Q12[ MAX_FRAME_LENGTH / MAX_NB_SUBFR ]; - opus_int16 st_res[ ( MAX_FRAME_LENGTH / MAX_NB_SUBFR ) + MAX_LPC_ORDER ]; - opus_int16 B_Q12[ 2 ]; - - /* Setup pointers */ - px = x; - pxw = xw; - lag = P->lagPrev; - for( k = 0; k < psEnc->sCmn.nb_subfr; k++ ) { - /* Update Variables that change per sub frame */ - if( psEnc->sCmn.indices.signalType == TYPE_VOICED ) { - lag = psEncCtrl->pitchL[ k ]; - } - - /* Noise shape parameters */ - HarmShapeGain_Q12 = SKP_SMULWB( psEncCtrl->HarmShapeGain_Q14[ k ], 16384 - psEncCtrl->HarmBoost_Q14[ k ] ); - SKP_assert( HarmShapeGain_Q12 >= 0 ); - HarmShapeFIRPacked_Q12 = SKP_RSHIFT( HarmShapeGain_Q12, 2 ); - HarmShapeFIRPacked_Q12 |= SKP_LSHIFT( ( opus_int32 )SKP_RSHIFT( HarmShapeGain_Q12, 1 ), 16 ); - Tilt_Q14 = psEncCtrl->Tilt_Q14[ k ]; - LF_shp_Q14 = psEncCtrl->LF_shp_Q14[ k ]; - AR1_shp_Q13 = &psEncCtrl->AR1_Q13[ k * MAX_SHAPE_LPC_ORDER ]; - - /* Short term FIR filtering*/ - silk_warped_LPC_analysis_filter_FIX( P->sAR_shp, st_res, AR1_shp_Q13, px, - psEnc->sCmn.warping_Q16, psEnc->sCmn.subfr_length, psEnc->sCmn.shapingLPCOrder ); - - /* reduce (mainly) low frequencies during harmonic emphasis */ - B_Q12[ 0 ] = SKP_RSHIFT_ROUND( psEncCtrl->GainsPre_Q14[ k ], 2 ); - tmp_32 = SKP_SMLABB( SILK_FIX_CONST( INPUT_TILT, 26 ), psEncCtrl->HarmBoost_Q14[ k ], HarmShapeGain_Q12 ); /* Q26 */ - tmp_32 = SKP_SMLABB( tmp_32, psEncCtrl->coding_quality_Q14, SILK_FIX_CONST( HIGH_RATE_INPUT_TILT, 12 ) ); /* Q26 */ - tmp_32 = SKP_SMULWB( tmp_32, -psEncCtrl->GainsPre_Q14[ k ] ); /* Q24 */ - tmp_32 = SKP_RSHIFT_ROUND( tmp_32, 12 ); /* Q12 */ - B_Q12[ 1 ]= SKP_SAT16( tmp_32 ); - - x_filt_Q12[ 0 ] = SKP_SMLABB( SKP_SMULBB( st_res[ 0 ], B_Q12[ 0 ] ), P->sHarmHP, B_Q12[ 1 ] ); - for( j = 1; j < psEnc->sCmn.subfr_length; j++ ) { - x_filt_Q12[ j ] = SKP_SMLABB( SKP_SMULBB( st_res[ j ], B_Q12[ 0 ] ), st_res[ j - 1 ], B_Q12[ 1 ] ); - } - P->sHarmHP = st_res[ psEnc->sCmn.subfr_length - 1 ]; - - silk_prefilt_FIX( P, x_filt_Q12, pxw, HarmShapeFIRPacked_Q12, Tilt_Q14, - LF_shp_Q14, lag, psEnc->sCmn.subfr_length ); - - px += psEnc->sCmn.subfr_length; - pxw += psEnc->sCmn.subfr_length; - } - - P->lagPrev = psEncCtrl->pitchL[ MAX_NB_SUBFR - 1 ]; -} - -/* silk_prefilter. Prefilter for finding Quantizer input signal */ -SKP_INLINE void silk_prefilt_FIX( - silk_prefilter_state_FIX *P, /* I/O state */ - opus_int32 st_res_Q12[], /* I short term residual signal */ - opus_int16 xw[], /* O prefiltered signal */ - opus_int32 HarmShapeFIRPacked_Q12, /* I Harmonic shaping coeficients */ - opus_int Tilt_Q14, /* I Tilt shaping coeficient */ - opus_int32 LF_shp_Q14, /* I Low-frequancy shaping coeficients*/ - opus_int lag, /* I Lag for harmonic shaping */ - opus_int length /* I Length of signals */ -) -{ - opus_int i, idx, LTP_shp_buf_idx; - opus_int32 n_LTP_Q12, n_Tilt_Q10, n_LF_Q10; - opus_int32 sLF_MA_shp_Q12, sLF_AR_shp_Q12; - opus_int16 *LTP_shp_buf; - - /* To speed up use temp variables instead of using the struct */ - LTP_shp_buf = P->sLTP_shp; - LTP_shp_buf_idx = P->sLTP_shp_buf_idx; - sLF_AR_shp_Q12 = P->sLF_AR_shp_Q12; - sLF_MA_shp_Q12 = P->sLF_MA_shp_Q12; - - for( i = 0; i < length; i++ ) { - if( lag > 0 ) { - /* unrolled loop */ - SKP_assert( HARM_SHAPE_FIR_TAPS == 3 ); - idx = lag + LTP_shp_buf_idx; - n_LTP_Q12 = SKP_SMULBB( LTP_shp_buf[ ( idx - HARM_SHAPE_FIR_TAPS / 2 - 1) & LTP_MASK ], HarmShapeFIRPacked_Q12 ); - n_LTP_Q12 = SKP_SMLABT( n_LTP_Q12, LTP_shp_buf[ ( idx - HARM_SHAPE_FIR_TAPS / 2 ) & LTP_MASK ], HarmShapeFIRPacked_Q12 ); - n_LTP_Q12 = SKP_SMLABB( n_LTP_Q12, LTP_shp_buf[ ( idx - HARM_SHAPE_FIR_TAPS / 2 + 1) & LTP_MASK ], HarmShapeFIRPacked_Q12 ); - } else { - n_LTP_Q12 = 0; - } - - n_Tilt_Q10 = SKP_SMULWB( sLF_AR_shp_Q12, Tilt_Q14 ); - n_LF_Q10 = SKP_SMLAWB( SKP_SMULWT( sLF_AR_shp_Q12, LF_shp_Q14 ), sLF_MA_shp_Q12, LF_shp_Q14 ); - - sLF_AR_shp_Q12 = SKP_SUB32( st_res_Q12[ i ], SKP_LSHIFT( n_Tilt_Q10, 2 ) ); - sLF_MA_shp_Q12 = SKP_SUB32( sLF_AR_shp_Q12, SKP_LSHIFT( n_LF_Q10, 2 ) ); - - LTP_shp_buf_idx = ( LTP_shp_buf_idx - 1 ) & LTP_MASK; - LTP_shp_buf[ LTP_shp_buf_idx ] = ( opus_int16 )SKP_SAT16( SKP_RSHIFT_ROUND( sLF_MA_shp_Q12, 12 ) ); - - xw[i] = ( opus_int16 )SKP_SAT16( SKP_RSHIFT_ROUND( SKP_SUB32( sLF_MA_shp_Q12, n_LTP_Q12 ), 12 ) ); - } - - /* Copy temp variable back to state */ - P->sLF_AR_shp_Q12 = sLF_AR_shp_Q12; - P->sLF_MA_shp_Q12 = sLF_MA_shp_Q12; - P->sLTP_shp_buf_idx = LTP_shp_buf_idx; -} +/*********************************************************************** +Copyright (c) 2006-2011, Skype Limited. All rights reserved. +Redistribution and use in source and binary forms, with or without +modification, (subject to the limitations in the disclaimer below) +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 Skype Limited, nor the names of specific +contributors, may be used to endorse or promote products derived from +this software without specific prior written permission. +NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED +BY THIS LICENSE. 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. +***********************************************************************/ + +#include "silk_main_FIX.h" +#include "silk_tuning_parameters.h" + +/* silk_prefilter. Prefilter for finding Quantizer input signal */ +SKP_INLINE void silk_prefilt_FIX( + silk_prefilter_state_FIX *P, /* I/O state */ + opus_int32 st_res_Q12[], /* I short term residual signal */ + opus_int16 xw[], /* O prefiltered signal */ + opus_int32 HarmShapeFIRPacked_Q12, /* I Harmonic shaping coeficients */ + opus_int Tilt_Q14, /* I Tilt shaping coeficient */ + opus_int32 LF_shp_Q14, /* I Low-frequancy shaping coeficients*/ + opus_int lag, /* I Lag for harmonic shaping */ + opus_int length /* I Length of signals */ +); + +void silk_warped_LPC_analysis_filter_FIX( + opus_int32 state[], /* I/O State [order + 1] */ + opus_int16 res[], /* O Residual signal [length] */ + const opus_int16 coef_Q13[], /* I Coefficients [order] */ + const opus_int16 input[], /* I Input signal [length] */ + const opus_int16 lambda_Q16, /* I Warping factor */ + const opus_int length, /* I Length of input signal */ + const opus_int order /* I Filter order (even) */ +) +{ + opus_int n, i; + opus_int32 acc_Q11, tmp1, tmp2; + + /* Order must be even */ + SKP_assert( ( order & 1 ) == 0 ); + + for( n = 0; n < length; n++ ) { + /* Output of lowpass section */ + tmp2 = SKP_SMLAWB( state[ 0 ], state[ 1 ], lambda_Q16 ); + state[ 0 ] = SKP_LSHIFT( input[ n ], 14 ); + /* Output of allpass section */ + tmp1 = SKP_SMLAWB( state[ 1 ], state[ 2 ] - tmp2, lambda_Q16 ); + state[ 1 ] = tmp2; + acc_Q11 = SKP_SMULWB( tmp2, coef_Q13[ 0 ] ); + /* Loop over allpass sections */ + for( i = 2; i < order; i += 2 ) { + /* Output of allpass section */ + tmp2 = SKP_SMLAWB( state[ i ], state[ i + 1 ] - tmp1, lambda_Q16 ); + state[ i ] = tmp1; + acc_Q11 = SKP_SMLAWB( acc_Q11, tmp1, coef_Q13[ i - 1 ] ); + /* Output of allpass section */ + tmp1 = SKP_SMLAWB( state[ i + 1 ], state[ i + 2 ] - tmp2, lambda_Q16 ); + state[ i + 1 ] = tmp2; + acc_Q11 = SKP_SMLAWB( acc_Q11, tmp2, coef_Q13[ i ] ); + } + state[ order ] = tmp1; + acc_Q11 = SKP_SMLAWB( acc_Q11, tmp1, coef_Q13[ order - 1 ] ); + res[ n ] = ( opus_int16 )SKP_SAT16( ( opus_int32 )input[ n ] - SKP_RSHIFT_ROUND( acc_Q11, 11 ) ); + } +} + +void silk_prefilter_FIX( + silk_encoder_state_FIX *psEnc, /* I/O Encoder state FIX */ + const silk_encoder_control_FIX *psEncCtrl, /* I Encoder control FIX */ + opus_int16 xw[], /* O Weighted signal */ + const opus_int16 x[] /* I Speech signal */ +) +{ + silk_prefilter_state_FIX *P = &psEnc->sPrefilt; + opus_int j, k, lag; + opus_int32 tmp_32; + const opus_int16 *AR1_shp_Q13; + const opus_int16 *px; + opus_int16 *pxw; + opus_int HarmShapeGain_Q12, Tilt_Q14; + opus_int32 HarmShapeFIRPacked_Q12, LF_shp_Q14; + opus_int32 x_filt_Q12[ MAX_FRAME_LENGTH / MAX_NB_SUBFR ]; + opus_int16 st_res[ ( MAX_FRAME_LENGTH / MAX_NB_SUBFR ) + MAX_LPC_ORDER ]; + opus_int16 B_Q12[ 2 ]; + + /* Setup pointers */ + px = x; + pxw = xw; + lag = P->lagPrev; + for( k = 0; k < psEnc->sCmn.nb_subfr; k++ ) { + /* Update Variables that change per sub frame */ + if( psEnc->sCmn.indices.signalType == TYPE_VOICED ) { + lag = psEncCtrl->pitchL[ k ]; + } + + /* Noise shape parameters */ + HarmShapeGain_Q12 = SKP_SMULWB( psEncCtrl->HarmShapeGain_Q14[ k ], 16384 - psEncCtrl->HarmBoost_Q14[ k ] ); + SKP_assert( HarmShapeGain_Q12 >= 0 ); + HarmShapeFIRPacked_Q12 = SKP_RSHIFT( HarmShapeGain_Q12, 2 ); + HarmShapeFIRPacked_Q12 |= SKP_LSHIFT( ( opus_int32 )SKP_RSHIFT( HarmShapeGain_Q12, 1 ), 16 ); + Tilt_Q14 = psEncCtrl->Tilt_Q14[ k ]; + LF_shp_Q14 = psEncCtrl->LF_shp_Q14[ k ]; + AR1_shp_Q13 = &psEncCtrl->AR1_Q13[ k * MAX_SHAPE_LPC_ORDER ]; + + /* Short term FIR filtering*/ + silk_warped_LPC_analysis_filter_FIX( P->sAR_shp, st_res, AR1_shp_Q13, px, + psEnc->sCmn.warping_Q16, psEnc->sCmn.subfr_length, psEnc->sCmn.shapingLPCOrder ); + + /* reduce (mainly) low frequencies during harmonic emphasis */ + B_Q12[ 0 ] = SKP_RSHIFT_ROUND( psEncCtrl->GainsPre_Q14[ k ], 2 ); + tmp_32 = SKP_SMLABB( SILK_FIX_CONST( INPUT_TILT, 26 ), psEncCtrl->HarmBoost_Q14[ k ], HarmShapeGain_Q12 ); /* Q26 */ + tmp_32 = SKP_SMLABB( tmp_32, psEncCtrl->coding_quality_Q14, SILK_FIX_CONST( HIGH_RATE_INPUT_TILT, 12 ) ); /* Q26 */ + tmp_32 = SKP_SMULWB( tmp_32, -psEncCtrl->GainsPre_Q14[ k ] ); /* Q24 */ + tmp_32 = SKP_RSHIFT_ROUND( tmp_32, 12 ); /* Q12 */ + B_Q12[ 1 ]= SKP_SAT16( tmp_32 ); + + x_filt_Q12[ 0 ] = SKP_SMLABB( SKP_SMULBB( st_res[ 0 ], B_Q12[ 0 ] ), P->sHarmHP, B_Q12[ 1 ] ); + for( j = 1; j < psEnc->sCmn.subfr_length; j++ ) { + x_filt_Q12[ j ] = SKP_SMLABB( SKP_SMULBB( st_res[ j ], B_Q12[ 0 ] ), st_res[ j - 1 ], B_Q12[ 1 ] ); + } + P->sHarmHP = st_res[ psEnc->sCmn.subfr_length - 1 ]; + + silk_prefilt_FIX( P, x_filt_Q12, pxw, HarmShapeFIRPacked_Q12, Tilt_Q14, + LF_shp_Q14, lag, psEnc->sCmn.subfr_length ); + + px += psEnc->sCmn.subfr_length; + pxw += psEnc->sCmn.subfr_length; + } + + P->lagPrev = psEncCtrl->pitchL[ MAX_NB_SUBFR - 1 ]; +} + +/* silk_prefilter. Prefilter for finding Quantizer input signal */ +SKP_INLINE void silk_prefilt_FIX( + silk_prefilter_state_FIX *P, /* I/O state */ + opus_int32 st_res_Q12[], /* I short term residual signal */ + opus_int16 xw[], /* O prefiltered signal */ + opus_int32 HarmShapeFIRPacked_Q12, /* I Harmonic shaping coeficients */ + opus_int Tilt_Q14, /* I Tilt shaping coeficient */ + opus_int32 LF_shp_Q14, /* I Low-frequancy shaping coeficients*/ + opus_int lag, /* I Lag for harmonic shaping */ + opus_int length /* I Length of signals */ +) +{ + opus_int i, idx, LTP_shp_buf_idx; + opus_int32 n_LTP_Q12, n_Tilt_Q10, n_LF_Q10; + opus_int32 sLF_MA_shp_Q12, sLF_AR_shp_Q12; + opus_int16 *LTP_shp_buf; + + /* To speed up use temp variables instead of using the struct */ + LTP_shp_buf = P->sLTP_shp; + LTP_shp_buf_idx = P->sLTP_shp_buf_idx; + sLF_AR_shp_Q12 = P->sLF_AR_shp_Q12; + sLF_MA_shp_Q12 = P->sLF_MA_shp_Q12; + + for( i = 0; i < length; i++ ) { + if( lag > 0 ) { + /* unrolled loop */ + SKP_assert( HARM_SHAPE_FIR_TAPS == 3 ); + idx = lag + LTP_shp_buf_idx; + n_LTP_Q12 = SKP_SMULBB( LTP_shp_buf[ ( idx - HARM_SHAPE_FIR_TAPS / 2 - 1) & LTP_MASK ], HarmShapeFIRPacked_Q12 ); + n_LTP_Q12 = SKP_SMLABT( n_LTP_Q12, LTP_shp_buf[ ( idx - HARM_SHAPE_FIR_TAPS / 2 ) & LTP_MASK ], HarmShapeFIRPacked_Q12 ); + n_LTP_Q12 = SKP_SMLABB( n_LTP_Q12, LTP_shp_buf[ ( idx - HARM_SHAPE_FIR_TAPS / 2 + 1) & LTP_MASK ], HarmShapeFIRPacked_Q12 ); + } else { + n_LTP_Q12 = 0; + } + + n_Tilt_Q10 = SKP_SMULWB( sLF_AR_shp_Q12, Tilt_Q14 ); + n_LF_Q10 = SKP_SMLAWB( SKP_SMULWT( sLF_AR_shp_Q12, LF_shp_Q14 ), sLF_MA_shp_Q12, LF_shp_Q14 ); + + sLF_AR_shp_Q12 = SKP_SUB32( st_res_Q12[ i ], SKP_LSHIFT( n_Tilt_Q10, 2 ) ); + sLF_MA_shp_Q12 = SKP_SUB32( sLF_AR_shp_Q12, SKP_LSHIFT( n_LF_Q10, 2 ) ); + + LTP_shp_buf_idx = ( LTP_shp_buf_idx - 1 ) & LTP_MASK; + LTP_shp_buf[ LTP_shp_buf_idx ] = ( opus_int16 )SKP_SAT16( SKP_RSHIFT_ROUND( sLF_MA_shp_Q12, 12 ) ); + + xw[i] = ( opus_int16 )SKP_SAT16( SKP_RSHIFT_ROUND( SKP_SUB32( sLF_MA_shp_Q12, n_LTP_Q12 ), 12 ) ); + } + + /* Copy temp variable back to state */ + P->sLF_AR_shp_Q12 = sLF_AR_shp_Q12; + P->sLF_MA_shp_Q12 = sLF_MA_shp_Q12; + P->sLTP_shp_buf_idx = LTP_shp_buf_idx; +} diff --git a/silk/fixed/silk_process_gains_FIX.c b/silk/fixed/silk_process_gains_FIX.c index 4341ac017..771bff358 100644 --- a/silk/fixed/silk_process_gains_FIX.c +++ b/silk/fixed/silk_process_gains_FIX.c @@ -1,108 +1,108 @@ -/*********************************************************************** -Copyright (c) 2006-2011, Skype Limited. All rights reserved. -Redistribution and use in source and binary forms, with or without -modification, (subject to the limitations in the disclaimer below) -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 Skype Limited, nor the names of specific -contributors, may be used to endorse or promote products derived from -this software without specific prior written permission. -NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED -BY THIS LICENSE. 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. -***********************************************************************/ - -#include "silk_main_FIX.h" -#include "silk_tuning_parameters.h" - -/* Processing of gains */ -void silk_process_gains_FIX( - silk_encoder_state_FIX *psEnc, /* I/O Encoder state_FIX */ - silk_encoder_control_FIX *psEncCtrl /* I/O Encoder control_FIX */ -) -{ - silk_shape_state_FIX *psShapeSt = &psEnc->sShape; - opus_int k; - opus_int32 s_Q16, InvMaxSqrVal_Q16, gain, gain_squared, ResNrg, ResNrgPart, quant_offset_Q10; - - /* Gain reduction when LTP coding gain is high */ - if( psEnc->sCmn.indices.signalType == TYPE_VOICED ) { - /*s = -0.5f * SKP_sigmoid( 0.25f * ( psEncCtrl->LTPredCodGain - 12.0f ) ); */ - s_Q16 = -silk_sigm_Q15( SKP_RSHIFT_ROUND( psEncCtrl->LTPredCodGain_Q7 - SILK_FIX_CONST( 12.0, 7 ), 4 ) ); - for( k = 0; k < psEnc->sCmn.nb_subfr; k++ ) { - psEncCtrl->Gains_Q16[ k ] = SKP_SMLAWB( psEncCtrl->Gains_Q16[ k ], psEncCtrl->Gains_Q16[ k ], s_Q16 ); - } - } - - /* Limit the quantized signal */ - /* InvMaxSqrVal = pow( 2.0f, 0.33f * ( 21.0f - SNR_dB ) ) / subfr_length; */ - InvMaxSqrVal_Q16 = SKP_DIV32_16( silk_log2lin( - SKP_SMULWB( SILK_FIX_CONST( 21 + 16 / 0.33, 7 ) - psEnc->sCmn.SNR_dB_Q7, SILK_FIX_CONST( 0.33, 16 ) ) ), psEnc->sCmn.subfr_length ); - - for( k = 0; k < psEnc->sCmn.nb_subfr; k++ ) { - /* Soft limit on ratio residual energy and squared gains */ - ResNrg = psEncCtrl->ResNrg[ k ]; - ResNrgPart = SKP_SMULWW( ResNrg, InvMaxSqrVal_Q16 ); - if( psEncCtrl->ResNrgQ[ k ] > 0 ) { - ResNrgPart = SKP_RSHIFT_ROUND( ResNrgPart, psEncCtrl->ResNrgQ[ k ] ); - } else { - if( ResNrgPart >= SKP_RSHIFT( SKP_int32_MAX, -psEncCtrl->ResNrgQ[ k ] ) ) { - ResNrgPart = SKP_int32_MAX; - } else { - ResNrgPart = SKP_LSHIFT( ResNrgPart, -psEncCtrl->ResNrgQ[ k ] ); - } - } - gain = psEncCtrl->Gains_Q16[ k ]; - gain_squared = SKP_ADD_SAT32( ResNrgPart, SKP_SMMUL( gain, gain ) ); - if( gain_squared < SKP_int16_MAX ) { - /* recalculate with higher precision */ - gain_squared = SKP_SMLAWW( SKP_LSHIFT( ResNrgPart, 16 ), gain, gain ); - SKP_assert( gain_squared > 0 ); - gain = silk_SQRT_APPROX( gain_squared ); /* Q8 */ - gain = SKP_min( gain, SKP_int32_MAX >> 8 ); - psEncCtrl->Gains_Q16[ k ] = SKP_LSHIFT_SAT32( gain, 8 ); /* Q16 */ - } else { - gain = silk_SQRT_APPROX( gain_squared ); /* Q0 */ - gain = SKP_min( gain, SKP_int32_MAX >> 16 ); - psEncCtrl->Gains_Q16[ k ] = SKP_LSHIFT_SAT32( gain, 16 ); /* Q16 */ - } - } - - /* Noise shaping quantization */ - silk_gains_quant( psEnc->sCmn.indices.GainsIndices, psEncCtrl->Gains_Q16, - &psShapeSt->LastGainIndex, psEnc->sCmn.nFramesEncoded, psEnc->sCmn.nb_subfr ); - - /* Set quantizer offset for voiced signals. Larger offset when LTP coding gain is low or tilt is high (ie low-pass) */ - if( psEnc->sCmn.indices.signalType == TYPE_VOICED ) { - if( psEncCtrl->LTPredCodGain_Q7 + SKP_RSHIFT( psEnc->sCmn.input_tilt_Q15, 8 ) > SILK_FIX_CONST( 1.0, 7 ) ) { - psEnc->sCmn.indices.quantOffsetType = 0; - } else { - psEnc->sCmn.indices.quantOffsetType = 1; - } - } - - /* Quantizer boundary adjustment */ - quant_offset_Q10 = silk_Quantization_Offsets_Q10[ psEnc->sCmn.indices.signalType >> 1 ][ psEnc->sCmn.indices.quantOffsetType ]; - psEncCtrl->Lambda_Q10 = SILK_FIX_CONST( LAMBDA_OFFSET, 10 ) - + SKP_SMULBB( SILK_FIX_CONST( LAMBDA_DELAYED_DECISIONS, 10 ), psEnc->sCmn.nStatesDelayedDecision ) - + SKP_SMULWB( SILK_FIX_CONST( LAMBDA_SPEECH_ACT, 18 ), psEnc->sCmn.speech_activity_Q8 ) - + SKP_SMULWB( SILK_FIX_CONST( LAMBDA_INPUT_QUALITY, 12 ), psEncCtrl->input_quality_Q14 ) - + SKP_SMULWB( SILK_FIX_CONST( LAMBDA_CODING_QUALITY, 12 ), psEncCtrl->coding_quality_Q14 ) - + SKP_SMULWB( SILK_FIX_CONST( LAMBDA_QUANT_OFFSET, 16 ), quant_offset_Q10 ); - - SKP_assert( psEncCtrl->Lambda_Q10 > 0 ); - SKP_assert( psEncCtrl->Lambda_Q10 < SILK_FIX_CONST( 2, 10 ) ); -} +/*********************************************************************** +Copyright (c) 2006-2011, Skype Limited. All rights reserved. +Redistribution and use in source and binary forms, with or without +modification, (subject to the limitations in the disclaimer below) +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 Skype Limited, nor the names of specific +contributors, may be used to endorse or promote products derived from +this software without specific prior written permission. +NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED +BY THIS LICENSE. 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. +***********************************************************************/ + +#include "silk_main_FIX.h" +#include "silk_tuning_parameters.h" + +/* Processing of gains */ +void silk_process_gains_FIX( + silk_encoder_state_FIX *psEnc, /* I/O Encoder state_FIX */ + silk_encoder_control_FIX *psEncCtrl /* I/O Encoder control_FIX */ +) +{ + silk_shape_state_FIX *psShapeSt = &psEnc->sShape; + opus_int k; + opus_int32 s_Q16, InvMaxSqrVal_Q16, gain, gain_squared, ResNrg, ResNrgPart, quant_offset_Q10; + + /* Gain reduction when LTP coding gain is high */ + if( psEnc->sCmn.indices.signalType == TYPE_VOICED ) { + /*s = -0.5f * SKP_sigmoid( 0.25f * ( psEncCtrl->LTPredCodGain - 12.0f ) ); */ + s_Q16 = -silk_sigm_Q15( SKP_RSHIFT_ROUND( psEncCtrl->LTPredCodGain_Q7 - SILK_FIX_CONST( 12.0, 7 ), 4 ) ); + for( k = 0; k < psEnc->sCmn.nb_subfr; k++ ) { + psEncCtrl->Gains_Q16[ k ] = SKP_SMLAWB( psEncCtrl->Gains_Q16[ k ], psEncCtrl->Gains_Q16[ k ], s_Q16 ); + } + } + + /* Limit the quantized signal */ + /* InvMaxSqrVal = pow( 2.0f, 0.33f * ( 21.0f - SNR_dB ) ) / subfr_length; */ + InvMaxSqrVal_Q16 = SKP_DIV32_16( silk_log2lin( + SKP_SMULWB( SILK_FIX_CONST( 21 + 16 / 0.33, 7 ) - psEnc->sCmn.SNR_dB_Q7, SILK_FIX_CONST( 0.33, 16 ) ) ), psEnc->sCmn.subfr_length ); + + for( k = 0; k < psEnc->sCmn.nb_subfr; k++ ) { + /* Soft limit on ratio residual energy and squared gains */ + ResNrg = psEncCtrl->ResNrg[ k ]; + ResNrgPart = SKP_SMULWW( ResNrg, InvMaxSqrVal_Q16 ); + if( psEncCtrl->ResNrgQ[ k ] > 0 ) { + ResNrgPart = SKP_RSHIFT_ROUND( ResNrgPart, psEncCtrl->ResNrgQ[ k ] ); + } else { + if( ResNrgPart >= SKP_RSHIFT( SKP_int32_MAX, -psEncCtrl->ResNrgQ[ k ] ) ) { + ResNrgPart = SKP_int32_MAX; + } else { + ResNrgPart = SKP_LSHIFT( ResNrgPart, -psEncCtrl->ResNrgQ[ k ] ); + } + } + gain = psEncCtrl->Gains_Q16[ k ]; + gain_squared = SKP_ADD_SAT32( ResNrgPart, SKP_SMMUL( gain, gain ) ); + if( gain_squared < SKP_int16_MAX ) { + /* recalculate with higher precision */ + gain_squared = SKP_SMLAWW( SKP_LSHIFT( ResNrgPart, 16 ), gain, gain ); + SKP_assert( gain_squared > 0 ); + gain = silk_SQRT_APPROX( gain_squared ); /* Q8 */ + gain = SKP_min( gain, SKP_int32_MAX >> 8 ); + psEncCtrl->Gains_Q16[ k ] = SKP_LSHIFT_SAT32( gain, 8 ); /* Q16 */ + } else { + gain = silk_SQRT_APPROX( gain_squared ); /* Q0 */ + gain = SKP_min( gain, SKP_int32_MAX >> 16 ); + psEncCtrl->Gains_Q16[ k ] = SKP_LSHIFT_SAT32( gain, 16 ); /* Q16 */ + } + } + + /* Noise shaping quantization */ + silk_gains_quant( psEnc->sCmn.indices.GainsIndices, psEncCtrl->Gains_Q16, + &psShapeSt->LastGainIndex, psEnc->sCmn.nFramesEncoded, psEnc->sCmn.nb_subfr ); + + /* Set quantizer offset for voiced signals. Larger offset when LTP coding gain is low or tilt is high (ie low-pass) */ + if( psEnc->sCmn.indices.signalType == TYPE_VOICED ) { + if( psEncCtrl->LTPredCodGain_Q7 + SKP_RSHIFT( psEnc->sCmn.input_tilt_Q15, 8 ) > SILK_FIX_CONST( 1.0, 7 ) ) { + psEnc->sCmn.indices.quantOffsetType = 0; + } else { + psEnc->sCmn.indices.quantOffsetType = 1; + } + } + + /* Quantizer boundary adjustment */ + quant_offset_Q10 = silk_Quantization_Offsets_Q10[ psEnc->sCmn.indices.signalType >> 1 ][ psEnc->sCmn.indices.quantOffsetType ]; + psEncCtrl->Lambda_Q10 = SILK_FIX_CONST( LAMBDA_OFFSET, 10 ) + + SKP_SMULBB( SILK_FIX_CONST( LAMBDA_DELAYED_DECISIONS, 10 ), psEnc->sCmn.nStatesDelayedDecision ) + + SKP_SMULWB( SILK_FIX_CONST( LAMBDA_SPEECH_ACT, 18 ), psEnc->sCmn.speech_activity_Q8 ) + + SKP_SMULWB( SILK_FIX_CONST( LAMBDA_INPUT_QUALITY, 12 ), psEncCtrl->input_quality_Q14 ) + + SKP_SMULWB( SILK_FIX_CONST( LAMBDA_CODING_QUALITY, 12 ), psEncCtrl->coding_quality_Q14 ) + + SKP_SMULWB( SILK_FIX_CONST( LAMBDA_QUANT_OFFSET, 16 ), quant_offset_Q10 ); + + SKP_assert( psEncCtrl->Lambda_Q10 > 0 ); + SKP_assert( psEncCtrl->Lambda_Q10 < SILK_FIX_CONST( 2, 10 ) ); +} diff --git a/silk/fixed/silk_regularize_correlations_FIX.c b/silk/fixed/silk_regularize_correlations_FIX.c index 8cca332ba..1fd899ee3 100644 --- a/silk/fixed/silk_regularize_correlations_FIX.c +++ b/silk/fixed/silk_regularize_correlations_FIX.c @@ -1,43 +1,43 @@ -/*********************************************************************** -Copyright (c) 2006-2011, Skype Limited. All rights reserved. -Redistribution and use in source and binary forms, with or without -modification, (subject to the limitations in the disclaimer below) -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 Skype Limited, nor the names of specific -contributors, may be used to endorse or promote products derived from -this software without specific prior written permission. -NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED -BY THIS LICENSE. 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. -***********************************************************************/ - -#include "silk_main_FIX.h" - -/* Add noise to matrix diagonal */ -void silk_regularize_correlations_FIX( - opus_int32 *XX, /* I/O Correlation matrices */ - opus_int32 *xx, /* I/O Correlation values */ - opus_int32 noise, /* I Noise to add */ - opus_int D /* I Dimension of XX */ -) -{ - opus_int i; - for( i = 0; i < D; i++ ) { - matrix_ptr( &XX[ 0 ], i, i, D ) = SKP_ADD32( matrix_ptr( &XX[ 0 ], i, i, D ), noise ); - } - xx[ 0 ] += noise; -} +/*********************************************************************** +Copyright (c) 2006-2011, Skype Limited. All rights reserved. +Redistribution and use in source and binary forms, with or without +modification, (subject to the limitations in the disclaimer below) +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 Skype Limited, nor the names of specific +contributors, may be used to endorse or promote products derived from +this software without specific prior written permission. +NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED +BY THIS LICENSE. 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. +***********************************************************************/ + +#include "silk_main_FIX.h" + +/* Add noise to matrix diagonal */ +void silk_regularize_correlations_FIX( + opus_int32 *XX, /* I/O Correlation matrices */ + opus_int32 *xx, /* I/O Correlation values */ + opus_int32 noise, /* I Noise to add */ + opus_int D /* I Dimension of XX */ +) +{ + opus_int i; + for( i = 0; i < D; i++ ) { + matrix_ptr( &XX[ 0 ], i, i, D ) = SKP_ADD32( matrix_ptr( &XX[ 0 ], i, i, D ), noise ); + } + xx[ 0 ] += noise; +} diff --git a/silk/fixed/silk_residual_energy16_FIX.c b/silk/fixed/silk_residual_energy16_FIX.c index c3b571c8b..c364ffbdb 100644 --- a/silk/fixed/silk_residual_energy16_FIX.c +++ b/silk/fixed/silk_residual_energy16_FIX.c @@ -1,99 +1,99 @@ -/*********************************************************************** -Copyright (c) 2006-2011, Skype Limited. All rights reserved. -Redistribution and use in source and binary forms, with or without -modification, (subject to the limitations in the disclaimer below) -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 Skype Limited, nor the names of specific -contributors, may be used to endorse or promote products derived from -this software without specific prior written permission. -NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED -BY THIS LICENSE. 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. -***********************************************************************/ - -#include "silk_main_FIX.h" - -/* Residual energy: nrg = wxx - 2 * wXx * c + c' * wXX * c */ -opus_int32 silk_residual_energy16_covar_FIX( - const opus_int16 *c, /* I Prediction vector */ - const opus_int32 *wXX, /* I Correlation matrix */ - const opus_int32 *wXx, /* I Correlation vector */ - opus_int32 wxx, /* I Signal energy */ - opus_int D, /* I Dimension */ - opus_int cQ /* I Q value for c vector 0 - 15 */ -) -{ - opus_int i, j, lshifts, Qxtra; - opus_int32 c_max, w_max, tmp, tmp2, nrg; - opus_int cn[ MAX_MATRIX_SIZE ]; - const opus_int32 *pRow; - - /* Safety checks */ - SKP_assert( D >= 0 ); - SKP_assert( D <= 16 ); - SKP_assert( cQ > 0 ); - SKP_assert( cQ < 16 ); - - lshifts = 16 - cQ; - Qxtra = lshifts; - - c_max = 0; - for( i = 0; i < D; i++ ) { - c_max = SKP_max_32( c_max, SKP_abs( ( opus_int32 )c[ i ] ) ); - } - Qxtra = SKP_min_int( Qxtra, silk_CLZ32( c_max ) - 17 ); - - w_max = SKP_max_32( wXX[ 0 ], wXX[ D * D - 1 ] ); - Qxtra = SKP_min_int( Qxtra, silk_CLZ32( SKP_MUL( D, SKP_RSHIFT( SKP_SMULWB( w_max, c_max ), 4 ) ) ) - 5 ); - Qxtra = SKP_max_int( Qxtra, 0 ); - for( i = 0; i < D; i++ ) { - cn[ i ] = SKP_LSHIFT( ( opus_int )c[ i ], Qxtra ); - SKP_assert( SKP_abs(cn[i]) <= ( SKP_int16_MAX + 1 ) ); /* Check that SKP_SMLAWB can be used */ - } - lshifts -= Qxtra; - - /* Compute wxx - 2 * wXx * c */ - tmp = 0; - for( i = 0; i < D; i++ ) { - tmp = SKP_SMLAWB( tmp, wXx[ i ], cn[ i ] ); - } - nrg = SKP_RSHIFT( wxx, 1 + lshifts ) - tmp; /* Q: -lshifts - 1 */ - - /* Add c' * wXX * c, assuming wXX is symmetric */ - tmp2 = 0; - for( i = 0; i < D; i++ ) { - tmp = 0; - pRow = &wXX[ i * D ]; - for( j = i + 1; j < D; j++ ) { - tmp = SKP_SMLAWB( tmp, pRow[ j ], cn[ j ] ); - } - tmp = SKP_SMLAWB( tmp, SKP_RSHIFT( pRow[ i ], 1 ), cn[ i ] ); - tmp2 = SKP_SMLAWB( tmp2, tmp, cn[ i ] ); - } - nrg = SKP_ADD_LSHIFT32( nrg, tmp2, lshifts ); /* Q: -lshifts - 1 */ - - /* Keep one bit free always, because we add them for LSF interpolation */ - if( nrg < 1 ) { - nrg = 1; - } else if( nrg > SKP_RSHIFT( SKP_int32_MAX, lshifts + 2 ) ) { - nrg = SKP_int32_MAX >> 1; - } else { - nrg = SKP_LSHIFT( nrg, lshifts + 1 ); /* Q0 */ - } - return nrg; - -} +/*********************************************************************** +Copyright (c) 2006-2011, Skype Limited. All rights reserved. +Redistribution and use in source and binary forms, with or without +modification, (subject to the limitations in the disclaimer below) +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 Skype Limited, nor the names of specific +contributors, may be used to endorse or promote products derived from +this software without specific prior written permission. +NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED +BY THIS LICENSE. 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. +***********************************************************************/ + +#include "silk_main_FIX.h" + +/* Residual energy: nrg = wxx - 2 * wXx * c + c' * wXX * c */ +opus_int32 silk_residual_energy16_covar_FIX( + const opus_int16 *c, /* I Prediction vector */ + const opus_int32 *wXX, /* I Correlation matrix */ + const opus_int32 *wXx, /* I Correlation vector */ + opus_int32 wxx, /* I Signal energy */ + opus_int D, /* I Dimension */ + opus_int cQ /* I Q value for c vector 0 - 15 */ +) +{ + opus_int i, j, lshifts, Qxtra; + opus_int32 c_max, w_max, tmp, tmp2, nrg; + opus_int cn[ MAX_MATRIX_SIZE ]; + const opus_int32 *pRow; + + /* Safety checks */ + SKP_assert( D >= 0 ); + SKP_assert( D <= 16 ); + SKP_assert( cQ > 0 ); + SKP_assert( cQ < 16 ); + + lshifts = 16 - cQ; + Qxtra = lshifts; + + c_max = 0; + for( i = 0; i < D; i++ ) { + c_max = SKP_max_32( c_max, SKP_abs( ( opus_int32 )c[ i ] ) ); + } + Qxtra = SKP_min_int( Qxtra, silk_CLZ32( c_max ) - 17 ); + + w_max = SKP_max_32( wXX[ 0 ], wXX[ D * D - 1 ] ); + Qxtra = SKP_min_int( Qxtra, silk_CLZ32( SKP_MUL( D, SKP_RSHIFT( SKP_SMULWB( w_max, c_max ), 4 ) ) ) - 5 ); + Qxtra = SKP_max_int( Qxtra, 0 ); + for( i = 0; i < D; i++ ) { + cn[ i ] = SKP_LSHIFT( ( opus_int )c[ i ], Qxtra ); + SKP_assert( SKP_abs(cn[i]) <= ( SKP_int16_MAX + 1 ) ); /* Check that SKP_SMLAWB can be used */ + } + lshifts -= Qxtra; + + /* Compute wxx - 2 * wXx * c */ + tmp = 0; + for( i = 0; i < D; i++ ) { + tmp = SKP_SMLAWB( tmp, wXx[ i ], cn[ i ] ); + } + nrg = SKP_RSHIFT( wxx, 1 + lshifts ) - tmp; /* Q: -lshifts - 1 */ + + /* Add c' * wXX * c, assuming wXX is symmetric */ + tmp2 = 0; + for( i = 0; i < D; i++ ) { + tmp = 0; + pRow = &wXX[ i * D ]; + for( j = i + 1; j < D; j++ ) { + tmp = SKP_SMLAWB( tmp, pRow[ j ], cn[ j ] ); + } + tmp = SKP_SMLAWB( tmp, SKP_RSHIFT( pRow[ i ], 1 ), cn[ i ] ); + tmp2 = SKP_SMLAWB( tmp2, tmp, cn[ i ] ); + } + nrg = SKP_ADD_LSHIFT32( nrg, tmp2, lshifts ); /* Q: -lshifts - 1 */ + + /* Keep one bit free always, because we add them for LSF interpolation */ + if( nrg < 1 ) { + nrg = 1; + } else if( nrg > SKP_RSHIFT( SKP_int32_MAX, lshifts + 2 ) ) { + nrg = SKP_int32_MAX >> 1; + } else { + nrg = SKP_LSHIFT( nrg, lshifts + 1 ); /* Q0 */ + } + return nrg; + +} diff --git a/silk/fixed/silk_residual_energy_FIX.c b/silk/fixed/silk_residual_energy_FIX.c index e156b3639..33427703f 100644 --- a/silk/fixed/silk_residual_energy_FIX.c +++ b/silk/fixed/silk_residual_energy_FIX.c @@ -1,87 +1,87 @@ -/*********************************************************************** -Copyright (c) 2006-2011, Skype Limited. All rights reserved. -Redistribution and use in source and binary forms, with or without -modification, (subject to the limitations in the disclaimer below) -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 Skype Limited, nor the names of specific -contributors, may be used to endorse or promote products derived from -this software without specific prior written permission. -NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED -BY THIS LICENSE. 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. -***********************************************************************/ - -#include "silk_main_FIX.h" - -/* Calculates residual energies of input subframes where all subframes have LPC_order */ -/* of preceeding samples */ -void silk_residual_energy_FIX( - opus_int32 nrgs[ MAX_NB_SUBFR ], /* O Residual energy per subframe */ - opus_int nrgsQ[ MAX_NB_SUBFR ], /* O Q value per subframe */ - const opus_int16 x[], /* I Input signal */ - opus_int16 a_Q12[ 2 ][ MAX_LPC_ORDER ], /* I AR coefs for each frame half */ - const opus_int32 gains[ MAX_NB_SUBFR ], /* I Quantization gains */ - const opus_int subfr_length, /* I Subframe length */ - const opus_int nb_subfr, /* I Number of subframes */ - const opus_int LPC_order /* I LPC order */ -) -{ - opus_int offset, i, j, rshift, lz1, lz2; - opus_int16 *LPC_res_ptr, LPC_res[ ( MAX_FRAME_LENGTH + MAX_NB_SUBFR * MAX_LPC_ORDER ) / 2 ]; - const opus_int16 *x_ptr; - opus_int32 tmp32; - - x_ptr = x; - offset = LPC_order + subfr_length; - - /* Filter input to create the LPC residual for each frame half, and measure subframe energies */ - for( i = 0; i < nb_subfr >> 1; i++ ) { - /* Calculate half frame LPC residual signal including preceeding samples */ - silk_LPC_analysis_filter( LPC_res, x_ptr, a_Q12[ i ], ( MAX_NB_SUBFR >> 1 ) * offset, LPC_order ); - - /* Point to first subframe of the just calculated LPC residual signal */ - LPC_res_ptr = LPC_res + LPC_order; - for( j = 0; j < ( MAX_NB_SUBFR >> 1 ); j++ ) { - /* Measure subframe energy */ - silk_sum_sqr_shift( &nrgs[ i * ( MAX_NB_SUBFR >> 1 ) + j ], &rshift, LPC_res_ptr, subfr_length ); - - /* Set Q values for the measured energy */ - nrgsQ[ i * ( MAX_NB_SUBFR >> 1 ) + j ] = -rshift; - - /* Move to next subframe */ - LPC_res_ptr += offset; - } - /* Move to next frame half */ - x_ptr += ( MAX_NB_SUBFR >> 1 ) * offset; - } - - /* Apply the squared subframe gains */ - for( i = 0; i < nb_subfr; i++ ) { - /* Fully upscale gains and energies */ - lz1 = silk_CLZ32( nrgs[ i ] ) - 1; - lz2 = silk_CLZ32( gains[ i ] ) - 1; - - tmp32 = SKP_LSHIFT32( gains[ i ], lz2 ); - - /* Find squared gains */ - tmp32 = SKP_SMMUL( tmp32, tmp32 ); // Q( 2 * lz2 - 32 ) - - /* Scale energies */ - nrgs[ i ] = SKP_SMMUL( tmp32, SKP_LSHIFT32( nrgs[ i ], lz1 ) ); // Q( nrgsQ[ i ] + lz1 + 2 * lz2 - 32 - 32 ) - nrgsQ[ i ] += lz1 + 2 * lz2 - 32 - 32; - } -} +/*********************************************************************** +Copyright (c) 2006-2011, Skype Limited. All rights reserved. +Redistribution and use in source and binary forms, with or without +modification, (subject to the limitations in the disclaimer below) +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 Skype Limited, nor the names of specific +contributors, may be used to endorse or promote products derived from +this software without specific prior written permission. +NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED +BY THIS LICENSE. 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. +***********************************************************************/ + +#include "silk_main_FIX.h" + +/* Calculates residual energies of input subframes where all subframes have LPC_order */ +/* of preceeding samples */ +void silk_residual_energy_FIX( + opus_int32 nrgs[ MAX_NB_SUBFR ], /* O Residual energy per subframe */ + opus_int nrgsQ[ MAX_NB_SUBFR ], /* O Q value per subframe */ + const opus_int16 x[], /* I Input signal */ + opus_int16 a_Q12[ 2 ][ MAX_LPC_ORDER ], /* I AR coefs for each frame half */ + const opus_int32 gains[ MAX_NB_SUBFR ], /* I Quantization gains */ + const opus_int subfr_length, /* I Subframe length */ + const opus_int nb_subfr, /* I Number of subframes */ + const opus_int LPC_order /* I LPC order */ +) +{ + opus_int offset, i, j, rshift, lz1, lz2; + opus_int16 *LPC_res_ptr, LPC_res[ ( MAX_FRAME_LENGTH + MAX_NB_SUBFR * MAX_LPC_ORDER ) / 2 ]; + const opus_int16 *x_ptr; + opus_int32 tmp32; + + x_ptr = x; + offset = LPC_order + subfr_length; + + /* Filter input to create the LPC residual for each frame half, and measure subframe energies */ + for( i = 0; i < nb_subfr >> 1; i++ ) { + /* Calculate half frame LPC residual signal including preceeding samples */ + silk_LPC_analysis_filter( LPC_res, x_ptr, a_Q12[ i ], ( MAX_NB_SUBFR >> 1 ) * offset, LPC_order ); + + /* Point to first subframe of the just calculated LPC residual signal */ + LPC_res_ptr = LPC_res + LPC_order; + for( j = 0; j < ( MAX_NB_SUBFR >> 1 ); j++ ) { + /* Measure subframe energy */ + silk_sum_sqr_shift( &nrgs[ i * ( MAX_NB_SUBFR >> 1 ) + j ], &rshift, LPC_res_ptr, subfr_length ); + + /* Set Q values for the measured energy */ + nrgsQ[ i * ( MAX_NB_SUBFR >> 1 ) + j ] = -rshift; + + /* Move to next subframe */ + LPC_res_ptr += offset; + } + /* Move to next frame half */ + x_ptr += ( MAX_NB_SUBFR >> 1 ) * offset; + } + + /* Apply the squared subframe gains */ + for( i = 0; i < nb_subfr; i++ ) { + /* Fully upscale gains and energies */ + lz1 = silk_CLZ32( nrgs[ i ] ) - 1; + lz2 = silk_CLZ32( gains[ i ] ) - 1; + + tmp32 = SKP_LSHIFT32( gains[ i ], lz2 ); + + /* Find squared gains */ + tmp32 = SKP_SMMUL( tmp32, tmp32 ); // Q( 2 * lz2 - 32 ) + + /* Scale energies */ + nrgs[ i ] = SKP_SMMUL( tmp32, SKP_LSHIFT32( nrgs[ i ], lz1 ) ); // Q( nrgsQ[ i ] + lz1 + 2 * lz2 - 32 - 32 ) + nrgsQ[ i ] += lz1 + 2 * lz2 - 32 - 32; + } +} diff --git a/silk/fixed/silk_solve_LS_FIX.c b/silk/fixed/silk_solve_LS_FIX.c index ef69fb458..9d05a8e86 100644 --- a/silk/fixed/silk_solve_LS_FIX.c +++ b/silk/fixed/silk_solve_LS_FIX.c @@ -1,241 +1,241 @@ -/*********************************************************************** -Copyright (c) 2006-2011, Skype Limited. All rights reserved. -Redistribution and use in source and binary forms, with or without -modification, (subject to the limitations in the disclaimer below) -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 Skype Limited, nor the names of specific -contributors, may be used to endorse or promote products derived from -this software without specific prior written permission. -NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED -BY THIS LICENSE. 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. -***********************************************************************/ - -#include "silk_main_FIX.h" -#include "silk_tuning_parameters.h" - -/*****************************/ -/* Internal function headers */ -/*****************************/ - -typedef struct { - opus_int32 Q36_part; - opus_int32 Q48_part; -} inv_D_t; - -/* Factorize square matrix A into LDL form */ -SKP_INLINE void silk_LDL_factorize_FIX( - opus_int32 *A, /* I/O Pointer to Symetric Square Matrix */ - opus_int M, /* I Size of Matrix */ - opus_int32 *L_Q16, /* I/O Pointer to Square Upper triangular Matrix */ - inv_D_t *inv_D /* I/O Pointer to vector holding inverted diagonal elements of D */ -); - -/* Solve Lx = b, when L is lower triangular and has ones on the diagonal */ -SKP_INLINE void silk_LS_SolveFirst_FIX( - const opus_int32 *L_Q16, /* I Pointer to Lower Triangular Matrix */ - opus_int M, /* I Dim of Matrix equation */ - const opus_int32 *b, /* I b Vector */ - opus_int32 *x_Q16 /* O x Vector */ -); - -/* Solve L^t*x = b, where L is lower triangular with ones on the diagonal */ -SKP_INLINE void silk_LS_SolveLast_FIX( - const opus_int32 *L_Q16, /* I Pointer to Lower Triangular Matrix */ - const opus_int M, /* I Dim of Matrix equation */ - const opus_int32 *b, /* I b Vector */ - opus_int32 *x_Q16 /* O x Vector */ -); - -SKP_INLINE void silk_LS_divide_Q16_FIX( - opus_int32 T[], /* I/O Numenator vector */ - inv_D_t *inv_D, /* I 1 / D vector */ - opus_int M /* I dimension */ -); - -/* Solves Ax = b, assuming A is symmetric */ -void silk_solve_LDL_FIX( - opus_int32 *A, /* I Pointer to symetric square matrix A */ - opus_int M, /* I Size of matrix */ - const opus_int32 *b, /* I Pointer to b vector */ - opus_int32 *x_Q16 /* O Pointer to x solution vector */ -) -{ - opus_int32 L_Q16[ MAX_MATRIX_SIZE * MAX_MATRIX_SIZE ]; - opus_int32 Y[ MAX_MATRIX_SIZE ]; - inv_D_t inv_D[ MAX_MATRIX_SIZE ]; - - SKP_assert( M <= MAX_MATRIX_SIZE ); - - /*************************************************** - Factorize A by LDL such that A = L*D*L', - where L is lower triangular with ones on diagonal - ****************************************************/ - silk_LDL_factorize_FIX( A, M, L_Q16, inv_D ); - - /**************************************************** - * substitute D*L'*x = Y. ie: - L*D*L'*x = b => L*Y = b <=> Y = inv(L)*b - ******************************************************/ - silk_LS_SolveFirst_FIX( L_Q16, M, b, Y ); - - /**************************************************** - D*L'*x = Y <=> L'*x = inv(D)*Y, because D is - diagonal just multiply with 1/d_i - ****************************************************/ - silk_LS_divide_Q16_FIX( Y, inv_D, M ); - - /**************************************************** - x = inv(L') * inv(D) * Y - *****************************************************/ - silk_LS_SolveLast_FIX( L_Q16, M, Y, x_Q16 ); -} - -SKP_INLINE void silk_LDL_factorize_FIX( - opus_int32 *A, /* I Pointer to Symetric Square Matrix */ - opus_int M, /* I Size of Matrix */ - opus_int32 *L_Q16, /* I/O Pointer to Square Upper triangular Matrix */ - inv_D_t *inv_D /* I/O Pointer to vector holding inverted diagonal elements of D */ -) -{ - opus_int i, j, k, status, loop_count; - const opus_int32 *ptr1, *ptr2; - opus_int32 diag_min_value, tmp_32, err; - opus_int32 v_Q0[ MAX_MATRIX_SIZE ], D_Q0[ MAX_MATRIX_SIZE ]; - opus_int32 one_div_diag_Q36, one_div_diag_Q40, one_div_diag_Q48; - - SKP_assert( M <= MAX_MATRIX_SIZE ); - - status = 1; - diag_min_value = SKP_max_32( SKP_SMMUL( SKP_ADD_SAT32( A[ 0 ], A[ SKP_SMULBB( M, M ) - 1 ] ), SILK_FIX_CONST( FIND_LTP_COND_FAC, 31 ) ), 1 << 9 ); - for( loop_count = 0; loop_count < M && status == 1; loop_count++ ) { - status = 0; - for( j = 0; j < M; j++ ) { - ptr1 = matrix_adr( L_Q16, j, 0, M ); - tmp_32 = 0; - for( i = 0; i < j; i++ ) { - v_Q0[ i ] = SKP_SMULWW( D_Q0[ i ], ptr1[ i ] ); /* Q0 */ - tmp_32 = SKP_SMLAWW( tmp_32, v_Q0[ i ], ptr1[ i ] ); /* Q0 */ - } - tmp_32 = SKP_SUB32( matrix_ptr( A, j, j, M ), tmp_32 ); - - if( tmp_32 < diag_min_value ) { - tmp_32 = SKP_SUB32( SKP_SMULBB( loop_count + 1, diag_min_value ), tmp_32 ); - /* Matrix not positive semi-definite, or ill conditioned */ - for( i = 0; i < M; i++ ) { - matrix_ptr( A, i, i, M ) = SKP_ADD32( matrix_ptr( A, i, i, M ), tmp_32 ); - } - status = 1; - break; - } - D_Q0[ j ] = tmp_32; /* always < max(Correlation) */ - - /* two-step division */ - one_div_diag_Q36 = silk_INVERSE32_varQ( tmp_32, 36 ); /* Q36 */ - one_div_diag_Q40 = SKP_LSHIFT( one_div_diag_Q36, 4 ); /* Q40 */ - err = SKP_SUB32( 1 << 24, SKP_SMULWW( tmp_32, one_div_diag_Q40 ) ); /* Q24 */ - one_div_diag_Q48 = SKP_SMULWW( err, one_div_diag_Q40 ); /* Q48 */ - - /* Save 1/Ds */ - inv_D[ j ].Q36_part = one_div_diag_Q36; - inv_D[ j ].Q48_part = one_div_diag_Q48; - - matrix_ptr( L_Q16, j, j, M ) = 65536; /* 1.0 in Q16 */ - ptr1 = matrix_adr( A, j, 0, M ); - ptr2 = matrix_adr( L_Q16, j + 1, 0, M ); - for( i = j + 1; i < M; i++ ) { - tmp_32 = 0; - for( k = 0; k < j; k++ ) { - tmp_32 = SKP_SMLAWW( tmp_32, v_Q0[ k ], ptr2[ k ] ); /* Q0 */ - } - tmp_32 = SKP_SUB32( ptr1[ i ], tmp_32 ); /* always < max(Correlation) */ - - /* tmp_32 / D_Q0[j] : Divide to Q16 */ - matrix_ptr( L_Q16, i, j, M ) = SKP_ADD32( SKP_SMMUL( tmp_32, one_div_diag_Q48 ), - SKP_RSHIFT( SKP_SMULWW( tmp_32, one_div_diag_Q36 ), 4 ) ); - - /* go to next column */ - ptr2 += M; - } - } - } - - SKP_assert( status == 0 ); -} - -SKP_INLINE void silk_LS_divide_Q16_FIX( - opus_int32 T[], /* I/O Numenator vector */ - inv_D_t *inv_D, /* I 1 / D vector */ - opus_int M /* I Order */ -) -{ - opus_int i; - opus_int32 tmp_32; - opus_int32 one_div_diag_Q36, one_div_diag_Q48; - - for( i = 0; i < M; i++ ) { - one_div_diag_Q36 = inv_D[ i ].Q36_part; - one_div_diag_Q48 = inv_D[ i ].Q48_part; - - tmp_32 = T[ i ]; - T[ i ] = SKP_ADD32( SKP_SMMUL( tmp_32, one_div_diag_Q48 ), SKP_RSHIFT( SKP_SMULWW( tmp_32, one_div_diag_Q36 ), 4 ) ); - } -} - -/* Solve Lx = b, when L is lower triangular and has ones on the diagonal */ -SKP_INLINE void silk_LS_SolveFirst_FIX( - const opus_int32 *L_Q16, /* I Pointer to Lower Triangular Matrix */ - opus_int M, /* I Dim of Matrix equation */ - const opus_int32 *b, /* I b Vector */ - opus_int32 *x_Q16 /* O x Vector */ -) -{ - opus_int i, j; - const opus_int32 *ptr32; - opus_int32 tmp_32; - - for( i = 0; i < M; i++ ) { - ptr32 = matrix_adr( L_Q16, i, 0, M ); - tmp_32 = 0; - for( j = 0; j < i; j++ ) { - tmp_32 = SKP_SMLAWW( tmp_32, ptr32[ j ], x_Q16[ j ] ); - } - x_Q16[ i ] = SKP_SUB32( b[ i ], tmp_32 ); - } -} - -/* Solve L^t*x = b, where L is lower triangular with ones on the diagonal */ -SKP_INLINE void silk_LS_SolveLast_FIX( - const opus_int32 *L_Q16, /* I Pointer to Lower Triangular Matrix */ - const opus_int M, /* I Dim of Matrix equation */ - const opus_int32 *b, /* I b Vector */ - opus_int32 *x_Q16 /* O x Vector */ -) -{ - opus_int i, j; - const opus_int32 *ptr32; - opus_int32 tmp_32; - - for( i = M - 1; i >= 0; i-- ) { - ptr32 = matrix_adr( L_Q16, 0, i, M ); - tmp_32 = 0; - for( j = M - 1; j > i; j-- ) { - tmp_32 = SKP_SMLAWW( tmp_32, ptr32[ SKP_SMULBB( j, M ) ], x_Q16[ j ] ); - } - x_Q16[ i ] = SKP_SUB32( b[ i ], tmp_32 ); - } -} +/*********************************************************************** +Copyright (c) 2006-2011, Skype Limited. All rights reserved. +Redistribution and use in source and binary forms, with or without +modification, (subject to the limitations in the disclaimer below) +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 Skype Limited, nor the names of specific +contributors, may be used to endorse or promote products derived from +this software without specific prior written permission. +NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED +BY THIS LICENSE. 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. +***********************************************************************/ + +#include "silk_main_FIX.h" +#include "silk_tuning_parameters.h" + +/*****************************/ +/* Internal function headers */ +/*****************************/ + +typedef struct { + opus_int32 Q36_part; + opus_int32 Q48_part; +} inv_D_t; + +/* Factorize square matrix A into LDL form */ +SKP_INLINE void silk_LDL_factorize_FIX( + opus_int32 *A, /* I/O Pointer to Symetric Square Matrix */ + opus_int M, /* I Size of Matrix */ + opus_int32 *L_Q16, /* I/O Pointer to Square Upper triangular Matrix */ + inv_D_t *inv_D /* I/O Pointer to vector holding inverted diagonal elements of D */ +); + +/* Solve Lx = b, when L is lower triangular and has ones on the diagonal */ +SKP_INLINE void silk_LS_SolveFirst_FIX( + const opus_int32 *L_Q16, /* I Pointer to Lower Triangular Matrix */ + opus_int M, /* I Dim of Matrix equation */ + const opus_int32 *b, /* I b Vector */ + opus_int32 *x_Q16 /* O x Vector */ +); + +/* Solve L^t*x = b, where L is lower triangular with ones on the diagonal */ +SKP_INLINE void silk_LS_SolveLast_FIX( + const opus_int32 *L_Q16, /* I Pointer to Lower Triangular Matrix */ + const opus_int M, /* I Dim of Matrix equation */ + const opus_int32 *b, /* I b Vector */ + opus_int32 *x_Q16 /* O x Vector */ +); + +SKP_INLINE void silk_LS_divide_Q16_FIX( + opus_int32 T[], /* I/O Numenator vector */ + inv_D_t *inv_D, /* I 1 / D vector */ + opus_int M /* I dimension */ +); + +/* Solves Ax = b, assuming A is symmetric */ +void silk_solve_LDL_FIX( + opus_int32 *A, /* I Pointer to symetric square matrix A */ + opus_int M, /* I Size of matrix */ + const opus_int32 *b, /* I Pointer to b vector */ + opus_int32 *x_Q16 /* O Pointer to x solution vector */ +) +{ + opus_int32 L_Q16[ MAX_MATRIX_SIZE * MAX_MATRIX_SIZE ]; + opus_int32 Y[ MAX_MATRIX_SIZE ]; + inv_D_t inv_D[ MAX_MATRIX_SIZE ]; + + SKP_assert( M <= MAX_MATRIX_SIZE ); + + /*************************************************** + Factorize A by LDL such that A = L*D*L', + where L is lower triangular with ones on diagonal + ****************************************************/ + silk_LDL_factorize_FIX( A, M, L_Q16, inv_D ); + + /**************************************************** + * substitute D*L'*x = Y. ie: + L*D*L'*x = b => L*Y = b <=> Y = inv(L)*b + ******************************************************/ + silk_LS_SolveFirst_FIX( L_Q16, M, b, Y ); + + /**************************************************** + D*L'*x = Y <=> L'*x = inv(D)*Y, because D is + diagonal just multiply with 1/d_i + ****************************************************/ + silk_LS_divide_Q16_FIX( Y, inv_D, M ); + + /**************************************************** + x = inv(L') * inv(D) * Y + *****************************************************/ + silk_LS_SolveLast_FIX( L_Q16, M, Y, x_Q16 ); +} + +SKP_INLINE void silk_LDL_factorize_FIX( + opus_int32 *A, /* I Pointer to Symetric Square Matrix */ + opus_int M, /* I Size of Matrix */ + opus_int32 *L_Q16, /* I/O Pointer to Square Upper triangular Matrix */ + inv_D_t *inv_D /* I/O Pointer to vector holding inverted diagonal elements of D */ +) +{ + opus_int i, j, k, status, loop_count; + const opus_int32 *ptr1, *ptr2; + opus_int32 diag_min_value, tmp_32, err; + opus_int32 v_Q0[ MAX_MATRIX_SIZE ], D_Q0[ MAX_MATRIX_SIZE ]; + opus_int32 one_div_diag_Q36, one_div_diag_Q40, one_div_diag_Q48; + + SKP_assert( M <= MAX_MATRIX_SIZE ); + + status = 1; + diag_min_value = SKP_max_32( SKP_SMMUL( SKP_ADD_SAT32( A[ 0 ], A[ SKP_SMULBB( M, M ) - 1 ] ), SILK_FIX_CONST( FIND_LTP_COND_FAC, 31 ) ), 1 << 9 ); + for( loop_count = 0; loop_count < M && status == 1; loop_count++ ) { + status = 0; + for( j = 0; j < M; j++ ) { + ptr1 = matrix_adr( L_Q16, j, 0, M ); + tmp_32 = 0; + for( i = 0; i < j; i++ ) { + v_Q0[ i ] = SKP_SMULWW( D_Q0[ i ], ptr1[ i ] ); /* Q0 */ + tmp_32 = SKP_SMLAWW( tmp_32, v_Q0[ i ], ptr1[ i ] ); /* Q0 */ + } + tmp_32 = SKP_SUB32( matrix_ptr( A, j, j, M ), tmp_32 ); + + if( tmp_32 < diag_min_value ) { + tmp_32 = SKP_SUB32( SKP_SMULBB( loop_count + 1, diag_min_value ), tmp_32 ); + /* Matrix not positive semi-definite, or ill conditioned */ + for( i = 0; i < M; i++ ) { + matrix_ptr( A, i, i, M ) = SKP_ADD32( matrix_ptr( A, i, i, M ), tmp_32 ); + } + status = 1; + break; + } + D_Q0[ j ] = tmp_32; /* always < max(Correlation) */ + + /* two-step division */ + one_div_diag_Q36 = silk_INVERSE32_varQ( tmp_32, 36 ); /* Q36 */ + one_div_diag_Q40 = SKP_LSHIFT( one_div_diag_Q36, 4 ); /* Q40 */ + err = SKP_SUB32( 1 << 24, SKP_SMULWW( tmp_32, one_div_diag_Q40 ) ); /* Q24 */ + one_div_diag_Q48 = SKP_SMULWW( err, one_div_diag_Q40 ); /* Q48 */ + + /* Save 1/Ds */ + inv_D[ j ].Q36_part = one_div_diag_Q36; + inv_D[ j ].Q48_part = one_div_diag_Q48; + + matrix_ptr( L_Q16, j, j, M ) = 65536; /* 1.0 in Q16 */ + ptr1 = matrix_adr( A, j, 0, M ); + ptr2 = matrix_adr( L_Q16, j + 1, 0, M ); + for( i = j + 1; i < M; i++ ) { + tmp_32 = 0; + for( k = 0; k < j; k++ ) { + tmp_32 = SKP_SMLAWW( tmp_32, v_Q0[ k ], ptr2[ k ] ); /* Q0 */ + } + tmp_32 = SKP_SUB32( ptr1[ i ], tmp_32 ); /* always < max(Correlation) */ + + /* tmp_32 / D_Q0[j] : Divide to Q16 */ + matrix_ptr( L_Q16, i, j, M ) = SKP_ADD32( SKP_SMMUL( tmp_32, one_div_diag_Q48 ), + SKP_RSHIFT( SKP_SMULWW( tmp_32, one_div_diag_Q36 ), 4 ) ); + + /* go to next column */ + ptr2 += M; + } + } + } + + SKP_assert( status == 0 ); +} + +SKP_INLINE void silk_LS_divide_Q16_FIX( + opus_int32 T[], /* I/O Numenator vector */ + inv_D_t *inv_D, /* I 1 / D vector */ + opus_int M /* I Order */ +) +{ + opus_int i; + opus_int32 tmp_32; + opus_int32 one_div_diag_Q36, one_div_diag_Q48; + + for( i = 0; i < M; i++ ) { + one_div_diag_Q36 = inv_D[ i ].Q36_part; + one_div_diag_Q48 = inv_D[ i ].Q48_part; + + tmp_32 = T[ i ]; + T[ i ] = SKP_ADD32( SKP_SMMUL( tmp_32, one_div_diag_Q48 ), SKP_RSHIFT( SKP_SMULWW( tmp_32, one_div_diag_Q36 ), 4 ) ); + } +} + +/* Solve Lx = b, when L is lower triangular and has ones on the diagonal */ +SKP_INLINE void silk_LS_SolveFirst_FIX( + const opus_int32 *L_Q16, /* I Pointer to Lower Triangular Matrix */ + opus_int M, /* I Dim of Matrix equation */ + const opus_int32 *b, /* I b Vector */ + opus_int32 *x_Q16 /* O x Vector */ +) +{ + opus_int i, j; + const opus_int32 *ptr32; + opus_int32 tmp_32; + + for( i = 0; i < M; i++ ) { + ptr32 = matrix_adr( L_Q16, i, 0, M ); + tmp_32 = 0; + for( j = 0; j < i; j++ ) { + tmp_32 = SKP_SMLAWW( tmp_32, ptr32[ j ], x_Q16[ j ] ); + } + x_Q16[ i ] = SKP_SUB32( b[ i ], tmp_32 ); + } +} + +/* Solve L^t*x = b, where L is lower triangular with ones on the diagonal */ +SKP_INLINE void silk_LS_SolveLast_FIX( + const opus_int32 *L_Q16, /* I Pointer to Lower Triangular Matrix */ + const opus_int M, /* I Dim of Matrix equation */ + const opus_int32 *b, /* I b Vector */ + opus_int32 *x_Q16 /* O x Vector */ +) +{ + opus_int i, j; + const opus_int32 *ptr32; + opus_int32 tmp_32; + + for( i = M - 1; i >= 0; i-- ) { + ptr32 = matrix_adr( L_Q16, 0, i, M ); + tmp_32 = 0; + for( j = M - 1; j > i; j-- ) { + tmp_32 = SKP_SMLAWW( tmp_32, ptr32[ SKP_SMULBB( j, M ) ], x_Q16[ j ] ); + } + x_Q16[ i ] = SKP_SUB32( b[ i ], tmp_32 ); + } +} diff --git a/silk/fixed/silk_structs_FIX.h b/silk/fixed/silk_structs_FIX.h index d7d5d8746..6cd74f119 100644 --- a/silk/fixed/silk_structs_FIX.h +++ b/silk/fixed/silk_structs_FIX.h @@ -1,132 +1,132 @@ -/*********************************************************************** -Copyright (c) 2006-2011, Skype Limited. All rights reserved. -Redistribution and use in source and binary forms, with or without -modification, (subject to the limitations in the disclaimer below) -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 Skype Limited, nor the names of specific -contributors, may be used to endorse or promote products derived from -this software without specific prior written permission. -NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED -BY THIS LICENSE. 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. -***********************************************************************/ - -#ifndef SILK_STRUCTS_FIX_H -#define SILK_STRUCTS_FIX_H - -#include "silk_typedef.h" -#include "silk_main.h" -#include "silk_structs.h" - -#ifdef __cplusplus -extern "C" -{ -#endif - -/********************************/ -/* Noise shaping analysis state */ -/********************************/ -typedef struct { - opus_int8 LastGainIndex; - opus_int32 HarmBoost_smth_Q16; - opus_int32 HarmShapeGain_smth_Q16; - opus_int32 Tilt_smth_Q16; -} silk_shape_state_FIX; - -/********************************/ -/* Prefilter state */ -/********************************/ -typedef struct { - opus_int16 sLTP_shp[ LTP_BUF_LENGTH ]; - opus_int32 sAR_shp[ MAX_SHAPE_LPC_ORDER + 1 ]; - opus_int sLTP_shp_buf_idx; - opus_int32 sLF_AR_shp_Q12; - opus_int32 sLF_MA_shp_Q12; - opus_int sHarmHP; - opus_int32 rand_seed; - opus_int lagPrev; -} silk_prefilter_state_FIX; - -/********************************/ -/* Encoder state FIX */ -/********************************/ -typedef struct { - silk_encoder_state sCmn; /* Common struct, shared with floating-point code */ - silk_shape_state_FIX sShape; /* Shape state */ - silk_prefilter_state_FIX sPrefilt; /* Prefilter State */ - - /* Buffer for find pitch and noise shape analysis */ - SKP_DWORD_ALIGN opus_int16 x_buf[ 2 * MAX_FRAME_LENGTH + LA_SHAPE_MAX ];/* Buffer for find pitch and noise shape analysis */ - opus_int LTPCorr_Q15; /* Normalized correlation from pitch lag estimator */ - - /* Parameters For LTP scaling Control */ - opus_int prevLTPredCodGain_Q7; - opus_int HPLTPredCodGain_Q7; -} silk_encoder_state_FIX; - -/************************/ -/* Encoder control FIX */ -/************************/ -typedef struct { - /* Prediction and coding parameters */ - opus_int32 Gains_Q16[ MAX_NB_SUBFR ]; - SKP_DWORD_ALIGN opus_int16 PredCoef_Q12[ 2 ][ MAX_LPC_ORDER ]; - opus_int16 LTPCoef_Q14[ LTP_ORDER * MAX_NB_SUBFR ]; - opus_int LTP_scale_Q14; - opus_int pitchL[ MAX_NB_SUBFR ]; - - /* Noise shaping parameters */ - /* Testing */ - SKP_DWORD_ALIGN opus_int16 AR1_Q13[ MAX_NB_SUBFR * MAX_SHAPE_LPC_ORDER ]; - SKP_DWORD_ALIGN opus_int16 AR2_Q13[ MAX_NB_SUBFR * MAX_SHAPE_LPC_ORDER ]; - opus_int32 LF_shp_Q14[ MAX_NB_SUBFR ]; /* Packs two int16 coefficients per int32 value */ - opus_int GainsPre_Q14[ MAX_NB_SUBFR ]; - opus_int HarmBoost_Q14[ MAX_NB_SUBFR ]; - opus_int Tilt_Q14[ MAX_NB_SUBFR ]; - opus_int HarmShapeGain_Q14[ MAX_NB_SUBFR ]; - opus_int Lambda_Q10; - opus_int input_quality_Q14; - opus_int coding_quality_Q14; - - /* measures */ - opus_int sparseness_Q8; - opus_int32 predGain_Q16; - opus_int LTPredCodGain_Q7; - opus_int32 ResNrg[ MAX_NB_SUBFR ]; /* Residual energy per subframe */ - opus_int ResNrgQ[ MAX_NB_SUBFR ]; /* Q domain for the residual energy > 0 */ - -} silk_encoder_control_FIX; - -/************************/ -/* Encoder Super Struct */ -/************************/ -typedef struct { - silk_encoder_state_FIX state_Fxx[ ENCODER_NUM_CHANNELS ]; - stereo_enc_state sStereo; - opus_int32 nBitsExceeded; - opus_int nChannelsAPI; - opus_int nChannelsInternal; - opus_int timeSinceSwitchAllowed_ms; - opus_int allowBandwidthSwitch; -} silk_encoder; - - -#ifdef __cplusplus -} -#endif - -#endif +/*********************************************************************** +Copyright (c) 2006-2011, Skype Limited. All rights reserved. +Redistribution and use in source and binary forms, with or without +modification, (subject to the limitations in the disclaimer below) +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 Skype Limited, nor the names of specific +contributors, may be used to endorse or promote products derived from +this software without specific prior written permission. +NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED +BY THIS LICENSE. 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. +***********************************************************************/ + +#ifndef SILK_STRUCTS_FIX_H +#define SILK_STRUCTS_FIX_H + +#include "silk_typedef.h" +#include "silk_main.h" +#include "silk_structs.h" + +#ifdef __cplusplus +extern "C" +{ +#endif + +/********************************/ +/* Noise shaping analysis state */ +/********************************/ +typedef struct { + opus_int8 LastGainIndex; + opus_int32 HarmBoost_smth_Q16; + opus_int32 HarmShapeGain_smth_Q16; + opus_int32 Tilt_smth_Q16; +} silk_shape_state_FIX; + +/********************************/ +/* Prefilter state */ +/********************************/ +typedef struct { + opus_int16 sLTP_shp[ LTP_BUF_LENGTH ]; + opus_int32 sAR_shp[ MAX_SHAPE_LPC_ORDER + 1 ]; + opus_int sLTP_shp_buf_idx; + opus_int32 sLF_AR_shp_Q12; + opus_int32 sLF_MA_shp_Q12; + opus_int sHarmHP; + opus_int32 rand_seed; + opus_int lagPrev; +} silk_prefilter_state_FIX; + +/********************************/ +/* Encoder state FIX */ +/********************************/ +typedef struct { + silk_encoder_state sCmn; /* Common struct, shared with floating-point code */ + silk_shape_state_FIX sShape; /* Shape state */ + silk_prefilter_state_FIX sPrefilt; /* Prefilter State */ + + /* Buffer for find pitch and noise shape analysis */ + SKP_DWORD_ALIGN opus_int16 x_buf[ 2 * MAX_FRAME_LENGTH + LA_SHAPE_MAX ];/* Buffer for find pitch and noise shape analysis */ + opus_int LTPCorr_Q15; /* Normalized correlation from pitch lag estimator */ + + /* Parameters For LTP scaling Control */ + opus_int prevLTPredCodGain_Q7; + opus_int HPLTPredCodGain_Q7; +} silk_encoder_state_FIX; + +/************************/ +/* Encoder control FIX */ +/************************/ +typedef struct { + /* Prediction and coding parameters */ + opus_int32 Gains_Q16[ MAX_NB_SUBFR ]; + SKP_DWORD_ALIGN opus_int16 PredCoef_Q12[ 2 ][ MAX_LPC_ORDER ]; + opus_int16 LTPCoef_Q14[ LTP_ORDER * MAX_NB_SUBFR ]; + opus_int LTP_scale_Q14; + opus_int pitchL[ MAX_NB_SUBFR ]; + + /* Noise shaping parameters */ + /* Testing */ + SKP_DWORD_ALIGN opus_int16 AR1_Q13[ MAX_NB_SUBFR * MAX_SHAPE_LPC_ORDER ]; + SKP_DWORD_ALIGN opus_int16 AR2_Q13[ MAX_NB_SUBFR * MAX_SHAPE_LPC_ORDER ]; + opus_int32 LF_shp_Q14[ MAX_NB_SUBFR ]; /* Packs two int16 coefficients per int32 value */ + opus_int GainsPre_Q14[ MAX_NB_SUBFR ]; + opus_int HarmBoost_Q14[ MAX_NB_SUBFR ]; + opus_int Tilt_Q14[ MAX_NB_SUBFR ]; + opus_int HarmShapeGain_Q14[ MAX_NB_SUBFR ]; + opus_int Lambda_Q10; + opus_int input_quality_Q14; + opus_int coding_quality_Q14; + + /* measures */ + opus_int sparseness_Q8; + opus_int32 predGain_Q16; + opus_int LTPredCodGain_Q7; + opus_int32 ResNrg[ MAX_NB_SUBFR ]; /* Residual energy per subframe */ + opus_int ResNrgQ[ MAX_NB_SUBFR ]; /* Q domain for the residual energy > 0 */ + +} silk_encoder_control_FIX; + +/************************/ +/* Encoder Super Struct */ +/************************/ +typedef struct { + silk_encoder_state_FIX state_Fxx[ ENCODER_NUM_CHANNELS ]; + stereo_enc_state sStereo; + opus_int32 nBitsExceeded; + opus_int nChannelsAPI; + opus_int nChannelsInternal; + opus_int timeSinceSwitchAllowed_ms; + opus_int allowBandwidthSwitch; +} silk_encoder; + + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/silk/fixed/silk_warped_autocorrelation_FIX.c b/silk/fixed/silk_warped_autocorrelation_FIX.c index 2f34cb964..3f67841da 100644 --- a/silk/fixed/silk_warped_autocorrelation_FIX.c +++ b/silk/fixed/silk_warped_autocorrelation_FIX.c @@ -1,84 +1,84 @@ -/*********************************************************************** -Copyright (c) 2006-2011, Skype Limited. All rights reserved. -Redistribution and use in source and binary forms, with or without -modification, (subject to the limitations in the disclaimer below) -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 Skype Limited, nor the names of specific -contributors, may be used to endorse or promote products derived from -this software without specific prior written permission. -NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED -BY THIS LICENSE. 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. -***********************************************************************/ - -#include "silk_main_FIX.h" - -#define QC 10 -#define QS 14 - -/* Autocorrelations for a warped frequency axis */ -void silk_warped_autocorrelation_FIX( - opus_int32 *corr, /* O Result [order + 1] */ - opus_int *scale, /* O Scaling of the correlation vector */ - const opus_int16 *input, /* I Input data to correlate */ - const opus_int warping_Q16, /* I Warping coefficient */ - const opus_int length, /* I Length of input */ - const opus_int order /* I Correlation order (even) */ -) -{ - opus_int n, i, lsh; - opus_int32 tmp1_QS, tmp2_QS; - opus_int32 state_QS[ MAX_SHAPE_LPC_ORDER + 1 ] = { 0 }; - opus_int64 corr_QC[ MAX_SHAPE_LPC_ORDER + 1 ] = { 0 }; - - /* Order must be even */ - SKP_assert( ( order & 1 ) == 0 ); - SKP_assert( 2 * QS - QC >= 0 ); - - /* Loop over samples */ - for( n = 0; n < length; n++ ) { - tmp1_QS = SKP_LSHIFT32( ( opus_int32 )input[ n ], QS ); - /* Loop over allpass sections */ - for( i = 0; i < order; i += 2 ) { - /* Output of allpass section */ - tmp2_QS = SKP_SMLAWB( state_QS[ i ], state_QS[ i + 1 ] - tmp1_QS, warping_Q16 ); - state_QS[ i ] = tmp1_QS; - corr_QC[ i ] += SKP_RSHIFT64( SKP_SMULL( tmp1_QS, state_QS[ 0 ] ), 2 * QS - QC ); - /* Output of allpass section */ - tmp1_QS = SKP_SMLAWB( state_QS[ i + 1 ], state_QS[ i + 2 ] - tmp2_QS, warping_Q16 ); - state_QS[ i + 1 ] = tmp2_QS; - corr_QC[ i + 1 ] += SKP_RSHIFT64( SKP_SMULL( tmp2_QS, state_QS[ 0 ] ), 2 * QS - QC ); - } - state_QS[ order ] = tmp1_QS; - corr_QC[ order ] += SKP_RSHIFT64( SKP_SMULL( tmp1_QS, state_QS[ 0 ] ), 2 * QS - QC ); - } - - lsh = silk_CLZ64( corr_QC[ 0 ] ) - 35; - lsh = SKP_LIMIT( lsh, -12 - QC, 30 - QC ); - *scale = -( QC + lsh ); - SKP_assert( *scale >= -30 && *scale <= 12 ); - if( lsh >= 0 ) { - for( i = 0; i < order + 1; i++ ) { - corr[ i ] = ( opus_int32 )SKP_CHECK_FIT32( SKP_LSHIFT64( corr_QC[ i ], lsh ) ); - } - } else { - for( i = 0; i < order + 1; i++ ) { - corr[ i ] = ( opus_int32 )SKP_CHECK_FIT32( SKP_RSHIFT64( corr_QC[ i ], -lsh ) ); - } - } - SKP_assert( corr_QC[ 0 ] >= 0 ); // If breaking, decrease QC -} +/*********************************************************************** +Copyright (c) 2006-2011, Skype Limited. All rights reserved. +Redistribution and use in source and binary forms, with or without +modification, (subject to the limitations in the disclaimer below) +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 Skype Limited, nor the names of specific +contributors, may be used to endorse or promote products derived from +this software without specific prior written permission. +NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED +BY THIS LICENSE. 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. +***********************************************************************/ + +#include "silk_main_FIX.h" + +#define QC 10 +#define QS 14 + +/* Autocorrelations for a warped frequency axis */ +void silk_warped_autocorrelation_FIX( + opus_int32 *corr, /* O Result [order + 1] */ + opus_int *scale, /* O Scaling of the correlation vector */ + const opus_int16 *input, /* I Input data to correlate */ + const opus_int warping_Q16, /* I Warping coefficient */ + const opus_int length, /* I Length of input */ + const opus_int order /* I Correlation order (even) */ +) +{ + opus_int n, i, lsh; + opus_int32 tmp1_QS, tmp2_QS; + opus_int32 state_QS[ MAX_SHAPE_LPC_ORDER + 1 ] = { 0 }; + opus_int64 corr_QC[ MAX_SHAPE_LPC_ORDER + 1 ] = { 0 }; + + /* Order must be even */ + SKP_assert( ( order & 1 ) == 0 ); + SKP_assert( 2 * QS - QC >= 0 ); + + /* Loop over samples */ + for( n = 0; n < length; n++ ) { + tmp1_QS = SKP_LSHIFT32( ( opus_int32 )input[ n ], QS ); + /* Loop over allpass sections */ + for( i = 0; i < order; i += 2 ) { + /* Output of allpass section */ + tmp2_QS = SKP_SMLAWB( state_QS[ i ], state_QS[ i + 1 ] - tmp1_QS, warping_Q16 ); + state_QS[ i ] = tmp1_QS; + corr_QC[ i ] += SKP_RSHIFT64( SKP_SMULL( tmp1_QS, state_QS[ 0 ] ), 2 * QS - QC ); + /* Output of allpass section */ + tmp1_QS = SKP_SMLAWB( state_QS[ i + 1 ], state_QS[ i + 2 ] - tmp2_QS, warping_Q16 ); + state_QS[ i + 1 ] = tmp2_QS; + corr_QC[ i + 1 ] += SKP_RSHIFT64( SKP_SMULL( tmp2_QS, state_QS[ 0 ] ), 2 * QS - QC ); + } + state_QS[ order ] = tmp1_QS; + corr_QC[ order ] += SKP_RSHIFT64( SKP_SMULL( tmp1_QS, state_QS[ 0 ] ), 2 * QS - QC ); + } + + lsh = silk_CLZ64( corr_QC[ 0 ] ) - 35; + lsh = SKP_LIMIT( lsh, -12 - QC, 30 - QC ); + *scale = -( QC + lsh ); + SKP_assert( *scale >= -30 && *scale <= 12 ); + if( lsh >= 0 ) { + for( i = 0; i < order + 1; i++ ) { + corr[ i ] = ( opus_int32 )SKP_CHECK_FIT32( SKP_LSHIFT64( corr_QC[ i ], lsh ) ); + } + } else { + for( i = 0; i < order + 1; i++ ) { + corr[ i ] = ( opus_int32 )SKP_CHECK_FIT32( SKP_RSHIFT64( corr_QC[ i ], -lsh ) ); + } + } + SKP_assert( corr_QC[ 0 ] >= 0 ); // If breaking, decrease QC +} diff --git a/silk/float/silk_LPC_analysis_filter_FLP.c b/silk/float/silk_LPC_analysis_filter_FLP.c index 645a6455a..b4920e001 100644 --- a/silk/float/silk_LPC_analysis_filter_FLP.c +++ b/silk/float/silk_LPC_analysis_filter_FLP.c @@ -1,286 +1,286 @@ -/*********************************************************************** -Copyright (c) 2006-2011, Skype Limited. All rights reserved. -Redistribution and use in source and binary forms, with or without -modification, (subject to the limitations in the disclaimer below) -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 Skype Limited, nor the names of specific -contributors, may be used to endorse or promote products derived from -this software without specific prior written permission. -NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED -BY THIS LICENSE. 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. -***********************************************************************/ - -#include <stdlib.h> -#include "silk_main_FLP.h" - -/************************************************/ -/* LPC analysis filter */ -/* NB! State is kept internally and the */ -/* filter always starts with zero state */ -/* first Order output samples are set to zero */ -/************************************************/ - -/* 16th order LPC analysis filter, does not write first 16 samples */ -void silk_LPC_analysis_filter16_FLP( - SKP_float r_LPC[], /* O LPC residual signal */ - const SKP_float PredCoef[], /* I LPC coefficients */ - const SKP_float s[], /* I Input signal */ - const opus_int length /* I Length of input signal */ -) -{ - opus_int ix; - SKP_float LPC_pred; - const SKP_float *s_ptr; - - for ( ix = 16; ix < length; ix++) { - s_ptr = &s[ix - 1]; - - /* short-term prediction */ - LPC_pred = s_ptr[ 0 ] * PredCoef[ 0 ] + - s_ptr[ -1 ] * PredCoef[ 1 ] + - s_ptr[ -2 ] * PredCoef[ 2 ] + - s_ptr[ -3 ] * PredCoef[ 3 ] + - s_ptr[ -4 ] * PredCoef[ 4 ] + - s_ptr[ -5 ] * PredCoef[ 5 ] + - s_ptr[ -6 ] * PredCoef[ 6 ] + - s_ptr[ -7 ] * PredCoef[ 7 ] + - s_ptr[ -8 ] * PredCoef[ 8 ] + - s_ptr[ -9 ] * PredCoef[ 9 ] + - s_ptr[ -10 ] * PredCoef[ 10 ] + - s_ptr[ -11 ] * PredCoef[ 11 ] + - s_ptr[ -12 ] * PredCoef[ 12 ] + - s_ptr[ -13 ] * PredCoef[ 13 ] + - s_ptr[ -14 ] * PredCoef[ 14 ] + - s_ptr[ -15 ] * PredCoef[ 15 ]; - - /* prediction error */ - r_LPC[ix] = s_ptr[ 1 ] - LPC_pred; - } -} - -/* 14th order LPC analysis filter, does not write first 14 samples */ -void silk_LPC_analysis_filter14_FLP( - SKP_float r_LPC[], /* O LPC residual signal */ - const SKP_float PredCoef[], /* I LPC coefficients */ - const SKP_float s[], /* I Input signal */ - const opus_int length /* I Length of input signal */ -) -{ - opus_int ix; - SKP_float LPC_pred; - const SKP_float *s_ptr; - - for ( ix = 14; ix < length; ix++) { - s_ptr = &s[ix - 1]; - - /* short-term prediction */ - LPC_pred = s_ptr[ 0 ] * PredCoef[ 0 ] + - s_ptr[ -1 ] * PredCoef[ 1 ] + - s_ptr[ -2 ] * PredCoef[ 2 ] + - s_ptr[ -3 ] * PredCoef[ 3 ] + - s_ptr[ -4 ] * PredCoef[ 4 ] + - s_ptr[ -5 ] * PredCoef[ 5 ] + - s_ptr[ -6 ] * PredCoef[ 6 ] + - s_ptr[ -7 ] * PredCoef[ 7 ] + - s_ptr[ -8 ] * PredCoef[ 8 ] + - s_ptr[ -9 ] * PredCoef[ 9 ] + - s_ptr[ -10 ] * PredCoef[ 10 ] + - s_ptr[ -11 ] * PredCoef[ 11 ] + - s_ptr[ -12 ] * PredCoef[ 12 ] + - s_ptr[ -13 ] * PredCoef[ 13 ]; - - /* prediction error */ - r_LPC[ix] = s_ptr[ 1 ] - LPC_pred; - } -} - -/* 12th order LPC analysis filter, does not write first 12 samples */ -void silk_LPC_analysis_filter12_FLP( - SKP_float r_LPC[], /* O LPC residual signal */ - const SKP_float PredCoef[], /* I LPC coefficients */ - const SKP_float s[], /* I Input signal */ - const opus_int length /* I Length of input signal */ -) -{ - opus_int ix; - SKP_float LPC_pred; - const SKP_float *s_ptr; - - for ( ix = 12; ix < length; ix++) { - s_ptr = &s[ix - 1]; - - /* short-term prediction */ - LPC_pred = s_ptr[ 0 ] * PredCoef[ 0 ] + - s_ptr[ -1 ] * PredCoef[ 1 ] + - s_ptr[ -2 ] * PredCoef[ 2 ] + - s_ptr[ -3 ] * PredCoef[ 3 ] + - s_ptr[ -4 ] * PredCoef[ 4 ] + - s_ptr[ -5 ] * PredCoef[ 5 ] + - s_ptr[ -6 ] * PredCoef[ 6 ] + - s_ptr[ -7 ] * PredCoef[ 7 ] + - s_ptr[ -8 ] * PredCoef[ 8 ] + - s_ptr[ -9 ] * PredCoef[ 9 ] + - s_ptr[ -10 ] * PredCoef[ 10 ] + - s_ptr[ -11 ] * PredCoef[ 11 ]; - - /* prediction error */ - r_LPC[ix] = s_ptr[ 1 ] - LPC_pred; - } -} - -/* 10th order LPC analysis filter, does not write first 10 samples */ -void silk_LPC_analysis_filter10_FLP( - SKP_float r_LPC[], /* O LPC residual signal */ - const SKP_float PredCoef[], /* I LPC coefficients */ - const SKP_float s[], /* I Input signal */ - const opus_int length /* I Length of input signal */ -) -{ - opus_int ix; - SKP_float LPC_pred; - const SKP_float *s_ptr; - - for ( ix = 10; ix < length; ix++) { - s_ptr = &s[ix - 1]; - - /* short-term prediction */ - LPC_pred = s_ptr[ 0 ] * PredCoef[ 0 ] + - s_ptr[ -1 ] * PredCoef[ 1 ] + - s_ptr[ -2 ] * PredCoef[ 2 ] + - s_ptr[ -3 ] * PredCoef[ 3 ] + - s_ptr[ -4 ] * PredCoef[ 4 ] + - s_ptr[ -5 ] * PredCoef[ 5 ] + - s_ptr[ -6 ] * PredCoef[ 6 ] + - s_ptr[ -7 ] * PredCoef[ 7 ] + - s_ptr[ -8 ] * PredCoef[ 8 ] + - s_ptr[ -9 ] * PredCoef[ 9 ]; - - /* prediction error */ - r_LPC[ix] = s_ptr[ 1 ] - LPC_pred; - } -} - -/* 8th order LPC analysis filter, does not write first 8 samples */ -void silk_LPC_analysis_filter8_FLP( - SKP_float r_LPC[], /* O LPC residual signal */ - const SKP_float PredCoef[], /* I LPC coefficients */ - const SKP_float s[], /* I Input signal */ - const opus_int length /* I Length of input signal */ -) -{ - opus_int ix; - SKP_float LPC_pred; - const SKP_float *s_ptr; - - for ( ix = 8; ix < length; ix++) { - s_ptr = &s[ix - 1]; - - /* short-term prediction */ - LPC_pred = s_ptr[ 0 ] * PredCoef[ 0 ] + - s_ptr[ -1 ] * PredCoef[ 1 ] + - s_ptr[ -2 ] * PredCoef[ 2 ] + - s_ptr[ -3 ] * PredCoef[ 3 ] + - s_ptr[ -4 ] * PredCoef[ 4 ] + - s_ptr[ -5 ] * PredCoef[ 5 ] + - s_ptr[ -6 ] * PredCoef[ 6 ] + - s_ptr[ -7 ] * PredCoef[ 7 ]; - - /* prediction error */ - r_LPC[ix] = s_ptr[ 1 ] - LPC_pred; - } -} - -/* 6th order LPC analysis filter, does not write first 6 samples */ -void silk_LPC_analysis_filter6_FLP( - SKP_float r_LPC[], /* O LPC residual signal */ - const SKP_float PredCoef[], /* I LPC coefficients */ - const SKP_float s[], /* I Input signal */ - const opus_int length /* I Length of input signal */ -) -{ - opus_int ix; - SKP_float LPC_pred; - const SKP_float *s_ptr; - - for ( ix = 6; ix < length; ix++) { - s_ptr = &s[ix - 1]; - - /* short-term prediction */ - LPC_pred = s_ptr[ 0 ] * PredCoef[ 0 ] + - s_ptr[ -1 ] * PredCoef[ 1 ] + - s_ptr[ -2 ] * PredCoef[ 2 ] + - s_ptr[ -3 ] * PredCoef[ 3 ] + - s_ptr[ -4 ] * PredCoef[ 4 ] + - s_ptr[ -5 ] * PredCoef[ 5 ]; - - /* prediction error */ - r_LPC[ix] = s_ptr[ 1 ] - LPC_pred; - } -} - -/************************************************/ -/* LPC analysis filter */ -/* NB! State is kept internally and the */ -/* filter always starts with zero state */ -/* first Order output samples are set to zero */ -/************************************************/ - -void silk_LPC_analysis_filter_FLP( - SKP_float r_LPC[], /* O LPC residual signal */ - const SKP_float PredCoef[], /* I LPC coefficients */ - const SKP_float s[], /* I Input signal */ - const opus_int length, /* I Length of input signal */ - const opus_int Order /* I LPC order */ -) -{ - SKP_assert( Order <= length ); - - switch( Order ) { - case 6: - silk_LPC_analysis_filter6_FLP( r_LPC, PredCoef, s, length ); - break; - - case 8: - silk_LPC_analysis_filter8_FLP( r_LPC, PredCoef, s, length ); - break; - - case 10: - silk_LPC_analysis_filter10_FLP( r_LPC, PredCoef, s, length ); - break; - - case 12: - silk_LPC_analysis_filter12_FLP( r_LPC, PredCoef, s, length ); - break; - - case 14: - silk_LPC_analysis_filter14_FLP( r_LPC, PredCoef, s, length ); - break; - - case 16: - silk_LPC_analysis_filter16_FLP( r_LPC, PredCoef, s, length ); - break; - - default: - SKP_assert( 0 ); - break; - } - - /* Set first Order output samples to zero */ - SKP_memset( r_LPC, 0, Order * sizeof( SKP_float ) ); -} - +/*********************************************************************** +Copyright (c) 2006-2011, Skype Limited. All rights reserved. +Redistribution and use in source and binary forms, with or without +modification, (subject to the limitations in the disclaimer below) +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 Skype Limited, nor the names of specific +contributors, may be used to endorse or promote products derived from +this software without specific prior written permission. +NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED +BY THIS LICENSE. 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. +***********************************************************************/ + +#include <stdlib.h> +#include "silk_main_FLP.h" + +/************************************************/ +/* LPC analysis filter */ +/* NB! State is kept internally and the */ +/* filter always starts with zero state */ +/* first Order output samples are set to zero */ +/************************************************/ + +/* 16th order LPC analysis filter, does not write first 16 samples */ +void silk_LPC_analysis_filter16_FLP( + SKP_float r_LPC[], /* O LPC residual signal */ + const SKP_float PredCoef[], /* I LPC coefficients */ + const SKP_float s[], /* I Input signal */ + const opus_int length /* I Length of input signal */ +) +{ + opus_int ix; + SKP_float LPC_pred; + const SKP_float *s_ptr; + + for ( ix = 16; ix < length; ix++) { + s_ptr = &s[ix - 1]; + + /* short-term prediction */ + LPC_pred = s_ptr[ 0 ] * PredCoef[ 0 ] + + s_ptr[ -1 ] * PredCoef[ 1 ] + + s_ptr[ -2 ] * PredCoef[ 2 ] + + s_ptr[ -3 ] * PredCoef[ 3 ] + + s_ptr[ -4 ] * PredCoef[ 4 ] + + s_ptr[ -5 ] * PredCoef[ 5 ] + + s_ptr[ -6 ] * PredCoef[ 6 ] + + s_ptr[ -7 ] * PredCoef[ 7 ] + + s_ptr[ -8 ] * PredCoef[ 8 ] + + s_ptr[ -9 ] * PredCoef[ 9 ] + + s_ptr[ -10 ] * PredCoef[ 10 ] + + s_ptr[ -11 ] * PredCoef[ 11 ] + + s_ptr[ -12 ] * PredCoef[ 12 ] + + s_ptr[ -13 ] * PredCoef[ 13 ] + + s_ptr[ -14 ] * PredCoef[ 14 ] + + s_ptr[ -15 ] * PredCoef[ 15 ]; + + /* prediction error */ + r_LPC[ix] = s_ptr[ 1 ] - LPC_pred; + } +} + +/* 14th order LPC analysis filter, does not write first 14 samples */ +void silk_LPC_analysis_filter14_FLP( + SKP_float r_LPC[], /* O LPC residual signal */ + const SKP_float PredCoef[], /* I LPC coefficients */ + const SKP_float s[], /* I Input signal */ + const opus_int length /* I Length of input signal */ +) +{ + opus_int ix; + SKP_float LPC_pred; + const SKP_float *s_ptr; + + for ( ix = 14; ix < length; ix++) { + s_ptr = &s[ix - 1]; + + /* short-term prediction */ + LPC_pred = s_ptr[ 0 ] * PredCoef[ 0 ] + + s_ptr[ -1 ] * PredCoef[ 1 ] + + s_ptr[ -2 ] * PredCoef[ 2 ] + + s_ptr[ -3 ] * PredCoef[ 3 ] + + s_ptr[ -4 ] * PredCoef[ 4 ] + + s_ptr[ -5 ] * PredCoef[ 5 ] + + s_ptr[ -6 ] * PredCoef[ 6 ] + + s_ptr[ -7 ] * PredCoef[ 7 ] + + s_ptr[ -8 ] * PredCoef[ 8 ] + + s_ptr[ -9 ] * PredCoef[ 9 ] + + s_ptr[ -10 ] * PredCoef[ 10 ] + + s_ptr[ -11 ] * PredCoef[ 11 ] + + s_ptr[ -12 ] * PredCoef[ 12 ] + + s_ptr[ -13 ] * PredCoef[ 13 ]; + + /* prediction error */ + r_LPC[ix] = s_ptr[ 1 ] - LPC_pred; + } +} + +/* 12th order LPC analysis filter, does not write first 12 samples */ +void silk_LPC_analysis_filter12_FLP( + SKP_float r_LPC[], /* O LPC residual signal */ + const SKP_float PredCoef[], /* I LPC coefficients */ + const SKP_float s[], /* I Input signal */ + const opus_int length /* I Length of input signal */ +) +{ + opus_int ix; + SKP_float LPC_pred; + const SKP_float *s_ptr; + + for ( ix = 12; ix < length; ix++) { + s_ptr = &s[ix - 1]; + + /* short-term prediction */ + LPC_pred = s_ptr[ 0 ] * PredCoef[ 0 ] + + s_ptr[ -1 ] * PredCoef[ 1 ] + + s_ptr[ -2 ] * PredCoef[ 2 ] + + s_ptr[ -3 ] * PredCoef[ 3 ] + + s_ptr[ -4 ] * PredCoef[ 4 ] + + s_ptr[ -5 ] * PredCoef[ 5 ] + + s_ptr[ -6 ] * PredCoef[ 6 ] + + s_ptr[ -7 ] * PredCoef[ 7 ] + + s_ptr[ -8 ] * PredCoef[ 8 ] + + s_ptr[ -9 ] * PredCoef[ 9 ] + + s_ptr[ -10 ] * PredCoef[ 10 ] + + s_ptr[ -11 ] * PredCoef[ 11 ]; + + /* prediction error */ + r_LPC[ix] = s_ptr[ 1 ] - LPC_pred; + } +} + +/* 10th order LPC analysis filter, does not write first 10 samples */ +void silk_LPC_analysis_filter10_FLP( + SKP_float r_LPC[], /* O LPC residual signal */ + const SKP_float PredCoef[], /* I LPC coefficients */ + const SKP_float s[], /* I Input signal */ + const opus_int length /* I Length of input signal */ +) +{ + opus_int ix; + SKP_float LPC_pred; + const SKP_float *s_ptr; + + for ( ix = 10; ix < length; ix++) { + s_ptr = &s[ix - 1]; + + /* short-term prediction */ + LPC_pred = s_ptr[ 0 ] * PredCoef[ 0 ] + + s_ptr[ -1 ] * PredCoef[ 1 ] + + s_ptr[ -2 ] * PredCoef[ 2 ] + + s_ptr[ -3 ] * PredCoef[ 3 ] + + s_ptr[ -4 ] * PredCoef[ 4 ] + + s_ptr[ -5 ] * PredCoef[ 5 ] + + s_ptr[ -6 ] * PredCoef[ 6 ] + + s_ptr[ -7 ] * PredCoef[ 7 ] + + s_ptr[ -8 ] * PredCoef[ 8 ] + + s_ptr[ -9 ] * PredCoef[ 9 ]; + + /* prediction error */ + r_LPC[ix] = s_ptr[ 1 ] - LPC_pred; + } +} + +/* 8th order LPC analysis filter, does not write first 8 samples */ +void silk_LPC_analysis_filter8_FLP( + SKP_float r_LPC[], /* O LPC residual signal */ + const SKP_float PredCoef[], /* I LPC coefficients */ + const SKP_float s[], /* I Input signal */ + const opus_int length /* I Length of input signal */ +) +{ + opus_int ix; + SKP_float LPC_pred; + const SKP_float *s_ptr; + + for ( ix = 8; ix < length; ix++) { + s_ptr = &s[ix - 1]; + + /* short-term prediction */ + LPC_pred = s_ptr[ 0 ] * PredCoef[ 0 ] + + s_ptr[ -1 ] * PredCoef[ 1 ] + + s_ptr[ -2 ] * PredCoef[ 2 ] + + s_ptr[ -3 ] * PredCoef[ 3 ] + + s_ptr[ -4 ] * PredCoef[ 4 ] + + s_ptr[ -5 ] * PredCoef[ 5 ] + + s_ptr[ -6 ] * PredCoef[ 6 ] + + s_ptr[ -7 ] * PredCoef[ 7 ]; + + /* prediction error */ + r_LPC[ix] = s_ptr[ 1 ] - LPC_pred; + } +} + +/* 6th order LPC analysis filter, does not write first 6 samples */ +void silk_LPC_analysis_filter6_FLP( + SKP_float r_LPC[], /* O LPC residual signal */ + const SKP_float PredCoef[], /* I LPC coefficients */ + const SKP_float s[], /* I Input signal */ + const opus_int length /* I Length of input signal */ +) +{ + opus_int ix; + SKP_float LPC_pred; + const SKP_float *s_ptr; + + for ( ix = 6; ix < length; ix++) { + s_ptr = &s[ix - 1]; + + /* short-term prediction */ + LPC_pred = s_ptr[ 0 ] * PredCoef[ 0 ] + + s_ptr[ -1 ] * PredCoef[ 1 ] + + s_ptr[ -2 ] * PredCoef[ 2 ] + + s_ptr[ -3 ] * PredCoef[ 3 ] + + s_ptr[ -4 ] * PredCoef[ 4 ] + + s_ptr[ -5 ] * PredCoef[ 5 ]; + + /* prediction error */ + r_LPC[ix] = s_ptr[ 1 ] - LPC_pred; + } +} + +/************************************************/ +/* LPC analysis filter */ +/* NB! State is kept internally and the */ +/* filter always starts with zero state */ +/* first Order output samples are set to zero */ +/************************************************/ + +void silk_LPC_analysis_filter_FLP( + SKP_float r_LPC[], /* O LPC residual signal */ + const SKP_float PredCoef[], /* I LPC coefficients */ + const SKP_float s[], /* I Input signal */ + const opus_int length, /* I Length of input signal */ + const opus_int Order /* I LPC order */ +) +{ + SKP_assert( Order <= length ); + + switch( Order ) { + case 6: + silk_LPC_analysis_filter6_FLP( r_LPC, PredCoef, s, length ); + break; + + case 8: + silk_LPC_analysis_filter8_FLP( r_LPC, PredCoef, s, length ); + break; + + case 10: + silk_LPC_analysis_filter10_FLP( r_LPC, PredCoef, s, length ); + break; + + case 12: + silk_LPC_analysis_filter12_FLP( r_LPC, PredCoef, s, length ); + break; + + case 14: + silk_LPC_analysis_filter14_FLP( r_LPC, PredCoef, s, length ); + break; + + case 16: + silk_LPC_analysis_filter16_FLP( r_LPC, PredCoef, s, length ); + break; + + default: + SKP_assert( 0 ); + break; + } + + /* Set first Order output samples to zero */ + SKP_memset( r_LPC, 0, Order * sizeof( SKP_float ) ); +} + diff --git a/silk/float/silk_LPC_inv_pred_gain_FLP.c b/silk/float/silk_LPC_inv_pred_gain_FLP.c index 9e5a3c8c9..0e930a988 100644 --- a/silk/float/silk_LPC_inv_pred_gain_FLP.c +++ b/silk/float/silk_LPC_inv_pred_gain_FLP.c @@ -1,73 +1,73 @@ -/*********************************************************************** -Copyright (c) 2006-2011, Skype Limited. All rights reserved. -Redistribution and use in source and binary forms, with or without -modification, (subject to the limitations in the disclaimer below) -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 Skype Limited, nor the names of specific -contributors, may be used to endorse or promote products derived from -this software without specific prior written permission. -NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED -BY THIS LICENSE. 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. -***********************************************************************/ - -#include "silk_SigProc_FIX.h" -#include "silk_SigProc_FLP.h" - -#define RC_THRESHOLD 0.9999f - -/* 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 */ - SKP_float *invGain, /* O: inverse prediction gain, energy domain */ - const SKP_float *A, /* I: prediction coefficients [order] */ - opus_int32 order /* I: prediction order */ -) -{ - opus_int k, n; - double rc, rc_mult1, rc_mult2; - SKP_float Atmp[ 2 ][ SILK_MAX_ORDER_LPC ]; - SKP_float *Aold, *Anew; - - Anew = Atmp[ order & 1 ]; - SKP_memcpy( Anew, A, order * sizeof(SKP_float) ); - - *invGain = 1.0f; - for( k = order - 1; k > 0; k-- ) { - rc = -Anew[ k ]; - if (rc > RC_THRESHOLD || rc < -RC_THRESHOLD) { - return 1; - } - rc_mult1 = 1.0f - rc * rc; - rc_mult2 = 1.0f / rc_mult1; - *invGain *= (SKP_float)rc_mult1; - /* swap pointers */ - Aold = Anew; - Anew = Atmp[ k & 1 ]; - for( n = 0; n < k; n++ ) { - Anew[ n ] = (SKP_float)( ( Aold[ n ] - Aold[ k - n - 1 ] * rc ) * rc_mult2 ); - } - } - rc = -Anew[ 0 ]; - if ( rc > RC_THRESHOLD || rc < -RC_THRESHOLD ) { - return 1; - } - rc_mult1 = 1.0f - rc * rc; - *invGain *= (SKP_float)rc_mult1; - return 0; -} +/*********************************************************************** +Copyright (c) 2006-2011, Skype Limited. All rights reserved. +Redistribution and use in source and binary forms, with or without +modification, (subject to the limitations in the disclaimer below) +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 Skype Limited, nor the names of specific +contributors, may be used to endorse or promote products derived from +this software without specific prior written permission. +NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED +BY THIS LICENSE. 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. +***********************************************************************/ + +#include "silk_SigProc_FIX.h" +#include "silk_SigProc_FLP.h" + +#define RC_THRESHOLD 0.9999f + +/* 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 */ + SKP_float *invGain, /* O: inverse prediction gain, energy domain */ + const SKP_float *A, /* I: prediction coefficients [order] */ + opus_int32 order /* I: prediction order */ +) +{ + opus_int k, n; + double rc, rc_mult1, rc_mult2; + SKP_float Atmp[ 2 ][ SILK_MAX_ORDER_LPC ]; + SKP_float *Aold, *Anew; + + Anew = Atmp[ order & 1 ]; + SKP_memcpy( Anew, A, order * sizeof(SKP_float) ); + + *invGain = 1.0f; + for( k = order - 1; k > 0; k-- ) { + rc = -Anew[ k ]; + if (rc > RC_THRESHOLD || rc < -RC_THRESHOLD) { + return 1; + } + rc_mult1 = 1.0f - rc * rc; + rc_mult2 = 1.0f / rc_mult1; + *invGain *= (SKP_float)rc_mult1; + /* swap pointers */ + Aold = Anew; + Anew = Atmp[ k & 1 ]; + for( n = 0; n < k; n++ ) { + Anew[ n ] = (SKP_float)( ( Aold[ n ] - Aold[ k - n - 1 ] * rc ) * rc_mult2 ); + } + } + rc = -Anew[ 0 ]; + if ( rc > RC_THRESHOLD || rc < -RC_THRESHOLD ) { + return 1; + } + rc_mult1 = 1.0f - rc * rc; + *invGain *= (SKP_float)rc_mult1; + return 0; +} diff --git a/silk/float/silk_LTP_analysis_filter_FLP.c b/silk/float/silk_LTP_analysis_filter_FLP.c index 60d04ee9f..9db8e6a0b 100644 --- a/silk/float/silk_LTP_analysis_filter_FLP.c +++ b/silk/float/silk_LTP_analysis_filter_FLP.c @@ -1,71 +1,71 @@ -/*********************************************************************** -Copyright (c) 2006-2011, Skype Limited. All rights reserved. -Redistribution and use in source and binary forms, with or without -modification, (subject to the limitations in the disclaimer below) -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 Skype Limited, nor the names of specific -contributors, may be used to endorse or promote products derived from -this software without specific prior written permission. -NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED -BY THIS LICENSE. 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. -***********************************************************************/ - -#include "silk_main_FLP.h" - -void silk_LTP_analysis_filter_FLP( - SKP_float *LTP_res, /* O LTP res MAX_NB_SUBFR*(pre_lgth+subfr_lngth) */ - const SKP_float *x, /* I Input signal, with preceeding samples */ - const SKP_float B[ LTP_ORDER * MAX_NB_SUBFR ], /* I LTP coefficients for each subframe */ - const opus_int pitchL[ MAX_NB_SUBFR ], /* I Pitch lags */ - const SKP_float invGains[ MAX_NB_SUBFR ], /* I Inverse quantization gains */ - const opus_int subfr_length, /* I Length of each subframe */ - const opus_int nb_subfr, /* I number of subframes */ - const opus_int pre_length /* I Preceeding samples for each subframe */ -) -{ - const SKP_float *x_ptr, *x_lag_ptr; - SKP_float Btmp[ LTP_ORDER ]; - SKP_float *LTP_res_ptr; - SKP_float inv_gain; - opus_int k, i, j; - - x_ptr = x; - LTP_res_ptr = LTP_res; - for( k = 0; k < nb_subfr; k++ ) { - x_lag_ptr = x_ptr - pitchL[ k ]; - inv_gain = invGains[ k ]; - for( i = 0; i < LTP_ORDER; i++ ) { - Btmp[ i ] = B[ k * LTP_ORDER + i ]; - } - - /* LTP analysis FIR filter */ - for( i = 0; i < subfr_length + pre_length; i++ ) { - LTP_res_ptr[ i ] = x_ptr[ i ]; - /* Subtract long-term prediction */ - for( j = 0; j < LTP_ORDER; j++ ) { - LTP_res_ptr[ i ] -= Btmp[ j ] * x_lag_ptr[ LTP_ORDER / 2 - j ]; - } - LTP_res_ptr[ i ] *= inv_gain; - x_lag_ptr++; - } - - /* Update pointers */ - LTP_res_ptr += subfr_length + pre_length; - x_ptr += subfr_length; - } -} +/*********************************************************************** +Copyright (c) 2006-2011, Skype Limited. All rights reserved. +Redistribution and use in source and binary forms, with or without +modification, (subject to the limitations in the disclaimer below) +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 Skype Limited, nor the names of specific +contributors, may be used to endorse or promote products derived from +this software without specific prior written permission. +NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED +BY THIS LICENSE. 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. +***********************************************************************/ + +#include "silk_main_FLP.h" + +void silk_LTP_analysis_filter_FLP( + SKP_float *LTP_res, /* O LTP res MAX_NB_SUBFR*(pre_lgth+subfr_lngth) */ + const SKP_float *x, /* I Input signal, with preceeding samples */ + const SKP_float B[ LTP_ORDER * MAX_NB_SUBFR ], /* I LTP coefficients for each subframe */ + const opus_int pitchL[ MAX_NB_SUBFR ], /* I Pitch lags */ + const SKP_float invGains[ MAX_NB_SUBFR ], /* I Inverse quantization gains */ + const opus_int subfr_length, /* I Length of each subframe */ + const opus_int nb_subfr, /* I number of subframes */ + const opus_int pre_length /* I Preceeding samples for each subframe */ +) +{ + const SKP_float *x_ptr, *x_lag_ptr; + SKP_float Btmp[ LTP_ORDER ]; + SKP_float *LTP_res_ptr; + SKP_float inv_gain; + opus_int k, i, j; + + x_ptr = x; + LTP_res_ptr = LTP_res; + for( k = 0; k < nb_subfr; k++ ) { + x_lag_ptr = x_ptr - pitchL[ k ]; + inv_gain = invGains[ k ]; + for( i = 0; i < LTP_ORDER; i++ ) { + Btmp[ i ] = B[ k * LTP_ORDER + i ]; + } + + /* LTP analysis FIR filter */ + for( i = 0; i < subfr_length + pre_length; i++ ) { + LTP_res_ptr[ i ] = x_ptr[ i ]; + /* Subtract long-term prediction */ + for( j = 0; j < LTP_ORDER; j++ ) { + LTP_res_ptr[ i ] -= Btmp[ j ] * x_lag_ptr[ LTP_ORDER / 2 - j ]; + } + LTP_res_ptr[ i ] *= inv_gain; + x_lag_ptr++; + } + + /* Update pointers */ + LTP_res_ptr += subfr_length + pre_length; + x_ptr += subfr_length; + } +} diff --git a/silk/float/silk_LTP_scale_ctrl_FLP.c b/silk/float/silk_LTP_scale_ctrl_FLP.c index 6babea309..2803f5900 100644 --- a/silk/float/silk_LTP_scale_ctrl_FLP.c +++ b/silk/float/silk_LTP_scale_ctrl_FLP.c @@ -1,52 +1,52 @@ -/*********************************************************************** -Copyright (c) 2006-2011, Skype Limited. All rights reserved. -Redistribution and use in source and binary forms, with or without -modification, (subject to the limitations in the disclaimer below) -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 Skype Limited, nor the names of specific -contributors, may be used to endorse or promote products derived from -this software without specific prior written permission. -NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED -BY THIS LICENSE. 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. -***********************************************************************/ - -#include "silk_main_FLP.h" - -void silk_LTP_scale_ctrl_FLP( - silk_encoder_state_FLP *psEnc, /* I/O Encoder state FLP */ - silk_encoder_control_FLP *psEncCtrl /* I/O Encoder control 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 = SKP_max_float( psEncCtrl->LTPredCodGain - 0.5 * psEnc->prevLTPredCodGain, 0.0f ) - + 0.5f * psEnc->HPLTPredCodGain; - psEnc->prevLTPredCodGain = psEncCtrl->LTPredCodGain; - - /* Only scale if first frame in packet */ - if( psEnc->sCmn.nFramesEncoded == 0 ) { - round_loss = psEnc->sCmn.PacketLoss_perc + psEnc->sCmn.nFramesPerPacket; - psEnc->sCmn.indices.LTP_scaleIndex = (opus_int8)SKP_LIMIT( round_loss * psEnc->HPLTPredCodGain * 0.1f, 0.0f, 2.0f ); - } else { - /* Default is minimum scaling */ - psEnc->sCmn.indices.LTP_scaleIndex = 0; - } - psEncCtrl->LTP_scale = (SKP_float)silk_LTPScales_table_Q14[ psEnc->sCmn.indices.LTP_scaleIndex ] / 16384.0f; -} +/*********************************************************************** +Copyright (c) 2006-2011, Skype Limited. All rights reserved. +Redistribution and use in source and binary forms, with or without +modification, (subject to the limitations in the disclaimer below) +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 Skype Limited, nor the names of specific +contributors, may be used to endorse or promote products derived from +this software without specific prior written permission. +NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED +BY THIS LICENSE. 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. +***********************************************************************/ + +#include "silk_main_FLP.h" + +void silk_LTP_scale_ctrl_FLP( + silk_encoder_state_FLP *psEnc, /* I/O Encoder state FLP */ + silk_encoder_control_FLP *psEncCtrl /* I/O Encoder control 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 = SKP_max_float( psEncCtrl->LTPredCodGain - 0.5 * psEnc->prevLTPredCodGain, 0.0f ) + + 0.5f * psEnc->HPLTPredCodGain; + psEnc->prevLTPredCodGain = psEncCtrl->LTPredCodGain; + + /* Only scale if first frame in packet */ + if( psEnc->sCmn.nFramesEncoded == 0 ) { + round_loss = psEnc->sCmn.PacketLoss_perc + psEnc->sCmn.nFramesPerPacket; + psEnc->sCmn.indices.LTP_scaleIndex = (opus_int8)SKP_LIMIT( round_loss * psEnc->HPLTPredCodGain * 0.1f, 0.0f, 2.0f ); + } else { + /* Default is minimum scaling */ + psEnc->sCmn.indices.LTP_scaleIndex = 0; + } + psEncCtrl->LTP_scale = (SKP_float)silk_LTPScales_table_Q14[ psEnc->sCmn.indices.LTP_scaleIndex ] / 16384.0f; +} diff --git a/silk/float/silk_SigProc_FLP.h b/silk/float/silk_SigProc_FLP.h index ece5af292..b59b41b3d 100644 --- a/silk/float/silk_SigProc_FLP.h +++ b/silk/float/silk_SigProc_FLP.h @@ -1,219 +1,219 @@ -/*********************************************************************** -Copyright (c) 2006-2011, Skype Limited. All rights reserved. -Redistribution and use in source and binary forms, with or without -modification, (subject to the limitations in the disclaimer below) -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 Skype Limited, nor the names of specific -contributors, may be used to endorse or promote products derived from -this software without specific prior written permission. -NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED -BY THIS LICENSE. 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. -***********************************************************************/ - -#ifndef _SILK_SIGPROC_FLP_H_ -#define _SILK_SIGPROC_FLP_H_ - -#include "silk_SigProc_FIX.h" -#include <math.h> - -#ifdef __cplusplus -extern "C" -{ -#endif - -/********************************************************************/ -/* SIGNAL PROCESSING FUNCTIONS */ -/********************************************************************/ - -/* Chirp (bw expand) LP AR filter */ -void silk_bwexpander_FLP( - SKP_float *ar, /* io AR filter to be expanded (without leading 1) */ - const opus_int d, /* i length of ar */ - const SKP_float chirp /* i chirp factor (typically in range (0..1) ) */ -); - -/* 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 */ - SKP_float *invGain, /* O: inverse prediction gain, energy domain */ - const SKP_float *A, /* I: prediction coefficients [order] */ - opus_int32 order /* I: prediction order */ -); - -SKP_float silk_schur_FLP( /* O returns residual energy */ - SKP_float refl_coef[], /* O reflection coefficients (length order) */ - const SKP_float auto_corr[], /* I autocorrelation sequence (length order+1) */ - opus_int order /* I order */ -); - -void silk_k2a_FLP( - SKP_float *A, /* O: prediction coefficients [order] */ - const SKP_float *rc, /* I: reflection coefficients [order] */ - opus_int32 order /* I: prediction order */ -); - -/* Solve the normal equations using the Levinson-Durbin recursion */ -SKP_float silk_levinsondurbin_FLP( /* O prediction error energy */ - SKP_float A[], /* O prediction coefficients [order] */ - const SKP_float corr[], /* I input auto-correlations [order + 1] */ - const opus_int order /* I prediction order */ -); - -/* compute autocorrelation */ -void silk_autocorrelation_FLP( - SKP_float *results, /* o result (length correlationCount) */ - const SKP_float *inputData, /* i input data to correlate */ - opus_int inputDataSize, /* i length of input */ - opus_int correlationCount /* i number of correlation taps to compute */ -); - -/* Pitch estimator */ -#define SigProc_PE_MIN_COMPLEX 0 -#define SigProc_PE_MID_COMPLEX 1 -#define SigProc_PE_MAX_COMPLEX 2 - -opus_int silk_pitch_analysis_core_FLP( /* O voicing estimate: 0 voiced, 1 unvoiced */ - const SKP_float *signal, /* I signal of length PE_FRAME_LENGTH_MS*Fs_kHz */ - opus_int *pitch_out, /* O 4 pitch lag values */ - opus_int16 *lagIndex, /* O lag Index */ - opus_int8 *contourIndex, /* O pitch contour Index */ - SKP_float *LTPCorr, /* I/O normalized correlation; input: value from previous frame */ - opus_int prevLag, /* I last lag of previous frame; set to zero is unvoiced */ - const SKP_float search_thres1, /* I first stage threshold for lag candidates 0 - 1 */ - const SKP_float search_thres2, /* I final threshold for lag candidates 0 - 1 */ - const opus_int Fs_kHz, /* I sample frequency (kHz) */ - const opus_int complexity, /* I Complexity setting, 0-2, where 2 is highest */ - const opus_int nb_subfr /* I number of 5 ms subframes */ -); - -#define PI (3.1415926536f) - -void silk_insertion_sort_decreasing_FLP( - SKP_float *a, /* I/O: Unsorted / Sorted vector */ - opus_int *idx, /* O: Index vector for the sorted elements */ - const opus_int L, /* I: Vector length */ - const opus_int K /* I: Number of correctly sorted positions */ -); - -/* Compute reflection coefficients from input signal */ -SKP_float silk_burg_modified_FLP( /* O returns residual energy */ - SKP_float A[], /* O prediction coefficients (length order) */ - const SKP_float x[], /* I input signal, length: nb_subfr*(D+L_sub) */ - const opus_int subfr_length, /* I input signal subframe length (including D preceeding samples) */ - const opus_int nb_subfr, /* I number of subframes stacked in x */ - const SKP_float WhiteNoiseFrac, /* I fraction added to zero-lag autocorrelation */ - const opus_int D /* I order */ -); - -/* multiply a vector by a constant */ -void silk_scale_vector_FLP( - SKP_float *data1, - SKP_float gain, - opus_int dataSize -); - -/* copy and multiply a vector by a constant */ -void silk_scale_copy_vector_FLP( - SKP_float *data_out, - const SKP_float *data_in, - SKP_float gain, - opus_int dataSize -); - -/* inner product of two SKP_float arrays, with result as double */ -double silk_inner_product_FLP( - const SKP_float *data1, - const SKP_float *data2, - opus_int dataSize -); - -/* sum of squares of a SKP_float array, with result as double */ -double silk_energy_FLP( - const SKP_float *data, - opus_int dataSize -); - -/********************************************************************/ -/* MACROS */ -/********************************************************************/ - -#define SKP_min_float(a, b) (((a) < (b)) ? (a) : (b)) -#define SKP_max_float(a, b) (((a) > (b)) ? (a) : (b)) -#define SKP_abs_float(a) ((SKP_float)fabs(a)) - -#define SKP_LIMIT_float( a, limit1, limit2) ((limit1) > (limit2) ? ((a) > (limit1) ? (limit1) : ((a) < (limit2) ? (limit2) : (a))) \ - : ((a) > (limit2) ? (limit2) : ((a) < (limit1) ? (limit1) : (a)))) - -/* sigmoid function */ -SKP_INLINE SKP_float SKP_sigmoid(SKP_float x) -{ - return (SKP_float)(1.0 / (1.0 + exp(-x))); -} - -/* floating-point to integer conversion (rounding) */ -SKP_INLINE opus_int32 SKP_float2int(double x) -{ -#ifdef _WIN32 - double t = x + 6755399441055744.0; - return *((opus_int32 *)( &t )); -#else - return (opus_int32)( ( x > 0 ) ? x + 0.5 : x - 0.5 ); -#endif -} - -/* floating-point to integer conversion (rounding) */ -SKP_INLINE void SKP_float2short_array( - opus_int16 *out, - const SKP_float *in, - opus_int32 length -) -{ - opus_int32 k; - for (k = length-1; k >= 0; k--) { -#ifdef _WIN32 - double t = in[k] + 6755399441055744.0; - out[k] = (opus_int16)SKP_SAT16(*(( opus_int32 * )( &t ))); -#else - double x = in[k]; - out[k] = (opus_int16)SKP_SAT16( ( x > 0 ) ? x + 0.5 : x - 0.5 ); -#endif - } -} - -/* integer to floating-point conversion */ -SKP_INLINE void SKP_short2float_array( - SKP_float *out, - const opus_int16 *in, - opus_int32 length -) -{ - opus_int32 k; - for (k = length-1; k >= 0; k--) { - out[k] = (SKP_float)in[k]; - } -} - -/* using log2() helps the fixed-point conversion */ -SKP_INLINE SKP_float silk_log2( double x ) { return ( SKP_float )( 3.32192809488736 * log10( x ) ); } - -#ifdef __cplusplus -} -#endif - -#endif +/*********************************************************************** +Copyright (c) 2006-2011, Skype Limited. All rights reserved. +Redistribution and use in source and binary forms, with or without +modification, (subject to the limitations in the disclaimer below) +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 Skype Limited, nor the names of specific +contributors, may be used to endorse or promote products derived from +this software without specific prior written permission. +NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED +BY THIS LICENSE. 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. +***********************************************************************/ + +#ifndef _SILK_SIGPROC_FLP_H_ +#define _SILK_SIGPROC_FLP_H_ + +#include "silk_SigProc_FIX.h" +#include <math.h> + +#ifdef __cplusplus +extern "C" +{ +#endif + +/********************************************************************/ +/* SIGNAL PROCESSING FUNCTIONS */ +/********************************************************************/ + +/* Chirp (bw expand) LP AR filter */ +void silk_bwexpander_FLP( + SKP_float *ar, /* io AR filter to be expanded (without leading 1) */ + const opus_int d, /* i length of ar */ + const SKP_float chirp /* i chirp factor (typically in range (0..1) ) */ +); + +/* 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 */ + SKP_float *invGain, /* O: inverse prediction gain, energy domain */ + const SKP_float *A, /* I: prediction coefficients [order] */ + opus_int32 order /* I: prediction order */ +); + +SKP_float silk_schur_FLP( /* O returns residual energy */ + SKP_float refl_coef[], /* O reflection coefficients (length order) */ + const SKP_float auto_corr[], /* I autocorrelation sequence (length order+1) */ + opus_int order /* I order */ +); + +void silk_k2a_FLP( + SKP_float *A, /* O: prediction coefficients [order] */ + const SKP_float *rc, /* I: reflection coefficients [order] */ + opus_int32 order /* I: prediction order */ +); + +/* Solve the normal equations using the Levinson-Durbin recursion */ +SKP_float silk_levinsondurbin_FLP( /* O prediction error energy */ + SKP_float A[], /* O prediction coefficients [order] */ + const SKP_float corr[], /* I input auto-correlations [order + 1] */ + const opus_int order /* I prediction order */ +); + +/* compute autocorrelation */ +void silk_autocorrelation_FLP( + SKP_float *results, /* o result (length correlationCount) */ + const SKP_float *inputData, /* i input data to correlate */ + opus_int inputDataSize, /* i length of input */ + opus_int correlationCount /* i number of correlation taps to compute */ +); + +/* Pitch estimator */ +#define SigProc_PE_MIN_COMPLEX 0 +#define SigProc_PE_MID_COMPLEX 1 +#define SigProc_PE_MAX_COMPLEX 2 + +opus_int silk_pitch_analysis_core_FLP( /* O voicing estimate: 0 voiced, 1 unvoiced */ + const SKP_float *signal, /* I signal of length PE_FRAME_LENGTH_MS*Fs_kHz */ + opus_int *pitch_out, /* O 4 pitch lag values */ + opus_int16 *lagIndex, /* O lag Index */ + opus_int8 *contourIndex, /* O pitch contour Index */ + SKP_float *LTPCorr, /* I/O normalized correlation; input: value from previous frame */ + opus_int prevLag, /* I last lag of previous frame; set to zero is unvoiced */ + const SKP_float search_thres1, /* I first stage threshold for lag candidates 0 - 1 */ + const SKP_float search_thres2, /* I final threshold for lag candidates 0 - 1 */ + const opus_int Fs_kHz, /* I sample frequency (kHz) */ + const opus_int complexity, /* I Complexity setting, 0-2, where 2 is highest */ + const opus_int nb_subfr /* I number of 5 ms subframes */ +); + +#define PI (3.1415926536f) + +void silk_insertion_sort_decreasing_FLP( + SKP_float *a, /* I/O: Unsorted / Sorted vector */ + opus_int *idx, /* O: Index vector for the sorted elements */ + const opus_int L, /* I: Vector length */ + const opus_int K /* I: Number of correctly sorted positions */ +); + +/* Compute reflection coefficients from input signal */ +SKP_float silk_burg_modified_FLP( /* O returns residual energy */ + SKP_float A[], /* O prediction coefficients (length order) */ + const SKP_float x[], /* I input signal, length: nb_subfr*(D+L_sub) */ + const opus_int subfr_length, /* I input signal subframe length (including D preceeding samples) */ + const opus_int nb_subfr, /* I number of subframes stacked in x */ + const SKP_float WhiteNoiseFrac, /* I fraction added to zero-lag autocorrelation */ + const opus_int D /* I order */ +); + +/* multiply a vector by a constant */ +void silk_scale_vector_FLP( + SKP_float *data1, + SKP_float gain, + opus_int dataSize +); + +/* copy and multiply a vector by a constant */ +void silk_scale_copy_vector_FLP( + SKP_float *data_out, + const SKP_float *data_in, + SKP_float gain, + opus_int dataSize +); + +/* inner product of two SKP_float arrays, with result as double */ +double silk_inner_product_FLP( + const SKP_float *data1, + const SKP_float *data2, + opus_int dataSize +); + +/* sum of squares of a SKP_float array, with result as double */ +double silk_energy_FLP( + const SKP_float *data, + opus_int dataSize +); + +/********************************************************************/ +/* MACROS */ +/********************************************************************/ + +#define SKP_min_float(a, b) (((a) < (b)) ? (a) : (b)) +#define SKP_max_float(a, b) (((a) > (b)) ? (a) : (b)) +#define SKP_abs_float(a) ((SKP_float)fabs(a)) + +#define SKP_LIMIT_float( a, limit1, limit2) ((limit1) > (limit2) ? ((a) > (limit1) ? (limit1) : ((a) < (limit2) ? (limit2) : (a))) \ + : ((a) > (limit2) ? (limit2) : ((a) < (limit1) ? (limit1) : (a)))) + +/* sigmoid function */ +SKP_INLINE SKP_float SKP_sigmoid(SKP_float x) +{ + return (SKP_float)(1.0 / (1.0 + exp(-x))); +} + +/* floating-point to integer conversion (rounding) */ +SKP_INLINE opus_int32 SKP_float2int(double x) +{ +#ifdef _WIN32 + double t = x + 6755399441055744.0; + return *((opus_int32 *)( &t )); +#else + return (opus_int32)( ( x > 0 ) ? x + 0.5 : x - 0.5 ); +#endif +} + +/* floating-point to integer conversion (rounding) */ +SKP_INLINE void SKP_float2short_array( + opus_int16 *out, + const SKP_float *in, + opus_int32 length +) +{ + opus_int32 k; + for (k = length-1; k >= 0; k--) { +#ifdef _WIN32 + double t = in[k] + 6755399441055744.0; + out[k] = (opus_int16)SKP_SAT16(*(( opus_int32 * )( &t ))); +#else + double x = in[k]; + out[k] = (opus_int16)SKP_SAT16( ( x > 0 ) ? x + 0.5 : x - 0.5 ); +#endif + } +} + +/* integer to floating-point conversion */ +SKP_INLINE void SKP_short2float_array( + SKP_float *out, + const opus_int16 *in, + opus_int32 length +) +{ + opus_int32 k; + for (k = length-1; k >= 0; k--) { + out[k] = (SKP_float)in[k]; + } +} + +/* using log2() helps the fixed-point conversion */ +SKP_INLINE SKP_float silk_log2( double x ) { return ( SKP_float )( 3.32192809488736 * log10( x ) ); } + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/silk/float/silk_apply_sine_window_FLP.c b/silk/float/silk_apply_sine_window_FLP.c index e52075c1b..deee13ba2 100644 --- a/silk/float/silk_apply_sine_window_FLP.c +++ b/silk/float/silk_apply_sine_window_FLP.c @@ -1,77 +1,77 @@ -/*********************************************************************** -Copyright (c) 2006-2011, Skype Limited. All rights reserved. -Redistribution and use in source and binary forms, with or without -modification, (subject to the limitations in the disclaimer below) -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 Skype Limited, nor the names of specific -contributors, may be used to endorse or promote products derived from -this software without specific prior written permission. -NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED -BY THIS LICENSE. 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. -***********************************************************************/ - -#include "silk_main_FLP.h" - -/* Apply sine window to signal vector. */ -/* Window types: */ -/* 1 -> sine window from 0 to pi/2 */ -/* 2 -> sine window from pi/2 to pi */ -void silk_apply_sine_window_FLP( - SKP_float px_win[], /* O Pointer to windowed signal */ - const SKP_float px[], /* I Pointer to input signal */ - const opus_int win_type, /* I Selects a window type */ - const opus_int length /* I Window length, multiple of 4 */ -) -{ - opus_int k; - SKP_float freq, c, S0, S1; - - SKP_assert( win_type == 1 || win_type == 2 ); - - /* Length must be multiple of 4 */ - SKP_assert( ( length & 3 ) == 0 ); - - freq = PI / ( length + 1 ); - - /* Approximation of 2 * cos(f) */ - c = 2.0f - freq * freq; - - /* Initialize state */ - if( win_type < 2 ) { - /* Start from 0 */ - S0 = 0.0f; - /* Approximation of sin(f) */ - S1 = freq; - } else { - /* Start from 1 */ - S0 = 1.0f; - /* Approximation of cos(f) */ - S1 = 0.5f * c; - } - - /* Uses the recursive equation: sin(n*f) = 2 * cos(f) * sin((n-1)*f) - sin((n-2)*f) */ - /* 4 samples at a time */ - for( k = 0; k < length; k += 4 ) { - px_win[ k + 0 ] = px[ k + 0 ] * 0.5f * ( S0 + S1 ); - px_win[ k + 1 ] = px[ k + 1 ] * S1; - S0 = c * S1 - S0; - px_win[ k + 2 ] = px[ k + 2 ] * 0.5f * ( S1 + S0 ); - px_win[ k + 3 ] = px[ k + 3 ] * S0; - S1 = c * S0 - S1; - } -} +/*********************************************************************** +Copyright (c) 2006-2011, Skype Limited. All rights reserved. +Redistribution and use in source and binary forms, with or without +modification, (subject to the limitations in the disclaimer below) +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 Skype Limited, nor the names of specific +contributors, may be used to endorse or promote products derived from +this software without specific prior written permission. +NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED +BY THIS LICENSE. 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. +***********************************************************************/ + +#include "silk_main_FLP.h" + +/* Apply sine window to signal vector. */ +/* Window types: */ +/* 1 -> sine window from 0 to pi/2 */ +/* 2 -> sine window from pi/2 to pi */ +void silk_apply_sine_window_FLP( + SKP_float px_win[], /* O Pointer to windowed signal */ + const SKP_float px[], /* I Pointer to input signal */ + const opus_int win_type, /* I Selects a window type */ + const opus_int length /* I Window length, multiple of 4 */ +) +{ + opus_int k; + SKP_float freq, c, S0, S1; + + SKP_assert( win_type == 1 || win_type == 2 ); + + /* Length must be multiple of 4 */ + SKP_assert( ( length & 3 ) == 0 ); + + freq = PI / ( length + 1 ); + + /* Approximation of 2 * cos(f) */ + c = 2.0f - freq * freq; + + /* Initialize state */ + if( win_type < 2 ) { + /* Start from 0 */ + S0 = 0.0f; + /* Approximation of sin(f) */ + S1 = freq; + } else { + /* Start from 1 */ + S0 = 1.0f; + /* Approximation of cos(f) */ + S1 = 0.5f * c; + } + + /* Uses the recursive equation: sin(n*f) = 2 * cos(f) * sin((n-1)*f) - sin((n-2)*f) */ + /* 4 samples at a time */ + for( k = 0; k < length; k += 4 ) { + px_win[ k + 0 ] = px[ k + 0 ] * 0.5f * ( S0 + S1 ); + px_win[ k + 1 ] = px[ k + 1 ] * S1; + S0 = c * S1 - S0; + px_win[ k + 2 ] = px[ k + 2 ] * 0.5f * ( S1 + S0 ); + px_win[ k + 3 ] = px[ k + 3 ] * S0; + S1 = c * S0 - S1; + } +} diff --git a/silk/float/silk_autocorrelation_FLP.c b/silk/float/silk_autocorrelation_FLP.c index 991513c1d..b5f3951a0 100644 --- a/silk/float/silk_autocorrelation_FLP.c +++ b/silk/float/silk_autocorrelation_FLP.c @@ -1,48 +1,48 @@ -/*********************************************************************** -Copyright (c) 2006-2011, Skype Limited. All rights reserved. -Redistribution and use in source and binary forms, with or without -modification, (subject to the limitations in the disclaimer below) -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 Skype Limited, nor the names of specific -contributors, may be used to endorse or promote products derived from -this software without specific prior written permission. -NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED -BY THIS LICENSE. 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. -***********************************************************************/ - -#include "silk_typedef.h" -#include "silk_SigProc_FLP.h" - -/* compute autocorrelation */ -void silk_autocorrelation_FLP( - SKP_float *results, /* O result (length correlationCount) */ - const SKP_float *inputData, /* I input data to correlate */ - opus_int inputDataSize, /* I length of input */ - opus_int correlationCount /* I number of correlation taps to compute */ -) -{ - opus_int i; - - if ( correlationCount > inputDataSize ) { - correlationCount = inputDataSize; - } - - for( i = 0; i < correlationCount; i++ ) { - results[ i ] = (SKP_float)silk_inner_product_FLP( inputData, inputData + i, inputDataSize - i ); - } -} +/*********************************************************************** +Copyright (c) 2006-2011, Skype Limited. All rights reserved. +Redistribution and use in source and binary forms, with or without +modification, (subject to the limitations in the disclaimer below) +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 Skype Limited, nor the names of specific +contributors, may be used to endorse or promote products derived from +this software without specific prior written permission. +NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED +BY THIS LICENSE. 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. +***********************************************************************/ + +#include "silk_typedef.h" +#include "silk_SigProc_FLP.h" + +/* compute autocorrelation */ +void silk_autocorrelation_FLP( + SKP_float *results, /* O result (length correlationCount) */ + const SKP_float *inputData, /* I input data to correlate */ + opus_int inputDataSize, /* I length of input */ + opus_int correlationCount /* I number of correlation taps to compute */ +) +{ + opus_int i; + + if ( correlationCount > inputDataSize ) { + correlationCount = inputDataSize; + } + + for( i = 0; i < correlationCount; i++ ) { + results[ i ] = (SKP_float)silk_inner_product_FLP( inputData, inputData + i, inputDataSize - i ); + } +} diff --git a/silk/float/silk_burg_modified_FLP.c b/silk/float/silk_burg_modified_FLP.c index 622f06110..8d2861e54 100644 --- a/silk/float/silk_burg_modified_FLP.c +++ b/silk/float/silk_burg_modified_FLP.c @@ -1,144 +1,144 @@ -/*********************************************************************** -Copyright (c) 2006-2011, Skype Limited. All rights reserved. -Redistribution and use in source and binary forms, with or without -modification, (subject to the limitations in the disclaimer below) -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 Skype Limited, nor the names of specific -contributors, may be used to endorse or promote products derived from -this software without specific prior written permission. -NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED -BY THIS LICENSE. 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. -***********************************************************************/ - -#include "silk_SigProc_FLP.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 */ -SKP_float silk_burg_modified_FLP( /* O returns residual energy */ - SKP_float A[], /* O prediction coefficients (length order) */ - const SKP_float x[], /* I input signal, length: nb_subfr*(D+L_sub) */ - const opus_int subfr_length, /* I input signal subframe length (including D preceeding samples) */ - const opus_int nb_subfr, /* I number of subframes stacked in x */ - const SKP_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; - const SKP_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 ]; - - SKP_assert( subfr_length * nb_subfr <= MAX_FRAME_SIZE ); - SKP_assert( nb_subfr <= MAX_NB_SUBFR ); - - /* Compute autocorrelations, added over subframes */ - C0 = silk_energy_FLP( x, nb_subfr * subfr_length ); - SKP_memset( C_first_row, 0, SILK_MAX_ORDER_LPC * sizeof( double ) ); - for( s = 0; s < nb_subfr; s++ ) { - x_ptr = x + s * subfr_length; - for( n = 1; n < D + 1; n++ ) { - C_first_row[ n - 1 ] += silk_inner_product_FLP( x_ptr, x_ptr + n, subfr_length - n ); - } - } - SKP_memcpy( C_last_row, C_first_row, SILK_MAX_ORDER_LPC * sizeof( double ) ); - - /* Initialize */ - CAb[ 0 ] = CAf[ 0 ] = C0 + WhiteNoiseFrac * C0 + 1e-9f; - - 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) */ - /* Update C * Af */ - /* Update C * flipud(Af) (stored in reversed order) */ - for( s = 0; s < nb_subfr; s++ ) { - x_ptr = x + s * subfr_length; - tmp1 = x_ptr[ n ]; - tmp2 = x_ptr[ subfr_length - n - 1 ]; - for( k = 0; k < n; k++ ) { - C_first_row[ k ] -= x_ptr[ n ] * x_ptr[ n - k - 1 ]; - C_last_row[ k ] -= x_ptr[ subfr_length - n - 1 ] * x_ptr[ subfr_length - n + k ]; - Atmp = Af[ k ]; - tmp1 += x_ptr[ n - k - 1 ] * Atmp; - tmp2 += x_ptr[ subfr_length - n + k ] * Atmp; - } - for( k = 0; k <= n; k++ ) { - CAf[ k ] -= tmp1 * x_ptr[ n - k ]; - CAb[ k ] -= tmp2 * x_ptr[ subfr_length - n + k - 1 ]; - } - } - tmp1 = C_first_row[ n ]; - tmp2 = C_last_row[ n ]; - for( k = 0; k < n; k++ ) { - Atmp = Af[ k ]; - tmp1 += C_last_row[ n - k - 1 ] * Atmp; - tmp2 += C_first_row[ n - k - 1 ] * Atmp; - } - CAf[ n + 1 ] = tmp1; - CAb[ n + 1 ] = tmp2; - - /* Calculate nominator and denominator for the next order reflection (parcor) coefficient */ - num = CAb[ n + 1 ]; - nrg_b = CAb[ 0 ]; - nrg_f = CAf[ 0 ]; - for( k = 0; k < n; k++ ) { - Atmp = Af[ k ]; - num += CAb[ n - k ] * Atmp; - nrg_b += CAb[ k + 1 ] * Atmp; - nrg_f += CAf[ k + 1 ] * Atmp; - } - SKP_assert( nrg_f > 0.0 ); - SKP_assert( nrg_b > 0.0 ); - - /* Calculate the next order reflection (parcor) coefficient */ - rc = -2.0 * num / ( nrg_f + nrg_b ); - SKP_assert( rc > -1.0 && rc < 1.0 ); - - /* Update the AR coefficients */ - for( k = 0; k < (n + 1) >> 1; k++ ) { - tmp1 = Af[ k ]; - tmp2 = Af[ n - k - 1 ]; - Af[ k ] = tmp1 + rc * tmp2; - Af[ n - k - 1 ] = tmp2 + rc * tmp1; - } - Af[ n ] = rc; - - /* Update C * Af and C * Ab */ - for( k = 0; k <= n + 1; k++ ) { - tmp1 = CAf[ k ]; - CAf[ k ] += rc * CAb[ n - k + 1 ]; - CAb[ n - k + 1 ] += rc * tmp1; - } - } - - /* 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 ] = (SKP_float)(-Atmp); - } - nrg_f -= WhiteNoiseFrac * C0 * tmp1; - - return (SKP_float)nrg_f; -} +/*********************************************************************** +Copyright (c) 2006-2011, Skype Limited. All rights reserved. +Redistribution and use in source and binary forms, with or without +modification, (subject to the limitations in the disclaimer below) +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 Skype Limited, nor the names of specific +contributors, may be used to endorse or promote products derived from +this software without specific prior written permission. +NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED +BY THIS LICENSE. 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. +***********************************************************************/ + +#include "silk_SigProc_FLP.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 */ +SKP_float silk_burg_modified_FLP( /* O returns residual energy */ + SKP_float A[], /* O prediction coefficients (length order) */ + const SKP_float x[], /* I input signal, length: nb_subfr*(D+L_sub) */ + const opus_int subfr_length, /* I input signal subframe length (including D preceeding samples) */ + const opus_int nb_subfr, /* I number of subframes stacked in x */ + const SKP_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; + const SKP_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 ]; + + SKP_assert( subfr_length * nb_subfr <= MAX_FRAME_SIZE ); + SKP_assert( nb_subfr <= MAX_NB_SUBFR ); + + /* Compute autocorrelations, added over subframes */ + C0 = silk_energy_FLP( x, nb_subfr * subfr_length ); + SKP_memset( C_first_row, 0, SILK_MAX_ORDER_LPC * sizeof( double ) ); + for( s = 0; s < nb_subfr; s++ ) { + x_ptr = x + s * subfr_length; + for( n = 1; n < D + 1; n++ ) { + C_first_row[ n - 1 ] += silk_inner_product_FLP( x_ptr, x_ptr + n, subfr_length - n ); + } + } + SKP_memcpy( C_last_row, C_first_row, SILK_MAX_ORDER_LPC * sizeof( double ) ); + + /* Initialize */ + CAb[ 0 ] = CAf[ 0 ] = C0 + WhiteNoiseFrac * C0 + 1e-9f; + + 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) */ + /* Update C * Af */ + /* Update C * flipud(Af) (stored in reversed order) */ + for( s = 0; s < nb_subfr; s++ ) { + x_ptr = x + s * subfr_length; + tmp1 = x_ptr[ n ]; + tmp2 = x_ptr[ subfr_length - n - 1 ]; + for( k = 0; k < n; k++ ) { + C_first_row[ k ] -= x_ptr[ n ] * x_ptr[ n - k - 1 ]; + C_last_row[ k ] -= x_ptr[ subfr_length - n - 1 ] * x_ptr[ subfr_length - n + k ]; + Atmp = Af[ k ]; + tmp1 += x_ptr[ n - k - 1 ] * Atmp; + tmp2 += x_ptr[ subfr_length - n + k ] * Atmp; + } + for( k = 0; k <= n; k++ ) { + CAf[ k ] -= tmp1 * x_ptr[ n - k ]; + CAb[ k ] -= tmp2 * x_ptr[ subfr_length - n + k - 1 ]; + } + } + tmp1 = C_first_row[ n ]; + tmp2 = C_last_row[ n ]; + for( k = 0; k < n; k++ ) { + Atmp = Af[ k ]; + tmp1 += C_last_row[ n - k - 1 ] * Atmp; + tmp2 += C_first_row[ n - k - 1 ] * Atmp; + } + CAf[ n + 1 ] = tmp1; + CAb[ n + 1 ] = tmp2; + + /* Calculate nominator and denominator for the next order reflection (parcor) coefficient */ + num = CAb[ n + 1 ]; + nrg_b = CAb[ 0 ]; + nrg_f = CAf[ 0 ]; + for( k = 0; k < n; k++ ) { + Atmp = Af[ k ]; + num += CAb[ n - k ] * Atmp; + nrg_b += CAb[ k + 1 ] * Atmp; + nrg_f += CAf[ k + 1 ] * Atmp; + } + SKP_assert( nrg_f > 0.0 ); + SKP_assert( nrg_b > 0.0 ); + + /* Calculate the next order reflection (parcor) coefficient */ + rc = -2.0 * num / ( nrg_f + nrg_b ); + SKP_assert( rc > -1.0 && rc < 1.0 ); + + /* Update the AR coefficients */ + for( k = 0; k < (n + 1) >> 1; k++ ) { + tmp1 = Af[ k ]; + tmp2 = Af[ n - k - 1 ]; + Af[ k ] = tmp1 + rc * tmp2; + Af[ n - k - 1 ] = tmp2 + rc * tmp1; + } + Af[ n ] = rc; + + /* Update C * Af and C * Ab */ + for( k = 0; k <= n + 1; k++ ) { + tmp1 = CAf[ k ]; + CAf[ k ] += rc * CAb[ n - k + 1 ]; + CAb[ n - k + 1 ] += rc * tmp1; + } + } + + /* 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 ] = (SKP_float)(-Atmp); + } + nrg_f -= WhiteNoiseFrac * C0 * tmp1; + + return (SKP_float)nrg_f; +} diff --git a/silk/float/silk_bwexpander_FLP.c b/silk/float/silk_bwexpander_FLP.c index 55d1fddc2..964e392aa 100644 --- a/silk/float/silk_bwexpander_FLP.c +++ b/silk/float/silk_bwexpander_FLP.c @@ -1,47 +1,47 @@ -/*********************************************************************** -Copyright (c) 2006-2011, Skype Limited. All rights reserved. -Redistribution and use in source and binary forms, with or without -modification, (subject to the limitations in the disclaimer below) -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 Skype Limited, nor the names of specific -contributors, may be used to endorse or promote products derived from -this software without specific prior written permission. -NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED -BY THIS LICENSE. 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. -***********************************************************************/ - - -#include "silk_SigProc_FLP.h" - - -/* Chirp (bw expand) LP AR filter */ -void silk_bwexpander_FLP( - SKP_float *ar, /* I/O AR filter to be expanded (without leading 1) */ - const opus_int d, /* I length of ar */ - const SKP_float chirp /* I chirp factor (typically in range (0..1) ) */ -) -{ - opus_int i; - SKP_float cfac = chirp; - - for( i = 0; i < d - 1; i++ ) { - ar[ i ] *= cfac; - cfac *= chirp; - } - ar[ d - 1 ] *= cfac; -} +/*********************************************************************** +Copyright (c) 2006-2011, Skype Limited. All rights reserved. +Redistribution and use in source and binary forms, with or without +modification, (subject to the limitations in the disclaimer below) +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 Skype Limited, nor the names of specific +contributors, may be used to endorse or promote products derived from +this software without specific prior written permission. +NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED +BY THIS LICENSE. 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. +***********************************************************************/ + + +#include "silk_SigProc_FLP.h" + + +/* Chirp (bw expand) LP AR filter */ +void silk_bwexpander_FLP( + SKP_float *ar, /* I/O AR filter to be expanded (without leading 1) */ + const opus_int d, /* I length of ar */ + const SKP_float chirp /* I chirp factor (typically in range (0..1) ) */ +) +{ + opus_int i; + SKP_float cfac = chirp; + + for( i = 0; i < d - 1; i++ ) { + ar[ i ] *= cfac; + cfac *= chirp; + } + ar[ d - 1 ] *= cfac; +} diff --git a/silk/float/silk_corrMatrix_FLP.c b/silk/float/silk_corrMatrix_FLP.c index 2b396ee5d..5a75b08a1 100644 --- a/silk/float/silk_corrMatrix_FLP.c +++ b/silk/float/silk_corrMatrix_FLP.c @@ -1,89 +1,89 @@ -/*********************************************************************** -Copyright (c) 2006-2011, Skype Limited. All rights reserved. -Redistribution and use in source and binary forms, with or without -modification, (subject to the limitations in the disclaimer below) -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 Skype Limited, nor the names of specific -contributors, may be used to endorse or promote products derived from -this software without specific prior written permission. -NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED -BY THIS LICENSE. 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. -***********************************************************************/ - -/********************************************************************** - * Correlation matrix computations for LS estimate. - **********************************************************************/ - -#include "silk_main_FLP.h" - -/* Calculates correlation vector X'*t */ -void silk_corrVector_FLP( - const SKP_float *x, /* I x vector [L+order-1] used to create X */ - const SKP_float *t, /* I Target vector [L] */ - const opus_int L, /* I Length of vecors */ - const opus_int Order, /* I Max lag for correlation */ - SKP_float *Xt /* O X'*t correlation vector [order] */ -) -{ - opus_int lag; - const SKP_float *ptr1; - - ptr1 = &x[ Order - 1 ]; /* Points to first sample of column 0 of X: X[:,0] */ - for( lag = 0; lag < Order; lag++ ) { - /* Calculate X[:,lag]'*t */ - Xt[ lag ] = (SKP_float)silk_inner_product_FLP( ptr1, t, L ); - ptr1--; /* Next column of X */ - } -} - -/* Calculates correlation matrix X'*X */ -void silk_corrMatrix_FLP( - const SKP_float *x, /* I x vector [ L+order-1 ] used to create X */ - const opus_int L, /* I Length of vectors */ - const opus_int Order, /* I Max lag for correlation */ - SKP_float *XX /* O X'*X correlation matrix [order x order] */ -) -{ - opus_int j, lag; - double energy; - const SKP_float *ptr1, *ptr2; - - ptr1 = &x[ Order - 1 ]; /* First sample of column 0 of X */ - energy = silk_energy_FLP( ptr1, L ); /* X[:,0]'*X[:,0] */ - matrix_ptr( XX, 0, 0, Order ) = ( SKP_float )energy; - for( j = 1; j < Order; j++ ) { - /* Calculate X[:,j]'*X[:,j] */ - energy += ptr1[ -j ] * ptr1[ -j ] - ptr1[ L - j ] * ptr1[ L - j ]; - matrix_ptr( XX, j, j, Order ) = ( SKP_float )energy; - } - - ptr2 = &x[ Order - 2 ]; /* First sample of column 1 of X */ - for( lag = 1; lag < Order; lag++ ) { - /* Calculate X[:,0]'*X[:,lag] */ - energy = silk_inner_product_FLP( ptr1, ptr2, L ); - matrix_ptr( XX, lag, 0, Order ) = ( SKP_float )energy; - matrix_ptr( XX, 0, lag, Order ) = ( SKP_float )energy; - /* Calculate X[:,j]'*X[:,j + lag] */ - for( j = 1; j < ( Order - lag ); j++ ) { - energy += ptr1[ -j ] * ptr2[ -j ] - ptr1[ L - j ] * ptr2[ L - j ]; - matrix_ptr( XX, lag + j, j, Order ) = ( SKP_float )energy; - matrix_ptr( XX, j, lag + j, Order ) = ( SKP_float )energy; - } - ptr2--; /* Next column of X */ - } -} +/*********************************************************************** +Copyright (c) 2006-2011, Skype Limited. All rights reserved. +Redistribution and use in source and binary forms, with or without +modification, (subject to the limitations in the disclaimer below) +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 Skype Limited, nor the names of specific +contributors, may be used to endorse or promote products derived from +this software without specific prior written permission. +NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED +BY THIS LICENSE. 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. +***********************************************************************/ + +/********************************************************************** + * Correlation matrix computations for LS estimate. + **********************************************************************/ + +#include "silk_main_FLP.h" + +/* Calculates correlation vector X'*t */ +void silk_corrVector_FLP( + const SKP_float *x, /* I x vector [L+order-1] used to create X */ + const SKP_float *t, /* I Target vector [L] */ + const opus_int L, /* I Length of vecors */ + const opus_int Order, /* I Max lag for correlation */ + SKP_float *Xt /* O X'*t correlation vector [order] */ +) +{ + opus_int lag; + const SKP_float *ptr1; + + ptr1 = &x[ Order - 1 ]; /* Points to first sample of column 0 of X: X[:,0] */ + for( lag = 0; lag < Order; lag++ ) { + /* Calculate X[:,lag]'*t */ + Xt[ lag ] = (SKP_float)silk_inner_product_FLP( ptr1, t, L ); + ptr1--; /* Next column of X */ + } +} + +/* Calculates correlation matrix X'*X */ +void silk_corrMatrix_FLP( + const SKP_float *x, /* I x vector [ L+order-1 ] used to create X */ + const opus_int L, /* I Length of vectors */ + const opus_int Order, /* I Max lag for correlation */ + SKP_float *XX /* O X'*X correlation matrix [order x order] */ +) +{ + opus_int j, lag; + double energy; + const SKP_float *ptr1, *ptr2; + + ptr1 = &x[ Order - 1 ]; /* First sample of column 0 of X */ + energy = silk_energy_FLP( ptr1, L ); /* X[:,0]'*X[:,0] */ + matrix_ptr( XX, 0, 0, Order ) = ( SKP_float )energy; + for( j = 1; j < Order; j++ ) { + /* Calculate X[:,j]'*X[:,j] */ + energy += ptr1[ -j ] * ptr1[ -j ] - ptr1[ L - j ] * ptr1[ L - j ]; + matrix_ptr( XX, j, j, Order ) = ( SKP_float )energy; + } + + ptr2 = &x[ Order - 2 ]; /* First sample of column 1 of X */ + for( lag = 1; lag < Order; lag++ ) { + /* Calculate X[:,0]'*X[:,lag] */ + energy = silk_inner_product_FLP( ptr1, ptr2, L ); + matrix_ptr( XX, lag, 0, Order ) = ( SKP_float )energy; + matrix_ptr( XX, 0, lag, Order ) = ( SKP_float )energy; + /* Calculate X[:,j]'*X[:,j + lag] */ + for( j = 1; j < ( Order - lag ); j++ ) { + energy += ptr1[ -j ] * ptr2[ -j ] - ptr1[ L - j ] * ptr2[ L - j ]; + matrix_ptr( XX, lag + j, j, Order ) = ( SKP_float )energy; + matrix_ptr( XX, j, lag + j, Order ) = ( SKP_float )energy; + } + ptr2--; /* Next column of X */ + } +} diff --git a/silk/float/silk_encode_frame_FLP.c b/silk/float/silk_encode_frame_FLP.c index b2e73f7dc..cbcf4d84c 100644 --- a/silk/float/silk_encode_frame_FLP.c +++ b/silk/float/silk_encode_frame_FLP.c @@ -1,271 +1,271 @@ -/*********************************************************************** -Copyright (c) 2006-2011, Skype Limited. All rights reserved. -Redistribution and use in source and binary forms, with or without -modification, (subject to the limitations in the disclaimer below) -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 Skype Limited, nor the names of specific -contributors, may be used to endorse or promote products derived from -this software without specific prior written permission. -NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED -BY THIS LICENSE. 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. -***********************************************************************/ - -#include "silk_main_FLP.h" -#include "silk_tuning_parameters.h" - -/****************/ -/* Encode frame */ -/****************/ -opus_int silk_encode_frame_FLP( - silk_encoder_state_FLP *psEnc, /* I/O Encoder state FLP */ - opus_int32 *pnBytesOut, /* O Number of payload bytes */ - ec_enc *psRangeEnc /* I/O compressor data structure */ -) -{ - silk_encoder_control_FLP sEncCtrl; - opus_int i, ret = 0; - SKP_float *x_frame, *res_pitch_frame; - SKP_float xfw[ MAX_FRAME_LENGTH ]; - SKP_float res_pitch[ 2 * MAX_FRAME_LENGTH + LA_PITCH_MAX ]; - -TIC(ENCODE_FRAME) - - psEnc->sCmn.indices.Seed = psEnc->sCmn.frameCounter++ & 3; - - /**************************************************************/ - /* Setup 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 */ - - /****************************/ - /* Voice Activity Detection */ - /****************************/ -TIC(VAD) - ret = silk_VAD_GetSA_Q8( &psEnc->sCmn, psEnc->sCmn.inputBuf - 1 ); -TOC(VAD) - - /**************************************************/ - /* Convert speech activity into VAD and DTX flags */ - /**************************************************/ - if( psEnc->sCmn.nFramesEncoded == 0 ) { - psEnc->sCmn.inDTX = psEnc->sCmn.useDTX; - } - if( psEnc->sCmn.speech_activity_Q8 < SILK_FIX_CONST( SPEECH_ACTIVITY_DTX_THRES, 8 ) ) { - psEnc->sCmn.indices.signalType = TYPE_NO_VOICE_ACTIVITY; - psEnc->sCmn.noSpeechCounter++; - if( psEnc->sCmn.noSpeechCounter < NB_SPEECH_FRAMES_BEFORE_DTX ) { - psEnc->sCmn.inDTX = 0; - } else if( psEnc->sCmn.noSpeechCounter > MAX_CONSECUTIVE_DTX + NB_SPEECH_FRAMES_BEFORE_DTX ) { - psEnc->sCmn.noSpeechCounter = NB_SPEECH_FRAMES_BEFORE_DTX; - psEnc->sCmn.inDTX = 0; - } - psEnc->sCmn.VAD_flags[ psEnc->sCmn.nFramesEncoded ] = 0; - } else { - psEnc->sCmn.noSpeechCounter = 0; - psEnc->sCmn.inDTX = 0; - psEnc->sCmn.indices.signalType = TYPE_UNVOICED; - psEnc->sCmn.VAD_flags[ psEnc->sCmn.nFramesEncoded ] = 1; - } - - /***************************************/ - /* Ensure smooth bandwidth transitions */ - /***************************************/ - silk_LP_variable_cutoff( &psEnc->sCmn.sLP, psEnc->sCmn.inputBuf - 1, psEnc->sCmn.frame_length ); - - /*******************************************/ - /* Copy new frame to front of input buffer */ - /*******************************************/ - SKP_short2float_array( x_frame + LA_SHAPE_MS * psEnc->sCmn.fs_kHz, psEnc->sCmn.inputBuf - 1, psEnc->sCmn.frame_length ); - - /* Add tiny signal to avoid high CPU load from denormalized floating point numbers */ - for( i = 0; i < 8; i++ ) { - x_frame[ LA_SHAPE_MS * psEnc->sCmn.fs_kHz + i * ( psEnc->sCmn.frame_length >> 3 ) ] += ( 1 - ( i & 2 ) ) * 1e-6f; - } - - /*****************************************/ - /* Find pitch lags, initial LPC analysis */ - /*****************************************/ -TIC(FIND_PITCH) - silk_find_pitch_lags_FLP( psEnc, &sEncCtrl, res_pitch, x_frame ); -TOC(FIND_PITCH) - - /************************/ - /* Noise shape analysis */ - /************************/ -TIC(NOISE_SHAPE_ANALYSIS) - silk_noise_shape_analysis_FLP( psEnc, &sEncCtrl, res_pitch_frame, x_frame ); -TOC(NOISE_SHAPE_ANALYSIS) - - /***************************************************/ - /* Find linear prediction coefficients (LPC + LTP) */ - /***************************************************/ -TIC(FIND_PRED_COEF) - silk_find_pred_coefs_FLP( psEnc, &sEncCtrl, res_pitch, x_frame ); -TOC(FIND_PRED_COEF) - - /****************************************/ - /* Process gains */ - /****************************************/ -TIC(PROCESS_GAINS) - silk_process_gains_FLP( psEnc, &sEncCtrl ); -TOC(PROCESS_GAINS) - - /*****************************************/ - /* Prefiltering for noise shaper */ - /*****************************************/ -TIC(PREFILTER) - silk_prefilter_FLP( psEnc, &sEncCtrl, xfw, x_frame ); -TOC(PREFILTER) - - /****************************************/ - /* Low Bitrate Redundant Encoding */ - /****************************************/ -TIC(LBRR) - silk_LBRR_encode_FLP( psEnc, &sEncCtrl, xfw ); -TOC(LBRR) - - /*****************************************/ - /* Noise shaping quantization */ - /*****************************************/ -TIC(NSQ) - silk_NSQ_wrapper_FLP( psEnc, &sEncCtrl, &psEnc->sCmn.indices, &psEnc->sCmn.sNSQ, psEnc->sCmn.pulses, xfw ); -TOC(NSQ) - - /* Update input buffer */ - SKP_memmove( psEnc->x_buf, &psEnc->x_buf[ psEnc->sCmn.frame_length ], - ( psEnc->sCmn.ltp_mem_length + LA_SHAPE_MS * psEnc->sCmn.fs_kHz ) * sizeof( SKP_float ) ); - - /* Parameters needed for next frame */ - psEnc->sCmn.prevLag = sEncCtrl.pitchL[ psEnc->sCmn.nb_subfr - 1 ]; - psEnc->sCmn.prevSignalType = psEnc->sCmn.indices.signalType; - - /* Exit without entropy coding */ - if( psEnc->sCmn.prefillFlag ) { - /* No payload */ - *pnBytesOut = 0; - return ret; - } - - /****************************************/ - /* Encode Parameters */ - /****************************************/ -TIC(ENCODE_PARAMS) - silk_encode_indices( &psEnc->sCmn, psRangeEnc, psEnc->sCmn.nFramesEncoded, 0 ); -TOC(ENCODE_PARAMS) - - /****************************************/ - /* Encode Excitation Signal */ - /****************************************/ -TIC(ENCODE_PULSES) - silk_encode_pulses( psRangeEnc, psEnc->sCmn.indices.signalType, psEnc->sCmn.indices.quantOffsetType, - psEnc->sCmn.pulses, psEnc->sCmn.frame_length ); -TOC(ENCODE_PULSES) - - /****************************************/ - /* Finalize payload */ - /****************************************/ - psEnc->sCmn.first_frame_after_reset = 0; - if( ++psEnc->sCmn.nFramesEncoded >= psEnc->sCmn.nFramesPerPacket ) { - /* Payload size */ - *pnBytesOut = SKP_RSHIFT( ec_tell( psRangeEnc ) + 7, 3 ); - - /* Reset the number of frames in payload buffer */ - psEnc->sCmn.nFramesEncoded = 0; - } else { - /* No payload this time */ - *pnBytesOut = 0; - } -TOC(ENCODE_FRAME) - -#ifdef SAVE_ALL_INTERNAL_DATA - //DEBUG_STORE_DATA( xf.dat, pIn_HP_LP, psEnc->sCmn.frame_length * sizeof( opus_int16 ) ); - //DEBUG_STORE_DATA( xfw.dat, xfw, psEnc->sCmn.frame_length * sizeof( SKP_float ) ); - DEBUG_STORE_DATA( pitchL.dat, sEncCtrl.pitchL, MAX_NB_SUBFR * sizeof( opus_int ) ); - DEBUG_STORE_DATA( pitchG_quantized.dat, sEncCtrl.LTPCoef, psEnc->sCmn.nb_subfr * LTP_ORDER * sizeof( SKP_float ) ); - DEBUG_STORE_DATA( LTPcorr.dat, &psEnc->LTPCorr, sizeof( SKP_float ) ); - DEBUG_STORE_DATA( gains.dat, sEncCtrl.Gains, psEnc->sCmn.nb_subfr * sizeof( SKP_float ) ); - DEBUG_STORE_DATA( gains_indices.dat, &psEnc->sCmn.indices.GainsIndices, psEnc->sCmn.nb_subfr * sizeof( opus_int8 ) ); - DEBUG_STORE_DATA( quantOffsetType.dat, &psEnc->sCmn.indices.quantOffsetType, sizeof( opus_int8 ) ); - DEBUG_STORE_DATA( speech_activity_q8.dat, &psEnc->sCmn.speech_activity_Q8, sizeof( opus_int ) ); - DEBUG_STORE_DATA( signalType.dat, &psEnc->sCmn.indices.signalType, sizeof( opus_int8 ) ); - DEBUG_STORE_DATA( lag_index.dat, &psEnc->sCmn.indices.lagIndex, sizeof( opus_int16 ) ); - DEBUG_STORE_DATA( contour_index.dat, &psEnc->sCmn.indices.contourIndex, sizeof( opus_int8 ) ); - DEBUG_STORE_DATA( per_index.dat, &psEnc->sCmn.indices.PERIndex, sizeof( opus_int8 ) ); - DEBUG_STORE_DATA( PredCoef.dat, &sEncCtrl.PredCoef[ 1 ], psEnc->sCmn.predictLPCOrder * sizeof( SKP_float ) ); - DEBUG_STORE_DATA( ltp_scale_idx.dat, &psEnc->sCmn.indices.LTP_scaleIndex, sizeof( opus_int8 ) ); -// DEBUG_STORE_DATA( xq.dat, psEnc->sCmn.sNSQ.xqBuf, psEnc->sCmn.frame_length * sizeof( SKP_float ) ); -#endif - return ret; -} - -/* Low-Bitrate Redundancy (LBRR) encoding. Reuse all parameters but encode excitation at lower bitrate */ -void silk_LBRR_encode_FLP( - silk_encoder_state_FLP *psEnc, /* I/O Encoder state FLP */ - silk_encoder_control_FLP *psEncCtrl, /* I/O Encoder control FLP */ - const SKP_float xfw[] /* I Input signal */ -) -{ - opus_int k; - opus_int32 Gains_Q16[ MAX_NB_SUBFR ]; - SKP_float TempGains[ MAX_NB_SUBFR ]; - SideInfoIndices *psIndices_LBRR = &psEnc->sCmn.indices_LBRR[ psEnc->sCmn.nFramesEncoded ]; - silk_nsq_state sNSQ_LBRR; - - /*******************************************/ - /* Control use of inband LBRR */ - /*******************************************/ - if( psEnc->sCmn.LBRR_enabled && psEnc->sCmn.speech_activity_Q8 > SILK_FIX_CONST( LBRR_SPEECH_ACTIVITY_THRES, 8 ) ) { - psEnc->sCmn.LBRR_flags[ psEnc->sCmn.nFramesEncoded ] = 1; - - /* Copy noise shaping quantizer state and quantization indices from regular encoding */ - SKP_memcpy( &sNSQ_LBRR, &psEnc->sCmn.sNSQ, sizeof( silk_nsq_state ) ); - SKP_memcpy( psIndices_LBRR, &psEnc->sCmn.indices, sizeof( SideInfoIndices ) ); - - /* Save original gains */ - SKP_memcpy( TempGains, psEncCtrl->Gains, psEnc->sCmn.nb_subfr * sizeof( SKP_float ) ); - - if( psEnc->sCmn.nFramesEncoded == 0 || psEnc->sCmn.LBRR_flags[ psEnc->sCmn.nFramesEncoded - 1 ] == 0 ) { - /* First frame in packet or previous frame not LBRR coded */ - psEnc->sCmn.LBRRprevLastGainIndex = psEnc->sShape.LastGainIndex; - - /* Increase Gains to get target LBRR rate */ - psIndices_LBRR->GainsIndices[ 0 ] += psEnc->sCmn.LBRR_GainIncreases; - psIndices_LBRR->GainsIndices[ 0 ] = SKP_min_int( psIndices_LBRR->GainsIndices[ 0 ], N_LEVELS_QGAIN - 1 ); - } - - /* Decode to get gains in sync with decoder */ - silk_gains_dequant( Gains_Q16, psIndices_LBRR->GainsIndices, - &psEnc->sCmn.LBRRprevLastGainIndex, psEnc->sCmn.nFramesEncoded, psEnc->sCmn.nb_subfr ); - - /* Overwrite unquantized gains with quantized gains and convert back to Q0 from Q16 */ - for( k = 0; k < psEnc->sCmn.nb_subfr; k++ ) { - psEncCtrl->Gains[ k ] = Gains_Q16[ k ] * ( 1.0f / 65536.0f ); - } - - /*****************************************/ - /* Noise shaping quantization */ - /*****************************************/ - silk_NSQ_wrapper_FLP( psEnc, psEncCtrl, psIndices_LBRR, &sNSQ_LBRR, - psEnc->sCmn.pulses_LBRR[ psEnc->sCmn.nFramesEncoded ], xfw ); - - /* Restore original gains */ - SKP_memcpy( psEncCtrl->Gains, TempGains, psEnc->sCmn.nb_subfr * sizeof( SKP_float ) ); - } -} +/*********************************************************************** +Copyright (c) 2006-2011, Skype Limited. All rights reserved. +Redistribution and use in source and binary forms, with or without +modification, (subject to the limitations in the disclaimer below) +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 Skype Limited, nor the names of specific +contributors, may be used to endorse or promote products derived from +this software without specific prior written permission. +NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED +BY THIS LICENSE. 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. +***********************************************************************/ + +#include "silk_main_FLP.h" +#include "silk_tuning_parameters.h" + +/****************/ +/* Encode frame */ +/****************/ +opus_int silk_encode_frame_FLP( + silk_encoder_state_FLP *psEnc, /* I/O Encoder state FLP */ + opus_int32 *pnBytesOut, /* O Number of payload bytes */ + ec_enc *psRangeEnc /* I/O compressor data structure */ +) +{ + silk_encoder_control_FLP sEncCtrl; + opus_int i, ret = 0; + SKP_float *x_frame, *res_pitch_frame; + SKP_float xfw[ MAX_FRAME_LENGTH ]; + SKP_float res_pitch[ 2 * MAX_FRAME_LENGTH + LA_PITCH_MAX ]; + +TIC(ENCODE_FRAME) + + psEnc->sCmn.indices.Seed = psEnc->sCmn.frameCounter++ & 3; + + /**************************************************************/ + /* Setup 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 */ + + /****************************/ + /* Voice Activity Detection */ + /****************************/ +TIC(VAD) + ret = silk_VAD_GetSA_Q8( &psEnc->sCmn, psEnc->sCmn.inputBuf - 1 ); +TOC(VAD) + + /**************************************************/ + /* Convert speech activity into VAD and DTX flags */ + /**************************************************/ + if( psEnc->sCmn.nFramesEncoded == 0 ) { + psEnc->sCmn.inDTX = psEnc->sCmn.useDTX; + } + if( psEnc->sCmn.speech_activity_Q8 < SILK_FIX_CONST( SPEECH_ACTIVITY_DTX_THRES, 8 ) ) { + psEnc->sCmn.indices.signalType = TYPE_NO_VOICE_ACTIVITY; + psEnc->sCmn.noSpeechCounter++; + if( psEnc->sCmn.noSpeechCounter < NB_SPEECH_FRAMES_BEFORE_DTX ) { + psEnc->sCmn.inDTX = 0; + } else if( psEnc->sCmn.noSpeechCounter > MAX_CONSECUTIVE_DTX + NB_SPEECH_FRAMES_BEFORE_DTX ) { + psEnc->sCmn.noSpeechCounter = NB_SPEECH_FRAMES_BEFORE_DTX; + psEnc->sCmn.inDTX = 0; + } + psEnc->sCmn.VAD_flags[ psEnc->sCmn.nFramesEncoded ] = 0; + } else { + psEnc->sCmn.noSpeechCounter = 0; + psEnc->sCmn.inDTX = 0; + psEnc->sCmn.indices.signalType = TYPE_UNVOICED; + psEnc->sCmn.VAD_flags[ psEnc->sCmn.nFramesEncoded ] = 1; + } + + /***************************************/ + /* Ensure smooth bandwidth transitions */ + /***************************************/ + silk_LP_variable_cutoff( &psEnc->sCmn.sLP, psEnc->sCmn.inputBuf - 1, psEnc->sCmn.frame_length ); + + /*******************************************/ + /* Copy new frame to front of input buffer */ + /*******************************************/ + SKP_short2float_array( x_frame + LA_SHAPE_MS * psEnc->sCmn.fs_kHz, psEnc->sCmn.inputBuf - 1, psEnc->sCmn.frame_length ); + + /* Add tiny signal to avoid high CPU load from denormalized floating point numbers */ + for( i = 0; i < 8; i++ ) { + x_frame[ LA_SHAPE_MS * psEnc->sCmn.fs_kHz + i * ( psEnc->sCmn.frame_length >> 3 ) ] += ( 1 - ( i & 2 ) ) * 1e-6f; + } + + /*****************************************/ + /* Find pitch lags, initial LPC analysis */ + /*****************************************/ +TIC(FIND_PITCH) + silk_find_pitch_lags_FLP( psEnc, &sEncCtrl, res_pitch, x_frame ); +TOC(FIND_PITCH) + + /************************/ + /* Noise shape analysis */ + /************************/ +TIC(NOISE_SHAPE_ANALYSIS) + silk_noise_shape_analysis_FLP( psEnc, &sEncCtrl, res_pitch_frame, x_frame ); +TOC(NOISE_SHAPE_ANALYSIS) + + /***************************************************/ + /* Find linear prediction coefficients (LPC + LTP) */ + /***************************************************/ +TIC(FIND_PRED_COEF) + silk_find_pred_coefs_FLP( psEnc, &sEncCtrl, res_pitch, x_frame ); +TOC(FIND_PRED_COEF) + + /****************************************/ + /* Process gains */ + /****************************************/ +TIC(PROCESS_GAINS) + silk_process_gains_FLP( psEnc, &sEncCtrl ); +TOC(PROCESS_GAINS) + + /*****************************************/ + /* Prefiltering for noise shaper */ + /*****************************************/ +TIC(PREFILTER) + silk_prefilter_FLP( psEnc, &sEncCtrl, xfw, x_frame ); +TOC(PREFILTER) + + /****************************************/ + /* Low Bitrate Redundant Encoding */ + /****************************************/ +TIC(LBRR) + silk_LBRR_encode_FLP( psEnc, &sEncCtrl, xfw ); +TOC(LBRR) + + /*****************************************/ + /* Noise shaping quantization */ + /*****************************************/ +TIC(NSQ) + silk_NSQ_wrapper_FLP( psEnc, &sEncCtrl, &psEnc->sCmn.indices, &psEnc->sCmn.sNSQ, psEnc->sCmn.pulses, xfw ); +TOC(NSQ) + + /* Update input buffer */ + SKP_memmove( psEnc->x_buf, &psEnc->x_buf[ psEnc->sCmn.frame_length ], + ( psEnc->sCmn.ltp_mem_length + LA_SHAPE_MS * psEnc->sCmn.fs_kHz ) * sizeof( SKP_float ) ); + + /* Parameters needed for next frame */ + psEnc->sCmn.prevLag = sEncCtrl.pitchL[ psEnc->sCmn.nb_subfr - 1 ]; + psEnc->sCmn.prevSignalType = psEnc->sCmn.indices.signalType; + + /* Exit without entropy coding */ + if( psEnc->sCmn.prefillFlag ) { + /* No payload */ + *pnBytesOut = 0; + return ret; + } + + /****************************************/ + /* Encode Parameters */ + /****************************************/ +TIC(ENCODE_PARAMS) + silk_encode_indices( &psEnc->sCmn, psRangeEnc, psEnc->sCmn.nFramesEncoded, 0 ); +TOC(ENCODE_PARAMS) + + /****************************************/ + /* Encode Excitation Signal */ + /****************************************/ +TIC(ENCODE_PULSES) + silk_encode_pulses( psRangeEnc, psEnc->sCmn.indices.signalType, psEnc->sCmn.indices.quantOffsetType, + psEnc->sCmn.pulses, psEnc->sCmn.frame_length ); +TOC(ENCODE_PULSES) + + /****************************************/ + /* Finalize payload */ + /****************************************/ + psEnc->sCmn.first_frame_after_reset = 0; + if( ++psEnc->sCmn.nFramesEncoded >= psEnc->sCmn.nFramesPerPacket ) { + /* Payload size */ + *pnBytesOut = SKP_RSHIFT( ec_tell( psRangeEnc ) + 7, 3 ); + + /* Reset the number of frames in payload buffer */ + psEnc->sCmn.nFramesEncoded = 0; + } else { + /* No payload this time */ + *pnBytesOut = 0; + } +TOC(ENCODE_FRAME) + +#ifdef SAVE_ALL_INTERNAL_DATA + //DEBUG_STORE_DATA( xf.dat, pIn_HP_LP, psEnc->sCmn.frame_length * sizeof( opus_int16 ) ); + //DEBUG_STORE_DATA( xfw.dat, xfw, psEnc->sCmn.frame_length * sizeof( SKP_float ) ); + DEBUG_STORE_DATA( pitchL.dat, sEncCtrl.pitchL, MAX_NB_SUBFR * sizeof( opus_int ) ); + DEBUG_STORE_DATA( pitchG_quantized.dat, sEncCtrl.LTPCoef, psEnc->sCmn.nb_subfr * LTP_ORDER * sizeof( SKP_float ) ); + DEBUG_STORE_DATA( LTPcorr.dat, &psEnc->LTPCorr, sizeof( SKP_float ) ); + DEBUG_STORE_DATA( gains.dat, sEncCtrl.Gains, psEnc->sCmn.nb_subfr * sizeof( SKP_float ) ); + DEBUG_STORE_DATA( gains_indices.dat, &psEnc->sCmn.indices.GainsIndices, psEnc->sCmn.nb_subfr * sizeof( opus_int8 ) ); + DEBUG_STORE_DATA( quantOffsetType.dat, &psEnc->sCmn.indices.quantOffsetType, sizeof( opus_int8 ) ); + DEBUG_STORE_DATA( speech_activity_q8.dat, &psEnc->sCmn.speech_activity_Q8, sizeof( opus_int ) ); + DEBUG_STORE_DATA( signalType.dat, &psEnc->sCmn.indices.signalType, sizeof( opus_int8 ) ); + DEBUG_STORE_DATA( lag_index.dat, &psEnc->sCmn.indices.lagIndex, sizeof( opus_int16 ) ); + DEBUG_STORE_DATA( contour_index.dat, &psEnc->sCmn.indices.contourIndex, sizeof( opus_int8 ) ); + DEBUG_STORE_DATA( per_index.dat, &psEnc->sCmn.indices.PERIndex, sizeof( opus_int8 ) ); + DEBUG_STORE_DATA( PredCoef.dat, &sEncCtrl.PredCoef[ 1 ], psEnc->sCmn.predictLPCOrder * sizeof( SKP_float ) ); + DEBUG_STORE_DATA( ltp_scale_idx.dat, &psEnc->sCmn.indices.LTP_scaleIndex, sizeof( opus_int8 ) ); +// DEBUG_STORE_DATA( xq.dat, psEnc->sCmn.sNSQ.xqBuf, psEnc->sCmn.frame_length * sizeof( SKP_float ) ); +#endif + return ret; +} + +/* Low-Bitrate Redundancy (LBRR) encoding. Reuse all parameters but encode excitation at lower bitrate */ +void silk_LBRR_encode_FLP( + silk_encoder_state_FLP *psEnc, /* I/O Encoder state FLP */ + silk_encoder_control_FLP *psEncCtrl, /* I/O Encoder control FLP */ + const SKP_float xfw[] /* I Input signal */ +) +{ + opus_int k; + opus_int32 Gains_Q16[ MAX_NB_SUBFR ]; + SKP_float TempGains[ MAX_NB_SUBFR ]; + SideInfoIndices *psIndices_LBRR = &psEnc->sCmn.indices_LBRR[ psEnc->sCmn.nFramesEncoded ]; + silk_nsq_state sNSQ_LBRR; + + /*******************************************/ + /* Control use of inband LBRR */ + /*******************************************/ + if( psEnc->sCmn.LBRR_enabled && psEnc->sCmn.speech_activity_Q8 > SILK_FIX_CONST( LBRR_SPEECH_ACTIVITY_THRES, 8 ) ) { + psEnc->sCmn.LBRR_flags[ psEnc->sCmn.nFramesEncoded ] = 1; + + /* Copy noise shaping quantizer state and quantization indices from regular encoding */ + SKP_memcpy( &sNSQ_LBRR, &psEnc->sCmn.sNSQ, sizeof( silk_nsq_state ) ); + SKP_memcpy( psIndices_LBRR, &psEnc->sCmn.indices, sizeof( SideInfoIndices ) ); + + /* Save original gains */ + SKP_memcpy( TempGains, psEncCtrl->Gains, psEnc->sCmn.nb_subfr * sizeof( SKP_float ) ); + + if( psEnc->sCmn.nFramesEncoded == 0 || psEnc->sCmn.LBRR_flags[ psEnc->sCmn.nFramesEncoded - 1 ] == 0 ) { + /* First frame in packet or previous frame not LBRR coded */ + psEnc->sCmn.LBRRprevLastGainIndex = psEnc->sShape.LastGainIndex; + + /* Increase Gains to get target LBRR rate */ + psIndices_LBRR->GainsIndices[ 0 ] += psEnc->sCmn.LBRR_GainIncreases; + psIndices_LBRR->GainsIndices[ 0 ] = SKP_min_int( psIndices_LBRR->GainsIndices[ 0 ], N_LEVELS_QGAIN - 1 ); + } + + /* Decode to get gains in sync with decoder */ + silk_gains_dequant( Gains_Q16, psIndices_LBRR->GainsIndices, + &psEnc->sCmn.LBRRprevLastGainIndex, psEnc->sCmn.nFramesEncoded, psEnc->sCmn.nb_subfr ); + + /* Overwrite unquantized gains with quantized gains and convert back to Q0 from Q16 */ + for( k = 0; k < psEnc->sCmn.nb_subfr; k++ ) { + psEncCtrl->Gains[ k ] = Gains_Q16[ k ] * ( 1.0f / 65536.0f ); + } + + /*****************************************/ + /* Noise shaping quantization */ + /*****************************************/ + silk_NSQ_wrapper_FLP( psEnc, psEncCtrl, psIndices_LBRR, &sNSQ_LBRR, + psEnc->sCmn.pulses_LBRR[ psEnc->sCmn.nFramesEncoded ], xfw ); + + /* Restore original gains */ + SKP_memcpy( psEncCtrl->Gains, TempGains, psEnc->sCmn.nb_subfr * sizeof( SKP_float ) ); + } +} diff --git a/silk/float/silk_energy_FLP.c b/silk/float/silk_energy_FLP.c index 86b634127..1f4cf2ba8 100644 --- a/silk/float/silk_energy_FLP.c +++ b/silk/float/silk_energy_FLP.c @@ -1,56 +1,56 @@ -/*********************************************************************** -Copyright (c) 2006-2011, Skype Limited. All rights reserved. -Redistribution and use in source and binary forms, with or without -modification, (subject to the limitations in the disclaimer below) -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 Skype Limited, nor the names of specific -contributors, may be used to endorse or promote products derived from -this software without specific prior written permission. -NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED -BY THIS LICENSE. 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. -***********************************************************************/ - -#include "silk_SigProc_FLP.h" - -/* sum of squares of a SKP_float array, with result as double */ -double silk_energy_FLP( - const SKP_float *data, - opus_int dataSize -) -{ - opus_int i, dataSize4; - double result; - - /* 4x unrolled loop */ - result = 0.0f; - dataSize4 = dataSize & 0xFFFC; - for( i = 0; i < dataSize4; i += 4 ) { - result += data[ i + 0 ] * data[ i + 0 ] + - data[ i + 1 ] * data[ i + 1 ] + - data[ i + 2 ] * data[ i + 2 ] + - data[ i + 3 ] * data[ i + 3 ]; - } - - /* add any remaining products */ - for( ; i < dataSize; i++ ) { - result += data[ i ] * data[ i ]; - } - - SKP_assert( result >= 0.0 ); - return result; -} +/*********************************************************************** +Copyright (c) 2006-2011, Skype Limited. All rights reserved. +Redistribution and use in source and binary forms, with or without +modification, (subject to the limitations in the disclaimer below) +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 Skype Limited, nor the names of specific +contributors, may be used to endorse or promote products derived from +this software without specific prior written permission. +NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED +BY THIS LICENSE. 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. +***********************************************************************/ + +#include "silk_SigProc_FLP.h" + +/* sum of squares of a SKP_float array, with result as double */ +double silk_energy_FLP( + const SKP_float *data, + opus_int dataSize +) +{ + opus_int i, dataSize4; + double result; + + /* 4x unrolled loop */ + result = 0.0f; + dataSize4 = dataSize & 0xFFFC; + for( i = 0; i < dataSize4; i += 4 ) { + result += data[ i + 0 ] * data[ i + 0 ] + + data[ i + 1 ] * data[ i + 1 ] + + data[ i + 2 ] * data[ i + 2 ] + + data[ i + 3 ] * data[ i + 3 ]; + } + + /* add any remaining products */ + for( ; i < dataSize; i++ ) { + result += data[ i ] * data[ i ]; + } + + SKP_assert( result >= 0.0 ); + return result; +} diff --git a/silk/float/silk_find_LPC_FLP.c b/silk/float/silk_find_LPC_FLP.c index 23657e586..bac251ab9 100644 --- a/silk/float/silk_find_LPC_FLP.c +++ b/silk/float/silk_find_LPC_FLP.c @@ -1,109 +1,109 @@ -/*********************************************************************** -Copyright (c) 2006-2011, Skype Limited. All rights reserved. -Redistribution and use in source and binary forms, with or without -modification, (subject to the limitations in the disclaimer below) -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 Skype Limited, nor the names of specific -contributors, may be used to endorse or promote products derived from -this software without specific prior written permission. -NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED -BY THIS LICENSE. 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. -***********************************************************************/ - -#include "silk_main_FLP.h" -#include "silk_tuning_parameters.h" - -void silk_find_LPC_FLP( - 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 SKP_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 */ -) -{ - opus_int k; - SKP_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 ]; - SKP_float a_tmp[ MAX_LPC_ORDER ]; - SKP_float LPC_res[ ( MAX_FRAME_LENGTH + MAX_NB_SUBFR * MAX_LPC_ORDER ) / 2 ]; - - /* Default: No interpolation */ - *interpIndex = 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 ); - } - - if( useInterpNLSFs && !firstFrameAfterReset && 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 ); - - /* Convert to NLSFs */ - silk_A2NLSF_FLP( NLSF_Q15, a_tmp, LPC_order ); - - /* Search over interpolation indices to find the one with lowest residual energy */ - res_nrg_2nd = SKP_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 ); - - /* Convert to LPC for residual energy evaluation */ - silk_NLSF2A_FLP( a_tmp, NLSF0_Q15, LPC_order ); - - /* 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 ); - - /* 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; - } else if( res_nrg_interp > res_nrg_2nd ) { - /* No reason to continue iterating - residual energies will continue to climb */ - break; - } - res_nrg_2nd = res_nrg_interp; - } - } - - if( *interpIndex == 4 ) { - /* NLSF interpolation is currently inactive, calculate NLSFs from full frame AR coefficients */ - silk_A2NLSF_FLP( NLSF_Q15, a, LPC_order ); - } - - SKP_assert( *interpIndex == 4 || ( useInterpNLSFs && !firstFrameAfterReset && nb_subfr == MAX_NB_SUBFR ) ); -} +/*********************************************************************** +Copyright (c) 2006-2011, Skype Limited. All rights reserved. +Redistribution and use in source and binary forms, with or without +modification, (subject to the limitations in the disclaimer below) +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 Skype Limited, nor the names of specific +contributors, may be used to endorse or promote products derived from +this software without specific prior written permission. +NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED +BY THIS LICENSE. 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. +***********************************************************************/ + +#include "silk_main_FLP.h" +#include "silk_tuning_parameters.h" + +void silk_find_LPC_FLP( + 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 SKP_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 */ +) +{ + opus_int k; + SKP_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 ]; + SKP_float a_tmp[ MAX_LPC_ORDER ]; + SKP_float LPC_res[ ( MAX_FRAME_LENGTH + MAX_NB_SUBFR * MAX_LPC_ORDER ) / 2 ]; + + /* Default: No interpolation */ + *interpIndex = 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 ); + } + + if( useInterpNLSFs && !firstFrameAfterReset && 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 ); + + /* Convert to NLSFs */ + silk_A2NLSF_FLP( NLSF_Q15, a_tmp, LPC_order ); + + /* Search over interpolation indices to find the one with lowest residual energy */ + res_nrg_2nd = SKP_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 ); + + /* Convert to LPC for residual energy evaluation */ + silk_NLSF2A_FLP( a_tmp, NLSF0_Q15, LPC_order ); + + /* 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 ); + + /* 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; + } else if( res_nrg_interp > res_nrg_2nd ) { + /* No reason to continue iterating - residual energies will continue to climb */ + break; + } + res_nrg_2nd = res_nrg_interp; + } + } + + if( *interpIndex == 4 ) { + /* NLSF interpolation is currently inactive, calculate NLSFs from full frame AR coefficients */ + silk_A2NLSF_FLP( NLSF_Q15, a, LPC_order ); + } + + SKP_assert( *interpIndex == 4 || ( useInterpNLSFs && !firstFrameAfterReset && nb_subfr == MAX_NB_SUBFR ) ); +} diff --git a/silk/float/silk_find_LTP_FLP.c b/silk/float/silk_find_LTP_FLP.c index 97ab20b72..38811db2e 100644 --- a/silk/float/silk_find_LTP_FLP.c +++ b/silk/float/silk_find_LTP_FLP.c @@ -1,128 +1,128 @@ -/*********************************************************************** -Copyright (c) 2006-2011, Skype Limited. All rights reserved. -Redistribution and use in source and binary forms, with or without -modification, (subject to the limitations in the disclaimer below) -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 Skype Limited, nor the names of specific -contributors, may be used to endorse or promote products derived from -this software without specific prior written permission. -NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED -BY THIS LICENSE. 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. -***********************************************************************/ - -#include "silk_main_FLP.h" -#include "silk_tuning_parameters.h" - -void silk_find_LTP_FLP( - SKP_float b[ MAX_NB_SUBFR * LTP_ORDER ], /* O LTP coefs */ - SKP_float WLTP[ MAX_NB_SUBFR * LTP_ORDER * LTP_ORDER ], /* O Weight for LTP quantization */ - SKP_float *LTPredCodGain, /* O LTP coding gain */ - const SKP_float r_lpc[], /* I LPC residual */ - const opus_int lag[ MAX_NB_SUBFR ], /* I LTP lags */ - const SKP_float Wght[ MAX_NB_SUBFR ], /* I Weights */ - const opus_int subfr_length, /* I Subframe length */ - const opus_int nb_subfr, /* I number of subframes */ - const opus_int mem_offset /* I Number of samples in LTP memory */ -) -{ - opus_int i, k; - SKP_float *b_ptr, temp, *WLTP_ptr; - SKP_float LPC_res_nrg, LPC_LTP_res_nrg; - SKP_float d[ MAX_NB_SUBFR ], m, g, delta_b[ LTP_ORDER ]; - SKP_float w[ MAX_NB_SUBFR ], nrg[ MAX_NB_SUBFR ], regu; - SKP_float Rr[ LTP_ORDER ], rr[ MAX_NB_SUBFR ]; - const SKP_float *r_ptr, *lag_ptr; - - b_ptr = b; - WLTP_ptr = WLTP; - r_ptr = &r_lpc[ mem_offset ]; - for( k = 0; k < nb_subfr; k++ ) { - lag_ptr = r_ptr - ( lag[ k ] + LTP_ORDER / 2 ); - - silk_corrMatrix_FLP( lag_ptr, subfr_length, LTP_ORDER, WLTP_ptr ); - silk_corrVector_FLP( lag_ptr, r_ptr, subfr_length, LTP_ORDER, Rr ); - - rr[ k ] = ( SKP_float )silk_energy_FLP( r_ptr, subfr_length ); - regu = 1.0f + rr[ k ] + - matrix_ptr( WLTP_ptr, 0, 0, LTP_ORDER ) + - matrix_ptr( WLTP_ptr, LTP_ORDER-1, LTP_ORDER-1, LTP_ORDER ); - regu *= LTP_DAMPING / 3; - silk_regularize_correlations_FLP( WLTP_ptr, &rr[ k ], regu, LTP_ORDER ); - silk_solve_LDL_FLP( WLTP_ptr, LTP_ORDER, Rr, b_ptr ); - - /* Calculate residual energy */ - nrg[ k ] = silk_residual_energy_covar_FLP( b_ptr, WLTP_ptr, Rr, rr[ k ], LTP_ORDER ); - - temp = Wght[ k ] / ( nrg[ k ] * Wght[ k ] + 0.01f * subfr_length ); - silk_scale_vector_FLP( WLTP_ptr, temp, LTP_ORDER * LTP_ORDER ); - w[ k ] = matrix_ptr( WLTP_ptr, LTP_ORDER / 2, LTP_ORDER / 2, LTP_ORDER ); - - r_ptr += subfr_length; - b_ptr += LTP_ORDER; - WLTP_ptr += LTP_ORDER * LTP_ORDER; - } - - /* Compute LTP coding gain */ - if( LTPredCodGain != NULL ) { - LPC_LTP_res_nrg = 1e-6f; - LPC_res_nrg = 0.0f; - for( k = 0; k < nb_subfr; k++ ) { - LPC_res_nrg += rr[ k ] * Wght[ k ]; - LPC_LTP_res_nrg += nrg[ k ] * Wght[ k ]; - } - - SKP_assert( LPC_LTP_res_nrg > 0 ); - *LTPredCodGain = 3.0f * silk_log2( LPC_res_nrg / LPC_LTP_res_nrg ); - } - - /* Smoothing */ - /* d = sum( B, 1 ); */ - b_ptr = b; - for( k = 0; k < nb_subfr; k++ ) { - d[ k ] = 0; - for( i = 0; i < LTP_ORDER; i++ ) { - d[ k ] += b_ptr[ i ]; - } - b_ptr += LTP_ORDER; - } - /* m = ( w * d' ) / ( sum( w ) + 1e-3 ); */ - temp = 1e-3f; - for( k = 0; k < nb_subfr; k++ ) { - temp += w[ k ]; - } - m = 0; - for( k = 0; k < nb_subfr; k++ ) { - m += d[ k ] * w[ k ]; - } - m = m / temp; - - b_ptr = b; - for( k = 0; k < nb_subfr; k++ ) { - g = LTP_SMOOTHING / ( LTP_SMOOTHING + w[ k ] ) * ( m - d[ k ] ); - temp = 0; - for( i = 0; i < LTP_ORDER; i++ ) { - delta_b[ i ] = SKP_max_float( b_ptr[ i ], 0.1f ); - temp += delta_b[ i ]; - } - temp = g / temp; - for( i = 0; i < LTP_ORDER; i++ ) { - b_ptr[ i ] = b_ptr[ i ] + delta_b[ i ] * temp; - } - b_ptr += LTP_ORDER; - } -} +/*********************************************************************** +Copyright (c) 2006-2011, Skype Limited. All rights reserved. +Redistribution and use in source and binary forms, with or without +modification, (subject to the limitations in the disclaimer below) +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 Skype Limited, nor the names of specific +contributors, may be used to endorse or promote products derived from +this software without specific prior written permission. +NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED +BY THIS LICENSE. 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. +***********************************************************************/ + +#include "silk_main_FLP.h" +#include "silk_tuning_parameters.h" + +void silk_find_LTP_FLP( + SKP_float b[ MAX_NB_SUBFR * LTP_ORDER ], /* O LTP coefs */ + SKP_float WLTP[ MAX_NB_SUBFR * LTP_ORDER * LTP_ORDER ], /* O Weight for LTP quantization */ + SKP_float *LTPredCodGain, /* O LTP coding gain */ + const SKP_float r_lpc[], /* I LPC residual */ + const opus_int lag[ MAX_NB_SUBFR ], /* I LTP lags */ + const SKP_float Wght[ MAX_NB_SUBFR ], /* I Weights */ + const opus_int subfr_length, /* I Subframe length */ + const opus_int nb_subfr, /* I number of subframes */ + const opus_int mem_offset /* I Number of samples in LTP memory */ +) +{ + opus_int i, k; + SKP_float *b_ptr, temp, *WLTP_ptr; + SKP_float LPC_res_nrg, LPC_LTP_res_nrg; + SKP_float d[ MAX_NB_SUBFR ], m, g, delta_b[ LTP_ORDER ]; + SKP_float w[ MAX_NB_SUBFR ], nrg[ MAX_NB_SUBFR ], regu; + SKP_float Rr[ LTP_ORDER ], rr[ MAX_NB_SUBFR ]; + const SKP_float *r_ptr, *lag_ptr; + + b_ptr = b; + WLTP_ptr = WLTP; + r_ptr = &r_lpc[ mem_offset ]; + for( k = 0; k < nb_subfr; k++ ) { + lag_ptr = r_ptr - ( lag[ k ] + LTP_ORDER / 2 ); + + silk_corrMatrix_FLP( lag_ptr, subfr_length, LTP_ORDER, WLTP_ptr ); + silk_corrVector_FLP( lag_ptr, r_ptr, subfr_length, LTP_ORDER, Rr ); + + rr[ k ] = ( SKP_float )silk_energy_FLP( r_ptr, subfr_length ); + regu = 1.0f + rr[ k ] + + matrix_ptr( WLTP_ptr, 0, 0, LTP_ORDER ) + + matrix_ptr( WLTP_ptr, LTP_ORDER-1, LTP_ORDER-1, LTP_ORDER ); + regu *= LTP_DAMPING / 3; + silk_regularize_correlations_FLP( WLTP_ptr, &rr[ k ], regu, LTP_ORDER ); + silk_solve_LDL_FLP( WLTP_ptr, LTP_ORDER, Rr, b_ptr ); + + /* Calculate residual energy */ + nrg[ k ] = silk_residual_energy_covar_FLP( b_ptr, WLTP_ptr, Rr, rr[ k ], LTP_ORDER ); + + temp = Wght[ k ] / ( nrg[ k ] * Wght[ k ] + 0.01f * subfr_length ); + silk_scale_vector_FLP( WLTP_ptr, temp, LTP_ORDER * LTP_ORDER ); + w[ k ] = matrix_ptr( WLTP_ptr, LTP_ORDER / 2, LTP_ORDER / 2, LTP_ORDER ); + + r_ptr += subfr_length; + b_ptr += LTP_ORDER; + WLTP_ptr += LTP_ORDER * LTP_ORDER; + } + + /* Compute LTP coding gain */ + if( LTPredCodGain != NULL ) { + LPC_LTP_res_nrg = 1e-6f; + LPC_res_nrg = 0.0f; + for( k = 0; k < nb_subfr; k++ ) { + LPC_res_nrg += rr[ k ] * Wght[ k ]; + LPC_LTP_res_nrg += nrg[ k ] * Wght[ k ]; + } + + SKP_assert( LPC_LTP_res_nrg > 0 ); + *LTPredCodGain = 3.0f * silk_log2( LPC_res_nrg / LPC_LTP_res_nrg ); + } + + /* Smoothing */ + /* d = sum( B, 1 ); */ + b_ptr = b; + for( k = 0; k < nb_subfr; k++ ) { + d[ k ] = 0; + for( i = 0; i < LTP_ORDER; i++ ) { + d[ k ] += b_ptr[ i ]; + } + b_ptr += LTP_ORDER; + } + /* m = ( w * d' ) / ( sum( w ) + 1e-3 ); */ + temp = 1e-3f; + for( k = 0; k < nb_subfr; k++ ) { + temp += w[ k ]; + } + m = 0; + for( k = 0; k < nb_subfr; k++ ) { + m += d[ k ] * w[ k ]; + } + m = m / temp; + + b_ptr = b; + for( k = 0; k < nb_subfr; k++ ) { + g = LTP_SMOOTHING / ( LTP_SMOOTHING + w[ k ] ) * ( m - d[ k ] ); + temp = 0; + for( i = 0; i < LTP_ORDER; i++ ) { + delta_b[ i ] = SKP_max_float( b_ptr[ i ], 0.1f ); + temp += delta_b[ i ]; + } + temp = g / temp; + for( i = 0; i < LTP_ORDER; i++ ) { + b_ptr[ i ] = b_ptr[ i ] + delta_b[ i ] * temp; + } + b_ptr += LTP_ORDER; + } +} diff --git a/silk/float/silk_find_pitch_lags_FLP.c b/silk/float/silk_find_pitch_lags_FLP.c index 873c7e0b9..249578159 100644 --- a/silk/float/silk_find_pitch_lags_FLP.c +++ b/silk/float/silk_find_pitch_lags_FLP.c @@ -1,127 +1,127 @@ -/*********************************************************************** -Copyright (c) 2006-2011, Skype Limited. All rights reserved. -Redistribution and use in source and binary forms, with or without -modification, (subject to the limitations in the disclaimer below) -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 Skype Limited, nor the names of specific -contributors, may be used to endorse or promote products derived from -this software without specific prior written permission. -NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED -BY THIS LICENSE. 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. -***********************************************************************/ - -#include <stdlib.h> -#include "silk_main_FLP.h" -#include "silk_tuning_parameters.h" - -void silk_find_pitch_lags_FLP( - silk_encoder_state_FLP *psEnc, /* I/O Encoder state FLP */ - silk_encoder_control_FLP *psEncCtrl, /* I/O Encoder control FLP */ - SKP_float res[], /* O Residual */ - const SKP_float x[] /* I Speech signal */ -) -{ - opus_int buf_len; - SKP_float thrhld, res_nrg; - const SKP_float *x_buf_ptr, *x_buf; - SKP_float auto_corr[ MAX_FIND_PITCH_LPC_ORDER + 1 ]; - SKP_float A[ MAX_FIND_PITCH_LPC_ORDER ]; - SKP_float refl_coef[ MAX_FIND_PITCH_LPC_ORDER ]; - SKP_float Wsig[ FIND_PITCH_LPC_WIN_MAX ]; - SKP_float *Wsig_ptr; - - /******************************************/ - /* Setup buffer lengths etc based on Fs */ - /******************************************/ - buf_len = psEnc->sCmn.la_pitch + psEnc->sCmn.frame_length + psEnc->sCmn.ltp_mem_length; - - /* Safty check */ - SKP_assert( buf_len >= psEnc->sCmn.pitch_LPC_win_length ); - - x_buf = x - psEnc->sCmn.ltp_mem_length; - - /******************************************/ - /* Estimate LPC AR coeficients */ - /******************************************/ - - /* Calculate windowed signal */ - - /* First LA_LTP samples */ - x_buf_ptr = x_buf + buf_len - psEnc->sCmn.pitch_LPC_win_length; - Wsig_ptr = Wsig; - silk_apply_sine_window_FLP( Wsig_ptr, x_buf_ptr, 1, psEnc->sCmn.la_pitch ); - - /* Middle non-windowed samples */ - Wsig_ptr += psEnc->sCmn.la_pitch; - x_buf_ptr += psEnc->sCmn.la_pitch; - SKP_memcpy( Wsig_ptr, x_buf_ptr, ( psEnc->sCmn.pitch_LPC_win_length - ( psEnc->sCmn.la_pitch << 1 ) ) * sizeof( SKP_float ) ); - - /* Last LA_LTP samples */ - Wsig_ptr += psEnc->sCmn.pitch_LPC_win_length - ( psEnc->sCmn.la_pitch << 1 ); - x_buf_ptr += psEnc->sCmn.pitch_LPC_win_length - ( psEnc->sCmn.la_pitch << 1 ); - silk_apply_sine_window_FLP( Wsig_ptr, x_buf_ptr, 2, psEnc->sCmn.la_pitch ); - - /* Calculate autocorrelation sequence */ - silk_autocorrelation_FLP( auto_corr, Wsig, psEnc->sCmn.pitch_LPC_win_length, psEnc->sCmn.pitchEstimationLPCOrder + 1 ); - - /* Add white noise, as a fraction of the energy */ - auto_corr[ 0 ] += auto_corr[ 0 ] * FIND_PITCH_WHITE_NOISE_FRACTION + 1; - - /* Calculate the reflection coefficients using Schur */ - res_nrg = silk_schur_FLP( refl_coef, auto_corr, psEnc->sCmn.pitchEstimationLPCOrder ); - - /* Prediction gain */ - psEncCtrl->predGain = auto_corr[ 0 ] / SKP_max_float( res_nrg, 1.0f ); - - /* Convert reflection coefficients to prediction coefficients */ - silk_k2a_FLP( A, refl_coef, psEnc->sCmn.pitchEstimationLPCOrder ); - - /* Bandwidth expansion */ - silk_bwexpander_FLP( A, psEnc->sCmn.pitchEstimationLPCOrder, FIND_PITCH_BANDWITH_EXPANSION ); - - /*****************************************/ - /* LPC analysis filtering */ - /*****************************************/ - silk_LPC_analysis_filter_FLP( res, A, x_buf, buf_len, psEnc->sCmn.pitchEstimationLPCOrder ); - - if( psEnc->sCmn.indices.signalType != TYPE_NO_VOICE_ACTIVITY && psEnc->sCmn.first_frame_after_reset == 0 ) { - /* Threshold for pitch estimator */ - thrhld = 0.6f; - thrhld -= 0.004f * psEnc->sCmn.pitchEstimationLPCOrder; - thrhld -= 0.1f * psEnc->sCmn.speech_activity_Q8 * ( 1.0f / 256.0f ); - thrhld -= 0.15f * (psEnc->sCmn.prevSignalType >> 1); - thrhld -= 0.1f * psEnc->sCmn.input_tilt_Q15 * ( 1.0f / 32768.0f ); - - /*****************************************/ - /* Call Pitch estimator */ - /*****************************************/ - if( silk_pitch_analysis_core_FLP( res, psEncCtrl->pitchL, &psEnc->sCmn.indices.lagIndex, - &psEnc->sCmn.indices.contourIndex, &psEnc->LTPCorr, psEnc->sCmn.prevLag, psEnc->sCmn.pitchEstimationThreshold_Q16 / 65536.0f, - thrhld, psEnc->sCmn.fs_kHz, psEnc->sCmn.pitchEstimationComplexity, psEnc->sCmn.nb_subfr ) == 0 ) - { - psEnc->sCmn.indices.signalType = TYPE_VOICED; - } else { - psEnc->sCmn.indices.signalType = TYPE_UNVOICED; - } - } else { - SKP_memset( psEncCtrl->pitchL, 0, sizeof( psEncCtrl->pitchL ) ); - psEnc->sCmn.indices.lagIndex = 0; - psEnc->sCmn.indices.contourIndex = 0; - psEnc->LTPCorr = 0; - } -} +/*********************************************************************** +Copyright (c) 2006-2011, Skype Limited. All rights reserved. +Redistribution and use in source and binary forms, with or without +modification, (subject to the limitations in the disclaimer below) +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 Skype Limited, nor the names of specific +contributors, may be used to endorse or promote products derived from +this software without specific prior written permission. +NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED +BY THIS LICENSE. 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. +***********************************************************************/ + +#include <stdlib.h> +#include "silk_main_FLP.h" +#include "silk_tuning_parameters.h" + +void silk_find_pitch_lags_FLP( + silk_encoder_state_FLP *psEnc, /* I/O Encoder state FLP */ + silk_encoder_control_FLP *psEncCtrl, /* I/O Encoder control FLP */ + SKP_float res[], /* O Residual */ + const SKP_float x[] /* I Speech signal */ +) +{ + opus_int buf_len; + SKP_float thrhld, res_nrg; + const SKP_float *x_buf_ptr, *x_buf; + SKP_float auto_corr[ MAX_FIND_PITCH_LPC_ORDER + 1 ]; + SKP_float A[ MAX_FIND_PITCH_LPC_ORDER ]; + SKP_float refl_coef[ MAX_FIND_PITCH_LPC_ORDER ]; + SKP_float Wsig[ FIND_PITCH_LPC_WIN_MAX ]; + SKP_float *Wsig_ptr; + + /******************************************/ + /* Setup buffer lengths etc based on Fs */ + /******************************************/ + buf_len = psEnc->sCmn.la_pitch + psEnc->sCmn.frame_length + psEnc->sCmn.ltp_mem_length; + + /* Safty check */ + SKP_assert( buf_len >= psEnc->sCmn.pitch_LPC_win_length ); + + x_buf = x - psEnc->sCmn.ltp_mem_length; + + /******************************************/ + /* Estimate LPC AR coeficients */ + /******************************************/ + + /* Calculate windowed signal */ + + /* First LA_LTP samples */ + x_buf_ptr = x_buf + buf_len - psEnc->sCmn.pitch_LPC_win_length; + Wsig_ptr = Wsig; + silk_apply_sine_window_FLP( Wsig_ptr, x_buf_ptr, 1, psEnc->sCmn.la_pitch ); + + /* Middle non-windowed samples */ + Wsig_ptr += psEnc->sCmn.la_pitch; + x_buf_ptr += psEnc->sCmn.la_pitch; + SKP_memcpy( Wsig_ptr, x_buf_ptr, ( psEnc->sCmn.pitch_LPC_win_length - ( psEnc->sCmn.la_pitch << 1 ) ) * sizeof( SKP_float ) ); + + /* Last LA_LTP samples */ + Wsig_ptr += psEnc->sCmn.pitch_LPC_win_length - ( psEnc->sCmn.la_pitch << 1 ); + x_buf_ptr += psEnc->sCmn.pitch_LPC_win_length - ( psEnc->sCmn.la_pitch << 1 ); + silk_apply_sine_window_FLP( Wsig_ptr, x_buf_ptr, 2, psEnc->sCmn.la_pitch ); + + /* Calculate autocorrelation sequence */ + silk_autocorrelation_FLP( auto_corr, Wsig, psEnc->sCmn.pitch_LPC_win_length, psEnc->sCmn.pitchEstimationLPCOrder + 1 ); + + /* Add white noise, as a fraction of the energy */ + auto_corr[ 0 ] += auto_corr[ 0 ] * FIND_PITCH_WHITE_NOISE_FRACTION + 1; + + /* Calculate the reflection coefficients using Schur */ + res_nrg = silk_schur_FLP( refl_coef, auto_corr, psEnc->sCmn.pitchEstimationLPCOrder ); + + /* Prediction gain */ + psEncCtrl->predGain = auto_corr[ 0 ] / SKP_max_float( res_nrg, 1.0f ); + + /* Convert reflection coefficients to prediction coefficients */ + silk_k2a_FLP( A, refl_coef, psEnc->sCmn.pitchEstimationLPCOrder ); + + /* Bandwidth expansion */ + silk_bwexpander_FLP( A, psEnc->sCmn.pitchEstimationLPCOrder, FIND_PITCH_BANDWITH_EXPANSION ); + + /*****************************************/ + /* LPC analysis filtering */ + /*****************************************/ + silk_LPC_analysis_filter_FLP( res, A, x_buf, buf_len, psEnc->sCmn.pitchEstimationLPCOrder ); + + if( psEnc->sCmn.indices.signalType != TYPE_NO_VOICE_ACTIVITY && psEnc->sCmn.first_frame_after_reset == 0 ) { + /* Threshold for pitch estimator */ + thrhld = 0.6f; + thrhld -= 0.004f * psEnc->sCmn.pitchEstimationLPCOrder; + thrhld -= 0.1f * psEnc->sCmn.speech_activity_Q8 * ( 1.0f / 256.0f ); + thrhld -= 0.15f * (psEnc->sCmn.prevSignalType >> 1); + thrhld -= 0.1f * psEnc->sCmn.input_tilt_Q15 * ( 1.0f / 32768.0f ); + + /*****************************************/ + /* Call Pitch estimator */ + /*****************************************/ + if( silk_pitch_analysis_core_FLP( res, psEncCtrl->pitchL, &psEnc->sCmn.indices.lagIndex, + &psEnc->sCmn.indices.contourIndex, &psEnc->LTPCorr, psEnc->sCmn.prevLag, psEnc->sCmn.pitchEstimationThreshold_Q16 / 65536.0f, + thrhld, psEnc->sCmn.fs_kHz, psEnc->sCmn.pitchEstimationComplexity, psEnc->sCmn.nb_subfr ) == 0 ) + { + psEnc->sCmn.indices.signalType = TYPE_VOICED; + } else { + psEnc->sCmn.indices.signalType = TYPE_UNVOICED; + } + } else { + SKP_memset( psEncCtrl->pitchL, 0, sizeof( psEncCtrl->pitchL ) ); + psEnc->sCmn.indices.lagIndex = 0; + psEnc->sCmn.indices.contourIndex = 0; + psEnc->LTPCorr = 0; + } +} diff --git a/silk/float/silk_find_pred_coefs_FLP.c b/silk/float/silk_find_pred_coefs_FLP.c index e4be48ee5..2c2db929a 100644 --- a/silk/float/silk_find_pred_coefs_FLP.c +++ b/silk/float/silk_find_pred_coefs_FLP.c @@ -1,113 +1,113 @@ -/*********************************************************************** -Copyright (c) 2006-2011, Skype Limited. All rights reserved. -Redistribution and use in source and binary forms, with or without -modification, (subject to the limitations in the disclaimer below) -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 Skype Limited, nor the names of specific -contributors, may be used to endorse or promote products derived from -this software without specific prior written permission. -NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED -BY THIS LICENSE. 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. -***********************************************************************/ - -#include "silk_main_FLP.h" - - -void silk_find_pred_coefs_FLP( - silk_encoder_state_FLP *psEnc, /* I/O Encoder state FLP */ - silk_encoder_control_FLP *psEncCtrl, /* I/O Encoder control FLP */ - const SKP_float res_pitch[], /* I Residual from pitch analysis */ - const SKP_float x[] /* I Speech signal */ -) -{ - opus_int i; - SKP_float WLTP[ MAX_NB_SUBFR * LTP_ORDER * LTP_ORDER ]; - SKP_float invGains[ MAX_NB_SUBFR ], Wght[ MAX_NB_SUBFR ]; - opus_int16 NLSF_Q15[ MAX_LPC_ORDER ]; - const SKP_float *x_ptr; - SKP_float *x_pre_ptr, LPC_in_pre[ MAX_NB_SUBFR * MAX_LPC_ORDER + MAX_FRAME_LENGTH ]; - - /* Weighting for weighted least squares */ - for( i = 0; i < psEnc->sCmn.nb_subfr; i++ ) { - SKP_assert( psEncCtrl->Gains[ i ] > 0.0f ); - invGains[ i ] = 1.0f / psEncCtrl->Gains[ i ]; - Wght[ i ] = invGains[ i ] * invGains[ i ]; - } - - if( psEnc->sCmn.indices.signalType == TYPE_VOICED ) { - /**********/ - /* VOICED */ - /**********/ - SKP_assert( psEnc->sCmn.ltp_mem_length - psEnc->sCmn.predictLPCOrder >= psEncCtrl->pitchL[ 0 ] + LTP_ORDER / 2 ); - - /* LTP analysis */ - silk_find_LTP_FLP( psEncCtrl->LTPCoef, WLTP, &psEncCtrl->LTPredCodGain, res_pitch, - psEncCtrl->pitchL, Wght, psEnc->sCmn.subfr_length, psEnc->sCmn.nb_subfr, psEnc->sCmn.ltp_mem_length ); - -#ifdef SAVE_ALL_INTERNAL_DATA - DEBUG_STORE_DATA( ltp_gains.dat, psEncCtrl->LTPCoef, sizeof( psEncCtrl->LTPCoef ) ); - DEBUG_STORE_DATA( ltp_weights.dat, WLTP, sizeof( WLTP ) ); -#endif - - /* Quantize LTP gain parameters */ - silk_quant_LTP_gains_FLP( psEncCtrl->LTPCoef, psEnc->sCmn.indices.LTPIndex, &psEnc->sCmn.indices.PERIndex, - WLTP, psEnc->sCmn.mu_LTP_Q9, psEnc->sCmn.LTPQuantLowComplexity, psEnc->sCmn.nb_subfr ); - - /* Control LTP scaling */ - silk_LTP_scale_ctrl_FLP( psEnc, psEncCtrl ); - - /* 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 */ - /************/ - /* Create signal with prepended subframes, scaled by inverse gains */ - x_ptr = x - psEnc->sCmn.predictLPCOrder; - x_pre_ptr = LPC_in_pre; - for( i = 0; i < psEnc->sCmn.nb_subfr; i++ ) { - silk_scale_copy_vector_FLP( x_pre_ptr, x_ptr, invGains[ i ], - psEnc->sCmn.subfr_length + psEnc->sCmn.predictLPCOrder ); - x_pre_ptr += psEnc->sCmn.subfr_length + psEnc->sCmn.predictLPCOrder; - x_ptr += psEnc->sCmn.subfr_length; - } - - SKP_memset( psEncCtrl->LTPCoef, 0, psEnc->sCmn.nb_subfr * LTP_ORDER * sizeof( SKP_float ) ); - psEncCtrl->LTPredCodGain = 0.0f; - } - - /* 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 ); - - /* Quantize LSFs */ -TIC(LSF_quant); - silk_process_NLSFs_FLP( &psEnc->sCmn, psEncCtrl->PredCoef, NLSF_Q15, psEnc->sCmn.prev_NLSFq_Q15 ); -TOC(LSF_quant); - - /* Calculate residual energy using quantized LPC coefficients */ - silk_residual_energy_FLP( psEncCtrl->ResNrg, LPC_in_pre, psEncCtrl->PredCoef, psEncCtrl->Gains, - psEnc->sCmn.subfr_length, psEnc->sCmn.nb_subfr, psEnc->sCmn.predictLPCOrder ); - - /* Copy to prediction struct for use in next frame for fluctuation reduction */ - SKP_memcpy( psEnc->sCmn.prev_NLSFq_Q15, NLSF_Q15, sizeof( psEnc->sCmn.prev_NLSFq_Q15 ) ); -} - +/*********************************************************************** +Copyright (c) 2006-2011, Skype Limited. All rights reserved. +Redistribution and use in source and binary forms, with or without +modification, (subject to the limitations in the disclaimer below) +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 Skype Limited, nor the names of specific +contributors, may be used to endorse or promote products derived from +this software without specific prior written permission. +NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED +BY THIS LICENSE. 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. +***********************************************************************/ + +#include "silk_main_FLP.h" + + +void silk_find_pred_coefs_FLP( + silk_encoder_state_FLP *psEnc, /* I/O Encoder state FLP */ + silk_encoder_control_FLP *psEncCtrl, /* I/O Encoder control FLP */ + const SKP_float res_pitch[], /* I Residual from pitch analysis */ + const SKP_float x[] /* I Speech signal */ +) +{ + opus_int i; + SKP_float WLTP[ MAX_NB_SUBFR * LTP_ORDER * LTP_ORDER ]; + SKP_float invGains[ MAX_NB_SUBFR ], Wght[ MAX_NB_SUBFR ]; + opus_int16 NLSF_Q15[ MAX_LPC_ORDER ]; + const SKP_float *x_ptr; + SKP_float *x_pre_ptr, LPC_in_pre[ MAX_NB_SUBFR * MAX_LPC_ORDER + MAX_FRAME_LENGTH ]; + + /* Weighting for weighted least squares */ + for( i = 0; i < psEnc->sCmn.nb_subfr; i++ ) { + SKP_assert( psEncCtrl->Gains[ i ] > 0.0f ); + invGains[ i ] = 1.0f / psEncCtrl->Gains[ i ]; + Wght[ i ] = invGains[ i ] * invGains[ i ]; + } + + if( psEnc->sCmn.indices.signalType == TYPE_VOICED ) { + /**********/ + /* VOICED */ + /**********/ + SKP_assert( psEnc->sCmn.ltp_mem_length - psEnc->sCmn.predictLPCOrder >= psEncCtrl->pitchL[ 0 ] + LTP_ORDER / 2 ); + + /* LTP analysis */ + silk_find_LTP_FLP( psEncCtrl->LTPCoef, WLTP, &psEncCtrl->LTPredCodGain, res_pitch, + psEncCtrl->pitchL, Wght, psEnc->sCmn.subfr_length, psEnc->sCmn.nb_subfr, psEnc->sCmn.ltp_mem_length ); + +#ifdef SAVE_ALL_INTERNAL_DATA + DEBUG_STORE_DATA( ltp_gains.dat, psEncCtrl->LTPCoef, sizeof( psEncCtrl->LTPCoef ) ); + DEBUG_STORE_DATA( ltp_weights.dat, WLTP, sizeof( WLTP ) ); +#endif + + /* Quantize LTP gain parameters */ + silk_quant_LTP_gains_FLP( psEncCtrl->LTPCoef, psEnc->sCmn.indices.LTPIndex, &psEnc->sCmn.indices.PERIndex, + WLTP, psEnc->sCmn.mu_LTP_Q9, psEnc->sCmn.LTPQuantLowComplexity, psEnc->sCmn.nb_subfr ); + + /* Control LTP scaling */ + silk_LTP_scale_ctrl_FLP( psEnc, psEncCtrl ); + + /* 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 */ + /************/ + /* Create signal with prepended subframes, scaled by inverse gains */ + x_ptr = x - psEnc->sCmn.predictLPCOrder; + x_pre_ptr = LPC_in_pre; + for( i = 0; i < psEnc->sCmn.nb_subfr; i++ ) { + silk_scale_copy_vector_FLP( x_pre_ptr, x_ptr, invGains[ i ], + psEnc->sCmn.subfr_length + psEnc->sCmn.predictLPCOrder ); + x_pre_ptr += psEnc->sCmn.subfr_length + psEnc->sCmn.predictLPCOrder; + x_ptr += psEnc->sCmn.subfr_length; + } + + SKP_memset( psEncCtrl->LTPCoef, 0, psEnc->sCmn.nb_subfr * LTP_ORDER * sizeof( SKP_float ) ); + psEncCtrl->LTPredCodGain = 0.0f; + } + + /* 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 ); + + /* Quantize LSFs */ +TIC(LSF_quant); + silk_process_NLSFs_FLP( &psEnc->sCmn, psEncCtrl->PredCoef, NLSF_Q15, psEnc->sCmn.prev_NLSFq_Q15 ); +TOC(LSF_quant); + + /* Calculate residual energy using quantized LPC coefficients */ + silk_residual_energy_FLP( psEncCtrl->ResNrg, LPC_in_pre, psEncCtrl->PredCoef, psEncCtrl->Gains, + psEnc->sCmn.subfr_length, psEnc->sCmn.nb_subfr, psEnc->sCmn.predictLPCOrder ); + + /* Copy to prediction struct for use in next frame for fluctuation reduction */ + SKP_memcpy( psEnc->sCmn.prev_NLSFq_Q15, NLSF_Q15, sizeof( psEnc->sCmn.prev_NLSFq_Q15 ) ); +} + diff --git a/silk/float/silk_inner_product_FLP.c b/silk/float/silk_inner_product_FLP.c index 55fbcf407..bb7c03e27 100644 --- a/silk/float/silk_inner_product_FLP.c +++ b/silk/float/silk_inner_product_FLP.c @@ -1,56 +1,56 @@ -/*********************************************************************** -Copyright (c) 2006-2011, Skype Limited. All rights reserved. -Redistribution and use in source and binary forms, with or without -modification, (subject to the limitations in the disclaimer below) -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 Skype Limited, nor the names of specific -contributors, may be used to endorse or promote products derived from -this software without specific prior written permission. -NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED -BY THIS LICENSE. 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. -***********************************************************************/ - -#include "silk_SigProc_FLP.h" - -/* inner product of two SKP_float arrays, with result as double */ -double silk_inner_product_FLP( /* O result */ - const SKP_float *data1, /* I vector 1 */ - const SKP_float *data2, /* I vector 2 */ - opus_int dataSize /* I length of vectors */ -) -{ - opus_int i, dataSize4; - double result; - - /* 4x unrolled loop */ - result = 0.0f; - dataSize4 = dataSize & 0xFFFC; - for( i = 0; i < dataSize4; i += 4 ) { - result += data1[ i + 0 ] * data2[ i + 0 ] + - data1[ i + 1 ] * data2[ i + 1 ] + - data1[ i + 2 ] * data2[ i + 2 ] + - data1[ i + 3 ] * data2[ i + 3 ]; - } - - /* add any remaining products */ - for( ; i < dataSize; i++ ) { - result += data1[ i ] * data2[ i ]; - } - - return result; -} +/*********************************************************************** +Copyright (c) 2006-2011, Skype Limited. All rights reserved. +Redistribution and use in source and binary forms, with or without +modification, (subject to the limitations in the disclaimer below) +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 Skype Limited, nor the names of specific +contributors, may be used to endorse or promote products derived from +this software without specific prior written permission. +NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED +BY THIS LICENSE. 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. +***********************************************************************/ + +#include "silk_SigProc_FLP.h" + +/* inner product of two SKP_float arrays, with result as double */ +double silk_inner_product_FLP( /* O result */ + const SKP_float *data1, /* I vector 1 */ + const SKP_float *data2, /* I vector 2 */ + opus_int dataSize /* I length of vectors */ +) +{ + opus_int i, dataSize4; + double result; + + /* 4x unrolled loop */ + result = 0.0f; + dataSize4 = dataSize & 0xFFFC; + for( i = 0; i < dataSize4; i += 4 ) { + result += data1[ i + 0 ] * data2[ i + 0 ] + + data1[ i + 1 ] * data2[ i + 1 ] + + data1[ i + 2 ] * data2[ i + 2 ] + + data1[ i + 3 ] * data2[ i + 3 ]; + } + + /* add any remaining products */ + for( ; i < dataSize; i++ ) { + result += data1[ i ] * data2[ i ]; + } + + return result; +} diff --git a/silk/float/silk_k2a_FLP.c b/silk/float/silk_k2a_FLP.c index eedcae4c9..a52795fe3 100644 --- a/silk/float/silk_k2a_FLP.c +++ b/silk/float/silk_k2a_FLP.c @@ -1,49 +1,49 @@ -/*********************************************************************** -Copyright (c) 2006-2011, Skype Limited. All rights reserved. -Redistribution and use in source and binary forms, with or without -modification, (subject to the limitations in the disclaimer below) -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 Skype Limited, nor the names of specific -contributors, may be used to endorse or promote products derived from -this software without specific prior written permission. -NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED -BY THIS LICENSE. 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. -***********************************************************************/ - -#include "silk_SigProc_FLP.h" - -/* step up function, converts reflection coefficients to prediction coefficients */ -void silk_k2a_FLP( - SKP_float *A, /* O: prediction coefficients [order] */ - const SKP_float *rc, /* I: reflection coefficients [order] */ - opus_int32 order /* I: prediction order */ -) -{ - opus_int k, n; - SKP_float Atmp[ SILK_MAX_ORDER_LPC ]; - - for( k = 0; k < order; k++ ){ - for( n = 0; n < k; n++ ){ - Atmp[ n ] = A[ n ]; - } - for( n = 0; n < k; n++ ) { - A[ n ] += Atmp[ k - n - 1 ] * rc[ k ]; - } - A[ k ] = -rc[ k ]; - } -} +/*********************************************************************** +Copyright (c) 2006-2011, Skype Limited. All rights reserved. +Redistribution and use in source and binary forms, with or without +modification, (subject to the limitations in the disclaimer below) +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 Skype Limited, nor the names of specific +contributors, may be used to endorse or promote products derived from +this software without specific prior written permission. +NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED +BY THIS LICENSE. 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. +***********************************************************************/ + +#include "silk_SigProc_FLP.h" + +/* step up function, converts reflection coefficients to prediction coefficients */ +void silk_k2a_FLP( + SKP_float *A, /* O: prediction coefficients [order] */ + const SKP_float *rc, /* I: reflection coefficients [order] */ + opus_int32 order /* I: prediction order */ +) +{ + opus_int k, n; + SKP_float Atmp[ SILK_MAX_ORDER_LPC ]; + + for( k = 0; k < order; k++ ){ + for( n = 0; n < k; n++ ){ + Atmp[ n ] = A[ n ]; + } + for( n = 0; n < k; n++ ) { + A[ n ] += Atmp[ k - n - 1 ] * rc[ k ]; + } + A[ k ] = -rc[ k ]; + } +} diff --git a/silk/float/silk_levinsondurbin_FLP.c b/silk/float/silk_levinsondurbin_FLP.c index b0bf862be..f823c42dd 100644 --- a/silk/float/silk_levinsondurbin_FLP.c +++ b/silk/float/silk_levinsondurbin_FLP.c @@ -1,77 +1,77 @@ -/*********************************************************************** -Copyright (c) 2006-2011, Skype Limited. All rights reserved. -Redistribution and use in source and binary forms, with or without -modification, (subject to the limitations in the disclaimer below) -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 Skype Limited, nor the names of specific -contributors, may be used to endorse or promote products derived from -this software without specific prior written permission. -NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED -BY THIS LICENSE. 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. -***********************************************************************/ - -#include "silk_SigProc_FLP.h" - -/* Solve the normal equations using the Levinson-Durbin recursion */ -SKP_float silk_levinsondurbin_FLP( /* O prediction error energy */ - SKP_float A[], /* O prediction coefficients [order] */ - const SKP_float corr[], /* I input auto-correlations [order + 1] */ - const opus_int order /* I prediction order */ -) -{ - opus_int i, mHalf, m; - SKP_float min_nrg, nrg, t, km, Atmp1, Atmp2; - - min_nrg = 1e-12f * corr[ 0 ] + 1e-9f; - nrg = corr[ 0 ]; - nrg = SKP_max_float(min_nrg, nrg); - A[ 0 ] = corr[ 1 ] / nrg; - nrg -= A[ 0 ] * corr[ 1 ]; - nrg = SKP_max_float(min_nrg, nrg); - - for( m = 1; m < order; m++ ) - { - t = corr[ m + 1 ]; - for( i = 0; i < m; i++ ) { - t -= A[ i ] * corr[ m - i ]; - } - - /* reflection coefficient */ - km = t / nrg; - - /* residual energy */ - nrg -= km * t; - nrg = SKP_max_float(min_nrg, nrg); - - mHalf = m >> 1; - for( i = 0; i < mHalf; i++ ) { - Atmp1 = A[ i ]; - Atmp2 = A[ m - i - 1 ]; - A[ m - i - 1 ] -= km * Atmp1; - A[ i ] -= km * Atmp2; - } - if( m & 1 ) { - A[ mHalf ] -= km * A[ mHalf ]; - } - A[ m ] = km; - } - - /* return the residual energy */ - return nrg; -} - +/*********************************************************************** +Copyright (c) 2006-2011, Skype Limited. All rights reserved. +Redistribution and use in source and binary forms, with or without +modification, (subject to the limitations in the disclaimer below) +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 Skype Limited, nor the names of specific +contributors, may be used to endorse or promote products derived from +this software without specific prior written permission. +NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED +BY THIS LICENSE. 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. +***********************************************************************/ + +#include "silk_SigProc_FLP.h" + +/* Solve the normal equations using the Levinson-Durbin recursion */ +SKP_float silk_levinsondurbin_FLP( /* O prediction error energy */ + SKP_float A[], /* O prediction coefficients [order] */ + const SKP_float corr[], /* I input auto-correlations [order + 1] */ + const opus_int order /* I prediction order */ +) +{ + opus_int i, mHalf, m; + SKP_float min_nrg, nrg, t, km, Atmp1, Atmp2; + + min_nrg = 1e-12f * corr[ 0 ] + 1e-9f; + nrg = corr[ 0 ]; + nrg = SKP_max_float(min_nrg, nrg); + A[ 0 ] = corr[ 1 ] / nrg; + nrg -= A[ 0 ] * corr[ 1 ]; + nrg = SKP_max_float(min_nrg, nrg); + + for( m = 1; m < order; m++ ) + { + t = corr[ m + 1 ]; + for( i = 0; i < m; i++ ) { + t -= A[ i ] * corr[ m - i ]; + } + + /* reflection coefficient */ + km = t / nrg; + + /* residual energy */ + nrg -= km * t; + nrg = SKP_max_float(min_nrg, nrg); + + mHalf = m >> 1; + for( i = 0; i < mHalf; i++ ) { + Atmp1 = A[ i ]; + Atmp2 = A[ m - i - 1 ]; + A[ m - i - 1 ] -= km * Atmp1; + A[ i ] -= km * Atmp2; + } + if( m & 1 ) { + A[ mHalf ] -= km * A[ mHalf ]; + } + A[ m ] = km; + } + + /* return the residual energy */ + return nrg; +} + diff --git a/silk/float/silk_main_FLP.h b/silk/float/silk_main_FLP.h index ccc552c8b..43761ab45 100644 --- a/silk/float/silk_main_FLP.h +++ b/silk/float/silk_main_FLP.h @@ -1,326 +1,326 @@ -/*********************************************************************** -Copyright (c) 2006-2011, Skype Limited. All rights reserved. -Redistribution and use in source and binary forms, with or without -modification, (subject to the limitations in the disclaimer below) -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 Skype Limited, nor the names of specific -contributors, may be used to endorse or promote products derived from -this software without specific prior written permission. -NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED -BY THIS LICENSE. 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. -***********************************************************************/ - -#ifndef SILK_MAIN_FLP_H -#define SILK_MAIN_FLP_H - -#include "silk_SigProc_FLP.h" -#include "silk_SigProc_FIX.h" -#include "silk_structs_FLP.h" -#include "silk_main.h" -#include "silk_define.h" -#include "silk_debug.h" -#include "entenc.h" - -#ifdef __cplusplus -extern "C" -{ -#endif - -#define silk_encoder_state_Fxx silk_encoder_state_FLP -#define silk_encode_frame_Fxx silk_encode_frame_FLP - -/*********************/ -/* Encoder Functions */ -/*********************/ - -/* High-pass filter with cutoff frequency adaptation based on pitch lag statistics */ -void silk_HP_variable_cutoff( - silk_encoder_state_Fxx state_Fxx[], /* I/O Encoder states */ - const opus_int nChannels /* I Number of channels */ -); - -/* Encoder main function */ -opus_int silk_encode_frame_FLP( - silk_encoder_state_FLP *psEnc, /* I/O Encoder state FLP */ - opus_int32 *pnBytesOut, /* O Number of payload bytes; */ - ec_enc *psRangeEnc /* I/O compressor data structure */ -); - -/* Low Bitrate Redundancy (LBRR) encoding. Reuse all parameters but encode with lower bitrate */ -void silk_LBRR_encode_FLP( - silk_encoder_state_FLP *psEnc, /* I/O Encoder state FLP */ - silk_encoder_control_FLP *psEncCtrl, /* I/O Encoder control FLP */ - const SKP_float xfw[] /* I Input signal */ -); - -/* Initializes the Silk encoder state */ -opus_int silk_init_encoder( - silk_encoder_state_FLP *psEnc /* I/O Encoder state FLP */ -); - -/* Control the Silk encoder */ -opus_int silk_control_encoder( - silk_encoder_state_FLP *psEnc, /* I/O Pointer to Silk encoder state FLP */ - silk_EncControlStruct *encControl, /* I: Control structure */ - const opus_int32 TargetRate_bps, /* I Target max bitrate (bps) */ - const opus_int allow_bw_switch, /* I Flag to allow switching audio bandwidth */ - const opus_int channelNb /* I Channel number */ -); - -/****************/ -/* Prefiltering */ -/****************/ -void silk_prefilter_FLP( - silk_encoder_state_FLP *psEnc, /* I/O Encoder state FLP */ - const silk_encoder_control_FLP *psEncCtrl, /* I Encoder control FLP */ - SKP_float xw[], /* O Weighted signal */ - const SKP_float x[] /* I Speech signal */ -); - -/**************************/ -/* Noise shaping analysis */ -/**************************/ -/* Compute noise shaping coefficients and initial gain values */ -void silk_noise_shape_analysis_FLP( - silk_encoder_state_FLP *psEnc, /* I/O Encoder state FLP */ - silk_encoder_control_FLP *psEncCtrl, /* I/O Encoder control FLP */ - const SKP_float *pitch_res, /* I LPC residual from pitch analysis */ - const SKP_float *x /* I Input signal [frame_length + la_shape] */ -); - -/* Autocorrelations for a warped frequency axis */ -void silk_warped_autocorrelation_FLP( - SKP_float *corr, /* O Result [order + 1] */ - const SKP_float *input, /* I Input data to correlate */ - const SKP_float warping, /* I Warping coefficient */ - const opus_int length, /* I Length of input */ - const opus_int order /* I Correlation order (even) */ -); - -/* Calculation of LTP state scaling */ -void silk_LTP_scale_ctrl_FLP( - silk_encoder_state_FLP *psEnc, /* I/O Encoder state FLP */ - silk_encoder_control_FLP *psEncCtrl /* I/O Encoder control FLP */ -); - -/**********************************************/ -/* Prediction Analysis */ -/**********************************************/ -/* Find pitch lags */ -void silk_find_pitch_lags_FLP( - silk_encoder_state_FLP *psEnc, /* I/O Encoder state FLP */ - silk_encoder_control_FLP *psEncCtrl, /* I/O Encoder control FLP */ - SKP_float res[], /* O Residual */ - const SKP_float x[] /* I Speech signal */ -); - -/* Find LPC and LTP coefficients */ -void silk_find_pred_coefs_FLP( - silk_encoder_state_FLP *psEnc, /* I/O Encoder state FLP */ - silk_encoder_control_FLP *psEncCtrl, /* I/O Encoder control FLP */ - const SKP_float res_pitch[], /* I Residual from pitch analysis */ - const SKP_float x[] /* I Speech signal */ -); - -/* LPC analysis */ -void silk_find_LPC_FLP( - 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 SKP_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 */ -); - -/* LTP analysis */ -void silk_find_LTP_FLP( - SKP_float b[ MAX_NB_SUBFR * LTP_ORDER ], /* O LTP coefs */ - SKP_float WLTP[ MAX_NB_SUBFR * LTP_ORDER * LTP_ORDER ], /* O Weight for LTP quantization */ - SKP_float *LTPredCodGain, /* O LTP coding gain */ - const SKP_float r_lpc[], /* I LPC residual */ - const opus_int lag[ MAX_NB_SUBFR ], /* I LTP lags */ - const SKP_float Wght[ MAX_NB_SUBFR ], /* I Weights */ - const opus_int subfr_length, /* I Subframe length */ - const opus_int nb_subfr, /* I number of subframes */ - const opus_int mem_offset /* I Number of samples in LTP memory */ -); - -void silk_LTP_analysis_filter_FLP( - SKP_float *LTP_res, /* O LTP res MAX_NB_SUBFR*(pre_lgth+subfr_lngth) */ - const SKP_float *x, /* I Input signal, with preceeding samples */ - const SKP_float B[ LTP_ORDER * MAX_NB_SUBFR ], /* I LTP coefficients for each subframe */ - const opus_int pitchL[ MAX_NB_SUBFR ], /* I Pitch lags */ - const SKP_float invGains[ MAX_NB_SUBFR ], /* I Inverse quantization gains */ - const opus_int subfr_length, /* I Length of each subframe */ - const opus_int nb_subfr, /* I number of subframes */ - const opus_int pre_length /* I Preceeding samples for each subframe */ -); - -/* Calculates residual energies of input subframes where all subframes have LPC_order */ -/* of preceeding samples */ -void silk_residual_energy_FLP( - SKP_float nrgs[ MAX_NB_SUBFR ], /* O Residual energy per subframe */ - const SKP_float x[], /* I Input signal */ - SKP_float a[ 2 ][ MAX_LPC_ORDER ],/* I AR coefs for each frame half */ - const SKP_float gains[], /* I Quantization gains */ - const opus_int subfr_length, /* I Subframe length */ - const opus_int nb_subfr, /* I number of subframes */ - const opus_int LPC_order /* I LPC order */ -); - -/* 16th order LPC analysis filter */ -void silk_LPC_analysis_filter_FLP( - SKP_float r_LPC[], /* O LPC residual signal */ - const SKP_float PredCoef[], /* I LPC coefficients */ - const SKP_float s[], /* I Input signal */ - const opus_int length, /* I Length of input signal */ - const opus_int Order /* I LPC order */ -); - -/* LTP tap quantizer */ -void silk_quant_LTP_gains_FLP( - SKP_float B[ MAX_NB_SUBFR * LTP_ORDER ], /* I/O (Un-)quantized LTP gains */ - opus_int8 cbk_index[ MAX_NB_SUBFR ], /* O Codebook index */ - opus_int8 *periodicity_index, /* O Periodicity index */ - const SKP_float W[ MAX_NB_SUBFR * LTP_ORDER * LTP_ORDER ], /* I Error weights */ - const opus_int mu_Q10, /* I Mu value (R/D tradeoff) */ - const opus_int lowComplexity, /* I Flag for low complexity */ - const opus_int nb_subfr /* I number of subframes */ -); - -/******************/ -/* NLSF Quantizer */ -/******************/ -/* Limit, stabilize, and quantize NLSFs */ -void silk_process_NLSFs_FLP( - silk_encoder_state *psEncC, /* I/O Encoder state */ - SKP_float PredCoef[ 2 ][ MAX_LPC_ORDER ], /* O Prediction coefficients */ - opus_int16 NLSF_Q15[ MAX_LPC_ORDER ], /* I/O Normalized LSFs (quant out) (0 - (2^15-1)) */ - const opus_int16 prev_NLSF_Q15[ MAX_LPC_ORDER ] /* I Previous Normalized LSFs (0 - (2^15-1)) */ -); - -/* Residual energy: nrg = wxx - 2 * wXx * c + c' * wXX * c */ -SKP_float silk_residual_energy_covar_FLP( /* O Weighted residual energy */ - const SKP_float *c, /* I Filter coefficients */ - SKP_float *wXX, /* I/O Weighted correlation matrix, reg. out */ - const SKP_float *wXx, /* I Weighted correlation vector */ - const SKP_float wxx, /* I Weighted correlation value */ - const opus_int D /* I Dimension */ -); - -/* Entropy constrained MATRIX-weighted VQ, for a single input data vector */ -void silk_VQ_WMat_EC_FLP( - opus_int *ind, /* O Index of best codebook vector */ - SKP_float *rate_dist, /* O Best weighted quant. error + mu * rate */ - const SKP_float *in, /* I Input vector to be quantized */ - const SKP_float *W, /* I Weighting matrix */ - const opus_int16 *cb, /* I Codebook */ - const opus_int16 *cl_Q6, /* I Code length for each codebook vector */ - const SKP_float mu, /* I Tradeoff between WSSE and rate */ - const opus_int L /* I Number of vectors in codebook */ -); - -/* Processing of gains */ -void silk_process_gains_FLP( - silk_encoder_state_FLP *psEnc, /* I/O Encoder state FLP */ - silk_encoder_control_FLP *psEncCtrl /* I/O Encoder control FLP */ -); - -/******************/ -/* Linear Algebra */ -/******************/ -/* Calculates correlation matrix X'*X */ -void silk_corrMatrix_FLP( - const SKP_float *x, /* I x vector [ L+order-1 ] used to create X */ - const opus_int L, /* I Length of vectors */ - const opus_int Order, /* I Max lag for correlation */ - SKP_float *XX /* O X'*X correlation matrix [order x order] */ -); - -/* Calculates correlation vector X'*t */ -void silk_corrVector_FLP( - const SKP_float *x, /* I x vector [L+order-1] used to create X */ - const SKP_float *t, /* I Target vector [L] */ - const opus_int L, /* I Length of vecors */ - const opus_int Order, /* I Max lag for correlation */ - SKP_float *Xt /* O X'*t correlation vector [order] */ -); - -/* Add noise to matrix diagonal */ -void silk_regularize_correlations_FLP( - SKP_float *XX, /* I/O Correlation matrices */ - SKP_float *xx, /* I/O Correlation values */ - const SKP_float noise, /* I Noise energy to add */ - const opus_int D /* I Dimension of XX */ -); - -/* Function to solve linear equation Ax = b, where A is an MxM symmetric matrix */ -void silk_solve_LDL_FLP( - SKP_float *A, /* I/O Symmetric square matrix, out: reg. */ - const opus_int M, /* I Size of matrix */ - const SKP_float *b, /* I Pointer to b vector */ - SKP_float *x /* O Pointer to x solution vector */ -); - -/* Apply sine window to signal vector. */ -/* Window types: */ -/* 1 -> sine window from 0 to pi/2 */ -/* 2 -> sine window from pi/2 to pi */ -void silk_apply_sine_window_FLP( - SKP_float px_win[], /* O Pointer to windowed signal */ - const SKP_float px[], /* I Pointer to input signal */ - const opus_int win_type, /* I Selects a window type */ - const opus_int length /* I Window length, multiple of 4 */ -); - -/* Wrapper functions. Call flp / fix code */ - -/* Convert AR filter coefficients to NLSF parameters */ -void silk_A2NLSF_FLP( - opus_int16 *NLSF_Q15, /* O NLSF vector [ LPC_order ] */ - const SKP_float *pAR, /* I LPC coefficients [ LPC_order ] */ - const opus_int LPC_order /* I LPC order */ -); - -/* Convert NLSF parameters to AR prediction filter coefficients */ -void silk_NLSF2A_FLP( - SKP_float *pAR, /* O LPC coefficients [ LPC_order ] */ - const opus_int16 *NLSF_Q15, /* I NLSF vector [ LPC_order ] */ - const opus_int LPC_order /* I LPC order */ -); - -/****************************************/ -/* Floating-point Silk NSQ wrapper */ -/****************************************/ -void silk_NSQ_wrapper_FLP( - silk_encoder_state_FLP *psEnc, /* I/O Encoder state FLP */ - silk_encoder_control_FLP *psEncCtrl, /* I/O Encoder control FLP */ - SideInfoIndices *psIndices, /* I/O Quantization indices */ - silk_nsq_state *psNSQ, /* I/O Noise Shaping Quantzation state */ - opus_int8 pulses[], /* O Quantized pulse signal */ - const SKP_float x[] /* I Prefiltered input signal */ -); - -#ifdef __cplusplus -} -#endif - -#endif +/*********************************************************************** +Copyright (c) 2006-2011, Skype Limited. All rights reserved. +Redistribution and use in source and binary forms, with or without +modification, (subject to the limitations in the disclaimer below) +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 Skype Limited, nor the names of specific +contributors, may be used to endorse or promote products derived from +this software without specific prior written permission. +NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED +BY THIS LICENSE. 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. +***********************************************************************/ + +#ifndef SILK_MAIN_FLP_H +#define SILK_MAIN_FLP_H + +#include "silk_SigProc_FLP.h" +#include "silk_SigProc_FIX.h" +#include "silk_structs_FLP.h" +#include "silk_main.h" +#include "silk_define.h" +#include "silk_debug.h" +#include "entenc.h" + +#ifdef __cplusplus +extern "C" +{ +#endif + +#define silk_encoder_state_Fxx silk_encoder_state_FLP +#define silk_encode_frame_Fxx silk_encode_frame_FLP + +/*********************/ +/* Encoder Functions */ +/*********************/ + +/* High-pass filter with cutoff frequency adaptation based on pitch lag statistics */ +void silk_HP_variable_cutoff( + silk_encoder_state_Fxx state_Fxx[], /* I/O Encoder states */ + const opus_int nChannels /* I Number of channels */ +); + +/* Encoder main function */ +opus_int silk_encode_frame_FLP( + silk_encoder_state_FLP *psEnc, /* I/O Encoder state FLP */ + opus_int32 *pnBytesOut, /* O Number of payload bytes; */ + ec_enc *psRangeEnc /* I/O compressor data structure */ +); + +/* Low Bitrate Redundancy (LBRR) encoding. Reuse all parameters but encode with lower bitrate */ +void silk_LBRR_encode_FLP( + silk_encoder_state_FLP *psEnc, /* I/O Encoder state FLP */ + silk_encoder_control_FLP *psEncCtrl, /* I/O Encoder control FLP */ + const SKP_float xfw[] /* I Input signal */ +); + +/* Initializes the Silk encoder state */ +opus_int silk_init_encoder( + silk_encoder_state_FLP *psEnc /* I/O Encoder state FLP */ +); + +/* Control the Silk encoder */ +opus_int silk_control_encoder( + silk_encoder_state_FLP *psEnc, /* I/O Pointer to Silk encoder state FLP */ + silk_EncControlStruct *encControl, /* I: Control structure */ + const opus_int32 TargetRate_bps, /* I Target max bitrate (bps) */ + const opus_int allow_bw_switch, /* I Flag to allow switching audio bandwidth */ + const opus_int channelNb /* I Channel number */ +); + +/****************/ +/* Prefiltering */ +/****************/ +void silk_prefilter_FLP( + silk_encoder_state_FLP *psEnc, /* I/O Encoder state FLP */ + const silk_encoder_control_FLP *psEncCtrl, /* I Encoder control FLP */ + SKP_float xw[], /* O Weighted signal */ + const SKP_float x[] /* I Speech signal */ +); + +/**************************/ +/* Noise shaping analysis */ +/**************************/ +/* Compute noise shaping coefficients and initial gain values */ +void silk_noise_shape_analysis_FLP( + silk_encoder_state_FLP *psEnc, /* I/O Encoder state FLP */ + silk_encoder_control_FLP *psEncCtrl, /* I/O Encoder control FLP */ + const SKP_float *pitch_res, /* I LPC residual from pitch analysis */ + const SKP_float *x /* I Input signal [frame_length + la_shape] */ +); + +/* Autocorrelations for a warped frequency axis */ +void silk_warped_autocorrelation_FLP( + SKP_float *corr, /* O Result [order + 1] */ + const SKP_float *input, /* I Input data to correlate */ + const SKP_float warping, /* I Warping coefficient */ + const opus_int length, /* I Length of input */ + const opus_int order /* I Correlation order (even) */ +); + +/* Calculation of LTP state scaling */ +void silk_LTP_scale_ctrl_FLP( + silk_encoder_state_FLP *psEnc, /* I/O Encoder state FLP */ + silk_encoder_control_FLP *psEncCtrl /* I/O Encoder control FLP */ +); + +/**********************************************/ +/* Prediction Analysis */ +/**********************************************/ +/* Find pitch lags */ +void silk_find_pitch_lags_FLP( + silk_encoder_state_FLP *psEnc, /* I/O Encoder state FLP */ + silk_encoder_control_FLP *psEncCtrl, /* I/O Encoder control FLP */ + SKP_float res[], /* O Residual */ + const SKP_float x[] /* I Speech signal */ +); + +/* Find LPC and LTP coefficients */ +void silk_find_pred_coefs_FLP( + silk_encoder_state_FLP *psEnc, /* I/O Encoder state FLP */ + silk_encoder_control_FLP *psEncCtrl, /* I/O Encoder control FLP */ + const SKP_float res_pitch[], /* I Residual from pitch analysis */ + const SKP_float x[] /* I Speech signal */ +); + +/* LPC analysis */ +void silk_find_LPC_FLP( + 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 SKP_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 */ +); + +/* LTP analysis */ +void silk_find_LTP_FLP( + SKP_float b[ MAX_NB_SUBFR * LTP_ORDER ], /* O LTP coefs */ + SKP_float WLTP[ MAX_NB_SUBFR * LTP_ORDER * LTP_ORDER ], /* O Weight for LTP quantization */ + SKP_float *LTPredCodGain, /* O LTP coding gain */ + const SKP_float r_lpc[], /* I LPC residual */ + const opus_int lag[ MAX_NB_SUBFR ], /* I LTP lags */ + const SKP_float Wght[ MAX_NB_SUBFR ], /* I Weights */ + const opus_int subfr_length, /* I Subframe length */ + const opus_int nb_subfr, /* I number of subframes */ + const opus_int mem_offset /* I Number of samples in LTP memory */ +); + +void silk_LTP_analysis_filter_FLP( + SKP_float *LTP_res, /* O LTP res MAX_NB_SUBFR*(pre_lgth+subfr_lngth) */ + const SKP_float *x, /* I Input signal, with preceeding samples */ + const SKP_float B[ LTP_ORDER * MAX_NB_SUBFR ], /* I LTP coefficients for each subframe */ + const opus_int pitchL[ MAX_NB_SUBFR ], /* I Pitch lags */ + const SKP_float invGains[ MAX_NB_SUBFR ], /* I Inverse quantization gains */ + const opus_int subfr_length, /* I Length of each subframe */ + const opus_int nb_subfr, /* I number of subframes */ + const opus_int pre_length /* I Preceeding samples for each subframe */ +); + +/* Calculates residual energies of input subframes where all subframes have LPC_order */ +/* of preceeding samples */ +void silk_residual_energy_FLP( + SKP_float nrgs[ MAX_NB_SUBFR ], /* O Residual energy per subframe */ + const SKP_float x[], /* I Input signal */ + SKP_float a[ 2 ][ MAX_LPC_ORDER ],/* I AR coefs for each frame half */ + const SKP_float gains[], /* I Quantization gains */ + const opus_int subfr_length, /* I Subframe length */ + const opus_int nb_subfr, /* I number of subframes */ + const opus_int LPC_order /* I LPC order */ +); + +/* 16th order LPC analysis filter */ +void silk_LPC_analysis_filter_FLP( + SKP_float r_LPC[], /* O LPC residual signal */ + const SKP_float PredCoef[], /* I LPC coefficients */ + const SKP_float s[], /* I Input signal */ + const opus_int length, /* I Length of input signal */ + const opus_int Order /* I LPC order */ +); + +/* LTP tap quantizer */ +void silk_quant_LTP_gains_FLP( + SKP_float B[ MAX_NB_SUBFR * LTP_ORDER ], /* I/O (Un-)quantized LTP gains */ + opus_int8 cbk_index[ MAX_NB_SUBFR ], /* O Codebook index */ + opus_int8 *periodicity_index, /* O Periodicity index */ + const SKP_float W[ MAX_NB_SUBFR * LTP_ORDER * LTP_ORDER ], /* I Error weights */ + const opus_int mu_Q10, /* I Mu value (R/D tradeoff) */ + const opus_int lowComplexity, /* I Flag for low complexity */ + const opus_int nb_subfr /* I number of subframes */ +); + +/******************/ +/* NLSF Quantizer */ +/******************/ +/* Limit, stabilize, and quantize NLSFs */ +void silk_process_NLSFs_FLP( + silk_encoder_state *psEncC, /* I/O Encoder state */ + SKP_float PredCoef[ 2 ][ MAX_LPC_ORDER ], /* O Prediction coefficients */ + opus_int16 NLSF_Q15[ MAX_LPC_ORDER ], /* I/O Normalized LSFs (quant out) (0 - (2^15-1)) */ + const opus_int16 prev_NLSF_Q15[ MAX_LPC_ORDER ] /* I Previous Normalized LSFs (0 - (2^15-1)) */ +); + +/* Residual energy: nrg = wxx - 2 * wXx * c + c' * wXX * c */ +SKP_float silk_residual_energy_covar_FLP( /* O Weighted residual energy */ + const SKP_float *c, /* I Filter coefficients */ + SKP_float *wXX, /* I/O Weighted correlation matrix, reg. out */ + const SKP_float *wXx, /* I Weighted correlation vector */ + const SKP_float wxx, /* I Weighted correlation value */ + const opus_int D /* I Dimension */ +); + +/* Entropy constrained MATRIX-weighted VQ, for a single input data vector */ +void silk_VQ_WMat_EC_FLP( + opus_int *ind, /* O Index of best codebook vector */ + SKP_float *rate_dist, /* O Best weighted quant. error + mu * rate */ + const SKP_float *in, /* I Input vector to be quantized */ + const SKP_float *W, /* I Weighting matrix */ + const opus_int16 *cb, /* I Codebook */ + const opus_int16 *cl_Q6, /* I Code length for each codebook vector */ + const SKP_float mu, /* I Tradeoff between WSSE and rate */ + const opus_int L /* I Number of vectors in codebook */ +); + +/* Processing of gains */ +void silk_process_gains_FLP( + silk_encoder_state_FLP *psEnc, /* I/O Encoder state FLP */ + silk_encoder_control_FLP *psEncCtrl /* I/O Encoder control FLP */ +); + +/******************/ +/* Linear Algebra */ +/******************/ +/* Calculates correlation matrix X'*X */ +void silk_corrMatrix_FLP( + const SKP_float *x, /* I x vector [ L+order-1 ] used to create X */ + const opus_int L, /* I Length of vectors */ + const opus_int Order, /* I Max lag for correlation */ + SKP_float *XX /* O X'*X correlation matrix [order x order] */ +); + +/* Calculates correlation vector X'*t */ +void silk_corrVector_FLP( + const SKP_float *x, /* I x vector [L+order-1] used to create X */ + const SKP_float *t, /* I Target vector [L] */ + const opus_int L, /* I Length of vecors */ + const opus_int Order, /* I Max lag for correlation */ + SKP_float *Xt /* O X'*t correlation vector [order] */ +); + +/* Add noise to matrix diagonal */ +void silk_regularize_correlations_FLP( + SKP_float *XX, /* I/O Correlation matrices */ + SKP_float *xx, /* I/O Correlation values */ + const SKP_float noise, /* I Noise energy to add */ + const opus_int D /* I Dimension of XX */ +); + +/* Function to solve linear equation Ax = b, where A is an MxM symmetric matrix */ +void silk_solve_LDL_FLP( + SKP_float *A, /* I/O Symmetric square matrix, out: reg. */ + const opus_int M, /* I Size of matrix */ + const SKP_float *b, /* I Pointer to b vector */ + SKP_float *x /* O Pointer to x solution vector */ +); + +/* Apply sine window to signal vector. */ +/* Window types: */ +/* 1 -> sine window from 0 to pi/2 */ +/* 2 -> sine window from pi/2 to pi */ +void silk_apply_sine_window_FLP( + SKP_float px_win[], /* O Pointer to windowed signal */ + const SKP_float px[], /* I Pointer to input signal */ + const opus_int win_type, /* I Selects a window type */ + const opus_int length /* I Window length, multiple of 4 */ +); + +/* Wrapper functions. Call flp / fix code */ + +/* Convert AR filter coefficients to NLSF parameters */ +void silk_A2NLSF_FLP( + opus_int16 *NLSF_Q15, /* O NLSF vector [ LPC_order ] */ + const SKP_float *pAR, /* I LPC coefficients [ LPC_order ] */ + const opus_int LPC_order /* I LPC order */ +); + +/* Convert NLSF parameters to AR prediction filter coefficients */ +void silk_NLSF2A_FLP( + SKP_float *pAR, /* O LPC coefficients [ LPC_order ] */ + const opus_int16 *NLSF_Q15, /* I NLSF vector [ LPC_order ] */ + const opus_int LPC_order /* I LPC order */ +); + +/****************************************/ +/* Floating-point Silk NSQ wrapper */ +/****************************************/ +void silk_NSQ_wrapper_FLP( + silk_encoder_state_FLP *psEnc, /* I/O Encoder state FLP */ + silk_encoder_control_FLP *psEncCtrl, /* I/O Encoder control FLP */ + SideInfoIndices *psIndices, /* I/O Quantization indices */ + silk_nsq_state *psNSQ, /* I/O Noise Shaping Quantzation state */ + opus_int8 pulses[], /* O Quantized pulse signal */ + const SKP_float x[] /* I Prefiltered input signal */ +); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/silk/float/silk_noise_shape_analysis_FLP.c b/silk/float/silk_noise_shape_analysis_FLP.c index 271ee51e2..03bb787f1 100644 --- a/silk/float/silk_noise_shape_analysis_FLP.c +++ b/silk/float/silk_noise_shape_analysis_FLP.c @@ -1,359 +1,359 @@ -/*********************************************************************** -Copyright (c) 2006-2011, Skype Limited. All rights reserved. -Redistribution and use in source and binary forms, with or without -modification, (subject to the limitations in the disclaimer below) -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 Skype Limited, nor the names of specific -contributors, may be used to endorse or promote products derived from -this software without specific prior written permission. -NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED -BY THIS LICENSE. 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. -***********************************************************************/ - -#include "silk_main_FLP.h" -#include "silk_tuning_parameters.h" - -/* Compute gain to make warped filter coefficients have a zero mean log frequency response on a */ -/* non-warped frequency scale. (So that it can be implemented with a minimum-phase monic filter.) */ -SKP_INLINE SKP_float warped_gain( - const SKP_float *coefs, - SKP_float lambda, - opus_int order -) { - opus_int i; - SKP_float gain; - - lambda = -lambda; - gain = coefs[ order - 1 ]; - for( i = order - 2; i >= 0; i-- ) { - gain = lambda * gain + coefs[ i ]; - } - return (SKP_float)( 1.0f / ( 1.0f - lambda * gain ) ); -} - -/* Convert warped filter coefficients to monic pseudo-warped coefficients and limit maximum */ -/* amplitude of monic warped coefficients by using bandwidth expansion on the true coefficients */ -SKP_INLINE void warped_true2monic_coefs( - SKP_float *coefs_syn, - SKP_float *coefs_ana, - SKP_float lambda, - SKP_float limit, - opus_int order -) { - opus_int i, iter, ind = 0; - SKP_float tmp, maxabs, chirp, gain_syn, gain_ana; - - /* Convert to monic coefficients */ - for( i = order - 1; i > 0; i-- ) { - coefs_syn[ i - 1 ] -= lambda * coefs_syn[ i ]; - coefs_ana[ i - 1 ] -= lambda * coefs_ana[ i ]; - } - gain_syn = ( 1.0f - lambda * lambda ) / ( 1.0f + lambda * coefs_syn[ 0 ] ); - gain_ana = ( 1.0f - lambda * lambda ) / ( 1.0f + lambda * coefs_ana[ 0 ] ); - for( i = 0; i < order; i++ ) { - coefs_syn[ i ] *= gain_syn; - coefs_ana[ i ] *= gain_ana; - } - - /* Limit */ - for( iter = 0; iter < 10; iter++ ) { - /* Find maximum absolute value */ - maxabs = -1.0f; - for( i = 0; i < order; i++ ) { - tmp = SKP_max( SKP_abs_float( coefs_syn[ i ] ), SKP_abs_float( coefs_ana[ i ] ) ); - if( tmp > maxabs ) { - maxabs = tmp; - ind = i; - } - } - if( maxabs <= limit ) { - /* Coefficients are within range - done */ - return; - } - - /* Convert back to true warped coefficients */ - for( i = 1; i < order; i++ ) { - coefs_syn[ i - 1 ] += lambda * coefs_syn[ i ]; - coefs_ana[ i - 1 ] += lambda * coefs_ana[ i ]; - } - gain_syn = 1.0f / gain_syn; - gain_ana = 1.0f / gain_ana; - for( i = 0; i < order; i++ ) { - coefs_syn[ i ] *= gain_syn; - coefs_ana[ i ] *= gain_ana; - } - - /* Apply bandwidth expansion */ - chirp = 0.99f - ( 0.8f + 0.1f * iter ) * ( maxabs - limit ) / ( maxabs * ( ind + 1 ) ); - silk_bwexpander_FLP( coefs_syn, order, chirp ); - silk_bwexpander_FLP( coefs_ana, order, chirp ); - - /* Convert to monic warped coefficients */ - for( i = order - 1; i > 0; i-- ) { - coefs_syn[ i - 1 ] -= lambda * coefs_syn[ i ]; - coefs_ana[ i - 1 ] -= lambda * coefs_ana[ i ]; - } - gain_syn = ( 1.0f - lambda * lambda ) / ( 1.0f + lambda * coefs_syn[ 0 ] ); - gain_ana = ( 1.0f - lambda * lambda ) / ( 1.0f + lambda * coefs_ana[ 0 ] ); - for( i = 0; i < order; i++ ) { - coefs_syn[ i ] *= gain_syn; - coefs_ana[ i ] *= gain_ana; - } - } - SKP_assert( 0 ); -} - -/* Compute noise shaping coefficients and initial gain values */ -void silk_noise_shape_analysis_FLP( - silk_encoder_state_FLP *psEnc, /* I/O Encoder state FLP */ - silk_encoder_control_FLP *psEncCtrl, /* I/O Encoder control FLP */ - const SKP_float *pitch_res, /* I LPC residual from pitch analysis */ - const SKP_float *x /* I Input signal [frame_length + la_shape] */ -) -{ - silk_shape_state_FLP *psShapeSt = &psEnc->sShape; - opus_int k, nSamples; - SKP_float SNR_adj_dB, HarmBoost, HarmShapeGain, Tilt; - SKP_float nrg, pre_nrg, log_energy, log_energy_prev, energy_variation; - SKP_float delta, BWExp1, BWExp2, gain_mult, gain_add, strength, b, warping; - SKP_float x_windowed[ SHAPE_LPC_WIN_MAX ]; - SKP_float auto_corr[ MAX_SHAPE_LPC_ORDER + 1 ]; - const SKP_float *x_ptr, *pitch_res_ptr; - - /* Point to start of first LPC analysis block */ - x_ptr = x - psEnc->sCmn.la_shape; - - /****************/ - /* GAIN CONTROL */ - /****************/ - SNR_adj_dB = psEnc->sCmn.SNR_dB_Q7 * ( 1 / 128.0f ); - - /* Input quality is the average of the quality in the lowest two VAD bands */ - 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 = SKP_sigmoid( 0.25f * ( SNR_adj_dB - 18.0f ) ); - - if( psEnc->sCmn.useCBR == 0 ) { - /* Reduce coding SNR during low speech activity */ - b = 1.0f - psEnc->sCmn.speech_activity_Q8 * ( 1.0f / 256.0f ); - SNR_adj_dB -= BG_SNR_DECR_dB * psEncCtrl->coding_quality * ( 0.5f + 0.5f * psEncCtrl->input_quality ) * b * b; - } - - if( psEnc->sCmn.indices.signalType == TYPE_VOICED ) { - /* Reduce gains for periodic signals */ - SNR_adj_dB += HARM_SNR_INCR_dB * psEnc->LTPCorr; - } else { - /* For unvoiced signals and low-quality input, adjust the quality slower than SNR_dB setting */ - SNR_adj_dB += ( -0.4f * psEnc->sCmn.SNR_dB_Q7 * ( 1 / 128.0f ) + 6.0f ) * ( 1.0f - psEncCtrl->input_quality ); - } - - /*************************/ - /* SPARSENESS PROCESSING */ - /*************************/ - /* Set quantizer offset */ - if( psEnc->sCmn.indices.signalType == TYPE_VOICED ) { - /* Initally set to 0; may be overruled in process_gains(..) */ - psEnc->sCmn.indices.quantOffsetType = 0; - psEncCtrl->sparseness = 0.0f; - } else { - /* Sparseness measure, based on relative fluctuations of energy per 2 milliseconds */ - nSamples = 2 * psEnc->sCmn.fs_kHz; - energy_variation = 0.0f; - log_energy_prev = 0.0f; - pitch_res_ptr = pitch_res; - for( k = 0; k < SKP_SMULBB( SUB_FRAME_LENGTH_MS, psEnc->sCmn.nb_subfr ) / 2; k++ ) { - nrg = ( SKP_float )nSamples + ( SKP_float )silk_energy_FLP( pitch_res_ptr, nSamples ); - log_energy = silk_log2( nrg ); - if( k > 0 ) { - energy_variation += SKP_abs_float( log_energy - log_energy_prev ); - } - log_energy_prev = log_energy; - pitch_res_ptr += nSamples; - } - psEncCtrl->sparseness = SKP_sigmoid( 0.4f * ( energy_variation - 5.0f ) ); - - /* Set quantization offset depending on sparseness measure */ - if( psEncCtrl->sparseness > SPARSENESS_THRESHOLD_QNT_OFFSET ) { - psEnc->sCmn.indices.quantOffsetType = 0; - } else { - psEnc->sCmn.indices.quantOffsetType = 1; - } - - /* Increase coding SNR for sparse signals */ - SNR_adj_dB += SPARSE_SNR_INCR_dB * ( psEncCtrl->sparseness - 0.5f ); - } - - /*******************************/ - /* Control bandwidth expansion */ - /*******************************/ - /* More BWE for signals with high prediction gain */ - strength = FIND_PITCH_WHITE_NOISE_FRACTION * psEncCtrl->predGain; /* between 0.0 and 1.0 */ - BWExp1 = BWExp2 = BANDWIDTH_EXPANSION / ( 1.0f + strength * strength ); - delta = LOW_RATE_BANDWIDTH_EXPANSION_DELTA * ( 1.0f - 0.75f * psEncCtrl->coding_quality ); - BWExp1 -= delta; - BWExp2 += delta; - /* BWExp1 will be applied after BWExp2, so make it relative */ - BWExp1 /= BWExp2; - - if( psEnc->sCmn.warping_Q16 > 0 ) { - /* Slightly more warping in analysis will move quantization noise up in frequency, where it's better masked */ - warping = (SKP_float)psEnc->sCmn.warping_Q16 / 65536.0f + 0.01f * psEncCtrl->coding_quality; - } else { - warping = 0.0f; - } - - /********************************************/ - /* Compute noise shaping AR coefs and gains */ - /********************************************/ - for( k = 0; k < psEnc->sCmn.nb_subfr; k++ ) { - /* Apply window: sine slope followed by flat part followed by cosine slope */ - opus_int shift, slope_part, flat_part; - flat_part = psEnc->sCmn.fs_kHz * 3; - slope_part = ( psEnc->sCmn.shapeWinLength - flat_part ) / 2; - - silk_apply_sine_window_FLP( x_windowed, x_ptr, 1, slope_part ); - shift = slope_part; - SKP_memcpy( x_windowed + shift, x_ptr + shift, flat_part * sizeof(SKP_float) ); - shift += flat_part; - silk_apply_sine_window_FLP( x_windowed + shift, x_ptr + shift, 2, slope_part ); - - /* Update pointer: next LPC analysis block */ - x_ptr += psEnc->sCmn.subfr_length; - - if( psEnc->sCmn.warping_Q16 > 0 ) { - /* Calculate warped auto correlation */ - silk_warped_autocorrelation_FLP( auto_corr, x_windowed, warping, - psEnc->sCmn.shapeWinLength, psEnc->sCmn.shapingLPCOrder ); - } else { - /* Calculate regular auto correlation */ - silk_autocorrelation_FLP( auto_corr, x_windowed, psEnc->sCmn.shapeWinLength, psEnc->sCmn.shapingLPCOrder + 1 ); - } - - /* Add white noise, as a fraction of energy */ - auto_corr[ 0 ] += auto_corr[ 0 ] * SHAPE_WHITE_NOISE_FRACTION; - - /* Convert correlations to prediction coefficients, and compute residual energy */ - nrg = silk_levinsondurbin_FLP( &psEncCtrl->AR2[ k * MAX_SHAPE_LPC_ORDER ], auto_corr, psEnc->sCmn.shapingLPCOrder ); - psEncCtrl->Gains[ k ] = ( SKP_float )sqrt( nrg ); - - if( psEnc->sCmn.warping_Q16 > 0 ) { - /* Adjust gain for warping */ - psEncCtrl->Gains[ k ] *= warped_gain( &psEncCtrl->AR2[ k * MAX_SHAPE_LPC_ORDER ], warping, psEnc->sCmn.shapingLPCOrder ); - } - - /* Bandwidth expansion for synthesis filter shaping */ - silk_bwexpander_FLP( &psEncCtrl->AR2[ k * MAX_SHAPE_LPC_ORDER ], psEnc->sCmn.shapingLPCOrder, BWExp2 ); - - /* Compute noise shaping filter coefficients */ - SKP_memcpy( - &psEncCtrl->AR1[ k * MAX_SHAPE_LPC_ORDER ], - &psEncCtrl->AR2[ k * MAX_SHAPE_LPC_ORDER ], - psEnc->sCmn.shapingLPCOrder * sizeof( SKP_float ) ); - - /* Bandwidth expansion for analysis filter shaping */ - 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 ); - psEncCtrl->GainsPre[ k ] = 1.0f - 0.7f * ( 1.0f - pre_nrg / nrg ); - - /* Convert to monic warped prediction coefficients and limit absolute values */ - warped_true2monic_coefs( &psEncCtrl->AR2[ k * MAX_SHAPE_LPC_ORDER ], &psEncCtrl->AR1[ k * MAX_SHAPE_LPC_ORDER ], - warping, 3.999f, psEnc->sCmn.shapingLPCOrder ); - } - - /*****************/ - /* Gain tweaking */ - /*****************/ - /* Increase gains during low speech activity */ - gain_mult = (SKP_float)pow( 2.0f, -0.16f * SNR_adj_dB ); - gain_add = (SKP_float)pow( 2.0f, 0.16f * MIN_QGAIN_DB ); - for( k = 0; k < psEnc->sCmn.nb_subfr; k++ ) { - psEncCtrl->Gains[ k ] *= gain_mult; - psEncCtrl->Gains[ k ] += gain_add; - } - - gain_mult = 1.0f + INPUT_TILT + psEncCtrl->coding_quality * HIGH_RATE_INPUT_TILT; - for( k = 0; k < psEnc->sCmn.nb_subfr; k++ ) { - psEncCtrl->GainsPre[ k ] *= gain_mult; - } - - /************************************************/ - /* Control low-frequency shaping and noise tilt */ - /************************************************/ - /* Less low frequency shaping for noisy inputs */ - strength = LOW_FREQ_SHAPING * ( 1.0f + LOW_QUALITY_LOW_FREQ_SHAPING_DECR * ( psEnc->sCmn.input_quality_bands_Q15[ 0 ] * ( 1.0f / 32768.0f ) - 1.0f ) ); - strength *= psEnc->sCmn.speech_activity_Q8 * ( 1.0f / 256.0f ); - if( psEnc->sCmn.indices.signalType == TYPE_VOICED ) { - /* Reduce low frequencies quantization noise for periodic signals, depending on pitch lag */ - /*f = 400; freqz([1, -0.98 + 2e-4 * f], [1, -0.97 + 7e-4 * f], 2^12, Fs); axis([0, 1000, -10, 1])*/ - for( k = 0; k < psEnc->sCmn.nb_subfr; k++ ) { - b = 0.2f / psEnc->sCmn.fs_kHz + 3.0f / psEncCtrl->pitchL[ k ]; - psEncCtrl->LF_MA_shp[ k ] = -1.0f + b; - psEncCtrl->LF_AR_shp[ k ] = 1.0f - b - b * strength; - } - Tilt = - HP_NOISE_COEF - - (1 - HP_NOISE_COEF) * HARM_HP_NOISE_COEF * psEnc->sCmn.speech_activity_Q8 * ( 1.0f / 256.0f ); - } else { - b = 1.3f / psEnc->sCmn.fs_kHz; - psEncCtrl->LF_MA_shp[ 0 ] = -1.0f + b; - psEncCtrl->LF_AR_shp[ 0 ] = 1.0f - b - b * strength * 0.6f; - for( k = 1; k < psEnc->sCmn.nb_subfr; k++ ) { - psEncCtrl->LF_MA_shp[ k ] = psEncCtrl->LF_MA_shp[ 0 ]; - psEncCtrl->LF_AR_shp[ k ] = psEncCtrl->LF_AR_shp[ 0 ]; - } - Tilt = -HP_NOISE_COEF; - } - - /****************************/ - /* HARMONIC SHAPING CONTROL */ - /****************************/ - /* Control boosting of harmonic frequencies */ - HarmBoost = LOW_RATE_HARMONIC_BOOST * ( 1.0f - psEncCtrl->coding_quality ) * psEnc->LTPCorr; - - /* More harmonic boost for noisy input signals */ - HarmBoost += LOW_INPUT_QUALITY_HARMONIC_BOOST * ( 1.0f - psEncCtrl->input_quality ); - - if( USE_HARM_SHAPING && psEnc->sCmn.indices.signalType == TYPE_VOICED ) { - /* Harmonic noise shaping */ - HarmShapeGain = HARMONIC_SHAPING; - - /* More harmonic noise shaping for high bitrates or noisy input */ - HarmShapeGain += HIGH_RATE_OR_LOW_QUALITY_HARMONIC_SHAPING * - ( 1.0f - ( 1.0f - psEncCtrl->coding_quality ) * psEncCtrl->input_quality ); - - /* Less harmonic noise shaping for less periodic signals */ - HarmShapeGain *= ( SKP_float )sqrt( psEnc->LTPCorr ); - } else { - HarmShapeGain = 0.0f; - } - - /*************************/ - /* Smooth over subframes */ - /*************************/ - for( k = 0; k < psEnc->sCmn.nb_subfr; k++ ) { - psShapeSt->HarmBoost_smth += SUBFR_SMTH_COEF * ( HarmBoost - psShapeSt->HarmBoost_smth ); - psEncCtrl->HarmBoost[ k ] = psShapeSt->HarmBoost_smth; - psShapeSt->HarmShapeGain_smth += SUBFR_SMTH_COEF * ( HarmShapeGain - psShapeSt->HarmShapeGain_smth ); - psEncCtrl->HarmShapeGain[ k ] = psShapeSt->HarmShapeGain_smth; - psShapeSt->Tilt_smth += SUBFR_SMTH_COEF * ( Tilt - psShapeSt->Tilt_smth ); - psEncCtrl->Tilt[ k ] = psShapeSt->Tilt_smth; - } -} +/*********************************************************************** +Copyright (c) 2006-2011, Skype Limited. All rights reserved. +Redistribution and use in source and binary forms, with or without +modification, (subject to the limitations in the disclaimer below) +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 Skype Limited, nor the names of specific +contributors, may be used to endorse or promote products derived from +this software without specific prior written permission. +NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED +BY THIS LICENSE. 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. +***********************************************************************/ + +#include "silk_main_FLP.h" +#include "silk_tuning_parameters.h" + +/* Compute gain to make warped filter coefficients have a zero mean log frequency response on a */ +/* non-warped frequency scale. (So that it can be implemented with a minimum-phase monic filter.) */ +SKP_INLINE SKP_float warped_gain( + const SKP_float *coefs, + SKP_float lambda, + opus_int order +) { + opus_int i; + SKP_float gain; + + lambda = -lambda; + gain = coefs[ order - 1 ]; + for( i = order - 2; i >= 0; i-- ) { + gain = lambda * gain + coefs[ i ]; + } + return (SKP_float)( 1.0f / ( 1.0f - lambda * gain ) ); +} + +/* Convert warped filter coefficients to monic pseudo-warped coefficients and limit maximum */ +/* amplitude of monic warped coefficients by using bandwidth expansion on the true coefficients */ +SKP_INLINE void warped_true2monic_coefs( + SKP_float *coefs_syn, + SKP_float *coefs_ana, + SKP_float lambda, + SKP_float limit, + opus_int order +) { + opus_int i, iter, ind = 0; + SKP_float tmp, maxabs, chirp, gain_syn, gain_ana; + + /* Convert to monic coefficients */ + for( i = order - 1; i > 0; i-- ) { + coefs_syn[ i - 1 ] -= lambda * coefs_syn[ i ]; + coefs_ana[ i - 1 ] -= lambda * coefs_ana[ i ]; + } + gain_syn = ( 1.0f - lambda * lambda ) / ( 1.0f + lambda * coefs_syn[ 0 ] ); + gain_ana = ( 1.0f - lambda * lambda ) / ( 1.0f + lambda * coefs_ana[ 0 ] ); + for( i = 0; i < order; i++ ) { + coefs_syn[ i ] *= gain_syn; + coefs_ana[ i ] *= gain_ana; + } + + /* Limit */ + for( iter = 0; iter < 10; iter++ ) { + /* Find maximum absolute value */ + maxabs = -1.0f; + for( i = 0; i < order; i++ ) { + tmp = SKP_max( SKP_abs_float( coefs_syn[ i ] ), SKP_abs_float( coefs_ana[ i ] ) ); + if( tmp > maxabs ) { + maxabs = tmp; + ind = i; + } + } + if( maxabs <= limit ) { + /* Coefficients are within range - done */ + return; + } + + /* Convert back to true warped coefficients */ + for( i = 1; i < order; i++ ) { + coefs_syn[ i - 1 ] += lambda * coefs_syn[ i ]; + coefs_ana[ i - 1 ] += lambda * coefs_ana[ i ]; + } + gain_syn = 1.0f / gain_syn; + gain_ana = 1.0f / gain_ana; + for( i = 0; i < order; i++ ) { + coefs_syn[ i ] *= gain_syn; + coefs_ana[ i ] *= gain_ana; + } + + /* Apply bandwidth expansion */ + chirp = 0.99f - ( 0.8f + 0.1f * iter ) * ( maxabs - limit ) / ( maxabs * ( ind + 1 ) ); + silk_bwexpander_FLP( coefs_syn, order, chirp ); + silk_bwexpander_FLP( coefs_ana, order, chirp ); + + /* Convert to monic warped coefficients */ + for( i = order - 1; i > 0; i-- ) { + coefs_syn[ i - 1 ] -= lambda * coefs_syn[ i ]; + coefs_ana[ i - 1 ] -= lambda * coefs_ana[ i ]; + } + gain_syn = ( 1.0f - lambda * lambda ) / ( 1.0f + lambda * coefs_syn[ 0 ] ); + gain_ana = ( 1.0f - lambda * lambda ) / ( 1.0f + lambda * coefs_ana[ 0 ] ); + for( i = 0; i < order; i++ ) { + coefs_syn[ i ] *= gain_syn; + coefs_ana[ i ] *= gain_ana; + } + } + SKP_assert( 0 ); +} + +/* Compute noise shaping coefficients and initial gain values */ +void silk_noise_shape_analysis_FLP( + silk_encoder_state_FLP *psEnc, /* I/O Encoder state FLP */ + silk_encoder_control_FLP *psEncCtrl, /* I/O Encoder control FLP */ + const SKP_float *pitch_res, /* I LPC residual from pitch analysis */ + const SKP_float *x /* I Input signal [frame_length + la_shape] */ +) +{ + silk_shape_state_FLP *psShapeSt = &psEnc->sShape; + opus_int k, nSamples; + SKP_float SNR_adj_dB, HarmBoost, HarmShapeGain, Tilt; + SKP_float nrg, pre_nrg, log_energy, log_energy_prev, energy_variation; + SKP_float delta, BWExp1, BWExp2, gain_mult, gain_add, strength, b, warping; + SKP_float x_windowed[ SHAPE_LPC_WIN_MAX ]; + SKP_float auto_corr[ MAX_SHAPE_LPC_ORDER + 1 ]; + const SKP_float *x_ptr, *pitch_res_ptr; + + /* Point to start of first LPC analysis block */ + x_ptr = x - psEnc->sCmn.la_shape; + + /****************/ + /* GAIN CONTROL */ + /****************/ + SNR_adj_dB = psEnc->sCmn.SNR_dB_Q7 * ( 1 / 128.0f ); + + /* Input quality is the average of the quality in the lowest two VAD bands */ + 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 = SKP_sigmoid( 0.25f * ( SNR_adj_dB - 18.0f ) ); + + if( psEnc->sCmn.useCBR == 0 ) { + /* Reduce coding SNR during low speech activity */ + b = 1.0f - psEnc->sCmn.speech_activity_Q8 * ( 1.0f / 256.0f ); + SNR_adj_dB -= BG_SNR_DECR_dB * psEncCtrl->coding_quality * ( 0.5f + 0.5f * psEncCtrl->input_quality ) * b * b; + } + + if( psEnc->sCmn.indices.signalType == TYPE_VOICED ) { + /* Reduce gains for periodic signals */ + SNR_adj_dB += HARM_SNR_INCR_dB * psEnc->LTPCorr; + } else { + /* For unvoiced signals and low-quality input, adjust the quality slower than SNR_dB setting */ + SNR_adj_dB += ( -0.4f * psEnc->sCmn.SNR_dB_Q7 * ( 1 / 128.0f ) + 6.0f ) * ( 1.0f - psEncCtrl->input_quality ); + } + + /*************************/ + /* SPARSENESS PROCESSING */ + /*************************/ + /* Set quantizer offset */ + if( psEnc->sCmn.indices.signalType == TYPE_VOICED ) { + /* Initally set to 0; may be overruled in process_gains(..) */ + psEnc->sCmn.indices.quantOffsetType = 0; + psEncCtrl->sparseness = 0.0f; + } else { + /* Sparseness measure, based on relative fluctuations of energy per 2 milliseconds */ + nSamples = 2 * psEnc->sCmn.fs_kHz; + energy_variation = 0.0f; + log_energy_prev = 0.0f; + pitch_res_ptr = pitch_res; + for( k = 0; k < SKP_SMULBB( SUB_FRAME_LENGTH_MS, psEnc->sCmn.nb_subfr ) / 2; k++ ) { + nrg = ( SKP_float )nSamples + ( SKP_float )silk_energy_FLP( pitch_res_ptr, nSamples ); + log_energy = silk_log2( nrg ); + if( k > 0 ) { + energy_variation += SKP_abs_float( log_energy - log_energy_prev ); + } + log_energy_prev = log_energy; + pitch_res_ptr += nSamples; + } + psEncCtrl->sparseness = SKP_sigmoid( 0.4f * ( energy_variation - 5.0f ) ); + + /* Set quantization offset depending on sparseness measure */ + if( psEncCtrl->sparseness > SPARSENESS_THRESHOLD_QNT_OFFSET ) { + psEnc->sCmn.indices.quantOffsetType = 0; + } else { + psEnc->sCmn.indices.quantOffsetType = 1; + } + + /* Increase coding SNR for sparse signals */ + SNR_adj_dB += SPARSE_SNR_INCR_dB * ( psEncCtrl->sparseness - 0.5f ); + } + + /*******************************/ + /* Control bandwidth expansion */ + /*******************************/ + /* More BWE for signals with high prediction gain */ + strength = FIND_PITCH_WHITE_NOISE_FRACTION * psEncCtrl->predGain; /* between 0.0 and 1.0 */ + BWExp1 = BWExp2 = BANDWIDTH_EXPANSION / ( 1.0f + strength * strength ); + delta = LOW_RATE_BANDWIDTH_EXPANSION_DELTA * ( 1.0f - 0.75f * psEncCtrl->coding_quality ); + BWExp1 -= delta; + BWExp2 += delta; + /* BWExp1 will be applied after BWExp2, so make it relative */ + BWExp1 /= BWExp2; + + if( psEnc->sCmn.warping_Q16 > 0 ) { + /* Slightly more warping in analysis will move quantization noise up in frequency, where it's better masked */ + warping = (SKP_float)psEnc->sCmn.warping_Q16 / 65536.0f + 0.01f * psEncCtrl->coding_quality; + } else { + warping = 0.0f; + } + + /********************************************/ + /* Compute noise shaping AR coefs and gains */ + /********************************************/ + for( k = 0; k < psEnc->sCmn.nb_subfr; k++ ) { + /* Apply window: sine slope followed by flat part followed by cosine slope */ + opus_int shift, slope_part, flat_part; + flat_part = psEnc->sCmn.fs_kHz * 3; + slope_part = ( psEnc->sCmn.shapeWinLength - flat_part ) / 2; + + silk_apply_sine_window_FLP( x_windowed, x_ptr, 1, slope_part ); + shift = slope_part; + SKP_memcpy( x_windowed + shift, x_ptr + shift, flat_part * sizeof(SKP_float) ); + shift += flat_part; + silk_apply_sine_window_FLP( x_windowed + shift, x_ptr + shift, 2, slope_part ); + + /* Update pointer: next LPC analysis block */ + x_ptr += psEnc->sCmn.subfr_length; + + if( psEnc->sCmn.warping_Q16 > 0 ) { + /* Calculate warped auto correlation */ + silk_warped_autocorrelation_FLP( auto_corr, x_windowed, warping, + psEnc->sCmn.shapeWinLength, psEnc->sCmn.shapingLPCOrder ); + } else { + /* Calculate regular auto correlation */ + silk_autocorrelation_FLP( auto_corr, x_windowed, psEnc->sCmn.shapeWinLength, psEnc->sCmn.shapingLPCOrder + 1 ); + } + + /* Add white noise, as a fraction of energy */ + auto_corr[ 0 ] += auto_corr[ 0 ] * SHAPE_WHITE_NOISE_FRACTION; + + /* Convert correlations to prediction coefficients, and compute residual energy */ + nrg = silk_levinsondurbin_FLP( &psEncCtrl->AR2[ k * MAX_SHAPE_LPC_ORDER ], auto_corr, psEnc->sCmn.shapingLPCOrder ); + psEncCtrl->Gains[ k ] = ( SKP_float )sqrt( nrg ); + + if( psEnc->sCmn.warping_Q16 > 0 ) { + /* Adjust gain for warping */ + psEncCtrl->Gains[ k ] *= warped_gain( &psEncCtrl->AR2[ k * MAX_SHAPE_LPC_ORDER ], warping, psEnc->sCmn.shapingLPCOrder ); + } + + /* Bandwidth expansion for synthesis filter shaping */ + silk_bwexpander_FLP( &psEncCtrl->AR2[ k * MAX_SHAPE_LPC_ORDER ], psEnc->sCmn.shapingLPCOrder, BWExp2 ); + + /* Compute noise shaping filter coefficients */ + SKP_memcpy( + &psEncCtrl->AR1[ k * MAX_SHAPE_LPC_ORDER ], + &psEncCtrl->AR2[ k * MAX_SHAPE_LPC_ORDER ], + psEnc->sCmn.shapingLPCOrder * sizeof( SKP_float ) ); + + /* Bandwidth expansion for analysis filter shaping */ + 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 ); + psEncCtrl->GainsPre[ k ] = 1.0f - 0.7f * ( 1.0f - pre_nrg / nrg ); + + /* Convert to monic warped prediction coefficients and limit absolute values */ + warped_true2monic_coefs( &psEncCtrl->AR2[ k * MAX_SHAPE_LPC_ORDER ], &psEncCtrl->AR1[ k * MAX_SHAPE_LPC_ORDER ], + warping, 3.999f, psEnc->sCmn.shapingLPCOrder ); + } + + /*****************/ + /* Gain tweaking */ + /*****************/ + /* Increase gains during low speech activity */ + gain_mult = (SKP_float)pow( 2.0f, -0.16f * SNR_adj_dB ); + gain_add = (SKP_float)pow( 2.0f, 0.16f * MIN_QGAIN_DB ); + for( k = 0; k < psEnc->sCmn.nb_subfr; k++ ) { + psEncCtrl->Gains[ k ] *= gain_mult; + psEncCtrl->Gains[ k ] += gain_add; + } + + gain_mult = 1.0f + INPUT_TILT + psEncCtrl->coding_quality * HIGH_RATE_INPUT_TILT; + for( k = 0; k < psEnc->sCmn.nb_subfr; k++ ) { + psEncCtrl->GainsPre[ k ] *= gain_mult; + } + + /************************************************/ + /* Control low-frequency shaping and noise tilt */ + /************************************************/ + /* Less low frequency shaping for noisy inputs */ + strength = LOW_FREQ_SHAPING * ( 1.0f + LOW_QUALITY_LOW_FREQ_SHAPING_DECR * ( psEnc->sCmn.input_quality_bands_Q15[ 0 ] * ( 1.0f / 32768.0f ) - 1.0f ) ); + strength *= psEnc->sCmn.speech_activity_Q8 * ( 1.0f / 256.0f ); + if( psEnc->sCmn.indices.signalType == TYPE_VOICED ) { + /* Reduce low frequencies quantization noise for periodic signals, depending on pitch lag */ + /*f = 400; freqz([1, -0.98 + 2e-4 * f], [1, -0.97 + 7e-4 * f], 2^12, Fs); axis([0, 1000, -10, 1])*/ + for( k = 0; k < psEnc->sCmn.nb_subfr; k++ ) { + b = 0.2f / psEnc->sCmn.fs_kHz + 3.0f / psEncCtrl->pitchL[ k ]; + psEncCtrl->LF_MA_shp[ k ] = -1.0f + b; + psEncCtrl->LF_AR_shp[ k ] = 1.0f - b - b * strength; + } + Tilt = - HP_NOISE_COEF - + (1 - HP_NOISE_COEF) * HARM_HP_NOISE_COEF * psEnc->sCmn.speech_activity_Q8 * ( 1.0f / 256.0f ); + } else { + b = 1.3f / psEnc->sCmn.fs_kHz; + psEncCtrl->LF_MA_shp[ 0 ] = -1.0f + b; + psEncCtrl->LF_AR_shp[ 0 ] = 1.0f - b - b * strength * 0.6f; + for( k = 1; k < psEnc->sCmn.nb_subfr; k++ ) { + psEncCtrl->LF_MA_shp[ k ] = psEncCtrl->LF_MA_shp[ 0 ]; + psEncCtrl->LF_AR_shp[ k ] = psEncCtrl->LF_AR_shp[ 0 ]; + } + Tilt = -HP_NOISE_COEF; + } + + /****************************/ + /* HARMONIC SHAPING CONTROL */ + /****************************/ + /* Control boosting of harmonic frequencies */ + HarmBoost = LOW_RATE_HARMONIC_BOOST * ( 1.0f - psEncCtrl->coding_quality ) * psEnc->LTPCorr; + + /* More harmonic boost for noisy input signals */ + HarmBoost += LOW_INPUT_QUALITY_HARMONIC_BOOST * ( 1.0f - psEncCtrl->input_quality ); + + if( USE_HARM_SHAPING && psEnc->sCmn.indices.signalType == TYPE_VOICED ) { + /* Harmonic noise shaping */ + HarmShapeGain = HARMONIC_SHAPING; + + /* More harmonic noise shaping for high bitrates or noisy input */ + HarmShapeGain += HIGH_RATE_OR_LOW_QUALITY_HARMONIC_SHAPING * + ( 1.0f - ( 1.0f - psEncCtrl->coding_quality ) * psEncCtrl->input_quality ); + + /* Less harmonic noise shaping for less periodic signals */ + HarmShapeGain *= ( SKP_float )sqrt( psEnc->LTPCorr ); + } else { + HarmShapeGain = 0.0f; + } + + /*************************/ + /* Smooth over subframes */ + /*************************/ + for( k = 0; k < psEnc->sCmn.nb_subfr; k++ ) { + psShapeSt->HarmBoost_smth += SUBFR_SMTH_COEF * ( HarmBoost - psShapeSt->HarmBoost_smth ); + psEncCtrl->HarmBoost[ k ] = psShapeSt->HarmBoost_smth; + psShapeSt->HarmShapeGain_smth += SUBFR_SMTH_COEF * ( HarmShapeGain - psShapeSt->HarmShapeGain_smth ); + psEncCtrl->HarmShapeGain[ k ] = psShapeSt->HarmShapeGain_smth; + psShapeSt->Tilt_smth += SUBFR_SMTH_COEF * ( Tilt - psShapeSt->Tilt_smth ); + psEncCtrl->Tilt[ k ] = psShapeSt->Tilt_smth; + } +} diff --git a/silk/float/silk_pitch_analysis_core_FLP.c b/silk/float/silk_pitch_analysis_core_FLP.c index cc7486677..35c5dc02b 100644 --- a/silk/float/silk_pitch_analysis_core_FLP.c +++ b/silk/float/silk_pitch_analysis_core_FLP.c @@ -1,632 +1,632 @@ -/*********************************************************************** -Copyright (c) 2006-2011, Skype Limited. All rights reserved. -Redistribution and use in source and binary forms, with or without -modification, (subject to the limitations in the disclaimer below) -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 Skype Limited, nor the names of specific -contributors, may be used to endorse or promote products derived from -this software without specific prior written permission. -NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED -BY THIS LICENSE. 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. -***********************************************************************/ - -/***************************************************************************** -* -* Pitch analyser function -* -******************************************************************************/ -#include "silk_SigProc_FLP.h" -#include "silk_SigProc_FIX.h" -#include "silk_pitch_est_defines.h" - -#define SCRATCH_SIZE 22 - -/************************************************************/ -/* Definitions */ -/************************************************************/ -#define eps 1.192092896e-07f - -/************************************************************/ -/* Internally used functions */ -/************************************************************/ -static void silk_P_Ana_calc_corr_st3( - SKP_float cross_corr_st3[ PE_MAX_NB_SUBFR ][ PE_NB_CBKS_STAGE3_MAX ][ PE_NB_STAGE3_LAGS ], /* O 3 DIM correlation array */ - const SKP_float signal[], /* I vector to correlate */ - opus_int start_lag, /* I start lag */ - opus_int sf_length, /* I sub frame length */ - opus_int nb_subfr, /* I number of subframes */ - opus_int complexity /* I Complexity setting */ -); - -static void silk_P_Ana_calc_energy_st3( - SKP_float energies_st3[ PE_MAX_NB_SUBFR ][ PE_NB_CBKS_STAGE3_MAX ][ PE_NB_STAGE3_LAGS ], /* O 3 DIM correlation array */ - const SKP_float signal[], /* I vector to correlate */ - opus_int start_lag, /* I start lag */ - opus_int sf_length, /* I sub frame length */ - opus_int nb_subfr, /* I number of subframes */ - opus_int complexity /* I Complexity setting */ -); - -//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -//% CORE PITCH ANALYSIS FUNCTION % -//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -opus_int silk_pitch_analysis_core_FLP( /* O voicing estimate: 0 voiced, 1 unvoiced */ - const SKP_float *signal, /* I signal of length PE_FRAME_LENGTH_MS*Fs_kHz */ - opus_int *pitch_out, /* O 4 pitch lag values */ - opus_int16 *lagIndex, /* O lag Index */ - opus_int8 *contourIndex, /* O pitch contour Index */ - SKP_float *LTPCorr, /* I/O normalized correlation; input: value from previous frame */ - opus_int prevLag, /* I last lag of previous frame; set to zero is unvoiced */ - const SKP_float search_thres1, /* I first stage threshold for lag candidates 0 - 1 */ - const SKP_float search_thres2, /* I final threshold for lag candidates 0 - 1 */ - const opus_int Fs_kHz, /* I sample frequency (kHz) */ - const opus_int complexity, /* I Complexity setting, 0-2, where 2 is highest */ - const opus_int nb_subfr /* I number of 5 ms subframes */ -) -{ - opus_int i, k, d, j; - SKP_float signal_8kHz[ PE_MAX_FRAME_LENGTH_MS * 8 ]; - SKP_float signal_4kHz[ PE_MAX_FRAME_LENGTH_MS * 4 ]; - opus_int16 signal_8_FIX[ PE_MAX_FRAME_LENGTH_MS * 8 ]; - opus_int16 signal_4_FIX[ PE_MAX_FRAME_LENGTH_MS * 4 ]; - opus_int32 filt_state[ 6 ]; - SKP_float threshold, contour_bias; - SKP_float C[ PE_MAX_NB_SUBFR][ (PE_MAX_LAG >> 1) + 5 ]; - SKP_float CC[ PE_NB_CBKS_STAGE2_EXT ]; - const SKP_float *target_ptr, *basis_ptr; - double cross_corr, normalizer, energy, energy_tmp; - opus_int d_srch[ PE_D_SRCH_LENGTH ]; - opus_int16 d_comp[ (PE_MAX_LAG >> 1) + 5 ]; - opus_int length_d_srch, length_d_comp; - SKP_float Cmax, CCmax, CCmax_b, CCmax_new_b, CCmax_new; - opus_int CBimax, CBimax_new, lag, start_lag, end_lag, lag_new; - opus_int cbk_size; - SKP_float lag_log2, prevLag_log2, delta_lag_log2_sqr; - SKP_float energies_st3[ PE_MAX_NB_SUBFR ][ PE_NB_CBKS_STAGE3_MAX ][ PE_NB_STAGE3_LAGS ]; - SKP_float cross_corr_st3[ PE_MAX_NB_SUBFR ][ PE_NB_CBKS_STAGE3_MAX ][ PE_NB_STAGE3_LAGS ]; - opus_int lag_counter; - opus_int frame_length, frame_length_8kHz, frame_length_4kHz; - opus_int sf_length, sf_length_8kHz, sf_length_4kHz; - opus_int min_lag, min_lag_8kHz, min_lag_4kHz; - opus_int max_lag, max_lag_8kHz, max_lag_4kHz; - opus_int nb_cbk_search; - const opus_int8 *Lag_CB_ptr; - - /* Check for valid sampling frequency */ - SKP_assert( Fs_kHz == 8 || Fs_kHz == 12 || Fs_kHz == 16 ); - - /* Check for valid complexity setting */ - SKP_assert( complexity >= SigProc_PE_MIN_COMPLEX ); - SKP_assert( complexity <= SigProc_PE_MAX_COMPLEX ); - - SKP_assert( search_thres1 >= 0.0f && search_thres1 <= 1.0f ); - SKP_assert( search_thres2 >= 0.0f && search_thres2 <= 1.0f ); - - /* Setup 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; - sf_length = PE_SUBFR_LENGTH_MS * Fs_kHz; - sf_length_4kHz = PE_SUBFR_LENGTH_MS * 4; - sf_length_8kHz = PE_SUBFR_LENGTH_MS * 8; - min_lag = PE_MIN_LAG_MS * Fs_kHz; - min_lag_4kHz = PE_MIN_LAG_MS * 4; - min_lag_8kHz = PE_MIN_LAG_MS * 8; - max_lag = PE_MAX_LAG_MS * Fs_kHz - 1; - max_lag_4kHz = PE_MAX_LAG_MS * 4; - max_lag_8kHz = PE_MAX_LAG_MS * 8 - 1; - - SKP_memset(C, 0, sizeof(SKP_float) * nb_subfr * ((PE_MAX_LAG >> 1) + 5)); - - /* Resample from input sampled at Fs_kHz to 8 kHz */ - if( Fs_kHz == 16 ) { - /* Resample to 16 -> 8 khz */ - opus_int16 signal_16_FIX[ 16 * PE_MAX_FRAME_LENGTH_MS ]; - SKP_float2short_array( signal_16_FIX, signal, frame_length ); - SKP_memset( filt_state, 0, 2 * sizeof( opus_int32 ) ); - silk_resampler_down2( filt_state, signal_8_FIX, signal_16_FIX, frame_length ); - SKP_short2float_array( signal_8kHz, signal_8_FIX, frame_length_8kHz ); - } else if( Fs_kHz == 12 ) { - /* Resample to 12 -> 8 khz */ - opus_int16 signal_12_FIX[ 12 * PE_MAX_FRAME_LENGTH_MS ]; - SKP_float2short_array( signal_12_FIX, signal, frame_length ); - SKP_memset( filt_state, 0, 6 * sizeof( opus_int32 ) ); - silk_resampler_down2_3( filt_state, signal_8_FIX, signal_12_FIX, frame_length ); - SKP_short2float_array( signal_8kHz, signal_8_FIX, frame_length_8kHz ); - } else { - SKP_assert( Fs_kHz == 8 ); - SKP_float2short_array( signal_8_FIX, signal, frame_length_8kHz ); - } - - /* Decimate again to 4 kHz */ - SKP_memset( filt_state, 0, 2 * sizeof( opus_int32 ) ); - silk_resampler_down2( filt_state, signal_4_FIX, signal_8_FIX, frame_length_8kHz ); - SKP_short2float_array( signal_4kHz, signal_4_FIX, frame_length_4kHz ); - - /* Low-pass filter */ - for( i = frame_length_4kHz - 1; i > 0; i-- ) { - signal_4kHz[ i ] += signal_4kHz[ i - 1 ]; - } - - /****************************************************************************** - * FIRST STAGE, operating in 4 khz - ******************************************************************************/ - target_ptr = &signal_4kHz[ SKP_LSHIFT( sf_length_4kHz, 2 ) ]; - for( k = 0; k < nb_subfr >> 1; k++ ) { - /* Check that we are within range of the array */ - SKP_assert( target_ptr >= signal_4kHz ); - SKP_assert( target_ptr + sf_length_8kHz <= signal_4kHz + frame_length_4kHz ); - - basis_ptr = target_ptr - min_lag_4kHz; - - /* Check that we are within range of the array */ - SKP_assert( basis_ptr >= signal_4kHz ); - SKP_assert( basis_ptr + sf_length_8kHz <= signal_4kHz + frame_length_4kHz ); - - /* Calculate first vector products before loop */ - cross_corr = silk_inner_product_FLP( target_ptr, basis_ptr, sf_length_8kHz ); - normalizer = silk_energy_FLP( basis_ptr, sf_length_8kHz ) + sf_length_8kHz * 4000.0f; - - C[ 0 ][ min_lag_4kHz ] += (SKP_float)(cross_corr / sqrt(normalizer)); - - /* From now on normalizer is computed recursively */ - for(d = min_lag_4kHz + 1; d <= max_lag_4kHz; d++) { - basis_ptr--; - - /* Check that we are within range of the array */ - SKP_assert( basis_ptr >= signal_4kHz ); - SKP_assert( basis_ptr + sf_length_8kHz <= signal_4kHz + frame_length_4kHz ); - - cross_corr = silk_inner_product_FLP(target_ptr, basis_ptr, sf_length_8kHz); - - /* Add contribution of new sample and remove contribution from oldest sample */ - normalizer += - basis_ptr[ 0 ] * basis_ptr[ 0 ] - - basis_ptr[ sf_length_8kHz ] * basis_ptr[ sf_length_8kHz ]; - C[ 0 ][ d ] += (SKP_float)(cross_corr / sqrt( normalizer )); - } - /* Update target pointer */ - target_ptr += sf_length_8kHz; - } - - /* Apply short-lag bias */ - for( i = max_lag_4kHz; i >= min_lag_4kHz; i-- ) { - C[ 0 ][ i ] -= C[ 0 ][ i ] * i / 4096.0f; - } - - /* Sort */ - length_d_srch = 4 + 2 * complexity; - SKP_assert( 3 * length_d_srch <= PE_D_SRCH_LENGTH ); - silk_insertion_sort_decreasing_FLP( &C[ 0 ][ min_lag_4kHz ], d_srch, max_lag_4kHz - min_lag_4kHz + 1, length_d_srch ); - - /* Escape if correlation is very low already here */ - Cmax = C[ 0 ][ min_lag_4kHz ]; - target_ptr = &signal_4kHz[ SKP_SMULBB( sf_length_4kHz, nb_subfr ) ]; - energy = 1000.0f; - for( i = 0; i < SKP_LSHIFT( sf_length_4kHz, 2 ); i++ ) { - energy += target_ptr[i] * target_ptr[i]; - } - threshold = Cmax * Cmax; - if( energy / 16.0f > threshold ) { - SKP_memset( pitch_out, 0, nb_subfr * sizeof( opus_int ) ); - *LTPCorr = 0.0f; - *lagIndex = 0; - *contourIndex = 0; - return 1; - } - - threshold = search_thres1 * Cmax; - for( i = 0; i < length_d_srch; i++ ) { - /* Convert to 8 kHz indices for the sorted correlation that exceeds the threshold */ - if( C[ 0 ][ min_lag_4kHz + i ] > threshold ) { - d_srch[ i ] = SKP_LSHIFT( d_srch[ i ] + min_lag_4kHz, 1 ); - } else { - length_d_srch = i; - break; - } - } - SKP_assert( length_d_srch > 0 ); - - for( i = min_lag_8kHz - 5; i < max_lag_8kHz + 5; i++ ) { - d_comp[ i ] = 0; - } - for( i = 0; i < length_d_srch; i++ ) { - d_comp[ d_srch[ i ] ] = 1; - } - - /* Convolution */ - for( i = max_lag_8kHz + 3; i >= min_lag_8kHz; i-- ) { - d_comp[ i ] += d_comp[ i - 1 ] + d_comp[ i - 2 ]; - } - - length_d_srch = 0; - for( i = min_lag_8kHz; i < max_lag_8kHz + 1; i++ ) { - if( d_comp[ i + 1 ] > 0 ) { - d_srch[ length_d_srch ] = i; - length_d_srch++; - } - } - - /* Convolution */ - for( i = max_lag_8kHz + 3; i >= min_lag_8kHz; i-- ) { - d_comp[ i ] += d_comp[ i - 1 ] + d_comp[ i - 2 ] + d_comp[ i - 3 ]; - } - - length_d_comp = 0; - for( i = min_lag_8kHz; i < max_lag_8kHz + 4; i++ ) { - if( d_comp[ i ] > 0 ) { - d_comp[ length_d_comp ] = (opus_int16)( i - 2 ); - length_d_comp++; - } - } - - /********************************************************************************** - ** SECOND STAGE, operating at 8 kHz, on lag sections with high correlation - *************************************************************************************/ - /********************************************************************************* - * Find energy of each subframe projected onto its history, for a range of delays - *********************************************************************************/ - SKP_memset( C, 0, PE_MAX_NB_SUBFR*((PE_MAX_LAG >> 1) + 5) * sizeof(SKP_float)); // Is this needed? - - if( Fs_kHz == 8 ) { - target_ptr = &signal[ PE_LTP_MEM_LENGTH_MS * 8 ]; - } else { - target_ptr = &signal_8kHz[ PE_LTP_MEM_LENGTH_MS * 8 ]; - } - for( k = 0; k < nb_subfr; k++ ) { - energy_tmp = silk_energy_FLP( target_ptr, sf_length_8kHz ); - for( j = 0; j < length_d_comp; j++ ) { - d = d_comp[ j ]; - basis_ptr = target_ptr - d; - cross_corr = silk_inner_product_FLP( basis_ptr, target_ptr, sf_length_8kHz ); - energy = silk_energy_FLP( basis_ptr, sf_length_8kHz ); - if (cross_corr > 0.0f) { - C[ k ][ d ] = (SKP_float)(cross_corr * cross_corr / (energy * energy_tmp + eps)); - } else { - C[ k ][ d ] = 0.0f; - } - } - target_ptr += sf_length_8kHz; - } - - /* search over lag range and lags codebook */ - /* scale factor for lag codebook, as a function of center lag */ - - CCmax = 0.0f; /* This value doesn't matter */ - CCmax_b = -1000.0f; - - CBimax = 0; /* To avoid returning undefined lag values */ - lag = -1; /* To check if lag with strong enough correlation has been found */ - - if( prevLag > 0 ) { - if( Fs_kHz == 12 ) { - prevLag = SKP_LSHIFT( prevLag, 1 ) / 3; - } else if( Fs_kHz == 16 ) { - prevLag = SKP_RSHIFT( prevLag, 1 ); - } - prevLag_log2 = silk_log2((SKP_float)prevLag); - } else { - prevLag_log2 = 0; - } - - /* Setup 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 ]; - if( Fs_kHz == 8 && complexity > SigProc_PE_MIN_COMPLEX ) { - /* If input is 8 khz use a larger codebook here because it is last stage */ - nb_cbk_search = PE_NB_CBKS_STAGE2_EXT; - } else { - nb_cbk_search = PE_NB_CBKS_STAGE2; - } - } else { - cbk_size = PE_NB_CBKS_STAGE2_10MS; - Lag_CB_ptr = &silk_CB_lags_stage2_10_ms[ 0 ][ 0 ]; - nb_cbk_search = PE_NB_CBKS_STAGE2_10MS; - } - - for( k = 0; k < length_d_srch; k++ ) { - d = d_srch[ k ]; - for( j = 0; j < nb_cbk_search; j++ ) { - CC[j] = 0.0f; - for( i = 0; i < nb_subfr; i++ ) { - /* Try all codebooks */ - CC[ j ] += C[ i ][ d + matrix_ptr( Lag_CB_ptr, i, j, cbk_size )]; - } - } - /* Find best codebook */ - CCmax_new = -1000.0f; - CBimax_new = 0; - for( i = 0; i < nb_cbk_search; i++ ) { - if( CC[ i ] > CCmax_new ) { - CCmax_new = CC[ i ]; - CBimax_new = i; - } - } - CCmax_new = SKP_max_float(CCmax_new, 0.0f); /* To avoid taking square root of negative number later */ - CCmax_new_b = CCmax_new; - - /* Bias towards shorter lags */ - lag_log2 = silk_log2((SKP_float)d); - CCmax_new_b -= PE_SHORTLAG_BIAS * nb_subfr * lag_log2; - - /* Bias towards previous lag */ - if ( prevLag > 0 ) { - delta_lag_log2_sqr = lag_log2 - prevLag_log2; - delta_lag_log2_sqr *= delta_lag_log2_sqr; - CCmax_new_b -= PE_PREVLAG_BIAS * nb_subfr * (*LTPCorr) * delta_lag_log2_sqr / (delta_lag_log2_sqr + 0.5f); - } - - if ( CCmax_new_b > CCmax_b && /* Find maximum biased correlation */ - CCmax_new > nb_subfr * search_thres2 * search_thres2 && /* Correlation needs to be high enough to be voiced */ - silk_CB_lags_stage2[ 0 ][ CBimax_new ] <= min_lag_8kHz /* Lag must be in range */ - ) { - CCmax_b = CCmax_new_b; - CCmax = CCmax_new; - lag = d; - CBimax = CBimax_new; - } - } - - if( lag == -1 ) { - /* No suitable candidate found */ - SKP_memset( pitch_out, 0, PE_MAX_NB_SUBFR * sizeof(opus_int) ); - *LTPCorr = 0.0f; - *lagIndex = 0; - *contourIndex = 0; - return 1; - } - - if( Fs_kHz > 8 ) { - /* Search in original signal */ - - /* Compensate for decimation */ - SKP_assert( lag == SKP_SAT16( lag ) ); - if( Fs_kHz == 12 ) { - lag = SKP_RSHIFT_ROUND( SKP_SMULBB( lag, 3 ), 1 ); - } else if( Fs_kHz == 16 ) { - lag = SKP_LSHIFT( lag, 1 ); - } else { - lag = SKP_SMULBB( lag, 3 ); - } - - lag = SKP_LIMIT_int( lag, min_lag, max_lag ); - start_lag = SKP_max_int( lag - 2, min_lag ); - end_lag = SKP_min_int( lag + 2, max_lag ); - lag_new = lag; /* to avoid undefined lag */ - CBimax = 0; /* to avoid undefined lag */ - SKP_assert( CCmax >= 0.0f ); - *LTPCorr = (SKP_float)sqrt( CCmax / nb_subfr ); /* Output normalized correlation */ - - CCmax = -1000.0f; - - /* Calculate the correlations and energies needed in stage 3 */ - silk_P_Ana_calc_corr_st3( cross_corr_st3, signal, start_lag, sf_length, nb_subfr, complexity ); - silk_P_Ana_calc_energy_st3( energies_st3, signal, start_lag, sf_length, nb_subfr, complexity ); - - lag_counter = 0; - SKP_assert( lag == SKP_SAT16( lag ) ); - contour_bias = PE_FLATCONTOUR_BIAS / lag; - - /* Setup 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; - Lag_CB_ptr = &silk_CB_lags_stage3[ 0 ][ 0 ]; - } else { - nb_cbk_search = PE_NB_CBKS_STAGE3_10MS; - cbk_size = PE_NB_CBKS_STAGE3_10MS; - Lag_CB_ptr = &silk_CB_lags_stage3_10_ms[ 0 ][ 0 ]; - } - - for( d = start_lag; d <= end_lag; d++ ) { - for( j = 0; j < nb_cbk_search; j++ ) { - cross_corr = 0.0; - energy = eps; - for( k = 0; k < nb_subfr; k++ ) { - energy += energies_st3[ k ][ j ][ lag_counter ]; - cross_corr += cross_corr_st3[ k ][ j ][ lag_counter ]; - } - if( cross_corr > 0.0 ) { - CCmax_new = (SKP_float)(cross_corr * cross_corr / energy); - /* Reduce depending on flatness of contour */ - CCmax_new *= 1.0f - contour_bias * j; - } else { - CCmax_new = 0.0f; - } - - if( CCmax_new > CCmax && - ( d + (opus_int)silk_CB_lags_stage3[ 0 ][ j ] ) <= max_lag - ) { - CCmax = CCmax_new; - lag_new = d; - CBimax = j; - } - } - lag_counter++; - } - - for( k = 0; k < nb_subfr; k++ ) { - pitch_out[ k ] = lag_new + matrix_ptr( Lag_CB_ptr, k, CBimax, cbk_size ); - } - *lagIndex = (opus_int16)( lag_new - min_lag ); - *contourIndex = (opus_int8)CBimax; - } else { - /* Save Lags and correlation */ - SKP_assert( CCmax >= 0.0f ); - *LTPCorr = (SKP_float)sqrt( CCmax / nb_subfr ); /* Output normalized correlation */ - for( k = 0; k < nb_subfr; k++ ) { - pitch_out[ k ] = lag + matrix_ptr( Lag_CB_ptr, k, CBimax, cbk_size ); - } - *lagIndex = (opus_int16)( lag - min_lag ); - *contourIndex = (opus_int8)CBimax; - } - SKP_assert( *lagIndex >= 0 ); - /* return as voiced */ - return 0; -} - -static void silk_P_Ana_calc_corr_st3( - SKP_float cross_corr_st3[ PE_MAX_NB_SUBFR ][ PE_NB_CBKS_STAGE3_MAX ][ PE_NB_STAGE3_LAGS ], /* O 3 DIM correlation array */ - const SKP_float signal[], /* I vector to correlate */ - opus_int start_lag, /* I start lag */ - opus_int sf_length, /* I sub frame length */ - opus_int nb_subfr, /* I number of subframes */ - opus_int complexity /* I Complexity setting */ -) - /*********************************************************************** - Calculates the correlations used in stage 3 search. In order to cover - the whole lag codebook for all the searched offset lags (lag +- 2), - the following correlations are needed in each sub frame: - - sf1: lag range [-8,...,7] total 16 correlations - sf2: lag range [-4,...,4] total 9 correlations - sf3: lag range [-3,....4] total 8 correltions - sf4: lag range [-6,....8] total 15 correlations - - In total 48 correlations. The direct implementation computed in worst case - 4*12*5 = 240 correlations, but more likely around 120. - **********************************************************************/ -{ - const SKP_float *target_ptr, *basis_ptr; - opus_int i, j, k, lag_counter, lag_low, lag_high; - opus_int nb_cbk_search, delta, idx, cbk_size; - SKP_float scratch_mem[ SCRATCH_SIZE ]; - const opus_int8 *Lag_range_ptr, *Lag_CB_ptr; - - SKP_assert( complexity >= SigProc_PE_MIN_COMPLEX ); - SKP_assert( complexity <= SigProc_PE_MAX_COMPLEX ); - - if( nb_subfr == PE_MAX_NB_SUBFR ){ - Lag_range_ptr = &silk_Lag_range_stage3[ complexity ][ 0 ][ 0 ]; - Lag_CB_ptr = &silk_CB_lags_stage3[ 0 ][ 0 ]; - nb_cbk_search = silk_nb_cbk_searchs_stage3[ complexity ]; - cbk_size = PE_NB_CBKS_STAGE3_MAX; - } else { - SKP_assert( nb_subfr == PE_MAX_NB_SUBFR >> 1); - Lag_range_ptr = &silk_Lag_range_stage3_10_ms[ 0 ][ 0 ]; - Lag_CB_ptr = &silk_CB_lags_stage3_10_ms[ 0 ][ 0 ]; - nb_cbk_search = PE_NB_CBKS_STAGE3_10MS; - cbk_size = PE_NB_CBKS_STAGE3_10MS; - } - - target_ptr = &signal[ SKP_LSHIFT( sf_length, 2 ) ]; /* Pointer to middle of frame */ - for( k = 0; k < nb_subfr; k++ ) { - lag_counter = 0; - - /* Calculate the correlations for each subframe */ - lag_low = matrix_ptr( Lag_range_ptr, k, 0, 2 ); - lag_high = matrix_ptr( Lag_range_ptr, k, 1, 2 ); - for( j = lag_low; j <= lag_high; j++ ) { - basis_ptr = target_ptr - ( start_lag + j ); - SKP_assert( lag_counter < SCRATCH_SIZE ); - scratch_mem[ lag_counter ] = (SKP_float)silk_inner_product_FLP( target_ptr, basis_ptr, sf_length ); - lag_counter++; - } - - delta = matrix_ptr( Lag_range_ptr, k, 0, 2 ); - for( i = 0; i < nb_cbk_search; i++ ) { - /* Fill out the 3 dim array that stores the correlations for */ - /* each code_book vector for each start lag */ - idx = matrix_ptr( Lag_CB_ptr, k, i, cbk_size ) - delta; - for( j = 0; j < PE_NB_STAGE3_LAGS; j++ ) { - SKP_assert( idx + j < SCRATCH_SIZE ); - SKP_assert( idx + j < lag_counter ); - cross_corr_st3[ k ][ i ][ j ] = scratch_mem[ idx + j ]; - } - } - target_ptr += sf_length; - } -} - -static void silk_P_Ana_calc_energy_st3( - SKP_float energies_st3[ PE_MAX_NB_SUBFR ][ PE_NB_CBKS_STAGE3_MAX ][ PE_NB_STAGE3_LAGS ], /* O 3 DIM correlation array */ - const SKP_float signal[], /* I vector to correlate */ - opus_int start_lag, /* I start lag */ - opus_int sf_length, /* I sub frame length */ - opus_int nb_subfr, /* I number of subframes */ - opus_int complexity /* I Complexity setting */ -) -/**************************************************************** -Calculate the energies for first two subframes. The energies are -calculated recursively. -****************************************************************/ -{ - const SKP_float *target_ptr, *basis_ptr; - double energy; - opus_int k, i, j, lag_counter; - opus_int nb_cbk_search, delta, idx, cbk_size, lag_diff; - SKP_float scratch_mem[ SCRATCH_SIZE ]; - const opus_int8 *Lag_range_ptr, *Lag_CB_ptr; - - SKP_assert( complexity >= SigProc_PE_MIN_COMPLEX ); - SKP_assert( complexity <= SigProc_PE_MAX_COMPLEX ); - - if( nb_subfr == PE_MAX_NB_SUBFR ){ - Lag_range_ptr = &silk_Lag_range_stage3[ complexity ][ 0 ][ 0 ]; - Lag_CB_ptr = &silk_CB_lags_stage3[ 0 ][ 0 ]; - nb_cbk_search = silk_nb_cbk_searchs_stage3[ complexity ]; - cbk_size = PE_NB_CBKS_STAGE3_MAX; - } else { - SKP_assert( nb_subfr == PE_MAX_NB_SUBFR >> 1); - Lag_range_ptr = &silk_Lag_range_stage3_10_ms[ 0 ][ 0 ]; - Lag_CB_ptr = &silk_CB_lags_stage3_10_ms[ 0 ][ 0 ]; - nb_cbk_search = PE_NB_CBKS_STAGE3_10MS; - cbk_size = PE_NB_CBKS_STAGE3_10MS; - } - - target_ptr = &signal[ SKP_LSHIFT( sf_length, 2 ) ]; - for( k = 0; k < nb_subfr; k++ ) { - lag_counter = 0; - - /* Calculate the energy for first lag */ - basis_ptr = target_ptr - ( start_lag + matrix_ptr( Lag_range_ptr, k, 0, 2 ) ); - energy = silk_energy_FLP( basis_ptr, sf_length ) + 1e-3; - SKP_assert( energy >= 0.0 ); - scratch_mem[lag_counter] = (SKP_float)energy; - lag_counter++; - - lag_diff = ( matrix_ptr( Lag_range_ptr, k, 1, 2 ) - matrix_ptr( Lag_range_ptr, k, 0, 2 ) + 1 ); - for( i = 1; i < lag_diff; i++ ) { - /* remove part outside new window */ - energy -= basis_ptr[sf_length - i] * basis_ptr[sf_length - i]; - SKP_assert( energy >= 0.0 ); - - /* add part that comes into window */ - energy += basis_ptr[ -i ] * basis_ptr[ -i ]; - SKP_assert( energy >= 0.0 ); - SKP_assert( lag_counter < SCRATCH_SIZE ); - scratch_mem[lag_counter] = (SKP_float)energy; - lag_counter++; - } - - delta = matrix_ptr( Lag_range_ptr, k, 0, 2 ); - for( i = 0; i < nb_cbk_search; i++ ) { - /* Fill out the 3 dim array that stores the correlations for */ - /* each code_book vector for each start lag */ - idx = matrix_ptr( Lag_CB_ptr, k, i, cbk_size ) - delta; - for( j = 0; j < PE_NB_STAGE3_LAGS; j++ ) { - SKP_assert( idx + j < SCRATCH_SIZE ); - SKP_assert( idx + j < lag_counter ); - energies_st3[ k ][ i ][ j ] = scratch_mem[ idx + j ]; - SKP_assert( energies_st3[ k ][ i ][ j ] >= 0.0f ); - } - } - target_ptr += sf_length; - } -} +/*********************************************************************** +Copyright (c) 2006-2011, Skype Limited. All rights reserved. +Redistribution and use in source and binary forms, with or without +modification, (subject to the limitations in the disclaimer below) +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 Skype Limited, nor the names of specific +contributors, may be used to endorse or promote products derived from +this software without specific prior written permission. +NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED +BY THIS LICENSE. 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. +***********************************************************************/ + +/***************************************************************************** +* +* Pitch analyser function +* +******************************************************************************/ +#include "silk_SigProc_FLP.h" +#include "silk_SigProc_FIX.h" +#include "silk_pitch_est_defines.h" + +#define SCRATCH_SIZE 22 + +/************************************************************/ +/* Definitions */ +/************************************************************/ +#define eps 1.192092896e-07f + +/************************************************************/ +/* Internally used functions */ +/************************************************************/ +static void silk_P_Ana_calc_corr_st3( + SKP_float cross_corr_st3[ PE_MAX_NB_SUBFR ][ PE_NB_CBKS_STAGE3_MAX ][ PE_NB_STAGE3_LAGS ], /* O 3 DIM correlation array */ + const SKP_float signal[], /* I vector to correlate */ + opus_int start_lag, /* I start lag */ + opus_int sf_length, /* I sub frame length */ + opus_int nb_subfr, /* I number of subframes */ + opus_int complexity /* I Complexity setting */ +); + +static void silk_P_Ana_calc_energy_st3( + SKP_float energies_st3[ PE_MAX_NB_SUBFR ][ PE_NB_CBKS_STAGE3_MAX ][ PE_NB_STAGE3_LAGS ], /* O 3 DIM correlation array */ + const SKP_float signal[], /* I vector to correlate */ + opus_int start_lag, /* I start lag */ + opus_int sf_length, /* I sub frame length */ + opus_int nb_subfr, /* I number of subframes */ + opus_int complexity /* I Complexity setting */ +); + +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +//% CORE PITCH ANALYSIS FUNCTION % +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +opus_int silk_pitch_analysis_core_FLP( /* O voicing estimate: 0 voiced, 1 unvoiced */ + const SKP_float *signal, /* I signal of length PE_FRAME_LENGTH_MS*Fs_kHz */ + opus_int *pitch_out, /* O 4 pitch lag values */ + opus_int16 *lagIndex, /* O lag Index */ + opus_int8 *contourIndex, /* O pitch contour Index */ + SKP_float *LTPCorr, /* I/O normalized correlation; input: value from previous frame */ + opus_int prevLag, /* I last lag of previous frame; set to zero is unvoiced */ + const SKP_float search_thres1, /* I first stage threshold for lag candidates 0 - 1 */ + const SKP_float search_thres2, /* I final threshold for lag candidates 0 - 1 */ + const opus_int Fs_kHz, /* I sample frequency (kHz) */ + const opus_int complexity, /* I Complexity setting, 0-2, where 2 is highest */ + const opus_int nb_subfr /* I number of 5 ms subframes */ +) +{ + opus_int i, k, d, j; + SKP_float signal_8kHz[ PE_MAX_FRAME_LENGTH_MS * 8 ]; + SKP_float signal_4kHz[ PE_MAX_FRAME_LENGTH_MS * 4 ]; + opus_int16 signal_8_FIX[ PE_MAX_FRAME_LENGTH_MS * 8 ]; + opus_int16 signal_4_FIX[ PE_MAX_FRAME_LENGTH_MS * 4 ]; + opus_int32 filt_state[ 6 ]; + SKP_float threshold, contour_bias; + SKP_float C[ PE_MAX_NB_SUBFR][ (PE_MAX_LAG >> 1) + 5 ]; + SKP_float CC[ PE_NB_CBKS_STAGE2_EXT ]; + const SKP_float *target_ptr, *basis_ptr; + double cross_corr, normalizer, energy, energy_tmp; + opus_int d_srch[ PE_D_SRCH_LENGTH ]; + opus_int16 d_comp[ (PE_MAX_LAG >> 1) + 5 ]; + opus_int length_d_srch, length_d_comp; + SKP_float Cmax, CCmax, CCmax_b, CCmax_new_b, CCmax_new; + opus_int CBimax, CBimax_new, lag, start_lag, end_lag, lag_new; + opus_int cbk_size; + SKP_float lag_log2, prevLag_log2, delta_lag_log2_sqr; + SKP_float energies_st3[ PE_MAX_NB_SUBFR ][ PE_NB_CBKS_STAGE3_MAX ][ PE_NB_STAGE3_LAGS ]; + SKP_float cross_corr_st3[ PE_MAX_NB_SUBFR ][ PE_NB_CBKS_STAGE3_MAX ][ PE_NB_STAGE3_LAGS ]; + opus_int lag_counter; + opus_int frame_length, frame_length_8kHz, frame_length_4kHz; + opus_int sf_length, sf_length_8kHz, sf_length_4kHz; + opus_int min_lag, min_lag_8kHz, min_lag_4kHz; + opus_int max_lag, max_lag_8kHz, max_lag_4kHz; + opus_int nb_cbk_search; + const opus_int8 *Lag_CB_ptr; + + /* Check for valid sampling frequency */ + SKP_assert( Fs_kHz == 8 || Fs_kHz == 12 || Fs_kHz == 16 ); + + /* Check for valid complexity setting */ + SKP_assert( complexity >= SigProc_PE_MIN_COMPLEX ); + SKP_assert( complexity <= SigProc_PE_MAX_COMPLEX ); + + SKP_assert( search_thres1 >= 0.0f && search_thres1 <= 1.0f ); + SKP_assert( search_thres2 >= 0.0f && search_thres2 <= 1.0f ); + + /* Setup 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; + sf_length = PE_SUBFR_LENGTH_MS * Fs_kHz; + sf_length_4kHz = PE_SUBFR_LENGTH_MS * 4; + sf_length_8kHz = PE_SUBFR_LENGTH_MS * 8; + min_lag = PE_MIN_LAG_MS * Fs_kHz; + min_lag_4kHz = PE_MIN_LAG_MS * 4; + min_lag_8kHz = PE_MIN_LAG_MS * 8; + max_lag = PE_MAX_LAG_MS * Fs_kHz - 1; + max_lag_4kHz = PE_MAX_LAG_MS * 4; + max_lag_8kHz = PE_MAX_LAG_MS * 8 - 1; + + SKP_memset(C, 0, sizeof(SKP_float) * nb_subfr * ((PE_MAX_LAG >> 1) + 5)); + + /* Resample from input sampled at Fs_kHz to 8 kHz */ + if( Fs_kHz == 16 ) { + /* Resample to 16 -> 8 khz */ + opus_int16 signal_16_FIX[ 16 * PE_MAX_FRAME_LENGTH_MS ]; + SKP_float2short_array( signal_16_FIX, signal, frame_length ); + SKP_memset( filt_state, 0, 2 * sizeof( opus_int32 ) ); + silk_resampler_down2( filt_state, signal_8_FIX, signal_16_FIX, frame_length ); + SKP_short2float_array( signal_8kHz, signal_8_FIX, frame_length_8kHz ); + } else if( Fs_kHz == 12 ) { + /* Resample to 12 -> 8 khz */ + opus_int16 signal_12_FIX[ 12 * PE_MAX_FRAME_LENGTH_MS ]; + SKP_float2short_array( signal_12_FIX, signal, frame_length ); + SKP_memset( filt_state, 0, 6 * sizeof( opus_int32 ) ); + silk_resampler_down2_3( filt_state, signal_8_FIX, signal_12_FIX, frame_length ); + SKP_short2float_array( signal_8kHz, signal_8_FIX, frame_length_8kHz ); + } else { + SKP_assert( Fs_kHz == 8 ); + SKP_float2short_array( signal_8_FIX, signal, frame_length_8kHz ); + } + + /* Decimate again to 4 kHz */ + SKP_memset( filt_state, 0, 2 * sizeof( opus_int32 ) ); + silk_resampler_down2( filt_state, signal_4_FIX, signal_8_FIX, frame_length_8kHz ); + SKP_short2float_array( signal_4kHz, signal_4_FIX, frame_length_4kHz ); + + /* Low-pass filter */ + for( i = frame_length_4kHz - 1; i > 0; i-- ) { + signal_4kHz[ i ] += signal_4kHz[ i - 1 ]; + } + + /****************************************************************************** + * FIRST STAGE, operating in 4 khz + ******************************************************************************/ + target_ptr = &signal_4kHz[ SKP_LSHIFT( sf_length_4kHz, 2 ) ]; + for( k = 0; k < nb_subfr >> 1; k++ ) { + /* Check that we are within range of the array */ + SKP_assert( target_ptr >= signal_4kHz ); + SKP_assert( target_ptr + sf_length_8kHz <= signal_4kHz + frame_length_4kHz ); + + basis_ptr = target_ptr - min_lag_4kHz; + + /* Check that we are within range of the array */ + SKP_assert( basis_ptr >= signal_4kHz ); + SKP_assert( basis_ptr + sf_length_8kHz <= signal_4kHz + frame_length_4kHz ); + + /* Calculate first vector products before loop */ + cross_corr = silk_inner_product_FLP( target_ptr, basis_ptr, sf_length_8kHz ); + normalizer = silk_energy_FLP( basis_ptr, sf_length_8kHz ) + sf_length_8kHz * 4000.0f; + + C[ 0 ][ min_lag_4kHz ] += (SKP_float)(cross_corr / sqrt(normalizer)); + + /* From now on normalizer is computed recursively */ + for(d = min_lag_4kHz + 1; d <= max_lag_4kHz; d++) { + basis_ptr--; + + /* Check that we are within range of the array */ + SKP_assert( basis_ptr >= signal_4kHz ); + SKP_assert( basis_ptr + sf_length_8kHz <= signal_4kHz + frame_length_4kHz ); + + cross_corr = silk_inner_product_FLP(target_ptr, basis_ptr, sf_length_8kHz); + + /* Add contribution of new sample and remove contribution from oldest sample */ + normalizer += + basis_ptr[ 0 ] * basis_ptr[ 0 ] - + basis_ptr[ sf_length_8kHz ] * basis_ptr[ sf_length_8kHz ]; + C[ 0 ][ d ] += (SKP_float)(cross_corr / sqrt( normalizer )); + } + /* Update target pointer */ + target_ptr += sf_length_8kHz; + } + + /* Apply short-lag bias */ + for( i = max_lag_4kHz; i >= min_lag_4kHz; i-- ) { + C[ 0 ][ i ] -= C[ 0 ][ i ] * i / 4096.0f; + } + + /* Sort */ + length_d_srch = 4 + 2 * complexity; + SKP_assert( 3 * length_d_srch <= PE_D_SRCH_LENGTH ); + silk_insertion_sort_decreasing_FLP( &C[ 0 ][ min_lag_4kHz ], d_srch, max_lag_4kHz - min_lag_4kHz + 1, length_d_srch ); + + /* Escape if correlation is very low already here */ + Cmax = C[ 0 ][ min_lag_4kHz ]; + target_ptr = &signal_4kHz[ SKP_SMULBB( sf_length_4kHz, nb_subfr ) ]; + energy = 1000.0f; + for( i = 0; i < SKP_LSHIFT( sf_length_4kHz, 2 ); i++ ) { + energy += target_ptr[i] * target_ptr[i]; + } + threshold = Cmax * Cmax; + if( energy / 16.0f > threshold ) { + SKP_memset( pitch_out, 0, nb_subfr * sizeof( opus_int ) ); + *LTPCorr = 0.0f; + *lagIndex = 0; + *contourIndex = 0; + return 1; + } + + threshold = search_thres1 * Cmax; + for( i = 0; i < length_d_srch; i++ ) { + /* Convert to 8 kHz indices for the sorted correlation that exceeds the threshold */ + if( C[ 0 ][ min_lag_4kHz + i ] > threshold ) { + d_srch[ i ] = SKP_LSHIFT( d_srch[ i ] + min_lag_4kHz, 1 ); + } else { + length_d_srch = i; + break; + } + } + SKP_assert( length_d_srch > 0 ); + + for( i = min_lag_8kHz - 5; i < max_lag_8kHz + 5; i++ ) { + d_comp[ i ] = 0; + } + for( i = 0; i < length_d_srch; i++ ) { + d_comp[ d_srch[ i ] ] = 1; + } + + /* Convolution */ + for( i = max_lag_8kHz + 3; i >= min_lag_8kHz; i-- ) { + d_comp[ i ] += d_comp[ i - 1 ] + d_comp[ i - 2 ]; + } + + length_d_srch = 0; + for( i = min_lag_8kHz; i < max_lag_8kHz + 1; i++ ) { + if( d_comp[ i + 1 ] > 0 ) { + d_srch[ length_d_srch ] = i; + length_d_srch++; + } + } + + /* Convolution */ + for( i = max_lag_8kHz + 3; i >= min_lag_8kHz; i-- ) { + d_comp[ i ] += d_comp[ i - 1 ] + d_comp[ i - 2 ] + d_comp[ i - 3 ]; + } + + length_d_comp = 0; + for( i = min_lag_8kHz; i < max_lag_8kHz + 4; i++ ) { + if( d_comp[ i ] > 0 ) { + d_comp[ length_d_comp ] = (opus_int16)( i - 2 ); + length_d_comp++; + } + } + + /********************************************************************************** + ** SECOND STAGE, operating at 8 kHz, on lag sections with high correlation + *************************************************************************************/ + /********************************************************************************* + * Find energy of each subframe projected onto its history, for a range of delays + *********************************************************************************/ + SKP_memset( C, 0, PE_MAX_NB_SUBFR*((PE_MAX_LAG >> 1) + 5) * sizeof(SKP_float)); // Is this needed? + + if( Fs_kHz == 8 ) { + target_ptr = &signal[ PE_LTP_MEM_LENGTH_MS * 8 ]; + } else { + target_ptr = &signal_8kHz[ PE_LTP_MEM_LENGTH_MS * 8 ]; + } + for( k = 0; k < nb_subfr; k++ ) { + energy_tmp = silk_energy_FLP( target_ptr, sf_length_8kHz ); + for( j = 0; j < length_d_comp; j++ ) { + d = d_comp[ j ]; + basis_ptr = target_ptr - d; + cross_corr = silk_inner_product_FLP( basis_ptr, target_ptr, sf_length_8kHz ); + energy = silk_energy_FLP( basis_ptr, sf_length_8kHz ); + if (cross_corr > 0.0f) { + C[ k ][ d ] = (SKP_float)(cross_corr * cross_corr / (energy * energy_tmp + eps)); + } else { + C[ k ][ d ] = 0.0f; + } + } + target_ptr += sf_length_8kHz; + } + + /* search over lag range and lags codebook */ + /* scale factor for lag codebook, as a function of center lag */ + + CCmax = 0.0f; /* This value doesn't matter */ + CCmax_b = -1000.0f; + + CBimax = 0; /* To avoid returning undefined lag values */ + lag = -1; /* To check if lag with strong enough correlation has been found */ + + if( prevLag > 0 ) { + if( Fs_kHz == 12 ) { + prevLag = SKP_LSHIFT( prevLag, 1 ) / 3; + } else if( Fs_kHz == 16 ) { + prevLag = SKP_RSHIFT( prevLag, 1 ); + } + prevLag_log2 = silk_log2((SKP_float)prevLag); + } else { + prevLag_log2 = 0; + } + + /* Setup 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 ]; + if( Fs_kHz == 8 && complexity > SigProc_PE_MIN_COMPLEX ) { + /* If input is 8 khz use a larger codebook here because it is last stage */ + nb_cbk_search = PE_NB_CBKS_STAGE2_EXT; + } else { + nb_cbk_search = PE_NB_CBKS_STAGE2; + } + } else { + cbk_size = PE_NB_CBKS_STAGE2_10MS; + Lag_CB_ptr = &silk_CB_lags_stage2_10_ms[ 0 ][ 0 ]; + nb_cbk_search = PE_NB_CBKS_STAGE2_10MS; + } + + for( k = 0; k < length_d_srch; k++ ) { + d = d_srch[ k ]; + for( j = 0; j < nb_cbk_search; j++ ) { + CC[j] = 0.0f; + for( i = 0; i < nb_subfr; i++ ) { + /* Try all codebooks */ + CC[ j ] += C[ i ][ d + matrix_ptr( Lag_CB_ptr, i, j, cbk_size )]; + } + } + /* Find best codebook */ + CCmax_new = -1000.0f; + CBimax_new = 0; + for( i = 0; i < nb_cbk_search; i++ ) { + if( CC[ i ] > CCmax_new ) { + CCmax_new = CC[ i ]; + CBimax_new = i; + } + } + CCmax_new = SKP_max_float(CCmax_new, 0.0f); /* To avoid taking square root of negative number later */ + CCmax_new_b = CCmax_new; + + /* Bias towards shorter lags */ + lag_log2 = silk_log2((SKP_float)d); + CCmax_new_b -= PE_SHORTLAG_BIAS * nb_subfr * lag_log2; + + /* Bias towards previous lag */ + if ( prevLag > 0 ) { + delta_lag_log2_sqr = lag_log2 - prevLag_log2; + delta_lag_log2_sqr *= delta_lag_log2_sqr; + CCmax_new_b -= PE_PREVLAG_BIAS * nb_subfr * (*LTPCorr) * delta_lag_log2_sqr / (delta_lag_log2_sqr + 0.5f); + } + + if ( CCmax_new_b > CCmax_b && /* Find maximum biased correlation */ + CCmax_new > nb_subfr * search_thres2 * search_thres2 && /* Correlation needs to be high enough to be voiced */ + silk_CB_lags_stage2[ 0 ][ CBimax_new ] <= min_lag_8kHz /* Lag must be in range */ + ) { + CCmax_b = CCmax_new_b; + CCmax = CCmax_new; + lag = d; + CBimax = CBimax_new; + } + } + + if( lag == -1 ) { + /* No suitable candidate found */ + SKP_memset( pitch_out, 0, PE_MAX_NB_SUBFR * sizeof(opus_int) ); + *LTPCorr = 0.0f; + *lagIndex = 0; + *contourIndex = 0; + return 1; + } + + if( Fs_kHz > 8 ) { + /* Search in original signal */ + + /* Compensate for decimation */ + SKP_assert( lag == SKP_SAT16( lag ) ); + if( Fs_kHz == 12 ) { + lag = SKP_RSHIFT_ROUND( SKP_SMULBB( lag, 3 ), 1 ); + } else if( Fs_kHz == 16 ) { + lag = SKP_LSHIFT( lag, 1 ); + } else { + lag = SKP_SMULBB( lag, 3 ); + } + + lag = SKP_LIMIT_int( lag, min_lag, max_lag ); + start_lag = SKP_max_int( lag - 2, min_lag ); + end_lag = SKP_min_int( lag + 2, max_lag ); + lag_new = lag; /* to avoid undefined lag */ + CBimax = 0; /* to avoid undefined lag */ + SKP_assert( CCmax >= 0.0f ); + *LTPCorr = (SKP_float)sqrt( CCmax / nb_subfr ); /* Output normalized correlation */ + + CCmax = -1000.0f; + + /* Calculate the correlations and energies needed in stage 3 */ + silk_P_Ana_calc_corr_st3( cross_corr_st3, signal, start_lag, sf_length, nb_subfr, complexity ); + silk_P_Ana_calc_energy_st3( energies_st3, signal, start_lag, sf_length, nb_subfr, complexity ); + + lag_counter = 0; + SKP_assert( lag == SKP_SAT16( lag ) ); + contour_bias = PE_FLATCONTOUR_BIAS / lag; + + /* Setup 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; + Lag_CB_ptr = &silk_CB_lags_stage3[ 0 ][ 0 ]; + } else { + nb_cbk_search = PE_NB_CBKS_STAGE3_10MS; + cbk_size = PE_NB_CBKS_STAGE3_10MS; + Lag_CB_ptr = &silk_CB_lags_stage3_10_ms[ 0 ][ 0 ]; + } + + for( d = start_lag; d <= end_lag; d++ ) { + for( j = 0; j < nb_cbk_search; j++ ) { + cross_corr = 0.0; + energy = eps; + for( k = 0; k < nb_subfr; k++ ) { + energy += energies_st3[ k ][ j ][ lag_counter ]; + cross_corr += cross_corr_st3[ k ][ j ][ lag_counter ]; + } + if( cross_corr > 0.0 ) { + CCmax_new = (SKP_float)(cross_corr * cross_corr / energy); + /* Reduce depending on flatness of contour */ + CCmax_new *= 1.0f - contour_bias * j; + } else { + CCmax_new = 0.0f; + } + + if( CCmax_new > CCmax && + ( d + (opus_int)silk_CB_lags_stage3[ 0 ][ j ] ) <= max_lag + ) { + CCmax = CCmax_new; + lag_new = d; + CBimax = j; + } + } + lag_counter++; + } + + for( k = 0; k < nb_subfr; k++ ) { + pitch_out[ k ] = lag_new + matrix_ptr( Lag_CB_ptr, k, CBimax, cbk_size ); + } + *lagIndex = (opus_int16)( lag_new - min_lag ); + *contourIndex = (opus_int8)CBimax; + } else { + /* Save Lags and correlation */ + SKP_assert( CCmax >= 0.0f ); + *LTPCorr = (SKP_float)sqrt( CCmax / nb_subfr ); /* Output normalized correlation */ + for( k = 0; k < nb_subfr; k++ ) { + pitch_out[ k ] = lag + matrix_ptr( Lag_CB_ptr, k, CBimax, cbk_size ); + } + *lagIndex = (opus_int16)( lag - min_lag ); + *contourIndex = (opus_int8)CBimax; + } + SKP_assert( *lagIndex >= 0 ); + /* return as voiced */ + return 0; +} + +static void silk_P_Ana_calc_corr_st3( + SKP_float cross_corr_st3[ PE_MAX_NB_SUBFR ][ PE_NB_CBKS_STAGE3_MAX ][ PE_NB_STAGE3_LAGS ], /* O 3 DIM correlation array */ + const SKP_float signal[], /* I vector to correlate */ + opus_int start_lag, /* I start lag */ + opus_int sf_length, /* I sub frame length */ + opus_int nb_subfr, /* I number of subframes */ + opus_int complexity /* I Complexity setting */ +) + /*********************************************************************** + Calculates the correlations used in stage 3 search. In order to cover + the whole lag codebook for all the searched offset lags (lag +- 2), + the following correlations are needed in each sub frame: + + sf1: lag range [-8,...,7] total 16 correlations + sf2: lag range [-4,...,4] total 9 correlations + sf3: lag range [-3,....4] total 8 correltions + sf4: lag range [-6,....8] total 15 correlations + + In total 48 correlations. The direct implementation computed in worst case + 4*12*5 = 240 correlations, but more likely around 120. + **********************************************************************/ +{ + const SKP_float *target_ptr, *basis_ptr; + opus_int i, j, k, lag_counter, lag_low, lag_high; + opus_int nb_cbk_search, delta, idx, cbk_size; + SKP_float scratch_mem[ SCRATCH_SIZE ]; + const opus_int8 *Lag_range_ptr, *Lag_CB_ptr; + + SKP_assert( complexity >= SigProc_PE_MIN_COMPLEX ); + SKP_assert( complexity <= SigProc_PE_MAX_COMPLEX ); + + if( nb_subfr == PE_MAX_NB_SUBFR ){ + Lag_range_ptr = &silk_Lag_range_stage3[ complexity ][ 0 ][ 0 ]; + Lag_CB_ptr = &silk_CB_lags_stage3[ 0 ][ 0 ]; + nb_cbk_search = silk_nb_cbk_searchs_stage3[ complexity ]; + cbk_size = PE_NB_CBKS_STAGE3_MAX; + } else { + SKP_assert( nb_subfr == PE_MAX_NB_SUBFR >> 1); + Lag_range_ptr = &silk_Lag_range_stage3_10_ms[ 0 ][ 0 ]; + Lag_CB_ptr = &silk_CB_lags_stage3_10_ms[ 0 ][ 0 ]; + nb_cbk_search = PE_NB_CBKS_STAGE3_10MS; + cbk_size = PE_NB_CBKS_STAGE3_10MS; + } + + target_ptr = &signal[ SKP_LSHIFT( sf_length, 2 ) ]; /* Pointer to middle of frame */ + for( k = 0; k < nb_subfr; k++ ) { + lag_counter = 0; + + /* Calculate the correlations for each subframe */ + lag_low = matrix_ptr( Lag_range_ptr, k, 0, 2 ); + lag_high = matrix_ptr( Lag_range_ptr, k, 1, 2 ); + for( j = lag_low; j <= lag_high; j++ ) { + basis_ptr = target_ptr - ( start_lag + j ); + SKP_assert( lag_counter < SCRATCH_SIZE ); + scratch_mem[ lag_counter ] = (SKP_float)silk_inner_product_FLP( target_ptr, basis_ptr, sf_length ); + lag_counter++; + } + + delta = matrix_ptr( Lag_range_ptr, k, 0, 2 ); + for( i = 0; i < nb_cbk_search; i++ ) { + /* Fill out the 3 dim array that stores the correlations for */ + /* each code_book vector for each start lag */ + idx = matrix_ptr( Lag_CB_ptr, k, i, cbk_size ) - delta; + for( j = 0; j < PE_NB_STAGE3_LAGS; j++ ) { + SKP_assert( idx + j < SCRATCH_SIZE ); + SKP_assert( idx + j < lag_counter ); + cross_corr_st3[ k ][ i ][ j ] = scratch_mem[ idx + j ]; + } + } + target_ptr += sf_length; + } +} + +static void silk_P_Ana_calc_energy_st3( + SKP_float energies_st3[ PE_MAX_NB_SUBFR ][ PE_NB_CBKS_STAGE3_MAX ][ PE_NB_STAGE3_LAGS ], /* O 3 DIM correlation array */ + const SKP_float signal[], /* I vector to correlate */ + opus_int start_lag, /* I start lag */ + opus_int sf_length, /* I sub frame length */ + opus_int nb_subfr, /* I number of subframes */ + opus_int complexity /* I Complexity setting */ +) +/**************************************************************** +Calculate the energies for first two subframes. The energies are +calculated recursively. +****************************************************************/ +{ + const SKP_float *target_ptr, *basis_ptr; + double energy; + opus_int k, i, j, lag_counter; + opus_int nb_cbk_search, delta, idx, cbk_size, lag_diff; + SKP_float scratch_mem[ SCRATCH_SIZE ]; + const opus_int8 *Lag_range_ptr, *Lag_CB_ptr; + + SKP_assert( complexity >= SigProc_PE_MIN_COMPLEX ); + SKP_assert( complexity <= SigProc_PE_MAX_COMPLEX ); + + if( nb_subfr == PE_MAX_NB_SUBFR ){ + Lag_range_ptr = &silk_Lag_range_stage3[ complexity ][ 0 ][ 0 ]; + Lag_CB_ptr = &silk_CB_lags_stage3[ 0 ][ 0 ]; + nb_cbk_search = silk_nb_cbk_searchs_stage3[ complexity ]; + cbk_size = PE_NB_CBKS_STAGE3_MAX; + } else { + SKP_assert( nb_subfr == PE_MAX_NB_SUBFR >> 1); + Lag_range_ptr = &silk_Lag_range_stage3_10_ms[ 0 ][ 0 ]; + Lag_CB_ptr = &silk_CB_lags_stage3_10_ms[ 0 ][ 0 ]; + nb_cbk_search = PE_NB_CBKS_STAGE3_10MS; + cbk_size = PE_NB_CBKS_STAGE3_10MS; + } + + target_ptr = &signal[ SKP_LSHIFT( sf_length, 2 ) ]; + for( k = 0; k < nb_subfr; k++ ) { + lag_counter = 0; + + /* Calculate the energy for first lag */ + basis_ptr = target_ptr - ( start_lag + matrix_ptr( Lag_range_ptr, k, 0, 2 ) ); + energy = silk_energy_FLP( basis_ptr, sf_length ) + 1e-3; + SKP_assert( energy >= 0.0 ); + scratch_mem[lag_counter] = (SKP_float)energy; + lag_counter++; + + lag_diff = ( matrix_ptr( Lag_range_ptr, k, 1, 2 ) - matrix_ptr( Lag_range_ptr, k, 0, 2 ) + 1 ); + for( i = 1; i < lag_diff; i++ ) { + /* remove part outside new window */ + energy -= basis_ptr[sf_length - i] * basis_ptr[sf_length - i]; + SKP_assert( energy >= 0.0 ); + + /* add part that comes into window */ + energy += basis_ptr[ -i ] * basis_ptr[ -i ]; + SKP_assert( energy >= 0.0 ); + SKP_assert( lag_counter < SCRATCH_SIZE ); + scratch_mem[lag_counter] = (SKP_float)energy; + lag_counter++; + } + + delta = matrix_ptr( Lag_range_ptr, k, 0, 2 ); + for( i = 0; i < nb_cbk_search; i++ ) { + /* Fill out the 3 dim array that stores the correlations for */ + /* each code_book vector for each start lag */ + idx = matrix_ptr( Lag_CB_ptr, k, i, cbk_size ) - delta; + for( j = 0; j < PE_NB_STAGE3_LAGS; j++ ) { + SKP_assert( idx + j < SCRATCH_SIZE ); + SKP_assert( idx + j < lag_counter ); + energies_st3[ k ][ i ][ j ] = scratch_mem[ idx + j ]; + SKP_assert( energies_st3[ k ][ i ][ j ] >= 0.0f ); + } + } + target_ptr += sf_length; + } +} diff --git a/silk/float/silk_prefilter_FLP.c b/silk/float/silk_prefilter_FLP.c index e2534c294..ef4eb5e53 100644 --- a/silk/float/silk_prefilter_FLP.c +++ b/silk/float/silk_prefilter_FLP.c @@ -1,202 +1,202 @@ -/*********************************************************************** -Copyright (c) 2006-2011, Skype Limited. All rights reserved. -Redistribution and use in source and binary forms, with or without -modification, (subject to the limitations in the disclaimer below) -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 Skype Limited, nor the names of specific -contributors, may be used to endorse or promote products derived from -this software without specific prior written permission. -NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED -BY THIS LICENSE. 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. -***********************************************************************/ - -#include "silk_main_FLP.h" -#include "silk_tuning_parameters.h" - -/* -* silk_prefilter. Prefilter for finding Quantizer input signal -*/ -SKP_INLINE void silk_prefilt_FLP( - silk_prefilter_state_FLP *P,/* I/O state */ - SKP_float st_res[], /* I */ - SKP_float xw[], /* O */ - SKP_float *HarmShapeFIR, /* I */ - SKP_float Tilt, /* I */ - SKP_float LF_MA_shp, /* I */ - SKP_float LF_AR_shp, /* I */ - opus_int lag, /* I */ - opus_int length /* I */ -); - -void silk_warped_LPC_analysis_filter_FLP( - SKP_float state[], /* I/O State [order + 1] */ - SKP_float res[], /* O Residual signal [length] */ - const SKP_float coef[], /* I Coefficients [order] */ - const SKP_float input[], /* I Input signal [length] */ - const SKP_float lambda, /* I Warping factor */ - const opus_int length, /* I Length of input signal */ - const opus_int order /* I Filter order (even) */ -) -{ - opus_int n, i; - SKP_float acc, tmp1, tmp2; - - /* Order must be even */ - SKP_assert( ( order & 1 ) == 0 ); - - for( n = 0; n < length; n++ ) { - /* Output of lowpass section */ - tmp2 = state[ 0 ] + lambda * state[ 1 ]; - state[ 0 ] = input[ n ]; - /* Output of allpass section */ - tmp1 = state[ 1 ] + lambda * ( state[ 2 ] - tmp2 ); - state[ 1 ] = tmp2; - acc = coef[ 0 ] * tmp2; - /* Loop over allpass sections */ - for( i = 2; i < order; i += 2 ) { - /* Output of allpass section */ - tmp2 = state[ i ] + lambda * ( state[ i + 1 ] - tmp1 ); - state[ i ] = tmp1; - acc += coef[ i - 1 ] * tmp1; - /* Output of allpass section */ - tmp1 = state[ i + 1 ] + lambda * ( state[ i + 2 ] - tmp2 ); - state[ i + 1 ] = tmp2; - acc += coef[ i ] * tmp2; - } - state[ order ] = tmp1; - acc += coef[ order - 1 ] * tmp1; - res[ n ] = input[ n ] - acc; - } -} - -/* -* silk_prefilter. Main prefilter function -*/ -void silk_prefilter_FLP( - silk_encoder_state_FLP *psEnc, /* I/O Encoder state FLP */ - const silk_encoder_control_FLP *psEncCtrl, /* I Encoder control FLP */ - SKP_float xw[], /* O Weighted signal */ - const SKP_float x[] /* I Speech signal */ -) -{ - silk_prefilter_state_FLP *P = &psEnc->sPrefilt; - opus_int j, k, lag; - SKP_float HarmShapeGain, Tilt, LF_MA_shp, LF_AR_shp; - SKP_float B[ 2 ]; - const SKP_float *AR1_shp; - const SKP_float *px; - SKP_float *pxw; - SKP_float HarmShapeFIR[ 3 ]; - SKP_float st_res[ MAX_SUB_FRAME_LENGTH + MAX_LPC_ORDER ]; - - /* Setup pointers */ - px = x; - pxw = xw; - lag = P->lagPrev; - for( k = 0; k < psEnc->sCmn.nb_subfr; k++ ) { - /* Update Variables that change per sub frame */ - if( psEnc->sCmn.indices.signalType == TYPE_VOICED ) { - lag = psEncCtrl->pitchL[ k ]; - } - - /* Noise shape parameters */ - HarmShapeGain = psEncCtrl->HarmShapeGain[ k ] * ( 1.0f - psEncCtrl->HarmBoost[ k ] ); - HarmShapeFIR[ 0 ] = 0.25f * HarmShapeGain; - HarmShapeFIR[ 1 ] = 32767.0f / 65536.0f * HarmShapeGain; - HarmShapeFIR[ 2 ] = 0.25f * HarmShapeGain; - Tilt = psEncCtrl->Tilt[ k ]; - LF_MA_shp = psEncCtrl->LF_MA_shp[ k ]; - LF_AR_shp = psEncCtrl->LF_AR_shp[ k ]; - AR1_shp = &psEncCtrl->AR1[ k * MAX_SHAPE_LPC_ORDER ]; - - /* Short term FIR filtering */ - silk_warped_LPC_analysis_filter_FLP( P->sAR_shp, st_res, AR1_shp, px, - (SKP_float)psEnc->sCmn.warping_Q16 / 65536.0f, psEnc->sCmn.subfr_length, psEnc->sCmn.shapingLPCOrder ); - - /* Reduce (mainly) low frequencies during harmonic emphasis */ - B[ 0 ] = psEncCtrl->GainsPre[ k ]; - B[ 1 ] = -psEncCtrl->GainsPre[ k ] * - ( psEncCtrl->HarmBoost[ k ] * HarmShapeGain + INPUT_TILT + psEncCtrl->coding_quality * HIGH_RATE_INPUT_TILT ); - pxw[ 0 ] = B[ 0 ] * st_res[ 0 ] + B[ 1 ] * P->sHarmHP; - for( j = 1; j < psEnc->sCmn.subfr_length; j++ ) { - pxw[ j ] = B[ 0 ] * st_res[ j ] + B[ 1 ] * st_res[ j - 1 ]; - } - P->sHarmHP = st_res[ psEnc->sCmn.subfr_length - 1 ]; - - silk_prefilt_FLP( P, pxw, pxw, HarmShapeFIR, Tilt, LF_MA_shp, LF_AR_shp, lag, psEnc->sCmn.subfr_length ); - - px += psEnc->sCmn.subfr_length; - pxw += psEnc->sCmn.subfr_length; - } - P->lagPrev = psEncCtrl->pitchL[ psEnc->sCmn.nb_subfr - 1 ]; -} - -/* -* Prefilter for finding Quantizer input signal -*/ -SKP_INLINE void silk_prefilt_FLP( - silk_prefilter_state_FLP *P,/* I/O state */ - SKP_float st_res[], /* I */ - SKP_float xw[], /* O */ - SKP_float *HarmShapeFIR, /* I */ - SKP_float Tilt, /* I */ - SKP_float LF_MA_shp, /* I */ - SKP_float LF_AR_shp, /* I */ - opus_int lag, /* I */ - opus_int length /* I */ -) -{ - opus_int i; - opus_int idx, LTP_shp_buf_idx; - SKP_float n_Tilt, n_LF, n_LTP; - SKP_float sLF_AR_shp, sLF_MA_shp; - SKP_float *LTP_shp_buf; - - /* To speed up use temp variables instead of using the struct */ - LTP_shp_buf = P->sLTP_shp; - LTP_shp_buf_idx = P->sLTP_shp_buf_idx; - sLF_AR_shp = P->sLF_AR_shp; - sLF_MA_shp = P->sLF_MA_shp; - - for( i = 0; i < length; i++ ) { - if( lag > 0 ) { - SKP_assert( HARM_SHAPE_FIR_TAPS == 3 ); - idx = lag + LTP_shp_buf_idx; - n_LTP = LTP_shp_buf[ ( idx - HARM_SHAPE_FIR_TAPS / 2 - 1) & LTP_MASK ] * HarmShapeFIR[ 0 ]; - n_LTP += LTP_shp_buf[ ( idx - HARM_SHAPE_FIR_TAPS / 2 ) & LTP_MASK ] * HarmShapeFIR[ 1 ]; - n_LTP += LTP_shp_buf[ ( idx - HARM_SHAPE_FIR_TAPS / 2 + 1) & LTP_MASK ] * HarmShapeFIR[ 2 ]; - } else { - n_LTP = 0; - } - - n_Tilt = sLF_AR_shp * Tilt; - n_LF = sLF_AR_shp * LF_AR_shp + sLF_MA_shp * LF_MA_shp; - - sLF_AR_shp = st_res[ i ] - n_Tilt; - sLF_MA_shp = sLF_AR_shp - n_LF; - - LTP_shp_buf_idx = ( LTP_shp_buf_idx - 1 ) & LTP_MASK; - LTP_shp_buf[ LTP_shp_buf_idx ] = sLF_MA_shp; - - xw[ i ] = sLF_MA_shp - n_LTP; - } - /* Copy temp variable back to state */ - P->sLF_AR_shp = sLF_AR_shp; - P->sLF_MA_shp = sLF_MA_shp; - P->sLTP_shp_buf_idx = LTP_shp_buf_idx; -} +/*********************************************************************** +Copyright (c) 2006-2011, Skype Limited. All rights reserved. +Redistribution and use in source and binary forms, with or without +modification, (subject to the limitations in the disclaimer below) +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 Skype Limited, nor the names of specific +contributors, may be used to endorse or promote products derived from +this software without specific prior written permission. +NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED +BY THIS LICENSE. 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. +***********************************************************************/ + +#include "silk_main_FLP.h" +#include "silk_tuning_parameters.h" + +/* +* silk_prefilter. Prefilter for finding Quantizer input signal +*/ +SKP_INLINE void silk_prefilt_FLP( + silk_prefilter_state_FLP *P,/* I/O state */ + SKP_float st_res[], /* I */ + SKP_float xw[], /* O */ + SKP_float *HarmShapeFIR, /* I */ + SKP_float Tilt, /* I */ + SKP_float LF_MA_shp, /* I */ + SKP_float LF_AR_shp, /* I */ + opus_int lag, /* I */ + opus_int length /* I */ +); + +void silk_warped_LPC_analysis_filter_FLP( + SKP_float state[], /* I/O State [order + 1] */ + SKP_float res[], /* O Residual signal [length] */ + const SKP_float coef[], /* I Coefficients [order] */ + const SKP_float input[], /* I Input signal [length] */ + const SKP_float lambda, /* I Warping factor */ + const opus_int length, /* I Length of input signal */ + const opus_int order /* I Filter order (even) */ +) +{ + opus_int n, i; + SKP_float acc, tmp1, tmp2; + + /* Order must be even */ + SKP_assert( ( order & 1 ) == 0 ); + + for( n = 0; n < length; n++ ) { + /* Output of lowpass section */ + tmp2 = state[ 0 ] + lambda * state[ 1 ]; + state[ 0 ] = input[ n ]; + /* Output of allpass section */ + tmp1 = state[ 1 ] + lambda * ( state[ 2 ] - tmp2 ); + state[ 1 ] = tmp2; + acc = coef[ 0 ] * tmp2; + /* Loop over allpass sections */ + for( i = 2; i < order; i += 2 ) { + /* Output of allpass section */ + tmp2 = state[ i ] + lambda * ( state[ i + 1 ] - tmp1 ); + state[ i ] = tmp1; + acc += coef[ i - 1 ] * tmp1; + /* Output of allpass section */ + tmp1 = state[ i + 1 ] + lambda * ( state[ i + 2 ] - tmp2 ); + state[ i + 1 ] = tmp2; + acc += coef[ i ] * tmp2; + } + state[ order ] = tmp1; + acc += coef[ order - 1 ] * tmp1; + res[ n ] = input[ n ] - acc; + } +} + +/* +* silk_prefilter. Main prefilter function +*/ +void silk_prefilter_FLP( + silk_encoder_state_FLP *psEnc, /* I/O Encoder state FLP */ + const silk_encoder_control_FLP *psEncCtrl, /* I Encoder control FLP */ + SKP_float xw[], /* O Weighted signal */ + const SKP_float x[] /* I Speech signal */ +) +{ + silk_prefilter_state_FLP *P = &psEnc->sPrefilt; + opus_int j, k, lag; + SKP_float HarmShapeGain, Tilt, LF_MA_shp, LF_AR_shp; + SKP_float B[ 2 ]; + const SKP_float *AR1_shp; + const SKP_float *px; + SKP_float *pxw; + SKP_float HarmShapeFIR[ 3 ]; + SKP_float st_res[ MAX_SUB_FRAME_LENGTH + MAX_LPC_ORDER ]; + + /* Setup pointers */ + px = x; + pxw = xw; + lag = P->lagPrev; + for( k = 0; k < psEnc->sCmn.nb_subfr; k++ ) { + /* Update Variables that change per sub frame */ + if( psEnc->sCmn.indices.signalType == TYPE_VOICED ) { + lag = psEncCtrl->pitchL[ k ]; + } + + /* Noise shape parameters */ + HarmShapeGain = psEncCtrl->HarmShapeGain[ k ] * ( 1.0f - psEncCtrl->HarmBoost[ k ] ); + HarmShapeFIR[ 0 ] = 0.25f * HarmShapeGain; + HarmShapeFIR[ 1 ] = 32767.0f / 65536.0f * HarmShapeGain; + HarmShapeFIR[ 2 ] = 0.25f * HarmShapeGain; + Tilt = psEncCtrl->Tilt[ k ]; + LF_MA_shp = psEncCtrl->LF_MA_shp[ k ]; + LF_AR_shp = psEncCtrl->LF_AR_shp[ k ]; + AR1_shp = &psEncCtrl->AR1[ k * MAX_SHAPE_LPC_ORDER ]; + + /* Short term FIR filtering */ + silk_warped_LPC_analysis_filter_FLP( P->sAR_shp, st_res, AR1_shp, px, + (SKP_float)psEnc->sCmn.warping_Q16 / 65536.0f, psEnc->sCmn.subfr_length, psEnc->sCmn.shapingLPCOrder ); + + /* Reduce (mainly) low frequencies during harmonic emphasis */ + B[ 0 ] = psEncCtrl->GainsPre[ k ]; + B[ 1 ] = -psEncCtrl->GainsPre[ k ] * + ( psEncCtrl->HarmBoost[ k ] * HarmShapeGain + INPUT_TILT + psEncCtrl->coding_quality * HIGH_RATE_INPUT_TILT ); + pxw[ 0 ] = B[ 0 ] * st_res[ 0 ] + B[ 1 ] * P->sHarmHP; + for( j = 1; j < psEnc->sCmn.subfr_length; j++ ) { + pxw[ j ] = B[ 0 ] * st_res[ j ] + B[ 1 ] * st_res[ j - 1 ]; + } + P->sHarmHP = st_res[ psEnc->sCmn.subfr_length - 1 ]; + + silk_prefilt_FLP( P, pxw, pxw, HarmShapeFIR, Tilt, LF_MA_shp, LF_AR_shp, lag, psEnc->sCmn.subfr_length ); + + px += psEnc->sCmn.subfr_length; + pxw += psEnc->sCmn.subfr_length; + } + P->lagPrev = psEncCtrl->pitchL[ psEnc->sCmn.nb_subfr - 1 ]; +} + +/* +* Prefilter for finding Quantizer input signal +*/ +SKP_INLINE void silk_prefilt_FLP( + silk_prefilter_state_FLP *P,/* I/O state */ + SKP_float st_res[], /* I */ + SKP_float xw[], /* O */ + SKP_float *HarmShapeFIR, /* I */ + SKP_float Tilt, /* I */ + SKP_float LF_MA_shp, /* I */ + SKP_float LF_AR_shp, /* I */ + opus_int lag, /* I */ + opus_int length /* I */ +) +{ + opus_int i; + opus_int idx, LTP_shp_buf_idx; + SKP_float n_Tilt, n_LF, n_LTP; + SKP_float sLF_AR_shp, sLF_MA_shp; + SKP_float *LTP_shp_buf; + + /* To speed up use temp variables instead of using the struct */ + LTP_shp_buf = P->sLTP_shp; + LTP_shp_buf_idx = P->sLTP_shp_buf_idx; + sLF_AR_shp = P->sLF_AR_shp; + sLF_MA_shp = P->sLF_MA_shp; + + for( i = 0; i < length; i++ ) { + if( lag > 0 ) { + SKP_assert( HARM_SHAPE_FIR_TAPS == 3 ); + idx = lag + LTP_shp_buf_idx; + n_LTP = LTP_shp_buf[ ( idx - HARM_SHAPE_FIR_TAPS / 2 - 1) & LTP_MASK ] * HarmShapeFIR[ 0 ]; + n_LTP += LTP_shp_buf[ ( idx - HARM_SHAPE_FIR_TAPS / 2 ) & LTP_MASK ] * HarmShapeFIR[ 1 ]; + n_LTP += LTP_shp_buf[ ( idx - HARM_SHAPE_FIR_TAPS / 2 + 1) & LTP_MASK ] * HarmShapeFIR[ 2 ]; + } else { + n_LTP = 0; + } + + n_Tilt = sLF_AR_shp * Tilt; + n_LF = sLF_AR_shp * LF_AR_shp + sLF_MA_shp * LF_MA_shp; + + sLF_AR_shp = st_res[ i ] - n_Tilt; + sLF_MA_shp = sLF_AR_shp - n_LF; + + LTP_shp_buf_idx = ( LTP_shp_buf_idx - 1 ) & LTP_MASK; + LTP_shp_buf[ LTP_shp_buf_idx ] = sLF_MA_shp; + + xw[ i ] = sLF_MA_shp - n_LTP; + } + /* Copy temp variable back to state */ + P->sLF_AR_shp = sLF_AR_shp; + P->sLF_MA_shp = sLF_MA_shp; + P->sLTP_shp_buf_idx = LTP_shp_buf_idx; +} diff --git a/silk/float/silk_process_gains_FLP.c b/silk/float/silk_process_gains_FLP.c index e29721dbb..55b5c32e5 100644 --- a/silk/float/silk_process_gains_FLP.c +++ b/silk/float/silk_process_gains_FLP.c @@ -1,94 +1,94 @@ -/*********************************************************************** -Copyright (c) 2006-2011, Skype Limited. All rights reserved. -Redistribution and use in source and binary forms, with or without -modification, (subject to the limitations in the disclaimer below) -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 Skype Limited, nor the names of specific -contributors, may be used to endorse or promote products derived from -this software without specific prior written permission. -NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED -BY THIS LICENSE. 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. -***********************************************************************/ - -#include "silk_main_FLP.h" -#include "silk_tuning_parameters.h" - -/* Processing of gains */ -void silk_process_gains_FLP( - silk_encoder_state_FLP *psEnc, /* I/O Encoder state FLP */ - silk_encoder_control_FLP *psEncCtrl /* I/O Encoder control FLP */ -) -{ - silk_shape_state_FLP *psShapeSt = &psEnc->sShape; - opus_int k; - opus_int32 pGains_Q16[ MAX_NB_SUBFR ]; - SKP_float s, InvMaxSqrVal, gain, quant_offset; - - /* Gain reduction when LTP coding gain is high */ - if( psEnc->sCmn.indices.signalType == TYPE_VOICED ) { - s = 1.0f - 0.5f * SKP_sigmoid( 0.25f * ( psEncCtrl->LTPredCodGain - 12.0f ) ); - for( k = 0; k < psEnc->sCmn.nb_subfr; k++ ) { - psEncCtrl->Gains[ k ] *= s; - } - } - - /* Limit the quantized signal */ - InvMaxSqrVal = ( SKP_float )( pow( 2.0f, 0.33f * ( 21.0f - psEnc->sCmn.SNR_dB_Q7 * ( 1 / 128.0f ) ) ) / psEnc->sCmn.subfr_length ); - - for( k = 0; k < psEnc->sCmn.nb_subfr; k++ ) { - /* Soft limit on ratio residual energy and squared gains */ - gain = psEncCtrl->Gains[ k ]; - gain = ( SKP_float )sqrt( gain * gain + psEncCtrl->ResNrg[ k ] * InvMaxSqrVal ); - psEncCtrl->Gains[ k ] = SKP_min_float( gain, 32767.0f ); - } - - /* 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 ); - } - - /* Noise shaping quantization */ - silk_gains_quant( psEnc->sCmn.indices.GainsIndices, pGains_Q16, - &psShapeSt->LastGainIndex, psEnc->sCmn.nFramesEncoded, psEnc->sCmn.nb_subfr ); - - /* Overwrite unquantized gains with quantized gains and convert back to Q0 from Q16 */ - for( k = 0; k < psEnc->sCmn.nb_subfr; k++ ) { - psEncCtrl->Gains[ k ] = pGains_Q16[ k ] / 65536.0f; - } - - /* Set quantizer offset for voiced signals. Larger offset when LTP coding gain is low or tilt is high (ie low-pass) */ - if( psEnc->sCmn.indices.signalType == TYPE_VOICED ) { - if( psEncCtrl->LTPredCodGain + psEnc->sCmn.input_tilt_Q15 * ( 1.0f / 32768.0f ) > 1.0f ) { - psEnc->sCmn.indices.quantOffsetType = 0; - } else { - psEnc->sCmn.indices.quantOffsetType = 1; - } - } - - /* Quantizer boundary adjustment */ - quant_offset = silk_Quantization_Offsets_Q10[ psEnc->sCmn.indices.signalType >> 1 ][ psEnc->sCmn.indices.quantOffsetType ] / 1024.0f; - psEncCtrl->Lambda = LAMBDA_OFFSET - + LAMBDA_DELAYED_DECISIONS * psEnc->sCmn.nStatesDelayedDecision - + LAMBDA_SPEECH_ACT * psEnc->sCmn.speech_activity_Q8 * ( 1.0f / 256.0f ) - + LAMBDA_INPUT_QUALITY * psEncCtrl->input_quality - + LAMBDA_CODING_QUALITY * psEncCtrl->coding_quality - + LAMBDA_QUANT_OFFSET * quant_offset; - - SKP_assert( psEncCtrl->Lambda > 0.0f ); - SKP_assert( psEncCtrl->Lambda < 2.0f ); -} +/*********************************************************************** +Copyright (c) 2006-2011, Skype Limited. All rights reserved. +Redistribution and use in source and binary forms, with or without +modification, (subject to the limitations in the disclaimer below) +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 Skype Limited, nor the names of specific +contributors, may be used to endorse or promote products derived from +this software without specific prior written permission. +NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED +BY THIS LICENSE. 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. +***********************************************************************/ + +#include "silk_main_FLP.h" +#include "silk_tuning_parameters.h" + +/* Processing of gains */ +void silk_process_gains_FLP( + silk_encoder_state_FLP *psEnc, /* I/O Encoder state FLP */ + silk_encoder_control_FLP *psEncCtrl /* I/O Encoder control FLP */ +) +{ + silk_shape_state_FLP *psShapeSt = &psEnc->sShape; + opus_int k; + opus_int32 pGains_Q16[ MAX_NB_SUBFR ]; + SKP_float s, InvMaxSqrVal, gain, quant_offset; + + /* Gain reduction when LTP coding gain is high */ + if( psEnc->sCmn.indices.signalType == TYPE_VOICED ) { + s = 1.0f - 0.5f * SKP_sigmoid( 0.25f * ( psEncCtrl->LTPredCodGain - 12.0f ) ); + for( k = 0; k < psEnc->sCmn.nb_subfr; k++ ) { + psEncCtrl->Gains[ k ] *= s; + } + } + + /* Limit the quantized signal */ + InvMaxSqrVal = ( SKP_float )( pow( 2.0f, 0.33f * ( 21.0f - psEnc->sCmn.SNR_dB_Q7 * ( 1 / 128.0f ) ) ) / psEnc->sCmn.subfr_length ); + + for( k = 0; k < psEnc->sCmn.nb_subfr; k++ ) { + /* Soft limit on ratio residual energy and squared gains */ + gain = psEncCtrl->Gains[ k ]; + gain = ( SKP_float )sqrt( gain * gain + psEncCtrl->ResNrg[ k ] * InvMaxSqrVal ); + psEncCtrl->Gains[ k ] = SKP_min_float( gain, 32767.0f ); + } + + /* 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 ); + } + + /* Noise shaping quantization */ + silk_gains_quant( psEnc->sCmn.indices.GainsIndices, pGains_Q16, + &psShapeSt->LastGainIndex, psEnc->sCmn.nFramesEncoded, psEnc->sCmn.nb_subfr ); + + /* Overwrite unquantized gains with quantized gains and convert back to Q0 from Q16 */ + for( k = 0; k < psEnc->sCmn.nb_subfr; k++ ) { + psEncCtrl->Gains[ k ] = pGains_Q16[ k ] / 65536.0f; + } + + /* Set quantizer offset for voiced signals. Larger offset when LTP coding gain is low or tilt is high (ie low-pass) */ + if( psEnc->sCmn.indices.signalType == TYPE_VOICED ) { + if( psEncCtrl->LTPredCodGain + psEnc->sCmn.input_tilt_Q15 * ( 1.0f / 32768.0f ) > 1.0f ) { + psEnc->sCmn.indices.quantOffsetType = 0; + } else { + psEnc->sCmn.indices.quantOffsetType = 1; + } + } + + /* Quantizer boundary adjustment */ + quant_offset = silk_Quantization_Offsets_Q10[ psEnc->sCmn.indices.signalType >> 1 ][ psEnc->sCmn.indices.quantOffsetType ] / 1024.0f; + psEncCtrl->Lambda = LAMBDA_OFFSET + + LAMBDA_DELAYED_DECISIONS * psEnc->sCmn.nStatesDelayedDecision + + LAMBDA_SPEECH_ACT * psEnc->sCmn.speech_activity_Q8 * ( 1.0f / 256.0f ) + + LAMBDA_INPUT_QUALITY * psEncCtrl->input_quality + + LAMBDA_CODING_QUALITY * psEncCtrl->coding_quality + + LAMBDA_QUANT_OFFSET * quant_offset; + + SKP_assert( psEncCtrl->Lambda > 0.0f ); + SKP_assert( psEncCtrl->Lambda < 2.0f ); +} diff --git a/silk/float/silk_regularize_correlations_FLP.c b/silk/float/silk_regularize_correlations_FLP.c index 111b1caaa..697127407 100644 --- a/silk/float/silk_regularize_correlations_FLP.c +++ b/silk/float/silk_regularize_correlations_FLP.c @@ -1,43 +1,43 @@ -/*********************************************************************** -Copyright (c) 2006-2011, Skype Limited. All rights reserved. -Redistribution and use in source and binary forms, with or without -modification, (subject to the limitations in the disclaimer below) -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 Skype Limited, nor the names of specific -contributors, may be used to endorse or promote products derived from -this software without specific prior written permission. -NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED -BY THIS LICENSE. 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. -***********************************************************************/ - -#include "silk_main_FLP.h" - -void silk_regularize_correlations_FLP( - SKP_float *XX, /* I/O Correlation matrices */ - SKP_float *xx, /* I/O Correlation values */ - const SKP_float noise, /* I Noise energy to add */ - const opus_int D /* I Dimension of XX */ -) -{ - opus_int i; - - for( i = 0; i < D; i++ ) { - matrix_ptr( &XX[ 0 ], i, i, D ) += noise; - } - xx[ 0 ] += noise; -} +/*********************************************************************** +Copyright (c) 2006-2011, Skype Limited. All rights reserved. +Redistribution and use in source and binary forms, with or without +modification, (subject to the limitations in the disclaimer below) +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 Skype Limited, nor the names of specific +contributors, may be used to endorse or promote products derived from +this software without specific prior written permission. +NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED +BY THIS LICENSE. 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. +***********************************************************************/ + +#include "silk_main_FLP.h" + +void silk_regularize_correlations_FLP( + SKP_float *XX, /* I/O Correlation matrices */ + SKP_float *xx, /* I/O Correlation values */ + const SKP_float noise, /* I Noise energy to add */ + const opus_int D /* I Dimension of XX */ +) +{ + opus_int i; + + for( i = 0; i < D; i++ ) { + matrix_ptr( &XX[ 0 ], i, i, D ) += noise; + } + xx[ 0 ] += noise; +} diff --git a/silk/float/silk_residual_energy_FLP.c b/silk/float/silk_residual_energy_FLP.c index 312a4c3ab..301bf1603 100644 --- a/silk/float/silk_residual_energy_FLP.c +++ b/silk/float/silk_residual_energy_FLP.c @@ -1,113 +1,113 @@ -/*********************************************************************** -Copyright (c) 2006-2011, Skype Limited. All rights reserved. -Redistribution and use in source and binary forms, with or without -modification, (subject to the limitations in the disclaimer below) -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 Skype Limited, nor the names of specific -contributors, may be used to endorse or promote products derived from -this software without specific prior written permission. -NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED -BY THIS LICENSE. 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. -***********************************************************************/ - -#include "silk_main_FLP.h" - -#define MAX_ITERATIONS_RESIDUAL_NRG 10 -#define REGULARIZATION_FACTOR 1e-8f - -/* Residual energy: nrg = wxx - 2 * wXx * c + c' * wXX * c */ -SKP_float silk_residual_energy_covar_FLP( /* O Weighted residual energy */ - const SKP_float *c, /* I Filter coefficients */ - SKP_float *wXX, /* I/O Weighted correlation matrix, reg. out */ - const SKP_float *wXx, /* I Weighted correlation vector */ - const SKP_float wxx, /* I Weighted correlation value */ - const opus_int D /* I Dimension */ -) -{ - opus_int i, j, k; - SKP_float tmp, nrg = 0.0f, regularization; - - /* Safety checks */ - SKP_assert( D >= 0 ); - - regularization = REGULARIZATION_FACTOR * ( wXX[ 0 ] + wXX[ D * D - 1 ] ); - for( k = 0; k < MAX_ITERATIONS_RESIDUAL_NRG; k++ ) { - nrg = wxx; - - tmp = 0.0f; - for( i = 0; i < D; i++ ) { - tmp += wXx[ i ] * c[ i ]; - } - nrg -= 2.0f * tmp; - - /* compute c' * wXX * c, assuming wXX is symmetric */ - for( i = 0; i < D; i++ ) { - tmp = 0.0f; - for( j = i + 1; j < D; j++ ) { - tmp += matrix_c_ptr( wXX, i, j, D ) * c[ j ]; - } - nrg += c[ i ] * ( 2.0f * tmp + matrix_c_ptr( wXX, i, i, D ) * c[ i ] ); - } - if( nrg > 0 ) { - break; - } else { - /* Add white noise */ - for( i = 0; i < D; i++ ) { - matrix_c_ptr( wXX, i, i, D ) += regularization; - } - /* Increase noise for next run */ - regularization *= 2.0f; - } - } - if( k == MAX_ITERATIONS_RESIDUAL_NRG ) { - SKP_assert( nrg == 0 ); - nrg = 1.0f; - } - - return nrg; -} - -/* Calculates residual energies of input subframes where all subframes have LPC_order */ -/* of preceeding samples */ -void silk_residual_energy_FLP( - SKP_float nrgs[ MAX_NB_SUBFR ], /* O Residual energy per subframe */ - const SKP_float x[], /* I Input signal */ - SKP_float a[ 2 ][ MAX_LPC_ORDER ], /* I AR coefs for each frame half */ - const SKP_float gains[], /* I Quantization gains */ - const opus_int subfr_length, /* I Subframe length */ - const opus_int nb_subfr, /* I number of subframes */ - const opus_int LPC_order /* I LPC order */ -) -{ - opus_int shift; - SKP_float *LPC_res_ptr, LPC_res[ ( MAX_FRAME_LENGTH + MAX_NB_SUBFR * MAX_LPC_ORDER ) / 2 ]; - - LPC_res_ptr = LPC_res + LPC_order; - shift = LPC_order + subfr_length; - - /* Filter input to create the LPC residual for each frame half, and measure subframe energies */ - silk_LPC_analysis_filter_FLP( LPC_res, a[ 0 ], x + 0 * shift, 2 * shift, LPC_order ); - nrgs[ 0 ] = ( SKP_float )( gains[ 0 ] * gains[ 0 ] * silk_energy_FLP( LPC_res_ptr + 0 * shift, subfr_length ) ); - nrgs[ 1 ] = ( SKP_float )( gains[ 1 ] * gains[ 1 ] * silk_energy_FLP( LPC_res_ptr + 1 * shift, subfr_length ) ); - - if( nb_subfr == MAX_NB_SUBFR ) { - silk_LPC_analysis_filter_FLP( LPC_res, a[ 1 ], x + 2 * shift, 2 * shift, LPC_order ); - nrgs[ 2 ] = ( SKP_float )( gains[ 2 ] * gains[ 2 ] * silk_energy_FLP( LPC_res_ptr + 0 * shift, subfr_length ) ); - nrgs[ 3 ] = ( SKP_float )( gains[ 3 ] * gains[ 3 ] * silk_energy_FLP( LPC_res_ptr + 1 * shift, subfr_length ) ); - } -} +/*********************************************************************** +Copyright (c) 2006-2011, Skype Limited. All rights reserved. +Redistribution and use in source and binary forms, with or without +modification, (subject to the limitations in the disclaimer below) +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 Skype Limited, nor the names of specific +contributors, may be used to endorse or promote products derived from +this software without specific prior written permission. +NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED +BY THIS LICENSE. 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. +***********************************************************************/ + +#include "silk_main_FLP.h" + +#define MAX_ITERATIONS_RESIDUAL_NRG 10 +#define REGULARIZATION_FACTOR 1e-8f + +/* Residual energy: nrg = wxx - 2 * wXx * c + c' * wXX * c */ +SKP_float silk_residual_energy_covar_FLP( /* O Weighted residual energy */ + const SKP_float *c, /* I Filter coefficients */ + SKP_float *wXX, /* I/O Weighted correlation matrix, reg. out */ + const SKP_float *wXx, /* I Weighted correlation vector */ + const SKP_float wxx, /* I Weighted correlation value */ + const opus_int D /* I Dimension */ +) +{ + opus_int i, j, k; + SKP_float tmp, nrg = 0.0f, regularization; + + /* Safety checks */ + SKP_assert( D >= 0 ); + + regularization = REGULARIZATION_FACTOR * ( wXX[ 0 ] + wXX[ D * D - 1 ] ); + for( k = 0; k < MAX_ITERATIONS_RESIDUAL_NRG; k++ ) { + nrg = wxx; + + tmp = 0.0f; + for( i = 0; i < D; i++ ) { + tmp += wXx[ i ] * c[ i ]; + } + nrg -= 2.0f * tmp; + + /* compute c' * wXX * c, assuming wXX is symmetric */ + for( i = 0; i < D; i++ ) { + tmp = 0.0f; + for( j = i + 1; j < D; j++ ) { + tmp += matrix_c_ptr( wXX, i, j, D ) * c[ j ]; + } + nrg += c[ i ] * ( 2.0f * tmp + matrix_c_ptr( wXX, i, i, D ) * c[ i ] ); + } + if( nrg > 0 ) { + break; + } else { + /* Add white noise */ + for( i = 0; i < D; i++ ) { + matrix_c_ptr( wXX, i, i, D ) += regularization; + } + /* Increase noise for next run */ + regularization *= 2.0f; + } + } + if( k == MAX_ITERATIONS_RESIDUAL_NRG ) { + SKP_assert( nrg == 0 ); + nrg = 1.0f; + } + + return nrg; +} + +/* Calculates residual energies of input subframes where all subframes have LPC_order */ +/* of preceeding samples */ +void silk_residual_energy_FLP( + SKP_float nrgs[ MAX_NB_SUBFR ], /* O Residual energy per subframe */ + const SKP_float x[], /* I Input signal */ + SKP_float a[ 2 ][ MAX_LPC_ORDER ], /* I AR coefs for each frame half */ + const SKP_float gains[], /* I Quantization gains */ + const opus_int subfr_length, /* I Subframe length */ + const opus_int nb_subfr, /* I number of subframes */ + const opus_int LPC_order /* I LPC order */ +) +{ + opus_int shift; + SKP_float *LPC_res_ptr, LPC_res[ ( MAX_FRAME_LENGTH + MAX_NB_SUBFR * MAX_LPC_ORDER ) / 2 ]; + + LPC_res_ptr = LPC_res + LPC_order; + shift = LPC_order + subfr_length; + + /* Filter input to create the LPC residual for each frame half, and measure subframe energies */ + silk_LPC_analysis_filter_FLP( LPC_res, a[ 0 ], x + 0 * shift, 2 * shift, LPC_order ); + nrgs[ 0 ] = ( SKP_float )( gains[ 0 ] * gains[ 0 ] * silk_energy_FLP( LPC_res_ptr + 0 * shift, subfr_length ) ); + nrgs[ 1 ] = ( SKP_float )( gains[ 1 ] * gains[ 1 ] * silk_energy_FLP( LPC_res_ptr + 1 * shift, subfr_length ) ); + + if( nb_subfr == MAX_NB_SUBFR ) { + silk_LPC_analysis_filter_FLP( LPC_res, a[ 1 ], x + 2 * shift, 2 * shift, LPC_order ); + nrgs[ 2 ] = ( SKP_float )( gains[ 2 ] * gains[ 2 ] * silk_energy_FLP( LPC_res_ptr + 0 * shift, subfr_length ) ); + nrgs[ 3 ] = ( SKP_float )( gains[ 3 ] * gains[ 3 ] * silk_energy_FLP( LPC_res_ptr + 1 * shift, subfr_length ) ); + } +} diff --git a/silk/float/silk_scale_copy_vector_FLP.c b/silk/float/silk_scale_copy_vector_FLP.c index 89f86c073..c3ef2294d 100644 --- a/silk/float/silk_scale_copy_vector_FLP.c +++ b/silk/float/silk_scale_copy_vector_FLP.c @@ -1,53 +1,53 @@ -/*********************************************************************** -Copyright (c) 2006-2011, Skype Limited. All rights reserved. -Redistribution and use in source and binary forms, with or without -modification, (subject to the limitations in the disclaimer below) -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 Skype Limited, nor the names of specific -contributors, may be used to endorse or promote products derived from -this software without specific prior written permission. -NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED -BY THIS LICENSE. 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. -***********************************************************************/ - -#include "silk_SigProc_FLP.h" - -/* copy and multiply a vector by a constant */ -void silk_scale_copy_vector_FLP( - SKP_float *data_out, - const SKP_float *data_in, - SKP_float gain, - opus_int dataSize -) -{ - opus_int i, dataSize4; - - /* 4x unrolled loop */ - dataSize4 = dataSize & 0xFFFC; - for( i = 0; i < dataSize4; i += 4 ) { - data_out[ i + 0 ] = gain * data_in[ i + 0 ]; - data_out[ i + 1 ] = gain * data_in[ i + 1 ]; - data_out[ i + 2 ] = gain * data_in[ i + 2 ]; - data_out[ i + 3 ] = gain * data_in[ i + 3 ]; - } - - /* any remaining elements */ - for( ; i < dataSize; i++ ) { - data_out[ i ] = gain * data_in[ i ]; - } -} +/*********************************************************************** +Copyright (c) 2006-2011, Skype Limited. All rights reserved. +Redistribution and use in source and binary forms, with or without +modification, (subject to the limitations in the disclaimer below) +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 Skype Limited, nor the names of specific +contributors, may be used to endorse or promote products derived from +this software without specific prior written permission. +NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED +BY THIS LICENSE. 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. +***********************************************************************/ + +#include "silk_SigProc_FLP.h" + +/* copy and multiply a vector by a constant */ +void silk_scale_copy_vector_FLP( + SKP_float *data_out, + const SKP_float *data_in, + SKP_float gain, + opus_int dataSize +) +{ + opus_int i, dataSize4; + + /* 4x unrolled loop */ + dataSize4 = dataSize & 0xFFFC; + for( i = 0; i < dataSize4; i += 4 ) { + data_out[ i + 0 ] = gain * data_in[ i + 0 ]; + data_out[ i + 1 ] = gain * data_in[ i + 1 ]; + data_out[ i + 2 ] = gain * data_in[ i + 2 ]; + data_out[ i + 3 ] = gain * data_in[ i + 3 ]; + } + + /* any remaining elements */ + for( ; i < dataSize; i++ ) { + data_out[ i ] = gain * data_in[ i ]; + } +} diff --git a/silk/float/silk_scale_vector_FLP.c b/silk/float/silk_scale_vector_FLP.c index 83dba6884..be321ab89 100644 --- a/silk/float/silk_scale_vector_FLP.c +++ b/silk/float/silk_scale_vector_FLP.c @@ -1,52 +1,52 @@ -/*********************************************************************** -Copyright (c) 2006-2011, Skype Limited. All rights reserved. -Redistribution and use in source and binary forms, with or without -modification, (subject to the limitations in the disclaimer below) -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 Skype Limited, nor the names of specific -contributors, may be used to endorse or promote products derived from -this software without specific prior written permission. -NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED -BY THIS LICENSE. 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. -***********************************************************************/ - -#include "silk_SigProc_FLP.h" - -/* multiply a vector by a constant */ -void silk_scale_vector_FLP( - SKP_float *data1, - SKP_float gain, - opus_int dataSize -) -{ - opus_int i, dataSize4; - - /* 4x unrolled loop */ - dataSize4 = dataSize & 0xFFFC; - for( i = 0; i < dataSize4; i += 4 ) { - data1[ i + 0 ] *= gain; - data1[ i + 1 ] *= gain; - data1[ i + 2 ] *= gain; - data1[ i + 3 ] *= gain; - } - - /* any remaining elements */ - for( ; i < dataSize; i++ ) { - data1[ i ] *= gain; - } -} +/*********************************************************************** +Copyright (c) 2006-2011, Skype Limited. All rights reserved. +Redistribution and use in source and binary forms, with or without +modification, (subject to the limitations in the disclaimer below) +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 Skype Limited, nor the names of specific +contributors, may be used to endorse or promote products derived from +this software without specific prior written permission. +NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED +BY THIS LICENSE. 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. +***********************************************************************/ + +#include "silk_SigProc_FLP.h" + +/* multiply a vector by a constant */ +void silk_scale_vector_FLP( + SKP_float *data1, + SKP_float gain, + opus_int dataSize +) +{ + opus_int i, dataSize4; + + /* 4x unrolled loop */ + dataSize4 = dataSize & 0xFFFC; + for( i = 0; i < dataSize4; i += 4 ) { + data1[ i + 0 ] *= gain; + data1[ i + 1 ] *= gain; + data1[ i + 2 ] *= gain; + data1[ i + 3 ] *= gain; + } + + /* any remaining elements */ + for( ; i < dataSize; i++ ) { + data1[ i ] *= gain; + } +} diff --git a/silk/float/silk_schur_FLP.c b/silk/float/silk_schur_FLP.c index 887cc1711..684799cfe 100644 --- a/silk/float/silk_schur_FLP.c +++ b/silk/float/silk_schur_FLP.c @@ -1,64 +1,64 @@ -/*********************************************************************** -Copyright (c) 2006-2011, Skype Limited. All rights reserved. -Redistribution and use in source and binary forms, with or without -modification, (subject to the limitations in the disclaimer below) -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 Skype Limited, nor the names of specific -contributors, may be used to endorse or promote products derived from -this software without specific prior written permission. -NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED -BY THIS LICENSE. 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. -***********************************************************************/ - -#include "silk_SigProc_FLP.h" - -SKP_float silk_schur_FLP( /* O returns residual energy */ - SKP_float refl_coef[], /* O reflection coefficients (length order) */ - const SKP_float auto_corr[], /* I autotcorrelation sequence (length order+1) */ - opus_int order /* I order */ -) -{ - opus_int k, n; - SKP_float C[ SILK_MAX_ORDER_LPC + 1 ][ 2 ]; - SKP_float Ctmp1, Ctmp2, rc_tmp; - - /* Copy correlations */ - for( k = 0; k < order+1; k++ ) { - C[ k ][ 0 ] = C[ k ][ 1 ] = auto_corr[ k ]; - } - - for( k = 0; k < order; k++ ) { - /* Get reflection coefficient */ - rc_tmp = -C[ k + 1 ][ 0 ] / SKP_max_float( C[ 0 ][ 1 ], 1e-9f ); - - /* Save the output */ - refl_coef[ k ] = rc_tmp; - - /* Update correlations */ - for( n = 0; n < order - k; n++ ){ - Ctmp1 = C[ n + k + 1 ][ 0 ]; - Ctmp2 = C[ n ][ 1 ]; - C[ n + k + 1 ][ 0 ] = Ctmp1 + Ctmp2 * rc_tmp; - C[ n ][ 1 ] = Ctmp2 + Ctmp1 * rc_tmp; - } - } - - /* Return residual energy */ - return C[ 0 ][ 1 ]; -} - +/*********************************************************************** +Copyright (c) 2006-2011, Skype Limited. All rights reserved. +Redistribution and use in source and binary forms, with or without +modification, (subject to the limitations in the disclaimer below) +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 Skype Limited, nor the names of specific +contributors, may be used to endorse or promote products derived from +this software without specific prior written permission. +NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED +BY THIS LICENSE. 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. +***********************************************************************/ + +#include "silk_SigProc_FLP.h" + +SKP_float silk_schur_FLP( /* O returns residual energy */ + SKP_float refl_coef[], /* O reflection coefficients (length order) */ + const SKP_float auto_corr[], /* I autotcorrelation sequence (length order+1) */ + opus_int order /* I order */ +) +{ + opus_int k, n; + SKP_float C[ SILK_MAX_ORDER_LPC + 1 ][ 2 ]; + SKP_float Ctmp1, Ctmp2, rc_tmp; + + /* Copy correlations */ + for( k = 0; k < order+1; k++ ) { + C[ k ][ 0 ] = C[ k ][ 1 ] = auto_corr[ k ]; + } + + for( k = 0; k < order; k++ ) { + /* Get reflection coefficient */ + rc_tmp = -C[ k + 1 ][ 0 ] / SKP_max_float( C[ 0 ][ 1 ], 1e-9f ); + + /* Save the output */ + refl_coef[ k ] = rc_tmp; + + /* Update correlations */ + for( n = 0; n < order - k; n++ ){ + Ctmp1 = C[ n + k + 1 ][ 0 ]; + Ctmp2 = C[ n ][ 1 ]; + C[ n + k + 1 ][ 0 ] = Ctmp1 + Ctmp2 * rc_tmp; + C[ n ][ 1 ] = Ctmp2 + Ctmp1 * rc_tmp; + } + } + + /* Return residual energy */ + return C[ 0 ][ 1 ]; +} + diff --git a/silk/float/silk_solve_LS_FLP.c b/silk/float/silk_solve_LS_FLP.c index f9ac62eb8..cbfbeaa79 100644 --- a/silk/float/silk_solve_LS_FLP.c +++ b/silk/float/silk_solve_LS_FLP.c @@ -1,203 +1,203 @@ -/*********************************************************************** -Copyright (c) 2006-2011, Skype Limited. All rights reserved. -Redistribution and use in source and binary forms, with or without -modification, (subject to the limitations in the disclaimer below) -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 Skype Limited, nor the names of specific -contributors, may be used to endorse or promote products derived from -this software without specific prior written permission. -NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED -BY THIS LICENSE. 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. -***********************************************************************/ - -#include "silk_main_FLP.h" -#include "silk_tuning_parameters.h" - -/********************************************************************** - * LDL Factorisation. Finds the upper triangular matrix L and the diagonal - * Matrix D (only the diagonal elements returned in a vector)such that - * the symmetric matric A is given by A = L*D*L'. - **********************************************************************/ -void silk_LDL_FLP( - SKP_float *A, /* (I/O) Pointer to Symetric Square Matrix */ - opus_int M, /* (I) Size of Matrix */ - SKP_float *L, /* (I/O) Pointer to Square Upper triangular Matrix */ - SKP_float *Dinv /* (I/O) Pointer to vector holding the inverse diagonal elements of D */ -); - -/********************************************************************** - * Function to solve linear equation Ax = b, when A is a MxM lower - * triangular matrix, with ones on the diagonal. - **********************************************************************/ -void silk_SolveWithLowerTriangularWdiagOnes_FLP( - const SKP_float *L, /* (I) Pointer to Lower Triangular Matrix */ - opus_int M, /* (I) Dim of Matrix equation */ - const SKP_float *b, /* (I) b Vector */ - SKP_float *x /* (O) x Vector */ -); - -/********************************************************************** - * Function to solve linear equation (A^T)x = b, when A is a MxM lower - * triangular, with ones on the diagonal. (ie then A^T is upper triangular) - **********************************************************************/ -void silk_SolveWithUpperTriangularFromLowerWdiagOnes_FLP( - const SKP_float *L, /* (I) Pointer to Lower Triangular Matrix */ - opus_int M, /* (I) Dim of Matrix equation */ - const SKP_float *b, /* (I) b Vector */ - SKP_float *x /* (O) x Vector */ -); - -/********************************************************************** - * Function to solve linear equation Ax = b, when A is a MxM - * symmetric square matrix - using LDL factorisation - **********************************************************************/ -void silk_solve_LDL_FLP( - SKP_float *A, /* I/O Symmetric square matrix, out: reg. */ - const opus_int M, /* I Size of matrix */ - const SKP_float *b, /* I Pointer to b vector */ - SKP_float *x /* O Pointer to x solution vector */ -) -{ - opus_int i; - SKP_float L[ MAX_MATRIX_SIZE ][ MAX_MATRIX_SIZE ]; - SKP_float T[ MAX_MATRIX_SIZE ]; - SKP_float Dinv[ MAX_MATRIX_SIZE ]; // inverse diagonal elements of D - - SKP_assert( M <= MAX_MATRIX_SIZE ); - - /*************************************************** - Factorize A by LDL such that A = L*D*(L^T), - where L is lower triangular with ones on diagonal - ****************************************************/ - silk_LDL_FLP( A, M, &L[ 0 ][ 0 ], Dinv ); - - /**************************************************** - * substitute D*(L^T) = T. ie: - L*D*(L^T)*x = b => L*T = b <=> T = inv(L)*b - ******************************************************/ - silk_SolveWithLowerTriangularWdiagOnes_FLP( &L[ 0 ][ 0 ], M, b, T ); - - /**************************************************** - D*(L^T)*x = T <=> (L^T)*x = inv(D)*T, because D is - diagonal just multiply with 1/d_i - ****************************************************/ - for( i = 0; i < M; i++ ) { - T[ i ] = T[ i ] * Dinv[ i ]; - } - /**************************************************** - x = inv(L') * inv(D) * T - *****************************************************/ - silk_SolveWithUpperTriangularFromLowerWdiagOnes_FLP( &L[ 0 ][ 0 ], M, T, x ); -} - -void silk_SolveWithUpperTriangularFromLowerWdiagOnes_FLP( - const SKP_float *L, /* (I) Pointer to Lower Triangular Matrix */ - opus_int M, /* (I) Dim of Matrix equation */ - const SKP_float *b, /* (I) b Vector */ - SKP_float *x /* (O) x Vector */ -) -{ - opus_int i, j; - SKP_float temp; - const SKP_float *ptr1; - - for( i = M - 1; i >= 0; i-- ) { - ptr1 = matrix_adr( L, 0, i, M ); - temp = 0; - for( j = M - 1; j > i ; j-- ) { - temp += ptr1[ j * M ] * x[ j ]; - } - temp = b[ i ] - temp; - x[ i ] = temp; - } -} - -void silk_SolveWithLowerTriangularWdiagOnes_FLP( - const SKP_float *L, /* (I) Pointer to Lower Triangular Matrix */ - opus_int M, /* (I) Dim of Matrix equation */ - const SKP_float *b, /* (I) b Vector */ - SKP_float *x /* (O) x Vector */ -) -{ - opus_int i, j; - SKP_float temp; - const SKP_float *ptr1; - - for( i = 0; i < M; i++ ) { - ptr1 = matrix_adr( L, i, 0, M ); - temp = 0; - for( j = 0; j < i; j++ ) { - temp += ptr1[ j ] * x[ j ]; - } - temp = b[ i ] - temp; - x[ i ] = temp; - } -} - -void silk_LDL_FLP( - SKP_float *A, /* (I/O) Pointer to Symetric Square Matrix */ - opus_int M, /* (I) Size of Matrix */ - SKP_float *L, /* (I/O) Pointer to Square Upper triangular Matrix */ - SKP_float *Dinv /* (I/O) Pointer to vector holding the inverse diagonal elements of D */ -) -{ - opus_int i, j, k, loop_count, err = 1; - SKP_float *ptr1, *ptr2; - double temp, diag_min_value; - SKP_float v[ MAX_MATRIX_SIZE ], D[ MAX_MATRIX_SIZE ]; // temp arrays - - SKP_assert( M <= MAX_MATRIX_SIZE ); - - diag_min_value = FIND_LTP_COND_FAC * 0.5f * ( A[ 0 ] + A[ M * M - 1 ] ); - for( loop_count = 0; loop_count < M && err == 1; loop_count++ ) { - err = 0; - for( j = 0; j < M; j++ ) { - ptr1 = matrix_adr( L, j, 0, M ); - temp = matrix_ptr( A, j, j, M ); // element in row j column j - for( i = 0; i < j; i++ ) { - v[ i ] = ptr1[ i ] * D[ i ]; - temp -= ptr1[ i ] * v[ i ]; - } - if( temp < diag_min_value ) { - /* Badly conditioned matrix: add white noise and run again */ - temp = ( loop_count + 1 ) * diag_min_value - temp; - for( i = 0; i < M; i++ ) { - matrix_ptr( A, i, i, M ) += ( SKP_float )temp; - } - err = 1; - break; - } - D[ j ] = ( SKP_float )temp; - Dinv[ j ] = ( SKP_float )( 1.0f / temp ); - matrix_ptr( L, j, j, M ) = 1.0f; - - ptr1 = matrix_adr( A, j, 0, M ); - ptr2 = matrix_adr( L, j + 1, 0, M); - for( i = j + 1; i < M; i++ ) { - temp = 0.0; - for( k = 0; k < j; k++ ) { - temp += ptr2[ k ] * v[ k ]; - } - matrix_ptr( L, i, j, M ) = ( SKP_float )( ( ptr1[ i ] - temp ) * Dinv[ j ] ); - ptr2 += M; // go to next column - } - } - } - SKP_assert( err == 0 ); -} - +/*********************************************************************** +Copyright (c) 2006-2011, Skype Limited. All rights reserved. +Redistribution and use in source and binary forms, with or without +modification, (subject to the limitations in the disclaimer below) +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 Skype Limited, nor the names of specific +contributors, may be used to endorse or promote products derived from +this software without specific prior written permission. +NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED +BY THIS LICENSE. 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. +***********************************************************************/ + +#include "silk_main_FLP.h" +#include "silk_tuning_parameters.h" + +/********************************************************************** + * LDL Factorisation. Finds the upper triangular matrix L and the diagonal + * Matrix D (only the diagonal elements returned in a vector)such that + * the symmetric matric A is given by A = L*D*L'. + **********************************************************************/ +void silk_LDL_FLP( + SKP_float *A, /* (I/O) Pointer to Symetric Square Matrix */ + opus_int M, /* (I) Size of Matrix */ + SKP_float *L, /* (I/O) Pointer to Square Upper triangular Matrix */ + SKP_float *Dinv /* (I/O) Pointer to vector holding the inverse diagonal elements of D */ +); + +/********************************************************************** + * Function to solve linear equation Ax = b, when A is a MxM lower + * triangular matrix, with ones on the diagonal. + **********************************************************************/ +void silk_SolveWithLowerTriangularWdiagOnes_FLP( + const SKP_float *L, /* (I) Pointer to Lower Triangular Matrix */ + opus_int M, /* (I) Dim of Matrix equation */ + const SKP_float *b, /* (I) b Vector */ + SKP_float *x /* (O) x Vector */ +); + +/********************************************************************** + * Function to solve linear equation (A^T)x = b, when A is a MxM lower + * triangular, with ones on the diagonal. (ie then A^T is upper triangular) + **********************************************************************/ +void silk_SolveWithUpperTriangularFromLowerWdiagOnes_FLP( + const SKP_float *L, /* (I) Pointer to Lower Triangular Matrix */ + opus_int M, /* (I) Dim of Matrix equation */ + const SKP_float *b, /* (I) b Vector */ + SKP_float *x /* (O) x Vector */ +); + +/********************************************************************** + * Function to solve linear equation Ax = b, when A is a MxM + * symmetric square matrix - using LDL factorisation + **********************************************************************/ +void silk_solve_LDL_FLP( + SKP_float *A, /* I/O Symmetric square matrix, out: reg. */ + const opus_int M, /* I Size of matrix */ + const SKP_float *b, /* I Pointer to b vector */ + SKP_float *x /* O Pointer to x solution vector */ +) +{ + opus_int i; + SKP_float L[ MAX_MATRIX_SIZE ][ MAX_MATRIX_SIZE ]; + SKP_float T[ MAX_MATRIX_SIZE ]; + SKP_float Dinv[ MAX_MATRIX_SIZE ]; // inverse diagonal elements of D + + SKP_assert( M <= MAX_MATRIX_SIZE ); + + /*************************************************** + Factorize A by LDL such that A = L*D*(L^T), + where L is lower triangular with ones on diagonal + ****************************************************/ + silk_LDL_FLP( A, M, &L[ 0 ][ 0 ], Dinv ); + + /**************************************************** + * substitute D*(L^T) = T. ie: + L*D*(L^T)*x = b => L*T = b <=> T = inv(L)*b + ******************************************************/ + silk_SolveWithLowerTriangularWdiagOnes_FLP( &L[ 0 ][ 0 ], M, b, T ); + + /**************************************************** + D*(L^T)*x = T <=> (L^T)*x = inv(D)*T, because D is + diagonal just multiply with 1/d_i + ****************************************************/ + for( i = 0; i < M; i++ ) { + T[ i ] = T[ i ] * Dinv[ i ]; + } + /**************************************************** + x = inv(L') * inv(D) * T + *****************************************************/ + silk_SolveWithUpperTriangularFromLowerWdiagOnes_FLP( &L[ 0 ][ 0 ], M, T, x ); +} + +void silk_SolveWithUpperTriangularFromLowerWdiagOnes_FLP( + const SKP_float *L, /* (I) Pointer to Lower Triangular Matrix */ + opus_int M, /* (I) Dim of Matrix equation */ + const SKP_float *b, /* (I) b Vector */ + SKP_float *x /* (O) x Vector */ +) +{ + opus_int i, j; + SKP_float temp; + const SKP_float *ptr1; + + for( i = M - 1; i >= 0; i-- ) { + ptr1 = matrix_adr( L, 0, i, M ); + temp = 0; + for( j = M - 1; j > i ; j-- ) { + temp += ptr1[ j * M ] * x[ j ]; + } + temp = b[ i ] - temp; + x[ i ] = temp; + } +} + +void silk_SolveWithLowerTriangularWdiagOnes_FLP( + const SKP_float *L, /* (I) Pointer to Lower Triangular Matrix */ + opus_int M, /* (I) Dim of Matrix equation */ + const SKP_float *b, /* (I) b Vector */ + SKP_float *x /* (O) x Vector */ +) +{ + opus_int i, j; + SKP_float temp; + const SKP_float *ptr1; + + for( i = 0; i < M; i++ ) { + ptr1 = matrix_adr( L, i, 0, M ); + temp = 0; + for( j = 0; j < i; j++ ) { + temp += ptr1[ j ] * x[ j ]; + } + temp = b[ i ] - temp; + x[ i ] = temp; + } +} + +void silk_LDL_FLP( + SKP_float *A, /* (I/O) Pointer to Symetric Square Matrix */ + opus_int M, /* (I) Size of Matrix */ + SKP_float *L, /* (I/O) Pointer to Square Upper triangular Matrix */ + SKP_float *Dinv /* (I/O) Pointer to vector holding the inverse diagonal elements of D */ +) +{ + opus_int i, j, k, loop_count, err = 1; + SKP_float *ptr1, *ptr2; + double temp, diag_min_value; + SKP_float v[ MAX_MATRIX_SIZE ], D[ MAX_MATRIX_SIZE ]; // temp arrays + + SKP_assert( M <= MAX_MATRIX_SIZE ); + + diag_min_value = FIND_LTP_COND_FAC * 0.5f * ( A[ 0 ] + A[ M * M - 1 ] ); + for( loop_count = 0; loop_count < M && err == 1; loop_count++ ) { + err = 0; + for( j = 0; j < M; j++ ) { + ptr1 = matrix_adr( L, j, 0, M ); + temp = matrix_ptr( A, j, j, M ); // element in row j column j + for( i = 0; i < j; i++ ) { + v[ i ] = ptr1[ i ] * D[ i ]; + temp -= ptr1[ i ] * v[ i ]; + } + if( temp < diag_min_value ) { + /* Badly conditioned matrix: add white noise and run again */ + temp = ( loop_count + 1 ) * diag_min_value - temp; + for( i = 0; i < M; i++ ) { + matrix_ptr( A, i, i, M ) += ( SKP_float )temp; + } + err = 1; + break; + } + D[ j ] = ( SKP_float )temp; + Dinv[ j ] = ( SKP_float )( 1.0f / temp ); + matrix_ptr( L, j, j, M ) = 1.0f; + + ptr1 = matrix_adr( A, j, 0, M ); + ptr2 = matrix_adr( L, j + 1, 0, M); + for( i = j + 1; i < M; i++ ) { + temp = 0.0; + for( k = 0; k < j; k++ ) { + temp += ptr2[ k ] * v[ k ]; + } + matrix_ptr( L, i, j, M ) = ( SKP_float )( ( ptr1[ i ] - temp ) * Dinv[ j ] ); + ptr2 += M; // go to next column + } + } + } + SKP_assert( err == 0 ); +} + diff --git a/silk/float/silk_sort_FLP.c b/silk/float/silk_sort_FLP.c index fc791a93c..fe6db3a39 100644 --- a/silk/float/silk_sort_FLP.c +++ b/silk/float/silk_sort_FLP.c @@ -1,79 +1,79 @@ -/*********************************************************************** -Copyright (c) 2006-2011, Skype Limited. All rights reserved. -Redistribution and use in source and binary forms, with or without -modification, (subject to the limitations in the disclaimer below) -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 Skype Limited, nor the names of specific -contributors, may be used to endorse or promote products derived from -this software without specific prior written permission. -NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED -BY THIS LICENSE. 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. -***********************************************************************/ - -/* Insertion sort (fast for already almost sorted arrays): */ -/* Best case: O(n) for an already sorted array */ -/* Worst case: O(n^2) for an inversely sorted array */ - -#include "silk_typedef.h" -#include "silk_SigProc_FLP.h" - -void silk_insertion_sort_decreasing_FLP( - SKP_float *a, /* I/O: Unsorted / Sorted vector */ - opus_int *idx, /* O: Index vector for the sorted elements */ - const opus_int L, /* I: Vector length */ - const opus_int K /* I: Number of correctly sorted positions */ -) -{ - SKP_float value; - opus_int i, j; - - /* Safety checks */ - SKP_assert( K > 0 ); - SKP_assert( L > 0 ); - SKP_assert( L >= K ); - - /* Write start indices in index vector */ - for( i = 0; i < K; i++ ) { - idx[ i ] = i; - } - - /* Sort vector elements by value, decreasing order */ - for( i = 1; i < K; i++ ) { - value = a[ i ]; - for( j = i - 1; ( j >= 0 ) && ( value > a[ j ] ); j-- ) { - a[ j + 1 ] = a[ j ]; /* Shift value */ - idx[ j + 1 ] = idx[ j ]; /* Shift index */ - } - a[ j + 1 ] = value; /* Write value */ - idx[ j + 1 ] = i; /* Write index */ - } - - /* If less than L values are asked check the remaining values, */ - /* but only spend CPU to ensure that the K first values are correct */ - for( i = K; i < L; i++ ) { - value = a[ i ]; - if( value > a[ K - 1 ] ) { - for( j = K - 2; ( j >= 0 ) && ( value > a[ j ] ); j-- ) { - a[ j + 1 ] = a[ j ]; /* Shift value */ - idx[ j + 1 ] = idx[ j ]; /* Shift index */ - } - a[ j + 1 ] = value; /* Write value */ - idx[ j + 1 ] = i; /* Write index */ - } - } -} +/*********************************************************************** +Copyright (c) 2006-2011, Skype Limited. All rights reserved. +Redistribution and use in source and binary forms, with or without +modification, (subject to the limitations in the disclaimer below) +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 Skype Limited, nor the names of specific +contributors, may be used to endorse or promote products derived from +this software without specific prior written permission. +NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED +BY THIS LICENSE. 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. +***********************************************************************/ + +/* Insertion sort (fast for already almost sorted arrays): */ +/* Best case: O(n) for an already sorted array */ +/* Worst case: O(n^2) for an inversely sorted array */ + +#include "silk_typedef.h" +#include "silk_SigProc_FLP.h" + +void silk_insertion_sort_decreasing_FLP( + SKP_float *a, /* I/O: Unsorted / Sorted vector */ + opus_int *idx, /* O: Index vector for the sorted elements */ + const opus_int L, /* I: Vector length */ + const opus_int K /* I: Number of correctly sorted positions */ +) +{ + SKP_float value; + opus_int i, j; + + /* Safety checks */ + SKP_assert( K > 0 ); + SKP_assert( L > 0 ); + SKP_assert( L >= K ); + + /* Write start indices in index vector */ + for( i = 0; i < K; i++ ) { + idx[ i ] = i; + } + + /* Sort vector elements by value, decreasing order */ + for( i = 1; i < K; i++ ) { + value = a[ i ]; + for( j = i - 1; ( j >= 0 ) && ( value > a[ j ] ); j-- ) { + a[ j + 1 ] = a[ j ]; /* Shift value */ + idx[ j + 1 ] = idx[ j ]; /* Shift index */ + } + a[ j + 1 ] = value; /* Write value */ + idx[ j + 1 ] = i; /* Write index */ + } + + /* If less than L values are asked check the remaining values, */ + /* but only spend CPU to ensure that the K first values are correct */ + for( i = K; i < L; i++ ) { + value = a[ i ]; + if( value > a[ K - 1 ] ) { + for( j = K - 2; ( j >= 0 ) && ( value > a[ j ] ); j-- ) { + a[ j + 1 ] = a[ j ]; /* Shift value */ + idx[ j + 1 ] = idx[ j ]; /* Shift index */ + } + a[ j + 1 ] = value; /* Write value */ + idx[ j + 1 ] = i; /* Write index */ + } + } +} diff --git a/silk/float/silk_structs_FLP.h b/silk/float/silk_structs_FLP.h index aa47ed112..e9c5b1aef 100644 --- a/silk/float/silk_structs_FLP.h +++ b/silk/float/silk_structs_FLP.h @@ -1,129 +1,129 @@ -/*********************************************************************** -Copyright (c) 2006-2011, Skype Limited. All rights reserved. -Redistribution and use in source and binary forms, with or without -modification, (subject to the limitations in the disclaimer below) -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 Skype Limited, nor the names of specific -contributors, may be used to endorse or promote products derived from -this software without specific prior written permission. -NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED -BY THIS LICENSE. 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. -***********************************************************************/ - -#ifndef SILK_STRUCTS_FLP_H -#define SILK_STRUCTS_FLP_H - -#include "silk_typedef.h" -#include "silk_main.h" -#include "silk_structs.h" - -#ifdef __cplusplus -extern "C" -{ -#endif - -/********************************/ -/* Noise shaping analysis state */ -/********************************/ -typedef struct { - opus_int8 LastGainIndex; - SKP_float HarmBoost_smth; - SKP_float HarmShapeGain_smth; - SKP_float Tilt_smth; -} silk_shape_state_FLP; - -/********************************/ -/* Prefilter state */ -/********************************/ -typedef struct { - SKP_float sLTP_shp[ LTP_BUF_LENGTH ]; - SKP_float sAR_shp[ MAX_SHAPE_LPC_ORDER + 1 ]; - opus_int sLTP_shp_buf_idx; - SKP_float sLF_AR_shp; - SKP_float sLF_MA_shp; - SKP_float sHarmHP; - opus_int32 rand_seed; - opus_int lagPrev; -} silk_prefilter_state_FLP; - -/********************************/ -/* Encoder state FLP */ -/********************************/ -typedef struct { - silk_encoder_state sCmn; /* Common struct, shared with fixed-point code */ - silk_shape_state_FLP sShape; /* Noise shaping state */ - silk_prefilter_state_FLP sPrefilt; /* Prefilter State */ - - /* Buffer for find pitch and noise shape analysis */ - SKP_float x_buf[ 2 * MAX_FRAME_LENGTH + LA_SHAPE_MAX ];/* Buffer for find pitch and noise shape analysis */ - SKP_float LTPCorr; /* Normalized correlation from pitch lag estimator */ - - /* Parameters for LTP scaling control */ - SKP_float prevLTPredCodGain; - SKP_float HPLTPredCodGain; -} silk_encoder_state_FLP; - -/************************/ -/* Encoder control FLP */ -/************************/ -typedef struct { - /* Prediction and coding parameters */ - SKP_float Gains[ MAX_NB_SUBFR ]; - SKP_float PredCoef[ 2 ][ MAX_LPC_ORDER ]; /* holds interpolated and final coefficients */ - SKP_float LTPCoef[LTP_ORDER * MAX_NB_SUBFR]; - SKP_float LTP_scale; - opus_int pitchL[ MAX_NB_SUBFR ]; - - /* Noise shaping parameters */ - SKP_float AR1[ MAX_NB_SUBFR * MAX_SHAPE_LPC_ORDER ]; - SKP_float AR2[ MAX_NB_SUBFR * MAX_SHAPE_LPC_ORDER ]; - SKP_float LF_MA_shp[ MAX_NB_SUBFR ]; - SKP_float LF_AR_shp[ MAX_NB_SUBFR ]; - SKP_float GainsPre[ MAX_NB_SUBFR ]; - SKP_float HarmBoost[ MAX_NB_SUBFR ]; - SKP_float Tilt[ MAX_NB_SUBFR ]; - SKP_float HarmShapeGain[ MAX_NB_SUBFR ]; - SKP_float Lambda; - SKP_float input_quality; - SKP_float coding_quality; - - /* Measures */ - SKP_float sparseness; - SKP_float predGain; - SKP_float LTPredCodGain; - SKP_float ResNrg[ MAX_NB_SUBFR ]; /* Residual energy per subframe */ -} silk_encoder_control_FLP; - -/************************/ -/* Encoder Super Struct */ -/************************/ -typedef struct { - silk_encoder_state_FLP state_Fxx[ ENCODER_NUM_CHANNELS ]; - stereo_enc_state sStereo; - opus_int32 nBitsExceeded; - opus_int nChannelsAPI; - opus_int nChannelsInternal; - opus_int timeSinceSwitchAllowed_ms; - opus_int allowBandwidthSwitch; -} silk_encoder; - -#ifdef __cplusplus -} -#endif - -#endif +/*********************************************************************** +Copyright (c) 2006-2011, Skype Limited. All rights reserved. +Redistribution and use in source and binary forms, with or without +modification, (subject to the limitations in the disclaimer below) +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 Skype Limited, nor the names of specific +contributors, may be used to endorse or promote products derived from +this software without specific prior written permission. +NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED +BY THIS LICENSE. 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. +***********************************************************************/ + +#ifndef SILK_STRUCTS_FLP_H +#define SILK_STRUCTS_FLP_H + +#include "silk_typedef.h" +#include "silk_main.h" +#include "silk_structs.h" + +#ifdef __cplusplus +extern "C" +{ +#endif + +/********************************/ +/* Noise shaping analysis state */ +/********************************/ +typedef struct { + opus_int8 LastGainIndex; + SKP_float HarmBoost_smth; + SKP_float HarmShapeGain_smth; + SKP_float Tilt_smth; +} silk_shape_state_FLP; + +/********************************/ +/* Prefilter state */ +/********************************/ +typedef struct { + SKP_float sLTP_shp[ LTP_BUF_LENGTH ]; + SKP_float sAR_shp[ MAX_SHAPE_LPC_ORDER + 1 ]; + opus_int sLTP_shp_buf_idx; + SKP_float sLF_AR_shp; + SKP_float sLF_MA_shp; + SKP_float sHarmHP; + opus_int32 rand_seed; + opus_int lagPrev; +} silk_prefilter_state_FLP; + +/********************************/ +/* Encoder state FLP */ +/********************************/ +typedef struct { + silk_encoder_state sCmn; /* Common struct, shared with fixed-point code */ + silk_shape_state_FLP sShape; /* Noise shaping state */ + silk_prefilter_state_FLP sPrefilt; /* Prefilter State */ + + /* Buffer for find pitch and noise shape analysis */ + SKP_float x_buf[ 2 * MAX_FRAME_LENGTH + LA_SHAPE_MAX ];/* Buffer for find pitch and noise shape analysis */ + SKP_float LTPCorr; /* Normalized correlation from pitch lag estimator */ + + /* Parameters for LTP scaling control */ + SKP_float prevLTPredCodGain; + SKP_float HPLTPredCodGain; +} silk_encoder_state_FLP; + +/************************/ +/* Encoder control FLP */ +/************************/ +typedef struct { + /* Prediction and coding parameters */ + SKP_float Gains[ MAX_NB_SUBFR ]; + SKP_float PredCoef[ 2 ][ MAX_LPC_ORDER ]; /* holds interpolated and final coefficients */ + SKP_float LTPCoef[LTP_ORDER * MAX_NB_SUBFR]; + SKP_float LTP_scale; + opus_int pitchL[ MAX_NB_SUBFR ]; + + /* Noise shaping parameters */ + SKP_float AR1[ MAX_NB_SUBFR * MAX_SHAPE_LPC_ORDER ]; + SKP_float AR2[ MAX_NB_SUBFR * MAX_SHAPE_LPC_ORDER ]; + SKP_float LF_MA_shp[ MAX_NB_SUBFR ]; + SKP_float LF_AR_shp[ MAX_NB_SUBFR ]; + SKP_float GainsPre[ MAX_NB_SUBFR ]; + SKP_float HarmBoost[ MAX_NB_SUBFR ]; + SKP_float Tilt[ MAX_NB_SUBFR ]; + SKP_float HarmShapeGain[ MAX_NB_SUBFR ]; + SKP_float Lambda; + SKP_float input_quality; + SKP_float coding_quality; + + /* Measures */ + SKP_float sparseness; + SKP_float predGain; + SKP_float LTPredCodGain; + SKP_float ResNrg[ MAX_NB_SUBFR ]; /* Residual energy per subframe */ +} silk_encoder_control_FLP; + +/************************/ +/* Encoder Super Struct */ +/************************/ +typedef struct { + silk_encoder_state_FLP state_Fxx[ ENCODER_NUM_CHANNELS ]; + stereo_enc_state sStereo; + opus_int32 nBitsExceeded; + opus_int nChannelsAPI; + opus_int nChannelsInternal; + opus_int timeSinceSwitchAllowed_ms; + opus_int allowBandwidthSwitch; +} silk_encoder; + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/silk/float/silk_warped_autocorrelation_FLP.c b/silk/float/silk_warped_autocorrelation_FLP.c index 92296c565..327535ae1 100644 --- a/silk/float/silk_warped_autocorrelation_FLP.c +++ b/silk/float/silk_warped_autocorrelation_FLP.c @@ -1,69 +1,69 @@ -/*********************************************************************** -Copyright (c) 2006-2011, Skype Limited. All rights reserved. -Redistribution and use in source and binary forms, with or without -modification, (subject to the limitations in the disclaimer below) -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 Skype Limited, nor the names of specific -contributors, may be used to endorse or promote products derived from -this software without specific prior written permission. -NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED -BY THIS LICENSE. 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. -***********************************************************************/ - -#include "silk_main_FLP.h" - -/* Autocorrelations for a warped frequency axis */ -void silk_warped_autocorrelation_FLP( - SKP_float *corr, /* O Result [order + 1] */ - const SKP_float *input, /* I Input data to correlate */ - const SKP_float warping, /* I Warping coefficient */ - const opus_int length, /* I Length of input */ - const opus_int order /* I Correlation order (even) */ -) -{ - opus_int n, i; - double tmp1, tmp2; - double state[ MAX_SHAPE_LPC_ORDER + 1 ] = { 0 }; - double C[ MAX_SHAPE_LPC_ORDER + 1 ] = { 0 }; - - /* Order must be even */ - SKP_assert( ( order & 1 ) == 0 ); - - /* Loop over samples */ - for( n = 0; n < length; n++ ) { - tmp1 = input[ n ]; - /* Loop over allpass sections */ - for( i = 0; i < order; i += 2 ) { - /* Output of allpass section */ - tmp2 = state[ i ] + warping * ( state[ i + 1 ] - tmp1 ); - state[ i ] = tmp1; - C[ i ] += state[ 0 ] * tmp1; - /* Output of allpass section */ - tmp1 = state[ i + 1 ] + warping * ( state[ i + 2 ] - tmp2 ); - state[ i + 1 ] = tmp2; - C[ i + 1 ] += state[ 0 ] * tmp2; - } - state[ order ] = tmp1; - C[ order ] += state[ 0 ] * tmp1; - } - - /* Copy correlations in SKP_float output format */ - for( i = 0; i < order + 1; i++ ) { - corr[ i ] = ( SKP_float )C[ i ]; - } -} +/*********************************************************************** +Copyright (c) 2006-2011, Skype Limited. All rights reserved. +Redistribution and use in source and binary forms, with or without +modification, (subject to the limitations in the disclaimer below) +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 Skype Limited, nor the names of specific +contributors, may be used to endorse or promote products derived from +this software without specific prior written permission. +NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED +BY THIS LICENSE. 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. +***********************************************************************/ + +#include "silk_main_FLP.h" + +/* Autocorrelations for a warped frequency axis */ +void silk_warped_autocorrelation_FLP( + SKP_float *corr, /* O Result [order + 1] */ + const SKP_float *input, /* I Input data to correlate */ + const SKP_float warping, /* I Warping coefficient */ + const opus_int length, /* I Length of input */ + const opus_int order /* I Correlation order (even) */ +) +{ + opus_int n, i; + double tmp1, tmp2; + double state[ MAX_SHAPE_LPC_ORDER + 1 ] = { 0 }; + double C[ MAX_SHAPE_LPC_ORDER + 1 ] = { 0 }; + + /* Order must be even */ + SKP_assert( ( order & 1 ) == 0 ); + + /* Loop over samples */ + for( n = 0; n < length; n++ ) { + tmp1 = input[ n ]; + /* Loop over allpass sections */ + for( i = 0; i < order; i += 2 ) { + /* Output of allpass section */ + tmp2 = state[ i ] + warping * ( state[ i + 1 ] - tmp1 ); + state[ i ] = tmp1; + C[ i ] += state[ 0 ] * tmp1; + /* Output of allpass section */ + tmp1 = state[ i + 1 ] + warping * ( state[ i + 2 ] - tmp2 ); + state[ i + 1 ] = tmp2; + C[ i + 1 ] += state[ 0 ] * tmp2; + } + state[ order ] = tmp1; + C[ order ] += state[ 0 ] * tmp1; + } + + /* Copy correlations in SKP_float output format */ + for( i = 0; i < order + 1; i++ ) { + corr[ i ] = ( SKP_float )C[ i ]; + } +} diff --git a/silk/float/silk_wrappers_FLP.c b/silk/float/silk_wrappers_FLP.c index f000e9d25..0a2a7f2f4 100644 --- a/silk/float/silk_wrappers_FLP.c +++ b/silk/float/silk_wrappers_FLP.c @@ -1,194 +1,194 @@ -/*********************************************************************** -Copyright (c) 2006-2011, Skype Limited. All rights reserved. -Redistribution and use in source and binary forms, with or without -modification, (subject to the limitations in the disclaimer below) -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 Skype Limited, nor the names of specific -contributors, may be used to endorse or promote products derived from -this software without specific prior written permission. -NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED -BY THIS LICENSE. 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. -***********************************************************************/ - -#include "silk_main_FLP.h" - -/* Wrappers. Calls flp / fix code */ - -/* Convert AR filter coefficients to NLSF parameters */ -void silk_A2NLSF_FLP( - opus_int16 *NLSF_Q15, /* O NLSF vector [ LPC_order ] */ - const SKP_float *pAR, /* I LPC coefficients [ LPC_order ] */ - const opus_int LPC_order /* I LPC order */ -) -{ - opus_int i; - opus_int32 a_fix_Q16[ MAX_LPC_ORDER ]; - - for( i = 0; i < LPC_order; i++ ) { - a_fix_Q16[ i ] = SKP_float2int( pAR[ i ] * 65536.0f ); - } - - silk_A2NLSF( NLSF_Q15, a_fix_Q16, LPC_order ); -} - -/* Convert LSF parameters to AR prediction filter coefficients */ -void silk_NLSF2A_FLP( - SKP_float *pAR, /* O LPC coefficients [ LPC_order ] */ - const opus_int16 *NLSF_Q15, /* I NLSF vector [ LPC_order ] */ - const opus_int LPC_order /* I LPC order */ -) -{ - opus_int i; - opus_int16 a_fix_Q12[ MAX_LPC_ORDER ]; - - silk_NLSF2A( a_fix_Q12, NLSF_Q15, LPC_order ); - - for( i = 0; i < LPC_order; i++ ) { - pAR[ i ] = ( SKP_float )a_fix_Q12[ i ] * ( 1.0f / 4096.0f ); - } -} - -/******************************************/ -/* Floating-point NLSF processing wrapper */ -/******************************************/ -void silk_process_NLSFs_FLP( - silk_encoder_state *psEncC, /* I/O Encoder state */ - SKP_float PredCoef[ 2 ][ MAX_LPC_ORDER ], /* O Prediction coefficients */ - opus_int16 NLSF_Q15[ MAX_LPC_ORDER ], /* I/O Normalized LSFs (quant out) (0 - (2^15-1)) */ - const opus_int16 prev_NLSF_Q15[ MAX_LPC_ORDER ] /* I Previous Normalized LSFs (0 - (2^15-1)) */ -) -{ - opus_int i, j; - opus_int16 PredCoef_Q12[ 2 ][ MAX_LPC_ORDER ]; - - silk_process_NLSFs( psEncC, PredCoef_Q12, NLSF_Q15, prev_NLSF_Q15); - - for( j = 0; j < 2; j++ ) { - for( i = 0; i < psEncC->predictLPCOrder; i++ ) { - PredCoef[ j ][ i ] = ( SKP_float )PredCoef_Q12[ j ][ i ] * ( 1.0f / 4096.0f ); - } - } -} - -/****************************************/ -/* Floating-point Silk NSQ wrapper */ -/****************************************/ -void silk_NSQ_wrapper_FLP( - silk_encoder_state_FLP *psEnc, /* I/O Encoder state FLP */ - silk_encoder_control_FLP *psEncCtrl, /* I/O Encoder control FLP */ - SideInfoIndices *psIndices, /* I/O Quantization indices */ - silk_nsq_state *psNSQ, /* I/O Noise Shaping Quantzation state */ - opus_int8 pulses[], /* O Quantized pulse signal */ - const SKP_float x[] /* I Prefiltered input signal */ -) -{ - opus_int i, j; - opus_int16 x_16[ MAX_FRAME_LENGTH ]; - opus_int32 Gains_Q16[ MAX_NB_SUBFR ]; - SKP_DWORD_ALIGN opus_int16 PredCoef_Q12[ 2 ][ MAX_LPC_ORDER ]; - opus_int16 LTPCoef_Q14[ LTP_ORDER * MAX_NB_SUBFR ]; - opus_int LTP_scale_Q14; - - /* Noise shaping parameters */ - opus_int16 AR2_Q13[ MAX_NB_SUBFR * MAX_SHAPE_LPC_ORDER ]; - opus_int32 LF_shp_Q14[ MAX_NB_SUBFR ]; /* Packs two int16 coefficients per int32 value */ - opus_int Lambda_Q10; - opus_int Tilt_Q14[ MAX_NB_SUBFR ]; - opus_int HarmShapeGain_Q14[ MAX_NB_SUBFR ]; - - /* Convert control struct to fix control struct */ - /* Noise shape parameters */ - for( i = 0; i < psEnc->sCmn.nb_subfr; i++ ) { - for( j = 0; j < psEnc->sCmn.shapingLPCOrder; j++ ) { - AR2_Q13[ i * MAX_SHAPE_LPC_ORDER + j ] = SKP_float2int( psEncCtrl->AR2[ i * MAX_SHAPE_LPC_ORDER + j ] * 8192.0f ); - } - } - - for( i = 0; i < psEnc->sCmn.nb_subfr; i++ ) { - LF_shp_Q14[ i ] = SKP_LSHIFT32( SKP_float2int( psEncCtrl->LF_AR_shp[ i ] * 16384.0f ), 16 ) | - (opus_uint16)SKP_float2int( psEncCtrl->LF_MA_shp[ i ] * 16384.0f ); - Tilt_Q14[ i ] = (opus_int)SKP_float2int( psEncCtrl->Tilt[ i ] * 16384.0f ); - HarmShapeGain_Q14[ i ] = (opus_int)SKP_float2int( psEncCtrl->HarmShapeGain[ i ] * 16384.0f ); - } - Lambda_Q10 = ( opus_int )SKP_float2int( psEncCtrl->Lambda * 1024.0f ); - - /* prediction and coding parameters */ - for( i = 0; i < psEnc->sCmn.nb_subfr * LTP_ORDER; i++ ) { - LTPCoef_Q14[ i ] = ( opus_int16 )SKP_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 )SKP_float2int( psEncCtrl->PredCoef[ j ][ i ] * 4096.0f ); - } - } - - for( i = 0; i < psEnc->sCmn.nb_subfr; i++ ) { - Gains_Q16[ i ] = SKP_float2int( psEncCtrl->Gains[ i ] * 65536.0f ); - SKP_assert( Gains_Q16[ i ] > 0 ); - } - - if( psIndices->signalType == TYPE_VOICED ) { - LTP_scale_Q14 = silk_LTPScales_table_Q14[ psIndices->LTP_scaleIndex ]; - } else { - LTP_scale_Q14 = 0; - } - - /* Convert input to fix */ - SKP_float2short_array( x_16, x, psEnc->sCmn.frame_length ); - - /* 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, - 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, - AR2_Q13, HarmShapeGain_Q14, Tilt_Q14, LF_shp_Q14, Gains_Q16, psEncCtrl->pitchL, Lambda_Q10, LTP_scale_Q14 ); - } -} - -/***********************************************/ -/* Floating-point Silk LTP quantiation wrapper */ -/***********************************************/ -void silk_quant_LTP_gains_FLP( - SKP_float B[ MAX_NB_SUBFR * LTP_ORDER ], /* I/O (Un-)quantized LTP gains */ - opus_int8 cbk_index[ MAX_NB_SUBFR ], /* O Codebook index */ - opus_int8 *periodicity_index, /* O Periodicity index */ - const SKP_float W[ MAX_NB_SUBFR * LTP_ORDER * LTP_ORDER ], /* I Error weights */ - const opus_int mu_Q10, /* I Mu value (R/D tradeoff) */ - const opus_int lowComplexity, /* I Flag for low complexity */ - const opus_int nb_subfr /* I number of subframes */ -) -{ - opus_int i; - opus_int16 B_Q14[ MAX_NB_SUBFR * LTP_ORDER ]; - opus_int32 W_Q18[ MAX_NB_SUBFR*LTP_ORDER*LTP_ORDER ]; - - for( i = 0; i < nb_subfr * LTP_ORDER; i++ ) { - B_Q14[ i ] = (opus_int16)SKP_float2int( B[ i ] * 16384.0f ); - } - for( i = 0; i < nb_subfr * LTP_ORDER * LTP_ORDER; i++ ) { - W_Q18[ i ] = (opus_int32)SKP_float2int( W[ i ] * 262144.0f ); - } - - silk_quant_LTP_gains( B_Q14, cbk_index, periodicity_index, W_Q18, mu_Q10, lowComplexity, nb_subfr ); - - for( i = 0; i < nb_subfr * LTP_ORDER; i++ ) { - B[ i ] = (SKP_float)B_Q14[ i ] * ( 1.0f / 16384.0f ); - } -} +/*********************************************************************** +Copyright (c) 2006-2011, Skype Limited. All rights reserved. +Redistribution and use in source and binary forms, with or without +modification, (subject to the limitations in the disclaimer below) +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 Skype Limited, nor the names of specific +contributors, may be used to endorse or promote products derived from +this software without specific prior written permission. +NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED +BY THIS LICENSE. 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. +***********************************************************************/ + +#include "silk_main_FLP.h" + +/* Wrappers. Calls flp / fix code */ + +/* Convert AR filter coefficients to NLSF parameters */ +void silk_A2NLSF_FLP( + opus_int16 *NLSF_Q15, /* O NLSF vector [ LPC_order ] */ + const SKP_float *pAR, /* I LPC coefficients [ LPC_order ] */ + const opus_int LPC_order /* I LPC order */ +) +{ + opus_int i; + opus_int32 a_fix_Q16[ MAX_LPC_ORDER ]; + + for( i = 0; i < LPC_order; i++ ) { + a_fix_Q16[ i ] = SKP_float2int( pAR[ i ] * 65536.0f ); + } + + silk_A2NLSF( NLSF_Q15, a_fix_Q16, LPC_order ); +} + +/* Convert LSF parameters to AR prediction filter coefficients */ +void silk_NLSF2A_FLP( + SKP_float *pAR, /* O LPC coefficients [ LPC_order ] */ + const opus_int16 *NLSF_Q15, /* I NLSF vector [ LPC_order ] */ + const opus_int LPC_order /* I LPC order */ +) +{ + opus_int i; + opus_int16 a_fix_Q12[ MAX_LPC_ORDER ]; + + silk_NLSF2A( a_fix_Q12, NLSF_Q15, LPC_order ); + + for( i = 0; i < LPC_order; i++ ) { + pAR[ i ] = ( SKP_float )a_fix_Q12[ i ] * ( 1.0f / 4096.0f ); + } +} + +/******************************************/ +/* Floating-point NLSF processing wrapper */ +/******************************************/ +void silk_process_NLSFs_FLP( + silk_encoder_state *psEncC, /* I/O Encoder state */ + SKP_float PredCoef[ 2 ][ MAX_LPC_ORDER ], /* O Prediction coefficients */ + opus_int16 NLSF_Q15[ MAX_LPC_ORDER ], /* I/O Normalized LSFs (quant out) (0 - (2^15-1)) */ + const opus_int16 prev_NLSF_Q15[ MAX_LPC_ORDER ] /* I Previous Normalized LSFs (0 - (2^15-1)) */ +) +{ + opus_int i, j; + opus_int16 PredCoef_Q12[ 2 ][ MAX_LPC_ORDER ]; + + silk_process_NLSFs( psEncC, PredCoef_Q12, NLSF_Q15, prev_NLSF_Q15); + + for( j = 0; j < 2; j++ ) { + for( i = 0; i < psEncC->predictLPCOrder; i++ ) { + PredCoef[ j ][ i ] = ( SKP_float )PredCoef_Q12[ j ][ i ] * ( 1.0f / 4096.0f ); + } + } +} + +/****************************************/ +/* Floating-point Silk NSQ wrapper */ +/****************************************/ +void silk_NSQ_wrapper_FLP( + silk_encoder_state_FLP *psEnc, /* I/O Encoder state FLP */ + silk_encoder_control_FLP *psEncCtrl, /* I/O Encoder control FLP */ + SideInfoIndices *psIndices, /* I/O Quantization indices */ + silk_nsq_state *psNSQ, /* I/O Noise Shaping Quantzation state */ + opus_int8 pulses[], /* O Quantized pulse signal */ + const SKP_float x[] /* I Prefiltered input signal */ +) +{ + opus_int i, j; + opus_int16 x_16[ MAX_FRAME_LENGTH ]; + opus_int32 Gains_Q16[ MAX_NB_SUBFR ]; + SKP_DWORD_ALIGN opus_int16 PredCoef_Q12[ 2 ][ MAX_LPC_ORDER ]; + opus_int16 LTPCoef_Q14[ LTP_ORDER * MAX_NB_SUBFR ]; + opus_int LTP_scale_Q14; + + /* Noise shaping parameters */ + opus_int16 AR2_Q13[ MAX_NB_SUBFR * MAX_SHAPE_LPC_ORDER ]; + opus_int32 LF_shp_Q14[ MAX_NB_SUBFR ]; /* Packs two int16 coefficients per int32 value */ + opus_int Lambda_Q10; + opus_int Tilt_Q14[ MAX_NB_SUBFR ]; + opus_int HarmShapeGain_Q14[ MAX_NB_SUBFR ]; + + /* Convert control struct to fix control struct */ + /* Noise shape parameters */ + for( i = 0; i < psEnc->sCmn.nb_subfr; i++ ) { + for( j = 0; j < psEnc->sCmn.shapingLPCOrder; j++ ) { + AR2_Q13[ i * MAX_SHAPE_LPC_ORDER + j ] = SKP_float2int( psEncCtrl->AR2[ i * MAX_SHAPE_LPC_ORDER + j ] * 8192.0f ); + } + } + + for( i = 0; i < psEnc->sCmn.nb_subfr; i++ ) { + LF_shp_Q14[ i ] = SKP_LSHIFT32( SKP_float2int( psEncCtrl->LF_AR_shp[ i ] * 16384.0f ), 16 ) | + (opus_uint16)SKP_float2int( psEncCtrl->LF_MA_shp[ i ] * 16384.0f ); + Tilt_Q14[ i ] = (opus_int)SKP_float2int( psEncCtrl->Tilt[ i ] * 16384.0f ); + HarmShapeGain_Q14[ i ] = (opus_int)SKP_float2int( psEncCtrl->HarmShapeGain[ i ] * 16384.0f ); + } + Lambda_Q10 = ( opus_int )SKP_float2int( psEncCtrl->Lambda * 1024.0f ); + + /* prediction and coding parameters */ + for( i = 0; i < psEnc->sCmn.nb_subfr * LTP_ORDER; i++ ) { + LTPCoef_Q14[ i ] = ( opus_int16 )SKP_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 )SKP_float2int( psEncCtrl->PredCoef[ j ][ i ] * 4096.0f ); + } + } + + for( i = 0; i < psEnc->sCmn.nb_subfr; i++ ) { + Gains_Q16[ i ] = SKP_float2int( psEncCtrl->Gains[ i ] * 65536.0f ); + SKP_assert( Gains_Q16[ i ] > 0 ); + } + + if( psIndices->signalType == TYPE_VOICED ) { + LTP_scale_Q14 = silk_LTPScales_table_Q14[ psIndices->LTP_scaleIndex ]; + } else { + LTP_scale_Q14 = 0; + } + + /* Convert input to fix */ + SKP_float2short_array( x_16, x, psEnc->sCmn.frame_length ); + + /* 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, + 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, + AR2_Q13, HarmShapeGain_Q14, Tilt_Q14, LF_shp_Q14, Gains_Q16, psEncCtrl->pitchL, Lambda_Q10, LTP_scale_Q14 ); + } +} + +/***********************************************/ +/* Floating-point Silk LTP quantiation wrapper */ +/***********************************************/ +void silk_quant_LTP_gains_FLP( + SKP_float B[ MAX_NB_SUBFR * LTP_ORDER ], /* I/O (Un-)quantized LTP gains */ + opus_int8 cbk_index[ MAX_NB_SUBFR ], /* O Codebook index */ + opus_int8 *periodicity_index, /* O Periodicity index */ + const SKP_float W[ MAX_NB_SUBFR * LTP_ORDER * LTP_ORDER ], /* I Error weights */ + const opus_int mu_Q10, /* I Mu value (R/D tradeoff) */ + const opus_int lowComplexity, /* I Flag for low complexity */ + const opus_int nb_subfr /* I number of subframes */ +) +{ + opus_int i; + opus_int16 B_Q14[ MAX_NB_SUBFR * LTP_ORDER ]; + opus_int32 W_Q18[ MAX_NB_SUBFR*LTP_ORDER*LTP_ORDER ]; + + for( i = 0; i < nb_subfr * LTP_ORDER; i++ ) { + B_Q14[ i ] = (opus_int16)SKP_float2int( B[ i ] * 16384.0f ); + } + for( i = 0; i < nb_subfr * LTP_ORDER * LTP_ORDER; i++ ) { + W_Q18[ i ] = (opus_int32)SKP_float2int( W[ i ] * 262144.0f ); + } + + silk_quant_LTP_gains( B_Q14, cbk_index, periodicity_index, W_Q18, mu_Q10, lowComplexity, nb_subfr ); + + for( i = 0; i < nb_subfr * LTP_ORDER; i++ ) { + B[ i ] = (SKP_float)B_Q14[ i ] * ( 1.0f / 16384.0f ); + } +} diff --git a/silk/silk_A2NLSF.c b/silk/silk_A2NLSF.c index de8f36087..34cfeeddf 100644 --- a/silk/silk_A2NLSF.c +++ b/silk/silk_A2NLSF.c @@ -1,280 +1,280 @@ -/*********************************************************************** -Copyright (c) 2006-2011, Skype Limited. All rights reserved. -Redistribution and use in source and binary forms, with or without -modification, (subject to the limitations in the disclaimer below) -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 Skype Limited, nor the names of specific -contributors, may be used to endorse or promote products derived from -this software without specific prior written permission. -NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED -BY THIS LICENSE. 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. -***********************************************************************/ - -/* Conversion between prediction filter coefficients and NLSFs */ -/* Requires the order to be an even number */ -/* A piecewise linear approximation maps LSF <-> cos(LSF) */ -/* Therefore the result is not accurate NLSFs, but the two */ -/* functions are accurate inverses of each other */ - -#include "silk_SigProc_FIX.h" -#include "silk_tables.h" - -/* 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 - -/* Flag for using 2x as many cosine sampling points, reduces the risk of missing a root */ -#define OVERSAMPLE_COSINE_TABLE 0 - -/* Helper function for A2NLSF(..) */ -/* Transforms polynomials from cos(n*f) to cos(f)^n */ -SKP_INLINE void silk_A2NLSF_trans_poly( - opus_int32 *p, /* I/O Polynomial */ - const opus_int dd /* I Polynomial order (= filter order / 2 ) */ -) -{ - opus_int k, n; - - for( k = 2; k <= dd; k++ ) { - for( n = dd; n > k; n-- ) { - p[ n - 2 ] -= p[ n ]; - } - p[ k - 2 ] -= SKP_LSHIFT( p[ k ], 1 ); - } -} -/* Helper function for A2NLSF(..) */ -/* Polynomial evaluation */ -SKP_INLINE opus_int32 silk_A2NLSF_eval_poly( /* return the polynomial evaluation, in QPoly */ - opus_int32 *p, /* I Polynomial, QPoly */ - const opus_int32 x, /* I Evaluation point, Q12 */ - const opus_int dd /* I Order */ -) -{ - opus_int n; - opus_int32 x_Q16, y32; - - y32 = p[ dd ]; /* QPoly */ - x_Q16 = SKP_LSHIFT( x, 4 ); - for( n = dd - 1; n >= 0; n-- ) { - y32 = SKP_SMLAWW( p[ n ], y32, x_Q16 ); /* QPoly */ - } - return y32; -} - -SKP_INLINE void silk_A2NLSF_init( - const opus_int32 *a_Q16, - opus_int32 *P, - opus_int32 *Q, - const opus_int dd -) -{ - opus_int k; - - /* Convert filter coefs to even and odd polynomials */ - P[dd] = SKP_LSHIFT( 1, QPoly ); - Q[dd] = SKP_LSHIFT( 1, QPoly ); - for( k = 0; k < dd; k++ ) { -#if( QPoly < 16 ) - P[ k ] = SKP_RSHIFT_ROUND( -a_Q16[ dd - k - 1 ] - a_Q16[ dd + k ], 16 - QPoly ); /* QPoly */ - Q[ k ] = SKP_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 ] = SKP_LSHIFT( -a_Q16[ dd - k - 1 ] - a_Q16[ dd + k ], QPoly - 16 ); /* QPoly */ - Q[ k ] = SKP_LSHIFT( -a_Q16[ dd - k - 1 ] + a_Q16[ dd + k ], QPoly - 16 ); /* QPoly */ -#endif - } - - /* Divide out zeros as we have that for even filter orders, */ - /* z = 1 is always a root in Q, and */ - /* z = -1 is always a root in P */ - for( k = dd; k > 0; k-- ) { - P[ k - 1 ] -= P[ k ]; - Q[ k - 1 ] += Q[ k ]; - } - - /* Transform polynomials from cos(n*f) to cos(f)^n */ - silk_A2NLSF_trans_poly( P, dd ); - silk_A2NLSF_trans_poly( Q, dd ); -} - -/* Compute Normalized Line Spectral Frequencies (NLSFs) from whitening filter coefficients */ -/* If not all roots are found, the a_Q16 coefficients are bandwidth expanded until convergence. */ -void silk_A2NLSF( - opus_int16 *NLSF, /* O Normalized Line Spectral Frequencies, Q15 (0 - (2^15-1)), [d] */ - opus_int32 *a_Q16, /* I/O Monic whitening filter coefficients in Q16 [d] */ - const opus_int d /* I Filter order (must be even) */ -) -{ - opus_int i, k, m, dd, root_ix, ffrac; - opus_int32 xlo, xhi, xmid; - opus_int32 ylo, yhi, ymid; - opus_int32 nom, den; - opus_int32 P[ SILK_MAX_ORDER_LPC / 2 + 1 ]; - opus_int32 Q[ SILK_MAX_ORDER_LPC / 2 + 1 ]; - opus_int32 *PQ[ 2 ]; - opus_int32 *p; - - /* Store pointers to array */ - PQ[ 0 ] = P; - PQ[ 1 ] = Q; - - dd = SKP_RSHIFT( d, 1 ); - - silk_A2NLSF_init( a_Q16, P, Q, dd ); - - /* Find roots, alternating between P and Q */ - p = P; /* Pointer to polynomial */ - - xlo = silk_LSFCosTab_FIX_Q12[ 0 ]; // Q12 - ylo = silk_A2NLSF_eval_poly( p, xlo, dd ); - - if( ylo < 0 ) { - /* Set the first NLSF to zero and move on to the next */ - NLSF[ 0 ] = 0; - p = Q; /* Pointer to polynomial */ - ylo = silk_A2NLSF_eval_poly( p, xlo, dd ); - root_ix = 1; /* Index of current root */ - } else { - root_ix = 0; /* Index of current root */ - } - k = 1; /* Loop counter */ - i = 0; /* Counter for bandwidth expansions applied */ - while( 1 ) { - /* Evaluate polynomial */ -#if OVERSAMPLE_COSINE_TABLE - xhi = silk_LSFCosTab_FIX_Q12[ k >> 1 ] + - ( ( silk_LSFCosTab_FIX_Q12[ ( k + 1 ) >> 1 ] - - silk_LSFCosTab_FIX_Q12[ k >> 1 ] ) >> 1 ); /* Q12 */ -#else - xhi = silk_LSFCosTab_FIX_Q12[ k ]; /* Q12 */ -#endif - yhi = silk_A2NLSF_eval_poly( p, xhi, dd ); - - /* Detect zero crossing */ - if( ( ylo <= 0 && yhi >= 0 ) || ( ylo >= 0 && yhi <= 0 ) ) { - /* Binary division */ -#if OVERSAMPLE_COSINE_TABLE - ffrac = -128; -#else - ffrac = -256; -#endif - for( m = 0; m < BIN_DIV_STEPS_A2NLSF_FIX; m++ ) { - /* Evaluate polynomial */ - xmid = SKP_RSHIFT_ROUND( xlo + xhi, 1 ); - ymid = silk_A2NLSF_eval_poly( p, xmid, dd ); - - /* Detect zero crossing */ - if( ( ylo <= 0 && ymid >= 0 ) || ( ylo >= 0 && ymid <= 0 ) ) { - /* Reduce frequency */ - xhi = xmid; - yhi = ymid; - } else { - /* Increase frequency */ - xlo = xmid; - ylo = ymid; -#if OVERSAMPLE_COSINE_TABLE - ffrac = SKP_ADD_RSHIFT( ffrac, 64, m ); -#else - ffrac = SKP_ADD_RSHIFT( ffrac, 128, m ); -#endif - } - } - - /* Interpolate */ - if( SKP_abs( ylo ) < 65536 ) { - /* Avoid dividing by zero */ - den = ylo - yhi; - nom = SKP_LSHIFT( ylo, 8 - BIN_DIV_STEPS_A2NLSF_FIX ) + SKP_RSHIFT( den, 1 ); - if( den != 0 ) { - ffrac += SKP_DIV32( nom, den ); - } - } else { - /* No risk of dividing by zero because abs(ylo - yhi) >= abs(ylo) >= 65536 */ - ffrac += SKP_DIV32( ylo, SKP_RSHIFT( ylo - yhi, 8 - BIN_DIV_STEPS_A2NLSF_FIX ) ); - } -#if OVERSAMPLE_COSINE_TABLE - NLSF[ root_ix ] = (opus_int16)SKP_min_32( SKP_LSHIFT( (opus_int32)k, 7 ) + ffrac, SKP_int16_MAX ); -#else - NLSF[ root_ix ] = (opus_int16)SKP_min_32( SKP_LSHIFT( (opus_int32)k, 8 ) + ffrac, SKP_int16_MAX ); -#endif - - SKP_assert( NLSF[ root_ix ] >= 0 ); - SKP_assert( NLSF[ root_ix ] <= 32767 ); - - root_ix++; /* Next root */ - if( root_ix >= d ) { - /* Found all roots */ - break; - } - /* Alternate pointer to polynomial */ - p = PQ[ root_ix & 1 ]; - - /* Evaluate polynomial */ -#if OVERSAMPLE_COSINE_TABLE - xlo = silk_LSFCosTab_FIX_Q12[ ( k - 1 ) >> 1 ] + - ( ( silk_LSFCosTab_FIX_Q12[ k >> 1 ] - - silk_LSFCosTab_FIX_Q12[ ( k - 1 ) >> 1 ] ) >> 1 ); // Q12 -#else - xlo = silk_LSFCosTab_FIX_Q12[ k - 1 ]; // Q12 -#endif - ylo = SKP_LSHIFT( 1 - ( root_ix & 2 ), 12 ); - } else { - /* Increment loop counter */ - k++; - xlo = xhi; - ylo = yhi; - -#if OVERSAMPLE_COSINE_TABLE - if( k > 2 * LSF_COS_TAB_SZ_FIX ) { -#else - if( k > LSF_COS_TAB_SZ_FIX ) { -#endif - i++; - if( i > MAX_ITERATIONS_A2NLSF_FIX ) { - /* Set NLSFs to white spectrum and exit */ - NLSF[ 0 ] = (opus_int16)SKP_DIV32_16( 1 << 15, d + 1 ); - for( k = 1; k < d; k++ ) { - NLSF[ k ] = (opus_int16)SKP_SMULBB( k + 1, NLSF[ 0 ] ); - } - return; - } - - /* Error: Apply progressively more bandwidth expansion and run again */ - silk_bwexpander_32( a_Q16, d, 65536 - SKP_SMULBB( 10 + i, i ) ); // 10_Q16 = 0.00015 - - silk_A2NLSF_init( a_Q16, P, Q, dd ); - p = P; /* Pointer to polynomial */ - xlo = silk_LSFCosTab_FIX_Q12[ 0 ]; // Q12 - ylo = silk_A2NLSF_eval_poly( p, xlo, dd ); - if( ylo < 0 ) { - /* Set the first NLSF to zero and move on to the next */ - NLSF[ 0 ] = 0; - p = Q; /* Pointer to polynomial */ - ylo = silk_A2NLSF_eval_poly( p, xlo, dd ); - root_ix = 1; /* Index of current root */ - } else { - root_ix = 0; /* Index of current root */ - } - k = 1; /* Reset loop counter */ - } - } - } -} +/*********************************************************************** +Copyright (c) 2006-2011, Skype Limited. All rights reserved. +Redistribution and use in source and binary forms, with or without +modification, (subject to the limitations in the disclaimer below) +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 Skype Limited, nor the names of specific +contributors, may be used to endorse or promote products derived from +this software without specific prior written permission. +NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED +BY THIS LICENSE. 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. +***********************************************************************/ + +/* Conversion between prediction filter coefficients and NLSFs */ +/* Requires the order to be an even number */ +/* A piecewise linear approximation maps LSF <-> cos(LSF) */ +/* Therefore the result is not accurate NLSFs, but the two */ +/* functions are accurate inverses of each other */ + +#include "silk_SigProc_FIX.h" +#include "silk_tables.h" + +/* 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 + +/* Flag for using 2x as many cosine sampling points, reduces the risk of missing a root */ +#define OVERSAMPLE_COSINE_TABLE 0 + +/* Helper function for A2NLSF(..) */ +/* Transforms polynomials from cos(n*f) to cos(f)^n */ +SKP_INLINE void silk_A2NLSF_trans_poly( + opus_int32 *p, /* I/O Polynomial */ + const opus_int dd /* I Polynomial order (= filter order / 2 ) */ +) +{ + opus_int k, n; + + for( k = 2; k <= dd; k++ ) { + for( n = dd; n > k; n-- ) { + p[ n - 2 ] -= p[ n ]; + } + p[ k - 2 ] -= SKP_LSHIFT( p[ k ], 1 ); + } +} +/* Helper function for A2NLSF(..) */ +/* Polynomial evaluation */ +SKP_INLINE opus_int32 silk_A2NLSF_eval_poly( /* return the polynomial evaluation, in QPoly */ + opus_int32 *p, /* I Polynomial, QPoly */ + const opus_int32 x, /* I Evaluation point, Q12 */ + const opus_int dd /* I Order */ +) +{ + opus_int n; + opus_int32 x_Q16, y32; + + y32 = p[ dd ]; /* QPoly */ + x_Q16 = SKP_LSHIFT( x, 4 ); + for( n = dd - 1; n >= 0; n-- ) { + y32 = SKP_SMLAWW( p[ n ], y32, x_Q16 ); /* QPoly */ + } + return y32; +} + +SKP_INLINE void silk_A2NLSF_init( + const opus_int32 *a_Q16, + opus_int32 *P, + opus_int32 *Q, + const opus_int dd +) +{ + opus_int k; + + /* Convert filter coefs to even and odd polynomials */ + P[dd] = SKP_LSHIFT( 1, QPoly ); + Q[dd] = SKP_LSHIFT( 1, QPoly ); + for( k = 0; k < dd; k++ ) { +#if( QPoly < 16 ) + P[ k ] = SKP_RSHIFT_ROUND( -a_Q16[ dd - k - 1 ] - a_Q16[ dd + k ], 16 - QPoly ); /* QPoly */ + Q[ k ] = SKP_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 ] = SKP_LSHIFT( -a_Q16[ dd - k - 1 ] - a_Q16[ dd + k ], QPoly - 16 ); /* QPoly */ + Q[ k ] = SKP_LSHIFT( -a_Q16[ dd - k - 1 ] + a_Q16[ dd + k ], QPoly - 16 ); /* QPoly */ +#endif + } + + /* Divide out zeros as we have that for even filter orders, */ + /* z = 1 is always a root in Q, and */ + /* z = -1 is always a root in P */ + for( k = dd; k > 0; k-- ) { + P[ k - 1 ] -= P[ k ]; + Q[ k - 1 ] += Q[ k ]; + } + + /* Transform polynomials from cos(n*f) to cos(f)^n */ + silk_A2NLSF_trans_poly( P, dd ); + silk_A2NLSF_trans_poly( Q, dd ); +} + +/* Compute Normalized Line Spectral Frequencies (NLSFs) from whitening filter coefficients */ +/* If not all roots are found, the a_Q16 coefficients are bandwidth expanded until convergence. */ +void silk_A2NLSF( + opus_int16 *NLSF, /* O Normalized Line Spectral Frequencies, Q15 (0 - (2^15-1)), [d] */ + opus_int32 *a_Q16, /* I/O Monic whitening filter coefficients in Q16 [d] */ + const opus_int d /* I Filter order (must be even) */ +) +{ + opus_int i, k, m, dd, root_ix, ffrac; + opus_int32 xlo, xhi, xmid; + opus_int32 ylo, yhi, ymid; + opus_int32 nom, den; + opus_int32 P[ SILK_MAX_ORDER_LPC / 2 + 1 ]; + opus_int32 Q[ SILK_MAX_ORDER_LPC / 2 + 1 ]; + opus_int32 *PQ[ 2 ]; + opus_int32 *p; + + /* Store pointers to array */ + PQ[ 0 ] = P; + PQ[ 1 ] = Q; + + dd = SKP_RSHIFT( d, 1 ); + + silk_A2NLSF_init( a_Q16, P, Q, dd ); + + /* Find roots, alternating between P and Q */ + p = P; /* Pointer to polynomial */ + + xlo = silk_LSFCosTab_FIX_Q12[ 0 ]; // Q12 + ylo = silk_A2NLSF_eval_poly( p, xlo, dd ); + + if( ylo < 0 ) { + /* Set the first NLSF to zero and move on to the next */ + NLSF[ 0 ] = 0; + p = Q; /* Pointer to polynomial */ + ylo = silk_A2NLSF_eval_poly( p, xlo, dd ); + root_ix = 1; /* Index of current root */ + } else { + root_ix = 0; /* Index of current root */ + } + k = 1; /* Loop counter */ + i = 0; /* Counter for bandwidth expansions applied */ + while( 1 ) { + /* Evaluate polynomial */ +#if OVERSAMPLE_COSINE_TABLE + xhi = silk_LSFCosTab_FIX_Q12[ k >> 1 ] + + ( ( silk_LSFCosTab_FIX_Q12[ ( k + 1 ) >> 1 ] - + silk_LSFCosTab_FIX_Q12[ k >> 1 ] ) >> 1 ); /* Q12 */ +#else + xhi = silk_LSFCosTab_FIX_Q12[ k ]; /* Q12 */ +#endif + yhi = silk_A2NLSF_eval_poly( p, xhi, dd ); + + /* Detect zero crossing */ + if( ( ylo <= 0 && yhi >= 0 ) || ( ylo >= 0 && yhi <= 0 ) ) { + /* Binary division */ +#if OVERSAMPLE_COSINE_TABLE + ffrac = -128; +#else + ffrac = -256; +#endif + for( m = 0; m < BIN_DIV_STEPS_A2NLSF_FIX; m++ ) { + /* Evaluate polynomial */ + xmid = SKP_RSHIFT_ROUND( xlo + xhi, 1 ); + ymid = silk_A2NLSF_eval_poly( p, xmid, dd ); + + /* Detect zero crossing */ + if( ( ylo <= 0 && ymid >= 0 ) || ( ylo >= 0 && ymid <= 0 ) ) { + /* Reduce frequency */ + xhi = xmid; + yhi = ymid; + } else { + /* Increase frequency */ + xlo = xmid; + ylo = ymid; +#if OVERSAMPLE_COSINE_TABLE + ffrac = SKP_ADD_RSHIFT( ffrac, 64, m ); +#else + ffrac = SKP_ADD_RSHIFT( ffrac, 128, m ); +#endif + } + } + + /* Interpolate */ + if( SKP_abs( ylo ) < 65536 ) { + /* Avoid dividing by zero */ + den = ylo - yhi; + nom = SKP_LSHIFT( ylo, 8 - BIN_DIV_STEPS_A2NLSF_FIX ) + SKP_RSHIFT( den, 1 ); + if( den != 0 ) { + ffrac += SKP_DIV32( nom, den ); + } + } else { + /* No risk of dividing by zero because abs(ylo - yhi) >= abs(ylo) >= 65536 */ + ffrac += SKP_DIV32( ylo, SKP_RSHIFT( ylo - yhi, 8 - BIN_DIV_STEPS_A2NLSF_FIX ) ); + } +#if OVERSAMPLE_COSINE_TABLE + NLSF[ root_ix ] = (opus_int16)SKP_min_32( SKP_LSHIFT( (opus_int32)k, 7 ) + ffrac, SKP_int16_MAX ); +#else + NLSF[ root_ix ] = (opus_int16)SKP_min_32( SKP_LSHIFT( (opus_int32)k, 8 ) + ffrac, SKP_int16_MAX ); +#endif + + SKP_assert( NLSF[ root_ix ] >= 0 ); + SKP_assert( NLSF[ root_ix ] <= 32767 ); + + root_ix++; /* Next root */ + if( root_ix >= d ) { + /* Found all roots */ + break; + } + /* Alternate pointer to polynomial */ + p = PQ[ root_ix & 1 ]; + + /* Evaluate polynomial */ +#if OVERSAMPLE_COSINE_TABLE + xlo = silk_LSFCosTab_FIX_Q12[ ( k - 1 ) >> 1 ] + + ( ( silk_LSFCosTab_FIX_Q12[ k >> 1 ] - + silk_LSFCosTab_FIX_Q12[ ( k - 1 ) >> 1 ] ) >> 1 ); // Q12 +#else + xlo = silk_LSFCosTab_FIX_Q12[ k - 1 ]; // Q12 +#endif + ylo = SKP_LSHIFT( 1 - ( root_ix & 2 ), 12 ); + } else { + /* Increment loop counter */ + k++; + xlo = xhi; + ylo = yhi; + +#if OVERSAMPLE_COSINE_TABLE + if( k > 2 * LSF_COS_TAB_SZ_FIX ) { +#else + if( k > LSF_COS_TAB_SZ_FIX ) { +#endif + i++; + if( i > MAX_ITERATIONS_A2NLSF_FIX ) { + /* Set NLSFs to white spectrum and exit */ + NLSF[ 0 ] = (opus_int16)SKP_DIV32_16( 1 << 15, d + 1 ); + for( k = 1; k < d; k++ ) { + NLSF[ k ] = (opus_int16)SKP_SMULBB( k + 1, NLSF[ 0 ] ); + } + return; + } + + /* Error: Apply progressively more bandwidth expansion and run again */ + silk_bwexpander_32( a_Q16, d, 65536 - SKP_SMULBB( 10 + i, i ) ); // 10_Q16 = 0.00015 + + silk_A2NLSF_init( a_Q16, P, Q, dd ); + p = P; /* Pointer to polynomial */ + xlo = silk_LSFCosTab_FIX_Q12[ 0 ]; // Q12 + ylo = silk_A2NLSF_eval_poly( p, xlo, dd ); + if( ylo < 0 ) { + /* Set the first NLSF to zero and move on to the next */ + NLSF[ 0 ] = 0; + p = Q; /* Pointer to polynomial */ + ylo = silk_A2NLSF_eval_poly( p, xlo, dd ); + root_ix = 1; /* Index of current root */ + } else { + root_ix = 0; /* Index of current root */ + } + k = 1; /* Reset loop counter */ + } + } + } +} diff --git a/silk/silk_API.h b/silk/silk_API.h index 1d00dc9c5..e6af6fd89 100644 --- a/silk/silk_API.h +++ b/silk/silk_API.h @@ -1,138 +1,138 @@ -/*********************************************************************** -Copyright (c) 2006-2011, Skype Limited. All rights reserved. -Redistribution and use in source and binary forms, with or without -modification, (subject to the limitations in the disclaimer below) -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 Skype Limited, nor the names of specific -contributors, may be used to endorse or promote products derived from -this software without specific prior written permission. -NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED -BY THIS LICENSE. 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. -***********************************************************************/ - -#ifndef SILK_API_H -#define SILK_API_H - -#include "silk_control.h" -#include "silk_typedef.h" -#include "silk_errors.h" -#include "entenc.h" -#include "entdec.h" - -#ifdef __cplusplus -extern "C" -{ -#endif - -#define SILK_MAX_FRAMES_PER_PACKET 3 - -/* Struct for TOC (Table of Contents) */ -typedef struct { - opus_int VADFlag; /* Voice activity for packet */ - opus_int VADFlags[ SILK_MAX_FRAMES_PER_PACKET ]; /* Voice activity for each frame in packet */ - opus_int inbandFECFlag; /* Flag indicating if packet contains in-band FEC */ -} silk_TOC_struct; - -/****************************************/ -/* Encoder functions */ -/****************************************/ - -/***********************************************/ -/* Get size in bytes of the Silk encoder state */ -/***********************************************/ -opus_int silk_Get_Encoder_Size( /* O: Returns error code */ - opus_int32 *encSizeBytes /* O: Number of bytes in SILK encoder state */ -); - -/*************************/ -/* Init or reset encoder */ -/*************************/ -opus_int silk_InitEncoder( /* O: Returns error code */ - void *encState, /* I/O: State */ - silk_EncControlStruct *encStatus /* O: Encoder Status */ -); - -/***************************************/ -/* Read control structure from encoder */ -/***************************************/ -opus_int silk_QueryEncoder( /* O: Returns error code */ - const void *encState, /* I: State */ - silk_EncControlStruct *encStatus /* O: Encoder Status */ -); - -/**************************/ -/* Encode frame with Silk */ -/**************************/ -/* Note: if prefillFlag is set, the input must contain 10 ms of audio, irrespective of what */ -/* encControl->payloadSize_ms is set to */ -opus_int silk_Encode( /* O: Returns error code */ - void *encState, /* I/O: State */ - silk_EncControlStruct *encControl, /* I: Control status */ - const opus_int16 *samplesIn, /* I: Speech sample input vector */ - opus_int nSamplesIn, /* I: Number of samples in input vector */ - ec_enc *psRangeEnc, /* I/O Compressor data structure */ - opus_int32 *nBytesOut, /* I/O: Number of bytes in payload (input: Max bytes) */ - const opus_int prefillFlag /* I: Flag to indicate prefilling buffers no coding */ -); - -/****************************************/ -/* Decoder functions */ -/****************************************/ - -/***********************************************/ -/* Get size in bytes of the Silk decoder state */ -/***********************************************/ -opus_int silk_Get_Decoder_Size( /* O: Returns error code */ - opus_int32 *decSizeBytes /* O: Number of bytes in SILK decoder state */ -); - -/*************************/ -/* Init or Reset decoder */ -/*************************/ -opus_int silk_InitDecoder( /* O: Returns error code */ - void *decState /* I/O: State */ -); - -/******************/ -/* Decode a frame */ -/******************/ -opus_int silk_Decode( /* O: Returns error code */ - void* decState, /* I/O: State */ - silk_DecControlStruct* decControl, /* I/O: Control Structure */ - opus_int lostFlag, /* I: 0: no loss, 1 loss, 2 decode fec */ - opus_int newPacketFlag, /* I: Indicates first decoder call for this packet */ - ec_dec *psRangeDec, /* I/O Compressor data structure */ - opus_int16 *samplesOut, /* O: Decoded output speech vector */ - opus_int32 *nSamplesOut /* O: Number of samples decoded */ -); - -/**************************************/ -/* Get table of contents for a packet */ -/**************************************/ -opus_int silk_get_TOC( - const opus_uint8 *payload, /* I Payload data */ - const opus_int nBytesIn, /* I: Number of input bytes */ - const opus_int nFramesPerPayload, /* I: Number of SILK frames per payload */ - silk_TOC_struct *Silk_TOC /* O: Type of content */ -); - -#ifdef __cplusplus -} -#endif - -#endif +/*********************************************************************** +Copyright (c) 2006-2011, Skype Limited. All rights reserved. +Redistribution and use in source and binary forms, with or without +modification, (subject to the limitations in the disclaimer below) +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 Skype Limited, nor the names of specific +contributors, may be used to endorse or promote products derived from +this software without specific prior written permission. +NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED +BY THIS LICENSE. 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. +***********************************************************************/ + +#ifndef SILK_API_H +#define SILK_API_H + +#include "silk_control.h" +#include "silk_typedef.h" +#include "silk_errors.h" +#include "entenc.h" +#include "entdec.h" + +#ifdef __cplusplus +extern "C" +{ +#endif + +#define SILK_MAX_FRAMES_PER_PACKET 3 + +/* Struct for TOC (Table of Contents) */ +typedef struct { + opus_int VADFlag; /* Voice activity for packet */ + opus_int VADFlags[ SILK_MAX_FRAMES_PER_PACKET ]; /* Voice activity for each frame in packet */ + opus_int inbandFECFlag; /* Flag indicating if packet contains in-band FEC */ +} silk_TOC_struct; + +/****************************************/ +/* Encoder functions */ +/****************************************/ + +/***********************************************/ +/* Get size in bytes of the Silk encoder state */ +/***********************************************/ +opus_int silk_Get_Encoder_Size( /* O: Returns error code */ + opus_int32 *encSizeBytes /* O: Number of bytes in SILK encoder state */ +); + +/*************************/ +/* Init or reset encoder */ +/*************************/ +opus_int silk_InitEncoder( /* O: Returns error code */ + void *encState, /* I/O: State */ + silk_EncControlStruct *encStatus /* O: Encoder Status */ +); + +/***************************************/ +/* Read control structure from encoder */ +/***************************************/ +opus_int silk_QueryEncoder( /* O: Returns error code */ + const void *encState, /* I: State */ + silk_EncControlStruct *encStatus /* O: Encoder Status */ +); + +/**************************/ +/* Encode frame with Silk */ +/**************************/ +/* Note: if prefillFlag is set, the input must contain 10 ms of audio, irrespective of what */ +/* encControl->payloadSize_ms is set to */ +opus_int silk_Encode( /* O: Returns error code */ + void *encState, /* I/O: State */ + silk_EncControlStruct *encControl, /* I: Control status */ + const opus_int16 *samplesIn, /* I: Speech sample input vector */ + opus_int nSamplesIn, /* I: Number of samples in input vector */ + ec_enc *psRangeEnc, /* I/O Compressor data structure */ + opus_int32 *nBytesOut, /* I/O: Number of bytes in payload (input: Max bytes) */ + const opus_int prefillFlag /* I: Flag to indicate prefilling buffers no coding */ +); + +/****************************************/ +/* Decoder functions */ +/****************************************/ + +/***********************************************/ +/* Get size in bytes of the Silk decoder state */ +/***********************************************/ +opus_int silk_Get_Decoder_Size( /* O: Returns error code */ + opus_int32 *decSizeBytes /* O: Number of bytes in SILK decoder state */ +); + +/*************************/ +/* Init or Reset decoder */ +/*************************/ +opus_int silk_InitDecoder( /* O: Returns error code */ + void *decState /* I/O: State */ +); + +/******************/ +/* Decode a frame */ +/******************/ +opus_int silk_Decode( /* O: Returns error code */ + void* decState, /* I/O: State */ + silk_DecControlStruct* decControl, /* I/O: Control Structure */ + opus_int lostFlag, /* I: 0: no loss, 1 loss, 2 decode fec */ + opus_int newPacketFlag, /* I: Indicates first decoder call for this packet */ + ec_dec *psRangeDec, /* I/O Compressor data structure */ + opus_int16 *samplesOut, /* O: Decoded output speech vector */ + opus_int32 *nSamplesOut /* O: Number of samples decoded */ +); + +/**************************************/ +/* Get table of contents for a packet */ +/**************************************/ +opus_int silk_get_TOC( + const opus_uint8 *payload, /* I Payload data */ + const opus_int nBytesIn, /* I: Number of input bytes */ + const opus_int nFramesPerPayload, /* I: Number of SILK frames per payload */ + silk_TOC_struct *Silk_TOC /* O: Type of content */ +); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/silk/silk_CNG.c b/silk/silk_CNG.c index 5183a0045..f345fa332 100644 --- a/silk/silk_CNG.c +++ b/silk/silk_CNG.c @@ -1,156 +1,156 @@ -/*********************************************************************** -Copyright (c) 2006-2011, Skype Limited. All rights reserved. -Redistribution and use in source and binary forms, with or without -modification, (subject to the limitations in the disclaimer below) -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 Skype Limited, nor the names of specific -contributors, may be used to endorse or promote products derived from -this software without specific prior written permission. -NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED -BY THIS LICENSE. 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. -***********************************************************************/ - -#include "silk_main.h" - -/* Generates excitation for CNG LPC synthesis */ -SKP_INLINE void silk_CNG_exc( - opus_int32 residual_Q10[], /* O CNG residual signal Q10 */ - opus_int32 exc_buf_Q10[], /* I Random samples buffer Q10 */ - opus_int32 Gain_Q16, /* I Gain to apply */ - opus_int length, /* I Length */ - opus_int32 *rand_seed /* I/O Seed to random index generator */ -) -{ - opus_int32 seed; - opus_int i, idx, exc_mask; - - exc_mask = CNG_BUF_MASK_MAX; - while( exc_mask > length ) { - exc_mask = SKP_RSHIFT( exc_mask, 1 ); - } - - seed = *rand_seed; - for( i = 0; i < length; i++ ) { - seed = SKP_RAND( seed ); - idx = ( opus_int )( SKP_RSHIFT( seed, 24 ) & exc_mask ); - SKP_assert( idx >= 0 ); - SKP_assert( idx <= CNG_BUF_MASK_MAX ); - residual_Q10[ i ] = ( opus_int16 )SKP_SAT16( SKP_SMULWW( exc_buf_Q10[ idx ], Gain_Q16 ) ); - } - *rand_seed = seed; -} - -void silk_CNG_Reset( - silk_decoder_state *psDec /* I/O Decoder state */ -) -{ - opus_int i, NLSF_step_Q15, NLSF_acc_Q15; - - NLSF_step_Q15 = SKP_DIV32_16( SKP_int16_MAX, psDec->LPC_order + 1 ); - NLSF_acc_Q15 = 0; - for( i = 0; i < psDec->LPC_order; i++ ) { - NLSF_acc_Q15 += NLSF_step_Q15; - psDec->sCNG.CNG_smth_NLSF_Q15[ i ] = NLSF_acc_Q15; - } - psDec->sCNG.CNG_smth_Gain_Q16 = 0; - psDec->sCNG.rand_seed = 3176576; -} - -/* Updates CNG estimate, and applies the CNG when packet was lost */ -void silk_CNG( - silk_decoder_state *psDec, /* I/O Decoder state */ - silk_decoder_control *psDecCtrl, /* I/O Decoder control */ - opus_int16 signal[], /* I/O Signal */ - opus_int length /* I Length of residual */ -) -{ - opus_int i, j, subfr; - opus_int32 sum_Q6, max_Gain_Q16; - opus_int16 A_Q12[ MAX_LPC_ORDER ]; - opus_int32 CNG_sig_Q10[ MAX_FRAME_LENGTH + MAX_LPC_ORDER ]; - silk_CNG_struct *psCNG = &psDec->sCNG; - - if( psDec->fs_kHz != psCNG->fs_kHz ) { - /* Reset state */ - silk_CNG_Reset( psDec ); - - psCNG->fs_kHz = psDec->fs_kHz; - } - if( psDec->lossCnt == 0 && psDec->prevSignalType == TYPE_NO_VOICE_ACTIVITY ) { - /* Update CNG parameters */ - - /* Smoothing of LSF's */ - for( i = 0; i < psDec->LPC_order; i++ ) { - psCNG->CNG_smth_NLSF_Q15[ i ] += SKP_SMULWB( psDec->prevNLSF_Q15[ i ] - psCNG->CNG_smth_NLSF_Q15[ i ], CNG_NLSF_SMTH_Q16 ); - } - /* Find the subframe with the highest gain */ - max_Gain_Q16 = 0; - subfr = 0; - for( i = 0; i < psDec->nb_subfr; i++ ) { - if( psDecCtrl->Gains_Q16[ i ] > max_Gain_Q16 ) { - max_Gain_Q16 = psDecCtrl->Gains_Q16[ i ]; - subfr = i; - } - } - /* Update CNG excitation buffer with excitation from this subframe */ - SKP_memmove( &psCNG->CNG_exc_buf_Q10[ psDec->subfr_length ], psCNG->CNG_exc_buf_Q10, ( psDec->nb_subfr - 1 ) * psDec->subfr_length * sizeof( opus_int32 ) ); - SKP_memcpy( psCNG->CNG_exc_buf_Q10, &psDec->exc_Q10[ subfr * psDec->subfr_length ], psDec->subfr_length * sizeof( opus_int32 ) ); - - /* Smooth gains */ - for( i = 0; i < psDec->nb_subfr; i++ ) { - psCNG->CNG_smth_Gain_Q16 += SKP_SMULWB( psDecCtrl->Gains_Q16[ i ] - psCNG->CNG_smth_Gain_Q16, CNG_GAIN_SMTH_Q16 ); - } - } - - /* Add CNG when packet is lost or during DTX */ - if( psDec->lossCnt ) { - - /* Generate CNG excitation */ - silk_CNG_exc( CNG_sig_Q10 + MAX_LPC_ORDER, psCNG->CNG_exc_buf_Q10, psCNG->CNG_smth_Gain_Q16, length, &psCNG->rand_seed ); - - /* Convert CNG NLSF to filter representation */ - silk_NLSF2A( A_Q12, psCNG->CNG_smth_NLSF_Q15, psDec->LPC_order ); - - /* Generate CNG signal, by synthesis filtering */ - SKP_memcpy( CNG_sig_Q10, psCNG->CNG_synth_state, MAX_LPC_ORDER * sizeof( opus_int32 ) ); - for( i = 0; i < length; i++ ) { - /* Partially unrolled */ - sum_Q6 = SKP_SMULWB( CNG_sig_Q10[ MAX_LPC_ORDER + i - 1 ], A_Q12[ 0 ] ); - sum_Q6 = SKP_SMLAWB( sum_Q6, CNG_sig_Q10[ MAX_LPC_ORDER + i - 2 ], A_Q12[ 1 ] ); - sum_Q6 = SKP_SMLAWB( sum_Q6, CNG_sig_Q10[ MAX_LPC_ORDER + i - 3 ], A_Q12[ 2 ] ); - sum_Q6 = SKP_SMLAWB( sum_Q6, CNG_sig_Q10[ MAX_LPC_ORDER + i - 4 ], A_Q12[ 3 ] ); - sum_Q6 = SKP_SMLAWB( sum_Q6, CNG_sig_Q10[ MAX_LPC_ORDER + i - 5 ], A_Q12[ 4 ] ); - sum_Q6 = SKP_SMLAWB( sum_Q6, CNG_sig_Q10[ MAX_LPC_ORDER + i - 6 ], A_Q12[ 5 ] ); - sum_Q6 = SKP_SMLAWB( sum_Q6, CNG_sig_Q10[ MAX_LPC_ORDER + i - 7 ], A_Q12[ 6 ] ); - sum_Q6 = SKP_SMLAWB( sum_Q6, CNG_sig_Q10[ MAX_LPC_ORDER + i - 8 ], A_Q12[ 7 ] ); - sum_Q6 = SKP_SMLAWB( sum_Q6, CNG_sig_Q10[ MAX_LPC_ORDER + i - 9 ], A_Q12[ 8 ] ); - sum_Q6 = SKP_SMLAWB( sum_Q6, CNG_sig_Q10[ MAX_LPC_ORDER + i - 10 ], A_Q12[ 9 ] ); - for( j = 10; j < psDec->LPC_order; j++ ) { - sum_Q6 = SKP_SMLAWB( sum_Q6, CNG_sig_Q10[ MAX_LPC_ORDER + i - j - 1 ], A_Q12[ j ] ); - } - - /* Update states */ - CNG_sig_Q10[ MAX_LPC_ORDER + i ] = SKP_ADD_LSHIFT( CNG_sig_Q10[ MAX_LPC_ORDER + i ], sum_Q6, 4 ); - - signal[ i ] = SKP_ADD_SAT16( signal[ i ], SKP_RSHIFT_ROUND( sum_Q6, 6 ) ); - } - SKP_memcpy( psCNG->CNG_synth_state, &CNG_sig_Q10[ length ], MAX_LPC_ORDER * sizeof( opus_int32 ) ); - } else { - SKP_memset( psCNG->CNG_synth_state, 0, psDec->LPC_order * sizeof( opus_int32 ) ); - } -} +/*********************************************************************** +Copyright (c) 2006-2011, Skype Limited. All rights reserved. +Redistribution and use in source and binary forms, with or without +modification, (subject to the limitations in the disclaimer below) +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 Skype Limited, nor the names of specific +contributors, may be used to endorse or promote products derived from +this software without specific prior written permission. +NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED +BY THIS LICENSE. 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. +***********************************************************************/ + +#include "silk_main.h" + +/* Generates excitation for CNG LPC synthesis */ +SKP_INLINE void silk_CNG_exc( + opus_int32 residual_Q10[], /* O CNG residual signal Q10 */ + opus_int32 exc_buf_Q10[], /* I Random samples buffer Q10 */ + opus_int32 Gain_Q16, /* I Gain to apply */ + opus_int length, /* I Length */ + opus_int32 *rand_seed /* I/O Seed to random index generator */ +) +{ + opus_int32 seed; + opus_int i, idx, exc_mask; + + exc_mask = CNG_BUF_MASK_MAX; + while( exc_mask > length ) { + exc_mask = SKP_RSHIFT( exc_mask, 1 ); + } + + seed = *rand_seed; + for( i = 0; i < length; i++ ) { + seed = SKP_RAND( seed ); + idx = ( opus_int )( SKP_RSHIFT( seed, 24 ) & exc_mask ); + SKP_assert( idx >= 0 ); + SKP_assert( idx <= CNG_BUF_MASK_MAX ); + residual_Q10[ i ] = ( opus_int16 )SKP_SAT16( SKP_SMULWW( exc_buf_Q10[ idx ], Gain_Q16 ) ); + } + *rand_seed = seed; +} + +void silk_CNG_Reset( + silk_decoder_state *psDec /* I/O Decoder state */ +) +{ + opus_int i, NLSF_step_Q15, NLSF_acc_Q15; + + NLSF_step_Q15 = SKP_DIV32_16( SKP_int16_MAX, psDec->LPC_order + 1 ); + NLSF_acc_Q15 = 0; + for( i = 0; i < psDec->LPC_order; i++ ) { + NLSF_acc_Q15 += NLSF_step_Q15; + psDec->sCNG.CNG_smth_NLSF_Q15[ i ] = NLSF_acc_Q15; + } + psDec->sCNG.CNG_smth_Gain_Q16 = 0; + psDec->sCNG.rand_seed = 3176576; +} + +/* Updates CNG estimate, and applies the CNG when packet was lost */ +void silk_CNG( + silk_decoder_state *psDec, /* I/O Decoder state */ + silk_decoder_control *psDecCtrl, /* I/O Decoder control */ + opus_int16 signal[], /* I/O Signal */ + opus_int length /* I Length of residual */ +) +{ + opus_int i, j, subfr; + opus_int32 sum_Q6, max_Gain_Q16; + opus_int16 A_Q12[ MAX_LPC_ORDER ]; + opus_int32 CNG_sig_Q10[ MAX_FRAME_LENGTH + MAX_LPC_ORDER ]; + silk_CNG_struct *psCNG = &psDec->sCNG; + + if( psDec->fs_kHz != psCNG->fs_kHz ) { + /* Reset state */ + silk_CNG_Reset( psDec ); + + psCNG->fs_kHz = psDec->fs_kHz; + } + if( psDec->lossCnt == 0 && psDec->prevSignalType == TYPE_NO_VOICE_ACTIVITY ) { + /* Update CNG parameters */ + + /* Smoothing of LSF's */ + for( i = 0; i < psDec->LPC_order; i++ ) { + psCNG->CNG_smth_NLSF_Q15[ i ] += SKP_SMULWB( psDec->prevNLSF_Q15[ i ] - psCNG->CNG_smth_NLSF_Q15[ i ], CNG_NLSF_SMTH_Q16 ); + } + /* Find the subframe with the highest gain */ + max_Gain_Q16 = 0; + subfr = 0; + for( i = 0; i < psDec->nb_subfr; i++ ) { + if( psDecCtrl->Gains_Q16[ i ] > max_Gain_Q16 ) { + max_Gain_Q16 = psDecCtrl->Gains_Q16[ i ]; + subfr = i; + } + } + /* Update CNG excitation buffer with excitation from this subframe */ + SKP_memmove( &psCNG->CNG_exc_buf_Q10[ psDec->subfr_length ], psCNG->CNG_exc_buf_Q10, ( psDec->nb_subfr - 1 ) * psDec->subfr_length * sizeof( opus_int32 ) ); + SKP_memcpy( psCNG->CNG_exc_buf_Q10, &psDec->exc_Q10[ subfr * psDec->subfr_length ], psDec->subfr_length * sizeof( opus_int32 ) ); + + /* Smooth gains */ + for( i = 0; i < psDec->nb_subfr; i++ ) { + psCNG->CNG_smth_Gain_Q16 += SKP_SMULWB( psDecCtrl->Gains_Q16[ i ] - psCNG->CNG_smth_Gain_Q16, CNG_GAIN_SMTH_Q16 ); + } + } + + /* Add CNG when packet is lost or during DTX */ + if( psDec->lossCnt ) { + + /* Generate CNG excitation */ + silk_CNG_exc( CNG_sig_Q10 + MAX_LPC_ORDER, psCNG->CNG_exc_buf_Q10, psCNG->CNG_smth_Gain_Q16, length, &psCNG->rand_seed ); + + /* Convert CNG NLSF to filter representation */ + silk_NLSF2A( A_Q12, psCNG->CNG_smth_NLSF_Q15, psDec->LPC_order ); + + /* Generate CNG signal, by synthesis filtering */ + SKP_memcpy( CNG_sig_Q10, psCNG->CNG_synth_state, MAX_LPC_ORDER * sizeof( opus_int32 ) ); + for( i = 0; i < length; i++ ) { + /* Partially unrolled */ + sum_Q6 = SKP_SMULWB( CNG_sig_Q10[ MAX_LPC_ORDER + i - 1 ], A_Q12[ 0 ] ); + sum_Q6 = SKP_SMLAWB( sum_Q6, CNG_sig_Q10[ MAX_LPC_ORDER + i - 2 ], A_Q12[ 1 ] ); + sum_Q6 = SKP_SMLAWB( sum_Q6, CNG_sig_Q10[ MAX_LPC_ORDER + i - 3 ], A_Q12[ 2 ] ); + sum_Q6 = SKP_SMLAWB( sum_Q6, CNG_sig_Q10[ MAX_LPC_ORDER + i - 4 ], A_Q12[ 3 ] ); + sum_Q6 = SKP_SMLAWB( sum_Q6, CNG_sig_Q10[ MAX_LPC_ORDER + i - 5 ], A_Q12[ 4 ] ); + sum_Q6 = SKP_SMLAWB( sum_Q6, CNG_sig_Q10[ MAX_LPC_ORDER + i - 6 ], A_Q12[ 5 ] ); + sum_Q6 = SKP_SMLAWB( sum_Q6, CNG_sig_Q10[ MAX_LPC_ORDER + i - 7 ], A_Q12[ 6 ] ); + sum_Q6 = SKP_SMLAWB( sum_Q6, CNG_sig_Q10[ MAX_LPC_ORDER + i - 8 ], A_Q12[ 7 ] ); + sum_Q6 = SKP_SMLAWB( sum_Q6, CNG_sig_Q10[ MAX_LPC_ORDER + i - 9 ], A_Q12[ 8 ] ); + sum_Q6 = SKP_SMLAWB( sum_Q6, CNG_sig_Q10[ MAX_LPC_ORDER + i - 10 ], A_Q12[ 9 ] ); + for( j = 10; j < psDec->LPC_order; j++ ) { + sum_Q6 = SKP_SMLAWB( sum_Q6, CNG_sig_Q10[ MAX_LPC_ORDER + i - j - 1 ], A_Q12[ j ] ); + } + + /* Update states */ + CNG_sig_Q10[ MAX_LPC_ORDER + i ] = SKP_ADD_LSHIFT( CNG_sig_Q10[ MAX_LPC_ORDER + i ], sum_Q6, 4 ); + + signal[ i ] = SKP_ADD_SAT16( signal[ i ], SKP_RSHIFT_ROUND( sum_Q6, 6 ) ); + } + SKP_memcpy( psCNG->CNG_synth_state, &CNG_sig_Q10[ length ], MAX_LPC_ORDER * sizeof( opus_int32 ) ); + } else { + SKP_memset( psCNG->CNG_synth_state, 0, psDec->LPC_order * sizeof( opus_int32 ) ); + } +} diff --git a/silk/silk_HP_variable_cutoff.c b/silk/silk_HP_variable_cutoff.c index 0345529f6..fb6c3665b 100644 --- a/silk/silk_HP_variable_cutoff.c +++ b/silk/silk_HP_variable_cutoff.c @@ -1,125 +1,125 @@ -/*********************************************************************** -Copyright (c) 2006-2011, Skype Limited. All rights reserved. -Redistribution and use in source and binary forms, with or without -modification, (subject to the limitations in the disclaimer below) -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 Skype Limited, nor the names of specific -contributors, may be used to endorse or promote products derived from -this software without specific prior written permission. -NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED -BY THIS LICENSE. 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 -#ifdef FIXED_POINT -#include "silk_main_FIX.h" -#else -#include "silk_main_FLP.h" -#endif -#include "silk_tuning_parameters.h" - -/* High-pass filter with cutoff frequency adaptation based on pitch lag statistics */ -void silk_HP_variable_cutoff( - silk_encoder_state_Fxx state_Fxx[], /* I/O Encoder states */ - const opus_int nChannels /* I Number of channels */ -) -{ - opus_int quality_Q15, cutoff_Hz; - opus_int32 B_Q28[ 3 ], A_Q28[ 2 ]; - opus_int32 Fc_Q19, r_Q28, r_Q22; - opus_int32 pitch_freq_Hz_Q16, pitch_freq_log_Q7, delta_freq_Q7; - silk_encoder_state *psEncC1 = &state_Fxx[ 0 ].sCmn; - - if( psEncC1->HP_cutoff_Hz == 0 ) { - /* Adaptive cutoff frequency: estimate low end of pitch frequency range */ - if( psEncC1->prevSignalType == TYPE_VOICED ) { - /* difference, in log domain */ - pitch_freq_Hz_Q16 = SKP_DIV32_16( SKP_LSHIFT( SKP_MUL( psEncC1->fs_kHz, 1000 ), 16 ), psEncC1->prevLag ); - pitch_freq_log_Q7 = silk_lin2log( pitch_freq_Hz_Q16 ) - ( 16 << 7 ); - - /* adjustment based on quality */ - quality_Q15 = psEncC1->input_quality_bands_Q15[ 0 ]; - pitch_freq_log_Q7 = SKP_SMLAWB( pitch_freq_log_Q7, SKP_SMULWB( SKP_LSHIFT( -quality_Q15, 2 ), quality_Q15 ), - pitch_freq_log_Q7 - ( silk_lin2log( SILK_FIX_CONST( VARIABLE_HP_MIN_CUTOFF_HZ, 16 ) ) - ( 16 << 7 ) ) ); - - /* delta_freq = pitch_freq_log - psEnc->variable_HP_smth1; */ - delta_freq_Q7 = pitch_freq_log_Q7 - SKP_RSHIFT( psEncC1->variable_HP_smth1_Q15, 8 ); - if( delta_freq_Q7 < 0 ) { - /* less smoothing for decreasing pitch frequency, to track something close to the minimum */ - delta_freq_Q7 = SKP_MUL( delta_freq_Q7, 3 ); - } - - /* limit delta, to reduce impact of outliers in pitch estimation */ - delta_freq_Q7 = SKP_LIMIT_32( delta_freq_Q7, -SILK_FIX_CONST( VARIABLE_HP_MAX_DELTA_FREQ, 7 ), SILK_FIX_CONST( VARIABLE_HP_MAX_DELTA_FREQ, 7 ) ); - - /* update smoother */ - psEncC1->variable_HP_smth1_Q15 = SKP_SMLAWB( psEncC1->variable_HP_smth1_Q15, - SKP_SMULBB( psEncC1->speech_activity_Q8, delta_freq_Q7 ), SILK_FIX_CONST( VARIABLE_HP_SMTH_COEF1, 16 ) ); - - /* limit frequency range */ - psEncC1->variable_HP_smth1_Q15 = SKP_LIMIT_32( psEncC1->variable_HP_smth1_Q15, - SKP_LSHIFT( silk_lin2log( VARIABLE_HP_MIN_CUTOFF_HZ ), 8 ), - SKP_LSHIFT( silk_lin2log( VARIABLE_HP_MAX_CUTOFF_HZ ), 8 ) ); - } - } else { - /* Externally-controlled cutoff frequency */ - cutoff_Hz = SKP_LIMIT( psEncC1->HP_cutoff_Hz, 10, 500 ); - psEncC1->variable_HP_smth1_Q15 = SKP_LSHIFT( silk_lin2log( cutoff_Hz ), 8 ); - } - - /* second smoother */ - psEncC1->variable_HP_smth2_Q15 = SKP_SMLAWB( psEncC1->variable_HP_smth2_Q15, - psEncC1->variable_HP_smth1_Q15 - psEncC1->variable_HP_smth2_Q15, SILK_FIX_CONST( VARIABLE_HP_SMTH_COEF2, 16 ) ); - - /* convert from log scale to Hertz */ - cutoff_Hz = silk_log2lin( SKP_RSHIFT( psEncC1->variable_HP_smth2_Q15, 8 ) ); - - /********************************/ - /* Compute Filter Coefficients */ - /********************************/ - /* compute cut-off frequency, in radians */ - /* Fc_num = 1.5 * 3.14159 * cutoff_Hz */ - /* Fc_denom = 1e3f * psEncC1->fs_kHz */ - SKP_assert( cutoff_Hz <= SKP_int32_MAX / SILK_FIX_CONST( 1.5 * 3.14159 / 1000, 19 ) ); - Fc_Q19 = SKP_DIV32_16( SKP_SMULBB( SILK_FIX_CONST( 1.5 * 3.14159 / 1000, 19 ), cutoff_Hz ), psEncC1->fs_kHz ); - SKP_assert( Fc_Q19 > 0 && Fc_Q19 < 32768 ); - - r_Q28 = SILK_FIX_CONST( 1.0, 28 ) - SKP_MUL( SILK_FIX_CONST( 0.92, 9 ), Fc_Q19 ); - - /* b = r * [ 1; -2; 1 ]; */ - /* a = [ 1; -2 * r * ( 1 - 0.5 * Fc^2 ); r^2 ]; */ - B_Q28[ 0 ] = r_Q28; - B_Q28[ 1 ] = SKP_LSHIFT( -r_Q28, 1 ); - B_Q28[ 2 ] = r_Q28; - - /* -r * ( 2 - Fc * Fc ); */ - r_Q22 = SKP_RSHIFT( r_Q28, 6 ); - A_Q28[ 0 ] = SKP_SMULWW( r_Q22, SKP_SMULWW( Fc_Q19, Fc_Q19 ) - SILK_FIX_CONST( 2.0, 22 ) ); - A_Q28[ 1 ] = SKP_SMULWW( r_Q22, r_Q22 ); - - /********************************/ - /* High-Pass Filter */ - /********************************/ - silk_biquad_alt( psEncC1->inputBuf, B_Q28, A_Q28, psEncC1->In_HP_State, psEncC1->inputBuf, psEncC1->frame_length ); - if( nChannels == 2 ) { - silk_biquad_alt( state_Fxx[ 1 ].sCmn.inputBuf, B_Q28, A_Q28, state_Fxx[ 1 ].sCmn.In_HP_State, - state_Fxx[ 1 ].sCmn.inputBuf, state_Fxx[ 1 ].sCmn.frame_length ); - } -} +/*********************************************************************** +Copyright (c) 2006-2011, Skype Limited. All rights reserved. +Redistribution and use in source and binary forms, with or without +modification, (subject to the limitations in the disclaimer below) +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 Skype Limited, nor the names of specific +contributors, may be used to endorse or promote products derived from +this software without specific prior written permission. +NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED +BY THIS LICENSE. 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 +#ifdef FIXED_POINT +#include "silk_main_FIX.h" +#else +#include "silk_main_FLP.h" +#endif +#include "silk_tuning_parameters.h" + +/* High-pass filter with cutoff frequency adaptation based on pitch lag statistics */ +void silk_HP_variable_cutoff( + silk_encoder_state_Fxx state_Fxx[], /* I/O Encoder states */ + const opus_int nChannels /* I Number of channels */ +) +{ + opus_int quality_Q15, cutoff_Hz; + opus_int32 B_Q28[ 3 ], A_Q28[ 2 ]; + opus_int32 Fc_Q19, r_Q28, r_Q22; + opus_int32 pitch_freq_Hz_Q16, pitch_freq_log_Q7, delta_freq_Q7; + silk_encoder_state *psEncC1 = &state_Fxx[ 0 ].sCmn; + + if( psEncC1->HP_cutoff_Hz == 0 ) { + /* Adaptive cutoff frequency: estimate low end of pitch frequency range */ + if( psEncC1->prevSignalType == TYPE_VOICED ) { + /* difference, in log domain */ + pitch_freq_Hz_Q16 = SKP_DIV32_16( SKP_LSHIFT( SKP_MUL( psEncC1->fs_kHz, 1000 ), 16 ), psEncC1->prevLag ); + pitch_freq_log_Q7 = silk_lin2log( pitch_freq_Hz_Q16 ) - ( 16 << 7 ); + + /* adjustment based on quality */ + quality_Q15 = psEncC1->input_quality_bands_Q15[ 0 ]; + pitch_freq_log_Q7 = SKP_SMLAWB( pitch_freq_log_Q7, SKP_SMULWB( SKP_LSHIFT( -quality_Q15, 2 ), quality_Q15 ), + pitch_freq_log_Q7 - ( silk_lin2log( SILK_FIX_CONST( VARIABLE_HP_MIN_CUTOFF_HZ, 16 ) ) - ( 16 << 7 ) ) ); + + /* delta_freq = pitch_freq_log - psEnc->variable_HP_smth1; */ + delta_freq_Q7 = pitch_freq_log_Q7 - SKP_RSHIFT( psEncC1->variable_HP_smth1_Q15, 8 ); + if( delta_freq_Q7 < 0 ) { + /* less smoothing for decreasing pitch frequency, to track something close to the minimum */ + delta_freq_Q7 = SKP_MUL( delta_freq_Q7, 3 ); + } + + /* limit delta, to reduce impact of outliers in pitch estimation */ + delta_freq_Q7 = SKP_LIMIT_32( delta_freq_Q7, -SILK_FIX_CONST( VARIABLE_HP_MAX_DELTA_FREQ, 7 ), SILK_FIX_CONST( VARIABLE_HP_MAX_DELTA_FREQ, 7 ) ); + + /* update smoother */ + psEncC1->variable_HP_smth1_Q15 = SKP_SMLAWB( psEncC1->variable_HP_smth1_Q15, + SKP_SMULBB( psEncC1->speech_activity_Q8, delta_freq_Q7 ), SILK_FIX_CONST( VARIABLE_HP_SMTH_COEF1, 16 ) ); + + /* limit frequency range */ + psEncC1->variable_HP_smth1_Q15 = SKP_LIMIT_32( psEncC1->variable_HP_smth1_Q15, + SKP_LSHIFT( silk_lin2log( VARIABLE_HP_MIN_CUTOFF_HZ ), 8 ), + SKP_LSHIFT( silk_lin2log( VARIABLE_HP_MAX_CUTOFF_HZ ), 8 ) ); + } + } else { + /* Externally-controlled cutoff frequency */ + cutoff_Hz = SKP_LIMIT( psEncC1->HP_cutoff_Hz, 10, 500 ); + psEncC1->variable_HP_smth1_Q15 = SKP_LSHIFT( silk_lin2log( cutoff_Hz ), 8 ); + } + + /* second smoother */ + psEncC1->variable_HP_smth2_Q15 = SKP_SMLAWB( psEncC1->variable_HP_smth2_Q15, + psEncC1->variable_HP_smth1_Q15 - psEncC1->variable_HP_smth2_Q15, SILK_FIX_CONST( VARIABLE_HP_SMTH_COEF2, 16 ) ); + + /* convert from log scale to Hertz */ + cutoff_Hz = silk_log2lin( SKP_RSHIFT( psEncC1->variable_HP_smth2_Q15, 8 ) ); + + /********************************/ + /* Compute Filter Coefficients */ + /********************************/ + /* compute cut-off frequency, in radians */ + /* Fc_num = 1.5 * 3.14159 * cutoff_Hz */ + /* Fc_denom = 1e3f * psEncC1->fs_kHz */ + SKP_assert( cutoff_Hz <= SKP_int32_MAX / SILK_FIX_CONST( 1.5 * 3.14159 / 1000, 19 ) ); + Fc_Q19 = SKP_DIV32_16( SKP_SMULBB( SILK_FIX_CONST( 1.5 * 3.14159 / 1000, 19 ), cutoff_Hz ), psEncC1->fs_kHz ); + SKP_assert( Fc_Q19 > 0 && Fc_Q19 < 32768 ); + + r_Q28 = SILK_FIX_CONST( 1.0, 28 ) - SKP_MUL( SILK_FIX_CONST( 0.92, 9 ), Fc_Q19 ); + + /* b = r * [ 1; -2; 1 ]; */ + /* a = [ 1; -2 * r * ( 1 - 0.5 * Fc^2 ); r^2 ]; */ + B_Q28[ 0 ] = r_Q28; + B_Q28[ 1 ] = SKP_LSHIFT( -r_Q28, 1 ); + B_Q28[ 2 ] = r_Q28; + + /* -r * ( 2 - Fc * Fc ); */ + r_Q22 = SKP_RSHIFT( r_Q28, 6 ); + A_Q28[ 0 ] = SKP_SMULWW( r_Q22, SKP_SMULWW( Fc_Q19, Fc_Q19 ) - SILK_FIX_CONST( 2.0, 22 ) ); + A_Q28[ 1 ] = SKP_SMULWW( r_Q22, r_Q22 ); + + /********************************/ + /* High-Pass Filter */ + /********************************/ + silk_biquad_alt( psEncC1->inputBuf, B_Q28, A_Q28, psEncC1->In_HP_State, psEncC1->inputBuf, psEncC1->frame_length ); + if( nChannels == 2 ) { + silk_biquad_alt( state_Fxx[ 1 ].sCmn.inputBuf, B_Q28, A_Q28, state_Fxx[ 1 ].sCmn.In_HP_State, + state_Fxx[ 1 ].sCmn.inputBuf, state_Fxx[ 1 ].sCmn.frame_length ); + } +} diff --git a/silk/silk_Inlines.h b/silk/silk_Inlines.h index 0921b4e34..ed8676684 100644 --- a/silk/silk_Inlines.h +++ b/silk/silk_Inlines.h @@ -1,185 +1,185 @@ -/*********************************************************************** -Copyright (c) 2006-2011, Skype Limited. All rights reserved. -Redistribution and use in source and binary forms, with or without -modification, (subject to the limitations in the disclaimer below) -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 Skype Limited, nor the names of specific -contributors, may be used to endorse or promote products derived from -this software without specific prior written permission. -NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED -BY THIS LICENSE. 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. -***********************************************************************/ - -/*! \file silk_Inlines.h - * \brief silk_Inlines.h defines inline signal processing functions. - */ - -#ifndef _SILK_FIX_INLINES_H_ -#define _SILK_FIX_INLINES_H_ - -#ifdef __cplusplus -extern "C" -{ -#endif - -/* count leading zeros of opus_int64 */ -SKP_INLINE opus_int32 silk_CLZ64(opus_int64 in) -{ - opus_int32 in_upper; - - in_upper = (opus_int32)SKP_RSHIFT64(in, 32); - if (in_upper == 0) { - /* Search in the lower 32 bits */ - return 32 + silk_CLZ32( (opus_int32) in ); - } else { - /* Search in the upper 32 bits */ - return silk_CLZ32( in_upper ); - } -} - -/* get number of leading zeros and fractional part (the bits right after the leading one */ -SKP_INLINE void silk_CLZ_FRAC(opus_int32 in, /* I: input */ - opus_int32 *lz, /* O: number of leading zeros */ - opus_int32 *frac_Q7) /* O: the 7 bits right after the leading one */ -{ - opus_int32 lzeros = silk_CLZ32(in); - - * lz = lzeros; - * frac_Q7 = silk_ROR32(in, 24 - lzeros) & 0x7f; -} - -/* Approximation of square root */ -/* Accuracy: < +/- 10% for output values > 15 */ -/* < +/- 2.5% for output values > 120 */ -SKP_INLINE opus_int32 silk_SQRT_APPROX(opus_int32 x) -{ - opus_int32 y, lz, frac_Q7; - - if( x <= 0 ) { - return 0; - } - - silk_CLZ_FRAC(x, &lz, &frac_Q7); - - if( lz & 1 ) { - y = 32768; - } else { - y = 46214; /* 46214 = sqrt(2) * 32768 */ - } - - /* get scaling right */ - y >>= SKP_RSHIFT(lz, 1); - - /* increment using fractional part of input */ - y = SKP_SMLAWB(y, y, SKP_SMULBB(213, frac_Q7)); - - return y; -} - -/* Divide two int32 values and return result as int32 in a given Q-domain */ -SKP_INLINE opus_int32 silk_DIV32_varQ( /* O returns a good approximation of "(a32 << Qres) / b32" */ - const opus_int32 a32, /* I numerator (Q0) */ - const opus_int32 b32, /* I denominator (Q0) */ - const opus_int Qres /* I Q-domain of result (>= 0) */ -) -{ - opus_int a_headrm, b_headrm, lshift; - opus_int32 b32_inv, a32_nrm, b32_nrm, result; - - SKP_assert( b32 != 0 ); - SKP_assert( Qres >= 0 ); - - /* Compute number of bits head room and normalize inputs */ - a_headrm = silk_CLZ32( SKP_abs(a32) ) - 1; - a32_nrm = SKP_LSHIFT(a32, a_headrm); /* Q: a_headrm */ - b_headrm = silk_CLZ32( SKP_abs(b32) ) - 1; - b32_nrm = SKP_LSHIFT(b32, b_headrm); /* Q: b_headrm */ - - /* Inverse of b32, with 14 bits of precision */ - b32_inv = SKP_DIV32_16( SKP_int32_MAX >> 2, SKP_RSHIFT(b32_nrm, 16) ); /* Q: 29 + 16 - b_headrm */ - - /* First approximation */ - result = SKP_SMULWB(a32_nrm, b32_inv); /* Q: 29 + a_headrm - b_headrm */ - - /* Compute residual by subtracting product of denominator and first approximation */ - a32_nrm -= SKP_LSHIFT_ovflw( SKP_SMMUL(b32_nrm, result), 3 ); /* Q: a_headrm */ - - /* Refinement */ - result = SKP_SMLAWB(result, a32_nrm, b32_inv); /* Q: 29 + a_headrm - b_headrm */ - - /* Convert to Qres domain */ - lshift = 29 + a_headrm - b_headrm - Qres; - if( lshift < 0 ) { - return SKP_LSHIFT_SAT32(result, -lshift); - } else { - if( lshift < 32){ - return SKP_RSHIFT(result, lshift); - } else { - /* Avoid undefined result */ - return 0; - } - } -} - -/* Invert int32 value and return result as int32 in a given Q-domain */ -SKP_INLINE opus_int32 silk_INVERSE32_varQ( /* O returns a good approximation of "(1 << Qres) / b32" */ - const opus_int32 b32, /* I denominator (Q0) */ - const opus_int Qres /* I Q-domain of result (> 0) */ -) -{ - opus_int b_headrm, lshift; - opus_int32 b32_inv, b32_nrm, err_Q32, result; - - SKP_assert( b32 != 0 ); - SKP_assert( Qres > 0 ); - - /* Compute number of bits head room and normalize input */ - b_headrm = silk_CLZ32( SKP_abs(b32) ) - 1; - b32_nrm = SKP_LSHIFT(b32, b_headrm); /* Q: b_headrm */ - - /* Inverse of b32, with 14 bits of precision */ - b32_inv = SKP_DIV32_16( SKP_int32_MAX >> 2, SKP_RSHIFT(b32_nrm, 16) ); /* Q: 29 + 16 - b_headrm */ - - /* First approximation */ - result = SKP_LSHIFT(b32_inv, 16); /* Q: 61 - b_headrm */ - - /* Compute residual by subtracting product of denominator and first approximation from one */ - err_Q32 = SKP_LSHIFT_ovflw( -SKP_SMULWB(b32_nrm, b32_inv), 3 ); /* Q32 */ - - /* Refinement */ - result = SKP_SMLAWW(result, err_Q32, b32_inv); /* Q: 61 - b_headrm */ - - /* Convert to Qres domain */ - lshift = 61 - b_headrm - Qres; - if( lshift <= 0 ) { - return SKP_LSHIFT_SAT32(result, -lshift); - } else { - if( lshift < 32){ - return SKP_RSHIFT(result, lshift); - }else{ - /* Avoid undefined result */ - return 0; - } - } -} - -#ifdef __cplusplus -} -#endif - -#endif //_SILK_FIX_INLINES_H_ +/*********************************************************************** +Copyright (c) 2006-2011, Skype Limited. All rights reserved. +Redistribution and use in source and binary forms, with or without +modification, (subject to the limitations in the disclaimer below) +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 Skype Limited, nor the names of specific +contributors, may be used to endorse or promote products derived from +this software without specific prior written permission. +NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED +BY THIS LICENSE. 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. +***********************************************************************/ + +/*! \file silk_Inlines.h + * \brief silk_Inlines.h defines inline signal processing functions. + */ + +#ifndef _SILK_FIX_INLINES_H_ +#define _SILK_FIX_INLINES_H_ + +#ifdef __cplusplus +extern "C" +{ +#endif + +/* count leading zeros of opus_int64 */ +SKP_INLINE opus_int32 silk_CLZ64(opus_int64 in) +{ + opus_int32 in_upper; + + in_upper = (opus_int32)SKP_RSHIFT64(in, 32); + if (in_upper == 0) { + /* Search in the lower 32 bits */ + return 32 + silk_CLZ32( (opus_int32) in ); + } else { + /* Search in the upper 32 bits */ + return silk_CLZ32( in_upper ); + } +} + +/* get number of leading zeros and fractional part (the bits right after the leading one */ +SKP_INLINE void silk_CLZ_FRAC(opus_int32 in, /* I: input */ + opus_int32 *lz, /* O: number of leading zeros */ + opus_int32 *frac_Q7) /* O: the 7 bits right after the leading one */ +{ + opus_int32 lzeros = silk_CLZ32(in); + + * lz = lzeros; + * frac_Q7 = silk_ROR32(in, 24 - lzeros) & 0x7f; +} + +/* Approximation of square root */ +/* Accuracy: < +/- 10% for output values > 15 */ +/* < +/- 2.5% for output values > 120 */ +SKP_INLINE opus_int32 silk_SQRT_APPROX(opus_int32 x) +{ + opus_int32 y, lz, frac_Q7; + + if( x <= 0 ) { + return 0; + } + + silk_CLZ_FRAC(x, &lz, &frac_Q7); + + if( lz & 1 ) { + y = 32768; + } else { + y = 46214; /* 46214 = sqrt(2) * 32768 */ + } + + /* get scaling right */ + y >>= SKP_RSHIFT(lz, 1); + + /* increment using fractional part of input */ + y = SKP_SMLAWB(y, y, SKP_SMULBB(213, frac_Q7)); + + return y; +} + +/* Divide two int32 values and return result as int32 in a given Q-domain */ +SKP_INLINE opus_int32 silk_DIV32_varQ( /* O returns a good approximation of "(a32 << Qres) / b32" */ + const opus_int32 a32, /* I numerator (Q0) */ + const opus_int32 b32, /* I denominator (Q0) */ + const opus_int Qres /* I Q-domain of result (>= 0) */ +) +{ + opus_int a_headrm, b_headrm, lshift; + opus_int32 b32_inv, a32_nrm, b32_nrm, result; + + SKP_assert( b32 != 0 ); + SKP_assert( Qres >= 0 ); + + /* Compute number of bits head room and normalize inputs */ + a_headrm = silk_CLZ32( SKP_abs(a32) ) - 1; + a32_nrm = SKP_LSHIFT(a32, a_headrm); /* Q: a_headrm */ + b_headrm = silk_CLZ32( SKP_abs(b32) ) - 1; + b32_nrm = SKP_LSHIFT(b32, b_headrm); /* Q: b_headrm */ + + /* Inverse of b32, with 14 bits of precision */ + b32_inv = SKP_DIV32_16( SKP_int32_MAX >> 2, SKP_RSHIFT(b32_nrm, 16) ); /* Q: 29 + 16 - b_headrm */ + + /* First approximation */ + result = SKP_SMULWB(a32_nrm, b32_inv); /* Q: 29 + a_headrm - b_headrm */ + + /* Compute residual by subtracting product of denominator and first approximation */ + a32_nrm -= SKP_LSHIFT_ovflw( SKP_SMMUL(b32_nrm, result), 3 ); /* Q: a_headrm */ + + /* Refinement */ + result = SKP_SMLAWB(result, a32_nrm, b32_inv); /* Q: 29 + a_headrm - b_headrm */ + + /* Convert to Qres domain */ + lshift = 29 + a_headrm - b_headrm - Qres; + if( lshift < 0 ) { + return SKP_LSHIFT_SAT32(result, -lshift); + } else { + if( lshift < 32){ + return SKP_RSHIFT(result, lshift); + } else { + /* Avoid undefined result */ + return 0; + } + } +} + +/* Invert int32 value and return result as int32 in a given Q-domain */ +SKP_INLINE opus_int32 silk_INVERSE32_varQ( /* O returns a good approximation of "(1 << Qres) / b32" */ + const opus_int32 b32, /* I denominator (Q0) */ + const opus_int Qres /* I Q-domain of result (> 0) */ +) +{ + opus_int b_headrm, lshift; + opus_int32 b32_inv, b32_nrm, err_Q32, result; + + SKP_assert( b32 != 0 ); + SKP_assert( Qres > 0 ); + + /* Compute number of bits head room and normalize input */ + b_headrm = silk_CLZ32( SKP_abs(b32) ) - 1; + b32_nrm = SKP_LSHIFT(b32, b_headrm); /* Q: b_headrm */ + + /* Inverse of b32, with 14 bits of precision */ + b32_inv = SKP_DIV32_16( SKP_int32_MAX >> 2, SKP_RSHIFT(b32_nrm, 16) ); /* Q: 29 + 16 - b_headrm */ + + /* First approximation */ + result = SKP_LSHIFT(b32_inv, 16); /* Q: 61 - b_headrm */ + + /* Compute residual by subtracting product of denominator and first approximation from one */ + err_Q32 = SKP_LSHIFT_ovflw( -SKP_SMULWB(b32_nrm, b32_inv), 3 ); /* Q32 */ + + /* Refinement */ + result = SKP_SMLAWW(result, err_Q32, b32_inv); /* Q: 61 - b_headrm */ + + /* Convert to Qres domain */ + lshift = 61 - b_headrm - Qres; + if( lshift <= 0 ) { + return SKP_LSHIFT_SAT32(result, -lshift); + } else { + if( lshift < 32){ + return SKP_RSHIFT(result, lshift); + }else{ + /* Avoid undefined result */ + return 0; + } + } +} + +#ifdef __cplusplus +} +#endif + +#endif //_SILK_FIX_INLINES_H_ diff --git a/silk/silk_LPC_analysis_filter.c b/silk/silk_LPC_analysis_filter.c index 86a7aaa54..5e672b9af 100644 --- a/silk/silk_LPC_analysis_filter.c +++ b/silk/silk_LPC_analysis_filter.c @@ -1,79 +1,79 @@ -/*********************************************************************** -Copyright (c) 2006-2011, Skype Limited. All rights reserved. -Redistribution and use in source and binary forms, with or without -modification, (subject to the limitations in the disclaimer below) -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 Skype Limited, nor the names of specific -contributors, may be used to endorse or promote products derived from -this software without specific prior written permission. -NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED -BY THIS LICENSE. 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. -***********************************************************************/ - -#include "silk_SigProc_FIX.h" - -/*******************************************/ -/* LPC analysis filter */ -/* NB! State is kept internally and the */ -/* filter always starts with zero state */ -/* first d output samples are set to zero */ -/*******************************************/ - -void silk_LPC_analysis_filter( - opus_int16 *out, /* O: Output signal */ - const opus_int16 *in, /* I: Input signal */ - const opus_int16 *B, /* I: MA prediction coefficients, Q12 [order] */ - const opus_int32 len, /* I: Signal length */ - const opus_int32 d /* I: Filter order */ -) -{ - opus_int ix, j; - opus_int32 out32_Q12, out32; - const opus_int16 *in_ptr; - - SKP_assert( d >= 6 ); - SKP_assert( (d & 1) == 0 ); - SKP_assert( d <= len ); - - for ( ix = d; ix < len; ix++) { - in_ptr = &in[ ix - 1 ]; - - out32_Q12 = SKP_SMULBB( in_ptr[ 0 ], B[ 0 ] ); - out32_Q12 = SKP_SMLABB( out32_Q12, in_ptr[ -1 ], B[ 1 ] ); - out32_Q12 = SKP_SMLABB( out32_Q12, in_ptr[ -2 ], B[ 2 ] ); - out32_Q12 = SKP_SMLABB( out32_Q12, in_ptr[ -3 ], B[ 3 ] ); - out32_Q12 = SKP_SMLABB( out32_Q12, in_ptr[ -4 ], B[ 4 ] ); - out32_Q12 = SKP_SMLABB( out32_Q12, in_ptr[ -5 ], B[ 5 ] ); - for( j = 6; j < d; j += 2 ) { - out32_Q12 = SKP_SMLABB( out32_Q12, in_ptr[ -j ], B[ j ] ); - out32_Q12 = SKP_SMLABB( out32_Q12, in_ptr[ -j - 1 ], B[ j + 1 ] ); - } - - /* Subtract prediction */ - out32_Q12 = SKP_SUB32( SKP_LSHIFT( (opus_int32)in_ptr[ 1 ], 12 ), out32_Q12 ); - - /* Scale to Q0 */ - out32 = SKP_RSHIFT_ROUND( out32_Q12, 12 ); - - /* Saturate output */ - out[ ix ] = ( opus_int16 )SKP_SAT16( out32 ); - } - - /* Set first d output samples to zero */ - SKP_memset( out, 0, d * sizeof( opus_int16 ) ); -} +/*********************************************************************** +Copyright (c) 2006-2011, Skype Limited. All rights reserved. +Redistribution and use in source and binary forms, with or without +modification, (subject to the limitations in the disclaimer below) +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 Skype Limited, nor the names of specific +contributors, may be used to endorse or promote products derived from +this software without specific prior written permission. +NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED +BY THIS LICENSE. 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. +***********************************************************************/ + +#include "silk_SigProc_FIX.h" + +/*******************************************/ +/* LPC analysis filter */ +/* NB! State is kept internally and the */ +/* filter always starts with zero state */ +/* first d output samples are set to zero */ +/*******************************************/ + +void silk_LPC_analysis_filter( + opus_int16 *out, /* O: Output signal */ + const opus_int16 *in, /* I: Input signal */ + const opus_int16 *B, /* I: MA prediction coefficients, Q12 [order] */ + const opus_int32 len, /* I: Signal length */ + const opus_int32 d /* I: Filter order */ +) +{ + opus_int ix, j; + opus_int32 out32_Q12, out32; + const opus_int16 *in_ptr; + + SKP_assert( d >= 6 ); + SKP_assert( (d & 1) == 0 ); + SKP_assert( d <= len ); + + for ( ix = d; ix < len; ix++) { + in_ptr = &in[ ix - 1 ]; + + out32_Q12 = SKP_SMULBB( in_ptr[ 0 ], B[ 0 ] ); + out32_Q12 = SKP_SMLABB( out32_Q12, in_ptr[ -1 ], B[ 1 ] ); + out32_Q12 = SKP_SMLABB( out32_Q12, in_ptr[ -2 ], B[ 2 ] ); + out32_Q12 = SKP_SMLABB( out32_Q12, in_ptr[ -3 ], B[ 3 ] ); + out32_Q12 = SKP_SMLABB( out32_Q12, in_ptr[ -4 ], B[ 4 ] ); + out32_Q12 = SKP_SMLABB( out32_Q12, in_ptr[ -5 ], B[ 5 ] ); + for( j = 6; j < d; j += 2 ) { + out32_Q12 = SKP_SMLABB( out32_Q12, in_ptr[ -j ], B[ j ] ); + out32_Q12 = SKP_SMLABB( out32_Q12, in_ptr[ -j - 1 ], B[ j + 1 ] ); + } + + /* Subtract prediction */ + out32_Q12 = SKP_SUB32( SKP_LSHIFT( (opus_int32)in_ptr[ 1 ], 12 ), out32_Q12 ); + + /* Scale to Q0 */ + out32 = SKP_RSHIFT_ROUND( out32_Q12, 12 ); + + /* Saturate output */ + out[ ix ] = ( opus_int16 )SKP_SAT16( out32 ); + } + + /* Set first d output samples to zero */ + SKP_memset( out, 0, d * sizeof( opus_int16 ) ); +} diff --git a/silk/silk_LPC_inv_pred_gain.c b/silk/silk_LPC_inv_pred_gain.c index 2e9346f3c..da551f1cc 100644 --- a/silk/silk_LPC_inv_pred_gain.c +++ b/silk/silk_LPC_inv_pred_gain.c @@ -1,146 +1,146 @@ -/*********************************************************************** -Copyright (c) 2006-2011, Skype Limited. All rights reserved. -Redistribution and use in source and binary forms, with or without -modification, (subject to the limitations in the disclaimer below) -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 Skype Limited, nor the names of specific -contributors, may be used to endorse or promote products derived from -this software without specific prior written permission. -NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED -BY THIS LICENSE. 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. -***********************************************************************/ - -#include "silk_SigProc_FIX.h" - -#define QA 16 -#define A_LIMIT SILK_FIX_CONST( 0.99975, QA ) - -/* Compute inverse of LPC prediction gain, and */ -/* test if LPC coefficients are stable (all poles within unit circle) */ -static opus_int LPC_inverse_pred_gain_QA( /* O: Returns 1 if unstable, otherwise 0 */ - opus_int32 *invGain_Q30, /* O: Inverse prediction gain, Q30 energy domain */ - opus_int32 A_QA[ 2 ][ SILK_MAX_ORDER_LPC ], - /* I: Prediction coefficients */ - const opus_int order /* I: Prediction order */ -) -{ - opus_int k, n, headrm; - opus_int32 rc_Q31, rc_mult1_Q30, rc_mult2_Q16, tmp_QA; - opus_int32 *Aold_QA, *Anew_QA; - - Anew_QA = A_QA[ order & 1 ]; - - *invGain_Q30 = ( 1 << 30 ); - for( k = order - 1; k > 0; k-- ) { - /* Check for stability */ - if( ( Anew_QA[ k ] > A_LIMIT ) || ( Anew_QA[ k ] < -A_LIMIT ) ) { - return 1; - } - - /* Set RC equal to negated AR coef */ - rc_Q31 = -SKP_LSHIFT( Anew_QA[ k ], 31 - QA ); - - /* rc_mult1_Q30 range: [ 1 : 2^30-1 ] */ - rc_mult1_Q30 = ( SKP_int32_MAX >> 1 ) - SKP_SMMUL( rc_Q31, rc_Q31 ); - SKP_assert( rc_mult1_Q30 > ( 1 << 15 ) ); /* reduce A_LIMIT if fails */ - SKP_assert( rc_mult1_Q30 < ( 1 << 30 ) ); - - /* rc_mult2_Q16 range: [ 2^16 : SKP_int32_MAX ] */ - rc_mult2_Q16 = silk_INVERSE32_varQ( rc_mult1_Q30, 46 ); /* 16 = 46 - 30 */ - - /* Update inverse gain */ - /* invGain_Q30 range: [ 0 : 2^30 ] */ - *invGain_Q30 = SKP_LSHIFT( SKP_SMMUL( *invGain_Q30, rc_mult1_Q30 ), 2 ); - SKP_assert( *invGain_Q30 >= 0 ); - SKP_assert( *invGain_Q30 <= ( 1 << 30 ) ); - - /* Swap pointers */ - Aold_QA = Anew_QA; - Anew_QA = A_QA[ k & 1 ]; - - /* Update AR coefficient */ - headrm = silk_CLZ32( rc_mult2_Q16 ) - 1; - rc_mult2_Q16 = SKP_LSHIFT( rc_mult2_Q16, headrm ); /* Q: 16 + headrm */ - for( n = 0; n < k; n++ ) { - tmp_QA = Aold_QA[ n ] - SKP_LSHIFT( SKP_SMMUL( Aold_QA[ k - n - 1 ], rc_Q31 ), 1 ); - Anew_QA[ n ] = SKP_LSHIFT( SKP_SMMUL( tmp_QA, rc_mult2_Q16 ), 16 - headrm ); - } - } - - /* Check for stability */ - if( ( Anew_QA[ 0 ] > A_LIMIT ) || ( Anew_QA[ 0 ] < -A_LIMIT ) ) { - return 1; - } - - /* Set RC equal to negated AR coef */ - rc_Q31 = -SKP_LSHIFT( Anew_QA[ 0 ], 31 - QA ); - - /* Range: [ 1 : 2^30 ] */ - rc_mult1_Q30 = ( SKP_int32_MAX >> 1 ) - SKP_SMMUL( rc_Q31, rc_Q31 ); - - /* Update inverse gain */ - /* Range: [ 0 : 2^30 ] */ - *invGain_Q30 = SKP_LSHIFT( SKP_SMMUL( *invGain_Q30, rc_mult1_Q30 ), 2 ); - SKP_assert( *invGain_Q30 >= 0 ); - SKP_assert( *invGain_Q30 <= 1<<30 ); - - return 0; -} - -/* For input in Q12 domain */ -opus_int silk_LPC_inverse_pred_gain( /* O: Returns 1 if unstable, otherwise 0 */ - opus_int32 *invGain_Q30, /* O: Inverse prediction gain, Q30 energy domain */ - const opus_int16 *A_Q12, /* I: Prediction coefficients, Q12 [order] */ - const opus_int order /* I: Prediction order */ -) -{ - opus_int k; - opus_int32 Atmp_QA[ 2 ][ SILK_MAX_ORDER_LPC ]; - opus_int32 *Anew_QA; - - Anew_QA = Atmp_QA[ order & 1 ]; - - /* Increase Q domain of the AR coefficients */ - for( k = 0; k < order; k++ ) { - Anew_QA[ k ] = SKP_LSHIFT( (opus_int32)A_Q12[ k ], QA - 12 ); - } - - return LPC_inverse_pred_gain_QA( invGain_Q30, Atmp_QA, order ); -} - -/* For input in Q24 domain */ -opus_int silk_LPC_inverse_pred_gain_Q24( /* O: Returns 1 if unstable, otherwise 0 */ - opus_int32 *invGain_Q30, /* O: Inverse prediction gain, Q30 energy domain */ - const opus_int32 *A_Q24, /* I: Prediction coefficients, Q24 [order] */ - const opus_int order /* I: Prediction order */ -) -{ - opus_int k; - opus_int32 Atmp_QA[ 2 ][ SILK_MAX_ORDER_LPC ]; - opus_int32 *Anew_QA; - - Anew_QA = Atmp_QA[ order & 1 ]; - - /* Increase Q domain of the AR coefficients */ - for( k = 0; k < order; k++ ) { - Anew_QA[ k ] = SKP_RSHIFT_ROUND( A_Q24[ k ], 24 - QA ); - } - - return LPC_inverse_pred_gain_QA( invGain_Q30, Atmp_QA, order ); -} - +/*********************************************************************** +Copyright (c) 2006-2011, Skype Limited. All rights reserved. +Redistribution and use in source and binary forms, with or without +modification, (subject to the limitations in the disclaimer below) +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 Skype Limited, nor the names of specific +contributors, may be used to endorse or promote products derived from +this software without specific prior written permission. +NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED +BY THIS LICENSE. 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. +***********************************************************************/ + +#include "silk_SigProc_FIX.h" + +#define QA 16 +#define A_LIMIT SILK_FIX_CONST( 0.99975, QA ) + +/* Compute inverse of LPC prediction gain, and */ +/* test if LPC coefficients are stable (all poles within unit circle) */ +static opus_int LPC_inverse_pred_gain_QA( /* O: Returns 1 if unstable, otherwise 0 */ + opus_int32 *invGain_Q30, /* O: Inverse prediction gain, Q30 energy domain */ + opus_int32 A_QA[ 2 ][ SILK_MAX_ORDER_LPC ], + /* I: Prediction coefficients */ + const opus_int order /* I: Prediction order */ +) +{ + opus_int k, n, headrm; + opus_int32 rc_Q31, rc_mult1_Q30, rc_mult2_Q16, tmp_QA; + opus_int32 *Aold_QA, *Anew_QA; + + Anew_QA = A_QA[ order & 1 ]; + + *invGain_Q30 = ( 1 << 30 ); + for( k = order - 1; k > 0; k-- ) { + /* Check for stability */ + if( ( Anew_QA[ k ] > A_LIMIT ) || ( Anew_QA[ k ] < -A_LIMIT ) ) { + return 1; + } + + /* Set RC equal to negated AR coef */ + rc_Q31 = -SKP_LSHIFT( Anew_QA[ k ], 31 - QA ); + + /* rc_mult1_Q30 range: [ 1 : 2^30-1 ] */ + rc_mult1_Q30 = ( SKP_int32_MAX >> 1 ) - SKP_SMMUL( rc_Q31, rc_Q31 ); + SKP_assert( rc_mult1_Q30 > ( 1 << 15 ) ); /* reduce A_LIMIT if fails */ + SKP_assert( rc_mult1_Q30 < ( 1 << 30 ) ); + + /* rc_mult2_Q16 range: [ 2^16 : SKP_int32_MAX ] */ + rc_mult2_Q16 = silk_INVERSE32_varQ( rc_mult1_Q30, 46 ); /* 16 = 46 - 30 */ + + /* Update inverse gain */ + /* invGain_Q30 range: [ 0 : 2^30 ] */ + *invGain_Q30 = SKP_LSHIFT( SKP_SMMUL( *invGain_Q30, rc_mult1_Q30 ), 2 ); + SKP_assert( *invGain_Q30 >= 0 ); + SKP_assert( *invGain_Q30 <= ( 1 << 30 ) ); + + /* Swap pointers */ + Aold_QA = Anew_QA; + Anew_QA = A_QA[ k & 1 ]; + + /* Update AR coefficient */ + headrm = silk_CLZ32( rc_mult2_Q16 ) - 1; + rc_mult2_Q16 = SKP_LSHIFT( rc_mult2_Q16, headrm ); /* Q: 16 + headrm */ + for( n = 0; n < k; n++ ) { + tmp_QA = Aold_QA[ n ] - SKP_LSHIFT( SKP_SMMUL( Aold_QA[ k - n - 1 ], rc_Q31 ), 1 ); + Anew_QA[ n ] = SKP_LSHIFT( SKP_SMMUL( tmp_QA, rc_mult2_Q16 ), 16 - headrm ); + } + } + + /* Check for stability */ + if( ( Anew_QA[ 0 ] > A_LIMIT ) || ( Anew_QA[ 0 ] < -A_LIMIT ) ) { + return 1; + } + + /* Set RC equal to negated AR coef */ + rc_Q31 = -SKP_LSHIFT( Anew_QA[ 0 ], 31 - QA ); + + /* Range: [ 1 : 2^30 ] */ + rc_mult1_Q30 = ( SKP_int32_MAX >> 1 ) - SKP_SMMUL( rc_Q31, rc_Q31 ); + + /* Update inverse gain */ + /* Range: [ 0 : 2^30 ] */ + *invGain_Q30 = SKP_LSHIFT( SKP_SMMUL( *invGain_Q30, rc_mult1_Q30 ), 2 ); + SKP_assert( *invGain_Q30 >= 0 ); + SKP_assert( *invGain_Q30 <= 1<<30 ); + + return 0; +} + +/* For input in Q12 domain */ +opus_int silk_LPC_inverse_pred_gain( /* O: Returns 1 if unstable, otherwise 0 */ + opus_int32 *invGain_Q30, /* O: Inverse prediction gain, Q30 energy domain */ + const opus_int16 *A_Q12, /* I: Prediction coefficients, Q12 [order] */ + const opus_int order /* I: Prediction order */ +) +{ + opus_int k; + opus_int32 Atmp_QA[ 2 ][ SILK_MAX_ORDER_LPC ]; + opus_int32 *Anew_QA; + + Anew_QA = Atmp_QA[ order & 1 ]; + + /* Increase Q domain of the AR coefficients */ + for( k = 0; k < order; k++ ) { + Anew_QA[ k ] = SKP_LSHIFT( (opus_int32)A_Q12[ k ], QA - 12 ); + } + + return LPC_inverse_pred_gain_QA( invGain_Q30, Atmp_QA, order ); +} + +/* For input in Q24 domain */ +opus_int silk_LPC_inverse_pred_gain_Q24( /* O: Returns 1 if unstable, otherwise 0 */ + opus_int32 *invGain_Q30, /* O: Inverse prediction gain, Q30 energy domain */ + const opus_int32 *A_Q24, /* I: Prediction coefficients, Q24 [order] */ + const opus_int order /* I: Prediction order */ +) +{ + opus_int k; + opus_int32 Atmp_QA[ 2 ][ SILK_MAX_ORDER_LPC ]; + opus_int32 *Anew_QA; + + Anew_QA = Atmp_QA[ order & 1 ]; + + /* Increase Q domain of the AR coefficients */ + for( k = 0; k < order; k++ ) { + Anew_QA[ k ] = SKP_RSHIFT_ROUND( A_Q24[ k ], 24 - QA ); + } + + return LPC_inverse_pred_gain_QA( invGain_Q30, Atmp_QA, order ); +} + diff --git a/silk/silk_LP_variable_cutoff.c b/silk/silk_LP_variable_cutoff.c index 4fc243da6..1ee916d62 100644 --- a/silk/silk_LP_variable_cutoff.c +++ b/silk/silk_LP_variable_cutoff.c @@ -1,132 +1,132 @@ -/*********************************************************************** -Copyright (c) 2006-2011, Skype Limited. All rights reserved. -Redistribution and use in source and binary forms, with or without -modification, (subject to the limitations in the disclaimer below) -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 Skype Limited, nor the names of specific -contributors, may be used to endorse or promote products derived from -this software without specific prior written permission. -NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED -BY THIS LICENSE. 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. -***********************************************************************/ - -/* - - Elliptic/Cauer filters designed with 0.1 dB passband ripple, - 80 dB minimum stopband attenuation, and - [0.95 : 0.15 : 0.35] normalized cut off frequencies. - -*/ -#include "silk_main.h" - -/* Helper function, interpolates the filter taps */ -SKP_INLINE void silk_LP_interpolate_filter_taps( - opus_int32 B_Q28[ TRANSITION_NB ], - opus_int32 A_Q28[ TRANSITION_NA ], - const opus_int ind, - const opus_int32 fac_Q16 -) -{ - opus_int nb, na; - - if( ind < TRANSITION_INT_NUM - 1 ) { - if( fac_Q16 > 0 ) { - if( fac_Q16 < 32768 ) { /* fac_Q16 is in range of a 16-bit int */ - /* Piece-wise linear interpolation of B and A */ - for( nb = 0; nb < TRANSITION_NB; nb++ ) { - B_Q28[ nb ] = SKP_SMLAWB( - silk_Transition_LP_B_Q28[ ind ][ nb ], - silk_Transition_LP_B_Q28[ ind + 1 ][ nb ] - - silk_Transition_LP_B_Q28[ ind ][ nb ], - fac_Q16 ); - } - for( na = 0; na < TRANSITION_NA; na++ ) { - A_Q28[ na ] = SKP_SMLAWB( - silk_Transition_LP_A_Q28[ ind ][ na ], - silk_Transition_LP_A_Q28[ ind + 1 ][ na ] - - silk_Transition_LP_A_Q28[ ind ][ na ], - fac_Q16 ); - } - } else { /* ( fac_Q16 - ( 1 << 16 ) ) is in range of a 16-bit int */ - SKP_assert( fac_Q16 - ( 1 << 16 ) == SKP_SAT16( fac_Q16 - ( 1 << 16 ) ) ); - /* Piece-wise linear interpolation of B and A */ - for( nb = 0; nb < TRANSITION_NB; nb++ ) { - B_Q28[ nb ] = SKP_SMLAWB( - silk_Transition_LP_B_Q28[ ind + 1 ][ nb ], - silk_Transition_LP_B_Q28[ ind + 1 ][ nb ] - - silk_Transition_LP_B_Q28[ ind ][ nb ], - fac_Q16 - ( 1 << 16 ) ); - } - for( na = 0; na < TRANSITION_NA; na++ ) { - A_Q28[ na ] = SKP_SMLAWB( - silk_Transition_LP_A_Q28[ ind + 1 ][ na ], - silk_Transition_LP_A_Q28[ ind + 1 ][ na ] - - silk_Transition_LP_A_Q28[ ind ][ na ], - fac_Q16 - ( 1 << 16 ) ); - } - } - } else { - SKP_memcpy( B_Q28, silk_Transition_LP_B_Q28[ ind ], TRANSITION_NB * sizeof( opus_int32 ) ); - SKP_memcpy( A_Q28, silk_Transition_LP_A_Q28[ ind ], TRANSITION_NA * sizeof( opus_int32 ) ); - } - } else { - SKP_memcpy( B_Q28, silk_Transition_LP_B_Q28[ TRANSITION_INT_NUM - 1 ], TRANSITION_NB * sizeof( opus_int32 ) ); - SKP_memcpy( A_Q28, silk_Transition_LP_A_Q28[ TRANSITION_INT_NUM - 1 ], TRANSITION_NA * sizeof( opus_int32 ) ); - } -} - -/* Low-pass filter with variable cutoff frequency based on */ -/* piece-wise linear interpolation between elliptic filters */ -/* Start by setting psEncC->mode <> 0; */ -/* Deactivate by setting psEncC->mode = 0; */ -void silk_LP_variable_cutoff( - silk_LP_state *psLP, /* I/O LP filter state */ - opus_int16 *signal, /* I/O Low-pass filtered output signal */ - const opus_int frame_length /* I Frame length */ -) -{ - opus_int32 B_Q28[ TRANSITION_NB ], A_Q28[ TRANSITION_NA ], fac_Q16 = 0; - opus_int ind = 0; - - SKP_assert( psLP->transition_frame_no >= 0 && psLP->transition_frame_no <= TRANSITION_FRAMES ); - - /* Run filter if needed */ - if( psLP->mode != 0 ) { - /* Calculate index and interpolation factor for interpolation */ -#if( TRANSITION_INT_STEPS == 64 ) - fac_Q16 = SKP_LSHIFT( TRANSITION_FRAMES - psLP->transition_frame_no, 16 - 6 ); -#else - fac_Q16 = SKP_DIV32_16( SKP_LSHIFT( TRANSITION_FRAMES - psLP->transition_frame_no, 16 ), TRANSITION_FRAMES ); -#endif - ind = SKP_RSHIFT( fac_Q16, 16 ); - fac_Q16 -= SKP_LSHIFT( ind, 16 ); - - SKP_assert( ind >= 0 ); - SKP_assert( ind < TRANSITION_INT_NUM ); - - /* Interpolate filter coefficients */ - silk_LP_interpolate_filter_taps( B_Q28, A_Q28, ind, fac_Q16 ); - - /* Update transition frame number for next frame */ - psLP->transition_frame_no = SKP_LIMIT( psLP->transition_frame_no + psLP->mode, 0, TRANSITION_FRAMES ); - - /* ARMA low-pass filtering */ - SKP_assert( TRANSITION_NB == 3 && TRANSITION_NA == 2 ); - silk_biquad_alt( signal, B_Q28, A_Q28, psLP->In_LP_State, signal, frame_length ); - } -} +/*********************************************************************** +Copyright (c) 2006-2011, Skype Limited. All rights reserved. +Redistribution and use in source and binary forms, with or without +modification, (subject to the limitations in the disclaimer below) +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 Skype Limited, nor the names of specific +contributors, may be used to endorse or promote products derived from +this software without specific prior written permission. +NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED +BY THIS LICENSE. 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. +***********************************************************************/ + +/* + + Elliptic/Cauer filters designed with 0.1 dB passband ripple, + 80 dB minimum stopband attenuation, and + [0.95 : 0.15 : 0.35] normalized cut off frequencies. + +*/ +#include "silk_main.h" + +/* Helper function, interpolates the filter taps */ +SKP_INLINE void silk_LP_interpolate_filter_taps( + opus_int32 B_Q28[ TRANSITION_NB ], + opus_int32 A_Q28[ TRANSITION_NA ], + const opus_int ind, + const opus_int32 fac_Q16 +) +{ + opus_int nb, na; + + if( ind < TRANSITION_INT_NUM - 1 ) { + if( fac_Q16 > 0 ) { + if( fac_Q16 < 32768 ) { /* fac_Q16 is in range of a 16-bit int */ + /* Piece-wise linear interpolation of B and A */ + for( nb = 0; nb < TRANSITION_NB; nb++ ) { + B_Q28[ nb ] = SKP_SMLAWB( + silk_Transition_LP_B_Q28[ ind ][ nb ], + silk_Transition_LP_B_Q28[ ind + 1 ][ nb ] - + silk_Transition_LP_B_Q28[ ind ][ nb ], + fac_Q16 ); + } + for( na = 0; na < TRANSITION_NA; na++ ) { + A_Q28[ na ] = SKP_SMLAWB( + silk_Transition_LP_A_Q28[ ind ][ na ], + silk_Transition_LP_A_Q28[ ind + 1 ][ na ] - + silk_Transition_LP_A_Q28[ ind ][ na ], + fac_Q16 ); + } + } else { /* ( fac_Q16 - ( 1 << 16 ) ) is in range of a 16-bit int */ + SKP_assert( fac_Q16 - ( 1 << 16 ) == SKP_SAT16( fac_Q16 - ( 1 << 16 ) ) ); + /* Piece-wise linear interpolation of B and A */ + for( nb = 0; nb < TRANSITION_NB; nb++ ) { + B_Q28[ nb ] = SKP_SMLAWB( + silk_Transition_LP_B_Q28[ ind + 1 ][ nb ], + silk_Transition_LP_B_Q28[ ind + 1 ][ nb ] - + silk_Transition_LP_B_Q28[ ind ][ nb ], + fac_Q16 - ( 1 << 16 ) ); + } + for( na = 0; na < TRANSITION_NA; na++ ) { + A_Q28[ na ] = SKP_SMLAWB( + silk_Transition_LP_A_Q28[ ind + 1 ][ na ], + silk_Transition_LP_A_Q28[ ind + 1 ][ na ] - + silk_Transition_LP_A_Q28[ ind ][ na ], + fac_Q16 - ( 1 << 16 ) ); + } + } + } else { + SKP_memcpy( B_Q28, silk_Transition_LP_B_Q28[ ind ], TRANSITION_NB * sizeof( opus_int32 ) ); + SKP_memcpy( A_Q28, silk_Transition_LP_A_Q28[ ind ], TRANSITION_NA * sizeof( opus_int32 ) ); + } + } else { + SKP_memcpy( B_Q28, silk_Transition_LP_B_Q28[ TRANSITION_INT_NUM - 1 ], TRANSITION_NB * sizeof( opus_int32 ) ); + SKP_memcpy( A_Q28, silk_Transition_LP_A_Q28[ TRANSITION_INT_NUM - 1 ], TRANSITION_NA * sizeof( opus_int32 ) ); + } +} + +/* Low-pass filter with variable cutoff frequency based on */ +/* piece-wise linear interpolation between elliptic filters */ +/* Start by setting psEncC->mode <> 0; */ +/* Deactivate by setting psEncC->mode = 0; */ +void silk_LP_variable_cutoff( + silk_LP_state *psLP, /* I/O LP filter state */ + opus_int16 *signal, /* I/O Low-pass filtered output signal */ + const opus_int frame_length /* I Frame length */ +) +{ + opus_int32 B_Q28[ TRANSITION_NB ], A_Q28[ TRANSITION_NA ], fac_Q16 = 0; + opus_int ind = 0; + + SKP_assert( psLP->transition_frame_no >= 0 && psLP->transition_frame_no <= TRANSITION_FRAMES ); + + /* Run filter if needed */ + if( psLP->mode != 0 ) { + /* Calculate index and interpolation factor for interpolation */ +#if( TRANSITION_INT_STEPS == 64 ) + fac_Q16 = SKP_LSHIFT( TRANSITION_FRAMES - psLP->transition_frame_no, 16 - 6 ); +#else + fac_Q16 = SKP_DIV32_16( SKP_LSHIFT( TRANSITION_FRAMES - psLP->transition_frame_no, 16 ), TRANSITION_FRAMES ); +#endif + ind = SKP_RSHIFT( fac_Q16, 16 ); + fac_Q16 -= SKP_LSHIFT( ind, 16 ); + + SKP_assert( ind >= 0 ); + SKP_assert( ind < TRANSITION_INT_NUM ); + + /* Interpolate filter coefficients */ + silk_LP_interpolate_filter_taps( B_Q28, A_Q28, ind, fac_Q16 ); + + /* Update transition frame number for next frame */ + psLP->transition_frame_no = SKP_LIMIT( psLP->transition_frame_no + psLP->mode, 0, TRANSITION_FRAMES ); + + /* ARMA low-pass filtering */ + SKP_assert( TRANSITION_NB == 3 && TRANSITION_NA == 2 ); + silk_biquad_alt( signal, B_Q28, A_Q28, psLP->In_LP_State, signal, frame_length ); + } +} diff --git a/silk/silk_MacroCount.h b/silk/silk_MacroCount.h index 247e670e8..6865b3e81 100644 --- a/silk/silk_MacroCount.h +++ b/silk/silk_MacroCount.h @@ -1,719 +1,719 @@ -/*********************************************************************** -Copyright (c) 2006-2011, Skype Limited. All rights reserved. -Redistribution and use in source and binary forms, with or without -modification, (subject to the limitations in the disclaimer below) -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 Skype Limited, nor the names of specific -contributors, may be used to endorse or promote products derived from -this software without specific prior written permission. -NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED -BY THIS LICENSE. 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. -***********************************************************************/ - -#ifndef _SIGPROCFIX_API_MACROCOUNT_H_ -#define _SIGPROCFIX_API_MACROCOUNT_H_ -#include <stdio.h> - -#ifdef SKP_MACRO_COUNT -#define varDefine opus_int64 ops_count = 0; - -extern opus_int64 ops_count; - -SKP_INLINE opus_int64 SKP_SaveCount(){ - return(ops_count); -} - -SKP_INLINE opus_int64 SKP_SaveResetCount(){ - opus_int64 ret; - - ret = ops_count; - ops_count = 0; - return(ret); -} - -SKP_INLINE SKP_PrintCount(){ - printf("ops_count = %d \n ", (opus_int32)ops_count); -} - -#undef SKP_MUL -SKP_INLINE opus_int32 SKP_MUL(opus_int32 a32, opus_int32 b32){ - opus_int32 ret; - ops_count += 4; - ret = a32 * b32; - return ret; -} - -#undef SKP_MUL_uint -SKP_INLINE opus_uint32 SKP_MUL_uint(opus_uint32 a32, opus_uint32 b32){ - opus_uint32 ret; - ops_count += 4; - ret = a32 * b32; - return ret; -} -#undef SKP_MLA -SKP_INLINE opus_int32 SKP_MLA(opus_int32 a32, opus_int32 b32, opus_int32 c32){ - opus_int32 ret; - ops_count += 4; - ret = a32 + b32 * c32; - return ret; -} - -#undef SKP_MLA_uint -SKP_INLINE opus_int32 SKP_MLA_uint(opus_uint32 a32, opus_uint32 b32, opus_uint32 c32){ - opus_uint32 ret; - ops_count += 4; - ret = a32 + b32 * c32; - return ret; -} - -#undef SKP_SMULWB -SKP_INLINE opus_int32 SKP_SMULWB(opus_int32 a32, opus_int32 b32){ - opus_int32 ret; - ops_count += 5; - ret = (a32 >> 16) * (opus_int32)((opus_int16)b32) + (((a32 & 0x0000FFFF) * (opus_int32)((opus_int16)b32)) >> 16); - return ret; -} -#undef SKP_SMLAWB -SKP_INLINE opus_int32 SKP_SMLAWB(opus_int32 a32, opus_int32 b32, opus_int32 c32){ - opus_int32 ret; - ops_count += 5; - ret = ((a32) + ((((b32) >> 16) * (opus_int32)((opus_int16)(c32))) + ((((b32) & 0x0000FFFF) * (opus_int32)((opus_int16)(c32))) >> 16))); - return ret; -} - -#undef SKP_SMULWT -SKP_INLINE opus_int32 SKP_SMULWT(opus_int32 a32, opus_int32 b32){ - opus_int32 ret; - ops_count += 4; - ret = (a32 >> 16) * (b32 >> 16) + (((a32 & 0x0000FFFF) * (b32 >> 16)) >> 16); - return ret; -} -#undef SKP_SMLAWT -SKP_INLINE opus_int32 SKP_SMLAWT(opus_int32 a32, opus_int32 b32, opus_int32 c32){ - opus_int32 ret; - ops_count += 4; - ret = a32 + ((b32 >> 16) * (c32 >> 16)) + (((b32 & 0x0000FFFF) * ((c32 >> 16)) >> 16)); - return ret; -} - -#undef SKP_SMULBB -SKP_INLINE opus_int32 SKP_SMULBB(opus_int32 a32, opus_int32 b32){ - opus_int32 ret; - ops_count += 1; - ret = (opus_int32)((opus_int16)a32) * (opus_int32)((opus_int16)b32); - return ret; -} -#undef SKP_SMLABB -SKP_INLINE opus_int32 SKP_SMLABB(opus_int32 a32, opus_int32 b32, opus_int32 c32){ - opus_int32 ret; - ops_count += 1; - ret = a32 + (opus_int32)((opus_int16)b32) * (opus_int32)((opus_int16)c32); - return ret; -} - -#undef SKP_SMULBT -SKP_INLINE opus_int32 SKP_SMULBT(opus_int32 a32, opus_int32 b32 ){ - opus_int32 ret; - ops_count += 4; - ret = ((opus_int32)((opus_int16)a32)) * (b32 >> 16); - return ret; -} - -#undef SKP_SMLABT -SKP_INLINE opus_int32 SKP_SMLABT(opus_int32 a32, opus_int32 b32, opus_int32 c32){ - opus_int32 ret; - ops_count += 1; - ret = a32 + ((opus_int32)((opus_int16)b32)) * (c32 >> 16); - return ret; -} - -#undef SKP_SMULTT -SKP_INLINE opus_int32 SKP_SMULTT(opus_int32 a32, opus_int32 b32){ - opus_int32 ret; - ops_count += 1; - ret = (a32 >> 16) * (b32 >> 16); - return ret; -} - -#undef SKP_SMLATT -SKP_INLINE opus_int32 SKP_SMLATT(opus_int32 a32, opus_int32 b32, opus_int32 c32){ - opus_int32 ret; - ops_count += 1; - ret = a32 + (b32 >> 16) * (c32 >> 16); - return ret; -} - - -// multiply-accumulate macros that allow overflow in the addition (ie, no asserts in debug mode) -#undef SKP_MLA_ovflw -#define SKP_MLA_ovflw SKP_MLA - -#undef SKP_SMLABB_ovflw -#define SKP_SMLABB_ovflw SKP_SMLABB - -#undef SKP_SMLABT_ovflw -#define SKP_SMLABT_ovflw SKP_SMLABT - -#undef SKP_SMLATT_ovflw -#define SKP_SMLATT_ovflw SKP_SMLATT - -#undef SKP_SMLAWB_ovflw -#define SKP_SMLAWB_ovflw SKP_SMLAWB - -#undef SKP_SMLAWT_ovflw -#define SKP_SMLAWT_ovflw SKP_SMLAWT - -#undef SKP_SMULL -SKP_INLINE opus_int64 SKP_SMULL(opus_int32 a32, opus_int32 b32){ - opus_int64 ret; - ops_count += 8; - ret = ((opus_int64)(a32) * /*(opus_int64)*/(b32)); - return ret; -} - -#undef SKP_SMLAL -SKP_INLINE opus_int64 SKP_SMLAL(opus_int64 a64, opus_int32 b32, opus_int32 c32){ - opus_int64 ret; - ops_count += 8; - ret = a64 + ((opus_int64)(b32) * /*(opus_int64)*/(c32)); - return ret; -} -#undef SKP_SMLALBB -SKP_INLINE opus_int64 SKP_SMLALBB(opus_int64 a64, opus_int16 b16, opus_int16 c16){ - opus_int64 ret; - ops_count += 4; - ret = a64 + ((opus_int64)(b16) * /*(opus_int64)*/(c16)); - return ret; -} - -#undef SigProcFIX_CLZ16 -SKP_INLINE opus_int32 SigProcFIX_CLZ16(opus_int16 in16) -{ - opus_int32 out32 = 0; - ops_count += 10; - if( in16 == 0 ) { - return 16; - } - /* test nibbles */ - if( in16 & 0xFF00 ) { - if( in16 & 0xF000 ) { - in16 >>= 12; - } else { - out32 += 4; - in16 >>= 8; - } - } else { - if( in16 & 0xFFF0 ) { - out32 += 8; - in16 >>= 4; - } else { - out32 += 12; - } - } - /* test bits and return */ - if( in16 & 0xC ) { - if( in16 & 0x8 ) - return out32 + 0; - else - return out32 + 1; - } else { - if( in16 & 0xE ) - return out32 + 2; - else - return out32 + 3; - } -} - -#undef SigProcFIX_CLZ32 -SKP_INLINE opus_int32 SigProcFIX_CLZ32(opus_int32 in32) -{ - /* test highest 16 bits and convert to opus_int16 */ - ops_count += 2; - if( in32 & 0xFFFF0000 ) { - return SigProcFIX_CLZ16((opus_int16)(in32 >> 16)); - } else { - return SigProcFIX_CLZ16((opus_int16)in32) + 16; - } -} - -#undef SKP_DIV32 -SKP_INLINE opus_int32 SKP_DIV32(opus_int32 a32, opus_int32 b32){ - ops_count += 64; - return a32 / b32; -} - -#undef SKP_DIV32_16 -SKP_INLINE opus_int32 SKP_DIV32_16(opus_int32 a32, opus_int32 b32){ - ops_count += 32; - return a32 / b32; -} - -#undef SKP_SAT8 -SKP_INLINE opus_int8 SKP_SAT8(opus_int64 a){ - opus_int8 tmp; - ops_count += 1; - tmp = (opus_int8)((a) > SKP_int8_MAX ? SKP_int8_MAX : \ - ((a) < SKP_int8_MIN ? SKP_int8_MIN : (a))); - return(tmp); -} - -#undef SKP_SAT16 -SKP_INLINE opus_int16 SKP_SAT16(opus_int64 a){ - opus_int16 tmp; - ops_count += 1; - tmp = (opus_int16)((a) > SKP_int16_MAX ? SKP_int16_MAX : \ - ((a) < SKP_int16_MIN ? SKP_int16_MIN : (a))); - return(tmp); -} -#undef SKP_SAT32 -SKP_INLINE opus_int32 SKP_SAT32(opus_int64 a){ - opus_int32 tmp; - ops_count += 1; - tmp = (opus_int32)((a) > SKP_int32_MAX ? SKP_int32_MAX : \ - ((a) < SKP_int32_MIN ? SKP_int32_MIN : (a))); - return(tmp); -} -#undef SKP_POS_SAT32 -SKP_INLINE opus_int32 SKP_POS_SAT32(opus_int64 a){ - opus_int32 tmp; - ops_count += 1; - tmp = (opus_int32)((a) > SKP_int32_MAX ? SKP_int32_MAX : (a)); - return(tmp); -} - -#undef SKP_ADD_POS_SAT8 -SKP_INLINE opus_int8 SKP_ADD_POS_SAT8(opus_int64 a, opus_int64 b){ - opus_int8 tmp; - ops_count += 1; - tmp = (opus_int8)((((a)+(b)) & 0x80) ? SKP_int8_MAX : ((a)+(b))); - return(tmp); -} -#undef SKP_ADD_POS_SAT16 -SKP_INLINE opus_int16 SKP_ADD_POS_SAT16(opus_int64 a, opus_int64 b){ - opus_int16 tmp; - ops_count += 1; - tmp = (opus_int16)((((a)+(b)) & 0x8000) ? SKP_int16_MAX : ((a)+(b))); - return(tmp); -} - -#undef SKP_ADD_POS_SAT32 -SKP_INLINE opus_int32 SKP_ADD_POS_SAT32(opus_int64 a, opus_int64 b){ - opus_int32 tmp; - ops_count += 1; - tmp = (opus_int32)((((a)+(b)) & 0x80000000) ? SKP_int32_MAX : ((a)+(b))); - return(tmp); -} - -#undef SKP_ADD_POS_SAT64 -SKP_INLINE opus_int64 SKP_ADD_POS_SAT64(opus_int64 a, opus_int64 b){ - opus_int64 tmp; - ops_count += 1; - tmp = ((((a)+(b)) & 0x8000000000000000LL) ? SKP_int64_MAX : ((a)+(b))); - return(tmp); -} - -#undef SKP_LSHIFT8 -SKP_INLINE opus_int8 SKP_LSHIFT8(opus_int8 a, opus_int32 shift){ - opus_int8 ret; - ops_count += 1; - ret = a << shift; - return ret; -} -#undef SKP_LSHIFT16 -SKP_INLINE opus_int16 SKP_LSHIFT16(opus_int16 a, opus_int32 shift){ - opus_int16 ret; - ops_count += 1; - ret = a << shift; - return ret; -} -#undef SKP_LSHIFT32 -SKP_INLINE opus_int32 SKP_LSHIFT32(opus_int32 a, opus_int32 shift){ - opus_int32 ret; - ops_count += 1; - ret = a << shift; - return ret; -} -#undef SKP_LSHIFT64 -SKP_INLINE opus_int64 SKP_LSHIFT64(opus_int64 a, opus_int shift){ - ops_count += 1; - return a << shift; -} - -#undef SKP_LSHIFT_ovflw -SKP_INLINE opus_int32 SKP_LSHIFT_ovflw(opus_int32 a, opus_int32 shift){ - ops_count += 1; - return a << shift; -} - -#undef SKP_LSHIFT_uint -SKP_INLINE opus_uint32 SKP_LSHIFT_uint(opus_uint32 a, opus_int32 shift){ - opus_uint32 ret; - ops_count += 1; - ret = a << shift; - return ret; -} - -#undef SKP_RSHIFT8 -SKP_INLINE opus_int8 SKP_RSHIFT8(opus_int8 a, opus_int32 shift){ - ops_count += 1; - return a >> shift; -} -#undef SKP_RSHIFT16 -SKP_INLINE opus_int16 SKP_RSHIFT16(opus_int16 a, opus_int32 shift){ - ops_count += 1; - return a >> shift; -} -#undef SKP_RSHIFT32 -SKP_INLINE opus_int32 SKP_RSHIFT32(opus_int32 a, opus_int32 shift){ - ops_count += 1; - return a >> shift; -} -#undef SKP_RSHIFT64 -SKP_INLINE opus_int64 SKP_RSHIFT64(opus_int64 a, opus_int64 shift){ - ops_count += 1; - return a >> shift; -} - -#undef SKP_RSHIFT_uint -SKP_INLINE opus_uint32 SKP_RSHIFT_uint(opus_uint32 a, opus_int32 shift){ - ops_count += 1; - return a >> shift; -} - -#undef SKP_ADD_LSHIFT -SKP_INLINE opus_int32 SKP_ADD_LSHIFT(opus_int32 a, opus_int32 b, opus_int32 shift){ - opus_int32 ret; - ops_count += 1; - ret = a + (b << shift); - return ret; // shift >= 0 -} -#undef SKP_ADD_LSHIFT32 -SKP_INLINE opus_int32 SKP_ADD_LSHIFT32(opus_int32 a, opus_int32 b, opus_int32 shift){ - opus_int32 ret; - ops_count += 1; - ret = a + (b << shift); - return ret; // shift >= 0 -} -#undef SKP_ADD_LSHIFT_uint -SKP_INLINE opus_uint32 SKP_ADD_LSHIFT_uint(opus_uint32 a, opus_uint32 b, opus_int32 shift){ - opus_uint32 ret; - ops_count += 1; - ret = a + (b << shift); - return ret; // shift >= 0 -} -#undef SKP_ADD_RSHIFT -SKP_INLINE opus_int32 SKP_ADD_RSHIFT(opus_int32 a, opus_int32 b, opus_int32 shift){ - opus_int32 ret; - ops_count += 1; - ret = a + (b >> shift); - return ret; // shift > 0 -} -#undef SKP_ADD_RSHIFT32 -SKP_INLINE opus_int32 SKP_ADD_RSHIFT32(opus_int32 a, opus_int32 b, opus_int32 shift){ - opus_int32 ret; - ops_count += 1; - ret = a + (b >> shift); - return ret; // shift > 0 -} -#undef SKP_ADD_RSHIFT_uint -SKP_INLINE opus_uint32 SKP_ADD_RSHIFT_uint(opus_uint32 a, opus_uint32 b, opus_int32 shift){ - opus_uint32 ret; - ops_count += 1; - ret = a + (b >> shift); - return ret; // shift > 0 -} -#undef SKP_SUB_LSHIFT32 -SKP_INLINE opus_int32 SKP_SUB_LSHIFT32(opus_int32 a, opus_int32 b, opus_int32 shift){ - opus_int32 ret; - ops_count += 1; - ret = a - (b << shift); - return ret; // shift >= 0 -} -#undef SKP_SUB_RSHIFT32 -SKP_INLINE opus_int32 SKP_SUB_RSHIFT32(opus_int32 a, opus_int32 b, opus_int32 shift){ - opus_int32 ret; - ops_count += 1; - ret = a - (b >> shift); - return ret; // shift > 0 -} - -#undef SKP_RSHIFT_ROUND -SKP_INLINE opus_int32 SKP_RSHIFT_ROUND(opus_int32 a, opus_int32 shift){ - opus_int32 ret; - ops_count += 3; - ret = shift == 1 ? (a >> 1) + (a & 1) : ((a >> (shift - 1)) + 1) >> 1; - return ret; -} - -#undef SKP_RSHIFT_ROUND64 -SKP_INLINE opus_int64 SKP_RSHIFT_ROUND64(opus_int64 a, opus_int32 shift){ - opus_int64 ret; - ops_count += 6; - ret = shift == 1 ? (a >> 1) + (a & 1) : ((a >> (shift - 1)) + 1) >> 1; - return ret; -} - -#undef SKP_abs_int64 -SKP_INLINE opus_int64 SKP_abs_int64(opus_int64 a){ - ops_count += 1; - return (((a) > 0) ? (a) : -(a)); // Be careful, SKP_abs returns wrong when input equals to SKP_intXX_MIN -} - -#undef SKP_abs_int32 -SKP_INLINE opus_int32 SKP_abs_int32(opus_int32 a){ - ops_count += 1; - return abs(a); -} - - -#undef SKP_min -static SKP_min(a, b){ - ops_count += 1; - return (((a) < (b)) ? (a) : (b)); -} -#undef SKP_max -static SKP_max(a, b){ - ops_count += 1; - return (((a) > (b)) ? (a) : (b)); -} -#undef SKP_sign -static SKP_sign(a){ - ops_count += 1; - return ((a) > 0 ? 1 : ( (a) < 0 ? -1 : 0 )); -} - -#undef SKP_ADD16 -SKP_INLINE opus_int16 SKP_ADD16(opus_int16 a, opus_int16 b){ - opus_int16 ret; - ops_count += 1; - ret = a + b; - return ret; -} - -#undef SKP_ADD32 -SKP_INLINE opus_int32 SKP_ADD32(opus_int32 a, opus_int32 b){ - opus_int32 ret; - ops_count += 1; - ret = a + b; - return ret; -} - -#undef SKP_ADD64 -SKP_INLINE opus_int64 SKP_ADD64(opus_int64 a, opus_int64 b){ - opus_int64 ret; - ops_count += 2; - ret = a + b; - return ret; -} - -#undef SKP_SUB16 -SKP_INLINE opus_int16 SKP_SUB16(opus_int16 a, opus_int16 b){ - opus_int16 ret; - ops_count += 1; - ret = a - b; - return ret; -} - -#undef SKP_SUB32 -SKP_INLINE opus_int32 SKP_SUB32(opus_int32 a, opus_int32 b){ - opus_int32 ret; - ops_count += 1; - ret = a - b; - return ret; -} - -#undef SKP_SUB64 -SKP_INLINE opus_int64 SKP_SUB64(opus_int64 a, opus_int64 b){ - opus_int64 ret; - ops_count += 2; - ret = a - b; - return ret; -} - -#undef SKP_ADD_SAT16 -SKP_INLINE opus_int16 SKP_ADD_SAT16( opus_int16 a16, opus_int16 b16 ) { - opus_int16 res; - // Nb will be counted in AKP_add32 and SKP_SAT16 - res = (opus_int16)SKP_SAT16( SKP_ADD32( (opus_int32)(a16), (b16) ) ); - return res; -} - -#undef SKP_ADD_SAT32 -SKP_INLINE opus_int32 SKP_ADD_SAT32(opus_int32 a32, opus_int32 b32){ - opus_int32 res; - ops_count += 1; - res = ((((a32) + (b32)) & 0x80000000) == 0 ? \ - ((((a32) & (b32)) & 0x80000000) != 0 ? SKP_int32_MIN : (a32)+(b32)) : \ - ((((a32) | (b32)) & 0x80000000) == 0 ? SKP_int32_MAX : (a32)+(b32)) ); - return res; -} - -#undef SKP_ADD_SAT64 -SKP_INLINE opus_int64 SKP_ADD_SAT64( opus_int64 a64, opus_int64 b64 ) { - opus_int64 res; - ops_count += 1; - res = ((((a64) + (b64)) & 0x8000000000000000LL) == 0 ? \ - ((((a64) & (b64)) & 0x8000000000000000LL) != 0 ? SKP_int64_MIN : (a64)+(b64)) : \ - ((((a64) | (b64)) & 0x8000000000000000LL) == 0 ? SKP_int64_MAX : (a64)+(b64)) ); - return res; -} - -#undef SKP_SUB_SAT16 -SKP_INLINE opus_int16 SKP_SUB_SAT16( opus_int16 a16, opus_int16 b16 ) { - opus_int16 res; - SKP_assert(0); - // Nb will be counted in sub-macros - res = (opus_int16)SKP_SAT16( SKP_SUB32( (opus_int32)(a16), (b16) ) ); - return res; -} - -#undef SKP_SUB_SAT32 -SKP_INLINE opus_int32 SKP_SUB_SAT32( opus_int32 a32, opus_int32 b32 ) { - opus_int32 res; - ops_count += 1; - res = ((((a32)-(b32)) & 0x80000000) == 0 ? \ - (( (a32) & ((b32)^0x80000000) & 0x80000000) ? SKP_int32_MIN : (a32)-(b32)) : \ - ((((a32)^0x80000000) & (b32) & 0x80000000) ? SKP_int32_MAX : (a32)-(b32)) ); - return res; -} - -#undef SKP_SUB_SAT64 -SKP_INLINE opus_int64 SKP_SUB_SAT64( opus_int64 a64, opus_int64 b64 ) { - opus_int64 res; - ops_count += 1; - res = ((((a64)-(b64)) & 0x8000000000000000LL) == 0 ? \ - (( (a64) & ((b64)^0x8000000000000000LL) & 0x8000000000000000LL) ? SKP_int64_MIN : (a64)-(b64)) : \ - ((((a64)^0x8000000000000000LL) & (b64) & 0x8000000000000000LL) ? SKP_int64_MAX : (a64)-(b64)) ); - - return res; -} - -#undef SKP_SMULWW -SKP_INLINE opus_int32 SKP_SMULWW(opus_int32 a32, opus_int32 b32){ - opus_int32 ret; - // Nb will be counted in sub-macros - ret = SKP_MLA(SKP_SMULWB((a32), (b32)), (a32), SKP_RSHIFT_ROUND((b32), 16)); - return ret; -} - -#undef SKP_SMLAWW -SKP_INLINE opus_int32 SKP_SMLAWW(opus_int32 a32, opus_int32 b32, opus_int32 c32){ - opus_int32 ret; - // Nb will be counted in sub-macros - ret = SKP_MLA(SKP_SMLAWB((a32), (b32), (c32)), (b32), SKP_RSHIFT_ROUND((c32), 16)); - return ret; -} - -#undef SKP_min_int -SKP_INLINE opus_int SKP_min_int(opus_int a, opus_int b) -{ - ops_count += 1; - return (((a) < (b)) ? (a) : (b)); -} - -#undef SKP_min_16 -SKP_INLINE opus_int16 SKP_min_16(opus_int16 a, opus_int16 b) -{ - ops_count += 1; - return (((a) < (b)) ? (a) : (b)); -} -#undef SKP_min_32 -SKP_INLINE opus_int32 SKP_min_32(opus_int32 a, opus_int32 b) -{ - ops_count += 1; - return (((a) < (b)) ? (a) : (b)); -} -#undef SKP_min_64 -SKP_INLINE opus_int64 SKP_min_64(opus_int64 a, opus_int64 b) -{ - ops_count += 1; - return (((a) < (b)) ? (a) : (b)); -} - -/* SKP_min() versions with typecast in the function call */ -#undef SKP_max_int -SKP_INLINE opus_int SKP_max_int(opus_int a, opus_int b) -{ - ops_count += 1; - return (((a) > (b)) ? (a) : (b)); -} -#undef SKP_max_16 -SKP_INLINE opus_int16 SKP_max_16(opus_int16 a, opus_int16 b) -{ - ops_count += 1; - return (((a) > (b)) ? (a) : (b)); -} -#undef SKP_max_32 -SKP_INLINE opus_int32 SKP_max_32(opus_int32 a, opus_int32 b) -{ - ops_count += 1; - return (((a) > (b)) ? (a) : (b)); -} - -#undef SKP_max_64 -SKP_INLINE opus_int64 SKP_max_64(opus_int64 a, opus_int64 b) -{ - ops_count += 1; - return (((a) > (b)) ? (a) : (b)); -} - - -#undef SKP_LIMIT_int -SKP_INLINE opus_int SKP_LIMIT_int(opus_int a, opus_int limit1, opus_int limit2) -{ - opus_int ret; - ops_count += 6; - - ret = ((limit1) > (limit2) ? ((a) > (limit1) ? (limit1) : ((a) < (limit2) ? (limit2) : (a))) \ - : ((a) > (limit2) ? (limit2) : ((a) < (limit1) ? (limit1) : (a)))); - - return(ret); -} - -#undef SKP_LIMIT_16 -SKP_INLINE opus_int16 SKP_LIMIT_16(opus_int16 a, opus_int16 limit1, opus_int16 limit2) -{ - opus_int16 ret; - ops_count += 6; - - ret = ((limit1) > (limit2) ? ((a) > (limit1) ? (limit1) : ((a) < (limit2) ? (limit2) : (a))) \ - : ((a) > (limit2) ? (limit2) : ((a) < (limit1) ? (limit1) : (a)))); - -return(ret); -} - - -#undef SKP_LIMIT_32 -SKP_INLINE opus_int SKP_LIMIT_32(opus_int32 a, opus_int32 limit1, opus_int32 limit2) -{ - opus_int32 ret; - ops_count += 6; - - ret = ((limit1) > (limit2) ? ((a) > (limit1) ? (limit1) : ((a) < (limit2) ? (limit2) : (a))) \ - : ((a) > (limit2) ? (limit2) : ((a) < (limit1) ? (limit1) : (a)))); - return(ret); -} - -#else -#define exVarDefine -#define varDefine -#define SKP_SaveCount() - -#endif -#endif - +/*********************************************************************** +Copyright (c) 2006-2011, Skype Limited. All rights reserved. +Redistribution and use in source and binary forms, with or without +modification, (subject to the limitations in the disclaimer below) +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 Skype Limited, nor the names of specific +contributors, may be used to endorse or promote products derived from +this software without specific prior written permission. +NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED +BY THIS LICENSE. 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. +***********************************************************************/ + +#ifndef _SIGPROCFIX_API_MACROCOUNT_H_ +#define _SIGPROCFIX_API_MACROCOUNT_H_ +#include <stdio.h> + +#ifdef SKP_MACRO_COUNT +#define varDefine opus_int64 ops_count = 0; + +extern opus_int64 ops_count; + +SKP_INLINE opus_int64 SKP_SaveCount(){ + return(ops_count); +} + +SKP_INLINE opus_int64 SKP_SaveResetCount(){ + opus_int64 ret; + + ret = ops_count; + ops_count = 0; + return(ret); +} + +SKP_INLINE SKP_PrintCount(){ + printf("ops_count = %d \n ", (opus_int32)ops_count); +} + +#undef SKP_MUL +SKP_INLINE opus_int32 SKP_MUL(opus_int32 a32, opus_int32 b32){ + opus_int32 ret; + ops_count += 4; + ret = a32 * b32; + return ret; +} + +#undef SKP_MUL_uint +SKP_INLINE opus_uint32 SKP_MUL_uint(opus_uint32 a32, opus_uint32 b32){ + opus_uint32 ret; + ops_count += 4; + ret = a32 * b32; + return ret; +} +#undef SKP_MLA +SKP_INLINE opus_int32 SKP_MLA(opus_int32 a32, opus_int32 b32, opus_int32 c32){ + opus_int32 ret; + ops_count += 4; + ret = a32 + b32 * c32; + return ret; +} + +#undef SKP_MLA_uint +SKP_INLINE opus_int32 SKP_MLA_uint(opus_uint32 a32, opus_uint32 b32, opus_uint32 c32){ + opus_uint32 ret; + ops_count += 4; + ret = a32 + b32 * c32; + return ret; +} + +#undef SKP_SMULWB +SKP_INLINE opus_int32 SKP_SMULWB(opus_int32 a32, opus_int32 b32){ + opus_int32 ret; + ops_count += 5; + ret = (a32 >> 16) * (opus_int32)((opus_int16)b32) + (((a32 & 0x0000FFFF) * (opus_int32)((opus_int16)b32)) >> 16); + return ret; +} +#undef SKP_SMLAWB +SKP_INLINE opus_int32 SKP_SMLAWB(opus_int32 a32, opus_int32 b32, opus_int32 c32){ + opus_int32 ret; + ops_count += 5; + ret = ((a32) + ((((b32) >> 16) * (opus_int32)((opus_int16)(c32))) + ((((b32) & 0x0000FFFF) * (opus_int32)((opus_int16)(c32))) >> 16))); + return ret; +} + +#undef SKP_SMULWT +SKP_INLINE opus_int32 SKP_SMULWT(opus_int32 a32, opus_int32 b32){ + opus_int32 ret; + ops_count += 4; + ret = (a32 >> 16) * (b32 >> 16) + (((a32 & 0x0000FFFF) * (b32 >> 16)) >> 16); + return ret; +} +#undef SKP_SMLAWT +SKP_INLINE opus_int32 SKP_SMLAWT(opus_int32 a32, opus_int32 b32, opus_int32 c32){ + opus_int32 ret; + ops_count += 4; + ret = a32 + ((b32 >> 16) * (c32 >> 16)) + (((b32 & 0x0000FFFF) * ((c32 >> 16)) >> 16)); + return ret; +} + +#undef SKP_SMULBB +SKP_INLINE opus_int32 SKP_SMULBB(opus_int32 a32, opus_int32 b32){ + opus_int32 ret; + ops_count += 1; + ret = (opus_int32)((opus_int16)a32) * (opus_int32)((opus_int16)b32); + return ret; +} +#undef SKP_SMLABB +SKP_INLINE opus_int32 SKP_SMLABB(opus_int32 a32, opus_int32 b32, opus_int32 c32){ + opus_int32 ret; + ops_count += 1; + ret = a32 + (opus_int32)((opus_int16)b32) * (opus_int32)((opus_int16)c32); + return ret; +} + +#undef SKP_SMULBT +SKP_INLINE opus_int32 SKP_SMULBT(opus_int32 a32, opus_int32 b32 ){ + opus_int32 ret; + ops_count += 4; + ret = ((opus_int32)((opus_int16)a32)) * (b32 >> 16); + return ret; +} + +#undef SKP_SMLABT +SKP_INLINE opus_int32 SKP_SMLABT(opus_int32 a32, opus_int32 b32, opus_int32 c32){ + opus_int32 ret; + ops_count += 1; + ret = a32 + ((opus_int32)((opus_int16)b32)) * (c32 >> 16); + return ret; +} + +#undef SKP_SMULTT +SKP_INLINE opus_int32 SKP_SMULTT(opus_int32 a32, opus_int32 b32){ + opus_int32 ret; + ops_count += 1; + ret = (a32 >> 16) * (b32 >> 16); + return ret; +} + +#undef SKP_SMLATT +SKP_INLINE opus_int32 SKP_SMLATT(opus_int32 a32, opus_int32 b32, opus_int32 c32){ + opus_int32 ret; + ops_count += 1; + ret = a32 + (b32 >> 16) * (c32 >> 16); + return ret; +} + + +// multiply-accumulate macros that allow overflow in the addition (ie, no asserts in debug mode) +#undef SKP_MLA_ovflw +#define SKP_MLA_ovflw SKP_MLA + +#undef SKP_SMLABB_ovflw +#define SKP_SMLABB_ovflw SKP_SMLABB + +#undef SKP_SMLABT_ovflw +#define SKP_SMLABT_ovflw SKP_SMLABT + +#undef SKP_SMLATT_ovflw +#define SKP_SMLATT_ovflw SKP_SMLATT + +#undef SKP_SMLAWB_ovflw +#define SKP_SMLAWB_ovflw SKP_SMLAWB + +#undef SKP_SMLAWT_ovflw +#define SKP_SMLAWT_ovflw SKP_SMLAWT + +#undef SKP_SMULL +SKP_INLINE opus_int64 SKP_SMULL(opus_int32 a32, opus_int32 b32){ + opus_int64 ret; + ops_count += 8; + ret = ((opus_int64)(a32) * /*(opus_int64)*/(b32)); + return ret; +} + +#undef SKP_SMLAL +SKP_INLINE opus_int64 SKP_SMLAL(opus_int64 a64, opus_int32 b32, opus_int32 c32){ + opus_int64 ret; + ops_count += 8; + ret = a64 + ((opus_int64)(b32) * /*(opus_int64)*/(c32)); + return ret; +} +#undef SKP_SMLALBB +SKP_INLINE opus_int64 SKP_SMLALBB(opus_int64 a64, opus_int16 b16, opus_int16 c16){ + opus_int64 ret; + ops_count += 4; + ret = a64 + ((opus_int64)(b16) * /*(opus_int64)*/(c16)); + return ret; +} + +#undef SigProcFIX_CLZ16 +SKP_INLINE opus_int32 SigProcFIX_CLZ16(opus_int16 in16) +{ + opus_int32 out32 = 0; + ops_count += 10; + if( in16 == 0 ) { + return 16; + } + /* test nibbles */ + if( in16 & 0xFF00 ) { + if( in16 & 0xF000 ) { + in16 >>= 12; + } else { + out32 += 4; + in16 >>= 8; + } + } else { + if( in16 & 0xFFF0 ) { + out32 += 8; + in16 >>= 4; + } else { + out32 += 12; + } + } + /* test bits and return */ + if( in16 & 0xC ) { + if( in16 & 0x8 ) + return out32 + 0; + else + return out32 + 1; + } else { + if( in16 & 0xE ) + return out32 + 2; + else + return out32 + 3; + } +} + +#undef SigProcFIX_CLZ32 +SKP_INLINE opus_int32 SigProcFIX_CLZ32(opus_int32 in32) +{ + /* test highest 16 bits and convert to opus_int16 */ + ops_count += 2; + if( in32 & 0xFFFF0000 ) { + return SigProcFIX_CLZ16((opus_int16)(in32 >> 16)); + } else { + return SigProcFIX_CLZ16((opus_int16)in32) + 16; + } +} + +#undef SKP_DIV32 +SKP_INLINE opus_int32 SKP_DIV32(opus_int32 a32, opus_int32 b32){ + ops_count += 64; + return a32 / b32; +} + +#undef SKP_DIV32_16 +SKP_INLINE opus_int32 SKP_DIV32_16(opus_int32 a32, opus_int32 b32){ + ops_count += 32; + return a32 / b32; +} + +#undef SKP_SAT8 +SKP_INLINE opus_int8 SKP_SAT8(opus_int64 a){ + opus_int8 tmp; + ops_count += 1; + tmp = (opus_int8)((a) > SKP_int8_MAX ? SKP_int8_MAX : \ + ((a) < SKP_int8_MIN ? SKP_int8_MIN : (a))); + return(tmp); +} + +#undef SKP_SAT16 +SKP_INLINE opus_int16 SKP_SAT16(opus_int64 a){ + opus_int16 tmp; + ops_count += 1; + tmp = (opus_int16)((a) > SKP_int16_MAX ? SKP_int16_MAX : \ + ((a) < SKP_int16_MIN ? SKP_int16_MIN : (a))); + return(tmp); +} +#undef SKP_SAT32 +SKP_INLINE opus_int32 SKP_SAT32(opus_int64 a){ + opus_int32 tmp; + ops_count += 1; + tmp = (opus_int32)((a) > SKP_int32_MAX ? SKP_int32_MAX : \ + ((a) < SKP_int32_MIN ? SKP_int32_MIN : (a))); + return(tmp); +} +#undef SKP_POS_SAT32 +SKP_INLINE opus_int32 SKP_POS_SAT32(opus_int64 a){ + opus_int32 tmp; + ops_count += 1; + tmp = (opus_int32)((a) > SKP_int32_MAX ? SKP_int32_MAX : (a)); + return(tmp); +} + +#undef SKP_ADD_POS_SAT8 +SKP_INLINE opus_int8 SKP_ADD_POS_SAT8(opus_int64 a, opus_int64 b){ + opus_int8 tmp; + ops_count += 1; + tmp = (opus_int8)((((a)+(b)) & 0x80) ? SKP_int8_MAX : ((a)+(b))); + return(tmp); +} +#undef SKP_ADD_POS_SAT16 +SKP_INLINE opus_int16 SKP_ADD_POS_SAT16(opus_int64 a, opus_int64 b){ + opus_int16 tmp; + ops_count += 1; + tmp = (opus_int16)((((a)+(b)) & 0x8000) ? SKP_int16_MAX : ((a)+(b))); + return(tmp); +} + +#undef SKP_ADD_POS_SAT32 +SKP_INLINE opus_int32 SKP_ADD_POS_SAT32(opus_int64 a, opus_int64 b){ + opus_int32 tmp; + ops_count += 1; + tmp = (opus_int32)((((a)+(b)) & 0x80000000) ? SKP_int32_MAX : ((a)+(b))); + return(tmp); +} + +#undef SKP_ADD_POS_SAT64 +SKP_INLINE opus_int64 SKP_ADD_POS_SAT64(opus_int64 a, opus_int64 b){ + opus_int64 tmp; + ops_count += 1; + tmp = ((((a)+(b)) & 0x8000000000000000LL) ? SKP_int64_MAX : ((a)+(b))); + return(tmp); +} + +#undef SKP_LSHIFT8 +SKP_INLINE opus_int8 SKP_LSHIFT8(opus_int8 a, opus_int32 shift){ + opus_int8 ret; + ops_count += 1; + ret = a << shift; + return ret; +} +#undef SKP_LSHIFT16 +SKP_INLINE opus_int16 SKP_LSHIFT16(opus_int16 a, opus_int32 shift){ + opus_int16 ret; + ops_count += 1; + ret = a << shift; + return ret; +} +#undef SKP_LSHIFT32 +SKP_INLINE opus_int32 SKP_LSHIFT32(opus_int32 a, opus_int32 shift){ + opus_int32 ret; + ops_count += 1; + ret = a << shift; + return ret; +} +#undef SKP_LSHIFT64 +SKP_INLINE opus_int64 SKP_LSHIFT64(opus_int64 a, opus_int shift){ + ops_count += 1; + return a << shift; +} + +#undef SKP_LSHIFT_ovflw +SKP_INLINE opus_int32 SKP_LSHIFT_ovflw(opus_int32 a, opus_int32 shift){ + ops_count += 1; + return a << shift; +} + +#undef SKP_LSHIFT_uint +SKP_INLINE opus_uint32 SKP_LSHIFT_uint(opus_uint32 a, opus_int32 shift){ + opus_uint32 ret; + ops_count += 1; + ret = a << shift; + return ret; +} + +#undef SKP_RSHIFT8 +SKP_INLINE opus_int8 SKP_RSHIFT8(opus_int8 a, opus_int32 shift){ + ops_count += 1; + return a >> shift; +} +#undef SKP_RSHIFT16 +SKP_INLINE opus_int16 SKP_RSHIFT16(opus_int16 a, opus_int32 shift){ + ops_count += 1; + return a >> shift; +} +#undef SKP_RSHIFT32 +SKP_INLINE opus_int32 SKP_RSHIFT32(opus_int32 a, opus_int32 shift){ + ops_count += 1; + return a >> shift; +} +#undef SKP_RSHIFT64 +SKP_INLINE opus_int64 SKP_RSHIFT64(opus_int64 a, opus_int64 shift){ + ops_count += 1; + return a >> shift; +} + +#undef SKP_RSHIFT_uint +SKP_INLINE opus_uint32 SKP_RSHIFT_uint(opus_uint32 a, opus_int32 shift){ + ops_count += 1; + return a >> shift; +} + +#undef SKP_ADD_LSHIFT +SKP_INLINE opus_int32 SKP_ADD_LSHIFT(opus_int32 a, opus_int32 b, opus_int32 shift){ + opus_int32 ret; + ops_count += 1; + ret = a + (b << shift); + return ret; // shift >= 0 +} +#undef SKP_ADD_LSHIFT32 +SKP_INLINE opus_int32 SKP_ADD_LSHIFT32(opus_int32 a, opus_int32 b, opus_int32 shift){ + opus_int32 ret; + ops_count += 1; + ret = a + (b << shift); + return ret; // shift >= 0 +} +#undef SKP_ADD_LSHIFT_uint +SKP_INLINE opus_uint32 SKP_ADD_LSHIFT_uint(opus_uint32 a, opus_uint32 b, opus_int32 shift){ + opus_uint32 ret; + ops_count += 1; + ret = a + (b << shift); + return ret; // shift >= 0 +} +#undef SKP_ADD_RSHIFT +SKP_INLINE opus_int32 SKP_ADD_RSHIFT(opus_int32 a, opus_int32 b, opus_int32 shift){ + opus_int32 ret; + ops_count += 1; + ret = a + (b >> shift); + return ret; // shift > 0 +} +#undef SKP_ADD_RSHIFT32 +SKP_INLINE opus_int32 SKP_ADD_RSHIFT32(opus_int32 a, opus_int32 b, opus_int32 shift){ + opus_int32 ret; + ops_count += 1; + ret = a + (b >> shift); + return ret; // shift > 0 +} +#undef SKP_ADD_RSHIFT_uint +SKP_INLINE opus_uint32 SKP_ADD_RSHIFT_uint(opus_uint32 a, opus_uint32 b, opus_int32 shift){ + opus_uint32 ret; + ops_count += 1; + ret = a + (b >> shift); + return ret; // shift > 0 +} +#undef SKP_SUB_LSHIFT32 +SKP_INLINE opus_int32 SKP_SUB_LSHIFT32(opus_int32 a, opus_int32 b, opus_int32 shift){ + opus_int32 ret; + ops_count += 1; + ret = a - (b << shift); + return ret; // shift >= 0 +} +#undef SKP_SUB_RSHIFT32 +SKP_INLINE opus_int32 SKP_SUB_RSHIFT32(opus_int32 a, opus_int32 b, opus_int32 shift){ + opus_int32 ret; + ops_count += 1; + ret = a - (b >> shift); + return ret; // shift > 0 +} + +#undef SKP_RSHIFT_ROUND +SKP_INLINE opus_int32 SKP_RSHIFT_ROUND(opus_int32 a, opus_int32 shift){ + opus_int32 ret; + ops_count += 3; + ret = shift == 1 ? (a >> 1) + (a & 1) : ((a >> (shift - 1)) + 1) >> 1; + return ret; +} + +#undef SKP_RSHIFT_ROUND64 +SKP_INLINE opus_int64 SKP_RSHIFT_ROUND64(opus_int64 a, opus_int32 shift){ + opus_int64 ret; + ops_count += 6; + ret = shift == 1 ? (a >> 1) + (a & 1) : ((a >> (shift - 1)) + 1) >> 1; + return ret; +} + +#undef SKP_abs_int64 +SKP_INLINE opus_int64 SKP_abs_int64(opus_int64 a){ + ops_count += 1; + return (((a) > 0) ? (a) : -(a)); // Be careful, SKP_abs returns wrong when input equals to SKP_intXX_MIN +} + +#undef SKP_abs_int32 +SKP_INLINE opus_int32 SKP_abs_int32(opus_int32 a){ + ops_count += 1; + return abs(a); +} + + +#undef SKP_min +static SKP_min(a, b){ + ops_count += 1; + return (((a) < (b)) ? (a) : (b)); +} +#undef SKP_max +static SKP_max(a, b){ + ops_count += 1; + return (((a) > (b)) ? (a) : (b)); +} +#undef SKP_sign +static SKP_sign(a){ + ops_count += 1; + return ((a) > 0 ? 1 : ( (a) < 0 ? -1 : 0 )); +} + +#undef SKP_ADD16 +SKP_INLINE opus_int16 SKP_ADD16(opus_int16 a, opus_int16 b){ + opus_int16 ret; + ops_count += 1; + ret = a + b; + return ret; +} + +#undef SKP_ADD32 +SKP_INLINE opus_int32 SKP_ADD32(opus_int32 a, opus_int32 b){ + opus_int32 ret; + ops_count += 1; + ret = a + b; + return ret; +} + +#undef SKP_ADD64 +SKP_INLINE opus_int64 SKP_ADD64(opus_int64 a, opus_int64 b){ + opus_int64 ret; + ops_count += 2; + ret = a + b; + return ret; +} + +#undef SKP_SUB16 +SKP_INLINE opus_int16 SKP_SUB16(opus_int16 a, opus_int16 b){ + opus_int16 ret; + ops_count += 1; + ret = a - b; + return ret; +} + +#undef SKP_SUB32 +SKP_INLINE opus_int32 SKP_SUB32(opus_int32 a, opus_int32 b){ + opus_int32 ret; + ops_count += 1; + ret = a - b; + return ret; +} + +#undef SKP_SUB64 +SKP_INLINE opus_int64 SKP_SUB64(opus_int64 a, opus_int64 b){ + opus_int64 ret; + ops_count += 2; + ret = a - b; + return ret; +} + +#undef SKP_ADD_SAT16 +SKP_INLINE opus_int16 SKP_ADD_SAT16( opus_int16 a16, opus_int16 b16 ) { + opus_int16 res; + // Nb will be counted in AKP_add32 and SKP_SAT16 + res = (opus_int16)SKP_SAT16( SKP_ADD32( (opus_int32)(a16), (b16) ) ); + return res; +} + +#undef SKP_ADD_SAT32 +SKP_INLINE opus_int32 SKP_ADD_SAT32(opus_int32 a32, opus_int32 b32){ + opus_int32 res; + ops_count += 1; + res = ((((a32) + (b32)) & 0x80000000) == 0 ? \ + ((((a32) & (b32)) & 0x80000000) != 0 ? SKP_int32_MIN : (a32)+(b32)) : \ + ((((a32) | (b32)) & 0x80000000) == 0 ? SKP_int32_MAX : (a32)+(b32)) ); + return res; +} + +#undef SKP_ADD_SAT64 +SKP_INLINE opus_int64 SKP_ADD_SAT64( opus_int64 a64, opus_int64 b64 ) { + opus_int64 res; + ops_count += 1; + res = ((((a64) + (b64)) & 0x8000000000000000LL) == 0 ? \ + ((((a64) & (b64)) & 0x8000000000000000LL) != 0 ? SKP_int64_MIN : (a64)+(b64)) : \ + ((((a64) | (b64)) & 0x8000000000000000LL) == 0 ? SKP_int64_MAX : (a64)+(b64)) ); + return res; +} + +#undef SKP_SUB_SAT16 +SKP_INLINE opus_int16 SKP_SUB_SAT16( opus_int16 a16, opus_int16 b16 ) { + opus_int16 res; + SKP_assert(0); + // Nb will be counted in sub-macros + res = (opus_int16)SKP_SAT16( SKP_SUB32( (opus_int32)(a16), (b16) ) ); + return res; +} + +#undef SKP_SUB_SAT32 +SKP_INLINE opus_int32 SKP_SUB_SAT32( opus_int32 a32, opus_int32 b32 ) { + opus_int32 res; + ops_count += 1; + res = ((((a32)-(b32)) & 0x80000000) == 0 ? \ + (( (a32) & ((b32)^0x80000000) & 0x80000000) ? SKP_int32_MIN : (a32)-(b32)) : \ + ((((a32)^0x80000000) & (b32) & 0x80000000) ? SKP_int32_MAX : (a32)-(b32)) ); + return res; +} + +#undef SKP_SUB_SAT64 +SKP_INLINE opus_int64 SKP_SUB_SAT64( opus_int64 a64, opus_int64 b64 ) { + opus_int64 res; + ops_count += 1; + res = ((((a64)-(b64)) & 0x8000000000000000LL) == 0 ? \ + (( (a64) & ((b64)^0x8000000000000000LL) & 0x8000000000000000LL) ? SKP_int64_MIN : (a64)-(b64)) : \ + ((((a64)^0x8000000000000000LL) & (b64) & 0x8000000000000000LL) ? SKP_int64_MAX : (a64)-(b64)) ); + + return res; +} + +#undef SKP_SMULWW +SKP_INLINE opus_int32 SKP_SMULWW(opus_int32 a32, opus_int32 b32){ + opus_int32 ret; + // Nb will be counted in sub-macros + ret = SKP_MLA(SKP_SMULWB((a32), (b32)), (a32), SKP_RSHIFT_ROUND((b32), 16)); + return ret; +} + +#undef SKP_SMLAWW +SKP_INLINE opus_int32 SKP_SMLAWW(opus_int32 a32, opus_int32 b32, opus_int32 c32){ + opus_int32 ret; + // Nb will be counted in sub-macros + ret = SKP_MLA(SKP_SMLAWB((a32), (b32), (c32)), (b32), SKP_RSHIFT_ROUND((c32), 16)); + return ret; +} + +#undef SKP_min_int +SKP_INLINE opus_int SKP_min_int(opus_int a, opus_int b) +{ + ops_count += 1; + return (((a) < (b)) ? (a) : (b)); +} + +#undef SKP_min_16 +SKP_INLINE opus_int16 SKP_min_16(opus_int16 a, opus_int16 b) +{ + ops_count += 1; + return (((a) < (b)) ? (a) : (b)); +} +#undef SKP_min_32 +SKP_INLINE opus_int32 SKP_min_32(opus_int32 a, opus_int32 b) +{ + ops_count += 1; + return (((a) < (b)) ? (a) : (b)); +} +#undef SKP_min_64 +SKP_INLINE opus_int64 SKP_min_64(opus_int64 a, opus_int64 b) +{ + ops_count += 1; + return (((a) < (b)) ? (a) : (b)); +} + +/* SKP_min() versions with typecast in the function call */ +#undef SKP_max_int +SKP_INLINE opus_int SKP_max_int(opus_int a, opus_int b) +{ + ops_count += 1; + return (((a) > (b)) ? (a) : (b)); +} +#undef SKP_max_16 +SKP_INLINE opus_int16 SKP_max_16(opus_int16 a, opus_int16 b) +{ + ops_count += 1; + return (((a) > (b)) ? (a) : (b)); +} +#undef SKP_max_32 +SKP_INLINE opus_int32 SKP_max_32(opus_int32 a, opus_int32 b) +{ + ops_count += 1; + return (((a) > (b)) ? (a) : (b)); +} + +#undef SKP_max_64 +SKP_INLINE opus_int64 SKP_max_64(opus_int64 a, opus_int64 b) +{ + ops_count += 1; + return (((a) > (b)) ? (a) : (b)); +} + + +#undef SKP_LIMIT_int +SKP_INLINE opus_int SKP_LIMIT_int(opus_int a, opus_int limit1, opus_int limit2) +{ + opus_int ret; + ops_count += 6; + + ret = ((limit1) > (limit2) ? ((a) > (limit1) ? (limit1) : ((a) < (limit2) ? (limit2) : (a))) \ + : ((a) > (limit2) ? (limit2) : ((a) < (limit1) ? (limit1) : (a)))); + + return(ret); +} + +#undef SKP_LIMIT_16 +SKP_INLINE opus_int16 SKP_LIMIT_16(opus_int16 a, opus_int16 limit1, opus_int16 limit2) +{ + opus_int16 ret; + ops_count += 6; + + ret = ((limit1) > (limit2) ? ((a) > (limit1) ? (limit1) : ((a) < (limit2) ? (limit2) : (a))) \ + : ((a) > (limit2) ? (limit2) : ((a) < (limit1) ? (limit1) : (a)))); + +return(ret); +} + + +#undef SKP_LIMIT_32 +SKP_INLINE opus_int SKP_LIMIT_32(opus_int32 a, opus_int32 limit1, opus_int32 limit2) +{ + opus_int32 ret; + ops_count += 6; + + ret = ((limit1) > (limit2) ? ((a) > (limit1) ? (limit1) : ((a) < (limit2) ? (limit2) : (a))) \ + : ((a) > (limit2) ? (limit2) : ((a) < (limit1) ? (limit1) : (a)))); + return(ret); +} + +#else +#define exVarDefine +#define varDefine +#define SKP_SaveCount() + +#endif +#endif + diff --git a/silk/silk_MacroDebug.h b/silk/silk_MacroDebug.h index dd6d073e3..eb8381b63 100644 --- a/silk/silk_MacroDebug.h +++ b/silk/silk_MacroDebug.h @@ -1,559 +1,559 @@ -/*********************************************************************** -Copyright (c) 2006-2011, Skype Limited. All rights reserved. -Redistribution and use in source and binary forms, with or without -modification, (subject to the limitations in the disclaimer below) -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 Skype Limited, nor the names of specific -contributors, may be used to endorse or promote products derived from -this software without specific prior written permission. -NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED -BY THIS LICENSE. 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. -***********************************************************************/ - -#ifndef _SIGPROCFIX_API_DEBUG_H_ -#define _SIGPROCFIX_API_DEBUG_H_ - -// Redefine macro functions with extensive assertion in Win32_DEBUG mode. -// As function can't be undefined, this file can't work with SigProcFIX_MacroCount.h - -#if 0 && defined (_WIN32) && defined (_DEBUG) && !defined (SKP_MACRO_COUNT) - -#undef SKP_ADD16 -SKP_INLINE opus_int16 SKP_ADD16(opus_int16 a, opus_int16 b){ - opus_int16 ret; - - ret = a + b; - SKP_assert( ret == SKP_ADD_SAT16( a, b )); - return ret; -} - -#undef SKP_ADD32 -SKP_INLINE opus_int32 SKP_ADD32(opus_int32 a, opus_int32 b){ - opus_int32 ret; - - ret = a + b; - SKP_assert( ret == SKP_ADD_SAT32( a, b )); - return ret; -} - -#undef SKP_ADD64 -SKP_INLINE opus_int64 SKP_ADD64(opus_int64 a, opus_int64 b){ - opus_int64 ret; - - ret = a + b; - SKP_assert( ret == SKP_ADD_SAT64( a, b )); - return ret; -} - -#undef SKP_SUB16 -SKP_INLINE opus_int16 SKP_SUB16(opus_int16 a, opus_int16 b){ - opus_int16 ret; - - ret = a - b; - SKP_assert( ret == SKP_SUB_SAT16( a, b )); - return ret; -} - -#undef SKP_SUB32 -SKP_INLINE opus_int32 SKP_SUB32(opus_int32 a, opus_int32 b){ - opus_int32 ret; - - ret = a - b; - SKP_assert( ret == SKP_SUB_SAT32( a, b )); - return ret; -} - -#undef SKP_SUB64 -SKP_INLINE opus_int64 SKP_SUB64(opus_int64 a, opus_int64 b){ - opus_int64 ret; - - ret = a - b; - SKP_assert( ret == SKP_SUB_SAT64( a, b )); - return ret; -} - -#undef SKP_ADD_SAT16 -SKP_INLINE opus_int16 SKP_ADD_SAT16( opus_int16 a16, opus_int16 b16 ) { - opus_int16 res; - res = (opus_int16)SKP_SAT16( SKP_ADD32( (opus_int32)(a16), (b16) ) ); - SKP_assert( res == SKP_SAT16( ( opus_int32 )a16 + ( opus_int32 )b16 ) ); - return res; -} - -#undef SKP_ADD_SAT32 -SKP_INLINE opus_int32 SKP_ADD_SAT32(opus_int32 a32, opus_int32 b32){ - opus_int32 res; - res = ((((a32) + (b32)) & 0x80000000) == 0 ? \ - ((((a32) & (b32)) & 0x80000000) != 0 ? SKP_int32_MIN : (a32)+(b32)) : \ - ((((a32) | (b32)) & 0x80000000) == 0 ? SKP_int32_MAX : (a32)+(b32)) ); - SKP_assert( res == SKP_SAT32( ( opus_int64 )a32 + ( opus_int64 )b32 ) ); - return res; -} - -#undef SKP_ADD_SAT64 -SKP_INLINE opus_int64 SKP_ADD_SAT64( opus_int64 a64, opus_int64 b64 ) { - opus_int64 res; - res = ((((a64) + (b64)) & 0x8000000000000000LL) == 0 ? \ - ((((a64) & (b64)) & 0x8000000000000000LL) != 0 ? SKP_int64_MIN : (a64)+(b64)) : \ - ((((a64) | (b64)) & 0x8000000000000000LL) == 0 ? SKP_int64_MAX : (a64)+(b64)) ); - if( res != a64 + b64 ) { - // Check that we saturated to the correct extreme value - SKP_assert( ( res == SKP_int64_MAX && ( ( a64 >> 1 ) + ( b64 >> 1 ) > ( SKP_int64_MAX >> 3 ) ) ) || - ( res == SKP_int64_MIN && ( ( a64 >> 1 ) + ( b64 >> 1 ) < ( SKP_int64_MIN >> 3 ) ) ) ); - } else { - // Saturation not necessary - SKP_assert( res == a64 + b64 ); - } - return res; -} - -#undef SKP_SUB_SAT16 -SKP_INLINE opus_int16 SKP_SUB_SAT16( opus_int16 a16, opus_int16 b16 ) { - opus_int16 res; - res = (opus_int16)SKP_SAT16( SKP_SUB32( (opus_int32)(a16), (b16) ) ); - SKP_assert( res == SKP_SAT16( ( opus_int32 )a16 - ( opus_int32 )b16 ) ); - return res; -} - -#undef SKP_SUB_SAT32 -SKP_INLINE opus_int32 SKP_SUB_SAT32( opus_int32 a32, opus_int32 b32 ) { - opus_int32 res; - res = ((((a32)-(b32)) & 0x80000000) == 0 ? \ - (( (a32) & ((b32)^0x80000000) & 0x80000000) ? SKP_int32_MIN : (a32)-(b32)) : \ - ((((a32)^0x80000000) & (b32) & 0x80000000) ? SKP_int32_MAX : (a32)-(b32)) ); - SKP_assert( res == SKP_SAT32( ( opus_int64 )a32 - ( opus_int64 )b32 ) ); - return res; -} - -#undef SKP_SUB_SAT64 -SKP_INLINE opus_int64 SKP_SUB_SAT64( opus_int64 a64, opus_int64 b64 ) { - opus_int64 res; - res = ((((a64)-(b64)) & 0x8000000000000000LL) == 0 ? \ - (( (a64) & ((b64)^0x8000000000000000LL) & 0x8000000000000000LL) ? SKP_int64_MIN : (a64)-(b64)) : \ - ((((a64)^0x8000000000000000LL) & (b64) & 0x8000000000000000LL) ? SKP_int64_MAX : (a64)-(b64)) ); - - if( res != a64 - b64 ) { - // Check that we saturated to the correct extreme value - SKP_assert( ( res == SKP_int64_MAX && ( ( a64 >> 1 ) + ( b64 >> 1 ) > ( SKP_int64_MAX >> 3 ) ) ) || - ( res == SKP_int64_MIN && ( ( a64 >> 1 ) + ( b64 >> 1 ) < ( SKP_int64_MIN >> 3 ) ) ) ); - } else { - // Saturation not necessary - SKP_assert( res == a64 - b64 ); - } - return res; -} - -#undef SKP_MUL -SKP_INLINE opus_int32 SKP_MUL(opus_int32 a32, opus_int32 b32){ - opus_int32 ret; - opus_int64 ret64; // Will easily show how many bits that are needed - ret = a32 * b32; - ret64 = (opus_int64)a32 * (opus_int64)b32; - SKP_assert((opus_int64)ret == ret64 ); //Check output overflow - return ret; -} - -#undef SKP_MUL_uint -SKP_INLINE opus_uint32 SKP_MUL_uint(opus_uint32 a32, opus_uint32 b32){ - opus_uint32 ret; - ret = a32 * b32; - SKP_assert((opus_uint64)ret == (opus_uint64)a32 * (opus_uint64)b32); //Check output overflow - return ret; -} -#undef SKP_MLA -SKP_INLINE opus_int32 SKP_MLA(opus_int32 a32, opus_int32 b32, opus_int32 c32){ - opus_int32 ret; - ret = a32 + b32 * c32; - SKP_assert((opus_int64)ret == (opus_int64)a32 + (opus_int64)b32 * (opus_int64)c32); //Check output overflow - return ret; -} - -#undef SKP_MLA_uint -SKP_INLINE opus_int32 SKP_MLA_uint(opus_uint32 a32, opus_uint32 b32, opus_uint32 c32){ - opus_uint32 ret; - ret = a32 + b32 * c32; - SKP_assert((opus_int64)ret == (opus_int64)a32 + (opus_int64)b32 * (opus_int64)c32); //Check output overflow - return ret; -} - -#undef SKP_SMULWB -SKP_INLINE opus_int32 SKP_SMULWB(opus_int32 a32, opus_int32 b32){ - opus_int32 ret; - ret = (a32 >> 16) * (opus_int32)((opus_int16)b32) + (((a32 & 0x0000FFFF) * (opus_int32)((opus_int16)b32)) >> 16); - SKP_assert((opus_int64)ret == ((opus_int64)a32 * (opus_int16)b32) >> 16); - return ret; -} -#undef SKP_SMLAWB -SKP_INLINE opus_int32 SKP_SMLAWB(opus_int32 a32, opus_int32 b32, opus_int32 c32){ - opus_int32 ret; - ret = SKP_ADD32( a32, SKP_SMULWB( b32, c32 ) ); - SKP_assert(SKP_ADD32( a32, SKP_SMULWB( b32, c32 ) ) == SKP_ADD_SAT32( a32, SKP_SMULWB( b32, c32 ) )); - return ret; -} - -#undef SKP_SMULWT -SKP_INLINE opus_int32 SKP_SMULWT(opus_int32 a32, opus_int32 b32){ - opus_int32 ret; - ret = (a32 >> 16) * (b32 >> 16) + (((a32 & 0x0000FFFF) * (b32 >> 16)) >> 16); - SKP_assert((opus_int64)ret == ((opus_int64)a32 * (b32 >> 16)) >> 16); - return ret; -} -#undef SKP_SMLAWT -SKP_INLINE opus_int32 SKP_SMLAWT(opus_int32 a32, opus_int32 b32, opus_int32 c32){ - opus_int32 ret; - ret = a32 + ((b32 >> 16) * (c32 >> 16)) + (((b32 & 0x0000FFFF) * ((c32 >> 16)) >> 16)); - SKP_assert((opus_int64)ret == (opus_int64)a32 + (((opus_int64)b32 * (c32 >> 16)) >> 16)); - return ret; -} - -#undef SKP_SMULL -SKP_INLINE opus_int64 SKP_SMULL(opus_int64 a64, opus_int64 b64){ - opus_int64 ret64; - ret64 = a64 * b64; - if( b64 != 0 ) { - SKP_assert( a64 == (ret64 / b64) ); - } else if( a64 != 0 ) { - SKP_assert( b64 == (ret64 / a64) ); - } - return ret64; -} - -// no checking needed for SKP_SMULBB -#undef SKP_SMLABB -SKP_INLINE opus_int32 SKP_SMLABB(opus_int32 a32, opus_int32 b32, opus_int32 c32){ - opus_int32 ret; - ret = a32 + (opus_int32)((opus_int16)b32) * (opus_int32)((opus_int16)c32); - SKP_assert((opus_int64)ret == (opus_int64)a32 + (opus_int64)b32 * (opus_int16)c32); - return ret; -} - -// no checking needed for SKP_SMULBT -#undef SKP_SMLABT -SKP_INLINE opus_int32 SKP_SMLABT(opus_int32 a32, opus_int32 b32, opus_int32 c32){ - opus_int32 ret; - ret = a32 + ((opus_int32)((opus_int16)b32)) * (c32 >> 16); - SKP_assert((opus_int64)ret == (opus_int64)a32 + (opus_int64)b32 * (c32 >> 16)); - return ret; -} - -// no checking needed for SKP_SMULTT -#undef SKP_SMLATT -SKP_INLINE opus_int32 SKP_SMLATT(opus_int32 a32, opus_int32 b32, opus_int32 c32){ - opus_int32 ret; - ret = a32 + (b32 >> 16) * (c32 >> 16); - SKP_assert((opus_int64)ret == (opus_int64)a32 + (b32 >> 16) * (c32 >> 16)); - return ret; -} - -#undef SKP_SMULWW -SKP_INLINE opus_int32 SKP_SMULWW(opus_int32 a32, opus_int32 b32){ - opus_int32 ret, tmp1, tmp2; - opus_int64 ret64; - - ret = SKP_SMULWB( a32, b32 ); - tmp1 = SKP_RSHIFT_ROUND( b32, 16 ); - tmp2 = SKP_MUL( a32, tmp1 ); - - SKP_assert( (opus_int64)tmp2 == (opus_int64) a32 * (opus_int64) tmp1 ); - - tmp1 = ret; - ret = SKP_ADD32( tmp1, tmp2 ); - SKP_assert( SKP_ADD32( tmp1, tmp2 ) == SKP_ADD_SAT32( tmp1, tmp2 ) ); - - ret64 = SKP_RSHIFT64( SKP_SMULL( a32, b32 ), 16 ); - SKP_assert( (opus_int64)ret == ret64 ); - - return ret; -} - -#undef SKP_SMLAWW -SKP_INLINE opus_int32 SKP_SMLAWW(opus_int32 a32, opus_int32 b32, opus_int32 c32){ - opus_int32 ret, tmp; - - tmp = SKP_SMULWW( b32, c32 ); - ret = SKP_ADD32( a32, tmp ); - SKP_assert( ret == SKP_ADD_SAT32( a32, tmp ) ); - return ret; -} - -// multiply-accumulate macros that allow overflow in the addition (ie, no asserts in debug mode) -#undef SKP_MLA_ovflw -#define SKP_MLA_ovflw(a32, b32, c32) ((a32) + ((b32) * (c32))) -#undef SKP_SMLABB_ovflw -#define SKP_SMLABB_ovflw(a32, b32, c32) ((a32) + ((opus_int32)((opus_int16)(b32))) * (opus_int32)((opus_int16)(c32))) -#undef SKP_SMLABT_ovflw -#define SKP_SMLABT_ovflw(a32, b32, c32) ((a32) + ((opus_int32)((opus_int16)(b32))) * ((c32) >> 16)) -#undef SKP_SMLATT_ovflw -#define SKP_SMLATT_ovflw(a32, b32, c32) ((a32) + ((b32) >> 16) * ((c32) >> 16)) -#undef SKP_SMLAWB_ovflw -#define SKP_SMLAWB_ovflw(a32, b32, c32) ((a32) + ((((b32) >> 16) * (opus_int32)((opus_int16)(c32))) + ((((b32) & 0x0000FFFF) * (opus_int32)((opus_int16)(c32))) >> 16))) -#undef SKP_SMLAWT_ovflw -#define SKP_SMLAWT_ovflw(a32, b32, c32) ((a32) + (((b32) >> 16) * ((c32) >> 16)) + ((((b32) & 0x0000FFFF) * ((c32) >> 16)) >> 16)) - -// no checking needed for SKP_SMULL -// no checking needed for SKP_SMLAL -// no checking needed for SKP_SMLALBB -// no checking needed for SigProcFIX_CLZ16 -// no checking needed for SigProcFIX_CLZ32 - -#undef SKP_DIV32 -SKP_INLINE opus_int32 SKP_DIV32(opus_int32 a32, opus_int32 b32){ - SKP_assert( b32 != 0 ); - return a32 / b32; -} - -#undef SKP_DIV32_16 -SKP_INLINE opus_int32 SKP_DIV32_16(opus_int32 a32, opus_int32 b32){ - SKP_assert( b32 != 0 ); - SKP_assert( b32 <= SKP_int16_MAX ); - SKP_assert( b32 >= SKP_int16_MIN ); - return a32 / b32; -} - -// no checking needed for SKP_SAT8 -// no checking needed for SKP_SAT16 -// no checking needed for SKP_SAT32 -// no checking needed for SKP_POS_SAT32 -// no checking needed for SKP_ADD_POS_SAT8 -// no checking needed for SKP_ADD_POS_SAT16 -// no checking needed for SKP_ADD_POS_SAT32 -// no checking needed for SKP_ADD_POS_SAT64 -#undef SKP_LSHIFT8 -SKP_INLINE opus_int8 SKP_LSHIFT8(opus_int8 a, opus_int32 shift){ - opus_int8 ret; - ret = a << shift; - SKP_assert(shift >= 0); - SKP_assert(shift < 8); - SKP_assert((opus_int64)ret == ((opus_int64)a) << shift); - return ret; -} -#undef SKP_LSHIFT16 -SKP_INLINE opus_int16 SKP_LSHIFT16(opus_int16 a, opus_int32 shift){ - opus_int16 ret; - ret = a << shift; - SKP_assert(shift >= 0); - SKP_assert(shift < 16); - SKP_assert((opus_int64)ret == ((opus_int64)a) << shift); - return ret; -} -#undef SKP_LSHIFT32 -SKP_INLINE opus_int32 SKP_LSHIFT32(opus_int32 a, opus_int32 shift){ - opus_int32 ret; - ret = a << shift; - SKP_assert(shift >= 0); - SKP_assert(shift < 32); - SKP_assert((opus_int64)ret == ((opus_int64)a) << shift); - return ret; -} -#undef SKP_LSHIFT64 -SKP_INLINE opus_int64 SKP_LSHIFT64(opus_int64 a, opus_int shift){ - SKP_assert(shift >= 0); - SKP_assert(shift < 64); - return a << shift; -} - -#undef SKP_LSHIFT_ovflw -SKP_INLINE opus_int32 SKP_LSHIFT_ovflw(opus_int32 a, opus_int32 shift){ - SKP_assert(shift >= 0); /* no check for overflow */ - return a << shift; -} - -#undef SKP_LSHIFT_uint -SKP_INLINE opus_uint32 SKP_LSHIFT_uint(opus_uint32 a, opus_int32 shift){ - opus_uint32 ret; - ret = a << shift; - SKP_assert(shift >= 0); - SKP_assert((opus_int64)ret == ((opus_int64)a) << shift); - return ret; -} - -#undef SKP_RSHIFT8 -SKP_INLINE opus_int8 SKP_RSHIFT8(opus_int8 a, opus_int32 shift){ - SKP_assert(shift >= 0); - SKP_assert(shift < 8); - return a >> shift; -} -#undef SKP_RSHIFT16 -SKP_INLINE opus_int16 SKP_RSHIFT16(opus_int16 a, opus_int32 shift){ - SKP_assert(shift >= 0); - SKP_assert(shift < 16); - return a >> shift; -} -#undef SKP_RSHIFT32 -SKP_INLINE opus_int32 SKP_RSHIFT32(opus_int32 a, opus_int32 shift){ - SKP_assert(shift >= 0); - SKP_assert(shift < 32); - return a >> shift; -} -#undef SKP_RSHIFT64 -SKP_INLINE opus_int64 SKP_RSHIFT64(opus_int64 a, opus_int64 shift){ - SKP_assert(shift >= 0); - SKP_assert(shift <= 63); - return a >> shift; -} - -#undef SKP_RSHIFT_uint -SKP_INLINE opus_uint32 SKP_RSHIFT_uint(opus_uint32 a, opus_int32 shift){ - SKP_assert(shift >= 0); - SKP_assert(shift <= 32); - return a >> shift; -} - -#undef SKP_ADD_LSHIFT -SKP_INLINE opus_int32 SKP_ADD_LSHIFT(opus_int32 a, opus_int32 b, opus_int32 shift){ - opus_int32 ret; - SKP_assert(shift >= 0); - SKP_assert(shift <= 31); - ret = a + (b << shift); - SKP_assert((opus_int64)ret == (opus_int64)a + (((opus_int64)b) << shift)); - return ret; // shift >= 0 -} -#undef SKP_ADD_LSHIFT32 -SKP_INLINE opus_int32 SKP_ADD_LSHIFT32(opus_int32 a, opus_int32 b, opus_int32 shift){ - opus_int32 ret; - SKP_assert(shift >= 0); - SKP_assert(shift <= 31); - ret = a + (b << shift); - SKP_assert((opus_int64)ret == (opus_int64)a + (((opus_int64)b) << shift)); - return ret; // shift >= 0 -} -#undef SKP_ADD_LSHIFT_uint -SKP_INLINE opus_uint32 SKP_ADD_LSHIFT_uint(opus_uint32 a, opus_uint32 b, opus_int32 shift){ - opus_uint32 ret; - SKP_assert(shift >= 0); - SKP_assert(shift <= 32); - ret = a + (b << shift); - SKP_assert((opus_int64)ret == (opus_int64)a + (((opus_int64)b) << shift)); - return ret; // shift >= 0 -} -#undef SKP_ADD_RSHIFT -SKP_INLINE opus_int32 SKP_ADD_RSHIFT(opus_int32 a, opus_int32 b, opus_int32 shift){ - opus_int32 ret; - SKP_assert(shift >= 0); - SKP_assert(shift <= 31); - ret = a + (b >> shift); - SKP_assert((opus_int64)ret == (opus_int64)a + (((opus_int64)b) >> shift)); - return ret; // shift > 0 -} -#undef SKP_ADD_RSHIFT32 -SKP_INLINE opus_int32 SKP_ADD_RSHIFT32(opus_int32 a, opus_int32 b, opus_int32 shift){ - opus_int32 ret; - SKP_assert(shift >= 0); - SKP_assert(shift <= 31); - ret = a + (b >> shift); - SKP_assert((opus_int64)ret == (opus_int64)a + (((opus_int64)b) >> shift)); - return ret; // shift > 0 -} -#undef SKP_ADD_RSHIFT_uint -SKP_INLINE opus_uint32 SKP_ADD_RSHIFT_uint(opus_uint32 a, opus_uint32 b, opus_int32 shift){ - opus_uint32 ret; - SKP_assert(shift >= 0); - SKP_assert(shift <= 32); - ret = a + (b >> shift); - SKP_assert((opus_int64)ret == (opus_int64)a + (((opus_int64)b) >> shift)); - return ret; // shift > 0 -} -#undef SKP_SUB_LSHIFT32 -SKP_INLINE opus_int32 SKP_SUB_LSHIFT32(opus_int32 a, opus_int32 b, opus_int32 shift){ - opus_int32 ret; - SKP_assert(shift >= 0); - SKP_assert(shift <= 31); - ret = a - (b << shift); - SKP_assert((opus_int64)ret == (opus_int64)a - (((opus_int64)b) << shift)); - return ret; // shift >= 0 -} -#undef SKP_SUB_RSHIFT32 -SKP_INLINE opus_int32 SKP_SUB_RSHIFT32(opus_int32 a, opus_int32 b, opus_int32 shift){ - opus_int32 ret; - SKP_assert(shift >= 0); - SKP_assert(shift <= 31); - ret = a - (b >> shift); - SKP_assert((opus_int64)ret == (opus_int64)a - (((opus_int64)b) >> shift)); - return ret; // shift > 0 -} - -#undef SKP_RSHIFT_ROUND -SKP_INLINE opus_int32 SKP_RSHIFT_ROUND(opus_int32 a, opus_int32 shift){ - opus_int32 ret; - SKP_assert(shift > 0); /* the marco definition can't handle a shift of zero */ - SKP_assert(shift < 32); - ret = shift == 1 ? (a >> 1) + (a & 1) : ((a >> (shift - 1)) + 1) >> 1; - SKP_assert((opus_int64)ret == ((opus_int64)a + ((opus_int64)1 << (shift - 1))) >> shift); - return ret; -} - -#undef SKP_RSHIFT_ROUND64 -SKP_INLINE opus_int64 SKP_RSHIFT_ROUND64(opus_int64 a, opus_int32 shift){ - opus_int64 ret; - SKP_assert(shift > 0); /* the marco definition can't handle a shift of zero */ - SKP_assert(shift < 64); - ret = shift == 1 ? (a >> 1) + (a & 1) : ((a >> (shift - 1)) + 1) >> 1; - return ret; -} - -// SKP_abs is used on floats also, so doesn't work... -//#undef SKP_abs -//SKP_INLINE opus_int32 SKP_abs(opus_int32 a){ -// SKP_assert(a != 0x80000000); -// return (((a) > 0) ? (a) : -(a)); // Be careful, SKP_abs returns wrong when input equals to SKP_intXX_MIN -//} - -#undef SKP_abs_int64 -SKP_INLINE opus_int64 SKP_abs_int64(opus_int64 a){ - SKP_assert(a != 0x8000000000000000); - return (((a) > 0) ? (a) : -(a)); // Be careful, SKP_abs returns wrong when input equals to SKP_intXX_MIN -} - -#undef SKP_abs_int32 -SKP_INLINE opus_int32 SKP_abs_int32(opus_int32 a){ - SKP_assert(a != 0x80000000); - return abs(a); -} - -#undef SKP_CHECK_FIT8 -SKP_INLINE opus_int8 SKP_CHECK_FIT8( opus_int64 a ){ - opus_int8 ret; - ret = (opus_int8)a; - SKP_assert( (opus_int64)ret == a ); - return( ret ); -} - -#undef SKP_CHECK_FIT16 -SKP_INLINE opus_int16 SKP_CHECK_FIT16( opus_int64 a ){ - opus_int16 ret; - ret = (opus_int16)a; - SKP_assert( (opus_int64)ret == a ); - return( ret ); -} - -#undef SKP_CHECK_FIT32 -SKP_INLINE opus_int32 SKP_CHECK_FIT32( opus_int64 a ){ - opus_int32 ret; - ret = (opus_int32)a; - SKP_assert( (opus_int64)ret == a ); - return( ret ); -} - -// no checking for SKP_NSHIFT_MUL_32_32 -// no checking for SKP_NSHIFT_MUL_16_16 -// no checking needed for SKP_min -// no checking needed for SKP_max -// no checking needed for SKP_sign - -#endif -#endif +/*********************************************************************** +Copyright (c) 2006-2011, Skype Limited. All rights reserved. +Redistribution and use in source and binary forms, with or without +modification, (subject to the limitations in the disclaimer below) +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 Skype Limited, nor the names of specific +contributors, may be used to endorse or promote products derived from +this software without specific prior written permission. +NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED +BY THIS LICENSE. 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. +***********************************************************************/ + +#ifndef _SIGPROCFIX_API_DEBUG_H_ +#define _SIGPROCFIX_API_DEBUG_H_ + +// Redefine macro functions with extensive assertion in Win32_DEBUG mode. +// As function can't be undefined, this file can't work with SigProcFIX_MacroCount.h + +#if 0 && defined (_WIN32) && defined (_DEBUG) && !defined (SKP_MACRO_COUNT) + +#undef SKP_ADD16 +SKP_INLINE opus_int16 SKP_ADD16(opus_int16 a, opus_int16 b){ + opus_int16 ret; + + ret = a + b; + SKP_assert( ret == SKP_ADD_SAT16( a, b )); + return ret; +} + +#undef SKP_ADD32 +SKP_INLINE opus_int32 SKP_ADD32(opus_int32 a, opus_int32 b){ + opus_int32 ret; + + ret = a + b; + SKP_assert( ret == SKP_ADD_SAT32( a, b )); + return ret; +} + +#undef SKP_ADD64 +SKP_INLINE opus_int64 SKP_ADD64(opus_int64 a, opus_int64 b){ + opus_int64 ret; + + ret = a + b; + SKP_assert( ret == SKP_ADD_SAT64( a, b )); + return ret; +} + +#undef SKP_SUB16 +SKP_INLINE opus_int16 SKP_SUB16(opus_int16 a, opus_int16 b){ + opus_int16 ret; + + ret = a - b; + SKP_assert( ret == SKP_SUB_SAT16( a, b )); + return ret; +} + +#undef SKP_SUB32 +SKP_INLINE opus_int32 SKP_SUB32(opus_int32 a, opus_int32 b){ + opus_int32 ret; + + ret = a - b; + SKP_assert( ret == SKP_SUB_SAT32( a, b )); + return ret; +} + +#undef SKP_SUB64 +SKP_INLINE opus_int64 SKP_SUB64(opus_int64 a, opus_int64 b){ + opus_int64 ret; + + ret = a - b; + SKP_assert( ret == SKP_SUB_SAT64( a, b )); + return ret; +} + +#undef SKP_ADD_SAT16 +SKP_INLINE opus_int16 SKP_ADD_SAT16( opus_int16 a16, opus_int16 b16 ) { + opus_int16 res; + res = (opus_int16)SKP_SAT16( SKP_ADD32( (opus_int32)(a16), (b16) ) ); + SKP_assert( res == SKP_SAT16( ( opus_int32 )a16 + ( opus_int32 )b16 ) ); + return res; +} + +#undef SKP_ADD_SAT32 +SKP_INLINE opus_int32 SKP_ADD_SAT32(opus_int32 a32, opus_int32 b32){ + opus_int32 res; + res = ((((a32) + (b32)) & 0x80000000) == 0 ? \ + ((((a32) & (b32)) & 0x80000000) != 0 ? SKP_int32_MIN : (a32)+(b32)) : \ + ((((a32) | (b32)) & 0x80000000) == 0 ? SKP_int32_MAX : (a32)+(b32)) ); + SKP_assert( res == SKP_SAT32( ( opus_int64 )a32 + ( opus_int64 )b32 ) ); + return res; +} + +#undef SKP_ADD_SAT64 +SKP_INLINE opus_int64 SKP_ADD_SAT64( opus_int64 a64, opus_int64 b64 ) { + opus_int64 res; + res = ((((a64) + (b64)) & 0x8000000000000000LL) == 0 ? \ + ((((a64) & (b64)) & 0x8000000000000000LL) != 0 ? SKP_int64_MIN : (a64)+(b64)) : \ + ((((a64) | (b64)) & 0x8000000000000000LL) == 0 ? SKP_int64_MAX : (a64)+(b64)) ); + if( res != a64 + b64 ) { + // Check that we saturated to the correct extreme value + SKP_assert( ( res == SKP_int64_MAX && ( ( a64 >> 1 ) + ( b64 >> 1 ) > ( SKP_int64_MAX >> 3 ) ) ) || + ( res == SKP_int64_MIN && ( ( a64 >> 1 ) + ( b64 >> 1 ) < ( SKP_int64_MIN >> 3 ) ) ) ); + } else { + // Saturation not necessary + SKP_assert( res == a64 + b64 ); + } + return res; +} + +#undef SKP_SUB_SAT16 +SKP_INLINE opus_int16 SKP_SUB_SAT16( opus_int16 a16, opus_int16 b16 ) { + opus_int16 res; + res = (opus_int16)SKP_SAT16( SKP_SUB32( (opus_int32)(a16), (b16) ) ); + SKP_assert( res == SKP_SAT16( ( opus_int32 )a16 - ( opus_int32 )b16 ) ); + return res; +} + +#undef SKP_SUB_SAT32 +SKP_INLINE opus_int32 SKP_SUB_SAT32( opus_int32 a32, opus_int32 b32 ) { + opus_int32 res; + res = ((((a32)-(b32)) & 0x80000000) == 0 ? \ + (( (a32) & ((b32)^0x80000000) & 0x80000000) ? SKP_int32_MIN : (a32)-(b32)) : \ + ((((a32)^0x80000000) & (b32) & 0x80000000) ? SKP_int32_MAX : (a32)-(b32)) ); + SKP_assert( res == SKP_SAT32( ( opus_int64 )a32 - ( opus_int64 )b32 ) ); + return res; +} + +#undef SKP_SUB_SAT64 +SKP_INLINE opus_int64 SKP_SUB_SAT64( opus_int64 a64, opus_int64 b64 ) { + opus_int64 res; + res = ((((a64)-(b64)) & 0x8000000000000000LL) == 0 ? \ + (( (a64) & ((b64)^0x8000000000000000LL) & 0x8000000000000000LL) ? SKP_int64_MIN : (a64)-(b64)) : \ + ((((a64)^0x8000000000000000LL) & (b64) & 0x8000000000000000LL) ? SKP_int64_MAX : (a64)-(b64)) ); + + if( res != a64 - b64 ) { + // Check that we saturated to the correct extreme value + SKP_assert( ( res == SKP_int64_MAX && ( ( a64 >> 1 ) + ( b64 >> 1 ) > ( SKP_int64_MAX >> 3 ) ) ) || + ( res == SKP_int64_MIN && ( ( a64 >> 1 ) + ( b64 >> 1 ) < ( SKP_int64_MIN >> 3 ) ) ) ); + } else { + // Saturation not necessary + SKP_assert( res == a64 - b64 ); + } + return res; +} + +#undef SKP_MUL +SKP_INLINE opus_int32 SKP_MUL(opus_int32 a32, opus_int32 b32){ + opus_int32 ret; + opus_int64 ret64; // Will easily show how many bits that are needed + ret = a32 * b32; + ret64 = (opus_int64)a32 * (opus_int64)b32; + SKP_assert((opus_int64)ret == ret64 ); //Check output overflow + return ret; +} + +#undef SKP_MUL_uint +SKP_INLINE opus_uint32 SKP_MUL_uint(opus_uint32 a32, opus_uint32 b32){ + opus_uint32 ret; + ret = a32 * b32; + SKP_assert((opus_uint64)ret == (opus_uint64)a32 * (opus_uint64)b32); //Check output overflow + return ret; +} +#undef SKP_MLA +SKP_INLINE opus_int32 SKP_MLA(opus_int32 a32, opus_int32 b32, opus_int32 c32){ + opus_int32 ret; + ret = a32 + b32 * c32; + SKP_assert((opus_int64)ret == (opus_int64)a32 + (opus_int64)b32 * (opus_int64)c32); //Check output overflow + return ret; +} + +#undef SKP_MLA_uint +SKP_INLINE opus_int32 SKP_MLA_uint(opus_uint32 a32, opus_uint32 b32, opus_uint32 c32){ + opus_uint32 ret; + ret = a32 + b32 * c32; + SKP_assert((opus_int64)ret == (opus_int64)a32 + (opus_int64)b32 * (opus_int64)c32); //Check output overflow + return ret; +} + +#undef SKP_SMULWB +SKP_INLINE opus_int32 SKP_SMULWB(opus_int32 a32, opus_int32 b32){ + opus_int32 ret; + ret = (a32 >> 16) * (opus_int32)((opus_int16)b32) + (((a32 & 0x0000FFFF) * (opus_int32)((opus_int16)b32)) >> 16); + SKP_assert((opus_int64)ret == ((opus_int64)a32 * (opus_int16)b32) >> 16); + return ret; +} +#undef SKP_SMLAWB +SKP_INLINE opus_int32 SKP_SMLAWB(opus_int32 a32, opus_int32 b32, opus_int32 c32){ + opus_int32 ret; + ret = SKP_ADD32( a32, SKP_SMULWB( b32, c32 ) ); + SKP_assert(SKP_ADD32( a32, SKP_SMULWB( b32, c32 ) ) == SKP_ADD_SAT32( a32, SKP_SMULWB( b32, c32 ) )); + return ret; +} + +#undef SKP_SMULWT +SKP_INLINE opus_int32 SKP_SMULWT(opus_int32 a32, opus_int32 b32){ + opus_int32 ret; + ret = (a32 >> 16) * (b32 >> 16) + (((a32 & 0x0000FFFF) * (b32 >> 16)) >> 16); + SKP_assert((opus_int64)ret == ((opus_int64)a32 * (b32 >> 16)) >> 16); + return ret; +} +#undef SKP_SMLAWT +SKP_INLINE opus_int32 SKP_SMLAWT(opus_int32 a32, opus_int32 b32, opus_int32 c32){ + opus_int32 ret; + ret = a32 + ((b32 >> 16) * (c32 >> 16)) + (((b32 & 0x0000FFFF) * ((c32 >> 16)) >> 16)); + SKP_assert((opus_int64)ret == (opus_int64)a32 + (((opus_int64)b32 * (c32 >> 16)) >> 16)); + return ret; +} + +#undef SKP_SMULL +SKP_INLINE opus_int64 SKP_SMULL(opus_int64 a64, opus_int64 b64){ + opus_int64 ret64; + ret64 = a64 * b64; + if( b64 != 0 ) { + SKP_assert( a64 == (ret64 / b64) ); + } else if( a64 != 0 ) { + SKP_assert( b64 == (ret64 / a64) ); + } + return ret64; +} + +// no checking needed for SKP_SMULBB +#undef SKP_SMLABB +SKP_INLINE opus_int32 SKP_SMLABB(opus_int32 a32, opus_int32 b32, opus_int32 c32){ + opus_int32 ret; + ret = a32 + (opus_int32)((opus_int16)b32) * (opus_int32)((opus_int16)c32); + SKP_assert((opus_int64)ret == (opus_int64)a32 + (opus_int64)b32 * (opus_int16)c32); + return ret; +} + +// no checking needed for SKP_SMULBT +#undef SKP_SMLABT +SKP_INLINE opus_int32 SKP_SMLABT(opus_int32 a32, opus_int32 b32, opus_int32 c32){ + opus_int32 ret; + ret = a32 + ((opus_int32)((opus_int16)b32)) * (c32 >> 16); + SKP_assert((opus_int64)ret == (opus_int64)a32 + (opus_int64)b32 * (c32 >> 16)); + return ret; +} + +// no checking needed for SKP_SMULTT +#undef SKP_SMLATT +SKP_INLINE opus_int32 SKP_SMLATT(opus_int32 a32, opus_int32 b32, opus_int32 c32){ + opus_int32 ret; + ret = a32 + (b32 >> 16) * (c32 >> 16); + SKP_assert((opus_int64)ret == (opus_int64)a32 + (b32 >> 16) * (c32 >> 16)); + return ret; +} + +#undef SKP_SMULWW +SKP_INLINE opus_int32 SKP_SMULWW(opus_int32 a32, opus_int32 b32){ + opus_int32 ret, tmp1, tmp2; + opus_int64 ret64; + + ret = SKP_SMULWB( a32, b32 ); + tmp1 = SKP_RSHIFT_ROUND( b32, 16 ); + tmp2 = SKP_MUL( a32, tmp1 ); + + SKP_assert( (opus_int64)tmp2 == (opus_int64) a32 * (opus_int64) tmp1 ); + + tmp1 = ret; + ret = SKP_ADD32( tmp1, tmp2 ); + SKP_assert( SKP_ADD32( tmp1, tmp2 ) == SKP_ADD_SAT32( tmp1, tmp2 ) ); + + ret64 = SKP_RSHIFT64( SKP_SMULL( a32, b32 ), 16 ); + SKP_assert( (opus_int64)ret == ret64 ); + + return ret; +} + +#undef SKP_SMLAWW +SKP_INLINE opus_int32 SKP_SMLAWW(opus_int32 a32, opus_int32 b32, opus_int32 c32){ + opus_int32 ret, tmp; + + tmp = SKP_SMULWW( b32, c32 ); + ret = SKP_ADD32( a32, tmp ); + SKP_assert( ret == SKP_ADD_SAT32( a32, tmp ) ); + return ret; +} + +// multiply-accumulate macros that allow overflow in the addition (ie, no asserts in debug mode) +#undef SKP_MLA_ovflw +#define SKP_MLA_ovflw(a32, b32, c32) ((a32) + ((b32) * (c32))) +#undef SKP_SMLABB_ovflw +#define SKP_SMLABB_ovflw(a32, b32, c32) ((a32) + ((opus_int32)((opus_int16)(b32))) * (opus_int32)((opus_int16)(c32))) +#undef SKP_SMLABT_ovflw +#define SKP_SMLABT_ovflw(a32, b32, c32) ((a32) + ((opus_int32)((opus_int16)(b32))) * ((c32) >> 16)) +#undef SKP_SMLATT_ovflw +#define SKP_SMLATT_ovflw(a32, b32, c32) ((a32) + ((b32) >> 16) * ((c32) >> 16)) +#undef SKP_SMLAWB_ovflw +#define SKP_SMLAWB_ovflw(a32, b32, c32) ((a32) + ((((b32) >> 16) * (opus_int32)((opus_int16)(c32))) + ((((b32) & 0x0000FFFF) * (opus_int32)((opus_int16)(c32))) >> 16))) +#undef SKP_SMLAWT_ovflw +#define SKP_SMLAWT_ovflw(a32, b32, c32) ((a32) + (((b32) >> 16) * ((c32) >> 16)) + ((((b32) & 0x0000FFFF) * ((c32) >> 16)) >> 16)) + +// no checking needed for SKP_SMULL +// no checking needed for SKP_SMLAL +// no checking needed for SKP_SMLALBB +// no checking needed for SigProcFIX_CLZ16 +// no checking needed for SigProcFIX_CLZ32 + +#undef SKP_DIV32 +SKP_INLINE opus_int32 SKP_DIV32(opus_int32 a32, opus_int32 b32){ + SKP_assert( b32 != 0 ); + return a32 / b32; +} + +#undef SKP_DIV32_16 +SKP_INLINE opus_int32 SKP_DIV32_16(opus_int32 a32, opus_int32 b32){ + SKP_assert( b32 != 0 ); + SKP_assert( b32 <= SKP_int16_MAX ); + SKP_assert( b32 >= SKP_int16_MIN ); + return a32 / b32; +} + +// no checking needed for SKP_SAT8 +// no checking needed for SKP_SAT16 +// no checking needed for SKP_SAT32 +// no checking needed for SKP_POS_SAT32 +// no checking needed for SKP_ADD_POS_SAT8 +// no checking needed for SKP_ADD_POS_SAT16 +// no checking needed for SKP_ADD_POS_SAT32 +// no checking needed for SKP_ADD_POS_SAT64 +#undef SKP_LSHIFT8 +SKP_INLINE opus_int8 SKP_LSHIFT8(opus_int8 a, opus_int32 shift){ + opus_int8 ret; + ret = a << shift; + SKP_assert(shift >= 0); + SKP_assert(shift < 8); + SKP_assert((opus_int64)ret == ((opus_int64)a) << shift); + return ret; +} +#undef SKP_LSHIFT16 +SKP_INLINE opus_int16 SKP_LSHIFT16(opus_int16 a, opus_int32 shift){ + opus_int16 ret; + ret = a << shift; + SKP_assert(shift >= 0); + SKP_assert(shift < 16); + SKP_assert((opus_int64)ret == ((opus_int64)a) << shift); + return ret; +} +#undef SKP_LSHIFT32 +SKP_INLINE opus_int32 SKP_LSHIFT32(opus_int32 a, opus_int32 shift){ + opus_int32 ret; + ret = a << shift; + SKP_assert(shift >= 0); + SKP_assert(shift < 32); + SKP_assert((opus_int64)ret == ((opus_int64)a) << shift); + return ret; +} +#undef SKP_LSHIFT64 +SKP_INLINE opus_int64 SKP_LSHIFT64(opus_int64 a, opus_int shift){ + SKP_assert(shift >= 0); + SKP_assert(shift < 64); + return a << shift; +} + +#undef SKP_LSHIFT_ovflw +SKP_INLINE opus_int32 SKP_LSHIFT_ovflw(opus_int32 a, opus_int32 shift){ + SKP_assert(shift >= 0); /* no check for overflow */ + return a << shift; +} + +#undef SKP_LSHIFT_uint +SKP_INLINE opus_uint32 SKP_LSHIFT_uint(opus_uint32 a, opus_int32 shift){ + opus_uint32 ret; + ret = a << shift; + SKP_assert(shift >= 0); + SKP_assert((opus_int64)ret == ((opus_int64)a) << shift); + return ret; +} + +#undef SKP_RSHIFT8 +SKP_INLINE opus_int8 SKP_RSHIFT8(opus_int8 a, opus_int32 shift){ + SKP_assert(shift >= 0); + SKP_assert(shift < 8); + return a >> shift; +} +#undef SKP_RSHIFT16 +SKP_INLINE opus_int16 SKP_RSHIFT16(opus_int16 a, opus_int32 shift){ + SKP_assert(shift >= 0); + SKP_assert(shift < 16); + return a >> shift; +} +#undef SKP_RSHIFT32 +SKP_INLINE opus_int32 SKP_RSHIFT32(opus_int32 a, opus_int32 shift){ + SKP_assert(shift >= 0); + SKP_assert(shift < 32); + return a >> shift; +} +#undef SKP_RSHIFT64 +SKP_INLINE opus_int64 SKP_RSHIFT64(opus_int64 a, opus_int64 shift){ + SKP_assert(shift >= 0); + SKP_assert(shift <= 63); + return a >> shift; +} + +#undef SKP_RSHIFT_uint +SKP_INLINE opus_uint32 SKP_RSHIFT_uint(opus_uint32 a, opus_int32 shift){ + SKP_assert(shift >= 0); + SKP_assert(shift <= 32); + return a >> shift; +} + +#undef SKP_ADD_LSHIFT +SKP_INLINE opus_int32 SKP_ADD_LSHIFT(opus_int32 a, opus_int32 b, opus_int32 shift){ + opus_int32 ret; + SKP_assert(shift >= 0); + SKP_assert(shift <= 31); + ret = a + (b << shift); + SKP_assert((opus_int64)ret == (opus_int64)a + (((opus_int64)b) << shift)); + return ret; // shift >= 0 +} +#undef SKP_ADD_LSHIFT32 +SKP_INLINE opus_int32 SKP_ADD_LSHIFT32(opus_int32 a, opus_int32 b, opus_int32 shift){ + opus_int32 ret; + SKP_assert(shift >= 0); + SKP_assert(shift <= 31); + ret = a + (b << shift); + SKP_assert((opus_int64)ret == (opus_int64)a + (((opus_int64)b) << shift)); + return ret; // shift >= 0 +} +#undef SKP_ADD_LSHIFT_uint +SKP_INLINE opus_uint32 SKP_ADD_LSHIFT_uint(opus_uint32 a, opus_uint32 b, opus_int32 shift){ + opus_uint32 ret; + SKP_assert(shift >= 0); + SKP_assert(shift <= 32); + ret = a + (b << shift); + SKP_assert((opus_int64)ret == (opus_int64)a + (((opus_int64)b) << shift)); + return ret; // shift >= 0 +} +#undef SKP_ADD_RSHIFT +SKP_INLINE opus_int32 SKP_ADD_RSHIFT(opus_int32 a, opus_int32 b, opus_int32 shift){ + opus_int32 ret; + SKP_assert(shift >= 0); + SKP_assert(shift <= 31); + ret = a + (b >> shift); + SKP_assert((opus_int64)ret == (opus_int64)a + (((opus_int64)b) >> shift)); + return ret; // shift > 0 +} +#undef SKP_ADD_RSHIFT32 +SKP_INLINE opus_int32 SKP_ADD_RSHIFT32(opus_int32 a, opus_int32 b, opus_int32 shift){ + opus_int32 ret; + SKP_assert(shift >= 0); + SKP_assert(shift <= 31); + ret = a + (b >> shift); + SKP_assert((opus_int64)ret == (opus_int64)a + (((opus_int64)b) >> shift)); + return ret; // shift > 0 +} +#undef SKP_ADD_RSHIFT_uint +SKP_INLINE opus_uint32 SKP_ADD_RSHIFT_uint(opus_uint32 a, opus_uint32 b, opus_int32 shift){ + opus_uint32 ret; + SKP_assert(shift >= 0); + SKP_assert(shift <= 32); + ret = a + (b >> shift); + SKP_assert((opus_int64)ret == (opus_int64)a + (((opus_int64)b) >> shift)); + return ret; // shift > 0 +} +#undef SKP_SUB_LSHIFT32 +SKP_INLINE opus_int32 SKP_SUB_LSHIFT32(opus_int32 a, opus_int32 b, opus_int32 shift){ + opus_int32 ret; + SKP_assert(shift >= 0); + SKP_assert(shift <= 31); + ret = a - (b << shift); + SKP_assert((opus_int64)ret == (opus_int64)a - (((opus_int64)b) << shift)); + return ret; // shift >= 0 +} +#undef SKP_SUB_RSHIFT32 +SKP_INLINE opus_int32 SKP_SUB_RSHIFT32(opus_int32 a, opus_int32 b, opus_int32 shift){ + opus_int32 ret; + SKP_assert(shift >= 0); + SKP_assert(shift <= 31); + ret = a - (b >> shift); + SKP_assert((opus_int64)ret == (opus_int64)a - (((opus_int64)b) >> shift)); + return ret; // shift > 0 +} + +#undef SKP_RSHIFT_ROUND +SKP_INLINE opus_int32 SKP_RSHIFT_ROUND(opus_int32 a, opus_int32 shift){ + opus_int32 ret; + SKP_assert(shift > 0); /* the marco definition can't handle a shift of zero */ + SKP_assert(shift < 32); + ret = shift == 1 ? (a >> 1) + (a & 1) : ((a >> (shift - 1)) + 1) >> 1; + SKP_assert((opus_int64)ret == ((opus_int64)a + ((opus_int64)1 << (shift - 1))) >> shift); + return ret; +} + +#undef SKP_RSHIFT_ROUND64 +SKP_INLINE opus_int64 SKP_RSHIFT_ROUND64(opus_int64 a, opus_int32 shift){ + opus_int64 ret; + SKP_assert(shift > 0); /* the marco definition can't handle a shift of zero */ + SKP_assert(shift < 64); + ret = shift == 1 ? (a >> 1) + (a & 1) : ((a >> (shift - 1)) + 1) >> 1; + return ret; +} + +// SKP_abs is used on floats also, so doesn't work... +//#undef SKP_abs +//SKP_INLINE opus_int32 SKP_abs(opus_int32 a){ +// SKP_assert(a != 0x80000000); +// return (((a) > 0) ? (a) : -(a)); // Be careful, SKP_abs returns wrong when input equals to SKP_intXX_MIN +//} + +#undef SKP_abs_int64 +SKP_INLINE opus_int64 SKP_abs_int64(opus_int64 a){ + SKP_assert(a != 0x8000000000000000); + return (((a) > 0) ? (a) : -(a)); // Be careful, SKP_abs returns wrong when input equals to SKP_intXX_MIN +} + +#undef SKP_abs_int32 +SKP_INLINE opus_int32 SKP_abs_int32(opus_int32 a){ + SKP_assert(a != 0x80000000); + return abs(a); +} + +#undef SKP_CHECK_FIT8 +SKP_INLINE opus_int8 SKP_CHECK_FIT8( opus_int64 a ){ + opus_int8 ret; + ret = (opus_int8)a; + SKP_assert( (opus_int64)ret == a ); + return( ret ); +} + +#undef SKP_CHECK_FIT16 +SKP_INLINE opus_int16 SKP_CHECK_FIT16( opus_int64 a ){ + opus_int16 ret; + ret = (opus_int16)a; + SKP_assert( (opus_int64)ret == a ); + return( ret ); +} + +#undef SKP_CHECK_FIT32 +SKP_INLINE opus_int32 SKP_CHECK_FIT32( opus_int64 a ){ + opus_int32 ret; + ret = (opus_int32)a; + SKP_assert( (opus_int64)ret == a ); + return( ret ); +} + +// no checking for SKP_NSHIFT_MUL_32_32 +// no checking for SKP_NSHIFT_MUL_16_16 +// no checking needed for SKP_min +// no checking needed for SKP_max +// no checking needed for SKP_sign + +#endif +#endif diff --git a/silk/silk_NLSF2A.c b/silk/silk_NLSF2A.c index da9cfa8eb..18a5a258a 100644 --- a/silk/silk_NLSF2A.c +++ b/silk/silk_NLSF2A.c @@ -1,171 +1,171 @@ -/*********************************************************************** -Copyright (c) 2006-2011, Skype Limited. All rights reserved. -Redistribution and use in source and binary forms, with or without -modification, (subject to the limitations in the disclaimer below) -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 Skype Limited, nor the names of specific -contributors, may be used to endorse or promote products derived from -this software without specific prior written permission. -NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED -BY THIS LICENSE. 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. -***********************************************************************/ - -/* conversion between prediction filter coefficients and LSFs */ -/* order should be even */ -/* a piecewise linear approximation maps LSF <-> cos(LSF) */ -/* therefore the result is not accurate LSFs, but the two */ -/* functions are accurate inverses of each other */ - -#include "silk_SigProc_FIX.h" -#include "silk_tables.h" - -#define QA 16 - -/* helper function for NLSF2A(..) */ -SKP_INLINE void silk_NLSF2A_find_poly( - opus_int32 *out, /* O intermediate polynomial, QA [dd+1] */ - const opus_int32 *cLSF, /* I vector of interleaved 2*cos(LSFs), QA [d] */ - opus_int dd /* I polynomial order (= 1/2 * filter order) */ -) -{ - opus_int k, n; - opus_int32 ftmp; - - out[0] = SKP_LSHIFT( 1, QA ); - out[1] = -cLSF[0]; - for( k = 1; k < dd; k++ ) { - ftmp = cLSF[2*k]; // QA - out[k+1] = SKP_LSHIFT( out[k-1], 1 ) - (opus_int32)SKP_RSHIFT_ROUND64( SKP_SMULL( ftmp, out[k] ), QA ); - for( n = k; n > 1; n-- ) { - out[n] += out[n-2] - (opus_int32)SKP_RSHIFT_ROUND64( SKP_SMULL( ftmp, out[n-1] ), QA ); - } - out[1] -= ftmp; - } -} - -/* compute whitening filter coefficients from normalized line spectral frequencies */ -void silk_NLSF2A( - opus_int16 *a_Q12, /* O monic whitening filter coefficients in Q12, [ d ] */ - const opus_int16 *NLSF, /* I normalized line spectral frequencies in Q15, [ d ] */ - const opus_int d /* I filter order (should be even) */ -) -{ - opus_int k, i, dd; - opus_int32 cos_LSF_QA[ SILK_MAX_ORDER_LPC ]; - opus_int32 P[ SILK_MAX_ORDER_LPC / 2 + 1 ], Q[ SILK_MAX_ORDER_LPC / 2 + 1 ]; - opus_int32 Ptmp, Qtmp, f_int, f_frac, cos_val, delta; - opus_int32 a32_QA1[ SILK_MAX_ORDER_LPC ]; - opus_int32 maxabs, absval, idx=0, sc_Q16, invGain_Q30; - - SKP_assert( LSF_COS_TAB_SZ_FIX == 128 ); - - /* convert LSFs to 2*cos(LSF), using piecewise linear curve from table */ - for( k = 0; k < d; k++ ) { - SKP_assert(NLSF[k] >= 0 ); - SKP_assert(NLSF[k] <= 32767 ); - - /* f_int on a scale 0-127 (rounded down) */ - f_int = SKP_RSHIFT( NLSF[k], 15 - 7 ); - - /* f_frac, range: 0..255 */ - f_frac = NLSF[k] - SKP_LSHIFT( f_int, 15 - 7 ); - - SKP_assert(f_int >= 0); - SKP_assert(f_int < LSF_COS_TAB_SZ_FIX ); - - /* Read start and end value from table */ - cos_val = silk_LSFCosTab_FIX_Q12[ f_int ]; /* Q12 */ - delta = silk_LSFCosTab_FIX_Q12[ f_int + 1 ] - cos_val; /* Q12, with a range of 0..200 */ - - /* Linear interpolation */ - cos_LSF_QA[k] = SKP_RSHIFT_ROUND( SKP_LSHIFT( cos_val, 8 ) + SKP_MUL( delta, f_frac ), 20 - QA ); /* QA */ - } - - dd = SKP_RSHIFT( d, 1 ); - - /* generate even and odd polynomials using convolution */ - silk_NLSF2A_find_poly( P, &cos_LSF_QA[ 0 ], dd ); - silk_NLSF2A_find_poly( Q, &cos_LSF_QA[ 1 ], dd ); - - /* convert even and odd polynomials to opus_int32 Q12 filter coefs */ - for( k = 0; k < dd; k++ ) { - Ptmp = P[ k+1 ] + P[ k ]; - Qtmp = Q[ k+1 ] - Q[ k ]; - - /* the Ptmp and Qtmp values at this stage need to fit in int32 */ - a32_QA1[ k ] = -Qtmp - Ptmp; /* QA+1 */ - a32_QA1[ d-k-1 ] = Qtmp - Ptmp; /* QA+1 */ - } - - /* Limit the maximum absolute value of the prediction coefficients, so that they'll fit in int16 */ - for( i = 0; i < 10; i++ ) { - /* Find maximum absolute value and its index */ - maxabs = 0; - for( k = 0; k < d; k++ ) { - absval = SKP_abs( a32_QA1[k] ); - if( absval > maxabs ) { - maxabs = absval; - idx = k; - } - } - maxabs = SKP_RSHIFT_ROUND( maxabs, QA + 1 - 12 ); /* QA+1 -> Q12 */ - - if( maxabs > SKP_int16_MAX ) { - /* Reduce magnitude of prediction coefficients */ - maxabs = SKP_min( maxabs, 163838 ); /* ( SKP_int32_MAX >> 14 ) + SKP_int16_MAX = 163838 */ - sc_Q16 = SILK_FIX_CONST( 0.999, 16 ) - SKP_DIV32( SKP_LSHIFT( maxabs - SKP_int16_MAX, 14 ), - SKP_RSHIFT32( SKP_MUL( maxabs, idx + 1), 2 ) ); - silk_bwexpander_32( a32_QA1, d, sc_Q16 ); - } else { - break; - } - } - - if( i == 10 ) { - /* Reached the last iteration, clip the coefficients */ - for( k = 0; k < d; k++ ) { - a_Q12[ k ] = (opus_int16)SKP_SAT16( SKP_RSHIFT_ROUND( a32_QA1[ k ], QA + 1 - 12 ) ); /* QA+1 -> Q12 */ - a32_QA1[ k ] = SKP_LSHIFT( (opus_int32)a_Q12[ k ], QA + 1 - 12 ); - } - } else { - for( k = 0; k < d; k++ ) { - a_Q12[ k ] = (opus_int16)SKP_RSHIFT_ROUND( a32_QA1[ k ], QA + 1 - 12 ); /* QA+1 -> Q12 */ - } - } - - for( i = 1; i < MAX_LPC_STABILIZE_ITERATIONS; i++ ) { - if( silk_LPC_inverse_pred_gain( &invGain_Q30, a_Q12, d ) == 1 ) { - /* 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 - SKP_SMULBB( 9 + i, i ) ); /* 10_Q16 = 0.00015 */ - for( k = 0; k < d; k++ ) { - a_Q12[ k ] = (opus_int16)SKP_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; - } - } -} - +/*********************************************************************** +Copyright (c) 2006-2011, Skype Limited. All rights reserved. +Redistribution and use in source and binary forms, with or without +modification, (subject to the limitations in the disclaimer below) +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 Skype Limited, nor the names of specific +contributors, may be used to endorse or promote products derived from +this software without specific prior written permission. +NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED +BY THIS LICENSE. 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. +***********************************************************************/ + +/* conversion between prediction filter coefficients and LSFs */ +/* order should be even */ +/* a piecewise linear approximation maps LSF <-> cos(LSF) */ +/* therefore the result is not accurate LSFs, but the two */ +/* functions are accurate inverses of each other */ + +#include "silk_SigProc_FIX.h" +#include "silk_tables.h" + +#define QA 16 + +/* helper function for NLSF2A(..) */ +SKP_INLINE void silk_NLSF2A_find_poly( + opus_int32 *out, /* O intermediate polynomial, QA [dd+1] */ + const opus_int32 *cLSF, /* I vector of interleaved 2*cos(LSFs), QA [d] */ + opus_int dd /* I polynomial order (= 1/2 * filter order) */ +) +{ + opus_int k, n; + opus_int32 ftmp; + + out[0] = SKP_LSHIFT( 1, QA ); + out[1] = -cLSF[0]; + for( k = 1; k < dd; k++ ) { + ftmp = cLSF[2*k]; // QA + out[k+1] = SKP_LSHIFT( out[k-1], 1 ) - (opus_int32)SKP_RSHIFT_ROUND64( SKP_SMULL( ftmp, out[k] ), QA ); + for( n = k; n > 1; n-- ) { + out[n] += out[n-2] - (opus_int32)SKP_RSHIFT_ROUND64( SKP_SMULL( ftmp, out[n-1] ), QA ); + } + out[1] -= ftmp; + } +} + +/* compute whitening filter coefficients from normalized line spectral frequencies */ +void silk_NLSF2A( + opus_int16 *a_Q12, /* O monic whitening filter coefficients in Q12, [ d ] */ + const opus_int16 *NLSF, /* I normalized line spectral frequencies in Q15, [ d ] */ + const opus_int d /* I filter order (should be even) */ +) +{ + opus_int k, i, dd; + opus_int32 cos_LSF_QA[ SILK_MAX_ORDER_LPC ]; + opus_int32 P[ SILK_MAX_ORDER_LPC / 2 + 1 ], Q[ SILK_MAX_ORDER_LPC / 2 + 1 ]; + opus_int32 Ptmp, Qtmp, f_int, f_frac, cos_val, delta; + opus_int32 a32_QA1[ SILK_MAX_ORDER_LPC ]; + opus_int32 maxabs, absval, idx=0, sc_Q16, invGain_Q30; + + SKP_assert( LSF_COS_TAB_SZ_FIX == 128 ); + + /* convert LSFs to 2*cos(LSF), using piecewise linear curve from table */ + for( k = 0; k < d; k++ ) { + SKP_assert(NLSF[k] >= 0 ); + SKP_assert(NLSF[k] <= 32767 ); + + /* f_int on a scale 0-127 (rounded down) */ + f_int = SKP_RSHIFT( NLSF[k], 15 - 7 ); + + /* f_frac, range: 0..255 */ + f_frac = NLSF[k] - SKP_LSHIFT( f_int, 15 - 7 ); + + SKP_assert(f_int >= 0); + SKP_assert(f_int < LSF_COS_TAB_SZ_FIX ); + + /* Read start and end value from table */ + cos_val = silk_LSFCosTab_FIX_Q12[ f_int ]; /* Q12 */ + delta = silk_LSFCosTab_FIX_Q12[ f_int + 1 ] - cos_val; /* Q12, with a range of 0..200 */ + + /* Linear interpolation */ + cos_LSF_QA[k] = SKP_RSHIFT_ROUND( SKP_LSHIFT( cos_val, 8 ) + SKP_MUL( delta, f_frac ), 20 - QA ); /* QA */ + } + + dd = SKP_RSHIFT( d, 1 ); + + /* generate even and odd polynomials using convolution */ + silk_NLSF2A_find_poly( P, &cos_LSF_QA[ 0 ], dd ); + silk_NLSF2A_find_poly( Q, &cos_LSF_QA[ 1 ], dd ); + + /* convert even and odd polynomials to opus_int32 Q12 filter coefs */ + for( k = 0; k < dd; k++ ) { + Ptmp = P[ k+1 ] + P[ k ]; + Qtmp = Q[ k+1 ] - Q[ k ]; + + /* the Ptmp and Qtmp values at this stage need to fit in int32 */ + a32_QA1[ k ] = -Qtmp - Ptmp; /* QA+1 */ + a32_QA1[ d-k-1 ] = Qtmp - Ptmp; /* QA+1 */ + } + + /* Limit the maximum absolute value of the prediction coefficients, so that they'll fit in int16 */ + for( i = 0; i < 10; i++ ) { + /* Find maximum absolute value and its index */ + maxabs = 0; + for( k = 0; k < d; k++ ) { + absval = SKP_abs( a32_QA1[k] ); + if( absval > maxabs ) { + maxabs = absval; + idx = k; + } + } + maxabs = SKP_RSHIFT_ROUND( maxabs, QA + 1 - 12 ); /* QA+1 -> Q12 */ + + if( maxabs > SKP_int16_MAX ) { + /* Reduce magnitude of prediction coefficients */ + maxabs = SKP_min( maxabs, 163838 ); /* ( SKP_int32_MAX >> 14 ) + SKP_int16_MAX = 163838 */ + sc_Q16 = SILK_FIX_CONST( 0.999, 16 ) - SKP_DIV32( SKP_LSHIFT( maxabs - SKP_int16_MAX, 14 ), + SKP_RSHIFT32( SKP_MUL( maxabs, idx + 1), 2 ) ); + silk_bwexpander_32( a32_QA1, d, sc_Q16 ); + } else { + break; + } + } + + if( i == 10 ) { + /* Reached the last iteration, clip the coefficients */ + for( k = 0; k < d; k++ ) { + a_Q12[ k ] = (opus_int16)SKP_SAT16( SKP_RSHIFT_ROUND( a32_QA1[ k ], QA + 1 - 12 ) ); /* QA+1 -> Q12 */ + a32_QA1[ k ] = SKP_LSHIFT( (opus_int32)a_Q12[ k ], QA + 1 - 12 ); + } + } else { + for( k = 0; k < d; k++ ) { + a_Q12[ k ] = (opus_int16)SKP_RSHIFT_ROUND( a32_QA1[ k ], QA + 1 - 12 ); /* QA+1 -> Q12 */ + } + } + + for( i = 1; i < MAX_LPC_STABILIZE_ITERATIONS; i++ ) { + if( silk_LPC_inverse_pred_gain( &invGain_Q30, a_Q12, d ) == 1 ) { + /* 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 - SKP_SMULBB( 9 + i, i ) ); /* 10_Q16 = 0.00015 */ + for( k = 0; k < d; k++ ) { + a_Q12[ k ] = (opus_int16)SKP_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; + } + } +} + diff --git a/silk/silk_NLSF_VQ.c b/silk/silk_NLSF_VQ.c index cc6c47c49..380a423b1 100644 --- a/silk/silk_NLSF_VQ.c +++ b/silk/silk_NLSF_VQ.c @@ -1,64 +1,64 @@ -/*********************************************************************** -Copyright (c) 2006-2011, Skype Limited. All rights reserved. -Redistribution and use in source and binary forms, with or without -modification, (subject to the limitations in the disclaimer below) -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 Skype Limited, nor the names of specific -contributors, may be used to endorse or promote products derived from -this software without specific prior written permission. -NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED -BY THIS LICENSE. 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. -***********************************************************************/ - -#include "silk_main.h" - -/* Compute quantization errors for an LPC_order element input vector for a VQ codebook */ -void silk_NLSF_VQ( - opus_int32 err_Q26[], /* O Quantization errors [K] */ - const opus_int16 in_Q15[], /* I Input vectors to be quantized [LPC_order] */ - const opus_uint8 pCB_Q8[], /* I Codebook vectors [K*LPC_order] */ - const opus_int K, /* I Number of codebook vectors */ - const opus_int LPC_order /* I Number of LPCs */ -) -{ - opus_int i, m; - opus_int32 diff_Q15, sum_error_Q30, sum_error_Q26; - - SKP_assert( LPC_order <= 16 ); - SKP_assert( ( LPC_order & 1 ) == 0 ); - - /* Loop over codebook */ - for( i = 0; i < K; i++ ) { - sum_error_Q26 = 0; - for( m = 0; m < LPC_order; m += 2 ) { - /* Compute weighted squared quantization error for index m */ - diff_Q15 = SKP_SUB_LSHIFT32( in_Q15[ m ], ( opus_int32 )*pCB_Q8++, 7 ); // range: [ -32767 : 32767 ] - sum_error_Q30 = SKP_SMULBB( diff_Q15, diff_Q15 ); - - /* Compute weighted squared quantization error for index m + 1 */ - diff_Q15 = SKP_SUB_LSHIFT32( in_Q15[m + 1], ( opus_int32 )*pCB_Q8++, 7 ); // range: [ -32767 : 32767 ] - sum_error_Q30 = SKP_SMLABB( sum_error_Q30, diff_Q15, diff_Q15 ); - - sum_error_Q26 = SKP_ADD_RSHIFT32( sum_error_Q26, sum_error_Q30, 4 ); - - SKP_assert( sum_error_Q26 >= 0 ); - SKP_assert( sum_error_Q30 >= 0 ); - } - err_Q26[ i ] = sum_error_Q26; - } -} +/*********************************************************************** +Copyright (c) 2006-2011, Skype Limited. All rights reserved. +Redistribution and use in source and binary forms, with or without +modification, (subject to the limitations in the disclaimer below) +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 Skype Limited, nor the names of specific +contributors, may be used to endorse or promote products derived from +this software without specific prior written permission. +NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED +BY THIS LICENSE. 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. +***********************************************************************/ + +#include "silk_main.h" + +/* Compute quantization errors for an LPC_order element input vector for a VQ codebook */ +void silk_NLSF_VQ( + opus_int32 err_Q26[], /* O Quantization errors [K] */ + const opus_int16 in_Q15[], /* I Input vectors to be quantized [LPC_order] */ + const opus_uint8 pCB_Q8[], /* I Codebook vectors [K*LPC_order] */ + const opus_int K, /* I Number of codebook vectors */ + const opus_int LPC_order /* I Number of LPCs */ +) +{ + opus_int i, m; + opus_int32 diff_Q15, sum_error_Q30, sum_error_Q26; + + SKP_assert( LPC_order <= 16 ); + SKP_assert( ( LPC_order & 1 ) == 0 ); + + /* Loop over codebook */ + for( i = 0; i < K; i++ ) { + sum_error_Q26 = 0; + for( m = 0; m < LPC_order; m += 2 ) { + /* Compute weighted squared quantization error for index m */ + diff_Q15 = SKP_SUB_LSHIFT32( in_Q15[ m ], ( opus_int32 )*pCB_Q8++, 7 ); // range: [ -32767 : 32767 ] + sum_error_Q30 = SKP_SMULBB( diff_Q15, diff_Q15 ); + + /* Compute weighted squared quantization error for index m + 1 */ + diff_Q15 = SKP_SUB_LSHIFT32( in_Q15[m + 1], ( opus_int32 )*pCB_Q8++, 7 ); // range: [ -32767 : 32767 ] + sum_error_Q30 = SKP_SMLABB( sum_error_Q30, diff_Q15, diff_Q15 ); + + sum_error_Q26 = SKP_ADD_RSHIFT32( sum_error_Q26, sum_error_Q30, 4 ); + + SKP_assert( sum_error_Q26 >= 0 ); + SKP_assert( sum_error_Q30 >= 0 ); + } + err_Q26[ i ] = sum_error_Q26; + } +} diff --git a/silk/silk_NLSF_VQ_weights_laroia.c b/silk/silk_NLSF_VQ_weights_laroia.c index 82d682536..91ada7d75 100644 --- a/silk/silk_NLSF_VQ_weights_laroia.c +++ b/silk/silk_NLSF_VQ_weights_laroia.c @@ -1,76 +1,76 @@ -/*********************************************************************** -Copyright (c) 2006-2011, Skype Limited. All rights reserved. -Redistribution and use in source and binary forms, with or without -modification, (subject to the limitations in the disclaimer below) -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 Skype Limited, nor the names of specific -contributors, may be used to endorse or promote products derived from -this software without specific prior written permission. -NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED -BY THIS LICENSE. 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. -***********************************************************************/ - -#include "silk_define.h" -#include "silk_SigProc_FIX.h" - -/* -R. Laroia, N. Phamdo and N. Farvardin, "Robust and Efficient Quantization of Speech LSP -Parameters Using Structured Vector Quantization", Proc. IEEE Int. Conf. Acoust., Speech, -Signal Processing, pp. 641-644, 1991. -*/ - -/* Laroia low complexity NLSF weights */ -void silk_NLSF_VQ_weights_laroia( - opus_int16 *pNLSFW_Q_OUT, /* O: Pointer to input vector weights [D x 1] */ - const opus_int16 *pNLSF_Q15, /* I: Pointer to input vector [D x 1] */ - const opus_int D /* I: Input vector dimension (even) */ -) -{ - opus_int k; - opus_int32 tmp1_int, tmp2_int; - - SKP_assert( D > 0 ); - SKP_assert( ( D & 1 ) == 0 ); - - /* First value */ - tmp1_int = SKP_max_int( pNLSF_Q15[ 0 ], 1 ); - tmp1_int = SKP_DIV32_16( 1 << ( 15 + NLSF_W_Q ), tmp1_int ); - tmp2_int = SKP_max_int( pNLSF_Q15[ 1 ] - pNLSF_Q15[ 0 ], 1 ); - tmp2_int = SKP_DIV32_16( 1 << ( 15 + NLSF_W_Q ), tmp2_int ); - pNLSFW_Q_OUT[ 0 ] = (opus_int16)SKP_min_int( tmp1_int + tmp2_int, SKP_int16_MAX ); - SKP_assert( pNLSFW_Q_OUT[ 0 ] > 0 ); - - /* Main loop */ - for( k = 1; k < D - 1; k += 2 ) { - tmp1_int = SKP_max_int( pNLSF_Q15[ k + 1 ] - pNLSF_Q15[ k ], 1 ); - tmp1_int = SKP_DIV32_16( 1 << ( 15 + NLSF_W_Q ), tmp1_int ); - pNLSFW_Q_OUT[ k ] = (opus_int16)SKP_min_int( tmp1_int + tmp2_int, SKP_int16_MAX ); - SKP_assert( pNLSFW_Q_OUT[ k ] > 0 ); - - tmp2_int = SKP_max_int( pNLSF_Q15[ k + 2 ] - pNLSF_Q15[ k + 1 ], 1 ); - tmp2_int = SKP_DIV32_16( 1 << ( 15 + NLSF_W_Q ), tmp2_int ); - pNLSFW_Q_OUT[ k + 1 ] = (opus_int16)SKP_min_int( tmp1_int + tmp2_int, SKP_int16_MAX ); - SKP_assert( pNLSFW_Q_OUT[ k + 1 ] > 0 ); - } - - /* Last value */ - tmp1_int = SKP_max_int( ( 1 << 15 ) - pNLSF_Q15[ D - 1 ], 1 ); - tmp1_int = SKP_DIV32_16( 1 << ( 15 + NLSF_W_Q ), tmp1_int ); - pNLSFW_Q_OUT[ D - 1 ] = (opus_int16)SKP_min_int( tmp1_int + tmp2_int, SKP_int16_MAX ); - SKP_assert( pNLSFW_Q_OUT[ D - 1 ] > 0 ); -} +/*********************************************************************** +Copyright (c) 2006-2011, Skype Limited. All rights reserved. +Redistribution and use in source and binary forms, with or without +modification, (subject to the limitations in the disclaimer below) +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 Skype Limited, nor the names of specific +contributors, may be used to endorse or promote products derived from +this software without specific prior written permission. +NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED +BY THIS LICENSE. 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. +***********************************************************************/ + +#include "silk_define.h" +#include "silk_SigProc_FIX.h" + +/* +R. Laroia, N. Phamdo and N. Farvardin, "Robust and Efficient Quantization of Speech LSP +Parameters Using Structured Vector Quantization", Proc. IEEE Int. Conf. Acoust., Speech, +Signal Processing, pp. 641-644, 1991. +*/ + +/* Laroia low complexity NLSF weights */ +void silk_NLSF_VQ_weights_laroia( + opus_int16 *pNLSFW_Q_OUT, /* O: Pointer to input vector weights [D x 1] */ + const opus_int16 *pNLSF_Q15, /* I: Pointer to input vector [D x 1] */ + const opus_int D /* I: Input vector dimension (even) */ +) +{ + opus_int k; + opus_int32 tmp1_int, tmp2_int; + + SKP_assert( D > 0 ); + SKP_assert( ( D & 1 ) == 0 ); + + /* First value */ + tmp1_int = SKP_max_int( pNLSF_Q15[ 0 ], 1 ); + tmp1_int = SKP_DIV32_16( 1 << ( 15 + NLSF_W_Q ), tmp1_int ); + tmp2_int = SKP_max_int( pNLSF_Q15[ 1 ] - pNLSF_Q15[ 0 ], 1 ); + tmp2_int = SKP_DIV32_16( 1 << ( 15 + NLSF_W_Q ), tmp2_int ); + pNLSFW_Q_OUT[ 0 ] = (opus_int16)SKP_min_int( tmp1_int + tmp2_int, SKP_int16_MAX ); + SKP_assert( pNLSFW_Q_OUT[ 0 ] > 0 ); + + /* Main loop */ + for( k = 1; k < D - 1; k += 2 ) { + tmp1_int = SKP_max_int( pNLSF_Q15[ k + 1 ] - pNLSF_Q15[ k ], 1 ); + tmp1_int = SKP_DIV32_16( 1 << ( 15 + NLSF_W_Q ), tmp1_int ); + pNLSFW_Q_OUT[ k ] = (opus_int16)SKP_min_int( tmp1_int + tmp2_int, SKP_int16_MAX ); + SKP_assert( pNLSFW_Q_OUT[ k ] > 0 ); + + tmp2_int = SKP_max_int( pNLSF_Q15[ k + 2 ] - pNLSF_Q15[ k + 1 ], 1 ); + tmp2_int = SKP_DIV32_16( 1 << ( 15 + NLSF_W_Q ), tmp2_int ); + pNLSFW_Q_OUT[ k + 1 ] = (opus_int16)SKP_min_int( tmp1_int + tmp2_int, SKP_int16_MAX ); + SKP_assert( pNLSFW_Q_OUT[ k + 1 ] > 0 ); + } + + /* Last value */ + tmp1_int = SKP_max_int( ( 1 << 15 ) - pNLSF_Q15[ D - 1 ], 1 ); + tmp1_int = SKP_DIV32_16( 1 << ( 15 + NLSF_W_Q ), tmp1_int ); + pNLSFW_Q_OUT[ D - 1 ] = (opus_int16)SKP_min_int( tmp1_int + tmp2_int, SKP_int16_MAX ); + SKP_assert( pNLSFW_Q_OUT[ D - 1 ] > 0 ); +} diff --git a/silk/silk_NLSF_decode.c b/silk/silk_NLSF_decode.c index 214d22bd1..a6e06bfc0 100644 --- a/silk/silk_NLSF_decode.c +++ b/silk/silk_NLSF_decode.c @@ -1,97 +1,97 @@ -/*********************************************************************** -Copyright (c) 2006-2011, Skype Limited. All rights reserved. -Redistribution and use in source and binary forms, with or without -modification, (subject to the limitations in the disclaimer below) -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 Skype Limited, nor the names of specific -contributors, may be used to endorse or promote products derived from -this software without specific prior written permission. -NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED -BY THIS LICENSE. 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. -***********************************************************************/ - -#include "silk_main.h" - -/* Predictive dequantizer for NLSF residuals */ -void silk_NLSF_residual_dequant( /* O Returns RD value in Q30 */ - opus_int16 x_Q10[], /* O Output [ order ] */ - const opus_int8 indices[], /* I Quantization indices [ order ] */ - const opus_uint8 pred_coef_Q8[], /* I Backward predictor coefs [ order ] */ - const opus_int quant_step_size_Q16, /* I Quantization step size */ - const opus_int16 order /* I Number of input values */ -) -{ - opus_int i, out_Q10, pred_Q10; - - out_Q10 = 0; - for( i = order-1; i >= 0; i-- ) { - pred_Q10 = SKP_RSHIFT( SKP_SMULBB( out_Q10, (opus_int16)pred_coef_Q8[ i ] ), 8 ); - out_Q10 = SKP_LSHIFT( indices[ i ], 10 ); - if( out_Q10 > 0 ) { - out_Q10 = SKP_SUB16( out_Q10, SILK_FIX_CONST( NLSF_QUANT_LEVEL_ADJ, 10 ) ); - } else if( out_Q10 < 0 ) { - out_Q10 = SKP_ADD16( out_Q10, SILK_FIX_CONST( NLSF_QUANT_LEVEL_ADJ, 10 ) ); - } - out_Q10 = SKP_SMLAWB( pred_Q10, out_Q10, quant_step_size_Q16 ); - x_Q10[ i ] = out_Q10; - } -} - - -/***********************/ -/* NLSF vector decoder */ -/***********************/ -void silk_NLSF_decode( - opus_int16 *pNLSF_Q15, /* O Quantized NLSF vector [ LPC_ORDER ] */ - opus_int8 *NLSFIndices, /* I Codebook path vector [ LPC_ORDER + 1 ] */ - const silk_NLSF_CB_struct *psNLSF_CB /* I Codebook object */ -) -{ - opus_int i; - opus_uint8 pred_Q8[ MAX_LPC_ORDER ]; - opus_int16 ec_ix[ MAX_LPC_ORDER ]; - opus_int16 res_Q10[ MAX_LPC_ORDER ]; - opus_int16 W_tmp_QW[ MAX_LPC_ORDER ]; - opus_int32 W_tmp_Q9, NLSF_Q15_tmp; - const opus_uint8 *pCB_element; - - /* Decode first stage */ - pCB_element = &psNLSF_CB->CB1_NLSF_Q8[ NLSFIndices[ 0 ] * psNLSF_CB->order ]; - for( i = 0; i < psNLSF_CB->order; i++ ) { - pNLSF_Q15[ i ] = SKP_LSHIFT( ( opus_int16 )pCB_element[ i ], 7 ); - } - - /* Unpack entropy table indices and predictor for current CB1 index */ - silk_NLSF_unpack( ec_ix, pred_Q8, psNLSF_CB, NLSFIndices[ 0 ] ); - - /* Trellis dequantizer */ - silk_NLSF_residual_dequant( res_Q10, &NLSFIndices[ 1 ], pred_Q8, psNLSF_CB->quantStepSize_Q16, psNLSF_CB->order ); - - /* Weights from codebook vector */ - silk_NLSF_VQ_weights_laroia( W_tmp_QW, pNLSF_Q15, psNLSF_CB->order ); - - /* Apply inverse square-rooted weights and add to output */ - for( i = 0; i < psNLSF_CB->order; i++ ) { - W_tmp_Q9 = silk_SQRT_APPROX( SKP_LSHIFT( ( opus_int32 )W_tmp_QW[ i ], 18 - NLSF_W_Q ) ); - NLSF_Q15_tmp = SKP_ADD32( pNLSF_Q15[ i ], SKP_DIV32_16( SKP_LSHIFT( ( opus_int32 )res_Q10[ i ], 14 ), W_tmp_Q9 ) ); - pNLSF_Q15[ i ] = (opus_int16)SKP_LIMIT( NLSF_Q15_tmp, 0, 32767 ); - } - - /* NLSF stabilization */ - silk_NLSF_stabilize( pNLSF_Q15, psNLSF_CB->deltaMin_Q15, psNLSF_CB->order ); -} +/*********************************************************************** +Copyright (c) 2006-2011, Skype Limited. All rights reserved. +Redistribution and use in source and binary forms, with or without +modification, (subject to the limitations in the disclaimer below) +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 Skype Limited, nor the names of specific +contributors, may be used to endorse or promote products derived from +this software without specific prior written permission. +NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED +BY THIS LICENSE. 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. +***********************************************************************/ + +#include "silk_main.h" + +/* Predictive dequantizer for NLSF residuals */ +void silk_NLSF_residual_dequant( /* O Returns RD value in Q30 */ + opus_int16 x_Q10[], /* O Output [ order ] */ + const opus_int8 indices[], /* I Quantization indices [ order ] */ + const opus_uint8 pred_coef_Q8[], /* I Backward predictor coefs [ order ] */ + const opus_int quant_step_size_Q16, /* I Quantization step size */ + const opus_int16 order /* I Number of input values */ +) +{ + opus_int i, out_Q10, pred_Q10; + + out_Q10 = 0; + for( i = order-1; i >= 0; i-- ) { + pred_Q10 = SKP_RSHIFT( SKP_SMULBB( out_Q10, (opus_int16)pred_coef_Q8[ i ] ), 8 ); + out_Q10 = SKP_LSHIFT( indices[ i ], 10 ); + if( out_Q10 > 0 ) { + out_Q10 = SKP_SUB16( out_Q10, SILK_FIX_CONST( NLSF_QUANT_LEVEL_ADJ, 10 ) ); + } else if( out_Q10 < 0 ) { + out_Q10 = SKP_ADD16( out_Q10, SILK_FIX_CONST( NLSF_QUANT_LEVEL_ADJ, 10 ) ); + } + out_Q10 = SKP_SMLAWB( pred_Q10, out_Q10, quant_step_size_Q16 ); + x_Q10[ i ] = out_Q10; + } +} + + +/***********************/ +/* NLSF vector decoder */ +/***********************/ +void silk_NLSF_decode( + opus_int16 *pNLSF_Q15, /* O Quantized NLSF vector [ LPC_ORDER ] */ + opus_int8 *NLSFIndices, /* I Codebook path vector [ LPC_ORDER + 1 ] */ + const silk_NLSF_CB_struct *psNLSF_CB /* I Codebook object */ +) +{ + opus_int i; + opus_uint8 pred_Q8[ MAX_LPC_ORDER ]; + opus_int16 ec_ix[ MAX_LPC_ORDER ]; + opus_int16 res_Q10[ MAX_LPC_ORDER ]; + opus_int16 W_tmp_QW[ MAX_LPC_ORDER ]; + opus_int32 W_tmp_Q9, NLSF_Q15_tmp; + const opus_uint8 *pCB_element; + + /* Decode first stage */ + pCB_element = &psNLSF_CB->CB1_NLSF_Q8[ NLSFIndices[ 0 ] * psNLSF_CB->order ]; + for( i = 0; i < psNLSF_CB->order; i++ ) { + pNLSF_Q15[ i ] = SKP_LSHIFT( ( opus_int16 )pCB_element[ i ], 7 ); + } + + /* Unpack entropy table indices and predictor for current CB1 index */ + silk_NLSF_unpack( ec_ix, pred_Q8, psNLSF_CB, NLSFIndices[ 0 ] ); + + /* Trellis dequantizer */ + silk_NLSF_residual_dequant( res_Q10, &NLSFIndices[ 1 ], pred_Q8, psNLSF_CB->quantStepSize_Q16, psNLSF_CB->order ); + + /* Weights from codebook vector */ + silk_NLSF_VQ_weights_laroia( W_tmp_QW, pNLSF_Q15, psNLSF_CB->order ); + + /* Apply inverse square-rooted weights and add to output */ + for( i = 0; i < psNLSF_CB->order; i++ ) { + W_tmp_Q9 = silk_SQRT_APPROX( SKP_LSHIFT( ( opus_int32 )W_tmp_QW[ i ], 18 - NLSF_W_Q ) ); + NLSF_Q15_tmp = SKP_ADD32( pNLSF_Q15[ i ], SKP_DIV32_16( SKP_LSHIFT( ( opus_int32 )res_Q10[ i ], 14 ), W_tmp_Q9 ) ); + pNLSF_Q15[ i ] = (opus_int16)SKP_LIMIT( NLSF_Q15_tmp, 0, 32767 ); + } + + /* NLSF stabilization */ + silk_NLSF_stabilize( pNLSF_Q15, psNLSF_CB->deltaMin_Q15, psNLSF_CB->order ); +} diff --git a/silk/silk_NLSF_del_dec_quant.c b/silk/silk_NLSF_del_dec_quant.c index aeb66dc56..8d05680bc 100644 --- a/silk/silk_NLSF_del_dec_quant.c +++ b/silk/silk_NLSF_del_dec_quant.c @@ -1,201 +1,201 @@ -/*********************************************************************** -Copyright (c) 2006-2011, Skype Limited. All rights reserved. -Redistribution and use in source and binary forms, with or without -modification, (subject to the limitations in the disclaimer below) -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 Skype Limited, nor the names of specific -contributors, may be used to endorse or promote products derived from -this software without specific prior written permission. -NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED -BY THIS LICENSE. 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. -***********************************************************************/ - -#include "silk_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 ] */ - 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 ] */ - const opus_int16 ec_ix[], /* I Indices to entropy coding tables [ order ] */ - const opus_uint8 ec_rates_Q5[], /* I Rates [] */ - const opus_int quant_step_size_Q16, /* I Quantization step size */ - const opus_int16 inv_quant_step_size_Q6, /* I Inverse quantization step size */ - const opus_int32 mu_Q20, /* I R/D tradeoff */ - const opus_int16 order /* I Number of input values */ -) -{ - 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_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 ]; - opus_int32 RD_Q25[ 2 * NLSF_QUANT_DEL_DEC_STATES ]; - opus_int32 RD_min_Q25[ NLSF_QUANT_DEL_DEC_STATES ]; - opus_int32 RD_max_Q25[ NLSF_QUANT_DEL_DEC_STATES ]; - const opus_uint8 *rates_Q5; - - SKP_assert( (NLSF_QUANT_DEL_DEC_STATES & (NLSF_QUANT_DEL_DEC_STATES-1)) == 0 ); /* must be power of two */ - - nStates = 1; - RD_Q25[ 0 ] = 0; - prev_out_Q10[ 0 ] = 0; - for( i = order - 1; ; i-- ) { - rates_Q5 = &ec_rates_Q5[ ec_ix[ i ] ]; - pred_coef_Q16 = SKP_LSHIFT( (opus_int32)pred_coef_Q8[ i ], 8 ); - in_Q10 = x_Q10[ i ]; - for( j = 0; j < nStates; j++ ) { - pred_Q10 = SKP_SMULWB( pred_coef_Q16, prev_out_Q10[ j ] ); - res_Q10 = SKP_SUB16( in_Q10, pred_Q10 ); - ind_tmp = SKP_SMULWB( inv_quant_step_size_Q6, res_Q10 ); - ind_tmp = SKP_LIMIT( ind_tmp, -NLSF_QUANT_MAX_AMPLITUDE_EXT, NLSF_QUANT_MAX_AMPLITUDE_EXT-1 ); - ind[ j ][ i ] = (opus_int8)ind_tmp; - - /* compute outputs for ind_tmp and ind_tmp + 1 */ - out0_Q10 = SKP_LSHIFT( ind_tmp, 10 ); - out1_Q10 = SKP_ADD16( out0_Q10, 1024 ); - if( ind_tmp > 0 ) { - out0_Q10 = SKP_SUB16( out0_Q10, SILK_FIX_CONST( NLSF_QUANT_LEVEL_ADJ, 10 ) ); - out1_Q10 = SKP_SUB16( out1_Q10, SILK_FIX_CONST( NLSF_QUANT_LEVEL_ADJ, 10 ) ); - } else if( ind_tmp == 0 ) { - out1_Q10 = SKP_SUB16( out1_Q10, SILK_FIX_CONST( NLSF_QUANT_LEVEL_ADJ, 10 ) ); - } else if( ind_tmp == -1 ) { - out0_Q10 = SKP_ADD16( out0_Q10, SILK_FIX_CONST( NLSF_QUANT_LEVEL_ADJ, 10 ) ); - } else { - out0_Q10 = SKP_ADD16( out0_Q10, SILK_FIX_CONST( NLSF_QUANT_LEVEL_ADJ, 10 ) ); - out1_Q10 = SKP_ADD16( out1_Q10, SILK_FIX_CONST( NLSF_QUANT_LEVEL_ADJ, 10 ) ); - } - out0_Q10 = SKP_SMULWB( out0_Q10, quant_step_size_Q16 ); - out1_Q10 = SKP_SMULWB( out1_Q10, quant_step_size_Q16 ); - out0_Q10 = SKP_ADD16( out0_Q10, pred_Q10 ); - out1_Q10 = SKP_ADD16( out1_Q10, pred_Q10 ); - prev_out_Q10[ j ] = out0_Q10; - prev_out_Q10[ j + nStates ] = out1_Q10; - - /* compute RD for ind_tmp and ind_tmp + 1 */ - if( ind_tmp + 1 >= NLSF_QUANT_MAX_AMPLITUDE ) { - if( ind_tmp + 1 == NLSF_QUANT_MAX_AMPLITUDE ) { - rate0_Q5 = rates_Q5[ ind_tmp + NLSF_QUANT_MAX_AMPLITUDE ]; - rate1_Q5 = 280; - } else { - rate0_Q5 = SKP_SMLABB( 280 - 43 * NLSF_QUANT_MAX_AMPLITUDE, 43, ind_tmp ); - rate1_Q5 = SKP_ADD16( rate0_Q5, 43 ); - } - } else if( ind_tmp <= -NLSF_QUANT_MAX_AMPLITUDE ) { - if( ind_tmp == -NLSF_QUANT_MAX_AMPLITUDE ) { - rate0_Q5 = 280; - rate1_Q5 = rates_Q5[ ind_tmp + 1 + NLSF_QUANT_MAX_AMPLITUDE ]; - } else { - rate0_Q5 = SKP_SMLABB( 280 - 43 * NLSF_QUANT_MAX_AMPLITUDE, -43, ind_tmp ); - rate1_Q5 = SKP_SUB16( rate0_Q5, 43 ); - } - } else { - rate0_Q5 = rates_Q5[ ind_tmp + NLSF_QUANT_MAX_AMPLITUDE ]; - rate1_Q5 = rates_Q5[ ind_tmp + 1 + NLSF_QUANT_MAX_AMPLITUDE ]; - } - RD_tmp_Q25 = RD_Q25[ j ]; - diff_Q10 = SKP_SUB16( in_Q10, out0_Q10 ); - RD_Q25[ j ] = SKP_SMLABB( SKP_MLA( RD_tmp_Q25, SKP_SMULBB( diff_Q10, diff_Q10 ), w_Q5[ i ] ), mu_Q20, rate0_Q5 ); - diff_Q10 = SKP_SUB16( in_Q10, out1_Q10 ); - RD_Q25[ j + nStates ] = SKP_SMLABB( SKP_MLA( RD_tmp_Q25, SKP_SMULBB( diff_Q10, diff_Q10 ), w_Q5[ i ] ), mu_Q20, rate1_Q5 ); - } - - if( nStates < NLSF_QUANT_DEL_DEC_STATES ) { - /* double number of states and copy */ - for( j = 0; j < nStates; j++ ) { - ind[ j + nStates ][ i ] = ind[ j ][ i ] + 1; - } - nStates = SKP_LSHIFT( nStates, 1 ); - for( j = nStates; j < NLSF_QUANT_DEL_DEC_STATES; j++ ) { - ind[ j ][ i ] = ind[ j - nStates ][ i ]; - } - } else if( i > 0 ) { - /* sort lower and upper half of RD_Q25, pairwise */ - for( j = 0; j < NLSF_QUANT_DEL_DEC_STATES; j++ ) { - if( RD_Q25[ j ] > RD_Q25[ j + NLSF_QUANT_DEL_DEC_STATES ] ) { - RD_max_Q25[ j ] = RD_Q25[ j ]; - RD_min_Q25[ j ] = RD_Q25[ j + NLSF_QUANT_DEL_DEC_STATES ]; - RD_Q25[ j ] = RD_min_Q25[ j ]; - RD_Q25[ j + NLSF_QUANT_DEL_DEC_STATES ] = RD_max_Q25[ j ]; - /* swap prev_out values */ - out0_Q10 = prev_out_Q10[ j ]; - prev_out_Q10[ j ] = prev_out_Q10[ j + NLSF_QUANT_DEL_DEC_STATES ]; - prev_out_Q10[ j + NLSF_QUANT_DEL_DEC_STATES ] = out0_Q10; - ind_sort[ j ] = j + NLSF_QUANT_DEL_DEC_STATES; - } else { - RD_min_Q25[ j ] = RD_Q25[ j ]; - RD_max_Q25[ j ] = RD_Q25[ j + NLSF_QUANT_DEL_DEC_STATES ]; - ind_sort[ j ] = j; - } - } - /* compare the highest RD values of the winning half with the lowest one in the losing half, and copy if necessary */ - /* afterwards ind_sort[] will contain the indices of the NLSF_QUANT_DEL_DEC_STATES winning RD values */ - while( 1 ) { - min_max_Q25 = SKP_int32_MAX; - max_min_Q25 = 0; - ind_min_max = 0; - ind_max_min = 0; - for( j = 0; j < NLSF_QUANT_DEL_DEC_STATES; j++ ) { - if( min_max_Q25 > RD_max_Q25[ j ] ) { - min_max_Q25 = RD_max_Q25[ j ]; - ind_min_max = j; - } - if( max_min_Q25 < RD_min_Q25[ j ] ) { - max_min_Q25 = RD_min_Q25[ j ]; - ind_max_min = j; - } - } - if( min_max_Q25 >= max_min_Q25 ) { - break; - } - /* copy ind_min_max to ind_max_min */ - ind_sort[ ind_max_min ] = ind_sort[ ind_min_max ] ^ NLSF_QUANT_DEL_DEC_STATES; - RD_Q25[ ind_max_min ] = RD_Q25[ ind_min_max + NLSF_QUANT_DEL_DEC_STATES ]; - prev_out_Q10[ ind_max_min ] = prev_out_Q10[ ind_min_max + NLSF_QUANT_DEL_DEC_STATES ]; - RD_min_Q25[ ind_max_min ] = 0; - RD_max_Q25[ ind_min_max ] = SKP_int32_MAX; - SKP_memcpy( ind[ ind_max_min ], ind[ ind_min_max ], MAX_LPC_ORDER * sizeof( opus_int8 ) ); - } - /* increment index if it comes from the upper half */ - for( j = 0; j < NLSF_QUANT_DEL_DEC_STATES; j++ ) { - ind[ j ][ i ] += SKP_RSHIFT( ind_sort[ j ], NLSF_QUANT_DEL_DEC_STATES_LOG2 ); - } - } else { /* i == 0 */ - /* last sample: find winner, copy indices and return RD value */ - ind_tmp = 0; - min_Q25 = SKP_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 ]; - SKP_assert( indices[ j ] >= -NLSF_QUANT_MAX_AMPLITUDE_EXT ); - SKP_assert( indices[ j ] <= NLSF_QUANT_MAX_AMPLITUDE_EXT ); - } - indices[ 0 ] += SKP_RSHIFT( ind_tmp, NLSF_QUANT_DEL_DEC_STATES_LOG2 ); - SKP_assert( indices[ 0 ] <= NLSF_QUANT_MAX_AMPLITUDE_EXT ); - SKP_assert( min_Q25 >= 0 ); - return min_Q25; - } - } -} +/*********************************************************************** +Copyright (c) 2006-2011, Skype Limited. All rights reserved. +Redistribution and use in source and binary forms, with or without +modification, (subject to the limitations in the disclaimer below) +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 Skype Limited, nor the names of specific +contributors, may be used to endorse or promote products derived from +this software without specific prior written permission. +NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED +BY THIS LICENSE. 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. +***********************************************************************/ + +#include "silk_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 ] */ + 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 ] */ + const opus_int16 ec_ix[], /* I Indices to entropy coding tables [ order ] */ + const opus_uint8 ec_rates_Q5[], /* I Rates [] */ + const opus_int quant_step_size_Q16, /* I Quantization step size */ + const opus_int16 inv_quant_step_size_Q6, /* I Inverse quantization step size */ + const opus_int32 mu_Q20, /* I R/D tradeoff */ + const opus_int16 order /* I Number of input values */ +) +{ + 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_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 ]; + opus_int32 RD_Q25[ 2 * NLSF_QUANT_DEL_DEC_STATES ]; + opus_int32 RD_min_Q25[ NLSF_QUANT_DEL_DEC_STATES ]; + opus_int32 RD_max_Q25[ NLSF_QUANT_DEL_DEC_STATES ]; + const opus_uint8 *rates_Q5; + + SKP_assert( (NLSF_QUANT_DEL_DEC_STATES & (NLSF_QUANT_DEL_DEC_STATES-1)) == 0 ); /* must be power of two */ + + nStates = 1; + RD_Q25[ 0 ] = 0; + prev_out_Q10[ 0 ] = 0; + for( i = order - 1; ; i-- ) { + rates_Q5 = &ec_rates_Q5[ ec_ix[ i ] ]; + pred_coef_Q16 = SKP_LSHIFT( (opus_int32)pred_coef_Q8[ i ], 8 ); + in_Q10 = x_Q10[ i ]; + for( j = 0; j < nStates; j++ ) { + pred_Q10 = SKP_SMULWB( pred_coef_Q16, prev_out_Q10[ j ] ); + res_Q10 = SKP_SUB16( in_Q10, pred_Q10 ); + ind_tmp = SKP_SMULWB( inv_quant_step_size_Q6, res_Q10 ); + ind_tmp = SKP_LIMIT( ind_tmp, -NLSF_QUANT_MAX_AMPLITUDE_EXT, NLSF_QUANT_MAX_AMPLITUDE_EXT-1 ); + ind[ j ][ i ] = (opus_int8)ind_tmp; + + /* compute outputs for ind_tmp and ind_tmp + 1 */ + out0_Q10 = SKP_LSHIFT( ind_tmp, 10 ); + out1_Q10 = SKP_ADD16( out0_Q10, 1024 ); + if( ind_tmp > 0 ) { + out0_Q10 = SKP_SUB16( out0_Q10, SILK_FIX_CONST( NLSF_QUANT_LEVEL_ADJ, 10 ) ); + out1_Q10 = SKP_SUB16( out1_Q10, SILK_FIX_CONST( NLSF_QUANT_LEVEL_ADJ, 10 ) ); + } else if( ind_tmp == 0 ) { + out1_Q10 = SKP_SUB16( out1_Q10, SILK_FIX_CONST( NLSF_QUANT_LEVEL_ADJ, 10 ) ); + } else if( ind_tmp == -1 ) { + out0_Q10 = SKP_ADD16( out0_Q10, SILK_FIX_CONST( NLSF_QUANT_LEVEL_ADJ, 10 ) ); + } else { + out0_Q10 = SKP_ADD16( out0_Q10, SILK_FIX_CONST( NLSF_QUANT_LEVEL_ADJ, 10 ) ); + out1_Q10 = SKP_ADD16( out1_Q10, SILK_FIX_CONST( NLSF_QUANT_LEVEL_ADJ, 10 ) ); + } + out0_Q10 = SKP_SMULWB( out0_Q10, quant_step_size_Q16 ); + out1_Q10 = SKP_SMULWB( out1_Q10, quant_step_size_Q16 ); + out0_Q10 = SKP_ADD16( out0_Q10, pred_Q10 ); + out1_Q10 = SKP_ADD16( out1_Q10, pred_Q10 ); + prev_out_Q10[ j ] = out0_Q10; + prev_out_Q10[ j + nStates ] = out1_Q10; + + /* compute RD for ind_tmp and ind_tmp + 1 */ + if( ind_tmp + 1 >= NLSF_QUANT_MAX_AMPLITUDE ) { + if( ind_tmp + 1 == NLSF_QUANT_MAX_AMPLITUDE ) { + rate0_Q5 = rates_Q5[ ind_tmp + NLSF_QUANT_MAX_AMPLITUDE ]; + rate1_Q5 = 280; + } else { + rate0_Q5 = SKP_SMLABB( 280 - 43 * NLSF_QUANT_MAX_AMPLITUDE, 43, ind_tmp ); + rate1_Q5 = SKP_ADD16( rate0_Q5, 43 ); + } + } else if( ind_tmp <= -NLSF_QUANT_MAX_AMPLITUDE ) { + if( ind_tmp == -NLSF_QUANT_MAX_AMPLITUDE ) { + rate0_Q5 = 280; + rate1_Q5 = rates_Q5[ ind_tmp + 1 + NLSF_QUANT_MAX_AMPLITUDE ]; + } else { + rate0_Q5 = SKP_SMLABB( 280 - 43 * NLSF_QUANT_MAX_AMPLITUDE, -43, ind_tmp ); + rate1_Q5 = SKP_SUB16( rate0_Q5, 43 ); + } + } else { + rate0_Q5 = rates_Q5[ ind_tmp + NLSF_QUANT_MAX_AMPLITUDE ]; + rate1_Q5 = rates_Q5[ ind_tmp + 1 + NLSF_QUANT_MAX_AMPLITUDE ]; + } + RD_tmp_Q25 = RD_Q25[ j ]; + diff_Q10 = SKP_SUB16( in_Q10, out0_Q10 ); + RD_Q25[ j ] = SKP_SMLABB( SKP_MLA( RD_tmp_Q25, SKP_SMULBB( diff_Q10, diff_Q10 ), w_Q5[ i ] ), mu_Q20, rate0_Q5 ); + diff_Q10 = SKP_SUB16( in_Q10, out1_Q10 ); + RD_Q25[ j + nStates ] = SKP_SMLABB( SKP_MLA( RD_tmp_Q25, SKP_SMULBB( diff_Q10, diff_Q10 ), w_Q5[ i ] ), mu_Q20, rate1_Q5 ); + } + + if( nStates < NLSF_QUANT_DEL_DEC_STATES ) { + /* double number of states and copy */ + for( j = 0; j < nStates; j++ ) { + ind[ j + nStates ][ i ] = ind[ j ][ i ] + 1; + } + nStates = SKP_LSHIFT( nStates, 1 ); + for( j = nStates; j < NLSF_QUANT_DEL_DEC_STATES; j++ ) { + ind[ j ][ i ] = ind[ j - nStates ][ i ]; + } + } else if( i > 0 ) { + /* sort lower and upper half of RD_Q25, pairwise */ + for( j = 0; j < NLSF_QUANT_DEL_DEC_STATES; j++ ) { + if( RD_Q25[ j ] > RD_Q25[ j + NLSF_QUANT_DEL_DEC_STATES ] ) { + RD_max_Q25[ j ] = RD_Q25[ j ]; + RD_min_Q25[ j ] = RD_Q25[ j + NLSF_QUANT_DEL_DEC_STATES ]; + RD_Q25[ j ] = RD_min_Q25[ j ]; + RD_Q25[ j + NLSF_QUANT_DEL_DEC_STATES ] = RD_max_Q25[ j ]; + /* swap prev_out values */ + out0_Q10 = prev_out_Q10[ j ]; + prev_out_Q10[ j ] = prev_out_Q10[ j + NLSF_QUANT_DEL_DEC_STATES ]; + prev_out_Q10[ j + NLSF_QUANT_DEL_DEC_STATES ] = out0_Q10; + ind_sort[ j ] = j + NLSF_QUANT_DEL_DEC_STATES; + } else { + RD_min_Q25[ j ] = RD_Q25[ j ]; + RD_max_Q25[ j ] = RD_Q25[ j + NLSF_QUANT_DEL_DEC_STATES ]; + ind_sort[ j ] = j; + } + } + /* compare the highest RD values of the winning half with the lowest one in the losing half, and copy if necessary */ + /* afterwards ind_sort[] will contain the indices of the NLSF_QUANT_DEL_DEC_STATES winning RD values */ + while( 1 ) { + min_max_Q25 = SKP_int32_MAX; + max_min_Q25 = 0; + ind_min_max = 0; + ind_max_min = 0; + for( j = 0; j < NLSF_QUANT_DEL_DEC_STATES; j++ ) { + if( min_max_Q25 > RD_max_Q25[ j ] ) { + min_max_Q25 = RD_max_Q25[ j ]; + ind_min_max = j; + } + if( max_min_Q25 < RD_min_Q25[ j ] ) { + max_min_Q25 = RD_min_Q25[ j ]; + ind_max_min = j; + } + } + if( min_max_Q25 >= max_min_Q25 ) { + break; + } + /* copy ind_min_max to ind_max_min */ + ind_sort[ ind_max_min ] = ind_sort[ ind_min_max ] ^ NLSF_QUANT_DEL_DEC_STATES; + RD_Q25[ ind_max_min ] = RD_Q25[ ind_min_max + NLSF_QUANT_DEL_DEC_STATES ]; + prev_out_Q10[ ind_max_min ] = prev_out_Q10[ ind_min_max + NLSF_QUANT_DEL_DEC_STATES ]; + RD_min_Q25[ ind_max_min ] = 0; + RD_max_Q25[ ind_min_max ] = SKP_int32_MAX; + SKP_memcpy( ind[ ind_max_min ], ind[ ind_min_max ], MAX_LPC_ORDER * sizeof( opus_int8 ) ); + } + /* increment index if it comes from the upper half */ + for( j = 0; j < NLSF_QUANT_DEL_DEC_STATES; j++ ) { + ind[ j ][ i ] += SKP_RSHIFT( ind_sort[ j ], NLSF_QUANT_DEL_DEC_STATES_LOG2 ); + } + } else { /* i == 0 */ + /* last sample: find winner, copy indices and return RD value */ + ind_tmp = 0; + min_Q25 = SKP_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 ]; + SKP_assert( indices[ j ] >= -NLSF_QUANT_MAX_AMPLITUDE_EXT ); + SKP_assert( indices[ j ] <= NLSF_QUANT_MAX_AMPLITUDE_EXT ); + } + indices[ 0 ] += SKP_RSHIFT( ind_tmp, NLSF_QUANT_DEL_DEC_STATES_LOG2 ); + SKP_assert( indices[ 0 ] <= NLSF_QUANT_MAX_AMPLITUDE_EXT ); + SKP_assert( min_Q25 >= 0 ); + return min_Q25; + } + } +} diff --git a/silk/silk_NLSF_encode.c b/silk/silk_NLSF_encode.c index cf35e5257..7e992ac63 100644 --- a/silk/silk_NLSF_encode.c +++ b/silk/silk_NLSF_encode.c @@ -1,183 +1,183 @@ -/*********************************************************************** -Copyright (c) 2006-2011, Skype Limited. All rights reserved. -Redistribution and use in source and binary forms, with or without -modification, (subject to the limitations in the disclaimer below) -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 Skype Limited, nor the names of specific -contributors, may be used to endorse or promote products derived from -this software without specific prior written permission. -NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED -BY THIS LICENSE. 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. -***********************************************************************/ - -#include "silk_main.h" - -#define STORE_LSF_DATA_FOR_TRAINING 0 - -/***********************/ -/* 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 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_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; - opus_int32 err_Q26[ NLSF_VQ_MAX_VECTORS ]; - opus_int32 RD_Q25[ NLSF_VQ_MAX_SURVIVORS ]; - opus_int tempIndices1[ NLSF_VQ_MAX_SURVIVORS ]; - opus_int8 tempIndices2[ NLSF_VQ_MAX_SURVIVORS * MAX_LPC_ORDER ]; - opus_int16 res_Q15[ MAX_LPC_ORDER ]; - opus_int16 res_Q10[ MAX_LPC_ORDER ]; - opus_int16 NLSF_tmp_Q15[ MAX_LPC_ORDER ]; - opus_int16 W_tmp_QW[ 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; - -#if STORE_LSF_DATA_FOR_TRAINING - opus_int16 pNLSF_Q15_orig[MAX_LPC_ORDER ]; - DEBUG_STORE_DATA( NLSF.dat, pNLSF_Q15, psNLSF_CB->order * sizeof( opus_int16 ) ); - DEBUG_STORE_DATA( WNLSF.dat, pW_Q5, psNLSF_CB->order * sizeof( opus_int16 ) ); - DEBUG_STORE_DATA( NLSF_mu.dat, &NLSF_mu_Q20, sizeof( opus_int ) ); - DEBUG_STORE_DATA( sigType.dat, &signalType, sizeof( opus_int ) ); - SKP_memcpy(pNLSF_Q15_orig, pNLSF_Q15, sizeof( pNLSF_Q15_orig )); -#endif - - SKP_assert( nSurvivors <= NLSF_VQ_MAX_SURVIVORS ); - SKP_assert( signalType >= 0 && signalType <= 2 ); - SKP_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 */ - silk_NLSF_VQ( err_Q26, pNLSF_Q15, psNLSF_CB->CB1_NLSF_Q8, psNLSF_CB->nVectors, psNLSF_CB->order ); - - /* Sort the quantization errors */ - silk_insertion_sort_increasing( err_Q26, tempIndices1, psNLSF_CB->nVectors, nSurvivors ); - - /* 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 ]; - for( i = 0; i < psNLSF_CB->order; i++ ) { - NLSF_tmp_Q15[ i ] = SKP_LSHIFT16( ( opus_int16 )pCB_element[ i ], 7 ); - res_Q15[ i ] = pNLSF_Q15[ i ] - NLSF_tmp_Q15[ i ]; - } - - /* Weights from codebook vector */ - silk_NLSF_VQ_weights_laroia( W_tmp_QW, NLSF_tmp_Q15, psNLSF_CB->order ); - - /* Apply square-rooted weights */ - for( i = 0; i < psNLSF_CB->order; i++ ) { - W_tmp_Q9 = silk_SQRT_APPROX( SKP_LSHIFT( ( opus_int32 )W_tmp_QW[ i ], 18 - NLSF_W_Q ) ); - res_Q10[ i ] = ( opus_int16 )SKP_RSHIFT( SKP_SMULBB( res_Q15[ i ], W_tmp_Q9 ), 14 ); - } - - /* Modify input weights accordingly */ - for( i = 0; i < psNLSF_CB->order; i++ ) { - W_adj_Q5[ i ] = SKP_DIV32_16( SKP_LSHIFT( ( opus_int32 )pW_QW[ i ], 5 ), W_tmp_QW[ i ] ); - } - - /* 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 ] = SKP_SMLABB( RD_Q25[ s ], bits_q7, SKP_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 ]; - SKP_memcpy( &NLSFIndices[ 1 ], &tempIndices2[ bestIndex * MAX_LPC_ORDER ], psNLSF_CB->order * sizeof( opus_int8 ) ); - - /* Decode */ - silk_NLSF_decode( pNLSF_Q15, NLSFIndices, psNLSF_CB ); - -#if STORE_LSF_DATA_FOR_TRAINING - { - /* code for training the codebooks */ - opus_int32 RD_dec_Q22, Dist_Q22_dec, Rate_Q7, diff_Q15; - ind1 = NLSFIndices[ 0 ]; - silk_NLSF_unpack( ec_ix, pred_Q8, psNLSF_CB, ind1 ); - - pCB_element = &psNLSF_CB->CB1_NLSF_Q8[ ind1 * psNLSF_CB->order ]; - for( i = 0; i < psNLSF_CB->order; i++ ) { - NLSF_tmp_Q15[ i ] = SKP_LSHIFT16( ( opus_int16 )pCB_element[ i ], 7 ); - } - silk_NLSF_VQ_weights_laroia( W_tmp_QW, NLSF_tmp_Q15, psNLSF_CB->order ); - for( i = 0; i < psNLSF_CB->order; i++ ) { - W_tmp_Q9 = silk_SQRT_APPROX( SKP_LSHIFT( ( opus_int32 )W_tmp_QW[ i ], 18 - NLSF_W_Q ) ); - res_Q15[ i ] = pNLSF_Q15_orig[ i ] - NLSF_tmp_Q15[ i ]; - res_Q10[ i ] = (opus_int16)SKP_RSHIFT( SKP_SMULBB( res_Q15[ i ], W_tmp_Q9 ), 14 ); - DEBUG_STORE_DATA( NLSF_res_q10.dat, &res_Q10[ i ], sizeof( opus_int16 ) ); - res_Q15[ i ] = pNLSF_Q15[ i ] - NLSF_tmp_Q15[ i ]; - res_Q10[ i ] = (opus_int16)SKP_RSHIFT( SKP_SMULBB( res_Q15[ i ], W_tmp_Q9 ), 14 ); - DEBUG_STORE_DATA( NLSF_resq_q10.dat, &res_Q10[ i ], sizeof( opus_int16 ) ); - } - - Dist_Q22_dec = 0; - for( i = 0; i < psNLSF_CB->order; i++ ) { - diff_Q15 = pNLSF_Q15_orig[ i ] - pNLSF_Q15[ i ]; - Dist_Q22_dec += ( ( (diff_Q15 >> 5) * (diff_Q15 >> 5) ) * pW_Q5[ i ] ) >> 3; - } - 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 ]; - } - Rate_Q7 = ( 8 << 7 ) - silk_lin2log( prob_Q8 ); - for( i = 0; i < psNLSF_CB->order; i++ ) { - Rate_Q7 += ((int)psNLSF_CB->ec_Rates_Q5[ ec_ix[ i ] + SKP_LIMIT( NLSFIndices[ i + 1 ] + NLSF_QUANT_MAX_AMPLITUDE, 0, 2 * NLSF_QUANT_MAX_AMPLITUDE ) ] ) << 2; - if( SKP_abs( NLSFIndices[ i + 1 ] ) >= NLSF_QUANT_MAX_AMPLITUDE ) { - Rate_Q7 += 128 << ( SKP_abs( NLSFIndices[ i + 1 ] ) - NLSF_QUANT_MAX_AMPLITUDE ); - } - } - RD_dec_Q22 = Dist_Q22_dec + Rate_Q7 * NLSF_mu_Q20 >> 5; - DEBUG_STORE_DATA( dec_dist_q22.dat, &Dist_Q22_dec, sizeof( opus_int32 ) ); - DEBUG_STORE_DATA( dec_rate_q7.dat, &Rate_Q7, sizeof( opus_int32 ) ); - DEBUG_STORE_DATA( dec_rd_q22.dat, &RD_dec_Q22, sizeof( opus_int32 ) ); - } - DEBUG_STORE_DATA( NLSF_ind.dat, NLSFIndices, (psNLSF_CB->order+1) * sizeof( opus_int8 ) ); -#endif - - return RD_Q25[ 0 ]; -} +/*********************************************************************** +Copyright (c) 2006-2011, Skype Limited. All rights reserved. +Redistribution and use in source and binary forms, with or without +modification, (subject to the limitations in the disclaimer below) +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 Skype Limited, nor the names of specific +contributors, may be used to endorse or promote products derived from +this software without specific prior written permission. +NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED +BY THIS LICENSE. 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. +***********************************************************************/ + +#include "silk_main.h" + +#define STORE_LSF_DATA_FOR_TRAINING 0 + +/***********************/ +/* 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 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_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; + opus_int32 err_Q26[ NLSF_VQ_MAX_VECTORS ]; + opus_int32 RD_Q25[ NLSF_VQ_MAX_SURVIVORS ]; + opus_int tempIndices1[ NLSF_VQ_MAX_SURVIVORS ]; + opus_int8 tempIndices2[ NLSF_VQ_MAX_SURVIVORS * MAX_LPC_ORDER ]; + opus_int16 res_Q15[ MAX_LPC_ORDER ]; + opus_int16 res_Q10[ MAX_LPC_ORDER ]; + opus_int16 NLSF_tmp_Q15[ MAX_LPC_ORDER ]; + opus_int16 W_tmp_QW[ 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; + +#if STORE_LSF_DATA_FOR_TRAINING + opus_int16 pNLSF_Q15_orig[MAX_LPC_ORDER ]; + DEBUG_STORE_DATA( NLSF.dat, pNLSF_Q15, psNLSF_CB->order * sizeof( opus_int16 ) ); + DEBUG_STORE_DATA( WNLSF.dat, pW_Q5, psNLSF_CB->order * sizeof( opus_int16 ) ); + DEBUG_STORE_DATA( NLSF_mu.dat, &NLSF_mu_Q20, sizeof( opus_int ) ); + DEBUG_STORE_DATA( sigType.dat, &signalType, sizeof( opus_int ) ); + SKP_memcpy(pNLSF_Q15_orig, pNLSF_Q15, sizeof( pNLSF_Q15_orig )); +#endif + + SKP_assert( nSurvivors <= NLSF_VQ_MAX_SURVIVORS ); + SKP_assert( signalType >= 0 && signalType <= 2 ); + SKP_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 */ + silk_NLSF_VQ( err_Q26, pNLSF_Q15, psNLSF_CB->CB1_NLSF_Q8, psNLSF_CB->nVectors, psNLSF_CB->order ); + + /* Sort the quantization errors */ + silk_insertion_sort_increasing( err_Q26, tempIndices1, psNLSF_CB->nVectors, nSurvivors ); + + /* 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 ]; + for( i = 0; i < psNLSF_CB->order; i++ ) { + NLSF_tmp_Q15[ i ] = SKP_LSHIFT16( ( opus_int16 )pCB_element[ i ], 7 ); + res_Q15[ i ] = pNLSF_Q15[ i ] - NLSF_tmp_Q15[ i ]; + } + + /* Weights from codebook vector */ + silk_NLSF_VQ_weights_laroia( W_tmp_QW, NLSF_tmp_Q15, psNLSF_CB->order ); + + /* Apply square-rooted weights */ + for( i = 0; i < psNLSF_CB->order; i++ ) { + W_tmp_Q9 = silk_SQRT_APPROX( SKP_LSHIFT( ( opus_int32 )W_tmp_QW[ i ], 18 - NLSF_W_Q ) ); + res_Q10[ i ] = ( opus_int16 )SKP_RSHIFT( SKP_SMULBB( res_Q15[ i ], W_tmp_Q9 ), 14 ); + } + + /* Modify input weights accordingly */ + for( i = 0; i < psNLSF_CB->order; i++ ) { + W_adj_Q5[ i ] = SKP_DIV32_16( SKP_LSHIFT( ( opus_int32 )pW_QW[ i ], 5 ), W_tmp_QW[ i ] ); + } + + /* 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 ] = SKP_SMLABB( RD_Q25[ s ], bits_q7, SKP_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 ]; + SKP_memcpy( &NLSFIndices[ 1 ], &tempIndices2[ bestIndex * MAX_LPC_ORDER ], psNLSF_CB->order * sizeof( opus_int8 ) ); + + /* Decode */ + silk_NLSF_decode( pNLSF_Q15, NLSFIndices, psNLSF_CB ); + +#if STORE_LSF_DATA_FOR_TRAINING + { + /* code for training the codebooks */ + opus_int32 RD_dec_Q22, Dist_Q22_dec, Rate_Q7, diff_Q15; + ind1 = NLSFIndices[ 0 ]; + silk_NLSF_unpack( ec_ix, pred_Q8, psNLSF_CB, ind1 ); + + pCB_element = &psNLSF_CB->CB1_NLSF_Q8[ ind1 * psNLSF_CB->order ]; + for( i = 0; i < psNLSF_CB->order; i++ ) { + NLSF_tmp_Q15[ i ] = SKP_LSHIFT16( ( opus_int16 )pCB_element[ i ], 7 ); + } + silk_NLSF_VQ_weights_laroia( W_tmp_QW, NLSF_tmp_Q15, psNLSF_CB->order ); + for( i = 0; i < psNLSF_CB->order; i++ ) { + W_tmp_Q9 = silk_SQRT_APPROX( SKP_LSHIFT( ( opus_int32 )W_tmp_QW[ i ], 18 - NLSF_W_Q ) ); + res_Q15[ i ] = pNLSF_Q15_orig[ i ] - NLSF_tmp_Q15[ i ]; + res_Q10[ i ] = (opus_int16)SKP_RSHIFT( SKP_SMULBB( res_Q15[ i ], W_tmp_Q9 ), 14 ); + DEBUG_STORE_DATA( NLSF_res_q10.dat, &res_Q10[ i ], sizeof( opus_int16 ) ); + res_Q15[ i ] = pNLSF_Q15[ i ] - NLSF_tmp_Q15[ i ]; + res_Q10[ i ] = (opus_int16)SKP_RSHIFT( SKP_SMULBB( res_Q15[ i ], W_tmp_Q9 ), 14 ); + DEBUG_STORE_DATA( NLSF_resq_q10.dat, &res_Q10[ i ], sizeof( opus_int16 ) ); + } + + Dist_Q22_dec = 0; + for( i = 0; i < psNLSF_CB->order; i++ ) { + diff_Q15 = pNLSF_Q15_orig[ i ] - pNLSF_Q15[ i ]; + Dist_Q22_dec += ( ( (diff_Q15 >> 5) * (diff_Q15 >> 5) ) * pW_Q5[ i ] ) >> 3; + } + 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 ]; + } + Rate_Q7 = ( 8 << 7 ) - silk_lin2log( prob_Q8 ); + for( i = 0; i < psNLSF_CB->order; i++ ) { + Rate_Q7 += ((int)psNLSF_CB->ec_Rates_Q5[ ec_ix[ i ] + SKP_LIMIT( NLSFIndices[ i + 1 ] + NLSF_QUANT_MAX_AMPLITUDE, 0, 2 * NLSF_QUANT_MAX_AMPLITUDE ) ] ) << 2; + if( SKP_abs( NLSFIndices[ i + 1 ] ) >= NLSF_QUANT_MAX_AMPLITUDE ) { + Rate_Q7 += 128 << ( SKP_abs( NLSFIndices[ i + 1 ] ) - NLSF_QUANT_MAX_AMPLITUDE ); + } + } + RD_dec_Q22 = Dist_Q22_dec + Rate_Q7 * NLSF_mu_Q20 >> 5; + DEBUG_STORE_DATA( dec_dist_q22.dat, &Dist_Q22_dec, sizeof( opus_int32 ) ); + DEBUG_STORE_DATA( dec_rate_q7.dat, &Rate_Q7, sizeof( opus_int32 ) ); + DEBUG_STORE_DATA( dec_rd_q22.dat, &RD_dec_Q22, sizeof( opus_int32 ) ); + } + DEBUG_STORE_DATA( NLSF_ind.dat, NLSFIndices, (psNLSF_CB->order+1) * sizeof( opus_int8 ) ); +#endif + + return RD_Q25[ 0 ]; +} diff --git a/silk/silk_NLSF_stabilize.c b/silk/silk_NLSF_stabilize.c index fadfec7ae..5ecddc7cd 100644 --- a/silk/silk_NLSF_stabilize.c +++ b/silk/silk_NLSF_stabilize.c @@ -1,138 +1,138 @@ -/*********************************************************************** -Copyright (c) 2006-2011, Skype Limited. All rights reserved. -Redistribution and use in source and binary forms, with or without -modification, (subject to the limitations in the disclaimer below) -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 Skype Limited, nor the names of specific -contributors, may be used to endorse or promote products derived from -this software without specific prior written permission. -NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED -BY THIS LICENSE. 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. -***********************************************************************/ - -/* NLSF stabilizer: */ -/* */ -/* - Moves NLSFs futher apart if they are too close */ -/* - Moves NLSFs away from borders if they are too close */ -/* - High effort to achieve a modification with minimum */ -/* Euclidean distance to input vector */ -/* - Output are sorted NLSF coefficients */ -/* */ - -#include "silk_SigProc_FIX.h" - -/* Constant Definitions */ -#define MAX_LOOPS 20 - -/* NLSF stabilizer, for a single input data vector */ -void silk_NLSF_stabilize( - opus_int16 *NLSF_Q15, /* I/O: Unstable/stabilized normalized LSF vector in Q15 [L] */ - const opus_int16 *NDeltaMin_Q15, /* I: Normalized delta min vector in Q15, NDeltaMin_Q15[L] must be >= 1 [L+1] */ - const opus_int L /* I: Number of NLSF parameters in the input vector */ -) -{ - opus_int i, I=0, k, loops; - opus_int16 center_freq_Q15; - opus_int32 diff_Q15, min_diff_Q15, min_center_Q15, max_center_Q15; - - /* This is necessary to ensure an output within range of a opus_int16 */ - SKP_assert( NDeltaMin_Q15[L] >= 1 ); - - for( loops = 0; loops < MAX_LOOPS; loops++ ) { - /**************************/ - /* Find smallest distance */ - /**************************/ - /* First element */ - min_diff_Q15 = NLSF_Q15[0] - NDeltaMin_Q15[0]; - I = 0; - /* Middle elements */ - for( i = 1; i <= L-1; i++ ) { - diff_Q15 = NLSF_Q15[i] - ( NLSF_Q15[i-1] + NDeltaMin_Q15[i] ); - if( diff_Q15 < min_diff_Q15 ) { - min_diff_Q15 = diff_Q15; - I = i; - } - } - /* Last element */ - diff_Q15 = ( 1 << 15 ) - ( NLSF_Q15[L-1] + NDeltaMin_Q15[L] ); - if( diff_Q15 < min_diff_Q15 ) { - min_diff_Q15 = diff_Q15; - I = L; - } - - /***************************************************/ - /* Now check if the smallest distance non-negative */ - /***************************************************/ - if (min_diff_Q15 >= 0) { - return; - } - - if( I == 0 ) { - /* Move away from lower limit */ - NLSF_Q15[0] = NDeltaMin_Q15[0]; - - } else if( I == L) { - /* Move away from higher limit */ - NLSF_Q15[L-1] = ( 1 << 15 ) - NDeltaMin_Q15[L]; - - } else { - /* Find the lower extreme for the location of the current center frequency */ - min_center_Q15 = 0; - for( k = 0; k < I; k++ ) { - min_center_Q15 += NDeltaMin_Q15[k]; - } - min_center_Q15 += SKP_RSHIFT( NDeltaMin_Q15[I], 1 ); - - /* Find the upper extreme for the location of the current center frequency */ - max_center_Q15 = 1 << 15; - for( k = L; k > I; k-- ) { - max_center_Q15 -= NDeltaMin_Q15[k]; - } - max_center_Q15 -= SKP_RSHIFT( NDeltaMin_Q15[I], 1 ); - - /* Move apart, sorted by value, keeping the same center frequency */ - center_freq_Q15 = (opus_int16)SKP_LIMIT_32( SKP_RSHIFT_ROUND( (opus_int32)NLSF_Q15[I-1] + (opus_int32)NLSF_Q15[I], 1 ), - min_center_Q15, max_center_Q15 ); - NLSF_Q15[I-1] = center_freq_Q15 - SKP_RSHIFT( NDeltaMin_Q15[I], 1 ); - NLSF_Q15[I] = NLSF_Q15[I-1] + NDeltaMin_Q15[I]; - } - } - - /* Safe and simple fall back method, which is less ideal than the above */ - if( loops == MAX_LOOPS ) - { - /* Insertion sort (fast for already almost sorted arrays): */ - /* Best case: O(n) for an already sorted array */ - /* Worst case: O(n^2) for an inversely sorted array */ - silk_insertion_sort_increasing_all_values_int16( &NLSF_Q15[0], L ); - - /* First NLSF should be no less than NDeltaMin[0] */ - NLSF_Q15[0] = SKP_max_int( NLSF_Q15[0], NDeltaMin_Q15[0] ); - - /* Keep delta_min distance between the NLSFs */ - for( i = 1; i < L; i++ ) - NLSF_Q15[i] = SKP_max_int( NLSF_Q15[i], NLSF_Q15[i-1] + NDeltaMin_Q15[i] ); - - /* Last NLSF should be no higher than 1 - NDeltaMin[L] */ - NLSF_Q15[L-1] = SKP_min_int( NLSF_Q15[L-1], (1<<15) - NDeltaMin_Q15[L] ); - - /* Keep NDeltaMin distance between the NLSFs */ - for( i = L-2; i >= 0; i-- ) - NLSF_Q15[i] = SKP_min_int( NLSF_Q15[i], NLSF_Q15[i+1] - NDeltaMin_Q15[i+1] ); - } -} +/*********************************************************************** +Copyright (c) 2006-2011, Skype Limited. All rights reserved. +Redistribution and use in source and binary forms, with or without +modification, (subject to the limitations in the disclaimer below) +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 Skype Limited, nor the names of specific +contributors, may be used to endorse or promote products derived from +this software without specific prior written permission. +NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED +BY THIS LICENSE. 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. +***********************************************************************/ + +/* NLSF stabilizer: */ +/* */ +/* - Moves NLSFs futher apart if they are too close */ +/* - Moves NLSFs away from borders if they are too close */ +/* - High effort to achieve a modification with minimum */ +/* Euclidean distance to input vector */ +/* - Output are sorted NLSF coefficients */ +/* */ + +#include "silk_SigProc_FIX.h" + +/* Constant Definitions */ +#define MAX_LOOPS 20 + +/* NLSF stabilizer, for a single input data vector */ +void silk_NLSF_stabilize( + opus_int16 *NLSF_Q15, /* I/O: Unstable/stabilized normalized LSF vector in Q15 [L] */ + const opus_int16 *NDeltaMin_Q15, /* I: Normalized delta min vector in Q15, NDeltaMin_Q15[L] must be >= 1 [L+1] */ + const opus_int L /* I: Number of NLSF parameters in the input vector */ +) +{ + opus_int i, I=0, k, loops; + opus_int16 center_freq_Q15; + opus_int32 diff_Q15, min_diff_Q15, min_center_Q15, max_center_Q15; + + /* This is necessary to ensure an output within range of a opus_int16 */ + SKP_assert( NDeltaMin_Q15[L] >= 1 ); + + for( loops = 0; loops < MAX_LOOPS; loops++ ) { + /**************************/ + /* Find smallest distance */ + /**************************/ + /* First element */ + min_diff_Q15 = NLSF_Q15[0] - NDeltaMin_Q15[0]; + I = 0; + /* Middle elements */ + for( i = 1; i <= L-1; i++ ) { + diff_Q15 = NLSF_Q15[i] - ( NLSF_Q15[i-1] + NDeltaMin_Q15[i] ); + if( diff_Q15 < min_diff_Q15 ) { + min_diff_Q15 = diff_Q15; + I = i; + } + } + /* Last element */ + diff_Q15 = ( 1 << 15 ) - ( NLSF_Q15[L-1] + NDeltaMin_Q15[L] ); + if( diff_Q15 < min_diff_Q15 ) { + min_diff_Q15 = diff_Q15; + I = L; + } + + /***************************************************/ + /* Now check if the smallest distance non-negative */ + /***************************************************/ + if (min_diff_Q15 >= 0) { + return; + } + + if( I == 0 ) { + /* Move away from lower limit */ + NLSF_Q15[0] = NDeltaMin_Q15[0]; + + } else if( I == L) { + /* Move away from higher limit */ + NLSF_Q15[L-1] = ( 1 << 15 ) - NDeltaMin_Q15[L]; + + } else { + /* Find the lower extreme for the location of the current center frequency */ + min_center_Q15 = 0; + for( k = 0; k < I; k++ ) { + min_center_Q15 += NDeltaMin_Q15[k]; + } + min_center_Q15 += SKP_RSHIFT( NDeltaMin_Q15[I], 1 ); + + /* Find the upper extreme for the location of the current center frequency */ + max_center_Q15 = 1 << 15; + for( k = L; k > I; k-- ) { + max_center_Q15 -= NDeltaMin_Q15[k]; + } + max_center_Q15 -= SKP_RSHIFT( NDeltaMin_Q15[I], 1 ); + + /* Move apart, sorted by value, keeping the same center frequency */ + center_freq_Q15 = (opus_int16)SKP_LIMIT_32( SKP_RSHIFT_ROUND( (opus_int32)NLSF_Q15[I-1] + (opus_int32)NLSF_Q15[I], 1 ), + min_center_Q15, max_center_Q15 ); + NLSF_Q15[I-1] = center_freq_Q15 - SKP_RSHIFT( NDeltaMin_Q15[I], 1 ); + NLSF_Q15[I] = NLSF_Q15[I-1] + NDeltaMin_Q15[I]; + } + } + + /* Safe and simple fall back method, which is less ideal than the above */ + if( loops == MAX_LOOPS ) + { + /* Insertion sort (fast for already almost sorted arrays): */ + /* Best case: O(n) for an already sorted array */ + /* Worst case: O(n^2) for an inversely sorted array */ + silk_insertion_sort_increasing_all_values_int16( &NLSF_Q15[0], L ); + + /* First NLSF should be no less than NDeltaMin[0] */ + NLSF_Q15[0] = SKP_max_int( NLSF_Q15[0], NDeltaMin_Q15[0] ); + + /* Keep delta_min distance between the NLSFs */ + for( i = 1; i < L; i++ ) + NLSF_Q15[i] = SKP_max_int( NLSF_Q15[i], NLSF_Q15[i-1] + NDeltaMin_Q15[i] ); + + /* Last NLSF should be no higher than 1 - NDeltaMin[L] */ + NLSF_Q15[L-1] = SKP_min_int( NLSF_Q15[L-1], (1<<15) - NDeltaMin_Q15[L] ); + + /* Keep NDeltaMin distance between the NLSFs */ + for( i = L-2; i >= 0; i-- ) + NLSF_Q15[i] = SKP_min_int( NLSF_Q15[i], NLSF_Q15[i+1] - NDeltaMin_Q15[i+1] ); + } +} diff --git a/silk/silk_NLSF_unpack.c b/silk/silk_NLSF_unpack.c index f9e496b03..116c0762b 100644 --- a/silk/silk_NLSF_unpack.c +++ b/silk/silk_NLSF_unpack.c @@ -1,51 +1,51 @@ -/*********************************************************************** -Copyright (c) 2006-2011, Skype Limited. All rights reserved. -Redistribution and use in source and binary forms, with or without -modification, (subject to the limitations in the disclaimer below) -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 Skype Limited, nor the names of specific -contributors, may be used to endorse or promote products derived from -this software without specific prior written permission. -NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED -BY THIS LICENSE. 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. -***********************************************************************/ - -#include "silk_main.h" - -/* 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_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 */ -) -{ - opus_int i; - opus_uint8 entry; - const opus_uint8 *ec_sel_ptr; - - ec_sel_ptr = &psNLSF_CB->ec_sel[ CB1_index * psNLSF_CB->order / 2 ]; - for( i = 0; i < psNLSF_CB->order; i += 2 ) { - entry = *ec_sel_ptr++; - ec_ix [ i ] = SKP_SMULBB( SKP_RSHIFT( entry, 1 ) & 7, 2 * NLSF_QUANT_MAX_AMPLITUDE + 1 ); - pred_Q8[ i ] = psNLSF_CB->pred_Q8[ i + ( entry & 1 ) * ( psNLSF_CB->order - 1 ) ]; - ec_ix [ i + 1 ] = SKP_SMULBB( SKP_RSHIFT( entry, 5 ) & 7, 2 * NLSF_QUANT_MAX_AMPLITUDE + 1 ); - pred_Q8[ i + 1 ] = psNLSF_CB->pred_Q8[ i + ( SKP_RSHIFT( entry, 4 ) & 1 ) * ( psNLSF_CB->order - 1 ) + 1 ]; - } -} - +/*********************************************************************** +Copyright (c) 2006-2011, Skype Limited. All rights reserved. +Redistribution and use in source and binary forms, with or without +modification, (subject to the limitations in the disclaimer below) +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 Skype Limited, nor the names of specific +contributors, may be used to endorse or promote products derived from +this software without specific prior written permission. +NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED +BY THIS LICENSE. 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. +***********************************************************************/ + +#include "silk_main.h" + +/* 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_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 */ +) +{ + opus_int i; + opus_uint8 entry; + const opus_uint8 *ec_sel_ptr; + + ec_sel_ptr = &psNLSF_CB->ec_sel[ CB1_index * psNLSF_CB->order / 2 ]; + for( i = 0; i < psNLSF_CB->order; i += 2 ) { + entry = *ec_sel_ptr++; + ec_ix [ i ] = SKP_SMULBB( SKP_RSHIFT( entry, 1 ) & 7, 2 * NLSF_QUANT_MAX_AMPLITUDE + 1 ); + pred_Q8[ i ] = psNLSF_CB->pred_Q8[ i + ( entry & 1 ) * ( psNLSF_CB->order - 1 ) ]; + ec_ix [ i + 1 ] = SKP_SMULBB( SKP_RSHIFT( entry, 5 ) & 7, 2 * NLSF_QUANT_MAX_AMPLITUDE + 1 ); + pred_Q8[ i + 1 ] = psNLSF_CB->pred_Q8[ i + ( SKP_RSHIFT( entry, 4 ) & 1 ) * ( psNLSF_CB->order - 1 ) + 1 ]; + } +} + diff --git a/silk/silk_NSQ.c b/silk/silk_NSQ.c index 5c70299ba..a3acafd5c 100644 --- a/silk/silk_NSQ.c +++ b/silk/silk_NSQ.c @@ -1,427 +1,427 @@ -/*********************************************************************** -Copyright (c) 2006-2011, Skype Limited. All rights reserved. -Redistribution and use in source and binary forms, with or without -modification, (subject to the limitations in the disclaimer below) -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 Skype Limited, nor the names of specific -contributors, may be used to endorse or promote products derived from -this software without specific prior written permission. -NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED -BY THIS LICENSE. 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. -***********************************************************************/ - -#include "silk_main.h" - -SKP_INLINE void silk_nsq_scale_states( - const silk_encoder_state *psEncC, /* I Encoder State */ - silk_nsq_state *NSQ, /* I/O NSQ state */ - const opus_int16 x[], /* I input in Q0 */ - 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_Q16[], /* O LTP state matching scaled input */ - opus_int subfr, /* I subframe number */ - const opus_int LTP_scale_Q14, /* I */ - const opus_int32 Gains_Q16[ MAX_NB_SUBFR ], /* I */ - const opus_int pitchL[ MAX_NB_SUBFR ] /* I */ -); - -SKP_INLINE void silk_noise_shape_quantizer( - silk_nsq_state *NSQ, /* I/O NSQ state */ - opus_int signalType, /* I Signal type */ - const opus_int32 x_sc_Q10[], /* I */ - opus_int8 pulses[], /* O */ - opus_int16 xq[], /* O */ - opus_int32 sLTP_Q16[], /* I/O LTP state */ - const opus_int16 a_Q12[], /* I Short term prediction coefs */ - const opus_int16 b_Q14[], /* I Long term prediction coefs */ - const opus_int16 AR_shp_Q13[], /* I Noise shaping AR coefs */ - opus_int lag, /* I Pitch lag */ - opus_int32 HarmShapeFIRPacked_Q14, /* I */ - opus_int Tilt_Q14, /* I Spectral tilt */ - opus_int32 LF_shp_Q14, /* I */ - opus_int32 Gain_Q16, /* I */ - opus_int Lambda_Q10, /* I */ - opus_int offset_Q10, /* I */ - opus_int length, /* I Input length */ - opus_int shapingLPCOrder, /* I Noise shaping AR filter order */ - opus_int predictLPCOrder /* I Prediction filter order */ -); - -void silk_NSQ( - const silk_encoder_state *psEncC, /* I/O Encoder State */ - silk_nsq_state *NSQ, /* I/O NSQ state */ - SideInfoIndices *psIndices, /* I/O Quantization Indices */ - const opus_int16 x[], /* I prefiltered input signal */ - opus_int8 pulses[], /* O quantized qulse signal */ - const opus_int16 PredCoef_Q12[ 2 * MAX_LPC_ORDER ], /* I Short term prediction coefficients */ - const opus_int16 LTPCoef_Q14[ LTP_ORDER * MAX_NB_SUBFR ], /* I Long term prediction coefficients */ - const opus_int16 AR2_Q13[ MAX_NB_SUBFR * MAX_SHAPE_LPC_ORDER ], /* I */ - const opus_int HarmShapeGain_Q14[ MAX_NB_SUBFR ], /* I */ - const opus_int Tilt_Q14[ MAX_NB_SUBFR ], /* I Spectral tilt */ - const opus_int32 LF_shp_Q14[ MAX_NB_SUBFR ], /* I */ - const opus_int32 Gains_Q16[ MAX_NB_SUBFR ], /* I */ - const opus_int pitchL[ MAX_NB_SUBFR ], /* I */ - const opus_int Lambda_Q10, /* I */ - const opus_int LTP_scale_Q14 /* I LTP state scaling */ -) -{ - opus_int k, lag, start_idx, LSF_interpolation_flag; - const opus_int16 *A_Q12, *B_Q14, *AR_shp_Q13; - opus_int16 *pxq; - opus_int32 sLTP_Q16[ 2 * MAX_FRAME_LENGTH ]; - opus_int16 sLTP[ 2 * MAX_FRAME_LENGTH ]; - opus_int32 HarmShapeFIRPacked_Q14; - opus_int offset_Q10; - opus_int32 x_sc_Q10[ MAX_FRAME_LENGTH / MAX_NB_SUBFR ]; - - NSQ->rand_seed = psIndices->Seed; - - /* Set unvoiced lag to the previous one, overwrite later for voiced */ - lag = NSQ->lagPrev; - - SKP_assert( NSQ->prev_inv_gain_Q16 != 0 ); - - offset_Q10 = silk_Quantization_Offsets_Q10[ psIndices->signalType >> 1 ][ psIndices->quantOffsetType ]; - - if( psIndices->NLSFInterpCoef_Q2 == 4 ) { - LSF_interpolation_flag = 0; - } else { - LSF_interpolation_flag = 1; - } - - /* Setup pointers to start of sub frame */ - NSQ->sLTP_shp_buf_idx = psEncC->ltp_mem_length; - NSQ->sLTP_buf_idx = psEncC->ltp_mem_length; - pxq = &NSQ->xq[ psEncC->ltp_mem_length ]; - for( k = 0; k < psEncC->nb_subfr; k++ ) { - A_Q12 = &PredCoef_Q12[ (( k >> 1 ) | ( 1 - LSF_interpolation_flag )) * MAX_LPC_ORDER ]; - B_Q14 = <PCoef_Q14[ k * LTP_ORDER ]; - AR_shp_Q13 = &AR2_Q13[ k * MAX_SHAPE_LPC_ORDER ]; - - /* Noise shape parameters */ - SKP_assert( HarmShapeGain_Q14[ k ] >= 0 ); - HarmShapeFIRPacked_Q14 = SKP_RSHIFT( HarmShapeGain_Q14[ k ], 2 ); - HarmShapeFIRPacked_Q14 |= SKP_LSHIFT( ( opus_int32 )SKP_RSHIFT( HarmShapeGain_Q14[ k ], 1 ), 16 ); - - NSQ->rewhite_flag = 0; - if( psIndices->signalType == TYPE_VOICED ) { - /* Voiced */ - lag = pitchL[ k ]; - - /* Re-whitening */ - if( ( k & ( 3 - SKP_LSHIFT( LSF_interpolation_flag, 1 ) ) ) == 0 ) { - /* Rewhiten with new A coefs */ - start_idx = psEncC->ltp_mem_length - lag - psEncC->predictLPCOrder - LTP_ORDER / 2; - SKP_assert( start_idx > 0 ); - - silk_LPC_analysis_filter( &sLTP[ start_idx ], &NSQ->xq[ start_idx + k * psEncC->subfr_length ], - A_Q12, psEncC->ltp_mem_length - start_idx, psEncC->predictLPCOrder ); - - NSQ->rewhite_flag = 1; - NSQ->sLTP_buf_idx = psEncC->ltp_mem_length; - } - } - - silk_nsq_scale_states( psEncC, NSQ, x, x_sc_Q10, sLTP, sLTP_Q16, k, LTP_scale_Q14, Gains_Q16, pitchL ); - - silk_noise_shape_quantizer( NSQ, psIndices->signalType, x_sc_Q10, pulses, pxq, sLTP_Q16, 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 ); - - x += psEncC->subfr_length; - pulses += psEncC->subfr_length; - pxq += psEncC->subfr_length; - } - - /* Update lagPrev for next frame */ - NSQ->lagPrev = pitchL[ psEncC->nb_subfr - 1 ]; - - /* Save quantized speech and noise shaping signals */ - SKP_memmove( NSQ->xq, &NSQ->xq[ psEncC->frame_length ], psEncC->ltp_mem_length * sizeof( opus_int16 ) ); - SKP_memmove( NSQ->sLTP_shp_Q10, &NSQ->sLTP_shp_Q10[ psEncC->frame_length ], psEncC->ltp_mem_length * sizeof( opus_int32 ) ); - -#ifdef SAVE_ALL_INTERNAL_DATA - DEBUG_STORE_DATA( xq.dat, &pxq[ -psEncC->frame_length ], psEncC->frame_length * sizeof( opus_int16 ) ); - DEBUG_STORE_DATA( q.dat, &pulses[ -psEncC->frame_length ], psEncC->frame_length * sizeof( opus_int8 ) ); - DEBUG_STORE_DATA( sLTP_Q16.dat, &sLTP_Q16[ psEncC->ltp_mem_length ], psEncC->frame_length * sizeof( opus_int32 ) ); -#endif -} - -/***********************************/ -/* silk_noise_shape_quantizer */ -/***********************************/ -SKP_INLINE void silk_noise_shape_quantizer( - silk_nsq_state *NSQ, /* I/O NSQ state */ - opus_int signalType, /* I Signal type */ - const opus_int32 x_sc_Q10[], /* I */ - opus_int8 pulses[], /* O */ - opus_int16 xq[], /* O */ - opus_int32 sLTP_Q16[], /* I/O LTP state */ - const opus_int16 a_Q12[], /* I Short term prediction coefs */ - const opus_int16 b_Q14[], /* I Long term prediction coefs */ - const opus_int16 AR_shp_Q13[], /* I Noise shaping AR coefs */ - opus_int lag, /* I Pitch lag */ - opus_int32 HarmShapeFIRPacked_Q14, /* I */ - opus_int Tilt_Q14, /* I Spectral tilt */ - opus_int32 LF_shp_Q14, /* I */ - opus_int32 Gain_Q16, /* I */ - opus_int Lambda_Q10, /* I */ - opus_int offset_Q10, /* I */ - opus_int length, /* I Input length */ - opus_int shapingLPCOrder, /* I Noise shaping AR filter order */ - opus_int predictLPCOrder /* I Prediction filter order */ -) -{ - opus_int i, j; - opus_int32 LTP_pred_Q14, LPC_pred_Q10, n_AR_Q10, n_LTP_Q14; - opus_int32 n_LF_Q10, r_Q10, rr_Q10, q1_Q10, q2_Q10, rd1_Q10, rd2_Q10; - opus_int32 dither, exc_Q10, LPC_exc_Q10, xq_Q10; - opus_int32 tmp1, tmp2, sLF_AR_shp_Q10; - opus_int32 *psLPC_Q14, *shp_lag_ptr, *pred_lag_ptr; - - shp_lag_ptr = &NSQ->sLTP_shp_Q10[ NSQ->sLTP_shp_buf_idx - lag + HARM_SHAPE_FIR_TAPS / 2 ]; - pred_lag_ptr = &sLTP_Q16[ NSQ->sLTP_buf_idx - lag + LTP_ORDER / 2 ]; - - /* Setup short term AR state */ - psLPC_Q14 = &NSQ->sLPC_Q14[ NSQ_LPC_BUF_LENGTH - 1 ]; - - for( i = 0; i < length; i++ ) { - /* Generate dither */ - NSQ->rand_seed = SKP_RAND( NSQ->rand_seed ); - - /* dither = rand_seed < 0 ? 0xFFFFFFFF : 0; */ - dither = SKP_RSHIFT( NSQ->rand_seed, 31 ); - - /* Short-term prediction */ - SKP_assert( ( predictLPCOrder & 1 ) == 0 ); /* check that order is even */ - SKP_assert( ( (opus_int64)a_Q12 & 3 ) == 0 ); /* check that array starts at 4-byte aligned address */ - SKP_assert( predictLPCOrder >= 10 ); /* check that unrolling works */ - - /* Partially unrolled */ - LPC_pred_Q10 = SKP_SMULWB( psLPC_Q14[ 0 ], a_Q12[ 0 ] ); - LPC_pred_Q10 = SKP_SMLAWB( LPC_pred_Q10, psLPC_Q14[ -1 ], a_Q12[ 1 ] ); - LPC_pred_Q10 = SKP_SMLAWB( LPC_pred_Q10, psLPC_Q14[ -2 ], a_Q12[ 2 ] ); - LPC_pred_Q10 = SKP_SMLAWB( LPC_pred_Q10, psLPC_Q14[ -3 ], a_Q12[ 3 ] ); - LPC_pred_Q10 = SKP_SMLAWB( LPC_pred_Q10, psLPC_Q14[ -4 ], a_Q12[ 4 ] ); - LPC_pred_Q10 = SKP_SMLAWB( LPC_pred_Q10, psLPC_Q14[ -5 ], a_Q12[ 5 ] ); - LPC_pred_Q10 = SKP_SMLAWB( LPC_pred_Q10, psLPC_Q14[ -6 ], a_Q12[ 6 ] ); - LPC_pred_Q10 = SKP_SMLAWB( LPC_pred_Q10, psLPC_Q14[ -7 ], a_Q12[ 7 ] ); - LPC_pred_Q10 = SKP_SMLAWB( LPC_pred_Q10, psLPC_Q14[ -8 ], a_Q12[ 8 ] ); - LPC_pred_Q10 = SKP_SMLAWB( LPC_pred_Q10, psLPC_Q14[ -9 ], a_Q12[ 9 ] ); - for( j = 10; j < predictLPCOrder; j ++ ) { - LPC_pred_Q10 = SKP_SMLAWB( LPC_pred_Q10, psLPC_Q14[ -j ], a_Q12[ j ] ); - } - - /* Long-term prediction */ - if( signalType == TYPE_VOICED ) { - /* Unrolled loop */ - LTP_pred_Q14 = SKP_SMULWB( pred_lag_ptr[ 0 ], b_Q14[ 0 ] ); - LTP_pred_Q14 = SKP_SMLAWB( LTP_pred_Q14, pred_lag_ptr[ -1 ], b_Q14[ 1 ] ); - LTP_pred_Q14 = SKP_SMLAWB( LTP_pred_Q14, pred_lag_ptr[ -2 ], b_Q14[ 2 ] ); - LTP_pred_Q14 = SKP_SMLAWB( LTP_pred_Q14, pred_lag_ptr[ -3 ], b_Q14[ 3 ] ); - LTP_pred_Q14 = SKP_SMLAWB( LTP_pred_Q14, pred_lag_ptr[ -4 ], b_Q14[ 4 ] ); - pred_lag_ptr++; - } else { - LTP_pred_Q14 = 0; - } - - /* Noise shape feedback */ - SKP_assert( ( shapingLPCOrder & 1 ) == 0 ); /* check that order is even */ - tmp2 = psLPC_Q14[ 0 ]; - tmp1 = NSQ->sAR2_Q14[ 0 ]; - NSQ->sAR2_Q14[ 0 ] = tmp2; - n_AR_Q10 = SKP_SMULWB( tmp2, AR_shp_Q13[ 0 ] ); - for( j = 2; j < shapingLPCOrder; j += 2 ) { - tmp2 = NSQ->sAR2_Q14[ j - 1 ]; - NSQ->sAR2_Q14[ j - 1 ] = tmp1; - n_AR_Q10 = SKP_SMLAWB( n_AR_Q10, tmp1, AR_shp_Q13[ j - 1 ] ); - tmp1 = NSQ->sAR2_Q14[ j + 0 ]; - NSQ->sAR2_Q14[ j + 0 ] = tmp2; - n_AR_Q10 = SKP_SMLAWB( n_AR_Q10, tmp2, AR_shp_Q13[ j ] ); - } - NSQ->sAR2_Q14[ shapingLPCOrder - 1 ] = tmp1; - n_AR_Q10 = SKP_SMLAWB( n_AR_Q10, tmp1, AR_shp_Q13[ shapingLPCOrder - 1 ] ); - - n_AR_Q10 = SKP_RSHIFT( n_AR_Q10, 1 ); /* Q11 -> Q10 */ - n_AR_Q10 = SKP_SMLAWB( n_AR_Q10, NSQ->sLF_AR_shp_Q12, Tilt_Q14 ); - - n_LF_Q10 = SKP_LSHIFT( SKP_SMULWB( NSQ->sLTP_shp_Q10[ NSQ->sLTP_shp_buf_idx - 1 ], LF_shp_Q14 ), 2 ); - n_LF_Q10 = SKP_SMLAWT( n_LF_Q10, NSQ->sLF_AR_shp_Q12, LF_shp_Q14 ); - - SKP_assert( lag > 0 || signalType != TYPE_VOICED ); - - /* Long-term shaping */ - if( lag > 0 ) { - /* Symmetric, packed FIR coefficients */ - n_LTP_Q14 = SKP_SMULWB( SKP_ADD32( shp_lag_ptr[ 0 ], shp_lag_ptr[ -2 ] ), HarmShapeFIRPacked_Q14 ); - n_LTP_Q14 = SKP_SMLAWT( n_LTP_Q14, shp_lag_ptr[ -1 ], HarmShapeFIRPacked_Q14 ); - n_LTP_Q14 = SKP_LSHIFT( n_LTP_Q14, 6 ); - shp_lag_ptr++; - - tmp1 = SKP_SUB32( LTP_pred_Q14, n_LTP_Q14 ); /* Add Q14 stuff */ - tmp1 = SKP_RSHIFT( tmp1, 4 ); /* convert to Q10 */ - tmp1 = SKP_ADD32( tmp1, LPC_pred_Q10 ); /* add Q10 stuff */ - tmp1 = SKP_SUB32( tmp1, n_AR_Q10 ); /* subtract Q10 stuff */ - } else { - tmp1 = SKP_SUB32( LPC_pred_Q10, n_AR_Q10 ); /* subtract Q10 stuff */ - } - - /* Input minus prediction plus noise feedback */ - //r = x[ i ] - LTP_pred - LPC_pred + n_AR + n_Tilt + n_LF + n_LTP; - tmp1 = SKP_SUB32( tmp1, n_LF_Q10 ); /* subtract Q10 stuff */ - r_Q10 = SKP_SUB32( x_sc_Q10[ i ], tmp1 ); - - /* Flip sign depending on dither */ - r_Q10 = r_Q10 ^ dither; - r_Q10 = SKP_LIMIT_32( r_Q10, -31 << 10, 30 << 10 ); - - /* Find two quantization level candidates and measure their rate-distortion */ - q1_Q10 = SKP_SUB32( r_Q10, offset_Q10 ); - q1_Q10 = SKP_RSHIFT( q1_Q10, 10 ); - if( q1_Q10 > 0 ) { - q1_Q10 = SKP_SUB32( SKP_LSHIFT( q1_Q10, 10 ), QUANT_LEVEL_ADJUST_Q10 ); - q1_Q10 = SKP_ADD32( q1_Q10, offset_Q10 ); - q2_Q10 = SKP_ADD32( q1_Q10, 1024 ); - rd1_Q10 = SKP_SMULBB( q1_Q10, Lambda_Q10 ); - rd2_Q10 = SKP_SMULBB( q2_Q10, Lambda_Q10 ); - } else if( q1_Q10 == 0 ) { - q1_Q10 = offset_Q10; - q2_Q10 = SKP_ADD32( q1_Q10, 1024 - QUANT_LEVEL_ADJUST_Q10 ); - rd1_Q10 = SKP_SMULBB( q1_Q10, Lambda_Q10 ); - rd2_Q10 = SKP_SMULBB( q2_Q10, Lambda_Q10 ); - } else if( q1_Q10 == -1 ) { - q2_Q10 = offset_Q10; - q1_Q10 = SKP_SUB32( q2_Q10, 1024 - QUANT_LEVEL_ADJUST_Q10 ); - rd1_Q10 = SKP_SMULBB( -q1_Q10, Lambda_Q10 ); - rd2_Q10 = SKP_SMULBB( q2_Q10, Lambda_Q10 ); - } else { /* Q1_Q10 < -1 */ - q1_Q10 = SKP_ADD32( SKP_LSHIFT( q1_Q10, 10 ), QUANT_LEVEL_ADJUST_Q10 ); - q1_Q10 = SKP_ADD32( q1_Q10, offset_Q10 ); - q2_Q10 = SKP_ADD32( q1_Q10, 1024 ); - rd1_Q10 = SKP_SMULBB( -q1_Q10, Lambda_Q10 ); - rd2_Q10 = SKP_SMULBB( -q2_Q10, Lambda_Q10 ); - } - rr_Q10 = SKP_SUB32( r_Q10, q1_Q10 ); - rd1_Q10 = SKP_RSHIFT( SKP_SMLABB( rd1_Q10, rr_Q10, rr_Q10 ), 10 ); - rr_Q10 = SKP_SUB32( r_Q10, q2_Q10 ); - rd2_Q10 = SKP_RSHIFT( SKP_SMLABB( rd2_Q10, rr_Q10, rr_Q10 ), 10 ); - - if( rd2_Q10 < rd1_Q10 ) { - q1_Q10 = q2_Q10; - } - - pulses[ i ] = ( opus_int8 )SKP_RSHIFT_ROUND( q1_Q10, 10 ); - - /* Excitation */ - exc_Q10 = q1_Q10 ^ dither; - - /* Add predictions */ - LPC_exc_Q10 = SKP_ADD32( exc_Q10, SKP_RSHIFT_ROUND( LTP_pred_Q14, 4 ) ); - xq_Q10 = SKP_ADD32( LPC_exc_Q10, LPC_pred_Q10 ); - - /* Scale XQ back to normal level before saving */ - xq[ i ] = ( opus_int16 )SKP_SAT16( SKP_RSHIFT_ROUND( SKP_SMULWW( xq_Q10, Gain_Q16 ), 10 ) ); - - /* Update states */ - psLPC_Q14++; - *psLPC_Q14 = SKP_LSHIFT( xq_Q10, 4 ); - sLF_AR_shp_Q10 = SKP_SUB32( xq_Q10, n_AR_Q10 ); - NSQ->sLF_AR_shp_Q12 = SKP_LSHIFT( sLF_AR_shp_Q10, 2 ); - - NSQ->sLTP_shp_Q10[ NSQ->sLTP_shp_buf_idx ] = SKP_SUB32( sLF_AR_shp_Q10, n_LF_Q10 ); - sLTP_Q16[ NSQ->sLTP_buf_idx ] = SKP_LSHIFT( LPC_exc_Q10, 6 ); - NSQ->sLTP_shp_buf_idx++; - NSQ->sLTP_buf_idx++; - - /* Make dither dependent on quantized signal */ - NSQ->rand_seed += pulses[ i ]; - } - - /* Update LPC synth buffer */ - SKP_memcpy( NSQ->sLPC_Q14, &NSQ->sLPC_Q14[ length ], NSQ_LPC_BUF_LENGTH * sizeof( opus_int32 ) ); -} - -SKP_INLINE void silk_nsq_scale_states( - const silk_encoder_state *psEncC, /* I Encoder State */ - silk_nsq_state *NSQ, /* I/O NSQ state */ - const opus_int16 x[], /* I input in Q0 */ - 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_Q16[], /* O LTP state matching scaled input */ - opus_int subfr, /* I subframe number */ - const opus_int LTP_scale_Q14, /* I */ - const opus_int32 Gains_Q16[ MAX_NB_SUBFR ], /* I */ - const opus_int pitchL[ MAX_NB_SUBFR ] /* I */ -) -{ - opus_int i, lag; - opus_int32 inv_gain_Q16, gain_adj_Q16, inv_gain_Q32; - - inv_gain_Q16 = silk_INVERSE32_varQ( SKP_max( Gains_Q16[ subfr ], 1 ), 32 ); - inv_gain_Q16 = SKP_min( inv_gain_Q16, SKP_int16_MAX ); - lag = pitchL[ subfr ]; - - /* After rewhitening the LTP state is un-scaled, so scale with inv_gain_Q16 */ - if( NSQ->rewhite_flag ) { - inv_gain_Q32 = SKP_LSHIFT( inv_gain_Q16, 16 ); - if( subfr == 0 ) { - /* Do LTP downscaling */ - inv_gain_Q32 = SKP_LSHIFT( SKP_SMULWB( inv_gain_Q32, LTP_scale_Q14 ), 2 ); - } - for( i = NSQ->sLTP_buf_idx - lag - LTP_ORDER / 2; i < NSQ->sLTP_buf_idx; i++ ) { - SKP_assert( i < MAX_FRAME_LENGTH ); - sLTP_Q16[ i ] = SKP_SMULWB( inv_gain_Q32, sLTP[ i ] ); - } - } - - /* Adjust for changing gain */ - if( inv_gain_Q16 != NSQ->prev_inv_gain_Q16 ) { - gain_adj_Q16 = silk_DIV32_varQ( inv_gain_Q16, NSQ->prev_inv_gain_Q16, 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_Q10[ i ] = SKP_SMULWW( gain_adj_Q16, NSQ->sLTP_shp_Q10[ i ] ); - } - - /* Scale long-term prediction state */ - if( NSQ->rewhite_flag == 0 ) { - for( i = NSQ->sLTP_buf_idx - lag - LTP_ORDER / 2; i < NSQ->sLTP_buf_idx; i++ ) { - sLTP_Q16[ i ] = SKP_SMULWW( gain_adj_Q16, sLTP_Q16[ i ] ); - } - } - - NSQ->sLF_AR_shp_Q12 = SKP_SMULWW( gain_adj_Q16, NSQ->sLF_AR_shp_Q12 ); - - /* Scale short-term prediction and shaping states */ - for( i = 0; i < NSQ_LPC_BUF_LENGTH; i++ ) { - NSQ->sLPC_Q14[ i ] = SKP_SMULWW( gain_adj_Q16, NSQ->sLPC_Q14[ i ] ); - } - for( i = 0; i < MAX_SHAPE_LPC_ORDER; i++ ) { - NSQ->sAR2_Q14[ i ] = SKP_SMULWW( gain_adj_Q16, NSQ->sAR2_Q14[ i ] ); - } - } - - /* Scale input */ - for( i = 0; i < psEncC->subfr_length; i++ ) { - x_sc_Q10[ i ] = SKP_RSHIFT( SKP_SMULBB( x[ i ], ( opus_int16 )inv_gain_Q16 ), 6 ); - } - - /* save inv_gain */ - SKP_assert( inv_gain_Q16 != 0 ); - NSQ->prev_inv_gain_Q16 = inv_gain_Q16; -} +/*********************************************************************** +Copyright (c) 2006-2011, Skype Limited. All rights reserved. +Redistribution and use in source and binary forms, with or without +modification, (subject to the limitations in the disclaimer below) +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 Skype Limited, nor the names of specific +contributors, may be used to endorse or promote products derived from +this software without specific prior written permission. +NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED +BY THIS LICENSE. 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. +***********************************************************************/ + +#include "silk_main.h" + +SKP_INLINE void silk_nsq_scale_states( + const silk_encoder_state *psEncC, /* I Encoder State */ + silk_nsq_state *NSQ, /* I/O NSQ state */ + const opus_int16 x[], /* I input in Q0 */ + 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_Q16[], /* O LTP state matching scaled input */ + opus_int subfr, /* I subframe number */ + const opus_int LTP_scale_Q14, /* I */ + const opus_int32 Gains_Q16[ MAX_NB_SUBFR ], /* I */ + const opus_int pitchL[ MAX_NB_SUBFR ] /* I */ +); + +SKP_INLINE void silk_noise_shape_quantizer( + silk_nsq_state *NSQ, /* I/O NSQ state */ + opus_int signalType, /* I Signal type */ + const opus_int32 x_sc_Q10[], /* I */ + opus_int8 pulses[], /* O */ + opus_int16 xq[], /* O */ + opus_int32 sLTP_Q16[], /* I/O LTP state */ + const opus_int16 a_Q12[], /* I Short term prediction coefs */ + const opus_int16 b_Q14[], /* I Long term prediction coefs */ + const opus_int16 AR_shp_Q13[], /* I Noise shaping AR coefs */ + opus_int lag, /* I Pitch lag */ + opus_int32 HarmShapeFIRPacked_Q14, /* I */ + opus_int Tilt_Q14, /* I Spectral tilt */ + opus_int32 LF_shp_Q14, /* I */ + opus_int32 Gain_Q16, /* I */ + opus_int Lambda_Q10, /* I */ + opus_int offset_Q10, /* I */ + opus_int length, /* I Input length */ + opus_int shapingLPCOrder, /* I Noise shaping AR filter order */ + opus_int predictLPCOrder /* I Prediction filter order */ +); + +void silk_NSQ( + const silk_encoder_state *psEncC, /* I/O Encoder State */ + silk_nsq_state *NSQ, /* I/O NSQ state */ + SideInfoIndices *psIndices, /* I/O Quantization Indices */ + const opus_int16 x[], /* I prefiltered input signal */ + opus_int8 pulses[], /* O quantized qulse signal */ + const opus_int16 PredCoef_Q12[ 2 * MAX_LPC_ORDER ], /* I Short term prediction coefficients */ + const opus_int16 LTPCoef_Q14[ LTP_ORDER * MAX_NB_SUBFR ], /* I Long term prediction coefficients */ + const opus_int16 AR2_Q13[ MAX_NB_SUBFR * MAX_SHAPE_LPC_ORDER ], /* I */ + const opus_int HarmShapeGain_Q14[ MAX_NB_SUBFR ], /* I */ + const opus_int Tilt_Q14[ MAX_NB_SUBFR ], /* I Spectral tilt */ + const opus_int32 LF_shp_Q14[ MAX_NB_SUBFR ], /* I */ + const opus_int32 Gains_Q16[ MAX_NB_SUBFR ], /* I */ + const opus_int pitchL[ MAX_NB_SUBFR ], /* I */ + const opus_int Lambda_Q10, /* I */ + const opus_int LTP_scale_Q14 /* I LTP state scaling */ +) +{ + opus_int k, lag, start_idx, LSF_interpolation_flag; + const opus_int16 *A_Q12, *B_Q14, *AR_shp_Q13; + opus_int16 *pxq; + opus_int32 sLTP_Q16[ 2 * MAX_FRAME_LENGTH ]; + opus_int16 sLTP[ 2 * MAX_FRAME_LENGTH ]; + opus_int32 HarmShapeFIRPacked_Q14; + opus_int offset_Q10; + opus_int32 x_sc_Q10[ MAX_FRAME_LENGTH / MAX_NB_SUBFR ]; + + NSQ->rand_seed = psIndices->Seed; + + /* Set unvoiced lag to the previous one, overwrite later for voiced */ + lag = NSQ->lagPrev; + + SKP_assert( NSQ->prev_inv_gain_Q16 != 0 ); + + offset_Q10 = silk_Quantization_Offsets_Q10[ psIndices->signalType >> 1 ][ psIndices->quantOffsetType ]; + + if( psIndices->NLSFInterpCoef_Q2 == 4 ) { + LSF_interpolation_flag = 0; + } else { + LSF_interpolation_flag = 1; + } + + /* Setup pointers to start of sub frame */ + NSQ->sLTP_shp_buf_idx = psEncC->ltp_mem_length; + NSQ->sLTP_buf_idx = psEncC->ltp_mem_length; + pxq = &NSQ->xq[ psEncC->ltp_mem_length ]; + for( k = 0; k < psEncC->nb_subfr; k++ ) { + A_Q12 = &PredCoef_Q12[ (( k >> 1 ) | ( 1 - LSF_interpolation_flag )) * MAX_LPC_ORDER ]; + B_Q14 = <PCoef_Q14[ k * LTP_ORDER ]; + AR_shp_Q13 = &AR2_Q13[ k * MAX_SHAPE_LPC_ORDER ]; + + /* Noise shape parameters */ + SKP_assert( HarmShapeGain_Q14[ k ] >= 0 ); + HarmShapeFIRPacked_Q14 = SKP_RSHIFT( HarmShapeGain_Q14[ k ], 2 ); + HarmShapeFIRPacked_Q14 |= SKP_LSHIFT( ( opus_int32 )SKP_RSHIFT( HarmShapeGain_Q14[ k ], 1 ), 16 ); + + NSQ->rewhite_flag = 0; + if( psIndices->signalType == TYPE_VOICED ) { + /* Voiced */ + lag = pitchL[ k ]; + + /* Re-whitening */ + if( ( k & ( 3 - SKP_LSHIFT( LSF_interpolation_flag, 1 ) ) ) == 0 ) { + /* Rewhiten with new A coefs */ + start_idx = psEncC->ltp_mem_length - lag - psEncC->predictLPCOrder - LTP_ORDER / 2; + SKP_assert( start_idx > 0 ); + + silk_LPC_analysis_filter( &sLTP[ start_idx ], &NSQ->xq[ start_idx + k * psEncC->subfr_length ], + A_Q12, psEncC->ltp_mem_length - start_idx, psEncC->predictLPCOrder ); + + NSQ->rewhite_flag = 1; + NSQ->sLTP_buf_idx = psEncC->ltp_mem_length; + } + } + + silk_nsq_scale_states( psEncC, NSQ, x, x_sc_Q10, sLTP, sLTP_Q16, k, LTP_scale_Q14, Gains_Q16, pitchL ); + + silk_noise_shape_quantizer( NSQ, psIndices->signalType, x_sc_Q10, pulses, pxq, sLTP_Q16, 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 ); + + x += psEncC->subfr_length; + pulses += psEncC->subfr_length; + pxq += psEncC->subfr_length; + } + + /* Update lagPrev for next frame */ + NSQ->lagPrev = pitchL[ psEncC->nb_subfr - 1 ]; + + /* Save quantized speech and noise shaping signals */ + SKP_memmove( NSQ->xq, &NSQ->xq[ psEncC->frame_length ], psEncC->ltp_mem_length * sizeof( opus_int16 ) ); + SKP_memmove( NSQ->sLTP_shp_Q10, &NSQ->sLTP_shp_Q10[ psEncC->frame_length ], psEncC->ltp_mem_length * sizeof( opus_int32 ) ); + +#ifdef SAVE_ALL_INTERNAL_DATA + DEBUG_STORE_DATA( xq.dat, &pxq[ -psEncC->frame_length ], psEncC->frame_length * sizeof( opus_int16 ) ); + DEBUG_STORE_DATA( q.dat, &pulses[ -psEncC->frame_length ], psEncC->frame_length * sizeof( opus_int8 ) ); + DEBUG_STORE_DATA( sLTP_Q16.dat, &sLTP_Q16[ psEncC->ltp_mem_length ], psEncC->frame_length * sizeof( opus_int32 ) ); +#endif +} + +/***********************************/ +/* silk_noise_shape_quantizer */ +/***********************************/ +SKP_INLINE void silk_noise_shape_quantizer( + silk_nsq_state *NSQ, /* I/O NSQ state */ + opus_int signalType, /* I Signal type */ + const opus_int32 x_sc_Q10[], /* I */ + opus_int8 pulses[], /* O */ + opus_int16 xq[], /* O */ + opus_int32 sLTP_Q16[], /* I/O LTP state */ + const opus_int16 a_Q12[], /* I Short term prediction coefs */ + const opus_int16 b_Q14[], /* I Long term prediction coefs */ + const opus_int16 AR_shp_Q13[], /* I Noise shaping AR coefs */ + opus_int lag, /* I Pitch lag */ + opus_int32 HarmShapeFIRPacked_Q14, /* I */ + opus_int Tilt_Q14, /* I Spectral tilt */ + opus_int32 LF_shp_Q14, /* I */ + opus_int32 Gain_Q16, /* I */ + opus_int Lambda_Q10, /* I */ + opus_int offset_Q10, /* I */ + opus_int length, /* I Input length */ + opus_int shapingLPCOrder, /* I Noise shaping AR filter order */ + opus_int predictLPCOrder /* I Prediction filter order */ +) +{ + opus_int i, j; + opus_int32 LTP_pred_Q14, LPC_pred_Q10, n_AR_Q10, n_LTP_Q14; + opus_int32 n_LF_Q10, r_Q10, rr_Q10, q1_Q10, q2_Q10, rd1_Q10, rd2_Q10; + opus_int32 dither, exc_Q10, LPC_exc_Q10, xq_Q10; + opus_int32 tmp1, tmp2, sLF_AR_shp_Q10; + opus_int32 *psLPC_Q14, *shp_lag_ptr, *pred_lag_ptr; + + shp_lag_ptr = &NSQ->sLTP_shp_Q10[ NSQ->sLTP_shp_buf_idx - lag + HARM_SHAPE_FIR_TAPS / 2 ]; + pred_lag_ptr = &sLTP_Q16[ NSQ->sLTP_buf_idx - lag + LTP_ORDER / 2 ]; + + /* Setup short term AR state */ + psLPC_Q14 = &NSQ->sLPC_Q14[ NSQ_LPC_BUF_LENGTH - 1 ]; + + for( i = 0; i < length; i++ ) { + /* Generate dither */ + NSQ->rand_seed = SKP_RAND( NSQ->rand_seed ); + + /* dither = rand_seed < 0 ? 0xFFFFFFFF : 0; */ + dither = SKP_RSHIFT( NSQ->rand_seed, 31 ); + + /* Short-term prediction */ + SKP_assert( ( predictLPCOrder & 1 ) == 0 ); /* check that order is even */ + SKP_assert( ( (opus_int64)a_Q12 & 3 ) == 0 ); /* check that array starts at 4-byte aligned address */ + SKP_assert( predictLPCOrder >= 10 ); /* check that unrolling works */ + + /* Partially unrolled */ + LPC_pred_Q10 = SKP_SMULWB( psLPC_Q14[ 0 ], a_Q12[ 0 ] ); + LPC_pred_Q10 = SKP_SMLAWB( LPC_pred_Q10, psLPC_Q14[ -1 ], a_Q12[ 1 ] ); + LPC_pred_Q10 = SKP_SMLAWB( LPC_pred_Q10, psLPC_Q14[ -2 ], a_Q12[ 2 ] ); + LPC_pred_Q10 = SKP_SMLAWB( LPC_pred_Q10, psLPC_Q14[ -3 ], a_Q12[ 3 ] ); + LPC_pred_Q10 = SKP_SMLAWB( LPC_pred_Q10, psLPC_Q14[ -4 ], a_Q12[ 4 ] ); + LPC_pred_Q10 = SKP_SMLAWB( LPC_pred_Q10, psLPC_Q14[ -5 ], a_Q12[ 5 ] ); + LPC_pred_Q10 = SKP_SMLAWB( LPC_pred_Q10, psLPC_Q14[ -6 ], a_Q12[ 6 ] ); + LPC_pred_Q10 = SKP_SMLAWB( LPC_pred_Q10, psLPC_Q14[ -7 ], a_Q12[ 7 ] ); + LPC_pred_Q10 = SKP_SMLAWB( LPC_pred_Q10, psLPC_Q14[ -8 ], a_Q12[ 8 ] ); + LPC_pred_Q10 = SKP_SMLAWB( LPC_pred_Q10, psLPC_Q14[ -9 ], a_Q12[ 9 ] ); + for( j = 10; j < predictLPCOrder; j ++ ) { + LPC_pred_Q10 = SKP_SMLAWB( LPC_pred_Q10, psLPC_Q14[ -j ], a_Q12[ j ] ); + } + + /* Long-term prediction */ + if( signalType == TYPE_VOICED ) { + /* Unrolled loop */ + LTP_pred_Q14 = SKP_SMULWB( pred_lag_ptr[ 0 ], b_Q14[ 0 ] ); + LTP_pred_Q14 = SKP_SMLAWB( LTP_pred_Q14, pred_lag_ptr[ -1 ], b_Q14[ 1 ] ); + LTP_pred_Q14 = SKP_SMLAWB( LTP_pred_Q14, pred_lag_ptr[ -2 ], b_Q14[ 2 ] ); + LTP_pred_Q14 = SKP_SMLAWB( LTP_pred_Q14, pred_lag_ptr[ -3 ], b_Q14[ 3 ] ); + LTP_pred_Q14 = SKP_SMLAWB( LTP_pred_Q14, pred_lag_ptr[ -4 ], b_Q14[ 4 ] ); + pred_lag_ptr++; + } else { + LTP_pred_Q14 = 0; + } + + /* Noise shape feedback */ + SKP_assert( ( shapingLPCOrder & 1 ) == 0 ); /* check that order is even */ + tmp2 = psLPC_Q14[ 0 ]; + tmp1 = NSQ->sAR2_Q14[ 0 ]; + NSQ->sAR2_Q14[ 0 ] = tmp2; + n_AR_Q10 = SKP_SMULWB( tmp2, AR_shp_Q13[ 0 ] ); + for( j = 2; j < shapingLPCOrder; j += 2 ) { + tmp2 = NSQ->sAR2_Q14[ j - 1 ]; + NSQ->sAR2_Q14[ j - 1 ] = tmp1; + n_AR_Q10 = SKP_SMLAWB( n_AR_Q10, tmp1, AR_shp_Q13[ j - 1 ] ); + tmp1 = NSQ->sAR2_Q14[ j + 0 ]; + NSQ->sAR2_Q14[ j + 0 ] = tmp2; + n_AR_Q10 = SKP_SMLAWB( n_AR_Q10, tmp2, AR_shp_Q13[ j ] ); + } + NSQ->sAR2_Q14[ shapingLPCOrder - 1 ] = tmp1; + n_AR_Q10 = SKP_SMLAWB( n_AR_Q10, tmp1, AR_shp_Q13[ shapingLPCOrder - 1 ] ); + + n_AR_Q10 = SKP_RSHIFT( n_AR_Q10, 1 ); /* Q11 -> Q10 */ + n_AR_Q10 = SKP_SMLAWB( n_AR_Q10, NSQ->sLF_AR_shp_Q12, Tilt_Q14 ); + + n_LF_Q10 = SKP_LSHIFT( SKP_SMULWB( NSQ->sLTP_shp_Q10[ NSQ->sLTP_shp_buf_idx - 1 ], LF_shp_Q14 ), 2 ); + n_LF_Q10 = SKP_SMLAWT( n_LF_Q10, NSQ->sLF_AR_shp_Q12, LF_shp_Q14 ); + + SKP_assert( lag > 0 || signalType != TYPE_VOICED ); + + /* Long-term shaping */ + if( lag > 0 ) { + /* Symmetric, packed FIR coefficients */ + n_LTP_Q14 = SKP_SMULWB( SKP_ADD32( shp_lag_ptr[ 0 ], shp_lag_ptr[ -2 ] ), HarmShapeFIRPacked_Q14 ); + n_LTP_Q14 = SKP_SMLAWT( n_LTP_Q14, shp_lag_ptr[ -1 ], HarmShapeFIRPacked_Q14 ); + n_LTP_Q14 = SKP_LSHIFT( n_LTP_Q14, 6 ); + shp_lag_ptr++; + + tmp1 = SKP_SUB32( LTP_pred_Q14, n_LTP_Q14 ); /* Add Q14 stuff */ + tmp1 = SKP_RSHIFT( tmp1, 4 ); /* convert to Q10 */ + tmp1 = SKP_ADD32( tmp1, LPC_pred_Q10 ); /* add Q10 stuff */ + tmp1 = SKP_SUB32( tmp1, n_AR_Q10 ); /* subtract Q10 stuff */ + } else { + tmp1 = SKP_SUB32( LPC_pred_Q10, n_AR_Q10 ); /* subtract Q10 stuff */ + } + + /* Input minus prediction plus noise feedback */ + //r = x[ i ] - LTP_pred - LPC_pred + n_AR + n_Tilt + n_LF + n_LTP; + tmp1 = SKP_SUB32( tmp1, n_LF_Q10 ); /* subtract Q10 stuff */ + r_Q10 = SKP_SUB32( x_sc_Q10[ i ], tmp1 ); + + /* Flip sign depending on dither */ + r_Q10 = r_Q10 ^ dither; + r_Q10 = SKP_LIMIT_32( r_Q10, -31 << 10, 30 << 10 ); + + /* Find two quantization level candidates and measure their rate-distortion */ + q1_Q10 = SKP_SUB32( r_Q10, offset_Q10 ); + q1_Q10 = SKP_RSHIFT( q1_Q10, 10 ); + if( q1_Q10 > 0 ) { + q1_Q10 = SKP_SUB32( SKP_LSHIFT( q1_Q10, 10 ), QUANT_LEVEL_ADJUST_Q10 ); + q1_Q10 = SKP_ADD32( q1_Q10, offset_Q10 ); + q2_Q10 = SKP_ADD32( q1_Q10, 1024 ); + rd1_Q10 = SKP_SMULBB( q1_Q10, Lambda_Q10 ); + rd2_Q10 = SKP_SMULBB( q2_Q10, Lambda_Q10 ); + } else if( q1_Q10 == 0 ) { + q1_Q10 = offset_Q10; + q2_Q10 = SKP_ADD32( q1_Q10, 1024 - QUANT_LEVEL_ADJUST_Q10 ); + rd1_Q10 = SKP_SMULBB( q1_Q10, Lambda_Q10 ); + rd2_Q10 = SKP_SMULBB( q2_Q10, Lambda_Q10 ); + } else if( q1_Q10 == -1 ) { + q2_Q10 = offset_Q10; + q1_Q10 = SKP_SUB32( q2_Q10, 1024 - QUANT_LEVEL_ADJUST_Q10 ); + rd1_Q10 = SKP_SMULBB( -q1_Q10, Lambda_Q10 ); + rd2_Q10 = SKP_SMULBB( q2_Q10, Lambda_Q10 ); + } else { /* Q1_Q10 < -1 */ + q1_Q10 = SKP_ADD32( SKP_LSHIFT( q1_Q10, 10 ), QUANT_LEVEL_ADJUST_Q10 ); + q1_Q10 = SKP_ADD32( q1_Q10, offset_Q10 ); + q2_Q10 = SKP_ADD32( q1_Q10, 1024 ); + rd1_Q10 = SKP_SMULBB( -q1_Q10, Lambda_Q10 ); + rd2_Q10 = SKP_SMULBB( -q2_Q10, Lambda_Q10 ); + } + rr_Q10 = SKP_SUB32( r_Q10, q1_Q10 ); + rd1_Q10 = SKP_RSHIFT( SKP_SMLABB( rd1_Q10, rr_Q10, rr_Q10 ), 10 ); + rr_Q10 = SKP_SUB32( r_Q10, q2_Q10 ); + rd2_Q10 = SKP_RSHIFT( SKP_SMLABB( rd2_Q10, rr_Q10, rr_Q10 ), 10 ); + + if( rd2_Q10 < rd1_Q10 ) { + q1_Q10 = q2_Q10; + } + + pulses[ i ] = ( opus_int8 )SKP_RSHIFT_ROUND( q1_Q10, 10 ); + + /* Excitation */ + exc_Q10 = q1_Q10 ^ dither; + + /* Add predictions */ + LPC_exc_Q10 = SKP_ADD32( exc_Q10, SKP_RSHIFT_ROUND( LTP_pred_Q14, 4 ) ); + xq_Q10 = SKP_ADD32( LPC_exc_Q10, LPC_pred_Q10 ); + + /* Scale XQ back to normal level before saving */ + xq[ i ] = ( opus_int16 )SKP_SAT16( SKP_RSHIFT_ROUND( SKP_SMULWW( xq_Q10, Gain_Q16 ), 10 ) ); + + /* Update states */ + psLPC_Q14++; + *psLPC_Q14 = SKP_LSHIFT( xq_Q10, 4 ); + sLF_AR_shp_Q10 = SKP_SUB32( xq_Q10, n_AR_Q10 ); + NSQ->sLF_AR_shp_Q12 = SKP_LSHIFT( sLF_AR_shp_Q10, 2 ); + + NSQ->sLTP_shp_Q10[ NSQ->sLTP_shp_buf_idx ] = SKP_SUB32( sLF_AR_shp_Q10, n_LF_Q10 ); + sLTP_Q16[ NSQ->sLTP_buf_idx ] = SKP_LSHIFT( LPC_exc_Q10, 6 ); + NSQ->sLTP_shp_buf_idx++; + NSQ->sLTP_buf_idx++; + + /* Make dither dependent on quantized signal */ + NSQ->rand_seed += pulses[ i ]; + } + + /* Update LPC synth buffer */ + SKP_memcpy( NSQ->sLPC_Q14, &NSQ->sLPC_Q14[ length ], NSQ_LPC_BUF_LENGTH * sizeof( opus_int32 ) ); +} + +SKP_INLINE void silk_nsq_scale_states( + const silk_encoder_state *psEncC, /* I Encoder State */ + silk_nsq_state *NSQ, /* I/O NSQ state */ + const opus_int16 x[], /* I input in Q0 */ + 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_Q16[], /* O LTP state matching scaled input */ + opus_int subfr, /* I subframe number */ + const opus_int LTP_scale_Q14, /* I */ + const opus_int32 Gains_Q16[ MAX_NB_SUBFR ], /* I */ + const opus_int pitchL[ MAX_NB_SUBFR ] /* I */ +) +{ + opus_int i, lag; + opus_int32 inv_gain_Q16, gain_adj_Q16, inv_gain_Q32; + + inv_gain_Q16 = silk_INVERSE32_varQ( SKP_max( Gains_Q16[ subfr ], 1 ), 32 ); + inv_gain_Q16 = SKP_min( inv_gain_Q16, SKP_int16_MAX ); + lag = pitchL[ subfr ]; + + /* After rewhitening the LTP state is un-scaled, so scale with inv_gain_Q16 */ + if( NSQ->rewhite_flag ) { + inv_gain_Q32 = SKP_LSHIFT( inv_gain_Q16, 16 ); + if( subfr == 0 ) { + /* Do LTP downscaling */ + inv_gain_Q32 = SKP_LSHIFT( SKP_SMULWB( inv_gain_Q32, LTP_scale_Q14 ), 2 ); + } + for( i = NSQ->sLTP_buf_idx - lag - LTP_ORDER / 2; i < NSQ->sLTP_buf_idx; i++ ) { + SKP_assert( i < MAX_FRAME_LENGTH ); + sLTP_Q16[ i ] = SKP_SMULWB( inv_gain_Q32, sLTP[ i ] ); + } + } + + /* Adjust for changing gain */ + if( inv_gain_Q16 != NSQ->prev_inv_gain_Q16 ) { + gain_adj_Q16 = silk_DIV32_varQ( inv_gain_Q16, NSQ->prev_inv_gain_Q16, 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_Q10[ i ] = SKP_SMULWW( gain_adj_Q16, NSQ->sLTP_shp_Q10[ i ] ); + } + + /* Scale long-term prediction state */ + if( NSQ->rewhite_flag == 0 ) { + for( i = NSQ->sLTP_buf_idx - lag - LTP_ORDER / 2; i < NSQ->sLTP_buf_idx; i++ ) { + sLTP_Q16[ i ] = SKP_SMULWW( gain_adj_Q16, sLTP_Q16[ i ] ); + } + } + + NSQ->sLF_AR_shp_Q12 = SKP_SMULWW( gain_adj_Q16, NSQ->sLF_AR_shp_Q12 ); + + /* Scale short-term prediction and shaping states */ + for( i = 0; i < NSQ_LPC_BUF_LENGTH; i++ ) { + NSQ->sLPC_Q14[ i ] = SKP_SMULWW( gain_adj_Q16, NSQ->sLPC_Q14[ i ] ); + } + for( i = 0; i < MAX_SHAPE_LPC_ORDER; i++ ) { + NSQ->sAR2_Q14[ i ] = SKP_SMULWW( gain_adj_Q16, NSQ->sAR2_Q14[ i ] ); + } + } + + /* Scale input */ + for( i = 0; i < psEncC->subfr_length; i++ ) { + x_sc_Q10[ i ] = SKP_RSHIFT( SKP_SMULBB( x[ i ], ( opus_int16 )inv_gain_Q16 ), 6 ); + } + + /* save inv_gain */ + SKP_assert( inv_gain_Q16 != 0 ); + NSQ->prev_inv_gain_Q16 = inv_gain_Q16; +} diff --git a/silk/silk_NSQ_del_dec.c b/silk/silk_NSQ_del_dec.c index d335015e2..68b92e767 100644 --- a/silk/silk_NSQ_del_dec.c +++ b/silk/silk_NSQ_del_dec.c @@ -1,680 +1,680 @@ -/*********************************************************************** -Copyright (c) 2006-2011, Skype Limited. All rights reserved. -Redistribution and use in source and binary forms, with or without -modification, (subject to the limitations in the disclaimer below) -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 Skype Limited, nor the names of specific -contributors, may be used to endorse or promote products derived from -this software without specific prior written permission. -NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED -BY THIS LICENSE. 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. -***********************************************************************/ - -#include "silk_main.h" - -typedef struct { - opus_int32 sLPC_Q14[ MAX_FRAME_LENGTH / MAX_NB_SUBFR + NSQ_LPC_BUF_LENGTH ]; - opus_int32 RandState[ DECISION_DELAY ]; - opus_int32 Q_Q10[ DECISION_DELAY ]; - opus_int32 Xq_Q10[ DECISION_DELAY ]; - opus_int32 Pred_Q16[ DECISION_DELAY ]; - opus_int32 Shape_Q10[ DECISION_DELAY ]; - opus_int32 sAR2_Q14[ MAX_SHAPE_LPC_ORDER ]; - opus_int32 LF_AR_Q12; - opus_int32 Seed; - opus_int32 SeedInit; - opus_int32 RD_Q10; -} NSQ_del_dec_struct; - -typedef struct { - opus_int32 Q_Q10; - opus_int32 RD_Q10; - opus_int32 xq_Q14; - opus_int32 LF_AR_Q12; - opus_int32 sLTP_shp_Q10; - opus_int32 LPC_exc_Q16; -} NSQ_sample_struct; - -SKP_INLINE void silk_nsq_del_dec_scale_states( - const silk_encoder_state *psEncC, /* I Encoder State */ - silk_nsq_state *NSQ, /* I/O NSQ state */ - NSQ_del_dec_struct psDelDec[], /* I/O Delayed decision states */ - const opus_int16 x[], /* I Input in Q0 */ - opus_int32 x_sc_Q10[], /* O Input scaled with 1/Gain in Q10 */ - const opus_int16 sLTP[], /* I Re-whitened LTP state in Q0 */ - opus_int32 sLTP_Q16[], /* O LTP state matching scaled input */ - opus_int subfr, /* I Subframe number */ - opus_int nStatesDelayedDecision, /* I Number of del dec states */ - opus_int smpl_buf_idx, /* I Index to newest samples in buffers */ - const opus_int LTP_scale_Q14, /* I LTP state scaling */ - const opus_int32 Gains_Q16[ MAX_NB_SUBFR ], /* I */ - const opus_int pitchL[ MAX_NB_SUBFR ] /* I Pitch lag */ -); - -/******************************************/ -/* Noise shape quantizer for one subframe */ -/******************************************/ -SKP_INLINE void silk_noise_shape_quantizer_del_dec( - silk_nsq_state *NSQ, /* I/O NSQ state */ - NSQ_del_dec_struct psDelDec[], /* I/O Delayed decision states */ - opus_int signalType, /* I Signal type */ - const opus_int32 x_Q10[], /* I */ - opus_int8 pulses[], /* O */ - opus_int16 xq[], /* O */ - opus_int32 sLTP_Q16[], /* I/O LTP filter state */ - opus_int32 delayedGain_Q16[], /* I/O Gain delay buffer */ - const opus_int16 a_Q12[], /* I Short term prediction coefs */ - const opus_int16 b_Q14[], /* I Long term prediction coefs */ - const opus_int16 AR_shp_Q13[], /* I Noise shaping coefs */ - opus_int lag, /* I Pitch lag */ - opus_int32 HarmShapeFIRPacked_Q14, /* I */ - opus_int Tilt_Q14, /* I Spectral tilt */ - opus_int32 LF_shp_Q14, /* I */ - opus_int32 Gain_Q16, /* I */ - opus_int Lambda_Q10, /* I */ - opus_int offset_Q10, /* I */ - opus_int length, /* I Input length */ - opus_int subfr, /* I Subframe number */ - opus_int shapingLPCOrder, /* I Shaping LPC filter order */ - opus_int predictLPCOrder, /* I Prediction filter order */ - opus_int warping_Q16, /* I */ - opus_int nStatesDelayedDecision, /* I Number of states in decision tree */ - opus_int *smpl_buf_idx, /* I Index to newest samples in buffers */ - opus_int decisionDelay /* I */ -); - -void silk_NSQ_del_dec( - const silk_encoder_state *psEncC, /* I/O Encoder State */ - silk_nsq_state *NSQ, /* I/O NSQ state */ - SideInfoIndices *psIndices, /* I/O Quantization Indices */ - const opus_int16 x[], /* I Prefiltered input signal */ - opus_int8 pulses[], /* O Quantized pulse signal */ - const opus_int16 PredCoef_Q12[ 2 * MAX_LPC_ORDER ], /* I Prediction coefs */ - const opus_int16 LTPCoef_Q14[ LTP_ORDER * MAX_NB_SUBFR ], /* I LT prediction coefs */ - const opus_int16 AR2_Q13[ MAX_NB_SUBFR * MAX_SHAPE_LPC_ORDER ], /* I */ - const opus_int HarmShapeGain_Q14[ MAX_NB_SUBFR ], /* I */ - const opus_int Tilt_Q14[ MAX_NB_SUBFR ], /* I Spectral tilt */ - const opus_int32 LF_shp_Q14[ MAX_NB_SUBFR ], /* I */ - const opus_int32 Gains_Q16[ MAX_NB_SUBFR ], /* I */ - const opus_int pitchL[ MAX_NB_SUBFR ], /* I */ - const opus_int Lambda_Q10, /* I */ - const opus_int LTP_scale_Q14 /* I LTP state scaling */ -) -{ - opus_int i, k, lag, start_idx, LSF_interpolation_flag, Winner_ind, subfr; - opus_int last_smple_idx, smpl_buf_idx, decisionDelay; - const opus_int16 *A_Q12, *B_Q14, *AR_shp_Q13; - opus_int16 *pxq; - opus_int32 sLTP_Q16[ 2 * MAX_FRAME_LENGTH ]; - opus_int16 sLTP[ 2 * MAX_FRAME_LENGTH ]; - opus_int32 HarmShapeFIRPacked_Q14; - opus_int offset_Q10; - opus_int32 RDmin_Q10; - opus_int32 x_sc_Q10[ MAX_SUB_FRAME_LENGTH ]; - opus_int32 delayedGain_Q16[ DECISION_DELAY ]; - NSQ_del_dec_struct psDelDec[ MAX_DEL_DEC_STATES ]; - NSQ_del_dec_struct *psDD; - - /* Set unvoiced lag to the previous one, overwrite later for voiced */ - lag = NSQ->lagPrev; - - SKP_assert( NSQ->prev_inv_gain_Q16 != 0 ); - - /* Initialize delayed decision states */ - SKP_memset( psDelDec, 0, psEncC->nStatesDelayedDecision * sizeof( NSQ_del_dec_struct ) ); - for( k = 0; k < psEncC->nStatesDelayedDecision; k++ ) { - psDD = &psDelDec[ k ]; - psDD->Seed = ( k + psIndices->Seed ) & 3; - psDD->SeedInit = psDD->Seed; - psDD->RD_Q10 = 0; - psDD->LF_AR_Q12 = NSQ->sLF_AR_shp_Q12; - psDD->Shape_Q10[ 0 ] = NSQ->sLTP_shp_Q10[ psEncC->ltp_mem_length - 1 ]; - SKP_memcpy( psDD->sLPC_Q14, NSQ->sLPC_Q14, NSQ_LPC_BUF_LENGTH * sizeof( opus_int32 ) ); - SKP_memcpy( psDD->sAR2_Q14, NSQ->sAR2_Q14, sizeof( NSQ->sAR2_Q14 ) ); - } - - offset_Q10 = silk_Quantization_Offsets_Q10[ psIndices->signalType >> 1 ][ psIndices->quantOffsetType ]; - smpl_buf_idx = 0; /* index of oldest samples */ - - decisionDelay = SKP_min_int( DECISION_DELAY, psEncC->subfr_length ); - - /* For voiced frames limit the decision delay to lower than the pitch lag */ - if( psIndices->signalType == TYPE_VOICED ) { - for( k = 0; k < psEncC->nb_subfr; k++ ) { - decisionDelay = SKP_min_int( decisionDelay, pitchL[ k ] - LTP_ORDER / 2 - 1 ); - } - } else { - if( lag > 0 ) { - decisionDelay = SKP_min_int( decisionDelay, lag - LTP_ORDER / 2 - 1 ); - } - } - - if( psIndices->NLSFInterpCoef_Q2 == 4 ) { - LSF_interpolation_flag = 0; - } else { - LSF_interpolation_flag = 1; - } - - /* Setup pointers to start of sub frame */ - pxq = &NSQ->xq[ psEncC->ltp_mem_length ]; - NSQ->sLTP_shp_buf_idx = psEncC->ltp_mem_length; - NSQ->sLTP_buf_idx = psEncC->ltp_mem_length; - subfr = 0; - for( k = 0; k < psEncC->nb_subfr; k++ ) { - A_Q12 = &PredCoef_Q12[ ( ( k >> 1 ) | ( 1 - LSF_interpolation_flag ) ) * MAX_LPC_ORDER ]; - B_Q14 = <PCoef_Q14[ k * LTP_ORDER ]; - AR_shp_Q13 = &AR2_Q13[ k * MAX_SHAPE_LPC_ORDER ]; - - /* Noise shape parameters */ - SKP_assert( HarmShapeGain_Q14[ k ] >= 0 ); - HarmShapeFIRPacked_Q14 = SKP_RSHIFT( HarmShapeGain_Q14[ k ], 2 ); - HarmShapeFIRPacked_Q14 |= SKP_LSHIFT( ( opus_int32 )SKP_RSHIFT( HarmShapeGain_Q14[ k ], 1 ), 16 ); - - NSQ->rewhite_flag = 0; - if( psIndices->signalType == TYPE_VOICED ) { - /* Voiced */ - lag = pitchL[ k ]; - - /* Re-whitening */ - if( ( k & ( 3 - SKP_LSHIFT( LSF_interpolation_flag, 1 ) ) ) == 0 ) { - if( k == 2 ) { - /* RESET DELAYED DECISIONS */ - /* Find winner */ - RDmin_Q10 = psDelDec[ 0 ].RD_Q10; - Winner_ind = 0; - for( i = 1; i < psEncC->nStatesDelayedDecision; i++ ) { - if( psDelDec[ i ].RD_Q10 < RDmin_Q10 ) { - RDmin_Q10 = psDelDec[ i ].RD_Q10; - Winner_ind = i; - } - } - for( i = 0; i < psEncC->nStatesDelayedDecision; i++ ) { - if( i != Winner_ind ) { - psDelDec[ i ].RD_Q10 += ( SKP_int32_MAX >> 4 ); - SKP_assert( psDelDec[ i ].RD_Q10 >= 0 ); - } - } - - /* Copy final part of signals from winner state to output and long-term filter states */ - psDD = &psDelDec[ Winner_ind ]; - last_smple_idx = smpl_buf_idx + decisionDelay; - for( i = 0; i < decisionDelay; i++ ) { - last_smple_idx = ( last_smple_idx - 1 ) & DECISION_DELAY_MASK; - pulses[ i - decisionDelay ] = ( opus_int8 )SKP_RSHIFT_ROUND( psDD->Q_Q10[ last_smple_idx ], 10 ); - pxq[ i - decisionDelay ] = ( opus_int16 )SKP_SAT16( SKP_RSHIFT_ROUND( - SKP_SMULWW( psDD->Xq_Q10[ last_smple_idx ], Gains_Q16[ 1 ] ), 10 ) ); - NSQ->sLTP_shp_Q10[ NSQ->sLTP_shp_buf_idx - decisionDelay + i ] = psDD->Shape_Q10[ last_smple_idx ]; - } - - subfr = 0; - } - - /* Rewhiten with new A coefs */ - start_idx = psEncC->ltp_mem_length - lag - psEncC->predictLPCOrder - LTP_ORDER / 2; - SKP_assert( start_idx > 0 ); - - silk_LPC_analysis_filter( &sLTP[ start_idx ], &NSQ->xq[ start_idx + k * psEncC->subfr_length ], - A_Q12, psEncC->ltp_mem_length - start_idx, psEncC->predictLPCOrder ); - - NSQ->sLTP_buf_idx = psEncC->ltp_mem_length; - NSQ->rewhite_flag = 1; - } - } - - silk_nsq_del_dec_scale_states( psEncC, NSQ, psDelDec, x, x_sc_Q10, sLTP, sLTP_Q16, k, - psEncC->nStatesDelayedDecision, smpl_buf_idx, LTP_scale_Q14, Gains_Q16, pitchL ); - - silk_noise_shape_quantizer_del_dec( NSQ, psDelDec, psIndices->signalType, x_sc_Q10, pulses, pxq, sLTP_Q16, - delayedGain_Q16, 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, subfr++, psEncC->shapingLPCOrder, - psEncC->predictLPCOrder, psEncC->warping_Q16, psEncC->nStatesDelayedDecision, &smpl_buf_idx, decisionDelay ); - - x += psEncC->subfr_length; - pulses += psEncC->subfr_length; - pxq += psEncC->subfr_length; - } - - /* Find winner */ - RDmin_Q10 = psDelDec[ 0 ].RD_Q10; - Winner_ind = 0; - for( k = 1; k < psEncC->nStatesDelayedDecision; k++ ) { - if( psDelDec[ k ].RD_Q10 < RDmin_Q10 ) { - RDmin_Q10 = psDelDec[ k ].RD_Q10; - Winner_ind = k; - } - } - - /* Copy final part of signals from winner state to output and long-term filter states */ - psDD = &psDelDec[ Winner_ind ]; - psIndices->Seed = psDD->SeedInit; - last_smple_idx = smpl_buf_idx + decisionDelay; - for( i = 0; i < decisionDelay; i++ ) { - last_smple_idx = ( last_smple_idx - 1 ) & DECISION_DELAY_MASK; - pulses[ i - decisionDelay ] = ( opus_int8 )SKP_RSHIFT_ROUND( psDD->Q_Q10[ last_smple_idx ], 10 ); - pxq[ i - decisionDelay ] = ( opus_int16 )SKP_SAT16( SKP_RSHIFT_ROUND( - SKP_SMULWW( psDD->Xq_Q10[ last_smple_idx ], Gains_Q16[ psEncC->nb_subfr - 1 ] ), 10 ) ); - NSQ->sLTP_shp_Q10[ NSQ->sLTP_shp_buf_idx - decisionDelay + i ] = psDD->Shape_Q10[ last_smple_idx ]; - sLTP_Q16[ NSQ->sLTP_buf_idx - decisionDelay + i ] = psDD->Pred_Q16[ last_smple_idx ]; - } - SKP_memcpy( NSQ->sLPC_Q14, &psDD->sLPC_Q14[ psEncC->subfr_length ], NSQ_LPC_BUF_LENGTH * sizeof( opus_int32 ) ); - SKP_memcpy( NSQ->sAR2_Q14, psDD->sAR2_Q14, sizeof( psDD->sAR2_Q14 ) ); - - /* Update states */ - NSQ->sLF_AR_shp_Q12 = psDD->LF_AR_Q12; - NSQ->lagPrev = pitchL[ psEncC->nb_subfr - 1 ]; - - /* Save quantized speech and noise shaping signals */ - SKP_memmove( NSQ->xq, &NSQ->xq[ psEncC->frame_length ], psEncC->ltp_mem_length * sizeof( opus_int16 ) ); - SKP_memmove( NSQ->sLTP_shp_Q10, &NSQ->sLTP_shp_Q10[ psEncC->frame_length ], psEncC->ltp_mem_length * sizeof( opus_int32 ) ); - -#ifdef SAVE_ALL_INTERNAL_DATA - DEBUG_STORE_DATA( xq.dat, &pxq[ -psEncC->frame_length ], psEncC->frame_length * sizeof( opus_int16 ) ); - DEBUG_STORE_DATA( q.dat, &pulses[ -psEncC->frame_length ], psEncC->frame_length * sizeof( opus_int8 ) ); - DEBUG_STORE_DATA( sLTP_Q16.dat, &sLTP_Q16[ psEncC->ltp_mem_length ], psEncC->frame_length * sizeof( opus_int32 ) ); -#endif -} - -/******************************************/ -/* Noise shape quantizer for one subframe */ -/******************************************/ -SKP_INLINE void silk_noise_shape_quantizer_del_dec( - silk_nsq_state *NSQ, /* I/O NSQ state */ - NSQ_del_dec_struct psDelDec[], /* I/O Delayed decision states */ - opus_int signalType, /* I Signal type */ - const opus_int32 x_Q10[], /* I */ - opus_int8 pulses[], /* O */ - opus_int16 xq[], /* O */ - opus_int32 sLTP_Q16[], /* I/O LTP filter state */ - opus_int32 delayedGain_Q16[], /* I/O Gain delay buffer */ - const opus_int16 a_Q12[], /* I Short term prediction coefs */ - const opus_int16 b_Q14[], /* I Long term prediction coefs */ - const opus_int16 AR_shp_Q13[], /* I Noise shaping coefs */ - opus_int lag, /* I Pitch lag */ - opus_int32 HarmShapeFIRPacked_Q14, /* I */ - opus_int Tilt_Q14, /* I Spectral tilt */ - opus_int32 LF_shp_Q14, /* I */ - opus_int32 Gain_Q16, /* I */ - opus_int Lambda_Q10, /* I */ - opus_int offset_Q10, /* I */ - opus_int length, /* I Input length */ - opus_int subfr, /* I Subframe number */ - opus_int shapingLPCOrder, /* I Shaping LPC filter order */ - opus_int predictLPCOrder, /* I Prediction filter order */ - opus_int warping_Q16, /* I */ - opus_int nStatesDelayedDecision, /* I Number of states in decision tree */ - opus_int *smpl_buf_idx, /* I Index to newest samples in buffers */ - opus_int decisionDelay /* I */ -) -{ - opus_int i, j, k, Winner_ind, RDmin_ind, RDmax_ind, last_smple_idx; - opus_int32 Winner_rand_state; - opus_int32 LTP_pred_Q14, LPC_pred_Q10, n_AR_Q10, n_LTP_Q14, LTP_Q10; - opus_int32 n_LF_Q10, r_Q10, rr_Q10, rd1_Q10, rd2_Q10, RDmin_Q10, RDmax_Q10; - opus_int32 q1_Q10, q2_Q10, dither, exc_Q10, LPC_exc_Q10, xq_Q10; - opus_int32 tmp1, tmp2, sLF_AR_shp_Q10; - opus_int32 *pred_lag_ptr, *shp_lag_ptr, *psLPC_Q14; - NSQ_sample_struct psSampleState[ MAX_DEL_DEC_STATES ][ 2 ]; - NSQ_del_dec_struct *psDD; - NSQ_sample_struct *psSS; - - shp_lag_ptr = &NSQ->sLTP_shp_Q10[ NSQ->sLTP_shp_buf_idx - lag + HARM_SHAPE_FIR_TAPS / 2 ]; - pred_lag_ptr = &sLTP_Q16[ NSQ->sLTP_buf_idx - lag + LTP_ORDER / 2 ]; - - for( i = 0; i < length; i++ ) { - /* Perform common calculations used in all states */ - - /* Long-term prediction */ - if( signalType == TYPE_VOICED ) { - /* Unrolled loop */ - LTP_pred_Q14 = SKP_SMULWB( pred_lag_ptr[ 0 ], b_Q14[ 0 ] ); - LTP_pred_Q14 = SKP_SMLAWB( LTP_pred_Q14, pred_lag_ptr[ -1 ], b_Q14[ 1 ] ); - LTP_pred_Q14 = SKP_SMLAWB( LTP_pred_Q14, pred_lag_ptr[ -2 ], b_Q14[ 2 ] ); - LTP_pred_Q14 = SKP_SMLAWB( LTP_pred_Q14, pred_lag_ptr[ -3 ], b_Q14[ 3 ] ); - LTP_pred_Q14 = SKP_SMLAWB( LTP_pred_Q14, pred_lag_ptr[ -4 ], b_Q14[ 4 ] ); - pred_lag_ptr++; - } else { - LTP_pred_Q14 = 0; - } - - /* Long-term shaping */ - if( lag > 0 ) { - /* Symmetric, packed FIR coefficients */ - n_LTP_Q14 = SKP_SMULWB( SKP_ADD32( shp_lag_ptr[ 0 ], shp_lag_ptr[ -2 ] ), HarmShapeFIRPacked_Q14 ); - n_LTP_Q14 = SKP_SMLAWT( n_LTP_Q14, shp_lag_ptr[ -1 ], HarmShapeFIRPacked_Q14 ); - n_LTP_Q14 = SKP_LSHIFT( n_LTP_Q14, 6 ); - shp_lag_ptr++; - - LTP_Q10 = SKP_RSHIFT( SKP_SUB32( LTP_pred_Q14, n_LTP_Q14 ), 4 ); - } else { - LTP_Q10 = 0; - } - - for( k = 0; k < nStatesDelayedDecision; k++ ) { - /* Delayed decision state */ - psDD = &psDelDec[ k ]; - - /* Sample state */ - psSS = psSampleState[ k ]; - - /* Generate dither */ - psDD->Seed = SKP_RAND( psDD->Seed ); - - /* dither = rand_seed < 0 ? 0xFFFFFFFF : 0; */ - dither = SKP_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 */ - SKP_assert( predictLPCOrder >= 10 ); /* check that unrolling works */ - SKP_assert( ( predictLPCOrder & 1 ) == 0 ); /* check that order is even */ - SKP_assert( ( (opus_int64)a_Q12 & 3 ) == 0 ); /* check that array starts at 4-byte aligned address */ - /* Partially unrolled */ - LPC_pred_Q10 = SKP_SMULWB( psLPC_Q14[ 0 ], a_Q12[ 0 ] ); - LPC_pred_Q10 = SKP_SMLAWB( LPC_pred_Q10, psLPC_Q14[ -1 ], a_Q12[ 1 ] ); - LPC_pred_Q10 = SKP_SMLAWB( LPC_pred_Q10, psLPC_Q14[ -2 ], a_Q12[ 2 ] ); - LPC_pred_Q10 = SKP_SMLAWB( LPC_pred_Q10, psLPC_Q14[ -3 ], a_Q12[ 3 ] ); - LPC_pred_Q10 = SKP_SMLAWB( LPC_pred_Q10, psLPC_Q14[ -4 ], a_Q12[ 4 ] ); - LPC_pred_Q10 = SKP_SMLAWB( LPC_pred_Q10, psLPC_Q14[ -5 ], a_Q12[ 5 ] ); - LPC_pred_Q10 = SKP_SMLAWB( LPC_pred_Q10, psLPC_Q14[ -6 ], a_Q12[ 6 ] ); - LPC_pred_Q10 = SKP_SMLAWB( LPC_pred_Q10, psLPC_Q14[ -7 ], a_Q12[ 7 ] ); - LPC_pred_Q10 = SKP_SMLAWB( LPC_pred_Q10, psLPC_Q14[ -8 ], a_Q12[ 8 ] ); - LPC_pred_Q10 = SKP_SMLAWB( LPC_pred_Q10, psLPC_Q14[ -9 ], a_Q12[ 9 ] ); - for( j = 10; j < predictLPCOrder; j ++ ) { - LPC_pred_Q10 = SKP_SMLAWB( LPC_pred_Q10, psLPC_Q14[ -j ], a_Q12[ j ] ); - } - - /* Noise shape feedback */ - SKP_assert( ( shapingLPCOrder & 1 ) == 0 ); /* check that order is even */ - /* Output of lowpass section */ - tmp2 = SKP_SMLAWB( psLPC_Q14[ 0 ], psDD->sAR2_Q14[ 0 ], warping_Q16 ); - /* Output of allpass section */ - tmp1 = SKP_SMLAWB( psDD->sAR2_Q14[ 0 ], psDD->sAR2_Q14[ 1 ] - tmp2, warping_Q16 ); - psDD->sAR2_Q14[ 0 ] = tmp2; - n_AR_Q10 = SKP_SMULWB( tmp2, AR_shp_Q13[ 0 ] ); - /* Loop over allpass sections */ - for( j = 2; j < shapingLPCOrder; j += 2 ) { - /* Output of allpass section */ - tmp2 = SKP_SMLAWB( psDD->sAR2_Q14[ j - 1 ], psDD->sAR2_Q14[ j + 0 ] - tmp1, warping_Q16 ); - psDD->sAR2_Q14[ j - 1 ] = tmp1; - n_AR_Q10 = SKP_SMLAWB( n_AR_Q10, tmp1, AR_shp_Q13[ j - 1 ] ); - /* Output of allpass section */ - tmp1 = SKP_SMLAWB( psDD->sAR2_Q14[ j + 0 ], psDD->sAR2_Q14[ j + 1 ] - tmp2, warping_Q16 ); - psDD->sAR2_Q14[ j + 0 ] = tmp2; - n_AR_Q10 = SKP_SMLAWB( n_AR_Q10, tmp2, AR_shp_Q13[ j ] ); - } - psDD->sAR2_Q14[ shapingLPCOrder - 1 ] = tmp1; - n_AR_Q10 = SKP_SMLAWB( n_AR_Q10, tmp1, AR_shp_Q13[ shapingLPCOrder - 1 ] ); - - n_AR_Q10 = SKP_RSHIFT( n_AR_Q10, 1 ); /* Q11 -> Q10 */ - n_AR_Q10 = SKP_SMLAWB( n_AR_Q10, psDD->LF_AR_Q12, Tilt_Q14 ); - - n_LF_Q10 = SKP_LSHIFT( SKP_SMULWB( psDD->Shape_Q10[ *smpl_buf_idx ], LF_shp_Q14 ), 2 ); - n_LF_Q10 = SKP_SMLAWT( n_LF_Q10, psDD->LF_AR_Q12, LF_shp_Q14 ); - - /* Input minus prediction plus noise feedback */ - /* r = x[ i ] - LTP_pred - LPC_pred + n_AR + n_Tilt + n_LF + n_LTP */ - tmp1 = SKP_ADD32( LTP_Q10, LPC_pred_Q10 ); /* add Q10 stuff */ - tmp1 = SKP_SUB32( tmp1, n_AR_Q10 ); /* subtract Q10 stuff */ - tmp1 = SKP_SUB32( tmp1, n_LF_Q10 ); /* subtract Q10 stuff */ - r_Q10 = SKP_SUB32( x_Q10[ i ], tmp1 ); /* residual error Q10 */ - - /* Flip sign depending on dither */ - r_Q10 = r_Q10 ^ dither; - r_Q10 = SKP_LIMIT_32( r_Q10, -31 << 10, 30 << 10 ); - - /* Find two quantization level candidates and measure their rate-distortion */ - q1_Q10 = SKP_SUB32( r_Q10, offset_Q10 ); - q1_Q10 = SKP_RSHIFT( q1_Q10, 10 ); - if( q1_Q10 > 0 ) { - q1_Q10 = SKP_SUB32( SKP_LSHIFT( q1_Q10, 10 ), QUANT_LEVEL_ADJUST_Q10 ); - q1_Q10 = SKP_ADD32( q1_Q10, offset_Q10 ); - q2_Q10 = SKP_ADD32( q1_Q10, 1024 ); - rd1_Q10 = SKP_SMULBB( q1_Q10, Lambda_Q10 ); - rd2_Q10 = SKP_SMULBB( q2_Q10, Lambda_Q10 ); - } else if( q1_Q10 == 0 ) { - q1_Q10 = offset_Q10; - q2_Q10 = SKP_ADD32( q1_Q10, 1024 - QUANT_LEVEL_ADJUST_Q10 ); - rd1_Q10 = SKP_SMULBB( q1_Q10, Lambda_Q10 ); - rd2_Q10 = SKP_SMULBB( q2_Q10, Lambda_Q10 ); - } else if( q1_Q10 == -1 ) { - q2_Q10 = offset_Q10; - q1_Q10 = SKP_SUB32( q2_Q10, 1024 - QUANT_LEVEL_ADJUST_Q10 ); - rd1_Q10 = SKP_SMULBB( -q1_Q10, Lambda_Q10 ); - rd2_Q10 = SKP_SMULBB( q2_Q10, Lambda_Q10 ); - } else { /* Q1_Q10 < -1 */ - q1_Q10 = SKP_ADD32( SKP_LSHIFT( q1_Q10, 10 ), QUANT_LEVEL_ADJUST_Q10 ); - q1_Q10 = SKP_ADD32( q1_Q10, offset_Q10 ); - q2_Q10 = SKP_ADD32( q1_Q10, 1024 ); - rd1_Q10 = SKP_SMULBB( -q1_Q10, Lambda_Q10 ); - rd2_Q10 = SKP_SMULBB( -q2_Q10, Lambda_Q10 ); - } - rr_Q10 = SKP_SUB32( r_Q10, q1_Q10 ); - rd1_Q10 = SKP_RSHIFT( SKP_SMLABB( rd1_Q10, rr_Q10, rr_Q10 ), 10 ); - rr_Q10 = SKP_SUB32( r_Q10, q2_Q10 ); - rd2_Q10 = SKP_RSHIFT( SKP_SMLABB( rd2_Q10, rr_Q10, rr_Q10 ), 10 ); - - if( rd1_Q10 < rd2_Q10 ) { - psSS[ 0 ].RD_Q10 = SKP_ADD32( psDD->RD_Q10, rd1_Q10 ); - psSS[ 1 ].RD_Q10 = SKP_ADD32( psDD->RD_Q10, rd2_Q10 ); - psSS[ 0 ].Q_Q10 = q1_Q10; - psSS[ 1 ].Q_Q10 = q2_Q10; - } else { - psSS[ 0 ].RD_Q10 = SKP_ADD32( psDD->RD_Q10, rd2_Q10 ); - psSS[ 1 ].RD_Q10 = SKP_ADD32( psDD->RD_Q10, rd1_Q10 ); - psSS[ 0 ].Q_Q10 = q2_Q10; - psSS[ 1 ].Q_Q10 = q1_Q10; - } - - /* Update states for best quantization */ - - /* Quantized excitation */ - exc_Q10 = psSS[ 0 ].Q_Q10 ^ dither; - - /* Add predictions */ - LPC_exc_Q10 = exc_Q10 + SKP_RSHIFT_ROUND( LTP_pred_Q14, 4 ); - xq_Q10 = SKP_ADD32( LPC_exc_Q10, LPC_pred_Q10 ); - - /* Update states */ - sLF_AR_shp_Q10 = SKP_SUB32( xq_Q10, n_AR_Q10 ); - psSS[ 0 ].sLTP_shp_Q10 = SKP_SUB32( sLF_AR_shp_Q10, n_LF_Q10 ); - psSS[ 0 ].LF_AR_Q12 = SKP_LSHIFT( sLF_AR_shp_Q10, 2 ); - psSS[ 0 ].xq_Q14 = SKP_LSHIFT( xq_Q10, 4 ); - psSS[ 0 ].LPC_exc_Q16 = SKP_LSHIFT( LPC_exc_Q10, 6 ); - - /* Update states for second best quantization */ - - /* Quantized excitation */ - exc_Q10 = psSS[ 1 ].Q_Q10 ^ dither; - - /* Add predictions */ - LPC_exc_Q10 = exc_Q10 + SKP_RSHIFT_ROUND( LTP_pred_Q14, 4 ); - xq_Q10 = SKP_ADD32( LPC_exc_Q10, LPC_pred_Q10 ); - - /* Update states */ - sLF_AR_shp_Q10 = SKP_SUB32( xq_Q10, n_AR_Q10 ); - psSS[ 1 ].sLTP_shp_Q10 = SKP_SUB32( sLF_AR_shp_Q10, n_LF_Q10 ); - psSS[ 1 ].LF_AR_Q12 = SKP_LSHIFT( sLF_AR_shp_Q10, 2 ); - psSS[ 1 ].xq_Q14 = SKP_LSHIFT( xq_Q10, 4 ); - psSS[ 1 ].LPC_exc_Q16 = SKP_LSHIFT( LPC_exc_Q10, 6 ); - } - - *smpl_buf_idx = ( *smpl_buf_idx - 1 ) & DECISION_DELAY_MASK; /* Index to newest samples */ - last_smple_idx = ( *smpl_buf_idx + decisionDelay ) & DECISION_DELAY_MASK; /* Index to decisionDelay old samples */ - - /* Find winner */ - RDmin_Q10 = psSampleState[ 0 ][ 0 ].RD_Q10; - Winner_ind = 0; - for( k = 1; k < nStatesDelayedDecision; k++ ) { - if( psSampleState[ k ][ 0 ].RD_Q10 < RDmin_Q10 ) { - RDmin_Q10 = psSampleState[ k ][ 0 ].RD_Q10; - Winner_ind = k; - } - } - - /* Increase RD values of expired states */ - Winner_rand_state = psDelDec[ Winner_ind ].RandState[ last_smple_idx ]; - for( k = 0; k < nStatesDelayedDecision; k++ ) { - if( psDelDec[ k ].RandState[ last_smple_idx ] != Winner_rand_state ) { - psSampleState[ k ][ 0 ].RD_Q10 = SKP_ADD32( psSampleState[ k ][ 0 ].RD_Q10, ( SKP_int32_MAX >> 4 ) ); - psSampleState[ k ][ 1 ].RD_Q10 = SKP_ADD32( psSampleState[ k ][ 1 ].RD_Q10, ( SKP_int32_MAX >> 4 ) ); - SKP_assert( psSampleState[ k ][ 0 ].RD_Q10 >= 0 ); - } - } - - /* Find worst in first set and best in second set */ - RDmax_Q10 = psSampleState[ 0 ][ 0 ].RD_Q10; - RDmin_Q10 = psSampleState[ 0 ][ 1 ].RD_Q10; - RDmax_ind = 0; - RDmin_ind = 0; - for( k = 1; k < nStatesDelayedDecision; k++ ) { - /* find worst in first set */ - if( psSampleState[ k ][ 0 ].RD_Q10 > RDmax_Q10 ) { - RDmax_Q10 = psSampleState[ k ][ 0 ].RD_Q10; - RDmax_ind = k; - } - /* find best in second set */ - if( psSampleState[ k ][ 1 ].RD_Q10 < RDmin_Q10 ) { - RDmin_Q10 = psSampleState[ k ][ 1 ].RD_Q10; - RDmin_ind = k; - } - } - - /* Replace a state if best from second set outperforms worst in first set */ - if( RDmin_Q10 < RDmax_Q10 ) { - SKP_memcpy( ((opus_int32 *)&psDelDec[ RDmax_ind ]) + i, - ((opus_int32 *)&psDelDec[ RDmin_ind ]) + i, sizeof( NSQ_del_dec_struct ) - i * sizeof( opus_int32) ); - SKP_memcpy( &psSampleState[ RDmax_ind ][ 0 ], &psSampleState[ RDmin_ind ][ 1 ], sizeof( NSQ_sample_struct ) ); - } - - /* Write samples from winner to output and long-term filter states */ - psDD = &psDelDec[ Winner_ind ]; - if( subfr > 0 || i >= decisionDelay ) { - pulses[ i - decisionDelay ] = ( opus_int8 )SKP_RSHIFT_ROUND( psDD->Q_Q10[ last_smple_idx ], 10 ); - xq[ i - decisionDelay ] = ( opus_int16 )SKP_SAT16( SKP_RSHIFT_ROUND( - SKP_SMULWW( psDD->Xq_Q10[ last_smple_idx ], delayedGain_Q16[ last_smple_idx ] ), 10 ) ); - NSQ->sLTP_shp_Q10[ NSQ->sLTP_shp_buf_idx - decisionDelay ] = psDD->Shape_Q10[ last_smple_idx ]; - sLTP_Q16[ NSQ->sLTP_buf_idx - decisionDelay ] = psDD->Pred_Q16[ last_smple_idx ]; - } - NSQ->sLTP_shp_buf_idx++; - NSQ->sLTP_buf_idx++; - - /* Update states */ - for( k = 0; k < nStatesDelayedDecision; k++ ) { - psDD = &psDelDec[ k ]; - psSS = &psSampleState[ k ][ 0 ]; - psDD->LF_AR_Q12 = psSS->LF_AR_Q12; - psDD->sLPC_Q14[ NSQ_LPC_BUF_LENGTH + i ] = psSS->xq_Q14; - psDD->Xq_Q10[ *smpl_buf_idx ] = SKP_RSHIFT( psSS->xq_Q14, 4 ); - psDD->Q_Q10[ *smpl_buf_idx ] = psSS->Q_Q10; - psDD->Pred_Q16[ *smpl_buf_idx ] = psSS->LPC_exc_Q16; - psDD->Shape_Q10[ *smpl_buf_idx ] = psSS->sLTP_shp_Q10; - psDD->Seed = SKP_ADD32( psDD->Seed, SKP_RSHIFT_ROUND( psSS->Q_Q10, 10 ) ); - psDD->RandState[ *smpl_buf_idx ] = psDD->Seed; - psDD->RD_Q10 = psSS->RD_Q10; - } - delayedGain_Q16[ *smpl_buf_idx ] = Gain_Q16; - } - /* Update LPC states */ - for( k = 0; k < nStatesDelayedDecision; k++ ) { - psDD = &psDelDec[ k ]; - SKP_memcpy( psDD->sLPC_Q14, &psDD->sLPC_Q14[ length ], NSQ_LPC_BUF_LENGTH * sizeof( opus_int32 ) ); - } -} - -SKP_INLINE void silk_nsq_del_dec_scale_states( - const silk_encoder_state *psEncC, /* I Encoder State */ - silk_nsq_state *NSQ, /* I/O NSQ state */ - NSQ_del_dec_struct psDelDec[], /* I/O Delayed decision states */ - const opus_int16 x[], /* I Input in Q0 */ - opus_int32 x_sc_Q10[], /* O Input scaled with 1/Gain in Q10 */ - const opus_int16 sLTP[], /* I Re-whitened LTP state in Q0 */ - opus_int32 sLTP_Q16[], /* O LTP state matching scaled input */ - opus_int subfr, /* I Subframe number */ - opus_int nStatesDelayedDecision, /* I Number of del dec states */ - opus_int smpl_buf_idx, /* I Index to newest samples in buffers */ - const opus_int LTP_scale_Q14, /* I LTP state scaling */ - const opus_int32 Gains_Q16[ MAX_NB_SUBFR ], /* I */ - const opus_int pitchL[ MAX_NB_SUBFR ] /* I Pitch lag */ -) -{ - opus_int i, k, lag; - opus_int32 inv_gain_Q16, gain_adj_Q16, inv_gain_Q32; - NSQ_del_dec_struct *psDD; - - inv_gain_Q16 = silk_INVERSE32_varQ( SKP_max( Gains_Q16[ subfr ], 1 ), 32 ); - inv_gain_Q16 = SKP_min( inv_gain_Q16, SKP_int16_MAX ); - lag = pitchL[ subfr ]; - - /* After rewhitening the LTP state is un-scaled, so scale with inv_gain_Q16 */ - if( NSQ->rewhite_flag ) { - inv_gain_Q32 = SKP_LSHIFT( inv_gain_Q16, 16 ); - if( subfr == 0 ) { - /* Do LTP downscaling */ - inv_gain_Q32 = SKP_LSHIFT( SKP_SMULWB( inv_gain_Q32, LTP_scale_Q14 ), 2 ); - } - for( i = NSQ->sLTP_buf_idx - lag - LTP_ORDER / 2; i < NSQ->sLTP_buf_idx; i++ ) { - SKP_assert( i < MAX_FRAME_LENGTH ); - sLTP_Q16[ i ] = SKP_SMULWB( inv_gain_Q32, sLTP[ i ] ); - } - } - - /* Adjust for changing gain */ - if( inv_gain_Q16 != NSQ->prev_inv_gain_Q16 ) { - gain_adj_Q16 = silk_DIV32_varQ( inv_gain_Q16, NSQ->prev_inv_gain_Q16, 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_Q10[ i ] = SKP_SMULWW( gain_adj_Q16, NSQ->sLTP_shp_Q10[ i ] ); - } - - /* Scale long-term prediction state */ - if( NSQ->rewhite_flag == 0 ) { - for( i = NSQ->sLTP_buf_idx - lag - LTP_ORDER / 2; i < NSQ->sLTP_buf_idx; i++ ) { - sLTP_Q16[ i ] = SKP_SMULWW( gain_adj_Q16, sLTP_Q16[ i ] ); - } - } - - for( k = 0; k < nStatesDelayedDecision; k++ ) { - psDD = &psDelDec[ k ]; - - /* Scale scalar states */ - psDD->LF_AR_Q12 = SKP_SMULWW( gain_adj_Q16, psDD->LF_AR_Q12 ); - - /* Scale short-term prediction and shaping states */ - for( i = 0; i < NSQ_LPC_BUF_LENGTH; i++ ) { - psDD->sLPC_Q14[ i ] = SKP_SMULWW( gain_adj_Q16, psDD->sLPC_Q14[ i ] ); - } - for( i = 0; i < MAX_SHAPE_LPC_ORDER; i++ ) { - psDD->sAR2_Q14[ i ] = SKP_SMULWW( gain_adj_Q16, psDD->sAR2_Q14[ i ] ); - } - for( i = 0; i < DECISION_DELAY; i++ ) { - psDD->Pred_Q16[ i ] = SKP_SMULWW( gain_adj_Q16, psDD->Pred_Q16[ i ] ); - psDD->Shape_Q10[ i ] = SKP_SMULWW( gain_adj_Q16, psDD->Shape_Q10[ i ] ); - } - } - } - - /* Scale input */ - for( i = 0; i < psEncC->subfr_length; i++ ) { - x_sc_Q10[ i ] = SKP_RSHIFT( SKP_SMULBB( x[ i ], ( opus_int16 )inv_gain_Q16 ), 6 ); - } - - /* save inv_gain */ - SKP_assert( inv_gain_Q16 != 0 ); - NSQ->prev_inv_gain_Q16 = inv_gain_Q16; -} +/*********************************************************************** +Copyright (c) 2006-2011, Skype Limited. All rights reserved. +Redistribution and use in source and binary forms, with or without +modification, (subject to the limitations in the disclaimer below) +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 Skype Limited, nor the names of specific +contributors, may be used to endorse or promote products derived from +this software without specific prior written permission. +NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED +BY THIS LICENSE. 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. +***********************************************************************/ + +#include "silk_main.h" + +typedef struct { + opus_int32 sLPC_Q14[ MAX_FRAME_LENGTH / MAX_NB_SUBFR + NSQ_LPC_BUF_LENGTH ]; + opus_int32 RandState[ DECISION_DELAY ]; + opus_int32 Q_Q10[ DECISION_DELAY ]; + opus_int32 Xq_Q10[ DECISION_DELAY ]; + opus_int32 Pred_Q16[ DECISION_DELAY ]; + opus_int32 Shape_Q10[ DECISION_DELAY ]; + opus_int32 sAR2_Q14[ MAX_SHAPE_LPC_ORDER ]; + opus_int32 LF_AR_Q12; + opus_int32 Seed; + opus_int32 SeedInit; + opus_int32 RD_Q10; +} NSQ_del_dec_struct; + +typedef struct { + opus_int32 Q_Q10; + opus_int32 RD_Q10; + opus_int32 xq_Q14; + opus_int32 LF_AR_Q12; + opus_int32 sLTP_shp_Q10; + opus_int32 LPC_exc_Q16; +} NSQ_sample_struct; + +SKP_INLINE void silk_nsq_del_dec_scale_states( + const silk_encoder_state *psEncC, /* I Encoder State */ + silk_nsq_state *NSQ, /* I/O NSQ state */ + NSQ_del_dec_struct psDelDec[], /* I/O Delayed decision states */ + const opus_int16 x[], /* I Input in Q0 */ + opus_int32 x_sc_Q10[], /* O Input scaled with 1/Gain in Q10 */ + const opus_int16 sLTP[], /* I Re-whitened LTP state in Q0 */ + opus_int32 sLTP_Q16[], /* O LTP state matching scaled input */ + opus_int subfr, /* I Subframe number */ + opus_int nStatesDelayedDecision, /* I Number of del dec states */ + opus_int smpl_buf_idx, /* I Index to newest samples in buffers */ + const opus_int LTP_scale_Q14, /* I LTP state scaling */ + const opus_int32 Gains_Q16[ MAX_NB_SUBFR ], /* I */ + const opus_int pitchL[ MAX_NB_SUBFR ] /* I Pitch lag */ +); + +/******************************************/ +/* Noise shape quantizer for one subframe */ +/******************************************/ +SKP_INLINE void silk_noise_shape_quantizer_del_dec( + silk_nsq_state *NSQ, /* I/O NSQ state */ + NSQ_del_dec_struct psDelDec[], /* I/O Delayed decision states */ + opus_int signalType, /* I Signal type */ + const opus_int32 x_Q10[], /* I */ + opus_int8 pulses[], /* O */ + opus_int16 xq[], /* O */ + opus_int32 sLTP_Q16[], /* I/O LTP filter state */ + opus_int32 delayedGain_Q16[], /* I/O Gain delay buffer */ + const opus_int16 a_Q12[], /* I Short term prediction coefs */ + const opus_int16 b_Q14[], /* I Long term prediction coefs */ + const opus_int16 AR_shp_Q13[], /* I Noise shaping coefs */ + opus_int lag, /* I Pitch lag */ + opus_int32 HarmShapeFIRPacked_Q14, /* I */ + opus_int Tilt_Q14, /* I Spectral tilt */ + opus_int32 LF_shp_Q14, /* I */ + opus_int32 Gain_Q16, /* I */ + opus_int Lambda_Q10, /* I */ + opus_int offset_Q10, /* I */ + opus_int length, /* I Input length */ + opus_int subfr, /* I Subframe number */ + opus_int shapingLPCOrder, /* I Shaping LPC filter order */ + opus_int predictLPCOrder, /* I Prediction filter order */ + opus_int warping_Q16, /* I */ + opus_int nStatesDelayedDecision, /* I Number of states in decision tree */ + opus_int *smpl_buf_idx, /* I Index to newest samples in buffers */ + opus_int decisionDelay /* I */ +); + +void silk_NSQ_del_dec( + const silk_encoder_state *psEncC, /* I/O Encoder State */ + silk_nsq_state *NSQ, /* I/O NSQ state */ + SideInfoIndices *psIndices, /* I/O Quantization Indices */ + const opus_int16 x[], /* I Prefiltered input signal */ + opus_int8 pulses[], /* O Quantized pulse signal */ + const opus_int16 PredCoef_Q12[ 2 * MAX_LPC_ORDER ], /* I Prediction coefs */ + const opus_int16 LTPCoef_Q14[ LTP_ORDER * MAX_NB_SUBFR ], /* I LT prediction coefs */ + const opus_int16 AR2_Q13[ MAX_NB_SUBFR * MAX_SHAPE_LPC_ORDER ], /* I */ + const opus_int HarmShapeGain_Q14[ MAX_NB_SUBFR ], /* I */ + const opus_int Tilt_Q14[ MAX_NB_SUBFR ], /* I Spectral tilt */ + const opus_int32 LF_shp_Q14[ MAX_NB_SUBFR ], /* I */ + const opus_int32 Gains_Q16[ MAX_NB_SUBFR ], /* I */ + const opus_int pitchL[ MAX_NB_SUBFR ], /* I */ + const opus_int Lambda_Q10, /* I */ + const opus_int LTP_scale_Q14 /* I LTP state scaling */ +) +{ + opus_int i, k, lag, start_idx, LSF_interpolation_flag, Winner_ind, subfr; + opus_int last_smple_idx, smpl_buf_idx, decisionDelay; + const opus_int16 *A_Q12, *B_Q14, *AR_shp_Q13; + opus_int16 *pxq; + opus_int32 sLTP_Q16[ 2 * MAX_FRAME_LENGTH ]; + opus_int16 sLTP[ 2 * MAX_FRAME_LENGTH ]; + opus_int32 HarmShapeFIRPacked_Q14; + opus_int offset_Q10; + opus_int32 RDmin_Q10; + opus_int32 x_sc_Q10[ MAX_SUB_FRAME_LENGTH ]; + opus_int32 delayedGain_Q16[ DECISION_DELAY ]; + NSQ_del_dec_struct psDelDec[ MAX_DEL_DEC_STATES ]; + NSQ_del_dec_struct *psDD; + + /* Set unvoiced lag to the previous one, overwrite later for voiced */ + lag = NSQ->lagPrev; + + SKP_assert( NSQ->prev_inv_gain_Q16 != 0 ); + + /* Initialize delayed decision states */ + SKP_memset( psDelDec, 0, psEncC->nStatesDelayedDecision * sizeof( NSQ_del_dec_struct ) ); + for( k = 0; k < psEncC->nStatesDelayedDecision; k++ ) { + psDD = &psDelDec[ k ]; + psDD->Seed = ( k + psIndices->Seed ) & 3; + psDD->SeedInit = psDD->Seed; + psDD->RD_Q10 = 0; + psDD->LF_AR_Q12 = NSQ->sLF_AR_shp_Q12; + psDD->Shape_Q10[ 0 ] = NSQ->sLTP_shp_Q10[ psEncC->ltp_mem_length - 1 ]; + SKP_memcpy( psDD->sLPC_Q14, NSQ->sLPC_Q14, NSQ_LPC_BUF_LENGTH * sizeof( opus_int32 ) ); + SKP_memcpy( psDD->sAR2_Q14, NSQ->sAR2_Q14, sizeof( NSQ->sAR2_Q14 ) ); + } + + offset_Q10 = silk_Quantization_Offsets_Q10[ psIndices->signalType >> 1 ][ psIndices->quantOffsetType ]; + smpl_buf_idx = 0; /* index of oldest samples */ + + decisionDelay = SKP_min_int( DECISION_DELAY, psEncC->subfr_length ); + + /* For voiced frames limit the decision delay to lower than the pitch lag */ + if( psIndices->signalType == TYPE_VOICED ) { + for( k = 0; k < psEncC->nb_subfr; k++ ) { + decisionDelay = SKP_min_int( decisionDelay, pitchL[ k ] - LTP_ORDER / 2 - 1 ); + } + } else { + if( lag > 0 ) { + decisionDelay = SKP_min_int( decisionDelay, lag - LTP_ORDER / 2 - 1 ); + } + } + + if( psIndices->NLSFInterpCoef_Q2 == 4 ) { + LSF_interpolation_flag = 0; + } else { + LSF_interpolation_flag = 1; + } + + /* Setup pointers to start of sub frame */ + pxq = &NSQ->xq[ psEncC->ltp_mem_length ]; + NSQ->sLTP_shp_buf_idx = psEncC->ltp_mem_length; + NSQ->sLTP_buf_idx = psEncC->ltp_mem_length; + subfr = 0; + for( k = 0; k < psEncC->nb_subfr; k++ ) { + A_Q12 = &PredCoef_Q12[ ( ( k >> 1 ) | ( 1 - LSF_interpolation_flag ) ) * MAX_LPC_ORDER ]; + B_Q14 = <PCoef_Q14[ k * LTP_ORDER ]; + AR_shp_Q13 = &AR2_Q13[ k * MAX_SHAPE_LPC_ORDER ]; + + /* Noise shape parameters */ + SKP_assert( HarmShapeGain_Q14[ k ] >= 0 ); + HarmShapeFIRPacked_Q14 = SKP_RSHIFT( HarmShapeGain_Q14[ k ], 2 ); + HarmShapeFIRPacked_Q14 |= SKP_LSHIFT( ( opus_int32 )SKP_RSHIFT( HarmShapeGain_Q14[ k ], 1 ), 16 ); + + NSQ->rewhite_flag = 0; + if( psIndices->signalType == TYPE_VOICED ) { + /* Voiced */ + lag = pitchL[ k ]; + + /* Re-whitening */ + if( ( k & ( 3 - SKP_LSHIFT( LSF_interpolation_flag, 1 ) ) ) == 0 ) { + if( k == 2 ) { + /* RESET DELAYED DECISIONS */ + /* Find winner */ + RDmin_Q10 = psDelDec[ 0 ].RD_Q10; + Winner_ind = 0; + for( i = 1; i < psEncC->nStatesDelayedDecision; i++ ) { + if( psDelDec[ i ].RD_Q10 < RDmin_Q10 ) { + RDmin_Q10 = psDelDec[ i ].RD_Q10; + Winner_ind = i; + } + } + for( i = 0; i < psEncC->nStatesDelayedDecision; i++ ) { + if( i != Winner_ind ) { + psDelDec[ i ].RD_Q10 += ( SKP_int32_MAX >> 4 ); + SKP_assert( psDelDec[ i ].RD_Q10 >= 0 ); + } + } + + /* Copy final part of signals from winner state to output and long-term filter states */ + psDD = &psDelDec[ Winner_ind ]; + last_smple_idx = smpl_buf_idx + decisionDelay; + for( i = 0; i < decisionDelay; i++ ) { + last_smple_idx = ( last_smple_idx - 1 ) & DECISION_DELAY_MASK; + pulses[ i - decisionDelay ] = ( opus_int8 )SKP_RSHIFT_ROUND( psDD->Q_Q10[ last_smple_idx ], 10 ); + pxq[ i - decisionDelay ] = ( opus_int16 )SKP_SAT16( SKP_RSHIFT_ROUND( + SKP_SMULWW( psDD->Xq_Q10[ last_smple_idx ], Gains_Q16[ 1 ] ), 10 ) ); + NSQ->sLTP_shp_Q10[ NSQ->sLTP_shp_buf_idx - decisionDelay + i ] = psDD->Shape_Q10[ last_smple_idx ]; + } + + subfr = 0; + } + + /* Rewhiten with new A coefs */ + start_idx = psEncC->ltp_mem_length - lag - psEncC->predictLPCOrder - LTP_ORDER / 2; + SKP_assert( start_idx > 0 ); + + silk_LPC_analysis_filter( &sLTP[ start_idx ], &NSQ->xq[ start_idx + k * psEncC->subfr_length ], + A_Q12, psEncC->ltp_mem_length - start_idx, psEncC->predictLPCOrder ); + + NSQ->sLTP_buf_idx = psEncC->ltp_mem_length; + NSQ->rewhite_flag = 1; + } + } + + silk_nsq_del_dec_scale_states( psEncC, NSQ, psDelDec, x, x_sc_Q10, sLTP, sLTP_Q16, k, + psEncC->nStatesDelayedDecision, smpl_buf_idx, LTP_scale_Q14, Gains_Q16, pitchL ); + + silk_noise_shape_quantizer_del_dec( NSQ, psDelDec, psIndices->signalType, x_sc_Q10, pulses, pxq, sLTP_Q16, + delayedGain_Q16, 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, subfr++, psEncC->shapingLPCOrder, + psEncC->predictLPCOrder, psEncC->warping_Q16, psEncC->nStatesDelayedDecision, &smpl_buf_idx, decisionDelay ); + + x += psEncC->subfr_length; + pulses += psEncC->subfr_length; + pxq += psEncC->subfr_length; + } + + /* Find winner */ + RDmin_Q10 = psDelDec[ 0 ].RD_Q10; + Winner_ind = 0; + for( k = 1; k < psEncC->nStatesDelayedDecision; k++ ) { + if( psDelDec[ k ].RD_Q10 < RDmin_Q10 ) { + RDmin_Q10 = psDelDec[ k ].RD_Q10; + Winner_ind = k; + } + } + + /* Copy final part of signals from winner state to output and long-term filter states */ + psDD = &psDelDec[ Winner_ind ]; + psIndices->Seed = psDD->SeedInit; + last_smple_idx = smpl_buf_idx + decisionDelay; + for( i = 0; i < decisionDelay; i++ ) { + last_smple_idx = ( last_smple_idx - 1 ) & DECISION_DELAY_MASK; + pulses[ i - decisionDelay ] = ( opus_int8 )SKP_RSHIFT_ROUND( psDD->Q_Q10[ last_smple_idx ], 10 ); + pxq[ i - decisionDelay ] = ( opus_int16 )SKP_SAT16( SKP_RSHIFT_ROUND( + SKP_SMULWW( psDD->Xq_Q10[ last_smple_idx ], Gains_Q16[ psEncC->nb_subfr - 1 ] ), 10 ) ); + NSQ->sLTP_shp_Q10[ NSQ->sLTP_shp_buf_idx - decisionDelay + i ] = psDD->Shape_Q10[ last_smple_idx ]; + sLTP_Q16[ NSQ->sLTP_buf_idx - decisionDelay + i ] = psDD->Pred_Q16[ last_smple_idx ]; + } + SKP_memcpy( NSQ->sLPC_Q14, &psDD->sLPC_Q14[ psEncC->subfr_length ], NSQ_LPC_BUF_LENGTH * sizeof( opus_int32 ) ); + SKP_memcpy( NSQ->sAR2_Q14, psDD->sAR2_Q14, sizeof( psDD->sAR2_Q14 ) ); + + /* Update states */ + NSQ->sLF_AR_shp_Q12 = psDD->LF_AR_Q12; + NSQ->lagPrev = pitchL[ psEncC->nb_subfr - 1 ]; + + /* Save quantized speech and noise shaping signals */ + SKP_memmove( NSQ->xq, &NSQ->xq[ psEncC->frame_length ], psEncC->ltp_mem_length * sizeof( opus_int16 ) ); + SKP_memmove( NSQ->sLTP_shp_Q10, &NSQ->sLTP_shp_Q10[ psEncC->frame_length ], psEncC->ltp_mem_length * sizeof( opus_int32 ) ); + +#ifdef SAVE_ALL_INTERNAL_DATA + DEBUG_STORE_DATA( xq.dat, &pxq[ -psEncC->frame_length ], psEncC->frame_length * sizeof( opus_int16 ) ); + DEBUG_STORE_DATA( q.dat, &pulses[ -psEncC->frame_length ], psEncC->frame_length * sizeof( opus_int8 ) ); + DEBUG_STORE_DATA( sLTP_Q16.dat, &sLTP_Q16[ psEncC->ltp_mem_length ], psEncC->frame_length * sizeof( opus_int32 ) ); +#endif +} + +/******************************************/ +/* Noise shape quantizer for one subframe */ +/******************************************/ +SKP_INLINE void silk_noise_shape_quantizer_del_dec( + silk_nsq_state *NSQ, /* I/O NSQ state */ + NSQ_del_dec_struct psDelDec[], /* I/O Delayed decision states */ + opus_int signalType, /* I Signal type */ + const opus_int32 x_Q10[], /* I */ + opus_int8 pulses[], /* O */ + opus_int16 xq[], /* O */ + opus_int32 sLTP_Q16[], /* I/O LTP filter state */ + opus_int32 delayedGain_Q16[], /* I/O Gain delay buffer */ + const opus_int16 a_Q12[], /* I Short term prediction coefs */ + const opus_int16 b_Q14[], /* I Long term prediction coefs */ + const opus_int16 AR_shp_Q13[], /* I Noise shaping coefs */ + opus_int lag, /* I Pitch lag */ + opus_int32 HarmShapeFIRPacked_Q14, /* I */ + opus_int Tilt_Q14, /* I Spectral tilt */ + opus_int32 LF_shp_Q14, /* I */ + opus_int32 Gain_Q16, /* I */ + opus_int Lambda_Q10, /* I */ + opus_int offset_Q10, /* I */ + opus_int length, /* I Input length */ + opus_int subfr, /* I Subframe number */ + opus_int shapingLPCOrder, /* I Shaping LPC filter order */ + opus_int predictLPCOrder, /* I Prediction filter order */ + opus_int warping_Q16, /* I */ + opus_int nStatesDelayedDecision, /* I Number of states in decision tree */ + opus_int *smpl_buf_idx, /* I Index to newest samples in buffers */ + opus_int decisionDelay /* I */ +) +{ + opus_int i, j, k, Winner_ind, RDmin_ind, RDmax_ind, last_smple_idx; + opus_int32 Winner_rand_state; + opus_int32 LTP_pred_Q14, LPC_pred_Q10, n_AR_Q10, n_LTP_Q14, LTP_Q10; + opus_int32 n_LF_Q10, r_Q10, rr_Q10, rd1_Q10, rd2_Q10, RDmin_Q10, RDmax_Q10; + opus_int32 q1_Q10, q2_Q10, dither, exc_Q10, LPC_exc_Q10, xq_Q10; + opus_int32 tmp1, tmp2, sLF_AR_shp_Q10; + opus_int32 *pred_lag_ptr, *shp_lag_ptr, *psLPC_Q14; + NSQ_sample_struct psSampleState[ MAX_DEL_DEC_STATES ][ 2 ]; + NSQ_del_dec_struct *psDD; + NSQ_sample_struct *psSS; + + shp_lag_ptr = &NSQ->sLTP_shp_Q10[ NSQ->sLTP_shp_buf_idx - lag + HARM_SHAPE_FIR_TAPS / 2 ]; + pred_lag_ptr = &sLTP_Q16[ NSQ->sLTP_buf_idx - lag + LTP_ORDER / 2 ]; + + for( i = 0; i < length; i++ ) { + /* Perform common calculations used in all states */ + + /* Long-term prediction */ + if( signalType == TYPE_VOICED ) { + /* Unrolled loop */ + LTP_pred_Q14 = SKP_SMULWB( pred_lag_ptr[ 0 ], b_Q14[ 0 ] ); + LTP_pred_Q14 = SKP_SMLAWB( LTP_pred_Q14, pred_lag_ptr[ -1 ], b_Q14[ 1 ] ); + LTP_pred_Q14 = SKP_SMLAWB( LTP_pred_Q14, pred_lag_ptr[ -2 ], b_Q14[ 2 ] ); + LTP_pred_Q14 = SKP_SMLAWB( LTP_pred_Q14, pred_lag_ptr[ -3 ], b_Q14[ 3 ] ); + LTP_pred_Q14 = SKP_SMLAWB( LTP_pred_Q14, pred_lag_ptr[ -4 ], b_Q14[ 4 ] ); + pred_lag_ptr++; + } else { + LTP_pred_Q14 = 0; + } + + /* Long-term shaping */ + if( lag > 0 ) { + /* Symmetric, packed FIR coefficients */ + n_LTP_Q14 = SKP_SMULWB( SKP_ADD32( shp_lag_ptr[ 0 ], shp_lag_ptr[ -2 ] ), HarmShapeFIRPacked_Q14 ); + n_LTP_Q14 = SKP_SMLAWT( n_LTP_Q14, shp_lag_ptr[ -1 ], HarmShapeFIRPacked_Q14 ); + n_LTP_Q14 = SKP_LSHIFT( n_LTP_Q14, 6 ); + shp_lag_ptr++; + + LTP_Q10 = SKP_RSHIFT( SKP_SUB32( LTP_pred_Q14, n_LTP_Q14 ), 4 ); + } else { + LTP_Q10 = 0; + } + + for( k = 0; k < nStatesDelayedDecision; k++ ) { + /* Delayed decision state */ + psDD = &psDelDec[ k ]; + + /* Sample state */ + psSS = psSampleState[ k ]; + + /* Generate dither */ + psDD->Seed = SKP_RAND( psDD->Seed ); + + /* dither = rand_seed < 0 ? 0xFFFFFFFF : 0; */ + dither = SKP_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 */ + SKP_assert( predictLPCOrder >= 10 ); /* check that unrolling works */ + SKP_assert( ( predictLPCOrder & 1 ) == 0 ); /* check that order is even */ + SKP_assert( ( (opus_int64)a_Q12 & 3 ) == 0 ); /* check that array starts at 4-byte aligned address */ + /* Partially unrolled */ + LPC_pred_Q10 = SKP_SMULWB( psLPC_Q14[ 0 ], a_Q12[ 0 ] ); + LPC_pred_Q10 = SKP_SMLAWB( LPC_pred_Q10, psLPC_Q14[ -1 ], a_Q12[ 1 ] ); + LPC_pred_Q10 = SKP_SMLAWB( LPC_pred_Q10, psLPC_Q14[ -2 ], a_Q12[ 2 ] ); + LPC_pred_Q10 = SKP_SMLAWB( LPC_pred_Q10, psLPC_Q14[ -3 ], a_Q12[ 3 ] ); + LPC_pred_Q10 = SKP_SMLAWB( LPC_pred_Q10, psLPC_Q14[ -4 ], a_Q12[ 4 ] ); + LPC_pred_Q10 = SKP_SMLAWB( LPC_pred_Q10, psLPC_Q14[ -5 ], a_Q12[ 5 ] ); + LPC_pred_Q10 = SKP_SMLAWB( LPC_pred_Q10, psLPC_Q14[ -6 ], a_Q12[ 6 ] ); + LPC_pred_Q10 = SKP_SMLAWB( LPC_pred_Q10, psLPC_Q14[ -7 ], a_Q12[ 7 ] ); + LPC_pred_Q10 = SKP_SMLAWB( LPC_pred_Q10, psLPC_Q14[ -8 ], a_Q12[ 8 ] ); + LPC_pred_Q10 = SKP_SMLAWB( LPC_pred_Q10, psLPC_Q14[ -9 ], a_Q12[ 9 ] ); + for( j = 10; j < predictLPCOrder; j ++ ) { + LPC_pred_Q10 = SKP_SMLAWB( LPC_pred_Q10, psLPC_Q14[ -j ], a_Q12[ j ] ); + } + + /* Noise shape feedback */ + SKP_assert( ( shapingLPCOrder & 1 ) == 0 ); /* check that order is even */ + /* Output of lowpass section */ + tmp2 = SKP_SMLAWB( psLPC_Q14[ 0 ], psDD->sAR2_Q14[ 0 ], warping_Q16 ); + /* Output of allpass section */ + tmp1 = SKP_SMLAWB( psDD->sAR2_Q14[ 0 ], psDD->sAR2_Q14[ 1 ] - tmp2, warping_Q16 ); + psDD->sAR2_Q14[ 0 ] = tmp2; + n_AR_Q10 = SKP_SMULWB( tmp2, AR_shp_Q13[ 0 ] ); + /* Loop over allpass sections */ + for( j = 2; j < shapingLPCOrder; j += 2 ) { + /* Output of allpass section */ + tmp2 = SKP_SMLAWB( psDD->sAR2_Q14[ j - 1 ], psDD->sAR2_Q14[ j + 0 ] - tmp1, warping_Q16 ); + psDD->sAR2_Q14[ j - 1 ] = tmp1; + n_AR_Q10 = SKP_SMLAWB( n_AR_Q10, tmp1, AR_shp_Q13[ j - 1 ] ); + /* Output of allpass section */ + tmp1 = SKP_SMLAWB( psDD->sAR2_Q14[ j + 0 ], psDD->sAR2_Q14[ j + 1 ] - tmp2, warping_Q16 ); + psDD->sAR2_Q14[ j + 0 ] = tmp2; + n_AR_Q10 = SKP_SMLAWB( n_AR_Q10, tmp2, AR_shp_Q13[ j ] ); + } + psDD->sAR2_Q14[ shapingLPCOrder - 1 ] = tmp1; + n_AR_Q10 = SKP_SMLAWB( n_AR_Q10, tmp1, AR_shp_Q13[ shapingLPCOrder - 1 ] ); + + n_AR_Q10 = SKP_RSHIFT( n_AR_Q10, 1 ); /* Q11 -> Q10 */ + n_AR_Q10 = SKP_SMLAWB( n_AR_Q10, psDD->LF_AR_Q12, Tilt_Q14 ); + + n_LF_Q10 = SKP_LSHIFT( SKP_SMULWB( psDD->Shape_Q10[ *smpl_buf_idx ], LF_shp_Q14 ), 2 ); + n_LF_Q10 = SKP_SMLAWT( n_LF_Q10, psDD->LF_AR_Q12, LF_shp_Q14 ); + + /* Input minus prediction plus noise feedback */ + /* r = x[ i ] - LTP_pred - LPC_pred + n_AR + n_Tilt + n_LF + n_LTP */ + tmp1 = SKP_ADD32( LTP_Q10, LPC_pred_Q10 ); /* add Q10 stuff */ + tmp1 = SKP_SUB32( tmp1, n_AR_Q10 ); /* subtract Q10 stuff */ + tmp1 = SKP_SUB32( tmp1, n_LF_Q10 ); /* subtract Q10 stuff */ + r_Q10 = SKP_SUB32( x_Q10[ i ], tmp1 ); /* residual error Q10 */ + + /* Flip sign depending on dither */ + r_Q10 = r_Q10 ^ dither; + r_Q10 = SKP_LIMIT_32( r_Q10, -31 << 10, 30 << 10 ); + + /* Find two quantization level candidates and measure their rate-distortion */ + q1_Q10 = SKP_SUB32( r_Q10, offset_Q10 ); + q1_Q10 = SKP_RSHIFT( q1_Q10, 10 ); + if( q1_Q10 > 0 ) { + q1_Q10 = SKP_SUB32( SKP_LSHIFT( q1_Q10, 10 ), QUANT_LEVEL_ADJUST_Q10 ); + q1_Q10 = SKP_ADD32( q1_Q10, offset_Q10 ); + q2_Q10 = SKP_ADD32( q1_Q10, 1024 ); + rd1_Q10 = SKP_SMULBB( q1_Q10, Lambda_Q10 ); + rd2_Q10 = SKP_SMULBB( q2_Q10, Lambda_Q10 ); + } else if( q1_Q10 == 0 ) { + q1_Q10 = offset_Q10; + q2_Q10 = SKP_ADD32( q1_Q10, 1024 - QUANT_LEVEL_ADJUST_Q10 ); + rd1_Q10 = SKP_SMULBB( q1_Q10, Lambda_Q10 ); + rd2_Q10 = SKP_SMULBB( q2_Q10, Lambda_Q10 ); + } else if( q1_Q10 == -1 ) { + q2_Q10 = offset_Q10; + q1_Q10 = SKP_SUB32( q2_Q10, 1024 - QUANT_LEVEL_ADJUST_Q10 ); + rd1_Q10 = SKP_SMULBB( -q1_Q10, Lambda_Q10 ); + rd2_Q10 = SKP_SMULBB( q2_Q10, Lambda_Q10 ); + } else { /* Q1_Q10 < -1 */ + q1_Q10 = SKP_ADD32( SKP_LSHIFT( q1_Q10, 10 ), QUANT_LEVEL_ADJUST_Q10 ); + q1_Q10 = SKP_ADD32( q1_Q10, offset_Q10 ); + q2_Q10 = SKP_ADD32( q1_Q10, 1024 ); + rd1_Q10 = SKP_SMULBB( -q1_Q10, Lambda_Q10 ); + rd2_Q10 = SKP_SMULBB( -q2_Q10, Lambda_Q10 ); + } + rr_Q10 = SKP_SUB32( r_Q10, q1_Q10 ); + rd1_Q10 = SKP_RSHIFT( SKP_SMLABB( rd1_Q10, rr_Q10, rr_Q10 ), 10 ); + rr_Q10 = SKP_SUB32( r_Q10, q2_Q10 ); + rd2_Q10 = SKP_RSHIFT( SKP_SMLABB( rd2_Q10, rr_Q10, rr_Q10 ), 10 ); + + if( rd1_Q10 < rd2_Q10 ) { + psSS[ 0 ].RD_Q10 = SKP_ADD32( psDD->RD_Q10, rd1_Q10 ); + psSS[ 1 ].RD_Q10 = SKP_ADD32( psDD->RD_Q10, rd2_Q10 ); + psSS[ 0 ].Q_Q10 = q1_Q10; + psSS[ 1 ].Q_Q10 = q2_Q10; + } else { + psSS[ 0 ].RD_Q10 = SKP_ADD32( psDD->RD_Q10, rd2_Q10 ); + psSS[ 1 ].RD_Q10 = SKP_ADD32( psDD->RD_Q10, rd1_Q10 ); + psSS[ 0 ].Q_Q10 = q2_Q10; + psSS[ 1 ].Q_Q10 = q1_Q10; + } + + /* Update states for best quantization */ + + /* Quantized excitation */ + exc_Q10 = psSS[ 0 ].Q_Q10 ^ dither; + + /* Add predictions */ + LPC_exc_Q10 = exc_Q10 + SKP_RSHIFT_ROUND( LTP_pred_Q14, 4 ); + xq_Q10 = SKP_ADD32( LPC_exc_Q10, LPC_pred_Q10 ); + + /* Update states */ + sLF_AR_shp_Q10 = SKP_SUB32( xq_Q10, n_AR_Q10 ); + psSS[ 0 ].sLTP_shp_Q10 = SKP_SUB32( sLF_AR_shp_Q10, n_LF_Q10 ); + psSS[ 0 ].LF_AR_Q12 = SKP_LSHIFT( sLF_AR_shp_Q10, 2 ); + psSS[ 0 ].xq_Q14 = SKP_LSHIFT( xq_Q10, 4 ); + psSS[ 0 ].LPC_exc_Q16 = SKP_LSHIFT( LPC_exc_Q10, 6 ); + + /* Update states for second best quantization */ + + /* Quantized excitation */ + exc_Q10 = psSS[ 1 ].Q_Q10 ^ dither; + + /* Add predictions */ + LPC_exc_Q10 = exc_Q10 + SKP_RSHIFT_ROUND( LTP_pred_Q14, 4 ); + xq_Q10 = SKP_ADD32( LPC_exc_Q10, LPC_pred_Q10 ); + + /* Update states */ + sLF_AR_shp_Q10 = SKP_SUB32( xq_Q10, n_AR_Q10 ); + psSS[ 1 ].sLTP_shp_Q10 = SKP_SUB32( sLF_AR_shp_Q10, n_LF_Q10 ); + psSS[ 1 ].LF_AR_Q12 = SKP_LSHIFT( sLF_AR_shp_Q10, 2 ); + psSS[ 1 ].xq_Q14 = SKP_LSHIFT( xq_Q10, 4 ); + psSS[ 1 ].LPC_exc_Q16 = SKP_LSHIFT( LPC_exc_Q10, 6 ); + } + + *smpl_buf_idx = ( *smpl_buf_idx - 1 ) & DECISION_DELAY_MASK; /* Index to newest samples */ + last_smple_idx = ( *smpl_buf_idx + decisionDelay ) & DECISION_DELAY_MASK; /* Index to decisionDelay old samples */ + + /* Find winner */ + RDmin_Q10 = psSampleState[ 0 ][ 0 ].RD_Q10; + Winner_ind = 0; + for( k = 1; k < nStatesDelayedDecision; k++ ) { + if( psSampleState[ k ][ 0 ].RD_Q10 < RDmin_Q10 ) { + RDmin_Q10 = psSampleState[ k ][ 0 ].RD_Q10; + Winner_ind = k; + } + } + + /* Increase RD values of expired states */ + Winner_rand_state = psDelDec[ Winner_ind ].RandState[ last_smple_idx ]; + for( k = 0; k < nStatesDelayedDecision; k++ ) { + if( psDelDec[ k ].RandState[ last_smple_idx ] != Winner_rand_state ) { + psSampleState[ k ][ 0 ].RD_Q10 = SKP_ADD32( psSampleState[ k ][ 0 ].RD_Q10, ( SKP_int32_MAX >> 4 ) ); + psSampleState[ k ][ 1 ].RD_Q10 = SKP_ADD32( psSampleState[ k ][ 1 ].RD_Q10, ( SKP_int32_MAX >> 4 ) ); + SKP_assert( psSampleState[ k ][ 0 ].RD_Q10 >= 0 ); + } + } + + /* Find worst in first set and best in second set */ + RDmax_Q10 = psSampleState[ 0 ][ 0 ].RD_Q10; + RDmin_Q10 = psSampleState[ 0 ][ 1 ].RD_Q10; + RDmax_ind = 0; + RDmin_ind = 0; + for( k = 1; k < nStatesDelayedDecision; k++ ) { + /* find worst in first set */ + if( psSampleState[ k ][ 0 ].RD_Q10 > RDmax_Q10 ) { + RDmax_Q10 = psSampleState[ k ][ 0 ].RD_Q10; + RDmax_ind = k; + } + /* find best in second set */ + if( psSampleState[ k ][ 1 ].RD_Q10 < RDmin_Q10 ) { + RDmin_Q10 = psSampleState[ k ][ 1 ].RD_Q10; + RDmin_ind = k; + } + } + + /* Replace a state if best from second set outperforms worst in first set */ + if( RDmin_Q10 < RDmax_Q10 ) { + SKP_memcpy( ((opus_int32 *)&psDelDec[ RDmax_ind ]) + i, + ((opus_int32 *)&psDelDec[ RDmin_ind ]) + i, sizeof( NSQ_del_dec_struct ) - i * sizeof( opus_int32) ); + SKP_memcpy( &psSampleState[ RDmax_ind ][ 0 ], &psSampleState[ RDmin_ind ][ 1 ], sizeof( NSQ_sample_struct ) ); + } + + /* Write samples from winner to output and long-term filter states */ + psDD = &psDelDec[ Winner_ind ]; + if( subfr > 0 || i >= decisionDelay ) { + pulses[ i - decisionDelay ] = ( opus_int8 )SKP_RSHIFT_ROUND( psDD->Q_Q10[ last_smple_idx ], 10 ); + xq[ i - decisionDelay ] = ( opus_int16 )SKP_SAT16( SKP_RSHIFT_ROUND( + SKP_SMULWW( psDD->Xq_Q10[ last_smple_idx ], delayedGain_Q16[ last_smple_idx ] ), 10 ) ); + NSQ->sLTP_shp_Q10[ NSQ->sLTP_shp_buf_idx - decisionDelay ] = psDD->Shape_Q10[ last_smple_idx ]; + sLTP_Q16[ NSQ->sLTP_buf_idx - decisionDelay ] = psDD->Pred_Q16[ last_smple_idx ]; + } + NSQ->sLTP_shp_buf_idx++; + NSQ->sLTP_buf_idx++; + + /* Update states */ + for( k = 0; k < nStatesDelayedDecision; k++ ) { + psDD = &psDelDec[ k ]; + psSS = &psSampleState[ k ][ 0 ]; + psDD->LF_AR_Q12 = psSS->LF_AR_Q12; + psDD->sLPC_Q14[ NSQ_LPC_BUF_LENGTH + i ] = psSS->xq_Q14; + psDD->Xq_Q10[ *smpl_buf_idx ] = SKP_RSHIFT( psSS->xq_Q14, 4 ); + psDD->Q_Q10[ *smpl_buf_idx ] = psSS->Q_Q10; + psDD->Pred_Q16[ *smpl_buf_idx ] = psSS->LPC_exc_Q16; + psDD->Shape_Q10[ *smpl_buf_idx ] = psSS->sLTP_shp_Q10; + psDD->Seed = SKP_ADD32( psDD->Seed, SKP_RSHIFT_ROUND( psSS->Q_Q10, 10 ) ); + psDD->RandState[ *smpl_buf_idx ] = psDD->Seed; + psDD->RD_Q10 = psSS->RD_Q10; + } + delayedGain_Q16[ *smpl_buf_idx ] = Gain_Q16; + } + /* Update LPC states */ + for( k = 0; k < nStatesDelayedDecision; k++ ) { + psDD = &psDelDec[ k ]; + SKP_memcpy( psDD->sLPC_Q14, &psDD->sLPC_Q14[ length ], NSQ_LPC_BUF_LENGTH * sizeof( opus_int32 ) ); + } +} + +SKP_INLINE void silk_nsq_del_dec_scale_states( + const silk_encoder_state *psEncC, /* I Encoder State */ + silk_nsq_state *NSQ, /* I/O NSQ state */ + NSQ_del_dec_struct psDelDec[], /* I/O Delayed decision states */ + const opus_int16 x[], /* I Input in Q0 */ + opus_int32 x_sc_Q10[], /* O Input scaled with 1/Gain in Q10 */ + const opus_int16 sLTP[], /* I Re-whitened LTP state in Q0 */ + opus_int32 sLTP_Q16[], /* O LTP state matching scaled input */ + opus_int subfr, /* I Subframe number */ + opus_int nStatesDelayedDecision, /* I Number of del dec states */ + opus_int smpl_buf_idx, /* I Index to newest samples in buffers */ + const opus_int LTP_scale_Q14, /* I LTP state scaling */ + const opus_int32 Gains_Q16[ MAX_NB_SUBFR ], /* I */ + const opus_int pitchL[ MAX_NB_SUBFR ] /* I Pitch lag */ +) +{ + opus_int i, k, lag; + opus_int32 inv_gain_Q16, gain_adj_Q16, inv_gain_Q32; + NSQ_del_dec_struct *psDD; + + inv_gain_Q16 = silk_INVERSE32_varQ( SKP_max( Gains_Q16[ subfr ], 1 ), 32 ); + inv_gain_Q16 = SKP_min( inv_gain_Q16, SKP_int16_MAX ); + lag = pitchL[ subfr ]; + + /* After rewhitening the LTP state is un-scaled, so scale with inv_gain_Q16 */ + if( NSQ->rewhite_flag ) { + inv_gain_Q32 = SKP_LSHIFT( inv_gain_Q16, 16 ); + if( subfr == 0 ) { + /* Do LTP downscaling */ + inv_gain_Q32 = SKP_LSHIFT( SKP_SMULWB( inv_gain_Q32, LTP_scale_Q14 ), 2 ); + } + for( i = NSQ->sLTP_buf_idx - lag - LTP_ORDER / 2; i < NSQ->sLTP_buf_idx; i++ ) { + SKP_assert( i < MAX_FRAME_LENGTH ); + sLTP_Q16[ i ] = SKP_SMULWB( inv_gain_Q32, sLTP[ i ] ); + } + } + + /* Adjust for changing gain */ + if( inv_gain_Q16 != NSQ->prev_inv_gain_Q16 ) { + gain_adj_Q16 = silk_DIV32_varQ( inv_gain_Q16, NSQ->prev_inv_gain_Q16, 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_Q10[ i ] = SKP_SMULWW( gain_adj_Q16, NSQ->sLTP_shp_Q10[ i ] ); + } + + /* Scale long-term prediction state */ + if( NSQ->rewhite_flag == 0 ) { + for( i = NSQ->sLTP_buf_idx - lag - LTP_ORDER / 2; i < NSQ->sLTP_buf_idx; i++ ) { + sLTP_Q16[ i ] = SKP_SMULWW( gain_adj_Q16, sLTP_Q16[ i ] ); + } + } + + for( k = 0; k < nStatesDelayedDecision; k++ ) { + psDD = &psDelDec[ k ]; + + /* Scale scalar states */ + psDD->LF_AR_Q12 = SKP_SMULWW( gain_adj_Q16, psDD->LF_AR_Q12 ); + + /* Scale short-term prediction and shaping states */ + for( i = 0; i < NSQ_LPC_BUF_LENGTH; i++ ) { + psDD->sLPC_Q14[ i ] = SKP_SMULWW( gain_adj_Q16, psDD->sLPC_Q14[ i ] ); + } + for( i = 0; i < MAX_SHAPE_LPC_ORDER; i++ ) { + psDD->sAR2_Q14[ i ] = SKP_SMULWW( gain_adj_Q16, psDD->sAR2_Q14[ i ] ); + } + for( i = 0; i < DECISION_DELAY; i++ ) { + psDD->Pred_Q16[ i ] = SKP_SMULWW( gain_adj_Q16, psDD->Pred_Q16[ i ] ); + psDD->Shape_Q10[ i ] = SKP_SMULWW( gain_adj_Q16, psDD->Shape_Q10[ i ] ); + } + } + } + + /* Scale input */ + for( i = 0; i < psEncC->subfr_length; i++ ) { + x_sc_Q10[ i ] = SKP_RSHIFT( SKP_SMULBB( x[ i ], ( opus_int16 )inv_gain_Q16 ), 6 ); + } + + /* save inv_gain */ + SKP_assert( inv_gain_Q16 != 0 ); + NSQ->prev_inv_gain_Q16 = inv_gain_Q16; +} diff --git a/silk/silk_PLC.c b/silk/silk_PLC.c index 3289adbfb..085b2f83b 100644 --- a/silk/silk_PLC.c +++ b/silk/silk_PLC.c @@ -1,391 +1,391 @@ -/*********************************************************************** -Copyright (c) 2006-2011, Skype Limited. All rights reserved. -Redistribution and use in source and binary forms, with or without -modification, (subject to the limitations in the disclaimer below) -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 Skype Limited, nor the names of specific -contributors, may be used to endorse or promote products derived from -this software without specific prior written permission. -NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED -BY THIS LICENSE. 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. -***********************************************************************/ - -#include "silk_main.h" -#include "silk_PLC.h" - -#define NB_ATT 2 -static const opus_int16 HARM_ATT_Q15[NB_ATT] = { 32440, 31130 }; /* 0.99, 0.95 */ -static const opus_int16 PLC_RAND_ATTENUATE_V_Q15[NB_ATT] = { 31130, 26214 }; /* 0.95, 0.8 */ -static const opus_int16 PLC_RAND_ATTENUATE_UV_Q15[NB_ATT] = { 32440, 29491 }; /* 0.99, 0.9 */ - -void silk_PLC_Reset( - silk_decoder_state *psDec /* I/O Decoder state */ -) -{ - psDec->sPLC.pitchL_Q8 = SKP_RSHIFT( psDec->frame_length, 1 ); -} - -void silk_PLC( - silk_decoder_state *psDec, /* I Decoder state */ - silk_decoder_control *psDecCtrl, /* I Decoder control */ - opus_int16 signal[], /* O Concealed signal */ - opus_int length, /* I length of residual */ - opus_int lost /* I Loss flag */ -) -{ - /* PLC control function */ - if( psDec->fs_kHz != psDec->sPLC.fs_kHz ) { - silk_PLC_Reset( psDec ); - psDec->sPLC.fs_kHz = psDec->fs_kHz; - } - - if( lost ) { - /****************************/ - /* Generate Signal */ - /****************************/ - silk_PLC_conceal( psDec, psDecCtrl, signal, length ); - - psDec->lossCnt++; - } else { - /****************************/ - /* Update state */ - /****************************/ - silk_PLC_update( psDec, psDecCtrl, signal, length ); - } -} - -/**************************************************/ -/* Update state of PLC */ -/**************************************************/ -void silk_PLC_update( - silk_decoder_state *psDec, /* (I/O) Decoder state */ - silk_decoder_control *psDecCtrl, /* (I/O) Decoder control */ - opus_int16 signal[], - opus_int length -) -{ - opus_int32 LTP_Gain_Q14, temp_LTP_Gain_Q14; - opus_int i, j; - silk_PLC_struct *psPLC; - - psPLC = &psDec->sPLC; - - /* Update parameters used in case of packet loss */ - psDec->prevSignalType = psDec->indices.signalType; - LTP_Gain_Q14 = 0; - if( psDec->indices.signalType == TYPE_VOICED ) { - /* Find the parameters for the last subframe which contains a pitch pulse */ - for( j = 0; j * psDec->subfr_length < psDecCtrl->pitchL[ psDec->nb_subfr - 1 ]; j++ ) { - if( j == psDec->nb_subfr ){ - break; - } - temp_LTP_Gain_Q14 = 0; - for( i = 0; i < LTP_ORDER; i++ ) { - temp_LTP_Gain_Q14 += psDecCtrl->LTPCoef_Q14[ ( psDec->nb_subfr - 1 - j ) * LTP_ORDER + i ]; - } - if( temp_LTP_Gain_Q14 > LTP_Gain_Q14 ) { - LTP_Gain_Q14 = temp_LTP_Gain_Q14; - SKP_memcpy( psPLC->LTPCoef_Q14, - &psDecCtrl->LTPCoef_Q14[ SKP_SMULBB( psDec->nb_subfr - 1 - j, LTP_ORDER ) ], - LTP_ORDER * sizeof( opus_int16 ) ); - - psPLC->pitchL_Q8 = SKP_LSHIFT( psDecCtrl->pitchL[ psDec->nb_subfr - 1 - j ], 8 ); - } - } - -#if USE_SINGLE_TAP - SKP_memset( psPLC->LTPCoef_Q14, 0, LTP_ORDER * sizeof( opus_int16 ) ); - psPLC->LTPCoef_Q14[ LTP_ORDER / 2 ] = LTP_Gain_Q14; -#endif - - /* Limit LT coefs */ - if( LTP_Gain_Q14 < V_PITCH_GAIN_START_MIN_Q14 ) { - opus_int scale_Q10; - opus_int32 tmp; - - tmp = SKP_LSHIFT( V_PITCH_GAIN_START_MIN_Q14, 10 ); - scale_Q10 = SKP_DIV32( tmp, SKP_max( LTP_Gain_Q14, 1 ) ); - for( i = 0; i < LTP_ORDER; i++ ) { - psPLC->LTPCoef_Q14[ i ] = SKP_RSHIFT( SKP_SMULBB( psPLC->LTPCoef_Q14[ i ], scale_Q10 ), 10 ); - } - } else if( LTP_Gain_Q14 > V_PITCH_GAIN_START_MAX_Q14 ) { - opus_int scale_Q14; - opus_int32 tmp; - - tmp = SKP_LSHIFT( V_PITCH_GAIN_START_MAX_Q14, 14 ); - scale_Q14 = SKP_DIV32( tmp, SKP_max( LTP_Gain_Q14, 1 ) ); - for( i = 0; i < LTP_ORDER; i++ ) { - psPLC->LTPCoef_Q14[ i ] = SKP_RSHIFT( SKP_SMULBB( psPLC->LTPCoef_Q14[ i ], scale_Q14 ), 14 ); - } - } - } else { - psPLC->pitchL_Q8 = SKP_LSHIFT( SKP_SMULBB( psDec->fs_kHz, 18 ), 8 ); - SKP_memset( psPLC->LTPCoef_Q14, 0, LTP_ORDER * sizeof( opus_int16 )); - } - - /* Save LPC coeficients */ - SKP_memcpy( psPLC->prevLPC_Q12, psDecCtrl->PredCoef_Q12[ 1 ], psDec->LPC_order * sizeof( opus_int16 ) ); - psPLC->prevLTP_scale_Q14 = psDecCtrl->LTP_scale_Q14; - - /* Save Gains */ - SKP_memcpy( psPLC->prevGain_Q16, psDecCtrl->Gains_Q16, psDec->nb_subfr * sizeof( opus_int32 ) ); -} - -void silk_PLC_conceal( - silk_decoder_state *psDec, /* I/O Decoder state */ - silk_decoder_control *psDecCtrl, /* I/O Decoder control */ - opus_int16 signal[], /* O concealed signal */ - opus_int length /* I length of residual */ -) -{ - opus_int i, j, k; - opus_int16 *B_Q14, exc_buf[ MAX_FRAME_LENGTH ], *exc_buf_ptr; - opus_int16 rand_scale_Q14, A_Q12_tmp[ MAX_LPC_ORDER ]; - opus_int32 rand_seed, harm_Gain_Q15, rand_Gain_Q15; - opus_int lag, idx, sLTP_buf_idx, shift1, shift2; - opus_int32 energy1, energy2, *rand_ptr, *pred_lag_ptr; - opus_int32 sig_Q10[ MAX_FRAME_LENGTH ], *sig_Q10_ptr, LPC_exc_Q10, LPC_pred_Q10, LTP_pred_Q14; - silk_PLC_struct *psPLC; - psPLC = &psDec->sPLC; - - /* Update LTP buffer */ - SKP_memmove( psDec->sLTP_Q16, &psDec->sLTP_Q16[ psDec->frame_length ], psDec->ltp_mem_length * sizeof( opus_int32 ) ); - - /* LPC concealment. Apply BWE to previous LPC */ - silk_bwexpander( psPLC->prevLPC_Q12, psDec->LPC_order, SILK_FIX_CONST( BWE_COEF, 16 ) ); - - /* Find random noise component */ - /* Scale previous excitation signal */ - exc_buf_ptr = exc_buf; - /* FIXME: JMV: Is this the right fix? */ - for (i=0;i<MAX_FRAME_LENGTH;i++) - exc_buf[i] = 0; - for( k = ( psDec->nb_subfr >> 1 ); k < psDec->nb_subfr; k++ ) { - for( i = 0; i < psDec->subfr_length; i++ ) { - exc_buf_ptr[ i ] = ( opus_int16 )SKP_RSHIFT( - SKP_SMULWW( psDec->exc_Q10[ i + k * psDec->subfr_length ], psPLC->prevGain_Q16[ k ] ), 10 ); - } - exc_buf_ptr += psDec->subfr_length; - } - /* Find the subframe with lowest energy of the last two and use that as random noise generator */ - silk_sum_sqr_shift( &energy1, &shift1, exc_buf, psDec->subfr_length ); - silk_sum_sqr_shift( &energy2, &shift2, &exc_buf[ psDec->subfr_length ], psDec->subfr_length ); - - if( SKP_RSHIFT( energy1, shift2 ) < SKP_RSHIFT( energy2, shift1 ) ) { - /* First sub-frame has lowest energy */ - rand_ptr = &psDec->exc_Q10[ SKP_max_int( 0, 3 * psDec->subfr_length - RAND_BUF_SIZE ) ]; - } else { - /* Second sub-frame has lowest energy */ - rand_ptr = &psDec->exc_Q10[ SKP_max_int( 0, psDec->frame_length - RAND_BUF_SIZE ) ]; - } - - /* Setup Gain to random noise component */ - B_Q14 = psPLC->LTPCoef_Q14; - rand_scale_Q14 = psPLC->randScale_Q14; - - /* Setup attenuation gains */ - harm_Gain_Q15 = HARM_ATT_Q15[ SKP_min_int( NB_ATT - 1, psDec->lossCnt ) ]; - if( psDec->prevSignalType == TYPE_VOICED ) { - rand_Gain_Q15 = PLC_RAND_ATTENUATE_V_Q15[ SKP_min_int( NB_ATT - 1, psDec->lossCnt ) ]; - } else { - rand_Gain_Q15 = PLC_RAND_ATTENUATE_UV_Q15[ SKP_min_int( NB_ATT - 1, psDec->lossCnt ) ]; - } - - /* First Lost frame */ - if( psDec->lossCnt == 0 ) { - rand_scale_Q14 = 1 << 14; - - /* Reduce random noise Gain for voiced frames */ - if( psDec->prevSignalType == TYPE_VOICED ) { - for( i = 0; i < LTP_ORDER; i++ ) { - rand_scale_Q14 -= B_Q14[ i ]; - } - rand_scale_Q14 = SKP_max_16( 3277, rand_scale_Q14 ); /* 0.2 */ - rand_scale_Q14 = ( opus_int16 )SKP_RSHIFT( SKP_SMULBB( rand_scale_Q14, psPLC->prevLTP_scale_Q14 ), 14 ); - } else { - /* Reduce random noise for unvoiced frames with high LPC gain */ - opus_int32 invGain_Q30, down_scale_Q30; - - silk_LPC_inverse_pred_gain( &invGain_Q30, psPLC->prevLPC_Q12, psDec->LPC_order ); - - down_scale_Q30 = SKP_min_32( SKP_RSHIFT( 1 << 30, LOG2_INV_LPC_GAIN_HIGH_THRES ), invGain_Q30 ); - down_scale_Q30 = SKP_max_32( SKP_RSHIFT( 1 << 30, LOG2_INV_LPC_GAIN_LOW_THRES ), down_scale_Q30 ); - down_scale_Q30 = SKP_LSHIFT( down_scale_Q30, LOG2_INV_LPC_GAIN_HIGH_THRES ); - - rand_Gain_Q15 = SKP_RSHIFT( SKP_SMULWB( down_scale_Q30, rand_Gain_Q15 ), 14 ); - } - } - - rand_seed = psPLC->rand_seed; - lag = SKP_RSHIFT_ROUND( psPLC->pitchL_Q8, 8 ); - sLTP_buf_idx = psDec->ltp_mem_length; - - /***************************/ - /* LTP synthesis filtering */ - /***************************/ - sig_Q10_ptr = sig_Q10; - for( k = 0; k < psDec->nb_subfr; k++ ) { - /* Setup pointer */ - pred_lag_ptr = &psDec->sLTP_Q16[ sLTP_buf_idx - lag + LTP_ORDER / 2 ]; - for( i = 0; i < psDec->subfr_length; i++ ) { - rand_seed = SKP_RAND( rand_seed ); - idx = SKP_RSHIFT( rand_seed, 25 ) & RAND_BUF_MASK; - - /* Unrolled loop */ - LTP_pred_Q14 = SKP_SMULWB( pred_lag_ptr[ 0 ], B_Q14[ 0 ] ); - LTP_pred_Q14 = SKP_SMLAWB( LTP_pred_Q14, pred_lag_ptr[ -1 ], B_Q14[ 1 ] ); - LTP_pred_Q14 = SKP_SMLAWB( LTP_pred_Q14, pred_lag_ptr[ -2 ], B_Q14[ 2 ] ); - LTP_pred_Q14 = SKP_SMLAWB( LTP_pred_Q14, pred_lag_ptr[ -3 ], B_Q14[ 3 ] ); - LTP_pred_Q14 = SKP_SMLAWB( LTP_pred_Q14, pred_lag_ptr[ -4 ], B_Q14[ 4 ] ); - pred_lag_ptr++; - - /* Generate LPC residual */ - LPC_exc_Q10 = SKP_LSHIFT( SKP_SMULWB( rand_ptr[ idx ], rand_scale_Q14 ), 2 ); /* Random noise part */ - LPC_exc_Q10 = SKP_ADD32( LPC_exc_Q10, SKP_RSHIFT_ROUND( LTP_pred_Q14, 4 ) ); /* Harmonic part */ - - /* Update states */ - psDec->sLTP_Q16[ sLTP_buf_idx ] = SKP_LSHIFT( LPC_exc_Q10, 6 ); - sLTP_buf_idx++; - - /* Save LPC residual */ - sig_Q10_ptr[ i ] = LPC_exc_Q10; - } - sig_Q10_ptr += psDec->subfr_length; - /* Gradually reduce LTP gain */ - for( j = 0; j < LTP_ORDER; j++ ) { - B_Q14[ j ] = SKP_RSHIFT( SKP_SMULBB( harm_Gain_Q15, B_Q14[ j ] ), 15 ); - } - /* Gradually reduce excitation gain */ - rand_scale_Q14 = SKP_RSHIFT( SKP_SMULBB( rand_scale_Q14, rand_Gain_Q15 ), 15 ); - - /* Slowly increase pitch lag */ - psPLC->pitchL_Q8 += SKP_SMULWB( psPLC->pitchL_Q8, PITCH_DRIFT_FAC_Q16 ); - psPLC->pitchL_Q8 = SKP_min_32( psPLC->pitchL_Q8, SKP_LSHIFT( SKP_SMULBB( MAX_PITCH_LAG_MS, psDec->fs_kHz ), 8 ) ); - lag = SKP_RSHIFT_ROUND( psPLC->pitchL_Q8, 8 ); - } - - /***************************/ - /* LPC synthesis filtering */ - /***************************/ - sig_Q10_ptr = sig_Q10; - /* Preload LPC coeficients to array on stack. Gives small performance gain */ - SKP_memcpy( A_Q12_tmp, psPLC->prevLPC_Q12, psDec->LPC_order * sizeof( opus_int16 ) ); - SKP_assert( psDec->LPC_order >= 10 ); /* check that unrolling works */ - for( k = 0; k < psDec->nb_subfr; k++ ) { - for( i = 0; i < psDec->subfr_length; i++ ){ - /* partly unrolled */ - LPC_pred_Q10 = SKP_SMULWB( psDec->sLPC_Q14[ MAX_LPC_ORDER + i - 1 ], A_Q12_tmp[ 0 ] ); - LPC_pred_Q10 = SKP_SMLAWB( LPC_pred_Q10, psDec->sLPC_Q14[ MAX_LPC_ORDER + i - 2 ], A_Q12_tmp[ 1 ] ); - LPC_pred_Q10 = SKP_SMLAWB( LPC_pred_Q10, psDec->sLPC_Q14[ MAX_LPC_ORDER + i - 3 ], A_Q12_tmp[ 2 ] ); - LPC_pred_Q10 = SKP_SMLAWB( LPC_pred_Q10, psDec->sLPC_Q14[ MAX_LPC_ORDER + i - 4 ], A_Q12_tmp[ 3 ] ); - LPC_pred_Q10 = SKP_SMLAWB( LPC_pred_Q10, psDec->sLPC_Q14[ MAX_LPC_ORDER + i - 5 ], A_Q12_tmp[ 4 ] ); - LPC_pred_Q10 = SKP_SMLAWB( LPC_pred_Q10, psDec->sLPC_Q14[ MAX_LPC_ORDER + i - 6 ], A_Q12_tmp[ 5 ] ); - LPC_pred_Q10 = SKP_SMLAWB( LPC_pred_Q10, psDec->sLPC_Q14[ MAX_LPC_ORDER + i - 7 ], A_Q12_tmp[ 6 ] ); - LPC_pred_Q10 = SKP_SMLAWB( LPC_pred_Q10, psDec->sLPC_Q14[ MAX_LPC_ORDER + i - 8 ], A_Q12_tmp[ 7 ] ); - LPC_pred_Q10 = SKP_SMLAWB( LPC_pred_Q10, psDec->sLPC_Q14[ MAX_LPC_ORDER + i - 9 ], A_Q12_tmp[ 8 ] ); - LPC_pred_Q10 = SKP_SMLAWB( LPC_pred_Q10, psDec->sLPC_Q14[ MAX_LPC_ORDER + i - 10 ], A_Q12_tmp[ 9 ] ); - - for( j = 10; j < psDec->LPC_order; j++ ) { - LPC_pred_Q10 = SKP_SMLAWB( LPC_pred_Q10, psDec->sLPC_Q14[ MAX_LPC_ORDER + i - j - 1 ], A_Q12_tmp[ j ] ); - } - - /* Add prediction to LPC residual */ - sig_Q10_ptr[ i ] = SKP_ADD32( sig_Q10_ptr[ i ], LPC_pred_Q10 ); - - /* Update states */ - psDec->sLPC_Q14[ MAX_LPC_ORDER + i ] = SKP_LSHIFT( sig_Q10_ptr[ i ], 4 ); - } - sig_Q10_ptr += psDec->subfr_length; - /* Update LPC filter state */ - SKP_memcpy( psDec->sLPC_Q14, &psDec->sLPC_Q14[ psDec->subfr_length ], MAX_LPC_ORDER * sizeof( opus_int32 ) ); - } - - /* Scale with Gain */ - for( i = 0; i < psDec->frame_length; i++ ) { - signal[ i ] = ( opus_int16 )SKP_SAT16( SKP_RSHIFT_ROUND( SKP_SMULWW( sig_Q10[ i ], psPLC->prevGain_Q16[ psDec->nb_subfr - 1 ] ), 10 ) ); - } - - /**************************************/ - /* Update states */ - /**************************************/ - psPLC->rand_seed = rand_seed; - psPLC->randScale_Q14 = rand_scale_Q14; - for( i = 0; i < MAX_NB_SUBFR; i++ ) { - psDecCtrl->pitchL[ i ] = lag; - } -} - -/* Glues concealed frames with new good recieved frames */ -void silk_PLC_glue_frames( - silk_decoder_state *psDec, /* I/O decoder state */ - silk_decoder_control *psDecCtrl, /* I/O Decoder control */ - opus_int16 signal[], /* I/O signal */ - opus_int length /* I length of residual */ -) -{ - opus_int i, energy_shift; - opus_int32 energy; - silk_PLC_struct *psPLC; - psPLC = &psDec->sPLC; - - if( psDec->lossCnt ) { - /* Calculate energy in concealed residual */ - silk_sum_sqr_shift( &psPLC->conc_energy, &psPLC->conc_energy_shift, signal, length ); - - psPLC->last_frame_lost = 1; - } else { - if( psDec->sPLC.last_frame_lost ) { - /* Calculate residual in decoded signal if last frame was lost */ - silk_sum_sqr_shift( &energy, &energy_shift, signal, length ); - - /* Normalize energies */ - if( energy_shift > psPLC->conc_energy_shift ) { - psPLC->conc_energy = SKP_RSHIFT( psPLC->conc_energy, energy_shift - psPLC->conc_energy_shift ); - } else if( energy_shift < psPLC->conc_energy_shift ) { - energy = SKP_RSHIFT( energy, psPLC->conc_energy_shift - energy_shift ); - } - - /* Fade in the energy difference */ - if( energy > psPLC->conc_energy ) { - opus_int32 frac_Q24, LZ; - opus_int32 gain_Q16, slope_Q16; - - LZ = silk_CLZ32( psPLC->conc_energy ); - LZ = LZ - 1; - psPLC->conc_energy = SKP_LSHIFT( psPLC->conc_energy, LZ ); - energy = SKP_RSHIFT( energy, SKP_max_32( 24 - LZ, 0 ) ); - - frac_Q24 = SKP_DIV32( psPLC->conc_energy, SKP_max( energy, 1 ) ); - - gain_Q16 = SKP_LSHIFT( silk_SQRT_APPROX( frac_Q24 ), 4 ); - slope_Q16 = SKP_DIV32_16( ( 1 << 16 ) - gain_Q16, length ); - /* Make slope 4x steeper to avoid missing onsets after DTX */ - slope_Q16 = SKP_LSHIFT( slope_Q16, 2 ); - - for( i = 0; i < length; i++ ) { - signal[ i ] = SKP_SMULWB( gain_Q16, signal[ i ] ); - gain_Q16 += slope_Q16; - if( gain_Q16 > 1 << 16 ) { - break; - } - } - } - } - psPLC->last_frame_lost = 0; - } -} +/*********************************************************************** +Copyright (c) 2006-2011, Skype Limited. All rights reserved. +Redistribution and use in source and binary forms, with or without +modification, (subject to the limitations in the disclaimer below) +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 Skype Limited, nor the names of specific +contributors, may be used to endorse or promote products derived from +this software without specific prior written permission. +NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED +BY THIS LICENSE. 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. +***********************************************************************/ + +#include "silk_main.h" +#include "silk_PLC.h" + +#define NB_ATT 2 +static const opus_int16 HARM_ATT_Q15[NB_ATT] = { 32440, 31130 }; /* 0.99, 0.95 */ +static const opus_int16 PLC_RAND_ATTENUATE_V_Q15[NB_ATT] = { 31130, 26214 }; /* 0.95, 0.8 */ +static const opus_int16 PLC_RAND_ATTENUATE_UV_Q15[NB_ATT] = { 32440, 29491 }; /* 0.99, 0.9 */ + +void silk_PLC_Reset( + silk_decoder_state *psDec /* I/O Decoder state */ +) +{ + psDec->sPLC.pitchL_Q8 = SKP_RSHIFT( psDec->frame_length, 1 ); +} + +void silk_PLC( + silk_decoder_state *psDec, /* I Decoder state */ + silk_decoder_control *psDecCtrl, /* I Decoder control */ + opus_int16 signal[], /* O Concealed signal */ + opus_int length, /* I length of residual */ + opus_int lost /* I Loss flag */ +) +{ + /* PLC control function */ + if( psDec->fs_kHz != psDec->sPLC.fs_kHz ) { + silk_PLC_Reset( psDec ); + psDec->sPLC.fs_kHz = psDec->fs_kHz; + } + + if( lost ) { + /****************************/ + /* Generate Signal */ + /****************************/ + silk_PLC_conceal( psDec, psDecCtrl, signal, length ); + + psDec->lossCnt++; + } else { + /****************************/ + /* Update state */ + /****************************/ + silk_PLC_update( psDec, psDecCtrl, signal, length ); + } +} + +/**************************************************/ +/* Update state of PLC */ +/**************************************************/ +void silk_PLC_update( + silk_decoder_state *psDec, /* (I/O) Decoder state */ + silk_decoder_control *psDecCtrl, /* (I/O) Decoder control */ + opus_int16 signal[], + opus_int length +) +{ + opus_int32 LTP_Gain_Q14, temp_LTP_Gain_Q14; + opus_int i, j; + silk_PLC_struct *psPLC; + + psPLC = &psDec->sPLC; + + /* Update parameters used in case of packet loss */ + psDec->prevSignalType = psDec->indices.signalType; + LTP_Gain_Q14 = 0; + if( psDec->indices.signalType == TYPE_VOICED ) { + /* Find the parameters for the last subframe which contains a pitch pulse */ + for( j = 0; j * psDec->subfr_length < psDecCtrl->pitchL[ psDec->nb_subfr - 1 ]; j++ ) { + if( j == psDec->nb_subfr ){ + break; + } + temp_LTP_Gain_Q14 = 0; + for( i = 0; i < LTP_ORDER; i++ ) { + temp_LTP_Gain_Q14 += psDecCtrl->LTPCoef_Q14[ ( psDec->nb_subfr - 1 - j ) * LTP_ORDER + i ]; + } + if( temp_LTP_Gain_Q14 > LTP_Gain_Q14 ) { + LTP_Gain_Q14 = temp_LTP_Gain_Q14; + SKP_memcpy( psPLC->LTPCoef_Q14, + &psDecCtrl->LTPCoef_Q14[ SKP_SMULBB( psDec->nb_subfr - 1 - j, LTP_ORDER ) ], + LTP_ORDER * sizeof( opus_int16 ) ); + + psPLC->pitchL_Q8 = SKP_LSHIFT( psDecCtrl->pitchL[ psDec->nb_subfr - 1 - j ], 8 ); + } + } + +#if USE_SINGLE_TAP + SKP_memset( psPLC->LTPCoef_Q14, 0, LTP_ORDER * sizeof( opus_int16 ) ); + psPLC->LTPCoef_Q14[ LTP_ORDER / 2 ] = LTP_Gain_Q14; +#endif + + /* Limit LT coefs */ + if( LTP_Gain_Q14 < V_PITCH_GAIN_START_MIN_Q14 ) { + opus_int scale_Q10; + opus_int32 tmp; + + tmp = SKP_LSHIFT( V_PITCH_GAIN_START_MIN_Q14, 10 ); + scale_Q10 = SKP_DIV32( tmp, SKP_max( LTP_Gain_Q14, 1 ) ); + for( i = 0; i < LTP_ORDER; i++ ) { + psPLC->LTPCoef_Q14[ i ] = SKP_RSHIFT( SKP_SMULBB( psPLC->LTPCoef_Q14[ i ], scale_Q10 ), 10 ); + } + } else if( LTP_Gain_Q14 > V_PITCH_GAIN_START_MAX_Q14 ) { + opus_int scale_Q14; + opus_int32 tmp; + + tmp = SKP_LSHIFT( V_PITCH_GAIN_START_MAX_Q14, 14 ); + scale_Q14 = SKP_DIV32( tmp, SKP_max( LTP_Gain_Q14, 1 ) ); + for( i = 0; i < LTP_ORDER; i++ ) { + psPLC->LTPCoef_Q14[ i ] = SKP_RSHIFT( SKP_SMULBB( psPLC->LTPCoef_Q14[ i ], scale_Q14 ), 14 ); + } + } + } else { + psPLC->pitchL_Q8 = SKP_LSHIFT( SKP_SMULBB( psDec->fs_kHz, 18 ), 8 ); + SKP_memset( psPLC->LTPCoef_Q14, 0, LTP_ORDER * sizeof( opus_int16 )); + } + + /* Save LPC coeficients */ + SKP_memcpy( psPLC->prevLPC_Q12, psDecCtrl->PredCoef_Q12[ 1 ], psDec->LPC_order * sizeof( opus_int16 ) ); + psPLC->prevLTP_scale_Q14 = psDecCtrl->LTP_scale_Q14; + + /* Save Gains */ + SKP_memcpy( psPLC->prevGain_Q16, psDecCtrl->Gains_Q16, psDec->nb_subfr * sizeof( opus_int32 ) ); +} + +void silk_PLC_conceal( + silk_decoder_state *psDec, /* I/O Decoder state */ + silk_decoder_control *psDecCtrl, /* I/O Decoder control */ + opus_int16 signal[], /* O concealed signal */ + opus_int length /* I length of residual */ +) +{ + opus_int i, j, k; + opus_int16 *B_Q14, exc_buf[ MAX_FRAME_LENGTH ], *exc_buf_ptr; + opus_int16 rand_scale_Q14, A_Q12_tmp[ MAX_LPC_ORDER ]; + opus_int32 rand_seed, harm_Gain_Q15, rand_Gain_Q15; + opus_int lag, idx, sLTP_buf_idx, shift1, shift2; + opus_int32 energy1, energy2, *rand_ptr, *pred_lag_ptr; + opus_int32 sig_Q10[ MAX_FRAME_LENGTH ], *sig_Q10_ptr, LPC_exc_Q10, LPC_pred_Q10, LTP_pred_Q14; + silk_PLC_struct *psPLC; + psPLC = &psDec->sPLC; + + /* Update LTP buffer */ + SKP_memmove( psDec->sLTP_Q16, &psDec->sLTP_Q16[ psDec->frame_length ], psDec->ltp_mem_length * sizeof( opus_int32 ) ); + + /* LPC concealment. Apply BWE to previous LPC */ + silk_bwexpander( psPLC->prevLPC_Q12, psDec->LPC_order, SILK_FIX_CONST( BWE_COEF, 16 ) ); + + /* Find random noise component */ + /* Scale previous excitation signal */ + exc_buf_ptr = exc_buf; + /* FIXME: JMV: Is this the right fix? */ + for (i=0;i<MAX_FRAME_LENGTH;i++) + exc_buf[i] = 0; + for( k = ( psDec->nb_subfr >> 1 ); k < psDec->nb_subfr; k++ ) { + for( i = 0; i < psDec->subfr_length; i++ ) { + exc_buf_ptr[ i ] = ( opus_int16 )SKP_RSHIFT( + SKP_SMULWW( psDec->exc_Q10[ i + k * psDec->subfr_length ], psPLC->prevGain_Q16[ k ] ), 10 ); + } + exc_buf_ptr += psDec->subfr_length; + } + /* Find the subframe with lowest energy of the last two and use that as random noise generator */ + silk_sum_sqr_shift( &energy1, &shift1, exc_buf, psDec->subfr_length ); + silk_sum_sqr_shift( &energy2, &shift2, &exc_buf[ psDec->subfr_length ], psDec->subfr_length ); + + if( SKP_RSHIFT( energy1, shift2 ) < SKP_RSHIFT( energy2, shift1 ) ) { + /* First sub-frame has lowest energy */ + rand_ptr = &psDec->exc_Q10[ SKP_max_int( 0, 3 * psDec->subfr_length - RAND_BUF_SIZE ) ]; + } else { + /* Second sub-frame has lowest energy */ + rand_ptr = &psDec->exc_Q10[ SKP_max_int( 0, psDec->frame_length - RAND_BUF_SIZE ) ]; + } + + /* Setup Gain to random noise component */ + B_Q14 = psPLC->LTPCoef_Q14; + rand_scale_Q14 = psPLC->randScale_Q14; + + /* Setup attenuation gains */ + harm_Gain_Q15 = HARM_ATT_Q15[ SKP_min_int( NB_ATT - 1, psDec->lossCnt ) ]; + if( psDec->prevSignalType == TYPE_VOICED ) { + rand_Gain_Q15 = PLC_RAND_ATTENUATE_V_Q15[ SKP_min_int( NB_ATT - 1, psDec->lossCnt ) ]; + } else { + rand_Gain_Q15 = PLC_RAND_ATTENUATE_UV_Q15[ SKP_min_int( NB_ATT - 1, psDec->lossCnt ) ]; + } + + /* First Lost frame */ + if( psDec->lossCnt == 0 ) { + rand_scale_Q14 = 1 << 14; + + /* Reduce random noise Gain for voiced frames */ + if( psDec->prevSignalType == TYPE_VOICED ) { + for( i = 0; i < LTP_ORDER; i++ ) { + rand_scale_Q14 -= B_Q14[ i ]; + } + rand_scale_Q14 = SKP_max_16( 3277, rand_scale_Q14 ); /* 0.2 */ + rand_scale_Q14 = ( opus_int16 )SKP_RSHIFT( SKP_SMULBB( rand_scale_Q14, psPLC->prevLTP_scale_Q14 ), 14 ); + } else { + /* Reduce random noise for unvoiced frames with high LPC gain */ + opus_int32 invGain_Q30, down_scale_Q30; + + silk_LPC_inverse_pred_gain( &invGain_Q30, psPLC->prevLPC_Q12, psDec->LPC_order ); + + down_scale_Q30 = SKP_min_32( SKP_RSHIFT( 1 << 30, LOG2_INV_LPC_GAIN_HIGH_THRES ), invGain_Q30 ); + down_scale_Q30 = SKP_max_32( SKP_RSHIFT( 1 << 30, LOG2_INV_LPC_GAIN_LOW_THRES ), down_scale_Q30 ); + down_scale_Q30 = SKP_LSHIFT( down_scale_Q30, LOG2_INV_LPC_GAIN_HIGH_THRES ); + + rand_Gain_Q15 = SKP_RSHIFT( SKP_SMULWB( down_scale_Q30, rand_Gain_Q15 ), 14 ); + } + } + + rand_seed = psPLC->rand_seed; + lag = SKP_RSHIFT_ROUND( psPLC->pitchL_Q8, 8 ); + sLTP_buf_idx = psDec->ltp_mem_length; + + /***************************/ + /* LTP synthesis filtering */ + /***************************/ + sig_Q10_ptr = sig_Q10; + for( k = 0; k < psDec->nb_subfr; k++ ) { + /* Setup pointer */ + pred_lag_ptr = &psDec->sLTP_Q16[ sLTP_buf_idx - lag + LTP_ORDER / 2 ]; + for( i = 0; i < psDec->subfr_length; i++ ) { + rand_seed = SKP_RAND( rand_seed ); + idx = SKP_RSHIFT( rand_seed, 25 ) & RAND_BUF_MASK; + + /* Unrolled loop */ + LTP_pred_Q14 = SKP_SMULWB( pred_lag_ptr[ 0 ], B_Q14[ 0 ] ); + LTP_pred_Q14 = SKP_SMLAWB( LTP_pred_Q14, pred_lag_ptr[ -1 ], B_Q14[ 1 ] ); + LTP_pred_Q14 = SKP_SMLAWB( LTP_pred_Q14, pred_lag_ptr[ -2 ], B_Q14[ 2 ] ); + LTP_pred_Q14 = SKP_SMLAWB( LTP_pred_Q14, pred_lag_ptr[ -3 ], B_Q14[ 3 ] ); + LTP_pred_Q14 = SKP_SMLAWB( LTP_pred_Q14, pred_lag_ptr[ -4 ], B_Q14[ 4 ] ); + pred_lag_ptr++; + + /* Generate LPC residual */ + LPC_exc_Q10 = SKP_LSHIFT( SKP_SMULWB( rand_ptr[ idx ], rand_scale_Q14 ), 2 ); /* Random noise part */ + LPC_exc_Q10 = SKP_ADD32( LPC_exc_Q10, SKP_RSHIFT_ROUND( LTP_pred_Q14, 4 ) ); /* Harmonic part */ + + /* Update states */ + psDec->sLTP_Q16[ sLTP_buf_idx ] = SKP_LSHIFT( LPC_exc_Q10, 6 ); + sLTP_buf_idx++; + + /* Save LPC residual */ + sig_Q10_ptr[ i ] = LPC_exc_Q10; + } + sig_Q10_ptr += psDec->subfr_length; + /* Gradually reduce LTP gain */ + for( j = 0; j < LTP_ORDER; j++ ) { + B_Q14[ j ] = SKP_RSHIFT( SKP_SMULBB( harm_Gain_Q15, B_Q14[ j ] ), 15 ); + } + /* Gradually reduce excitation gain */ + rand_scale_Q14 = SKP_RSHIFT( SKP_SMULBB( rand_scale_Q14, rand_Gain_Q15 ), 15 ); + + /* Slowly increase pitch lag */ + psPLC->pitchL_Q8 += SKP_SMULWB( psPLC->pitchL_Q8, PITCH_DRIFT_FAC_Q16 ); + psPLC->pitchL_Q8 = SKP_min_32( psPLC->pitchL_Q8, SKP_LSHIFT( SKP_SMULBB( MAX_PITCH_LAG_MS, psDec->fs_kHz ), 8 ) ); + lag = SKP_RSHIFT_ROUND( psPLC->pitchL_Q8, 8 ); + } + + /***************************/ + /* LPC synthesis filtering */ + /***************************/ + sig_Q10_ptr = sig_Q10; + /* Preload LPC coeficients to array on stack. Gives small performance gain */ + SKP_memcpy( A_Q12_tmp, psPLC->prevLPC_Q12, psDec->LPC_order * sizeof( opus_int16 ) ); + SKP_assert( psDec->LPC_order >= 10 ); /* check that unrolling works */ + for( k = 0; k < psDec->nb_subfr; k++ ) { + for( i = 0; i < psDec->subfr_length; i++ ){ + /* partly unrolled */ + LPC_pred_Q10 = SKP_SMULWB( psDec->sLPC_Q14[ MAX_LPC_ORDER + i - 1 ], A_Q12_tmp[ 0 ] ); + LPC_pred_Q10 = SKP_SMLAWB( LPC_pred_Q10, psDec->sLPC_Q14[ MAX_LPC_ORDER + i - 2 ], A_Q12_tmp[ 1 ] ); + LPC_pred_Q10 = SKP_SMLAWB( LPC_pred_Q10, psDec->sLPC_Q14[ MAX_LPC_ORDER + i - 3 ], A_Q12_tmp[ 2 ] ); + LPC_pred_Q10 = SKP_SMLAWB( LPC_pred_Q10, psDec->sLPC_Q14[ MAX_LPC_ORDER + i - 4 ], A_Q12_tmp[ 3 ] ); + LPC_pred_Q10 = SKP_SMLAWB( LPC_pred_Q10, psDec->sLPC_Q14[ MAX_LPC_ORDER + i - 5 ], A_Q12_tmp[ 4 ] ); + LPC_pred_Q10 = SKP_SMLAWB( LPC_pred_Q10, psDec->sLPC_Q14[ MAX_LPC_ORDER + i - 6 ], A_Q12_tmp[ 5 ] ); + LPC_pred_Q10 = SKP_SMLAWB( LPC_pred_Q10, psDec->sLPC_Q14[ MAX_LPC_ORDER + i - 7 ], A_Q12_tmp[ 6 ] ); + LPC_pred_Q10 = SKP_SMLAWB( LPC_pred_Q10, psDec->sLPC_Q14[ MAX_LPC_ORDER + i - 8 ], A_Q12_tmp[ 7 ] ); + LPC_pred_Q10 = SKP_SMLAWB( LPC_pred_Q10, psDec->sLPC_Q14[ MAX_LPC_ORDER + i - 9 ], A_Q12_tmp[ 8 ] ); + LPC_pred_Q10 = SKP_SMLAWB( LPC_pred_Q10, psDec->sLPC_Q14[ MAX_LPC_ORDER + i - 10 ], A_Q12_tmp[ 9 ] ); + + for( j = 10; j < psDec->LPC_order; j++ ) { + LPC_pred_Q10 = SKP_SMLAWB( LPC_pred_Q10, psDec->sLPC_Q14[ MAX_LPC_ORDER + i - j - 1 ], A_Q12_tmp[ j ] ); + } + + /* Add prediction to LPC residual */ + sig_Q10_ptr[ i ] = SKP_ADD32( sig_Q10_ptr[ i ], LPC_pred_Q10 ); + + /* Update states */ + psDec->sLPC_Q14[ MAX_LPC_ORDER + i ] = SKP_LSHIFT( sig_Q10_ptr[ i ], 4 ); + } + sig_Q10_ptr += psDec->subfr_length; + /* Update LPC filter state */ + SKP_memcpy( psDec->sLPC_Q14, &psDec->sLPC_Q14[ psDec->subfr_length ], MAX_LPC_ORDER * sizeof( opus_int32 ) ); + } + + /* Scale with Gain */ + for( i = 0; i < psDec->frame_length; i++ ) { + signal[ i ] = ( opus_int16 )SKP_SAT16( SKP_RSHIFT_ROUND( SKP_SMULWW( sig_Q10[ i ], psPLC->prevGain_Q16[ psDec->nb_subfr - 1 ] ), 10 ) ); + } + + /**************************************/ + /* Update states */ + /**************************************/ + psPLC->rand_seed = rand_seed; + psPLC->randScale_Q14 = rand_scale_Q14; + for( i = 0; i < MAX_NB_SUBFR; i++ ) { + psDecCtrl->pitchL[ i ] = lag; + } +} + +/* Glues concealed frames with new good recieved frames */ +void silk_PLC_glue_frames( + silk_decoder_state *psDec, /* I/O decoder state */ + silk_decoder_control *psDecCtrl, /* I/O Decoder control */ + opus_int16 signal[], /* I/O signal */ + opus_int length /* I length of residual */ +) +{ + opus_int i, energy_shift; + opus_int32 energy; + silk_PLC_struct *psPLC; + psPLC = &psDec->sPLC; + + if( psDec->lossCnt ) { + /* Calculate energy in concealed residual */ + silk_sum_sqr_shift( &psPLC->conc_energy, &psPLC->conc_energy_shift, signal, length ); + + psPLC->last_frame_lost = 1; + } else { + if( psDec->sPLC.last_frame_lost ) { + /* Calculate residual in decoded signal if last frame was lost */ + silk_sum_sqr_shift( &energy, &energy_shift, signal, length ); + + /* Normalize energies */ + if( energy_shift > psPLC->conc_energy_shift ) { + psPLC->conc_energy = SKP_RSHIFT( psPLC->conc_energy, energy_shift - psPLC->conc_energy_shift ); + } else if( energy_shift < psPLC->conc_energy_shift ) { + energy = SKP_RSHIFT( energy, psPLC->conc_energy_shift - energy_shift ); + } + + /* Fade in the energy difference */ + if( energy > psPLC->conc_energy ) { + opus_int32 frac_Q24, LZ; + opus_int32 gain_Q16, slope_Q16; + + LZ = silk_CLZ32( psPLC->conc_energy ); + LZ = LZ - 1; + psPLC->conc_energy = SKP_LSHIFT( psPLC->conc_energy, LZ ); + energy = SKP_RSHIFT( energy, SKP_max_32( 24 - LZ, 0 ) ); + + frac_Q24 = SKP_DIV32( psPLC->conc_energy, SKP_max( energy, 1 ) ); + + gain_Q16 = SKP_LSHIFT( silk_SQRT_APPROX( frac_Q24 ), 4 ); + slope_Q16 = SKP_DIV32_16( ( 1 << 16 ) - gain_Q16, length ); + /* Make slope 4x steeper to avoid missing onsets after DTX */ + slope_Q16 = SKP_LSHIFT( slope_Q16, 2 ); + + for( i = 0; i < length; i++ ) { + signal[ i ] = SKP_SMULWB( gain_Q16, signal[ i ] ); + gain_Q16 += slope_Q16; + if( gain_Q16 > 1 << 16 ) { + break; + } + } + } + } + psPLC->last_frame_lost = 0; + } +} diff --git a/silk/silk_PLC.h b/silk/silk_PLC.h index 3c78e7a33..44297c2b8 100644 --- a/silk/silk_PLC.h +++ b/silk/silk_PLC.h @@ -1,79 +1,79 @@ -/*********************************************************************** -Copyright (c) 2006-2011, Skype Limited. All rights reserved. -Redistribution and use in source and binary forms, with or without -modification, (subject to the limitations in the disclaimer below) -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 Skype Limited, nor the names of specific -contributors, may be used to endorse or promote products derived from -this software without specific prior written permission. -NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED -BY THIS LICENSE. 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. -***********************************************************************/ - -#ifndef SILK_PLC_FIX_H -#define SILK_PLC_FIX_H - -#include "silk_main.h" - -#define BWE_COEF 0.99 -#define V_PITCH_GAIN_START_MIN_Q14 11469 /* 0.7 in Q14 */ -#define V_PITCH_GAIN_START_MAX_Q14 15565 /* 0.95 in Q14 */ -#define MAX_PITCH_LAG_MS 18 -#define SA_THRES_Q8 50 -#define USE_SINGLE_TAP 1 -#define RAND_BUF_SIZE 128 -#define RAND_BUF_MASK (RAND_BUF_SIZE - 1) -#define LOG2_INV_LPC_GAIN_HIGH_THRES 3 /* 2^3 = 8 dB LPC gain */ -#define LOG2_INV_LPC_GAIN_LOW_THRES 8 /* 2^8 = 24 dB LPC gain */ -#define PITCH_DRIFT_FAC_Q16 655 /* 0.01 in Q16 */ - -void silk_PLC_Reset( - silk_decoder_state *psDec /* I/O Decoder state */ -); - -void silk_PLC( - silk_decoder_state *psDec, /* I/O Decoder state */ - silk_decoder_control *psDecCtrl, /* I/O Decoder control */ - opus_int16 signal[], /* I/O signal */ - opus_int length, /* I length of residual */ - opus_int lost /* I Loss flag */ -); - -void silk_PLC_update( - silk_decoder_state *psDec, /* I/O Decoder state */ - silk_decoder_control *psDecCtrl, /* I/O Decoder control */ - opus_int16 signal[], - opus_int length -); - -void silk_PLC_conceal( - silk_decoder_state *psDec, /* I/O Decoder state */ - silk_decoder_control *psDecCtrl, /* I/O Decoder control */ - opus_int16 signal[], /* O LPC residual signal */ - opus_int length /* I length of signal */ -); - -void silk_PLC_glue_frames( - silk_decoder_state *psDec, /* I/O decoder state */ - silk_decoder_control *psDecCtrl, /* I/O Decoder control */ - opus_int16 signal[], /* I/O signal */ - opus_int length /* I length of signal */ -); - -#endif - +/*********************************************************************** +Copyright (c) 2006-2011, Skype Limited. All rights reserved. +Redistribution and use in source and binary forms, with or without +modification, (subject to the limitations in the disclaimer below) +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 Skype Limited, nor the names of specific +contributors, may be used to endorse or promote products derived from +this software without specific prior written permission. +NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED +BY THIS LICENSE. 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. +***********************************************************************/ + +#ifndef SILK_PLC_FIX_H +#define SILK_PLC_FIX_H + +#include "silk_main.h" + +#define BWE_COEF 0.99 +#define V_PITCH_GAIN_START_MIN_Q14 11469 /* 0.7 in Q14 */ +#define V_PITCH_GAIN_START_MAX_Q14 15565 /* 0.95 in Q14 */ +#define MAX_PITCH_LAG_MS 18 +#define SA_THRES_Q8 50 +#define USE_SINGLE_TAP 1 +#define RAND_BUF_SIZE 128 +#define RAND_BUF_MASK (RAND_BUF_SIZE - 1) +#define LOG2_INV_LPC_GAIN_HIGH_THRES 3 /* 2^3 = 8 dB LPC gain */ +#define LOG2_INV_LPC_GAIN_LOW_THRES 8 /* 2^8 = 24 dB LPC gain */ +#define PITCH_DRIFT_FAC_Q16 655 /* 0.01 in Q16 */ + +void silk_PLC_Reset( + silk_decoder_state *psDec /* I/O Decoder state */ +); + +void silk_PLC( + silk_decoder_state *psDec, /* I/O Decoder state */ + silk_decoder_control *psDecCtrl, /* I/O Decoder control */ + opus_int16 signal[], /* I/O signal */ + opus_int length, /* I length of residual */ + opus_int lost /* I Loss flag */ +); + +void silk_PLC_update( + silk_decoder_state *psDec, /* I/O Decoder state */ + silk_decoder_control *psDecCtrl, /* I/O Decoder control */ + opus_int16 signal[], + opus_int length +); + +void silk_PLC_conceal( + silk_decoder_state *psDec, /* I/O Decoder state */ + silk_decoder_control *psDecCtrl, /* I/O Decoder control */ + opus_int16 signal[], /* O LPC residual signal */ + opus_int length /* I length of signal */ +); + +void silk_PLC_glue_frames( + silk_decoder_state *psDec, /* I/O decoder state */ + silk_decoder_control *psDecCtrl, /* I/O Decoder control */ + opus_int16 signal[], /* I/O signal */ + opus_int length /* I length of signal */ +); + +#endif + diff --git a/silk/silk_SigProc_FIX.h b/silk/silk_SigProc_FIX.h index 428e67d5c..2b39f3b75 100644 --- a/silk/silk_SigProc_FIX.h +++ b/silk/silk_SigProc_FIX.h @@ -1,617 +1,617 @@ -/*********************************************************************** -Copyright (c) 2006-2011, Skype Limited. All rights reserved. -Redistribution and use in source and binary forms, with or without -modification, (subject to the limitations in the disclaimer below) -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 Skype Limited, nor the names of specific -contributors, may be used to endorse or promote products derived from -this software without specific prior written permission. -NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED -BY THIS LICENSE. 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. -***********************************************************************/ - -#ifndef _SILK_SIGPROC_FIX_H_ -#define _SILK_SIGPROC_FIX_H_ - -#ifdef __cplusplus -extern "C" -{ -#endif - -//#define SKP_MACRO_COUNT /* Used to enable WMOPS counting */ - -#define SILK_MAX_ORDER_LPC 16 /* max order of the LPC analysis in schur() and k2a() */ - -#include <stdlib.h> /* for abs() */ -#include <string.h> /* for memset(), memcpy(), memmove() */ -#include "silk_typedef.h" -#include "silk_resampler_structs.h" -#include "silk_macros.h" - - -/********************************************************************/ -/* SIGNAL PROCESSING FUNCTIONS */ -/********************************************************************/ - -/*! - * Initialize/reset the resampler state for a given pair of input/output sampling rates -*/ -opus_int silk_resampler_init( - silk_resampler_state_struct *S, /* I/O: Resampler state */ - opus_int32 Fs_Hz_in, /* I: Input sampling rate (Hz) */ - opus_int32 Fs_Hz_out /* I: Output sampling rate (Hz) */ -); - -/*! - * Clear the states of all resampling filters, without resetting sampling rate ratio - */ -opus_int silk_resampler_clear( - silk_resampler_state_struct *S /* I/O: Resampler state */ -); - -/*! - * Resampler: convert from one sampling rate to another - */ -opus_int silk_resampler( - silk_resampler_state_struct *S, /* I/O: Resampler state */ - opus_int16 out[], /* O: Output signal */ - const opus_int16 in[], /* I: Input signal */ - opus_int32 inLen /* I: Number of input samples */ -); - -/*! - Upsample 2x, low quality - */ -void silk_resampler_up2( - opus_int32 *S, /* I/O: State vector [ 2 ] */ - opus_int16 *out, /* O: Output signal [ 2 * len ] */ - const opus_int16 *in, /* I: Input signal [ len ] */ - opus_int32 len /* I: Number of input samples */ -); - -/*! -* Downsample 2x, mediocre quality -*/ -void silk_resampler_down2( - opus_int32 *S, /* I/O: State vector [ 2 ] */ - opus_int16 *out, /* O: Output signal [ len ] */ - const opus_int16 *in, /* I: Input signal [ floor(len/2) ] */ - opus_int32 inLen /* I: Number of input samples */ -); - - -/*! - * Downsample by a factor 2/3, low quality -*/ -void silk_resampler_down2_3( - opus_int32 *S, /* I/O: State vector [ 6 ] */ - opus_int16 *out, /* O: Output signal [ floor(2*inLen/3) ] */ - const opus_int16 *in, /* I: Input signal [ inLen ] */ - opus_int32 inLen /* I: Number of input samples */ -); - -/*! - * Downsample by a factor 3, low quality -*/ -void silk_resampler_down3( - opus_int32 *S, /* I/O: State vector [ 8 ] */ - opus_int16 *out, /* O: Output signal [ floor(inLen/3) ] */ - const opus_int16 *in, /* I: Input signal [ inLen ] */ - opus_int32 inLen /* I: Number of input samples */ -); - -/*! - * second order ARMA filter; - * slower than biquad() but uses more precise coefficients - * can handle (slowly) varying coefficients - */ -void silk_biquad_alt( - const opus_int16 *in, /* I: input signal */ - const opus_int32 *B_Q28, /* I: MA coefficients [3] */ - const opus_int32 *A_Q28, /* I: AR coefficients [2] */ - opus_int32 *S, /* I/O: State vector [2] */ - opus_int16 *out, /* O: output signal */ - const opus_int32 len /* I: signal length (must be even) */ -); - -/* Variable order MA prediction error filter. */ -void silk_LPC_analysis_filter( - opus_int16 *out, /* O: Output signal */ - const opus_int16 *in, /* I: Input signal */ - const opus_int16 *B, /* I: MA prediction coefficients, Q12 [order] */ - const opus_int32 len, /* I: Signal length */ - const opus_int32 Order /* I: Filter order */ -); - -/* Chirp (bandwidth expand) LP AR filter */ -void silk_bwexpander( - opus_int16 *ar, /* I/O AR filter to be expanded (without leading 1) */ - const opus_int d, /* I Length of ar */ - opus_int32 chirp_Q16 /* I Chirp factor (typically in the range 0 to 1) */ -); - -/* Chirp (bandwidth expand) LP AR filter */ -void silk_bwexpander_32( - opus_int32 *ar, /* I/O AR filter to be expanded (without leading 1) */ - const opus_int d, /* I Length of ar */ - opus_int32 chirp_Q16 /* I Chirp factor in Q16 */ -); - -/* Compute inverse of LPC prediction gain, and */ -/* test if LPC coefficients are stable (all poles within unit circle) */ -opus_int silk_LPC_inverse_pred_gain( /* O: Returns 1 if unstable, otherwise 0 */ - opus_int32 *invGain_Q30, /* O: Inverse prediction gain, Q30 energy domain */ - const opus_int16 *A_Q12, /* I: Prediction coefficients, Q12 [order] */ - const opus_int order /* I: Prediction order */ -); - -opus_int silk_LPC_inverse_pred_gain_Q24( /* O: Returns 1 if unstable, otherwise 0 */ - opus_int32 *invGain_Q30, /* O: Inverse prediction gain, Q30 energy domain */ - const opus_int32 *A_Q24, /* I: Prediction coefficients, Q24 [order] */ - const opus_int order /* I: Prediction order */ -); - -/* split signal in two decimated bands using first-order allpass filters */ -void silk_ana_filt_bank_1( - const opus_int16 *in, /* I: Input signal [N] */ - opus_int32 *S, /* I/O: State vector [2] */ - opus_int16 *outL, /* O: Low band [N/2] */ - opus_int16 *outH, /* O: High band [N/2] */ - const opus_int32 N /* I: Number of input samples */ -); - -/********************************************************************/ -/* SCALAR FUNCTIONS */ -/********************************************************************/ - -/* approximation of 128 * log2() (exact inverse of approx 2^() below) */ -/* convert input to a log scale */ -opus_int32 silk_lin2log(const opus_int32 inLin); /* I: input in linear scale */ - -/* Approximation of a sigmoid function */ -opus_int silk_sigm_Q15(opus_int in_Q5); - -/* approximation of 2^() (exact inverse of approx log2() above) */ -/* convert input to a linear scale */ -opus_int32 silk_log2lin(const opus_int32 inLog_Q7); /* I: input on log scale */ - -/* Function that returns the maximum absolut value of the input vector */ -opus_int16 silk_int16_array_maxabs( /* O Maximum absolute value, max: 2^15-1 */ - const opus_int16 *vec, /* I Input vector [len] */ - const opus_int32 len /* I Length of input vector */ -); - -/* Compute number of bits to right shift the sum of squares of a vector */ -/* of int16s to make it fit in an int32 */ -void silk_sum_sqr_shift( - opus_int32 *energy, /* O Energy of x, after shifting to the right */ - opus_int *shift, /* O Number of bits right shift applied to energy */ - const opus_int16 *x, /* I Input vector */ - opus_int len /* I Length of input vector */ -); - -/* Calculates the reflection coefficients from the correlation sequence */ -/* Faster than schur64(), but much less accurate. */ -/* uses SMLAWB(), requiring armv5E and higher. */ -opus_int32 silk_schur( /* O: Returns residual energy */ - opus_int16 *rc_Q15, /* O: reflection coefficients [order] Q15 */ - const opus_int32 *c, /* I: correlations [order+1] */ - const opus_int32 order /* I: prediction order */ -);; - -/* Calculates the reflection coefficients from the correlation sequence */ -/* Slower than schur(), but more accurate. */ -/* Uses SMULL(), available on armv4 */ -opus_int32 silk_schur64( /* O: returns residual energy */ - opus_int32 rc_Q16[], /* O: Reflection coefficients [order] Q16 */ - const opus_int32 c[], /* I: Correlations [order+1] */ - opus_int32 order /* I: Prediction order */ -); - -/* Step up function, converts reflection coefficients to prediction coefficients */ -void silk_k2a( - opus_int32 *A_Q24, /* O: Prediction coefficients [order] Q24 */ - const opus_int16 *rc_Q15, /* I: Reflection coefficients [order] Q15 */ - const opus_int32 order /* I: Prediction order */ -); - -/* Step up function, converts reflection coefficients to prediction coefficients */ -void silk_k2a_Q16( - opus_int32 *A_Q24, /* O: Prediction coefficients [order] Q24 */ - const opus_int32 *rc_Q16, /* I: Reflection coefficients [order] Q16 */ - const opus_int32 order /* I: Prediction order */ -); - -/* Apply sine window to signal vector. */ -/* Window types: */ -/* 1 -> sine window from 0 to pi/2 */ -/* 2 -> sine window from pi/2 to pi */ -/* every other sample of window is linearly interpolated, for speed */ -void silk_apply_sine_window( - opus_int16 px_win[], /* O Pointer to windowed signal */ - const opus_int16 px[], /* I Pointer to input signal */ - const opus_int win_type, /* I Selects a window type */ - const opus_int length /* I Window length, multiple of 4 */ -); - -/* Compute autocorrelation */ -void silk_autocorr( - opus_int32 *results, /* O Result (length correlationCount) */ - opus_int *scale, /* O Scaling of the correlation vector */ - const opus_int16 *inputData, /* I Input data to correlate */ - const opus_int inputDataSize, /* I Length of input */ - const opus_int correlationCount /* I Number of correlation taps to compute */ -); - -/* Pitch estimator */ -#define SILK_PE_MIN_COMPLEX 0 -#define SILK_PE_MID_COMPLEX 1 -#define SILK_PE_MAX_COMPLEX 2 - -void silk_decode_pitch( - opus_int16 lagIndex, /* I */ - opus_int8 contourIndex, /* O */ - opus_int pitch_lags[], /* O 4 pitch values */ - const opus_int Fs_kHz, /* I sampling frequency (kHz) */ - const opus_int nb_subfr /* I number of sub frames */ -); - -opus_int silk_pitch_analysis_core( /* O Voicing estimate: 0 voiced, 1 unvoiced */ - const opus_int16 *signal, /* I Signal of length PE_FRAME_LENGTH_MS*Fs_kHz */ - opus_int *pitch_out, /* O 4 pitch lag values */ - opus_int16 *lagIndex, /* O Lag Index */ - opus_int8 *contourIndex, /* O Pitch contour Index */ - opus_int *LTPCorr_Q15, /* I/O Normalized correlation; input: value from previous frame */ - opus_int prevLag, /* I Last lag of previous frame; set to zero is unvoiced */ - const opus_int32 search_thres1_Q16, /* I First stage threshold for lag candidates 0 - 1 */ - const opus_int search_thres2_Q15, /* I Final threshold for lag candidates 0 - 1 */ - const opus_int Fs_kHz, /* I Sample frequency (kHz) */ - const opus_int complexity, /* I Complexity setting, 0-2, where 2 is highest */ - const opus_int nb_subfr /* I number of 5 ms subframes */ -); - -/* Compute Normalized Line Spectral Frequencies (NLSFs) from whitening filter coefficients */ -/* If not all roots are found, the a_Q16 coefficients are bandwidth expanded until convergence. */ -void silk_A2NLSF( - opus_int16 *NLSF, /* O Normalized Line Spectral Frequencies, Q15 (0 - (2^15-1)), [d] */ - opus_int32 *a_Q16, /* I/O Monic whitening filter coefficients in Q16 [d] */ - const opus_int d /* I Filter order (must be even) */ -); - -/* compute whitening filter coefficients from normalized line spectral frequencies */ -void silk_NLSF2A( - opus_int16 *a_Q12, /* O monic whitening filter coefficients in Q12, [ d ] */ - const opus_int16 *NLSF, /* I normalized line spectral frequencies in Q15, [ d ] */ - const opus_int d /* I filter order (should be even) */ -); - -void silk_insertion_sort_increasing( - opus_int32 *a, /* I/O Unsorted / Sorted vector */ - opus_int *idx, /* O: Index vector for the sorted elements */ - const opus_int L, /* I: Vector length */ - const opus_int K /* I: Number of correctly sorted positions */ -); - -void silk_insertion_sort_decreasing_int16( - opus_int16 *a, /* I/O: Unsorted / Sorted vector */ - opus_int *idx, /* O: Index vector for the sorted elements */ - const opus_int L, /* I: Vector length */ - const opus_int K /* I: Number of correctly sorted positions */ -); - -void silk_insertion_sort_increasing_all_values_int16( - opus_int16 *a, /* I/O: Unsorted / Sorted vector */ - const opus_int L /* I: Vector length */ -); - -/* NLSF stabilizer, for a single input data vector */ -void silk_NLSF_stabilize( - opus_int16 *NLSF_Q15, /* I/O: Unstable/stabilized normalized LSF vector in Q15 [L] */ - const opus_int16 *NDeltaMin_Q15, /* I: Normalized delta min vector in Q15, NDeltaMin_Q15[L] must be >= 1 [L+1] */ - const opus_int L /* I: Number of NLSF parameters in the input vector */ -); - -/* Laroia low complexity NLSF weights */ -void silk_NLSF_VQ_weights_laroia( - opus_int16 *pNLSFW_Q_OUT, /* O: Pointer to input vector weights [D x 1] */ - const opus_int16 *pNLSF_Q15, /* I: Pointer to input vector [D x 1] */ - const opus_int D /* I: Input vector dimension (even) */ -); - -/* Compute reflection coefficients from input signal */ -void silk_burg_modified( - opus_int32 *res_nrg, /* O residual energy */ - opus_int *res_nrgQ, /* O residual energy Q value */ - opus_int32 A_Q16[], /* O prediction coefficients (length order) */ - const opus_int16 x[], /* I input signal, length: nb_subfr * ( D + subfr_length ) */ - const opus_int subfr_length, /* I input signal subframe length (including D preceeding samples) */ - const opus_int nb_subfr, /* I number of subframes stacked in x */ - const opus_int32 WhiteNoiseFrac_Q32, /* I fraction added to zero-lag autocorrelation */ - const opus_int D /* I order */ -); - -/* Copy and multiply a vector by a constant */ -void silk_scale_copy_vector16( - opus_int16 *data_out, - const opus_int16 *data_in, - opus_int32 gain_Q16, /* I: gain in Q16 */ - const opus_int dataSize /* I: length */ -); - -/* Some for the LTP related function requires Q26 to work.*/ -void silk_scale_vector32_Q26_lshift_18( - opus_int32 *data1, /* I/O: Q0/Q18 */ - opus_int32 gain_Q26, /* I: Q26 */ - opus_int dataSize /* I: length */ -); - -/********************************************************************/ -/* INLINE ARM MATH */ -/********************************************************************/ - -/* return sum(inVec1[i]*inVec2[i]) */ -opus_int32 silk_inner_prod_aligned( - const opus_int16 *const inVec1, /* I input vector 1 */ - const opus_int16 *const inVec2, /* I input vector 2 */ - const opus_int len /* I vector lengths */ -); - -opus_int32 silk_inner_prod_aligned_scale( - const opus_int16 *const inVec1, /* I input vector 1 */ - const opus_int16 *const inVec2, /* I input vector 2 */ - const opus_int scale, /* I number of bits to shift */ - const opus_int len /* I vector lengths */ -); - -opus_int64 silk_inner_prod16_aligned_64( - const opus_int16 *inVec1, /* I input vector 1 */ - const opus_int16 *inVec2, /* I input vector 2 */ - const opus_int len /* I vector lengths */ -); - -/********************************************************************/ -/* MACROS */ -/********************************************************************/ - -/* Rotate a32 right by 'rot' bits. Negative rot values result in rotating - left. Output is 32bit int. - Note: contemporary compilers recognize the C expression below and - compile it into a 'ror' instruction if available. No need for inline ASM! */ -SKP_INLINE opus_int32 silk_ROR32( opus_int32 a32, opus_int rot ) -{ - opus_uint32 x = (opus_uint32) a32; - opus_uint32 r = (opus_uint32) rot; - opus_uint32 m = (opus_uint32) -rot; - if(rot <= 0) - return (opus_int32) ((x << m) | (x >> (32 - m))); - else - return (opus_int32) ((x << (32 - r)) | (x >> r)); -} - -/* Allocate opus_int16 alligned to 4-byte memory address */ -#if EMBEDDED_ARM -#define SKP_DWORD_ALIGN __attribute__((aligned(4))) -#else -#define SKP_DWORD_ALIGN -#endif - -/* Useful Macros that can be adjusted to other platforms */ -#define SKP_memcpy(a, b, c) memcpy((a), (b), (c)) /* Dest, Src, ByteCount */ -#define SKP_memset(a, b, c) memset((a), (b), (c)) /* Dest, value, ByteCount */ -#define SKP_memmove(a, b, c) memmove((a), (b), (c)) /* Dest, Src, ByteCount */ -/* fixed point macros */ - -// (a32 * b32) output have to be 32bit int -#define SKP_MUL(a32, b32) ((a32) * (b32)) - -// (a32 * b32) output have to be 32bit uint -#define SKP_MUL_uint(a32, b32) SKP_MUL(a32, b32) - -// a32 + (b32 * c32) output have to be 32bit int -#define SKP_MLA(a32, b32, c32) SKP_ADD32((a32),((b32) * (c32))) - -// a32 + (b32 * c32) output have to be 32bit uint -#define SKP_MLA_uint(a32, b32, c32) SKP_MLA(a32, b32, c32) - -// ((a32 >> 16) * (b32 >> 16)) output have to be 32bit int -#define SKP_SMULTT(a32, b32) (((a32) >> 16) * ((b32) >> 16)) - -// a32 + ((a32 >> 16) * (b32 >> 16)) output have to be 32bit int -#define SKP_SMLATT(a32, b32, c32) SKP_ADD32((a32),((b32) >> 16) * ((c32) >> 16)) - -#define SKP_SMLALBB(a64, b16, c16) SKP_ADD64((a64),(opus_int64)((opus_int32)(b16) * (opus_int32)(c16))) - -// (a32 * b32) -#define SKP_SMULL(a32, b32) ((opus_int64)(a32) * /*(opus_int64)*/(b32)) - -// multiply-accumulate macros that allow overflow in the addition (ie, no asserts in debug mode) -#define SKP_MLA_ovflw(a32, b32, c32) SKP_MLA(a32, b32, c32) -#ifndef SKP_SMLABB_ovflw -# define SKP_SMLABB_ovflw(a32, b32, c32) SKP_SMLABB(a32, b32, c32) -#endif -#define SKP_SMLABT_ovflw(a32, b32, c32) SKP_SMLABT(a32, b32, c32) -#define SKP_SMLATT_ovflw(a32, b32, c32) SKP_SMLATT(a32, b32, c32) -#define SKP_SMLAWB_ovflw(a32, b32, c32) SKP_SMLAWB(a32, b32, c32) -#define SKP_SMLAWT_ovflw(a32, b32, c32) SKP_SMLAWT(a32, b32, c32) - -#define SKP_DIV32_16(a32, b16) ((opus_int32)((a32) / (b16))) -#define SKP_DIV32(a32, b32) ((opus_int32)((a32) / (b32))) - -// These macros enables checking for overflow in silk_API_Debug.h -#define SKP_ADD16(a, b) ((a) + (b)) -#define SKP_ADD32(a, b) ((a) + (b)) -#define SKP_ADD64(a, b) ((a) + (b)) - -#define SKP_SUB16(a, b) ((a) - (b)) -#define SKP_SUB32(a, b) ((a) - (b)) -#define SKP_SUB64(a, b) ((a) - (b)) - -#define SKP_SAT8(a) ((a) > SKP_int8_MAX ? SKP_int8_MAX : \ - ((a) < SKP_int8_MIN ? SKP_int8_MIN : (a))) -#define SKP_SAT16(a) ((a) > SKP_int16_MAX ? SKP_int16_MAX : \ - ((a) < SKP_int16_MIN ? SKP_int16_MIN : (a))) -#define SKP_SAT32(a) ((a) > SKP_int32_MAX ? SKP_int32_MAX : \ - ((a) < SKP_int32_MIN ? SKP_int32_MIN : (a))) - -#define SKP_CHECK_FIT8(a) (a) -#define SKP_CHECK_FIT16(a) (a) -#define SKP_CHECK_FIT32(a) (a) - -#define SKP_ADD_SAT16(a, b) (opus_int16)SKP_SAT16( SKP_ADD32( (opus_int32)(a), (b) ) ) -#define SKP_ADD_SAT64(a, b) ((((a) + (b)) & 0x8000000000000000LL) == 0 ? \ - ((((a) & (b)) & 0x8000000000000000LL) != 0 ? SKP_int64_MIN : (a)+(b)) : \ - ((((a) | (b)) & 0x8000000000000000LL) == 0 ? SKP_int64_MAX : (a)+(b)) ) - -#define SKP_SUB_SAT16(a, b) (opus_int16)SKP_SAT16( SKP_SUB32( (opus_int32)(a), (b) ) ) -#define SKP_SUB_SAT64(a, b) ((((a)-(b)) & 0x8000000000000000LL) == 0 ? \ - (( (a) & ((b)^0x8000000000000000LL) & 0x8000000000000000LL) ? SKP_int64_MIN : (a)-(b)) : \ - ((((a)^0x8000000000000000LL) & (b) & 0x8000000000000000LL) ? SKP_int64_MAX : (a)-(b)) ) - -/* Saturation for positive input values */ -#define SKP_POS_SAT32(a) ((a) > SKP_int32_MAX ? SKP_int32_MAX : (a)) - -/* Add with saturation for positive input values */ -#define SKP_ADD_POS_SAT8(a, b) ((((a)+(b)) & 0x80) ? SKP_int8_MAX : ((a)+(b))) -#define SKP_ADD_POS_SAT16(a, b) ((((a)+(b)) & 0x8000) ? SKP_int16_MAX : ((a)+(b))) -#define SKP_ADD_POS_SAT32(a, b) ((((a)+(b)) & 0x80000000) ? SKP_int32_MAX : ((a)+(b))) -#define SKP_ADD_POS_SAT64(a, b) ((((a)+(b)) & 0x8000000000000000LL) ? SKP_int64_MAX : ((a)+(b))) - -#define SKP_LSHIFT8(a, shift) ((a)<<(shift)) // shift >= 0, shift < 8 -#define SKP_LSHIFT16(a, shift) ((a)<<(shift)) // shift >= 0, shift < 16 -#define SKP_LSHIFT32(a, shift) ((a)<<(shift)) // shift >= 0, shift < 32 -#define SKP_LSHIFT64(a, shift) ((a)<<(shift)) // shift >= 0, shift < 64 -#define SKP_LSHIFT(a, shift) SKP_LSHIFT32(a, shift) // shift >= 0, shift < 32 - -#define SKP_RSHIFT8(a, shift) ((a)>>(shift)) // shift >= 0, shift < 8 -#define SKP_RSHIFT16(a, shift) ((a)>>(shift)) // shift >= 0, shift < 16 -#define SKP_RSHIFT32(a, shift) ((a)>>(shift)) // shift >= 0, shift < 32 -#define SKP_RSHIFT64(a, shift) ((a)>>(shift)) // shift >= 0, shift < 64 -#define SKP_RSHIFT(a, shift) SKP_RSHIFT32(a, shift) // shift >= 0, shift < 32 - -/* saturates before shifting */ -#define SKP_LSHIFT_SAT16(a, shift) (SKP_LSHIFT16( SKP_LIMIT( (a), SKP_RSHIFT16( SKP_int16_MIN, (shift) ), \ - SKP_RSHIFT16( SKP_int16_MAX, (shift) ) ), (shift) )) -#define SKP_LSHIFT_SAT32(a, shift) (SKP_LSHIFT32( SKP_LIMIT( (a), SKP_RSHIFT32( SKP_int32_MIN, (shift) ), \ - SKP_RSHIFT32( SKP_int32_MAX, (shift) ) ), (shift) )) - -#define SKP_LSHIFT_ovflw(a, shift) ((a)<<(shift)) // shift >= 0, allowed to overflow -#define SKP_LSHIFT_uint(a, shift) ((a)<<(shift)) // shift >= 0 -#define SKP_RSHIFT_uint(a, shift) ((a)>>(shift)) // shift >= 0 - -#define SKP_ADD_LSHIFT(a, b, shift) ((a) + SKP_LSHIFT((b), (shift))) // shift >= 0 -#define SKP_ADD_LSHIFT32(a, b, shift) SKP_ADD32((a), SKP_LSHIFT32((b), (shift))) // shift >= 0 -#define SKP_ADD_LSHIFT_uint(a, b, shift) ((a) + SKP_LSHIFT_uint((b), (shift))) // shift >= 0 -#define SKP_ADD_RSHIFT(a, b, shift) ((a) + SKP_RSHIFT((b), (shift))) // shift >= 0 -#define SKP_ADD_RSHIFT32(a, b, shift) SKP_ADD32((a), SKP_RSHIFT32((b), (shift))) // shift >= 0 -#define SKP_ADD_RSHIFT_uint(a, b, shift) ((a) + SKP_RSHIFT_uint((b), (shift))) // shift >= 0 -#define SKP_SUB_LSHIFT32(a, b, shift) SKP_SUB32((a), SKP_LSHIFT32((b), (shift))) // shift >= 0 -#define SKP_SUB_RSHIFT32(a, b, shift) SKP_SUB32((a), SKP_RSHIFT32((b), (shift))) // shift >= 0 - -/* Requires that shift > 0 */ -#define SKP_RSHIFT_ROUND(a, shift) ((shift) == 1 ? ((a) >> 1) + ((a) & 1) : (((a) >> ((shift) - 1)) + 1) >> 1) -#define SKP_RSHIFT_ROUND64(a, shift) ((shift) == 1 ? ((a) >> 1) + ((a) & 1) : (((a) >> ((shift) - 1)) + 1) >> 1) - -/* Number of rightshift required to fit the multiplication */ -#define SKP_NSHIFT_MUL_32_32(a, b) ( -(31- (32-silk_CLZ32(SKP_abs(a)) + (32-silk_CLZ32(SKP_abs(b))))) ) -#define SKP_NSHIFT_MUL_16_16(a, b) ( -(15- (16-silk_CLZ16(SKP_abs(a)) + (16-silk_CLZ16(SKP_abs(b))))) ) - - -#define SKP_min(a, b) (((a) < (b)) ? (a) : (b)) -#define SKP_max(a, b) (((a) > (b)) ? (a) : (b)) - -/* Macro to convert floating-point constants to fixed-point */ -#define SILK_FIX_CONST( C, Q ) ((opus_int32)((C) * ((opus_int64)1 << (Q)) + 0.5)) - -/* SKP_min() versions with typecast in the function call */ -SKP_INLINE opus_int SKP_min_int(opus_int a, opus_int b) -{ - return (((a) < (b)) ? (a) : (b)); -} -SKP_INLINE opus_int16 SKP_min_16(opus_int16 a, opus_int16 b) -{ - return (((a) < (b)) ? (a) : (b)); -} -SKP_INLINE opus_int32 SKP_min_32(opus_int32 a, opus_int32 b) -{ - return (((a) < (b)) ? (a) : (b)); -} -SKP_INLINE opus_int64 SKP_min_64(opus_int64 a, opus_int64 b) -{ - return (((a) < (b)) ? (a) : (b)); -} - -/* SKP_min() versions with typecast in the function call */ -SKP_INLINE opus_int SKP_max_int(opus_int a, opus_int b) -{ - return (((a) > (b)) ? (a) : (b)); -} -SKP_INLINE opus_int16 SKP_max_16(opus_int16 a, opus_int16 b) -{ - return (((a) > (b)) ? (a) : (b)); -} -SKP_INLINE opus_int32 SKP_max_32(opus_int32 a, opus_int32 b) -{ - return (((a) > (b)) ? (a) : (b)); -} -SKP_INLINE opus_int64 SKP_max_64(opus_int64 a, opus_int64 b) -{ - return (((a) > (b)) ? (a) : (b)); -} - -#define SKP_LIMIT( a, limit1, limit2) ((limit1) > (limit2) ? ((a) > (limit1) ? (limit1) : ((a) < (limit2) ? (limit2) : (a))) \ - : ((a) > (limit2) ? (limit2) : ((a) < (limit1) ? (limit1) : (a)))) - -#define SKP_LIMIT_int SKP_LIMIT -#define SKP_LIMIT_16 SKP_LIMIT -#define SKP_LIMIT_32 SKP_LIMIT - -//#define SKP_non_neg(a) ((a) & ((-(a)) >> (8 * sizeof(a) - 1))) /* doesn't seem faster than SKP_max(0, a); - -#define SKP_abs(a) (((a) > 0) ? (a) : -(a)) // Be careful, SKP_abs returns wrong when input equals to SKP_intXX_MIN -#define SKP_abs_int(a) (((a) ^ ((a) >> (8 * sizeof(a) - 1))) - ((a) >> (8 * sizeof(a) - 1))) -#define SKP_abs_int32(a) (((a) ^ ((a) >> 31)) - ((a) >> 31)) -#define SKP_abs_int64(a) (((a) > 0) ? (a) : -(a)) - -#define SKP_sign(a) ((a) > 0 ? 1 : ( (a) < 0 ? -1 : 0 )) - -#define SKP_sqrt(a) (sqrt(a)) - -/* PSEUDO-RANDOM GENERATOR */ -/* Make sure to store the result as the seed for the next call (also in between */ -/* frames), otherwise result won't be random at all. When only using some of the */ -/* bits, take the most significant bits by right-shifting. */ -#define SKP_RAND(seed) (SKP_MLA_ovflw(907633515, (seed), 196314165)) - -// Add some multiplication functions that can be easily mapped to ARM. - -// SKP_SMMUL: Signed top word multiply. -// ARMv6 2 instruction cycles. -// ARMv3M+ 3 instruction cycles. use SMULL and ignore LSB registers.(except xM) -//#define SKP_SMMUL(a32, b32) (opus_int32)SKP_RSHIFT(SKP_SMLAL(SKP_SMULWB((a32), (b32)), (a32), SKP_RSHIFT_ROUND((b32), 16)), 16) -// the following seems faster on x86 -#define SKP_SMMUL(a32, b32) (opus_int32)SKP_RSHIFT64(SKP_SMULL((a32), (b32)), 32) - -#include "silk_Inlines.h" -#include "silk_MacroCount.h" -#include "silk_MacroDebug.h" - -#ifdef __cplusplus -} -#endif - -#endif +/*********************************************************************** +Copyright (c) 2006-2011, Skype Limited. All rights reserved. +Redistribution and use in source and binary forms, with or without +modification, (subject to the limitations in the disclaimer below) +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 Skype Limited, nor the names of specific +contributors, may be used to endorse or promote products derived from +this software without specific prior written permission. +NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED +BY THIS LICENSE. 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. +***********************************************************************/ + +#ifndef _SILK_SIGPROC_FIX_H_ +#define _SILK_SIGPROC_FIX_H_ + +#ifdef __cplusplus +extern "C" +{ +#endif + +//#define SKP_MACRO_COUNT /* Used to enable WMOPS counting */ + +#define SILK_MAX_ORDER_LPC 16 /* max order of the LPC analysis in schur() and k2a() */ + +#include <stdlib.h> /* for abs() */ +#include <string.h> /* for memset(), memcpy(), memmove() */ +#include "silk_typedef.h" +#include "silk_resampler_structs.h" +#include "silk_macros.h" + + +/********************************************************************/ +/* SIGNAL PROCESSING FUNCTIONS */ +/********************************************************************/ + +/*! + * Initialize/reset the resampler state for a given pair of input/output sampling rates +*/ +opus_int silk_resampler_init( + silk_resampler_state_struct *S, /* I/O: Resampler state */ + opus_int32 Fs_Hz_in, /* I: Input sampling rate (Hz) */ + opus_int32 Fs_Hz_out /* I: Output sampling rate (Hz) */ +); + +/*! + * Clear the states of all resampling filters, without resetting sampling rate ratio + */ +opus_int silk_resampler_clear( + silk_resampler_state_struct *S /* I/O: Resampler state */ +); + +/*! + * Resampler: convert from one sampling rate to another + */ +opus_int silk_resampler( + silk_resampler_state_struct *S, /* I/O: Resampler state */ + opus_int16 out[], /* O: Output signal */ + const opus_int16 in[], /* I: Input signal */ + opus_int32 inLen /* I: Number of input samples */ +); + +/*! + Upsample 2x, low quality + */ +void silk_resampler_up2( + opus_int32 *S, /* I/O: State vector [ 2 ] */ + opus_int16 *out, /* O: Output signal [ 2 * len ] */ + const opus_int16 *in, /* I: Input signal [ len ] */ + opus_int32 len /* I: Number of input samples */ +); + +/*! +* Downsample 2x, mediocre quality +*/ +void silk_resampler_down2( + opus_int32 *S, /* I/O: State vector [ 2 ] */ + opus_int16 *out, /* O: Output signal [ len ] */ + const opus_int16 *in, /* I: Input signal [ floor(len/2) ] */ + opus_int32 inLen /* I: Number of input samples */ +); + + +/*! + * Downsample by a factor 2/3, low quality +*/ +void silk_resampler_down2_3( + opus_int32 *S, /* I/O: State vector [ 6 ] */ + opus_int16 *out, /* O: Output signal [ floor(2*inLen/3) ] */ + const opus_int16 *in, /* I: Input signal [ inLen ] */ + opus_int32 inLen /* I: Number of input samples */ +); + +/*! + * Downsample by a factor 3, low quality +*/ +void silk_resampler_down3( + opus_int32 *S, /* I/O: State vector [ 8 ] */ + opus_int16 *out, /* O: Output signal [ floor(inLen/3) ] */ + const opus_int16 *in, /* I: Input signal [ inLen ] */ + opus_int32 inLen /* I: Number of input samples */ +); + +/*! + * second order ARMA filter; + * slower than biquad() but uses more precise coefficients + * can handle (slowly) varying coefficients + */ +void silk_biquad_alt( + const opus_int16 *in, /* I: input signal */ + const opus_int32 *B_Q28, /* I: MA coefficients [3] */ + const opus_int32 *A_Q28, /* I: AR coefficients [2] */ + opus_int32 *S, /* I/O: State vector [2] */ + opus_int16 *out, /* O: output signal */ + const opus_int32 len /* I: signal length (must be even) */ +); + +/* Variable order MA prediction error filter. */ +void silk_LPC_analysis_filter( + opus_int16 *out, /* O: Output signal */ + const opus_int16 *in, /* I: Input signal */ + const opus_int16 *B, /* I: MA prediction coefficients, Q12 [order] */ + const opus_int32 len, /* I: Signal length */ + const opus_int32 Order /* I: Filter order */ +); + +/* Chirp (bandwidth expand) LP AR filter */ +void silk_bwexpander( + opus_int16 *ar, /* I/O AR filter to be expanded (without leading 1) */ + const opus_int d, /* I Length of ar */ + opus_int32 chirp_Q16 /* I Chirp factor (typically in the range 0 to 1) */ +); + +/* Chirp (bandwidth expand) LP AR filter */ +void silk_bwexpander_32( + opus_int32 *ar, /* I/O AR filter to be expanded (without leading 1) */ + const opus_int d, /* I Length of ar */ + opus_int32 chirp_Q16 /* I Chirp factor in Q16 */ +); + +/* Compute inverse of LPC prediction gain, and */ +/* test if LPC coefficients are stable (all poles within unit circle) */ +opus_int silk_LPC_inverse_pred_gain( /* O: Returns 1 if unstable, otherwise 0 */ + opus_int32 *invGain_Q30, /* O: Inverse prediction gain, Q30 energy domain */ + const opus_int16 *A_Q12, /* I: Prediction coefficients, Q12 [order] */ + const opus_int order /* I: Prediction order */ +); + +opus_int silk_LPC_inverse_pred_gain_Q24( /* O: Returns 1 if unstable, otherwise 0 */ + opus_int32 *invGain_Q30, /* O: Inverse prediction gain, Q30 energy domain */ + const opus_int32 *A_Q24, /* I: Prediction coefficients, Q24 [order] */ + const opus_int order /* I: Prediction order */ +); + +/* split signal in two decimated bands using first-order allpass filters */ +void silk_ana_filt_bank_1( + const opus_int16 *in, /* I: Input signal [N] */ + opus_int32 *S, /* I/O: State vector [2] */ + opus_int16 *outL, /* O: Low band [N/2] */ + opus_int16 *outH, /* O: High band [N/2] */ + const opus_int32 N /* I: Number of input samples */ +); + +/********************************************************************/ +/* SCALAR FUNCTIONS */ +/********************************************************************/ + +/* approximation of 128 * log2() (exact inverse of approx 2^() below) */ +/* convert input to a log scale */ +opus_int32 silk_lin2log(const opus_int32 inLin); /* I: input in linear scale */ + +/* Approximation of a sigmoid function */ +opus_int silk_sigm_Q15(opus_int in_Q5); + +/* approximation of 2^() (exact inverse of approx log2() above) */ +/* convert input to a linear scale */ +opus_int32 silk_log2lin(const opus_int32 inLog_Q7); /* I: input on log scale */ + +/* Function that returns the maximum absolut value of the input vector */ +opus_int16 silk_int16_array_maxabs( /* O Maximum absolute value, max: 2^15-1 */ + const opus_int16 *vec, /* I Input vector [len] */ + const opus_int32 len /* I Length of input vector */ +); + +/* Compute number of bits to right shift the sum of squares of a vector */ +/* of int16s to make it fit in an int32 */ +void silk_sum_sqr_shift( + opus_int32 *energy, /* O Energy of x, after shifting to the right */ + opus_int *shift, /* O Number of bits right shift applied to energy */ + const opus_int16 *x, /* I Input vector */ + opus_int len /* I Length of input vector */ +); + +/* Calculates the reflection coefficients from the correlation sequence */ +/* Faster than schur64(), but much less accurate. */ +/* uses SMLAWB(), requiring armv5E and higher. */ +opus_int32 silk_schur( /* O: Returns residual energy */ + opus_int16 *rc_Q15, /* O: reflection coefficients [order] Q15 */ + const opus_int32 *c, /* I: correlations [order+1] */ + const opus_int32 order /* I: prediction order */ +);; + +/* Calculates the reflection coefficients from the correlation sequence */ +/* Slower than schur(), but more accurate. */ +/* Uses SMULL(), available on armv4 */ +opus_int32 silk_schur64( /* O: returns residual energy */ + opus_int32 rc_Q16[], /* O: Reflection coefficients [order] Q16 */ + const opus_int32 c[], /* I: Correlations [order+1] */ + opus_int32 order /* I: Prediction order */ +); + +/* Step up function, converts reflection coefficients to prediction coefficients */ +void silk_k2a( + opus_int32 *A_Q24, /* O: Prediction coefficients [order] Q24 */ + const opus_int16 *rc_Q15, /* I: Reflection coefficients [order] Q15 */ + const opus_int32 order /* I: Prediction order */ +); + +/* Step up function, converts reflection coefficients to prediction coefficients */ +void silk_k2a_Q16( + opus_int32 *A_Q24, /* O: Prediction coefficients [order] Q24 */ + const opus_int32 *rc_Q16, /* I: Reflection coefficients [order] Q16 */ + const opus_int32 order /* I: Prediction order */ +); + +/* Apply sine window to signal vector. */ +/* Window types: */ +/* 1 -> sine window from 0 to pi/2 */ +/* 2 -> sine window from pi/2 to pi */ +/* every other sample of window is linearly interpolated, for speed */ +void silk_apply_sine_window( + opus_int16 px_win[], /* O Pointer to windowed signal */ + const opus_int16 px[], /* I Pointer to input signal */ + const opus_int win_type, /* I Selects a window type */ + const opus_int length /* I Window length, multiple of 4 */ +); + +/* Compute autocorrelation */ +void silk_autocorr( + opus_int32 *results, /* O Result (length correlationCount) */ + opus_int *scale, /* O Scaling of the correlation vector */ + const opus_int16 *inputData, /* I Input data to correlate */ + const opus_int inputDataSize, /* I Length of input */ + const opus_int correlationCount /* I Number of correlation taps to compute */ +); + +/* Pitch estimator */ +#define SILK_PE_MIN_COMPLEX 0 +#define SILK_PE_MID_COMPLEX 1 +#define SILK_PE_MAX_COMPLEX 2 + +void silk_decode_pitch( + opus_int16 lagIndex, /* I */ + opus_int8 contourIndex, /* O */ + opus_int pitch_lags[], /* O 4 pitch values */ + const opus_int Fs_kHz, /* I sampling frequency (kHz) */ + const opus_int nb_subfr /* I number of sub frames */ +); + +opus_int silk_pitch_analysis_core( /* O Voicing estimate: 0 voiced, 1 unvoiced */ + const opus_int16 *signal, /* I Signal of length PE_FRAME_LENGTH_MS*Fs_kHz */ + opus_int *pitch_out, /* O 4 pitch lag values */ + opus_int16 *lagIndex, /* O Lag Index */ + opus_int8 *contourIndex, /* O Pitch contour Index */ + opus_int *LTPCorr_Q15, /* I/O Normalized correlation; input: value from previous frame */ + opus_int prevLag, /* I Last lag of previous frame; set to zero is unvoiced */ + const opus_int32 search_thres1_Q16, /* I First stage threshold for lag candidates 0 - 1 */ + const opus_int search_thres2_Q15, /* I Final threshold for lag candidates 0 - 1 */ + const opus_int Fs_kHz, /* I Sample frequency (kHz) */ + const opus_int complexity, /* I Complexity setting, 0-2, where 2 is highest */ + const opus_int nb_subfr /* I number of 5 ms subframes */ +); + +/* Compute Normalized Line Spectral Frequencies (NLSFs) from whitening filter coefficients */ +/* If not all roots are found, the a_Q16 coefficients are bandwidth expanded until convergence. */ +void silk_A2NLSF( + opus_int16 *NLSF, /* O Normalized Line Spectral Frequencies, Q15 (0 - (2^15-1)), [d] */ + opus_int32 *a_Q16, /* I/O Monic whitening filter coefficients in Q16 [d] */ + const opus_int d /* I Filter order (must be even) */ +); + +/* compute whitening filter coefficients from normalized line spectral frequencies */ +void silk_NLSF2A( + opus_int16 *a_Q12, /* O monic whitening filter coefficients in Q12, [ d ] */ + const opus_int16 *NLSF, /* I normalized line spectral frequencies in Q15, [ d ] */ + const opus_int d /* I filter order (should be even) */ +); + +void silk_insertion_sort_increasing( + opus_int32 *a, /* I/O Unsorted / Sorted vector */ + opus_int *idx, /* O: Index vector for the sorted elements */ + const opus_int L, /* I: Vector length */ + const opus_int K /* I: Number of correctly sorted positions */ +); + +void silk_insertion_sort_decreasing_int16( + opus_int16 *a, /* I/O: Unsorted / Sorted vector */ + opus_int *idx, /* O: Index vector for the sorted elements */ + const opus_int L, /* I: Vector length */ + const opus_int K /* I: Number of correctly sorted positions */ +); + +void silk_insertion_sort_increasing_all_values_int16( + opus_int16 *a, /* I/O: Unsorted / Sorted vector */ + const opus_int L /* I: Vector length */ +); + +/* NLSF stabilizer, for a single input data vector */ +void silk_NLSF_stabilize( + opus_int16 *NLSF_Q15, /* I/O: Unstable/stabilized normalized LSF vector in Q15 [L] */ + const opus_int16 *NDeltaMin_Q15, /* I: Normalized delta min vector in Q15, NDeltaMin_Q15[L] must be >= 1 [L+1] */ + const opus_int L /* I: Number of NLSF parameters in the input vector */ +); + +/* Laroia low complexity NLSF weights */ +void silk_NLSF_VQ_weights_laroia( + opus_int16 *pNLSFW_Q_OUT, /* O: Pointer to input vector weights [D x 1] */ + const opus_int16 *pNLSF_Q15, /* I: Pointer to input vector [D x 1] */ + const opus_int D /* I: Input vector dimension (even) */ +); + +/* Compute reflection coefficients from input signal */ +void silk_burg_modified( + opus_int32 *res_nrg, /* O residual energy */ + opus_int *res_nrgQ, /* O residual energy Q value */ + opus_int32 A_Q16[], /* O prediction coefficients (length order) */ + const opus_int16 x[], /* I input signal, length: nb_subfr * ( D + subfr_length ) */ + const opus_int subfr_length, /* I input signal subframe length (including D preceeding samples) */ + const opus_int nb_subfr, /* I number of subframes stacked in x */ + const opus_int32 WhiteNoiseFrac_Q32, /* I fraction added to zero-lag autocorrelation */ + const opus_int D /* I order */ +); + +/* Copy and multiply a vector by a constant */ +void silk_scale_copy_vector16( + opus_int16 *data_out, + const opus_int16 *data_in, + opus_int32 gain_Q16, /* I: gain in Q16 */ + const opus_int dataSize /* I: length */ +); + +/* Some for the LTP related function requires Q26 to work.*/ +void silk_scale_vector32_Q26_lshift_18( + opus_int32 *data1, /* I/O: Q0/Q18 */ + opus_int32 gain_Q26, /* I: Q26 */ + opus_int dataSize /* I: length */ +); + +/********************************************************************/ +/* INLINE ARM MATH */ +/********************************************************************/ + +/* return sum(inVec1[i]*inVec2[i]) */ +opus_int32 silk_inner_prod_aligned( + const opus_int16 *const inVec1, /* I input vector 1 */ + const opus_int16 *const inVec2, /* I input vector 2 */ + const opus_int len /* I vector lengths */ +); + +opus_int32 silk_inner_prod_aligned_scale( + const opus_int16 *const inVec1, /* I input vector 1 */ + const opus_int16 *const inVec2, /* I input vector 2 */ + const opus_int scale, /* I number of bits to shift */ + const opus_int len /* I vector lengths */ +); + +opus_int64 silk_inner_prod16_aligned_64( + const opus_int16 *inVec1, /* I input vector 1 */ + const opus_int16 *inVec2, /* I input vector 2 */ + const opus_int len /* I vector lengths */ +); + +/********************************************************************/ +/* MACROS */ +/********************************************************************/ + +/* Rotate a32 right by 'rot' bits. Negative rot values result in rotating + left. Output is 32bit int. + Note: contemporary compilers recognize the C expression below and + compile it into a 'ror' instruction if available. No need for inline ASM! */ +SKP_INLINE opus_int32 silk_ROR32( opus_int32 a32, opus_int rot ) +{ + opus_uint32 x = (opus_uint32) a32; + opus_uint32 r = (opus_uint32) rot; + opus_uint32 m = (opus_uint32) -rot; + if(rot <= 0) + return (opus_int32) ((x << m) | (x >> (32 - m))); + else + return (opus_int32) ((x << (32 - r)) | (x >> r)); +} + +/* Allocate opus_int16 alligned to 4-byte memory address */ +#if EMBEDDED_ARM +#define SKP_DWORD_ALIGN __attribute__((aligned(4))) +#else +#define SKP_DWORD_ALIGN +#endif + +/* Useful Macros that can be adjusted to other platforms */ +#define SKP_memcpy(a, b, c) memcpy((a), (b), (c)) /* Dest, Src, ByteCount */ +#define SKP_memset(a, b, c) memset((a), (b), (c)) /* Dest, value, ByteCount */ +#define SKP_memmove(a, b, c) memmove((a), (b), (c)) /* Dest, Src, ByteCount */ +/* fixed point macros */ + +// (a32 * b32) output have to be 32bit int +#define SKP_MUL(a32, b32) ((a32) * (b32)) + +// (a32 * b32) output have to be 32bit uint +#define SKP_MUL_uint(a32, b32) SKP_MUL(a32, b32) + +// a32 + (b32 * c32) output have to be 32bit int +#define SKP_MLA(a32, b32, c32) SKP_ADD32((a32),((b32) * (c32))) + +// a32 + (b32 * c32) output have to be 32bit uint +#define SKP_MLA_uint(a32, b32, c32) SKP_MLA(a32, b32, c32) + +// ((a32 >> 16) * (b32 >> 16)) output have to be 32bit int +#define SKP_SMULTT(a32, b32) (((a32) >> 16) * ((b32) >> 16)) + +// a32 + ((a32 >> 16) * (b32 >> 16)) output have to be 32bit int +#define SKP_SMLATT(a32, b32, c32) SKP_ADD32((a32),((b32) >> 16) * ((c32) >> 16)) + +#define SKP_SMLALBB(a64, b16, c16) SKP_ADD64((a64),(opus_int64)((opus_int32)(b16) * (opus_int32)(c16))) + +// (a32 * b32) +#define SKP_SMULL(a32, b32) ((opus_int64)(a32) * /*(opus_int64)*/(b32)) + +// multiply-accumulate macros that allow overflow in the addition (ie, no asserts in debug mode) +#define SKP_MLA_ovflw(a32, b32, c32) SKP_MLA(a32, b32, c32) +#ifndef SKP_SMLABB_ovflw +# define SKP_SMLABB_ovflw(a32, b32, c32) SKP_SMLABB(a32, b32, c32) +#endif +#define SKP_SMLABT_ovflw(a32, b32, c32) SKP_SMLABT(a32, b32, c32) +#define SKP_SMLATT_ovflw(a32, b32, c32) SKP_SMLATT(a32, b32, c32) +#define SKP_SMLAWB_ovflw(a32, b32, c32) SKP_SMLAWB(a32, b32, c32) +#define SKP_SMLAWT_ovflw(a32, b32, c32) SKP_SMLAWT(a32, b32, c32) + +#define SKP_DIV32_16(a32, b16) ((opus_int32)((a32) / (b16))) +#define SKP_DIV32(a32, b32) ((opus_int32)((a32) / (b32))) + +// These macros enables checking for overflow in silk_API_Debug.h +#define SKP_ADD16(a, b) ((a) + (b)) +#define SKP_ADD32(a, b) ((a) + (b)) +#define SKP_ADD64(a, b) ((a) + (b)) + +#define SKP_SUB16(a, b) ((a) - (b)) +#define SKP_SUB32(a, b) ((a) - (b)) +#define SKP_SUB64(a, b) ((a) - (b)) + +#define SKP_SAT8(a) ((a) > SKP_int8_MAX ? SKP_int8_MAX : \ + ((a) < SKP_int8_MIN ? SKP_int8_MIN : (a))) +#define SKP_SAT16(a) ((a) > SKP_int16_MAX ? SKP_int16_MAX : \ + ((a) < SKP_int16_MIN ? SKP_int16_MIN : (a))) +#define SKP_SAT32(a) ((a) > SKP_int32_MAX ? SKP_int32_MAX : \ + ((a) < SKP_int32_MIN ? SKP_int32_MIN : (a))) + +#define SKP_CHECK_FIT8(a) (a) +#define SKP_CHECK_FIT16(a) (a) +#define SKP_CHECK_FIT32(a) (a) + +#define SKP_ADD_SAT16(a, b) (opus_int16)SKP_SAT16( SKP_ADD32( (opus_int32)(a), (b) ) ) +#define SKP_ADD_SAT64(a, b) ((((a) + (b)) & 0x8000000000000000LL) == 0 ? \ + ((((a) & (b)) & 0x8000000000000000LL) != 0 ? SKP_int64_MIN : (a)+(b)) : \ + ((((a) | (b)) & 0x8000000000000000LL) == 0 ? SKP_int64_MAX : (a)+(b)) ) + +#define SKP_SUB_SAT16(a, b) (opus_int16)SKP_SAT16( SKP_SUB32( (opus_int32)(a), (b) ) ) +#define SKP_SUB_SAT64(a, b) ((((a)-(b)) & 0x8000000000000000LL) == 0 ? \ + (( (a) & ((b)^0x8000000000000000LL) & 0x8000000000000000LL) ? SKP_int64_MIN : (a)-(b)) : \ + ((((a)^0x8000000000000000LL) & (b) & 0x8000000000000000LL) ? SKP_int64_MAX : (a)-(b)) ) + +/* Saturation for positive input values */ +#define SKP_POS_SAT32(a) ((a) > SKP_int32_MAX ? SKP_int32_MAX : (a)) + +/* Add with saturation for positive input values */ +#define SKP_ADD_POS_SAT8(a, b) ((((a)+(b)) & 0x80) ? SKP_int8_MAX : ((a)+(b))) +#define SKP_ADD_POS_SAT16(a, b) ((((a)+(b)) & 0x8000) ? SKP_int16_MAX : ((a)+(b))) +#define SKP_ADD_POS_SAT32(a, b) ((((a)+(b)) & 0x80000000) ? SKP_int32_MAX : ((a)+(b))) +#define SKP_ADD_POS_SAT64(a, b) ((((a)+(b)) & 0x8000000000000000LL) ? SKP_int64_MAX : ((a)+(b))) + +#define SKP_LSHIFT8(a, shift) ((a)<<(shift)) // shift >= 0, shift < 8 +#define SKP_LSHIFT16(a, shift) ((a)<<(shift)) // shift >= 0, shift < 16 +#define SKP_LSHIFT32(a, shift) ((a)<<(shift)) // shift >= 0, shift < 32 +#define SKP_LSHIFT64(a, shift) ((a)<<(shift)) // shift >= 0, shift < 64 +#define SKP_LSHIFT(a, shift) SKP_LSHIFT32(a, shift) // shift >= 0, shift < 32 + +#define SKP_RSHIFT8(a, shift) ((a)>>(shift)) // shift >= 0, shift < 8 +#define SKP_RSHIFT16(a, shift) ((a)>>(shift)) // shift >= 0, shift < 16 +#define SKP_RSHIFT32(a, shift) ((a)>>(shift)) // shift >= 0, shift < 32 +#define SKP_RSHIFT64(a, shift) ((a)>>(shift)) // shift >= 0, shift < 64 +#define SKP_RSHIFT(a, shift) SKP_RSHIFT32(a, shift) // shift >= 0, shift < 32 + +/* saturates before shifting */ +#define SKP_LSHIFT_SAT16(a, shift) (SKP_LSHIFT16( SKP_LIMIT( (a), SKP_RSHIFT16( SKP_int16_MIN, (shift) ), \ + SKP_RSHIFT16( SKP_int16_MAX, (shift) ) ), (shift) )) +#define SKP_LSHIFT_SAT32(a, shift) (SKP_LSHIFT32( SKP_LIMIT( (a), SKP_RSHIFT32( SKP_int32_MIN, (shift) ), \ + SKP_RSHIFT32( SKP_int32_MAX, (shift) ) ), (shift) )) + +#define SKP_LSHIFT_ovflw(a, shift) ((a)<<(shift)) // shift >= 0, allowed to overflow +#define SKP_LSHIFT_uint(a, shift) ((a)<<(shift)) // shift >= 0 +#define SKP_RSHIFT_uint(a, shift) ((a)>>(shift)) // shift >= 0 + +#define SKP_ADD_LSHIFT(a, b, shift) ((a) + SKP_LSHIFT((b), (shift))) // shift >= 0 +#define SKP_ADD_LSHIFT32(a, b, shift) SKP_ADD32((a), SKP_LSHIFT32((b), (shift))) // shift >= 0 +#define SKP_ADD_LSHIFT_uint(a, b, shift) ((a) + SKP_LSHIFT_uint((b), (shift))) // shift >= 0 +#define SKP_ADD_RSHIFT(a, b, shift) ((a) + SKP_RSHIFT((b), (shift))) // shift >= 0 +#define SKP_ADD_RSHIFT32(a, b, shift) SKP_ADD32((a), SKP_RSHIFT32((b), (shift))) // shift >= 0 +#define SKP_ADD_RSHIFT_uint(a, b, shift) ((a) + SKP_RSHIFT_uint((b), (shift))) // shift >= 0 +#define SKP_SUB_LSHIFT32(a, b, shift) SKP_SUB32((a), SKP_LSHIFT32((b), (shift))) // shift >= 0 +#define SKP_SUB_RSHIFT32(a, b, shift) SKP_SUB32((a), SKP_RSHIFT32((b), (shift))) // shift >= 0 + +/* Requires that shift > 0 */ +#define SKP_RSHIFT_ROUND(a, shift) ((shift) == 1 ? ((a) >> 1) + ((a) & 1) : (((a) >> ((shift) - 1)) + 1) >> 1) +#define SKP_RSHIFT_ROUND64(a, shift) ((shift) == 1 ? ((a) >> 1) + ((a) & 1) : (((a) >> ((shift) - 1)) + 1) >> 1) + +/* Number of rightshift required to fit the multiplication */ +#define SKP_NSHIFT_MUL_32_32(a, b) ( -(31- (32-silk_CLZ32(SKP_abs(a)) + (32-silk_CLZ32(SKP_abs(b))))) ) +#define SKP_NSHIFT_MUL_16_16(a, b) ( -(15- (16-silk_CLZ16(SKP_abs(a)) + (16-silk_CLZ16(SKP_abs(b))))) ) + + +#define SKP_min(a, b) (((a) < (b)) ? (a) : (b)) +#define SKP_max(a, b) (((a) > (b)) ? (a) : (b)) + +/* Macro to convert floating-point constants to fixed-point */ +#define SILK_FIX_CONST( C, Q ) ((opus_int32)((C) * ((opus_int64)1 << (Q)) + 0.5)) + +/* SKP_min() versions with typecast in the function call */ +SKP_INLINE opus_int SKP_min_int(opus_int a, opus_int b) +{ + return (((a) < (b)) ? (a) : (b)); +} +SKP_INLINE opus_int16 SKP_min_16(opus_int16 a, opus_int16 b) +{ + return (((a) < (b)) ? (a) : (b)); +} +SKP_INLINE opus_int32 SKP_min_32(opus_int32 a, opus_int32 b) +{ + return (((a) < (b)) ? (a) : (b)); +} +SKP_INLINE opus_int64 SKP_min_64(opus_int64 a, opus_int64 b) +{ + return (((a) < (b)) ? (a) : (b)); +} + +/* SKP_min() versions with typecast in the function call */ +SKP_INLINE opus_int SKP_max_int(opus_int a, opus_int b) +{ + return (((a) > (b)) ? (a) : (b)); +} +SKP_INLINE opus_int16 SKP_max_16(opus_int16 a, opus_int16 b) +{ + return (((a) > (b)) ? (a) : (b)); +} +SKP_INLINE opus_int32 SKP_max_32(opus_int32 a, opus_int32 b) +{ + return (((a) > (b)) ? (a) : (b)); +} +SKP_INLINE opus_int64 SKP_max_64(opus_int64 a, opus_int64 b) +{ + return (((a) > (b)) ? (a) : (b)); +} + +#define SKP_LIMIT( a, limit1, limit2) ((limit1) > (limit2) ? ((a) > (limit1) ? (limit1) : ((a) < (limit2) ? (limit2) : (a))) \ + : ((a) > (limit2) ? (limit2) : ((a) < (limit1) ? (limit1) : (a)))) + +#define SKP_LIMIT_int SKP_LIMIT +#define SKP_LIMIT_16 SKP_LIMIT +#define SKP_LIMIT_32 SKP_LIMIT + +//#define SKP_non_neg(a) ((a) & ((-(a)) >> (8 * sizeof(a) - 1))) /* doesn't seem faster than SKP_max(0, a); + +#define SKP_abs(a) (((a) > 0) ? (a) : -(a)) // Be careful, SKP_abs returns wrong when input equals to SKP_intXX_MIN +#define SKP_abs_int(a) (((a) ^ ((a) >> (8 * sizeof(a) - 1))) - ((a) >> (8 * sizeof(a) - 1))) +#define SKP_abs_int32(a) (((a) ^ ((a) >> 31)) - ((a) >> 31)) +#define SKP_abs_int64(a) (((a) > 0) ? (a) : -(a)) + +#define SKP_sign(a) ((a) > 0 ? 1 : ( (a) < 0 ? -1 : 0 )) + +#define SKP_sqrt(a) (sqrt(a)) + +/* PSEUDO-RANDOM GENERATOR */ +/* Make sure to store the result as the seed for the next call (also in between */ +/* frames), otherwise result won't be random at all. When only using some of the */ +/* bits, take the most significant bits by right-shifting. */ +#define SKP_RAND(seed) (SKP_MLA_ovflw(907633515, (seed), 196314165)) + +// Add some multiplication functions that can be easily mapped to ARM. + +// SKP_SMMUL: Signed top word multiply. +// ARMv6 2 instruction cycles. +// ARMv3M+ 3 instruction cycles. use SMULL and ignore LSB registers.(except xM) +//#define SKP_SMMUL(a32, b32) (opus_int32)SKP_RSHIFT(SKP_SMLAL(SKP_SMULWB((a32), (b32)), (a32), SKP_RSHIFT_ROUND((b32), 16)), 16) +// the following seems faster on x86 +#define SKP_SMMUL(a32, b32) (opus_int32)SKP_RSHIFT64(SKP_SMULL((a32), (b32)), 32) + +#include "silk_Inlines.h" +#include "silk_MacroCount.h" +#include "silk_MacroDebug.h" + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/silk/silk_VAD.c b/silk/silk_VAD.c index a0ab835df..8fecf7361 100644 --- a/silk/silk_VAD.c +++ b/silk/silk_VAD.c @@ -1,321 +1,321 @@ -/*********************************************************************** -Copyright (c) 2006-2011, Skype Limited. All rights reserved. -Redistribution and use in source and binary forms, with or without -modification, (subject to the limitations in the disclaimer below) -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 Skype Limited, nor the names of specific -contributors, may be used to endorse or promote products derived from -this software without specific prior written permission. -NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED -BY THIS LICENSE. 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. -***********************************************************************/ - -#include <stdlib.h> -#include "silk_main.h" - -/**********************************/ -/* Initialization of the Silk VAD */ -/**********************************/ -opus_int silk_VAD_Init( /* O Return value, 0 if success */ - silk_VAD_state *psSilk_VAD /* I/O Pointer to Silk VAD state */ -) -{ - opus_int b, ret = 0; - - /* reset state memory */ - SKP_memset( psSilk_VAD, 0, sizeof( silk_VAD_state ) ); - - /* init noise levels */ - /* Initialize array with approx pink noise levels (psd proportional to inverse of frequency) */ - for( b = 0; b < VAD_N_BANDS; b++ ) { - psSilk_VAD->NoiseLevelBias[ b ] = SKP_max_32( SKP_DIV32_16( VAD_NOISE_LEVELS_BIAS, b + 1 ), 1 ); - } - - /* Initialize state */ - for( b = 0; b < VAD_N_BANDS; b++ ) { - psSilk_VAD->NL[ b ] = SKP_MUL( 100, psSilk_VAD->NoiseLevelBias[ b ] ); - psSilk_VAD->inv_NL[ b ] = SKP_DIV32( SKP_int32_MAX, psSilk_VAD->NL[ b ] ); - } - psSilk_VAD->counter = 15; - - /* init smoothed energy-to-noise ratio*/ - for( b = 0; b < VAD_N_BANDS; b++ ) { - psSilk_VAD->NrgRatioSmth_Q8[ b ] = 100 * 256; /* 100 * 256 --> 20 dB SNR */ - } - - return( ret ); -} - -/* Weighting factors for tilt measure */ -static const opus_int32 tiltWeights[ VAD_N_BANDS ] = { 30000, 6000, -12000, -12000 }; - -/***************************************/ -/* Get the speech activity level in Q8 */ -/***************************************/ -opus_int silk_VAD_GetSA_Q8( /* O Return value, 0 if success */ - silk_encoder_state *psEncC, /* I/O Encoder state */ - const opus_int16 pIn[] /* I PCM input */ -) -{ - opus_int SA_Q15, pSNR_dB_Q7, input_tilt; - opus_int decimated_framelength, dec_subframe_length, dec_subframe_offset, SNR_Q7, i, b, s; - opus_int32 sumSquared, smooth_coef_Q16; - opus_int16 HPstateTmp; - opus_int16 X[ VAD_N_BANDS ][ MAX_FRAME_LENGTH / 2 ]; - opus_int32 Xnrg[ VAD_N_BANDS ]; - opus_int32 NrgToNoiseRatio_Q8[ VAD_N_BANDS ]; - opus_int32 speech_nrg, x_tmp; - opus_int ret = 0; - silk_VAD_state *psSilk_VAD = &psEncC->sVAD; - - /* Safety checks */ - SKP_assert( VAD_N_BANDS == 4 ); - SKP_assert( MAX_FRAME_LENGTH >= psEncC->frame_length ); - SKP_assert( psEncC->frame_length <= 512 ); - SKP_assert( psEncC->frame_length == 8 * SKP_RSHIFT( psEncC->frame_length, 3 ) ); - - /***********************/ - /* Filter and Decimate */ - /***********************/ - /* 0-8 kHz to 0-4 kHz and 4-8 kHz */ - silk_ana_filt_bank_1( pIn, &psSilk_VAD->AnaState[ 0 ], &X[ 0 ][ 0 ], &X[ 3 ][ 0 ], psEncC->frame_length ); - - /* 0-4 kHz to 0-2 kHz and 2-4 kHz */ - silk_ana_filt_bank_1( &X[ 0 ][ 0 ], &psSilk_VAD->AnaState1[ 0 ], &X[ 0 ][ 0 ], &X[ 2 ][ 0 ], SKP_RSHIFT( psEncC->frame_length, 1 ) ); - - /* 0-2 kHz to 0-1 kHz and 1-2 kHz */ - silk_ana_filt_bank_1( &X[ 0 ][ 0 ], &psSilk_VAD->AnaState2[ 0 ], &X[ 0 ][ 0 ], &X[ 1 ][ 0 ], SKP_RSHIFT( psEncC->frame_length, 2 ) ); - - /*********************************************/ - /* HP filter on lowest band (differentiator) */ - /*********************************************/ - decimated_framelength = SKP_RSHIFT( psEncC->frame_length, 3 ); - X[ 0 ][ decimated_framelength - 1 ] = SKP_RSHIFT( X[ 0 ][ decimated_framelength - 1 ], 1 ); - HPstateTmp = X[ 0 ][ decimated_framelength - 1 ]; - for( i = decimated_framelength - 1; i > 0; i-- ) { - X[ 0 ][ i - 1 ] = SKP_RSHIFT( X[ 0 ][ i - 1 ], 1 ); - X[ 0 ][ i ] -= X[ 0 ][ i - 1 ]; - } - X[ 0 ][ 0 ] -= psSilk_VAD->HPstate; - psSilk_VAD->HPstate = HPstateTmp; - - /*************************************/ - /* Calculate the energy in each band */ - /*************************************/ - for( b = 0; b < VAD_N_BANDS; b++ ) { - /* Find the decimated framelength in the non-uniformly divided bands */ - decimated_framelength = SKP_RSHIFT( psEncC->frame_length, SKP_min_int( VAD_N_BANDS - b, VAD_N_BANDS - 1 ) ); - - /* Split length into subframe lengths */ - dec_subframe_length = SKP_RSHIFT( decimated_framelength, VAD_INTERNAL_SUBFRAMES_LOG2 ); - dec_subframe_offset = 0; - - /* Compute energy per sub-frame */ - /* initialize with summed energy of last subframe */ - Xnrg[ b ] = psSilk_VAD->XnrgSubfr[ b ]; - for( s = 0; s < VAD_INTERNAL_SUBFRAMES; s++ ) { - sumSquared = 0; - for( i = 0; i < dec_subframe_length; i++ ) { - /* The energy will be less than dec_subframe_length * ( SKP_int16_MIN / 8 ) ^ 2. */ - /* Therefore we can accumulate with no risk of overflow (unless dec_subframe_length > 128) */ - x_tmp = SKP_RSHIFT( X[ b ][ i + dec_subframe_offset ], 3 ); - sumSquared = SKP_SMLABB( sumSquared, x_tmp, x_tmp ); - - /* Safety check */ - SKP_assert( sumSquared >= 0 ); - } - - /* Add/saturate summed energy of current subframe */ - if( s < VAD_INTERNAL_SUBFRAMES - 1 ) { - Xnrg[ b ] = SKP_ADD_POS_SAT32( Xnrg[ b ], sumSquared ); - } else { - /* Look-ahead subframe */ - Xnrg[ b ] = SKP_ADD_POS_SAT32( Xnrg[ b ], SKP_RSHIFT( sumSquared, 1 ) ); - } - - dec_subframe_offset += dec_subframe_length; - } - psSilk_VAD->XnrgSubfr[ b ] = sumSquared; - } - - /********************/ - /* Noise estimation */ - /********************/ - silk_VAD_GetNoiseLevels( &Xnrg[ 0 ], psSilk_VAD ); - - /***********************************************/ - /* Signal-plus-noise to noise ratio estimation */ - /***********************************************/ - sumSquared = 0; - input_tilt = 0; - for( b = 0; b < VAD_N_BANDS; b++ ) { - speech_nrg = Xnrg[ b ] - psSilk_VAD->NL[ b ]; - if( speech_nrg > 0 ) { - /* Divide, with sufficient resolution */ - if( ( Xnrg[ b ] & 0xFF800000 ) == 0 ) { - NrgToNoiseRatio_Q8[ b ] = SKP_DIV32( SKP_LSHIFT( Xnrg[ b ], 8 ), psSilk_VAD->NL[ b ] + 1 ); - } else { - NrgToNoiseRatio_Q8[ b ] = SKP_DIV32( Xnrg[ b ], SKP_RSHIFT( psSilk_VAD->NL[ b ], 8 ) + 1 ); - } - - /* Convert to log domain */ - SNR_Q7 = silk_lin2log( NrgToNoiseRatio_Q8[ b ] ) - 8 * 128; - - /* Sum-of-squares */ - sumSquared = SKP_SMLABB( sumSquared, SNR_Q7, SNR_Q7 ); /* Q14 */ - - /* Tilt measure */ - if( speech_nrg < ( 1 << 20 ) ) { - /* Scale down SNR value for small subband speech energies */ - SNR_Q7 = SKP_SMULWB( SKP_LSHIFT( silk_SQRT_APPROX( speech_nrg ), 6 ), SNR_Q7 ); - } - input_tilt = SKP_SMLAWB( input_tilt, tiltWeights[ b ], SNR_Q7 ); - } else { - NrgToNoiseRatio_Q8[ b ] = 256; - } - } - - /* Mean-of-squares */ - sumSquared = SKP_DIV32_16( sumSquared, VAD_N_BANDS ); /* Q14 */ - - /* Root-mean-square approximation, scale to dBs, and write to output pointer */ - pSNR_dB_Q7 = ( opus_int16 )( 3 * silk_SQRT_APPROX( sumSquared ) ); /* Q7 */ - - /*********************************/ - /* Speech Probability Estimation */ - /*********************************/ - SA_Q15 = silk_sigm_Q15( SKP_SMULWB( VAD_SNR_FACTOR_Q16, pSNR_dB_Q7 ) - VAD_NEGATIVE_OFFSET_Q5 ); - - /**************************/ - /* Frequency Tilt Measure */ - /**************************/ - psEncC->input_tilt_Q15 = SKP_LSHIFT( silk_sigm_Q15( input_tilt ) - 16384, 1 ); - - /**************************************************/ - /* Scale the sigmoid output based on power levels */ - /**************************************************/ - speech_nrg = 0; - for( b = 0; b < VAD_N_BANDS; b++ ) { - /* Accumulate signal-without-noise energies, higher frequency bands have more weight */ - speech_nrg += ( b + 1 ) * SKP_RSHIFT( Xnrg[ b ] - psSilk_VAD->NL[ b ], 4 ); - } - - /* Power scaling */ - if( speech_nrg <= 0 ) { - SA_Q15 = SKP_RSHIFT( SA_Q15, 1 ); - } else if( speech_nrg < 32768 ) { - if( psEncC->frame_length == 10 * psEncC->fs_kHz ) { - speech_nrg = SKP_LSHIFT_SAT32( speech_nrg, 16 ); - } else { - speech_nrg = SKP_LSHIFT_SAT32( speech_nrg, 15 ); - } - - /* square-root */ - speech_nrg = silk_SQRT_APPROX( speech_nrg ); - SA_Q15 = SKP_SMULWB( 32768 + speech_nrg, SA_Q15 ); - } - - /* Copy the resulting speech activity in Q8 */ - psEncC->speech_activity_Q8 = SKP_min_int( SKP_RSHIFT( SA_Q15, 7 ), SKP_uint8_MAX ); - - /***********************************/ - /* Energy Level and SNR estimation */ - /***********************************/ - /* Smoothing coefficient */ - smooth_coef_Q16 = SKP_SMULWB( VAD_SNR_SMOOTH_COEF_Q18, SKP_SMULWB( SA_Q15, SA_Q15 ) ); - - if( psEncC->frame_length == 10 * psEncC->fs_kHz ) { - smooth_coef_Q16 >>= 1; - } - - for( b = 0; b < VAD_N_BANDS; b++ ) { - /* compute smoothed energy-to-noise ratio per band */ - psSilk_VAD->NrgRatioSmth_Q8[ b ] = SKP_SMLAWB( psSilk_VAD->NrgRatioSmth_Q8[ b ], - NrgToNoiseRatio_Q8[ b ] - psSilk_VAD->NrgRatioSmth_Q8[ b ], smooth_coef_Q16 ); - - /* signal to noise ratio in dB per band */ - SNR_Q7 = 3 * ( silk_lin2log( psSilk_VAD->NrgRatioSmth_Q8[b] ) - 8 * 128 ); - /* quality = sigmoid( 0.25 * ( SNR_dB - 16 ) ); */ - psEncC->input_quality_bands_Q15[ b ] = silk_sigm_Q15( SKP_RSHIFT( SNR_Q7 - 16 * 128, 4 ) ); - } - - return( ret ); -} - -/**************************/ -/* Noise level estimation */ -/**************************/ -void silk_VAD_GetNoiseLevels( - const opus_int32 pX[ VAD_N_BANDS ], /* I subband energies */ - silk_VAD_state *psSilk_VAD /* I/O Pointer to Silk VAD state */ -) -{ - opus_int k; - opus_int32 nl, nrg, inv_nrg; - opus_int coef, min_coef; - - /* Initially faster smoothing */ - if( psSilk_VAD->counter < 1000 ) { /* 1000 = 20 sec */ - min_coef = SKP_DIV32_16( SKP_int16_MAX, SKP_RSHIFT( psSilk_VAD->counter, 4 ) + 1 ); - } else { - min_coef = 0; - } - - for( k = 0; k < VAD_N_BANDS; k++ ) { - /* Get old noise level estimate for current band */ - nl = psSilk_VAD->NL[ k ]; - SKP_assert( nl >= 0 ); - - /* Add bias */ - nrg = SKP_ADD_POS_SAT32( pX[ k ], psSilk_VAD->NoiseLevelBias[ k ] ); - SKP_assert( nrg > 0 ); - - /* Invert energies */ - inv_nrg = SKP_DIV32( SKP_int32_MAX, nrg ); - SKP_assert( inv_nrg >= 0 ); - - /* Less update when subband energy is high */ - if( nrg > SKP_LSHIFT( nl, 3 ) ) { - coef = VAD_NOISE_LEVEL_SMOOTH_COEF_Q16 >> 3; - } else if( nrg < nl ) { - coef = VAD_NOISE_LEVEL_SMOOTH_COEF_Q16; - } else { - coef = SKP_SMULWB( SKP_SMULWW( inv_nrg, nl ), VAD_NOISE_LEVEL_SMOOTH_COEF_Q16 << 1 ); - } - - /* Initially faster smoothing */ - coef = SKP_max_int( coef, min_coef ); - - /* Smooth inverse energies */ - psSilk_VAD->inv_NL[ k ] = SKP_SMLAWB( psSilk_VAD->inv_NL[ k ], inv_nrg - psSilk_VAD->inv_NL[ k ], coef ); - SKP_assert( psSilk_VAD->inv_NL[ k ] >= 0 ); - - /* Compute noise level by inverting again */ - nl = SKP_DIV32( SKP_int32_MAX, psSilk_VAD->inv_NL[ k ] ); - SKP_assert( nl >= 0 ); - - /* Limit noise levels (guarantee 7 bits of head room) */ - nl = SKP_min( nl, 0x00FFFFFF ); - - /* Store as part of state */ - psSilk_VAD->NL[ k ] = nl; - } - - /* Increment frame counter */ - psSilk_VAD->counter++; -} +/*********************************************************************** +Copyright (c) 2006-2011, Skype Limited. All rights reserved. +Redistribution and use in source and binary forms, with or without +modification, (subject to the limitations in the disclaimer below) +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 Skype Limited, nor the names of specific +contributors, may be used to endorse or promote products derived from +this software without specific prior written permission. +NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED +BY THIS LICENSE. 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. +***********************************************************************/ + +#include <stdlib.h> +#include "silk_main.h" + +/**********************************/ +/* Initialization of the Silk VAD */ +/**********************************/ +opus_int silk_VAD_Init( /* O Return value, 0 if success */ + silk_VAD_state *psSilk_VAD /* I/O Pointer to Silk VAD state */ +) +{ + opus_int b, ret = 0; + + /* reset state memory */ + SKP_memset( psSilk_VAD, 0, sizeof( silk_VAD_state ) ); + + /* init noise levels */ + /* Initialize array with approx pink noise levels (psd proportional to inverse of frequency) */ + for( b = 0; b < VAD_N_BANDS; b++ ) { + psSilk_VAD->NoiseLevelBias[ b ] = SKP_max_32( SKP_DIV32_16( VAD_NOISE_LEVELS_BIAS, b + 1 ), 1 ); + } + + /* Initialize state */ + for( b = 0; b < VAD_N_BANDS; b++ ) { + psSilk_VAD->NL[ b ] = SKP_MUL( 100, psSilk_VAD->NoiseLevelBias[ b ] ); + psSilk_VAD->inv_NL[ b ] = SKP_DIV32( SKP_int32_MAX, psSilk_VAD->NL[ b ] ); + } + psSilk_VAD->counter = 15; + + /* init smoothed energy-to-noise ratio*/ + for( b = 0; b < VAD_N_BANDS; b++ ) { + psSilk_VAD->NrgRatioSmth_Q8[ b ] = 100 * 256; /* 100 * 256 --> 20 dB SNR */ + } + + return( ret ); +} + +/* Weighting factors for tilt measure */ +static const opus_int32 tiltWeights[ VAD_N_BANDS ] = { 30000, 6000, -12000, -12000 }; + +/***************************************/ +/* Get the speech activity level in Q8 */ +/***************************************/ +opus_int silk_VAD_GetSA_Q8( /* O Return value, 0 if success */ + silk_encoder_state *psEncC, /* I/O Encoder state */ + const opus_int16 pIn[] /* I PCM input */ +) +{ + opus_int SA_Q15, pSNR_dB_Q7, input_tilt; + opus_int decimated_framelength, dec_subframe_length, dec_subframe_offset, SNR_Q7, i, b, s; + opus_int32 sumSquared, smooth_coef_Q16; + opus_int16 HPstateTmp; + opus_int16 X[ VAD_N_BANDS ][ MAX_FRAME_LENGTH / 2 ]; + opus_int32 Xnrg[ VAD_N_BANDS ]; + opus_int32 NrgToNoiseRatio_Q8[ VAD_N_BANDS ]; + opus_int32 speech_nrg, x_tmp; + opus_int ret = 0; + silk_VAD_state *psSilk_VAD = &psEncC->sVAD; + + /* Safety checks */ + SKP_assert( VAD_N_BANDS == 4 ); + SKP_assert( MAX_FRAME_LENGTH >= psEncC->frame_length ); + SKP_assert( psEncC->frame_length <= 512 ); + SKP_assert( psEncC->frame_length == 8 * SKP_RSHIFT( psEncC->frame_length, 3 ) ); + + /***********************/ + /* Filter and Decimate */ + /***********************/ + /* 0-8 kHz to 0-4 kHz and 4-8 kHz */ + silk_ana_filt_bank_1( pIn, &psSilk_VAD->AnaState[ 0 ], &X[ 0 ][ 0 ], &X[ 3 ][ 0 ], psEncC->frame_length ); + + /* 0-4 kHz to 0-2 kHz and 2-4 kHz */ + silk_ana_filt_bank_1( &X[ 0 ][ 0 ], &psSilk_VAD->AnaState1[ 0 ], &X[ 0 ][ 0 ], &X[ 2 ][ 0 ], SKP_RSHIFT( psEncC->frame_length, 1 ) ); + + /* 0-2 kHz to 0-1 kHz and 1-2 kHz */ + silk_ana_filt_bank_1( &X[ 0 ][ 0 ], &psSilk_VAD->AnaState2[ 0 ], &X[ 0 ][ 0 ], &X[ 1 ][ 0 ], SKP_RSHIFT( psEncC->frame_length, 2 ) ); + + /*********************************************/ + /* HP filter on lowest band (differentiator) */ + /*********************************************/ + decimated_framelength = SKP_RSHIFT( psEncC->frame_length, 3 ); + X[ 0 ][ decimated_framelength - 1 ] = SKP_RSHIFT( X[ 0 ][ decimated_framelength - 1 ], 1 ); + HPstateTmp = X[ 0 ][ decimated_framelength - 1 ]; + for( i = decimated_framelength - 1; i > 0; i-- ) { + X[ 0 ][ i - 1 ] = SKP_RSHIFT( X[ 0 ][ i - 1 ], 1 ); + X[ 0 ][ i ] -= X[ 0 ][ i - 1 ]; + } + X[ 0 ][ 0 ] -= psSilk_VAD->HPstate; + psSilk_VAD->HPstate = HPstateTmp; + + /*************************************/ + /* Calculate the energy in each band */ + /*************************************/ + for( b = 0; b < VAD_N_BANDS; b++ ) { + /* Find the decimated framelength in the non-uniformly divided bands */ + decimated_framelength = SKP_RSHIFT( psEncC->frame_length, SKP_min_int( VAD_N_BANDS - b, VAD_N_BANDS - 1 ) ); + + /* Split length into subframe lengths */ + dec_subframe_length = SKP_RSHIFT( decimated_framelength, VAD_INTERNAL_SUBFRAMES_LOG2 ); + dec_subframe_offset = 0; + + /* Compute energy per sub-frame */ + /* initialize with summed energy of last subframe */ + Xnrg[ b ] = psSilk_VAD->XnrgSubfr[ b ]; + for( s = 0; s < VAD_INTERNAL_SUBFRAMES; s++ ) { + sumSquared = 0; + for( i = 0; i < dec_subframe_length; i++ ) { + /* The energy will be less than dec_subframe_length * ( SKP_int16_MIN / 8 ) ^ 2. */ + /* Therefore we can accumulate with no risk of overflow (unless dec_subframe_length > 128) */ + x_tmp = SKP_RSHIFT( X[ b ][ i + dec_subframe_offset ], 3 ); + sumSquared = SKP_SMLABB( sumSquared, x_tmp, x_tmp ); + + /* Safety check */ + SKP_assert( sumSquared >= 0 ); + } + + /* Add/saturate summed energy of current subframe */ + if( s < VAD_INTERNAL_SUBFRAMES - 1 ) { + Xnrg[ b ] = SKP_ADD_POS_SAT32( Xnrg[ b ], sumSquared ); + } else { + /* Look-ahead subframe */ + Xnrg[ b ] = SKP_ADD_POS_SAT32( Xnrg[ b ], SKP_RSHIFT( sumSquared, 1 ) ); + } + + dec_subframe_offset += dec_subframe_length; + } + psSilk_VAD->XnrgSubfr[ b ] = sumSquared; + } + + /********************/ + /* Noise estimation */ + /********************/ + silk_VAD_GetNoiseLevels( &Xnrg[ 0 ], psSilk_VAD ); + + /***********************************************/ + /* Signal-plus-noise to noise ratio estimation */ + /***********************************************/ + sumSquared = 0; + input_tilt = 0; + for( b = 0; b < VAD_N_BANDS; b++ ) { + speech_nrg = Xnrg[ b ] - psSilk_VAD->NL[ b ]; + if( speech_nrg > 0 ) { + /* Divide, with sufficient resolution */ + if( ( Xnrg[ b ] & 0xFF800000 ) == 0 ) { + NrgToNoiseRatio_Q8[ b ] = SKP_DIV32( SKP_LSHIFT( Xnrg[ b ], 8 ), psSilk_VAD->NL[ b ] + 1 ); + } else { + NrgToNoiseRatio_Q8[ b ] = SKP_DIV32( Xnrg[ b ], SKP_RSHIFT( psSilk_VAD->NL[ b ], 8 ) + 1 ); + } + + /* Convert to log domain */ + SNR_Q7 = silk_lin2log( NrgToNoiseRatio_Q8[ b ] ) - 8 * 128; + + /* Sum-of-squares */ + sumSquared = SKP_SMLABB( sumSquared, SNR_Q7, SNR_Q7 ); /* Q14 */ + + /* Tilt measure */ + if( speech_nrg < ( 1 << 20 ) ) { + /* Scale down SNR value for small subband speech energies */ + SNR_Q7 = SKP_SMULWB( SKP_LSHIFT( silk_SQRT_APPROX( speech_nrg ), 6 ), SNR_Q7 ); + } + input_tilt = SKP_SMLAWB( input_tilt, tiltWeights[ b ], SNR_Q7 ); + } else { + NrgToNoiseRatio_Q8[ b ] = 256; + } + } + + /* Mean-of-squares */ + sumSquared = SKP_DIV32_16( sumSquared, VAD_N_BANDS ); /* Q14 */ + + /* Root-mean-square approximation, scale to dBs, and write to output pointer */ + pSNR_dB_Q7 = ( opus_int16 )( 3 * silk_SQRT_APPROX( sumSquared ) ); /* Q7 */ + + /*********************************/ + /* Speech Probability Estimation */ + /*********************************/ + SA_Q15 = silk_sigm_Q15( SKP_SMULWB( VAD_SNR_FACTOR_Q16, pSNR_dB_Q7 ) - VAD_NEGATIVE_OFFSET_Q5 ); + + /**************************/ + /* Frequency Tilt Measure */ + /**************************/ + psEncC->input_tilt_Q15 = SKP_LSHIFT( silk_sigm_Q15( input_tilt ) - 16384, 1 ); + + /**************************************************/ + /* Scale the sigmoid output based on power levels */ + /**************************************************/ + speech_nrg = 0; + for( b = 0; b < VAD_N_BANDS; b++ ) { + /* Accumulate signal-without-noise energies, higher frequency bands have more weight */ + speech_nrg += ( b + 1 ) * SKP_RSHIFT( Xnrg[ b ] - psSilk_VAD->NL[ b ], 4 ); + } + + /* Power scaling */ + if( speech_nrg <= 0 ) { + SA_Q15 = SKP_RSHIFT( SA_Q15, 1 ); + } else if( speech_nrg < 32768 ) { + if( psEncC->frame_length == 10 * psEncC->fs_kHz ) { + speech_nrg = SKP_LSHIFT_SAT32( speech_nrg, 16 ); + } else { + speech_nrg = SKP_LSHIFT_SAT32( speech_nrg, 15 ); + } + + /* square-root */ + speech_nrg = silk_SQRT_APPROX( speech_nrg ); + SA_Q15 = SKP_SMULWB( 32768 + speech_nrg, SA_Q15 ); + } + + /* Copy the resulting speech activity in Q8 */ + psEncC->speech_activity_Q8 = SKP_min_int( SKP_RSHIFT( SA_Q15, 7 ), SKP_uint8_MAX ); + + /***********************************/ + /* Energy Level and SNR estimation */ + /***********************************/ + /* Smoothing coefficient */ + smooth_coef_Q16 = SKP_SMULWB( VAD_SNR_SMOOTH_COEF_Q18, SKP_SMULWB( SA_Q15, SA_Q15 ) ); + + if( psEncC->frame_length == 10 * psEncC->fs_kHz ) { + smooth_coef_Q16 >>= 1; + } + + for( b = 0; b < VAD_N_BANDS; b++ ) { + /* compute smoothed energy-to-noise ratio per band */ + psSilk_VAD->NrgRatioSmth_Q8[ b ] = SKP_SMLAWB( psSilk_VAD->NrgRatioSmth_Q8[ b ], + NrgToNoiseRatio_Q8[ b ] - psSilk_VAD->NrgRatioSmth_Q8[ b ], smooth_coef_Q16 ); + + /* signal to noise ratio in dB per band */ + SNR_Q7 = 3 * ( silk_lin2log( psSilk_VAD->NrgRatioSmth_Q8[b] ) - 8 * 128 ); + /* quality = sigmoid( 0.25 * ( SNR_dB - 16 ) ); */ + psEncC->input_quality_bands_Q15[ b ] = silk_sigm_Q15( SKP_RSHIFT( SNR_Q7 - 16 * 128, 4 ) ); + } + + return( ret ); +} + +/**************************/ +/* Noise level estimation */ +/**************************/ +void silk_VAD_GetNoiseLevels( + const opus_int32 pX[ VAD_N_BANDS ], /* I subband energies */ + silk_VAD_state *psSilk_VAD /* I/O Pointer to Silk VAD state */ +) +{ + opus_int k; + opus_int32 nl, nrg, inv_nrg; + opus_int coef, min_coef; + + /* Initially faster smoothing */ + if( psSilk_VAD->counter < 1000 ) { /* 1000 = 20 sec */ + min_coef = SKP_DIV32_16( SKP_int16_MAX, SKP_RSHIFT( psSilk_VAD->counter, 4 ) + 1 ); + } else { + min_coef = 0; + } + + for( k = 0; k < VAD_N_BANDS; k++ ) { + /* Get old noise level estimate for current band */ + nl = psSilk_VAD->NL[ k ]; + SKP_assert( nl >= 0 ); + + /* Add bias */ + nrg = SKP_ADD_POS_SAT32( pX[ k ], psSilk_VAD->NoiseLevelBias[ k ] ); + SKP_assert( nrg > 0 ); + + /* Invert energies */ + inv_nrg = SKP_DIV32( SKP_int32_MAX, nrg ); + SKP_assert( inv_nrg >= 0 ); + + /* Less update when subband energy is high */ + if( nrg > SKP_LSHIFT( nl, 3 ) ) { + coef = VAD_NOISE_LEVEL_SMOOTH_COEF_Q16 >> 3; + } else if( nrg < nl ) { + coef = VAD_NOISE_LEVEL_SMOOTH_COEF_Q16; + } else { + coef = SKP_SMULWB( SKP_SMULWW( inv_nrg, nl ), VAD_NOISE_LEVEL_SMOOTH_COEF_Q16 << 1 ); + } + + /* Initially faster smoothing */ + coef = SKP_max_int( coef, min_coef ); + + /* Smooth inverse energies */ + psSilk_VAD->inv_NL[ k ] = SKP_SMLAWB( psSilk_VAD->inv_NL[ k ], inv_nrg - psSilk_VAD->inv_NL[ k ], coef ); + SKP_assert( psSilk_VAD->inv_NL[ k ] >= 0 ); + + /* Compute noise level by inverting again */ + nl = SKP_DIV32( SKP_int32_MAX, psSilk_VAD->inv_NL[ k ] ); + SKP_assert( nl >= 0 ); + + /* Limit noise levels (guarantee 7 bits of head room) */ + nl = SKP_min( nl, 0x00FFFFFF ); + + /* Store as part of state */ + psSilk_VAD->NL[ k ] = nl; + } + + /* Increment frame counter */ + psSilk_VAD->counter++; +} diff --git a/silk/silk_VQ_WMat_EC.c b/silk/silk_VQ_WMat_EC.c index e35e48136..448876c31 100644 --- a/silk/silk_VQ_WMat_EC.c +++ b/silk/silk_VQ_WMat_EC.c @@ -1,107 +1,107 @@ -/*********************************************************************** -Copyright (c) 2006-2011, Skype Limited. All rights reserved. -Redistribution and use in source and binary forms, with or without -modification, (subject to the limitations in the disclaimer below) -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 Skype Limited, nor the names of specific -contributors, may be used to endorse or promote products derived from -this software without specific prior written permission. -NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED -BY THIS LICENSE. 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. -***********************************************************************/ - -#include "silk_main.h" - -/* Entropy constrained matrix-weighted VQ, hard-coded to 5-element vectors, for a single input data vector */ -void silk_VQ_WMat_EC( - opus_int8 *ind, /* O index of best codebook vector */ - opus_int32 *rate_dist_Q14, /* O best weighted quantization error + mu * rate*/ - const opus_int16 *in_Q14, /* I input vector to be quantized */ - const opus_int32 *W_Q18, /* I weighting matrix */ - const opus_int8 *cb_Q7, /* I codebook */ - const opus_uint8 *cl_Q5, /* I code length for each codebook vector */ - const opus_int mu_Q9, /* I tradeoff between weighted error and rate */ - opus_int L /* I number of vectors in codebook */ -) -{ - opus_int k; - const opus_int8 *cb_row_Q7; - opus_int16 diff_Q14[ 5 ]; - opus_int32 sum1_Q14, sum2_Q16; - - /* Loop over codebook */ - *rate_dist_Q14 = SKP_int32_MAX; - cb_row_Q7 = cb_Q7; - for( k = 0; k < L; k++ ) { - diff_Q14[ 0 ] = in_Q14[ 0 ] - SKP_LSHIFT( cb_row_Q7[ 0 ], 7 ); - diff_Q14[ 1 ] = in_Q14[ 1 ] - SKP_LSHIFT( cb_row_Q7[ 1 ], 7 ); - diff_Q14[ 2 ] = in_Q14[ 2 ] - SKP_LSHIFT( cb_row_Q7[ 2 ], 7 ); - diff_Q14[ 3 ] = in_Q14[ 3 ] - SKP_LSHIFT( cb_row_Q7[ 3 ], 7 ); - diff_Q14[ 4 ] = in_Q14[ 4 ] - SKP_LSHIFT( cb_row_Q7[ 4 ], 7 ); - - /* Weighted rate */ - sum1_Q14 = SKP_SMULBB( mu_Q9, cl_Q5[ k ] ); - - SKP_assert( sum1_Q14 >= 0 ); - - /* first row of W_Q18 */ - sum2_Q16 = SKP_SMULWB( W_Q18[ 1 ], diff_Q14[ 1 ] ); - sum2_Q16 = SKP_SMLAWB( sum2_Q16, W_Q18[ 2 ], diff_Q14[ 2 ] ); - sum2_Q16 = SKP_SMLAWB( sum2_Q16, W_Q18[ 3 ], diff_Q14[ 3 ] ); - sum2_Q16 = SKP_SMLAWB( sum2_Q16, W_Q18[ 4 ], diff_Q14[ 4 ] ); - sum2_Q16 = SKP_LSHIFT( sum2_Q16, 1 ); - sum2_Q16 = SKP_SMLAWB( sum2_Q16, W_Q18[ 0 ], diff_Q14[ 0 ] ); - sum1_Q14 = SKP_SMLAWB( sum1_Q14, sum2_Q16, diff_Q14[ 0 ] ); - - /* second row of W_Q18 */ - sum2_Q16 = SKP_SMULWB( W_Q18[ 7 ], diff_Q14[ 2 ] ); - sum2_Q16 = SKP_SMLAWB( sum2_Q16, W_Q18[ 8 ], diff_Q14[ 3 ] ); - sum2_Q16 = SKP_SMLAWB( sum2_Q16, W_Q18[ 9 ], diff_Q14[ 4 ] ); - sum2_Q16 = SKP_LSHIFT( sum2_Q16, 1 ); - sum2_Q16 = SKP_SMLAWB( sum2_Q16, W_Q18[ 6 ], diff_Q14[ 1 ] ); - sum1_Q14 = SKP_SMLAWB( sum1_Q14, sum2_Q16, diff_Q14[ 1 ] ); - - /* third row of W_Q18 */ - sum2_Q16 = SKP_SMULWB( W_Q18[ 13 ], diff_Q14[ 3 ] ); - sum2_Q16 = SKP_SMLAWB( sum2_Q16, W_Q18[ 14 ], diff_Q14[ 4 ] ); - sum2_Q16 = SKP_LSHIFT( sum2_Q16, 1 ); - sum2_Q16 = SKP_SMLAWB( sum2_Q16, W_Q18[ 12 ], diff_Q14[ 2 ] ); - sum1_Q14 = SKP_SMLAWB( sum1_Q14, sum2_Q16, diff_Q14[ 2 ] ); - - /* fourth row of W_Q18 */ - sum2_Q16 = SKP_SMULWB( W_Q18[ 19 ], diff_Q14[ 4 ] ); - sum2_Q16 = SKP_LSHIFT( sum2_Q16, 1 ); - sum2_Q16 = SKP_SMLAWB( sum2_Q16, W_Q18[ 18 ], diff_Q14[ 3 ] ); - sum1_Q14 = SKP_SMLAWB( sum1_Q14, sum2_Q16, diff_Q14[ 3 ] ); - - /* last row of W_Q18 */ - sum2_Q16 = SKP_SMULWB( W_Q18[ 24 ], diff_Q14[ 4 ] ); - sum1_Q14 = SKP_SMLAWB( sum1_Q14, sum2_Q16, diff_Q14[ 4 ] ); - - SKP_assert( sum1_Q14 >= 0 ); - - /* find best */ - if( sum1_Q14 < *rate_dist_Q14 ) { - *rate_dist_Q14 = sum1_Q14; - *ind = (opus_int8)k; - } - - /* Go to next cbk vector */ - cb_row_Q7 += LTP_ORDER; - } -} +/*********************************************************************** +Copyright (c) 2006-2011, Skype Limited. All rights reserved. +Redistribution and use in source and binary forms, with or without +modification, (subject to the limitations in the disclaimer below) +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 Skype Limited, nor the names of specific +contributors, may be used to endorse or promote products derived from +this software without specific prior written permission. +NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED +BY THIS LICENSE. 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. +***********************************************************************/ + +#include "silk_main.h" + +/* Entropy constrained matrix-weighted VQ, hard-coded to 5-element vectors, for a single input data vector */ +void silk_VQ_WMat_EC( + opus_int8 *ind, /* O index of best codebook vector */ + opus_int32 *rate_dist_Q14, /* O best weighted quantization error + mu * rate*/ + const opus_int16 *in_Q14, /* I input vector to be quantized */ + const opus_int32 *W_Q18, /* I weighting matrix */ + const opus_int8 *cb_Q7, /* I codebook */ + const opus_uint8 *cl_Q5, /* I code length for each codebook vector */ + const opus_int mu_Q9, /* I tradeoff between weighted error and rate */ + opus_int L /* I number of vectors in codebook */ +) +{ + opus_int k; + const opus_int8 *cb_row_Q7; + opus_int16 diff_Q14[ 5 ]; + opus_int32 sum1_Q14, sum2_Q16; + + /* Loop over codebook */ + *rate_dist_Q14 = SKP_int32_MAX; + cb_row_Q7 = cb_Q7; + for( k = 0; k < L; k++ ) { + diff_Q14[ 0 ] = in_Q14[ 0 ] - SKP_LSHIFT( cb_row_Q7[ 0 ], 7 ); + diff_Q14[ 1 ] = in_Q14[ 1 ] - SKP_LSHIFT( cb_row_Q7[ 1 ], 7 ); + diff_Q14[ 2 ] = in_Q14[ 2 ] - SKP_LSHIFT( cb_row_Q7[ 2 ], 7 ); + diff_Q14[ 3 ] = in_Q14[ 3 ] - SKP_LSHIFT( cb_row_Q7[ 3 ], 7 ); + diff_Q14[ 4 ] = in_Q14[ 4 ] - SKP_LSHIFT( cb_row_Q7[ 4 ], 7 ); + + /* Weighted rate */ + sum1_Q14 = SKP_SMULBB( mu_Q9, cl_Q5[ k ] ); + + SKP_assert( sum1_Q14 >= 0 ); + + /* first row of W_Q18 */ + sum2_Q16 = SKP_SMULWB( W_Q18[ 1 ], diff_Q14[ 1 ] ); + sum2_Q16 = SKP_SMLAWB( sum2_Q16, W_Q18[ 2 ], diff_Q14[ 2 ] ); + sum2_Q16 = SKP_SMLAWB( sum2_Q16, W_Q18[ 3 ], diff_Q14[ 3 ] ); + sum2_Q16 = SKP_SMLAWB( sum2_Q16, W_Q18[ 4 ], diff_Q14[ 4 ] ); + sum2_Q16 = SKP_LSHIFT( sum2_Q16, 1 ); + sum2_Q16 = SKP_SMLAWB( sum2_Q16, W_Q18[ 0 ], diff_Q14[ 0 ] ); + sum1_Q14 = SKP_SMLAWB( sum1_Q14, sum2_Q16, diff_Q14[ 0 ] ); + + /* second row of W_Q18 */ + sum2_Q16 = SKP_SMULWB( W_Q18[ 7 ], diff_Q14[ 2 ] ); + sum2_Q16 = SKP_SMLAWB( sum2_Q16, W_Q18[ 8 ], diff_Q14[ 3 ] ); + sum2_Q16 = SKP_SMLAWB( sum2_Q16, W_Q18[ 9 ], diff_Q14[ 4 ] ); + sum2_Q16 = SKP_LSHIFT( sum2_Q16, 1 ); + sum2_Q16 = SKP_SMLAWB( sum2_Q16, W_Q18[ 6 ], diff_Q14[ 1 ] ); + sum1_Q14 = SKP_SMLAWB( sum1_Q14, sum2_Q16, diff_Q14[ 1 ] ); + + /* third row of W_Q18 */ + sum2_Q16 = SKP_SMULWB( W_Q18[ 13 ], diff_Q14[ 3 ] ); + sum2_Q16 = SKP_SMLAWB( sum2_Q16, W_Q18[ 14 ], diff_Q14[ 4 ] ); + sum2_Q16 = SKP_LSHIFT( sum2_Q16, 1 ); + sum2_Q16 = SKP_SMLAWB( sum2_Q16, W_Q18[ 12 ], diff_Q14[ 2 ] ); + sum1_Q14 = SKP_SMLAWB( sum1_Q14, sum2_Q16, diff_Q14[ 2 ] ); + + /* fourth row of W_Q18 */ + sum2_Q16 = SKP_SMULWB( W_Q18[ 19 ], diff_Q14[ 4 ] ); + sum2_Q16 = SKP_LSHIFT( sum2_Q16, 1 ); + sum2_Q16 = SKP_SMLAWB( sum2_Q16, W_Q18[ 18 ], diff_Q14[ 3 ] ); + sum1_Q14 = SKP_SMLAWB( sum1_Q14, sum2_Q16, diff_Q14[ 3 ] ); + + /* last row of W_Q18 */ + sum2_Q16 = SKP_SMULWB( W_Q18[ 24 ], diff_Q14[ 4 ] ); + sum1_Q14 = SKP_SMLAWB( sum1_Q14, sum2_Q16, diff_Q14[ 4 ] ); + + SKP_assert( sum1_Q14 >= 0 ); + + /* find best */ + if( sum1_Q14 < *rate_dist_Q14 ) { + *rate_dist_Q14 = sum1_Q14; + *ind = (opus_int8)k; + } + + /* Go to next cbk vector */ + cb_row_Q7 += LTP_ORDER; + } +} diff --git a/silk/silk_ana_filt_bank_1.c b/silk/silk_ana_filt_bank_1.c index 1cc3baf63..77bd5c549 100644 --- a/silk/silk_ana_filt_bank_1.c +++ b/silk/silk_ana_filt_bank_1.c @@ -1,71 +1,71 @@ -/*********************************************************************** -Copyright (c) 2006-2011, Skype Limited. All rights reserved. -Redistribution and use in source and binary forms, with or without -modification, (subject to the limitations in the disclaimer below) -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 Skype Limited, nor the names of specific -contributors, may be used to endorse or promote products derived from -this software without specific prior written permission. -NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED -BY THIS LICENSE. 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. -***********************************************************************/ - -#include "silk_SigProc_FIX.h" - -/* Coefficients for 2-band filter bank based on first-order allpass filters */ -// old -static opus_int16 A_fb1_20[ 1 ] = { 5394 << 1 }; -static opus_int16 A_fb1_21[ 1 ] = { 20623 << 1 }; /* wrap-around to negative number is intentional */ - -/* Split signal into two decimated bands using first-order allpass filters */ -void silk_ana_filt_bank_1( - const opus_int16 *in, /* I: Input signal [N] */ - opus_int32 *S, /* I/O: State vector [2] */ - opus_int16 *outL, /* O: Low band [N/2] */ - opus_int16 *outH, /* O: High band [N/2] */ - const opus_int32 N /* I: Number of input samples */ -) -{ - opus_int k, N2 = SKP_RSHIFT( N, 1 ); - opus_int32 in32, X, Y, out_1, out_2; - - /* Internal variables and state are in Q10 format */ - for( k = 0; k < N2; k++ ) { - /* Convert to Q10 */ - in32 = SKP_LSHIFT( (opus_int32)in[ 2 * k ], 10 ); - - /* All-pass section for even input sample */ - Y = SKP_SUB32( in32, S[ 0 ] ); - X = SKP_SMLAWB( Y, Y, A_fb1_21[ 0 ] ); - out_1 = SKP_ADD32( S[ 0 ], X ); - S[ 0 ] = SKP_ADD32( in32, X ); - - /* Convert to Q10 */ - in32 = SKP_LSHIFT( (opus_int32)in[ 2 * k + 1 ], 10 ); - - /* All-pass section for odd input sample, and add to output of previous section */ - Y = SKP_SUB32( in32, S[ 1 ] ); - X = SKP_SMULWB( Y, A_fb1_20[ 0 ] ); - out_2 = SKP_ADD32( S[ 1 ], X ); - S[ 1 ] = SKP_ADD32( in32, X ); - - /* Add/subtract, convert back to int16 and store to output */ - outL[ k ] = (opus_int16)SKP_SAT16( SKP_RSHIFT_ROUND( SKP_ADD32( out_2, out_1 ), 11 ) ); - outH[ k ] = (opus_int16)SKP_SAT16( SKP_RSHIFT_ROUND( SKP_SUB32( out_2, out_1 ), 11 ) ); - } -} +/*********************************************************************** +Copyright (c) 2006-2011, Skype Limited. All rights reserved. +Redistribution and use in source and binary forms, with or without +modification, (subject to the limitations in the disclaimer below) +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 Skype Limited, nor the names of specific +contributors, may be used to endorse or promote products derived from +this software without specific prior written permission. +NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED +BY THIS LICENSE. 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. +***********************************************************************/ + +#include "silk_SigProc_FIX.h" + +/* Coefficients for 2-band filter bank based on first-order allpass filters */ +// old +static opus_int16 A_fb1_20[ 1 ] = { 5394 << 1 }; +static opus_int16 A_fb1_21[ 1 ] = { 20623 << 1 }; /* wrap-around to negative number is intentional */ + +/* Split signal into two decimated bands using first-order allpass filters */ +void silk_ana_filt_bank_1( + const opus_int16 *in, /* I: Input signal [N] */ + opus_int32 *S, /* I/O: State vector [2] */ + opus_int16 *outL, /* O: Low band [N/2] */ + opus_int16 *outH, /* O: High band [N/2] */ + const opus_int32 N /* I: Number of input samples */ +) +{ + opus_int k, N2 = SKP_RSHIFT( N, 1 ); + opus_int32 in32, X, Y, out_1, out_2; + + /* Internal variables and state are in Q10 format */ + for( k = 0; k < N2; k++ ) { + /* Convert to Q10 */ + in32 = SKP_LSHIFT( (opus_int32)in[ 2 * k ], 10 ); + + /* All-pass section for even input sample */ + Y = SKP_SUB32( in32, S[ 0 ] ); + X = SKP_SMLAWB( Y, Y, A_fb1_21[ 0 ] ); + out_1 = SKP_ADD32( S[ 0 ], X ); + S[ 0 ] = SKP_ADD32( in32, X ); + + /* Convert to Q10 */ + in32 = SKP_LSHIFT( (opus_int32)in[ 2 * k + 1 ], 10 ); + + /* All-pass section for odd input sample, and add to output of previous section */ + Y = SKP_SUB32( in32, S[ 1 ] ); + X = SKP_SMULWB( Y, A_fb1_20[ 0 ] ); + out_2 = SKP_ADD32( S[ 1 ], X ); + S[ 1 ] = SKP_ADD32( in32, X ); + + /* Add/subtract, convert back to int16 and store to output */ + outL[ k ] = (opus_int16)SKP_SAT16( SKP_RSHIFT_ROUND( SKP_ADD32( out_2, out_1 ), 11 ) ); + outH[ k ] = (opus_int16)SKP_SAT16( SKP_RSHIFT_ROUND( SKP_SUB32( out_2, out_1 ), 11 ) ); + } +} diff --git a/silk/silk_apply_sine_window.c b/silk/silk_apply_sine_window.c index f9f44bfcb..681ba29ff 100644 --- a/silk/silk_apply_sine_window.c +++ b/silk/silk_apply_sine_window.c @@ -1,97 +1,97 @@ -/*********************************************************************** -Copyright (c) 2006-2011, Skype Limited. All rights reserved. -Redistribution and use in source and binary forms, with or without -modification, (subject to the limitations in the disclaimer below) -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 Skype Limited, nor the names of specific -contributors, may be used to endorse or promote products derived from -this software without specific prior written permission. -NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED -BY THIS LICENSE. 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. -***********************************************************************/ - -#include "silk_SigProc_FIX.h" - -/* Apply sine window to signal vector. */ -/* Window types: */ -/* 1 -> sine window from 0 to pi/2 */ -/* 2 -> sine window from pi/2 to pi */ -/* Every other sample is linearly interpolated, for speed. */ -/* Window length must be between 16 and 120 (incl) and a multiple of 4. */ - -/* Matlab code for table: - for k=16:9*4:16+2*9*4, fprintf(' %7.d,', -round(65536*pi ./ (k:4:k+8*4))); fprintf('\n'); end -*/ -static opus_int16 freq_table_Q16[ 27 ] = { - 12111, 9804, 8235, 7100, 6239, 5565, 5022, 4575, 4202, - 3885, 3612, 3375, 3167, 2984, 2820, 2674, 2542, 2422, - 2313, 2214, 2123, 2038, 1961, 1889, 1822, 1760, 1702, -}; - -void silk_apply_sine_window( - opus_int16 px_win[], /* O Pointer to windowed signal */ - const opus_int16 px[], /* I Pointer to input signal */ - const opus_int win_type, /* I Selects a window type */ - const opus_int length /* I Window length, multiple of 4 */ -) -{ - opus_int k, f_Q16, c_Q16; - opus_int32 S0_Q16, S1_Q16; - - SKP_assert( win_type == 1 || win_type == 2 ); - - /* Length must be in a range from 16 to 120 and a multiple of 4 */ - SKP_assert( length >= 16 && length <= 120 ); - SKP_assert( ( length & 3 ) == 0 ); - - /* Frequency */ - k = ( length >> 2 ) - 4; - SKP_assert( k >= 0 && k <= 26 ); - f_Q16 = (opus_int)freq_table_Q16[ k ]; - - /* Factor used for cosine approximation */ - c_Q16 = SKP_SMULWB( f_Q16, -f_Q16 ); - SKP_assert( c_Q16 >= -32768 ); - - /* initialize state */ - if( win_type == 1 ) { - /* start from 0 */ - S0_Q16 = 0; - /* approximation of sin(f) */ - S1_Q16 = f_Q16 + SKP_RSHIFT( length, 3 ); - } else { - /* start from 1 */ - S0_Q16 = ( 1 << 16 ); - /* approximation of cos(f) */ - S1_Q16 = ( 1 << 16 ) + SKP_RSHIFT( c_Q16, 1 ) + SKP_RSHIFT( length, 4 ); - } - - /* Uses the recursive equation: sin(n*f) = 2 * cos(f) * sin((n-1)*f) - sin((n-2)*f) */ - /* 4 samples at a time */ - for( k = 0; k < length; k += 4 ) { - px_win[ k ] = (opus_int16)SKP_SMULWB( SKP_RSHIFT( S0_Q16 + S1_Q16, 1 ), px[ k ] ); - px_win[ k + 1 ] = (opus_int16)SKP_SMULWB( S1_Q16, px[ k + 1] ); - S0_Q16 = SKP_SMULWB( S1_Q16, c_Q16 ) + SKP_LSHIFT( S1_Q16, 1 ) - S0_Q16 + 1; - S0_Q16 = SKP_min( S0_Q16, ( 1 << 16 ) ); - - px_win[ k + 2 ] = (opus_int16)SKP_SMULWB( SKP_RSHIFT( S0_Q16 + S1_Q16, 1 ), px[ k + 2] ); - px_win[ k + 3 ] = (opus_int16)SKP_SMULWB( S0_Q16, px[ k + 3 ] ); - S1_Q16 = SKP_SMULWB( S0_Q16, c_Q16 ) + SKP_LSHIFT( S0_Q16, 1 ) - S1_Q16; - S1_Q16 = SKP_min( S1_Q16, ( 1 << 16 ) ); - } -} +/*********************************************************************** +Copyright (c) 2006-2011, Skype Limited. All rights reserved. +Redistribution and use in source and binary forms, with or without +modification, (subject to the limitations in the disclaimer below) +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 Skype Limited, nor the names of specific +contributors, may be used to endorse or promote products derived from +this software without specific prior written permission. +NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED +BY THIS LICENSE. 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. +***********************************************************************/ + +#include "silk_SigProc_FIX.h" + +/* Apply sine window to signal vector. */ +/* Window types: */ +/* 1 -> sine window from 0 to pi/2 */ +/* 2 -> sine window from pi/2 to pi */ +/* Every other sample is linearly interpolated, for speed. */ +/* Window length must be between 16 and 120 (incl) and a multiple of 4. */ + +/* Matlab code for table: + for k=16:9*4:16+2*9*4, fprintf(' %7.d,', -round(65536*pi ./ (k:4:k+8*4))); fprintf('\n'); end +*/ +static opus_int16 freq_table_Q16[ 27 ] = { + 12111, 9804, 8235, 7100, 6239, 5565, 5022, 4575, 4202, + 3885, 3612, 3375, 3167, 2984, 2820, 2674, 2542, 2422, + 2313, 2214, 2123, 2038, 1961, 1889, 1822, 1760, 1702, +}; + +void silk_apply_sine_window( + opus_int16 px_win[], /* O Pointer to windowed signal */ + const opus_int16 px[], /* I Pointer to input signal */ + const opus_int win_type, /* I Selects a window type */ + const opus_int length /* I Window length, multiple of 4 */ +) +{ + opus_int k, f_Q16, c_Q16; + opus_int32 S0_Q16, S1_Q16; + + SKP_assert( win_type == 1 || win_type == 2 ); + + /* Length must be in a range from 16 to 120 and a multiple of 4 */ + SKP_assert( length >= 16 && length <= 120 ); + SKP_assert( ( length & 3 ) == 0 ); + + /* Frequency */ + k = ( length >> 2 ) - 4; + SKP_assert( k >= 0 && k <= 26 ); + f_Q16 = (opus_int)freq_table_Q16[ k ]; + + /* Factor used for cosine approximation */ + c_Q16 = SKP_SMULWB( f_Q16, -f_Q16 ); + SKP_assert( c_Q16 >= -32768 ); + + /* initialize state */ + if( win_type == 1 ) { + /* start from 0 */ + S0_Q16 = 0; + /* approximation of sin(f) */ + S1_Q16 = f_Q16 + SKP_RSHIFT( length, 3 ); + } else { + /* start from 1 */ + S0_Q16 = ( 1 << 16 ); + /* approximation of cos(f) */ + S1_Q16 = ( 1 << 16 ) + SKP_RSHIFT( c_Q16, 1 ) + SKP_RSHIFT( length, 4 ); + } + + /* Uses the recursive equation: sin(n*f) = 2 * cos(f) * sin((n-1)*f) - sin((n-2)*f) */ + /* 4 samples at a time */ + for( k = 0; k < length; k += 4 ) { + px_win[ k ] = (opus_int16)SKP_SMULWB( SKP_RSHIFT( S0_Q16 + S1_Q16, 1 ), px[ k ] ); + px_win[ k + 1 ] = (opus_int16)SKP_SMULWB( S1_Q16, px[ k + 1] ); + S0_Q16 = SKP_SMULWB( S1_Q16, c_Q16 ) + SKP_LSHIFT( S1_Q16, 1 ) - S0_Q16 + 1; + S0_Q16 = SKP_min( S0_Q16, ( 1 << 16 ) ); + + px_win[ k + 2 ] = (opus_int16)SKP_SMULWB( SKP_RSHIFT( S0_Q16 + S1_Q16, 1 ), px[ k + 2] ); + px_win[ k + 3 ] = (opus_int16)SKP_SMULWB( S0_Q16, px[ k + 3 ] ); + S1_Q16 = SKP_SMULWB( S0_Q16, c_Q16 ) + SKP_LSHIFT( S0_Q16, 1 ) - S1_Q16; + S1_Q16 = SKP_min( S1_Q16, ( 1 << 16 ) ); + } +} diff --git a/silk/silk_array_maxabs.c b/silk/silk_array_maxabs.c index b93dfc890..bb80fd4c9 100644 --- a/silk/silk_array_maxabs.c +++ b/silk/silk_array_maxabs.c @@ -1,60 +1,60 @@ -/*********************************************************************** -Copyright (c) 2006-2011, Skype Limited. All rights reserved. -Redistribution and use in source and binary forms, with or without -modification, (subject to the limitations in the disclaimer below) -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 Skype Limited, nor the names of specific -contributors, may be used to endorse or promote products derived from -this software without specific prior written permission. -NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED -BY THIS LICENSE. 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. -***********************************************************************/ - -#include "silk_SigProc_FIX.h" - -/* Function that returns the maximum absolut value of the input vector */ -opus_int16 silk_int16_array_maxabs( /* O Maximum absolute value, max: 2^15-1 */ - const opus_int16 *vec, /* I Input vector [len] */ - const opus_int32 len /* I Length of input vector */ -) -{ - opus_int32 max = 0, i, lvl = 0, ind; - if( len == 0 ) return 0; - - ind = len - 1; - max = SKP_SMULBB( vec[ ind ], vec[ ind ] ); - for( i = len - 2; i >= 0; i-- ) { - lvl = SKP_SMULBB( vec[ i ], vec[ i ] ); - if( lvl > max ) { - max = lvl; - ind = i; - } - } - - /* Do not return 32768, as it will not fit in an int16 so may lead to problems later on */ - if( max >= 1073676289 ) { // (2^15-1)^2 = 1073676289 - return( SKP_int16_MAX ); - } else { - if( vec[ ind ] < 0 ) { - return( -vec[ ind ] ); - } else { - return( vec[ ind ] ); - } - } -} - +/*********************************************************************** +Copyright (c) 2006-2011, Skype Limited. All rights reserved. +Redistribution and use in source and binary forms, with or without +modification, (subject to the limitations in the disclaimer below) +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 Skype Limited, nor the names of specific +contributors, may be used to endorse or promote products derived from +this software without specific prior written permission. +NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED +BY THIS LICENSE. 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. +***********************************************************************/ + +#include "silk_SigProc_FIX.h" + +/* Function that returns the maximum absolut value of the input vector */ +opus_int16 silk_int16_array_maxabs( /* O Maximum absolute value, max: 2^15-1 */ + const opus_int16 *vec, /* I Input vector [len] */ + const opus_int32 len /* I Length of input vector */ +) +{ + opus_int32 max = 0, i, lvl = 0, ind; + if( len == 0 ) return 0; + + ind = len - 1; + max = SKP_SMULBB( vec[ ind ], vec[ ind ] ); + for( i = len - 2; i >= 0; i-- ) { + lvl = SKP_SMULBB( vec[ i ], vec[ i ] ); + if( lvl > max ) { + max = lvl; + ind = i; + } + } + + /* Do not return 32768, as it will not fit in an int16 so may lead to problems later on */ + if( max >= 1073676289 ) { // (2^15-1)^2 = 1073676289 + return( SKP_int16_MAX ); + } else { + if( vec[ ind ] < 0 ) { + return( -vec[ ind ] ); + } else { + return( vec[ ind ] ); + } + } +} + diff --git a/silk/silk_autocorr.c b/silk/silk_autocorr.c index 16294011b..5ab69e735 100644 --- a/silk/silk_autocorr.c +++ b/silk/silk_autocorr.c @@ -1,72 +1,72 @@ -/*********************************************************************** -Copyright (c) 2006-2011, Skype Limited. All rights reserved. -Redistribution and use in source and binary forms, with or without -modification, (subject to the limitations in the disclaimer below) -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 Skype Limited, nor the names of specific -contributors, may be used to endorse or promote products derived from -this software without specific prior written permission. -NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED -BY THIS LICENSE. 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. -***********************************************************************/ - -#include "silk_SigProc_FIX.h" - -/* Compute autocorrelation */ -void silk_autocorr( - opus_int32 *results, /* O Result (length correlationCount) */ - opus_int *scale, /* O Scaling of the correlation vector */ - const opus_int16 *inputData, /* I Input data to correlate */ - const opus_int inputDataSize, /* I Length of input */ - const opus_int correlationCount /* I Number of correlation taps to compute */ -) -{ - opus_int i, lz, nRightShifts, corrCount; - opus_int64 corr64; - - corrCount = SKP_min_int( inputDataSize, correlationCount ); - - /* compute energy (zero-lag correlation) */ - corr64 = silk_inner_prod16_aligned_64( inputData, inputData, inputDataSize ); - - /* deal with all-zero input data */ - corr64 += 1; - - /* number of leading zeros */ - lz = silk_CLZ64( corr64 ); - - /* scaling: number of right shifts applied to correlations */ - nRightShifts = 35 - lz; - *scale = nRightShifts; - - if( nRightShifts <= 0 ) { - results[ 0 ] = SKP_LSHIFT( (opus_int32)SKP_CHECK_FIT32( corr64 ), -nRightShifts ); - - /* compute remaining correlations based on int32 inner product */ - for( i = 1; i < corrCount; i++ ) { - results[ i ] = SKP_LSHIFT( silk_inner_prod_aligned( inputData, inputData + i, inputDataSize - i ), -nRightShifts ); - } - } else { - results[ 0 ] = (opus_int32)SKP_CHECK_FIT32( SKP_RSHIFT64( corr64, nRightShifts ) ); - - /* compute remaining correlations based on int64 inner product */ - for( i = 1; i < corrCount; i++ ) { - results[ i ] = (opus_int32)SKP_CHECK_FIT32( SKP_RSHIFT64( silk_inner_prod16_aligned_64( inputData, inputData + i, inputDataSize - i ), nRightShifts ) ); - } - } -} +/*********************************************************************** +Copyright (c) 2006-2011, Skype Limited. All rights reserved. +Redistribution and use in source and binary forms, with or without +modification, (subject to the limitations in the disclaimer below) +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 Skype Limited, nor the names of specific +contributors, may be used to endorse or promote products derived from +this software without specific prior written permission. +NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED +BY THIS LICENSE. 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. +***********************************************************************/ + +#include "silk_SigProc_FIX.h" + +/* Compute autocorrelation */ +void silk_autocorr( + opus_int32 *results, /* O Result (length correlationCount) */ + opus_int *scale, /* O Scaling of the correlation vector */ + const opus_int16 *inputData, /* I Input data to correlate */ + const opus_int inputDataSize, /* I Length of input */ + const opus_int correlationCount /* I Number of correlation taps to compute */ +) +{ + opus_int i, lz, nRightShifts, corrCount; + opus_int64 corr64; + + corrCount = SKP_min_int( inputDataSize, correlationCount ); + + /* compute energy (zero-lag correlation) */ + corr64 = silk_inner_prod16_aligned_64( inputData, inputData, inputDataSize ); + + /* deal with all-zero input data */ + corr64 += 1; + + /* number of leading zeros */ + lz = silk_CLZ64( corr64 ); + + /* scaling: number of right shifts applied to correlations */ + nRightShifts = 35 - lz; + *scale = nRightShifts; + + if( nRightShifts <= 0 ) { + results[ 0 ] = SKP_LSHIFT( (opus_int32)SKP_CHECK_FIT32( corr64 ), -nRightShifts ); + + /* compute remaining correlations based on int32 inner product */ + for( i = 1; i < corrCount; i++ ) { + results[ i ] = SKP_LSHIFT( silk_inner_prod_aligned( inputData, inputData + i, inputDataSize - i ), -nRightShifts ); + } + } else { + results[ 0 ] = (opus_int32)SKP_CHECK_FIT32( SKP_RSHIFT64( corr64, nRightShifts ) ); + + /* compute remaining correlations based on int64 inner product */ + for( i = 1; i < corrCount; i++ ) { + results[ i ] = (opus_int32)SKP_CHECK_FIT32( SKP_RSHIFT64( silk_inner_prod16_aligned_64( inputData, inputData + i, inputDataSize - i ), nRightShifts ) ); + } + } +} diff --git a/silk/silk_biquad_alt.c b/silk/silk_biquad_alt.c index ab81f41e1..7d0be3f7a 100644 --- a/silk/silk_biquad_alt.c +++ b/silk/silk_biquad_alt.c @@ -1,73 +1,73 @@ -/*********************************************************************** -Copyright (c) 2006-2011, Skype Limited. All rights reserved. -Redistribution and use in source and binary forms, with or without -modification, (subject to the limitations in the disclaimer below) -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 Skype Limited, nor the names of specific -contributors, may be used to endorse or promote products derived from -this software without specific prior written permission. -NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED -BY THIS LICENSE. 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. -***********************************************************************/ - -/* * - * silk_biquad_alt.c * - * * - * Second order ARMA filter * - * Can handle slowly varying filter coefficients * - * */ -#include "silk_SigProc_FIX.h" - - -/* Second order ARMA filter, alternative implementation */ -void silk_biquad_alt( - const opus_int16 *in, /* I: Input signal */ - const opus_int32 *B_Q28, /* I: MA coefficients [3] */ - const opus_int32 *A_Q28, /* I: AR coefficients [2] */ - opus_int32 *S, /* I/O: State vector [2] */ - opus_int16 *out, /* O: Output signal */ - const opus_int32 len /* I: Signal length (must be even) */ -) -{ - /* DIRECT FORM II TRANSPOSED (uses 2 element state vector) */ - opus_int k; - opus_int32 inval, A0_U_Q28, A0_L_Q28, A1_U_Q28, A1_L_Q28, out32_Q14; - - /* Negate A_Q28 values and split in two parts */ - A0_L_Q28 = ( -A_Q28[ 0 ] ) & 0x00003FFF; /* lower part */ - A0_U_Q28 = SKP_RSHIFT( -A_Q28[ 0 ], 14 ); /* upper part */ - A1_L_Q28 = ( -A_Q28[ 1 ] ) & 0x00003FFF; /* lower part */ - A1_U_Q28 = SKP_RSHIFT( -A_Q28[ 1 ], 14 ); /* upper part */ - - for( k = 0; k < len; k++ ) { - /* S[ 0 ], S[ 1 ]: Q12 */ - inval = in[ k ]; - out32_Q14 = SKP_LSHIFT( SKP_SMLAWB( S[ 0 ], B_Q28[ 0 ], inval ), 2 ); - - S[ 0 ] = S[1] + SKP_RSHIFT_ROUND( SKP_SMULWB( out32_Q14, A0_L_Q28 ), 14 ); - S[ 0 ] = SKP_SMLAWB( S[ 0 ], out32_Q14, A0_U_Q28 ); - S[ 0 ] = SKP_SMLAWB( S[ 0 ], B_Q28[ 1 ], inval); - - S[ 1 ] = SKP_RSHIFT_ROUND( SKP_SMULWB( out32_Q14, A1_L_Q28 ), 14 ); - S[ 1 ] = SKP_SMLAWB( S[ 1 ], out32_Q14, A1_U_Q28 ); - S[ 1 ] = SKP_SMLAWB( S[ 1 ], B_Q28[ 2 ], inval ); - - /* Scale back to Q0 and saturate */ - out[ k ] = (opus_int16)SKP_SAT16( SKP_RSHIFT( out32_Q14 + (1<<14) - 1, 14 ) ); - } -} +/*********************************************************************** +Copyright (c) 2006-2011, Skype Limited. All rights reserved. +Redistribution and use in source and binary forms, with or without +modification, (subject to the limitations in the disclaimer below) +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 Skype Limited, nor the names of specific +contributors, may be used to endorse or promote products derived from +this software without specific prior written permission. +NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED +BY THIS LICENSE. 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. +***********************************************************************/ + +/* * + * silk_biquad_alt.c * + * * + * Second order ARMA filter * + * Can handle slowly varying filter coefficients * + * */ +#include "silk_SigProc_FIX.h" + + +/* Second order ARMA filter, alternative implementation */ +void silk_biquad_alt( + const opus_int16 *in, /* I: Input signal */ + const opus_int32 *B_Q28, /* I: MA coefficients [3] */ + const opus_int32 *A_Q28, /* I: AR coefficients [2] */ + opus_int32 *S, /* I/O: State vector [2] */ + opus_int16 *out, /* O: Output signal */ + const opus_int32 len /* I: Signal length (must be even) */ +) +{ + /* DIRECT FORM II TRANSPOSED (uses 2 element state vector) */ + opus_int k; + opus_int32 inval, A0_U_Q28, A0_L_Q28, A1_U_Q28, A1_L_Q28, out32_Q14; + + /* Negate A_Q28 values and split in two parts */ + A0_L_Q28 = ( -A_Q28[ 0 ] ) & 0x00003FFF; /* lower part */ + A0_U_Q28 = SKP_RSHIFT( -A_Q28[ 0 ], 14 ); /* upper part */ + A1_L_Q28 = ( -A_Q28[ 1 ] ) & 0x00003FFF; /* lower part */ + A1_U_Q28 = SKP_RSHIFT( -A_Q28[ 1 ], 14 ); /* upper part */ + + for( k = 0; k < len; k++ ) { + /* S[ 0 ], S[ 1 ]: Q12 */ + inval = in[ k ]; + out32_Q14 = SKP_LSHIFT( SKP_SMLAWB( S[ 0 ], B_Q28[ 0 ], inval ), 2 ); + + S[ 0 ] = S[1] + SKP_RSHIFT_ROUND( SKP_SMULWB( out32_Q14, A0_L_Q28 ), 14 ); + S[ 0 ] = SKP_SMLAWB( S[ 0 ], out32_Q14, A0_U_Q28 ); + S[ 0 ] = SKP_SMLAWB( S[ 0 ], B_Q28[ 1 ], inval); + + S[ 1 ] = SKP_RSHIFT_ROUND( SKP_SMULWB( out32_Q14, A1_L_Q28 ), 14 ); + S[ 1 ] = SKP_SMLAWB( S[ 1 ], out32_Q14, A1_U_Q28 ); + S[ 1 ] = SKP_SMLAWB( S[ 1 ], B_Q28[ 2 ], inval ); + + /* Scale back to Q0 and saturate */ + out[ k ] = (opus_int16)SKP_SAT16( SKP_RSHIFT( out32_Q14 + (1<<14) - 1, 14 ) ); + } +} diff --git a/silk/silk_burg_modified.c b/silk/silk_burg_modified.c index 8295c7fb6..d28a0ed89 100644 --- a/silk/silk_burg_modified.c +++ b/silk/silk_burg_modified.c @@ -1,218 +1,218 @@ -/*********************************************************************** -Copyright (c) 2006-2011, Skype Limited. All rights reserved. -Redistribution and use in source and binary forms, with or without -modification, (subject to the limitations in the disclaimer below) -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 Skype Limited, nor the names of specific -contributors, may be used to endorse or promote products derived from -this software without specific prior written permission. -NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED -BY THIS LICENSE. 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. -***********************************************************************/ - -#include "silk_SigProc_FIX.h" - -#define MAX_FRAME_SIZE 384 // subfr_length * nb_subfr = ( 0.005 * 16000 + 16 ) * 4 = 384 -#define MAX_NB_SUBFR 4 - -#define QA 25 -#define N_BITS_HEAD_ROOM 2 -#define MIN_RSHIFTS -16 -#define MAX_RSHIFTS (32 - QA) - -/* Compute reflection coefficients from input signal */ -void silk_burg_modified( - opus_int32 *res_nrg, /* O residual energy */ - opus_int *res_nrg_Q, /* O residual energy Q value */ - opus_int32 A_Q16[], /* O prediction coefficients (length order) */ - const opus_int16 x[], /* I input signal, length: nb_subfr * ( D + subfr_length ) */ - const opus_int subfr_length, /* I input signal subframe length (including D preceeding samples) */ - const opus_int nb_subfr, /* I number of subframes stacked in x */ - const opus_int32 WhiteNoiseFrac_Q32, /* I fraction added to zero-lag autocorrelation */ - const opus_int D /* I order */ -) -{ - opus_int k, n, s, lz, rshifts, rshifts_extra; - opus_int32 C0, num, nrg, rc_Q31, Atmp_QA, Atmp1, tmp1, tmp2, x1, x2; - const opus_int16 *x_ptr; - - opus_int32 C_first_row[ SILK_MAX_ORDER_LPC ]; - opus_int32 C_last_row[ SILK_MAX_ORDER_LPC ]; - opus_int32 Af_QA[ SILK_MAX_ORDER_LPC ]; - - opus_int32 CAf[ SILK_MAX_ORDER_LPC + 1 ]; - opus_int32 CAb[ SILK_MAX_ORDER_LPC + 1 ]; - - SKP_assert( subfr_length * nb_subfr <= MAX_FRAME_SIZE ); - SKP_assert( nb_subfr <= MAX_NB_SUBFR ); - - - /* Compute autocorrelations, added over subframes */ - silk_sum_sqr_shift( &C0, &rshifts, x, nb_subfr * subfr_length ); - if( rshifts > MAX_RSHIFTS ) { - C0 = SKP_LSHIFT32( C0, rshifts - MAX_RSHIFTS ); - SKP_assert( C0 > 0 ); - rshifts = MAX_RSHIFTS; - } else { - lz = silk_CLZ32( C0 ) - 1; - rshifts_extra = N_BITS_HEAD_ROOM - lz; - if( rshifts_extra > 0 ) { - rshifts_extra = SKP_min( rshifts_extra, MAX_RSHIFTS - rshifts ); - C0 = SKP_RSHIFT32( C0, rshifts_extra ); - } else { - rshifts_extra = SKP_max( rshifts_extra, MIN_RSHIFTS - rshifts ); - C0 = SKP_LSHIFT32( C0, -rshifts_extra ); - } - rshifts += rshifts_extra; - } - SKP_memset( C_first_row, 0, SILK_MAX_ORDER_LPC * sizeof( opus_int32 ) ); - if( rshifts > 0 ) { - for( s = 0; s < nb_subfr; s++ ) { - x_ptr = x + s * subfr_length; - for( n = 1; n < D + 1; n++ ) { - C_first_row[ n - 1 ] += (opus_int32)SKP_RSHIFT64( - silk_inner_prod16_aligned_64( x_ptr, x_ptr + n, subfr_length - n ), rshifts ); - } - } - } else { - for( s = 0; s < nb_subfr; s++ ) { - x_ptr = x + s * subfr_length; - for( n = 1; n < D + 1; n++ ) { - C_first_row[ n - 1 ] += SKP_LSHIFT32( - silk_inner_prod_aligned( x_ptr, x_ptr + n, subfr_length - n ), -rshifts ); - } - } - } - SKP_memcpy( C_last_row, C_first_row, SILK_MAX_ORDER_LPC * sizeof( opus_int32 ) ); - - /* Initialize */ - CAb[ 0 ] = CAf[ 0 ] = C0 + SKP_SMMUL( WhiteNoiseFrac_Q32, C0 ) + 1; // Q(-rshifts) - - 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) */ - /* Update C * Af */ - /* Update C * flipud(Af) (stored in reversed order) */ - if( rshifts > -2 ) { - for( s = 0; s < nb_subfr; s++ ) { - x_ptr = x + s * subfr_length; - x1 = -SKP_LSHIFT32( (opus_int32)x_ptr[ n ], 16 - rshifts ); // Q(16-rshifts) - x2 = -SKP_LSHIFT32( (opus_int32)x_ptr[ subfr_length - n - 1 ], 16 - rshifts ); // Q(16-rshifts) - tmp1 = SKP_LSHIFT32( (opus_int32)x_ptr[ n ], QA - 16 ); // Q(QA-16) - tmp2 = SKP_LSHIFT32( (opus_int32)x_ptr[ subfr_length - n - 1 ], QA - 16 ); // Q(QA-16) - for( k = 0; k < n; k++ ) { - C_first_row[ k ] = SKP_SMLAWB( C_first_row[ k ], x1, x_ptr[ n - k - 1 ] ); // Q( -rshifts ) - C_last_row[ k ] = SKP_SMLAWB( C_last_row[ k ], x2, x_ptr[ subfr_length - n + k ] ); // Q( -rshifts ) - Atmp_QA = Af_QA[ k ]; - tmp1 = SKP_SMLAWB( tmp1, Atmp_QA, x_ptr[ n - k - 1 ] ); // Q(QA-16) - tmp2 = SKP_SMLAWB( tmp2, Atmp_QA, x_ptr[ subfr_length - n + k ] ); // Q(QA-16) - } - tmp1 = SKP_LSHIFT32( -tmp1, 32 - QA - rshifts ); // Q(16-rshifts) - tmp2 = SKP_LSHIFT32( -tmp2, 32 - QA - rshifts ); // Q(16-rshifts) - for( k = 0; k <= n; k++ ) { - CAf[ k ] = SKP_SMLAWB( CAf[ k ], tmp1, x_ptr[ n - k ] ); // Q( -rshift ) - CAb[ k ] = SKP_SMLAWB( CAb[ k ], tmp2, x_ptr[ subfr_length - n + k - 1 ] ); // Q( -rshift ) - } - } - } else { - for( s = 0; s < nb_subfr; s++ ) { - x_ptr = x + s * subfr_length; - x1 = -SKP_LSHIFT32( (opus_int32)x_ptr[ n ], -rshifts ); // Q( -rshifts ) - x2 = -SKP_LSHIFT32( (opus_int32)x_ptr[ subfr_length - n - 1 ], -rshifts ); // Q( -rshifts ) - tmp1 = SKP_LSHIFT32( (opus_int32)x_ptr[ n ], 17 ); // Q17 - tmp2 = SKP_LSHIFT32( (opus_int32)x_ptr[ subfr_length - n - 1 ], 17 ); // Q17 - for( k = 0; k < n; k++ ) { - C_first_row[ k ] = SKP_MLA( C_first_row[ k ], x1, x_ptr[ n - k - 1 ] ); // Q( -rshifts ) - C_last_row[ k ] = SKP_MLA( C_last_row[ k ], x2, x_ptr[ subfr_length - n + k ] ); // Q( -rshifts ) - Atmp1 = SKP_RSHIFT_ROUND( Af_QA[ k ], QA - 17 ); // Q17 - tmp1 = SKP_MLA( tmp1, x_ptr[ n - k - 1 ], Atmp1 ); // Q17 - tmp2 = SKP_MLA( tmp2, x_ptr[ subfr_length - n + k ], Atmp1 ); // Q17 - } - tmp1 = -tmp1; // Q17 - tmp2 = -tmp2; // Q17 - for( k = 0; k <= n; k++ ) { - CAf[ k ] = SKP_SMLAWW( CAf[ k ], tmp1, - SKP_LSHIFT32( (opus_int32)x_ptr[ n - k ], -rshifts - 1 ) ); // Q( -rshift ) - CAb[ k ] = SKP_SMLAWW( CAb[ k ], tmp2, - SKP_LSHIFT32( (opus_int32)x_ptr[ subfr_length - n + k - 1 ], -rshifts - 1 ) );// Q( -rshift ) - } - } - } - - /* Calculate nominator and denominator for the next order reflection (parcor) coefficient */ - tmp1 = C_first_row[ n ]; // Q( -rshifts ) - tmp2 = C_last_row[ n ]; // Q( -rshifts ) - num = 0; // Q( -rshifts ) - nrg = SKP_ADD32( CAb[ 0 ], CAf[ 0 ] ); // Q( 1-rshifts ) - for( k = 0; k < n; k++ ) { - Atmp_QA = Af_QA[ k ]; - lz = silk_CLZ32( SKP_abs( Atmp_QA ) ) - 1; - lz = SKP_min( 32 - QA, lz ); - Atmp1 = SKP_LSHIFT32( Atmp_QA, lz ); // Q( QA + lz ) - - tmp1 = SKP_ADD_LSHIFT32( tmp1, SKP_SMMUL( C_last_row[ n - k - 1 ], Atmp1 ), 32 - QA - lz ); // Q( -rshifts ) - tmp2 = SKP_ADD_LSHIFT32( tmp2, SKP_SMMUL( C_first_row[ n - k - 1 ], Atmp1 ), 32 - QA - lz ); // Q( -rshifts ) - num = SKP_ADD_LSHIFT32( num, SKP_SMMUL( CAb[ n - k ], Atmp1 ), 32 - QA - lz ); // Q( -rshifts ) - nrg = SKP_ADD_LSHIFT32( nrg, SKP_SMMUL( SKP_ADD32( CAb[ k + 1 ], CAf[ k + 1 ] ), - Atmp1 ), 32 - QA - lz ); // Q( 1-rshifts ) - } - CAf[ n + 1 ] = tmp1; // Q( -rshifts ) - CAb[ n + 1 ] = tmp2; // Q( -rshifts ) - num = SKP_ADD32( num, tmp2 ); // Q( -rshifts ) - num = SKP_LSHIFT32( -num, 1 ); // Q( 1-rshifts ) - - /* Calculate the next order reflection (parcor) coefficient */ - if( SKP_abs( num ) < nrg ) { - rc_Q31 = silk_DIV32_varQ( num, nrg, 31 ); - } else { - /* Negative energy or ratio too high; set remaining coefficients to zero and exit loop */ - SKP_memset( &Af_QA[ n ], 0, ( D - n ) * sizeof( opus_int32 ) ); - SKP_assert( 0 ); - break; - } - - /* Update the AR coefficients */ - for( k = 0; k < (n + 1) >> 1; k++ ) { - tmp1 = Af_QA[ k ]; // QA - tmp2 = Af_QA[ n - k - 1 ]; // QA - Af_QA[ k ] = SKP_ADD_LSHIFT32( tmp1, SKP_SMMUL( tmp2, rc_Q31 ), 1 ); // QA - Af_QA[ n - k - 1 ] = SKP_ADD_LSHIFT32( tmp2, SKP_SMMUL( tmp1, rc_Q31 ), 1 ); // QA - } - Af_QA[ n ] = SKP_RSHIFT32( rc_Q31, 31 - QA ); // QA - - /* Update C * Af and C * Ab */ - for( k = 0; k <= n + 1; k++ ) { - tmp1 = CAf[ k ]; // Q( -rshifts ) - tmp2 = CAb[ n - k + 1 ]; // Q( -rshifts ) - CAf[ k ] = SKP_ADD_LSHIFT32( tmp1, SKP_SMMUL( tmp2, rc_Q31 ), 1 ); // Q( -rshifts ) - CAb[ n - k + 1 ] = SKP_ADD_LSHIFT32( tmp2, SKP_SMMUL( tmp1, rc_Q31 ), 1 ); // Q( -rshifts ) - } - } - - /* Return residual energy */ - nrg = CAf[ 0 ]; // Q( -rshifts ) - tmp1 = 1 << 16; // Q16 - for( k = 0; k < D; k++ ) { - Atmp1 = SKP_RSHIFT_ROUND( Af_QA[ k ], QA - 16 ); // Q16 - nrg = SKP_SMLAWW( nrg, CAf[ k + 1 ], Atmp1 ); // Q( -rshifts ) - tmp1 = SKP_SMLAWW( tmp1, Atmp1, Atmp1 ); // Q16 - A_Q16[ k ] = -Atmp1; - } - *res_nrg = SKP_SMLAWW( nrg, SKP_SMMUL( WhiteNoiseFrac_Q32, C0 ), -tmp1 ); // Q( -rshifts ) - *res_nrg_Q = -rshifts; -} +/*********************************************************************** +Copyright (c) 2006-2011, Skype Limited. All rights reserved. +Redistribution and use in source and binary forms, with or without +modification, (subject to the limitations in the disclaimer below) +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 Skype Limited, nor the names of specific +contributors, may be used to endorse or promote products derived from +this software without specific prior written permission. +NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED +BY THIS LICENSE. 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. +***********************************************************************/ + +#include "silk_SigProc_FIX.h" + +#define MAX_FRAME_SIZE 384 // subfr_length * nb_subfr = ( 0.005 * 16000 + 16 ) * 4 = 384 +#define MAX_NB_SUBFR 4 + +#define QA 25 +#define N_BITS_HEAD_ROOM 2 +#define MIN_RSHIFTS -16 +#define MAX_RSHIFTS (32 - QA) + +/* Compute reflection coefficients from input signal */ +void silk_burg_modified( + opus_int32 *res_nrg, /* O residual energy */ + opus_int *res_nrg_Q, /* O residual energy Q value */ + opus_int32 A_Q16[], /* O prediction coefficients (length order) */ + const opus_int16 x[], /* I input signal, length: nb_subfr * ( D + subfr_length ) */ + const opus_int subfr_length, /* I input signal subframe length (including D preceeding samples) */ + const opus_int nb_subfr, /* I number of subframes stacked in x */ + const opus_int32 WhiteNoiseFrac_Q32, /* I fraction added to zero-lag autocorrelation */ + const opus_int D /* I order */ +) +{ + opus_int k, n, s, lz, rshifts, rshifts_extra; + opus_int32 C0, num, nrg, rc_Q31, Atmp_QA, Atmp1, tmp1, tmp2, x1, x2; + const opus_int16 *x_ptr; + + opus_int32 C_first_row[ SILK_MAX_ORDER_LPC ]; + opus_int32 C_last_row[ SILK_MAX_ORDER_LPC ]; + opus_int32 Af_QA[ SILK_MAX_ORDER_LPC ]; + + opus_int32 CAf[ SILK_MAX_ORDER_LPC + 1 ]; + opus_int32 CAb[ SILK_MAX_ORDER_LPC + 1 ]; + + SKP_assert( subfr_length * nb_subfr <= MAX_FRAME_SIZE ); + SKP_assert( nb_subfr <= MAX_NB_SUBFR ); + + + /* Compute autocorrelations, added over subframes */ + silk_sum_sqr_shift( &C0, &rshifts, x, nb_subfr * subfr_length ); + if( rshifts > MAX_RSHIFTS ) { + C0 = SKP_LSHIFT32( C0, rshifts - MAX_RSHIFTS ); + SKP_assert( C0 > 0 ); + rshifts = MAX_RSHIFTS; + } else { + lz = silk_CLZ32( C0 ) - 1; + rshifts_extra = N_BITS_HEAD_ROOM - lz; + if( rshifts_extra > 0 ) { + rshifts_extra = SKP_min( rshifts_extra, MAX_RSHIFTS - rshifts ); + C0 = SKP_RSHIFT32( C0, rshifts_extra ); + } else { + rshifts_extra = SKP_max( rshifts_extra, MIN_RSHIFTS - rshifts ); + C0 = SKP_LSHIFT32( C0, -rshifts_extra ); + } + rshifts += rshifts_extra; + } + SKP_memset( C_first_row, 0, SILK_MAX_ORDER_LPC * sizeof( opus_int32 ) ); + if( rshifts > 0 ) { + for( s = 0; s < nb_subfr; s++ ) { + x_ptr = x + s * subfr_length; + for( n = 1; n < D + 1; n++ ) { + C_first_row[ n - 1 ] += (opus_int32)SKP_RSHIFT64( + silk_inner_prod16_aligned_64( x_ptr, x_ptr + n, subfr_length - n ), rshifts ); + } + } + } else { + for( s = 0; s < nb_subfr; s++ ) { + x_ptr = x + s * subfr_length; + for( n = 1; n < D + 1; n++ ) { + C_first_row[ n - 1 ] += SKP_LSHIFT32( + silk_inner_prod_aligned( x_ptr, x_ptr + n, subfr_length - n ), -rshifts ); + } + } + } + SKP_memcpy( C_last_row, C_first_row, SILK_MAX_ORDER_LPC * sizeof( opus_int32 ) ); + + /* Initialize */ + CAb[ 0 ] = CAf[ 0 ] = C0 + SKP_SMMUL( WhiteNoiseFrac_Q32, C0 ) + 1; // Q(-rshifts) + + 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) */ + /* Update C * Af */ + /* Update C * flipud(Af) (stored in reversed order) */ + if( rshifts > -2 ) { + for( s = 0; s < nb_subfr; s++ ) { + x_ptr = x + s * subfr_length; + x1 = -SKP_LSHIFT32( (opus_int32)x_ptr[ n ], 16 - rshifts ); // Q(16-rshifts) + x2 = -SKP_LSHIFT32( (opus_int32)x_ptr[ subfr_length - n - 1 ], 16 - rshifts ); // Q(16-rshifts) + tmp1 = SKP_LSHIFT32( (opus_int32)x_ptr[ n ], QA - 16 ); // Q(QA-16) + tmp2 = SKP_LSHIFT32( (opus_int32)x_ptr[ subfr_length - n - 1 ], QA - 16 ); // Q(QA-16) + for( k = 0; k < n; k++ ) { + C_first_row[ k ] = SKP_SMLAWB( C_first_row[ k ], x1, x_ptr[ n - k - 1 ] ); // Q( -rshifts ) + C_last_row[ k ] = SKP_SMLAWB( C_last_row[ k ], x2, x_ptr[ subfr_length - n + k ] ); // Q( -rshifts ) + Atmp_QA = Af_QA[ k ]; + tmp1 = SKP_SMLAWB( tmp1, Atmp_QA, x_ptr[ n - k - 1 ] ); // Q(QA-16) + tmp2 = SKP_SMLAWB( tmp2, Atmp_QA, x_ptr[ subfr_length - n + k ] ); // Q(QA-16) + } + tmp1 = SKP_LSHIFT32( -tmp1, 32 - QA - rshifts ); // Q(16-rshifts) + tmp2 = SKP_LSHIFT32( -tmp2, 32 - QA - rshifts ); // Q(16-rshifts) + for( k = 0; k <= n; k++ ) { + CAf[ k ] = SKP_SMLAWB( CAf[ k ], tmp1, x_ptr[ n - k ] ); // Q( -rshift ) + CAb[ k ] = SKP_SMLAWB( CAb[ k ], tmp2, x_ptr[ subfr_length - n + k - 1 ] ); // Q( -rshift ) + } + } + } else { + for( s = 0; s < nb_subfr; s++ ) { + x_ptr = x + s * subfr_length; + x1 = -SKP_LSHIFT32( (opus_int32)x_ptr[ n ], -rshifts ); // Q( -rshifts ) + x2 = -SKP_LSHIFT32( (opus_int32)x_ptr[ subfr_length - n - 1 ], -rshifts ); // Q( -rshifts ) + tmp1 = SKP_LSHIFT32( (opus_int32)x_ptr[ n ], 17 ); // Q17 + tmp2 = SKP_LSHIFT32( (opus_int32)x_ptr[ subfr_length - n - 1 ], 17 ); // Q17 + for( k = 0; k < n; k++ ) { + C_first_row[ k ] = SKP_MLA( C_first_row[ k ], x1, x_ptr[ n - k - 1 ] ); // Q( -rshifts ) + C_last_row[ k ] = SKP_MLA( C_last_row[ k ], x2, x_ptr[ subfr_length - n + k ] ); // Q( -rshifts ) + Atmp1 = SKP_RSHIFT_ROUND( Af_QA[ k ], QA - 17 ); // Q17 + tmp1 = SKP_MLA( tmp1, x_ptr[ n - k - 1 ], Atmp1 ); // Q17 + tmp2 = SKP_MLA( tmp2, x_ptr[ subfr_length - n + k ], Atmp1 ); // Q17 + } + tmp1 = -tmp1; // Q17 + tmp2 = -tmp2; // Q17 + for( k = 0; k <= n; k++ ) { + CAf[ k ] = SKP_SMLAWW( CAf[ k ], tmp1, + SKP_LSHIFT32( (opus_int32)x_ptr[ n - k ], -rshifts - 1 ) ); // Q( -rshift ) + CAb[ k ] = SKP_SMLAWW( CAb[ k ], tmp2, + SKP_LSHIFT32( (opus_int32)x_ptr[ subfr_length - n + k - 1 ], -rshifts - 1 ) );// Q( -rshift ) + } + } + } + + /* Calculate nominator and denominator for the next order reflection (parcor) coefficient */ + tmp1 = C_first_row[ n ]; // Q( -rshifts ) + tmp2 = C_last_row[ n ]; // Q( -rshifts ) + num = 0; // Q( -rshifts ) + nrg = SKP_ADD32( CAb[ 0 ], CAf[ 0 ] ); // Q( 1-rshifts ) + for( k = 0; k < n; k++ ) { + Atmp_QA = Af_QA[ k ]; + lz = silk_CLZ32( SKP_abs( Atmp_QA ) ) - 1; + lz = SKP_min( 32 - QA, lz ); + Atmp1 = SKP_LSHIFT32( Atmp_QA, lz ); // Q( QA + lz ) + + tmp1 = SKP_ADD_LSHIFT32( tmp1, SKP_SMMUL( C_last_row[ n - k - 1 ], Atmp1 ), 32 - QA - lz ); // Q( -rshifts ) + tmp2 = SKP_ADD_LSHIFT32( tmp2, SKP_SMMUL( C_first_row[ n - k - 1 ], Atmp1 ), 32 - QA - lz ); // Q( -rshifts ) + num = SKP_ADD_LSHIFT32( num, SKP_SMMUL( CAb[ n - k ], Atmp1 ), 32 - QA - lz ); // Q( -rshifts ) + nrg = SKP_ADD_LSHIFT32( nrg, SKP_SMMUL( SKP_ADD32( CAb[ k + 1 ], CAf[ k + 1 ] ), + Atmp1 ), 32 - QA - lz ); // Q( 1-rshifts ) + } + CAf[ n + 1 ] = tmp1; // Q( -rshifts ) + CAb[ n + 1 ] = tmp2; // Q( -rshifts ) + num = SKP_ADD32( num, tmp2 ); // Q( -rshifts ) + num = SKP_LSHIFT32( -num, 1 ); // Q( 1-rshifts ) + + /* Calculate the next order reflection (parcor) coefficient */ + if( SKP_abs( num ) < nrg ) { + rc_Q31 = silk_DIV32_varQ( num, nrg, 31 ); + } else { + /* Negative energy or ratio too high; set remaining coefficients to zero and exit loop */ + SKP_memset( &Af_QA[ n ], 0, ( D - n ) * sizeof( opus_int32 ) ); + SKP_assert( 0 ); + break; + } + + /* Update the AR coefficients */ + for( k = 0; k < (n + 1) >> 1; k++ ) { + tmp1 = Af_QA[ k ]; // QA + tmp2 = Af_QA[ n - k - 1 ]; // QA + Af_QA[ k ] = SKP_ADD_LSHIFT32( tmp1, SKP_SMMUL( tmp2, rc_Q31 ), 1 ); // QA + Af_QA[ n - k - 1 ] = SKP_ADD_LSHIFT32( tmp2, SKP_SMMUL( tmp1, rc_Q31 ), 1 ); // QA + } + Af_QA[ n ] = SKP_RSHIFT32( rc_Q31, 31 - QA ); // QA + + /* Update C * Af and C * Ab */ + for( k = 0; k <= n + 1; k++ ) { + tmp1 = CAf[ k ]; // Q( -rshifts ) + tmp2 = CAb[ n - k + 1 ]; // Q( -rshifts ) + CAf[ k ] = SKP_ADD_LSHIFT32( tmp1, SKP_SMMUL( tmp2, rc_Q31 ), 1 ); // Q( -rshifts ) + CAb[ n - k + 1 ] = SKP_ADD_LSHIFT32( tmp2, SKP_SMMUL( tmp1, rc_Q31 ), 1 ); // Q( -rshifts ) + } + } + + /* Return residual energy */ + nrg = CAf[ 0 ]; // Q( -rshifts ) + tmp1 = 1 << 16; // Q16 + for( k = 0; k < D; k++ ) { + Atmp1 = SKP_RSHIFT_ROUND( Af_QA[ k ], QA - 16 ); // Q16 + nrg = SKP_SMLAWW( nrg, CAf[ k + 1 ], Atmp1 ); // Q( -rshifts ) + tmp1 = SKP_SMLAWW( tmp1, Atmp1, Atmp1 ); // Q16 + A_Q16[ k ] = -Atmp1; + } + *res_nrg = SKP_SMLAWW( nrg, SKP_SMMUL( WhiteNoiseFrac_Q32, C0 ), -tmp1 ); // Q( -rshifts ) + *res_nrg_Q = -rshifts; +} diff --git a/silk/silk_bwexpander.c b/silk/silk_bwexpander.c index 8f65f04ce..1758f2ba7 100644 --- a/silk/silk_bwexpander.c +++ b/silk/silk_bwexpander.c @@ -1,47 +1,47 @@ -/*********************************************************************** -Copyright (c) 2006-2011, Skype Limited. All rights reserved. -Redistribution and use in source and binary forms, with or without -modification, (subject to the limitations in the disclaimer below) -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 Skype Limited, nor the names of specific -contributors, may be used to endorse or promote products derived from -this software without specific prior written permission. -NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED -BY THIS LICENSE. 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. -***********************************************************************/ - -#include "silk_SigProc_FIX.h" - -/* Chirp (bandwidth expand) LP AR filter */ -void silk_bwexpander( - opus_int16 *ar, /* I/O AR filter to be expanded (without leading 1) */ - const opus_int d, /* I Length of ar */ - opus_int32 chirp_Q16 /* I Chirp factor (typically in the range 0 to 1) */ -) -{ - opus_int i; - opus_int32 chirp_minus_one_Q16 = chirp_Q16 - 65536; - - /* NB: Dont use SKP_SMULWB, instead of SKP_RSHIFT_ROUND( SKP_MUL(), 16 ), below. */ - /* Bias in SKP_SMULWB can lead to unstable filters */ - for( i = 0; i < d - 1; i++ ) { - ar[ i ] = (opus_int16)SKP_RSHIFT_ROUND( SKP_MUL( chirp_Q16, ar[ i ] ), 16 ); - chirp_Q16 += SKP_RSHIFT_ROUND( SKP_MUL( chirp_Q16, chirp_minus_one_Q16 ), 16 ); - } - ar[ d - 1 ] = (opus_int16)SKP_RSHIFT_ROUND( SKP_MUL( chirp_Q16, ar[ d - 1 ] ), 16 ); -} +/*********************************************************************** +Copyright (c) 2006-2011, Skype Limited. All rights reserved. +Redistribution and use in source and binary forms, with or without +modification, (subject to the limitations in the disclaimer below) +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 Skype Limited, nor the names of specific +contributors, may be used to endorse or promote products derived from +this software without specific prior written permission. +NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED +BY THIS LICENSE. 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. +***********************************************************************/ + +#include "silk_SigProc_FIX.h" + +/* Chirp (bandwidth expand) LP AR filter */ +void silk_bwexpander( + opus_int16 *ar, /* I/O AR filter to be expanded (without leading 1) */ + const opus_int d, /* I Length of ar */ + opus_int32 chirp_Q16 /* I Chirp factor (typically in the range 0 to 1) */ +) +{ + opus_int i; + opus_int32 chirp_minus_one_Q16 = chirp_Q16 - 65536; + + /* NB: Dont use SKP_SMULWB, instead of SKP_RSHIFT_ROUND( SKP_MUL(), 16 ), below. */ + /* Bias in SKP_SMULWB can lead to unstable filters */ + for( i = 0; i < d - 1; i++ ) { + ar[ i ] = (opus_int16)SKP_RSHIFT_ROUND( SKP_MUL( chirp_Q16, ar[ i ] ), 16 ); + chirp_Q16 += SKP_RSHIFT_ROUND( SKP_MUL( chirp_Q16, chirp_minus_one_Q16 ), 16 ); + } + ar[ d - 1 ] = (opus_int16)SKP_RSHIFT_ROUND( SKP_MUL( chirp_Q16, ar[ d - 1 ] ), 16 ); +} diff --git a/silk/silk_bwexpander_32.c b/silk/silk_bwexpander_32.c index c5a857d19..ac5d50d65 100644 --- a/silk/silk_bwexpander_32.c +++ b/silk/silk_bwexpander_32.c @@ -1,46 +1,46 @@ -/*********************************************************************** -Copyright (c) 2006-2011, Skype Limited. All rights reserved. -Redistribution and use in source and binary forms, with or without -modification, (subject to the limitations in the disclaimer below) -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 Skype Limited, nor the names of specific -contributors, may be used to endorse or promote products derived from -this software without specific prior written permission. -NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED -BY THIS LICENSE. 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. -***********************************************************************/ - -#include "silk_SigProc_FIX.h" - -/* Chirp (bandwidth expand) LP AR filter */ -void silk_bwexpander_32( - opus_int32 *ar, /* I/O AR filter to be expanded (without leading 1) */ - const opus_int d, /* I Length of ar */ - opus_int32 chirp_Q16 /* I Chirp factor in Q16 */ -) -{ - opus_int i; - opus_int32 chirp_minus_one_Q16 = chirp_Q16 - 65536; - - for( i = 0; i < d - 1; i++ ) { - ar[ i ] = SKP_SMULWW( chirp_Q16, ar[ i ] ); - chirp_Q16 += SKP_RSHIFT_ROUND( SKP_MUL( chirp_Q16, chirp_minus_one_Q16 ), 16 ); - } - ar[ d - 1 ] = SKP_SMULWW( chirp_Q16, ar[ d - 1 ] ); -} - +/*********************************************************************** +Copyright (c) 2006-2011, Skype Limited. All rights reserved. +Redistribution and use in source and binary forms, with or without +modification, (subject to the limitations in the disclaimer below) +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 Skype Limited, nor the names of specific +contributors, may be used to endorse or promote products derived from +this software without specific prior written permission. +NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED +BY THIS LICENSE. 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. +***********************************************************************/ + +#include "silk_SigProc_FIX.h" + +/* Chirp (bandwidth expand) LP AR filter */ +void silk_bwexpander_32( + opus_int32 *ar, /* I/O AR filter to be expanded (without leading 1) */ + const opus_int d, /* I Length of ar */ + opus_int32 chirp_Q16 /* I Chirp factor in Q16 */ +) +{ + opus_int i; + opus_int32 chirp_minus_one_Q16 = chirp_Q16 - 65536; + + for( i = 0; i < d - 1; i++ ) { + ar[ i ] = SKP_SMULWW( chirp_Q16, ar[ i ] ); + chirp_Q16 += SKP_RSHIFT_ROUND( SKP_MUL( chirp_Q16, chirp_minus_one_Q16 ), 16 ); + } + ar[ d - 1 ] = SKP_SMULWW( chirp_Q16, ar[ d - 1 ] ); +} + diff --git a/silk/silk_check_control_input.c b/silk/silk_check_control_input.c index 6ece48b05..9e11d9043 100644 --- a/silk/silk_check_control_input.c +++ b/silk/silk_check_control_input.c @@ -1,102 +1,102 @@ -/*********************************************************************** -Copyright (c) 2006-2011, Skype Limited. All rights reserved. -Redistribution and use in source and binary forms, with or without -modification, (subject to the limitations in the disclaimer below) -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 Skype Limited, nor the names of specific -contributors, may be used to endorse or promote products derived from -this software without specific prior written permission. -NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED -BY THIS LICENSE. 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. -***********************************************************************/ - -#include "silk_main.h" -#include "silk_control.h" -#include "silk_errors.h" - -/* Check encoder control struct */ -opus_int check_control_input( - silk_EncControlStruct *encControl /* I: Control structure */ -) -{ - SKP_assert( encControl != NULL ); - - if( ( ( encControl->API_sampleRate != 8000 ) && - ( encControl->API_sampleRate != 12000 ) && - ( encControl->API_sampleRate != 16000 ) && - ( encControl->API_sampleRate != 24000 ) && - ( encControl->API_sampleRate != 32000 ) && - ( encControl->API_sampleRate != 44100 ) && - ( encControl->API_sampleRate != 48000 ) ) || - ( ( encControl->desiredInternalSampleRate != 8000 ) && - ( encControl->desiredInternalSampleRate != 12000 ) && - ( encControl->desiredInternalSampleRate != 16000 ) ) || - ( ( encControl->maxInternalSampleRate != 8000 ) && - ( encControl->maxInternalSampleRate != 12000 ) && - ( encControl->maxInternalSampleRate != 16000 ) ) || - ( ( encControl->minInternalSampleRate != 8000 ) && - ( encControl->minInternalSampleRate != 12000 ) && - ( encControl->minInternalSampleRate != 16000 ) ) || - ( encControl->minInternalSampleRate > encControl->desiredInternalSampleRate ) || - ( encControl->maxInternalSampleRate < encControl->desiredInternalSampleRate ) || - ( encControl->minInternalSampleRate > encControl->maxInternalSampleRate ) ) { - SKP_assert( 0 ); - return SILK_ENC_FS_NOT_SUPPORTED; - } - if( encControl->payloadSize_ms != 10 && - encControl->payloadSize_ms != 20 && - encControl->payloadSize_ms != 40 && - encControl->payloadSize_ms != 60 ) { - SKP_assert( 0 ); - return SILK_ENC_PACKET_SIZE_NOT_SUPPORTED; - } - if( encControl->packetLossPercentage < 0 || encControl->packetLossPercentage > 100 ) { - SKP_assert( 0 ); - return SILK_ENC_INVALID_LOSS_RATE; - } - if( encControl->useDTX < 0 || encControl->useDTX > 1 ) { - SKP_assert( 0 ); - return SILK_ENC_INVALID_DTX_SETTING; - } - if( encControl->useCBR < 0 || encControl->useCBR > 1 ) { - SKP_assert( 0 ); - return SILK_ENC_INVALID_CBR_SETTING; - } - if( encControl->useInBandFEC < 0 || encControl->useInBandFEC > 1 ) { - SKP_assert( 0 ); - return SILK_ENC_INVALID_INBAND_FEC_SETTING; - } - if( encControl->nChannelsAPI < 1 || encControl->nChannelsAPI > ENCODER_NUM_CHANNELS ) { - SKP_assert( 0 ); - return SILK_ENC_INVALID_NUMBER_OF_CHANNELS_ERROR; - } - if( encControl->nChannelsInternal < 1 || encControl->nChannelsInternal > ENCODER_NUM_CHANNELS ) { - SKP_assert( 0 ); - return SILK_ENC_INVALID_NUMBER_OF_CHANNELS_ERROR; - } - if( encControl->nChannelsInternal > encControl->nChannelsAPI ) { - SKP_assert( 0 ); - return SILK_ENC_INVALID_NUMBER_OF_CHANNELS_ERROR; - } - if( encControl->complexity < 0 || encControl->complexity > 10 ) { - SKP_assert( 0 ); - return SILK_ENC_INVALID_COMPLEXITY_SETTING; - } - - return SILK_NO_ERROR; -} +/*********************************************************************** +Copyright (c) 2006-2011, Skype Limited. All rights reserved. +Redistribution and use in source and binary forms, with or without +modification, (subject to the limitations in the disclaimer below) +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 Skype Limited, nor the names of specific +contributors, may be used to endorse or promote products derived from +this software without specific prior written permission. +NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED +BY THIS LICENSE. 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. +***********************************************************************/ + +#include "silk_main.h" +#include "silk_control.h" +#include "silk_errors.h" + +/* Check encoder control struct */ +opus_int check_control_input( + silk_EncControlStruct *encControl /* I: Control structure */ +) +{ + SKP_assert( encControl != NULL ); + + if( ( ( encControl->API_sampleRate != 8000 ) && + ( encControl->API_sampleRate != 12000 ) && + ( encControl->API_sampleRate != 16000 ) && + ( encControl->API_sampleRate != 24000 ) && + ( encControl->API_sampleRate != 32000 ) && + ( encControl->API_sampleRate != 44100 ) && + ( encControl->API_sampleRate != 48000 ) ) || + ( ( encControl->desiredInternalSampleRate != 8000 ) && + ( encControl->desiredInternalSampleRate != 12000 ) && + ( encControl->desiredInternalSampleRate != 16000 ) ) || + ( ( encControl->maxInternalSampleRate != 8000 ) && + ( encControl->maxInternalSampleRate != 12000 ) && + ( encControl->maxInternalSampleRate != 16000 ) ) || + ( ( encControl->minInternalSampleRate != 8000 ) && + ( encControl->minInternalSampleRate != 12000 ) && + ( encControl->minInternalSampleRate != 16000 ) ) || + ( encControl->minInternalSampleRate > encControl->desiredInternalSampleRate ) || + ( encControl->maxInternalSampleRate < encControl->desiredInternalSampleRate ) || + ( encControl->minInternalSampleRate > encControl->maxInternalSampleRate ) ) { + SKP_assert( 0 ); + return SILK_ENC_FS_NOT_SUPPORTED; + } + if( encControl->payloadSize_ms != 10 && + encControl->payloadSize_ms != 20 && + encControl->payloadSize_ms != 40 && + encControl->payloadSize_ms != 60 ) { + SKP_assert( 0 ); + return SILK_ENC_PACKET_SIZE_NOT_SUPPORTED; + } + if( encControl->packetLossPercentage < 0 || encControl->packetLossPercentage > 100 ) { + SKP_assert( 0 ); + return SILK_ENC_INVALID_LOSS_RATE; + } + if( encControl->useDTX < 0 || encControl->useDTX > 1 ) { + SKP_assert( 0 ); + return SILK_ENC_INVALID_DTX_SETTING; + } + if( encControl->useCBR < 0 || encControl->useCBR > 1 ) { + SKP_assert( 0 ); + return SILK_ENC_INVALID_CBR_SETTING; + } + if( encControl->useInBandFEC < 0 || encControl->useInBandFEC > 1 ) { + SKP_assert( 0 ); + return SILK_ENC_INVALID_INBAND_FEC_SETTING; + } + if( encControl->nChannelsAPI < 1 || encControl->nChannelsAPI > ENCODER_NUM_CHANNELS ) { + SKP_assert( 0 ); + return SILK_ENC_INVALID_NUMBER_OF_CHANNELS_ERROR; + } + if( encControl->nChannelsInternal < 1 || encControl->nChannelsInternal > ENCODER_NUM_CHANNELS ) { + SKP_assert( 0 ); + return SILK_ENC_INVALID_NUMBER_OF_CHANNELS_ERROR; + } + if( encControl->nChannelsInternal > encControl->nChannelsAPI ) { + SKP_assert( 0 ); + return SILK_ENC_INVALID_NUMBER_OF_CHANNELS_ERROR; + } + if( encControl->complexity < 0 || encControl->complexity > 10 ) { + SKP_assert( 0 ); + return SILK_ENC_INVALID_COMPLEXITY_SETTING; + } + + return SILK_NO_ERROR; +} diff --git a/silk/silk_code_signs.c b/silk/silk_code_signs.c index d875778b8..d43801ed7 100644 --- a/silk/silk_code_signs.c +++ b/silk/silk_code_signs.c @@ -1,111 +1,111 @@ -/*********************************************************************** -Copyright (c) 2006-2011, Skype Limited. All rights reserved. -Redistribution and use in source and binary forms, with or without -modification, (subject to the limitations in the disclaimer below) -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 Skype Limited, nor the names of specific -contributors, may be used to endorse or promote products derived from -this software without specific prior written permission. -NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED -BY THIS LICENSE. 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. -***********************************************************************/ - -#include "silk_main.h" - -//#define SKP_enc_map(a) ((a) > 0 ? 1 : 0) -//#define SKP_dec_map(a) ((a) > 0 ? 1 : -1) -/* shifting avoids if-statement */ -#define SKP_enc_map(a) ( SKP_RSHIFT( (a), 15 ) + 1 ) -#define SKP_dec_map(a) ( SKP_LSHIFT( (a), 1 ) - 1 ) - -/* Encodes signs of excitation */ -void silk_encode_signs( - ec_enc *psRangeEnc, /* I/O Compressor data structure */ - const opus_int8 pulses[], /* I pulse signal */ - opus_int length, /* I length of input */ - const opus_int signalType, /* I Signal type */ - const opus_int quantOffsetType, /* I Quantization offset type */ - const opus_int sum_pulses[ MAX_NB_SHELL_BLOCKS ] /* I Sum of absolute pulses per block */ -) -{ - opus_int i, j, p; - opus_uint8 icdf[ 2 ]; - const opus_int8 *q_ptr; - const opus_uint8 *icdf_ptr; - - icdf[ 1 ] = 0; - q_ptr = pulses; - i = SKP_SMULBB( 6, SKP_ADD_LSHIFT( quantOffsetType, signalType, 1 ) ); - icdf_ptr = &silk_sign_iCDF[ i ]; - length = SKP_RSHIFT( length + SHELL_CODEC_FRAME_LENGTH/2, LOG2_SHELL_CODEC_FRAME_LENGTH ); - for( i = 0; i < length; i++ ) { - p = sum_pulses[ i ]; - if( p > 0 ) { - icdf[ 0 ] = icdf_ptr[ SKP_min( p - 1, 5 ) ]; - for( j = 0; j < SHELL_CODEC_FRAME_LENGTH; j++ ) { - if( q_ptr[ j ] != 0 ) { - ec_enc_icdf( psRangeEnc, SKP_enc_map( q_ptr[ j ]), icdf, 8 ); - } - } - } - q_ptr += SHELL_CODEC_FRAME_LENGTH; - } -} - -/* Decodes signs of excitation */ -void silk_decode_signs( - ec_dec *psRangeDec, /* I/O Compressor data structure */ - opus_int pulses[], /* I/O pulse signal */ - opus_int length, /* I length of input */ - const opus_int signalType, /* I Signal type */ - const opus_int quantOffsetType, /* I Quantization offset type */ - const opus_int sum_pulses[ MAX_NB_SHELL_BLOCKS ] /* I Sum of absolute pulses per block */ -) -{ - opus_int i, j, p; - opus_uint8 icdf[ 2 ]; - opus_int *q_ptr; - const opus_uint8 *icdf_ptr; - - icdf[ 1 ] = 0; - q_ptr = pulses; - i = SKP_SMULBB( 6, SKP_ADD_LSHIFT( quantOffsetType, signalType, 1 ) ); - icdf_ptr = &silk_sign_iCDF[ i ]; - length = SKP_RSHIFT( length + SHELL_CODEC_FRAME_LENGTH/2, LOG2_SHELL_CODEC_FRAME_LENGTH ); - for( i = 0; i < length; i++ ) { - p = sum_pulses[ i ]; - if( p > 0 ) { - icdf[ 0 ] = icdf_ptr[ SKP_min( p - 1, 5 ) ]; - for( j = 0; j < SHELL_CODEC_FRAME_LENGTH; j++ ) { - if( q_ptr[ j ] > 0 ) { - /* attach sign */ -#if 0 - /* conditional implementation */ - if( ec_dec_icdf( psRangeDec, icdf, 8 ) == 0 ) { - q_ptr[ j ] = -q_ptr[ j ]; - } -#else - /* implementation with shift, subtraction, multiplication */ - q_ptr[ j ] *= SKP_dec_map( ec_dec_icdf( psRangeDec, icdf, 8 ) ); -#endif - } - } - } - q_ptr += SHELL_CODEC_FRAME_LENGTH; - } -} +/*********************************************************************** +Copyright (c) 2006-2011, Skype Limited. All rights reserved. +Redistribution and use in source and binary forms, with or without +modification, (subject to the limitations in the disclaimer below) +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 Skype Limited, nor the names of specific +contributors, may be used to endorse or promote products derived from +this software without specific prior written permission. +NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED +BY THIS LICENSE. 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. +***********************************************************************/ + +#include "silk_main.h" + +//#define SKP_enc_map(a) ((a) > 0 ? 1 : 0) +//#define SKP_dec_map(a) ((a) > 0 ? 1 : -1) +/* shifting avoids if-statement */ +#define SKP_enc_map(a) ( SKP_RSHIFT( (a), 15 ) + 1 ) +#define SKP_dec_map(a) ( SKP_LSHIFT( (a), 1 ) - 1 ) + +/* Encodes signs of excitation */ +void silk_encode_signs( + ec_enc *psRangeEnc, /* I/O Compressor data structure */ + const opus_int8 pulses[], /* I pulse signal */ + opus_int length, /* I length of input */ + const opus_int signalType, /* I Signal type */ + const opus_int quantOffsetType, /* I Quantization offset type */ + const opus_int sum_pulses[ MAX_NB_SHELL_BLOCKS ] /* I Sum of absolute pulses per block */ +) +{ + opus_int i, j, p; + opus_uint8 icdf[ 2 ]; + const opus_int8 *q_ptr; + const opus_uint8 *icdf_ptr; + + icdf[ 1 ] = 0; + q_ptr = pulses; + i = SKP_SMULBB( 6, SKP_ADD_LSHIFT( quantOffsetType, signalType, 1 ) ); + icdf_ptr = &silk_sign_iCDF[ i ]; + length = SKP_RSHIFT( length + SHELL_CODEC_FRAME_LENGTH/2, LOG2_SHELL_CODEC_FRAME_LENGTH ); + for( i = 0; i < length; i++ ) { + p = sum_pulses[ i ]; + if( p > 0 ) { + icdf[ 0 ] = icdf_ptr[ SKP_min( p - 1, 5 ) ]; + for( j = 0; j < SHELL_CODEC_FRAME_LENGTH; j++ ) { + if( q_ptr[ j ] != 0 ) { + ec_enc_icdf( psRangeEnc, SKP_enc_map( q_ptr[ j ]), icdf, 8 ); + } + } + } + q_ptr += SHELL_CODEC_FRAME_LENGTH; + } +} + +/* Decodes signs of excitation */ +void silk_decode_signs( + ec_dec *psRangeDec, /* I/O Compressor data structure */ + opus_int pulses[], /* I/O pulse signal */ + opus_int length, /* I length of input */ + const opus_int signalType, /* I Signal type */ + const opus_int quantOffsetType, /* I Quantization offset type */ + const opus_int sum_pulses[ MAX_NB_SHELL_BLOCKS ] /* I Sum of absolute pulses per block */ +) +{ + opus_int i, j, p; + opus_uint8 icdf[ 2 ]; + opus_int *q_ptr; + const opus_uint8 *icdf_ptr; + + icdf[ 1 ] = 0; + q_ptr = pulses; + i = SKP_SMULBB( 6, SKP_ADD_LSHIFT( quantOffsetType, signalType, 1 ) ); + icdf_ptr = &silk_sign_iCDF[ i ]; + length = SKP_RSHIFT( length + SHELL_CODEC_FRAME_LENGTH/2, LOG2_SHELL_CODEC_FRAME_LENGTH ); + for( i = 0; i < length; i++ ) { + p = sum_pulses[ i ]; + if( p > 0 ) { + icdf[ 0 ] = icdf_ptr[ SKP_min( p - 1, 5 ) ]; + for( j = 0; j < SHELL_CODEC_FRAME_LENGTH; j++ ) { + if( q_ptr[ j ] > 0 ) { + /* attach sign */ +#if 0 + /* conditional implementation */ + if( ec_dec_icdf( psRangeDec, icdf, 8 ) == 0 ) { + q_ptr[ j ] = -q_ptr[ j ]; + } +#else + /* implementation with shift, subtraction, multiplication */ + q_ptr[ j ] *= SKP_dec_map( ec_dec_icdf( psRangeDec, icdf, 8 ) ); +#endif + } + } + } + q_ptr += SHELL_CODEC_FRAME_LENGTH; + } +} diff --git a/silk/silk_control.h b/silk/silk_control.h index 6e6b8c995..58f8a7ae2 100644 --- a/silk/silk_control.h +++ b/silk/silk_control.h @@ -1,126 +1,126 @@ -/*********************************************************************** -Copyright (c) 2006-2011, Skype Limited. All rights reserved. -Redistribution and use in source and binary forms, with or without -modification, (subject to the limitations in the disclaimer below) -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 Skype Limited, nor the names of specific -contributors, may be used to endorse or promote products derived from -this software without specific prior written permission. -NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED -BY THIS LICENSE. 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. -***********************************************************************/ - -#ifndef SILK_CONTROL_H -#define SILK_CONTROL_H - -#include "silk_typedef.h" - -#ifdef __cplusplus -extern "C" -{ -#endif - -/* Decoder API flags */ -#define FLAG_DECODE_NORMAL 0 -#define FLAG_PACKET_LOST 1 -#define FLAG_DECODE_LBRR 2 - -/***********************************************/ -/* Structure for controlling encoder operation */ -/***********************************************/ -typedef struct { - /* I: Number of channels; 1/2 */ - opus_int32 nChannelsAPI; - - /* I: Number of channels; 1/2 */ - opus_int32 nChannelsInternal; - - /* I: Input signal sampling rate in Hertz; 8000/12000/16000/24000/32000/44100/48000 */ - opus_int32 API_sampleRate; - - /* I: Maximum internal sampling rate in Hertz; 8000/12000/16000 */ - opus_int32 maxInternalSampleRate; - - /* I: Minimum internal sampling rate in Hertz; 8000/12000/16000 */ - opus_int32 minInternalSampleRate; - - /* I: Soft request for internal sampling rate in Hertz; 8000/12000/16000 */ - opus_int32 desiredInternalSampleRate; - - /* I: Number of samples per packet in milliseconds; 10/20/40/60 */ - opus_int payloadSize_ms; - - /* I: Bitrate during active speech in bits/second; internally limited */ - opus_int32 bitRate; - - /* I: Uplink packet loss in percent (0-100) */ - opus_int packetLossPercentage; - - /* I: Complexity mode; 0 is lowest, 10 is highest complexity */ - opus_int complexity; - - /* I: Flag to enable in-band Forward Error Correction (FEC); 0/1 */ - opus_int useInBandFEC; - - /* I: Flag to enable discontinuous transmission (DTX); 0/1 */ - opus_int useDTX; - - /* I: Flag to use constant bitrate */ - opus_int useCBR; - - /* I: Cutoff frequency of input HP filter (of zero: adaptive) */ - opus_int HP_cutoff_Hz; - - /* O: Internal sampling rate used, in Hertz; 8000/12000/16000 */ - opus_int32 internalSampleRate; - - /* O: Flag that bandwidth switching is allowed (because low voice activity) */ - opus_int allowBandwidthSwitch; - - /* O: Flag that SILK runs in WB mode without variable LP filter (use for switching between WB/SWB/FB) */ - opus_int inWBmodeWithoutVariableLP; - - /* O: Stereo width */ - opus_int stereoWidth_Q14; -} silk_EncControlStruct; - -/**************************************************************************/ -/* Structure for controlling decoder operation and reading decoder status */ -/**************************************************************************/ -typedef struct { - /* I: Number of channels; 1/2 */ - opus_int32 nChannelsAPI; - - /* I: Number of channels; 1/2 */ - opus_int32 nChannelsInternal; - - /* I: Output signal sampling rate in Hertz; 8000/12000/16000/24000/32000/44100/48000 */ - opus_int32 API_sampleRate; - - /* I: Internal sampling rate used, in Hertz; 8000/12000/16000 */ - opus_int32 internalSampleRate; - - /* I: Number of samples per packet in milliseconds; 10/20/40/60 */ - opus_int payloadSize_ms; -} silk_DecControlStruct; - -#ifdef __cplusplus -} -#endif - -#endif +/*********************************************************************** +Copyright (c) 2006-2011, Skype Limited. All rights reserved. +Redistribution and use in source and binary forms, with or without +modification, (subject to the limitations in the disclaimer below) +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 Skype Limited, nor the names of specific +contributors, may be used to endorse or promote products derived from +this software without specific prior written permission. +NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED +BY THIS LICENSE. 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. +***********************************************************************/ + +#ifndef SILK_CONTROL_H +#define SILK_CONTROL_H + +#include "silk_typedef.h" + +#ifdef __cplusplus +extern "C" +{ +#endif + +/* Decoder API flags */ +#define FLAG_DECODE_NORMAL 0 +#define FLAG_PACKET_LOST 1 +#define FLAG_DECODE_LBRR 2 + +/***********************************************/ +/* Structure for controlling encoder operation */ +/***********************************************/ +typedef struct { + /* I: Number of channels; 1/2 */ + opus_int32 nChannelsAPI; + + /* I: Number of channels; 1/2 */ + opus_int32 nChannelsInternal; + + /* I: Input signal sampling rate in Hertz; 8000/12000/16000/24000/32000/44100/48000 */ + opus_int32 API_sampleRate; + + /* I: Maximum internal sampling rate in Hertz; 8000/12000/16000 */ + opus_int32 maxInternalSampleRate; + + /* I: Minimum internal sampling rate in Hertz; 8000/12000/16000 */ + opus_int32 minInternalSampleRate; + + /* I: Soft request for internal sampling rate in Hertz; 8000/12000/16000 */ + opus_int32 desiredInternalSampleRate; + + /* I: Number of samples per packet in milliseconds; 10/20/40/60 */ + opus_int payloadSize_ms; + + /* I: Bitrate during active speech in bits/second; internally limited */ + opus_int32 bitRate; + + /* I: Uplink packet loss in percent (0-100) */ + opus_int packetLossPercentage; + + /* I: Complexity mode; 0 is lowest, 10 is highest complexity */ + opus_int complexity; + + /* I: Flag to enable in-band Forward Error Correction (FEC); 0/1 */ + opus_int useInBandFEC; + + /* I: Flag to enable discontinuous transmission (DTX); 0/1 */ + opus_int useDTX; + + /* I: Flag to use constant bitrate */ + opus_int useCBR; + + /* I: Cutoff frequency of input HP filter (of zero: adaptive) */ + opus_int HP_cutoff_Hz; + + /* O: Internal sampling rate used, in Hertz; 8000/12000/16000 */ + opus_int32 internalSampleRate; + + /* O: Flag that bandwidth switching is allowed (because low voice activity) */ + opus_int allowBandwidthSwitch; + + /* O: Flag that SILK runs in WB mode without variable LP filter (use for switching between WB/SWB/FB) */ + opus_int inWBmodeWithoutVariableLP; + + /* O: Stereo width */ + opus_int stereoWidth_Q14; +} silk_EncControlStruct; + +/**************************************************************************/ +/* Structure for controlling decoder operation and reading decoder status */ +/**************************************************************************/ +typedef struct { + /* I: Number of channels; 1/2 */ + opus_int32 nChannelsAPI; + + /* I: Number of channels; 1/2 */ + opus_int32 nChannelsInternal; + + /* I: Output signal sampling rate in Hertz; 8000/12000/16000/24000/32000/44100/48000 */ + opus_int32 API_sampleRate; + + /* I: Internal sampling rate used, in Hertz; 8000/12000/16000 */ + opus_int32 internalSampleRate; + + /* I: Number of samples per packet in milliseconds; 10/20/40/60 */ + opus_int payloadSize_ms; +} silk_DecControlStruct; + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/silk/silk_control_SNR.c b/silk/silk_control_SNR.c index 686de96cb..f30d31887 100644 --- a/silk/silk_control_SNR.c +++ b/silk/silk_control_SNR.c @@ -1,77 +1,77 @@ -/*********************************************************************** -Copyright (c) 2006-2011, Skype Limited. All rights reserved. -Redistribution and use in source and binary forms, with or without -modification, (subject to the limitations in the disclaimer below) -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 Skype Limited, nor the names of specific -contributors, may be used to endorse or promote products derived from -this software without specific prior written permission. -NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED -BY THIS LICENSE. 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. -***********************************************************************/ - -#include "silk_main.h" -#include "silk_tuning_parameters.h" - -/* Control SNR of redidual quantizer */ -opus_int silk_control_SNR( - silk_encoder_state *psEncC, /* I/O Pointer to Silk encoder state */ - opus_int32 TargetRate_bps /* I Target max bitrate (bps) */ -) -{ - opus_int k, ret = SILK_NO_ERROR; - opus_int32 frac_Q6; - const opus_int32 *rateTable; - - /* Set bitrate/coding quality */ - TargetRate_bps = SKP_LIMIT( TargetRate_bps, MIN_TARGET_RATE_BPS, MAX_TARGET_RATE_BPS ); - if( TargetRate_bps != psEncC->TargetRate_bps ) { - psEncC->TargetRate_bps = TargetRate_bps; - - /* If new TargetRate_bps, translate to SNR_dB value */ - if( psEncC->fs_kHz == 8 ) { - rateTable = silk_TargetRate_table_NB; - } else if( psEncC->fs_kHz == 12 ) { - rateTable = silk_TargetRate_table_MB; - } else { - rateTable = silk_TargetRate_table_WB; - } - - /* Reduce bitrate for 10 ms modes in these calculations */ - if( psEncC->nb_subfr == 2 ) { - TargetRate_bps -= REDUCE_BITRATE_10_MS_BPS; - } - - /* Find bitrate interval in table and interpolate */ - for( k = 1; k < TARGET_RATE_TAB_SZ; k++ ) { - if( TargetRate_bps <= rateTable[ k ] ) { - frac_Q6 = SKP_DIV32( SKP_LSHIFT( TargetRate_bps - rateTable[ k - 1 ], 6 ), - rateTable[ k ] - rateTable[ k - 1 ] ); - psEncC->SNR_dB_Q7 = SKP_LSHIFT( silk_SNR_table_Q1[ k - 1 ], 6 ) + SKP_MUL( frac_Q6, silk_SNR_table_Q1[ k ] - silk_SNR_table_Q1[ k - 1 ] ); - break; - } - } - - /* Reduce coding quality whenever LBRR is enabled, to free up some bits */ - if( psEncC->LBRR_enabled ) { - psEncC->SNR_dB_Q7 = SKP_SMLABB( psEncC->SNR_dB_Q7, 12 - psEncC->LBRR_GainIncreases, SILK_FIX_CONST( -0.25, 7 ) ); - } - } - - return ret; -} +/*********************************************************************** +Copyright (c) 2006-2011, Skype Limited. All rights reserved. +Redistribution and use in source and binary forms, with or without +modification, (subject to the limitations in the disclaimer below) +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 Skype Limited, nor the names of specific +contributors, may be used to endorse or promote products derived from +this software without specific prior written permission. +NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED +BY THIS LICENSE. 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. +***********************************************************************/ + +#include "silk_main.h" +#include "silk_tuning_parameters.h" + +/* Control SNR of redidual quantizer */ +opus_int silk_control_SNR( + silk_encoder_state *psEncC, /* I/O Pointer to Silk encoder state */ + opus_int32 TargetRate_bps /* I Target max bitrate (bps) */ +) +{ + opus_int k, ret = SILK_NO_ERROR; + opus_int32 frac_Q6; + const opus_int32 *rateTable; + + /* Set bitrate/coding quality */ + TargetRate_bps = SKP_LIMIT( TargetRate_bps, MIN_TARGET_RATE_BPS, MAX_TARGET_RATE_BPS ); + if( TargetRate_bps != psEncC->TargetRate_bps ) { + psEncC->TargetRate_bps = TargetRate_bps; + + /* If new TargetRate_bps, translate to SNR_dB value */ + if( psEncC->fs_kHz == 8 ) { + rateTable = silk_TargetRate_table_NB; + } else if( psEncC->fs_kHz == 12 ) { + rateTable = silk_TargetRate_table_MB; + } else { + rateTable = silk_TargetRate_table_WB; + } + + /* Reduce bitrate for 10 ms modes in these calculations */ + if( psEncC->nb_subfr == 2 ) { + TargetRate_bps -= REDUCE_BITRATE_10_MS_BPS; + } + + /* Find bitrate interval in table and interpolate */ + for( k = 1; k < TARGET_RATE_TAB_SZ; k++ ) { + if( TargetRate_bps <= rateTable[ k ] ) { + frac_Q6 = SKP_DIV32( SKP_LSHIFT( TargetRate_bps - rateTable[ k - 1 ], 6 ), + rateTable[ k ] - rateTable[ k - 1 ] ); + psEncC->SNR_dB_Q7 = SKP_LSHIFT( silk_SNR_table_Q1[ k - 1 ], 6 ) + SKP_MUL( frac_Q6, silk_SNR_table_Q1[ k ] - silk_SNR_table_Q1[ k - 1 ] ); + break; + } + } + + /* Reduce coding quality whenever LBRR is enabled, to free up some bits */ + if( psEncC->LBRR_enabled ) { + psEncC->SNR_dB_Q7 = SKP_SMLABB( psEncC->SNR_dB_Q7, 12 - psEncC->LBRR_GainIncreases, SILK_FIX_CONST( -0.25, 7 ) ); + } + } + + return ret; +} diff --git a/silk/silk_control_audio_bandwidth.c b/silk/silk_control_audio_bandwidth.c index 92f965e09..11e536df0 100644 --- a/silk/silk_control_audio_bandwidth.c +++ b/silk/silk_control_audio_bandwidth.c @@ -1,106 +1,106 @@ -/*********************************************************************** -Copyright (c) 2006-2011, Skype Limited. All rights reserved. -Redistribution and use in source and binary forms, with or without -modification, (subject to the limitations in the disclaimer below) -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 Skype Limited, nor the names of specific -contributors, may be used to endorse or promote products derived from -this software without specific prior written permission. -NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED -BY THIS LICENSE. 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. -***********************************************************************/ - -#include "silk_main.h" -#include "silk_tuning_parameters.h" - -/* Control internal sampling rate */ -opus_int silk_control_audio_bandwidth( - silk_encoder_state *psEncC /* I/O Pointer to Silk encoder state */ -) -{ - opus_int fs_kHz; - opus_int32 fs_Hz; - - fs_kHz = psEncC->fs_kHz; - fs_Hz = SKP_SMULBB( fs_kHz, 1000 ); - if( fs_Hz == 0 ) { - /* Encoder has just been initialized */ - fs_Hz = SKP_min( psEncC->desiredInternal_fs_Hz, psEncC->API_fs_Hz ); - fs_kHz = SKP_DIV32_16( fs_Hz, 1000 ); - } else if( fs_Hz > psEncC->API_fs_Hz || fs_Hz > psEncC->maxInternal_fs_Hz || fs_Hz < psEncC->minInternal_fs_Hz ) { - /* Make sure internal rate is not higher than external rate or maximum allowed, or lower than minimum allowed */ - fs_Hz = psEncC->API_fs_Hz; - fs_Hz = SKP_min( fs_Hz, psEncC->maxInternal_fs_Hz ); - fs_Hz = SKP_max( fs_Hz, psEncC->minInternal_fs_Hz ); - fs_kHz = SKP_DIV32_16( fs_Hz, 1000 ); - } else { - /* State machine for the internal sampling rate switching */ - if( psEncC->sLP.transition_frame_no >= TRANSITION_FRAMES ) { - /* Stop transition phase */ - psEncC->sLP.mode = 0; - } - if( psEncC->allow_bandwidth_switch ) { - /* Check if we should switch down */ - if( SKP_SMULBB( psEncC->fs_kHz, 1000 ) > psEncC->desiredInternal_fs_Hz ) - { - /* Switch down */ - if( psEncC->sLP.mode == 0 ) { - /* New transition */ - psEncC->sLP.transition_frame_no = TRANSITION_FRAMES; - - /* Reset transition filter state */ - SKP_memset( psEncC->sLP.In_LP_State, 0, sizeof( psEncC->sLP.In_LP_State ) ); - } - if( psEncC->sLP.transition_frame_no <= 0 ) { - /* Stop transition phase */ - psEncC->sLP.mode = 0; - - /* Switch to a lower sample frequency */ - fs_kHz = psEncC->fs_kHz == 16 ? 12 : 8; - } else { - /* Direction: down (at double speed) */ - psEncC->sLP.mode = -2; - } - } - else - /* Check if we should switch up */ - if( SKP_SMULBB( psEncC->fs_kHz, 1000 ) < psEncC->desiredInternal_fs_Hz ) - { - /* Switch up */ - if( psEncC->sLP.mode == 0 ) { - /* Switch to a higher sample frequency */ - fs_kHz = psEncC->fs_kHz == 8 ? 12 : 16; - - /* New transition */ - psEncC->sLP.transition_frame_no = 0; - - /* Reset transition filter state */ - SKP_memset( psEncC->sLP.In_LP_State, 0, sizeof( psEncC->sLP.In_LP_State ) ); - } - /* Direction: up */ - psEncC->sLP.mode = 1; - } - } - } - -#ifdef FORCE_INTERNAL_FS_KHZ - fs_kHz = FORCE_INTERNAL_FS_KHZ; -#endif - - return fs_kHz; -} +/*********************************************************************** +Copyright (c) 2006-2011, Skype Limited. All rights reserved. +Redistribution and use in source and binary forms, with or without +modification, (subject to the limitations in the disclaimer below) +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 Skype Limited, nor the names of specific +contributors, may be used to endorse or promote products derived from +this software without specific prior written permission. +NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED +BY THIS LICENSE. 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. +***********************************************************************/ + +#include "silk_main.h" +#include "silk_tuning_parameters.h" + +/* Control internal sampling rate */ +opus_int silk_control_audio_bandwidth( + silk_encoder_state *psEncC /* I/O Pointer to Silk encoder state */ +) +{ + opus_int fs_kHz; + opus_int32 fs_Hz; + + fs_kHz = psEncC->fs_kHz; + fs_Hz = SKP_SMULBB( fs_kHz, 1000 ); + if( fs_Hz == 0 ) { + /* Encoder has just been initialized */ + fs_Hz = SKP_min( psEncC->desiredInternal_fs_Hz, psEncC->API_fs_Hz ); + fs_kHz = SKP_DIV32_16( fs_Hz, 1000 ); + } else if( fs_Hz > psEncC->API_fs_Hz || fs_Hz > psEncC->maxInternal_fs_Hz || fs_Hz < psEncC->minInternal_fs_Hz ) { + /* Make sure internal rate is not higher than external rate or maximum allowed, or lower than minimum allowed */ + fs_Hz = psEncC->API_fs_Hz; + fs_Hz = SKP_min( fs_Hz, psEncC->maxInternal_fs_Hz ); + fs_Hz = SKP_max( fs_Hz, psEncC->minInternal_fs_Hz ); + fs_kHz = SKP_DIV32_16( fs_Hz, 1000 ); + } else { + /* State machine for the internal sampling rate switching */ + if( psEncC->sLP.transition_frame_no >= TRANSITION_FRAMES ) { + /* Stop transition phase */ + psEncC->sLP.mode = 0; + } + if( psEncC->allow_bandwidth_switch ) { + /* Check if we should switch down */ + if( SKP_SMULBB( psEncC->fs_kHz, 1000 ) > psEncC->desiredInternal_fs_Hz ) + { + /* Switch down */ + if( psEncC->sLP.mode == 0 ) { + /* New transition */ + psEncC->sLP.transition_frame_no = TRANSITION_FRAMES; + + /* Reset transition filter state */ + SKP_memset( psEncC->sLP.In_LP_State, 0, sizeof( psEncC->sLP.In_LP_State ) ); + } + if( psEncC->sLP.transition_frame_no <= 0 ) { + /* Stop transition phase */ + psEncC->sLP.mode = 0; + + /* Switch to a lower sample frequency */ + fs_kHz = psEncC->fs_kHz == 16 ? 12 : 8; + } else { + /* Direction: down (at double speed) */ + psEncC->sLP.mode = -2; + } + } + else + /* Check if we should switch up */ + if( SKP_SMULBB( psEncC->fs_kHz, 1000 ) < psEncC->desiredInternal_fs_Hz ) + { + /* Switch up */ + if( psEncC->sLP.mode == 0 ) { + /* Switch to a higher sample frequency */ + fs_kHz = psEncC->fs_kHz == 8 ? 12 : 16; + + /* New transition */ + psEncC->sLP.transition_frame_no = 0; + + /* Reset transition filter state */ + SKP_memset( psEncC->sLP.In_LP_State, 0, sizeof( psEncC->sLP.In_LP_State ) ); + } + /* Direction: up */ + psEncC->sLP.mode = 1; + } + } + } + +#ifdef FORCE_INTERNAL_FS_KHZ + fs_kHz = FORCE_INTERNAL_FS_KHZ; +#endif + + return fs_kHz; +} diff --git a/silk/silk_control_codec.c b/silk/silk_control_codec.c index 8e261d39b..0ddfac9aa 100644 --- a/silk/silk_control_codec.c +++ b/silk/silk_control_codec.c @@ -1,421 +1,421 @@ -/*********************************************************************** -Copyright (c) 2006-2011, Skype Limited. All rights reserved. -Redistribution and use in source and binary forms, with or without -modification, (subject to the limitations in the disclaimer below) -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 Skype Limited, nor the names of specific -contributors, may be used to endorse or promote products derived from -this software without specific prior written permission. -NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED -BY THIS LICENSE. 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 -#ifdef FIXED_POINT -#include "silk_main_FIX.h" -#define silk_encoder_state_Fxx silk_encoder_state_FIX -#else -#include "silk_main_FLP.h" -#define silk_encoder_state_Fxx silk_encoder_state_FLP -#endif -#include "silk_tuning_parameters.h" - -opus_int silk_setup_resamplers( - silk_encoder_state_Fxx *psEnc, /* I/O */ - opus_int fs_kHz /* I */ -); - -opus_int silk_setup_fs( - silk_encoder_state_Fxx *psEnc, /* I/O */ - opus_int fs_kHz, /* I */ - opus_int PacketSize_ms /* I */ -); - -opus_int silk_setup_complexity( - silk_encoder_state *psEncC, /* I/O */ - opus_int Complexity /* I */ -); - -SKP_INLINE opus_int silk_setup_LBRR( - silk_encoder_state *psEncC, /* I/O */ - const opus_int32 TargetRate_bps /* I */ -); - - -/* Control encoder */ -opus_int silk_control_encoder( - silk_encoder_state_Fxx *psEnc, /* I/O Pointer to Silk encoder state */ - silk_EncControlStruct *encControl, /* I: Control structure */ - const opus_int32 TargetRate_bps, /* I Target max bitrate (bps) */ - const opus_int allow_bw_switch, /* I Flag to allow switching audio bandwidth */ - const opus_int channelNb /* I Channel number */ -) -{ - opus_int fs_kHz, ret = 0; - - psEnc->sCmn.useDTX = encControl->useDTX; - psEnc->sCmn.useCBR = encControl->useCBR; - psEnc->sCmn.API_fs_Hz = encControl->API_sampleRate; - psEnc->sCmn.maxInternal_fs_Hz = encControl->maxInternalSampleRate; - psEnc->sCmn.minInternal_fs_Hz = encControl->minInternalSampleRate; - psEnc->sCmn.desiredInternal_fs_Hz = encControl->desiredInternalSampleRate; - psEnc->sCmn.useInBandFEC = encControl->useInBandFEC; - psEnc->sCmn.nChannelsAPI = encControl->nChannelsAPI; - psEnc->sCmn.nChannelsInternal = encControl->nChannelsInternal; - psEnc->sCmn.allow_bandwidth_switch = allow_bw_switch; - psEnc->sCmn.channelNb = channelNb; - - if( psEnc->sCmn.controlled_since_last_payload != 0 && psEnc->sCmn.prefillFlag == 0 ) { - if( psEnc->sCmn.API_fs_Hz != psEnc->sCmn.prev_API_fs_Hz && psEnc->sCmn.fs_kHz > 0 ) { - /* Change in API sampling rate in the middle of encoding a packet */ - ret += silk_setup_resamplers( psEnc, psEnc->sCmn.fs_kHz ); - } - return ret; - } - - /* Beyond this point we know that there are no previously coded frames in the payload buffer */ - - /********************************************/ - /* Determine internal sampling rate */ - /********************************************/ - fs_kHz = silk_control_audio_bandwidth( &psEnc->sCmn ); - - /********************************************/ - /* Prepare resampler and buffered data */ - /********************************************/ - ret += silk_setup_resamplers( psEnc, fs_kHz ); - - /********************************************/ - /* Set internal sampling frequency */ - /********************************************/ - ret += silk_setup_fs( psEnc, fs_kHz, encControl->payloadSize_ms ); - - /********************************************/ - /* Set encoding complexity */ - /********************************************/ - ret += silk_setup_complexity( &psEnc->sCmn, encControl->complexity ); - - /********************************************/ - /* Set packet loss rate measured by farend */ - /********************************************/ - psEnc->sCmn.PacketLoss_perc = encControl->packetLossPercentage; - - /********************************************/ - /* Set LBRR usage */ - /********************************************/ - ret += silk_setup_LBRR( &psEnc->sCmn, TargetRate_bps ); - - psEnc->sCmn.controlled_since_last_payload = 1; - - return ret; -} - -opus_int silk_setup_resamplers( - silk_encoder_state_Fxx *psEnc, /* I/O */ - opus_int fs_kHz /* I */ -) -{ - opus_int ret = SILK_NO_ERROR; - opus_int32 nSamples_temp; - - if( psEnc->sCmn.fs_kHz != fs_kHz || psEnc->sCmn.prev_API_fs_Hz != psEnc->sCmn.API_fs_Hz ) - { - if( psEnc->sCmn.fs_kHz == 0 ) { - /* Initialize the resampler for enc_API.c preparing resampling from API_fs_Hz to fs_kHz */ - ret += silk_resampler_init( &psEnc->sCmn.resampler_state, psEnc->sCmn.API_fs_Hz, fs_kHz * 1000 ); - } else { - /* Allocate worst case space for temporary upsampling, 8 to 48 kHz, so a factor 6 */ - opus_int16 x_buf_API_fs_Hz[ ( 2 * MAX_FRAME_LENGTH_MS + LA_SHAPE_MS ) * MAX_API_FS_KHZ ]; -#ifdef FIXED_POINT - opus_int16 *x_bufFIX = psEnc->x_buf; -#else - opus_int16 x_bufFIX[ 2 * MAX_FRAME_LENGTH + LA_SHAPE_MAX ]; -#endif - - nSamples_temp = SKP_LSHIFT( psEnc->sCmn.frame_length, 1 ) + LA_SHAPE_MS * psEnc->sCmn.fs_kHz; - -#ifndef FIXED_POINT - SKP_float2short_array( x_bufFIX, psEnc->x_buf, nSamples_temp ); -#endif - - if( SKP_SMULBB( fs_kHz, 1000 ) < psEnc->sCmn.API_fs_Hz && psEnc->sCmn.fs_kHz != 0 ) { - /* Resample buffered data in x_buf to API_fs_Hz */ - - silk_resampler_state_struct temp_resampler_state; - - /* Initialize resampler for temporary resampling of x_buf data to API_fs_Hz */ - ret += silk_resampler_init( &temp_resampler_state, SKP_SMULBB( psEnc->sCmn.fs_kHz, 1000 ), psEnc->sCmn.API_fs_Hz ); - - /* Temporary resampling of x_buf data to API_fs_Hz */ - ret += silk_resampler( &temp_resampler_state, x_buf_API_fs_Hz, x_bufFIX, nSamples_temp ); - - /* Calculate number of samples that has been temporarily upsampled */ - nSamples_temp = SKP_DIV32_16( nSamples_temp * psEnc->sCmn.API_fs_Hz, SKP_SMULBB( psEnc->sCmn.fs_kHz, 1000 ) ); - - /* Initialize the resampler for enc_API.c preparing resampling from API_fs_Hz to fs_kHz */ - ret += silk_resampler_init( &psEnc->sCmn.resampler_state, psEnc->sCmn.API_fs_Hz, SKP_SMULBB( fs_kHz, 1000 ) ); - - } else { - /* Copy data */ - SKP_memcpy( x_buf_API_fs_Hz, x_bufFIX, nSamples_temp * sizeof( opus_int16 ) ); - } - - if( 1000 * fs_kHz != psEnc->sCmn.API_fs_Hz ) { - /* Correct resampler state (unless resampling by a factor 1) by resampling buffered data from API_fs_Hz to fs_kHz */ - ret += silk_resampler( &psEnc->sCmn.resampler_state, x_bufFIX, x_buf_API_fs_Hz, nSamples_temp ); - } -#ifndef FIXED_POINT - SKP_short2float_array( psEnc->x_buf, x_bufFIX, ( 2 * MAX_FRAME_LENGTH_MS + LA_SHAPE_MS ) * fs_kHz ); -#endif - } - } - - psEnc->sCmn.prev_API_fs_Hz = psEnc->sCmn.API_fs_Hz; - - return ret; -} - -opus_int silk_setup_fs( - silk_encoder_state_Fxx *psEnc, /* I/O */ - opus_int fs_kHz, /* I */ - opus_int PacketSize_ms /* I */ -) -{ - opus_int ret = SILK_NO_ERROR; - - /* Set packet size */ - if( PacketSize_ms != psEnc->sCmn.PacketSize_ms ) { - if( ( PacketSize_ms != 10 ) && - ( PacketSize_ms != 20 ) && - ( PacketSize_ms != 40 ) && - ( PacketSize_ms != 60 ) ) { - ret = SILK_ENC_PACKET_SIZE_NOT_SUPPORTED; - } - if( PacketSize_ms <= 10 ) { - psEnc->sCmn.nFramesPerPacket = 1; - psEnc->sCmn.nb_subfr = PacketSize_ms == 10 ? 2 : 1; - psEnc->sCmn.frame_length = SKP_SMULBB( PacketSize_ms, fs_kHz ); - psEnc->sCmn.pitch_LPC_win_length = SKP_SMULBB( FIND_PITCH_LPC_WIN_MS_2_SF, fs_kHz ); - if( psEnc->sCmn.fs_kHz == 8 ) { - psEnc->sCmn.pitch_contour_iCDF = silk_pitch_contour_10_ms_NB_iCDF; - } else { - psEnc->sCmn.pitch_contour_iCDF = silk_pitch_contour_10_ms_iCDF; - } - } else { - psEnc->sCmn.nFramesPerPacket = SKP_DIV32_16( PacketSize_ms, MAX_FRAME_LENGTH_MS ); - psEnc->sCmn.nb_subfr = MAX_NB_SUBFR; - psEnc->sCmn.frame_length = SKP_SMULBB( 20, fs_kHz ); - psEnc->sCmn.pitch_LPC_win_length = SKP_SMULBB( FIND_PITCH_LPC_WIN_MS, fs_kHz ); - if( psEnc->sCmn.fs_kHz == 8 ) { - psEnc->sCmn.pitch_contour_iCDF = silk_pitch_contour_NB_iCDF; - } else { - psEnc->sCmn.pitch_contour_iCDF = silk_pitch_contour_iCDF; - } - } - psEnc->sCmn.PacketSize_ms = PacketSize_ms; - psEnc->sCmn.TargetRate_bps = 0; /* trigger new SNR computation */ - } - - /* Set internal sampling frequency */ - SKP_assert( fs_kHz == 8 || fs_kHz == 12 || fs_kHz == 16 ); - SKP_assert( psEnc->sCmn.nb_subfr == 2 || psEnc->sCmn.nb_subfr == 4 ); - if( psEnc->sCmn.fs_kHz != fs_kHz ) { - /* reset part of the state */ -#ifdef FIXED_POINT - SKP_memset( &psEnc->sShape, 0, sizeof( silk_shape_state_FIX ) ); - SKP_memset( &psEnc->sPrefilt, 0, sizeof( silk_prefilter_state_FIX ) ); -#else - SKP_memset( &psEnc->sShape, 0, sizeof( silk_shape_state_FLP ) ); - SKP_memset( &psEnc->sPrefilt, 0, sizeof( silk_prefilter_state_FLP ) ); -#endif - SKP_memset( &psEnc->sCmn.sNSQ, 0, sizeof( silk_nsq_state ) ); - SKP_memset( psEnc->sCmn.prev_NLSFq_Q15, 0, sizeof( psEnc->sCmn.prev_NLSFq_Q15 ) ); - SKP_memset( &psEnc->sCmn.sLP.In_LP_State, 0, sizeof( psEnc->sCmn.sLP.In_LP_State ) ); - psEnc->sCmn.inputBufIx = 0; - psEnc->sCmn.nFramesEncoded = 0; - psEnc->sCmn.TargetRate_bps = 0; /* trigger new SNR computation */ - - /* Initialize non-zero parameters */ - psEnc->sCmn.prevLag = 100; - psEnc->sCmn.first_frame_after_reset = 1; - psEnc->sPrefilt.lagPrev = 100; - psEnc->sShape.LastGainIndex = 10; - psEnc->sCmn.sNSQ.lagPrev = 100; - psEnc->sCmn.sNSQ.prev_inv_gain_Q16 = 65536; - - psEnc->sCmn.fs_kHz = fs_kHz; - if( psEnc->sCmn.fs_kHz == 8 ) { - if( psEnc->sCmn.nb_subfr == MAX_NB_SUBFR ) { - psEnc->sCmn.pitch_contour_iCDF = silk_pitch_contour_NB_iCDF; - } else { - psEnc->sCmn.pitch_contour_iCDF = silk_pitch_contour_10_ms_NB_iCDF; - } - } else { - if( psEnc->sCmn.nb_subfr == MAX_NB_SUBFR ) { - psEnc->sCmn.pitch_contour_iCDF = silk_pitch_contour_iCDF; - } else { - psEnc->sCmn.pitch_contour_iCDF = silk_pitch_contour_10_ms_iCDF; - } - } - if( psEnc->sCmn.fs_kHz == 8 || psEnc->sCmn.fs_kHz == 12 ) { - psEnc->sCmn.predictLPCOrder = MIN_LPC_ORDER; - psEnc->sCmn.psNLSF_CB = &silk_NLSF_CB_NB_MB; - } else { - psEnc->sCmn.predictLPCOrder = MAX_LPC_ORDER; - psEnc->sCmn.psNLSF_CB = &silk_NLSF_CB_WB; - } - psEnc->sCmn.subfr_length = SUB_FRAME_LENGTH_MS * fs_kHz; - psEnc->sCmn.frame_length = SKP_SMULBB( psEnc->sCmn.subfr_length, psEnc->sCmn.nb_subfr ); - psEnc->sCmn.ltp_mem_length = SKP_SMULBB( LTP_MEM_LENGTH_MS, fs_kHz ); - psEnc->sCmn.la_pitch = SKP_SMULBB( LA_PITCH_MS, fs_kHz ); - psEnc->sCmn.max_pitch_lag = SKP_SMULBB( 18, fs_kHz ); - if( psEnc->sCmn.nb_subfr == MAX_NB_SUBFR ) { - psEnc->sCmn.pitch_LPC_win_length = SKP_SMULBB( FIND_PITCH_LPC_WIN_MS, fs_kHz ); - } else { - psEnc->sCmn.pitch_LPC_win_length = SKP_SMULBB( FIND_PITCH_LPC_WIN_MS_2_SF, fs_kHz ); - } - if( psEnc->sCmn.fs_kHz == 16 ) { - psEnc->sCmn.mu_LTP_Q9 = SILK_FIX_CONST( MU_LTP_QUANT_WB, 9 ); - psEnc->sCmn.pitch_lag_low_bits_iCDF = silk_uniform8_iCDF; - } else if( psEnc->sCmn.fs_kHz == 12 ) { - psEnc->sCmn.mu_LTP_Q9 = SILK_FIX_CONST( MU_LTP_QUANT_MB, 9 ); - psEnc->sCmn.pitch_lag_low_bits_iCDF = silk_uniform6_iCDF; - } else { - psEnc->sCmn.mu_LTP_Q9 = SILK_FIX_CONST( MU_LTP_QUANT_NB, 9 ); - psEnc->sCmn.pitch_lag_low_bits_iCDF = silk_uniform4_iCDF; - } - } - - /* Check that settings are valid */ - SKP_assert( ( psEnc->sCmn.subfr_length * psEnc->sCmn.nb_subfr ) == psEnc->sCmn.frame_length ); - - return ret; -} - -opus_int silk_setup_complexity( - silk_encoder_state *psEncC, /* I/O */ - opus_int Complexity /* I */ -) -{ - opus_int ret = 0; - - /* Set encoding complexity */ - SKP_assert( Complexity >= 0 && Complexity <= 10 ); - if( Complexity < 2 ) { - psEncC->pitchEstimationComplexity = SILK_PE_MIN_COMPLEX; - psEncC->pitchEstimationThreshold_Q16 = SILK_FIX_CONST( 0.8, 16 ); - psEncC->pitchEstimationLPCOrder = 6; - psEncC->shapingLPCOrder = 8; - psEncC->la_shape = 3 * psEncC->fs_kHz; - psEncC->nStatesDelayedDecision = 1; - psEncC->useInterpolatedNLSFs = 0; - psEncC->LTPQuantLowComplexity = 1; - psEncC->NLSF_MSVQ_Survivors = 2; - psEncC->warping_Q16 = 0; - } else if( Complexity < 4 ) { - psEncC->pitchEstimationComplexity = SILK_PE_MID_COMPLEX; - psEncC->pitchEstimationThreshold_Q16 = SILK_FIX_CONST( 0.76, 16 ); - psEncC->pitchEstimationLPCOrder = 8; - psEncC->shapingLPCOrder = 10; - psEncC->la_shape = 5 * psEncC->fs_kHz; - psEncC->nStatesDelayedDecision = 1; - psEncC->useInterpolatedNLSFs = 1; - psEncC->LTPQuantLowComplexity = 0; - psEncC->NLSF_MSVQ_Survivors = 4; - psEncC->warping_Q16 = 0; - } else if( Complexity < 6 ) { - psEncC->pitchEstimationComplexity = SILK_PE_MID_COMPLEX; - psEncC->pitchEstimationThreshold_Q16 = SILK_FIX_CONST( 0.74, 16 ); - psEncC->pitchEstimationLPCOrder = 10; - psEncC->shapingLPCOrder = 12; - psEncC->la_shape = 5 * psEncC->fs_kHz; - psEncC->nStatesDelayedDecision = 2; - psEncC->useInterpolatedNLSFs = 0; - psEncC->LTPQuantLowComplexity = 0; - psEncC->NLSF_MSVQ_Survivors = 8; - psEncC->warping_Q16 = psEncC->fs_kHz * SILK_FIX_CONST( WARPING_MULTIPLIER, 16 ); - } else if( Complexity < 8 ) { - psEncC->pitchEstimationComplexity = SILK_PE_MID_COMPLEX; - psEncC->pitchEstimationThreshold_Q16 = SILK_FIX_CONST( 0.72, 16 ); - psEncC->pitchEstimationLPCOrder = 12; - psEncC->shapingLPCOrder = 14; - psEncC->la_shape = 5 * psEncC->fs_kHz; - psEncC->nStatesDelayedDecision = 3; - psEncC->useInterpolatedNLSFs = 0; - psEncC->LTPQuantLowComplexity = 0; - psEncC->NLSF_MSVQ_Survivors = 16; - psEncC->warping_Q16 = psEncC->fs_kHz * SILK_FIX_CONST( WARPING_MULTIPLIER, 16 ); - } else { - psEncC->pitchEstimationComplexity = SILK_PE_MAX_COMPLEX; - psEncC->pitchEstimationThreshold_Q16 = SILK_FIX_CONST( 0.7, 16 ); - psEncC->pitchEstimationLPCOrder = 16; - psEncC->shapingLPCOrder = 16; - psEncC->la_shape = 5 * psEncC->fs_kHz; - psEncC->nStatesDelayedDecision = MAX_DEL_DEC_STATES; - psEncC->useInterpolatedNLSFs = 1; - psEncC->LTPQuantLowComplexity = 0; - psEncC->NLSF_MSVQ_Survivors = 32; - psEncC->warping_Q16 = psEncC->fs_kHz * SILK_FIX_CONST( WARPING_MULTIPLIER, 16 ); - } - - /* Do not allow higher pitch estimation LPC order than predict LPC order */ - psEncC->pitchEstimationLPCOrder = SKP_min_int( psEncC->pitchEstimationLPCOrder, psEncC->predictLPCOrder ); - psEncC->shapeWinLength = SUB_FRAME_LENGTH_MS * psEncC->fs_kHz + 2 * psEncC->la_shape; - psEncC->Complexity = Complexity; - - SKP_assert( psEncC->pitchEstimationLPCOrder <= MAX_FIND_PITCH_LPC_ORDER ); - SKP_assert( psEncC->shapingLPCOrder <= MAX_SHAPE_LPC_ORDER ); - SKP_assert( psEncC->nStatesDelayedDecision <= MAX_DEL_DEC_STATES ); - SKP_assert( psEncC->warping_Q16 <= 32767 ); - SKP_assert( psEncC->la_shape <= LA_SHAPE_MAX ); - SKP_assert( psEncC->shapeWinLength <= SHAPE_LPC_WIN_MAX ); - SKP_assert( psEncC->NLSF_MSVQ_Survivors <= NLSF_VQ_MAX_SURVIVORS ); - - return ret; -} - -SKP_INLINE opus_int silk_setup_LBRR( - silk_encoder_state *psEncC, /* I/O */ - const opus_int32 TargetRate_bps /* I */ -) -{ - opus_int ret = SILK_NO_ERROR; - opus_int32 LBRR_rate_thres_bps; - - psEncC->LBRR_enabled = 0; - if( psEncC->useInBandFEC && psEncC->PacketLoss_perc > 0 ) { - if( psEncC->fs_kHz == 8 ) { - LBRR_rate_thres_bps = LBRR_NB_MIN_RATE_BPS; - } else if( psEncC->fs_kHz == 12 ) { - LBRR_rate_thres_bps = LBRR_MB_MIN_RATE_BPS; - } else { - LBRR_rate_thres_bps = LBRR_WB_MIN_RATE_BPS; - } - LBRR_rate_thres_bps = SKP_SMULWB( SKP_MUL( LBRR_rate_thres_bps, 125 - SKP_min( psEncC->PacketLoss_perc, 25 ) ), SILK_FIX_CONST( 0.01, 16 ) ); - - if( TargetRate_bps > LBRR_rate_thres_bps ) { - /* Set gain increase for coding LBRR excitation */ - psEncC->LBRR_enabled = 1; - psEncC->LBRR_GainIncreases = SKP_max_int( 7 - SKP_SMULWB( psEncC->PacketLoss_perc, SILK_FIX_CONST( 0.4, 16 ) ), 2 ); - } - } - - return ret; -} +/*********************************************************************** +Copyright (c) 2006-2011, Skype Limited. All rights reserved. +Redistribution and use in source and binary forms, with or without +modification, (subject to the limitations in the disclaimer below) +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 Skype Limited, nor the names of specific +contributors, may be used to endorse or promote products derived from +this software without specific prior written permission. +NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED +BY THIS LICENSE. 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 +#ifdef FIXED_POINT +#include "silk_main_FIX.h" +#define silk_encoder_state_Fxx silk_encoder_state_FIX +#else +#include "silk_main_FLP.h" +#define silk_encoder_state_Fxx silk_encoder_state_FLP +#endif +#include "silk_tuning_parameters.h" + +opus_int silk_setup_resamplers( + silk_encoder_state_Fxx *psEnc, /* I/O */ + opus_int fs_kHz /* I */ +); + +opus_int silk_setup_fs( + silk_encoder_state_Fxx *psEnc, /* I/O */ + opus_int fs_kHz, /* I */ + opus_int PacketSize_ms /* I */ +); + +opus_int silk_setup_complexity( + silk_encoder_state *psEncC, /* I/O */ + opus_int Complexity /* I */ +); + +SKP_INLINE opus_int silk_setup_LBRR( + silk_encoder_state *psEncC, /* I/O */ + const opus_int32 TargetRate_bps /* I */ +); + + +/* Control encoder */ +opus_int silk_control_encoder( + silk_encoder_state_Fxx *psEnc, /* I/O Pointer to Silk encoder state */ + silk_EncControlStruct *encControl, /* I: Control structure */ + const opus_int32 TargetRate_bps, /* I Target max bitrate (bps) */ + const opus_int allow_bw_switch, /* I Flag to allow switching audio bandwidth */ + const opus_int channelNb /* I Channel number */ +) +{ + opus_int fs_kHz, ret = 0; + + psEnc->sCmn.useDTX = encControl->useDTX; + psEnc->sCmn.useCBR = encControl->useCBR; + psEnc->sCmn.API_fs_Hz = encControl->API_sampleRate; + psEnc->sCmn.maxInternal_fs_Hz = encControl->maxInternalSampleRate; + psEnc->sCmn.minInternal_fs_Hz = encControl->minInternalSampleRate; + psEnc->sCmn.desiredInternal_fs_Hz = encControl->desiredInternalSampleRate; + psEnc->sCmn.useInBandFEC = encControl->useInBandFEC; + psEnc->sCmn.nChannelsAPI = encControl->nChannelsAPI; + psEnc->sCmn.nChannelsInternal = encControl->nChannelsInternal; + psEnc->sCmn.allow_bandwidth_switch = allow_bw_switch; + psEnc->sCmn.channelNb = channelNb; + + if( psEnc->sCmn.controlled_since_last_payload != 0 && psEnc->sCmn.prefillFlag == 0 ) { + if( psEnc->sCmn.API_fs_Hz != psEnc->sCmn.prev_API_fs_Hz && psEnc->sCmn.fs_kHz > 0 ) { + /* Change in API sampling rate in the middle of encoding a packet */ + ret += silk_setup_resamplers( psEnc, psEnc->sCmn.fs_kHz ); + } + return ret; + } + + /* Beyond this point we know that there are no previously coded frames in the payload buffer */ + + /********************************************/ + /* Determine internal sampling rate */ + /********************************************/ + fs_kHz = silk_control_audio_bandwidth( &psEnc->sCmn ); + + /********************************************/ + /* Prepare resampler and buffered data */ + /********************************************/ + ret += silk_setup_resamplers( psEnc, fs_kHz ); + + /********************************************/ + /* Set internal sampling frequency */ + /********************************************/ + ret += silk_setup_fs( psEnc, fs_kHz, encControl->payloadSize_ms ); + + /********************************************/ + /* Set encoding complexity */ + /********************************************/ + ret += silk_setup_complexity( &psEnc->sCmn, encControl->complexity ); + + /********************************************/ + /* Set packet loss rate measured by farend */ + /********************************************/ + psEnc->sCmn.PacketLoss_perc = encControl->packetLossPercentage; + + /********************************************/ + /* Set LBRR usage */ + /********************************************/ + ret += silk_setup_LBRR( &psEnc->sCmn, TargetRate_bps ); + + psEnc->sCmn.controlled_since_last_payload = 1; + + return ret; +} + +opus_int silk_setup_resamplers( + silk_encoder_state_Fxx *psEnc, /* I/O */ + opus_int fs_kHz /* I */ +) +{ + opus_int ret = SILK_NO_ERROR; + opus_int32 nSamples_temp; + + if( psEnc->sCmn.fs_kHz != fs_kHz || psEnc->sCmn.prev_API_fs_Hz != psEnc->sCmn.API_fs_Hz ) + { + if( psEnc->sCmn.fs_kHz == 0 ) { + /* Initialize the resampler for enc_API.c preparing resampling from API_fs_Hz to fs_kHz */ + ret += silk_resampler_init( &psEnc->sCmn.resampler_state, psEnc->sCmn.API_fs_Hz, fs_kHz * 1000 ); + } else { + /* Allocate worst case space for temporary upsampling, 8 to 48 kHz, so a factor 6 */ + opus_int16 x_buf_API_fs_Hz[ ( 2 * MAX_FRAME_LENGTH_MS + LA_SHAPE_MS ) * MAX_API_FS_KHZ ]; +#ifdef FIXED_POINT + opus_int16 *x_bufFIX = psEnc->x_buf; +#else + opus_int16 x_bufFIX[ 2 * MAX_FRAME_LENGTH + LA_SHAPE_MAX ]; +#endif + + nSamples_temp = SKP_LSHIFT( psEnc->sCmn.frame_length, 1 ) + LA_SHAPE_MS * psEnc->sCmn.fs_kHz; + +#ifndef FIXED_POINT + SKP_float2short_array( x_bufFIX, psEnc->x_buf, nSamples_temp ); +#endif + + if( SKP_SMULBB( fs_kHz, 1000 ) < psEnc->sCmn.API_fs_Hz && psEnc->sCmn.fs_kHz != 0 ) { + /* Resample buffered data in x_buf to API_fs_Hz */ + + silk_resampler_state_struct temp_resampler_state; + + /* Initialize resampler for temporary resampling of x_buf data to API_fs_Hz */ + ret += silk_resampler_init( &temp_resampler_state, SKP_SMULBB( psEnc->sCmn.fs_kHz, 1000 ), psEnc->sCmn.API_fs_Hz ); + + /* Temporary resampling of x_buf data to API_fs_Hz */ + ret += silk_resampler( &temp_resampler_state, x_buf_API_fs_Hz, x_bufFIX, nSamples_temp ); + + /* Calculate number of samples that has been temporarily upsampled */ + nSamples_temp = SKP_DIV32_16( nSamples_temp * psEnc->sCmn.API_fs_Hz, SKP_SMULBB( psEnc->sCmn.fs_kHz, 1000 ) ); + + /* Initialize the resampler for enc_API.c preparing resampling from API_fs_Hz to fs_kHz */ + ret += silk_resampler_init( &psEnc->sCmn.resampler_state, psEnc->sCmn.API_fs_Hz, SKP_SMULBB( fs_kHz, 1000 ) ); + + } else { + /* Copy data */ + SKP_memcpy( x_buf_API_fs_Hz, x_bufFIX, nSamples_temp * sizeof( opus_int16 ) ); + } + + if( 1000 * fs_kHz != psEnc->sCmn.API_fs_Hz ) { + /* Correct resampler state (unless resampling by a factor 1) by resampling buffered data from API_fs_Hz to fs_kHz */ + ret += silk_resampler( &psEnc->sCmn.resampler_state, x_bufFIX, x_buf_API_fs_Hz, nSamples_temp ); + } +#ifndef FIXED_POINT + SKP_short2float_array( psEnc->x_buf, x_bufFIX, ( 2 * MAX_FRAME_LENGTH_MS + LA_SHAPE_MS ) * fs_kHz ); +#endif + } + } + + psEnc->sCmn.prev_API_fs_Hz = psEnc->sCmn.API_fs_Hz; + + return ret; +} + +opus_int silk_setup_fs( + silk_encoder_state_Fxx *psEnc, /* I/O */ + opus_int fs_kHz, /* I */ + opus_int PacketSize_ms /* I */ +) +{ + opus_int ret = SILK_NO_ERROR; + + /* Set packet size */ + if( PacketSize_ms != psEnc->sCmn.PacketSize_ms ) { + if( ( PacketSize_ms != 10 ) && + ( PacketSize_ms != 20 ) && + ( PacketSize_ms != 40 ) && + ( PacketSize_ms != 60 ) ) { + ret = SILK_ENC_PACKET_SIZE_NOT_SUPPORTED; + } + if( PacketSize_ms <= 10 ) { + psEnc->sCmn.nFramesPerPacket = 1; + psEnc->sCmn.nb_subfr = PacketSize_ms == 10 ? 2 : 1; + psEnc->sCmn.frame_length = SKP_SMULBB( PacketSize_ms, fs_kHz ); + psEnc->sCmn.pitch_LPC_win_length = SKP_SMULBB( FIND_PITCH_LPC_WIN_MS_2_SF, fs_kHz ); + if( psEnc->sCmn.fs_kHz == 8 ) { + psEnc->sCmn.pitch_contour_iCDF = silk_pitch_contour_10_ms_NB_iCDF; + } else { + psEnc->sCmn.pitch_contour_iCDF = silk_pitch_contour_10_ms_iCDF; + } + } else { + psEnc->sCmn.nFramesPerPacket = SKP_DIV32_16( PacketSize_ms, MAX_FRAME_LENGTH_MS ); + psEnc->sCmn.nb_subfr = MAX_NB_SUBFR; + psEnc->sCmn.frame_length = SKP_SMULBB( 20, fs_kHz ); + psEnc->sCmn.pitch_LPC_win_length = SKP_SMULBB( FIND_PITCH_LPC_WIN_MS, fs_kHz ); + if( psEnc->sCmn.fs_kHz == 8 ) { + psEnc->sCmn.pitch_contour_iCDF = silk_pitch_contour_NB_iCDF; + } else { + psEnc->sCmn.pitch_contour_iCDF = silk_pitch_contour_iCDF; + } + } + psEnc->sCmn.PacketSize_ms = PacketSize_ms; + psEnc->sCmn.TargetRate_bps = 0; /* trigger new SNR computation */ + } + + /* Set internal sampling frequency */ + SKP_assert( fs_kHz == 8 || fs_kHz == 12 || fs_kHz == 16 ); + SKP_assert( psEnc->sCmn.nb_subfr == 2 || psEnc->sCmn.nb_subfr == 4 ); + if( psEnc->sCmn.fs_kHz != fs_kHz ) { + /* reset part of the state */ +#ifdef FIXED_POINT + SKP_memset( &psEnc->sShape, 0, sizeof( silk_shape_state_FIX ) ); + SKP_memset( &psEnc->sPrefilt, 0, sizeof( silk_prefilter_state_FIX ) ); +#else + SKP_memset( &psEnc->sShape, 0, sizeof( silk_shape_state_FLP ) ); + SKP_memset( &psEnc->sPrefilt, 0, sizeof( silk_prefilter_state_FLP ) ); +#endif + SKP_memset( &psEnc->sCmn.sNSQ, 0, sizeof( silk_nsq_state ) ); + SKP_memset( psEnc->sCmn.prev_NLSFq_Q15, 0, sizeof( psEnc->sCmn.prev_NLSFq_Q15 ) ); + SKP_memset( &psEnc->sCmn.sLP.In_LP_State, 0, sizeof( psEnc->sCmn.sLP.In_LP_State ) ); + psEnc->sCmn.inputBufIx = 0; + psEnc->sCmn.nFramesEncoded = 0; + psEnc->sCmn.TargetRate_bps = 0; /* trigger new SNR computation */ + + /* Initialize non-zero parameters */ + psEnc->sCmn.prevLag = 100; + psEnc->sCmn.first_frame_after_reset = 1; + psEnc->sPrefilt.lagPrev = 100; + psEnc->sShape.LastGainIndex = 10; + psEnc->sCmn.sNSQ.lagPrev = 100; + psEnc->sCmn.sNSQ.prev_inv_gain_Q16 = 65536; + + psEnc->sCmn.fs_kHz = fs_kHz; + if( psEnc->sCmn.fs_kHz == 8 ) { + if( psEnc->sCmn.nb_subfr == MAX_NB_SUBFR ) { + psEnc->sCmn.pitch_contour_iCDF = silk_pitch_contour_NB_iCDF; + } else { + psEnc->sCmn.pitch_contour_iCDF = silk_pitch_contour_10_ms_NB_iCDF; + } + } else { + if( psEnc->sCmn.nb_subfr == MAX_NB_SUBFR ) { + psEnc->sCmn.pitch_contour_iCDF = silk_pitch_contour_iCDF; + } else { + psEnc->sCmn.pitch_contour_iCDF = silk_pitch_contour_10_ms_iCDF; + } + } + if( psEnc->sCmn.fs_kHz == 8 || psEnc->sCmn.fs_kHz == 12 ) { + psEnc->sCmn.predictLPCOrder = MIN_LPC_ORDER; + psEnc->sCmn.psNLSF_CB = &silk_NLSF_CB_NB_MB; + } else { + psEnc->sCmn.predictLPCOrder = MAX_LPC_ORDER; + psEnc->sCmn.psNLSF_CB = &silk_NLSF_CB_WB; + } + psEnc->sCmn.subfr_length = SUB_FRAME_LENGTH_MS * fs_kHz; + psEnc->sCmn.frame_length = SKP_SMULBB( psEnc->sCmn.subfr_length, psEnc->sCmn.nb_subfr ); + psEnc->sCmn.ltp_mem_length = SKP_SMULBB( LTP_MEM_LENGTH_MS, fs_kHz ); + psEnc->sCmn.la_pitch = SKP_SMULBB( LA_PITCH_MS, fs_kHz ); + psEnc->sCmn.max_pitch_lag = SKP_SMULBB( 18, fs_kHz ); + if( psEnc->sCmn.nb_subfr == MAX_NB_SUBFR ) { + psEnc->sCmn.pitch_LPC_win_length = SKP_SMULBB( FIND_PITCH_LPC_WIN_MS, fs_kHz ); + } else { + psEnc->sCmn.pitch_LPC_win_length = SKP_SMULBB( FIND_PITCH_LPC_WIN_MS_2_SF, fs_kHz ); + } + if( psEnc->sCmn.fs_kHz == 16 ) { + psEnc->sCmn.mu_LTP_Q9 = SILK_FIX_CONST( MU_LTP_QUANT_WB, 9 ); + psEnc->sCmn.pitch_lag_low_bits_iCDF = silk_uniform8_iCDF; + } else if( psEnc->sCmn.fs_kHz == 12 ) { + psEnc->sCmn.mu_LTP_Q9 = SILK_FIX_CONST( MU_LTP_QUANT_MB, 9 ); + psEnc->sCmn.pitch_lag_low_bits_iCDF = silk_uniform6_iCDF; + } else { + psEnc->sCmn.mu_LTP_Q9 = SILK_FIX_CONST( MU_LTP_QUANT_NB, 9 ); + psEnc->sCmn.pitch_lag_low_bits_iCDF = silk_uniform4_iCDF; + } + } + + /* Check that settings are valid */ + SKP_assert( ( psEnc->sCmn.subfr_length * psEnc->sCmn.nb_subfr ) == psEnc->sCmn.frame_length ); + + return ret; +} + +opus_int silk_setup_complexity( + silk_encoder_state *psEncC, /* I/O */ + opus_int Complexity /* I */ +) +{ + opus_int ret = 0; + + /* Set encoding complexity */ + SKP_assert( Complexity >= 0 && Complexity <= 10 ); + if( Complexity < 2 ) { + psEncC->pitchEstimationComplexity = SILK_PE_MIN_COMPLEX; + psEncC->pitchEstimationThreshold_Q16 = SILK_FIX_CONST( 0.8, 16 ); + psEncC->pitchEstimationLPCOrder = 6; + psEncC->shapingLPCOrder = 8; + psEncC->la_shape = 3 * psEncC->fs_kHz; + psEncC->nStatesDelayedDecision = 1; + psEncC->useInterpolatedNLSFs = 0; + psEncC->LTPQuantLowComplexity = 1; + psEncC->NLSF_MSVQ_Survivors = 2; + psEncC->warping_Q16 = 0; + } else if( Complexity < 4 ) { + psEncC->pitchEstimationComplexity = SILK_PE_MID_COMPLEX; + psEncC->pitchEstimationThreshold_Q16 = SILK_FIX_CONST( 0.76, 16 ); + psEncC->pitchEstimationLPCOrder = 8; + psEncC->shapingLPCOrder = 10; + psEncC->la_shape = 5 * psEncC->fs_kHz; + psEncC->nStatesDelayedDecision = 1; + psEncC->useInterpolatedNLSFs = 1; + psEncC->LTPQuantLowComplexity = 0; + psEncC->NLSF_MSVQ_Survivors = 4; + psEncC->warping_Q16 = 0; + } else if( Complexity < 6 ) { + psEncC->pitchEstimationComplexity = SILK_PE_MID_COMPLEX; + psEncC->pitchEstimationThreshold_Q16 = SILK_FIX_CONST( 0.74, 16 ); + psEncC->pitchEstimationLPCOrder = 10; + psEncC->shapingLPCOrder = 12; + psEncC->la_shape = 5 * psEncC->fs_kHz; + psEncC->nStatesDelayedDecision = 2; + psEncC->useInterpolatedNLSFs = 0; + psEncC->LTPQuantLowComplexity = 0; + psEncC->NLSF_MSVQ_Survivors = 8; + psEncC->warping_Q16 = psEncC->fs_kHz * SILK_FIX_CONST( WARPING_MULTIPLIER, 16 ); + } else if( Complexity < 8 ) { + psEncC->pitchEstimationComplexity = SILK_PE_MID_COMPLEX; + psEncC->pitchEstimationThreshold_Q16 = SILK_FIX_CONST( 0.72, 16 ); + psEncC->pitchEstimationLPCOrder = 12; + psEncC->shapingLPCOrder = 14; + psEncC->la_shape = 5 * psEncC->fs_kHz; + psEncC->nStatesDelayedDecision = 3; + psEncC->useInterpolatedNLSFs = 0; + psEncC->LTPQuantLowComplexity = 0; + psEncC->NLSF_MSVQ_Survivors = 16; + psEncC->warping_Q16 = psEncC->fs_kHz * SILK_FIX_CONST( WARPING_MULTIPLIER, 16 ); + } else { + psEncC->pitchEstimationComplexity = SILK_PE_MAX_COMPLEX; + psEncC->pitchEstimationThreshold_Q16 = SILK_FIX_CONST( 0.7, 16 ); + psEncC->pitchEstimationLPCOrder = 16; + psEncC->shapingLPCOrder = 16; + psEncC->la_shape = 5 * psEncC->fs_kHz; + psEncC->nStatesDelayedDecision = MAX_DEL_DEC_STATES; + psEncC->useInterpolatedNLSFs = 1; + psEncC->LTPQuantLowComplexity = 0; + psEncC->NLSF_MSVQ_Survivors = 32; + psEncC->warping_Q16 = psEncC->fs_kHz * SILK_FIX_CONST( WARPING_MULTIPLIER, 16 ); + } + + /* Do not allow higher pitch estimation LPC order than predict LPC order */ + psEncC->pitchEstimationLPCOrder = SKP_min_int( psEncC->pitchEstimationLPCOrder, psEncC->predictLPCOrder ); + psEncC->shapeWinLength = SUB_FRAME_LENGTH_MS * psEncC->fs_kHz + 2 * psEncC->la_shape; + psEncC->Complexity = Complexity; + + SKP_assert( psEncC->pitchEstimationLPCOrder <= MAX_FIND_PITCH_LPC_ORDER ); + SKP_assert( psEncC->shapingLPCOrder <= MAX_SHAPE_LPC_ORDER ); + SKP_assert( psEncC->nStatesDelayedDecision <= MAX_DEL_DEC_STATES ); + SKP_assert( psEncC->warping_Q16 <= 32767 ); + SKP_assert( psEncC->la_shape <= LA_SHAPE_MAX ); + SKP_assert( psEncC->shapeWinLength <= SHAPE_LPC_WIN_MAX ); + SKP_assert( psEncC->NLSF_MSVQ_Survivors <= NLSF_VQ_MAX_SURVIVORS ); + + return ret; +} + +SKP_INLINE opus_int silk_setup_LBRR( + silk_encoder_state *psEncC, /* I/O */ + const opus_int32 TargetRate_bps /* I */ +) +{ + opus_int ret = SILK_NO_ERROR; + opus_int32 LBRR_rate_thres_bps; + + psEncC->LBRR_enabled = 0; + if( psEncC->useInBandFEC && psEncC->PacketLoss_perc > 0 ) { + if( psEncC->fs_kHz == 8 ) { + LBRR_rate_thres_bps = LBRR_NB_MIN_RATE_BPS; + } else if( psEncC->fs_kHz == 12 ) { + LBRR_rate_thres_bps = LBRR_MB_MIN_RATE_BPS; + } else { + LBRR_rate_thres_bps = LBRR_WB_MIN_RATE_BPS; + } + LBRR_rate_thres_bps = SKP_SMULWB( SKP_MUL( LBRR_rate_thres_bps, 125 - SKP_min( psEncC->PacketLoss_perc, 25 ) ), SILK_FIX_CONST( 0.01, 16 ) ); + + if( TargetRate_bps > LBRR_rate_thres_bps ) { + /* Set gain increase for coding LBRR excitation */ + psEncC->LBRR_enabled = 1; + psEncC->LBRR_GainIncreases = SKP_max_int( 7 - SKP_SMULWB( psEncC->PacketLoss_perc, SILK_FIX_CONST( 0.4, 16 ) ), 2 ); + } + } + + return ret; +} diff --git a/silk/silk_create_init_destroy.c b/silk/silk_create_init_destroy.c index 524dafd18..506df18ff 100644 --- a/silk/silk_create_init_destroy.c +++ b/silk/silk_create_init_destroy.c @@ -1,53 +1,53 @@ -/*********************************************************************** -Copyright (c) 2006-2011, Skype Limited. All rights reserved. -Redistribution and use in source and binary forms, with or without -modification, (subject to the limitations in the disclaimer below) -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 Skype Limited, nor the names of specific -contributors, may be used to endorse or promote products derived from -this software without specific prior written permission. -NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED -BY THIS LICENSE. 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. -***********************************************************************/ - -#include "silk_main.h" - - -/************************/ -/* Init Decoder State */ -/************************/ -opus_int silk_init_decoder( - silk_decoder_state *psDec /* I/O Decoder state pointer */ -) -{ - /* Clear the entire encoder state, except anything copied */ - SKP_memset( psDec, 0, sizeof( silk_decoder_state ) ); - - /* Used to deactivate e.g. LSF interpolation and fluctuation reduction */ - psDec->first_frame_after_reset = 1; - psDec->prev_inv_gain_Q16 = 65536; - - /* Reset CNG state */ - silk_CNG_Reset( psDec ); - - /* Reset PLC state */ - silk_PLC_Reset( psDec ); - - return(0); -} - +/*********************************************************************** +Copyright (c) 2006-2011, Skype Limited. All rights reserved. +Redistribution and use in source and binary forms, with or without +modification, (subject to the limitations in the disclaimer below) +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 Skype Limited, nor the names of specific +contributors, may be used to endorse or promote products derived from +this software without specific prior written permission. +NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED +BY THIS LICENSE. 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. +***********************************************************************/ + +#include "silk_main.h" + + +/************************/ +/* Init Decoder State */ +/************************/ +opus_int silk_init_decoder( + silk_decoder_state *psDec /* I/O Decoder state pointer */ +) +{ + /* Clear the entire encoder state, except anything copied */ + SKP_memset( psDec, 0, sizeof( silk_decoder_state ) ); + + /* Used to deactivate e.g. LSF interpolation and fluctuation reduction */ + psDec->first_frame_after_reset = 1; + psDec->prev_inv_gain_Q16 = 65536; + + /* Reset CNG state */ + silk_CNG_Reset( psDec ); + + /* Reset PLC state */ + silk_PLC_Reset( psDec ); + + return(0); +} + diff --git a/silk/silk_debug.c b/silk/silk_debug.c index ff5399e40..3a824a891 100644 --- a/silk/silk_debug.c +++ b/silk/silk_debug.c @@ -1,166 +1,166 @@ -/*********************************************************************** -Copyright (c) 2006-2011, Skype Limited. All rights reserved. -Redistribution and use in source and binary forms, with or without -modification, (subject to the limitations in the disclaimer below) -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 Skype Limited, nor the names of specific -contributors, may be used to endorse or promote products derived from -this software without specific prior written permission. -NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED -BY THIS LICENSE. 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. -***********************************************************************/ - -#include "silk_debug.h" -#include "silk_SigProc_FIX.h" - -#if SILK_TIC_TOC - -#ifdef _WIN32 - -#if (defined(_WIN32) || defined(_WINCE)) -#include <windows.h> /* timer */ -#else // Linux or Mac -#include <sys/time.h> -#endif - -unsigned long silk_GetHighResolutionTime(void) /* O: time in usec*/ -{ - /* Returns a time counter in microsec */ - /* the resolution is platform dependent */ - /* but is typically 1.62 us resolution */ - LARGE_INTEGER lpPerformanceCount; - LARGE_INTEGER lpFrequency; - QueryPerformanceCounter(&lpPerformanceCount); - QueryPerformanceFrequency(&lpFrequency); - return (unsigned long)((1000000*(lpPerformanceCount.QuadPart)) / lpFrequency.QuadPart); -} -#else // Linux or Mac -unsigned long GetHighResolutionTime(void) /* O: time in usec*/ -{ - struct timeval tv; - gettimeofday(&tv, 0); - return((tv.tv_sec*1000000)+(tv.tv_usec)); -} -#endif - -int silk_Timer_nTimers = 0; -int silk_Timer_depth_ctr = 0; -char silk_Timer_tags[SKP_NUM_TIMERS_MAX][SKP_NUM_TIMERS_MAX_TAG_LEN]; -#ifdef WIN32 -LARGE_INTEGER silk_Timer_start[SKP_NUM_TIMERS_MAX]; -#else -unsigned long silk_Timer_start[SKP_NUM_TIMERS_MAX]; -#endif -unsigned int silk_Timer_cnt[SKP_NUM_TIMERS_MAX]; -opus_int64 silk_Timer_min[SKP_NUM_TIMERS_MAX]; -opus_int64 silk_Timer_sum[SKP_NUM_TIMERS_MAX]; -opus_int64 silk_Timer_max[SKP_NUM_TIMERS_MAX]; -opus_int64 silk_Timer_depth[SKP_NUM_TIMERS_MAX]; - -#ifdef WIN32 -void silk_TimerSave(char *file_name) -{ - if( silk_Timer_nTimers > 0 ) - { - int k; - FILE *fp; - LARGE_INTEGER lpFrequency; - LARGE_INTEGER lpPerformanceCount1, lpPerformanceCount2; - int del = 0x7FFFFFFF; - double avg, sum_avg; - /* estimate overhead of calling performance counters */ - for( k = 0; k < 1000; k++ ) { - QueryPerformanceCounter(&lpPerformanceCount1); - QueryPerformanceCounter(&lpPerformanceCount2); - lpPerformanceCount2.QuadPart -= lpPerformanceCount1.QuadPart; - if( (int)lpPerformanceCount2.LowPart < del ) - del = lpPerformanceCount2.LowPart; - } - QueryPerformanceFrequency(&lpFrequency); - /* print results to file */ - sum_avg = 0.0f; - for( k = 0; k < silk_Timer_nTimers; k++ ) { - if (silk_Timer_depth[k] == 0) { - sum_avg += (1e6 * silk_Timer_sum[k] / silk_Timer_cnt[k] - del) / lpFrequency.QuadPart * silk_Timer_cnt[k]; - } - } - fp = fopen(file_name, "w"); - fprintf(fp, " min avg %% max count\n"); - for( k = 0; k < silk_Timer_nTimers; k++ ) { - if (silk_Timer_depth[k] == 0) { - fprintf(fp, "%-28s", silk_Timer_tags[k]); - } else if (silk_Timer_depth[k] == 1) { - fprintf(fp, " %-27s", silk_Timer_tags[k]); - } else if (silk_Timer_depth[k] == 2) { - fprintf(fp, " %-26s", silk_Timer_tags[k]); - } else if (silk_Timer_depth[k] == 3) { - fprintf(fp, " %-25s", silk_Timer_tags[k]); - } else { - fprintf(fp, " %-24s", silk_Timer_tags[k]); - } - avg = (1e6 * silk_Timer_sum[k] / silk_Timer_cnt[k] - del) / lpFrequency.QuadPart; - fprintf(fp, "%8.2f", (1e6 * (SKP_max_64(silk_Timer_min[k] - del, 0))) / lpFrequency.QuadPart); - fprintf(fp, "%12.2f %6.2f", avg, 100.0 * avg / sum_avg * silk_Timer_cnt[k]); - fprintf(fp, "%12.2f", (1e6 * (SKP_max_64(silk_Timer_max[k] - del, 0))) / lpFrequency.QuadPart); - fprintf(fp, "%10d\n", silk_Timer_cnt[k]); - } - fprintf(fp, " microseconds\n"); - fclose(fp); - } -} -#else -void silk_TimerSave(char *file_name) -{ - if( silk_Timer_nTimers > 0 ) - { - int k; - FILE *fp; - /* print results to file */ - fp = fopen(file_name, "w"); - fprintf(fp, " min avg max count\n"); - for( k = 0; k < silk_Timer_nTimers; k++ ) - { - if (silk_Timer_depth[k] == 0) { - fprintf(fp, "%-28s", silk_Timer_tags[k]); - } else if (silk_Timer_depth[k] == 1) { - fprintf(fp, " %-27s", silk_Timer_tags[k]); - } else if (silk_Timer_depth[k] == 2) { - fprintf(fp, " %-26s", silk_Timer_tags[k]); - } else if (silk_Timer_depth[k] == 3) { - fprintf(fp, " %-25s", silk_Timer_tags[k]); - } else { - fprintf(fp, " %-24s", silk_Timer_tags[k]); - } - fprintf(fp, "%d ", silk_Timer_min[k]); - fprintf(fp, "%f ", (double)silk_Timer_sum[k] / (double)silk_Timer_cnt[k]); - fprintf(fp, "%d ", silk_Timer_max[k]); - fprintf(fp, "%10d\n", silk_Timer_cnt[k]); - } - fprintf(fp, " microseconds\n"); - fclose(fp); - } -} -#endif - -#endif /* SILK_TIC_TOC */ - -#if SILK_DEBUG -FILE *silk_debug_store_fp[ SKP_NUM_STORES_MAX ]; -int silk_debug_store_count = 0; -#endif /* SILK_DEBUG */ - +/*********************************************************************** +Copyright (c) 2006-2011, Skype Limited. All rights reserved. +Redistribution and use in source and binary forms, with or without +modification, (subject to the limitations in the disclaimer below) +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 Skype Limited, nor the names of specific +contributors, may be used to endorse or promote products derived from +this software without specific prior written permission. +NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED +BY THIS LICENSE. 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. +***********************************************************************/ + +#include "silk_debug.h" +#include "silk_SigProc_FIX.h" + +#if SILK_TIC_TOC + +#ifdef _WIN32 + +#if (defined(_WIN32) || defined(_WINCE)) +#include <windows.h> /* timer */ +#else // Linux or Mac +#include <sys/time.h> +#endif + +unsigned long silk_GetHighResolutionTime(void) /* O: time in usec*/ +{ + /* Returns a time counter in microsec */ + /* the resolution is platform dependent */ + /* but is typically 1.62 us resolution */ + LARGE_INTEGER lpPerformanceCount; + LARGE_INTEGER lpFrequency; + QueryPerformanceCounter(&lpPerformanceCount); + QueryPerformanceFrequency(&lpFrequency); + return (unsigned long)((1000000*(lpPerformanceCount.QuadPart)) / lpFrequency.QuadPart); +} +#else // Linux or Mac +unsigned long GetHighResolutionTime(void) /* O: time in usec*/ +{ + struct timeval tv; + gettimeofday(&tv, 0); + return((tv.tv_sec*1000000)+(tv.tv_usec)); +} +#endif + +int silk_Timer_nTimers = 0; +int silk_Timer_depth_ctr = 0; +char silk_Timer_tags[SKP_NUM_TIMERS_MAX][SKP_NUM_TIMERS_MAX_TAG_LEN]; +#ifdef WIN32 +LARGE_INTEGER silk_Timer_start[SKP_NUM_TIMERS_MAX]; +#else +unsigned long silk_Timer_start[SKP_NUM_TIMERS_MAX]; +#endif +unsigned int silk_Timer_cnt[SKP_NUM_TIMERS_MAX]; +opus_int64 silk_Timer_min[SKP_NUM_TIMERS_MAX]; +opus_int64 silk_Timer_sum[SKP_NUM_TIMERS_MAX]; +opus_int64 silk_Timer_max[SKP_NUM_TIMERS_MAX]; +opus_int64 silk_Timer_depth[SKP_NUM_TIMERS_MAX]; + +#ifdef WIN32 +void silk_TimerSave(char *file_name) +{ + if( silk_Timer_nTimers > 0 ) + { + int k; + FILE *fp; + LARGE_INTEGER lpFrequency; + LARGE_INTEGER lpPerformanceCount1, lpPerformanceCount2; + int del = 0x7FFFFFFF; + double avg, sum_avg; + /* estimate overhead of calling performance counters */ + for( k = 0; k < 1000; k++ ) { + QueryPerformanceCounter(&lpPerformanceCount1); + QueryPerformanceCounter(&lpPerformanceCount2); + lpPerformanceCount2.QuadPart -= lpPerformanceCount1.QuadPart; + if( (int)lpPerformanceCount2.LowPart < del ) + del = lpPerformanceCount2.LowPart; + } + QueryPerformanceFrequency(&lpFrequency); + /* print results to file */ + sum_avg = 0.0f; + for( k = 0; k < silk_Timer_nTimers; k++ ) { + if (silk_Timer_depth[k] == 0) { + sum_avg += (1e6 * silk_Timer_sum[k] / silk_Timer_cnt[k] - del) / lpFrequency.QuadPart * silk_Timer_cnt[k]; + } + } + fp = fopen(file_name, "w"); + fprintf(fp, " min avg %% max count\n"); + for( k = 0; k < silk_Timer_nTimers; k++ ) { + if (silk_Timer_depth[k] == 0) { + fprintf(fp, "%-28s", silk_Timer_tags[k]); + } else if (silk_Timer_depth[k] == 1) { + fprintf(fp, " %-27s", silk_Timer_tags[k]); + } else if (silk_Timer_depth[k] == 2) { + fprintf(fp, " %-26s", silk_Timer_tags[k]); + } else if (silk_Timer_depth[k] == 3) { + fprintf(fp, " %-25s", silk_Timer_tags[k]); + } else { + fprintf(fp, " %-24s", silk_Timer_tags[k]); + } + avg = (1e6 * silk_Timer_sum[k] / silk_Timer_cnt[k] - del) / lpFrequency.QuadPart; + fprintf(fp, "%8.2f", (1e6 * (SKP_max_64(silk_Timer_min[k] - del, 0))) / lpFrequency.QuadPart); + fprintf(fp, "%12.2f %6.2f", avg, 100.0 * avg / sum_avg * silk_Timer_cnt[k]); + fprintf(fp, "%12.2f", (1e6 * (SKP_max_64(silk_Timer_max[k] - del, 0))) / lpFrequency.QuadPart); + fprintf(fp, "%10d\n", silk_Timer_cnt[k]); + } + fprintf(fp, " microseconds\n"); + fclose(fp); + } +} +#else +void silk_TimerSave(char *file_name) +{ + if( silk_Timer_nTimers > 0 ) + { + int k; + FILE *fp; + /* print results to file */ + fp = fopen(file_name, "w"); + fprintf(fp, " min avg max count\n"); + for( k = 0; k < silk_Timer_nTimers; k++ ) + { + if (silk_Timer_depth[k] == 0) { + fprintf(fp, "%-28s", silk_Timer_tags[k]); + } else if (silk_Timer_depth[k] == 1) { + fprintf(fp, " %-27s", silk_Timer_tags[k]); + } else if (silk_Timer_depth[k] == 2) { + fprintf(fp, " %-26s", silk_Timer_tags[k]); + } else if (silk_Timer_depth[k] == 3) { + fprintf(fp, " %-25s", silk_Timer_tags[k]); + } else { + fprintf(fp, " %-24s", silk_Timer_tags[k]); + } + fprintf(fp, "%d ", silk_Timer_min[k]); + fprintf(fp, "%f ", (double)silk_Timer_sum[k] / (double)silk_Timer_cnt[k]); + fprintf(fp, "%d ", silk_Timer_max[k]); + fprintf(fp, "%10d\n", silk_Timer_cnt[k]); + } + fprintf(fp, " microseconds\n"); + fclose(fp); + } +} +#endif + +#endif /* SILK_TIC_TOC */ + +#if SILK_DEBUG +FILE *silk_debug_store_fp[ SKP_NUM_STORES_MAX ]; +int silk_debug_store_count = 0; +#endif /* SILK_DEBUG */ + diff --git a/silk/silk_debug.h b/silk/silk_debug.h index c25ec973f..654ab7c4f 100644 --- a/silk/silk_debug.h +++ b/silk/silk_debug.h @@ -1,311 +1,311 @@ -/*********************************************************************** -Copyright (c) 2006-2011, Skype Limited. All rights reserved. -Redistribution and use in source and binary forms, with or without -modification, (subject to the limitations in the disclaimer below) -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 Skype Limited, nor the names of specific -contributors, may be used to endorse or promote products derived from -this software without specific prior written permission. -NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED -BY THIS LICENSE. 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. -***********************************************************************/ - -#ifndef _SILK_DEBUG_H_ -#define _SILK_DEBUG_H_ - -#ifdef _WIN32 -#define _CRT_SECURE_NO_DEPRECATE 1 -#endif - -#include "silk_typedef.h" -#include <stdio.h> /* file writing */ -#include <string.h> /* strcpy, strcmp */ - -#ifdef __cplusplus -extern "C" -{ -#endif - -unsigned long GetHighResolutionTime(void); /* O: time in usec*/ - -/* make SILK_DEBUG dependent on compiler's _DEBUG */ -#if defined _WIN32 - #ifdef _DEBUG - #define SILK_DEBUG 1 - #else - #define SILK_DEBUG 0 - #endif - - /* overrule the above */ - #if 0 - // #define NO_ASSERTS - #undef SILK_DEBUG - #define SILK_DEBUG 1 - #endif -#else - #define SILK_DEBUG 0 -#endif - -/* Flag for using timers */ -#define SILK_TIC_TOC 0 - -#if SILK_TIC_TOC - -#if (defined(_WIN32) || defined(_WINCE)) -#include <windows.h> /* timer */ -#pragma warning( disable : 4996 ) // stop bitching about strcpy in TIC() -#else // Linux or Mac -#include <sys/time.h> -#endif - -/*********************************/ -/* timer functions for profiling */ -/*********************************/ -/* example: */ -/* */ -/* TIC(LPC) */ -/* do_LPC(in_vec, order, acoef); // do LPC analysis */ -/* TOC(LPC) */ -/* */ -/* and call the following just before exiting (from main) */ -/* */ -/* silk_TimerSave("SKP_TimingData.txt"); */ -/* */ -/* results are now in SKP_TimingData.txt */ - -void silk_TimerSave(char *file_name); - -/* max number of timers (in different locations) */ -#define SKP_NUM_TIMERS_MAX 50 -/* max length of name tags in TIC(..), TOC(..) */ -#define SKP_NUM_TIMERS_MAX_TAG_LEN 30 - -extern int silk_Timer_nTimers; -extern int silk_Timer_depth_ctr; -extern char silk_Timer_tags[SKP_NUM_TIMERS_MAX][SKP_NUM_TIMERS_MAX_TAG_LEN]; -#ifdef _WIN32 -extern LARGE_INTEGER silk_Timer_start[SKP_NUM_TIMERS_MAX]; -#else -extern unsigned long silk_Timer_start[SKP_NUM_TIMERS_MAX]; -#endif -extern unsigned int silk_Timer_cnt[SKP_NUM_TIMERS_MAX]; -extern opus_int64 silk_Timer_sum[SKP_NUM_TIMERS_MAX]; -extern opus_int64 silk_Timer_max[SKP_NUM_TIMERS_MAX]; -extern opus_int64 silk_Timer_min[SKP_NUM_TIMERS_MAX]; -extern opus_int64 silk_Timer_depth[SKP_NUM_TIMERS_MAX]; - -/* WARNING: TIC()/TOC can measure only up to 0.1 seconds at a time */ -#ifdef _WIN32 -#define TIC(TAG_NAME) { \ - static int init = 0; \ - static int ID = -1; \ - if( init == 0 ) \ - { \ - int k; \ - init = 1; \ - for( k = 0; k < silk_Timer_nTimers; k++ ) { \ - if( strcmp(silk_Timer_tags[k], #TAG_NAME) == 0 ) { \ - ID = k; \ - break; \ - } \ - } \ - if (ID == -1) { \ - ID = silk_Timer_nTimers; \ - silk_Timer_nTimers++; \ - silk_Timer_depth[ID] = silk_Timer_depth_ctr; \ - strcpy(silk_Timer_tags[ID], #TAG_NAME); \ - silk_Timer_cnt[ID] = 0; \ - silk_Timer_sum[ID] = 0; \ - silk_Timer_min[ID] = 0xFFFFFFFF; \ - silk_Timer_max[ID] = 0; \ - } \ - } \ - silk_Timer_depth_ctr++; \ - QueryPerformanceCounter(&silk_Timer_start[ID]); \ -} -#else -#define TIC(TAG_NAME) { \ - static int init = 0; \ - static int ID = -1; \ - if( init == 0 ) \ - { \ - int k; \ - init = 1; \ - for( k = 0; k < silk_Timer_nTimers; k++ ) { \ - if( strcmp(silk_Timer_tags[k], #TAG_NAME) == 0 ) { \ - ID = k; \ - break; \ - } \ - } \ - if (ID == -1) { \ - ID = silk_Timer_nTimers; \ - silk_Timer_nTimers++; \ - silk_Timer_depth[ID] = silk_Timer_depth_ctr; \ - strcpy(silk_Timer_tags[ID], #TAG_NAME); \ - silk_Timer_cnt[ID] = 0; \ - silk_Timer_sum[ID] = 0; \ - silk_Timer_min[ID] = 0xFFFFFFFF; \ - silk_Timer_max[ID] = 0; \ - } \ - } \ - silk_Timer_depth_ctr++; \ - silk_Timer_start[ID] = GetHighResolutionTime(); \ -} -#endif - -#ifdef _WIN32 -#define TOC(TAG_NAME) { \ - LARGE_INTEGER lpPerformanceCount; \ - static int init = 0; \ - static int ID = 0; \ - if( init == 0 ) \ - { \ - int k; \ - init = 1; \ - for( k = 0; k < silk_Timer_nTimers; k++ ) { \ - if( strcmp(silk_Timer_tags[k], #TAG_NAME) == 0 ) { \ - ID = k; \ - break; \ - } \ - } \ - } \ - QueryPerformanceCounter(&lpPerformanceCount); \ - lpPerformanceCount.QuadPart -= silk_Timer_start[ID].QuadPart; \ - if((lpPerformanceCount.QuadPart < 100000000) && \ - (lpPerformanceCount.QuadPart >= 0)) { \ - silk_Timer_cnt[ID]++; \ - silk_Timer_sum[ID] += lpPerformanceCount.QuadPart; \ - if( lpPerformanceCount.QuadPart > silk_Timer_max[ID] ) \ - silk_Timer_max[ID] = lpPerformanceCount.QuadPart; \ - if( lpPerformanceCount.QuadPart < silk_Timer_min[ID] ) \ - silk_Timer_min[ID] = lpPerformanceCount.QuadPart; \ - } \ - silk_Timer_depth_ctr--; \ -} -#else -#define TOC(TAG_NAME) { \ - unsigned long endTime; \ - static int init = 0; \ - static int ID = 0; \ - if( init == 0 ) \ - { \ - int k; \ - init = 1; \ - for( k = 0; k < silk_Timer_nTimers; k++ ) { \ - if( strcmp(silk_Timer_tags[k], #TAG_NAME) == 0 ) { \ - ID = k; \ - break; \ - } \ - } \ - } \ - endTime = GetHighResolutionTime(); \ - endTime -= silk_Timer_start[ID]; \ - if((endTime < 100000000) && \ - (endTime >= 0)) { \ - silk_Timer_cnt[ID]++; \ - silk_Timer_sum[ID] += endTime; \ - if( endTime > silk_Timer_max[ID] ) \ - silk_Timer_max[ID] = endTime; \ - if( endTime < silk_Timer_min[ID] ) \ - silk_Timer_min[ID] = endTime; \ - } \ - silk_Timer_depth_ctr--; \ -} -#endif - -#else /* SILK_TIC_TOC */ - -/* define macros as empty strings */ -#define TIC(TAG_NAME) -#define TOC(TAG_NAME) -#define silk_TimerSave(FILE_NAME) - -#endif /* SILK_TIC_TOC */ - - - -#if SILK_DEBUG -/************************************/ -/* write data to file for debugging */ -/************************************/ -/* opens an empty file if this file has not yet been open, then writes to the file and closes it */ -/* if file has been open previously it is opened again and the fwrite is appending, finally it is closed */ -#define SAVE_DATA( FILE_NAME, DATA_PTR, N_BYTES ) { \ - static opus_int32 init = 0; \ - FILE *fp; \ - if (init == 0) { \ - init = 1; \ - fp = fopen(#FILE_NAME, "wb"); \ - } else { \ - fp = fopen(#FILE_NAME, "ab+"); \ - } \ - fwrite((DATA_PTR), (N_BYTES), 1, fp); \ - fclose(fp); \ -} - -/* Example: DEBUG_STORE_DATA(testfile.pcm, &RIN[0], 160*sizeof(opus_int16)); */ - -#if 0 -/* Ensure that everything is written to files when an assert breaks */ -#define DEBUG_STORE_DATA(FILE_NAME, DATA_PTR, N_BYTES) SAVE_DATA(FILE_NAME, DATA_PTR, N_BYTES) -#define SILK_DEBUG_STORE_CLOSE_FILES - -#else - -#define SKP_NUM_STORES_MAX 100 -extern FILE *silk_debug_store_fp[ SKP_NUM_STORES_MAX ]; -extern int silk_debug_store_count; - -/* Faster way of storing the data */ -#define DEBUG_STORE_DATA( FILE_NAME, DATA_PTR, N_BYTES ) { \ - static opus_int init = 0, cnt = 0; \ - static FILE **fp; \ - if (init == 0) { \ - init = 1; \ - cnt = silk_debug_store_count++; \ - silk_debug_store_fp[ cnt ] = fopen(#FILE_NAME, "wb"); \ - } \ - fwrite((DATA_PTR), (N_BYTES), 1, silk_debug_store_fp[ cnt ]); \ -} - -/* Call this at the end of main() */ -#define SILK_DEBUG_STORE_CLOSE_FILES { \ - opus_int i; \ - for( i = 0; i < silk_debug_store_count; i++ ) { \ - fclose( silk_debug_store_fp[ i ] ); \ - } \ -} -#endif - -/* micro sec */ -#define SKP_GETTIME(void) time = (opus_int64) silk_GetHighResolutionTime(); - -#else /* SILK_DEBUG */ - -/* define macros as empty strings */ -#define DEBUG_STORE_DATA(FILE_NAME, DATA_PTR, N_BYTES) -#define SAVE_DATA(FILE_NAME, DATA_PTR, N_BYTES) -#define SILK_DEBUG_STORE_CLOSE_FILES - -#endif /* SILK_DEBUG */ - -#ifdef __cplusplus -} -#endif - -#endif /* _SILK_DEBUG_H_ */ +/*********************************************************************** +Copyright (c) 2006-2011, Skype Limited. All rights reserved. +Redistribution and use in source and binary forms, with or without +modification, (subject to the limitations in the disclaimer below) +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 Skype Limited, nor the names of specific +contributors, may be used to endorse or promote products derived from +this software without specific prior written permission. +NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED +BY THIS LICENSE. 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. +***********************************************************************/ + +#ifndef _SILK_DEBUG_H_ +#define _SILK_DEBUG_H_ + +#ifdef _WIN32 +#define _CRT_SECURE_NO_DEPRECATE 1 +#endif + +#include "silk_typedef.h" +#include <stdio.h> /* file writing */ +#include <string.h> /* strcpy, strcmp */ + +#ifdef __cplusplus +extern "C" +{ +#endif + +unsigned long GetHighResolutionTime(void); /* O: time in usec*/ + +/* make SILK_DEBUG dependent on compiler's _DEBUG */ +#if defined _WIN32 + #ifdef _DEBUG + #define SILK_DEBUG 1 + #else + #define SILK_DEBUG 0 + #endif + + /* overrule the above */ + #if 0 + // #define NO_ASSERTS + #undef SILK_DEBUG + #define SILK_DEBUG 1 + #endif +#else + #define SILK_DEBUG 0 +#endif + +/* Flag for using timers */ +#define SILK_TIC_TOC 0 + +#if SILK_TIC_TOC + +#if (defined(_WIN32) || defined(_WINCE)) +#include <windows.h> /* timer */ +#pragma warning( disable : 4996 ) // stop bitching about strcpy in TIC() +#else // Linux or Mac +#include <sys/time.h> +#endif + +/*********************************/ +/* timer functions for profiling */ +/*********************************/ +/* example: */ +/* */ +/* TIC(LPC) */ +/* do_LPC(in_vec, order, acoef); // do LPC analysis */ +/* TOC(LPC) */ +/* */ +/* and call the following just before exiting (from main) */ +/* */ +/* silk_TimerSave("SKP_TimingData.txt"); */ +/* */ +/* results are now in SKP_TimingData.txt */ + +void silk_TimerSave(char *file_name); + +/* max number of timers (in different locations) */ +#define SKP_NUM_TIMERS_MAX 50 +/* max length of name tags in TIC(..), TOC(..) */ +#define SKP_NUM_TIMERS_MAX_TAG_LEN 30 + +extern int silk_Timer_nTimers; +extern int silk_Timer_depth_ctr; +extern char silk_Timer_tags[SKP_NUM_TIMERS_MAX][SKP_NUM_TIMERS_MAX_TAG_LEN]; +#ifdef _WIN32 +extern LARGE_INTEGER silk_Timer_start[SKP_NUM_TIMERS_MAX]; +#else +extern unsigned long silk_Timer_start[SKP_NUM_TIMERS_MAX]; +#endif +extern unsigned int silk_Timer_cnt[SKP_NUM_TIMERS_MAX]; +extern opus_int64 silk_Timer_sum[SKP_NUM_TIMERS_MAX]; +extern opus_int64 silk_Timer_max[SKP_NUM_TIMERS_MAX]; +extern opus_int64 silk_Timer_min[SKP_NUM_TIMERS_MAX]; +extern opus_int64 silk_Timer_depth[SKP_NUM_TIMERS_MAX]; + +/* WARNING: TIC()/TOC can measure only up to 0.1 seconds at a time */ +#ifdef _WIN32 +#define TIC(TAG_NAME) { \ + static int init = 0; \ + static int ID = -1; \ + if( init == 0 ) \ + { \ + int k; \ + init = 1; \ + for( k = 0; k < silk_Timer_nTimers; k++ ) { \ + if( strcmp(silk_Timer_tags[k], #TAG_NAME) == 0 ) { \ + ID = k; \ + break; \ + } \ + } \ + if (ID == -1) { \ + ID = silk_Timer_nTimers; \ + silk_Timer_nTimers++; \ + silk_Timer_depth[ID] = silk_Timer_depth_ctr; \ + strcpy(silk_Timer_tags[ID], #TAG_NAME); \ + silk_Timer_cnt[ID] = 0; \ + silk_Timer_sum[ID] = 0; \ + silk_Timer_min[ID] = 0xFFFFFFFF; \ + silk_Timer_max[ID] = 0; \ + } \ + } \ + silk_Timer_depth_ctr++; \ + QueryPerformanceCounter(&silk_Timer_start[ID]); \ +} +#else +#define TIC(TAG_NAME) { \ + static int init = 0; \ + static int ID = -1; \ + if( init == 0 ) \ + { \ + int k; \ + init = 1; \ + for( k = 0; k < silk_Timer_nTimers; k++ ) { \ + if( strcmp(silk_Timer_tags[k], #TAG_NAME) == 0 ) { \ + ID = k; \ + break; \ + } \ + } \ + if (ID == -1) { \ + ID = silk_Timer_nTimers; \ + silk_Timer_nTimers++; \ + silk_Timer_depth[ID] = silk_Timer_depth_ctr; \ + strcpy(silk_Timer_tags[ID], #TAG_NAME); \ + silk_Timer_cnt[ID] = 0; \ + silk_Timer_sum[ID] = 0; \ + silk_Timer_min[ID] = 0xFFFFFFFF; \ + silk_Timer_max[ID] = 0; \ + } \ + } \ + silk_Timer_depth_ctr++; \ + silk_Timer_start[ID] = GetHighResolutionTime(); \ +} +#endif + +#ifdef _WIN32 +#define TOC(TAG_NAME) { \ + LARGE_INTEGER lpPerformanceCount; \ + static int init = 0; \ + static int ID = 0; \ + if( init == 0 ) \ + { \ + int k; \ + init = 1; \ + for( k = 0; k < silk_Timer_nTimers; k++ ) { \ + if( strcmp(silk_Timer_tags[k], #TAG_NAME) == 0 ) { \ + ID = k; \ + break; \ + } \ + } \ + } \ + QueryPerformanceCounter(&lpPerformanceCount); \ + lpPerformanceCount.QuadPart -= silk_Timer_start[ID].QuadPart; \ + if((lpPerformanceCount.QuadPart < 100000000) && \ + (lpPerformanceCount.QuadPart >= 0)) { \ + silk_Timer_cnt[ID]++; \ + silk_Timer_sum[ID] += lpPerformanceCount.QuadPart; \ + if( lpPerformanceCount.QuadPart > silk_Timer_max[ID] ) \ + silk_Timer_max[ID] = lpPerformanceCount.QuadPart; \ + if( lpPerformanceCount.QuadPart < silk_Timer_min[ID] ) \ + silk_Timer_min[ID] = lpPerformanceCount.QuadPart; \ + } \ + silk_Timer_depth_ctr--; \ +} +#else +#define TOC(TAG_NAME) { \ + unsigned long endTime; \ + static int init = 0; \ + static int ID = 0; \ + if( init == 0 ) \ + { \ + int k; \ + init = 1; \ + for( k = 0; k < silk_Timer_nTimers; k++ ) { \ + if( strcmp(silk_Timer_tags[k], #TAG_NAME) == 0 ) { \ + ID = k; \ + break; \ + } \ + } \ + } \ + endTime = GetHighResolutionTime(); \ + endTime -= silk_Timer_start[ID]; \ + if((endTime < 100000000) && \ + (endTime >= 0)) { \ + silk_Timer_cnt[ID]++; \ + silk_Timer_sum[ID] += endTime; \ + if( endTime > silk_Timer_max[ID] ) \ + silk_Timer_max[ID] = endTime; \ + if( endTime < silk_Timer_min[ID] ) \ + silk_Timer_min[ID] = endTime; \ + } \ + silk_Timer_depth_ctr--; \ +} +#endif + +#else /* SILK_TIC_TOC */ + +/* define macros as empty strings */ +#define TIC(TAG_NAME) +#define TOC(TAG_NAME) +#define silk_TimerSave(FILE_NAME) + +#endif /* SILK_TIC_TOC */ + + + +#if SILK_DEBUG +/************************************/ +/* write data to file for debugging */ +/************************************/ +/* opens an empty file if this file has not yet been open, then writes to the file and closes it */ +/* if file has been open previously it is opened again and the fwrite is appending, finally it is closed */ +#define SAVE_DATA( FILE_NAME, DATA_PTR, N_BYTES ) { \ + static opus_int32 init = 0; \ + FILE *fp; \ + if (init == 0) { \ + init = 1; \ + fp = fopen(#FILE_NAME, "wb"); \ + } else { \ + fp = fopen(#FILE_NAME, "ab+"); \ + } \ + fwrite((DATA_PTR), (N_BYTES), 1, fp); \ + fclose(fp); \ +} + +/* Example: DEBUG_STORE_DATA(testfile.pcm, &RIN[0], 160*sizeof(opus_int16)); */ + +#if 0 +/* Ensure that everything is written to files when an assert breaks */ +#define DEBUG_STORE_DATA(FILE_NAME, DATA_PTR, N_BYTES) SAVE_DATA(FILE_NAME, DATA_PTR, N_BYTES) +#define SILK_DEBUG_STORE_CLOSE_FILES + +#else + +#define SKP_NUM_STORES_MAX 100 +extern FILE *silk_debug_store_fp[ SKP_NUM_STORES_MAX ]; +extern int silk_debug_store_count; + +/* Faster way of storing the data */ +#define DEBUG_STORE_DATA( FILE_NAME, DATA_PTR, N_BYTES ) { \ + static opus_int init = 0, cnt = 0; \ + static FILE **fp; \ + if (init == 0) { \ + init = 1; \ + cnt = silk_debug_store_count++; \ + silk_debug_store_fp[ cnt ] = fopen(#FILE_NAME, "wb"); \ + } \ + fwrite((DATA_PTR), (N_BYTES), 1, silk_debug_store_fp[ cnt ]); \ +} + +/* Call this at the end of main() */ +#define SILK_DEBUG_STORE_CLOSE_FILES { \ + opus_int i; \ + for( i = 0; i < silk_debug_store_count; i++ ) { \ + fclose( silk_debug_store_fp[ i ] ); \ + } \ +} +#endif + +/* micro sec */ +#define SKP_GETTIME(void) time = (opus_int64) silk_GetHighResolutionTime(); + +#else /* SILK_DEBUG */ + +/* define macros as empty strings */ +#define DEBUG_STORE_DATA(FILE_NAME, DATA_PTR, N_BYTES) +#define SAVE_DATA(FILE_NAME, DATA_PTR, N_BYTES) +#define SILK_DEBUG_STORE_CLOSE_FILES + +#endif /* SILK_DEBUG */ + +#ifdef __cplusplus +} +#endif + +#endif /* _SILK_DEBUG_H_ */ diff --git a/silk/silk_dec_API.c b/silk/silk_dec_API.c index 212b494bd..4d27bfb1e 100644 --- a/silk/silk_dec_API.c +++ b/silk/silk_dec_API.c @@ -1,297 +1,297 @@ -/*********************************************************************** -Copyright (c) 2006-2011, Skype Limited. All rights reserved. -Redistribution and use in source and binary forms, with or without -modification, (subject to the limitations in the disclaimer below) -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 Skype Limited, nor the names of specific -contributors, may be used to endorse or promote products derived from -this software without specific prior written permission. -NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED -BY THIS LICENSE. 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 "silk_API.h" -#include "silk_main.h" - -/************************/ -/* Decoder Super Struct */ -/************************/ -typedef struct { - silk_decoder_state channel_state[ DECODER_NUM_CHANNELS ]; - stereo_dec_state sStereo; - opus_int nChannelsAPI; - opus_int nChannelsInternal; -} silk_decoder; - -/*********************/ -/* Decoder functions */ -/*********************/ - -opus_int silk_Get_Decoder_Size( opus_int32 *decSizeBytes ) -{ - opus_int ret = SILK_NO_ERROR; - - *decSizeBytes = sizeof( silk_decoder ); - - return ret; -} - -/* Reset decoder state */ -opus_int silk_InitDecoder( - void* decState /* I/O: State */ -) -{ - opus_int n, ret = SILK_NO_ERROR; - silk_decoder_state *channel_state = ((silk_decoder *)decState)->channel_state; - - for( n = 0; n < DECODER_NUM_CHANNELS; n++ ) { - ret = silk_init_decoder( &channel_state[ n ] ); - } - - return ret; -} - -/* Decode a frame */ -opus_int silk_Decode( - void* decState, /* I/O: State */ - silk_DecControlStruct* decControl, /* I/O: Control Structure */ - opus_int lostFlag, /* I: 0: no loss, 1 loss, 2 decode FEC */ - opus_int newPacketFlag, /* I: Indicates first decoder call for this packet */ - ec_dec *psRangeDec, /* I/O Compressor data structure */ - opus_int16 *samplesOut, /* O: Decoded output speech vector */ - opus_int32 *nSamplesOut /* O: Number of samples decoded */ -) -{ - opus_int i, n, prev_fs_kHz, decode_only_middle = 0, ret = SILK_NO_ERROR; - opus_int32 nSamplesOutDec, LBRR_symbol; - opus_int16 samplesOut1_tmp[ 2 ][ MAX_FS_KHZ * MAX_FRAME_LENGTH_MS + 2 ]; - opus_int16 samplesOut2_tmp[ MAX_API_FS_KHZ * MAX_FRAME_LENGTH_MS ]; - opus_int MS_pred_Q13[ 2 ] = { 0 }; - opus_int16 *resample_out_ptr; - silk_decoder *psDec = ( silk_decoder * )decState; - silk_decoder_state *channel_state = psDec->channel_state; - - /**********************************/ - /* Test if first frame in payload */ - /**********************************/ - if( newPacketFlag ) { - for( n = 0; n < decControl->nChannelsInternal; n++ ) { - channel_state[ n ].nFramesDecoded = 0; /* Used to count frames in packet */ - } - } - - /* Save previous sample frequency */ - prev_fs_kHz = channel_state[ 0 ].fs_kHz; - - /* If Mono -> Stereo transition in bitstream: init state of second channel */ - if( decControl->nChannelsInternal > psDec->nChannelsInternal ) { - ret += silk_init_decoder( &channel_state[ 1 ] ); - if( psDec->nChannelsAPI == 2 ) { - SKP_memcpy( &channel_state[ 1 ].resampler_state, &channel_state[ 0 ].resampler_state, sizeof( silk_resampler_state_struct ) ); - } - } - - for( n = 0; n < decControl->nChannelsInternal; n++ ) { - if( channel_state[ n ].nFramesDecoded == 0 ) { - opus_int fs_kHz_dec; - if( decControl->payloadSize_ms == 0 ) { - /* Assuming packet loss, use 10 ms */ - channel_state[ n ].nFramesPerPacket = 1; - channel_state[ n ].nb_subfr = 2; - } else if( decControl->payloadSize_ms == 10 ) { - channel_state[ n ].nFramesPerPacket = 1; - channel_state[ n ].nb_subfr = 2; - } else if( decControl->payloadSize_ms == 20 ) { - channel_state[ n ].nFramesPerPacket = 1; - channel_state[ n ].nb_subfr = 4; - } else if( decControl->payloadSize_ms == 40 ) { - channel_state[ n ].nFramesPerPacket = 2; - channel_state[ n ].nb_subfr = 4; - } else if( decControl->payloadSize_ms == 60 ) { - channel_state[ n ].nFramesPerPacket = 3; - channel_state[ n ].nb_subfr = 4; - } else { - SKP_assert( 0 ); - return SILK_DEC_INVALID_FRAME_SIZE; - } - fs_kHz_dec = ( decControl->internalSampleRate >> 10 ) + 1; - if( fs_kHz_dec != 8 && fs_kHz_dec != 12 && fs_kHz_dec != 16 ) { - SKP_assert( 0 ); - return SILK_DEC_INVALID_SAMPLING_FREQUENCY; - } - silk_decoder_set_fs( &channel_state[ n ], fs_kHz_dec ); - } - } - - /* Initialize resampler when switching internal or external sampling frequency */ - if( prev_fs_kHz != channel_state[ 0 ].fs_kHz || channel_state[ 0 ].prev_API_sampleRate != decControl->API_sampleRate ) { - ret = silk_resampler_init( &channel_state[ 0 ].resampler_state, SKP_SMULBB( channel_state[ 0 ].fs_kHz, 1000 ), decControl->API_sampleRate ); - if( decControl->nChannelsAPI == 2 && decControl->nChannelsInternal == 2 ) { - SKP_memcpy( &channel_state[ 1 ].resampler_state, &channel_state[ 0 ].resampler_state, sizeof( silk_resampler_state_struct ) ); - } - } - channel_state[ 0 ].prev_API_sampleRate = decControl->API_sampleRate; - if( decControl->nChannelsAPI == 2 && decControl->nChannelsInternal == 2 && ( psDec->nChannelsAPI == 1 || psDec->nChannelsInternal == 1 ) ) { - SKP_memset( psDec->sStereo.pred_prev_Q13, 0, sizeof( psDec->sStereo.pred_prev_Q13 ) ); - SKP_memset( psDec->sStereo.sSide, 0, sizeof( psDec->sStereo.sSide ) ); - } - psDec->nChannelsAPI = decControl->nChannelsAPI; - psDec->nChannelsInternal = decControl->nChannelsInternal; - - if( decControl->API_sampleRate > MAX_API_FS_KHZ * 1000 || decControl->API_sampleRate < 8000 ) { - ret = SILK_DEC_INVALID_SAMPLING_FREQUENCY; - return( ret ); - } - - if( lostFlag != FLAG_PACKET_LOST && channel_state[ 0 ].nFramesDecoded == 0 ) { - /* First decoder call for this payload */ - /* Decode VAD flags and LBRR flag */ - for( n = 0; n < decControl->nChannelsInternal; n++ ) { - for( i = 0; i < channel_state[ n ].nFramesPerPacket; i++ ) { - channel_state[ n ].VAD_flags[ i ] = ec_dec_bit_logp(psRangeDec, 1); - } - channel_state[ n ].LBRR_flag = ec_dec_bit_logp(psRangeDec, 1); - } - /* Decode LBRR flags */ - for( n = 0; n < decControl->nChannelsInternal; n++ ) { - SKP_memset( channel_state[ n ].LBRR_flags, 0, sizeof( channel_state[ n ].LBRR_flags ) ); - if( channel_state[ n ].LBRR_flag ) { - if( channel_state[ n ].nFramesPerPacket == 1 ) { - channel_state[ n ].LBRR_flags[ 0 ] = 1; - } else { - LBRR_symbol = ec_dec_icdf( psRangeDec, silk_LBRR_flags_iCDF_ptr[ channel_state[ n ].nFramesPerPacket - 2 ], 8 ) + 1; - for( i = 0; i < channel_state[ n ].nFramesPerPacket; i++ ) { - channel_state[ n ].LBRR_flags[ i ] = SKP_RSHIFT( LBRR_symbol, i ) & 1; - } - } - } - } - - if( lostFlag == FLAG_DECODE_NORMAL ) { - /* Regular decoding: skip all LBRR data */ - for( i = 0; i < channel_state[ 0 ].nFramesPerPacket; i++ ) { - for( n = 0; n < decControl->nChannelsInternal; n++ ) { - if( channel_state[ n ].LBRR_flags[ i ] ) { - opus_int pulses[ MAX_FRAME_LENGTH ]; - if( decControl->nChannelsInternal == 2 && n == 0 ) { - silk_stereo_decode_pred( psRangeDec, &decode_only_middle, MS_pred_Q13 ); - } - silk_decode_indices( &channel_state[ n ], psRangeDec, i, 1 ); - silk_decode_pulses( psRangeDec, pulses, channel_state[ n ].indices.signalType, - channel_state[ n ].indices.quantOffsetType, channel_state[ n ].frame_length ); - } - } - } - } - } - - /* Get MS predictor index */ - if( decControl->nChannelsInternal == 2 ) { - if( lostFlag == FLAG_DECODE_NORMAL || - ( lostFlag == FLAG_DECODE_LBRR && channel_state[ 0 ].LBRR_flags[ channel_state[ 0 ].nFramesDecoded ] == 1 ) ) - { - silk_stereo_decode_pred( psRangeDec, &decode_only_middle, MS_pred_Q13 ); - } else { - SKP_memcpy( MS_pred_Q13, &psDec->sStereo.pred_prev_Q13, sizeof( MS_pred_Q13 ) ); - } - } - - /* Call decoder for one frame */ - for( n = 0; n < decControl->nChannelsInternal; n++ ) { - if( n == 0 || decode_only_middle == 0 ) { - ret += silk_decode_frame( &channel_state[ n ], psRangeDec, &samplesOut1_tmp[ n ][ 2 ], &nSamplesOutDec, lostFlag ); - } else { - SKP_memset( &samplesOut1_tmp[ n ][ 2 ], 0, nSamplesOutDec * sizeof( opus_int16 ) ); - } - } - - if( decControl->nChannelsAPI == 2 && decControl->nChannelsInternal == 2 ) { - /* Convert Mid/Side to Left/Right */ - silk_stereo_MS_to_LR( &psDec->sStereo, samplesOut1_tmp[ 0 ], samplesOut1_tmp[ 1 ], MS_pred_Q13, channel_state[ 0 ].fs_kHz, nSamplesOutDec ); - } else { - /* Buffering */ - SKP_memcpy( samplesOut1_tmp[ 0 ], psDec->sStereo.sMid, 2 * sizeof( opus_int16 ) ); - SKP_memcpy( psDec->sStereo.sMid, &samplesOut1_tmp[ 0 ][ nSamplesOutDec ], 2 * sizeof( opus_int16 ) ); - } - - /* Number of output samples */ - *nSamplesOut = SKP_DIV32( nSamplesOutDec * decControl->API_sampleRate, SKP_SMULBB( channel_state[ 0 ].fs_kHz, 1000 ) ); - - /* Set up pointers to temp buffers */ - if( decControl->nChannelsAPI == 2 ) { - resample_out_ptr = samplesOut2_tmp; - } else { - resample_out_ptr = samplesOut; - } - - for( n = 0; n < SKP_min( decControl->nChannelsAPI, decControl->nChannelsInternal ); n++ ) { - /* Resample decoded signal to API_sampleRate */ - ret += silk_resampler( &channel_state[ n ].resampler_state, resample_out_ptr, &samplesOut1_tmp[ n ][ 1 ], nSamplesOutDec ); - - /* Interleave if stereo output and stereo stream */ - if( decControl->nChannelsAPI == 2 && decControl->nChannelsInternal == 2 ) { - for( i = 0; i < *nSamplesOut; i++ ) { - samplesOut[ n + 2 * i ] = resample_out_ptr[ i ]; - } - } - } - - /* Create two channel output from mono stream */ - if( decControl->nChannelsAPI == 2 && decControl->nChannelsInternal == 1 ) { - for( i = 0; i < *nSamplesOut; i++ ) { - samplesOut[ 0 + 2 * i ] = samplesOut[ 1 + 2 * i ] = resample_out_ptr[ i ]; - } - } - - return ret; -} - -/* Getting table of contents for a packet */ -opus_int silk_get_TOC( - const opus_uint8 *payload, /* I Payload data */ - const opus_int nBytesIn, /* I: Number of input bytes */ - const opus_int nFramesPerPayload, /* I: Number of SILK frames per payload */ - silk_TOC_struct *Silk_TOC /* O: Type of content */ -) -{ - opus_int i, flags, ret = SILK_NO_ERROR; - - if( nBytesIn < 1 ) { - return -1; - } - if( nFramesPerPayload < 0 || nFramesPerPayload > 3 ) { - return -1; - } - - SKP_memset( Silk_TOC, 0, sizeof( Silk_TOC ) ); - - /* For stereo, extract the flags for the mid channel */ - flags = SKP_RSHIFT( payload[ 0 ], 7 - nFramesPerPayload ) & ( SKP_LSHIFT( 1, nFramesPerPayload + 1 ) - 1 ); - - Silk_TOC->inbandFECFlag = flags & 1; - for( i = nFramesPerPayload - 1; i >= 0 ; i-- ) { - flags = SKP_RSHIFT( flags, 1 ); - Silk_TOC->VADFlags[ i ] = flags & 1; - Silk_TOC->VADFlag |= flags & 1; - } - - return ret; -} +/*********************************************************************** +Copyright (c) 2006-2011, Skype Limited. All rights reserved. +Redistribution and use in source and binary forms, with or without +modification, (subject to the limitations in the disclaimer below) +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 Skype Limited, nor the names of specific +contributors, may be used to endorse or promote products derived from +this software without specific prior written permission. +NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED +BY THIS LICENSE. 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 "silk_API.h" +#include "silk_main.h" + +/************************/ +/* Decoder Super Struct */ +/************************/ +typedef struct { + silk_decoder_state channel_state[ DECODER_NUM_CHANNELS ]; + stereo_dec_state sStereo; + opus_int nChannelsAPI; + opus_int nChannelsInternal; +} silk_decoder; + +/*********************/ +/* Decoder functions */ +/*********************/ + +opus_int silk_Get_Decoder_Size( opus_int32 *decSizeBytes ) +{ + opus_int ret = SILK_NO_ERROR; + + *decSizeBytes = sizeof( silk_decoder ); + + return ret; +} + +/* Reset decoder state */ +opus_int silk_InitDecoder( + void* decState /* I/O: State */ +) +{ + opus_int n, ret = SILK_NO_ERROR; + silk_decoder_state *channel_state = ((silk_decoder *)decState)->channel_state; + + for( n = 0; n < DECODER_NUM_CHANNELS; n++ ) { + ret = silk_init_decoder( &channel_state[ n ] ); + } + + return ret; +} + +/* Decode a frame */ +opus_int silk_Decode( + void* decState, /* I/O: State */ + silk_DecControlStruct* decControl, /* I/O: Control Structure */ + opus_int lostFlag, /* I: 0: no loss, 1 loss, 2 decode FEC */ + opus_int newPacketFlag, /* I: Indicates first decoder call for this packet */ + ec_dec *psRangeDec, /* I/O Compressor data structure */ + opus_int16 *samplesOut, /* O: Decoded output speech vector */ + opus_int32 *nSamplesOut /* O: Number of samples decoded */ +) +{ + opus_int i, n, prev_fs_kHz, decode_only_middle = 0, ret = SILK_NO_ERROR; + opus_int32 nSamplesOutDec, LBRR_symbol; + opus_int16 samplesOut1_tmp[ 2 ][ MAX_FS_KHZ * MAX_FRAME_LENGTH_MS + 2 ]; + opus_int16 samplesOut2_tmp[ MAX_API_FS_KHZ * MAX_FRAME_LENGTH_MS ]; + opus_int MS_pred_Q13[ 2 ] = { 0 }; + opus_int16 *resample_out_ptr; + silk_decoder *psDec = ( silk_decoder * )decState; + silk_decoder_state *channel_state = psDec->channel_state; + + /**********************************/ + /* Test if first frame in payload */ + /**********************************/ + if( newPacketFlag ) { + for( n = 0; n < decControl->nChannelsInternal; n++ ) { + channel_state[ n ].nFramesDecoded = 0; /* Used to count frames in packet */ + } + } + + /* Save previous sample frequency */ + prev_fs_kHz = channel_state[ 0 ].fs_kHz; + + /* If Mono -> Stereo transition in bitstream: init state of second channel */ + if( decControl->nChannelsInternal > psDec->nChannelsInternal ) { + ret += silk_init_decoder( &channel_state[ 1 ] ); + if( psDec->nChannelsAPI == 2 ) { + SKP_memcpy( &channel_state[ 1 ].resampler_state, &channel_state[ 0 ].resampler_state, sizeof( silk_resampler_state_struct ) ); + } + } + + for( n = 0; n < decControl->nChannelsInternal; n++ ) { + if( channel_state[ n ].nFramesDecoded == 0 ) { + opus_int fs_kHz_dec; + if( decControl->payloadSize_ms == 0 ) { + /* Assuming packet loss, use 10 ms */ + channel_state[ n ].nFramesPerPacket = 1; + channel_state[ n ].nb_subfr = 2; + } else if( decControl->payloadSize_ms == 10 ) { + channel_state[ n ].nFramesPerPacket = 1; + channel_state[ n ].nb_subfr = 2; + } else if( decControl->payloadSize_ms == 20 ) { + channel_state[ n ].nFramesPerPacket = 1; + channel_state[ n ].nb_subfr = 4; + } else if( decControl->payloadSize_ms == 40 ) { + channel_state[ n ].nFramesPerPacket = 2; + channel_state[ n ].nb_subfr = 4; + } else if( decControl->payloadSize_ms == 60 ) { + channel_state[ n ].nFramesPerPacket = 3; + channel_state[ n ].nb_subfr = 4; + } else { + SKP_assert( 0 ); + return SILK_DEC_INVALID_FRAME_SIZE; + } + fs_kHz_dec = ( decControl->internalSampleRate >> 10 ) + 1; + if( fs_kHz_dec != 8 && fs_kHz_dec != 12 && fs_kHz_dec != 16 ) { + SKP_assert( 0 ); + return SILK_DEC_INVALID_SAMPLING_FREQUENCY; + } + silk_decoder_set_fs( &channel_state[ n ], fs_kHz_dec ); + } + } + + /* Initialize resampler when switching internal or external sampling frequency */ + if( prev_fs_kHz != channel_state[ 0 ].fs_kHz || channel_state[ 0 ].prev_API_sampleRate != decControl->API_sampleRate ) { + ret = silk_resampler_init( &channel_state[ 0 ].resampler_state, SKP_SMULBB( channel_state[ 0 ].fs_kHz, 1000 ), decControl->API_sampleRate ); + if( decControl->nChannelsAPI == 2 && decControl->nChannelsInternal == 2 ) { + SKP_memcpy( &channel_state[ 1 ].resampler_state, &channel_state[ 0 ].resampler_state, sizeof( silk_resampler_state_struct ) ); + } + } + channel_state[ 0 ].prev_API_sampleRate = decControl->API_sampleRate; + if( decControl->nChannelsAPI == 2 && decControl->nChannelsInternal == 2 && ( psDec->nChannelsAPI == 1 || psDec->nChannelsInternal == 1 ) ) { + SKP_memset( psDec->sStereo.pred_prev_Q13, 0, sizeof( psDec->sStereo.pred_prev_Q13 ) ); + SKP_memset( psDec->sStereo.sSide, 0, sizeof( psDec->sStereo.sSide ) ); + } + psDec->nChannelsAPI = decControl->nChannelsAPI; + psDec->nChannelsInternal = decControl->nChannelsInternal; + + if( decControl->API_sampleRate > MAX_API_FS_KHZ * 1000 || decControl->API_sampleRate < 8000 ) { + ret = SILK_DEC_INVALID_SAMPLING_FREQUENCY; + return( ret ); + } + + if( lostFlag != FLAG_PACKET_LOST && channel_state[ 0 ].nFramesDecoded == 0 ) { + /* First decoder call for this payload */ + /* Decode VAD flags and LBRR flag */ + for( n = 0; n < decControl->nChannelsInternal; n++ ) { + for( i = 0; i < channel_state[ n ].nFramesPerPacket; i++ ) { + channel_state[ n ].VAD_flags[ i ] = ec_dec_bit_logp(psRangeDec, 1); + } + channel_state[ n ].LBRR_flag = ec_dec_bit_logp(psRangeDec, 1); + } + /* Decode LBRR flags */ + for( n = 0; n < decControl->nChannelsInternal; n++ ) { + SKP_memset( channel_state[ n ].LBRR_flags, 0, sizeof( channel_state[ n ].LBRR_flags ) ); + if( channel_state[ n ].LBRR_flag ) { + if( channel_state[ n ].nFramesPerPacket == 1 ) { + channel_state[ n ].LBRR_flags[ 0 ] = 1; + } else { + LBRR_symbol = ec_dec_icdf( psRangeDec, silk_LBRR_flags_iCDF_ptr[ channel_state[ n ].nFramesPerPacket - 2 ], 8 ) + 1; + for( i = 0; i < channel_state[ n ].nFramesPerPacket; i++ ) { + channel_state[ n ].LBRR_flags[ i ] = SKP_RSHIFT( LBRR_symbol, i ) & 1; + } + } + } + } + + if( lostFlag == FLAG_DECODE_NORMAL ) { + /* Regular decoding: skip all LBRR data */ + for( i = 0; i < channel_state[ 0 ].nFramesPerPacket; i++ ) { + for( n = 0; n < decControl->nChannelsInternal; n++ ) { + if( channel_state[ n ].LBRR_flags[ i ] ) { + opus_int pulses[ MAX_FRAME_LENGTH ]; + if( decControl->nChannelsInternal == 2 && n == 0 ) { + silk_stereo_decode_pred( psRangeDec, &decode_only_middle, MS_pred_Q13 ); + } + silk_decode_indices( &channel_state[ n ], psRangeDec, i, 1 ); + silk_decode_pulses( psRangeDec, pulses, channel_state[ n ].indices.signalType, + channel_state[ n ].indices.quantOffsetType, channel_state[ n ].frame_length ); + } + } + } + } + } + + /* Get MS predictor index */ + if( decControl->nChannelsInternal == 2 ) { + if( lostFlag == FLAG_DECODE_NORMAL || + ( lostFlag == FLAG_DECODE_LBRR && channel_state[ 0 ].LBRR_flags[ channel_state[ 0 ].nFramesDecoded ] == 1 ) ) + { + silk_stereo_decode_pred( psRangeDec, &decode_only_middle, MS_pred_Q13 ); + } else { + SKP_memcpy( MS_pred_Q13, &psDec->sStereo.pred_prev_Q13, sizeof( MS_pred_Q13 ) ); + } + } + + /* Call decoder for one frame */ + for( n = 0; n < decControl->nChannelsInternal; n++ ) { + if( n == 0 || decode_only_middle == 0 ) { + ret += silk_decode_frame( &channel_state[ n ], psRangeDec, &samplesOut1_tmp[ n ][ 2 ], &nSamplesOutDec, lostFlag ); + } else { + SKP_memset( &samplesOut1_tmp[ n ][ 2 ], 0, nSamplesOutDec * sizeof( opus_int16 ) ); + } + } + + if( decControl->nChannelsAPI == 2 && decControl->nChannelsInternal == 2 ) { + /* Convert Mid/Side to Left/Right */ + silk_stereo_MS_to_LR( &psDec->sStereo, samplesOut1_tmp[ 0 ], samplesOut1_tmp[ 1 ], MS_pred_Q13, channel_state[ 0 ].fs_kHz, nSamplesOutDec ); + } else { + /* Buffering */ + SKP_memcpy( samplesOut1_tmp[ 0 ], psDec->sStereo.sMid, 2 * sizeof( opus_int16 ) ); + SKP_memcpy( psDec->sStereo.sMid, &samplesOut1_tmp[ 0 ][ nSamplesOutDec ], 2 * sizeof( opus_int16 ) ); + } + + /* Number of output samples */ + *nSamplesOut = SKP_DIV32( nSamplesOutDec * decControl->API_sampleRate, SKP_SMULBB( channel_state[ 0 ].fs_kHz, 1000 ) ); + + /* Set up pointers to temp buffers */ + if( decControl->nChannelsAPI == 2 ) { + resample_out_ptr = samplesOut2_tmp; + } else { + resample_out_ptr = samplesOut; + } + + for( n = 0; n < SKP_min( decControl->nChannelsAPI, decControl->nChannelsInternal ); n++ ) { + /* Resample decoded signal to API_sampleRate */ + ret += silk_resampler( &channel_state[ n ].resampler_state, resample_out_ptr, &samplesOut1_tmp[ n ][ 1 ], nSamplesOutDec ); + + /* Interleave if stereo output and stereo stream */ + if( decControl->nChannelsAPI == 2 && decControl->nChannelsInternal == 2 ) { + for( i = 0; i < *nSamplesOut; i++ ) { + samplesOut[ n + 2 * i ] = resample_out_ptr[ i ]; + } + } + } + + /* Create two channel output from mono stream */ + if( decControl->nChannelsAPI == 2 && decControl->nChannelsInternal == 1 ) { + for( i = 0; i < *nSamplesOut; i++ ) { + samplesOut[ 0 + 2 * i ] = samplesOut[ 1 + 2 * i ] = resample_out_ptr[ i ]; + } + } + + return ret; +} + +/* Getting table of contents for a packet */ +opus_int silk_get_TOC( + const opus_uint8 *payload, /* I Payload data */ + const opus_int nBytesIn, /* I: Number of input bytes */ + const opus_int nFramesPerPayload, /* I: Number of SILK frames per payload */ + silk_TOC_struct *Silk_TOC /* O: Type of content */ +) +{ + opus_int i, flags, ret = SILK_NO_ERROR; + + if( nBytesIn < 1 ) { + return -1; + } + if( nFramesPerPayload < 0 || nFramesPerPayload > 3 ) { + return -1; + } + + SKP_memset( Silk_TOC, 0, sizeof( Silk_TOC ) ); + + /* For stereo, extract the flags for the mid channel */ + flags = SKP_RSHIFT( payload[ 0 ], 7 - nFramesPerPayload ) & ( SKP_LSHIFT( 1, nFramesPerPayload + 1 ) - 1 ); + + Silk_TOC->inbandFECFlag = flags & 1; + for( i = nFramesPerPayload - 1; i >= 0 ; i-- ) { + flags = SKP_RSHIFT( flags, 1 ); + Silk_TOC->VADFlags[ i ] = flags & 1; + Silk_TOC->VADFlag |= flags & 1; + } + + return ret; +} diff --git a/silk/silk_decode_core.c b/silk/silk_decode_core.c index e1b7dbd0c..bc1a81d6b 100644 --- a/silk/silk_decode_core.c +++ b/silk/silk_decode_core.c @@ -1,224 +1,224 @@ -/*********************************************************************** -Copyright (c) 2006-2011, Skype Limited. All rights reserved. -Redistribution and use in source and binary forms, with or without -modification, (subject to the limitations in the disclaimer below) -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 Skype Limited, nor the names of specific -contributors, may be used to endorse or promote products derived from -this software without specific prior written permission. -NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED -BY THIS LICENSE. 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. -***********************************************************************/ - -#include "silk_main.h" - -/**********************************************************/ -/* Core decoder. Performs inverse NSQ operation LTP + LPC */ -/**********************************************************/ -void silk_decode_core( - silk_decoder_state *psDec, /* I/O Decoder state */ - silk_decoder_control *psDecCtrl, /* I Decoder control */ - opus_int16 xq[], /* O Decoded speech */ - const opus_int pulses[ MAX_FRAME_LENGTH ] /* I Pulse signal */ -) -{ - opus_int i, j, k, lag = 0, start_idx, sLTP_buf_idx, NLSF_interpolation_flag, signalType; - opus_int16 *A_Q12, *B_Q14, *pxq, A_Q12_tmp[ MAX_LPC_ORDER ]; - opus_int16 sLTP[ MAX_FRAME_LENGTH ]; - opus_int32 LTP_pred_Q14, LPC_pred_Q10, Gain_Q16, inv_gain_Q16, inv_gain_Q32, gain_adj_Q16, rand_seed, offset_Q10; - opus_int32 *pred_lag_ptr, *pexc_Q10, *pres_Q10; - opus_int32 res_Q10[ MAX_SUB_FRAME_LENGTH ]; - opus_int32 vec_Q10[ MAX_SUB_FRAME_LENGTH ]; - - SKP_assert( psDec->prev_inv_gain_Q16 != 0 ); - - offset_Q10 = silk_Quantization_Offsets_Q10[ psDec->indices.signalType >> 1 ][ psDec->indices.quantOffsetType ]; - - if( psDec->indices.NLSFInterpCoef_Q2 < 1 << 2 ) { - NLSF_interpolation_flag = 1; - } else { - NLSF_interpolation_flag = 0; - } - - /* Decode excitation */ - rand_seed = psDec->indices.Seed; - for( i = 0; i < psDec->frame_length; i++ ) { - rand_seed = SKP_RAND( rand_seed ); - psDec->exc_Q10[ i ] = SKP_LSHIFT( ( opus_int32 )pulses[ i ], 10 ); - if( psDec->exc_Q10[ i ] > 0 ) { - psDec->exc_Q10[ i ] -= QUANT_LEVEL_ADJUST_Q10; - } else - if( psDec->exc_Q10[ i ] < 0 ) { - psDec->exc_Q10[ i ] += QUANT_LEVEL_ADJUST_Q10; - } - psDec->exc_Q10[ i ] += offset_Q10; - psDec->exc_Q10[ i ] ^= SKP_RSHIFT( rand_seed, 31 ); - - rand_seed += pulses[ i ]; - } - -#ifdef SAVE_ALL_INTERNAL_DATA - DEBUG_STORE_DATA( dec_q.dat, pulses, psDec->frame_length * sizeof( opus_int ) ); -#endif - - pexc_Q10 = psDec->exc_Q10; - pxq = &psDec->outBuf[ psDec->ltp_mem_length ]; - sLTP_buf_idx = psDec->ltp_mem_length; - /* Loop over subframes */ - for( k = 0; k < psDec->nb_subfr; k++ ) { - pres_Q10 = res_Q10; - A_Q12 = psDecCtrl->PredCoef_Q12[ k >> 1 ]; - - /* Preload LPC coeficients to array on stack. Gives small performance gain */ - SKP_memcpy( A_Q12_tmp, A_Q12, psDec->LPC_order * sizeof( opus_int16 ) ); - B_Q14 = &psDecCtrl->LTPCoef_Q14[ k * LTP_ORDER ]; - Gain_Q16 = psDecCtrl->Gains_Q16[ k ]; - signalType = psDec->indices.signalType; - - inv_gain_Q16 = silk_INVERSE32_varQ( SKP_max( Gain_Q16, 1 ), 32 ); - inv_gain_Q16 = SKP_min( inv_gain_Q16, SKP_int16_MAX ); - - /* Calculate Gain adjustment factor */ - gain_adj_Q16 = 1 << 16; - if( inv_gain_Q16 != psDec->prev_inv_gain_Q16 ) { - gain_adj_Q16 = silk_DIV32_varQ( inv_gain_Q16, psDec->prev_inv_gain_Q16, 16 ); - - /* Scale short term state */ - for( i = 0; i < MAX_LPC_ORDER; i++ ) { - psDec->sLPC_Q14[ i ] = SKP_SMULWW( gain_adj_Q16, psDec->sLPC_Q14[ i ] ); - } - } - - /* Save inv_gain */ - SKP_assert( inv_gain_Q16 != 0 ); - psDec->prev_inv_gain_Q16 = inv_gain_Q16; - - /* Avoid abrupt transition from voiced PLC to unvoiced normal decoding */ - if( psDec->lossCnt && psDec->prevSignalType == TYPE_VOICED && - psDec->indices.signalType != TYPE_VOICED && k < MAX_NB_SUBFR/2 ) { - - SKP_memset( B_Q14, 0, LTP_ORDER * sizeof( opus_int16 ) ); - B_Q14[ LTP_ORDER/2 ] = SILK_FIX_CONST( 0.25, 14 ); - - signalType = TYPE_VOICED; - psDecCtrl->pitchL[ k ] = psDec->lagPrev; - } - - if( signalType == TYPE_VOICED ) { - /* Voiced */ - lag = psDecCtrl->pitchL[ k ]; - - /* Re-whitening */ - if( ( k & ( 3 - SKP_LSHIFT( NLSF_interpolation_flag, 1 ) ) ) == 0 ) { - /* Rewhiten with new A coefs */ - start_idx = psDec->ltp_mem_length - lag - psDec->LPC_order - LTP_ORDER / 2; - SKP_assert( start_idx > 0 ); - - silk_LPC_analysis_filter( &sLTP[ start_idx ], &psDec->outBuf[ start_idx + k * psDec->subfr_length ], - A_Q12, psDec->ltp_mem_length - start_idx, psDec->LPC_order ); - - /* After rewhitening the LTP state is unscaled */ - inv_gain_Q32 = SKP_LSHIFT( inv_gain_Q16, 16 ); - if( k == 0 ) { - /* Do LTP downscaling */ - inv_gain_Q32 = SKP_LSHIFT( SKP_SMULWB( inv_gain_Q32, psDecCtrl->LTP_scale_Q14 ), 2 ); - } - for( i = 0; i < lag + LTP_ORDER/2; i++ ) { - psDec->sLTP_Q16[ sLTP_buf_idx - i - 1 ] = SKP_SMULWB( inv_gain_Q32, sLTP[ psDec->ltp_mem_length - i - 1 ] ); - } - } else { - /* Update LTP state when Gain changes */ - if( gain_adj_Q16 != 1 << 16 ) { - for( i = 0; i < lag + LTP_ORDER/2; i++ ) { - psDec->sLTP_Q16[ sLTP_buf_idx - i - 1 ] = SKP_SMULWW( gain_adj_Q16, psDec->sLTP_Q16[ sLTP_buf_idx - i - 1 ] ); - } - } - } - } - - /* Long-term prediction */ - if( signalType == TYPE_VOICED ) { - /* Setup pointer */ - pred_lag_ptr = &psDec->sLTP_Q16[ sLTP_buf_idx - lag + LTP_ORDER / 2 ]; - for( i = 0; i < psDec->subfr_length; i++ ) { - /* Unrolled loop */ - LTP_pred_Q14 = SKP_SMULWB( pred_lag_ptr[ 0 ], B_Q14[ 0 ] ); - LTP_pred_Q14 = SKP_SMLAWB( LTP_pred_Q14, pred_lag_ptr[ -1 ], B_Q14[ 1 ] ); - LTP_pred_Q14 = SKP_SMLAWB( LTP_pred_Q14, pred_lag_ptr[ -2 ], B_Q14[ 2 ] ); - LTP_pred_Q14 = SKP_SMLAWB( LTP_pred_Q14, pred_lag_ptr[ -3 ], B_Q14[ 3 ] ); - LTP_pred_Q14 = SKP_SMLAWB( LTP_pred_Q14, pred_lag_ptr[ -4 ], B_Q14[ 4 ] ); - pred_lag_ptr++; - - /* Generate LPC excitation */ - pres_Q10[ i ] = SKP_ADD32( pexc_Q10[ i ], SKP_RSHIFT_ROUND( LTP_pred_Q14, 4 ) ); - - /* Update states */ - psDec->sLTP_Q16[ sLTP_buf_idx ] = SKP_LSHIFT( pres_Q10[ i ], 6 ); - sLTP_buf_idx++; - } - } else { - pres_Q10 = pexc_Q10; - } - -#ifdef SAVE_ALL_INTERNAL_DATA - DEBUG_STORE_DATA( dec_exc_Q10.dat, pexc_Q10, psDec->subfr_length * sizeof( opus_int32 ) ); - DEBUG_STORE_DATA( dec_res_Q10.dat, pres_Q10, psDec->subfr_length * sizeof( opus_int32 ) ); -#endif - - for( i = 0; i < psDec->subfr_length; i++ ) { - /* Partially unrolled */ - LPC_pred_Q10 = SKP_SMULWB( psDec->sLPC_Q14[ MAX_LPC_ORDER + i - 1 ], A_Q12_tmp[ 0 ] ); - LPC_pred_Q10 = SKP_SMLAWB( LPC_pred_Q10, psDec->sLPC_Q14[ MAX_LPC_ORDER + i - 2 ], A_Q12_tmp[ 1 ] ); - LPC_pred_Q10 = SKP_SMLAWB( LPC_pred_Q10, psDec->sLPC_Q14[ MAX_LPC_ORDER + i - 3 ], A_Q12_tmp[ 2 ] ); - LPC_pred_Q10 = SKP_SMLAWB( LPC_pred_Q10, psDec->sLPC_Q14[ MAX_LPC_ORDER + i - 4 ], A_Q12_tmp[ 3 ] ); - LPC_pred_Q10 = SKP_SMLAWB( LPC_pred_Q10, psDec->sLPC_Q14[ MAX_LPC_ORDER + i - 5 ], A_Q12_tmp[ 4 ] ); - LPC_pred_Q10 = SKP_SMLAWB( LPC_pred_Q10, psDec->sLPC_Q14[ MAX_LPC_ORDER + i - 6 ], A_Q12_tmp[ 5 ] ); - LPC_pred_Q10 = SKP_SMLAWB( LPC_pred_Q10, psDec->sLPC_Q14[ MAX_LPC_ORDER + i - 7 ], A_Q12_tmp[ 6 ] ); - LPC_pred_Q10 = SKP_SMLAWB( LPC_pred_Q10, psDec->sLPC_Q14[ MAX_LPC_ORDER + i - 8 ], A_Q12_tmp[ 7 ] ); - LPC_pred_Q10 = SKP_SMLAWB( LPC_pred_Q10, psDec->sLPC_Q14[ MAX_LPC_ORDER + i - 9 ], A_Q12_tmp[ 8 ] ); - LPC_pred_Q10 = SKP_SMLAWB( LPC_pred_Q10, psDec->sLPC_Q14[ MAX_LPC_ORDER + i - 10 ], A_Q12_tmp[ 9 ] ); - for( j = 10; j < psDec->LPC_order; j++ ) { - LPC_pred_Q10 = SKP_SMLAWB( LPC_pred_Q10, psDec->sLPC_Q14[ MAX_LPC_ORDER + i - j - 1 ], A_Q12_tmp[ j ] ); - } - - /* Add prediction to LPC excitation */ - vec_Q10[ i ] = SKP_ADD32( pres_Q10[ i ], LPC_pred_Q10 ); - - /* Update states */ - psDec->sLPC_Q14[ MAX_LPC_ORDER + i ] = SKP_LSHIFT( vec_Q10[ i ], 4 ); - } - - /* Scale with Gain */ - for( i = 0; i < psDec->subfr_length; i++ ) { - pxq[ i ] = ( opus_int16 )SKP_SAT16( SKP_RSHIFT_ROUND( SKP_SMULWW( vec_Q10[ i ], Gain_Q16 ), 10 ) ); - } - - /* Update LPC filter state */ - SKP_memcpy( psDec->sLPC_Q14, &psDec->sLPC_Q14[ psDec->subfr_length ], MAX_LPC_ORDER * sizeof( opus_int32 ) ); - pexc_Q10 += psDec->subfr_length; - pxq += psDec->subfr_length; - } - - /* Copy to output */ - SKP_memcpy( xq, &psDec->outBuf[ psDec->ltp_mem_length ], psDec->frame_length * sizeof( opus_int16 ) ); - -#ifdef SAVE_ALL_INTERNAL_DATA - DEBUG_STORE_DATA( dec_sLTP_Q16.dat, &psDec->sLTP_Q16[ psDec->ltp_mem_length ], psDec->frame_length * sizeof( opus_int32 )); - DEBUG_STORE_DATA( dec_xq.dat, xq, psDec->frame_length * sizeof( opus_int16 ) ); -#endif -} +/*********************************************************************** +Copyright (c) 2006-2011, Skype Limited. All rights reserved. +Redistribution and use in source and binary forms, with or without +modification, (subject to the limitations in the disclaimer below) +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 Skype Limited, nor the names of specific +contributors, may be used to endorse or promote products derived from +this software without specific prior written permission. +NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED +BY THIS LICENSE. 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. +***********************************************************************/ + +#include "silk_main.h" + +/**********************************************************/ +/* Core decoder. Performs inverse NSQ operation LTP + LPC */ +/**********************************************************/ +void silk_decode_core( + silk_decoder_state *psDec, /* I/O Decoder state */ + silk_decoder_control *psDecCtrl, /* I Decoder control */ + opus_int16 xq[], /* O Decoded speech */ + const opus_int pulses[ MAX_FRAME_LENGTH ] /* I Pulse signal */ +) +{ + opus_int i, j, k, lag = 0, start_idx, sLTP_buf_idx, NLSF_interpolation_flag, signalType; + opus_int16 *A_Q12, *B_Q14, *pxq, A_Q12_tmp[ MAX_LPC_ORDER ]; + opus_int16 sLTP[ MAX_FRAME_LENGTH ]; + opus_int32 LTP_pred_Q14, LPC_pred_Q10, Gain_Q16, inv_gain_Q16, inv_gain_Q32, gain_adj_Q16, rand_seed, offset_Q10; + opus_int32 *pred_lag_ptr, *pexc_Q10, *pres_Q10; + opus_int32 res_Q10[ MAX_SUB_FRAME_LENGTH ]; + opus_int32 vec_Q10[ MAX_SUB_FRAME_LENGTH ]; + + SKP_assert( psDec->prev_inv_gain_Q16 != 0 ); + + offset_Q10 = silk_Quantization_Offsets_Q10[ psDec->indices.signalType >> 1 ][ psDec->indices.quantOffsetType ]; + + if( psDec->indices.NLSFInterpCoef_Q2 < 1 << 2 ) { + NLSF_interpolation_flag = 1; + } else { + NLSF_interpolation_flag = 0; + } + + /* Decode excitation */ + rand_seed = psDec->indices.Seed; + for( i = 0; i < psDec->frame_length; i++ ) { + rand_seed = SKP_RAND( rand_seed ); + psDec->exc_Q10[ i ] = SKP_LSHIFT( ( opus_int32 )pulses[ i ], 10 ); + if( psDec->exc_Q10[ i ] > 0 ) { + psDec->exc_Q10[ i ] -= QUANT_LEVEL_ADJUST_Q10; + } else + if( psDec->exc_Q10[ i ] < 0 ) { + psDec->exc_Q10[ i ] += QUANT_LEVEL_ADJUST_Q10; + } + psDec->exc_Q10[ i ] += offset_Q10; + psDec->exc_Q10[ i ] ^= SKP_RSHIFT( rand_seed, 31 ); + + rand_seed += pulses[ i ]; + } + +#ifdef SAVE_ALL_INTERNAL_DATA + DEBUG_STORE_DATA( dec_q.dat, pulses, psDec->frame_length * sizeof( opus_int ) ); +#endif + + pexc_Q10 = psDec->exc_Q10; + pxq = &psDec->outBuf[ psDec->ltp_mem_length ]; + sLTP_buf_idx = psDec->ltp_mem_length; + /* Loop over subframes */ + for( k = 0; k < psDec->nb_subfr; k++ ) { + pres_Q10 = res_Q10; + A_Q12 = psDecCtrl->PredCoef_Q12[ k >> 1 ]; + + /* Preload LPC coeficients to array on stack. Gives small performance gain */ + SKP_memcpy( A_Q12_tmp, A_Q12, psDec->LPC_order * sizeof( opus_int16 ) ); + B_Q14 = &psDecCtrl->LTPCoef_Q14[ k * LTP_ORDER ]; + Gain_Q16 = psDecCtrl->Gains_Q16[ k ]; + signalType = psDec->indices.signalType; + + inv_gain_Q16 = silk_INVERSE32_varQ( SKP_max( Gain_Q16, 1 ), 32 ); + inv_gain_Q16 = SKP_min( inv_gain_Q16, SKP_int16_MAX ); + + /* Calculate Gain adjustment factor */ + gain_adj_Q16 = 1 << 16; + if( inv_gain_Q16 != psDec->prev_inv_gain_Q16 ) { + gain_adj_Q16 = silk_DIV32_varQ( inv_gain_Q16, psDec->prev_inv_gain_Q16, 16 ); + + /* Scale short term state */ + for( i = 0; i < MAX_LPC_ORDER; i++ ) { + psDec->sLPC_Q14[ i ] = SKP_SMULWW( gain_adj_Q16, psDec->sLPC_Q14[ i ] ); + } + } + + /* Save inv_gain */ + SKP_assert( inv_gain_Q16 != 0 ); + psDec->prev_inv_gain_Q16 = inv_gain_Q16; + + /* Avoid abrupt transition from voiced PLC to unvoiced normal decoding */ + if( psDec->lossCnt && psDec->prevSignalType == TYPE_VOICED && + psDec->indices.signalType != TYPE_VOICED && k < MAX_NB_SUBFR/2 ) { + + SKP_memset( B_Q14, 0, LTP_ORDER * sizeof( opus_int16 ) ); + B_Q14[ LTP_ORDER/2 ] = SILK_FIX_CONST( 0.25, 14 ); + + signalType = TYPE_VOICED; + psDecCtrl->pitchL[ k ] = psDec->lagPrev; + } + + if( signalType == TYPE_VOICED ) { + /* Voiced */ + lag = psDecCtrl->pitchL[ k ]; + + /* Re-whitening */ + if( ( k & ( 3 - SKP_LSHIFT( NLSF_interpolation_flag, 1 ) ) ) == 0 ) { + /* Rewhiten with new A coefs */ + start_idx = psDec->ltp_mem_length - lag - psDec->LPC_order - LTP_ORDER / 2; + SKP_assert( start_idx > 0 ); + + silk_LPC_analysis_filter( &sLTP[ start_idx ], &psDec->outBuf[ start_idx + k * psDec->subfr_length ], + A_Q12, psDec->ltp_mem_length - start_idx, psDec->LPC_order ); + + /* After rewhitening the LTP state is unscaled */ + inv_gain_Q32 = SKP_LSHIFT( inv_gain_Q16, 16 ); + if( k == 0 ) { + /* Do LTP downscaling */ + inv_gain_Q32 = SKP_LSHIFT( SKP_SMULWB( inv_gain_Q32, psDecCtrl->LTP_scale_Q14 ), 2 ); + } + for( i = 0; i < lag + LTP_ORDER/2; i++ ) { + psDec->sLTP_Q16[ sLTP_buf_idx - i - 1 ] = SKP_SMULWB( inv_gain_Q32, sLTP[ psDec->ltp_mem_length - i - 1 ] ); + } + } else { + /* Update LTP state when Gain changes */ + if( gain_adj_Q16 != 1 << 16 ) { + for( i = 0; i < lag + LTP_ORDER/2; i++ ) { + psDec->sLTP_Q16[ sLTP_buf_idx - i - 1 ] = SKP_SMULWW( gain_adj_Q16, psDec->sLTP_Q16[ sLTP_buf_idx - i - 1 ] ); + } + } + } + } + + /* Long-term prediction */ + if( signalType == TYPE_VOICED ) { + /* Setup pointer */ + pred_lag_ptr = &psDec->sLTP_Q16[ sLTP_buf_idx - lag + LTP_ORDER / 2 ]; + for( i = 0; i < psDec->subfr_length; i++ ) { + /* Unrolled loop */ + LTP_pred_Q14 = SKP_SMULWB( pred_lag_ptr[ 0 ], B_Q14[ 0 ] ); + LTP_pred_Q14 = SKP_SMLAWB( LTP_pred_Q14, pred_lag_ptr[ -1 ], B_Q14[ 1 ] ); + LTP_pred_Q14 = SKP_SMLAWB( LTP_pred_Q14, pred_lag_ptr[ -2 ], B_Q14[ 2 ] ); + LTP_pred_Q14 = SKP_SMLAWB( LTP_pred_Q14, pred_lag_ptr[ -3 ], B_Q14[ 3 ] ); + LTP_pred_Q14 = SKP_SMLAWB( LTP_pred_Q14, pred_lag_ptr[ -4 ], B_Q14[ 4 ] ); + pred_lag_ptr++; + + /* Generate LPC excitation */ + pres_Q10[ i ] = SKP_ADD32( pexc_Q10[ i ], SKP_RSHIFT_ROUND( LTP_pred_Q14, 4 ) ); + + /* Update states */ + psDec->sLTP_Q16[ sLTP_buf_idx ] = SKP_LSHIFT( pres_Q10[ i ], 6 ); + sLTP_buf_idx++; + } + } else { + pres_Q10 = pexc_Q10; + } + +#ifdef SAVE_ALL_INTERNAL_DATA + DEBUG_STORE_DATA( dec_exc_Q10.dat, pexc_Q10, psDec->subfr_length * sizeof( opus_int32 ) ); + DEBUG_STORE_DATA( dec_res_Q10.dat, pres_Q10, psDec->subfr_length * sizeof( opus_int32 ) ); +#endif + + for( i = 0; i < psDec->subfr_length; i++ ) { + /* Partially unrolled */ + LPC_pred_Q10 = SKP_SMULWB( psDec->sLPC_Q14[ MAX_LPC_ORDER + i - 1 ], A_Q12_tmp[ 0 ] ); + LPC_pred_Q10 = SKP_SMLAWB( LPC_pred_Q10, psDec->sLPC_Q14[ MAX_LPC_ORDER + i - 2 ], A_Q12_tmp[ 1 ] ); + LPC_pred_Q10 = SKP_SMLAWB( LPC_pred_Q10, psDec->sLPC_Q14[ MAX_LPC_ORDER + i - 3 ], A_Q12_tmp[ 2 ] ); + LPC_pred_Q10 = SKP_SMLAWB( LPC_pred_Q10, psDec->sLPC_Q14[ MAX_LPC_ORDER + i - 4 ], A_Q12_tmp[ 3 ] ); + LPC_pred_Q10 = SKP_SMLAWB( LPC_pred_Q10, psDec->sLPC_Q14[ MAX_LPC_ORDER + i - 5 ], A_Q12_tmp[ 4 ] ); + LPC_pred_Q10 = SKP_SMLAWB( LPC_pred_Q10, psDec->sLPC_Q14[ MAX_LPC_ORDER + i - 6 ], A_Q12_tmp[ 5 ] ); + LPC_pred_Q10 = SKP_SMLAWB( LPC_pred_Q10, psDec->sLPC_Q14[ MAX_LPC_ORDER + i - 7 ], A_Q12_tmp[ 6 ] ); + LPC_pred_Q10 = SKP_SMLAWB( LPC_pred_Q10, psDec->sLPC_Q14[ MAX_LPC_ORDER + i - 8 ], A_Q12_tmp[ 7 ] ); + LPC_pred_Q10 = SKP_SMLAWB( LPC_pred_Q10, psDec->sLPC_Q14[ MAX_LPC_ORDER + i - 9 ], A_Q12_tmp[ 8 ] ); + LPC_pred_Q10 = SKP_SMLAWB( LPC_pred_Q10, psDec->sLPC_Q14[ MAX_LPC_ORDER + i - 10 ], A_Q12_tmp[ 9 ] ); + for( j = 10; j < psDec->LPC_order; j++ ) { + LPC_pred_Q10 = SKP_SMLAWB( LPC_pred_Q10, psDec->sLPC_Q14[ MAX_LPC_ORDER + i - j - 1 ], A_Q12_tmp[ j ] ); + } + + /* Add prediction to LPC excitation */ + vec_Q10[ i ] = SKP_ADD32( pres_Q10[ i ], LPC_pred_Q10 ); + + /* Update states */ + psDec->sLPC_Q14[ MAX_LPC_ORDER + i ] = SKP_LSHIFT( vec_Q10[ i ], 4 ); + } + + /* Scale with Gain */ + for( i = 0; i < psDec->subfr_length; i++ ) { + pxq[ i ] = ( opus_int16 )SKP_SAT16( SKP_RSHIFT_ROUND( SKP_SMULWW( vec_Q10[ i ], Gain_Q16 ), 10 ) ); + } + + /* Update LPC filter state */ + SKP_memcpy( psDec->sLPC_Q14, &psDec->sLPC_Q14[ psDec->subfr_length ], MAX_LPC_ORDER * sizeof( opus_int32 ) ); + pexc_Q10 += psDec->subfr_length; + pxq += psDec->subfr_length; + } + + /* Copy to output */ + SKP_memcpy( xq, &psDec->outBuf[ psDec->ltp_mem_length ], psDec->frame_length * sizeof( opus_int16 ) ); + +#ifdef SAVE_ALL_INTERNAL_DATA + DEBUG_STORE_DATA( dec_sLTP_Q16.dat, &psDec->sLTP_Q16[ psDec->ltp_mem_length ], psDec->frame_length * sizeof( opus_int32 )); + DEBUG_STORE_DATA( dec_xq.dat, xq, psDec->frame_length * sizeof( opus_int16 ) ); +#endif +} diff --git a/silk/silk_decode_frame.c b/silk/silk_decode_frame.c index 731bc83cb..87285089e 100644 --- a/silk/silk_decode_frame.c +++ b/silk/silk_decode_frame.c @@ -1,134 +1,133 @@ -/*********************************************************************** -Copyright (c) 2006-2011, Skype Limited. All rights reserved. -Redistribution and use in source and binary forms, with or without -modification, (subject to the limitations in the disclaimer below) -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 Skype Limited, nor the names of specific -contributors, may be used to endorse or promote products derived from -this software without specific prior written permission. -NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED -BY THIS LICENSE. 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. -***********************************************************************/ - -#include "silk_main.h" -#include "silk_PLC.h" - -/****************/ -/* Decode frame */ -/****************/ -opus_int silk_decode_frame( - silk_decoder_state *psDec, /* I/O Pointer to Silk decoder state */ - ec_dec *psRangeDec, /* I/O Compressor data structure */ - opus_int16 pOut[], /* O Pointer to output speech frame */ - opus_int32 *pN, /* O Pointer to size of output frame */ - opus_int lostFlag /* I 0: no loss, 1 loss, 2 decode fec */ -) -{ - silk_decoder_control sDecCtrl; - opus_int L, mv_len, ret = 0; - opus_int pulses[ MAX_FRAME_LENGTH ]; - -TIC(DECODE_FRAME) - - L = psDec->frame_length; - sDecCtrl.LTP_scale_Q14 = 0; - - /* Safety checks */ - SKP_assert( L > 0 && L <= MAX_FRAME_LENGTH ); - - if( lostFlag == FLAG_DECODE_NORMAL || - ( lostFlag == FLAG_DECODE_LBRR && psDec->LBRR_flags[ psDec->nFramesDecoded ] == 1 ) ) - { - /*********************************************/ - /* Decode quantization indices of side info */ - /*********************************************/ -TIC(decode_indices) - silk_decode_indices( psDec, psRangeDec, psDec->nFramesDecoded, lostFlag ); -TOC(decode_indices) - - /*********************************************/ - /* Decode quantization indices of excitation */ - /*********************************************/ -TIC(decode_pulses) - silk_decode_pulses( psRangeDec, pulses, psDec->indices.signalType, - psDec->indices.quantOffsetType, psDec->frame_length ); -TOC(decode_pulses) - - /********************************************/ - /* Decode parameters and pulse signal */ - /********************************************/ -TIC(decode_params) - silk_decode_parameters( psDec, &sDecCtrl ); -TOC(decode_params) - - /* Update length. Sampling frequency may have changed */ - L = psDec->frame_length; - - /********************************************************/ - /* Run inverse NSQ */ - /********************************************************/ -TIC(decode_core) - silk_decode_core( psDec, &sDecCtrl, pOut, pulses ); -TOC(decode_core) - - /********************************************************/ - /* Update PLC state */ - /********************************************************/ - silk_PLC( psDec, &sDecCtrl, pOut, L, 0 ); - - psDec->lossCnt = 0; - psDec->prevSignalType = psDec->indices.signalType; - SKP_assert( psDec->prevSignalType >= 0 && psDec->prevSignalType <= 2 ); - - /* A frame has been decoded without errors */ - psDec->first_frame_after_reset = 0; - } else { - /* Handle packet loss by extrapolation */ - silk_PLC( psDec, &sDecCtrl, pOut, L, 1 ); - } - - /*************************/ - /* Update output buffer. */ - /*************************/ - SKP_assert( psDec->ltp_mem_length >= psDec->frame_length ); - mv_len = psDec->ltp_mem_length - psDec->frame_length; - SKP_memmove( psDec->outBuf, &psDec->outBuf[ psDec->frame_length ], mv_len * sizeof(opus_int16) ); - SKP_memcpy( &psDec->outBuf[ mv_len ], pOut, psDec->frame_length * sizeof( opus_int16 ) ); - - /****************************************************************/ - /* Ensure smooth connection of extrapolated and good frames */ - /****************************************************************/ - silk_PLC_glue_frames( psDec, &sDecCtrl, pOut, L ); - - /************************************************/ - /* Comfort noise generation / estimation */ - /************************************************/ - silk_CNG( psDec, &sDecCtrl, pOut, L ); - - /* Update some decoder state variables */ - psDec->lagPrev = sDecCtrl.pitchL[ psDec->nb_subfr - 1 ]; - psDec->nFramesDecoded++; - - /* Set output frame length */ - *pN = L; - -TOC(DECODE_FRAME) - - return ret; -} - \ No newline at end of file +/*********************************************************************** +Copyright (c) 2006-2011, Skype Limited. All rights reserved. +Redistribution and use in source and binary forms, with or without +modification, (subject to the limitations in the disclaimer below) +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 Skype Limited, nor the names of specific +contributors, may be used to endorse or promote products derived from +this software without specific prior written permission. +NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED +BY THIS LICENSE. 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. +***********************************************************************/ + +#include "silk_main.h" +#include "silk_PLC.h" + +/****************/ +/* Decode frame */ +/****************/ +opus_int silk_decode_frame( + silk_decoder_state *psDec, /* I/O Pointer to Silk decoder state */ + ec_dec *psRangeDec, /* I/O Compressor data structure */ + opus_int16 pOut[], /* O Pointer to output speech frame */ + opus_int32 *pN, /* O Pointer to size of output frame */ + opus_int lostFlag /* I 0: no loss, 1 loss, 2 decode fec */ +) +{ + silk_decoder_control sDecCtrl; + opus_int L, mv_len, ret = 0; + opus_int pulses[ MAX_FRAME_LENGTH ]; + +TIC(DECODE_FRAME) + + L = psDec->frame_length; + sDecCtrl.LTP_scale_Q14 = 0; + + /* Safety checks */ + SKP_assert( L > 0 && L <= MAX_FRAME_LENGTH ); + + if( lostFlag == FLAG_DECODE_NORMAL || + ( lostFlag == FLAG_DECODE_LBRR && psDec->LBRR_flags[ psDec->nFramesDecoded ] == 1 ) ) + { + /*********************************************/ + /* Decode quantization indices of side info */ + /*********************************************/ +TIC(decode_indices) + silk_decode_indices( psDec, psRangeDec, psDec->nFramesDecoded, lostFlag ); +TOC(decode_indices) + + /*********************************************/ + /* Decode quantization indices of excitation */ + /*********************************************/ +TIC(decode_pulses) + silk_decode_pulses( psRangeDec, pulses, psDec->indices.signalType, + psDec->indices.quantOffsetType, psDec->frame_length ); +TOC(decode_pulses) + + /********************************************/ + /* Decode parameters and pulse signal */ + /********************************************/ +TIC(decode_params) + silk_decode_parameters( psDec, &sDecCtrl ); +TOC(decode_params) + + /* Update length. Sampling frequency may have changed */ + L = psDec->frame_length; + + /********************************************************/ + /* Run inverse NSQ */ + /********************************************************/ +TIC(decode_core) + silk_decode_core( psDec, &sDecCtrl, pOut, pulses ); +TOC(decode_core) + + /********************************************************/ + /* Update PLC state */ + /********************************************************/ + silk_PLC( psDec, &sDecCtrl, pOut, L, 0 ); + + psDec->lossCnt = 0; + psDec->prevSignalType = psDec->indices.signalType; + SKP_assert( psDec->prevSignalType >= 0 && psDec->prevSignalType <= 2 ); + + /* A frame has been decoded without errors */ + psDec->first_frame_after_reset = 0; + } else { + /* Handle packet loss by extrapolation */ + silk_PLC( psDec, &sDecCtrl, pOut, L, 1 ); + } + + /*************************/ + /* Update output buffer. */ + /*************************/ + SKP_assert( psDec->ltp_mem_length >= psDec->frame_length ); + mv_len = psDec->ltp_mem_length - psDec->frame_length; + SKP_memmove( psDec->outBuf, &psDec->outBuf[ psDec->frame_length ], mv_len * sizeof(opus_int16) ); + SKP_memcpy( &psDec->outBuf[ mv_len ], pOut, psDec->frame_length * sizeof( opus_int16 ) ); + + /****************************************************************/ + /* Ensure smooth connection of extrapolated and good frames */ + /****************************************************************/ + silk_PLC_glue_frames( psDec, &sDecCtrl, pOut, L ); + + /************************************************/ + /* Comfort noise generation / estimation */ + /************************************************/ + silk_CNG( psDec, &sDecCtrl, pOut, L ); + + /* Update some decoder state variables */ + psDec->lagPrev = sDecCtrl.pitchL[ psDec->nb_subfr - 1 ]; + psDec->nFramesDecoded++; + + /* Set output frame length */ + *pN = L; + +TOC(DECODE_FRAME) + + return ret; +} diff --git a/silk/silk_decode_indices.c b/silk/silk_decode_indices.c index c30a041e5..7c1705fde 100644 --- a/silk/silk_decode_indices.c +++ b/silk/silk_decode_indices.c @@ -1,153 +1,153 @@ -/*********************************************************************** -Copyright (c) 2006-2011, Skype Limited. All rights reserved. -Redistribution and use in source and binary forms, with or without -modification, (subject to the limitations in the disclaimer below) -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 Skype Limited, nor the names of specific -contributors, may be used to endorse or promote products derived from -this software without specific prior written permission. -NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED -BY THIS LICENSE. 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. -***********************************************************************/ - -#include "silk_main.h" - -/* Decode side-information parameters from payload */ -void silk_decode_indices( - silk_decoder_state *psDec, /* I/O State */ - ec_dec *psRangeDec, /* I/O Compressor data structure */ - opus_int FrameIndex, /* I Frame number */ - opus_int decode_LBRR /* I Flag indicating LBRR data is being decoded */ -) -{ - opus_int i, k, Ix, condCoding; - opus_int decode_absolute_lagIndex, delta_lagIndex; - opus_int16 ec_ix[ MAX_LPC_ORDER ]; - opus_uint8 pred_Q8[ MAX_LPC_ORDER ]; - - /* Use conditional coding if previous frame available */ - if( FrameIndex > 0 && ( decode_LBRR == 0 || psDec->LBRR_flags[ FrameIndex - 1 ] == 1 ) ) { - condCoding = 1; - } else { - condCoding = 0; - } - - /*******************************************/ - /* Decode signal type and quantizer offset */ - /*******************************************/ - if( decode_LBRR || psDec->VAD_flags[ FrameIndex ] ) { - Ix = ec_dec_icdf( psRangeDec, silk_type_offset_VAD_iCDF, 8 ) + 2; - } else { - Ix = ec_dec_icdf( psRangeDec, silk_type_offset_no_VAD_iCDF, 8 ); - } - psDec->indices.signalType = (opus_int8)SKP_RSHIFT( Ix, 1 ); - psDec->indices.quantOffsetType = (opus_int8)( Ix & 1 ); - - /****************/ - /* Decode gains */ - /****************/ - /* First subframe */ - if( condCoding ) { - /* Conditional coding */ - psDec->indices.GainsIndices[ 0 ] = (opus_int8)ec_dec_icdf( psRangeDec, silk_delta_gain_iCDF, 8 ); - } else { - /* Independent coding, in two stages: MSB bits followed by 3 LSBs */ - psDec->indices.GainsIndices[ 0 ] = (opus_int8)SKP_LSHIFT( ec_dec_icdf( psRangeDec, silk_gain_iCDF[ psDec->indices.signalType ], 8 ), 3 ); - psDec->indices.GainsIndices[ 0 ] += (opus_int8)ec_dec_icdf( psRangeDec, silk_uniform8_iCDF, 8 ); - } - - /* Remaining subframes */ - for( i = 1; i < psDec->nb_subfr; i++ ) { - psDec->indices.GainsIndices[ i ] = (opus_int8)ec_dec_icdf( psRangeDec, silk_delta_gain_iCDF, 8 ); - } - - /**********************/ - /* Decode LSF Indices */ - /**********************/ - psDec->indices.NLSFIndices[ 0 ] = (opus_int8)ec_dec_icdf( psRangeDec, &psDec->psNLSF_CB->CB1_iCDF[ ( psDec->indices.signalType >> 1 ) * psDec->psNLSF_CB->nVectors ], 8 ); - silk_NLSF_unpack( ec_ix, pred_Q8, psDec->psNLSF_CB, psDec->indices.NLSFIndices[ 0 ] ); - SKP_assert( psDec->psNLSF_CB->order == psDec->LPC_order ); - for( i = 0; i < psDec->psNLSF_CB->order; i++ ) { - Ix = ec_dec_icdf( psRangeDec, &psDec->psNLSF_CB->ec_iCDF[ ec_ix[ i ] ], 8 ); - if( Ix == 0 ) { - Ix -= ec_dec_icdf( psRangeDec, silk_NLSF_EXT_iCDF, 8 ); - } else if( Ix == 2 * NLSF_QUANT_MAX_AMPLITUDE ) { - Ix += ec_dec_icdf( psRangeDec, silk_NLSF_EXT_iCDF, 8 ); - } - psDec->indices.NLSFIndices[ i+1 ] = (opus_int8)( Ix - NLSF_QUANT_MAX_AMPLITUDE ); - } - - /* Decode LSF interpolation factor */ - if( psDec->nb_subfr == MAX_NB_SUBFR ) { - psDec->indices.NLSFInterpCoef_Q2 = (opus_int8)ec_dec_icdf( psRangeDec, silk_NLSF_interpolation_factor_iCDF, 8 ); - } else { - psDec->indices.NLSFInterpCoef_Q2 = 4; - } - - if( psDec->indices.signalType == TYPE_VOICED ) - { - /*********************/ - /* Decode pitch lags */ - /*********************/ - /* Get lag index */ - decode_absolute_lagIndex = 1; - if( condCoding && psDec->ec_prevSignalType == TYPE_VOICED ) { - /* Decode Delta index */ - delta_lagIndex = (opus_int16)ec_dec_icdf( psRangeDec, silk_pitch_delta_iCDF, 8 ); - if( delta_lagIndex > 0 ) { - delta_lagIndex = delta_lagIndex - 9; - psDec->indices.lagIndex = (opus_int16)( psDec->ec_prevLagIndex + delta_lagIndex ); - decode_absolute_lagIndex = 0; - } - } - if( decode_absolute_lagIndex ) { - /* Absolute decoding */ - psDec->indices.lagIndex = (opus_int16)ec_dec_icdf( psRangeDec, silk_pitch_lag_iCDF, 8 ) * SKP_RSHIFT( psDec->fs_kHz, 1 ); - psDec->indices.lagIndex += (opus_int16)ec_dec_icdf( psRangeDec, psDec->pitch_lag_low_bits_iCDF, 8 ); - } - psDec->ec_prevLagIndex = psDec->indices.lagIndex; - - /* Get countour index */ - psDec->indices.contourIndex = (opus_int8)ec_dec_icdf( psRangeDec, psDec->pitch_contour_iCDF, 8 ); - - /********************/ - /* Decode LTP gains */ - /********************/ - /* Decode PERIndex value */ - psDec->indices.PERIndex = (opus_int8)ec_dec_icdf( psRangeDec, silk_LTP_per_index_iCDF, 8 ); - - for( k = 0; k < psDec->nb_subfr; k++ ) { - psDec->indices.LTPIndex[ k ] = (opus_int8)ec_dec_icdf( psRangeDec, silk_LTP_gain_iCDF_ptrs[ psDec->indices.PERIndex ], 8 ); - } - - /**********************/ - /* Decode LTP scaling */ - /**********************/ - if( !condCoding ) { - psDec->indices.LTP_scaleIndex = (opus_int8)ec_dec_icdf( psRangeDec, silk_LTPscale_iCDF, 8 ); - } else { - psDec->indices.LTP_scaleIndex = 0; - } - } - psDec->ec_prevSignalType = psDec->indices.signalType; - - /***************/ - /* Decode seed */ - /***************/ - psDec->indices.Seed = (opus_int8)ec_dec_icdf( psRangeDec, silk_uniform4_iCDF, 8 ); -} +/*********************************************************************** +Copyright (c) 2006-2011, Skype Limited. All rights reserved. +Redistribution and use in source and binary forms, with or without +modification, (subject to the limitations in the disclaimer below) +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 Skype Limited, nor the names of specific +contributors, may be used to endorse or promote products derived from +this software without specific prior written permission. +NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED +BY THIS LICENSE. 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. +***********************************************************************/ + +#include "silk_main.h" + +/* Decode side-information parameters from payload */ +void silk_decode_indices( + silk_decoder_state *psDec, /* I/O State */ + ec_dec *psRangeDec, /* I/O Compressor data structure */ + opus_int FrameIndex, /* I Frame number */ + opus_int decode_LBRR /* I Flag indicating LBRR data is being decoded */ +) +{ + opus_int i, k, Ix, condCoding; + opus_int decode_absolute_lagIndex, delta_lagIndex; + opus_int16 ec_ix[ MAX_LPC_ORDER ]; + opus_uint8 pred_Q8[ MAX_LPC_ORDER ]; + + /* Use conditional coding if previous frame available */ + if( FrameIndex > 0 && ( decode_LBRR == 0 || psDec->LBRR_flags[ FrameIndex - 1 ] == 1 ) ) { + condCoding = 1; + } else { + condCoding = 0; + } + + /*******************************************/ + /* Decode signal type and quantizer offset */ + /*******************************************/ + if( decode_LBRR || psDec->VAD_flags[ FrameIndex ] ) { + Ix = ec_dec_icdf( psRangeDec, silk_type_offset_VAD_iCDF, 8 ) + 2; + } else { + Ix = ec_dec_icdf( psRangeDec, silk_type_offset_no_VAD_iCDF, 8 ); + } + psDec->indices.signalType = (opus_int8)SKP_RSHIFT( Ix, 1 ); + psDec->indices.quantOffsetType = (opus_int8)( Ix & 1 ); + + /****************/ + /* Decode gains */ + /****************/ + /* First subframe */ + if( condCoding ) { + /* Conditional coding */ + psDec->indices.GainsIndices[ 0 ] = (opus_int8)ec_dec_icdf( psRangeDec, silk_delta_gain_iCDF, 8 ); + } else { + /* Independent coding, in two stages: MSB bits followed by 3 LSBs */ + psDec->indices.GainsIndices[ 0 ] = (opus_int8)SKP_LSHIFT( ec_dec_icdf( psRangeDec, silk_gain_iCDF[ psDec->indices.signalType ], 8 ), 3 ); + psDec->indices.GainsIndices[ 0 ] += (opus_int8)ec_dec_icdf( psRangeDec, silk_uniform8_iCDF, 8 ); + } + + /* Remaining subframes */ + for( i = 1; i < psDec->nb_subfr; i++ ) { + psDec->indices.GainsIndices[ i ] = (opus_int8)ec_dec_icdf( psRangeDec, silk_delta_gain_iCDF, 8 ); + } + + /**********************/ + /* Decode LSF Indices */ + /**********************/ + psDec->indices.NLSFIndices[ 0 ] = (opus_int8)ec_dec_icdf( psRangeDec, &psDec->psNLSF_CB->CB1_iCDF[ ( psDec->indices.signalType >> 1 ) * psDec->psNLSF_CB->nVectors ], 8 ); + silk_NLSF_unpack( ec_ix, pred_Q8, psDec->psNLSF_CB, psDec->indices.NLSFIndices[ 0 ] ); + SKP_assert( psDec->psNLSF_CB->order == psDec->LPC_order ); + for( i = 0; i < psDec->psNLSF_CB->order; i++ ) { + Ix = ec_dec_icdf( psRangeDec, &psDec->psNLSF_CB->ec_iCDF[ ec_ix[ i ] ], 8 ); + if( Ix == 0 ) { + Ix -= ec_dec_icdf( psRangeDec, silk_NLSF_EXT_iCDF, 8 ); + } else if( Ix == 2 * NLSF_QUANT_MAX_AMPLITUDE ) { + Ix += ec_dec_icdf( psRangeDec, silk_NLSF_EXT_iCDF, 8 ); + } + psDec->indices.NLSFIndices[ i+1 ] = (opus_int8)( Ix - NLSF_QUANT_MAX_AMPLITUDE ); + } + + /* Decode LSF interpolation factor */ + if( psDec->nb_subfr == MAX_NB_SUBFR ) { + psDec->indices.NLSFInterpCoef_Q2 = (opus_int8)ec_dec_icdf( psRangeDec, silk_NLSF_interpolation_factor_iCDF, 8 ); + } else { + psDec->indices.NLSFInterpCoef_Q2 = 4; + } + + if( psDec->indices.signalType == TYPE_VOICED ) + { + /*********************/ + /* Decode pitch lags */ + /*********************/ + /* Get lag index */ + decode_absolute_lagIndex = 1; + if( condCoding && psDec->ec_prevSignalType == TYPE_VOICED ) { + /* Decode Delta index */ + delta_lagIndex = (opus_int16)ec_dec_icdf( psRangeDec, silk_pitch_delta_iCDF, 8 ); + if( delta_lagIndex > 0 ) { + delta_lagIndex = delta_lagIndex - 9; + psDec->indices.lagIndex = (opus_int16)( psDec->ec_prevLagIndex + delta_lagIndex ); + decode_absolute_lagIndex = 0; + } + } + if( decode_absolute_lagIndex ) { + /* Absolute decoding */ + psDec->indices.lagIndex = (opus_int16)ec_dec_icdf( psRangeDec, silk_pitch_lag_iCDF, 8 ) * SKP_RSHIFT( psDec->fs_kHz, 1 ); + psDec->indices.lagIndex += (opus_int16)ec_dec_icdf( psRangeDec, psDec->pitch_lag_low_bits_iCDF, 8 ); + } + psDec->ec_prevLagIndex = psDec->indices.lagIndex; + + /* Get countour index */ + psDec->indices.contourIndex = (opus_int8)ec_dec_icdf( psRangeDec, psDec->pitch_contour_iCDF, 8 ); + + /********************/ + /* Decode LTP gains */ + /********************/ + /* Decode PERIndex value */ + psDec->indices.PERIndex = (opus_int8)ec_dec_icdf( psRangeDec, silk_LTP_per_index_iCDF, 8 ); + + for( k = 0; k < psDec->nb_subfr; k++ ) { + psDec->indices.LTPIndex[ k ] = (opus_int8)ec_dec_icdf( psRangeDec, silk_LTP_gain_iCDF_ptrs[ psDec->indices.PERIndex ], 8 ); + } + + /**********************/ + /* Decode LTP scaling */ + /**********************/ + if( !condCoding ) { + psDec->indices.LTP_scaleIndex = (opus_int8)ec_dec_icdf( psRangeDec, silk_LTPscale_iCDF, 8 ); + } else { + psDec->indices.LTP_scaleIndex = 0; + } + } + psDec->ec_prevSignalType = psDec->indices.signalType; + + /***************/ + /* Decode seed */ + /***************/ + psDec->indices.Seed = (opus_int8)ec_dec_icdf( psRangeDec, silk_uniform4_iCDF, 8 ); +} diff --git a/silk/silk_decode_parameters.c b/silk/silk_decode_parameters.c index d59778408..d662dcf49 100644 --- a/silk/silk_decode_parameters.c +++ b/silk/silk_decode_parameters.c @@ -1,111 +1,111 @@ -/*********************************************************************** -Copyright (c) 2006-2011, Skype Limited. All rights reserved. -Redistribution and use in source and binary forms, with or without -modification, (subject to the limitations in the disclaimer below) -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 Skype Limited, nor the names of specific -contributors, may be used to endorse or promote products derived from -this software without specific prior written permission. -NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED -BY THIS LICENSE. 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. -***********************************************************************/ - -#include "silk_main.h" - -/* Decode parameters from payload */ -void silk_decode_parameters( - silk_decoder_state *psDec, /* I/O State */ - silk_decoder_control *psDecCtrl /* I/O Decoder control */ -) -{ - opus_int i, k, Ix; - opus_int16 pNLSF_Q15[ MAX_LPC_ORDER ], pNLSF0_Q15[ MAX_LPC_ORDER ]; - const opus_int8 *cbk_ptr_Q7; - - /* Dequant Gains */ - silk_gains_dequant( psDecCtrl->Gains_Q16, psDec->indices.GainsIndices, - &psDec->LastGainIndex, psDec->nFramesDecoded, psDec->nb_subfr ); - - /****************/ - /* Decode NLSFs */ - /****************/ - silk_NLSF_decode( pNLSF_Q15, psDec->indices.NLSFIndices, psDec->psNLSF_CB ); - - /* Convert NLSF parameters to AR prediction filter coefficients */ - silk_NLSF2A( psDecCtrl->PredCoef_Q12[ 1 ], pNLSF_Q15, psDec->LPC_order ); - - /* If just reset, e.g., because internal Fs changed, do not allow interpolation */ - /* improves the case of packet loss in the first frame after a switch */ - if( psDec->first_frame_after_reset == 1 ) { - psDec->indices.NLSFInterpCoef_Q2 = 4; - } - - if( psDec->indices.NLSFInterpCoef_Q2 < 4 ) { - /* Calculation of the interpolated NLSF0 vector from the interpolation factor, */ - /* the previous NLSF1, and the current NLSF1 */ - for( i = 0; i < psDec->LPC_order; i++ ) { - pNLSF0_Q15[ i ] = psDec->prevNLSF_Q15[ i ] + SKP_RSHIFT( SKP_MUL( psDec->indices.NLSFInterpCoef_Q2, - pNLSF_Q15[ i ] - psDec->prevNLSF_Q15[ i ] ), 2 ); - } - - /* Convert NLSF parameters to AR prediction filter coefficients */ - silk_NLSF2A( psDecCtrl->PredCoef_Q12[ 0 ], pNLSF0_Q15, psDec->LPC_order ); - } else { - /* Copy LPC coefficients for first half from second half */ - SKP_memcpy( psDecCtrl->PredCoef_Q12[ 0 ], psDecCtrl->PredCoef_Q12[ 1 ], - psDec->LPC_order * sizeof( opus_int16 ) ); - } - - SKP_memcpy( psDec->prevNLSF_Q15, pNLSF_Q15, psDec->LPC_order * sizeof( opus_int16 ) ); - - /* After a packet loss do BWE of LPC coefs */ - if( psDec->lossCnt ) { - silk_bwexpander( psDecCtrl->PredCoef_Q12[ 0 ], psDec->LPC_order, BWE_AFTER_LOSS_Q16 ); - silk_bwexpander( psDecCtrl->PredCoef_Q12[ 1 ], psDec->LPC_order, BWE_AFTER_LOSS_Q16 ); - } - - if( psDec->indices.signalType == TYPE_VOICED ) { - /*********************/ - /* Decode pitch lags */ - /*********************/ - - /* Decode pitch values */ - silk_decode_pitch( psDec->indices.lagIndex, psDec->indices.contourIndex, psDecCtrl->pitchL, psDec->fs_kHz, psDec->nb_subfr ); - - /* Decode Codebook Index */ - cbk_ptr_Q7 = silk_LTP_vq_ptrs_Q7[ psDec->indices.PERIndex ]; /* set pointer to start of codebook */ - - for( k = 0; k < psDec->nb_subfr; k++ ) { - Ix = psDec->indices.LTPIndex[ k ]; - for( i = 0; i < LTP_ORDER; i++ ) { - psDecCtrl->LTPCoef_Q14[ k * LTP_ORDER + i ] = SKP_LSHIFT( cbk_ptr_Q7[ Ix * LTP_ORDER + i ], 7 ); - } - } - - /**********************/ - /* Decode LTP scaling */ - /**********************/ - Ix = psDec->indices.LTP_scaleIndex; - psDecCtrl->LTP_scale_Q14 = silk_LTPScales_table_Q14[ Ix ]; - } else { - SKP_memset( psDecCtrl->pitchL, 0, psDec->nb_subfr * sizeof( opus_int ) ); - SKP_memset( psDecCtrl->LTPCoef_Q14, 0, LTP_ORDER * psDec->nb_subfr * sizeof( opus_int16 ) ); - psDec->indices.PERIndex = 0; - psDecCtrl->LTP_scale_Q14 = 0; - } -} +/*********************************************************************** +Copyright (c) 2006-2011, Skype Limited. All rights reserved. +Redistribution and use in source and binary forms, with or without +modification, (subject to the limitations in the disclaimer below) +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 Skype Limited, nor the names of specific +contributors, may be used to endorse or promote products derived from +this software without specific prior written permission. +NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED +BY THIS LICENSE. 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. +***********************************************************************/ + +#include "silk_main.h" + +/* Decode parameters from payload */ +void silk_decode_parameters( + silk_decoder_state *psDec, /* I/O State */ + silk_decoder_control *psDecCtrl /* I/O Decoder control */ +) +{ + opus_int i, k, Ix; + opus_int16 pNLSF_Q15[ MAX_LPC_ORDER ], pNLSF0_Q15[ MAX_LPC_ORDER ]; + const opus_int8 *cbk_ptr_Q7; + + /* Dequant Gains */ + silk_gains_dequant( psDecCtrl->Gains_Q16, psDec->indices.GainsIndices, + &psDec->LastGainIndex, psDec->nFramesDecoded, psDec->nb_subfr ); + + /****************/ + /* Decode NLSFs */ + /****************/ + silk_NLSF_decode( pNLSF_Q15, psDec->indices.NLSFIndices, psDec->psNLSF_CB ); + + /* Convert NLSF parameters to AR prediction filter coefficients */ + silk_NLSF2A( psDecCtrl->PredCoef_Q12[ 1 ], pNLSF_Q15, psDec->LPC_order ); + + /* If just reset, e.g., because internal Fs changed, do not allow interpolation */ + /* improves the case of packet loss in the first frame after a switch */ + if( psDec->first_frame_after_reset == 1 ) { + psDec->indices.NLSFInterpCoef_Q2 = 4; + } + + if( psDec->indices.NLSFInterpCoef_Q2 < 4 ) { + /* Calculation of the interpolated NLSF0 vector from the interpolation factor, */ + /* the previous NLSF1, and the current NLSF1 */ + for( i = 0; i < psDec->LPC_order; i++ ) { + pNLSF0_Q15[ i ] = psDec->prevNLSF_Q15[ i ] + SKP_RSHIFT( SKP_MUL( psDec->indices.NLSFInterpCoef_Q2, + pNLSF_Q15[ i ] - psDec->prevNLSF_Q15[ i ] ), 2 ); + } + + /* Convert NLSF parameters to AR prediction filter coefficients */ + silk_NLSF2A( psDecCtrl->PredCoef_Q12[ 0 ], pNLSF0_Q15, psDec->LPC_order ); + } else { + /* Copy LPC coefficients for first half from second half */ + SKP_memcpy( psDecCtrl->PredCoef_Q12[ 0 ], psDecCtrl->PredCoef_Q12[ 1 ], + psDec->LPC_order * sizeof( opus_int16 ) ); + } + + SKP_memcpy( psDec->prevNLSF_Q15, pNLSF_Q15, psDec->LPC_order * sizeof( opus_int16 ) ); + + /* After a packet loss do BWE of LPC coefs */ + if( psDec->lossCnt ) { + silk_bwexpander( psDecCtrl->PredCoef_Q12[ 0 ], psDec->LPC_order, BWE_AFTER_LOSS_Q16 ); + silk_bwexpander( psDecCtrl->PredCoef_Q12[ 1 ], psDec->LPC_order, BWE_AFTER_LOSS_Q16 ); + } + + if( psDec->indices.signalType == TYPE_VOICED ) { + /*********************/ + /* Decode pitch lags */ + /*********************/ + + /* Decode pitch values */ + silk_decode_pitch( psDec->indices.lagIndex, psDec->indices.contourIndex, psDecCtrl->pitchL, psDec->fs_kHz, psDec->nb_subfr ); + + /* Decode Codebook Index */ + cbk_ptr_Q7 = silk_LTP_vq_ptrs_Q7[ psDec->indices.PERIndex ]; /* set pointer to start of codebook */ + + for( k = 0; k < psDec->nb_subfr; k++ ) { + Ix = psDec->indices.LTPIndex[ k ]; + for( i = 0; i < LTP_ORDER; i++ ) { + psDecCtrl->LTPCoef_Q14[ k * LTP_ORDER + i ] = SKP_LSHIFT( cbk_ptr_Q7[ Ix * LTP_ORDER + i ], 7 ); + } + } + + /**********************/ + /* Decode LTP scaling */ + /**********************/ + Ix = psDec->indices.LTP_scaleIndex; + psDecCtrl->LTP_scale_Q14 = silk_LTPScales_table_Q14[ Ix ]; + } else { + SKP_memset( psDecCtrl->pitchL, 0, psDec->nb_subfr * sizeof( opus_int ) ); + SKP_memset( psDecCtrl->LTPCoef_Q14, 0, LTP_ORDER * psDec->nb_subfr * sizeof( opus_int16 ) ); + psDec->indices.PERIndex = 0; + psDecCtrl->LTP_scale_Q14 = 0; + } +} diff --git a/silk/silk_decode_pitch.c b/silk/silk_decode_pitch.c index 32d05cc79..43d3983ff 100644 --- a/silk/silk_decode_pitch.c +++ b/silk/silk_decode_pitch.c @@ -1,73 +1,73 @@ -/*********************************************************************** -Copyright (c) 2006-2011, Skype Limited. All rights reserved. -Redistribution and use in source and binary forms, with or without -modification, (subject to the limitations in the disclaimer below) -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 Skype Limited, nor the names of specific -contributors, may be used to endorse or promote products derived from -this software without specific prior written permission. -NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED -BY THIS LICENSE. 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. -***********************************************************************/ - -/*********************************************************** -* Pitch analyser function -********************************************************** */ -#include "silk_SigProc_FIX.h" -#include "silk_pitch_est_defines.h" - -void silk_decode_pitch( - opus_int16 lagIndex, /* I */ - opus_int8 contourIndex, /* O */ - opus_int pitch_lags[], /* O pitch values */ - const opus_int Fs_kHz, /* I sampling frequency (kHz) */ - const opus_int nb_subfr /* I number of sub frames */ -) -{ - opus_int lag, k, min_lag, max_lag, cbk_size; - const opus_int8 *Lag_CB_ptr; - - if( Fs_kHz == 8 ) { - if( nb_subfr == PE_MAX_NB_SUBFR ) { - Lag_CB_ptr = &silk_CB_lags_stage2[ 0 ][ 0 ]; - cbk_size = PE_NB_CBKS_STAGE2_EXT; - } else { - SKP_assert( nb_subfr == PE_MAX_NB_SUBFR >> 1 ); - Lag_CB_ptr = &silk_CB_lags_stage2_10_ms[ 0 ][ 0 ]; - cbk_size = PE_NB_CBKS_STAGE2_10MS; - } - } else { - if( nb_subfr == PE_MAX_NB_SUBFR ) { - Lag_CB_ptr = &silk_CB_lags_stage3[ 0 ][ 0 ]; - cbk_size = PE_NB_CBKS_STAGE3_MAX; - } else { - SKP_assert( nb_subfr == PE_MAX_NB_SUBFR >> 1 ); - Lag_CB_ptr = &silk_CB_lags_stage3_10_ms[ 0 ][ 0 ]; - cbk_size = PE_NB_CBKS_STAGE3_10MS; - } - } - - min_lag = SKP_SMULBB( PE_MIN_LAG_MS, Fs_kHz ); - max_lag = SKP_SMULBB( PE_MAX_LAG_MS, Fs_kHz ); - lag = min_lag + lagIndex; - - for( k = 0; k < nb_subfr; k++ ) { - pitch_lags[ k ] = lag + matrix_ptr( Lag_CB_ptr, k, contourIndex, cbk_size ); - pitch_lags[ k ] = SKP_LIMIT( pitch_lags[ k ], min_lag, max_lag ); - } +/*********************************************************************** +Copyright (c) 2006-2011, Skype Limited. All rights reserved. +Redistribution and use in source and binary forms, with or without +modification, (subject to the limitations in the disclaimer below) +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 Skype Limited, nor the names of specific +contributors, may be used to endorse or promote products derived from +this software without specific prior written permission. +NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED +BY THIS LICENSE. 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. +***********************************************************************/ + +/*********************************************************** +* Pitch analyser function +********************************************************** */ +#include "silk_SigProc_FIX.h" +#include "silk_pitch_est_defines.h" + +void silk_decode_pitch( + opus_int16 lagIndex, /* I */ + opus_int8 contourIndex, /* O */ + opus_int pitch_lags[], /* O pitch values */ + const opus_int Fs_kHz, /* I sampling frequency (kHz) */ + const opus_int nb_subfr /* I number of sub frames */ +) +{ + opus_int lag, k, min_lag, max_lag, cbk_size; + const opus_int8 *Lag_CB_ptr; + + if( Fs_kHz == 8 ) { + if( nb_subfr == PE_MAX_NB_SUBFR ) { + Lag_CB_ptr = &silk_CB_lags_stage2[ 0 ][ 0 ]; + cbk_size = PE_NB_CBKS_STAGE2_EXT; + } else { + SKP_assert( nb_subfr == PE_MAX_NB_SUBFR >> 1 ); + Lag_CB_ptr = &silk_CB_lags_stage2_10_ms[ 0 ][ 0 ]; + cbk_size = PE_NB_CBKS_STAGE2_10MS; + } + } else { + if( nb_subfr == PE_MAX_NB_SUBFR ) { + Lag_CB_ptr = &silk_CB_lags_stage3[ 0 ][ 0 ]; + cbk_size = PE_NB_CBKS_STAGE3_MAX; + } else { + SKP_assert( nb_subfr == PE_MAX_NB_SUBFR >> 1 ); + Lag_CB_ptr = &silk_CB_lags_stage3_10_ms[ 0 ][ 0 ]; + cbk_size = PE_NB_CBKS_STAGE3_10MS; + } + } + + min_lag = SKP_SMULBB( PE_MIN_LAG_MS, Fs_kHz ); + max_lag = SKP_SMULBB( PE_MAX_LAG_MS, Fs_kHz ); + lag = min_lag + lagIndex; + + for( k = 0; k < nb_subfr; k++ ) { + pitch_lags[ k ] = lag + matrix_ptr( Lag_CB_ptr, k, contourIndex, cbk_size ); + pitch_lags[ k ] = SKP_LIMIT( pitch_lags[ k ], min_lag, max_lag ); + } } \ No newline at end of file diff --git a/silk/silk_decode_pulses.c b/silk/silk_decode_pulses.c index 3eba50cd5..f5a91bdc6 100644 --- a/silk/silk_decode_pulses.c +++ b/silk/silk_decode_pulses.c @@ -1,109 +1,109 @@ -/*********************************************************************** -Copyright (c) 2006-2011, Skype Limited. All rights reserved. -Redistribution and use in source and binary forms, with or without -modification, (subject to the limitations in the disclaimer below) -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 Skype Limited, nor the names of specific -contributors, may be used to endorse or promote products derived from -this software without specific prior written permission. -NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED -BY THIS LICENSE. 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. -***********************************************************************/ - -#include "silk_main.h" - -/*********************************************/ -/* Decode quantization indices of excitation */ -/*********************************************/ -void silk_decode_pulses( - ec_dec *psRangeDec, /* I/O Compressor data structure */ - opus_int pulses[], /* O Excitation signal */ - const opus_int signalType, /* I Sigtype */ - const opus_int quantOffsetType, /* I quantOffsetType */ - const opus_int frame_length /* I Frame length */ -) -{ - opus_int i, j, k, iter, abs_q, nLS, RateLevelIndex; - opus_int sum_pulses[ MAX_NB_SHELL_BLOCKS ], nLshifts[ MAX_NB_SHELL_BLOCKS ]; - opus_int *pulses_ptr; - const opus_uint8 *cdf_ptr; - - /*********************/ - /* Decode rate level */ - /*********************/ - RateLevelIndex = ec_dec_icdf( psRangeDec, silk_rate_levels_iCDF[ signalType >> 1 ], 8 ); - - /* Calculate number of shell blocks */ - SKP_assert( 1 << LOG2_SHELL_CODEC_FRAME_LENGTH == SHELL_CODEC_FRAME_LENGTH ); - iter = SKP_RSHIFT( frame_length, LOG2_SHELL_CODEC_FRAME_LENGTH ); - if( iter * SHELL_CODEC_FRAME_LENGTH < frame_length ){ - SKP_assert( frame_length == 12 * 10 ); /* Make sure only happens for 10 ms @ 12 kHz */ - iter++; - } - - /***************************************************/ - /* Sum-Weighted-Pulses Decoding */ - /***************************************************/ - cdf_ptr = silk_pulses_per_block_iCDF[ RateLevelIndex ]; - for( i = 0; i < iter; i++ ) { - nLshifts[ i ] = 0; - sum_pulses[ i ] = ec_dec_icdf( psRangeDec, cdf_ptr, 8 ); - - /* LSB indication */ - while( sum_pulses[ i ] == MAX_PULSES + 1 ) { - nLshifts[ i ]++; - /* When we've already got 10 LSBs, we shift the table to not allow (MAX_PULSES + 1) */ - sum_pulses[ i ] = ec_dec_icdf( psRangeDec, - silk_pulses_per_block_iCDF[ N_RATE_LEVELS - 1] + (nLshifts[ i ]==10), 8 ); - } - } - - /***************************************************/ - /* Shell decoding */ - /***************************************************/ - for( i = 0; i < iter; i++ ) { - if( sum_pulses[ i ] > 0 ) { - silk_shell_decoder( &pulses[ SKP_SMULBB( i, SHELL_CODEC_FRAME_LENGTH ) ], psRangeDec, sum_pulses[ i ] ); - } else { - SKP_memset( &pulses[ SKP_SMULBB( i, SHELL_CODEC_FRAME_LENGTH ) ], 0, SHELL_CODEC_FRAME_LENGTH * sizeof( opus_int ) ); - } - } - - /***************************************************/ - /* LSB Decoding */ - /***************************************************/ - for( i = 0; i < iter; i++ ) { - if( nLshifts[ i ] > 0 ) { - nLS = nLshifts[ i ]; - pulses_ptr = &pulses[ SKP_SMULBB( i, SHELL_CODEC_FRAME_LENGTH ) ]; - for( k = 0; k < SHELL_CODEC_FRAME_LENGTH; k++ ) { - abs_q = pulses_ptr[ k ]; - for( j = 0; j < nLS; j++ ) { - abs_q = SKP_LSHIFT( abs_q, 1 ); - abs_q += ec_dec_icdf( psRangeDec, silk_lsb_iCDF, 8 ); - } - pulses_ptr[ k ] = abs_q; - } - } - } - - /****************************************/ - /* Decode and add signs to pulse signal */ - /****************************************/ - silk_decode_signs( psRangeDec, pulses, frame_length, signalType, quantOffsetType, sum_pulses ); -} +/*********************************************************************** +Copyright (c) 2006-2011, Skype Limited. All rights reserved. +Redistribution and use in source and binary forms, with or without +modification, (subject to the limitations in the disclaimer below) +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 Skype Limited, nor the names of specific +contributors, may be used to endorse or promote products derived from +this software without specific prior written permission. +NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED +BY THIS LICENSE. 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. +***********************************************************************/ + +#include "silk_main.h" + +/*********************************************/ +/* Decode quantization indices of excitation */ +/*********************************************/ +void silk_decode_pulses( + ec_dec *psRangeDec, /* I/O Compressor data structure */ + opus_int pulses[], /* O Excitation signal */ + const opus_int signalType, /* I Sigtype */ + const opus_int quantOffsetType, /* I quantOffsetType */ + const opus_int frame_length /* I Frame length */ +) +{ + opus_int i, j, k, iter, abs_q, nLS, RateLevelIndex; + opus_int sum_pulses[ MAX_NB_SHELL_BLOCKS ], nLshifts[ MAX_NB_SHELL_BLOCKS ]; + opus_int *pulses_ptr; + const opus_uint8 *cdf_ptr; + + /*********************/ + /* Decode rate level */ + /*********************/ + RateLevelIndex = ec_dec_icdf( psRangeDec, silk_rate_levels_iCDF[ signalType >> 1 ], 8 ); + + /* Calculate number of shell blocks */ + SKP_assert( 1 << LOG2_SHELL_CODEC_FRAME_LENGTH == SHELL_CODEC_FRAME_LENGTH ); + iter = SKP_RSHIFT( frame_length, LOG2_SHELL_CODEC_FRAME_LENGTH ); + if( iter * SHELL_CODEC_FRAME_LENGTH < frame_length ){ + SKP_assert( frame_length == 12 * 10 ); /* Make sure only happens for 10 ms @ 12 kHz */ + iter++; + } + + /***************************************************/ + /* Sum-Weighted-Pulses Decoding */ + /***************************************************/ + cdf_ptr = silk_pulses_per_block_iCDF[ RateLevelIndex ]; + for( i = 0; i < iter; i++ ) { + nLshifts[ i ] = 0; + sum_pulses[ i ] = ec_dec_icdf( psRangeDec, cdf_ptr, 8 ); + + /* LSB indication */ + while( sum_pulses[ i ] == MAX_PULSES + 1 ) { + nLshifts[ i ]++; + /* When we've already got 10 LSBs, we shift the table to not allow (MAX_PULSES + 1) */ + sum_pulses[ i ] = ec_dec_icdf( psRangeDec, + silk_pulses_per_block_iCDF[ N_RATE_LEVELS - 1] + (nLshifts[ i ]==10), 8 ); + } + } + + /***************************************************/ + /* Shell decoding */ + /***************************************************/ + for( i = 0; i < iter; i++ ) { + if( sum_pulses[ i ] > 0 ) { + silk_shell_decoder( &pulses[ SKP_SMULBB( i, SHELL_CODEC_FRAME_LENGTH ) ], psRangeDec, sum_pulses[ i ] ); + } else { + SKP_memset( &pulses[ SKP_SMULBB( i, SHELL_CODEC_FRAME_LENGTH ) ], 0, SHELL_CODEC_FRAME_LENGTH * sizeof( opus_int ) ); + } + } + + /***************************************************/ + /* LSB Decoding */ + /***************************************************/ + for( i = 0; i < iter; i++ ) { + if( nLshifts[ i ] > 0 ) { + nLS = nLshifts[ i ]; + pulses_ptr = &pulses[ SKP_SMULBB( i, SHELL_CODEC_FRAME_LENGTH ) ]; + for( k = 0; k < SHELL_CODEC_FRAME_LENGTH; k++ ) { + abs_q = pulses_ptr[ k ]; + for( j = 0; j < nLS; j++ ) { + abs_q = SKP_LSHIFT( abs_q, 1 ); + abs_q += ec_dec_icdf( psRangeDec, silk_lsb_iCDF, 8 ); + } + pulses_ptr[ k ] = abs_q; + } + } + } + + /****************************************/ + /* Decode and add signs to pulse signal */ + /****************************************/ + silk_decode_signs( psRangeDec, pulses, frame_length, signalType, quantOffsetType, sum_pulses ); +} diff --git a/silk/silk_decoder_set_fs.c b/silk/silk_decoder_set_fs.c index be45eb22f..f705d7e15 100644 --- a/silk/silk_decoder_set_fs.c +++ b/silk/silk_decoder_set_fs.c @@ -1,93 +1,93 @@ -/*********************************************************************** -Copyright (c) 2006-2011, Skype Limited. All rights reserved. -Redistribution and use in source and binary forms, with or without -modification, (subject to the limitations in the disclaimer below) -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 Skype Limited, nor the names of specific -contributors, may be used to endorse or promote products derived from -this software without specific prior written permission. -NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED -BY THIS LICENSE. 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. -***********************************************************************/ - -#include "silk_main.h" - -/* Set decoder sampling rate */ -void silk_decoder_set_fs( - silk_decoder_state *psDec, /* I/O Decoder state pointer */ - opus_int fs_kHz /* I Sampling frequency (kHz) */ -) -{ - opus_int frame_length; - - SKP_assert( fs_kHz == 8 || fs_kHz == 12 || fs_kHz == 16 ); - SKP_assert( psDec->nb_subfr == MAX_NB_SUBFR || psDec->nb_subfr == MAX_NB_SUBFR/2 ); - - psDec->subfr_length = SKP_SMULBB( SUB_FRAME_LENGTH_MS, fs_kHz ); - frame_length = SKP_SMULBB( psDec->nb_subfr, psDec->subfr_length ); - if( psDec->fs_kHz != fs_kHz || frame_length != psDec->frame_length ) { - psDec->fs_kHz = fs_kHz; - psDec->frame_length = frame_length; - psDec->ltp_mem_length = SKP_SMULBB( LTP_MEM_LENGTH_MS, fs_kHz ); - if( psDec->fs_kHz == 8 ) { - if( psDec->nb_subfr == MAX_NB_SUBFR ) { - psDec->pitch_contour_iCDF = silk_pitch_contour_NB_iCDF; - } else { - psDec->pitch_contour_iCDF = silk_pitch_contour_10_ms_NB_iCDF; - } - } else { - if( psDec->nb_subfr == MAX_NB_SUBFR ) { - psDec->pitch_contour_iCDF = silk_pitch_contour_iCDF; - } else { - psDec->pitch_contour_iCDF = silk_pitch_contour_10_ms_iCDF; - } - } - if( psDec->fs_kHz == 8 || psDec->fs_kHz == 12 ) { - psDec->LPC_order = MIN_LPC_ORDER; - psDec->psNLSF_CB = &silk_NLSF_CB_NB_MB; - } else { - psDec->LPC_order = MAX_LPC_ORDER; - psDec->psNLSF_CB = &silk_NLSF_CB_WB; - } - - /* Reset part of the decoder state */ - SKP_memset( psDec->sLPC_Q14, 0, sizeof( psDec->sLPC_Q14 ) ); - SKP_memset( psDec->outBuf, 0, MAX_FRAME_LENGTH * sizeof( opus_int16 ) ); - SKP_memset( psDec->prevNLSF_Q15, 0, sizeof( psDec->prevNLSF_Q15 ) ); - - psDec->lagPrev = 100; - psDec->LastGainIndex = 10; - psDec->prevSignalType = TYPE_NO_VOICE_ACTIVITY; - psDec->first_frame_after_reset = 1; - - if( fs_kHz == 16 ) { - psDec->pitch_lag_low_bits_iCDF = silk_uniform8_iCDF; - } else if( fs_kHz == 12 ) { - psDec->pitch_lag_low_bits_iCDF = silk_uniform6_iCDF; - } else if( fs_kHz == 8 ) { - psDec->pitch_lag_low_bits_iCDF = silk_uniform4_iCDF; - } else { - /* unsupported sampling rate */ - SKP_assert( 0 ); - } - } - - /* Check that settings are valid */ - SKP_assert( psDec->frame_length > 0 && psDec->frame_length <= MAX_FRAME_LENGTH ); -} - +/*********************************************************************** +Copyright (c) 2006-2011, Skype Limited. All rights reserved. +Redistribution and use in source and binary forms, with or without +modification, (subject to the limitations in the disclaimer below) +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 Skype Limited, nor the names of specific +contributors, may be used to endorse or promote products derived from +this software without specific prior written permission. +NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED +BY THIS LICENSE. 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. +***********************************************************************/ + +#include "silk_main.h" + +/* Set decoder sampling rate */ +void silk_decoder_set_fs( + silk_decoder_state *psDec, /* I/O Decoder state pointer */ + opus_int fs_kHz /* I Sampling frequency (kHz) */ +) +{ + opus_int frame_length; + + SKP_assert( fs_kHz == 8 || fs_kHz == 12 || fs_kHz == 16 ); + SKP_assert( psDec->nb_subfr == MAX_NB_SUBFR || psDec->nb_subfr == MAX_NB_SUBFR/2 ); + + psDec->subfr_length = SKP_SMULBB( SUB_FRAME_LENGTH_MS, fs_kHz ); + frame_length = SKP_SMULBB( psDec->nb_subfr, psDec->subfr_length ); + if( psDec->fs_kHz != fs_kHz || frame_length != psDec->frame_length ) { + psDec->fs_kHz = fs_kHz; + psDec->frame_length = frame_length; + psDec->ltp_mem_length = SKP_SMULBB( LTP_MEM_LENGTH_MS, fs_kHz ); + if( psDec->fs_kHz == 8 ) { + if( psDec->nb_subfr == MAX_NB_SUBFR ) { + psDec->pitch_contour_iCDF = silk_pitch_contour_NB_iCDF; + } else { + psDec->pitch_contour_iCDF = silk_pitch_contour_10_ms_NB_iCDF; + } + } else { + if( psDec->nb_subfr == MAX_NB_SUBFR ) { + psDec->pitch_contour_iCDF = silk_pitch_contour_iCDF; + } else { + psDec->pitch_contour_iCDF = silk_pitch_contour_10_ms_iCDF; + } + } + if( psDec->fs_kHz == 8 || psDec->fs_kHz == 12 ) { + psDec->LPC_order = MIN_LPC_ORDER; + psDec->psNLSF_CB = &silk_NLSF_CB_NB_MB; + } else { + psDec->LPC_order = MAX_LPC_ORDER; + psDec->psNLSF_CB = &silk_NLSF_CB_WB; + } + + /* Reset part of the decoder state */ + SKP_memset( psDec->sLPC_Q14, 0, sizeof( psDec->sLPC_Q14 ) ); + SKP_memset( psDec->outBuf, 0, MAX_FRAME_LENGTH * sizeof( opus_int16 ) ); + SKP_memset( psDec->prevNLSF_Q15, 0, sizeof( psDec->prevNLSF_Q15 ) ); + + psDec->lagPrev = 100; + psDec->LastGainIndex = 10; + psDec->prevSignalType = TYPE_NO_VOICE_ACTIVITY; + psDec->first_frame_after_reset = 1; + + if( fs_kHz == 16 ) { + psDec->pitch_lag_low_bits_iCDF = silk_uniform8_iCDF; + } else if( fs_kHz == 12 ) { + psDec->pitch_lag_low_bits_iCDF = silk_uniform6_iCDF; + } else if( fs_kHz == 8 ) { + psDec->pitch_lag_low_bits_iCDF = silk_uniform4_iCDF; + } else { + /* unsupported sampling rate */ + SKP_assert( 0 ); + } + } + + /* Check that settings are valid */ + SKP_assert( psDec->frame_length > 0 && psDec->frame_length <= MAX_FRAME_LENGTH ); +} + diff --git a/silk/silk_define.h b/silk/silk_define.h index 7bc8a15db..be15dd61d 100644 --- a/silk/silk_define.h +++ b/silk/silk_define.h @@ -1,237 +1,237 @@ -/*********************************************************************** -Copyright (c) 2006-2011, Skype Limited. All rights reserved. -Redistribution and use in source and binary forms, with or without -modification, (subject to the limitations in the disclaimer below) -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 Skype Limited, nor the names of specific -contributors, may be used to endorse or promote products derived from -this software without specific prior written permission. -NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED -BY THIS LICENSE. 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. -***********************************************************************/ - -#ifndef SILK_DEFINE_H -#define SILK_DEFINE_H - -#include "silk_errors.h" -#include "silk_typedef.h" - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#ifdef __cplusplus -extern "C" -{ -#endif - -/* Max number of encoder channels (1/2) */ -#define ENCODER_NUM_CHANNELS 2 -/* Number of decoder channels (1/2) */ -#define DECODER_NUM_CHANNELS 2 - -#define MAX_FRAMES_PER_PACKET 3 - -/* Limits on bitrate */ -#define MIN_TARGET_RATE_BPS 5000 -#define MAX_TARGET_RATE_BPS 80000 -#define TARGET_RATE_TAB_SZ 8 - -/* LBRR thresholds */ -#define LBRR_NB_MIN_RATE_BPS 12000 -#define LBRR_MB_MIN_RATE_BPS 14000 -#define LBRR_WB_MIN_RATE_BPS 16000 - -/* DTX settings */ -#define NB_SPEECH_FRAMES_BEFORE_DTX 10 /* eq 200 ms */ -#define MAX_CONSECUTIVE_DTX 20 /* eq 400 ms */ - -/* Maximum sampling frequency, should be 16 for embedded */ -#define MAX_FS_KHZ 16 -#define MAX_API_FS_KHZ 48 - -/* Signal types */ -#define TYPE_NO_VOICE_ACTIVITY 0 -#define TYPE_UNVOICED 1 -#define TYPE_VOICED 2 - -/* Settings for stereo processing */ -#define STEREO_QUANT_TAB_SIZE 16 -#define STEREO_QUANT_SUB_STEPS 5 -#define STEREO_INTERP_LEN_MS 8 /* must be even */ -#define STEREO_RATIO_SMOOTH_COEF 0.01 /* smoothing coef for signal norms and stereo width */ - -/* Range of pitch lag estimates */ -#define PITCH_EST_MIN_LAG_MS 2 /* 2 ms -> 500 Hz */ -#define PITCH_EST_MAX_LAG_MS 18 /* 18 ms -> 56 Hz */ - -/* Maximum number of subframes */ -#define MAX_NB_SUBFR 4 - -/* Number of samples per frame */ -#define LTP_MEM_LENGTH_MS 20 -#define SUB_FRAME_LENGTH_MS 5 -#define MAX_SUB_FRAME_LENGTH ( SUB_FRAME_LENGTH_MS * MAX_FS_KHZ ) -#define MAX_FRAME_LENGTH_MS ( SUB_FRAME_LENGTH_MS * MAX_NB_SUBFR ) -#define MAX_FRAME_LENGTH ( MAX_FRAME_LENGTH_MS * MAX_FS_KHZ ) - -/* Milliseconds of lookahead for pitch analysis */ -#define LA_PITCH_MS 2 -#define LA_PITCH_MAX ( LA_PITCH_MS * MAX_FS_KHZ ) - -/* Order of LPC used in find pitch */ -#define MAX_FIND_PITCH_LPC_ORDER 16 - -/* Length of LPC window used in find pitch */ -#define FIND_PITCH_LPC_WIN_MS ( 20 + (LA_PITCH_MS << 1) ) -#define FIND_PITCH_LPC_WIN_MS_2_SF ( 10 + (LA_PITCH_MS << 1) ) -#define FIND_PITCH_LPC_WIN_MAX ( FIND_PITCH_LPC_WIN_MS * MAX_FS_KHZ ) - -/* Milliseconds of lookahead for noise shape analysis */ -#define LA_SHAPE_MS 5 -#define LA_SHAPE_MAX ( LA_SHAPE_MS * MAX_FS_KHZ ) - -/* Maximum length of LPC window used in noise shape analysis */ -#define SHAPE_LPC_WIN_MAX ( 15 * MAX_FS_KHZ ) - -/* dB level of lowest gain quantization level */ -#define MIN_QGAIN_DB 2 -/* dB level of highest gain quantization level */ -#define MAX_QGAIN_DB 88 -/* Number of gain quantization levels */ -#define N_LEVELS_QGAIN 64 -/* Max increase in gain quantization index */ -#define MAX_DELTA_GAIN_QUANT 36 -/* Max decrease in gain quantization index */ -#define MIN_DELTA_GAIN_QUANT -4 - -/* Quantization offsets (multiples of 4) */ -#define OFFSET_VL_Q10 32 -#define OFFSET_VH_Q10 100 -#define OFFSET_UVL_Q10 100 -#define OFFSET_UVH_Q10 240 - -#define QUANT_LEVEL_ADJUST_Q10 80 - -/* Maximum numbers of iterations used to stabilize a LPC vector */ -#define MAX_LPC_STABILIZE_ITERATIONS 20 - -#define MAX_LPC_ORDER 16 -#define MIN_LPC_ORDER 10 - -/* Find Pred Coef defines */ -#define LTP_ORDER 5 - -/* LTP quantization settings */ -#define NB_LTP_CBKS 3 - -/* Flag to use harmonic noise shaping */ -#define USE_HARM_SHAPING 1 - -/* Max LPC order of noise shaping filters */ -#define MAX_SHAPE_LPC_ORDER 16 - -#define HARM_SHAPE_FIR_TAPS 3 - -/* Maximum number of delayed decision states */ -#define MAX_DEL_DEC_STATES 4 - -#define LTP_BUF_LENGTH 512 -#define LTP_MASK ( LTP_BUF_LENGTH - 1 ) - -#define DECISION_DELAY 32 -#define DECISION_DELAY_MASK ( DECISION_DELAY - 1 ) - -/* Number of subframes for excitation entropy coding */ -#define SHELL_CODEC_FRAME_LENGTH 16 -#define LOG2_SHELL_CODEC_FRAME_LENGTH 4 -#define MAX_NB_SHELL_BLOCKS ( MAX_FRAME_LENGTH / SHELL_CODEC_FRAME_LENGTH ) - -/* Number of rate levels, for entropy coding of excitation */ -#define N_RATE_LEVELS 10 - -/* Maximum sum of pulses per shell coding frame */ -#define MAX_PULSES 16 - -#define MAX_MATRIX_SIZE MAX_LPC_ORDER /* Max of LPC Order and LTP order */ - -#if( MAX_LPC_ORDER > DECISION_DELAY ) -# define NSQ_LPC_BUF_LENGTH MAX_LPC_ORDER -#else -# define NSQ_LPC_BUF_LENGTH DECISION_DELAY -#endif - -/***********************/ -/* High pass filtering */ -/***********************/ -#define HIGH_PASS_INPUT 1 - -/***************************/ -/* Voice activity detector */ -/***************************/ -#define VAD_N_BANDS 4 - -#define VAD_INTERNAL_SUBFRAMES_LOG2 2 -#define VAD_INTERNAL_SUBFRAMES (1 << VAD_INTERNAL_SUBFRAMES_LOG2) - -#define VAD_NOISE_LEVEL_SMOOTH_COEF_Q16 1024 /* Must be < 4096 */ -#define VAD_NOISE_LEVELS_BIAS 50 - -/* Sigmoid settings */ -#define VAD_NEGATIVE_OFFSET_Q5 128 /* sigmoid is 0 at -128 */ -#define VAD_SNR_FACTOR_Q16 45000 - -/* smoothing for SNR measurement */ -#define VAD_SNR_SMOOTH_COEF_Q18 4096 - -/* Size of the piecewise linear cosine approximation table for the LSFs */ -#define LSF_COS_TAB_SZ_FIX 128 - -/******************/ -/* NLSF quantizer */ -/******************/ -#define NLSF_W_Q 2 -#define NLSF_VQ_MAX_VECTORS 32 -#define NLSF_VQ_MAX_SURVIVORS 32 -#define NLSF_QUANT_MAX_AMPLITUDE 4 -#define NLSF_QUANT_MAX_AMPLITUDE_EXT 10 -#define NLSF_QUANT_LEVEL_ADJ 0.1 -#define NLSF_QUANT_DEL_DEC_STATES_LOG2 2 -#define NLSF_QUANT_DEL_DEC_STATES ( 1 << NLSF_QUANT_DEL_DEC_STATES_LOG2 ) - -/* Transition filtering for mode switching */ -# define TRANSITION_TIME_MS 5120 // 5120 = 64 * FRAME_LENGTH_MS * ( TRANSITION_INT_NUM - 1 ) = 64*(20*4) -# define TRANSITION_NB 3 /* Hardcoded in tables */ -# define TRANSITION_NA 2 /* Hardcoded in tables */ -# define TRANSITION_INT_NUM 5 /* Hardcoded in tables */ -# define TRANSITION_FRAMES ( TRANSITION_TIME_MS / MAX_FRAME_LENGTH_MS ) // todo: needs to be made flexible for 10 ms frames -# define TRANSITION_INT_STEPS ( TRANSITION_FRAMES / ( TRANSITION_INT_NUM - 1 ) ) - -/* BWE factors to apply after packet loss */ -#define BWE_AFTER_LOSS_Q16 63570 - -/* Defines for CN generation */ -#define CNG_BUF_MASK_MAX 255 /* 2^floor(log2(MAX_FRAME_LENGTH))-1 */ -#define CNG_GAIN_SMTH_Q16 4634 /* 0.25^(1/4) */ -#define CNG_NLSF_SMTH_Q16 16348 /* 0.25 */ - -#ifdef __cplusplus -} -#endif - -#endif +/*********************************************************************** +Copyright (c) 2006-2011, Skype Limited. All rights reserved. +Redistribution and use in source and binary forms, with or without +modification, (subject to the limitations in the disclaimer below) +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 Skype Limited, nor the names of specific +contributors, may be used to endorse or promote products derived from +this software without specific prior written permission. +NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED +BY THIS LICENSE. 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. +***********************************************************************/ + +#ifndef SILK_DEFINE_H +#define SILK_DEFINE_H + +#include "silk_errors.h" +#include "silk_typedef.h" + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#ifdef __cplusplus +extern "C" +{ +#endif + +/* Max number of encoder channels (1/2) */ +#define ENCODER_NUM_CHANNELS 2 +/* Number of decoder channels (1/2) */ +#define DECODER_NUM_CHANNELS 2 + +#define MAX_FRAMES_PER_PACKET 3 + +/* Limits on bitrate */ +#define MIN_TARGET_RATE_BPS 5000 +#define MAX_TARGET_RATE_BPS 80000 +#define TARGET_RATE_TAB_SZ 8 + +/* LBRR thresholds */ +#define LBRR_NB_MIN_RATE_BPS 12000 +#define LBRR_MB_MIN_RATE_BPS 14000 +#define LBRR_WB_MIN_RATE_BPS 16000 + +/* DTX settings */ +#define NB_SPEECH_FRAMES_BEFORE_DTX 10 /* eq 200 ms */ +#define MAX_CONSECUTIVE_DTX 20 /* eq 400 ms */ + +/* Maximum sampling frequency, should be 16 for embedded */ +#define MAX_FS_KHZ 16 +#define MAX_API_FS_KHZ 48 + +/* Signal types */ +#define TYPE_NO_VOICE_ACTIVITY 0 +#define TYPE_UNVOICED 1 +#define TYPE_VOICED 2 + +/* Settings for stereo processing */ +#define STEREO_QUANT_TAB_SIZE 16 +#define STEREO_QUANT_SUB_STEPS 5 +#define STEREO_INTERP_LEN_MS 8 /* must be even */ +#define STEREO_RATIO_SMOOTH_COEF 0.01 /* smoothing coef for signal norms and stereo width */ + +/* Range of pitch lag estimates */ +#define PITCH_EST_MIN_LAG_MS 2 /* 2 ms -> 500 Hz */ +#define PITCH_EST_MAX_LAG_MS 18 /* 18 ms -> 56 Hz */ + +/* Maximum number of subframes */ +#define MAX_NB_SUBFR 4 + +/* Number of samples per frame */ +#define LTP_MEM_LENGTH_MS 20 +#define SUB_FRAME_LENGTH_MS 5 +#define MAX_SUB_FRAME_LENGTH ( SUB_FRAME_LENGTH_MS * MAX_FS_KHZ ) +#define MAX_FRAME_LENGTH_MS ( SUB_FRAME_LENGTH_MS * MAX_NB_SUBFR ) +#define MAX_FRAME_LENGTH ( MAX_FRAME_LENGTH_MS * MAX_FS_KHZ ) + +/* Milliseconds of lookahead for pitch analysis */ +#define LA_PITCH_MS 2 +#define LA_PITCH_MAX ( LA_PITCH_MS * MAX_FS_KHZ ) + +/* Order of LPC used in find pitch */ +#define MAX_FIND_PITCH_LPC_ORDER 16 + +/* Length of LPC window used in find pitch */ +#define FIND_PITCH_LPC_WIN_MS ( 20 + (LA_PITCH_MS << 1) ) +#define FIND_PITCH_LPC_WIN_MS_2_SF ( 10 + (LA_PITCH_MS << 1) ) +#define FIND_PITCH_LPC_WIN_MAX ( FIND_PITCH_LPC_WIN_MS * MAX_FS_KHZ ) + +/* Milliseconds of lookahead for noise shape analysis */ +#define LA_SHAPE_MS 5 +#define LA_SHAPE_MAX ( LA_SHAPE_MS * MAX_FS_KHZ ) + +/* Maximum length of LPC window used in noise shape analysis */ +#define SHAPE_LPC_WIN_MAX ( 15 * MAX_FS_KHZ ) + +/* dB level of lowest gain quantization level */ +#define MIN_QGAIN_DB 2 +/* dB level of highest gain quantization level */ +#define MAX_QGAIN_DB 88 +/* Number of gain quantization levels */ +#define N_LEVELS_QGAIN 64 +/* Max increase in gain quantization index */ +#define MAX_DELTA_GAIN_QUANT 36 +/* Max decrease in gain quantization index */ +#define MIN_DELTA_GAIN_QUANT -4 + +/* Quantization offsets (multiples of 4) */ +#define OFFSET_VL_Q10 32 +#define OFFSET_VH_Q10 100 +#define OFFSET_UVL_Q10 100 +#define OFFSET_UVH_Q10 240 + +#define QUANT_LEVEL_ADJUST_Q10 80 + +/* Maximum numbers of iterations used to stabilize a LPC vector */ +#define MAX_LPC_STABILIZE_ITERATIONS 20 + +#define MAX_LPC_ORDER 16 +#define MIN_LPC_ORDER 10 + +/* Find Pred Coef defines */ +#define LTP_ORDER 5 + +/* LTP quantization settings */ +#define NB_LTP_CBKS 3 + +/* Flag to use harmonic noise shaping */ +#define USE_HARM_SHAPING 1 + +/* Max LPC order of noise shaping filters */ +#define MAX_SHAPE_LPC_ORDER 16 + +#define HARM_SHAPE_FIR_TAPS 3 + +/* Maximum number of delayed decision states */ +#define MAX_DEL_DEC_STATES 4 + +#define LTP_BUF_LENGTH 512 +#define LTP_MASK ( LTP_BUF_LENGTH - 1 ) + +#define DECISION_DELAY 32 +#define DECISION_DELAY_MASK ( DECISION_DELAY - 1 ) + +/* Number of subframes for excitation entropy coding */ +#define SHELL_CODEC_FRAME_LENGTH 16 +#define LOG2_SHELL_CODEC_FRAME_LENGTH 4 +#define MAX_NB_SHELL_BLOCKS ( MAX_FRAME_LENGTH / SHELL_CODEC_FRAME_LENGTH ) + +/* Number of rate levels, for entropy coding of excitation */ +#define N_RATE_LEVELS 10 + +/* Maximum sum of pulses per shell coding frame */ +#define MAX_PULSES 16 + +#define MAX_MATRIX_SIZE MAX_LPC_ORDER /* Max of LPC Order and LTP order */ + +#if( MAX_LPC_ORDER > DECISION_DELAY ) +# define NSQ_LPC_BUF_LENGTH MAX_LPC_ORDER +#else +# define NSQ_LPC_BUF_LENGTH DECISION_DELAY +#endif + +/***********************/ +/* High pass filtering */ +/***********************/ +#define HIGH_PASS_INPUT 1 + +/***************************/ +/* Voice activity detector */ +/***************************/ +#define VAD_N_BANDS 4 + +#define VAD_INTERNAL_SUBFRAMES_LOG2 2 +#define VAD_INTERNAL_SUBFRAMES (1 << VAD_INTERNAL_SUBFRAMES_LOG2) + +#define VAD_NOISE_LEVEL_SMOOTH_COEF_Q16 1024 /* Must be < 4096 */ +#define VAD_NOISE_LEVELS_BIAS 50 + +/* Sigmoid settings */ +#define VAD_NEGATIVE_OFFSET_Q5 128 /* sigmoid is 0 at -128 */ +#define VAD_SNR_FACTOR_Q16 45000 + +/* smoothing for SNR measurement */ +#define VAD_SNR_SMOOTH_COEF_Q18 4096 + +/* Size of the piecewise linear cosine approximation table for the LSFs */ +#define LSF_COS_TAB_SZ_FIX 128 + +/******************/ +/* NLSF quantizer */ +/******************/ +#define NLSF_W_Q 2 +#define NLSF_VQ_MAX_VECTORS 32 +#define NLSF_VQ_MAX_SURVIVORS 32 +#define NLSF_QUANT_MAX_AMPLITUDE 4 +#define NLSF_QUANT_MAX_AMPLITUDE_EXT 10 +#define NLSF_QUANT_LEVEL_ADJ 0.1 +#define NLSF_QUANT_DEL_DEC_STATES_LOG2 2 +#define NLSF_QUANT_DEL_DEC_STATES ( 1 << NLSF_QUANT_DEL_DEC_STATES_LOG2 ) + +/* Transition filtering for mode switching */ +# define TRANSITION_TIME_MS 5120 // 5120 = 64 * FRAME_LENGTH_MS * ( TRANSITION_INT_NUM - 1 ) = 64*(20*4) +# define TRANSITION_NB 3 /* Hardcoded in tables */ +# define TRANSITION_NA 2 /* Hardcoded in tables */ +# define TRANSITION_INT_NUM 5 /* Hardcoded in tables */ +# define TRANSITION_FRAMES ( TRANSITION_TIME_MS / MAX_FRAME_LENGTH_MS ) // todo: needs to be made flexible for 10 ms frames +# define TRANSITION_INT_STEPS ( TRANSITION_FRAMES / ( TRANSITION_INT_NUM - 1 ) ) + +/* BWE factors to apply after packet loss */ +#define BWE_AFTER_LOSS_Q16 63570 + +/* Defines for CN generation */ +#define CNG_BUF_MASK_MAX 255 /* 2^floor(log2(MAX_FRAME_LENGTH))-1 */ +#define CNG_GAIN_SMTH_Q16 4634 /* 0.25^(1/4) */ +#define CNG_NLSF_SMTH_Q16 16348 /* 0.25 */ + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/silk/silk_enc_API.c b/silk/silk_enc_API.c index 992ba6607..957b8f964 100644 --- a/silk/silk_enc_API.c +++ b/silk/silk_enc_API.c @@ -1,412 +1,412 @@ -/*********************************************************************** -Copyright (c) 2006-2011, Skype Limited. All rights reserved. -Redistribution and use in source and binary forms, with or without -modification, (subject to the limitations in the disclaimer below) -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 Skype Limited, nor the names of specific -contributors, may be used to endorse or promote products derived from -this software without specific prior written permission. -NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED -BY THIS LICENSE. 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 "silk_define.h" -#include "silk_API.h" -#include "silk_control.h" -#include "silk_typedef.h" -#include "silk_structs.h" -#include "silk_tuning_parameters.h" -#ifdef FIXED_POINT -#include "silk_main_FIX.h" -#else -#include "silk_main_FLP.h" -#endif - -/****************************************/ -/* Encoder functions */ -/****************************************/ - -opus_int silk_Get_Encoder_Size( opus_int32 *encSizeBytes ) -{ - opus_int ret = SILK_NO_ERROR; - - *encSizeBytes = sizeof( silk_encoder ); - - return ret; -} - -/*************************/ -/* Init or Reset encoder */ -/*************************/ -opus_int silk_InitEncoder( - void *encState, /* I/O: State */ - silk_EncControlStruct *encStatus /* O: Control structure */ -) -{ - silk_encoder *psEnc; - opus_int n, ret = SILK_NO_ERROR; - - psEnc = (silk_encoder *)encState; - - /* Reset encoder */ - SKP_memset( psEnc, 0, sizeof( silk_encoder ) ); - for( n = 0; n < ENCODER_NUM_CHANNELS; n++ ) { - if( ret += silk_init_encoder( &psEnc->state_Fxx[ n ] ) ) { - SKP_assert( 0 ); - } - } - - psEnc->nChannelsAPI = 1; - psEnc->nChannelsInternal = 1; - - /* Read control structure */ - if( ret += silk_QueryEncoder( encState, encStatus ) ) { - SKP_assert( 0 ); - } - - return ret; -} - -/***************************************/ -/* Read control structure from encoder */ -/***************************************/ -opus_int silk_QueryEncoder( - const void *encState, /* I: State Vector */ - silk_EncControlStruct *encStatus /* O: Control Structure */ -) -{ - opus_int ret = SILK_NO_ERROR; - silk_encoder_state_Fxx *state_Fxx; - silk_encoder *psEnc = (silk_encoder *)encState; - - state_Fxx = psEnc->state_Fxx; - - encStatus->nChannelsAPI = psEnc->nChannelsAPI; - encStatus->nChannelsInternal = psEnc->nChannelsInternal; - encStatus->API_sampleRate = state_Fxx[ 0 ].sCmn.API_fs_Hz; - encStatus->maxInternalSampleRate = state_Fxx[ 0 ].sCmn.maxInternal_fs_Hz; - encStatus->minInternalSampleRate = state_Fxx[ 0 ].sCmn.minInternal_fs_Hz; - encStatus->desiredInternalSampleRate = state_Fxx[ 0 ].sCmn.desiredInternal_fs_Hz; - encStatus->payloadSize_ms = state_Fxx[ 0 ].sCmn.PacketSize_ms; - encStatus->bitRate = state_Fxx[ 0 ].sCmn.TargetRate_bps; - encStatus->packetLossPercentage = state_Fxx[ 0 ].sCmn.PacketLoss_perc; - encStatus->complexity = state_Fxx[ 0 ].sCmn.Complexity; - encStatus->useInBandFEC = state_Fxx[ 0 ].sCmn.useInBandFEC; - encStatus->useDTX = state_Fxx[ 0 ].sCmn.useDTX; - encStatus->useCBR = state_Fxx[ 0 ].sCmn.useCBR; - encStatus->HP_cutoff_Hz = state_Fxx[ 0 ].sCmn.HP_cutoff_Hz; - encStatus->internalSampleRate = SKP_SMULBB( state_Fxx[ 0 ].sCmn.fs_kHz, 1000 ); - encStatus->allowBandwidthSwitch = state_Fxx[ 0 ].sCmn.allow_bandwidth_switch; - encStatus->inWBmodeWithoutVariableLP = state_Fxx[ 0 ].sCmn.fs_kHz == 16 && state_Fxx[ 0 ].sCmn.sLP.mode == 0; - - return ret; -} - -/**************************/ -/* Encode frame with Silk */ -/**************************/ -opus_int silk_Encode( - void *encState, /* I/O: State */ - silk_EncControlStruct *encControl, /* I: Control structure */ - const opus_int16 *samplesIn, /* I: Speech sample input vector */ - opus_int nSamplesIn, /* I: Number of samples in input vector */ - ec_enc *psRangeEnc, /* I/O Compressor data structure */ - opus_int32 *nBytesOut, /* I/O: Number of bytes in payload (input: Max bytes) */ - const opus_int prefillFlag /* I: Flag to indicate prefilling buffers; no coding */ -) -{ - opus_int n, i, nBits, flags, tmp_payloadSize_ms = 0, tmp_complexity = 0, ret = 0; - opus_int nSamplesToBuffer, nBlocksOf10ms, nSamplesFromInput = 0; - opus_int speech_act_thr_for_switch_Q8; - opus_int32 TargetRate_bps, MStargetRates_bps[ 2 ], channelRate_bps, LBRR_symbol; - silk_encoder *psEnc = ( silk_encoder * )encState; - opus_int16 buf[ MAX_FRAME_LENGTH_MS * MAX_API_FS_KHZ ]; - - /* Check values in encoder control structure */ - if( ( ret = check_control_input( encControl ) != 0 ) ) { - SKP_assert( 0 ); - return ret; - } - - if( encControl->nChannelsInternal > psEnc->nChannelsInternal ) { - /* Mono -> Stereo transition: init state of second channel and stereo state */ - ret += silk_init_encoder( &psEnc->state_Fxx[ 1 ] ); - SKP_memset( psEnc->sStereo.pred_prev_Q13, 0, sizeof( psEnc->sStereo.pred_prev_Q13 ) ); - SKP_memset( psEnc->sStereo.sSide, 0, sizeof( psEnc->sStereo.sSide ) ); - SKP_memset( psEnc->sStereo.mid_side_amp_Q0, 0, sizeof( psEnc->sStereo.mid_side_amp_Q0 ) ); - psEnc->sStereo.width_prev_Q14 = 0; - psEnc->sStereo.smth_width_Q14 = SILK_FIX_CONST( 1, 14 ); - if( psEnc->nChannelsAPI == 2 ) { - SKP_memcpy( &psEnc->state_Fxx[ 1 ].sCmn.resampler_state, &psEnc->state_Fxx[ 0 ].sCmn.resampler_state, sizeof( silk_resampler_state_struct ) ); - SKP_memcpy( &psEnc->state_Fxx[ 1 ].sCmn.In_HP_State, &psEnc->state_Fxx[ 0 ].sCmn.In_HP_State, sizeof( psEnc->state_Fxx[ 1 ].sCmn.In_HP_State ) ); - } - } - psEnc->nChannelsAPI = encControl->nChannelsAPI; - psEnc->nChannelsInternal = encControl->nChannelsInternal; - - nBlocksOf10ms = SKP_DIV32( 100 * nSamplesIn, encControl->API_sampleRate ); - if( prefillFlag ) { - /* Only accept input length of 10 ms */ - if( nBlocksOf10ms != 1 ) { - ret = SILK_ENC_INPUT_INVALID_NO_OF_SAMPLES; - SKP_assert( 0 ); - return ret; - } - /* Reset Encoder */ - for( n = 0; n < encControl->nChannelsInternal; n++ ) { - if( ret = silk_init_encoder( &psEnc->state_Fxx[ n ] ) ) { - SKP_assert( 0 ); - } - } - tmp_payloadSize_ms = encControl->payloadSize_ms; - encControl->payloadSize_ms = 10; - tmp_complexity = encControl->complexity; - encControl->complexity = 0; - for( n = 0; n < encControl->nChannelsInternal; n++ ) { - psEnc->state_Fxx[ n ].sCmn.controlled_since_last_payload = 0; - psEnc->state_Fxx[ n ].sCmn.prefillFlag = 1; - } - } else { - /* Only accept input lengths that are a multiple of 10 ms */ - if( nBlocksOf10ms * encControl->API_sampleRate != 100 * nSamplesIn || nSamplesIn < 0 ) { - ret = SILK_ENC_INPUT_INVALID_NO_OF_SAMPLES; - SKP_assert( 0 ); - return ret; - } - /* Make sure no more than one packet can be produced */ - if( 1000 * (opus_int32)nSamplesIn > encControl->payloadSize_ms * encControl->API_sampleRate ) { - ret = SILK_ENC_INPUT_INVALID_NO_OF_SAMPLES; - SKP_assert( 0 ); - return ret; - } - } - - TargetRate_bps = SKP_RSHIFT32( encControl->bitRate, encControl->nChannelsInternal - 1 ); - for( n = 0; n < encControl->nChannelsInternal; n++ ) { - if( ( ret = silk_control_encoder( &psEnc->state_Fxx[ n ], encControl, TargetRate_bps, psEnc->allowBandwidthSwitch, n ) ) != 0 ) { - SKP_assert( 0 ); - return ret; - } - } - SKP_assert( encControl->nChannelsInternal == 1 || psEnc->state_Fxx[ 0 ].sCmn.fs_kHz == psEnc->state_Fxx[ 1 ].sCmn.fs_kHz ); - - /* Input buffering/resampling and encoding */ - while( 1 ) { - nSamplesToBuffer = psEnc->state_Fxx[ 0 ].sCmn.frame_length - psEnc->state_Fxx[ 0 ].sCmn.inputBufIx; - nSamplesToBuffer = SKP_min( nSamplesToBuffer, 10 * nBlocksOf10ms * psEnc->state_Fxx[ 0 ].sCmn.fs_kHz ); - nSamplesFromInput = SKP_DIV32_16( nSamplesToBuffer * psEnc->state_Fxx[ 0 ].sCmn.API_fs_Hz, psEnc->state_Fxx[ 0 ].sCmn.fs_kHz * 1000 ); - /* Resample and write to buffer */ - if( encControl->nChannelsAPI == 2 && encControl->nChannelsInternal == 2 ) { - for( n = 0; n < nSamplesFromInput; n++ ) { - buf[ n ] = samplesIn[ 2 * n ]; - } - ret += silk_resampler( &psEnc->state_Fxx[ 0 ].sCmn.resampler_state, - &psEnc->state_Fxx[ 0 ].sCmn.inputBuf[ psEnc->state_Fxx[ 0 ].sCmn.inputBufIx ], buf, nSamplesFromInput ); - psEnc->state_Fxx[ 0 ].sCmn.inputBufIx += nSamplesToBuffer; - - nSamplesToBuffer = psEnc->state_Fxx[ 1 ].sCmn.frame_length - psEnc->state_Fxx[ 1 ].sCmn.inputBufIx; - nSamplesToBuffer = SKP_min( nSamplesToBuffer, 10 * nBlocksOf10ms * psEnc->state_Fxx[ 1 ].sCmn.fs_kHz ); - for( n = 0; n < nSamplesFromInput; n++ ) { - buf[ n ] = samplesIn[ 2 * n + 1 ]; - } - ret += silk_resampler( &psEnc->state_Fxx[ 1 ].sCmn.resampler_state, - &psEnc->state_Fxx[ 1 ].sCmn.inputBuf[ psEnc->state_Fxx[ 1 ].sCmn.inputBufIx ], buf, nSamplesFromInput ); - psEnc->state_Fxx[ 1 ].sCmn.inputBufIx += nSamplesToBuffer; - } else if( encControl->nChannelsAPI == 2 && encControl->nChannelsInternal == 1 ) { - /* Combine left and right channels before resampling */ - for( n = 0; n < nSamplesFromInput; n++ ) { - buf[ n ] = (opus_int16)SKP_RSHIFT_ROUND( samplesIn[ 2 * n ] + samplesIn[ 2 * n + 1 ], 1 ); - } - ret += silk_resampler( &psEnc->state_Fxx[ 0 ].sCmn.resampler_state, - &psEnc->state_Fxx[ 0 ].sCmn.inputBuf[ psEnc->state_Fxx[ 0 ].sCmn.inputBufIx ], buf, nSamplesFromInput ); - psEnc->state_Fxx[ 0 ].sCmn.inputBufIx += nSamplesToBuffer; - } else { - SKP_assert( encControl->nChannelsAPI == 1 && encControl->nChannelsInternal == 1 ); - ret += silk_resampler( &psEnc->state_Fxx[ 0 ].sCmn.resampler_state, - &psEnc->state_Fxx[ 0 ].sCmn.inputBuf[ psEnc->state_Fxx[ 0 ].sCmn.inputBufIx ], samplesIn, nSamplesFromInput ); - psEnc->state_Fxx[ 0 ].sCmn.inputBufIx += nSamplesToBuffer; - } - samplesIn += nSamplesFromInput * encControl->nChannelsAPI; - nSamplesIn -= nSamplesFromInput; - - /* Default */ - psEnc->allowBandwidthSwitch = 0; - - /* Silk encoder */ - if( psEnc->state_Fxx[ 0 ].sCmn.inputBufIx >= psEnc->state_Fxx[ 0 ].sCmn.frame_length ) { - /* Enough data in input buffer, so encode */ - SKP_assert( psEnc->state_Fxx[ 0 ].sCmn.inputBufIx == psEnc->state_Fxx[ 0 ].sCmn.frame_length ); - SKP_assert( encControl->nChannelsInternal == 1 || psEnc->state_Fxx[ 1 ].sCmn.inputBufIx == psEnc->state_Fxx[ 1 ].sCmn.frame_length ); - - /* Deal with LBRR data */ - if( psEnc->state_Fxx[ 0 ].sCmn.nFramesEncoded == 0 && !prefillFlag ) { - /* Create space at start of payload for VAD and FEC flags */ - opus_uint8 iCDF[ 2 ] = { 0, 0 }; - iCDF[ 0 ] = 256 - SKP_RSHIFT( 256, ( psEnc->state_Fxx[ 0 ].sCmn.nFramesPerPacket + 1 ) * encControl->nChannelsInternal ); - ec_enc_icdf( psRangeEnc, 0, iCDF, 8 ); - - /* Encode any LBRR data from previous packet */ - /* Encode LBRR flags */ - for( n = 0; n < encControl->nChannelsInternal; n++ ) { - LBRR_symbol = 0; - for( i = 0; i < psEnc->state_Fxx[ n ].sCmn.nFramesPerPacket; i++ ) { - LBRR_symbol |= SKP_LSHIFT( psEnc->state_Fxx[ n ].sCmn.LBRR_flags[ i ], i ); - } - psEnc->state_Fxx[ n ].sCmn.LBRR_flag = LBRR_symbol > 0 ? 1 : 0; - if( LBRR_symbol && psEnc->state_Fxx[ n ].sCmn.nFramesPerPacket > 1 ) { - ec_enc_icdf( psRangeEnc, LBRR_symbol - 1, silk_LBRR_flags_iCDF_ptr[ psEnc->state_Fxx[ n ].sCmn.nFramesPerPacket - 2 ], 8 ); - } - } - - /* Code LBRR indices and excitation signals */ - for( i = 0; i < psEnc->state_Fxx[ 0 ].sCmn.nFramesPerPacket; i++ ) { - for( n = 0; n < encControl->nChannelsInternal; n++ ) { - if( psEnc->state_Fxx[ n ].sCmn.LBRR_flags[ i ] ) { - if( encControl->nChannelsInternal == 2 && n == 0 ) { - silk_stereo_encode_pred( psRangeEnc, psEnc->sStereo.ix[ i ] ); - } - silk_encode_indices( &psEnc->state_Fxx[ n ].sCmn, psRangeEnc, i, 1 ); - silk_encode_pulses( psRangeEnc, psEnc->state_Fxx[ n ].sCmn.indices_LBRR[i].signalType, psEnc->state_Fxx[ n ].sCmn.indices_LBRR[i].quantOffsetType, - psEnc->state_Fxx[ n ].sCmn.pulses_LBRR[ i ], psEnc->state_Fxx[ n ].sCmn.frame_length ); - } - } - } - - /* Reset LBRR flags */ - for( n = 0; n < encControl->nChannelsInternal; n++ ) { - SKP_memset( psEnc->state_Fxx[ n ].sCmn.LBRR_flags, 0, sizeof( psEnc->state_Fxx[ n ].sCmn.LBRR_flags ) ); - } - } - - /* High-pass filter */ - psEnc->state_Fxx[ 0 ].sCmn.HP_cutoff_Hz = encControl->HP_cutoff_Hz; - silk_HP_variable_cutoff( psEnc->state_Fxx, psEnc->nChannelsInternal ); - - /* Total target bits for packet */ - nBits = SKP_DIV32_16( SKP_MUL( encControl->bitRate, encControl->payloadSize_ms ), 1000 ); - /* Subtract half of the bits already used */ - if (!prefillFlag) - nBits -= ec_tell( psRangeEnc ) >> 1; - /* Divide by number of uncoded frames left in packet */ - nBits = SKP_DIV32_16( nBits, psEnc->state_Fxx[ 0 ].sCmn.nFramesPerPacket - psEnc->state_Fxx[ 0 ].sCmn.nFramesEncoded ); - /* Convert to bits/second */ - if( encControl->payloadSize_ms == 10 ) { - TargetRate_bps = SKP_SMULBB( nBits, 100 ); - } else { - TargetRate_bps = SKP_SMULBB( nBits, 50 ); - } - /* Subtract fraction of bits in excess of target in previous packets */ - TargetRate_bps -= SKP_DIV32_16( SKP_MUL( psEnc->nBitsExceeded, 1000 ), BITRESERVOIR_DECAY_TIME_MS ); - /* Never exceed input bitrate */ - TargetRate_bps = SKP_LIMIT( TargetRate_bps, encControl->bitRate, 5000 ); - - /* Convert Left/Right to Mid/Side */ - if( encControl->nChannelsInternal == 2 ) { - silk_stereo_LR_to_MS( &psEnc->sStereo, psEnc->state_Fxx[ 0 ].sCmn.inputBuf, psEnc->state_Fxx[ 1 ].sCmn.inputBuf, - psEnc->sStereo.ix[ psEnc->state_Fxx[ 0 ].sCmn.nFramesEncoded ], MStargetRates_bps, TargetRate_bps, - psEnc->state_Fxx[ 0 ].sCmn.speech_activity_Q8, psEnc->state_Fxx[ 0 ].sCmn.fs_kHz, psEnc->state_Fxx[ 0 ].sCmn.frame_length ); - if (!prefillFlag) - silk_stereo_encode_pred( psRangeEnc, psEnc->sStereo.ix[ psEnc->state_Fxx[ 0 ].sCmn.nFramesEncoded ] ); - } else { - /* Buffering */ - SKP_memcpy( &psEnc->state_Fxx[ 0 ].sCmn.inputBuf[ -2 ], psEnc->sStereo.sMid, 2 * sizeof( opus_int16 ) ); - SKP_memcpy( psEnc->sStereo.sMid, &psEnc->state_Fxx[ 0 ].sCmn.inputBuf[ psEnc->state_Fxx[ 0 ].sCmn.frame_length - 2 ], 2 * sizeof( opus_int16 ) ); - } - - /* Encode */ - for( n = 0; n < encControl->nChannelsInternal; n++ ) { - if( encControl->nChannelsInternal == 1 ) { - channelRate_bps = TargetRate_bps; - } else { - channelRate_bps = MStargetRates_bps[ n ]; - } - - if( channelRate_bps > 0 ) { - silk_control_SNR( &psEnc->state_Fxx[ n ].sCmn, channelRate_bps ); - - if( ( ret = silk_encode_frame_Fxx( &psEnc->state_Fxx[ n ], nBytesOut, psRangeEnc ) ) != 0 ) { - SKP_assert( 0 ); - } - } - - psEnc->state_Fxx[ n ].sCmn.controlled_since_last_payload = 0; - psEnc->state_Fxx[ n ].sCmn.inputBufIx = 0; - } - - /* Insert VAD and FEC flags at beginning of bitstream */ - if( *nBytesOut > 0 ) { - flags = 0; - for( n = 0; n < encControl->nChannelsInternal; n++ ) { - for( i = 0; i < psEnc->state_Fxx[ n ].sCmn.nFramesPerPacket; i++ ) { - flags = SKP_LSHIFT( flags, 1 ); - flags |= psEnc->state_Fxx[ n ].sCmn.VAD_flags[ i ]; - } - flags = SKP_LSHIFT( flags, 1 ); - flags |= psEnc->state_Fxx[ n ].sCmn.LBRR_flag; - } - if (!prefillFlag) - ec_enc_patch_initial_bits( psRangeEnc, flags, ( psEnc->state_Fxx[ 0 ].sCmn.nFramesPerPacket + 1 ) * encControl->nChannelsInternal ); - - /* Return zero bytes if all channels DTXed */ - if( psEnc->state_Fxx[ 0 ].sCmn.inDTX && ( encControl->nChannelsInternal == 1 || psEnc->state_Fxx[ 1 ].sCmn.inDTX ) ) { - *nBytesOut = 0; - } - - psEnc->nBitsExceeded += *nBytesOut * 8; - psEnc->nBitsExceeded -= SKP_DIV32_16( SKP_MUL( encControl->bitRate, encControl->payloadSize_ms ), 1000 ); - psEnc->nBitsExceeded = SKP_LIMIT( psEnc->nBitsExceeded, 0, 10000 ); - - /* Update flag indicating if bandwidth switching is allowed */ - speech_act_thr_for_switch_Q8 = SKP_SMLAWB( SILK_FIX_CONST( SPEECH_ACTIVITY_DTX_THRES, 8 ), - SILK_FIX_CONST( ( 1 - SPEECH_ACTIVITY_DTX_THRES ) / MAX_BANDWIDTH_SWITCH_DELAY_MS, 16 + 8 ), psEnc->timeSinceSwitchAllowed_ms ); - if( psEnc->state_Fxx[ 0 ].sCmn.speech_activity_Q8 < speech_act_thr_for_switch_Q8 ) { - psEnc->allowBandwidthSwitch = 1; - psEnc->timeSinceSwitchAllowed_ms = 0; - } else { - psEnc->allowBandwidthSwitch = 0; - psEnc->timeSinceSwitchAllowed_ms += encControl->payloadSize_ms; - } - } - - if( nSamplesIn == 0 ) { - break; - } - } else { - break; - } - } - - encControl->allowBandwidthSwitch = psEnc->allowBandwidthSwitch; - encControl->inWBmodeWithoutVariableLP = psEnc->state_Fxx[ 0 ].sCmn.fs_kHz == 16 && psEnc->state_Fxx[ 0 ].sCmn.sLP.mode == 0; - encControl->internalSampleRate = SKP_SMULBB( psEnc->state_Fxx[ 0 ].sCmn.fs_kHz, 1000 ); - encControl->stereoWidth_Q14 = psEnc->sStereo.width_prev_Q14; - if( prefillFlag ) { - encControl->payloadSize_ms = tmp_payloadSize_ms; - encControl->complexity = tmp_complexity; - for( n = 0; n < encControl->nChannelsInternal; n++ ) { - psEnc->state_Fxx[ n ].sCmn.controlled_since_last_payload = 0; - psEnc->state_Fxx[ n ].sCmn.prefillFlag = 0; - } - } - - return ret; -} - +/*********************************************************************** +Copyright (c) 2006-2011, Skype Limited. All rights reserved. +Redistribution and use in source and binary forms, with or without +modification, (subject to the limitations in the disclaimer below) +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 Skype Limited, nor the names of specific +contributors, may be used to endorse or promote products derived from +this software without specific prior written permission. +NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED +BY THIS LICENSE. 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 "silk_define.h" +#include "silk_API.h" +#include "silk_control.h" +#include "silk_typedef.h" +#include "silk_structs.h" +#include "silk_tuning_parameters.h" +#ifdef FIXED_POINT +#include "silk_main_FIX.h" +#else +#include "silk_main_FLP.h" +#endif + +/****************************************/ +/* Encoder functions */ +/****************************************/ + +opus_int silk_Get_Encoder_Size( opus_int32 *encSizeBytes ) +{ + opus_int ret = SILK_NO_ERROR; + + *encSizeBytes = sizeof( silk_encoder ); + + return ret; +} + +/*************************/ +/* Init or Reset encoder */ +/*************************/ +opus_int silk_InitEncoder( + void *encState, /* I/O: State */ + silk_EncControlStruct *encStatus /* O: Control structure */ +) +{ + silk_encoder *psEnc; + opus_int n, ret = SILK_NO_ERROR; + + psEnc = (silk_encoder *)encState; + + /* Reset encoder */ + SKP_memset( psEnc, 0, sizeof( silk_encoder ) ); + for( n = 0; n < ENCODER_NUM_CHANNELS; n++ ) { + if( ret += silk_init_encoder( &psEnc->state_Fxx[ n ] ) ) { + SKP_assert( 0 ); + } + } + + psEnc->nChannelsAPI = 1; + psEnc->nChannelsInternal = 1; + + /* Read control structure */ + if( ret += silk_QueryEncoder( encState, encStatus ) ) { + SKP_assert( 0 ); + } + + return ret; +} + +/***************************************/ +/* Read control structure from encoder */ +/***************************************/ +opus_int silk_QueryEncoder( + const void *encState, /* I: State Vector */ + silk_EncControlStruct *encStatus /* O: Control Structure */ +) +{ + opus_int ret = SILK_NO_ERROR; + silk_encoder_state_Fxx *state_Fxx; + silk_encoder *psEnc = (silk_encoder *)encState; + + state_Fxx = psEnc->state_Fxx; + + encStatus->nChannelsAPI = psEnc->nChannelsAPI; + encStatus->nChannelsInternal = psEnc->nChannelsInternal; + encStatus->API_sampleRate = state_Fxx[ 0 ].sCmn.API_fs_Hz; + encStatus->maxInternalSampleRate = state_Fxx[ 0 ].sCmn.maxInternal_fs_Hz; + encStatus->minInternalSampleRate = state_Fxx[ 0 ].sCmn.minInternal_fs_Hz; + encStatus->desiredInternalSampleRate = state_Fxx[ 0 ].sCmn.desiredInternal_fs_Hz; + encStatus->payloadSize_ms = state_Fxx[ 0 ].sCmn.PacketSize_ms; + encStatus->bitRate = state_Fxx[ 0 ].sCmn.TargetRate_bps; + encStatus->packetLossPercentage = state_Fxx[ 0 ].sCmn.PacketLoss_perc; + encStatus->complexity = state_Fxx[ 0 ].sCmn.Complexity; + encStatus->useInBandFEC = state_Fxx[ 0 ].sCmn.useInBandFEC; + encStatus->useDTX = state_Fxx[ 0 ].sCmn.useDTX; + encStatus->useCBR = state_Fxx[ 0 ].sCmn.useCBR; + encStatus->HP_cutoff_Hz = state_Fxx[ 0 ].sCmn.HP_cutoff_Hz; + encStatus->internalSampleRate = SKP_SMULBB( state_Fxx[ 0 ].sCmn.fs_kHz, 1000 ); + encStatus->allowBandwidthSwitch = state_Fxx[ 0 ].sCmn.allow_bandwidth_switch; + encStatus->inWBmodeWithoutVariableLP = state_Fxx[ 0 ].sCmn.fs_kHz == 16 && state_Fxx[ 0 ].sCmn.sLP.mode == 0; + + return ret; +} + +/**************************/ +/* Encode frame with Silk */ +/**************************/ +opus_int silk_Encode( + void *encState, /* I/O: State */ + silk_EncControlStruct *encControl, /* I: Control structure */ + const opus_int16 *samplesIn, /* I: Speech sample input vector */ + opus_int nSamplesIn, /* I: Number of samples in input vector */ + ec_enc *psRangeEnc, /* I/O Compressor data structure */ + opus_int32 *nBytesOut, /* I/O: Number of bytes in payload (input: Max bytes) */ + const opus_int prefillFlag /* I: Flag to indicate prefilling buffers; no coding */ +) +{ + opus_int n, i, nBits, flags, tmp_payloadSize_ms = 0, tmp_complexity = 0, ret = 0; + opus_int nSamplesToBuffer, nBlocksOf10ms, nSamplesFromInput = 0; + opus_int speech_act_thr_for_switch_Q8; + opus_int32 TargetRate_bps, MStargetRates_bps[ 2 ], channelRate_bps, LBRR_symbol; + silk_encoder *psEnc = ( silk_encoder * )encState; + opus_int16 buf[ MAX_FRAME_LENGTH_MS * MAX_API_FS_KHZ ]; + + /* Check values in encoder control structure */ + if( ( ret = check_control_input( encControl ) != 0 ) ) { + SKP_assert( 0 ); + return ret; + } + + if( encControl->nChannelsInternal > psEnc->nChannelsInternal ) { + /* Mono -> Stereo transition: init state of second channel and stereo state */ + ret += silk_init_encoder( &psEnc->state_Fxx[ 1 ] ); + SKP_memset( psEnc->sStereo.pred_prev_Q13, 0, sizeof( psEnc->sStereo.pred_prev_Q13 ) ); + SKP_memset( psEnc->sStereo.sSide, 0, sizeof( psEnc->sStereo.sSide ) ); + SKP_memset( psEnc->sStereo.mid_side_amp_Q0, 0, sizeof( psEnc->sStereo.mid_side_amp_Q0 ) ); + psEnc->sStereo.width_prev_Q14 = 0; + psEnc->sStereo.smth_width_Q14 = SILK_FIX_CONST( 1, 14 ); + if( psEnc->nChannelsAPI == 2 ) { + SKP_memcpy( &psEnc->state_Fxx[ 1 ].sCmn.resampler_state, &psEnc->state_Fxx[ 0 ].sCmn.resampler_state, sizeof( silk_resampler_state_struct ) ); + SKP_memcpy( &psEnc->state_Fxx[ 1 ].sCmn.In_HP_State, &psEnc->state_Fxx[ 0 ].sCmn.In_HP_State, sizeof( psEnc->state_Fxx[ 1 ].sCmn.In_HP_State ) ); + } + } + psEnc->nChannelsAPI = encControl->nChannelsAPI; + psEnc->nChannelsInternal = encControl->nChannelsInternal; + + nBlocksOf10ms = SKP_DIV32( 100 * nSamplesIn, encControl->API_sampleRate ); + if( prefillFlag ) { + /* Only accept input length of 10 ms */ + if( nBlocksOf10ms != 1 ) { + ret = SILK_ENC_INPUT_INVALID_NO_OF_SAMPLES; + SKP_assert( 0 ); + return ret; + } + /* Reset Encoder */ + for( n = 0; n < encControl->nChannelsInternal; n++ ) { + if( ret = silk_init_encoder( &psEnc->state_Fxx[ n ] ) ) { + SKP_assert( 0 ); + } + } + tmp_payloadSize_ms = encControl->payloadSize_ms; + encControl->payloadSize_ms = 10; + tmp_complexity = encControl->complexity; + encControl->complexity = 0; + for( n = 0; n < encControl->nChannelsInternal; n++ ) { + psEnc->state_Fxx[ n ].sCmn.controlled_since_last_payload = 0; + psEnc->state_Fxx[ n ].sCmn.prefillFlag = 1; + } + } else { + /* Only accept input lengths that are a multiple of 10 ms */ + if( nBlocksOf10ms * encControl->API_sampleRate != 100 * nSamplesIn || nSamplesIn < 0 ) { + ret = SILK_ENC_INPUT_INVALID_NO_OF_SAMPLES; + SKP_assert( 0 ); + return ret; + } + /* Make sure no more than one packet can be produced */ + if( 1000 * (opus_int32)nSamplesIn > encControl->payloadSize_ms * encControl->API_sampleRate ) { + ret = SILK_ENC_INPUT_INVALID_NO_OF_SAMPLES; + SKP_assert( 0 ); + return ret; + } + } + + TargetRate_bps = SKP_RSHIFT32( encControl->bitRate, encControl->nChannelsInternal - 1 ); + for( n = 0; n < encControl->nChannelsInternal; n++ ) { + if( ( ret = silk_control_encoder( &psEnc->state_Fxx[ n ], encControl, TargetRate_bps, psEnc->allowBandwidthSwitch, n ) ) != 0 ) { + SKP_assert( 0 ); + return ret; + } + } + SKP_assert( encControl->nChannelsInternal == 1 || psEnc->state_Fxx[ 0 ].sCmn.fs_kHz == psEnc->state_Fxx[ 1 ].sCmn.fs_kHz ); + + /* Input buffering/resampling and encoding */ + while( 1 ) { + nSamplesToBuffer = psEnc->state_Fxx[ 0 ].sCmn.frame_length - psEnc->state_Fxx[ 0 ].sCmn.inputBufIx; + nSamplesToBuffer = SKP_min( nSamplesToBuffer, 10 * nBlocksOf10ms * psEnc->state_Fxx[ 0 ].sCmn.fs_kHz ); + nSamplesFromInput = SKP_DIV32_16( nSamplesToBuffer * psEnc->state_Fxx[ 0 ].sCmn.API_fs_Hz, psEnc->state_Fxx[ 0 ].sCmn.fs_kHz * 1000 ); + /* Resample and write to buffer */ + if( encControl->nChannelsAPI == 2 && encControl->nChannelsInternal == 2 ) { + for( n = 0; n < nSamplesFromInput; n++ ) { + buf[ n ] = samplesIn[ 2 * n ]; + } + ret += silk_resampler( &psEnc->state_Fxx[ 0 ].sCmn.resampler_state, + &psEnc->state_Fxx[ 0 ].sCmn.inputBuf[ psEnc->state_Fxx[ 0 ].sCmn.inputBufIx ], buf, nSamplesFromInput ); + psEnc->state_Fxx[ 0 ].sCmn.inputBufIx += nSamplesToBuffer; + + nSamplesToBuffer = psEnc->state_Fxx[ 1 ].sCmn.frame_length - psEnc->state_Fxx[ 1 ].sCmn.inputBufIx; + nSamplesToBuffer = SKP_min( nSamplesToBuffer, 10 * nBlocksOf10ms * psEnc->state_Fxx[ 1 ].sCmn.fs_kHz ); + for( n = 0; n < nSamplesFromInput; n++ ) { + buf[ n ] = samplesIn[ 2 * n + 1 ]; + } + ret += silk_resampler( &psEnc->state_Fxx[ 1 ].sCmn.resampler_state, + &psEnc->state_Fxx[ 1 ].sCmn.inputBuf[ psEnc->state_Fxx[ 1 ].sCmn.inputBufIx ], buf, nSamplesFromInput ); + psEnc->state_Fxx[ 1 ].sCmn.inputBufIx += nSamplesToBuffer; + } else if( encControl->nChannelsAPI == 2 && encControl->nChannelsInternal == 1 ) { + /* Combine left and right channels before resampling */ + for( n = 0; n < nSamplesFromInput; n++ ) { + buf[ n ] = (opus_int16)SKP_RSHIFT_ROUND( samplesIn[ 2 * n ] + samplesIn[ 2 * n + 1 ], 1 ); + } + ret += silk_resampler( &psEnc->state_Fxx[ 0 ].sCmn.resampler_state, + &psEnc->state_Fxx[ 0 ].sCmn.inputBuf[ psEnc->state_Fxx[ 0 ].sCmn.inputBufIx ], buf, nSamplesFromInput ); + psEnc->state_Fxx[ 0 ].sCmn.inputBufIx += nSamplesToBuffer; + } else { + SKP_assert( encControl->nChannelsAPI == 1 && encControl->nChannelsInternal == 1 ); + ret += silk_resampler( &psEnc->state_Fxx[ 0 ].sCmn.resampler_state, + &psEnc->state_Fxx[ 0 ].sCmn.inputBuf[ psEnc->state_Fxx[ 0 ].sCmn.inputBufIx ], samplesIn, nSamplesFromInput ); + psEnc->state_Fxx[ 0 ].sCmn.inputBufIx += nSamplesToBuffer; + } + samplesIn += nSamplesFromInput * encControl->nChannelsAPI; + nSamplesIn -= nSamplesFromInput; + + /* Default */ + psEnc->allowBandwidthSwitch = 0; + + /* Silk encoder */ + if( psEnc->state_Fxx[ 0 ].sCmn.inputBufIx >= psEnc->state_Fxx[ 0 ].sCmn.frame_length ) { + /* Enough data in input buffer, so encode */ + SKP_assert( psEnc->state_Fxx[ 0 ].sCmn.inputBufIx == psEnc->state_Fxx[ 0 ].sCmn.frame_length ); + SKP_assert( encControl->nChannelsInternal == 1 || psEnc->state_Fxx[ 1 ].sCmn.inputBufIx == psEnc->state_Fxx[ 1 ].sCmn.frame_length ); + + /* Deal with LBRR data */ + if( psEnc->state_Fxx[ 0 ].sCmn.nFramesEncoded == 0 && !prefillFlag ) { + /* Create space at start of payload for VAD and FEC flags */ + opus_uint8 iCDF[ 2 ] = { 0, 0 }; + iCDF[ 0 ] = 256 - SKP_RSHIFT( 256, ( psEnc->state_Fxx[ 0 ].sCmn.nFramesPerPacket + 1 ) * encControl->nChannelsInternal ); + ec_enc_icdf( psRangeEnc, 0, iCDF, 8 ); + + /* Encode any LBRR data from previous packet */ + /* Encode LBRR flags */ + for( n = 0; n < encControl->nChannelsInternal; n++ ) { + LBRR_symbol = 0; + for( i = 0; i < psEnc->state_Fxx[ n ].sCmn.nFramesPerPacket; i++ ) { + LBRR_symbol |= SKP_LSHIFT( psEnc->state_Fxx[ n ].sCmn.LBRR_flags[ i ], i ); + } + psEnc->state_Fxx[ n ].sCmn.LBRR_flag = LBRR_symbol > 0 ? 1 : 0; + if( LBRR_symbol && psEnc->state_Fxx[ n ].sCmn.nFramesPerPacket > 1 ) { + ec_enc_icdf( psRangeEnc, LBRR_symbol - 1, silk_LBRR_flags_iCDF_ptr[ psEnc->state_Fxx[ n ].sCmn.nFramesPerPacket - 2 ], 8 ); + } + } + + /* Code LBRR indices and excitation signals */ + for( i = 0; i < psEnc->state_Fxx[ 0 ].sCmn.nFramesPerPacket; i++ ) { + for( n = 0; n < encControl->nChannelsInternal; n++ ) { + if( psEnc->state_Fxx[ n ].sCmn.LBRR_flags[ i ] ) { + if( encControl->nChannelsInternal == 2 && n == 0 ) { + silk_stereo_encode_pred( psRangeEnc, psEnc->sStereo.ix[ i ] ); + } + silk_encode_indices( &psEnc->state_Fxx[ n ].sCmn, psRangeEnc, i, 1 ); + silk_encode_pulses( psRangeEnc, psEnc->state_Fxx[ n ].sCmn.indices_LBRR[i].signalType, psEnc->state_Fxx[ n ].sCmn.indices_LBRR[i].quantOffsetType, + psEnc->state_Fxx[ n ].sCmn.pulses_LBRR[ i ], psEnc->state_Fxx[ n ].sCmn.frame_length ); + } + } + } + + /* Reset LBRR flags */ + for( n = 0; n < encControl->nChannelsInternal; n++ ) { + SKP_memset( psEnc->state_Fxx[ n ].sCmn.LBRR_flags, 0, sizeof( psEnc->state_Fxx[ n ].sCmn.LBRR_flags ) ); + } + } + + /* High-pass filter */ + psEnc->state_Fxx[ 0 ].sCmn.HP_cutoff_Hz = encControl->HP_cutoff_Hz; + silk_HP_variable_cutoff( psEnc->state_Fxx, psEnc->nChannelsInternal ); + + /* Total target bits for packet */ + nBits = SKP_DIV32_16( SKP_MUL( encControl->bitRate, encControl->payloadSize_ms ), 1000 ); + /* Subtract half of the bits already used */ + if (!prefillFlag) + nBits -= ec_tell( psRangeEnc ) >> 1; + /* Divide by number of uncoded frames left in packet */ + nBits = SKP_DIV32_16( nBits, psEnc->state_Fxx[ 0 ].sCmn.nFramesPerPacket - psEnc->state_Fxx[ 0 ].sCmn.nFramesEncoded ); + /* Convert to bits/second */ + if( encControl->payloadSize_ms == 10 ) { + TargetRate_bps = SKP_SMULBB( nBits, 100 ); + } else { + TargetRate_bps = SKP_SMULBB( nBits, 50 ); + } + /* Subtract fraction of bits in excess of target in previous packets */ + TargetRate_bps -= SKP_DIV32_16( SKP_MUL( psEnc->nBitsExceeded, 1000 ), BITRESERVOIR_DECAY_TIME_MS ); + /* Never exceed input bitrate */ + TargetRate_bps = SKP_LIMIT( TargetRate_bps, encControl->bitRate, 5000 ); + + /* Convert Left/Right to Mid/Side */ + if( encControl->nChannelsInternal == 2 ) { + silk_stereo_LR_to_MS( &psEnc->sStereo, psEnc->state_Fxx[ 0 ].sCmn.inputBuf, psEnc->state_Fxx[ 1 ].sCmn.inputBuf, + psEnc->sStereo.ix[ psEnc->state_Fxx[ 0 ].sCmn.nFramesEncoded ], MStargetRates_bps, TargetRate_bps, + psEnc->state_Fxx[ 0 ].sCmn.speech_activity_Q8, psEnc->state_Fxx[ 0 ].sCmn.fs_kHz, psEnc->state_Fxx[ 0 ].sCmn.frame_length ); + if (!prefillFlag) + silk_stereo_encode_pred( psRangeEnc, psEnc->sStereo.ix[ psEnc->state_Fxx[ 0 ].sCmn.nFramesEncoded ] ); + } else { + /* Buffering */ + SKP_memcpy( &psEnc->state_Fxx[ 0 ].sCmn.inputBuf[ -2 ], psEnc->sStereo.sMid, 2 * sizeof( opus_int16 ) ); + SKP_memcpy( psEnc->sStereo.sMid, &psEnc->state_Fxx[ 0 ].sCmn.inputBuf[ psEnc->state_Fxx[ 0 ].sCmn.frame_length - 2 ], 2 * sizeof( opus_int16 ) ); + } + + /* Encode */ + for( n = 0; n < encControl->nChannelsInternal; n++ ) { + if( encControl->nChannelsInternal == 1 ) { + channelRate_bps = TargetRate_bps; + } else { + channelRate_bps = MStargetRates_bps[ n ]; + } + + if( channelRate_bps > 0 ) { + silk_control_SNR( &psEnc->state_Fxx[ n ].sCmn, channelRate_bps ); + + if( ( ret = silk_encode_frame_Fxx( &psEnc->state_Fxx[ n ], nBytesOut, psRangeEnc ) ) != 0 ) { + SKP_assert( 0 ); + } + } + + psEnc->state_Fxx[ n ].sCmn.controlled_since_last_payload = 0; + psEnc->state_Fxx[ n ].sCmn.inputBufIx = 0; + } + + /* Insert VAD and FEC flags at beginning of bitstream */ + if( *nBytesOut > 0 ) { + flags = 0; + for( n = 0; n < encControl->nChannelsInternal; n++ ) { + for( i = 0; i < psEnc->state_Fxx[ n ].sCmn.nFramesPerPacket; i++ ) { + flags = SKP_LSHIFT( flags, 1 ); + flags |= psEnc->state_Fxx[ n ].sCmn.VAD_flags[ i ]; + } + flags = SKP_LSHIFT( flags, 1 ); + flags |= psEnc->state_Fxx[ n ].sCmn.LBRR_flag; + } + if (!prefillFlag) + ec_enc_patch_initial_bits( psRangeEnc, flags, ( psEnc->state_Fxx[ 0 ].sCmn.nFramesPerPacket + 1 ) * encControl->nChannelsInternal ); + + /* Return zero bytes if all channels DTXed */ + if( psEnc->state_Fxx[ 0 ].sCmn.inDTX && ( encControl->nChannelsInternal == 1 || psEnc->state_Fxx[ 1 ].sCmn.inDTX ) ) { + *nBytesOut = 0; + } + + psEnc->nBitsExceeded += *nBytesOut * 8; + psEnc->nBitsExceeded -= SKP_DIV32_16( SKP_MUL( encControl->bitRate, encControl->payloadSize_ms ), 1000 ); + psEnc->nBitsExceeded = SKP_LIMIT( psEnc->nBitsExceeded, 0, 10000 ); + + /* Update flag indicating if bandwidth switching is allowed */ + speech_act_thr_for_switch_Q8 = SKP_SMLAWB( SILK_FIX_CONST( SPEECH_ACTIVITY_DTX_THRES, 8 ), + SILK_FIX_CONST( ( 1 - SPEECH_ACTIVITY_DTX_THRES ) / MAX_BANDWIDTH_SWITCH_DELAY_MS, 16 + 8 ), psEnc->timeSinceSwitchAllowed_ms ); + if( psEnc->state_Fxx[ 0 ].sCmn.speech_activity_Q8 < speech_act_thr_for_switch_Q8 ) { + psEnc->allowBandwidthSwitch = 1; + psEnc->timeSinceSwitchAllowed_ms = 0; + } else { + psEnc->allowBandwidthSwitch = 0; + psEnc->timeSinceSwitchAllowed_ms += encControl->payloadSize_ms; + } + } + + if( nSamplesIn == 0 ) { + break; + } + } else { + break; + } + } + + encControl->allowBandwidthSwitch = psEnc->allowBandwidthSwitch; + encControl->inWBmodeWithoutVariableLP = psEnc->state_Fxx[ 0 ].sCmn.fs_kHz == 16 && psEnc->state_Fxx[ 0 ].sCmn.sLP.mode == 0; + encControl->internalSampleRate = SKP_SMULBB( psEnc->state_Fxx[ 0 ].sCmn.fs_kHz, 1000 ); + encControl->stereoWidth_Q14 = psEnc->sStereo.width_prev_Q14; + if( prefillFlag ) { + encControl->payloadSize_ms = tmp_payloadSize_ms; + encControl->complexity = tmp_complexity; + for( n = 0; n < encControl->nChannelsInternal; n++ ) { + psEnc->state_Fxx[ n ].sCmn.controlled_since_last_payload = 0; + psEnc->state_Fxx[ n ].sCmn.prefillFlag = 0; + } + } + + return ret; +} + diff --git a/silk/silk_encode_indices.c b/silk/silk_encode_indices.c index 2087121b1..01b0092fa 100644 --- a/silk/silk_encode_indices.c +++ b/silk/silk_encode_indices.c @@ -1,246 +1,246 @@ -/*********************************************************************** -Copyright (c) 2006-2011, Skype Limited. All rights reserved. -Redistribution and use in source and binary forms, with or without -modification, (subject to the limitations in the disclaimer below) -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 Skype Limited, nor the names of specific -contributors, may be used to endorse or promote products derived from -this software without specific prior written permission. -NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED -BY THIS LICENSE. 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. -***********************************************************************/ - -#include "silk_main.h" - -/* Encode side-information parameters to payload */ -void silk_encode_indices( - silk_encoder_state *psEncC, /* I/O Encoder state */ - ec_enc *psRangeEnc, /* I/O Compressor data structure */ - opus_int FrameIndex, /* I Frame number */ - opus_int encode_LBRR /* I Flag indicating LBRR data is being encoded */ -) -{ - opus_int i, k, condCoding, typeOffset; - opus_int encode_absolute_lagIndex, delta_lagIndex; - opus_int16 ec_ix[ MAX_LPC_ORDER ]; - opus_uint8 pred_Q8[ MAX_LPC_ORDER ]; - const SideInfoIndices *psIndices; -#if SAVE_ALL_INTERNAL_DATA - opus_int nBytes_lagIndex, nBytes_contourIndex, nBytes_LTP; - opus_int nBytes_after, nBytes_before; -#endif - - /* Use conditional coding if previous frame available */ - if( FrameIndex > 0 && ( encode_LBRR == 0 || psEncC->LBRR_flags[ FrameIndex - 1 ] == 1 ) ) { - condCoding = 1; - } else { - condCoding = 0; - } - - if( encode_LBRR ) { - psIndices = &psEncC->indices_LBRR[ FrameIndex ]; - } else { - psIndices = &psEncC->indices; - } - - /*******************************************/ - /* Encode signal type and quantizer offset */ - /*******************************************/ - typeOffset = 2 * psIndices->signalType + psIndices->quantOffsetType; - SKP_assert( typeOffset >= 0 && typeOffset < 6 ); - SKP_assert( encode_LBRR == 0 || typeOffset >= 2 ); - if( encode_LBRR || typeOffset >= 2 ) { - ec_enc_icdf( psRangeEnc, typeOffset - 2, silk_type_offset_VAD_iCDF, 8 ); - } else { - ec_enc_icdf( psRangeEnc, typeOffset, silk_type_offset_no_VAD_iCDF, 8 ); - } - - /****************/ - /* Encode gains */ - /****************/ -#ifdef SAVE_ALL_INTERNAL_DATA - nBytes_before = SKP_RSHIFT( ec_tell( psRangeEnc ) + 7, 3 ); -#endif - /* first subframe */ - if( condCoding ) { - /* conditional coding */ - SKP_assert( psIndices->GainsIndices[ 0 ] >= 0 && psIndices->GainsIndices[ 0 ] < MAX_DELTA_GAIN_QUANT - MIN_DELTA_GAIN_QUANT + 1 ); - ec_enc_icdf( psRangeEnc, psIndices->GainsIndices[ 0 ], silk_delta_gain_iCDF, 8 ); - } else { - /* independent coding, in two stages: MSB bits followed by 3 LSBs */ - SKP_assert( psIndices->GainsIndices[ 0 ] >= 0 && psIndices->GainsIndices[ 0 ] < N_LEVELS_QGAIN ); - ec_enc_icdf( psRangeEnc, SKP_RSHIFT( psIndices->GainsIndices[ 0 ], 3 ), silk_gain_iCDF[ psIndices->signalType ], 8 ); - ec_enc_icdf( psRangeEnc, psIndices->GainsIndices[ 0 ] & 7, silk_uniform8_iCDF, 8 ); - } - - /* remaining subframes */ - for( i = 1; i < psEncC->nb_subfr; i++ ) { - SKP_assert( psIndices->GainsIndices[ i ] >= 0 && psIndices->GainsIndices[ i ] < MAX_DELTA_GAIN_QUANT - MIN_DELTA_GAIN_QUANT + 1 ); - ec_enc_icdf( psRangeEnc, psIndices->GainsIndices[ i ], silk_delta_gain_iCDF, 8 ); - } - -#ifdef SAVE_ALL_INTERNAL_DATA - nBytes_after = SKP_RSHIFT( ec_tell( psRangeEnc ) + 7, 3 ); - nBytes_after -= nBytes_before; // bytes just added - DEBUG_STORE_DATA( nBytes_gains.dat, &nBytes_after, sizeof( opus_int ) ); -#endif - - /****************/ - /* Encode NLSFs */ - /****************/ -#ifdef SAVE_ALL_INTERNAL_DATA - nBytes_before = SKP_RSHIFT( ec_tell( psRangeEnc ) + 7, 3 ); -#endif - ec_enc_icdf( psRangeEnc, psIndices->NLSFIndices[ 0 ], &psEncC->psNLSF_CB->CB1_iCDF[ ( psIndices->signalType >> 1 ) * psEncC->psNLSF_CB->nVectors ], 8 ); - silk_NLSF_unpack( ec_ix, pred_Q8, psEncC->psNLSF_CB, psIndices->NLSFIndices[ 0 ] ); - SKP_assert( psEncC->psNLSF_CB->order == psEncC->predictLPCOrder ); - for( i = 0; i < psEncC->psNLSF_CB->order; i++ ) { - if( psIndices->NLSFIndices[ i+1 ] >= NLSF_QUANT_MAX_AMPLITUDE ) { - ec_enc_icdf( psRangeEnc, 2 * NLSF_QUANT_MAX_AMPLITUDE, &psEncC->psNLSF_CB->ec_iCDF[ ec_ix[ i ] ], 8 ); - ec_enc_icdf( psRangeEnc, psIndices->NLSFIndices[ i+1 ] - NLSF_QUANT_MAX_AMPLITUDE, silk_NLSF_EXT_iCDF, 8 ); - } else if( psIndices->NLSFIndices[ i+1 ] <= -NLSF_QUANT_MAX_AMPLITUDE ) { - ec_enc_icdf( psRangeEnc, 0, &psEncC->psNLSF_CB->ec_iCDF[ ec_ix[ i ] ], 8 ); - ec_enc_icdf( psRangeEnc, -psIndices->NLSFIndices[ i+1 ] - NLSF_QUANT_MAX_AMPLITUDE, silk_NLSF_EXT_iCDF, 8 ); - } else { - ec_enc_icdf( psRangeEnc, psIndices->NLSFIndices[ i+1 ] + NLSF_QUANT_MAX_AMPLITUDE, &psEncC->psNLSF_CB->ec_iCDF[ ec_ix[ i ] ], 8 ); - } - } - - /* Encode NLSF interpolation factor */ - if( psEncC->nb_subfr == MAX_NB_SUBFR ) { - SKP_assert( psEncC->useInterpolatedNLSFs == 1 || psIndices->NLSFInterpCoef_Q2 == ( 1 << 2 ) ); - SKP_assert( psIndices->NLSFInterpCoef_Q2 >= 0 && psIndices->NLSFInterpCoef_Q2 < 5 ); - ec_enc_icdf( psRangeEnc, psIndices->NLSFInterpCoef_Q2, silk_NLSF_interpolation_factor_iCDF, 8 ); - } - -#ifdef SAVE_ALL_INTERNAL_DATA - DEBUG_STORE_DATA( lsf_interpol.dat, &psIndices->NLSFInterpCoef_Q2, sizeof(int) ); - nBytes_after = SKP_RSHIFT( ec_tell( psRangeEnc ) + 7, 3 ); - nBytes_after -= nBytes_before; // bytes just added - DEBUG_STORE_DATA( nBytes_LSF.dat, &nBytes_after, sizeof( opus_int ) ); -#endif - - if( psIndices->signalType == TYPE_VOICED ) - { - /*********************/ - /* Encode pitch lags */ - /*********************/ -#ifdef SAVE_ALL_INTERNAL_DATA - nBytes_before = SKP_RSHIFT( ec_tell( psRangeEnc ) + 7, 3 ); -#endif - /* lag index */ - encode_absolute_lagIndex = 1; - if( condCoding && psEncC->ec_prevSignalType == TYPE_VOICED ) { - /* Delta Encoding */ - delta_lagIndex = psIndices->lagIndex - psEncC->ec_prevLagIndex; - if( delta_lagIndex < -8 || delta_lagIndex > 11 ) { - delta_lagIndex = 0; - } else { - delta_lagIndex = delta_lagIndex + 9; - encode_absolute_lagIndex = 0; /* Only use delta */ - } - SKP_assert( delta_lagIndex >= 0 && delta_lagIndex < 21 ); - ec_enc_icdf( psRangeEnc, delta_lagIndex, silk_pitch_delta_iCDF, 8 ); - } - if( encode_absolute_lagIndex ) { - /* Absolute encoding */ - opus_int32 pitch_high_bits, pitch_low_bits; - pitch_high_bits = SKP_DIV32_16( psIndices->lagIndex, SKP_RSHIFT( psEncC->fs_kHz, 1 ) ); - pitch_low_bits = psIndices->lagIndex - SKP_SMULBB( pitch_high_bits, SKP_RSHIFT( psEncC->fs_kHz, 1 ) ); - SKP_assert( pitch_low_bits < psEncC->fs_kHz / 2 ); - SKP_assert( pitch_high_bits < 32 ); - ec_enc_icdf( psRangeEnc, pitch_high_bits, silk_pitch_lag_iCDF, 8 ); - ec_enc_icdf( psRangeEnc, pitch_low_bits, psEncC->pitch_lag_low_bits_iCDF, 8 ); - } - psEncC->ec_prevLagIndex = psIndices->lagIndex; - -#ifdef SAVE_ALL_INTERNAL_DATA - nBytes_after = SKP_RSHIFT( ec_tell( psRangeEnc ) + 7, 3 ); - nBytes_lagIndex = nBytes_after - nBytes_before; // bytes just added -#endif - -#ifdef SAVE_ALL_INTERNAL_DATA - nBytes_before = SKP_RSHIFT( ec_tell( psRangeEnc ) + 7, 3 ); -#endif - /* Countour index */ - SKP_assert( psIndices->contourIndex >= 0 ); - SKP_assert( ( psIndices->contourIndex < 34 && psEncC->fs_kHz > 8 && psEncC->nb_subfr == 4 ) || - ( psIndices->contourIndex < 11 && psEncC->fs_kHz == 8 && psEncC->nb_subfr == 4 ) || - ( psIndices->contourIndex < 12 && psEncC->fs_kHz > 8 && psEncC->nb_subfr == 2 ) || - ( psIndices->contourIndex < 3 && psEncC->fs_kHz == 8 && psEncC->nb_subfr == 2 ) ); - ec_enc_icdf( psRangeEnc, psIndices->contourIndex, psEncC->pitch_contour_iCDF, 8 ); -#ifdef SAVE_ALL_INTERNAL_DATA - nBytes_after = SKP_RSHIFT( ec_tell( psRangeEnc ) + 7, 3 ); - nBytes_contourIndex = nBytes_after - nBytes_before; // bytes just added -#endif - - /********************/ - /* Encode LTP gains */ - /********************/ -#ifdef SAVE_ALL_INTERNAL_DATA - nBytes_before = SKP_RSHIFT( ec_tell( psRangeEnc ) + 7, 3 ); -#endif - - /* PERIndex value */ - SKP_assert( psIndices->PERIndex >= 0 && psIndices->PERIndex < 3 ); - ec_enc_icdf( psRangeEnc, psIndices->PERIndex, silk_LTP_per_index_iCDF, 8 ); - - /* Codebook Indices */ - for( k = 0; k < psEncC->nb_subfr; k++ ) { - SKP_assert( psIndices->LTPIndex[ k ] >= 0 && psIndices->LTPIndex[ k ] < ( 8 << psIndices->PERIndex ) ); - ec_enc_icdf( psRangeEnc, psIndices->LTPIndex[ k ], silk_LTP_gain_iCDF_ptrs[ psIndices->PERIndex ], 8 ); - } - - /**********************/ - /* Encode LTP scaling */ - /**********************/ - if( !condCoding ) { - SKP_assert( psIndices->LTP_scaleIndex >= 0 && psIndices->LTP_scaleIndex < 3 ); - ec_enc_icdf( psRangeEnc, psIndices->LTP_scaleIndex, silk_LTPscale_iCDF, 8 ); - } - SKP_assert( !condCoding || psIndices->LTP_scaleIndex == 0 ); - -#ifdef SAVE_ALL_INTERNAL_DATA - nBytes_after = SKP_RSHIFT( ec_tell( psRangeEnc ) + 7, 3 ); - nBytes_LTP = nBytes_after - nBytes_before; // bytes just added -#endif - } -#ifdef SAVE_ALL_INTERNAL_DATA - else { - // Unvoiced speech - nBytes_lagIndex = 0; - nBytes_contourIndex = 0; - nBytes_LTP = 0; - } - DEBUG_STORE_DATA( nBytes_lagIndex.dat, &nBytes_lagIndex, sizeof( opus_int ) ); - DEBUG_STORE_DATA( nBytes_contourIndex.dat, &nBytes_contourIndex, sizeof( opus_int ) ); - DEBUG_STORE_DATA( nBytes_LTP.dat, &nBytes_LTP, sizeof( opus_int ) ); -#endif - - psEncC->ec_prevSignalType = psIndices->signalType; - -#ifdef SAVE_ALL_INTERNAL_DATA - nBytes_before = SKP_RSHIFT( ec_tell( psRangeEnc ) + 7, 3 ); -#endif - - /***************/ - /* Encode seed */ - /***************/ - SKP_assert( psIndices->Seed >= 0 && psIndices->Seed < 4 ); - ec_enc_icdf( psRangeEnc, psIndices->Seed, silk_uniform4_iCDF, 8 ); -} +/*********************************************************************** +Copyright (c) 2006-2011, Skype Limited. All rights reserved. +Redistribution and use in source and binary forms, with or without +modification, (subject to the limitations in the disclaimer below) +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 Skype Limited, nor the names of specific +contributors, may be used to endorse or promote products derived from +this software without specific prior written permission. +NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED +BY THIS LICENSE. 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. +***********************************************************************/ + +#include "silk_main.h" + +/* Encode side-information parameters to payload */ +void silk_encode_indices( + silk_encoder_state *psEncC, /* I/O Encoder state */ + ec_enc *psRangeEnc, /* I/O Compressor data structure */ + opus_int FrameIndex, /* I Frame number */ + opus_int encode_LBRR /* I Flag indicating LBRR data is being encoded */ +) +{ + opus_int i, k, condCoding, typeOffset; + opus_int encode_absolute_lagIndex, delta_lagIndex; + opus_int16 ec_ix[ MAX_LPC_ORDER ]; + opus_uint8 pred_Q8[ MAX_LPC_ORDER ]; + const SideInfoIndices *psIndices; +#if SAVE_ALL_INTERNAL_DATA + opus_int nBytes_lagIndex, nBytes_contourIndex, nBytes_LTP; + opus_int nBytes_after, nBytes_before; +#endif + + /* Use conditional coding if previous frame available */ + if( FrameIndex > 0 && ( encode_LBRR == 0 || psEncC->LBRR_flags[ FrameIndex - 1 ] == 1 ) ) { + condCoding = 1; + } else { + condCoding = 0; + } + + if( encode_LBRR ) { + psIndices = &psEncC->indices_LBRR[ FrameIndex ]; + } else { + psIndices = &psEncC->indices; + } + + /*******************************************/ + /* Encode signal type and quantizer offset */ + /*******************************************/ + typeOffset = 2 * psIndices->signalType + psIndices->quantOffsetType; + SKP_assert( typeOffset >= 0 && typeOffset < 6 ); + SKP_assert( encode_LBRR == 0 || typeOffset >= 2 ); + if( encode_LBRR || typeOffset >= 2 ) { + ec_enc_icdf( psRangeEnc, typeOffset - 2, silk_type_offset_VAD_iCDF, 8 ); + } else { + ec_enc_icdf( psRangeEnc, typeOffset, silk_type_offset_no_VAD_iCDF, 8 ); + } + + /****************/ + /* Encode gains */ + /****************/ +#ifdef SAVE_ALL_INTERNAL_DATA + nBytes_before = SKP_RSHIFT( ec_tell( psRangeEnc ) + 7, 3 ); +#endif + /* first subframe */ + if( condCoding ) { + /* conditional coding */ + SKP_assert( psIndices->GainsIndices[ 0 ] >= 0 && psIndices->GainsIndices[ 0 ] < MAX_DELTA_GAIN_QUANT - MIN_DELTA_GAIN_QUANT + 1 ); + ec_enc_icdf( psRangeEnc, psIndices->GainsIndices[ 0 ], silk_delta_gain_iCDF, 8 ); + } else { + /* independent coding, in two stages: MSB bits followed by 3 LSBs */ + SKP_assert( psIndices->GainsIndices[ 0 ] >= 0 && psIndices->GainsIndices[ 0 ] < N_LEVELS_QGAIN ); + ec_enc_icdf( psRangeEnc, SKP_RSHIFT( psIndices->GainsIndices[ 0 ], 3 ), silk_gain_iCDF[ psIndices->signalType ], 8 ); + ec_enc_icdf( psRangeEnc, psIndices->GainsIndices[ 0 ] & 7, silk_uniform8_iCDF, 8 ); + } + + /* remaining subframes */ + for( i = 1; i < psEncC->nb_subfr; i++ ) { + SKP_assert( psIndices->GainsIndices[ i ] >= 0 && psIndices->GainsIndices[ i ] < MAX_DELTA_GAIN_QUANT - MIN_DELTA_GAIN_QUANT + 1 ); + ec_enc_icdf( psRangeEnc, psIndices->GainsIndices[ i ], silk_delta_gain_iCDF, 8 ); + } + +#ifdef SAVE_ALL_INTERNAL_DATA + nBytes_after = SKP_RSHIFT( ec_tell( psRangeEnc ) + 7, 3 ); + nBytes_after -= nBytes_before; // bytes just added + DEBUG_STORE_DATA( nBytes_gains.dat, &nBytes_after, sizeof( opus_int ) ); +#endif + + /****************/ + /* Encode NLSFs */ + /****************/ +#ifdef SAVE_ALL_INTERNAL_DATA + nBytes_before = SKP_RSHIFT( ec_tell( psRangeEnc ) + 7, 3 ); +#endif + ec_enc_icdf( psRangeEnc, psIndices->NLSFIndices[ 0 ], &psEncC->psNLSF_CB->CB1_iCDF[ ( psIndices->signalType >> 1 ) * psEncC->psNLSF_CB->nVectors ], 8 ); + silk_NLSF_unpack( ec_ix, pred_Q8, psEncC->psNLSF_CB, psIndices->NLSFIndices[ 0 ] ); + SKP_assert( psEncC->psNLSF_CB->order == psEncC->predictLPCOrder ); + for( i = 0; i < psEncC->psNLSF_CB->order; i++ ) { + if( psIndices->NLSFIndices[ i+1 ] >= NLSF_QUANT_MAX_AMPLITUDE ) { + ec_enc_icdf( psRangeEnc, 2 * NLSF_QUANT_MAX_AMPLITUDE, &psEncC->psNLSF_CB->ec_iCDF[ ec_ix[ i ] ], 8 ); + ec_enc_icdf( psRangeEnc, psIndices->NLSFIndices[ i+1 ] - NLSF_QUANT_MAX_AMPLITUDE, silk_NLSF_EXT_iCDF, 8 ); + } else if( psIndices->NLSFIndices[ i+1 ] <= -NLSF_QUANT_MAX_AMPLITUDE ) { + ec_enc_icdf( psRangeEnc, 0, &psEncC->psNLSF_CB->ec_iCDF[ ec_ix[ i ] ], 8 ); + ec_enc_icdf( psRangeEnc, -psIndices->NLSFIndices[ i+1 ] - NLSF_QUANT_MAX_AMPLITUDE, silk_NLSF_EXT_iCDF, 8 ); + } else { + ec_enc_icdf( psRangeEnc, psIndices->NLSFIndices[ i+1 ] + NLSF_QUANT_MAX_AMPLITUDE, &psEncC->psNLSF_CB->ec_iCDF[ ec_ix[ i ] ], 8 ); + } + } + + /* Encode NLSF interpolation factor */ + if( psEncC->nb_subfr == MAX_NB_SUBFR ) { + SKP_assert( psEncC->useInterpolatedNLSFs == 1 || psIndices->NLSFInterpCoef_Q2 == ( 1 << 2 ) ); + SKP_assert( psIndices->NLSFInterpCoef_Q2 >= 0 && psIndices->NLSFInterpCoef_Q2 < 5 ); + ec_enc_icdf( psRangeEnc, psIndices->NLSFInterpCoef_Q2, silk_NLSF_interpolation_factor_iCDF, 8 ); + } + +#ifdef SAVE_ALL_INTERNAL_DATA + DEBUG_STORE_DATA( lsf_interpol.dat, &psIndices->NLSFInterpCoef_Q2, sizeof(int) ); + nBytes_after = SKP_RSHIFT( ec_tell( psRangeEnc ) + 7, 3 ); + nBytes_after -= nBytes_before; // bytes just added + DEBUG_STORE_DATA( nBytes_LSF.dat, &nBytes_after, sizeof( opus_int ) ); +#endif + + if( psIndices->signalType == TYPE_VOICED ) + { + /*********************/ + /* Encode pitch lags */ + /*********************/ +#ifdef SAVE_ALL_INTERNAL_DATA + nBytes_before = SKP_RSHIFT( ec_tell( psRangeEnc ) + 7, 3 ); +#endif + /* lag index */ + encode_absolute_lagIndex = 1; + if( condCoding && psEncC->ec_prevSignalType == TYPE_VOICED ) { + /* Delta Encoding */ + delta_lagIndex = psIndices->lagIndex - psEncC->ec_prevLagIndex; + if( delta_lagIndex < -8 || delta_lagIndex > 11 ) { + delta_lagIndex = 0; + } else { + delta_lagIndex = delta_lagIndex + 9; + encode_absolute_lagIndex = 0; /* Only use delta */ + } + SKP_assert( delta_lagIndex >= 0 && delta_lagIndex < 21 ); + ec_enc_icdf( psRangeEnc, delta_lagIndex, silk_pitch_delta_iCDF, 8 ); + } + if( encode_absolute_lagIndex ) { + /* Absolute encoding */ + opus_int32 pitch_high_bits, pitch_low_bits; + pitch_high_bits = SKP_DIV32_16( psIndices->lagIndex, SKP_RSHIFT( psEncC->fs_kHz, 1 ) ); + pitch_low_bits = psIndices->lagIndex - SKP_SMULBB( pitch_high_bits, SKP_RSHIFT( psEncC->fs_kHz, 1 ) ); + SKP_assert( pitch_low_bits < psEncC->fs_kHz / 2 ); + SKP_assert( pitch_high_bits < 32 ); + ec_enc_icdf( psRangeEnc, pitch_high_bits, silk_pitch_lag_iCDF, 8 ); + ec_enc_icdf( psRangeEnc, pitch_low_bits, psEncC->pitch_lag_low_bits_iCDF, 8 ); + } + psEncC->ec_prevLagIndex = psIndices->lagIndex; + +#ifdef SAVE_ALL_INTERNAL_DATA + nBytes_after = SKP_RSHIFT( ec_tell( psRangeEnc ) + 7, 3 ); + nBytes_lagIndex = nBytes_after - nBytes_before; // bytes just added +#endif + +#ifdef SAVE_ALL_INTERNAL_DATA + nBytes_before = SKP_RSHIFT( ec_tell( psRangeEnc ) + 7, 3 ); +#endif + /* Countour index */ + SKP_assert( psIndices->contourIndex >= 0 ); + SKP_assert( ( psIndices->contourIndex < 34 && psEncC->fs_kHz > 8 && psEncC->nb_subfr == 4 ) || + ( psIndices->contourIndex < 11 && psEncC->fs_kHz == 8 && psEncC->nb_subfr == 4 ) || + ( psIndices->contourIndex < 12 && psEncC->fs_kHz > 8 && psEncC->nb_subfr == 2 ) || + ( psIndices->contourIndex < 3 && psEncC->fs_kHz == 8 && psEncC->nb_subfr == 2 ) ); + ec_enc_icdf( psRangeEnc, psIndices->contourIndex, psEncC->pitch_contour_iCDF, 8 ); +#ifdef SAVE_ALL_INTERNAL_DATA + nBytes_after = SKP_RSHIFT( ec_tell( psRangeEnc ) + 7, 3 ); + nBytes_contourIndex = nBytes_after - nBytes_before; // bytes just added +#endif + + /********************/ + /* Encode LTP gains */ + /********************/ +#ifdef SAVE_ALL_INTERNAL_DATA + nBytes_before = SKP_RSHIFT( ec_tell( psRangeEnc ) + 7, 3 ); +#endif + + /* PERIndex value */ + SKP_assert( psIndices->PERIndex >= 0 && psIndices->PERIndex < 3 ); + ec_enc_icdf( psRangeEnc, psIndices->PERIndex, silk_LTP_per_index_iCDF, 8 ); + + /* Codebook Indices */ + for( k = 0; k < psEncC->nb_subfr; k++ ) { + SKP_assert( psIndices->LTPIndex[ k ] >= 0 && psIndices->LTPIndex[ k ] < ( 8 << psIndices->PERIndex ) ); + ec_enc_icdf( psRangeEnc, psIndices->LTPIndex[ k ], silk_LTP_gain_iCDF_ptrs[ psIndices->PERIndex ], 8 ); + } + + /**********************/ + /* Encode LTP scaling */ + /**********************/ + if( !condCoding ) { + SKP_assert( psIndices->LTP_scaleIndex >= 0 && psIndices->LTP_scaleIndex < 3 ); + ec_enc_icdf( psRangeEnc, psIndices->LTP_scaleIndex, silk_LTPscale_iCDF, 8 ); + } + SKP_assert( !condCoding || psIndices->LTP_scaleIndex == 0 ); + +#ifdef SAVE_ALL_INTERNAL_DATA + nBytes_after = SKP_RSHIFT( ec_tell( psRangeEnc ) + 7, 3 ); + nBytes_LTP = nBytes_after - nBytes_before; // bytes just added +#endif + } +#ifdef SAVE_ALL_INTERNAL_DATA + else { + // Unvoiced speech + nBytes_lagIndex = 0; + nBytes_contourIndex = 0; + nBytes_LTP = 0; + } + DEBUG_STORE_DATA( nBytes_lagIndex.dat, &nBytes_lagIndex, sizeof( opus_int ) ); + DEBUG_STORE_DATA( nBytes_contourIndex.dat, &nBytes_contourIndex, sizeof( opus_int ) ); + DEBUG_STORE_DATA( nBytes_LTP.dat, &nBytes_LTP, sizeof( opus_int ) ); +#endif + + psEncC->ec_prevSignalType = psIndices->signalType; + +#ifdef SAVE_ALL_INTERNAL_DATA + nBytes_before = SKP_RSHIFT( ec_tell( psRangeEnc ) + 7, 3 ); +#endif + + /***************/ + /* Encode seed */ + /***************/ + SKP_assert( psIndices->Seed >= 0 && psIndices->Seed < 4 ); + ec_enc_icdf( psRangeEnc, psIndices->Seed, silk_uniform4_iCDF, 8 ); +} diff --git a/silk/silk_encode_pulses.c b/silk/silk_encode_pulses.c index 8410be9d1..6143cabc8 100644 --- a/silk/silk_encode_pulses.c +++ b/silk/silk_encode_pulses.c @@ -1,195 +1,195 @@ -/*********************************************************************** -Copyright (c) 2006-2011, Skype Limited. All rights reserved. -Redistribution and use in source and binary forms, with or without -modification, (subject to the limitations in the disclaimer below) -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 Skype Limited, nor the names of specific -contributors, may be used to endorse or promote products derived from -this software without specific prior written permission. -NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED -BY THIS LICENSE. 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. -***********************************************************************/ - -#include "silk_main.h" - -/*********************************************/ -/* Encode quantization indices of excitation */ -/*********************************************/ - -SKP_INLINE opus_int combine_and_check( /* return ok */ - opus_int *pulses_comb, /* O */ - const opus_int *pulses_in, /* I */ - opus_int max_pulses, /* I max value for sum of pulses */ - opus_int len /* I number of output values */ -) -{ - opus_int k, sum; - - for( k = 0; k < len; k++ ) { - sum = pulses_in[ 2 * k ] + pulses_in[ 2 * k + 1 ]; - if( sum > max_pulses ) { - return 1; - } - pulses_comb[ k ] = sum; - } - - return 0; -} - -/* Encode quantization indices of excitation */ -void silk_encode_pulses( - ec_enc *psRangeEnc, /* I/O compressor data structure */ - const opus_int signalType, /* I Sigtype */ - const opus_int quantOffsetType, /* I quantOffsetType */ - opus_int8 pulses[], /* I quantization indices */ - const opus_int frame_length /* I Frame length */ -) -{ - opus_int i, k, j, iter, bit, nLS, scale_down, RateLevelIndex = 0; - opus_int32 abs_q, minSumBits_Q5, sumBits_Q5; - opus_int abs_pulses[ MAX_FRAME_LENGTH ]; - opus_int sum_pulses[ MAX_NB_SHELL_BLOCKS ]; - opus_int nRshifts[ MAX_NB_SHELL_BLOCKS ]; - opus_int pulses_comb[ 8 ]; - opus_int *abs_pulses_ptr; - const opus_int8 *pulses_ptr; - const opus_uint8 *cdf_ptr; - const opus_uint8 *nBits_ptr; - - SKP_memset( pulses_comb, 0, 8 * sizeof( opus_int ) ); // Fixing Valgrind reported problem - - /****************************/ - /* Prepare for shell coding */ - /****************************/ - /* Calculate number of shell blocks */ - SKP_assert( 1 << LOG2_SHELL_CODEC_FRAME_LENGTH == SHELL_CODEC_FRAME_LENGTH ); - iter = SKP_RSHIFT( frame_length, LOG2_SHELL_CODEC_FRAME_LENGTH ); - if( iter * SHELL_CODEC_FRAME_LENGTH < frame_length ){ - SKP_assert( frame_length == 12 * 10 ); /* Make sure only happens for 10 ms @ 12 kHz */ - iter++; - SKP_memset( &pulses[ frame_length ], 0, SHELL_CODEC_FRAME_LENGTH * sizeof(opus_int8)); - } - - /* Take the absolute value of the pulses */ - for( i = 0; i < iter * SHELL_CODEC_FRAME_LENGTH; i+=4 ) { - abs_pulses[i+0] = ( opus_int )SKP_abs( pulses[ i + 0 ] ); - abs_pulses[i+1] = ( opus_int )SKP_abs( pulses[ i + 1 ] ); - abs_pulses[i+2] = ( opus_int )SKP_abs( pulses[ i + 2 ] ); - abs_pulses[i+3] = ( opus_int )SKP_abs( pulses[ i + 3 ] ); - } - - /* Calc sum pulses per shell code frame */ - abs_pulses_ptr = abs_pulses; - for( i = 0; i < iter; i++ ) { - nRshifts[ i ] = 0; - - while( 1 ) { - /* 1+1 -> 2 */ - scale_down = combine_and_check( pulses_comb, abs_pulses_ptr, silk_max_pulses_table[ 0 ], 8 ); - /* 2+2 -> 4 */ - scale_down += combine_and_check( pulses_comb, pulses_comb, silk_max_pulses_table[ 1 ], 4 ); - /* 4+4 -> 8 */ - scale_down += combine_and_check( pulses_comb, pulses_comb, silk_max_pulses_table[ 2 ], 2 ); - /* 8+8 -> 16 */ - scale_down += combine_and_check( &sum_pulses[ i ], pulses_comb, silk_max_pulses_table[ 3 ], 1 ); - - if( scale_down ) { - /* We need to downscale the quantization signal */ - nRshifts[ i ]++; - for( k = 0; k < SHELL_CODEC_FRAME_LENGTH; k++ ) { - abs_pulses_ptr[ k ] = SKP_RSHIFT( abs_pulses_ptr[ k ], 1 ); - } - } else { - /* Jump out of while(1) loop and go to next shell coding frame */ - break; - } - } - abs_pulses_ptr += SHELL_CODEC_FRAME_LENGTH; - } - - /**************/ - /* Rate level */ - /**************/ - /* find rate level that leads to fewest bits for coding of pulses per block info */ - minSumBits_Q5 = SKP_int32_MAX; - for( k = 0; k < N_RATE_LEVELS - 1; k++ ) { - nBits_ptr = silk_pulses_per_block_BITS_Q5[ k ]; - sumBits_Q5 = silk_rate_levels_BITS_Q5[ signalType >> 1 ][ k ]; - for( i = 0; i < iter; i++ ) { - if( nRshifts[ i ] > 0 ) { - sumBits_Q5 += nBits_ptr[ MAX_PULSES + 1 ]; - } else { - sumBits_Q5 += nBits_ptr[ sum_pulses[ i ] ]; - } - } - if( sumBits_Q5 < minSumBits_Q5 ) { - minSumBits_Q5 = sumBits_Q5; - RateLevelIndex = k; - } - } - ec_enc_icdf( psRangeEnc, RateLevelIndex, silk_rate_levels_iCDF[ signalType >> 1 ], 8 ); - - /***************************************************/ - /* Sum-Weighted-Pulses Encoding */ - /***************************************************/ - cdf_ptr = silk_pulses_per_block_iCDF[ RateLevelIndex ]; - for( i = 0; i < iter; i++ ) { - if( nRshifts[ i ] == 0 ) { - ec_enc_icdf( psRangeEnc, sum_pulses[ i ], cdf_ptr, 8 ); - } else { - ec_enc_icdf( psRangeEnc, MAX_PULSES + 1, cdf_ptr, 8 ); - for( k = 0; k < nRshifts[ i ] - 1; k++ ) { - ec_enc_icdf( psRangeEnc, MAX_PULSES + 1, silk_pulses_per_block_iCDF[ N_RATE_LEVELS - 1 ], 8 ); - } - ec_enc_icdf( psRangeEnc, sum_pulses[ i ], silk_pulses_per_block_iCDF[ N_RATE_LEVELS - 1 ], 8 ); - } - } - - /******************/ - /* Shell Encoding */ - /******************/ - for( i = 0; i < iter; i++ ) { - if( sum_pulses[ i ] > 0 ) { - silk_shell_encoder( psRangeEnc, &abs_pulses[ i * SHELL_CODEC_FRAME_LENGTH ] ); - } - } - - /****************/ - /* LSB Encoding */ - /****************/ - for( i = 0; i < iter; i++ ) { - if( nRshifts[ i ] > 0 ) { - pulses_ptr = &pulses[ i * SHELL_CODEC_FRAME_LENGTH ]; - nLS = nRshifts[ i ] - 1; - for( k = 0; k < SHELL_CODEC_FRAME_LENGTH; k++ ) { - abs_q = (opus_int8)SKP_abs( pulses_ptr[ k ] ); - for( j = nLS; j > 0; j-- ) { - bit = SKP_RSHIFT( abs_q, j ) & 1; - ec_enc_icdf( psRangeEnc, bit, silk_lsb_iCDF, 8 ); - } - bit = abs_q & 1; - ec_enc_icdf( psRangeEnc, bit, silk_lsb_iCDF, 8 ); - } - } - } - - /****************/ - /* Encode signs */ - /****************/ - silk_encode_signs( psRangeEnc, pulses, frame_length, signalType, quantOffsetType, sum_pulses ); -} +/*********************************************************************** +Copyright (c) 2006-2011, Skype Limited. All rights reserved. +Redistribution and use in source and binary forms, with or without +modification, (subject to the limitations in the disclaimer below) +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 Skype Limited, nor the names of specific +contributors, may be used to endorse or promote products derived from +this software without specific prior written permission. +NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED +BY THIS LICENSE. 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. +***********************************************************************/ + +#include "silk_main.h" + +/*********************************************/ +/* Encode quantization indices of excitation */ +/*********************************************/ + +SKP_INLINE opus_int combine_and_check( /* return ok */ + opus_int *pulses_comb, /* O */ + const opus_int *pulses_in, /* I */ + opus_int max_pulses, /* I max value for sum of pulses */ + opus_int len /* I number of output values */ +) +{ + opus_int k, sum; + + for( k = 0; k < len; k++ ) { + sum = pulses_in[ 2 * k ] + pulses_in[ 2 * k + 1 ]; + if( sum > max_pulses ) { + return 1; + } + pulses_comb[ k ] = sum; + } + + return 0; +} + +/* Encode quantization indices of excitation */ +void silk_encode_pulses( + ec_enc *psRangeEnc, /* I/O compressor data structure */ + const opus_int signalType, /* I Sigtype */ + const opus_int quantOffsetType, /* I quantOffsetType */ + opus_int8 pulses[], /* I quantization indices */ + const opus_int frame_length /* I Frame length */ +) +{ + opus_int i, k, j, iter, bit, nLS, scale_down, RateLevelIndex = 0; + opus_int32 abs_q, minSumBits_Q5, sumBits_Q5; + opus_int abs_pulses[ MAX_FRAME_LENGTH ]; + opus_int sum_pulses[ MAX_NB_SHELL_BLOCKS ]; + opus_int nRshifts[ MAX_NB_SHELL_BLOCKS ]; + opus_int pulses_comb[ 8 ]; + opus_int *abs_pulses_ptr; + const opus_int8 *pulses_ptr; + const opus_uint8 *cdf_ptr; + const opus_uint8 *nBits_ptr; + + SKP_memset( pulses_comb, 0, 8 * sizeof( opus_int ) ); // Fixing Valgrind reported problem + + /****************************/ + /* Prepare for shell coding */ + /****************************/ + /* Calculate number of shell blocks */ + SKP_assert( 1 << LOG2_SHELL_CODEC_FRAME_LENGTH == SHELL_CODEC_FRAME_LENGTH ); + iter = SKP_RSHIFT( frame_length, LOG2_SHELL_CODEC_FRAME_LENGTH ); + if( iter * SHELL_CODEC_FRAME_LENGTH < frame_length ){ + SKP_assert( frame_length == 12 * 10 ); /* Make sure only happens for 10 ms @ 12 kHz */ + iter++; + SKP_memset( &pulses[ frame_length ], 0, SHELL_CODEC_FRAME_LENGTH * sizeof(opus_int8)); + } + + /* Take the absolute value of the pulses */ + for( i = 0; i < iter * SHELL_CODEC_FRAME_LENGTH; i+=4 ) { + abs_pulses[i+0] = ( opus_int )SKP_abs( pulses[ i + 0 ] ); + abs_pulses[i+1] = ( opus_int )SKP_abs( pulses[ i + 1 ] ); + abs_pulses[i+2] = ( opus_int )SKP_abs( pulses[ i + 2 ] ); + abs_pulses[i+3] = ( opus_int )SKP_abs( pulses[ i + 3 ] ); + } + + /* Calc sum pulses per shell code frame */ + abs_pulses_ptr = abs_pulses; + for( i = 0; i < iter; i++ ) { + nRshifts[ i ] = 0; + + while( 1 ) { + /* 1+1 -> 2 */ + scale_down = combine_and_check( pulses_comb, abs_pulses_ptr, silk_max_pulses_table[ 0 ], 8 ); + /* 2+2 -> 4 */ + scale_down += combine_and_check( pulses_comb, pulses_comb, silk_max_pulses_table[ 1 ], 4 ); + /* 4+4 -> 8 */ + scale_down += combine_and_check( pulses_comb, pulses_comb, silk_max_pulses_table[ 2 ], 2 ); + /* 8+8 -> 16 */ + scale_down += combine_and_check( &sum_pulses[ i ], pulses_comb, silk_max_pulses_table[ 3 ], 1 ); + + if( scale_down ) { + /* We need to downscale the quantization signal */ + nRshifts[ i ]++; + for( k = 0; k < SHELL_CODEC_FRAME_LENGTH; k++ ) { + abs_pulses_ptr[ k ] = SKP_RSHIFT( abs_pulses_ptr[ k ], 1 ); + } + } else { + /* Jump out of while(1) loop and go to next shell coding frame */ + break; + } + } + abs_pulses_ptr += SHELL_CODEC_FRAME_LENGTH; + } + + /**************/ + /* Rate level */ + /**************/ + /* find rate level that leads to fewest bits for coding of pulses per block info */ + minSumBits_Q5 = SKP_int32_MAX; + for( k = 0; k < N_RATE_LEVELS - 1; k++ ) { + nBits_ptr = silk_pulses_per_block_BITS_Q5[ k ]; + sumBits_Q5 = silk_rate_levels_BITS_Q5[ signalType >> 1 ][ k ]; + for( i = 0; i < iter; i++ ) { + if( nRshifts[ i ] > 0 ) { + sumBits_Q5 += nBits_ptr[ MAX_PULSES + 1 ]; + } else { + sumBits_Q5 += nBits_ptr[ sum_pulses[ i ] ]; + } + } + if( sumBits_Q5 < minSumBits_Q5 ) { + minSumBits_Q5 = sumBits_Q5; + RateLevelIndex = k; + } + } + ec_enc_icdf( psRangeEnc, RateLevelIndex, silk_rate_levels_iCDF[ signalType >> 1 ], 8 ); + + /***************************************************/ + /* Sum-Weighted-Pulses Encoding */ + /***************************************************/ + cdf_ptr = silk_pulses_per_block_iCDF[ RateLevelIndex ]; + for( i = 0; i < iter; i++ ) { + if( nRshifts[ i ] == 0 ) { + ec_enc_icdf( psRangeEnc, sum_pulses[ i ], cdf_ptr, 8 ); + } else { + ec_enc_icdf( psRangeEnc, MAX_PULSES + 1, cdf_ptr, 8 ); + for( k = 0; k < nRshifts[ i ] - 1; k++ ) { + ec_enc_icdf( psRangeEnc, MAX_PULSES + 1, silk_pulses_per_block_iCDF[ N_RATE_LEVELS - 1 ], 8 ); + } + ec_enc_icdf( psRangeEnc, sum_pulses[ i ], silk_pulses_per_block_iCDF[ N_RATE_LEVELS - 1 ], 8 ); + } + } + + /******************/ + /* Shell Encoding */ + /******************/ + for( i = 0; i < iter; i++ ) { + if( sum_pulses[ i ] > 0 ) { + silk_shell_encoder( psRangeEnc, &abs_pulses[ i * SHELL_CODEC_FRAME_LENGTH ] ); + } + } + + /****************/ + /* LSB Encoding */ + /****************/ + for( i = 0; i < iter; i++ ) { + if( nRshifts[ i ] > 0 ) { + pulses_ptr = &pulses[ i * SHELL_CODEC_FRAME_LENGTH ]; + nLS = nRshifts[ i ] - 1; + for( k = 0; k < SHELL_CODEC_FRAME_LENGTH; k++ ) { + abs_q = (opus_int8)SKP_abs( pulses_ptr[ k ] ); + for( j = nLS; j > 0; j-- ) { + bit = SKP_RSHIFT( abs_q, j ) & 1; + ec_enc_icdf( psRangeEnc, bit, silk_lsb_iCDF, 8 ); + } + bit = abs_q & 1; + ec_enc_icdf( psRangeEnc, bit, silk_lsb_iCDF, 8 ); + } + } + } + + /****************/ + /* Encode signs */ + /****************/ + silk_encode_signs( psRangeEnc, pulses, frame_length, signalType, quantOffsetType, sum_pulses ); +} diff --git a/silk/silk_errors.h b/silk/silk_errors.h index f27dcc7f1..b936cf5af 100644 --- a/silk/silk_errors.h +++ b/silk/silk_errors.h @@ -1,98 +1,98 @@ -/*********************************************************************** -Copyright (c) 2006-2011, Skype Limited. All rights reserved. -Redistribution and use in source and binary forms, with or without -modification, (subject to the limitations in the disclaimer below) -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 Skype Limited, nor the names of specific -contributors, may be used to endorse or promote products derived from -this software without specific prior written permission. -NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED -BY THIS LICENSE. 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. -***********************************************************************/ - -#ifndef SILK_ERRORS_H -#define SILK_ERRORS_H - -#ifdef __cplusplus -extern "C" -{ -#endif - -/******************/ -/* Error messages */ -/******************/ -#define SILK_NO_ERROR 0 - -/**************************/ -/* Encoder error messages */ -/**************************/ - -/* Input length is not a multiple of 10 ms, or length is longer than the packet length */ -#define SILK_ENC_INPUT_INVALID_NO_OF_SAMPLES -101 - -/* Sampling frequency not 8000, 12000 or 16000 Hertz */ -#define SILK_ENC_FS_NOT_SUPPORTED -102 - -/* Packet size not 10, 20, 40, or 60 ms */ -#define SILK_ENC_PACKET_SIZE_NOT_SUPPORTED -103 - -/* Allocated payload buffer too short */ -#define SILK_ENC_PAYLOAD_BUF_TOO_SHORT -104 - -/* Loss rate not between 0 and 100 percent */ -#define SILK_ENC_INVALID_LOSS_RATE -105 - -/* Complexity setting not valid, use 0...10 */ -#define SILK_ENC_INVALID_COMPLEXITY_SETTING -106 - -/* Inband FEC setting not valid, use 0 or 1 */ -#define SILK_ENC_INVALID_INBAND_FEC_SETTING -107 - -/* DTX setting not valid, use 0 or 1 */ -#define SILK_ENC_INVALID_DTX_SETTING -108 - -/* CBR setting not valid, use 0 or 1 */ -#define SILK_ENC_INVALID_CBR_SETTING -109 - -/* Internal encoder error */ -#define SILK_ENC_INTERNAL_ERROR -110 - -/* Internal encoder error */ -#define SILK_ENC_INVALID_NUMBER_OF_CHANNELS_ERROR -111 - -/**************************/ -/* Decoder error messages */ -/**************************/ - -/* Output sampling frequency lower than internal decoded sampling frequency */ -#define SILK_DEC_INVALID_SAMPLING_FREQUENCY -200 - -/* Payload size exceeded the maximum allowed 1024 bytes */ -#define SILK_DEC_PAYLOAD_TOO_LARGE -201 - -/* Payload has bit errors */ -#define SILK_DEC_PAYLOAD_ERROR -202 - -/* Payload has bit errors */ -#define SILK_DEC_INVALID_FRAME_SIZE -203 - -#ifdef __cplusplus -} -#endif - -#endif +/*********************************************************************** +Copyright (c) 2006-2011, Skype Limited. All rights reserved. +Redistribution and use in source and binary forms, with or without +modification, (subject to the limitations in the disclaimer below) +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 Skype Limited, nor the names of specific +contributors, may be used to endorse or promote products derived from +this software without specific prior written permission. +NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED +BY THIS LICENSE. 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. +***********************************************************************/ + +#ifndef SILK_ERRORS_H +#define SILK_ERRORS_H + +#ifdef __cplusplus +extern "C" +{ +#endif + +/******************/ +/* Error messages */ +/******************/ +#define SILK_NO_ERROR 0 + +/**************************/ +/* Encoder error messages */ +/**************************/ + +/* Input length is not a multiple of 10 ms, or length is longer than the packet length */ +#define SILK_ENC_INPUT_INVALID_NO_OF_SAMPLES -101 + +/* Sampling frequency not 8000, 12000 or 16000 Hertz */ +#define SILK_ENC_FS_NOT_SUPPORTED -102 + +/* Packet size not 10, 20, 40, or 60 ms */ +#define SILK_ENC_PACKET_SIZE_NOT_SUPPORTED -103 + +/* Allocated payload buffer too short */ +#define SILK_ENC_PAYLOAD_BUF_TOO_SHORT -104 + +/* Loss rate not between 0 and 100 percent */ +#define SILK_ENC_INVALID_LOSS_RATE -105 + +/* Complexity setting not valid, use 0...10 */ +#define SILK_ENC_INVALID_COMPLEXITY_SETTING -106 + +/* Inband FEC setting not valid, use 0 or 1 */ +#define SILK_ENC_INVALID_INBAND_FEC_SETTING -107 + +/* DTX setting not valid, use 0 or 1 */ +#define SILK_ENC_INVALID_DTX_SETTING -108 + +/* CBR setting not valid, use 0 or 1 */ +#define SILK_ENC_INVALID_CBR_SETTING -109 + +/* Internal encoder error */ +#define SILK_ENC_INTERNAL_ERROR -110 + +/* Internal encoder error */ +#define SILK_ENC_INVALID_NUMBER_OF_CHANNELS_ERROR -111 + +/**************************/ +/* Decoder error messages */ +/**************************/ + +/* Output sampling frequency lower than internal decoded sampling frequency */ +#define SILK_DEC_INVALID_SAMPLING_FREQUENCY -200 + +/* Payload size exceeded the maximum allowed 1024 bytes */ +#define SILK_DEC_PAYLOAD_TOO_LARGE -201 + +/* Payload has bit errors */ +#define SILK_DEC_PAYLOAD_ERROR -202 + +/* Payload has bit errors */ +#define SILK_DEC_INVALID_FRAME_SIZE -203 + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/silk/silk_gain_quant.c b/silk/silk_gain_quant.c index 9e4e4aa3d..88bc940d2 100644 --- a/silk/silk_gain_quant.c +++ b/silk/silk_gain_quant.c @@ -1,119 +1,119 @@ -/*********************************************************************** -Copyright (c) 2006-2011, Skype Limited. All rights reserved. -Redistribution and use in source and binary forms, with or without -modification, (subject to the limitations in the disclaimer below) -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 Skype Limited, nor the names of specific -contributors, may be used to endorse or promote products derived from -this software without specific prior written permission. -NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED -BY THIS LICENSE. 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. -***********************************************************************/ - -#include "silk_main.h" - -#define OFFSET ( ( MIN_QGAIN_DB * 128 ) / 6 + 16 * 128 ) -#define SCALE_Q16 ( ( 65536 * ( N_LEVELS_QGAIN - 1 ) ) / ( ( ( MAX_QGAIN_DB - MIN_QGAIN_DB ) * 128 ) / 6 ) ) -#define INV_SCALE_Q16 ( ( 65536 * ( ( ( MAX_QGAIN_DB - MIN_QGAIN_DB ) * 128 ) / 6 ) ) / ( N_LEVELS_QGAIN - 1 ) ) - -/* Gain scalar quantization with hysteresis, uniform on log scale */ -void silk_gains_quant( - opus_int8 ind[ MAX_NB_SUBFR ], /* O gain indices */ - opus_int32 gain_Q16[ MAX_NB_SUBFR ], /* I/O gains (quantized out) */ - opus_int8 *prev_ind, /* I/O last index in previous frame */ - const opus_int conditional, /* I first gain is delta coded if 1 */ - const opus_int nb_subfr /* I number of subframes */ -) -{ - opus_int k, double_step_size_threshold; - - for( k = 0; k < nb_subfr; k++ ) { - /* Add half of previous quantization error, convert to log scale, scale, floor() */ - ind[ k ] = SKP_SMULWB( SCALE_Q16, silk_lin2log( gain_Q16[ k ] ) - OFFSET ); - - /* Round towards previous quantized gain (hysteresis) */ - if( ind[ k ] < *prev_ind ) { - ind[ k ]++; - } - ind[ k ] = SKP_max_int( ind[ k ], 0 ); - - /* Compute delta indices and limit */ - if( k == 0 && conditional == 0 ) { - /* Full index */ - ind[ k ] = SKP_LIMIT_int( ind[ k ], *prev_ind + MIN_DELTA_GAIN_QUANT, N_LEVELS_QGAIN - 1 ); - *prev_ind = ind[ k ]; - } else { - /* Delta index */ - ind[ k ] = ind[ k ] - *prev_ind; - - /* Double the quantization step size for large gain increases, so that the max gain level can be reached */ - double_step_size_threshold = 2 * MAX_DELTA_GAIN_QUANT - N_LEVELS_QGAIN + *prev_ind; - if( ind[ k ] > double_step_size_threshold ) { - ind[ k ] = double_step_size_threshold + SKP_RSHIFT( ind[ k ] - double_step_size_threshold + 1, 1 ); - } - - ind[ k ] = SKP_LIMIT_int( ind[ k ], MIN_DELTA_GAIN_QUANT, MAX_DELTA_GAIN_QUANT ); - - /* Accumulate deltas */ - if( ind[ k ] > double_step_size_threshold ) { - *prev_ind += SKP_LSHIFT( ind[ k ], 1 ) - double_step_size_threshold; - } else { - *prev_ind += ind[ k ]; - } - - /* Shift to make non-negative */ - ind[ k ] -= MIN_DELTA_GAIN_QUANT; - } - - /* Convert to linear scale and scale */ - gain_Q16[ k ] = silk_log2lin( SKP_min_32( SKP_SMULWB( INV_SCALE_Q16, *prev_ind ) + OFFSET, 3967 ) ); /* 3967 = 31 in Q7 */ - } -} - -/* Gains scalar dequantization, uniform on log scale */ -void silk_gains_dequant( - opus_int32 gain_Q16[ MAX_NB_SUBFR ], /* O quantized gains */ - const opus_int8 ind[ MAX_NB_SUBFR ], /* I gain indices */ - opus_int8 *prev_ind, /* I/O last index in previous frame */ - const opus_int conditional, /* I first gain is delta coded if 1 */ - const opus_int nb_subfr /* I number of subframes */ -) -{ - opus_int k, ind_tmp, double_step_size_threshold; - - for( k = 0; k < nb_subfr; k++ ) { - if( k == 0 && conditional == 0 ) { - *prev_ind = ind[ k ]; - } else { - /* Delta index */ - ind_tmp = ind[ k ] + MIN_DELTA_GAIN_QUANT; - - /* Accumulate deltas */ - double_step_size_threshold = 2 * MAX_DELTA_GAIN_QUANT - N_LEVELS_QGAIN + *prev_ind; - if( ind_tmp > double_step_size_threshold ) { - *prev_ind += SKP_LSHIFT( ind_tmp, 1 ) - double_step_size_threshold; - } else { - *prev_ind += ind_tmp; - } - } - *prev_ind = SKP_min( *prev_ind, N_LEVELS_QGAIN - 1 ); - - /* Convert to linear scale and scale */ - gain_Q16[ k ] = silk_log2lin( SKP_min_32( SKP_SMULWB( INV_SCALE_Q16, *prev_ind ) + OFFSET, 3967 ) ); /* 3967 = 31 in Q7 */ - } -} +/*********************************************************************** +Copyright (c) 2006-2011, Skype Limited. All rights reserved. +Redistribution and use in source and binary forms, with or without +modification, (subject to the limitations in the disclaimer below) +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 Skype Limited, nor the names of specific +contributors, may be used to endorse or promote products derived from +this software without specific prior written permission. +NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED +BY THIS LICENSE. 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. +***********************************************************************/ + +#include "silk_main.h" + +#define OFFSET ( ( MIN_QGAIN_DB * 128 ) / 6 + 16 * 128 ) +#define SCALE_Q16 ( ( 65536 * ( N_LEVELS_QGAIN - 1 ) ) / ( ( ( MAX_QGAIN_DB - MIN_QGAIN_DB ) * 128 ) / 6 ) ) +#define INV_SCALE_Q16 ( ( 65536 * ( ( ( MAX_QGAIN_DB - MIN_QGAIN_DB ) * 128 ) / 6 ) ) / ( N_LEVELS_QGAIN - 1 ) ) + +/* Gain scalar quantization with hysteresis, uniform on log scale */ +void silk_gains_quant( + opus_int8 ind[ MAX_NB_SUBFR ], /* O gain indices */ + opus_int32 gain_Q16[ MAX_NB_SUBFR ], /* I/O gains (quantized out) */ + opus_int8 *prev_ind, /* I/O last index in previous frame */ + const opus_int conditional, /* I first gain is delta coded if 1 */ + const opus_int nb_subfr /* I number of subframes */ +) +{ + opus_int k, double_step_size_threshold; + + for( k = 0; k < nb_subfr; k++ ) { + /* Add half of previous quantization error, convert to log scale, scale, floor() */ + ind[ k ] = SKP_SMULWB( SCALE_Q16, silk_lin2log( gain_Q16[ k ] ) - OFFSET ); + + /* Round towards previous quantized gain (hysteresis) */ + if( ind[ k ] < *prev_ind ) { + ind[ k ]++; + } + ind[ k ] = SKP_max_int( ind[ k ], 0 ); + + /* Compute delta indices and limit */ + if( k == 0 && conditional == 0 ) { + /* Full index */ + ind[ k ] = SKP_LIMIT_int( ind[ k ], *prev_ind + MIN_DELTA_GAIN_QUANT, N_LEVELS_QGAIN - 1 ); + *prev_ind = ind[ k ]; + } else { + /* Delta index */ + ind[ k ] = ind[ k ] - *prev_ind; + + /* Double the quantization step size for large gain increases, so that the max gain level can be reached */ + double_step_size_threshold = 2 * MAX_DELTA_GAIN_QUANT - N_LEVELS_QGAIN + *prev_ind; + if( ind[ k ] > double_step_size_threshold ) { + ind[ k ] = double_step_size_threshold + SKP_RSHIFT( ind[ k ] - double_step_size_threshold + 1, 1 ); + } + + ind[ k ] = SKP_LIMIT_int( ind[ k ], MIN_DELTA_GAIN_QUANT, MAX_DELTA_GAIN_QUANT ); + + /* Accumulate deltas */ + if( ind[ k ] > double_step_size_threshold ) { + *prev_ind += SKP_LSHIFT( ind[ k ], 1 ) - double_step_size_threshold; + } else { + *prev_ind += ind[ k ]; + } + + /* Shift to make non-negative */ + ind[ k ] -= MIN_DELTA_GAIN_QUANT; + } + + /* Convert to linear scale and scale */ + gain_Q16[ k ] = silk_log2lin( SKP_min_32( SKP_SMULWB( INV_SCALE_Q16, *prev_ind ) + OFFSET, 3967 ) ); /* 3967 = 31 in Q7 */ + } +} + +/* Gains scalar dequantization, uniform on log scale */ +void silk_gains_dequant( + opus_int32 gain_Q16[ MAX_NB_SUBFR ], /* O quantized gains */ + const opus_int8 ind[ MAX_NB_SUBFR ], /* I gain indices */ + opus_int8 *prev_ind, /* I/O last index in previous frame */ + const opus_int conditional, /* I first gain is delta coded if 1 */ + const opus_int nb_subfr /* I number of subframes */ +) +{ + opus_int k, ind_tmp, double_step_size_threshold; + + for( k = 0; k < nb_subfr; k++ ) { + if( k == 0 && conditional == 0 ) { + *prev_ind = ind[ k ]; + } else { + /* Delta index */ + ind_tmp = ind[ k ] + MIN_DELTA_GAIN_QUANT; + + /* Accumulate deltas */ + double_step_size_threshold = 2 * MAX_DELTA_GAIN_QUANT - N_LEVELS_QGAIN + *prev_ind; + if( ind_tmp > double_step_size_threshold ) { + *prev_ind += SKP_LSHIFT( ind_tmp, 1 ) - double_step_size_threshold; + } else { + *prev_ind += ind_tmp; + } + } + *prev_ind = SKP_min( *prev_ind, N_LEVELS_QGAIN - 1 ); + + /* Convert to linear scale and scale */ + gain_Q16[ k ] = silk_log2lin( SKP_min_32( SKP_SMULWB( INV_SCALE_Q16, *prev_ind ) + OFFSET, 3967 ) ); /* 3967 = 31 in Q7 */ + } +} diff --git a/silk/silk_init_encoder.c b/silk/silk_init_encoder.c index 2a5000144..0a6779649 100644 --- a/silk/silk_init_encoder.c +++ b/silk/silk_init_encoder.c @@ -1,61 +1,61 @@ -/*********************************************************************** -Copyright (c) 2006-2011, Skype Limited. All rights reserved. -Redistribution and use in source and binary forms, with or without -modification, (subject to the limitations in the disclaimer below) -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 Skype Limited, nor the names of specific -contributors, may be used to endorse or promote products derived from -this software without specific prior written permission. -NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED -BY THIS LICENSE. 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 -#ifdef FIXED_POINT -#include "silk_main_FIX.h" -#else -#include "silk_main_FLP.h" -#endif -#include "silk_tuning_parameters.h" - -/*********************************/ -/* Initialize Silk Encoder state */ -/*********************************/ -opus_int silk_init_encoder( - silk_encoder_state_Fxx *psEnc /* I/O Pointer to Silk encoder state */ -) { - opus_int ret = 0; - - /* Clear the entire encoder state */ - SKP_memset( psEnc, 0, sizeof( silk_encoder_state_Fxx ) ); - - psEnc->sCmn.inputBuf = &psEnc->sCmn.inputBuf__[ 2 ]; - - psEnc->sCmn.variable_HP_smth1_Q15 = SKP_LSHIFT( silk_lin2log( SILK_FIX_CONST( VARIABLE_HP_MIN_CUTOFF_HZ, 16 ) ) - ( 16 << 7 ), 8 ); - psEnc->sCmn.variable_HP_smth2_Q15 = psEnc->sCmn.variable_HP_smth1_Q15; - - /* Used to deactivate LSF interpolation, fluctuation reduction, pitch prediction */ - psEnc->sCmn.first_frame_after_reset = 1; - - /* Initialize Silk VAD */ - ret += silk_VAD_Init( &psEnc->sCmn.sVAD ); - - return ret; -} +/*********************************************************************** +Copyright (c) 2006-2011, Skype Limited. All rights reserved. +Redistribution and use in source and binary forms, with or without +modification, (subject to the limitations in the disclaimer below) +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 Skype Limited, nor the names of specific +contributors, may be used to endorse or promote products derived from +this software without specific prior written permission. +NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED +BY THIS LICENSE. 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 +#ifdef FIXED_POINT +#include "silk_main_FIX.h" +#else +#include "silk_main_FLP.h" +#endif +#include "silk_tuning_parameters.h" + +/*********************************/ +/* Initialize Silk Encoder state */ +/*********************************/ +opus_int silk_init_encoder( + silk_encoder_state_Fxx *psEnc /* I/O Pointer to Silk encoder state */ +) { + opus_int ret = 0; + + /* Clear the entire encoder state */ + SKP_memset( psEnc, 0, sizeof( silk_encoder_state_Fxx ) ); + + psEnc->sCmn.inputBuf = &psEnc->sCmn.inputBuf__[ 2 ]; + + psEnc->sCmn.variable_HP_smth1_Q15 = SKP_LSHIFT( silk_lin2log( SILK_FIX_CONST( VARIABLE_HP_MIN_CUTOFF_HZ, 16 ) ) - ( 16 << 7 ), 8 ); + psEnc->sCmn.variable_HP_smth2_Q15 = psEnc->sCmn.variable_HP_smth1_Q15; + + /* Used to deactivate LSF interpolation, fluctuation reduction, pitch prediction */ + psEnc->sCmn.first_frame_after_reset = 1; + + /* Initialize Silk VAD */ + ret += silk_VAD_Init( &psEnc->sCmn.sVAD ); + + return ret; +} diff --git a/silk/silk_inner_prod_aligned.c b/silk/silk_inner_prod_aligned.c index c0e9faae6..c9a970f1d 100644 --- a/silk/silk_inner_prod_aligned.c +++ b/silk/silk_inner_prod_aligned.c @@ -1,77 +1,77 @@ -/*********************************************************************** -Copyright (c) 2006-2011, Skype Limited. All rights reserved. -Redistribution and use in source and binary forms, with or without -modification, (subject to the limitations in the disclaimer below) -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 Skype Limited, nor the names of specific -contributors, may be used to endorse or promote products derived from -this software without specific prior written permission. -NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED -BY THIS LICENSE. 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. -***********************************************************************/ - -#include "silk_SigProc_FIX.h" - -/* sum= for(i=0;i<len;i++)inVec1[i]*inVec2[i]; --- inner product */ -/* Note for ARM asm: */ -/* * inVec1 and inVec2 should be at least 2 byte aligned. (Or defined as short/int16) */ -/* * len should be positive 16bit integer. */ -/* * only when len>6, memory access can be reduced by half. */ - -opus_int32 silk_inner_prod_aligned( - const opus_int16 *const inVec1, /* I input vector 1 */ - const opus_int16 *const inVec2, /* I input vector 2 */ - const opus_int len /* I vector lengths */ -) -{ - opus_int i; - opus_int32 sum = 0; - for( i = 0; i < len; i++ ) { - sum = SKP_SMLABB( sum, inVec1[ i ], inVec2[ i ] ); - } - return sum; -} - -opus_int32 silk_inner_prod_aligned_scale( - const opus_int16 *const inVec1, /* I input vector 1 */ - const opus_int16 *const inVec2, /* I input vector 2 */ - const opus_int scale, /* I number of bits to shift */ - const opus_int len /* I vector lengths */ -) -{ - opus_int i; - opus_int32 sum = 0; - for( i = 0; i < len; i++ ) { - sum = SKP_ADD_RSHIFT32( sum, SKP_SMULBB( inVec1[ i ], inVec2[ i ] ), scale ); - } - return sum; -} - -opus_int64 silk_inner_prod16_aligned_64( - const opus_int16 *inVec1, /* I input vector 1 */ - const opus_int16 *inVec2, /* I input vector 2 */ - const opus_int len /* I vector lengths */ -) -{ - opus_int i; - opus_int64 sum = 0; - for( i = 0; i < len; i++ ) { - sum = SKP_SMLALBB( sum, inVec1[ i ], inVec2[ i ] ); - } - return sum; -} +/*********************************************************************** +Copyright (c) 2006-2011, Skype Limited. All rights reserved. +Redistribution and use in source and binary forms, with or without +modification, (subject to the limitations in the disclaimer below) +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 Skype Limited, nor the names of specific +contributors, may be used to endorse or promote products derived from +this software without specific prior written permission. +NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED +BY THIS LICENSE. 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. +***********************************************************************/ + +#include "silk_SigProc_FIX.h" + +/* sum= for(i=0;i<len;i++)inVec1[i]*inVec2[i]; --- inner product */ +/* Note for ARM asm: */ +/* * inVec1 and inVec2 should be at least 2 byte aligned. (Or defined as short/int16) */ +/* * len should be positive 16bit integer. */ +/* * only when len>6, memory access can be reduced by half. */ + +opus_int32 silk_inner_prod_aligned( + const opus_int16 *const inVec1, /* I input vector 1 */ + const opus_int16 *const inVec2, /* I input vector 2 */ + const opus_int len /* I vector lengths */ +) +{ + opus_int i; + opus_int32 sum = 0; + for( i = 0; i < len; i++ ) { + sum = SKP_SMLABB( sum, inVec1[ i ], inVec2[ i ] ); + } + return sum; +} + +opus_int32 silk_inner_prod_aligned_scale( + const opus_int16 *const inVec1, /* I input vector 1 */ + const opus_int16 *const inVec2, /* I input vector 2 */ + const opus_int scale, /* I number of bits to shift */ + const opus_int len /* I vector lengths */ +) +{ + opus_int i; + opus_int32 sum = 0; + for( i = 0; i < len; i++ ) { + sum = SKP_ADD_RSHIFT32( sum, SKP_SMULBB( inVec1[ i ], inVec2[ i ] ), scale ); + } + return sum; +} + +opus_int64 silk_inner_prod16_aligned_64( + const opus_int16 *inVec1, /* I input vector 1 */ + const opus_int16 *inVec2, /* I input vector 2 */ + const opus_int len /* I vector lengths */ +) +{ + opus_int i; + opus_int64 sum = 0; + for( i = 0; i < len; i++ ) { + sum = SKP_SMLALBB( sum, inVec1[ i ], inVec2[ i ] ); + } + return sum; +} diff --git a/silk/silk_interpolate.c b/silk/silk_interpolate.c index 4c50a4a62..987331f4a 100644 --- a/silk/silk_interpolate.c +++ b/silk/silk_interpolate.c @@ -1,47 +1,47 @@ -/*********************************************************************** -Copyright (c) 2006-2011, Skype Limited. All rights reserved. -Redistribution and use in source and binary forms, with or without -modification, (subject to the limitations in the disclaimer below) -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 Skype Limited, nor the names of specific -contributors, may be used to endorse or promote products derived from -this software without specific prior written permission. -NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED -BY THIS LICENSE. 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. -***********************************************************************/ - -#include "silk_main.h" - -/* Interpolate two vectors */ -void silk_interpolate( - opus_int16 xi[ MAX_LPC_ORDER ], /* O interpolated vector */ - const opus_int16 x0[ MAX_LPC_ORDER ], /* I first vector */ - const opus_int16 x1[ MAX_LPC_ORDER ], /* I second vector */ - const opus_int ifact_Q2, /* I interp. factor, weight on 2nd vector */ - const opus_int d /* I number of parameters */ -) -{ - opus_int i; - - SKP_assert( ifact_Q2 >= 0 ); - SKP_assert( ifact_Q2 <= 4 ); - - for( i = 0; i < d; i++ ) { - xi[ i ] = ( opus_int16 )SKP_ADD_RSHIFT( x0[ i ], SKP_SMULBB( x1[ i ] - x0[ i ], ifact_Q2 ), 2 ); - } -} +/*********************************************************************** +Copyright (c) 2006-2011, Skype Limited. All rights reserved. +Redistribution and use in source and binary forms, with or without +modification, (subject to the limitations in the disclaimer below) +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 Skype Limited, nor the names of specific +contributors, may be used to endorse or promote products derived from +this software without specific prior written permission. +NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED +BY THIS LICENSE. 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. +***********************************************************************/ + +#include "silk_main.h" + +/* Interpolate two vectors */ +void silk_interpolate( + opus_int16 xi[ MAX_LPC_ORDER ], /* O interpolated vector */ + const opus_int16 x0[ MAX_LPC_ORDER ], /* I first vector */ + const opus_int16 x1[ MAX_LPC_ORDER ], /* I second vector */ + const opus_int ifact_Q2, /* I interp. factor, weight on 2nd vector */ + const opus_int d /* I number of parameters */ +) +{ + opus_int i; + + SKP_assert( ifact_Q2 >= 0 ); + SKP_assert( ifact_Q2 <= 4 ); + + for( i = 0; i < d; i++ ) { + xi[ i ] = ( opus_int16 )SKP_ADD_RSHIFT( x0[ i ], SKP_SMULBB( x1[ i ] - x0[ i ], ifact_Q2 ), 2 ); + } +} diff --git a/silk/silk_k2a.c b/silk/silk_k2a.c index ef43c1651..13a22fba6 100644 --- a/silk/silk_k2a.c +++ b/silk/silk_k2a.c @@ -1,49 +1,49 @@ -/*********************************************************************** -Copyright (c) 2006-2011, Skype Limited. All rights reserved. -Redistribution and use in source and binary forms, with or without -modification, (subject to the limitations in the disclaimer below) -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 Skype Limited, nor the names of specific -contributors, may be used to endorse or promote products derived from -this software without specific prior written permission. -NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED -BY THIS LICENSE. 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. -***********************************************************************/ - -#include "silk_SigProc_FIX.h" - -/* Step up function, converts reflection coefficients to prediction coefficients */ -void silk_k2a( - opus_int32 *A_Q24, /* O: Prediction coefficients [order] Q24 */ - const opus_int16 *rc_Q15, /* I: Reflection coefficients [order] Q15 */ - const opus_int32 order /* I: Prediction order */ -) -{ - opus_int k, n; - opus_int32 Atmp[ SILK_MAX_ORDER_LPC ]; - - for( k = 0; k < order; k++ ) { - for( n = 0; n < k; n++ ) { - Atmp[ n ] = A_Q24[ n ]; - } - for( n = 0; n < k; n++ ) { - A_Q24[ n ] = SKP_SMLAWB( A_Q24[ n ], SKP_LSHIFT( Atmp[ k - n - 1 ], 1 ), rc_Q15[ k ] ); - } - A_Q24[ k ] = -SKP_LSHIFT( (opus_int32)rc_Q15[ k ], 9 ); - } -} +/*********************************************************************** +Copyright (c) 2006-2011, Skype Limited. All rights reserved. +Redistribution and use in source and binary forms, with or without +modification, (subject to the limitations in the disclaimer below) +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 Skype Limited, nor the names of specific +contributors, may be used to endorse or promote products derived from +this software without specific prior written permission. +NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED +BY THIS LICENSE. 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. +***********************************************************************/ + +#include "silk_SigProc_FIX.h" + +/* Step up function, converts reflection coefficients to prediction coefficients */ +void silk_k2a( + opus_int32 *A_Q24, /* O: Prediction coefficients [order] Q24 */ + const opus_int16 *rc_Q15, /* I: Reflection coefficients [order] Q15 */ + const opus_int32 order /* I: Prediction order */ +) +{ + opus_int k, n; + opus_int32 Atmp[ SILK_MAX_ORDER_LPC ]; + + for( k = 0; k < order; k++ ) { + for( n = 0; n < k; n++ ) { + Atmp[ n ] = A_Q24[ n ]; + } + for( n = 0; n < k; n++ ) { + A_Q24[ n ] = SKP_SMLAWB( A_Q24[ n ], SKP_LSHIFT( Atmp[ k - n - 1 ], 1 ), rc_Q15[ k ] ); + } + A_Q24[ k ] = -SKP_LSHIFT( (opus_int32)rc_Q15[ k ], 9 ); + } +} diff --git a/silk/silk_k2a_Q16.c b/silk/silk_k2a_Q16.c index 2b7c5b78c..115b2d7a6 100644 --- a/silk/silk_k2a_Q16.c +++ b/silk/silk_k2a_Q16.c @@ -1,49 +1,49 @@ -/*********************************************************************** -Copyright (c) 2006-2011, Skype Limited. All rights reserved. -Redistribution and use in source and binary forms, with or without -modification, (subject to the limitations in the disclaimer below) -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 Skype Limited, nor the names of specific -contributors, may be used to endorse or promote products derived from -this software without specific prior written permission. -NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED -BY THIS LICENSE. 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. -***********************************************************************/ - -#include "silk_SigProc_FIX.h" - -/* Step up function, converts reflection coefficients to prediction coefficients */ -void silk_k2a_Q16( - opus_int32 *A_Q24, /* O: Prediction coefficients [order] Q24 */ - const opus_int32 *rc_Q16, /* I: Reflection coefficients [order] Q16 */ - const opus_int32 order /* I: Prediction order */ -) -{ - opus_int k, n; - opus_int32 Atmp[ SILK_MAX_ORDER_LPC ]; - - for( k = 0; k < order; k++ ) { - for( n = 0; n < k; n++ ) { - Atmp[ n ] = A_Q24[ n ]; - } - for( n = 0; n < k; n++ ) { - A_Q24[ n ] = SKP_SMLAWW( A_Q24[ n ], Atmp[ k - n - 1 ], rc_Q16[ k ] ); - } - A_Q24[ k ] = -SKP_LSHIFT( rc_Q16[ k ], 8 ); - } -} +/*********************************************************************** +Copyright (c) 2006-2011, Skype Limited. All rights reserved. +Redistribution and use in source and binary forms, with or without +modification, (subject to the limitations in the disclaimer below) +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 Skype Limited, nor the names of specific +contributors, may be used to endorse or promote products derived from +this software without specific prior written permission. +NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED +BY THIS LICENSE. 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. +***********************************************************************/ + +#include "silk_SigProc_FIX.h" + +/* Step up function, converts reflection coefficients to prediction coefficients */ +void silk_k2a_Q16( + opus_int32 *A_Q24, /* O: Prediction coefficients [order] Q24 */ + const opus_int32 *rc_Q16, /* I: Reflection coefficients [order] Q16 */ + const opus_int32 order /* I: Prediction order */ +) +{ + opus_int k, n; + opus_int32 Atmp[ SILK_MAX_ORDER_LPC ]; + + for( k = 0; k < order; k++ ) { + for( n = 0; n < k; n++ ) { + Atmp[ n ] = A_Q24[ n ]; + } + for( n = 0; n < k; n++ ) { + A_Q24[ n ] = SKP_SMLAWW( A_Q24[ n ], Atmp[ k - n - 1 ], rc_Q16[ k ] ); + } + A_Q24[ k ] = -SKP_LSHIFT( rc_Q16[ k ], 8 ); + } +} diff --git a/silk/silk_lin2log.c b/silk/silk_lin2log.c index 7de345a7e..de43d6a44 100644 --- a/silk/silk_lin2log.c +++ b/silk/silk_lin2log.c @@ -1,40 +1,40 @@ -/*********************************************************************** -Copyright (c) 2006-2011, Skype Limited. All rights reserved. -Redistribution and use in source and binary forms, with or without -modification, (subject to the limitations in the disclaimer below) -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 Skype Limited, nor the names of specific -contributors, may be used to endorse or promote products derived from -this software without specific prior written permission. -NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED -BY THIS LICENSE. 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. -***********************************************************************/ - -#include "silk_SigProc_FIX.h" -/* Approximation of 128 * log2() (very close inverse of silk_log2lin()) */ -/* Convert input to a log scale */ -opus_int32 silk_lin2log( const opus_int32 inLin ) /* I: Input in linear scale */ -{ - opus_int32 lz, frac_Q7; - - silk_CLZ_FRAC( inLin, &lz, &frac_Q7 ); - - /* Piece-wise parabolic approximation */ - return SKP_LSHIFT( 31 - lz, 7 ) + SKP_SMLAWB( frac_Q7, SKP_MUL( frac_Q7, 128 - frac_Q7 ), 179 ); -} - +/*********************************************************************** +Copyright (c) 2006-2011, Skype Limited. All rights reserved. +Redistribution and use in source and binary forms, with or without +modification, (subject to the limitations in the disclaimer below) +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 Skype Limited, nor the names of specific +contributors, may be used to endorse or promote products derived from +this software without specific prior written permission. +NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED +BY THIS LICENSE. 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. +***********************************************************************/ + +#include "silk_SigProc_FIX.h" +/* Approximation of 128 * log2() (very close inverse of silk_log2lin()) */ +/* Convert input to a log scale */ +opus_int32 silk_lin2log( const opus_int32 inLin ) /* I: Input in linear scale */ +{ + opus_int32 lz, frac_Q7; + + silk_CLZ_FRAC( inLin, &lz, &frac_Q7 ); + + /* Piece-wise parabolic approximation */ + return SKP_LSHIFT( 31 - lz, 7 ) + SKP_SMLAWB( frac_Q7, SKP_MUL( frac_Q7, 128 - frac_Q7 ), 179 ); +} + diff --git a/silk/silk_log2lin.c b/silk/silk_log2lin.c index a7bb26e25..05141c2ca 100644 --- a/silk/silk_log2lin.c +++ b/silk/silk_log2lin.c @@ -1,50 +1,50 @@ -/*********************************************************************** -Copyright (c) 2006-2011, Skype Limited. All rights reserved. -Redistribution and use in source and binary forms, with or without -modification, (subject to the limitations in the disclaimer below) -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 Skype Limited, nor the names of specific -contributors, may be used to endorse or promote products derived from -this software without specific prior written permission. -NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED -BY THIS LICENSE. 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. -***********************************************************************/ - -#include "silk_SigProc_FIX.h" - -/* Approximation of 2^() (very close inverse of silk_lin2log()) */ -/* Convert input to a linear scale */ -opus_int32 silk_log2lin( const opus_int32 inLog_Q7 ) /* I: Input on log scale */ -{ - opus_int32 out, frac_Q7; - - if( inLog_Q7 < 0 ) { - return 0; - } - - out = SKP_LSHIFT( 1, SKP_RSHIFT( inLog_Q7, 7 ) ); - frac_Q7 = inLog_Q7 & 0x7F; - if( inLog_Q7 < 2048 ) { - /* Piece-wise parabolic approximation */ - out = SKP_ADD_RSHIFT( out, SKP_MUL( out, SKP_SMLAWB( frac_Q7, SKP_MUL( frac_Q7, 128 - frac_Q7 ), -174 ) ), 7 ); - } else { - /* Piece-wise parabolic approximation */ - out = SKP_MLA( out, SKP_RSHIFT( out, 7 ), SKP_SMLAWB( frac_Q7, SKP_MUL( frac_Q7, 128 - frac_Q7 ), -174 ) ); - } - return out; -} +/*********************************************************************** +Copyright (c) 2006-2011, Skype Limited. All rights reserved. +Redistribution and use in source and binary forms, with or without +modification, (subject to the limitations in the disclaimer below) +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 Skype Limited, nor the names of specific +contributors, may be used to endorse or promote products derived from +this software without specific prior written permission. +NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED +BY THIS LICENSE. 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. +***********************************************************************/ + +#include "silk_SigProc_FIX.h" + +/* Approximation of 2^() (very close inverse of silk_lin2log()) */ +/* Convert input to a linear scale */ +opus_int32 silk_log2lin( const opus_int32 inLog_Q7 ) /* I: Input on log scale */ +{ + opus_int32 out, frac_Q7; + + if( inLog_Q7 < 0 ) { + return 0; + } + + out = SKP_LSHIFT( 1, SKP_RSHIFT( inLog_Q7, 7 ) ); + frac_Q7 = inLog_Q7 & 0x7F; + if( inLog_Q7 < 2048 ) { + /* Piece-wise parabolic approximation */ + out = SKP_ADD_RSHIFT( out, SKP_MUL( out, SKP_SMLAWB( frac_Q7, SKP_MUL( frac_Q7, 128 - frac_Q7 ), -174 ) ), 7 ); + } else { + /* Piece-wise parabolic approximation */ + out = SKP_MLA( out, SKP_RSHIFT( out, 7 ), SKP_SMLAWB( frac_Q7, SKP_MUL( frac_Q7, 128 - frac_Q7 ), -174 ) ); + } + return out; +} diff --git a/silk/silk_macros.h b/silk/silk_macros.h index 56424669e..27299c52f 100644 --- a/silk/silk_macros.h +++ b/silk/silk_macros.h @@ -1,132 +1,132 @@ -/*********************************************************************** -Copyright (c) 2006-2011, Skype Limited. All rights reserved. -Redistribution and use in source and binary forms, with or without -modification, (subject to the limitations in the disclaimer below) -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 Skype Limited, nor the names of specific -contributors, may be used to endorse or promote products derived from -this software without specific prior written permission. -NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED -BY THIS LICENSE. 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. -***********************************************************************/ - -#ifndef _SILK_API_C_H_ -#define _SILK_API_C_H_ - -// This is an inline header file for general platform. - -// (a32 * (opus_int32)((opus_int16)(b32))) >> 16 output have to be 32bit int -#define SKP_SMULWB(a32, b32) ((((a32) >> 16) * (opus_int32)((opus_int16)(b32))) + ((((a32) & 0x0000FFFF) * (opus_int32)((opus_int16)(b32))) >> 16)) - -// a32 + (b32 * (opus_int32)((opus_int16)(c32))) >> 16 output have to be 32bit int -#define SKP_SMLAWB(a32, b32, c32) ((a32) + ((((b32) >> 16) * (opus_int32)((opus_int16)(c32))) + ((((b32) & 0x0000FFFF) * (opus_int32)((opus_int16)(c32))) >> 16))) - -// (a32 * (b32 >> 16)) >> 16 -#define SKP_SMULWT(a32, b32) (((a32) >> 16) * ((b32) >> 16) + ((((a32) & 0x0000FFFF) * ((b32) >> 16)) >> 16)) - -// a32 + (b32 * (c32 >> 16)) >> 16 -#define SKP_SMLAWT(a32, b32, c32) ((a32) + (((b32) >> 16) * ((c32) >> 16)) + ((((b32) & 0x0000FFFF) * ((c32) >> 16)) >> 16)) - -// (opus_int32)((opus_int16)(a3))) * (opus_int32)((opus_int16)(b32)) output have to be 32bit int -#define SKP_SMULBB(a32, b32) ((opus_int32)((opus_int16)(a32)) * (opus_int32)((opus_int16)(b32))) - -// a32 + (opus_int32)((opus_int16)(b32)) * (opus_int32)((opus_int16)(c32)) output have to be 32bit int -#define SKP_SMLABB(a32, b32, c32) ((a32) + ((opus_int32)((opus_int16)(b32))) * (opus_int32)((opus_int16)(c32))) - -// (opus_int32)((opus_int16)(a32)) * (b32 >> 16) -#define SKP_SMULBT(a32, b32) ((opus_int32)((opus_int16)(a32)) * ((b32) >> 16)) - -// a32 + (opus_int32)((opus_int16)(b32)) * (c32 >> 16) -#define SKP_SMLABT(a32, b32, c32) ((a32) + ((opus_int32)((opus_int16)(b32))) * ((c32) >> 16)) - -// a64 + (b32 * c32) -#define SKP_SMLAL(a64, b32, c32) (SKP_ADD64((a64), ((opus_int64)(b32) * (opus_int64)(c32)))) - -// (a32 * b32) >> 16 -#define SKP_SMULWW(a32, b32) SKP_MLA(SKP_SMULWB((a32), (b32)), (a32), SKP_RSHIFT_ROUND((b32), 16)) - -// a32 + ((b32 * c32) >> 16) -#define SKP_SMLAWW(a32, b32, c32) SKP_MLA(SKP_SMLAWB((a32), (b32), (c32)), (b32), SKP_RSHIFT_ROUND((c32), 16)) - -/* add/subtract with output saturated */ -#define SKP_ADD_SAT32(a, b) ((((a) + (b)) & 0x80000000) == 0 ? \ - ((((a) & (b)) & 0x80000000) != 0 ? SKP_int32_MIN : (a)+(b)) : \ - ((((a) | (b)) & 0x80000000) == 0 ? SKP_int32_MAX : (a)+(b)) ) - -#define SKP_SUB_SAT32(a, b) ((((a)-(b)) & 0x80000000) == 0 ? \ - (( (a) & ((b)^0x80000000) & 0x80000000) ? SKP_int32_MIN : (a)-(b)) : \ - ((((a)^0x80000000) & (b) & 0x80000000) ? SKP_int32_MAX : (a)-(b)) ) - -SKP_INLINE opus_int32 silk_CLZ16(opus_int16 in16) -{ - opus_int32 out32 = 0; - if( in16 == 0 ) { - return 16; - } - /* test nibbles */ - if( in16 & 0xFF00 ) { - if( in16 & 0xF000 ) { - in16 >>= 12; - } else { - out32 += 4; - in16 >>= 8; - } - } else { - if( in16 & 0xFFF0 ) { - out32 += 8; - in16 >>= 4; - } else { - out32 += 12; - } - } - /* test bits and return */ - if( in16 & 0xC ) { - if( in16 & 0x8 ) - return out32 + 0; - else - return out32 + 1; - } else { - if( in16 & 0xE ) - return out32 + 2; - else - return out32 + 3; - } -} - -SKP_INLINE opus_int32 silk_CLZ32(opus_int32 in32) -{ - /* test highest 16 bits and convert to opus_int16 */ - if( in32 & 0xFFFF0000 ) { - return silk_CLZ16((opus_int16)(in32 >> 16)); - } else { - return silk_CLZ16((opus_int16)in32) + 16; - } -} - -/* Row based */ -#define matrix_ptr(Matrix_base_adr, row, column, N) *(Matrix_base_adr + ((row)*(N)+(column))) -#define matrix_adr(Matrix_base_adr, row, column, N) (Matrix_base_adr + ((row)*(N)+(column))) - -/* Column based */ -#ifndef matrix_c_ptr -# define matrix_c_ptr(Matrix_base_adr, row, column, M) *(Matrix_base_adr + ((row)+(M)*(column))) -#endif -#define matrix_c_adr(Matrix_base_adr, row, column, M) (Matrix_base_adr + ((row)+(M)*(column))) - -#endif //_SILK_API_C_H_ - +/*********************************************************************** +Copyright (c) 2006-2011, Skype Limited. All rights reserved. +Redistribution and use in source and binary forms, with or without +modification, (subject to the limitations in the disclaimer below) +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 Skype Limited, nor the names of specific +contributors, may be used to endorse or promote products derived from +this software without specific prior written permission. +NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED +BY THIS LICENSE. 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. +***********************************************************************/ + +#ifndef _SILK_API_C_H_ +#define _SILK_API_C_H_ + +// This is an inline header file for general platform. + +// (a32 * (opus_int32)((opus_int16)(b32))) >> 16 output have to be 32bit int +#define SKP_SMULWB(a32, b32) ((((a32) >> 16) * (opus_int32)((opus_int16)(b32))) + ((((a32) & 0x0000FFFF) * (opus_int32)((opus_int16)(b32))) >> 16)) + +// a32 + (b32 * (opus_int32)((opus_int16)(c32))) >> 16 output have to be 32bit int +#define SKP_SMLAWB(a32, b32, c32) ((a32) + ((((b32) >> 16) * (opus_int32)((opus_int16)(c32))) + ((((b32) & 0x0000FFFF) * (opus_int32)((opus_int16)(c32))) >> 16))) + +// (a32 * (b32 >> 16)) >> 16 +#define SKP_SMULWT(a32, b32) (((a32) >> 16) * ((b32) >> 16) + ((((a32) & 0x0000FFFF) * ((b32) >> 16)) >> 16)) + +// a32 + (b32 * (c32 >> 16)) >> 16 +#define SKP_SMLAWT(a32, b32, c32) ((a32) + (((b32) >> 16) * ((c32) >> 16)) + ((((b32) & 0x0000FFFF) * ((c32) >> 16)) >> 16)) + +// (opus_int32)((opus_int16)(a3))) * (opus_int32)((opus_int16)(b32)) output have to be 32bit int +#define SKP_SMULBB(a32, b32) ((opus_int32)((opus_int16)(a32)) * (opus_int32)((opus_int16)(b32))) + +// a32 + (opus_int32)((opus_int16)(b32)) * (opus_int32)((opus_int16)(c32)) output have to be 32bit int +#define SKP_SMLABB(a32, b32, c32) ((a32) + ((opus_int32)((opus_int16)(b32))) * (opus_int32)((opus_int16)(c32))) + +// (opus_int32)((opus_int16)(a32)) * (b32 >> 16) +#define SKP_SMULBT(a32, b32) ((opus_int32)((opus_int16)(a32)) * ((b32) >> 16)) + +// a32 + (opus_int32)((opus_int16)(b32)) * (c32 >> 16) +#define SKP_SMLABT(a32, b32, c32) ((a32) + ((opus_int32)((opus_int16)(b32))) * ((c32) >> 16)) + +// a64 + (b32 * c32) +#define SKP_SMLAL(a64, b32, c32) (SKP_ADD64((a64), ((opus_int64)(b32) * (opus_int64)(c32)))) + +// (a32 * b32) >> 16 +#define SKP_SMULWW(a32, b32) SKP_MLA(SKP_SMULWB((a32), (b32)), (a32), SKP_RSHIFT_ROUND((b32), 16)) + +// a32 + ((b32 * c32) >> 16) +#define SKP_SMLAWW(a32, b32, c32) SKP_MLA(SKP_SMLAWB((a32), (b32), (c32)), (b32), SKP_RSHIFT_ROUND((c32), 16)) + +/* add/subtract with output saturated */ +#define SKP_ADD_SAT32(a, b) ((((a) + (b)) & 0x80000000) == 0 ? \ + ((((a) & (b)) & 0x80000000) != 0 ? SKP_int32_MIN : (a)+(b)) : \ + ((((a) | (b)) & 0x80000000) == 0 ? SKP_int32_MAX : (a)+(b)) ) + +#define SKP_SUB_SAT32(a, b) ((((a)-(b)) & 0x80000000) == 0 ? \ + (( (a) & ((b)^0x80000000) & 0x80000000) ? SKP_int32_MIN : (a)-(b)) : \ + ((((a)^0x80000000) & (b) & 0x80000000) ? SKP_int32_MAX : (a)-(b)) ) + +SKP_INLINE opus_int32 silk_CLZ16(opus_int16 in16) +{ + opus_int32 out32 = 0; + if( in16 == 0 ) { + return 16; + } + /* test nibbles */ + if( in16 & 0xFF00 ) { + if( in16 & 0xF000 ) { + in16 >>= 12; + } else { + out32 += 4; + in16 >>= 8; + } + } else { + if( in16 & 0xFFF0 ) { + out32 += 8; + in16 >>= 4; + } else { + out32 += 12; + } + } + /* test bits and return */ + if( in16 & 0xC ) { + if( in16 & 0x8 ) + return out32 + 0; + else + return out32 + 1; + } else { + if( in16 & 0xE ) + return out32 + 2; + else + return out32 + 3; + } +} + +SKP_INLINE opus_int32 silk_CLZ32(opus_int32 in32) +{ + /* test highest 16 bits and convert to opus_int16 */ + if( in32 & 0xFFFF0000 ) { + return silk_CLZ16((opus_int16)(in32 >> 16)); + } else { + return silk_CLZ16((opus_int16)in32) + 16; + } +} + +/* Row based */ +#define matrix_ptr(Matrix_base_adr, row, column, N) *(Matrix_base_adr + ((row)*(N)+(column))) +#define matrix_adr(Matrix_base_adr, row, column, N) (Matrix_base_adr + ((row)*(N)+(column))) + +/* Column based */ +#ifndef matrix_c_ptr +# define matrix_c_ptr(Matrix_base_adr, row, column, M) *(Matrix_base_adr + ((row)+(M)*(column))) +#endif +#define matrix_c_adr(Matrix_base_adr, row, column, M) (Matrix_base_adr + ((row)+(M)*(column))) + +#endif //_SILK_API_C_H_ + diff --git a/silk/silk_main.h b/silk/silk_main.h index 68a79be2a..92d07177b 100644 --- a/silk/silk_main.h +++ b/silk/silk_main.h @@ -1,446 +1,446 @@ -/*********************************************************************** -Copyright (c) 2006-2011, Skype Limited. All rights reserved. -Redistribution and use in source and binary forms, with or without -modification, (subject to the limitations in the disclaimer below) -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 Skype Limited, nor the names of specific -contributors, may be used to endorse or promote products derived from -this software without specific prior written permission. -NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED -BY THIS LICENSE. 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. -***********************************************************************/ - -#ifndef SILK_MAIN_H -#define SILK_MAIN_H - -#ifdef __cplusplus -extern "C" -{ -#endif - -#include "silk_SigProc_FIX.h" -#include "silk_define.h" -#include "silk_structs.h" -#include "silk_tables.h" -#include "silk_PLC.h" -#include "silk_control.h" -#include "silk_debug.h" -#include "entenc.h" -#include "entdec.h" - - -/* Uncomment the next line to store intermadiate data to files */ -//#define SAVE_ALL_INTERNAL_DATA 1 -/* Uncomment the next line to force a fixed internal sampling rate (independent of what bitrate is used */ -//#define FORCE_INTERNAL_FS_KHZ 16 - - -/* Convert Left/Right stereo signal to adaptive Mid/Side representation */ -void silk_stereo_LR_to_MS( - stereo_enc_state *state, /* I/O State */ - opus_int16 x1[], /* I/O Left input signal, becomes mid signal */ - opus_int16 x2[], /* I/O Right input signal, becomes side signal */ - opus_int8 ix[ 2 ][ 4 ], /* O Quantization indices */ - opus_int32 mid_side_rates_bps[], /* O Bitrates for mid and side signals */ - opus_int32 total_rate_bps, /* I Total bitrate */ - opus_int prev_speech_act_Q8, /* I Speech activity level in previous frame */ - opus_int fs_kHz, /* I Sample rate (kHz) */ - opus_int frame_length /* I Number of samples */ -); - -/* Convert adaptive Mid/Side representation to Left/Right stereo signal */ -void silk_stereo_MS_to_LR( - stereo_dec_state *state, /* I/O State */ - opus_int16 x1[], /* I/O Left input signal, becomes mid signal */ - opus_int16 x2[], /* I/O Right input signal, becomes side signal */ - const opus_int32 pred_Q13[], /* I Predictors */ - opus_int fs_kHz, /* I Samples rate (kHz) */ - opus_int frame_length /* I Number of samples */ -); - -/* Find least-squares prediction gain for one signal based on another and quantize it */ -opus_int32 silk_stereo_find_predictor( /* O Returns predictor in Q13 */ - opus_int32 *ratio_Q14, /* O Ratio of residual and mid energies */ - const opus_int16 x[], /* I Basis signal */ - const opus_int16 y[], /* I Target signal */ - opus_int32 mid_res_amp_Q0[], /* I/O Smoothed mid, residual norms */ - opus_int length, /* I Number of samples */ - opus_int smooth_coef_Q16 /* I Smoothing coefficient */ -); - -/* Quantize mid/side predictors */ -void silk_stereo_quant_pred( - stereo_enc_state *state, /* I/O State */ - opus_int32 pred_Q13[], /* I/O Predictors (out: quantized) */ - opus_int8 ix[ 2 ][ 4 ] /* O Quantization indices */ -); - -/* Entropy code the mid/side quantization indices */ -void silk_stereo_encode_pred( - ec_enc *psRangeEnc, /* I/O Compressor data structure */ - opus_int8 ix[ 2 ][ 4 ] /* I Quantization indices */ -); - -/* Decode mid/side predictors */ -void silk_stereo_decode_pred( - ec_dec *psRangeDec, /* I/O Compressor data structure */ - opus_int *decode_only_mid, /* O Flag that only mid channel has been coded */ - opus_int32 pred_Q13[] /* O Predictors */ -); - -/* Encodes signs of excitation */ -void silk_encode_signs( - ec_enc *psRangeEnc, /* I/O Compressor data structure */ - const opus_int8 pulses[], /* I pulse signal */ - opus_int length, /* I length of input */ - const opus_int signalType, /* I Signal type */ - const opus_int quantOffsetType, /* I Quantization offset type */ - const opus_int sum_pulses[ MAX_NB_SHELL_BLOCKS ] /* I Sum of absolute pulses per block */ -); - -/* Decodes signs of excitation */ -void silk_decode_signs( - ec_dec *psRangeDec, /* I/O Compressor data structure */ - opus_int pulses[], /* I/O pulse signal */ - opus_int length, /* I length of input */ - const opus_int signalType, /* I Signal type */ - const opus_int quantOffsetType, /* I Quantization offset type */ - const opus_int sum_pulses[ MAX_NB_SHELL_BLOCKS ] /* I Sum of absolute pulses per block */ -); - -/* Check encoder control struct */ -opus_int check_control_input( - silk_EncControlStruct *encControl /* I: Control structure */ -); - -/* Control internal sampling rate */ -opus_int silk_control_audio_bandwidth( - silk_encoder_state *psEncC /* I/O Pointer to Silk encoder state */ -); - -/* Control SNR of redidual quantizer */ -opus_int silk_control_SNR( - silk_encoder_state *psEncC, /* I/O Pointer to Silk encoder state */ - opus_int32 TargetRate_bps /* I Target max bitrate (bps) */ -); - -/***************/ -/* Shell coder */ -/***************/ - -/* Encode quantization indices of excitation */ -void silk_encode_pulses( - ec_enc *psRangeEnc, /* I/O compressor data structure */ - const opus_int signalType, /* I Signal type */ - const opus_int quantOffsetType, /* I quantOffsetType */ - opus_int8 pulses[], /* I quantization indices */ - const opus_int frame_length /* I Frame length */ -); - -/* Shell encoder, operates on one shell code frame of 16 pulses */ -void silk_shell_encoder( - ec_enc *psRangeEnc, /* I/O compressor data structure */ - const opus_int *pulses0 /* I data: nonnegative pulse amplitudes */ -); - -/* Shell decoder, operates on one shell code frame of 16 pulses */ -void silk_shell_decoder( - opus_int *pulses0, /* O data: nonnegative pulse amplitudes */ - ec_dec *psRangeDec, /* I/O Compressor data structure */ - const opus_int pulses4 /* I number of pulses per pulse-subframe */ -); - -/* Gain scalar quantization with hysteresis, uniform on log scale */ -void silk_gains_quant( - opus_int8 ind[ MAX_NB_SUBFR ], /* O gain indices */ - opus_int32 gain_Q16[ MAX_NB_SUBFR ], /* I/O gains (quantized out) */ - opus_int8 *prev_ind, /* I/O last index in previous frame */ - const opus_int conditional, /* I first gain is delta coded if 1 */ - const opus_int nb_subfr /* I number of subframes */ -); - -/* Gains scalar dequantization, uniform on log scale */ -void silk_gains_dequant( - opus_int32 gain_Q16[ MAX_NB_SUBFR ], /* O quantized gains */ - const opus_int8 ind[ MAX_NB_SUBFR ], /* I gain indices */ - opus_int8 *prev_ind, /* I/O last index in previous frame */ - const opus_int conditional, /* I first gain is delta coded if 1 */ - const opus_int nb_subfr /* I number of subframes */ -); - -/* Interpolate two vectors */ -void silk_interpolate( - opus_int16 xi[ MAX_LPC_ORDER ], /* O interpolated vector */ - const opus_int16 x0[ MAX_LPC_ORDER ], /* I first vector */ - const opus_int16 x1[ MAX_LPC_ORDER ], /* I second vector */ - const opus_int ifact_Q2, /* I interp. factor, weight on 2nd vector */ - const opus_int d /* I number of parameters */ -); - -/* LTP tap quantizer */ -void silk_quant_LTP_gains( - opus_int16 B_Q14[ MAX_NB_SUBFR * LTP_ORDER ], /* I/O (un)quantized LTP gains */ - opus_int8 cbk_index[ MAX_NB_SUBFR ], /* O Codebook Index */ - opus_int8 *periodicity_index, /* O Periodicity Index */ - const opus_int32 W_Q18[ MAX_NB_SUBFR*LTP_ORDER*LTP_ORDER ], /* I Error Weights in Q18 */ - opus_int mu_Q9, /* I Mu value (R/D tradeoff) */ - opus_int lowComplexity, /* I Flag for low complexity */ - const opus_int nb_subfr /* I number of subframes */ -); - -/* Entropy constrained matrix-weighted VQ, for a single input data vector */ -void silk_VQ_WMat_EC( - opus_int8 *ind, /* O index of best codebook vector */ - opus_int32 *rate_dist_Q14, /* O best weighted quantization error + mu * rate*/ - const opus_int16 *in_Q14, /* I input vector to be quantized */ - const opus_int32 *W_Q18, /* I weighting matrix */ - const opus_int8 *cb_Q7, /* I codebook */ - const opus_uint8 *cl_Q5, /* I code length for each codebook vector */ - const opus_int mu_Q9, /* I tradeoff between weighted error and rate */ - opus_int L /* I number of vectors in codebook */ -); - -/***********************************/ -/* Noise shaping quantization (NSQ)*/ -/***********************************/ -void silk_NSQ( - const silk_encoder_state *psEncC, /* I/O Encoder State */ - silk_nsq_state *NSQ, /* I/O NSQ state */ - SideInfoIndices *psIndices, /* I/O Quantization Indices */ - const opus_int16 x[], /* I prefiltered input signal */ - opus_int8 pulses[], /* O quantized qulse signal */ - const opus_int16 PredCoef_Q12[ 2 * MAX_LPC_ORDER ], /* I Short term prediction coefficients */ - const opus_int16 LTPCoef_Q14[ LTP_ORDER * MAX_NB_SUBFR ], /* I Long term prediction coefficients */ - const opus_int16 AR2_Q13[ MAX_NB_SUBFR * MAX_SHAPE_LPC_ORDER ], /* I */ - const opus_int HarmShapeGain_Q14[ MAX_NB_SUBFR ], /* I */ - const opus_int Tilt_Q14[ MAX_NB_SUBFR ], /* I Spectral tilt */ - const opus_int32 LF_shp_Q14[ MAX_NB_SUBFR ], /* I */ - const opus_int32 Gains_Q16[ MAX_NB_SUBFR ], /* I */ - const opus_int pitchL[ MAX_NB_SUBFR ], /* I */ - const opus_int Lambda_Q10, /* I */ - const opus_int LTP_scale_Q14 /* I LTP state scaling */ -); - -/* Noise shaping using delayed decision */ -void silk_NSQ_del_dec( - const silk_encoder_state *psEncC, /* I/O Encoder State */ - silk_nsq_state *NSQ, /* I/O NSQ state */ - SideInfoIndices *psIndices, /* I/O Quantization Indices */ - const opus_int16 x[], /* I Prefiltered input signal */ - opus_int8 pulses[], /* O Quantized pulse signal */ - const opus_int16 PredCoef_Q12[ 2 * MAX_LPC_ORDER ], /* I Prediction coefs */ - const opus_int16 LTPCoef_Q14[ LTP_ORDER * MAX_NB_SUBFR ], /* I LT prediction coefs */ - const opus_int16 AR2_Q13[ MAX_NB_SUBFR * MAX_SHAPE_LPC_ORDER ], /* I */ - const opus_int HarmShapeGain_Q14[ MAX_NB_SUBFR ], /* I */ - const opus_int Tilt_Q14[ MAX_NB_SUBFR ], /* I Spectral tilt */ - const opus_int32 LF_shp_Q14[ MAX_NB_SUBFR ], /* I */ - const opus_int32 Gains_Q16[ MAX_NB_SUBFR ], /* I */ - const opus_int pitchL[ MAX_NB_SUBFR ], /* I */ - const opus_int Lambda_Q10, /* I */ - const opus_int LTP_scale_Q14 /* I LTP state scaling */ -); - -/************/ -/* Silk VAD */ -/************/ -/* Initialize the Silk VAD */ -opus_int silk_VAD_Init( /* O Return value, 0 if success */ - silk_VAD_state *psSilk_VAD /* I/O Pointer to Silk VAD state */ -); - -/* Silk VAD noise level estimation */ -void silk_VAD_GetNoiseLevels( - const opus_int32 pX[ VAD_N_BANDS ], /* I subband energies */ - silk_VAD_state *psSilk_VAD /* I/O Pointer to Silk VAD state */ -); - -/* Get speech activity level in Q8 */ -opus_int silk_VAD_GetSA_Q8( /* O Return value, 0 if success */ - silk_encoder_state *psEncC, /* I/O Encoder state */ - const opus_int16 pIn[] /* I PCM input */ -); - -/* Low-pass filter with variable cutoff frequency based on */ -/* piece-wise linear interpolation between elliptic filters */ -/* Start by setting transition_frame_no = 1; */ -void silk_LP_variable_cutoff( - silk_LP_state *psLP, /* I/O LP filter state */ - opus_int16 *signal, /* I/O Low-pass filtered output signal */ - const opus_int frame_length /* I Frame length */ -); - -/******************/ -/* NLSF Quantizer */ -/******************/ -/* Limit, stabilize, convert and quantize NLSFs */ -void silk_process_NLSFs( - silk_encoder_state *psEncC, /* I/O Encoder state */ - opus_int16 PredCoef_Q12[ 2 ][ MAX_LPC_ORDER ], /* O Prediction coefficients */ - opus_int16 pNLSF_Q15[ MAX_LPC_ORDER ], /* I/O Normalized LSFs (quant out) (0 - (2^15-1)) */ - const opus_int16 prev_NLSFq_Q15[ MAX_LPC_ORDER ] /* I Previous Normalized LSFs (0 - (2^15-1)) */ -); - -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 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_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 */ -); - -/* Compute quantization errors for an LPC_order element input vector for a VQ codebook */ -void silk_NLSF_VQ( - opus_int32 err_Q26[], /* O Quantization errors [K] */ - const opus_int16 in_Q15[], /* I Input vectors to be quantized [LPC_order] */ - const opus_uint8 pCB_Q8[], /* I Codebook vectors [K*LPC_order] */ - const opus_int K, /* I Number of codebook vectors */ - const opus_int LPC_order /* I Number of LPCs */ -); - -/* 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 ] */ - 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 ] */ - const opus_int16 ec_ix[], /* I Indices to entropy coding tables [ order ] */ - const opus_uint8 ec_rates_Q5[], /* I Rates [] */ - const opus_int quant_step_size_Q16, /* I Quantization step size */ - const opus_int16 inv_quant_step_size_Q6, /* I Inverse quantization step size */ - const opus_int32 mu_Q20, /* I R/D tradeoff */ - const opus_int16 order /* I Number of input values */ -); - -/* 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_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 */ -); - -/***********************/ -/* NLSF vector decoder */ -/***********************/ -void silk_NLSF_decode( - opus_int16 *pNLSF_Q15, /* O Quantized NLSF vector [ LPC_ORDER ] */ - opus_int8 *NLSFIndices, /* I Codebook path vector [ LPC_ORDER + 1 ] */ - const silk_NLSF_CB_struct *psNLSF_CB /* I Codebook object */ -); - -/****************************************************/ -/* Decoder Functions */ -/****************************************************/ -opus_int silk_create_decoder( - silk_decoder_state **ppsDec /* I/O Decoder state pointer pointer */ -); - -opus_int silk_free_decoder( - silk_decoder_state *psDec /* I/O Decoder state pointer */ -); - -opus_int silk_init_decoder( - silk_decoder_state *psDec /* I/O Decoder state pointer */ -); - -/* Set decoder sampling rate */ -void silk_decoder_set_fs( - silk_decoder_state *psDec, /* I/O Decoder state pointer */ - opus_int fs_kHz /* I Sampling frequency (kHz) */ -); - -/****************/ -/* Decode frame */ -/****************/ -opus_int silk_decode_frame( - silk_decoder_state *psDec, /* I/O Pointer to Silk decoder state */ - ec_dec *psRangeDec, /* I/O Compressor data structure */ - opus_int16 pOut[], /* O Pointer to output speech frame */ - opus_int32 *pN, /* O Pointer to size of output frame */ - opus_int lostFlag /* I 0: no loss, 1 loss, 2 decode fec */ -); - -/* Decode LBRR side info and excitation */ -void silk_LBRR_extract( - silk_decoder_state *psDec, /* I/O State */ - ec_dec *psRangeDec /* I/O Compressor data structure */ -); - -/* Decode indices from payload v4 Bitstream */ -void silk_decode_indices( - silk_decoder_state *psDec, /* I/O State */ - ec_dec *psRangeDec, /* I/O Compressor data structure */ - opus_int FrameIndex, /* I Frame number */ - opus_int decode_LBRR /* I Flag indicating LBRR data is being decoded */ -); - -/* Decode parameters from payload */ -void silk_decode_parameters( - silk_decoder_state *psDec, /* I/O State */ - silk_decoder_control *psDecCtrl /* I/O Decoder control */ -); - -/* Core decoder. Performs inverse NSQ operation LTP + LPC */ -void silk_decode_core( - silk_decoder_state *psDec, /* I/O Decoder state */ - silk_decoder_control *psDecCtrl, /* I Decoder control */ - opus_int16 xq[], /* O Decoded speech */ - const opus_int pulses[ MAX_FRAME_LENGTH ] /* I Pulse signal */ -); - -/* Decode quantization indices of excitation (Shell coding) */ -void silk_decode_pulses( - ec_dec *psRangeDec, /* I/O Compressor data structure */ - opus_int pulses[], /* O Excitation signal */ - const opus_int signalType, /* I Sigtype */ - const opus_int quantOffsetType, /* I quantOffsetType */ - const opus_int frame_length /* I Frame length */ -); - -/******************/ -/* CNG */ -/******************/ - -/* Reset CNG */ -void silk_CNG_Reset( - silk_decoder_state *psDec /* I/O Decoder state */ -); - -/* Updates CNG estimate, and applies the CNG when packet was lost */ -void silk_CNG( - silk_decoder_state *psDec, /* I/O Decoder state */ - silk_decoder_control *psDecCtrl, /* I/O Decoder control */ - opus_int16 signal[], /* I/O Signal */ - opus_int length /* I Length of residual */ -); - -/* Encoding of various parameters */ -void silk_encode_indices( - silk_encoder_state *psEncC, /* I/O Encoder state */ - ec_enc *psRangeEnc, /* I/O Compressor data structure */ - opus_int FrameIndex, /* I Frame number */ - opus_int encode_LBRR /* I Flag indicating LBRR data is being encoded */ -); - -#ifdef __cplusplus -} -#endif - -#endif +/*********************************************************************** +Copyright (c) 2006-2011, Skype Limited. All rights reserved. +Redistribution and use in source and binary forms, with or without +modification, (subject to the limitations in the disclaimer below) +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 Skype Limited, nor the names of specific +contributors, may be used to endorse or promote products derived from +this software without specific prior written permission. +NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED +BY THIS LICENSE. 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. +***********************************************************************/ + +#ifndef SILK_MAIN_H +#define SILK_MAIN_H + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include "silk_SigProc_FIX.h" +#include "silk_define.h" +#include "silk_structs.h" +#include "silk_tables.h" +#include "silk_PLC.h" +#include "silk_control.h" +#include "silk_debug.h" +#include "entenc.h" +#include "entdec.h" + + +/* Uncomment the next line to store intermadiate data to files */ +//#define SAVE_ALL_INTERNAL_DATA 1 +/* Uncomment the next line to force a fixed internal sampling rate (independent of what bitrate is used */ +//#define FORCE_INTERNAL_FS_KHZ 16 + + +/* Convert Left/Right stereo signal to adaptive Mid/Side representation */ +void silk_stereo_LR_to_MS( + stereo_enc_state *state, /* I/O State */ + opus_int16 x1[], /* I/O Left input signal, becomes mid signal */ + opus_int16 x2[], /* I/O Right input signal, becomes side signal */ + opus_int8 ix[ 2 ][ 4 ], /* O Quantization indices */ + opus_int32 mid_side_rates_bps[], /* O Bitrates for mid and side signals */ + opus_int32 total_rate_bps, /* I Total bitrate */ + opus_int prev_speech_act_Q8, /* I Speech activity level in previous frame */ + opus_int fs_kHz, /* I Sample rate (kHz) */ + opus_int frame_length /* I Number of samples */ +); + +/* Convert adaptive Mid/Side representation to Left/Right stereo signal */ +void silk_stereo_MS_to_LR( + stereo_dec_state *state, /* I/O State */ + opus_int16 x1[], /* I/O Left input signal, becomes mid signal */ + opus_int16 x2[], /* I/O Right input signal, becomes side signal */ + const opus_int32 pred_Q13[], /* I Predictors */ + opus_int fs_kHz, /* I Samples rate (kHz) */ + opus_int frame_length /* I Number of samples */ +); + +/* Find least-squares prediction gain for one signal based on another and quantize it */ +opus_int32 silk_stereo_find_predictor( /* O Returns predictor in Q13 */ + opus_int32 *ratio_Q14, /* O Ratio of residual and mid energies */ + const opus_int16 x[], /* I Basis signal */ + const opus_int16 y[], /* I Target signal */ + opus_int32 mid_res_amp_Q0[], /* I/O Smoothed mid, residual norms */ + opus_int length, /* I Number of samples */ + opus_int smooth_coef_Q16 /* I Smoothing coefficient */ +); + +/* Quantize mid/side predictors */ +void silk_stereo_quant_pred( + stereo_enc_state *state, /* I/O State */ + opus_int32 pred_Q13[], /* I/O Predictors (out: quantized) */ + opus_int8 ix[ 2 ][ 4 ] /* O Quantization indices */ +); + +/* Entropy code the mid/side quantization indices */ +void silk_stereo_encode_pred( + ec_enc *psRangeEnc, /* I/O Compressor data structure */ + opus_int8 ix[ 2 ][ 4 ] /* I Quantization indices */ +); + +/* Decode mid/side predictors */ +void silk_stereo_decode_pred( + ec_dec *psRangeDec, /* I/O Compressor data structure */ + opus_int *decode_only_mid, /* O Flag that only mid channel has been coded */ + opus_int32 pred_Q13[] /* O Predictors */ +); + +/* Encodes signs of excitation */ +void silk_encode_signs( + ec_enc *psRangeEnc, /* I/O Compressor data structure */ + const opus_int8 pulses[], /* I pulse signal */ + opus_int length, /* I length of input */ + const opus_int signalType, /* I Signal type */ + const opus_int quantOffsetType, /* I Quantization offset type */ + const opus_int sum_pulses[ MAX_NB_SHELL_BLOCKS ] /* I Sum of absolute pulses per block */ +); + +/* Decodes signs of excitation */ +void silk_decode_signs( + ec_dec *psRangeDec, /* I/O Compressor data structure */ + opus_int pulses[], /* I/O pulse signal */ + opus_int length, /* I length of input */ + const opus_int signalType, /* I Signal type */ + const opus_int quantOffsetType, /* I Quantization offset type */ + const opus_int sum_pulses[ MAX_NB_SHELL_BLOCKS ] /* I Sum of absolute pulses per block */ +); + +/* Check encoder control struct */ +opus_int check_control_input( + silk_EncControlStruct *encControl /* I: Control structure */ +); + +/* Control internal sampling rate */ +opus_int silk_control_audio_bandwidth( + silk_encoder_state *psEncC /* I/O Pointer to Silk encoder state */ +); + +/* Control SNR of redidual quantizer */ +opus_int silk_control_SNR( + silk_encoder_state *psEncC, /* I/O Pointer to Silk encoder state */ + opus_int32 TargetRate_bps /* I Target max bitrate (bps) */ +); + +/***************/ +/* Shell coder */ +/***************/ + +/* Encode quantization indices of excitation */ +void silk_encode_pulses( + ec_enc *psRangeEnc, /* I/O compressor data structure */ + const opus_int signalType, /* I Signal type */ + const opus_int quantOffsetType, /* I quantOffsetType */ + opus_int8 pulses[], /* I quantization indices */ + const opus_int frame_length /* I Frame length */ +); + +/* Shell encoder, operates on one shell code frame of 16 pulses */ +void silk_shell_encoder( + ec_enc *psRangeEnc, /* I/O compressor data structure */ + const opus_int *pulses0 /* I data: nonnegative pulse amplitudes */ +); + +/* Shell decoder, operates on one shell code frame of 16 pulses */ +void silk_shell_decoder( + opus_int *pulses0, /* O data: nonnegative pulse amplitudes */ + ec_dec *psRangeDec, /* I/O Compressor data structure */ + const opus_int pulses4 /* I number of pulses per pulse-subframe */ +); + +/* Gain scalar quantization with hysteresis, uniform on log scale */ +void silk_gains_quant( + opus_int8 ind[ MAX_NB_SUBFR ], /* O gain indices */ + opus_int32 gain_Q16[ MAX_NB_SUBFR ], /* I/O gains (quantized out) */ + opus_int8 *prev_ind, /* I/O last index in previous frame */ + const opus_int conditional, /* I first gain is delta coded if 1 */ + const opus_int nb_subfr /* I number of subframes */ +); + +/* Gains scalar dequantization, uniform on log scale */ +void silk_gains_dequant( + opus_int32 gain_Q16[ MAX_NB_SUBFR ], /* O quantized gains */ + const opus_int8 ind[ MAX_NB_SUBFR ], /* I gain indices */ + opus_int8 *prev_ind, /* I/O last index in previous frame */ + const opus_int conditional, /* I first gain is delta coded if 1 */ + const opus_int nb_subfr /* I number of subframes */ +); + +/* Interpolate two vectors */ +void silk_interpolate( + opus_int16 xi[ MAX_LPC_ORDER ], /* O interpolated vector */ + const opus_int16 x0[ MAX_LPC_ORDER ], /* I first vector */ + const opus_int16 x1[ MAX_LPC_ORDER ], /* I second vector */ + const opus_int ifact_Q2, /* I interp. factor, weight on 2nd vector */ + const opus_int d /* I number of parameters */ +); + +/* LTP tap quantizer */ +void silk_quant_LTP_gains( + opus_int16 B_Q14[ MAX_NB_SUBFR * LTP_ORDER ], /* I/O (un)quantized LTP gains */ + opus_int8 cbk_index[ MAX_NB_SUBFR ], /* O Codebook Index */ + opus_int8 *periodicity_index, /* O Periodicity Index */ + const opus_int32 W_Q18[ MAX_NB_SUBFR*LTP_ORDER*LTP_ORDER ], /* I Error Weights in Q18 */ + opus_int mu_Q9, /* I Mu value (R/D tradeoff) */ + opus_int lowComplexity, /* I Flag for low complexity */ + const opus_int nb_subfr /* I number of subframes */ +); + +/* Entropy constrained matrix-weighted VQ, for a single input data vector */ +void silk_VQ_WMat_EC( + opus_int8 *ind, /* O index of best codebook vector */ + opus_int32 *rate_dist_Q14, /* O best weighted quantization error + mu * rate*/ + const opus_int16 *in_Q14, /* I input vector to be quantized */ + const opus_int32 *W_Q18, /* I weighting matrix */ + const opus_int8 *cb_Q7, /* I codebook */ + const opus_uint8 *cl_Q5, /* I code length for each codebook vector */ + const opus_int mu_Q9, /* I tradeoff between weighted error and rate */ + opus_int L /* I number of vectors in codebook */ +); + +/***********************************/ +/* Noise shaping quantization (NSQ)*/ +/***********************************/ +void silk_NSQ( + const silk_encoder_state *psEncC, /* I/O Encoder State */ + silk_nsq_state *NSQ, /* I/O NSQ state */ + SideInfoIndices *psIndices, /* I/O Quantization Indices */ + const opus_int16 x[], /* I prefiltered input signal */ + opus_int8 pulses[], /* O quantized qulse signal */ + const opus_int16 PredCoef_Q12[ 2 * MAX_LPC_ORDER ], /* I Short term prediction coefficients */ + const opus_int16 LTPCoef_Q14[ LTP_ORDER * MAX_NB_SUBFR ], /* I Long term prediction coefficients */ + const opus_int16 AR2_Q13[ MAX_NB_SUBFR * MAX_SHAPE_LPC_ORDER ], /* I */ + const opus_int HarmShapeGain_Q14[ MAX_NB_SUBFR ], /* I */ + const opus_int Tilt_Q14[ MAX_NB_SUBFR ], /* I Spectral tilt */ + const opus_int32 LF_shp_Q14[ MAX_NB_SUBFR ], /* I */ + const opus_int32 Gains_Q16[ MAX_NB_SUBFR ], /* I */ + const opus_int pitchL[ MAX_NB_SUBFR ], /* I */ + const opus_int Lambda_Q10, /* I */ + const opus_int LTP_scale_Q14 /* I LTP state scaling */ +); + +/* Noise shaping using delayed decision */ +void silk_NSQ_del_dec( + const silk_encoder_state *psEncC, /* I/O Encoder State */ + silk_nsq_state *NSQ, /* I/O NSQ state */ + SideInfoIndices *psIndices, /* I/O Quantization Indices */ + const opus_int16 x[], /* I Prefiltered input signal */ + opus_int8 pulses[], /* O Quantized pulse signal */ + const opus_int16 PredCoef_Q12[ 2 * MAX_LPC_ORDER ], /* I Prediction coefs */ + const opus_int16 LTPCoef_Q14[ LTP_ORDER * MAX_NB_SUBFR ], /* I LT prediction coefs */ + const opus_int16 AR2_Q13[ MAX_NB_SUBFR * MAX_SHAPE_LPC_ORDER ], /* I */ + const opus_int HarmShapeGain_Q14[ MAX_NB_SUBFR ], /* I */ + const opus_int Tilt_Q14[ MAX_NB_SUBFR ], /* I Spectral tilt */ + const opus_int32 LF_shp_Q14[ MAX_NB_SUBFR ], /* I */ + const opus_int32 Gains_Q16[ MAX_NB_SUBFR ], /* I */ + const opus_int pitchL[ MAX_NB_SUBFR ], /* I */ + const opus_int Lambda_Q10, /* I */ + const opus_int LTP_scale_Q14 /* I LTP state scaling */ +); + +/************/ +/* Silk VAD */ +/************/ +/* Initialize the Silk VAD */ +opus_int silk_VAD_Init( /* O Return value, 0 if success */ + silk_VAD_state *psSilk_VAD /* I/O Pointer to Silk VAD state */ +); + +/* Silk VAD noise level estimation */ +void silk_VAD_GetNoiseLevels( + const opus_int32 pX[ VAD_N_BANDS ], /* I subband energies */ + silk_VAD_state *psSilk_VAD /* I/O Pointer to Silk VAD state */ +); + +/* Get speech activity level in Q8 */ +opus_int silk_VAD_GetSA_Q8( /* O Return value, 0 if success */ + silk_encoder_state *psEncC, /* I/O Encoder state */ + const opus_int16 pIn[] /* I PCM input */ +); + +/* Low-pass filter with variable cutoff frequency based on */ +/* piece-wise linear interpolation between elliptic filters */ +/* Start by setting transition_frame_no = 1; */ +void silk_LP_variable_cutoff( + silk_LP_state *psLP, /* I/O LP filter state */ + opus_int16 *signal, /* I/O Low-pass filtered output signal */ + const opus_int frame_length /* I Frame length */ +); + +/******************/ +/* NLSF Quantizer */ +/******************/ +/* Limit, stabilize, convert and quantize NLSFs */ +void silk_process_NLSFs( + silk_encoder_state *psEncC, /* I/O Encoder state */ + opus_int16 PredCoef_Q12[ 2 ][ MAX_LPC_ORDER ], /* O Prediction coefficients */ + opus_int16 pNLSF_Q15[ MAX_LPC_ORDER ], /* I/O Normalized LSFs (quant out) (0 - (2^15-1)) */ + const opus_int16 prev_NLSFq_Q15[ MAX_LPC_ORDER ] /* I Previous Normalized LSFs (0 - (2^15-1)) */ +); + +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 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_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 */ +); + +/* Compute quantization errors for an LPC_order element input vector for a VQ codebook */ +void silk_NLSF_VQ( + opus_int32 err_Q26[], /* O Quantization errors [K] */ + const opus_int16 in_Q15[], /* I Input vectors to be quantized [LPC_order] */ + const opus_uint8 pCB_Q8[], /* I Codebook vectors [K*LPC_order] */ + const opus_int K, /* I Number of codebook vectors */ + const opus_int LPC_order /* I Number of LPCs */ +); + +/* 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 ] */ + 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 ] */ + const opus_int16 ec_ix[], /* I Indices to entropy coding tables [ order ] */ + const opus_uint8 ec_rates_Q5[], /* I Rates [] */ + const opus_int quant_step_size_Q16, /* I Quantization step size */ + const opus_int16 inv_quant_step_size_Q6, /* I Inverse quantization step size */ + const opus_int32 mu_Q20, /* I R/D tradeoff */ + const opus_int16 order /* I Number of input values */ +); + +/* 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_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 */ +); + +/***********************/ +/* NLSF vector decoder */ +/***********************/ +void silk_NLSF_decode( + opus_int16 *pNLSF_Q15, /* O Quantized NLSF vector [ LPC_ORDER ] */ + opus_int8 *NLSFIndices, /* I Codebook path vector [ LPC_ORDER + 1 ] */ + const silk_NLSF_CB_struct *psNLSF_CB /* I Codebook object */ +); + +/****************************************************/ +/* Decoder Functions */ +/****************************************************/ +opus_int silk_create_decoder( + silk_decoder_state **ppsDec /* I/O Decoder state pointer pointer */ +); + +opus_int silk_free_decoder( + silk_decoder_state *psDec /* I/O Decoder state pointer */ +); + +opus_int silk_init_decoder( + silk_decoder_state *psDec /* I/O Decoder state pointer */ +); + +/* Set decoder sampling rate */ +void silk_decoder_set_fs( + silk_decoder_state *psDec, /* I/O Decoder state pointer */ + opus_int fs_kHz /* I Sampling frequency (kHz) */ +); + +/****************/ +/* Decode frame */ +/****************/ +opus_int silk_decode_frame( + silk_decoder_state *psDec, /* I/O Pointer to Silk decoder state */ + ec_dec *psRangeDec, /* I/O Compressor data structure */ + opus_int16 pOut[], /* O Pointer to output speech frame */ + opus_int32 *pN, /* O Pointer to size of output frame */ + opus_int lostFlag /* I 0: no loss, 1 loss, 2 decode fec */ +); + +/* Decode LBRR side info and excitation */ +void silk_LBRR_extract( + silk_decoder_state *psDec, /* I/O State */ + ec_dec *psRangeDec /* I/O Compressor data structure */ +); + +/* Decode indices from payload v4 Bitstream */ +void silk_decode_indices( + silk_decoder_state *psDec, /* I/O State */ + ec_dec *psRangeDec, /* I/O Compressor data structure */ + opus_int FrameIndex, /* I Frame number */ + opus_int decode_LBRR /* I Flag indicating LBRR data is being decoded */ +); + +/* Decode parameters from payload */ +void silk_decode_parameters( + silk_decoder_state *psDec, /* I/O State */ + silk_decoder_control *psDecCtrl /* I/O Decoder control */ +); + +/* Core decoder. Performs inverse NSQ operation LTP + LPC */ +void silk_decode_core( + silk_decoder_state *psDec, /* I/O Decoder state */ + silk_decoder_control *psDecCtrl, /* I Decoder control */ + opus_int16 xq[], /* O Decoded speech */ + const opus_int pulses[ MAX_FRAME_LENGTH ] /* I Pulse signal */ +); + +/* Decode quantization indices of excitation (Shell coding) */ +void silk_decode_pulses( + ec_dec *psRangeDec, /* I/O Compressor data structure */ + opus_int pulses[], /* O Excitation signal */ + const opus_int signalType, /* I Sigtype */ + const opus_int quantOffsetType, /* I quantOffsetType */ + const opus_int frame_length /* I Frame length */ +); + +/******************/ +/* CNG */ +/******************/ + +/* Reset CNG */ +void silk_CNG_Reset( + silk_decoder_state *psDec /* I/O Decoder state */ +); + +/* Updates CNG estimate, and applies the CNG when packet was lost */ +void silk_CNG( + silk_decoder_state *psDec, /* I/O Decoder state */ + silk_decoder_control *psDecCtrl, /* I/O Decoder control */ + opus_int16 signal[], /* I/O Signal */ + opus_int length /* I Length of residual */ +); + +/* Encoding of various parameters */ +void silk_encode_indices( + silk_encoder_state *psEncC, /* I/O Encoder state */ + ec_enc *psRangeEnc, /* I/O Compressor data structure */ + opus_int FrameIndex, /* I Frame number */ + opus_int encode_LBRR /* I Flag indicating LBRR data is being encoded */ +); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/silk/silk_pitch_analysis_core.c b/silk/silk_pitch_analysis_core.c index df1c1bca8..1bc90d3cd 100644 --- a/silk/silk_pitch_analysis_core.c +++ b/silk/silk_pitch_analysis_core.c @@ -1,744 +1,744 @@ -/*********************************************************************** -Copyright (c) 2006-2011, Skype Limited. All rights reserved. -Redistribution and use in source and binary forms, with or without -modification, (subject to the limitations in the disclaimer below) -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 Skype Limited, nor the names of specific -contributors, may be used to endorse or promote products derived from -this software without specific prior written permission. -NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED -BY THIS LICENSE. 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. -***********************************************************************/ - -/*********************************************************** -* Pitch analyser function -********************************************************** */ -#include "silk_SigProc_FIX.h" -#include "silk_pitch_est_defines.h" -#include "silk_debug.h" - -#define SCRATCH_SIZE 22 - -/************************************************************/ -/* Internally used functions */ -/************************************************************/ -void silk_P_Ana_calc_corr_st3( - opus_int32 cross_corr_st3[ PE_MAX_NB_SUBFR ][ PE_NB_CBKS_STAGE3_MAX ][ PE_NB_STAGE3_LAGS ],/* (O) 3 DIM correlation array */ - const opus_int16 signal[], /* I vector to correlate */ - opus_int start_lag, /* I lag offset to search around */ - opus_int sf_length, /* I length of a 5 ms subframe */ - opus_int nb_subfr, /* I number of subframes */ - opus_int complexity /* I Complexity setting */ -); - -void silk_P_Ana_calc_energy_st3( - opus_int32 energies_st3[ PE_MAX_NB_SUBFR ][ PE_NB_CBKS_STAGE3_MAX ][ PE_NB_STAGE3_LAGS ],/* (O) 3 DIM energy array */ - const opus_int16 signal[], /* I vector to calc energy in */ - opus_int start_lag, /* I lag offset to search around */ - opus_int sf_length, /* I length of one 5 ms subframe */ - opus_int nb_subfr, /* I number of subframes */ - opus_int complexity /* I Complexity setting */ -); - -opus_int32 silk_P_Ana_find_scaling( - const opus_int16 *signal, - const opus_int signal_length, - const opus_int sum_sqr_len -); - -/*************************************************************/ -/* FIXED POINT CORE PITCH ANALYSIS FUNCTION */ -/*************************************************************/ -opus_int silk_pitch_analysis_core( /* O Voicing estimate: 0 voiced, 1 unvoiced */ - const opus_int16 *signal, /* I Signal of length PE_FRAME_LENGTH_MS*Fs_kHz */ - opus_int *pitch_out, /* O 4 pitch lag values */ - opus_int16 *lagIndex, /* O Lag Index */ - opus_int8 *contourIndex, /* O Pitch contour Index */ - opus_int *LTPCorr_Q15, /* I/O Normalized correlation; input: value from previous frame */ - opus_int prevLag, /* I Last lag of previous frame; set to zero is unvoiced */ - const opus_int32 search_thres1_Q16, /* I First stage threshold for lag candidates 0 - 1 */ - const opus_int search_thres2_Q15, /* I Final threshold for lag candidates 0 - 1 */ - const opus_int Fs_kHz, /* I Sample frequency (kHz) */ - const opus_int complexity, /* I Complexity setting, 0-2, where 2 is highest */ - const opus_int nb_subfr /* I number of 5 ms subframes */ -) -{ - opus_int16 signal_8kHz[ PE_MAX_FRAME_LENGTH_ST_2 ]; - opus_int16 signal_4kHz[ PE_MAX_FRAME_LENGTH_ST_1 ]; - opus_int32 filt_state[ 6 ]; - opus_int32 scratch_mem[ 3 * PE_MAX_FRAME_LENGTH ]; - opus_int16 *input_signal_ptr; - opus_int i, k, d, j; - opus_int16 C[ PE_MAX_NB_SUBFR ][ ( PE_MAX_LAG >> 1 ) + 5 ]; - const opus_int16 *target_ptr, *basis_ptr; - opus_int32 cross_corr, normalizer, energy, shift, energy_basis, energy_target; - opus_int d_srch[ PE_D_SRCH_LENGTH ], Cmax, length_d_srch, length_d_comp; - opus_int16 d_comp[ ( PE_MAX_LAG >> 1 ) + 5 ]; - opus_int32 sum, threshold, temp32, lag_counter; - opus_int CBimax, CBimax_new, CBimax_old, lag, start_lag, end_lag, lag_new; - opus_int32 CC[ PE_NB_CBKS_STAGE2_EXT ], CCmax, CCmax_b, CCmax_new_b, CCmax_new; - opus_int32 energies_st3[ PE_MAX_NB_SUBFR ][ PE_NB_CBKS_STAGE3_MAX ][ PE_NB_STAGE3_LAGS ]; - opus_int32 crosscorr_st3[ PE_MAX_NB_SUBFR ][ PE_NB_CBKS_STAGE3_MAX ][ PE_NB_STAGE3_LAGS ]; - opus_int frame_length, frame_length_8kHz, frame_length_4kHz, max_sum_sq_length; - opus_int sf_length, sf_length_8kHz, sf_length_4kHz; - opus_int min_lag, min_lag_8kHz, min_lag_4kHz; - opus_int max_lag, max_lag_8kHz, max_lag_4kHz; - opus_int32 contour_bias_Q20, diff, lz, lshift; - opus_int nb_cbk_search, cbk_size; - opus_int32 delta_lag_log2_sqr_Q7, lag_log2_Q7, prevLag_log2_Q7, prev_lag_bias_Q15, corr_thres_Q15; - const opus_int8 *Lag_CB_ptr; - /* Check for valid sampling frequency */ - SKP_assert( Fs_kHz == 8 || Fs_kHz == 12 || Fs_kHz == 16 ); - - /* Check for valid complexity setting */ - SKP_assert( complexity >= SILK_PE_MIN_COMPLEX ); - SKP_assert( complexity <= SILK_PE_MAX_COMPLEX ); - - SKP_assert( search_thres1_Q16 >= 0 && search_thres1_Q16 <= (1<<16) ); - SKP_assert( search_thres2_Q15 >= 0 && search_thres2_Q15 <= (1<<15) ); - - /* Setup 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; - sf_length = PE_SUBFR_LENGTH_MS * Fs_kHz; - sf_length_4kHz = PE_SUBFR_LENGTH_MS * 4; - sf_length_8kHz = PE_SUBFR_LENGTH_MS * 8; - min_lag = PE_MIN_LAG_MS * Fs_kHz; - min_lag_4kHz = PE_MIN_LAG_MS * 4; - min_lag_8kHz = PE_MIN_LAG_MS * 8; - max_lag = PE_MAX_LAG_MS * Fs_kHz - 1; - max_lag_4kHz = PE_MAX_LAG_MS * 4; - max_lag_8kHz = PE_MAX_LAG_MS * 8 - 1; - - SKP_memset( C, 0, sizeof( opus_int16 ) * nb_subfr * ( ( PE_MAX_LAG >> 1 ) + 5) ); - - /* Resample from input sampled at Fs_kHz to 8 kHz */ - if( Fs_kHz == 16 ) { - SKP_memset( filt_state, 0, 2 * sizeof( opus_int32 ) ); - silk_resampler_down2( filt_state, signal_8kHz, signal, frame_length ); - } else if ( Fs_kHz == 12 ) { - SKP_memset( filt_state, 0, 6 * sizeof( opus_int32 ) ); - silk_resampler_down2_3( filt_state, signal_8kHz, signal, frame_length ); - } else { - SKP_assert( Fs_kHz == 8 ); - SKP_memcpy( signal_8kHz, signal, frame_length_8kHz * sizeof(opus_int16) ); - } - - /* Decimate again to 4 kHz */ - SKP_memset( filt_state, 0, 2 * sizeof( opus_int32 ) );/* Set state to zero */ - silk_resampler_down2( filt_state, signal_4kHz, signal_8kHz, frame_length_8kHz ); - - /* Low-pass filter */ - for( i = frame_length_4kHz - 1; i > 0; i-- ) { - signal_4kHz[ i ] = SKP_ADD_SAT16( signal_4kHz[ i ], signal_4kHz[ i - 1 ] ); - } - - /******************************************************************************* - ** Scale 4 kHz signal down to prevent correlations measures from overflowing - ** find scaling as max scaling for each 8kHz(?) subframe - *******************************************************************************/ - - /* Inner product is calculated with different lengths, so scale for the worst case */ - max_sum_sq_length = SKP_max_32( sf_length_8kHz, SKP_LSHIFT( sf_length_4kHz, 2 ) ); - shift = silk_P_Ana_find_scaling( signal_4kHz, frame_length_4kHz, max_sum_sq_length ); - if( shift > 0 ) { - for( i = 0; i < frame_length_4kHz; i++ ) { - signal_4kHz[ i ] = SKP_RSHIFT( signal_4kHz[ i ], shift ); - } - } - - /****************************************************************************** - * FIRST STAGE, operating in 4 khz - ******************************************************************************/ - target_ptr = &signal_4kHz[ SKP_LSHIFT( sf_length_4kHz, 2 ) ]; - for( k = 0; k < nb_subfr >> 1; k++ ) { - /* Check that we are within range of the array */ - SKP_assert( target_ptr >= signal_4kHz ); - SKP_assert( target_ptr + sf_length_8kHz <= signal_4kHz + frame_length_4kHz ); - - basis_ptr = target_ptr - min_lag_4kHz; - - /* Check that we are within range of the array */ - SKP_assert( basis_ptr >= signal_4kHz ); - SKP_assert( basis_ptr + sf_length_8kHz <= signal_4kHz + frame_length_4kHz ); - - normalizer = 0; - cross_corr = 0; - /* Calculate first vector products before loop */ - cross_corr = silk_inner_prod_aligned( target_ptr, basis_ptr, sf_length_8kHz ); - normalizer = silk_inner_prod_aligned( basis_ptr, basis_ptr, sf_length_8kHz ); - normalizer = SKP_ADD_SAT32( normalizer, SKP_SMULBB( sf_length_8kHz, 4000 ) ); - - temp32 = SKP_DIV32( cross_corr, silk_SQRT_APPROX( normalizer ) + 1 ); - C[ k ][ min_lag_4kHz ] = (opus_int16)SKP_SAT16( temp32 ); /* Q0 */ - - /* From now on normalizer is computed recursively */ - for( d = min_lag_4kHz + 1; d <= max_lag_4kHz; d++ ) { - basis_ptr--; - - /* Check that we are within range of the array */ - SKP_assert( basis_ptr >= signal_4kHz ); - SKP_assert( basis_ptr + sf_length_8kHz <= signal_4kHz + frame_length_4kHz ); - - cross_corr = silk_inner_prod_aligned( target_ptr, basis_ptr, sf_length_8kHz ); - - /* Add contribution of new sample and remove contribution from oldest sample */ - normalizer += - SKP_SMULBB( basis_ptr[ 0 ], basis_ptr[ 0 ] ) - - SKP_SMULBB( basis_ptr[ sf_length_8kHz ], basis_ptr[ sf_length_8kHz ] ); - - temp32 = SKP_DIV32( cross_corr, silk_SQRT_APPROX( normalizer ) + 1 ); - C[ k ][ d ] = (opus_int16)SKP_SAT16( temp32 ); /* Q0 */ - } - /* Update target pointer */ - target_ptr += sf_length_8kHz; - } - - /* Combine two subframes into single correlation measure and apply short-lag bias */ - if( nb_subfr == PE_MAX_NB_SUBFR ) { - for( i = max_lag_4kHz; i >= min_lag_4kHz; i-- ) { - sum = (opus_int32)C[ 0 ][ i ] + (opus_int32)C[ 1 ][ i ]; /* Q0 */ - SKP_assert( SKP_RSHIFT( sum, 1 ) == SKP_SAT16( SKP_RSHIFT( sum, 1 ) ) ); - sum = SKP_RSHIFT( sum, 1 ); /* Q-1 */ - SKP_assert( SKP_LSHIFT( (opus_int32)-i, 4 ) == SKP_SAT16( SKP_LSHIFT( (opus_int32)-i, 4 ) ) ); - sum = SKP_SMLAWB( sum, sum, SKP_LSHIFT( -i, 4 ) ); /* Q-1 */ - SKP_assert( sum == SKP_SAT16( sum ) ); - C[ 0 ][ i ] = (opus_int16)sum; /* Q-1 */ - } - } else { - /* Only short-lag bias */ - for( i = max_lag_4kHz; i >= min_lag_4kHz; i-- ) { - sum = (opus_int32)C[ 0 ][ i ]; - sum = SKP_SMLAWB( sum, sum, SKP_LSHIFT( -i, 4 ) ); /* Q-1 */ - C[ 0 ][ i ] = (opus_int16)sum; /* Q-1 */ - } - } - - /* Sort */ - length_d_srch = SKP_ADD_LSHIFT32( 4, complexity, 1 ); - SKP_assert( 3 * length_d_srch <= PE_D_SRCH_LENGTH ); - silk_insertion_sort_decreasing_int16( &C[ 0 ][ min_lag_4kHz ], d_srch, max_lag_4kHz - min_lag_4kHz + 1, length_d_srch ); - - /* Escape if correlation is very low already here */ - target_ptr = &signal_4kHz[ SKP_SMULBB( sf_length_4kHz, nb_subfr ) ]; - energy = silk_inner_prod_aligned( target_ptr, target_ptr, SKP_LSHIFT( sf_length_4kHz, 2 ) ); - energy = SKP_ADD_SAT32( energy, 1000 ); /* Q0 */ - Cmax = (opus_int)C[ 0 ][ min_lag_4kHz ]; /* Q-1 */ - threshold = SKP_SMULBB( Cmax, Cmax ); /* Q-2 */ - - /* Compare in Q-2 domain */ - if( SKP_RSHIFT( energy, 4 + 2 ) > threshold ) { - SKP_memset( pitch_out, 0, nb_subfr * sizeof( opus_int ) ); - *LTPCorr_Q15 = 0; - *lagIndex = 0; - *contourIndex = 0; - return 1; - } - - threshold = SKP_SMULWB( search_thres1_Q16, Cmax ); - for( i = 0; i < length_d_srch; i++ ) { - /* Convert to 8 kHz indices for the sorted correlation that exceeds the threshold */ - if( C[ 0 ][ min_lag_4kHz + i ] > threshold ) { - d_srch[ i ] = SKP_LSHIFT( d_srch[ i ] + min_lag_4kHz, 1 ); - } else { - length_d_srch = i; - break; - } - } - SKP_assert( length_d_srch > 0 ); - - for( i = min_lag_8kHz - 5; i < max_lag_8kHz + 5; i++ ) { - d_comp[ i ] = 0; - } - for( i = 0; i < length_d_srch; i++ ) { - d_comp[ d_srch[ i ] ] = 1; - } - - /* Convolution */ - for( i = max_lag_8kHz + 3; i >= min_lag_8kHz; i-- ) { - d_comp[ i ] += d_comp[ i - 1 ] + d_comp[ i - 2 ]; - } - - length_d_srch = 0; - for( i = min_lag_8kHz; i < max_lag_8kHz + 1; i++ ) { - if( d_comp[ i + 1 ] > 0 ) { - d_srch[ length_d_srch ] = i; - length_d_srch++; - } - } - - /* Convolution */ - for( i = max_lag_8kHz + 3; i >= min_lag_8kHz; i-- ) { - d_comp[ i ] += d_comp[ i - 1 ] + d_comp[ i - 2 ] + d_comp[ i - 3 ]; - } - - length_d_comp = 0; - for( i = min_lag_8kHz; i < max_lag_8kHz + 4; i++ ) { - if( d_comp[ i ] > 0 ) { - d_comp[ length_d_comp ] = i - 2; - length_d_comp++; - } - } - - /********************************************************************************** - ** SECOND STAGE, operating at 8 kHz, on lag sections with high correlation - *************************************************************************************/ - - /****************************************************************************** - ** Scale signal down to avoid correlations measures from overflowing - *******************************************************************************/ - /* find scaling as max scaling for each subframe */ - shift = silk_P_Ana_find_scaling( signal_8kHz, frame_length_8kHz, sf_length_8kHz ); - if( shift > 0 ) { - for( i = 0; i < frame_length_8kHz; i++ ) { - signal_8kHz[ i ] = SKP_RSHIFT( signal_8kHz[ i ], shift ); - } - } - - /********************************************************************************* - * Find energy of each subframe projected onto its history, for a range of delays - *********************************************************************************/ - SKP_memset( C, 0, PE_MAX_NB_SUBFR * ( ( PE_MAX_LAG >> 1 ) + 5 ) * sizeof( opus_int16 ) ); - - target_ptr = &signal_8kHz[ PE_LTP_MEM_LENGTH_MS * 8 ]; - for( k = 0; k < nb_subfr; k++ ) { - - /* Check that we are within range of the array */ - SKP_assert( target_ptr >= signal_8kHz ); - SKP_assert( target_ptr + sf_length_8kHz <= signal_8kHz + frame_length_8kHz ); - - energy_target = silk_inner_prod_aligned( target_ptr, target_ptr, sf_length_8kHz ); - // ToDo: Calculate 1 / energy_target here and save one division inside next for loop - for( j = 0; j < length_d_comp; j++ ) { - d = d_comp[ j ]; - basis_ptr = target_ptr - d; - - /* Check that we are within range of the array */ - SKP_assert( basis_ptr >= signal_8kHz ); - SKP_assert( basis_ptr + sf_length_8kHz <= signal_8kHz + frame_length_8kHz ); - - cross_corr = silk_inner_prod_aligned( target_ptr, basis_ptr, sf_length_8kHz ); - energy_basis = silk_inner_prod_aligned( basis_ptr, basis_ptr, sf_length_8kHz ); - if( cross_corr > 0 ) { - energy = SKP_max( energy_target, energy_basis ); /* Find max to make sure first division < 1.0 */ - lz = silk_CLZ32( cross_corr ); - lshift = SKP_LIMIT_32( lz - 1, 0, 15 ); - temp32 = SKP_DIV32( SKP_LSHIFT( cross_corr, lshift ), SKP_RSHIFT( energy, 15 - lshift ) + 1 ); /* Q15 */ - SKP_assert( temp32 == SKP_SAT16( temp32 ) ); - temp32 = SKP_SMULWB( cross_corr, temp32 ); /* Q(-1), cc * ( cc / max(b, t) ) */ - temp32 = SKP_ADD_SAT32( temp32, temp32 ); /* Q(0) */ - lz = silk_CLZ32( temp32 ); - lshift = SKP_LIMIT_32( lz - 1, 0, 15 ); - energy = SKP_min( energy_target, energy_basis ); - C[ k ][ d ] = SKP_DIV32( SKP_LSHIFT( temp32, lshift ), SKP_RSHIFT( energy, 15 - lshift ) + 1 ); // Q15 - } else { - C[ k ][ d ] = 0; - } - } - target_ptr += sf_length_8kHz; - } - - /* search over lag range and lags codebook */ - /* scale factor for lag codebook, as a function of center lag */ - - CCmax = SKP_int32_MIN; - CCmax_b = SKP_int32_MIN; - - CBimax = 0; /* To avoid returning undefined lag values */ - lag = -1; /* To check if lag with strong enough correlation has been found */ - - if( prevLag > 0 ) { - if( Fs_kHz == 12 ) { - prevLag = SKP_DIV32_16( SKP_LSHIFT( prevLag, 1 ), 3 ); - } else if( Fs_kHz == 16 ) { - prevLag = SKP_RSHIFT( prevLag, 1 ); - } - prevLag_log2_Q7 = silk_lin2log( (opus_int32)prevLag ); - } else { - prevLag_log2_Q7 = 0; - } - SKP_assert( search_thres2_Q15 == SKP_SAT16( search_thres2_Q15 ) ); - /* Setup 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 ]; - if( Fs_kHz == 8 && complexity > SILK_PE_MIN_COMPLEX ) { - /* If input is 8 khz use a larger codebook here because it is last stage */ - nb_cbk_search = PE_NB_CBKS_STAGE2_EXT; - } else { - nb_cbk_search = PE_NB_CBKS_STAGE2; - } - corr_thres_Q15 = SKP_RSHIFT( SKP_SMULBB( search_thres2_Q15, search_thres2_Q15 ), 13 ); - } else { - cbk_size = PE_NB_CBKS_STAGE2_10MS; - Lag_CB_ptr = &silk_CB_lags_stage2_10_ms[ 0 ][ 0 ]; - nb_cbk_search = PE_NB_CBKS_STAGE2_10MS; - corr_thres_Q15 = SKP_RSHIFT( SKP_SMULBB( search_thres2_Q15, search_thres2_Q15 ), 14 ); - } - - for( k = 0; k < length_d_srch; k++ ) { - d = d_srch[ k ]; - for( j = 0; j < nb_cbk_search; j++ ) { - CC[ j ] = 0; - for( i = 0; i < nb_subfr; i++ ) { - /* Try all codebooks */ - CC[ j ] = CC[ j ] + (opus_int32)C[ i ][ d + matrix_ptr( Lag_CB_ptr, i, j, cbk_size )]; - } - } - /* Find best codebook */ - CCmax_new = SKP_int32_MIN; - CBimax_new = 0; - for( i = 0; i < nb_cbk_search; i++ ) { - if( CC[ i ] > CCmax_new ) { - CCmax_new = CC[ i ]; - CBimax_new = i; - } - } - - /* Bias towards shorter lags */ - lag_log2_Q7 = silk_lin2log( (opus_int32)d ); /* Q7 */ - SKP_assert( lag_log2_Q7 == SKP_SAT16( lag_log2_Q7 ) ); - SKP_assert( nb_subfr * SILK_FIX_CONST( PE_SHORTLAG_BIAS, 15 ) == SKP_SAT16( nb_subfr * SILK_FIX_CONST( PE_SHORTLAG_BIAS, 15 ) ) ); - CCmax_new_b = CCmax_new - SKP_RSHIFT( SKP_SMULBB( nb_subfr * SILK_FIX_CONST( PE_SHORTLAG_BIAS, 15 ), lag_log2_Q7 ), 7 ); /* Q15 */ - - /* Bias towards previous lag */ - SKP_assert( nb_subfr * SILK_FIX_CONST( PE_PREVLAG_BIAS, 15 ) == SKP_SAT16( nb_subfr * SILK_FIX_CONST( PE_PREVLAG_BIAS, 15 ) ) ); - if( prevLag > 0 ) { - delta_lag_log2_sqr_Q7 = lag_log2_Q7 - prevLag_log2_Q7; - SKP_assert( delta_lag_log2_sqr_Q7 == SKP_SAT16( delta_lag_log2_sqr_Q7 ) ); - delta_lag_log2_sqr_Q7 = SKP_RSHIFT( SKP_SMULBB( delta_lag_log2_sqr_Q7, delta_lag_log2_sqr_Q7 ), 7 ); - prev_lag_bias_Q15 = SKP_RSHIFT( SKP_SMULBB( nb_subfr * SILK_FIX_CONST( PE_PREVLAG_BIAS, 15 ), *LTPCorr_Q15 ), 15 ); /* Q15 */ - prev_lag_bias_Q15 = SKP_DIV32( SKP_MUL( prev_lag_bias_Q15, delta_lag_log2_sqr_Q7 ), delta_lag_log2_sqr_Q7 + ( 1 << 6 ) ); - CCmax_new_b -= prev_lag_bias_Q15; /* Q15 */ - } - - if ( CCmax_new_b > CCmax_b && /* Find maximum biased correlation */ - CCmax_new > corr_thres_Q15 && /* Correlation needs to be high enough to be voiced */ - silk_CB_lags_stage2[ 0 ][ CBimax_new ] <= min_lag_8kHz /* Lag must be in range */ - ) { - CCmax_b = CCmax_new_b; - CCmax = CCmax_new; - lag = d; - CBimax = CBimax_new; - } - } - - if( lag == -1 ) { - /* No suitable candidate found */ - SKP_memset( pitch_out, 0, nb_subfr * sizeof( opus_int ) ); - *LTPCorr_Q15 = 0; - *lagIndex = 0; - *contourIndex = 0; - return 1; - } - - if( Fs_kHz > 8 ) { - - /****************************************************************************** - ** Scale input signal down to avoid correlations measures from overflowing - *******************************************************************************/ - /* find scaling as max scaling for each subframe */ - shift = silk_P_Ana_find_scaling( signal, frame_length, sf_length ); - if( shift > 0 ) { - /* Move signal to scratch mem because the input signal should be unchanged */ - /* Reuse the 32 bit scratch mem vector, use a 16 bit pointer from now */ - input_signal_ptr = (opus_int16*)scratch_mem; - for( i = 0; i < frame_length; i++ ) { - input_signal_ptr[ i ] = SKP_RSHIFT( signal[ i ], shift ); - } - } else { - input_signal_ptr = (opus_int16*)signal; - } - /*********************************************************************************/ - - /* Search in original signal */ - - CBimax_old = CBimax; - /* Compensate for decimation */ - SKP_assert( lag == SKP_SAT16( lag ) ); - if( Fs_kHz == 12 ) { - lag = SKP_RSHIFT( SKP_SMULBB( lag, 3 ), 1 ); - } else if( Fs_kHz == 16 ) { - lag = SKP_LSHIFT( lag, 1 ); - } else { - lag = SKP_SMULBB( lag, 3 ); - } - - lag = SKP_LIMIT_int( lag, min_lag, max_lag ); - start_lag = SKP_max_int( lag - 2, min_lag ); - end_lag = SKP_min_int( lag + 2, max_lag ); - lag_new = lag; /* to avoid undefined lag */ - CBimax = 0; /* to avoid undefined lag */ - SKP_assert( SKP_LSHIFT( CCmax, 13 ) >= 0 ); - *LTPCorr_Q15 = (opus_int)silk_SQRT_APPROX( SKP_LSHIFT( CCmax, 13 ) ); /* Output normalized correlation */ - - CCmax = SKP_int32_MIN; - /* pitch lags according to second stage */ - for( k = 0; k < nb_subfr; k++ ) { - pitch_out[ k ] = lag + 2 * silk_CB_lags_stage2[ k ][ CBimax_old ]; - } - /* Calculate the correlations and energies needed in stage 3 */ - silk_P_Ana_calc_corr_st3( crosscorr_st3, input_signal_ptr, start_lag, sf_length, nb_subfr, complexity ); - silk_P_Ana_calc_energy_st3( energies_st3, input_signal_ptr, start_lag, sf_length, nb_subfr, complexity ); - - lag_counter = 0; - SKP_assert( lag == SKP_SAT16( lag ) ); - contour_bias_Q20 = SKP_DIV32_16( SILK_FIX_CONST( PE_FLATCONTOUR_BIAS, 20 ), lag ); - - /* Setup 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; - Lag_CB_ptr = &silk_CB_lags_stage3[ 0 ][ 0 ]; - } else { - nb_cbk_search = PE_NB_CBKS_STAGE3_10MS; - cbk_size = PE_NB_CBKS_STAGE3_10MS; - Lag_CB_ptr = &silk_CB_lags_stage3_10_ms[ 0 ][ 0 ]; - } - for( d = start_lag; d <= end_lag; d++ ) { - for( j = 0; j < nb_cbk_search; j++ ) { - cross_corr = 0; - energy = 0; - for( k = 0; k < nb_subfr; k++ ) { - SKP_assert( PE_MAX_NB_SUBFR == 4 ); - energy += SKP_RSHIFT( energies_st3[ k ][ j ][ lag_counter ], 2 ); /* use mean, to avoid overflow */ - SKP_assert( energy >= 0 ); - cross_corr += SKP_RSHIFT( crosscorr_st3[ k ][ j ][ lag_counter ], 2 ); /* use mean, to avoid overflow */ - } - if( cross_corr > 0 ) { - /* Divide cross_corr / energy and get result in Q15 */ - lz = silk_CLZ32( cross_corr ); - /* Divide with result in Q13, cross_corr could be larger than energy */ - lshift = SKP_LIMIT_32( lz - 1, 0, 13 ); - CCmax_new = SKP_DIV32( SKP_LSHIFT( cross_corr, lshift ), SKP_RSHIFT( energy, 13 - lshift ) + 1 ); - CCmax_new = SKP_SAT16( CCmax_new ); - CCmax_new = SKP_SMULWB( cross_corr, CCmax_new ); - /* Saturate */ - if( CCmax_new > SKP_RSHIFT( SKP_int32_MAX, 3 ) ) { - CCmax_new = SKP_int32_MAX; - } else { - CCmax_new = SKP_LSHIFT( CCmax_new, 3 ); - } - /* Reduce depending on flatness of contour */ - diff = SKP_int16_MAX - SKP_RSHIFT( SKP_MUL( contour_bias_Q20, j ), 5 ); /* Q20 -> Q15 */ - SKP_assert( diff == SKP_SAT16( diff ) ); - CCmax_new = SKP_LSHIFT( SKP_SMULWB( CCmax_new, diff ), 1 ); - } else { - CCmax_new = 0; - } - - if( CCmax_new > CCmax && - ( d + silk_CB_lags_stage3[ 0 ][ j ] ) <= max_lag - ) { - CCmax = CCmax_new; - lag_new = d; - CBimax = j; - } - } - lag_counter++; - } - - for( k = 0; k < nb_subfr; k++ ) { - pitch_out[ k ] = lag_new + matrix_ptr( Lag_CB_ptr, k, CBimax, cbk_size ); - } - *lagIndex = (opus_int16)( lag_new - min_lag); - *contourIndex = (opus_int8)CBimax; - } else { - /* Save Lags and correlation */ - CCmax = SKP_max( CCmax, 0 ); - *LTPCorr_Q15 = (opus_int)silk_SQRT_APPROX( SKP_LSHIFT( CCmax, 13 ) ); /* Output normalized correlation */ - for( k = 0; k < nb_subfr; k++ ) { - pitch_out[ k ] = lag + matrix_ptr( Lag_CB_ptr, k, CBimax, cbk_size ); - } - *lagIndex = (opus_int16)( lag - min_lag_8kHz ); - *contourIndex = (opus_int8)CBimax; - } - SKP_assert( *lagIndex >= 0 ); - /* return as voiced */ - return 0; -} - -/*************************************************************************/ -/* Calculates the correlations used in stage 3 search. In order to cover */ -/* the whole lag codebook for all the searched offset lags (lag +- 2), */ -/*************************************************************************/ -void silk_P_Ana_calc_corr_st3( - opus_int32 cross_corr_st3[ PE_MAX_NB_SUBFR ][ PE_NB_CBKS_STAGE3_MAX ][ PE_NB_STAGE3_LAGS ],/* (O) 3 DIM correlation array */ - const opus_int16 signal[], /* I vector to correlate */ - opus_int start_lag, /* I lag offset to search around */ - opus_int sf_length, /* I length of a 5 ms subframe */ - opus_int nb_subfr, /* I number of subframes */ - opus_int complexity /* I Complexity setting */ -) -{ - const opus_int16 *target_ptr, *basis_ptr; - opus_int32 cross_corr; - opus_int i, j, k, lag_counter, lag_low, lag_high; - opus_int nb_cbk_search, delta, idx, cbk_size; - opus_int32 scratch_mem[ SCRATCH_SIZE ]; - const opus_int8 *Lag_range_ptr, *Lag_CB_ptr; - - SKP_assert( complexity >= SILK_PE_MIN_COMPLEX ); - SKP_assert( complexity <= SILK_PE_MAX_COMPLEX ); - - if( nb_subfr == PE_MAX_NB_SUBFR ){ - Lag_range_ptr = &silk_Lag_range_stage3[ complexity ][ 0 ][ 0 ]; - Lag_CB_ptr = &silk_CB_lags_stage3[ 0 ][ 0 ]; - nb_cbk_search = silk_nb_cbk_searchs_stage3[ complexity ]; - cbk_size = PE_NB_CBKS_STAGE3_MAX; - } else { - SKP_assert( nb_subfr == PE_MAX_NB_SUBFR >> 1); - Lag_range_ptr = &silk_Lag_range_stage3_10_ms[ 0 ][ 0 ]; - Lag_CB_ptr = &silk_CB_lags_stage3_10_ms[ 0 ][ 0 ]; - nb_cbk_search = PE_NB_CBKS_STAGE3_10MS; - cbk_size = PE_NB_CBKS_STAGE3_10MS; - } - - target_ptr = &signal[ SKP_LSHIFT( sf_length, 2 ) ]; /* Pointer to middle of frame */ - for( k = 0; k < nb_subfr; k++ ) { - lag_counter = 0; - - /* Calculate the correlations for each subframe */ - lag_low = matrix_ptr( Lag_range_ptr, k, 0, 2 ); - lag_high = matrix_ptr( Lag_range_ptr, k, 1, 2 ); - for( j = lag_low; j <= lag_high; j++ ) { - basis_ptr = target_ptr - ( start_lag + j ); - cross_corr = silk_inner_prod_aligned( (opus_int16*)target_ptr, (opus_int16*)basis_ptr, sf_length ); - SKP_assert( lag_counter < SCRATCH_SIZE ); - scratch_mem[ lag_counter ] = cross_corr; - lag_counter++; - } - - delta = matrix_ptr( Lag_range_ptr, k, 0, 2 ); - for( i = 0; i < nb_cbk_search; i++ ) { - /* Fill out the 3 dim array that stores the correlations for */ - /* each code_book vector for each start lag */ - idx = matrix_ptr( Lag_CB_ptr, k, i, cbk_size ) - delta; - for( j = 0; j < PE_NB_STAGE3_LAGS; j++ ) { - SKP_assert( idx + j < SCRATCH_SIZE ); - SKP_assert( idx + j < lag_counter ); - cross_corr_st3[ k ][ i ][ j ] = scratch_mem[ idx + j ]; - } - } - target_ptr += sf_length; - } -} - -/********************************************************************/ -/* Calculate the energies for first two subframes. The energies are */ -/* calculated recursively. */ -/********************************************************************/ -void silk_P_Ana_calc_energy_st3( - opus_int32 energies_st3[ PE_MAX_NB_SUBFR ][ PE_NB_CBKS_STAGE3_MAX ][ PE_NB_STAGE3_LAGS ],/* (O) 3 DIM energy array */ - const opus_int16 signal[], /* I vector to calc energy in */ - opus_int start_lag, /* I lag offset to search around */ - opus_int sf_length, /* I length of one 5 ms subframe */ - opus_int nb_subfr, /* I number of subframes */ - opus_int complexity /* I Complexity setting */ -) -{ - const opus_int16 *target_ptr, *basis_ptr; - opus_int32 energy; - opus_int k, i, j, lag_counter; - opus_int nb_cbk_search, delta, idx, cbk_size, lag_diff; - opus_int32 scratch_mem[ SCRATCH_SIZE ]; - const opus_int8 *Lag_range_ptr, *Lag_CB_ptr; - - SKP_assert( complexity >= SILK_PE_MIN_COMPLEX ); - SKP_assert( complexity <= SILK_PE_MAX_COMPLEX ); - - if( nb_subfr == PE_MAX_NB_SUBFR ){ - Lag_range_ptr = &silk_Lag_range_stage3[ complexity ][ 0 ][ 0 ]; - Lag_CB_ptr = &silk_CB_lags_stage3[ 0 ][ 0 ]; - nb_cbk_search = silk_nb_cbk_searchs_stage3[ complexity ]; - cbk_size = PE_NB_CBKS_STAGE3_MAX; - } else { - SKP_assert( nb_subfr == PE_MAX_NB_SUBFR >> 1); - Lag_range_ptr = &silk_Lag_range_stage3_10_ms[ 0 ][ 0 ]; - Lag_CB_ptr = &silk_CB_lags_stage3_10_ms[ 0 ][ 0 ]; - nb_cbk_search = PE_NB_CBKS_STAGE3_10MS; - cbk_size = PE_NB_CBKS_STAGE3_10MS; - } - target_ptr = &signal[ SKP_LSHIFT( sf_length, 2 ) ]; - for( k = 0; k < nb_subfr; k++ ) { - lag_counter = 0; - - /* Calculate the energy for first lag */ - basis_ptr = target_ptr - ( start_lag + matrix_ptr( Lag_range_ptr, k, 0, 2 ) ); - energy = silk_inner_prod_aligned( basis_ptr, basis_ptr, sf_length ); - SKP_assert( energy >= 0 ); - scratch_mem[ lag_counter ] = energy; - lag_counter++; - - lag_diff = ( matrix_ptr( Lag_range_ptr, k, 1, 2 ) - matrix_ptr( Lag_range_ptr, k, 0, 2 ) + 1 ); - for( i = 1; i < lag_diff; i++ ) { - /* remove part outside new window */ - energy -= SKP_SMULBB( basis_ptr[ sf_length - i ], basis_ptr[ sf_length - i ] ); - SKP_assert( energy >= 0 ); - - /* add part that comes into window */ - energy = SKP_ADD_SAT32( energy, SKP_SMULBB( basis_ptr[ -i ], basis_ptr[ -i ] ) ); - SKP_assert( energy >= 0 ); - SKP_assert( lag_counter < SCRATCH_SIZE ); - scratch_mem[ lag_counter ] = energy; - lag_counter++; - } - - delta = matrix_ptr( Lag_range_ptr, k, 0, 2 ); - for( i = 0; i < nb_cbk_search; i++ ) { - /* Fill out the 3 dim array that stores the correlations for */ - /* each code_book vector for each start lag */ - idx = matrix_ptr( Lag_CB_ptr, k, i, cbk_size ) - delta; - for( j = 0; j < PE_NB_STAGE3_LAGS; j++ ) { - SKP_assert( idx + j < SCRATCH_SIZE ); - SKP_assert( idx + j < lag_counter ); - energies_st3[ k ][ i ][ j ] = scratch_mem[ idx + j ]; - SKP_assert( energies_st3[ k ][ i ][ j ] >= 0 ); - } - } - target_ptr += sf_length; - } -} - -opus_int32 silk_P_Ana_find_scaling( - const opus_int16 *signal, - const opus_int signal_length, - const opus_int sum_sqr_len -) -{ - opus_int32 nbits, x_max; - - x_max = silk_int16_array_maxabs( signal, signal_length ); - - if( x_max < SKP_int16_MAX ) { - /* Number of bits needed for the sum of the squares */ - nbits = 32 - silk_CLZ32( SKP_SMULBB( x_max, x_max ) ); - } else { - /* Here we don't know if x_max should have been SKP_int16_MAX + 1, so we expect the worst case */ - nbits = 30; - } - nbits += 17 - silk_CLZ16( sum_sqr_len ); - - /* Without a guarantee of saturation, we need to keep the 31st bit free */ - if( nbits < 31 ) { - return 0; - } else { - return( nbits - 30 ); - } -} +/*********************************************************************** +Copyright (c) 2006-2011, Skype Limited. All rights reserved. +Redistribution and use in source and binary forms, with or without +modification, (subject to the limitations in the disclaimer below) +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 Skype Limited, nor the names of specific +contributors, may be used to endorse or promote products derived from +this software without specific prior written permission. +NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED +BY THIS LICENSE. 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. +***********************************************************************/ + +/*********************************************************** +* Pitch analyser function +********************************************************** */ +#include "silk_SigProc_FIX.h" +#include "silk_pitch_est_defines.h" +#include "silk_debug.h" + +#define SCRATCH_SIZE 22 + +/************************************************************/ +/* Internally used functions */ +/************************************************************/ +void silk_P_Ana_calc_corr_st3( + opus_int32 cross_corr_st3[ PE_MAX_NB_SUBFR ][ PE_NB_CBKS_STAGE3_MAX ][ PE_NB_STAGE3_LAGS ],/* (O) 3 DIM correlation array */ + const opus_int16 signal[], /* I vector to correlate */ + opus_int start_lag, /* I lag offset to search around */ + opus_int sf_length, /* I length of a 5 ms subframe */ + opus_int nb_subfr, /* I number of subframes */ + opus_int complexity /* I Complexity setting */ +); + +void silk_P_Ana_calc_energy_st3( + opus_int32 energies_st3[ PE_MAX_NB_SUBFR ][ PE_NB_CBKS_STAGE3_MAX ][ PE_NB_STAGE3_LAGS ],/* (O) 3 DIM energy array */ + const opus_int16 signal[], /* I vector to calc energy in */ + opus_int start_lag, /* I lag offset to search around */ + opus_int sf_length, /* I length of one 5 ms subframe */ + opus_int nb_subfr, /* I number of subframes */ + opus_int complexity /* I Complexity setting */ +); + +opus_int32 silk_P_Ana_find_scaling( + const opus_int16 *signal, + const opus_int signal_length, + const opus_int sum_sqr_len +); + +/*************************************************************/ +/* FIXED POINT CORE PITCH ANALYSIS FUNCTION */ +/*************************************************************/ +opus_int silk_pitch_analysis_core( /* O Voicing estimate: 0 voiced, 1 unvoiced */ + const opus_int16 *signal, /* I Signal of length PE_FRAME_LENGTH_MS*Fs_kHz */ + opus_int *pitch_out, /* O 4 pitch lag values */ + opus_int16 *lagIndex, /* O Lag Index */ + opus_int8 *contourIndex, /* O Pitch contour Index */ + opus_int *LTPCorr_Q15, /* I/O Normalized correlation; input: value from previous frame */ + opus_int prevLag, /* I Last lag of previous frame; set to zero is unvoiced */ + const opus_int32 search_thres1_Q16, /* I First stage threshold for lag candidates 0 - 1 */ + const opus_int search_thres2_Q15, /* I Final threshold for lag candidates 0 - 1 */ + const opus_int Fs_kHz, /* I Sample frequency (kHz) */ + const opus_int complexity, /* I Complexity setting, 0-2, where 2 is highest */ + const opus_int nb_subfr /* I number of 5 ms subframes */ +) +{ + opus_int16 signal_8kHz[ PE_MAX_FRAME_LENGTH_ST_2 ]; + opus_int16 signal_4kHz[ PE_MAX_FRAME_LENGTH_ST_1 ]; + opus_int32 filt_state[ 6 ]; + opus_int32 scratch_mem[ 3 * PE_MAX_FRAME_LENGTH ]; + opus_int16 *input_signal_ptr; + opus_int i, k, d, j; + opus_int16 C[ PE_MAX_NB_SUBFR ][ ( PE_MAX_LAG >> 1 ) + 5 ]; + const opus_int16 *target_ptr, *basis_ptr; + opus_int32 cross_corr, normalizer, energy, shift, energy_basis, energy_target; + opus_int d_srch[ PE_D_SRCH_LENGTH ], Cmax, length_d_srch, length_d_comp; + opus_int16 d_comp[ ( PE_MAX_LAG >> 1 ) + 5 ]; + opus_int32 sum, threshold, temp32, lag_counter; + opus_int CBimax, CBimax_new, CBimax_old, lag, start_lag, end_lag, lag_new; + opus_int32 CC[ PE_NB_CBKS_STAGE2_EXT ], CCmax, CCmax_b, CCmax_new_b, CCmax_new; + opus_int32 energies_st3[ PE_MAX_NB_SUBFR ][ PE_NB_CBKS_STAGE3_MAX ][ PE_NB_STAGE3_LAGS ]; + opus_int32 crosscorr_st3[ PE_MAX_NB_SUBFR ][ PE_NB_CBKS_STAGE3_MAX ][ PE_NB_STAGE3_LAGS ]; + opus_int frame_length, frame_length_8kHz, frame_length_4kHz, max_sum_sq_length; + opus_int sf_length, sf_length_8kHz, sf_length_4kHz; + opus_int min_lag, min_lag_8kHz, min_lag_4kHz; + opus_int max_lag, max_lag_8kHz, max_lag_4kHz; + opus_int32 contour_bias_Q20, diff, lz, lshift; + opus_int nb_cbk_search, cbk_size; + opus_int32 delta_lag_log2_sqr_Q7, lag_log2_Q7, prevLag_log2_Q7, prev_lag_bias_Q15, corr_thres_Q15; + const opus_int8 *Lag_CB_ptr; + /* Check for valid sampling frequency */ + SKP_assert( Fs_kHz == 8 || Fs_kHz == 12 || Fs_kHz == 16 ); + + /* Check for valid complexity setting */ + SKP_assert( complexity >= SILK_PE_MIN_COMPLEX ); + SKP_assert( complexity <= SILK_PE_MAX_COMPLEX ); + + SKP_assert( search_thres1_Q16 >= 0 && search_thres1_Q16 <= (1<<16) ); + SKP_assert( search_thres2_Q15 >= 0 && search_thres2_Q15 <= (1<<15) ); + + /* Setup 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; + sf_length = PE_SUBFR_LENGTH_MS * Fs_kHz; + sf_length_4kHz = PE_SUBFR_LENGTH_MS * 4; + sf_length_8kHz = PE_SUBFR_LENGTH_MS * 8; + min_lag = PE_MIN_LAG_MS * Fs_kHz; + min_lag_4kHz = PE_MIN_LAG_MS * 4; + min_lag_8kHz = PE_MIN_LAG_MS * 8; + max_lag = PE_MAX_LAG_MS * Fs_kHz - 1; + max_lag_4kHz = PE_MAX_LAG_MS * 4; + max_lag_8kHz = PE_MAX_LAG_MS * 8 - 1; + + SKP_memset( C, 0, sizeof( opus_int16 ) * nb_subfr * ( ( PE_MAX_LAG >> 1 ) + 5) ); + + /* Resample from input sampled at Fs_kHz to 8 kHz */ + if( Fs_kHz == 16 ) { + SKP_memset( filt_state, 0, 2 * sizeof( opus_int32 ) ); + silk_resampler_down2( filt_state, signal_8kHz, signal, frame_length ); + } else if ( Fs_kHz == 12 ) { + SKP_memset( filt_state, 0, 6 * sizeof( opus_int32 ) ); + silk_resampler_down2_3( filt_state, signal_8kHz, signal, frame_length ); + } else { + SKP_assert( Fs_kHz == 8 ); + SKP_memcpy( signal_8kHz, signal, frame_length_8kHz * sizeof(opus_int16) ); + } + + /* Decimate again to 4 kHz */ + SKP_memset( filt_state, 0, 2 * sizeof( opus_int32 ) );/* Set state to zero */ + silk_resampler_down2( filt_state, signal_4kHz, signal_8kHz, frame_length_8kHz ); + + /* Low-pass filter */ + for( i = frame_length_4kHz - 1; i > 0; i-- ) { + signal_4kHz[ i ] = SKP_ADD_SAT16( signal_4kHz[ i ], signal_4kHz[ i - 1 ] ); + } + + /******************************************************************************* + ** Scale 4 kHz signal down to prevent correlations measures from overflowing + ** find scaling as max scaling for each 8kHz(?) subframe + *******************************************************************************/ + + /* Inner product is calculated with different lengths, so scale for the worst case */ + max_sum_sq_length = SKP_max_32( sf_length_8kHz, SKP_LSHIFT( sf_length_4kHz, 2 ) ); + shift = silk_P_Ana_find_scaling( signal_4kHz, frame_length_4kHz, max_sum_sq_length ); + if( shift > 0 ) { + for( i = 0; i < frame_length_4kHz; i++ ) { + signal_4kHz[ i ] = SKP_RSHIFT( signal_4kHz[ i ], shift ); + } + } + + /****************************************************************************** + * FIRST STAGE, operating in 4 khz + ******************************************************************************/ + target_ptr = &signal_4kHz[ SKP_LSHIFT( sf_length_4kHz, 2 ) ]; + for( k = 0; k < nb_subfr >> 1; k++ ) { + /* Check that we are within range of the array */ + SKP_assert( target_ptr >= signal_4kHz ); + SKP_assert( target_ptr + sf_length_8kHz <= signal_4kHz + frame_length_4kHz ); + + basis_ptr = target_ptr - min_lag_4kHz; + + /* Check that we are within range of the array */ + SKP_assert( basis_ptr >= signal_4kHz ); + SKP_assert( basis_ptr + sf_length_8kHz <= signal_4kHz + frame_length_4kHz ); + + normalizer = 0; + cross_corr = 0; + /* Calculate first vector products before loop */ + cross_corr = silk_inner_prod_aligned( target_ptr, basis_ptr, sf_length_8kHz ); + normalizer = silk_inner_prod_aligned( basis_ptr, basis_ptr, sf_length_8kHz ); + normalizer = SKP_ADD_SAT32( normalizer, SKP_SMULBB( sf_length_8kHz, 4000 ) ); + + temp32 = SKP_DIV32( cross_corr, silk_SQRT_APPROX( normalizer ) + 1 ); + C[ k ][ min_lag_4kHz ] = (opus_int16)SKP_SAT16( temp32 ); /* Q0 */ + + /* From now on normalizer is computed recursively */ + for( d = min_lag_4kHz + 1; d <= max_lag_4kHz; d++ ) { + basis_ptr--; + + /* Check that we are within range of the array */ + SKP_assert( basis_ptr >= signal_4kHz ); + SKP_assert( basis_ptr + sf_length_8kHz <= signal_4kHz + frame_length_4kHz ); + + cross_corr = silk_inner_prod_aligned( target_ptr, basis_ptr, sf_length_8kHz ); + + /* Add contribution of new sample and remove contribution from oldest sample */ + normalizer += + SKP_SMULBB( basis_ptr[ 0 ], basis_ptr[ 0 ] ) - + SKP_SMULBB( basis_ptr[ sf_length_8kHz ], basis_ptr[ sf_length_8kHz ] ); + + temp32 = SKP_DIV32( cross_corr, silk_SQRT_APPROX( normalizer ) + 1 ); + C[ k ][ d ] = (opus_int16)SKP_SAT16( temp32 ); /* Q0 */ + } + /* Update target pointer */ + target_ptr += sf_length_8kHz; + } + + /* Combine two subframes into single correlation measure and apply short-lag bias */ + if( nb_subfr == PE_MAX_NB_SUBFR ) { + for( i = max_lag_4kHz; i >= min_lag_4kHz; i-- ) { + sum = (opus_int32)C[ 0 ][ i ] + (opus_int32)C[ 1 ][ i ]; /* Q0 */ + SKP_assert( SKP_RSHIFT( sum, 1 ) == SKP_SAT16( SKP_RSHIFT( sum, 1 ) ) ); + sum = SKP_RSHIFT( sum, 1 ); /* Q-1 */ + SKP_assert( SKP_LSHIFT( (opus_int32)-i, 4 ) == SKP_SAT16( SKP_LSHIFT( (opus_int32)-i, 4 ) ) ); + sum = SKP_SMLAWB( sum, sum, SKP_LSHIFT( -i, 4 ) ); /* Q-1 */ + SKP_assert( sum == SKP_SAT16( sum ) ); + C[ 0 ][ i ] = (opus_int16)sum; /* Q-1 */ + } + } else { + /* Only short-lag bias */ + for( i = max_lag_4kHz; i >= min_lag_4kHz; i-- ) { + sum = (opus_int32)C[ 0 ][ i ]; + sum = SKP_SMLAWB( sum, sum, SKP_LSHIFT( -i, 4 ) ); /* Q-1 */ + C[ 0 ][ i ] = (opus_int16)sum; /* Q-1 */ + } + } + + /* Sort */ + length_d_srch = SKP_ADD_LSHIFT32( 4, complexity, 1 ); + SKP_assert( 3 * length_d_srch <= PE_D_SRCH_LENGTH ); + silk_insertion_sort_decreasing_int16( &C[ 0 ][ min_lag_4kHz ], d_srch, max_lag_4kHz - min_lag_4kHz + 1, length_d_srch ); + + /* Escape if correlation is very low already here */ + target_ptr = &signal_4kHz[ SKP_SMULBB( sf_length_4kHz, nb_subfr ) ]; + energy = silk_inner_prod_aligned( target_ptr, target_ptr, SKP_LSHIFT( sf_length_4kHz, 2 ) ); + energy = SKP_ADD_SAT32( energy, 1000 ); /* Q0 */ + Cmax = (opus_int)C[ 0 ][ min_lag_4kHz ]; /* Q-1 */ + threshold = SKP_SMULBB( Cmax, Cmax ); /* Q-2 */ + + /* Compare in Q-2 domain */ + if( SKP_RSHIFT( energy, 4 + 2 ) > threshold ) { + SKP_memset( pitch_out, 0, nb_subfr * sizeof( opus_int ) ); + *LTPCorr_Q15 = 0; + *lagIndex = 0; + *contourIndex = 0; + return 1; + } + + threshold = SKP_SMULWB( search_thres1_Q16, Cmax ); + for( i = 0; i < length_d_srch; i++ ) { + /* Convert to 8 kHz indices for the sorted correlation that exceeds the threshold */ + if( C[ 0 ][ min_lag_4kHz + i ] > threshold ) { + d_srch[ i ] = SKP_LSHIFT( d_srch[ i ] + min_lag_4kHz, 1 ); + } else { + length_d_srch = i; + break; + } + } + SKP_assert( length_d_srch > 0 ); + + for( i = min_lag_8kHz - 5; i < max_lag_8kHz + 5; i++ ) { + d_comp[ i ] = 0; + } + for( i = 0; i < length_d_srch; i++ ) { + d_comp[ d_srch[ i ] ] = 1; + } + + /* Convolution */ + for( i = max_lag_8kHz + 3; i >= min_lag_8kHz; i-- ) { + d_comp[ i ] += d_comp[ i - 1 ] + d_comp[ i - 2 ]; + } + + length_d_srch = 0; + for( i = min_lag_8kHz; i < max_lag_8kHz + 1; i++ ) { + if( d_comp[ i + 1 ] > 0 ) { + d_srch[ length_d_srch ] = i; + length_d_srch++; + } + } + + /* Convolution */ + for( i = max_lag_8kHz + 3; i >= min_lag_8kHz; i-- ) { + d_comp[ i ] += d_comp[ i - 1 ] + d_comp[ i - 2 ] + d_comp[ i - 3 ]; + } + + length_d_comp = 0; + for( i = min_lag_8kHz; i < max_lag_8kHz + 4; i++ ) { + if( d_comp[ i ] > 0 ) { + d_comp[ length_d_comp ] = i - 2; + length_d_comp++; + } + } + + /********************************************************************************** + ** SECOND STAGE, operating at 8 kHz, on lag sections with high correlation + *************************************************************************************/ + + /****************************************************************************** + ** Scale signal down to avoid correlations measures from overflowing + *******************************************************************************/ + /* find scaling as max scaling for each subframe */ + shift = silk_P_Ana_find_scaling( signal_8kHz, frame_length_8kHz, sf_length_8kHz ); + if( shift > 0 ) { + for( i = 0; i < frame_length_8kHz; i++ ) { + signal_8kHz[ i ] = SKP_RSHIFT( signal_8kHz[ i ], shift ); + } + } + + /********************************************************************************* + * Find energy of each subframe projected onto its history, for a range of delays + *********************************************************************************/ + SKP_memset( C, 0, PE_MAX_NB_SUBFR * ( ( PE_MAX_LAG >> 1 ) + 5 ) * sizeof( opus_int16 ) ); + + target_ptr = &signal_8kHz[ PE_LTP_MEM_LENGTH_MS * 8 ]; + for( k = 0; k < nb_subfr; k++ ) { + + /* Check that we are within range of the array */ + SKP_assert( target_ptr >= signal_8kHz ); + SKP_assert( target_ptr + sf_length_8kHz <= signal_8kHz + frame_length_8kHz ); + + energy_target = silk_inner_prod_aligned( target_ptr, target_ptr, sf_length_8kHz ); + // ToDo: Calculate 1 / energy_target here and save one division inside next for loop + for( j = 0; j < length_d_comp; j++ ) { + d = d_comp[ j ]; + basis_ptr = target_ptr - d; + + /* Check that we are within range of the array */ + SKP_assert( basis_ptr >= signal_8kHz ); + SKP_assert( basis_ptr + sf_length_8kHz <= signal_8kHz + frame_length_8kHz ); + + cross_corr = silk_inner_prod_aligned( target_ptr, basis_ptr, sf_length_8kHz ); + energy_basis = silk_inner_prod_aligned( basis_ptr, basis_ptr, sf_length_8kHz ); + if( cross_corr > 0 ) { + energy = SKP_max( energy_target, energy_basis ); /* Find max to make sure first division < 1.0 */ + lz = silk_CLZ32( cross_corr ); + lshift = SKP_LIMIT_32( lz - 1, 0, 15 ); + temp32 = SKP_DIV32( SKP_LSHIFT( cross_corr, lshift ), SKP_RSHIFT( energy, 15 - lshift ) + 1 ); /* Q15 */ + SKP_assert( temp32 == SKP_SAT16( temp32 ) ); + temp32 = SKP_SMULWB( cross_corr, temp32 ); /* Q(-1), cc * ( cc / max(b, t) ) */ + temp32 = SKP_ADD_SAT32( temp32, temp32 ); /* Q(0) */ + lz = silk_CLZ32( temp32 ); + lshift = SKP_LIMIT_32( lz - 1, 0, 15 ); + energy = SKP_min( energy_target, energy_basis ); + C[ k ][ d ] = SKP_DIV32( SKP_LSHIFT( temp32, lshift ), SKP_RSHIFT( energy, 15 - lshift ) + 1 ); // Q15 + } else { + C[ k ][ d ] = 0; + } + } + target_ptr += sf_length_8kHz; + } + + /* search over lag range and lags codebook */ + /* scale factor for lag codebook, as a function of center lag */ + + CCmax = SKP_int32_MIN; + CCmax_b = SKP_int32_MIN; + + CBimax = 0; /* To avoid returning undefined lag values */ + lag = -1; /* To check if lag with strong enough correlation has been found */ + + if( prevLag > 0 ) { + if( Fs_kHz == 12 ) { + prevLag = SKP_DIV32_16( SKP_LSHIFT( prevLag, 1 ), 3 ); + } else if( Fs_kHz == 16 ) { + prevLag = SKP_RSHIFT( prevLag, 1 ); + } + prevLag_log2_Q7 = silk_lin2log( (opus_int32)prevLag ); + } else { + prevLag_log2_Q7 = 0; + } + SKP_assert( search_thres2_Q15 == SKP_SAT16( search_thres2_Q15 ) ); + /* Setup 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 ]; + if( Fs_kHz == 8 && complexity > SILK_PE_MIN_COMPLEX ) { + /* If input is 8 khz use a larger codebook here because it is last stage */ + nb_cbk_search = PE_NB_CBKS_STAGE2_EXT; + } else { + nb_cbk_search = PE_NB_CBKS_STAGE2; + } + corr_thres_Q15 = SKP_RSHIFT( SKP_SMULBB( search_thres2_Q15, search_thres2_Q15 ), 13 ); + } else { + cbk_size = PE_NB_CBKS_STAGE2_10MS; + Lag_CB_ptr = &silk_CB_lags_stage2_10_ms[ 0 ][ 0 ]; + nb_cbk_search = PE_NB_CBKS_STAGE2_10MS; + corr_thres_Q15 = SKP_RSHIFT( SKP_SMULBB( search_thres2_Q15, search_thres2_Q15 ), 14 ); + } + + for( k = 0; k < length_d_srch; k++ ) { + d = d_srch[ k ]; + for( j = 0; j < nb_cbk_search; j++ ) { + CC[ j ] = 0; + for( i = 0; i < nb_subfr; i++ ) { + /* Try all codebooks */ + CC[ j ] = CC[ j ] + (opus_int32)C[ i ][ d + matrix_ptr( Lag_CB_ptr, i, j, cbk_size )]; + } + } + /* Find best codebook */ + CCmax_new = SKP_int32_MIN; + CBimax_new = 0; + for( i = 0; i < nb_cbk_search; i++ ) { + if( CC[ i ] > CCmax_new ) { + CCmax_new = CC[ i ]; + CBimax_new = i; + } + } + + /* Bias towards shorter lags */ + lag_log2_Q7 = silk_lin2log( (opus_int32)d ); /* Q7 */ + SKP_assert( lag_log2_Q7 == SKP_SAT16( lag_log2_Q7 ) ); + SKP_assert( nb_subfr * SILK_FIX_CONST( PE_SHORTLAG_BIAS, 15 ) == SKP_SAT16( nb_subfr * SILK_FIX_CONST( PE_SHORTLAG_BIAS, 15 ) ) ); + CCmax_new_b = CCmax_new - SKP_RSHIFT( SKP_SMULBB( nb_subfr * SILK_FIX_CONST( PE_SHORTLAG_BIAS, 15 ), lag_log2_Q7 ), 7 ); /* Q15 */ + + /* Bias towards previous lag */ + SKP_assert( nb_subfr * SILK_FIX_CONST( PE_PREVLAG_BIAS, 15 ) == SKP_SAT16( nb_subfr * SILK_FIX_CONST( PE_PREVLAG_BIAS, 15 ) ) ); + if( prevLag > 0 ) { + delta_lag_log2_sqr_Q7 = lag_log2_Q7 - prevLag_log2_Q7; + SKP_assert( delta_lag_log2_sqr_Q7 == SKP_SAT16( delta_lag_log2_sqr_Q7 ) ); + delta_lag_log2_sqr_Q7 = SKP_RSHIFT( SKP_SMULBB( delta_lag_log2_sqr_Q7, delta_lag_log2_sqr_Q7 ), 7 ); + prev_lag_bias_Q15 = SKP_RSHIFT( SKP_SMULBB( nb_subfr * SILK_FIX_CONST( PE_PREVLAG_BIAS, 15 ), *LTPCorr_Q15 ), 15 ); /* Q15 */ + prev_lag_bias_Q15 = SKP_DIV32( SKP_MUL( prev_lag_bias_Q15, delta_lag_log2_sqr_Q7 ), delta_lag_log2_sqr_Q7 + ( 1 << 6 ) ); + CCmax_new_b -= prev_lag_bias_Q15; /* Q15 */ + } + + if ( CCmax_new_b > CCmax_b && /* Find maximum biased correlation */ + CCmax_new > corr_thres_Q15 && /* Correlation needs to be high enough to be voiced */ + silk_CB_lags_stage2[ 0 ][ CBimax_new ] <= min_lag_8kHz /* Lag must be in range */ + ) { + CCmax_b = CCmax_new_b; + CCmax = CCmax_new; + lag = d; + CBimax = CBimax_new; + } + } + + if( lag == -1 ) { + /* No suitable candidate found */ + SKP_memset( pitch_out, 0, nb_subfr * sizeof( opus_int ) ); + *LTPCorr_Q15 = 0; + *lagIndex = 0; + *contourIndex = 0; + return 1; + } + + if( Fs_kHz > 8 ) { + + /****************************************************************************** + ** Scale input signal down to avoid correlations measures from overflowing + *******************************************************************************/ + /* find scaling as max scaling for each subframe */ + shift = silk_P_Ana_find_scaling( signal, frame_length, sf_length ); + if( shift > 0 ) { + /* Move signal to scratch mem because the input signal should be unchanged */ + /* Reuse the 32 bit scratch mem vector, use a 16 bit pointer from now */ + input_signal_ptr = (opus_int16*)scratch_mem; + for( i = 0; i < frame_length; i++ ) { + input_signal_ptr[ i ] = SKP_RSHIFT( signal[ i ], shift ); + } + } else { + input_signal_ptr = (opus_int16*)signal; + } + /*********************************************************************************/ + + /* Search in original signal */ + + CBimax_old = CBimax; + /* Compensate for decimation */ + SKP_assert( lag == SKP_SAT16( lag ) ); + if( Fs_kHz == 12 ) { + lag = SKP_RSHIFT( SKP_SMULBB( lag, 3 ), 1 ); + } else if( Fs_kHz == 16 ) { + lag = SKP_LSHIFT( lag, 1 ); + } else { + lag = SKP_SMULBB( lag, 3 ); + } + + lag = SKP_LIMIT_int( lag, min_lag, max_lag ); + start_lag = SKP_max_int( lag - 2, min_lag ); + end_lag = SKP_min_int( lag + 2, max_lag ); + lag_new = lag; /* to avoid undefined lag */ + CBimax = 0; /* to avoid undefined lag */ + SKP_assert( SKP_LSHIFT( CCmax, 13 ) >= 0 ); + *LTPCorr_Q15 = (opus_int)silk_SQRT_APPROX( SKP_LSHIFT( CCmax, 13 ) ); /* Output normalized correlation */ + + CCmax = SKP_int32_MIN; + /* pitch lags according to second stage */ + for( k = 0; k < nb_subfr; k++ ) { + pitch_out[ k ] = lag + 2 * silk_CB_lags_stage2[ k ][ CBimax_old ]; + } + /* Calculate the correlations and energies needed in stage 3 */ + silk_P_Ana_calc_corr_st3( crosscorr_st3, input_signal_ptr, start_lag, sf_length, nb_subfr, complexity ); + silk_P_Ana_calc_energy_st3( energies_st3, input_signal_ptr, start_lag, sf_length, nb_subfr, complexity ); + + lag_counter = 0; + SKP_assert( lag == SKP_SAT16( lag ) ); + contour_bias_Q20 = SKP_DIV32_16( SILK_FIX_CONST( PE_FLATCONTOUR_BIAS, 20 ), lag ); + + /* Setup 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; + Lag_CB_ptr = &silk_CB_lags_stage3[ 0 ][ 0 ]; + } else { + nb_cbk_search = PE_NB_CBKS_STAGE3_10MS; + cbk_size = PE_NB_CBKS_STAGE3_10MS; + Lag_CB_ptr = &silk_CB_lags_stage3_10_ms[ 0 ][ 0 ]; + } + for( d = start_lag; d <= end_lag; d++ ) { + for( j = 0; j < nb_cbk_search; j++ ) { + cross_corr = 0; + energy = 0; + for( k = 0; k < nb_subfr; k++ ) { + SKP_assert( PE_MAX_NB_SUBFR == 4 ); + energy += SKP_RSHIFT( energies_st3[ k ][ j ][ lag_counter ], 2 ); /* use mean, to avoid overflow */ + SKP_assert( energy >= 0 ); + cross_corr += SKP_RSHIFT( crosscorr_st3[ k ][ j ][ lag_counter ], 2 ); /* use mean, to avoid overflow */ + } + if( cross_corr > 0 ) { + /* Divide cross_corr / energy and get result in Q15 */ + lz = silk_CLZ32( cross_corr ); + /* Divide with result in Q13, cross_corr could be larger than energy */ + lshift = SKP_LIMIT_32( lz - 1, 0, 13 ); + CCmax_new = SKP_DIV32( SKP_LSHIFT( cross_corr, lshift ), SKP_RSHIFT( energy, 13 - lshift ) + 1 ); + CCmax_new = SKP_SAT16( CCmax_new ); + CCmax_new = SKP_SMULWB( cross_corr, CCmax_new ); + /* Saturate */ + if( CCmax_new > SKP_RSHIFT( SKP_int32_MAX, 3 ) ) { + CCmax_new = SKP_int32_MAX; + } else { + CCmax_new = SKP_LSHIFT( CCmax_new, 3 ); + } + /* Reduce depending on flatness of contour */ + diff = SKP_int16_MAX - SKP_RSHIFT( SKP_MUL( contour_bias_Q20, j ), 5 ); /* Q20 -> Q15 */ + SKP_assert( diff == SKP_SAT16( diff ) ); + CCmax_new = SKP_LSHIFT( SKP_SMULWB( CCmax_new, diff ), 1 ); + } else { + CCmax_new = 0; + } + + if( CCmax_new > CCmax && + ( d + silk_CB_lags_stage3[ 0 ][ j ] ) <= max_lag + ) { + CCmax = CCmax_new; + lag_new = d; + CBimax = j; + } + } + lag_counter++; + } + + for( k = 0; k < nb_subfr; k++ ) { + pitch_out[ k ] = lag_new + matrix_ptr( Lag_CB_ptr, k, CBimax, cbk_size ); + } + *lagIndex = (opus_int16)( lag_new - min_lag); + *contourIndex = (opus_int8)CBimax; + } else { + /* Save Lags and correlation */ + CCmax = SKP_max( CCmax, 0 ); + *LTPCorr_Q15 = (opus_int)silk_SQRT_APPROX( SKP_LSHIFT( CCmax, 13 ) ); /* Output normalized correlation */ + for( k = 0; k < nb_subfr; k++ ) { + pitch_out[ k ] = lag + matrix_ptr( Lag_CB_ptr, k, CBimax, cbk_size ); + } + *lagIndex = (opus_int16)( lag - min_lag_8kHz ); + *contourIndex = (opus_int8)CBimax; + } + SKP_assert( *lagIndex >= 0 ); + /* return as voiced */ + return 0; +} + +/*************************************************************************/ +/* Calculates the correlations used in stage 3 search. In order to cover */ +/* the whole lag codebook for all the searched offset lags (lag +- 2), */ +/*************************************************************************/ +void silk_P_Ana_calc_corr_st3( + opus_int32 cross_corr_st3[ PE_MAX_NB_SUBFR ][ PE_NB_CBKS_STAGE3_MAX ][ PE_NB_STAGE3_LAGS ],/* (O) 3 DIM correlation array */ + const opus_int16 signal[], /* I vector to correlate */ + opus_int start_lag, /* I lag offset to search around */ + opus_int sf_length, /* I length of a 5 ms subframe */ + opus_int nb_subfr, /* I number of subframes */ + opus_int complexity /* I Complexity setting */ +) +{ + const opus_int16 *target_ptr, *basis_ptr; + opus_int32 cross_corr; + opus_int i, j, k, lag_counter, lag_low, lag_high; + opus_int nb_cbk_search, delta, idx, cbk_size; + opus_int32 scratch_mem[ SCRATCH_SIZE ]; + const opus_int8 *Lag_range_ptr, *Lag_CB_ptr; + + SKP_assert( complexity >= SILK_PE_MIN_COMPLEX ); + SKP_assert( complexity <= SILK_PE_MAX_COMPLEX ); + + if( nb_subfr == PE_MAX_NB_SUBFR ){ + Lag_range_ptr = &silk_Lag_range_stage3[ complexity ][ 0 ][ 0 ]; + Lag_CB_ptr = &silk_CB_lags_stage3[ 0 ][ 0 ]; + nb_cbk_search = silk_nb_cbk_searchs_stage3[ complexity ]; + cbk_size = PE_NB_CBKS_STAGE3_MAX; + } else { + SKP_assert( nb_subfr == PE_MAX_NB_SUBFR >> 1); + Lag_range_ptr = &silk_Lag_range_stage3_10_ms[ 0 ][ 0 ]; + Lag_CB_ptr = &silk_CB_lags_stage3_10_ms[ 0 ][ 0 ]; + nb_cbk_search = PE_NB_CBKS_STAGE3_10MS; + cbk_size = PE_NB_CBKS_STAGE3_10MS; + } + + target_ptr = &signal[ SKP_LSHIFT( sf_length, 2 ) ]; /* Pointer to middle of frame */ + for( k = 0; k < nb_subfr; k++ ) { + lag_counter = 0; + + /* Calculate the correlations for each subframe */ + lag_low = matrix_ptr( Lag_range_ptr, k, 0, 2 ); + lag_high = matrix_ptr( Lag_range_ptr, k, 1, 2 ); + for( j = lag_low; j <= lag_high; j++ ) { + basis_ptr = target_ptr - ( start_lag + j ); + cross_corr = silk_inner_prod_aligned( (opus_int16*)target_ptr, (opus_int16*)basis_ptr, sf_length ); + SKP_assert( lag_counter < SCRATCH_SIZE ); + scratch_mem[ lag_counter ] = cross_corr; + lag_counter++; + } + + delta = matrix_ptr( Lag_range_ptr, k, 0, 2 ); + for( i = 0; i < nb_cbk_search; i++ ) { + /* Fill out the 3 dim array that stores the correlations for */ + /* each code_book vector for each start lag */ + idx = matrix_ptr( Lag_CB_ptr, k, i, cbk_size ) - delta; + for( j = 0; j < PE_NB_STAGE3_LAGS; j++ ) { + SKP_assert( idx + j < SCRATCH_SIZE ); + SKP_assert( idx + j < lag_counter ); + cross_corr_st3[ k ][ i ][ j ] = scratch_mem[ idx + j ]; + } + } + target_ptr += sf_length; + } +} + +/********************************************************************/ +/* Calculate the energies for first two subframes. The energies are */ +/* calculated recursively. */ +/********************************************************************/ +void silk_P_Ana_calc_energy_st3( + opus_int32 energies_st3[ PE_MAX_NB_SUBFR ][ PE_NB_CBKS_STAGE3_MAX ][ PE_NB_STAGE3_LAGS ],/* (O) 3 DIM energy array */ + const opus_int16 signal[], /* I vector to calc energy in */ + opus_int start_lag, /* I lag offset to search around */ + opus_int sf_length, /* I length of one 5 ms subframe */ + opus_int nb_subfr, /* I number of subframes */ + opus_int complexity /* I Complexity setting */ +) +{ + const opus_int16 *target_ptr, *basis_ptr; + opus_int32 energy; + opus_int k, i, j, lag_counter; + opus_int nb_cbk_search, delta, idx, cbk_size, lag_diff; + opus_int32 scratch_mem[ SCRATCH_SIZE ]; + const opus_int8 *Lag_range_ptr, *Lag_CB_ptr; + + SKP_assert( complexity >= SILK_PE_MIN_COMPLEX ); + SKP_assert( complexity <= SILK_PE_MAX_COMPLEX ); + + if( nb_subfr == PE_MAX_NB_SUBFR ){ + Lag_range_ptr = &silk_Lag_range_stage3[ complexity ][ 0 ][ 0 ]; + Lag_CB_ptr = &silk_CB_lags_stage3[ 0 ][ 0 ]; + nb_cbk_search = silk_nb_cbk_searchs_stage3[ complexity ]; + cbk_size = PE_NB_CBKS_STAGE3_MAX; + } else { + SKP_assert( nb_subfr == PE_MAX_NB_SUBFR >> 1); + Lag_range_ptr = &silk_Lag_range_stage3_10_ms[ 0 ][ 0 ]; + Lag_CB_ptr = &silk_CB_lags_stage3_10_ms[ 0 ][ 0 ]; + nb_cbk_search = PE_NB_CBKS_STAGE3_10MS; + cbk_size = PE_NB_CBKS_STAGE3_10MS; + } + target_ptr = &signal[ SKP_LSHIFT( sf_length, 2 ) ]; + for( k = 0; k < nb_subfr; k++ ) { + lag_counter = 0; + + /* Calculate the energy for first lag */ + basis_ptr = target_ptr - ( start_lag + matrix_ptr( Lag_range_ptr, k, 0, 2 ) ); + energy = silk_inner_prod_aligned( basis_ptr, basis_ptr, sf_length ); + SKP_assert( energy >= 0 ); + scratch_mem[ lag_counter ] = energy; + lag_counter++; + + lag_diff = ( matrix_ptr( Lag_range_ptr, k, 1, 2 ) - matrix_ptr( Lag_range_ptr, k, 0, 2 ) + 1 ); + for( i = 1; i < lag_diff; i++ ) { + /* remove part outside new window */ + energy -= SKP_SMULBB( basis_ptr[ sf_length - i ], basis_ptr[ sf_length - i ] ); + SKP_assert( energy >= 0 ); + + /* add part that comes into window */ + energy = SKP_ADD_SAT32( energy, SKP_SMULBB( basis_ptr[ -i ], basis_ptr[ -i ] ) ); + SKP_assert( energy >= 0 ); + SKP_assert( lag_counter < SCRATCH_SIZE ); + scratch_mem[ lag_counter ] = energy; + lag_counter++; + } + + delta = matrix_ptr( Lag_range_ptr, k, 0, 2 ); + for( i = 0; i < nb_cbk_search; i++ ) { + /* Fill out the 3 dim array that stores the correlations for */ + /* each code_book vector for each start lag */ + idx = matrix_ptr( Lag_CB_ptr, k, i, cbk_size ) - delta; + for( j = 0; j < PE_NB_STAGE3_LAGS; j++ ) { + SKP_assert( idx + j < SCRATCH_SIZE ); + SKP_assert( idx + j < lag_counter ); + energies_st3[ k ][ i ][ j ] = scratch_mem[ idx + j ]; + SKP_assert( energies_st3[ k ][ i ][ j ] >= 0 ); + } + } + target_ptr += sf_length; + } +} + +opus_int32 silk_P_Ana_find_scaling( + const opus_int16 *signal, + const opus_int signal_length, + const opus_int sum_sqr_len +) +{ + opus_int32 nbits, x_max; + + x_max = silk_int16_array_maxabs( signal, signal_length ); + + if( x_max < SKP_int16_MAX ) { + /* Number of bits needed for the sum of the squares */ + nbits = 32 - silk_CLZ32( SKP_SMULBB( x_max, x_max ) ); + } else { + /* Here we don't know if x_max should have been SKP_int16_MAX + 1, so we expect the worst case */ + nbits = 30; + } + nbits += 17 - silk_CLZ16( sum_sqr_len ); + + /* Without a guarantee of saturation, we need to keep the 31st bit free */ + if( nbits < 31 ) { + return 0; + } else { + return( nbits - 30 ); + } +} diff --git a/silk/silk_pitch_est_defines.h b/silk/silk_pitch_est_defines.h index 1a6edb66f..f18c7ca79 100644 --- a/silk/silk_pitch_est_defines.h +++ b/silk/silk_pitch_est_defines.h @@ -1,87 +1,87 @@ -/*********************************************************************** -Copyright (c) 2006-2011, Skype Limited. All rights reserved. -Redistribution and use in source and binary forms, with or without -modification, (subject to the limitations in the disclaimer below) -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 Skype Limited, nor the names of specific -contributors, may be used to endorse or promote products derived from -this software without specific prior written permission. -NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED -BY THIS LICENSE. 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. -***********************************************************************/ - -#ifndef SILK_PE_DEFINES_H -#define SILK_PE_DEFINES_H - -#include "silk_SigProc_FIX.h" - -/************************************************************/ -/* Definitions For Fix pitch estimator */ -/************************************************************/ - -#define PE_MAX_FS_KHZ 16 /* Maximum sampling frequency used */ - -#define PE_MAX_NB_SUBFR 4 -#define PE_SUBFR_LENGTH_MS 5 /* 5 ms */ - -#define PE_LTP_MEM_LENGTH_MS (4 * PE_SUBFR_LENGTH_MS) - -#define PE_MAX_FRAME_LENGTH_MS (PE_LTP_MEM_LENGTH_MS + PE_MAX_NB_SUBFR * PE_SUBFR_LENGTH_MS) -#define PE_MAX_FRAME_LENGTH (PE_MAX_FRAME_LENGTH_MS * PE_MAX_FS_KHZ) -#define PE_MAX_FRAME_LENGTH_ST_1 (PE_MAX_FRAME_LENGTH >> 2) -#define PE_MAX_FRAME_LENGTH_ST_2 (PE_MAX_FRAME_LENGTH >> 1) -#define PE_MAX_SF_FRAME_LENGTH (PE_SUB_FRAME * PE_MAX_FS_KHZ) - -#define PE_MAX_LAG_MS 18 /* 18 ms -> 56 Hz */ -#define PE_MIN_LAG_MS 2 /* 2 ms -> 500 Hz */ -#define PE_MAX_LAG (PE_MAX_LAG_MS * PE_MAX_FS_KHZ) -#define PE_MIN_LAG (PE_MIN_LAG_MS * PE_MAX_FS_KHZ) - -#define PE_D_SRCH_LENGTH 24 - -#define PE_NB_STAGE3_LAGS 5 - -#define PE_NB_CBKS_STAGE2 3 -#define PE_NB_CBKS_STAGE2_EXT 11 - -#define PE_CB_mn2 1 -#define PE_CB_mx2 2 - -#define PE_NB_CBKS_STAGE3_MAX 34 -#define PE_NB_CBKS_STAGE3_MID 24 -#define PE_NB_CBKS_STAGE3_MIN 16 - -#define PE_NB_CBKS_STAGE3_10MS 12 -#define PE_NB_CBKS_STAGE2_10MS 3 - -#define PE_SHORTLAG_BIAS 0.2f /* for logarithmic weighting */ -#define PE_PREVLAG_BIAS 0.2f /* for logarithmic weighting */ -#define PE_FLATCONTOUR_BIAS 0.05f - -extern const opus_int8 silk_CB_lags_stage2[ PE_MAX_NB_SUBFR ][ PE_NB_CBKS_STAGE2_EXT ]; -extern const opus_int8 silk_CB_lags_stage3[ PE_MAX_NB_SUBFR ][ PE_NB_CBKS_STAGE3_MAX ]; -extern const opus_int8 silk_Lag_range_stage3[ SILK_PE_MAX_COMPLEX + 1 ] [ PE_MAX_NB_SUBFR ][ 2 ]; -extern const opus_int8 silk_nb_cbk_searchs_stage3[ SILK_PE_MAX_COMPLEX + 1 ]; - -/* Tables added for 10 ms frames */ -extern const opus_int8 silk_CB_lags_stage2_10_ms[ PE_MAX_NB_SUBFR >> 1][ 3 ]; -extern const opus_int8 silk_CB_lags_stage3_10_ms[ PE_MAX_NB_SUBFR >> 1 ][ 12 ]; -extern const opus_int8 silk_Lag_range_stage3_10_ms[ PE_MAX_NB_SUBFR >> 1 ][ 2 ]; - -#endif - +/*********************************************************************** +Copyright (c) 2006-2011, Skype Limited. All rights reserved. +Redistribution and use in source and binary forms, with or without +modification, (subject to the limitations in the disclaimer below) +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 Skype Limited, nor the names of specific +contributors, may be used to endorse or promote products derived from +this software without specific prior written permission. +NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED +BY THIS LICENSE. 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. +***********************************************************************/ + +#ifndef SILK_PE_DEFINES_H +#define SILK_PE_DEFINES_H + +#include "silk_SigProc_FIX.h" + +/************************************************************/ +/* Definitions For Fix pitch estimator */ +/************************************************************/ + +#define PE_MAX_FS_KHZ 16 /* Maximum sampling frequency used */ + +#define PE_MAX_NB_SUBFR 4 +#define PE_SUBFR_LENGTH_MS 5 /* 5 ms */ + +#define PE_LTP_MEM_LENGTH_MS (4 * PE_SUBFR_LENGTH_MS) + +#define PE_MAX_FRAME_LENGTH_MS (PE_LTP_MEM_LENGTH_MS + PE_MAX_NB_SUBFR * PE_SUBFR_LENGTH_MS) +#define PE_MAX_FRAME_LENGTH (PE_MAX_FRAME_LENGTH_MS * PE_MAX_FS_KHZ) +#define PE_MAX_FRAME_LENGTH_ST_1 (PE_MAX_FRAME_LENGTH >> 2) +#define PE_MAX_FRAME_LENGTH_ST_2 (PE_MAX_FRAME_LENGTH >> 1) +#define PE_MAX_SF_FRAME_LENGTH (PE_SUB_FRAME * PE_MAX_FS_KHZ) + +#define PE_MAX_LAG_MS 18 /* 18 ms -> 56 Hz */ +#define PE_MIN_LAG_MS 2 /* 2 ms -> 500 Hz */ +#define PE_MAX_LAG (PE_MAX_LAG_MS * PE_MAX_FS_KHZ) +#define PE_MIN_LAG (PE_MIN_LAG_MS * PE_MAX_FS_KHZ) + +#define PE_D_SRCH_LENGTH 24 + +#define PE_NB_STAGE3_LAGS 5 + +#define PE_NB_CBKS_STAGE2 3 +#define PE_NB_CBKS_STAGE2_EXT 11 + +#define PE_CB_mn2 1 +#define PE_CB_mx2 2 + +#define PE_NB_CBKS_STAGE3_MAX 34 +#define PE_NB_CBKS_STAGE3_MID 24 +#define PE_NB_CBKS_STAGE3_MIN 16 + +#define PE_NB_CBKS_STAGE3_10MS 12 +#define PE_NB_CBKS_STAGE2_10MS 3 + +#define PE_SHORTLAG_BIAS 0.2f /* for logarithmic weighting */ +#define PE_PREVLAG_BIAS 0.2f /* for logarithmic weighting */ +#define PE_FLATCONTOUR_BIAS 0.05f + +extern const opus_int8 silk_CB_lags_stage2[ PE_MAX_NB_SUBFR ][ PE_NB_CBKS_STAGE2_EXT ]; +extern const opus_int8 silk_CB_lags_stage3[ PE_MAX_NB_SUBFR ][ PE_NB_CBKS_STAGE3_MAX ]; +extern const opus_int8 silk_Lag_range_stage3[ SILK_PE_MAX_COMPLEX + 1 ] [ PE_MAX_NB_SUBFR ][ 2 ]; +extern const opus_int8 silk_nb_cbk_searchs_stage3[ SILK_PE_MAX_COMPLEX + 1 ]; + +/* Tables added for 10 ms frames */ +extern const opus_int8 silk_CB_lags_stage2_10_ms[ PE_MAX_NB_SUBFR >> 1][ 3 ]; +extern const opus_int8 silk_CB_lags_stage3_10_ms[ PE_MAX_NB_SUBFR >> 1 ][ 12 ]; +extern const opus_int8 silk_Lag_range_stage3_10_ms[ PE_MAX_NB_SUBFR >> 1 ][ 2 ]; + +#endif + diff --git a/silk/silk_pitch_est_tables.c b/silk/silk_pitch_est_tables.c index 5a4c35856..ebfb595cb 100644 --- a/silk/silk_pitch_est_tables.c +++ b/silk/silk_pitch_est_tables.c @@ -1,95 +1,95 @@ -/*********************************************************************** -Copyright (c) 2006-2011, Skype Limited. All rights reserved. -Redistribution and use in source and binary forms, with or without -modification, (subject to the limitations in the disclaimer below) -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 Skype Limited, nor the names of specific -contributors, may be used to endorse or promote products derived from -this software without specific prior written permission. -NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED -BY THIS LICENSE. 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. -***********************************************************************/ - -#include "silk_typedef.h" -#include "silk_pitch_est_defines.h" - -const opus_int8 silk_CB_lags_stage2_10_ms[ PE_MAX_NB_SUBFR >> 1][ PE_NB_CBKS_STAGE2_10MS ] = -{ - {0, 1, 0}, - {0, 0, 1} -}; - -const opus_int8 silk_CB_lags_stage3_10_ms[ PE_MAX_NB_SUBFR >> 1 ][ PE_NB_CBKS_STAGE3_10MS ] = -{ - { 0, 0, 1,-1, 1,-1, 2,-2, 2,-2, 3,-3}, - { 0, 1, 0, 1,-1, 2,-1, 2,-2, 3,-2, 3} -}; - -const opus_int8 silk_Lag_range_stage3_10_ms[ PE_MAX_NB_SUBFR >> 1 ][ 2 ] = -{ - {-3, 7}, - {-2, 7} -}; - -const opus_int8 silk_CB_lags_stage2[ PE_MAX_NB_SUBFR ][ PE_NB_CBKS_STAGE2_EXT ] = -{ - {0, 2,-1,-1,-1, 0, 0, 1, 1, 0, 1}, - {0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0}, - {0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0}, - {0,-1, 2, 1, 0, 1, 1, 0, 0,-1,-1} -}; - -const opus_int8 silk_CB_lags_stage3[ PE_MAX_NB_SUBFR ][ PE_NB_CBKS_STAGE3_MAX ] = -{ - {0, 0, 1,-1, 0, 1,-1, 0,-1, 1,-2, 2,-2,-2, 2,-3, 2, 3,-3,-4, 3,-4, 4, 4,-5, 5,-6,-5, 6,-7, 6, 5, 8,-9}, - {0, 0, 1, 0, 0, 0, 0, 0, 0, 0,-1, 1, 0, 0, 1,-1, 0, 1,-1,-1, 1,-1, 2, 1,-1, 2,-2,-2, 2,-2, 2, 2, 3,-3}, - {0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 1,-1, 1, 0, 0, 2, 1,-1, 2,-1,-1, 2,-1, 2, 2,-1, 3,-2,-2,-2, 3}, - {0, 1, 0, 0, 1, 0, 1,-1, 2,-1, 2,-1, 2, 3,-2, 3,-2,-2, 4, 4,-3, 5,-3,-4, 6,-4, 6, 5,-5, 8,-6,-5,-7, 9} -}; - -const opus_int8 silk_Lag_range_stage3[ SILK_PE_MAX_COMPLEX + 1 ] [ PE_MAX_NB_SUBFR ][ 2 ] = -{ - /* Lags to search for low number of stage3 cbks */ - { - {-5,8}, - {-1,6}, - {-1,6}, - {-4,10} - }, - /* Lags to search for middle number of stage3 cbks */ - { - {-6,10}, - {-2,6}, - {-1,6}, - {-5,10} - }, - /* Lags to search for max number of stage3 cbks */ - { - {-9,12}, - {-3,7}, - {-2,7}, - {-7,13} - } -}; - -const opus_int8 silk_nb_cbk_searchs_stage3[ SILK_PE_MAX_COMPLEX + 1 ] = -{ - PE_NB_CBKS_STAGE3_MIN, - PE_NB_CBKS_STAGE3_MID, - PE_NB_CBKS_STAGE3_MAX -}; +/*********************************************************************** +Copyright (c) 2006-2011, Skype Limited. All rights reserved. +Redistribution and use in source and binary forms, with or without +modification, (subject to the limitations in the disclaimer below) +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 Skype Limited, nor the names of specific +contributors, may be used to endorse or promote products derived from +this software without specific prior written permission. +NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED +BY THIS LICENSE. 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. +***********************************************************************/ + +#include "silk_typedef.h" +#include "silk_pitch_est_defines.h" + +const opus_int8 silk_CB_lags_stage2_10_ms[ PE_MAX_NB_SUBFR >> 1][ PE_NB_CBKS_STAGE2_10MS ] = +{ + {0, 1, 0}, + {0, 0, 1} +}; + +const opus_int8 silk_CB_lags_stage3_10_ms[ PE_MAX_NB_SUBFR >> 1 ][ PE_NB_CBKS_STAGE3_10MS ] = +{ + { 0, 0, 1,-1, 1,-1, 2,-2, 2,-2, 3,-3}, + { 0, 1, 0, 1,-1, 2,-1, 2,-2, 3,-2, 3} +}; + +const opus_int8 silk_Lag_range_stage3_10_ms[ PE_MAX_NB_SUBFR >> 1 ][ 2 ] = +{ + {-3, 7}, + {-2, 7} +}; + +const opus_int8 silk_CB_lags_stage2[ PE_MAX_NB_SUBFR ][ PE_NB_CBKS_STAGE2_EXT ] = +{ + {0, 2,-1,-1,-1, 0, 0, 1, 1, 0, 1}, + {0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0}, + {0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0}, + {0,-1, 2, 1, 0, 1, 1, 0, 0,-1,-1} +}; + +const opus_int8 silk_CB_lags_stage3[ PE_MAX_NB_SUBFR ][ PE_NB_CBKS_STAGE3_MAX ] = +{ + {0, 0, 1,-1, 0, 1,-1, 0,-1, 1,-2, 2,-2,-2, 2,-3, 2, 3,-3,-4, 3,-4, 4, 4,-5, 5,-6,-5, 6,-7, 6, 5, 8,-9}, + {0, 0, 1, 0, 0, 0, 0, 0, 0, 0,-1, 1, 0, 0, 1,-1, 0, 1,-1,-1, 1,-1, 2, 1,-1, 2,-2,-2, 2,-2, 2, 2, 3,-3}, + {0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 1,-1, 1, 0, 0, 2, 1,-1, 2,-1,-1, 2,-1, 2, 2,-1, 3,-2,-2,-2, 3}, + {0, 1, 0, 0, 1, 0, 1,-1, 2,-1, 2,-1, 2, 3,-2, 3,-2,-2, 4, 4,-3, 5,-3,-4, 6,-4, 6, 5,-5, 8,-6,-5,-7, 9} +}; + +const opus_int8 silk_Lag_range_stage3[ SILK_PE_MAX_COMPLEX + 1 ] [ PE_MAX_NB_SUBFR ][ 2 ] = +{ + /* Lags to search for low number of stage3 cbks */ + { + {-5,8}, + {-1,6}, + {-1,6}, + {-4,10} + }, + /* Lags to search for middle number of stage3 cbks */ + { + {-6,10}, + {-2,6}, + {-1,6}, + {-5,10} + }, + /* Lags to search for max number of stage3 cbks */ + { + {-9,12}, + {-3,7}, + {-2,7}, + {-7,13} + } +}; + +const opus_int8 silk_nb_cbk_searchs_stage3[ SILK_PE_MAX_COMPLEX + 1 ] = +{ + PE_NB_CBKS_STAGE3_MIN, + PE_NB_CBKS_STAGE3_MID, + PE_NB_CBKS_STAGE3_MAX +}; diff --git a/silk/silk_process_NLSFs.c b/silk/silk_process_NLSFs.c index 57329c4e7..c0a7703e5 100644 --- a/silk/silk_process_NLSFs.c +++ b/silk/silk_process_NLSFs.c @@ -1,103 +1,103 @@ -/*********************************************************************** -Copyright (c) 2006-2011, Skype Limited. All rights reserved. -Redistribution and use in source and binary forms, with or without -modification, (subject to the limitations in the disclaimer below) -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 Skype Limited, nor the names of specific -contributors, may be used to endorse or promote products derived from -this software without specific prior written permission. -NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED -BY THIS LICENSE. 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. -***********************************************************************/ - -#include "silk_main.h" - -/* Limit, stabilize, convert and quantize NLSFs */ -void silk_process_NLSFs( - silk_encoder_state *psEncC, /* I/O Encoder state */ - opus_int16 PredCoef_Q12[ 2 ][ MAX_LPC_ORDER ], /* O Prediction coefficients */ - opus_int16 pNLSF_Q15[ MAX_LPC_ORDER ], /* I/O Normalized LSFs (quant out) (0 - (2^15-1)) */ - const opus_int16 prev_NLSFq_Q15[ MAX_LPC_ORDER ] /* I Previous Normalized LSFs (0 - (2^15-1)) */ -) -{ - opus_int i, doInterpolate; - opus_int NLSF_mu_Q20; - opus_int32 i_sqr_Q15; - opus_int16 pNLSF0_temp_Q15[ MAX_LPC_ORDER ]; - opus_int16 pNLSFW_QW[ MAX_LPC_ORDER ]; - opus_int16 pNLSFW0_temp_QW[ MAX_LPC_ORDER ]; - - SKP_assert( psEncC->speech_activity_Q8 >= 0 ); - SKP_assert( psEncC->speech_activity_Q8 <= SILK_FIX_CONST( 1.0, 8 ) ); - - /***********************/ - /* Calculate mu values */ - /***********************/ - /* NLSF_mu = 0.003 - 0.0015 * psEnc->speech_activity; */ - NLSF_mu_Q20 = SKP_SMLAWB( SILK_FIX_CONST( 0.0025, 20 ), SILK_FIX_CONST( -0.001, 28 ), psEncC->speech_activity_Q8 ); - if( psEncC->nb_subfr == 2 ) { - /* Multiply by 1.5 for 10 ms packets */ - NLSF_mu_Q20 = SKP_ADD_RSHIFT( NLSF_mu_Q20, NLSF_mu_Q20, 1 ); - } - - SKP_assert( NLSF_mu_Q20 > 0 ); - SKP_assert( NLSF_mu_Q20 <= SILK_FIX_CONST( 0.0045, 20 ) ); - - /* Calculate NLSF weights */ - silk_NLSF_VQ_weights_laroia( pNLSFW_QW, pNLSF_Q15, psEncC->predictLPCOrder ); - - /* Update NLSF weights for interpolated NLSFs */ - doInterpolate = ( psEncC->useInterpolatedNLSFs == 1 ) && ( psEncC->indices.NLSFInterpCoef_Q2 < 4 ); - if( doInterpolate ) { - /* Calculate the interpolated NLSF vector for the first half */ - silk_interpolate( pNLSF0_temp_Q15, prev_NLSFq_Q15, pNLSF_Q15, - psEncC->indices.NLSFInterpCoef_Q2, psEncC->predictLPCOrder ); - - /* Calculate first half NLSF weights for the interpolated NLSFs */ - silk_NLSF_VQ_weights_laroia( pNLSFW0_temp_QW, pNLSF0_temp_Q15, psEncC->predictLPCOrder ); - - /* Update NLSF weights with contribution from first half */ - i_sqr_Q15 = SKP_LSHIFT( SKP_SMULBB( psEncC->indices.NLSFInterpCoef_Q2, psEncC->indices.NLSFInterpCoef_Q2 ), 11 ); - for( i = 0; i < psEncC->predictLPCOrder; i++ ) { - pNLSFW_QW[ i ] = SKP_SMLAWB( SKP_RSHIFT( pNLSFW_QW[ i ], 1 ), pNLSFW0_temp_QW[ i ], i_sqr_Q15 ); - SKP_assert( pNLSFW_QW[ i ] <= SKP_int16_MAX ); - SKP_assert( pNLSFW_QW[ i ] >= 1 ); - } - } - - TIC(NLSF_encode) - silk_NLSF_encode( psEncC->indices.NLSFIndices, pNLSF_Q15, psEncC->psNLSF_CB, pNLSFW_QW, - NLSF_mu_Q20, psEncC->NLSF_MSVQ_Survivors, psEncC->indices.signalType ); - TOC(NLSF_encode) - - /* Convert quantized NLSFs back to LPC coefficients */ - silk_NLSF2A( PredCoef_Q12[ 1 ], pNLSF_Q15, psEncC->predictLPCOrder ); - - if( doInterpolate ) { - /* Calculate the interpolated, quantized LSF vector for the first half */ - silk_interpolate( pNLSF0_temp_Q15, prev_NLSFq_Q15, pNLSF_Q15, - psEncC->indices.NLSFInterpCoef_Q2, psEncC->predictLPCOrder ); - - /* Convert back to LPC coefficients */ - silk_NLSF2A( PredCoef_Q12[ 0 ], pNLSF0_temp_Q15, psEncC->predictLPCOrder ); - - } else { - /* Copy LPC coefficients for first half from second half */ - SKP_memcpy( PredCoef_Q12[ 0 ], PredCoef_Q12[ 1 ], psEncC->predictLPCOrder * sizeof( opus_int16 ) ); - } -} +/*********************************************************************** +Copyright (c) 2006-2011, Skype Limited. All rights reserved. +Redistribution and use in source and binary forms, with or without +modification, (subject to the limitations in the disclaimer below) +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 Skype Limited, nor the names of specific +contributors, may be used to endorse or promote products derived from +this software without specific prior written permission. +NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED +BY THIS LICENSE. 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. +***********************************************************************/ + +#include "silk_main.h" + +/* Limit, stabilize, convert and quantize NLSFs */ +void silk_process_NLSFs( + silk_encoder_state *psEncC, /* I/O Encoder state */ + opus_int16 PredCoef_Q12[ 2 ][ MAX_LPC_ORDER ], /* O Prediction coefficients */ + opus_int16 pNLSF_Q15[ MAX_LPC_ORDER ], /* I/O Normalized LSFs (quant out) (0 - (2^15-1)) */ + const opus_int16 prev_NLSFq_Q15[ MAX_LPC_ORDER ] /* I Previous Normalized LSFs (0 - (2^15-1)) */ +) +{ + opus_int i, doInterpolate; + opus_int NLSF_mu_Q20; + opus_int32 i_sqr_Q15; + opus_int16 pNLSF0_temp_Q15[ MAX_LPC_ORDER ]; + opus_int16 pNLSFW_QW[ MAX_LPC_ORDER ]; + opus_int16 pNLSFW0_temp_QW[ MAX_LPC_ORDER ]; + + SKP_assert( psEncC->speech_activity_Q8 >= 0 ); + SKP_assert( psEncC->speech_activity_Q8 <= SILK_FIX_CONST( 1.0, 8 ) ); + + /***********************/ + /* Calculate mu values */ + /***********************/ + /* NLSF_mu = 0.003 - 0.0015 * psEnc->speech_activity; */ + NLSF_mu_Q20 = SKP_SMLAWB( SILK_FIX_CONST( 0.0025, 20 ), SILK_FIX_CONST( -0.001, 28 ), psEncC->speech_activity_Q8 ); + if( psEncC->nb_subfr == 2 ) { + /* Multiply by 1.5 for 10 ms packets */ + NLSF_mu_Q20 = SKP_ADD_RSHIFT( NLSF_mu_Q20, NLSF_mu_Q20, 1 ); + } + + SKP_assert( NLSF_mu_Q20 > 0 ); + SKP_assert( NLSF_mu_Q20 <= SILK_FIX_CONST( 0.0045, 20 ) ); + + /* Calculate NLSF weights */ + silk_NLSF_VQ_weights_laroia( pNLSFW_QW, pNLSF_Q15, psEncC->predictLPCOrder ); + + /* Update NLSF weights for interpolated NLSFs */ + doInterpolate = ( psEncC->useInterpolatedNLSFs == 1 ) && ( psEncC->indices.NLSFInterpCoef_Q2 < 4 ); + if( doInterpolate ) { + /* Calculate the interpolated NLSF vector for the first half */ + silk_interpolate( pNLSF0_temp_Q15, prev_NLSFq_Q15, pNLSF_Q15, + psEncC->indices.NLSFInterpCoef_Q2, psEncC->predictLPCOrder ); + + /* Calculate first half NLSF weights for the interpolated NLSFs */ + silk_NLSF_VQ_weights_laroia( pNLSFW0_temp_QW, pNLSF0_temp_Q15, psEncC->predictLPCOrder ); + + /* Update NLSF weights with contribution from first half */ + i_sqr_Q15 = SKP_LSHIFT( SKP_SMULBB( psEncC->indices.NLSFInterpCoef_Q2, psEncC->indices.NLSFInterpCoef_Q2 ), 11 ); + for( i = 0; i < psEncC->predictLPCOrder; i++ ) { + pNLSFW_QW[ i ] = SKP_SMLAWB( SKP_RSHIFT( pNLSFW_QW[ i ], 1 ), pNLSFW0_temp_QW[ i ], i_sqr_Q15 ); + SKP_assert( pNLSFW_QW[ i ] <= SKP_int16_MAX ); + SKP_assert( pNLSFW_QW[ i ] >= 1 ); + } + } + + TIC(NLSF_encode) + silk_NLSF_encode( psEncC->indices.NLSFIndices, pNLSF_Q15, psEncC->psNLSF_CB, pNLSFW_QW, + NLSF_mu_Q20, psEncC->NLSF_MSVQ_Survivors, psEncC->indices.signalType ); + TOC(NLSF_encode) + + /* Convert quantized NLSFs back to LPC coefficients */ + silk_NLSF2A( PredCoef_Q12[ 1 ], pNLSF_Q15, psEncC->predictLPCOrder ); + + if( doInterpolate ) { + /* Calculate the interpolated, quantized LSF vector for the first half */ + silk_interpolate( pNLSF0_temp_Q15, prev_NLSFq_Q15, pNLSF_Q15, + psEncC->indices.NLSFInterpCoef_Q2, psEncC->predictLPCOrder ); + + /* Convert back to LPC coefficients */ + silk_NLSF2A( PredCoef_Q12[ 0 ], pNLSF0_temp_Q15, psEncC->predictLPCOrder ); + + } else { + /* Copy LPC coefficients for first half from second half */ + SKP_memcpy( PredCoef_Q12[ 0 ], PredCoef_Q12[ 1 ], psEncC->predictLPCOrder * sizeof( opus_int16 ) ); + } +} diff --git a/silk/silk_quant_LTP_gains.c b/silk/silk_quant_LTP_gains.c index 6d68ead3b..bb803824c 100644 --- a/silk/silk_quant_LTP_gains.c +++ b/silk/silk_quant_LTP_gains.c @@ -1,107 +1,107 @@ -/*********************************************************************** -Copyright (c) 2006-2011, Skype Limited. All rights reserved. -Redistribution and use in source and binary forms, with or without -modification, (subject to the limitations in the disclaimer below) -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 Skype Limited, nor the names of specific -contributors, may be used to endorse or promote products derived from -this software without specific prior written permission. -NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED -BY THIS LICENSE. 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. -***********************************************************************/ - -#include "silk_main.h" - -void silk_quant_LTP_gains( - opus_int16 B_Q14[ MAX_NB_SUBFR * LTP_ORDER ], /* I/O (un)quantized LTP gains */ - opus_int8 cbk_index[ MAX_NB_SUBFR ], /* O Codebook Index */ - opus_int8 *periodicity_index, /* O Periodicity Index */ - const opus_int32 W_Q18[ MAX_NB_SUBFR*LTP_ORDER*LTP_ORDER ], /* I Error Weights in Q18 */ - opus_int mu_Q9, /* I Mu value (R/D tradeoff) */ - opus_int lowComplexity, /* I Flag for low complexity */ - const opus_int nb_subfr /* I number of subframes */ -) -{ - opus_int j, k, cbk_size; - opus_int8 temp_idx[ MAX_NB_SUBFR ]; - const opus_uint8 *cl_ptr_Q5; - const opus_int8 *cbk_ptr_Q7; - const opus_int16 *b_Q14_ptr; - const opus_int32 *W_Q18_ptr; - opus_int32 rate_dist_Q14_subfr, rate_dist_Q14, min_rate_dist_Q14; - -TIC(quant_LTP) - - /***************************************************/ - /* iterate over different codebooks with different */ - /* rates/distortions, and choose best */ - /***************************************************/ - min_rate_dist_Q14 = SKP_int32_MAX; - for( k = 0; k < 3; k++ ) { - cl_ptr_Q5 = silk_LTP_gain_BITS_Q5_ptrs[ k ]; - cbk_ptr_Q7 = silk_LTP_vq_ptrs_Q7[ k ]; - cbk_size = silk_LTP_vq_sizes[ k ]; - - /* Setup pointer to first subframe */ - W_Q18_ptr = W_Q18; - b_Q14_ptr = B_Q14; - - rate_dist_Q14 = 0; - for( j = 0; j < nb_subfr; j++ ) { - - silk_VQ_WMat_EC( - &temp_idx[ j ], /* O index of best codebook vector */ - &rate_dist_Q14_subfr, /* O best weighted quantization error + mu * rate */ - b_Q14_ptr, /* I input vector to be quantized */ - W_Q18_ptr, /* I weighting matrix */ - cbk_ptr_Q7, /* I codebook */ - cl_ptr_Q5, /* I code length for each codebook vector */ - mu_Q9, /* I tradeoff between weighted error and rate */ - cbk_size /* I number of vectors in codebook */ - ); - - rate_dist_Q14 = SKP_ADD_POS_SAT32( rate_dist_Q14, rate_dist_Q14_subfr ); - - b_Q14_ptr += LTP_ORDER; - W_Q18_ptr += LTP_ORDER * LTP_ORDER; - } - - /* Avoid never finding a codebook */ - rate_dist_Q14 = SKP_min( SKP_int32_MAX - 1, rate_dist_Q14 ); - - if( rate_dist_Q14 < min_rate_dist_Q14 ) { - min_rate_dist_Q14 = rate_dist_Q14; - *periodicity_index = (opus_int8)k; - SKP_memcpy( cbk_index, temp_idx, nb_subfr * sizeof( opus_int8 ) ); - } - - /* Break early in low-complexity mode if rate distortion is below threshold */ - if( lowComplexity && ( rate_dist_Q14 < silk_LTP_gain_middle_avg_RD_Q14 ) ) { - break; - } - } - - cbk_ptr_Q7 = silk_LTP_vq_ptrs_Q7[ *periodicity_index ]; - for( j = 0; j < nb_subfr; j++ ) { - for( k = 0; k < LTP_ORDER; k++ ) { - B_Q14[ j * LTP_ORDER + k ] = SKP_LSHIFT( cbk_ptr_Q7[ cbk_index[ j ] * LTP_ORDER + k ], 7 ); - } - } -TOC(quant_LTP) -} - +/*********************************************************************** +Copyright (c) 2006-2011, Skype Limited. All rights reserved. +Redistribution and use in source and binary forms, with or without +modification, (subject to the limitations in the disclaimer below) +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 Skype Limited, nor the names of specific +contributors, may be used to endorse or promote products derived from +this software without specific prior written permission. +NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED +BY THIS LICENSE. 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. +***********************************************************************/ + +#include "silk_main.h" + +void silk_quant_LTP_gains( + opus_int16 B_Q14[ MAX_NB_SUBFR * LTP_ORDER ], /* I/O (un)quantized LTP gains */ + opus_int8 cbk_index[ MAX_NB_SUBFR ], /* O Codebook Index */ + opus_int8 *periodicity_index, /* O Periodicity Index */ + const opus_int32 W_Q18[ MAX_NB_SUBFR*LTP_ORDER*LTP_ORDER ], /* I Error Weights in Q18 */ + opus_int mu_Q9, /* I Mu value (R/D tradeoff) */ + opus_int lowComplexity, /* I Flag for low complexity */ + const opus_int nb_subfr /* I number of subframes */ +) +{ + opus_int j, k, cbk_size; + opus_int8 temp_idx[ MAX_NB_SUBFR ]; + const opus_uint8 *cl_ptr_Q5; + const opus_int8 *cbk_ptr_Q7; + const opus_int16 *b_Q14_ptr; + const opus_int32 *W_Q18_ptr; + opus_int32 rate_dist_Q14_subfr, rate_dist_Q14, min_rate_dist_Q14; + +TIC(quant_LTP) + + /***************************************************/ + /* iterate over different codebooks with different */ + /* rates/distortions, and choose best */ + /***************************************************/ + min_rate_dist_Q14 = SKP_int32_MAX; + for( k = 0; k < 3; k++ ) { + cl_ptr_Q5 = silk_LTP_gain_BITS_Q5_ptrs[ k ]; + cbk_ptr_Q7 = silk_LTP_vq_ptrs_Q7[ k ]; + cbk_size = silk_LTP_vq_sizes[ k ]; + + /* Setup pointer to first subframe */ + W_Q18_ptr = W_Q18; + b_Q14_ptr = B_Q14; + + rate_dist_Q14 = 0; + for( j = 0; j < nb_subfr; j++ ) { + + silk_VQ_WMat_EC( + &temp_idx[ j ], /* O index of best codebook vector */ + &rate_dist_Q14_subfr, /* O best weighted quantization error + mu * rate */ + b_Q14_ptr, /* I input vector to be quantized */ + W_Q18_ptr, /* I weighting matrix */ + cbk_ptr_Q7, /* I codebook */ + cl_ptr_Q5, /* I code length for each codebook vector */ + mu_Q9, /* I tradeoff between weighted error and rate */ + cbk_size /* I number of vectors in codebook */ + ); + + rate_dist_Q14 = SKP_ADD_POS_SAT32( rate_dist_Q14, rate_dist_Q14_subfr ); + + b_Q14_ptr += LTP_ORDER; + W_Q18_ptr += LTP_ORDER * LTP_ORDER; + } + + /* Avoid never finding a codebook */ + rate_dist_Q14 = SKP_min( SKP_int32_MAX - 1, rate_dist_Q14 ); + + if( rate_dist_Q14 < min_rate_dist_Q14 ) { + min_rate_dist_Q14 = rate_dist_Q14; + *periodicity_index = (opus_int8)k; + SKP_memcpy( cbk_index, temp_idx, nb_subfr * sizeof( opus_int8 ) ); + } + + /* Break early in low-complexity mode if rate distortion is below threshold */ + if( lowComplexity && ( rate_dist_Q14 < silk_LTP_gain_middle_avg_RD_Q14 ) ) { + break; + } + } + + cbk_ptr_Q7 = silk_LTP_vq_ptrs_Q7[ *periodicity_index ]; + for( j = 0; j < nb_subfr; j++ ) { + for( k = 0; k < LTP_ORDER; k++ ) { + B_Q14[ j * LTP_ORDER + k ] = SKP_LSHIFT( cbk_ptr_Q7[ cbk_index[ j ] * LTP_ORDER + k ], 7 ); + } + } +TOC(quant_LTP) +} + diff --git a/silk/silk_resampler.c b/silk/silk_resampler.c index 1f3d2f0b3..ae0077e8d 100644 --- a/silk/silk_resampler.c +++ b/silk/silk_resampler.c @@ -1,314 +1,314 @@ -/*********************************************************************** -Copyright (c) 2006-2011, Skype Limited. All rights reserved. -Redistribution and use in source and binary forms, with or without -modification, (subject to the limitations in the disclaimer below) -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 Skype Limited, nor the names of specific -contributors, may be used to endorse or promote products derived from -this software without specific prior written permission. -NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED -BY THIS LICENSE. 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. -***********************************************************************/ - -/* Matrix of resampling methods used: - * Fs_out (kHz) - * 8 12 16 24 32 44.1 48 - * - * 8 C UF U UF UF UF UF - * 12 AF C UF U UF UF UF - * 16 D AF C UF U UF UF - * Fs_in (kHz) 24 AIF D AF C UF UF U - * 32 UF AF D AF C UF UF - * 44.1 AMI AMI AMI AMI AMI C UF - * 48 DAF DAF AF D AF UF C - * - * default method: UF - * - * C -> Copy (no resampling) - * D -> Allpass-based 2x downsampling - * U -> Allpass-based 2x upsampling - * DAF -> Allpass-based 2x downsampling followed by AR2 filter followed by FIR interpolation - * UF -> Allpass-based 2x upsampling followed by FIR interpolation - * AMI -> ARMA4 filter followed by FIR interpolation - * AF -> AR2 filter followed by FIR interpolation - * - * Input signals sampled above 48 kHz are first downsampled to at most 48 kHz. - * Output signals sampled above 48 kHz are upsampled from at most 48 kHz. - */ - -#include "silk_resampler_private.h" - -/* Greatest common divisor */ -static opus_int32 gcd( - opus_int32 a, - opus_int32 b -) -{ - opus_int32 tmp; - while( b > 0 ) { - tmp = a - b * SKP_DIV32( a, b ); - a = b; - b = tmp; - } - return a; -} - -/* Initialize/reset the resampler state for a given pair of input/output sampling rates */ -opus_int silk_resampler_init( - silk_resampler_state_struct *S, /* I/O: Resampler state */ - opus_int32 Fs_Hz_in, /* I: Input sampling rate (Hz) */ - opus_int32 Fs_Hz_out /* I: Output sampling rate (Hz) */ -) -{ - opus_int32 cycleLen, cyclesPerBatch, up2 = 0, down2 = 0; - - /* Clear state */ - SKP_memset( S, 0, sizeof( silk_resampler_state_struct ) ); - - /* Input checking */ -#if RESAMPLER_SUPPORT_ABOVE_48KHZ - if( Fs_Hz_in < 8000 || Fs_Hz_in > 192000 || Fs_Hz_out < 8000 || Fs_Hz_out > 192000 ) { -#else - if( Fs_Hz_in < 8000 || Fs_Hz_in > 48000 || Fs_Hz_out < 8000 || Fs_Hz_out > 48000 ) { -#endif - SKP_assert( 0 ); - return -1; - } - -#if RESAMPLER_SUPPORT_ABOVE_48KHZ - /* Determine pre downsampling and post upsampling */ - if( Fs_Hz_in > 96000 ) { - S->nPreDownsamplers = 2; - S->down_pre_function = silk_resampler_private_down4; - } else if( Fs_Hz_in > 48000 ) { - S->nPreDownsamplers = 1; - S->down_pre_function = silk_resampler_down2; - } else { - S->nPreDownsamplers = 0; - S->down_pre_function = NULL; - } - - if( Fs_Hz_out > 96000 ) { - S->nPostUpsamplers = 2; - S->up_post_function = silk_resampler_private_up4; - } else if( Fs_Hz_out > 48000 ) { - S->nPostUpsamplers = 1; - S->up_post_function = silk_resampler_up2; - } else { - S->nPostUpsamplers = 0; - S->up_post_function = NULL; - } - - if( S->nPreDownsamplers + S->nPostUpsamplers > 0 ) { - /* Ratio of output/input samples */ - S->ratio_Q16 = SKP_LSHIFT32( SKP_DIV32( SKP_LSHIFT32( Fs_Hz_out, 13 ), Fs_Hz_in ), 3 ); - /* Make sure the ratio is rounded up */ - while( SKP_SMULWW( S->ratio_Q16, Fs_Hz_in ) < Fs_Hz_out ) S->ratio_Q16++; - - /* Batch size is 10 ms */ - S->batchSizePrePost = SKP_DIV32_16( Fs_Hz_in, 100 ); - - /* Convert sampling rate to those after pre-downsampling and before post-upsampling */ - Fs_Hz_in = SKP_RSHIFT( Fs_Hz_in, S->nPreDownsamplers ); - Fs_Hz_out = SKP_RSHIFT( Fs_Hz_out, S->nPostUpsamplers ); - } -#endif - - /* Number of samples processed per batch */ - /* First, try 10 ms frames */ - S->batchSize = SKP_DIV32_16( Fs_Hz_in, 100 ); - if( ( SKP_MUL( S->batchSize, 100 ) != Fs_Hz_in ) || ( Fs_Hz_in % 100 != 0 ) ) { - /* No integer number of input or output samples with 10 ms frames, use greatest common divisor */ - cycleLen = SKP_DIV32( Fs_Hz_in, gcd( Fs_Hz_in, Fs_Hz_out ) ); - cyclesPerBatch = SKP_DIV32( RESAMPLER_MAX_BATCH_SIZE_IN, cycleLen ); - if( cyclesPerBatch == 0 ) { - /* cycleLen too big, let's just use the maximum batch size. Some distortion will result. */ - S->batchSize = RESAMPLER_MAX_BATCH_SIZE_IN; - SKP_assert( 0 ); - } else { - S->batchSize = SKP_MUL( cyclesPerBatch, cycleLen ); - } - } - - - /* Find resampler with the right sampling ratio */ - if( Fs_Hz_out > Fs_Hz_in ) { - /* Upsample */ - if( Fs_Hz_out == SKP_MUL( Fs_Hz_in, 2 ) ) { /* Fs_out : Fs_in = 2 : 1 */ - /* Special case: directly use 2x upsampler */ - S->resampler_function = silk_resampler_private_up2_HQ_wrapper; - } else { - /* Default resampler */ - S->resampler_function = silk_resampler_private_IIR_FIR; - up2 = 1; - if( Fs_Hz_in > 24000 ) { - /* Low-quality all-pass upsampler */ - S->up2_function = silk_resampler_up2; - } else { - /* High-quality all-pass upsampler */ - S->up2_function = silk_resampler_private_up2_HQ; - } - } - } else if ( Fs_Hz_out < Fs_Hz_in ) { - /* Downsample */ - if( SKP_MUL( Fs_Hz_out, 4 ) == SKP_MUL( Fs_Hz_in, 3 ) ) { /* Fs_out : Fs_in = 3 : 4 */ - S->FIR_Fracs = 3; - S->Coefs = silk_Resampler_3_4_COEFS; - S->resampler_function = silk_resampler_private_down_FIR; - } else if( SKP_MUL( Fs_Hz_out, 3 ) == SKP_MUL( Fs_Hz_in, 2 ) ) { /* Fs_out : Fs_in = 2 : 3 */ - S->FIR_Fracs = 2; - S->Coefs = silk_Resampler_2_3_COEFS; - S->resampler_function = silk_resampler_private_down_FIR; - } else if( SKP_MUL( Fs_Hz_out, 2 ) == Fs_Hz_in ) { /* Fs_out : Fs_in = 1 : 2 */ - S->FIR_Fracs = 1; - S->Coefs = silk_Resampler_1_2_COEFS; - S->resampler_function = silk_resampler_private_down_FIR; - } else if( SKP_MUL( Fs_Hz_out, 8 ) == SKP_MUL( Fs_Hz_in, 3 ) ) { /* Fs_out : Fs_in = 3 : 8 */ - S->FIR_Fracs = 3; - S->Coefs = silk_Resampler_3_8_COEFS; - S->resampler_function = silk_resampler_private_down_FIR; - } else if( SKP_MUL( Fs_Hz_out, 3 ) == Fs_Hz_in ) { /* Fs_out : Fs_in = 1 : 3 */ - S->FIR_Fracs = 1; - S->Coefs = silk_Resampler_1_3_COEFS; - S->resampler_function = silk_resampler_private_down_FIR; - } else if( SKP_MUL( Fs_Hz_out, 4 ) == Fs_Hz_in ) { /* Fs_out : Fs_in = 1 : 4 */ - S->FIR_Fracs = 1; - down2 = 1; - S->Coefs = silk_Resampler_1_2_COEFS; - S->resampler_function = silk_resampler_private_down_FIR; - } else if( SKP_MUL( Fs_Hz_out, 6 ) == Fs_Hz_in ) { /* Fs_out : Fs_in = 1 : 6 */ - S->FIR_Fracs = 1; - down2 = 1; - S->Coefs = silk_Resampler_1_3_COEFS; - S->resampler_function = silk_resampler_private_down_FIR; - } else if( SKP_MUL( Fs_Hz_out, 441 ) == SKP_MUL( Fs_Hz_in, 80 ) ) { /* Fs_out : Fs_in = 80 : 441 */ - S->Coefs = silk_Resampler_80_441_ARMA4_COEFS; - S->resampler_function = silk_resampler_private_IIR_FIR; - } else if( SKP_MUL( Fs_Hz_out, 441 ) == SKP_MUL( Fs_Hz_in, 120 ) ) { /* Fs_out : Fs_in = 120 : 441 */ - S->Coefs = silk_Resampler_120_441_ARMA4_COEFS; - S->resampler_function = silk_resampler_private_IIR_FIR; - } else if( SKP_MUL( Fs_Hz_out, 441 ) == SKP_MUL( Fs_Hz_in, 160 ) ) { /* Fs_out : Fs_in = 160 : 441 */ - S->Coefs = silk_Resampler_160_441_ARMA4_COEFS; - S->resampler_function = silk_resampler_private_IIR_FIR; - } else if( SKP_MUL( Fs_Hz_out, 441 ) == SKP_MUL( Fs_Hz_in, 240 ) ) { /* Fs_out : Fs_in = 240 : 441 */ - S->Coefs = silk_Resampler_240_441_ARMA4_COEFS; - S->resampler_function = silk_resampler_private_IIR_FIR; - } else if( SKP_MUL( Fs_Hz_out, 441 ) == SKP_MUL( Fs_Hz_in, 320 ) ) { /* Fs_out : Fs_in = 320 : 441 */ - S->Coefs = silk_Resampler_320_441_ARMA4_COEFS; - S->resampler_function = silk_resampler_private_IIR_FIR; - } else { - /* Default resampler */ - S->resampler_function = silk_resampler_private_IIR_FIR; - up2 = 1; - if( Fs_Hz_in > 24000 ) { - /* Low-quality all-pass upsampler */ - S->up2_function = silk_resampler_up2; - } else { - /* High-quality all-pass upsampler */ - S->up2_function = silk_resampler_private_up2_HQ; - } - } - } else { - /* Input and output sampling rates are equal: copy */ - S->resampler_function = silk_resampler_private_copy; - } - - S->input2x = up2 | down2; - - /* Ratio of input/output samples */ - S->invRatio_Q16 = SKP_LSHIFT32( SKP_DIV32( SKP_LSHIFT32( Fs_Hz_in, 14 + up2 - down2 ), Fs_Hz_out ), 2 ); - /* Make sure the ratio is rounded up */ - while( SKP_SMULWW( S->invRatio_Q16, SKP_LSHIFT32( Fs_Hz_out, down2 ) ) < SKP_LSHIFT32( Fs_Hz_in, up2 ) ) { - S->invRatio_Q16++; - } - - S->magic_number = 123456789; - - return 0; -} - -/* Clear the states of all resampling filters, without resetting sampling rate ratio */ -opus_int silk_resampler_clear( - silk_resampler_state_struct *S /* I/O: Resampler state */ -) -{ - /* Clear state */ - SKP_memset( S->sDown2, 0, sizeof( S->sDown2 ) ); - SKP_memset( S->sIIR, 0, sizeof( S->sIIR ) ); - SKP_memset( S->sFIR, 0, sizeof( S->sFIR ) ); -#if RESAMPLER_SUPPORT_ABOVE_48KHZ - SKP_memset( S->sDownPre, 0, sizeof( S->sDownPre ) ); - SKP_memset( S->sUpPost, 0, sizeof( S->sUpPost ) ); -#endif - return 0; -} - -/* Resampler: convert from one sampling rate to another */ -opus_int silk_resampler( - silk_resampler_state_struct *S, /* I/O: Resampler state */ - opus_int16 out[], /* O: Output signal */ - const opus_int16 in[], /* I: Input signal */ - opus_int32 inLen /* I: Number of input samples */ -) -{ - /* Verify that state was initialized and has not been corrupted */ - if( S->magic_number != 123456789 ) { - SKP_assert( 0 ); - return -1; - } - -#if RESAMPLER_SUPPORT_ABOVE_48KHZ - if( S->nPreDownsamplers + S->nPostUpsamplers > 0 ) { - /* The input and/or output sampling rate is above 48000 Hz */ - opus_int32 nSamplesIn, nSamplesOut; - opus_int16 in_buf[ 480 ], out_buf[ 480 ]; - - while( inLen > 0 ) { - /* Number of input and output samples to process */ - nSamplesIn = SKP_min( inLen, S->batchSizePrePost ); - nSamplesOut = SKP_SMULWB( S->ratio_Q16, nSamplesIn ); - - SKP_assert( SKP_RSHIFT32( nSamplesIn, S->nPreDownsamplers ) <= 480 ); - SKP_assert( SKP_RSHIFT32( nSamplesOut, S->nPostUpsamplers ) <= 480 ); - - if( S->nPreDownsamplers > 0 ) { - S->down_pre_function( S->sDownPre, in_buf, in, nSamplesIn ); - if( S->nPostUpsamplers > 0 ) { - S->resampler_function( S, out_buf, in_buf, SKP_RSHIFT32( nSamplesIn, S->nPreDownsamplers ) ); - S->up_post_function( S->sUpPost, out, out_buf, SKP_RSHIFT32( nSamplesOut, S->nPostUpsamplers ) ); - } else { - S->resampler_function( S, out, in_buf, SKP_RSHIFT32( nSamplesIn, S->nPreDownsamplers ) ); - } - } else { - S->resampler_function( S, out_buf, in, SKP_RSHIFT32( nSamplesIn, S->nPreDownsamplers ) ); - S->up_post_function( S->sUpPost, out, out_buf, SKP_RSHIFT32( nSamplesOut, S->nPostUpsamplers ) ); - } - - in += nSamplesIn; - out += nSamplesOut; - inLen -= nSamplesIn; - } - } else -#endif - { - /* Input and output sampling rate are at most 48000 Hz */ - S->resampler_function( S, out, in, inLen ); - } - - return 0; -} +/*********************************************************************** +Copyright (c) 2006-2011, Skype Limited. All rights reserved. +Redistribution and use in source and binary forms, with or without +modification, (subject to the limitations in the disclaimer below) +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 Skype Limited, nor the names of specific +contributors, may be used to endorse or promote products derived from +this software without specific prior written permission. +NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED +BY THIS LICENSE. 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. +***********************************************************************/ + +/* Matrix of resampling methods used: + * Fs_out (kHz) + * 8 12 16 24 32 44.1 48 + * + * 8 C UF U UF UF UF UF + * 12 AF C UF U UF UF UF + * 16 D AF C UF U UF UF + * Fs_in (kHz) 24 AIF D AF C UF UF U + * 32 UF AF D AF C UF UF + * 44.1 AMI AMI AMI AMI AMI C UF + * 48 DAF DAF AF D AF UF C + * + * default method: UF + * + * C -> Copy (no resampling) + * D -> Allpass-based 2x downsampling + * U -> Allpass-based 2x upsampling + * DAF -> Allpass-based 2x downsampling followed by AR2 filter followed by FIR interpolation + * UF -> Allpass-based 2x upsampling followed by FIR interpolation + * AMI -> ARMA4 filter followed by FIR interpolation + * AF -> AR2 filter followed by FIR interpolation + * + * Input signals sampled above 48 kHz are first downsampled to at most 48 kHz. + * Output signals sampled above 48 kHz are upsampled from at most 48 kHz. + */ + +#include "silk_resampler_private.h" + +/* Greatest common divisor */ +static opus_int32 gcd( + opus_int32 a, + opus_int32 b +) +{ + opus_int32 tmp; + while( b > 0 ) { + tmp = a - b * SKP_DIV32( a, b ); + a = b; + b = tmp; + } + return a; +} + +/* Initialize/reset the resampler state for a given pair of input/output sampling rates */ +opus_int silk_resampler_init( + silk_resampler_state_struct *S, /* I/O: Resampler state */ + opus_int32 Fs_Hz_in, /* I: Input sampling rate (Hz) */ + opus_int32 Fs_Hz_out /* I: Output sampling rate (Hz) */ +) +{ + opus_int32 cycleLen, cyclesPerBatch, up2 = 0, down2 = 0; + + /* Clear state */ + SKP_memset( S, 0, sizeof( silk_resampler_state_struct ) ); + + /* Input checking */ +#if RESAMPLER_SUPPORT_ABOVE_48KHZ + if( Fs_Hz_in < 8000 || Fs_Hz_in > 192000 || Fs_Hz_out < 8000 || Fs_Hz_out > 192000 ) { +#else + if( Fs_Hz_in < 8000 || Fs_Hz_in > 48000 || Fs_Hz_out < 8000 || Fs_Hz_out > 48000 ) { +#endif + SKP_assert( 0 ); + return -1; + } + +#if RESAMPLER_SUPPORT_ABOVE_48KHZ + /* Determine pre downsampling and post upsampling */ + if( Fs_Hz_in > 96000 ) { + S->nPreDownsamplers = 2; + S->down_pre_function = silk_resampler_private_down4; + } else if( Fs_Hz_in > 48000 ) { + S->nPreDownsamplers = 1; + S->down_pre_function = silk_resampler_down2; + } else { + S->nPreDownsamplers = 0; + S->down_pre_function = NULL; + } + + if( Fs_Hz_out > 96000 ) { + S->nPostUpsamplers = 2; + S->up_post_function = silk_resampler_private_up4; + } else if( Fs_Hz_out > 48000 ) { + S->nPostUpsamplers = 1; + S->up_post_function = silk_resampler_up2; + } else { + S->nPostUpsamplers = 0; + S->up_post_function = NULL; + } + + if( S->nPreDownsamplers + S->nPostUpsamplers > 0 ) { + /* Ratio of output/input samples */ + S->ratio_Q16 = SKP_LSHIFT32( SKP_DIV32( SKP_LSHIFT32( Fs_Hz_out, 13 ), Fs_Hz_in ), 3 ); + /* Make sure the ratio is rounded up */ + while( SKP_SMULWW( S->ratio_Q16, Fs_Hz_in ) < Fs_Hz_out ) S->ratio_Q16++; + + /* Batch size is 10 ms */ + S->batchSizePrePost = SKP_DIV32_16( Fs_Hz_in, 100 ); + + /* Convert sampling rate to those after pre-downsampling and before post-upsampling */ + Fs_Hz_in = SKP_RSHIFT( Fs_Hz_in, S->nPreDownsamplers ); + Fs_Hz_out = SKP_RSHIFT( Fs_Hz_out, S->nPostUpsamplers ); + } +#endif + + /* Number of samples processed per batch */ + /* First, try 10 ms frames */ + S->batchSize = SKP_DIV32_16( Fs_Hz_in, 100 ); + if( ( SKP_MUL( S->batchSize, 100 ) != Fs_Hz_in ) || ( Fs_Hz_in % 100 != 0 ) ) { + /* No integer number of input or output samples with 10 ms frames, use greatest common divisor */ + cycleLen = SKP_DIV32( Fs_Hz_in, gcd( Fs_Hz_in, Fs_Hz_out ) ); + cyclesPerBatch = SKP_DIV32( RESAMPLER_MAX_BATCH_SIZE_IN, cycleLen ); + if( cyclesPerBatch == 0 ) { + /* cycleLen too big, let's just use the maximum batch size. Some distortion will result. */ + S->batchSize = RESAMPLER_MAX_BATCH_SIZE_IN; + SKP_assert( 0 ); + } else { + S->batchSize = SKP_MUL( cyclesPerBatch, cycleLen ); + } + } + + + /* Find resampler with the right sampling ratio */ + if( Fs_Hz_out > Fs_Hz_in ) { + /* Upsample */ + if( Fs_Hz_out == SKP_MUL( Fs_Hz_in, 2 ) ) { /* Fs_out : Fs_in = 2 : 1 */ + /* Special case: directly use 2x upsampler */ + S->resampler_function = silk_resampler_private_up2_HQ_wrapper; + } else { + /* Default resampler */ + S->resampler_function = silk_resampler_private_IIR_FIR; + up2 = 1; + if( Fs_Hz_in > 24000 ) { + /* Low-quality all-pass upsampler */ + S->up2_function = silk_resampler_up2; + } else { + /* High-quality all-pass upsampler */ + S->up2_function = silk_resampler_private_up2_HQ; + } + } + } else if ( Fs_Hz_out < Fs_Hz_in ) { + /* Downsample */ + if( SKP_MUL( Fs_Hz_out, 4 ) == SKP_MUL( Fs_Hz_in, 3 ) ) { /* Fs_out : Fs_in = 3 : 4 */ + S->FIR_Fracs = 3; + S->Coefs = silk_Resampler_3_4_COEFS; + S->resampler_function = silk_resampler_private_down_FIR; + } else if( SKP_MUL( Fs_Hz_out, 3 ) == SKP_MUL( Fs_Hz_in, 2 ) ) { /* Fs_out : Fs_in = 2 : 3 */ + S->FIR_Fracs = 2; + S->Coefs = silk_Resampler_2_3_COEFS; + S->resampler_function = silk_resampler_private_down_FIR; + } else if( SKP_MUL( Fs_Hz_out, 2 ) == Fs_Hz_in ) { /* Fs_out : Fs_in = 1 : 2 */ + S->FIR_Fracs = 1; + S->Coefs = silk_Resampler_1_2_COEFS; + S->resampler_function = silk_resampler_private_down_FIR; + } else if( SKP_MUL( Fs_Hz_out, 8 ) == SKP_MUL( Fs_Hz_in, 3 ) ) { /* Fs_out : Fs_in = 3 : 8 */ + S->FIR_Fracs = 3; + S->Coefs = silk_Resampler_3_8_COEFS; + S->resampler_function = silk_resampler_private_down_FIR; + } else if( SKP_MUL( Fs_Hz_out, 3 ) == Fs_Hz_in ) { /* Fs_out : Fs_in = 1 : 3 */ + S->FIR_Fracs = 1; + S->Coefs = silk_Resampler_1_3_COEFS; + S->resampler_function = silk_resampler_private_down_FIR; + } else if( SKP_MUL( Fs_Hz_out, 4 ) == Fs_Hz_in ) { /* Fs_out : Fs_in = 1 : 4 */ + S->FIR_Fracs = 1; + down2 = 1; + S->Coefs = silk_Resampler_1_2_COEFS; + S->resampler_function = silk_resampler_private_down_FIR; + } else if( SKP_MUL( Fs_Hz_out, 6 ) == Fs_Hz_in ) { /* Fs_out : Fs_in = 1 : 6 */ + S->FIR_Fracs = 1; + down2 = 1; + S->Coefs = silk_Resampler_1_3_COEFS; + S->resampler_function = silk_resampler_private_down_FIR; + } else if( SKP_MUL( Fs_Hz_out, 441 ) == SKP_MUL( Fs_Hz_in, 80 ) ) { /* Fs_out : Fs_in = 80 : 441 */ + S->Coefs = silk_Resampler_80_441_ARMA4_COEFS; + S->resampler_function = silk_resampler_private_IIR_FIR; + } else if( SKP_MUL( Fs_Hz_out, 441 ) == SKP_MUL( Fs_Hz_in, 120 ) ) { /* Fs_out : Fs_in = 120 : 441 */ + S->Coefs = silk_Resampler_120_441_ARMA4_COEFS; + S->resampler_function = silk_resampler_private_IIR_FIR; + } else if( SKP_MUL( Fs_Hz_out, 441 ) == SKP_MUL( Fs_Hz_in, 160 ) ) { /* Fs_out : Fs_in = 160 : 441 */ + S->Coefs = silk_Resampler_160_441_ARMA4_COEFS; + S->resampler_function = silk_resampler_private_IIR_FIR; + } else if( SKP_MUL( Fs_Hz_out, 441 ) == SKP_MUL( Fs_Hz_in, 240 ) ) { /* Fs_out : Fs_in = 240 : 441 */ + S->Coefs = silk_Resampler_240_441_ARMA4_COEFS; + S->resampler_function = silk_resampler_private_IIR_FIR; + } else if( SKP_MUL( Fs_Hz_out, 441 ) == SKP_MUL( Fs_Hz_in, 320 ) ) { /* Fs_out : Fs_in = 320 : 441 */ + S->Coefs = silk_Resampler_320_441_ARMA4_COEFS; + S->resampler_function = silk_resampler_private_IIR_FIR; + } else { + /* Default resampler */ + S->resampler_function = silk_resampler_private_IIR_FIR; + up2 = 1; + if( Fs_Hz_in > 24000 ) { + /* Low-quality all-pass upsampler */ + S->up2_function = silk_resampler_up2; + } else { + /* High-quality all-pass upsampler */ + S->up2_function = silk_resampler_private_up2_HQ; + } + } + } else { + /* Input and output sampling rates are equal: copy */ + S->resampler_function = silk_resampler_private_copy; + } + + S->input2x = up2 | down2; + + /* Ratio of input/output samples */ + S->invRatio_Q16 = SKP_LSHIFT32( SKP_DIV32( SKP_LSHIFT32( Fs_Hz_in, 14 + up2 - down2 ), Fs_Hz_out ), 2 ); + /* Make sure the ratio is rounded up */ + while( SKP_SMULWW( S->invRatio_Q16, SKP_LSHIFT32( Fs_Hz_out, down2 ) ) < SKP_LSHIFT32( Fs_Hz_in, up2 ) ) { + S->invRatio_Q16++; + } + + S->magic_number = 123456789; + + return 0; +} + +/* Clear the states of all resampling filters, without resetting sampling rate ratio */ +opus_int silk_resampler_clear( + silk_resampler_state_struct *S /* I/O: Resampler state */ +) +{ + /* Clear state */ + SKP_memset( S->sDown2, 0, sizeof( S->sDown2 ) ); + SKP_memset( S->sIIR, 0, sizeof( S->sIIR ) ); + SKP_memset( S->sFIR, 0, sizeof( S->sFIR ) ); +#if RESAMPLER_SUPPORT_ABOVE_48KHZ + SKP_memset( S->sDownPre, 0, sizeof( S->sDownPre ) ); + SKP_memset( S->sUpPost, 0, sizeof( S->sUpPost ) ); +#endif + return 0; +} + +/* Resampler: convert from one sampling rate to another */ +opus_int silk_resampler( + silk_resampler_state_struct *S, /* I/O: Resampler state */ + opus_int16 out[], /* O: Output signal */ + const opus_int16 in[], /* I: Input signal */ + opus_int32 inLen /* I: Number of input samples */ +) +{ + /* Verify that state was initialized and has not been corrupted */ + if( S->magic_number != 123456789 ) { + SKP_assert( 0 ); + return -1; + } + +#if RESAMPLER_SUPPORT_ABOVE_48KHZ + if( S->nPreDownsamplers + S->nPostUpsamplers > 0 ) { + /* The input and/or output sampling rate is above 48000 Hz */ + opus_int32 nSamplesIn, nSamplesOut; + opus_int16 in_buf[ 480 ], out_buf[ 480 ]; + + while( inLen > 0 ) { + /* Number of input and output samples to process */ + nSamplesIn = SKP_min( inLen, S->batchSizePrePost ); + nSamplesOut = SKP_SMULWB( S->ratio_Q16, nSamplesIn ); + + SKP_assert( SKP_RSHIFT32( nSamplesIn, S->nPreDownsamplers ) <= 480 ); + SKP_assert( SKP_RSHIFT32( nSamplesOut, S->nPostUpsamplers ) <= 480 ); + + if( S->nPreDownsamplers > 0 ) { + S->down_pre_function( S->sDownPre, in_buf, in, nSamplesIn ); + if( S->nPostUpsamplers > 0 ) { + S->resampler_function( S, out_buf, in_buf, SKP_RSHIFT32( nSamplesIn, S->nPreDownsamplers ) ); + S->up_post_function( S->sUpPost, out, out_buf, SKP_RSHIFT32( nSamplesOut, S->nPostUpsamplers ) ); + } else { + S->resampler_function( S, out, in_buf, SKP_RSHIFT32( nSamplesIn, S->nPreDownsamplers ) ); + } + } else { + S->resampler_function( S, out_buf, in, SKP_RSHIFT32( nSamplesIn, S->nPreDownsamplers ) ); + S->up_post_function( S->sUpPost, out, out_buf, SKP_RSHIFT32( nSamplesOut, S->nPostUpsamplers ) ); + } + + in += nSamplesIn; + out += nSamplesOut; + inLen -= nSamplesIn; + } + } else +#endif + { + /* Input and output sampling rate are at most 48000 Hz */ + S->resampler_function( S, out, in, inLen ); + } + + return 0; +} diff --git a/silk/silk_resampler_down2.c b/silk/silk_resampler_down2.c index 0f950e574..ab6eac679 100644 --- a/silk/silk_resampler_down2.c +++ b/silk/silk_resampler_down2.c @@ -1,70 +1,70 @@ -/*********************************************************************** -Copyright (c) 2006-2011, Skype Limited. All rights reserved. -Redistribution and use in source and binary forms, with or without -modification, (subject to the limitations in the disclaimer below) -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 Skype Limited, nor the names of specific -contributors, may be used to endorse or promote products derived from -this software without specific prior written permission. -NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED -BY THIS LICENSE. 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. -***********************************************************************/ - -#include "silk_SigProc_FIX.h" -#include "silk_resampler_rom.h" - -/* Downsample by a factor 2, mediocre quality */ -void silk_resampler_down2( - opus_int32 *S, /* I/O: State vector [ 2 ] */ - opus_int16 *out, /* O: Output signal [ len ] */ - const opus_int16 *in, /* I: Input signal [ floor(len/2) ] */ - opus_int32 inLen /* I: Number of input samples */ -) -{ - opus_int32 k, len2 = SKP_RSHIFT32( inLen, 1 ); - opus_int32 in32, out32, Y, X; - - SKP_assert( silk_resampler_down2_0 > 0 ); - SKP_assert( silk_resampler_down2_1 < 0 ); - - /* Internal variables and state are in Q10 format */ - for( k = 0; k < len2; k++ ) { - /* Convert to Q10 */ - in32 = SKP_LSHIFT( (opus_int32)in[ 2 * k ], 10 ); - - /* All-pass section for even input sample */ - Y = SKP_SUB32( in32, S[ 0 ] ); - X = SKP_SMLAWB( Y, Y, silk_resampler_down2_1 ); - out32 = SKP_ADD32( S[ 0 ], X ); - S[ 0 ] = SKP_ADD32( in32, X ); - - /* Convert to Q10 */ - in32 = SKP_LSHIFT( (opus_int32)in[ 2 * k + 1 ], 10 ); - - /* All-pass section for odd input sample, and add to output of previous section */ - Y = SKP_SUB32( in32, S[ 1 ] ); - X = SKP_SMULWB( Y, silk_resampler_down2_0 ); - out32 = SKP_ADD32( out32, S[ 1 ] ); - out32 = SKP_ADD32( out32, X ); - S[ 1 ] = SKP_ADD32( in32, X ); - - /* Add, convert back to int16 and store to output */ - out[ k ] = (opus_int16)SKP_SAT16( SKP_RSHIFT_ROUND( out32, 11 ) ); - } -} - +/*********************************************************************** +Copyright (c) 2006-2011, Skype Limited. All rights reserved. +Redistribution and use in source and binary forms, with or without +modification, (subject to the limitations in the disclaimer below) +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 Skype Limited, nor the names of specific +contributors, may be used to endorse or promote products derived from +this software without specific prior written permission. +NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED +BY THIS LICENSE. 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. +***********************************************************************/ + +#include "silk_SigProc_FIX.h" +#include "silk_resampler_rom.h" + +/* Downsample by a factor 2, mediocre quality */ +void silk_resampler_down2( + opus_int32 *S, /* I/O: State vector [ 2 ] */ + opus_int16 *out, /* O: Output signal [ len ] */ + const opus_int16 *in, /* I: Input signal [ floor(len/2) ] */ + opus_int32 inLen /* I: Number of input samples */ +) +{ + opus_int32 k, len2 = SKP_RSHIFT32( inLen, 1 ); + opus_int32 in32, out32, Y, X; + + SKP_assert( silk_resampler_down2_0 > 0 ); + SKP_assert( silk_resampler_down2_1 < 0 ); + + /* Internal variables and state are in Q10 format */ + for( k = 0; k < len2; k++ ) { + /* Convert to Q10 */ + in32 = SKP_LSHIFT( (opus_int32)in[ 2 * k ], 10 ); + + /* All-pass section for even input sample */ + Y = SKP_SUB32( in32, S[ 0 ] ); + X = SKP_SMLAWB( Y, Y, silk_resampler_down2_1 ); + out32 = SKP_ADD32( S[ 0 ], X ); + S[ 0 ] = SKP_ADD32( in32, X ); + + /* Convert to Q10 */ + in32 = SKP_LSHIFT( (opus_int32)in[ 2 * k + 1 ], 10 ); + + /* All-pass section for odd input sample, and add to output of previous section */ + Y = SKP_SUB32( in32, S[ 1 ] ); + X = SKP_SMULWB( Y, silk_resampler_down2_0 ); + out32 = SKP_ADD32( out32, S[ 1 ] ); + out32 = SKP_ADD32( out32, X ); + S[ 1 ] = SKP_ADD32( in32, X ); + + /* Add, convert back to int16 and store to output */ + out[ k ] = (opus_int16)SKP_SAT16( SKP_RSHIFT_ROUND( out32, 11 ) ); + } +} + diff --git a/silk/silk_resampler_down2_3.c b/silk/silk_resampler_down2_3.c index 6a6af2390..b0b838440 100644 --- a/silk/silk_resampler_down2_3.c +++ b/silk/silk_resampler_down2_3.c @@ -1,94 +1,94 @@ -/*********************************************************************** -Copyright (c) 2006-2011, Skype Limited. All rights reserved. -Redistribution and use in source and binary forms, with or without -modification, (subject to the limitations in the disclaimer below) -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 Skype Limited, nor the names of specific -contributors, may be used to endorse or promote products derived from -this software without specific prior written permission. -NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED -BY THIS LICENSE. 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. -***********************************************************************/ - -#include "silk_SigProc_FIX.h" -#include "silk_resampler_private.h" - -#define ORDER_FIR 4 - -/* Downsample by a factor 2/3, low quality */ -void silk_resampler_down2_3( - opus_int32 *S, /* I/O: State vector [ 6 ] */ - opus_int16 *out, /* O: Output signal [ floor(2*inLen/3) ] */ - const opus_int16 *in, /* I: Input signal [ inLen ] */ - opus_int32 inLen /* I: Number of input samples */ -) -{ - opus_int32 nSamplesIn, counter, res_Q6; - opus_int32 buf[ RESAMPLER_MAX_BATCH_SIZE_IN + ORDER_FIR ]; - opus_int32 *buf_ptr; - - /* Copy buffered samples to start of buffer */ - SKP_memcpy( buf, S, ORDER_FIR * sizeof( opus_int32 ) ); - - /* Iterate over blocks of frameSizeIn input samples */ - while( 1 ) { - nSamplesIn = SKP_min( inLen, RESAMPLER_MAX_BATCH_SIZE_IN ); - - /* Second-order AR filter (output in Q8) */ - silk_resampler_private_AR2( &S[ ORDER_FIR ], &buf[ ORDER_FIR ], in, - silk_Resampler_2_3_COEFS_LQ, nSamplesIn ); - - /* Interpolate filtered signal */ - buf_ptr = buf; - counter = nSamplesIn; - while( counter > 2 ) { - /* Inner product */ - res_Q6 = SKP_SMULWB( buf_ptr[ 0 ], silk_Resampler_2_3_COEFS_LQ[ 2 ] ); - res_Q6 = SKP_SMLAWB( res_Q6, buf_ptr[ 1 ], silk_Resampler_2_3_COEFS_LQ[ 3 ] ); - res_Q6 = SKP_SMLAWB( res_Q6, buf_ptr[ 2 ], silk_Resampler_2_3_COEFS_LQ[ 5 ] ); - res_Q6 = SKP_SMLAWB( res_Q6, buf_ptr[ 3 ], silk_Resampler_2_3_COEFS_LQ[ 4 ] ); - - /* Scale down, saturate and store in output array */ - *out++ = (opus_int16)SKP_SAT16( SKP_RSHIFT_ROUND( res_Q6, 6 ) ); - - res_Q6 = SKP_SMULWB( buf_ptr[ 1 ], silk_Resampler_2_3_COEFS_LQ[ 4 ] ); - res_Q6 = SKP_SMLAWB( res_Q6, buf_ptr[ 2 ], silk_Resampler_2_3_COEFS_LQ[ 5 ] ); - res_Q6 = SKP_SMLAWB( res_Q6, buf_ptr[ 3 ], silk_Resampler_2_3_COEFS_LQ[ 3 ] ); - res_Q6 = SKP_SMLAWB( res_Q6, buf_ptr[ 4 ], silk_Resampler_2_3_COEFS_LQ[ 2 ] ); - - /* Scale down, saturate and store in output array */ - *out++ = (opus_int16)SKP_SAT16( SKP_RSHIFT_ROUND( res_Q6, 6 ) ); - - buf_ptr += 3; - counter -= 3; - } - - in += nSamplesIn; - inLen -= nSamplesIn; - - if( inLen > 0 ) { - /* More iterations to do; copy last part of filtered signal to beginning of buffer */ - SKP_memcpy( buf, &buf[ nSamplesIn ], ORDER_FIR * sizeof( opus_int32 ) ); - } else { - break; - } - } - - /* Copy last part of filtered signal to the state for the next call */ - SKP_memcpy( S, &buf[ nSamplesIn ], ORDER_FIR * sizeof( opus_int32 ) ); -} +/*********************************************************************** +Copyright (c) 2006-2011, Skype Limited. All rights reserved. +Redistribution and use in source and binary forms, with or without +modification, (subject to the limitations in the disclaimer below) +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 Skype Limited, nor the names of specific +contributors, may be used to endorse or promote products derived from +this software without specific prior written permission. +NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED +BY THIS LICENSE. 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. +***********************************************************************/ + +#include "silk_SigProc_FIX.h" +#include "silk_resampler_private.h" + +#define ORDER_FIR 4 + +/* Downsample by a factor 2/3, low quality */ +void silk_resampler_down2_3( + opus_int32 *S, /* I/O: State vector [ 6 ] */ + opus_int16 *out, /* O: Output signal [ floor(2*inLen/3) ] */ + const opus_int16 *in, /* I: Input signal [ inLen ] */ + opus_int32 inLen /* I: Number of input samples */ +) +{ + opus_int32 nSamplesIn, counter, res_Q6; + opus_int32 buf[ RESAMPLER_MAX_BATCH_SIZE_IN + ORDER_FIR ]; + opus_int32 *buf_ptr; + + /* Copy buffered samples to start of buffer */ + SKP_memcpy( buf, S, ORDER_FIR * sizeof( opus_int32 ) ); + + /* Iterate over blocks of frameSizeIn input samples */ + while( 1 ) { + nSamplesIn = SKP_min( inLen, RESAMPLER_MAX_BATCH_SIZE_IN ); + + /* Second-order AR filter (output in Q8) */ + silk_resampler_private_AR2( &S[ ORDER_FIR ], &buf[ ORDER_FIR ], in, + silk_Resampler_2_3_COEFS_LQ, nSamplesIn ); + + /* Interpolate filtered signal */ + buf_ptr = buf; + counter = nSamplesIn; + while( counter > 2 ) { + /* Inner product */ + res_Q6 = SKP_SMULWB( buf_ptr[ 0 ], silk_Resampler_2_3_COEFS_LQ[ 2 ] ); + res_Q6 = SKP_SMLAWB( res_Q6, buf_ptr[ 1 ], silk_Resampler_2_3_COEFS_LQ[ 3 ] ); + res_Q6 = SKP_SMLAWB( res_Q6, buf_ptr[ 2 ], silk_Resampler_2_3_COEFS_LQ[ 5 ] ); + res_Q6 = SKP_SMLAWB( res_Q6, buf_ptr[ 3 ], silk_Resampler_2_3_COEFS_LQ[ 4 ] ); + + /* Scale down, saturate and store in output array */ + *out++ = (opus_int16)SKP_SAT16( SKP_RSHIFT_ROUND( res_Q6, 6 ) ); + + res_Q6 = SKP_SMULWB( buf_ptr[ 1 ], silk_Resampler_2_3_COEFS_LQ[ 4 ] ); + res_Q6 = SKP_SMLAWB( res_Q6, buf_ptr[ 2 ], silk_Resampler_2_3_COEFS_LQ[ 5 ] ); + res_Q6 = SKP_SMLAWB( res_Q6, buf_ptr[ 3 ], silk_Resampler_2_3_COEFS_LQ[ 3 ] ); + res_Q6 = SKP_SMLAWB( res_Q6, buf_ptr[ 4 ], silk_Resampler_2_3_COEFS_LQ[ 2 ] ); + + /* Scale down, saturate and store in output array */ + *out++ = (opus_int16)SKP_SAT16( SKP_RSHIFT_ROUND( res_Q6, 6 ) ); + + buf_ptr += 3; + counter -= 3; + } + + in += nSamplesIn; + inLen -= nSamplesIn; + + if( inLen > 0 ) { + /* More iterations to do; copy last part of filtered signal to beginning of buffer */ + SKP_memcpy( buf, &buf[ nSamplesIn ], ORDER_FIR * sizeof( opus_int32 ) ); + } else { + break; + } + } + + /* Copy last part of filtered signal to the state for the next call */ + SKP_memcpy( S, &buf[ nSamplesIn ], ORDER_FIR * sizeof( opus_int32 ) ); +} diff --git a/silk/silk_resampler_down3.c b/silk/silk_resampler_down3.c index 58169d5e8..f35991e0b 100644 --- a/silk/silk_resampler_down3.c +++ b/silk/silk_resampler_down3.c @@ -1,85 +1,85 @@ -/*********************************************************************** -Copyright (c) 2006-2011, Skype Limited. All rights reserved. -Redistribution and use in source and binary forms, with or without -modification, (subject to the limitations in the disclaimer below) -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 Skype Limited, nor the names of specific -contributors, may be used to endorse or promote products derived from -this software without specific prior written permission. -NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED -BY THIS LICENSE. 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. -***********************************************************************/ - -#include "silk_SigProc_FIX.h" -#include "silk_resampler_private.h" - -#define ORDER_FIR 6 - -/* Downsample by a factor 3, low quality */ -void silk_resampler_down3( - opus_int32 *S, /* I/O: State vector [ 8 ] */ - opus_int16 *out, /* O: Output signal [ floor(inLen/3) ] */ - const opus_int16 *in, /* I: Input signal [ inLen ] */ - opus_int32 inLen /* I: Number of input samples */ -) -{ - opus_int32 nSamplesIn, counter, res_Q6; - opus_int32 buf[ RESAMPLER_MAX_BATCH_SIZE_IN + ORDER_FIR ]; - opus_int32 *buf_ptr; - - /* Copy buffered samples to start of buffer */ - SKP_memcpy( buf, S, ORDER_FIR * sizeof( opus_int32 ) ); - - /* Iterate over blocks of frameSizeIn input samples */ - while( 1 ) { - nSamplesIn = SKP_min( inLen, RESAMPLER_MAX_BATCH_SIZE_IN ); - - /* Second-order AR filter (output in Q8) */ - silk_resampler_private_AR2( &S[ ORDER_FIR ], &buf[ ORDER_FIR ], in, - silk_Resampler_1_3_COEFS_LQ, nSamplesIn ); - - /* Interpolate filtered signal */ - buf_ptr = buf; - counter = nSamplesIn; - while( counter > 2 ) { - /* Inner product */ - res_Q6 = SKP_SMULWB( SKP_ADD32( buf_ptr[ 0 ], buf_ptr[ 5 ] ), silk_Resampler_1_3_COEFS_LQ[ 2 ] ); - res_Q6 = SKP_SMLAWB( res_Q6, SKP_ADD32( buf_ptr[ 1 ], buf_ptr[ 4 ] ), silk_Resampler_1_3_COEFS_LQ[ 3 ] ); - res_Q6 = SKP_SMLAWB( res_Q6, SKP_ADD32( buf_ptr[ 2 ], buf_ptr[ 3 ] ), silk_Resampler_1_3_COEFS_LQ[ 4 ] ); - - /* Scale down, saturate and store in output array */ - *out++ = (opus_int16)SKP_SAT16( SKP_RSHIFT_ROUND( res_Q6, 6 ) ); - - buf_ptr += 3; - counter -= 3; - } - - in += nSamplesIn; - inLen -= nSamplesIn; - - if( inLen > 0 ) { - /* More iterations to do; copy last part of filtered signal to beginning of buffer */ - SKP_memcpy( buf, &buf[ nSamplesIn ], ORDER_FIR * sizeof( opus_int32 ) ); - } else { - break; - } - } - - /* Copy last part of filtered signal to the state for the next call */ - SKP_memcpy( S, &buf[ nSamplesIn ], ORDER_FIR * sizeof( opus_int32 ) ); -} +/*********************************************************************** +Copyright (c) 2006-2011, Skype Limited. All rights reserved. +Redistribution and use in source and binary forms, with or without +modification, (subject to the limitations in the disclaimer below) +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 Skype Limited, nor the names of specific +contributors, may be used to endorse or promote products derived from +this software without specific prior written permission. +NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED +BY THIS LICENSE. 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. +***********************************************************************/ + +#include "silk_SigProc_FIX.h" +#include "silk_resampler_private.h" + +#define ORDER_FIR 6 + +/* Downsample by a factor 3, low quality */ +void silk_resampler_down3( + opus_int32 *S, /* I/O: State vector [ 8 ] */ + opus_int16 *out, /* O: Output signal [ floor(inLen/3) ] */ + const opus_int16 *in, /* I: Input signal [ inLen ] */ + opus_int32 inLen /* I: Number of input samples */ +) +{ + opus_int32 nSamplesIn, counter, res_Q6; + opus_int32 buf[ RESAMPLER_MAX_BATCH_SIZE_IN + ORDER_FIR ]; + opus_int32 *buf_ptr; + + /* Copy buffered samples to start of buffer */ + SKP_memcpy( buf, S, ORDER_FIR * sizeof( opus_int32 ) ); + + /* Iterate over blocks of frameSizeIn input samples */ + while( 1 ) { + nSamplesIn = SKP_min( inLen, RESAMPLER_MAX_BATCH_SIZE_IN ); + + /* Second-order AR filter (output in Q8) */ + silk_resampler_private_AR2( &S[ ORDER_FIR ], &buf[ ORDER_FIR ], in, + silk_Resampler_1_3_COEFS_LQ, nSamplesIn ); + + /* Interpolate filtered signal */ + buf_ptr = buf; + counter = nSamplesIn; + while( counter > 2 ) { + /* Inner product */ + res_Q6 = SKP_SMULWB( SKP_ADD32( buf_ptr[ 0 ], buf_ptr[ 5 ] ), silk_Resampler_1_3_COEFS_LQ[ 2 ] ); + res_Q6 = SKP_SMLAWB( res_Q6, SKP_ADD32( buf_ptr[ 1 ], buf_ptr[ 4 ] ), silk_Resampler_1_3_COEFS_LQ[ 3 ] ); + res_Q6 = SKP_SMLAWB( res_Q6, SKP_ADD32( buf_ptr[ 2 ], buf_ptr[ 3 ] ), silk_Resampler_1_3_COEFS_LQ[ 4 ] ); + + /* Scale down, saturate and store in output array */ + *out++ = (opus_int16)SKP_SAT16( SKP_RSHIFT_ROUND( res_Q6, 6 ) ); + + buf_ptr += 3; + counter -= 3; + } + + in += nSamplesIn; + inLen -= nSamplesIn; + + if( inLen > 0 ) { + /* More iterations to do; copy last part of filtered signal to beginning of buffer */ + SKP_memcpy( buf, &buf[ nSamplesIn ], ORDER_FIR * sizeof( opus_int32 ) ); + } else { + break; + } + } + + /* Copy last part of filtered signal to the state for the next call */ + SKP_memcpy( S, &buf[ nSamplesIn ], ORDER_FIR * sizeof( opus_int32 ) ); +} diff --git a/silk/silk_resampler_private.h b/silk/silk_resampler_private.h index f69b8ea46..3c2c7c02e 100644 --- a/silk/silk_resampler_private.h +++ b/silk/silk_resampler_private.h @@ -1,121 +1,121 @@ -/*********************************************************************** -Copyright (c) 2006-2011, Skype Limited. All rights reserved. -Redistribution and use in source and binary forms, with or without -modification, (subject to the limitations in the disclaimer below) -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 Skype Limited, nor the names of specific -contributors, may be used to endorse or promote products derived from -this software without specific prior written permission. -NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED -BY THIS LICENSE. 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. -***********************************************************************/ - -#ifndef SILK_RESAMPLER_H -#define SILK_RESAMPLER_H - -#ifdef __cplusplus -extern "C" { -#endif - -#include "silk_SigProc_FIX.h" -#include "silk_resampler_structs.h" -#include "silk_resampler_rom.h" - -/* Number of input samples to process in the inner loop */ -#define RESAMPLER_MAX_BATCH_SIZE_IN 480 - -/* Description: Hybrid IIR/FIR polyphase implementation of resampling */ -void silk_resampler_private_IIR_FIR( - void *SS, /* I/O: Resampler state */ - opus_int16 out[], /* O: Output signal */ - const opus_int16 in[], /* I: Input signal */ - opus_int32 inLen /* I: Number of input samples */ -); - -/* Description: Hybrid IIR/FIR polyphase implementation of resampling */ -void silk_resampler_private_down_FIR( - void *SS, /* I/O: Resampler state */ - opus_int16 out[], /* O: Output signal */ - const opus_int16 in[], /* I: Input signal */ - opus_int32 inLen /* I: Number of input samples */ -); - -/* Copy */ -void silk_resampler_private_copy( - void *SS, /* I/O: Resampler state (unused) */ - opus_int16 out[], /* O: Output signal */ - const opus_int16 in[], /* I: Input signal */ - opus_int32 inLen /* I: Number of input samples */ -); - -/* Upsample by a factor 2, high quality */ -void silk_resampler_private_up2_HQ_wrapper( - void *SS, /* I/O: Resampler state (unused) */ - opus_int16 *out, /* O: Output signal [ 2 * len ] */ - const opus_int16 *in, /* I: Input signal [ len ] */ - opus_int32 len /* I: Number of input samples */ -); - -/* Upsample by a factor 2, high quality */ -void silk_resampler_private_up2_HQ( - opus_int32 *S, /* I/O: Resampler state [ 6 ] */ - opus_int16 *out, /* O: Output signal [ 2 * len ] */ - const opus_int16 *in, /* I: Input signal [ len ] */ - opus_int32 len /* I: Number of input samples */ -); - -/* Upsample 4x, low quality */ -void silk_resampler_private_up4( - opus_int32 *S, /* I/O: State vector [ 2 ] */ - opus_int16 *out, /* O: Output signal [ 4 * len ] */ - const opus_int16 *in, /* I: Input signal [ len ] */ - opus_int32 len /* I: Number of input samples */ -); - -/* Downsample 4x, low quality */ -void silk_resampler_private_down4( - opus_int32 *S, /* I/O: State vector [ 2 ] */ - opus_int16 *out, /* O: Output signal [ floor(len/2) ] */ - const opus_int16 *in, /* I: Input signal [ len ] */ - opus_int32 inLen /* I: Number of input samples */ -); - -/* Second order AR filter */ -void silk_resampler_private_AR2( - opus_int32 S[], /* I/O: State vector [ 2 ] */ - opus_int32 out_Q8[], /* O: Output signal */ - const opus_int16 in[], /* I: Input signal */ - const opus_int16 A_Q14[], /* I: AR coefficients, Q14 */ - opus_int32 len /* I: Signal length */ -); - -/* Fourth order ARMA filter */ -void silk_resampler_private_ARMA4( - opus_int32 S[], /* I/O: State vector [ 4 ] */ - opus_int16 out[], /* O: Output signal */ - const opus_int16 in[], /* I: Input signal */ - const opus_int16 Coef[], /* I: ARMA coefficients [ 7 ] */ - opus_int32 len /* I: Signal length */ -); - - -#ifdef __cplusplus -} -#endif -#endif // SILK_RESAMPLER_H - +/*********************************************************************** +Copyright (c) 2006-2011, Skype Limited. All rights reserved. +Redistribution and use in source and binary forms, with or without +modification, (subject to the limitations in the disclaimer below) +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 Skype Limited, nor the names of specific +contributors, may be used to endorse or promote products derived from +this software without specific prior written permission. +NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED +BY THIS LICENSE. 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. +***********************************************************************/ + +#ifndef SILK_RESAMPLER_H +#define SILK_RESAMPLER_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include "silk_SigProc_FIX.h" +#include "silk_resampler_structs.h" +#include "silk_resampler_rom.h" + +/* Number of input samples to process in the inner loop */ +#define RESAMPLER_MAX_BATCH_SIZE_IN 480 + +/* Description: Hybrid IIR/FIR polyphase implementation of resampling */ +void silk_resampler_private_IIR_FIR( + void *SS, /* I/O: Resampler state */ + opus_int16 out[], /* O: Output signal */ + const opus_int16 in[], /* I: Input signal */ + opus_int32 inLen /* I: Number of input samples */ +); + +/* Description: Hybrid IIR/FIR polyphase implementation of resampling */ +void silk_resampler_private_down_FIR( + void *SS, /* I/O: Resampler state */ + opus_int16 out[], /* O: Output signal */ + const opus_int16 in[], /* I: Input signal */ + opus_int32 inLen /* I: Number of input samples */ +); + +/* Copy */ +void silk_resampler_private_copy( + void *SS, /* I/O: Resampler state (unused) */ + opus_int16 out[], /* O: Output signal */ + const opus_int16 in[], /* I: Input signal */ + opus_int32 inLen /* I: Number of input samples */ +); + +/* Upsample by a factor 2, high quality */ +void silk_resampler_private_up2_HQ_wrapper( + void *SS, /* I/O: Resampler state (unused) */ + opus_int16 *out, /* O: Output signal [ 2 * len ] */ + const opus_int16 *in, /* I: Input signal [ len ] */ + opus_int32 len /* I: Number of input samples */ +); + +/* Upsample by a factor 2, high quality */ +void silk_resampler_private_up2_HQ( + opus_int32 *S, /* I/O: Resampler state [ 6 ] */ + opus_int16 *out, /* O: Output signal [ 2 * len ] */ + const opus_int16 *in, /* I: Input signal [ len ] */ + opus_int32 len /* I: Number of input samples */ +); + +/* Upsample 4x, low quality */ +void silk_resampler_private_up4( + opus_int32 *S, /* I/O: State vector [ 2 ] */ + opus_int16 *out, /* O: Output signal [ 4 * len ] */ + const opus_int16 *in, /* I: Input signal [ len ] */ + opus_int32 len /* I: Number of input samples */ +); + +/* Downsample 4x, low quality */ +void silk_resampler_private_down4( + opus_int32 *S, /* I/O: State vector [ 2 ] */ + opus_int16 *out, /* O: Output signal [ floor(len/2) ] */ + const opus_int16 *in, /* I: Input signal [ len ] */ + opus_int32 inLen /* I: Number of input samples */ +); + +/* Second order AR filter */ +void silk_resampler_private_AR2( + opus_int32 S[], /* I/O: State vector [ 2 ] */ + opus_int32 out_Q8[], /* O: Output signal */ + const opus_int16 in[], /* I: Input signal */ + const opus_int16 A_Q14[], /* I: AR coefficients, Q14 */ + opus_int32 len /* I: Signal length */ +); + +/* Fourth order ARMA filter */ +void silk_resampler_private_ARMA4( + opus_int32 S[], /* I/O: State vector [ 4 ] */ + opus_int16 out[], /* O: Output signal */ + const opus_int16 in[], /* I: Input signal */ + const opus_int16 Coef[], /* I: ARMA coefficients [ 7 ] */ + opus_int32 len /* I: Signal length */ +); + + +#ifdef __cplusplus +} +#endif +#endif // SILK_RESAMPLER_H + diff --git a/silk/silk_resampler_private_AR2.c b/silk/silk_resampler_private_AR2.c index 98d8e21fe..c2c2c6292 100644 --- a/silk/silk_resampler_private_AR2.c +++ b/silk/silk_resampler_private_AR2.c @@ -1,51 +1,51 @@ -/*********************************************************************** -Copyright (c) 2006-2011, Skype Limited. All rights reserved. -Redistribution and use in source and binary forms, with or without -modification, (subject to the limitations in the disclaimer below) -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 Skype Limited, nor the names of specific -contributors, may be used to endorse or promote products derived from -this software without specific prior written permission. -NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED -BY THIS LICENSE. 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. -***********************************************************************/ - -#include "silk_SigProc_FIX.h" -#include "silk_resampler_private.h" - -/* Second order AR filter with single delay elements */ -void silk_resampler_private_AR2( - opus_int32 S[], /* I/O: State vector [ 2 ] */ - opus_int32 out_Q8[], /* O: Output signal */ - const opus_int16 in[], /* I: Input signal */ - const opus_int16 A_Q14[], /* I: AR coefficients, Q14 */ - opus_int32 len /* I: Signal length */ -) -{ - opus_int32 k; - opus_int32 out32; - - for( k = 0; k < len; k++ ) { - out32 = SKP_ADD_LSHIFT32( S[ 0 ], (opus_int32)in[ k ], 8 ); - out_Q8[ k ] = out32; - out32 = SKP_LSHIFT( out32, 2 ); - S[ 0 ] = SKP_SMLAWB( S[ 1 ], out32, A_Q14[ 0 ] ); - S[ 1 ] = SKP_SMULWB( out32, A_Q14[ 1 ] ); - } -} - +/*********************************************************************** +Copyright (c) 2006-2011, Skype Limited. All rights reserved. +Redistribution and use in source and binary forms, with or without +modification, (subject to the limitations in the disclaimer below) +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 Skype Limited, nor the names of specific +contributors, may be used to endorse or promote products derived from +this software without specific prior written permission. +NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED +BY THIS LICENSE. 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. +***********************************************************************/ + +#include "silk_SigProc_FIX.h" +#include "silk_resampler_private.h" + +/* Second order AR filter with single delay elements */ +void silk_resampler_private_AR2( + opus_int32 S[], /* I/O: State vector [ 2 ] */ + opus_int32 out_Q8[], /* O: Output signal */ + const opus_int16 in[], /* I: Input signal */ + const opus_int16 A_Q14[], /* I: AR coefficients, Q14 */ + opus_int32 len /* I: Signal length */ +) +{ + opus_int32 k; + opus_int32 out32; + + for( k = 0; k < len; k++ ) { + out32 = SKP_ADD_LSHIFT32( S[ 0 ], (opus_int32)in[ k ], 8 ); + out_Q8[ k ] = out32; + out32 = SKP_LSHIFT( out32, 2 ); + S[ 0 ] = SKP_SMLAWB( S[ 1 ], out32, A_Q14[ 0 ] ); + S[ 1 ] = SKP_SMULWB( out32, A_Q14[ 1 ] ); + } +} + diff --git a/silk/silk_resampler_private_ARMA4.c b/silk/silk_resampler_private_ARMA4.c index cfc214077..1cecd7ff9 100644 --- a/silk/silk_resampler_private_ARMA4.c +++ b/silk/silk_resampler_private_ARMA4.c @@ -1,71 +1,71 @@ -/*********************************************************************** -Copyright (c) 2006-2011, Skype Limited. All rights reserved. -Redistribution and use in source and binary forms, with or without -modification, (subject to the limitations in the disclaimer below) -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 Skype Limited, nor the names of specific -contributors, may be used to endorse or promote products derived from -this software without specific prior written permission. -NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED -BY THIS LICENSE. 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. -***********************************************************************/ - -#include "silk_SigProc_FIX.h" -#include "silk_resampler_private.h" - -/* Fourth order ARMA filter */ -/* Internally operates as two biquad filters in sequence. */ - -/* Coeffients are stored in a packed format: */ -/* { B1_Q14[1], B2_Q14[1], -A1_Q14[1], -A1_Q14[2], -A2_Q14[1], -A2_Q14[2], gain_Q16 } */ -/* where it is assumed that B*_Q14[0], B*_Q14[2], A*_Q14[0] are all 16384 */ - -void silk_resampler_private_ARMA4( - opus_int32 S[], /* I/O: State vector [ 4 ] */ - opus_int16 out[], /* O: Output signal */ - const opus_int16 in[], /* I: Input signal */ - const opus_int16 Coef[], /* I: ARMA coefficients [ 7 ] */ - opus_int32 len /* I: Signal length */ -) -{ - opus_int32 k; - opus_int32 in_Q8, out1_Q8, out2_Q8, X; - - for( k = 0; k < len; k++ ) { - in_Q8 = SKP_LSHIFT32( (opus_int32)in[ k ], 8 ); - - /* Outputs of first and second biquad */ - out1_Q8 = SKP_ADD_LSHIFT32( in_Q8, S[ 0 ], 2 ); - out2_Q8 = SKP_ADD_LSHIFT32( out1_Q8, S[ 2 ], 2 ); - - /* Update states, which are stored in Q6. Coefficients are in Q14 here */ - X = SKP_SMLAWB( S[ 1 ], in_Q8, Coef[ 0 ] ); - S[ 0 ] = SKP_SMLAWB( X, out1_Q8, Coef[ 2 ] ); - - X = SKP_SMLAWB( S[ 3 ], out1_Q8, Coef[ 1 ] ); - S[ 2 ] = SKP_SMLAWB( X, out2_Q8, Coef[ 4 ] ); - - S[ 1 ] = SKP_SMLAWB( SKP_RSHIFT32( in_Q8, 2 ), out1_Q8, Coef[ 3 ] ); - S[ 3 ] = SKP_SMLAWB( SKP_RSHIFT32( out1_Q8, 2 ), out2_Q8, Coef[ 5 ] ); - - /* Apply gain and store to output. The coefficient is in Q16 */ - out[ k ] = (opus_int16)SKP_SAT16( SKP_RSHIFT32( SKP_SMLAWB( 128, out2_Q8, Coef[ 6 ] ), 8 ) ); - } -} - - +/*********************************************************************** +Copyright (c) 2006-2011, Skype Limited. All rights reserved. +Redistribution and use in source and binary forms, with or without +modification, (subject to the limitations in the disclaimer below) +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 Skype Limited, nor the names of specific +contributors, may be used to endorse or promote products derived from +this software without specific prior written permission. +NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED +BY THIS LICENSE. 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. +***********************************************************************/ + +#include "silk_SigProc_FIX.h" +#include "silk_resampler_private.h" + +/* Fourth order ARMA filter */ +/* Internally operates as two biquad filters in sequence. */ + +/* Coeffients are stored in a packed format: */ +/* { B1_Q14[1], B2_Q14[1], -A1_Q14[1], -A1_Q14[2], -A2_Q14[1], -A2_Q14[2], gain_Q16 } */ +/* where it is assumed that B*_Q14[0], B*_Q14[2], A*_Q14[0] are all 16384 */ + +void silk_resampler_private_ARMA4( + opus_int32 S[], /* I/O: State vector [ 4 ] */ + opus_int16 out[], /* O: Output signal */ + const opus_int16 in[], /* I: Input signal */ + const opus_int16 Coef[], /* I: ARMA coefficients [ 7 ] */ + opus_int32 len /* I: Signal length */ +) +{ + opus_int32 k; + opus_int32 in_Q8, out1_Q8, out2_Q8, X; + + for( k = 0; k < len; k++ ) { + in_Q8 = SKP_LSHIFT32( (opus_int32)in[ k ], 8 ); + + /* Outputs of first and second biquad */ + out1_Q8 = SKP_ADD_LSHIFT32( in_Q8, S[ 0 ], 2 ); + out2_Q8 = SKP_ADD_LSHIFT32( out1_Q8, S[ 2 ], 2 ); + + /* Update states, which are stored in Q6. Coefficients are in Q14 here */ + X = SKP_SMLAWB( S[ 1 ], in_Q8, Coef[ 0 ] ); + S[ 0 ] = SKP_SMLAWB( X, out1_Q8, Coef[ 2 ] ); + + X = SKP_SMLAWB( S[ 3 ], out1_Q8, Coef[ 1 ] ); + S[ 2 ] = SKP_SMLAWB( X, out2_Q8, Coef[ 4 ] ); + + S[ 1 ] = SKP_SMLAWB( SKP_RSHIFT32( in_Q8, 2 ), out1_Q8, Coef[ 3 ] ); + S[ 3 ] = SKP_SMLAWB( SKP_RSHIFT32( out1_Q8, 2 ), out2_Q8, Coef[ 5 ] ); + + /* Apply gain and store to output. The coefficient is in Q16 */ + out[ k ] = (opus_int16)SKP_SAT16( SKP_RSHIFT32( SKP_SMLAWB( 128, out2_Q8, Coef[ 6 ] ), 8 ) ); + } +} + + diff --git a/silk/silk_resampler_private_IIR_FIR.c b/silk/silk_resampler_private_IIR_FIR.c index 1fcf8f90d..b2ea23942 100644 --- a/silk/silk_resampler_private_IIR_FIR.c +++ b/silk/silk_resampler_private_IIR_FIR.c @@ -1,97 +1,97 @@ -/*********************************************************************** -Copyright (c) 2006-2011, Skype Limited. All rights reserved. -Redistribution and use in source and binary forms, with or without -modification, (subject to the limitations in the disclaimer below) -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 Skype Limited, nor the names of specific -contributors, may be used to endorse or promote products derived from -this software without specific prior written permission. -NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED -BY THIS LICENSE. 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. -***********************************************************************/ - -#include "silk_SigProc_FIX.h" -#include "silk_resampler_private.h" - -SKP_INLINE opus_int16 *silk_resampler_private_IIR_FIR_INTERPOL( - opus_int16 * out, opus_int16 * buf, opus_int32 max_index_Q16 , opus_int32 index_increment_Q16 ){ - opus_int32 index_Q16, res_Q15; - opus_int16 *buf_ptr; - opus_int32 table_index; - /* Interpolate upsampled signal and store in output array */ - for( index_Q16 = 0; index_Q16 < max_index_Q16; index_Q16 += index_increment_Q16 ) { - table_index = SKP_SMULWB( index_Q16 & 0xFFFF, 144 ); - buf_ptr = &buf[ index_Q16 >> 16 ]; - - res_Q15 = SKP_SMULBB( buf_ptr[ 0 ], silk_resampler_frac_FIR_144[ table_index ][ 0 ] ); - res_Q15 = SKP_SMLABB( res_Q15, buf_ptr[ 1 ], silk_resampler_frac_FIR_144[ table_index ][ 1 ] ); - res_Q15 = SKP_SMLABB( res_Q15, buf_ptr[ 2 ], silk_resampler_frac_FIR_144[ table_index ][ 2 ] ); - res_Q15 = SKP_SMLABB( res_Q15, buf_ptr[ 3 ], silk_resampler_frac_FIR_144[ 143 - table_index ][ 2 ] ); - res_Q15 = SKP_SMLABB( res_Q15, buf_ptr[ 4 ], silk_resampler_frac_FIR_144[ 143 - table_index ][ 1 ] ); - res_Q15 = SKP_SMLABB( res_Q15, buf_ptr[ 5 ], silk_resampler_frac_FIR_144[ 143 - table_index ][ 0 ] ); - *out++ = (opus_int16)SKP_SAT16( SKP_RSHIFT_ROUND( res_Q15, 15 ) ); - } - return out; -} -/* Upsample using a combination of allpass-based 2x upsampling and FIR interpolation */ -void silk_resampler_private_IIR_FIR( - void *SS, /* I/O: Resampler state */ - opus_int16 out[], /* O: Output signal */ - const opus_int16 in[], /* I: Input signal */ - opus_int32 inLen /* I: Number of input samples */ -) -{ - silk_resampler_state_struct *S = (silk_resampler_state_struct *)SS; - opus_int32 nSamplesIn; - opus_int32 max_index_Q16, index_increment_Q16; - opus_int16 buf[ 2 * RESAMPLER_MAX_BATCH_SIZE_IN + RESAMPLER_ORDER_FIR_144 ]; - - - /* Copy buffered samples to start of buffer */ - SKP_memcpy( buf, S->sFIR, RESAMPLER_ORDER_FIR_144 * sizeof( opus_int32 ) ); - - /* Iterate over blocks of frameSizeIn input samples */ - index_increment_Q16 = S->invRatio_Q16; - while( 1 ) { - nSamplesIn = SKP_min( inLen, S->batchSize ); - - if( S->input2x == 1 ) { - /* Upsample 2x */ - S->up2_function( S->sIIR, &buf[ RESAMPLER_ORDER_FIR_144 ], in, nSamplesIn ); - } else { - /* Fourth-order ARMA filter */ - silk_resampler_private_ARMA4( S->sIIR, &buf[ RESAMPLER_ORDER_FIR_144 ], in, S->Coefs, nSamplesIn ); - } - - max_index_Q16 = SKP_LSHIFT32( nSamplesIn, 16 + S->input2x ); /* +1 if 2x upsampling */ - out = silk_resampler_private_IIR_FIR_INTERPOL(out, buf, max_index_Q16, index_increment_Q16); - in += nSamplesIn; - inLen -= nSamplesIn; - - if( inLen > 0 ) { - /* More iterations to do; copy last part of filtered signal to beginning of buffer */ - SKP_memcpy( buf, &buf[ nSamplesIn << S->input2x ], RESAMPLER_ORDER_FIR_144 * sizeof( opus_int32 ) ); - } else { - break; - } - } - - /* Copy last part of filtered signal to the state for the next call */ - SKP_memcpy( S->sFIR, &buf[nSamplesIn << S->input2x ], RESAMPLER_ORDER_FIR_144 * sizeof( opus_int32 ) ); -} - +/*********************************************************************** +Copyright (c) 2006-2011, Skype Limited. All rights reserved. +Redistribution and use in source and binary forms, with or without +modification, (subject to the limitations in the disclaimer below) +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 Skype Limited, nor the names of specific +contributors, may be used to endorse or promote products derived from +this software without specific prior written permission. +NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED +BY THIS LICENSE. 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. +***********************************************************************/ + +#include "silk_SigProc_FIX.h" +#include "silk_resampler_private.h" + +SKP_INLINE opus_int16 *silk_resampler_private_IIR_FIR_INTERPOL( + opus_int16 * out, opus_int16 * buf, opus_int32 max_index_Q16 , opus_int32 index_increment_Q16 ){ + opus_int32 index_Q16, res_Q15; + opus_int16 *buf_ptr; + opus_int32 table_index; + /* Interpolate upsampled signal and store in output array */ + for( index_Q16 = 0; index_Q16 < max_index_Q16; index_Q16 += index_increment_Q16 ) { + table_index = SKP_SMULWB( index_Q16 & 0xFFFF, 144 ); + buf_ptr = &buf[ index_Q16 >> 16 ]; + + res_Q15 = SKP_SMULBB( buf_ptr[ 0 ], silk_resampler_frac_FIR_144[ table_index ][ 0 ] ); + res_Q15 = SKP_SMLABB( res_Q15, buf_ptr[ 1 ], silk_resampler_frac_FIR_144[ table_index ][ 1 ] ); + res_Q15 = SKP_SMLABB( res_Q15, buf_ptr[ 2 ], silk_resampler_frac_FIR_144[ table_index ][ 2 ] ); + res_Q15 = SKP_SMLABB( res_Q15, buf_ptr[ 3 ], silk_resampler_frac_FIR_144[ 143 - table_index ][ 2 ] ); + res_Q15 = SKP_SMLABB( res_Q15, buf_ptr[ 4 ], silk_resampler_frac_FIR_144[ 143 - table_index ][ 1 ] ); + res_Q15 = SKP_SMLABB( res_Q15, buf_ptr[ 5 ], silk_resampler_frac_FIR_144[ 143 - table_index ][ 0 ] ); + *out++ = (opus_int16)SKP_SAT16( SKP_RSHIFT_ROUND( res_Q15, 15 ) ); + } + return out; +} +/* Upsample using a combination of allpass-based 2x upsampling and FIR interpolation */ +void silk_resampler_private_IIR_FIR( + void *SS, /* I/O: Resampler state */ + opus_int16 out[], /* O: Output signal */ + const opus_int16 in[], /* I: Input signal */ + opus_int32 inLen /* I: Number of input samples */ +) +{ + silk_resampler_state_struct *S = (silk_resampler_state_struct *)SS; + opus_int32 nSamplesIn; + opus_int32 max_index_Q16, index_increment_Q16; + opus_int16 buf[ 2 * RESAMPLER_MAX_BATCH_SIZE_IN + RESAMPLER_ORDER_FIR_144 ]; + + + /* Copy buffered samples to start of buffer */ + SKP_memcpy( buf, S->sFIR, RESAMPLER_ORDER_FIR_144 * sizeof( opus_int32 ) ); + + /* Iterate over blocks of frameSizeIn input samples */ + index_increment_Q16 = S->invRatio_Q16; + while( 1 ) { + nSamplesIn = SKP_min( inLen, S->batchSize ); + + if( S->input2x == 1 ) { + /* Upsample 2x */ + S->up2_function( S->sIIR, &buf[ RESAMPLER_ORDER_FIR_144 ], in, nSamplesIn ); + } else { + /* Fourth-order ARMA filter */ + silk_resampler_private_ARMA4( S->sIIR, &buf[ RESAMPLER_ORDER_FIR_144 ], in, S->Coefs, nSamplesIn ); + } + + max_index_Q16 = SKP_LSHIFT32( nSamplesIn, 16 + S->input2x ); /* +1 if 2x upsampling */ + out = silk_resampler_private_IIR_FIR_INTERPOL(out, buf, max_index_Q16, index_increment_Q16); + in += nSamplesIn; + inLen -= nSamplesIn; + + if( inLen > 0 ) { + /* More iterations to do; copy last part of filtered signal to beginning of buffer */ + SKP_memcpy( buf, &buf[ nSamplesIn << S->input2x ], RESAMPLER_ORDER_FIR_144 * sizeof( opus_int32 ) ); + } else { + break; + } + } + + /* Copy last part of filtered signal to the state for the next call */ + SKP_memcpy( S->sFIR, &buf[nSamplesIn << S->input2x ], RESAMPLER_ORDER_FIR_144 * sizeof( opus_int32 ) ); +} + diff --git a/silk/silk_resampler_private_copy.c b/silk/silk_resampler_private_copy.c index 828e64b85..ff45ab0e4 100644 --- a/silk/silk_resampler_private_copy.c +++ b/silk/silk_resampler_private_copy.c @@ -1,40 +1,40 @@ -/*********************************************************************** -Copyright (c) 2006-2011, Skype Limited. All rights reserved. -Redistribution and use in source and binary forms, with or without -modification, (subject to the limitations in the disclaimer below) -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 Skype Limited, nor the names of specific -contributors, may be used to endorse or promote products derived from -this software without specific prior written permission. -NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED -BY THIS LICENSE. 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. -***********************************************************************/ - -#include "silk_SigProc_FIX.h" -#include "silk_resampler_private.h" - -/* Copy */ -void silk_resampler_private_copy( - void *SS, /* I/O: Resampler state (unused) */ - opus_int16 out[], /* O: Output signal */ - const opus_int16 in[], /* I: Input signal */ - opus_int32 inLen /* I: Number of input samples */ -) -{ - SKP_memcpy( out, in, inLen * sizeof( opus_int16 ) ); -} +/*********************************************************************** +Copyright (c) 2006-2011, Skype Limited. All rights reserved. +Redistribution and use in source and binary forms, with or without +modification, (subject to the limitations in the disclaimer below) +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 Skype Limited, nor the names of specific +contributors, may be used to endorse or promote products derived from +this software without specific prior written permission. +NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED +BY THIS LICENSE. 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. +***********************************************************************/ + +#include "silk_SigProc_FIX.h" +#include "silk_resampler_private.h" + +/* Copy */ +void silk_resampler_private_copy( + void *SS, /* I/O: Resampler state (unused) */ + opus_int16 out[], /* O: Output signal */ + const opus_int16 in[], /* I: Input signal */ + opus_int32 inLen /* I: Number of input samples */ +) +{ + SKP_memcpy( out, in, inLen * sizeof( opus_int16 ) ); +} diff --git a/silk/silk_resampler_private_down4.c b/silk/silk_resampler_private_down4.c index 48c610154..53cb4eb24 100644 --- a/silk/silk_resampler_private_down4.c +++ b/silk/silk_resampler_private_down4.c @@ -1,69 +1,69 @@ -/*********************************************************************** -Copyright (c) 2006-2011, Skype Limited. All rights reserved. -Redistribution and use in source and binary forms, with or without -modification, (subject to the limitations in the disclaimer below) -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 Skype Limited, nor the names of specific -contributors, may be used to endorse or promote products derived from -this software without specific prior written permission. -NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED -BY THIS LICENSE. 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. -***********************************************************************/ - -#include "silk_SigProc_FIX.h" -#include "silk_resampler_private.h" - -/* Downsample by a factor 4. Note: very low quality, only use with input sampling rates above 96 kHz. */ -void silk_resampler_private_down4( - opus_int32 *S, /* I/O: State vector [ 2 ] */ - opus_int16 *out, /* O: Output signal [ floor(len/2) ] */ - const opus_int16 *in, /* I: Input signal [ len ] */ - opus_int32 inLen /* I: Number of input samples */ -) -{ - opus_int32 k, len4 = SKP_RSHIFT32( inLen, 2 ); - opus_int32 in32, out32, Y, X; - - SKP_assert( silk_resampler_down2_0 > 0 ); - SKP_assert( silk_resampler_down2_1 < 0 ); - - /* Internal variables and state are in Q10 format */ - for( k = 0; k < len4; k++ ) { - /* Add two input samples and convert to Q10 */ - in32 = SKP_LSHIFT( SKP_ADD32( (opus_int32)in[ 4 * k ], (opus_int32)in[ 4 * k + 1 ] ), 9 ); - - /* All-pass section for even input sample */ - Y = SKP_SUB32( in32, S[ 0 ] ); - X = SKP_SMLAWB( Y, Y, silk_resampler_down2_1 ); - out32 = SKP_ADD32( S[ 0 ], X ); - S[ 0 ] = SKP_ADD32( in32, X ); - - /* Add two input samples and convert to Q10 */ - in32 = SKP_LSHIFT( SKP_ADD32( (opus_int32)in[ 4 * k + 2 ], (opus_int32)in[ 4 * k + 3 ] ), 9 ); - - /* All-pass section for odd input sample */ - Y = SKP_SUB32( in32, S[ 1 ] ); - X = SKP_SMULWB( Y, silk_resampler_down2_0 ); - out32 = SKP_ADD32( out32, S[ 1 ] ); - out32 = SKP_ADD32( out32, X ); - S[ 1 ] = SKP_ADD32( in32, X ); - - /* Add, convert back to int16 and store to output */ - out[ k ] = (opus_int16)SKP_SAT16( SKP_RSHIFT_ROUND( out32, 11 ) ); - } -} +/*********************************************************************** +Copyright (c) 2006-2011, Skype Limited. All rights reserved. +Redistribution and use in source and binary forms, with or without +modification, (subject to the limitations in the disclaimer below) +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 Skype Limited, nor the names of specific +contributors, may be used to endorse or promote products derived from +this software without specific prior written permission. +NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED +BY THIS LICENSE. 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. +***********************************************************************/ + +#include "silk_SigProc_FIX.h" +#include "silk_resampler_private.h" + +/* Downsample by a factor 4. Note: very low quality, only use with input sampling rates above 96 kHz. */ +void silk_resampler_private_down4( + opus_int32 *S, /* I/O: State vector [ 2 ] */ + opus_int16 *out, /* O: Output signal [ floor(len/2) ] */ + const opus_int16 *in, /* I: Input signal [ len ] */ + opus_int32 inLen /* I: Number of input samples */ +) +{ + opus_int32 k, len4 = SKP_RSHIFT32( inLen, 2 ); + opus_int32 in32, out32, Y, X; + + SKP_assert( silk_resampler_down2_0 > 0 ); + SKP_assert( silk_resampler_down2_1 < 0 ); + + /* Internal variables and state are in Q10 format */ + for( k = 0; k < len4; k++ ) { + /* Add two input samples and convert to Q10 */ + in32 = SKP_LSHIFT( SKP_ADD32( (opus_int32)in[ 4 * k ], (opus_int32)in[ 4 * k + 1 ] ), 9 ); + + /* All-pass section for even input sample */ + Y = SKP_SUB32( in32, S[ 0 ] ); + X = SKP_SMLAWB( Y, Y, silk_resampler_down2_1 ); + out32 = SKP_ADD32( S[ 0 ], X ); + S[ 0 ] = SKP_ADD32( in32, X ); + + /* Add two input samples and convert to Q10 */ + in32 = SKP_LSHIFT( SKP_ADD32( (opus_int32)in[ 4 * k + 2 ], (opus_int32)in[ 4 * k + 3 ] ), 9 ); + + /* All-pass section for odd input sample */ + Y = SKP_SUB32( in32, S[ 1 ] ); + X = SKP_SMULWB( Y, silk_resampler_down2_0 ); + out32 = SKP_ADD32( out32, S[ 1 ] ); + out32 = SKP_ADD32( out32, X ); + S[ 1 ] = SKP_ADD32( in32, X ); + + /* Add, convert back to int16 and store to output */ + out[ k ] = (opus_int16)SKP_SAT16( SKP_RSHIFT_ROUND( out32, 11 ) ); + } +} diff --git a/silk/silk_resampler_private_down_FIR.c b/silk/silk_resampler_private_down_FIR.c index c8a0e06e1..47b6458b8 100644 --- a/silk/silk_resampler_private_down_FIR.c +++ b/silk/silk_resampler_private_down_FIR.c @@ -1,158 +1,158 @@ -/*********************************************************************** -Copyright (c) 2006-2011, Skype Limited. All rights reserved. -Redistribution and use in source and binary forms, with or without -modification, (subject to the limitations in the disclaimer below) -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 Skype Limited, nor the names of specific -contributors, may be used to endorse or promote products derived from -this software without specific prior written permission. -NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED -BY THIS LICENSE. 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. -***********************************************************************/ - -#include "silk_SigProc_FIX.h" -#include "silk_resampler_private.h" - -SKP_INLINE opus_int16 *silk_resampler_private_down_FIR_INTERPOL0( - opus_int16 *out, opus_int32 *buf2, const opus_int16 *FIR_Coefs, opus_int32 max_index_Q16, opus_int32 index_increment_Q16){ - - opus_int32 index_Q16, res_Q6; - opus_int32 *buf_ptr; - for( index_Q16 = 0; index_Q16 < max_index_Q16; index_Q16 += index_increment_Q16 ) { - /* Integer part gives pointer to buffered input */ - buf_ptr = buf2 + SKP_RSHIFT( index_Q16, 16 ); - - /* Inner product */ - res_Q6 = SKP_SMULWB( SKP_ADD32( buf_ptr[ 0 ], buf_ptr[ 15 ] ), FIR_Coefs[ 0 ] ); - res_Q6 = SKP_SMLAWB( res_Q6, SKP_ADD32( buf_ptr[ 1 ], buf_ptr[ 14 ] ), FIR_Coefs[ 1 ] ); - res_Q6 = SKP_SMLAWB( res_Q6, SKP_ADD32( buf_ptr[ 2 ], buf_ptr[ 13 ] ), FIR_Coefs[ 2 ] ); - res_Q6 = SKP_SMLAWB( res_Q6, SKP_ADD32( buf_ptr[ 3 ], buf_ptr[ 12 ] ), FIR_Coefs[ 3 ] ); - res_Q6 = SKP_SMLAWB( res_Q6, SKP_ADD32( buf_ptr[ 4 ], buf_ptr[ 11 ] ), FIR_Coefs[ 4 ] ); - res_Q6 = SKP_SMLAWB( res_Q6, SKP_ADD32( buf_ptr[ 5 ], buf_ptr[ 10 ] ), FIR_Coefs[ 5 ] ); - res_Q6 = SKP_SMLAWB( res_Q6, SKP_ADD32( buf_ptr[ 6 ], buf_ptr[ 9 ] ), FIR_Coefs[ 6 ] ); - res_Q6 = SKP_SMLAWB( res_Q6, SKP_ADD32( buf_ptr[ 7 ], buf_ptr[ 8 ] ), FIR_Coefs[ 7 ] ); - - /* Scale down, saturate and store in output array */ - *out++ = (opus_int16)SKP_SAT16( SKP_RSHIFT_ROUND( res_Q6, 6 ) ); - } - return out; -} - -SKP_INLINE opus_int16 *silk_resampler_private_down_FIR_INTERPOL1( - opus_int16 *out, opus_int32 *buf2, const opus_int16 *FIR_Coefs, opus_int32 max_index_Q16, opus_int32 index_increment_Q16, opus_int32 FIR_Fracs){ - - opus_int32 index_Q16, res_Q6; - opus_int32 *buf_ptr; - opus_int32 interpol_ind; - const opus_int16 *interpol_ptr; - for( index_Q16 = 0; index_Q16 < max_index_Q16; index_Q16 += index_increment_Q16 ) { - /* Integer part gives pointer to buffered input */ - buf_ptr = buf2 + SKP_RSHIFT( index_Q16, 16 ); - - /* Fractional part gives interpolation coefficients */ - interpol_ind = SKP_SMULWB( index_Q16 & 0xFFFF, FIR_Fracs ); - - /* Inner product */ - interpol_ptr = &FIR_Coefs[ RESAMPLER_DOWN_ORDER_FIR / 2 * interpol_ind ]; - res_Q6 = SKP_SMULWB( buf_ptr[ 0 ], interpol_ptr[ 0 ] ); - res_Q6 = SKP_SMLAWB( res_Q6, buf_ptr[ 1 ], interpol_ptr[ 1 ] ); - res_Q6 = SKP_SMLAWB( res_Q6, buf_ptr[ 2 ], interpol_ptr[ 2 ] ); - res_Q6 = SKP_SMLAWB( res_Q6, buf_ptr[ 3 ], interpol_ptr[ 3 ] ); - res_Q6 = SKP_SMLAWB( res_Q6, buf_ptr[ 4 ], interpol_ptr[ 4 ] ); - res_Q6 = SKP_SMLAWB( res_Q6, buf_ptr[ 5 ], interpol_ptr[ 5 ] ); - res_Q6 = SKP_SMLAWB( res_Q6, buf_ptr[ 6 ], interpol_ptr[ 6 ] ); - res_Q6 = SKP_SMLAWB( res_Q6, buf_ptr[ 7 ], interpol_ptr[ 7 ] ); - interpol_ptr = &FIR_Coefs[ RESAMPLER_DOWN_ORDER_FIR / 2 * ( FIR_Fracs - 1 - interpol_ind ) ]; - res_Q6 = SKP_SMLAWB( res_Q6, buf_ptr[ 15 ], interpol_ptr[ 0 ] ); - res_Q6 = SKP_SMLAWB( res_Q6, buf_ptr[ 14 ], interpol_ptr[ 1 ] ); - res_Q6 = SKP_SMLAWB( res_Q6, buf_ptr[ 13 ], interpol_ptr[ 2 ] ); - res_Q6 = SKP_SMLAWB( res_Q6, buf_ptr[ 12 ], interpol_ptr[ 3 ] ); - res_Q6 = SKP_SMLAWB( res_Q6, buf_ptr[ 11 ], interpol_ptr[ 4 ] ); - res_Q6 = SKP_SMLAWB( res_Q6, buf_ptr[ 10 ], interpol_ptr[ 5 ] ); - res_Q6 = SKP_SMLAWB( res_Q6, buf_ptr[ 9 ], interpol_ptr[ 6 ] ); - res_Q6 = SKP_SMLAWB( res_Q6, buf_ptr[ 8 ], interpol_ptr[ 7 ] ); - - /* Scale down, saturate and store in output array */ - *out++ = (opus_int16)SKP_SAT16( SKP_RSHIFT_ROUND( res_Q6, 6 ) ); - } - return out; -} - - -/* Resample with a 2x downsampler (optional), a 2nd order AR filter followed by FIR interpolation */ -void silk_resampler_private_down_FIR( - void *SS, /* I/O: Resampler state */ - opus_int16 out[], /* O: Output signal */ - const opus_int16 in[], /* I: Input signal */ - opus_int32 inLen /* I: Number of input samples */ -) -{ - silk_resampler_state_struct *S = (silk_resampler_state_struct *)SS; - opus_int32 nSamplesIn; - opus_int32 max_index_Q16, index_increment_Q16; - opus_int16 buf1[ RESAMPLER_MAX_BATCH_SIZE_IN / 2 ]; - opus_int32 buf2[ RESAMPLER_MAX_BATCH_SIZE_IN + RESAMPLER_DOWN_ORDER_FIR ]; - const opus_int16 *FIR_Coefs; - - /* Copy buffered samples to start of buffer */ - SKP_memcpy( buf2, S->sFIR, RESAMPLER_DOWN_ORDER_FIR * sizeof( opus_int32 ) ); - - FIR_Coefs = &S->Coefs[ 2 ]; - - /* Iterate over blocks of frameSizeIn input samples */ - index_increment_Q16 = S->invRatio_Q16; - while( 1 ) { - nSamplesIn = SKP_min( inLen, S->batchSize ); - - if( S->input2x == 1 ) { - /* Downsample 2x */ - silk_resampler_down2( S->sDown2, buf1, in, nSamplesIn ); - - nSamplesIn = SKP_RSHIFT32( nSamplesIn, 1 ); - - /* Second-order AR filter (output in Q8) */ - silk_resampler_private_AR2( S->sIIR, &buf2[ RESAMPLER_DOWN_ORDER_FIR ], buf1, S->Coefs, nSamplesIn ); - } else { - /* Second-order AR filter (output in Q8) */ - silk_resampler_private_AR2( S->sIIR, &buf2[ RESAMPLER_DOWN_ORDER_FIR ], in, S->Coefs, nSamplesIn ); - } - - max_index_Q16 = SKP_LSHIFT32( nSamplesIn, 16 ); - - /* Interpolate filtered signal */ - if( S->FIR_Fracs == 1 ) { - out = silk_resampler_private_down_FIR_INTERPOL0(out, buf2, FIR_Coefs, max_index_Q16, index_increment_Q16); - } else { - out = silk_resampler_private_down_FIR_INTERPOL1(out, buf2, FIR_Coefs, max_index_Q16, index_increment_Q16, S->FIR_Fracs); - } - - in += nSamplesIn << S->input2x; - inLen -= nSamplesIn << S->input2x; - - if( inLen > S->input2x ) { - /* More iterations to do; copy last part of filtered signal to beginning of buffer */ - SKP_memcpy( buf2, &buf2[ nSamplesIn ], RESAMPLER_DOWN_ORDER_FIR * sizeof( opus_int32 ) ); - } else { - break; - } - } - - /* Copy last part of filtered signal to the state for the next call */ - SKP_memcpy( S->sFIR, &buf2[ nSamplesIn ], RESAMPLER_DOWN_ORDER_FIR * sizeof( opus_int32 ) ); -} - +/*********************************************************************** +Copyright (c) 2006-2011, Skype Limited. All rights reserved. +Redistribution and use in source and binary forms, with or without +modification, (subject to the limitations in the disclaimer below) +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 Skype Limited, nor the names of specific +contributors, may be used to endorse or promote products derived from +this software without specific prior written permission. +NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED +BY THIS LICENSE. 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. +***********************************************************************/ + +#include "silk_SigProc_FIX.h" +#include "silk_resampler_private.h" + +SKP_INLINE opus_int16 *silk_resampler_private_down_FIR_INTERPOL0( + opus_int16 *out, opus_int32 *buf2, const opus_int16 *FIR_Coefs, opus_int32 max_index_Q16, opus_int32 index_increment_Q16){ + + opus_int32 index_Q16, res_Q6; + opus_int32 *buf_ptr; + for( index_Q16 = 0; index_Q16 < max_index_Q16; index_Q16 += index_increment_Q16 ) { + /* Integer part gives pointer to buffered input */ + buf_ptr = buf2 + SKP_RSHIFT( index_Q16, 16 ); + + /* Inner product */ + res_Q6 = SKP_SMULWB( SKP_ADD32( buf_ptr[ 0 ], buf_ptr[ 15 ] ), FIR_Coefs[ 0 ] ); + res_Q6 = SKP_SMLAWB( res_Q6, SKP_ADD32( buf_ptr[ 1 ], buf_ptr[ 14 ] ), FIR_Coefs[ 1 ] ); + res_Q6 = SKP_SMLAWB( res_Q6, SKP_ADD32( buf_ptr[ 2 ], buf_ptr[ 13 ] ), FIR_Coefs[ 2 ] ); + res_Q6 = SKP_SMLAWB( res_Q6, SKP_ADD32( buf_ptr[ 3 ], buf_ptr[ 12 ] ), FIR_Coefs[ 3 ] ); + res_Q6 = SKP_SMLAWB( res_Q6, SKP_ADD32( buf_ptr[ 4 ], buf_ptr[ 11 ] ), FIR_Coefs[ 4 ] ); + res_Q6 = SKP_SMLAWB( res_Q6, SKP_ADD32( buf_ptr[ 5 ], buf_ptr[ 10 ] ), FIR_Coefs[ 5 ] ); + res_Q6 = SKP_SMLAWB( res_Q6, SKP_ADD32( buf_ptr[ 6 ], buf_ptr[ 9 ] ), FIR_Coefs[ 6 ] ); + res_Q6 = SKP_SMLAWB( res_Q6, SKP_ADD32( buf_ptr[ 7 ], buf_ptr[ 8 ] ), FIR_Coefs[ 7 ] ); + + /* Scale down, saturate and store in output array */ + *out++ = (opus_int16)SKP_SAT16( SKP_RSHIFT_ROUND( res_Q6, 6 ) ); + } + return out; +} + +SKP_INLINE opus_int16 *silk_resampler_private_down_FIR_INTERPOL1( + opus_int16 *out, opus_int32 *buf2, const opus_int16 *FIR_Coefs, opus_int32 max_index_Q16, opus_int32 index_increment_Q16, opus_int32 FIR_Fracs){ + + opus_int32 index_Q16, res_Q6; + opus_int32 *buf_ptr; + opus_int32 interpol_ind; + const opus_int16 *interpol_ptr; + for( index_Q16 = 0; index_Q16 < max_index_Q16; index_Q16 += index_increment_Q16 ) { + /* Integer part gives pointer to buffered input */ + buf_ptr = buf2 + SKP_RSHIFT( index_Q16, 16 ); + + /* Fractional part gives interpolation coefficients */ + interpol_ind = SKP_SMULWB( index_Q16 & 0xFFFF, FIR_Fracs ); + + /* Inner product */ + interpol_ptr = &FIR_Coefs[ RESAMPLER_DOWN_ORDER_FIR / 2 * interpol_ind ]; + res_Q6 = SKP_SMULWB( buf_ptr[ 0 ], interpol_ptr[ 0 ] ); + res_Q6 = SKP_SMLAWB( res_Q6, buf_ptr[ 1 ], interpol_ptr[ 1 ] ); + res_Q6 = SKP_SMLAWB( res_Q6, buf_ptr[ 2 ], interpol_ptr[ 2 ] ); + res_Q6 = SKP_SMLAWB( res_Q6, buf_ptr[ 3 ], interpol_ptr[ 3 ] ); + res_Q6 = SKP_SMLAWB( res_Q6, buf_ptr[ 4 ], interpol_ptr[ 4 ] ); + res_Q6 = SKP_SMLAWB( res_Q6, buf_ptr[ 5 ], interpol_ptr[ 5 ] ); + res_Q6 = SKP_SMLAWB( res_Q6, buf_ptr[ 6 ], interpol_ptr[ 6 ] ); + res_Q6 = SKP_SMLAWB( res_Q6, buf_ptr[ 7 ], interpol_ptr[ 7 ] ); + interpol_ptr = &FIR_Coefs[ RESAMPLER_DOWN_ORDER_FIR / 2 * ( FIR_Fracs - 1 - interpol_ind ) ]; + res_Q6 = SKP_SMLAWB( res_Q6, buf_ptr[ 15 ], interpol_ptr[ 0 ] ); + res_Q6 = SKP_SMLAWB( res_Q6, buf_ptr[ 14 ], interpol_ptr[ 1 ] ); + res_Q6 = SKP_SMLAWB( res_Q6, buf_ptr[ 13 ], interpol_ptr[ 2 ] ); + res_Q6 = SKP_SMLAWB( res_Q6, buf_ptr[ 12 ], interpol_ptr[ 3 ] ); + res_Q6 = SKP_SMLAWB( res_Q6, buf_ptr[ 11 ], interpol_ptr[ 4 ] ); + res_Q6 = SKP_SMLAWB( res_Q6, buf_ptr[ 10 ], interpol_ptr[ 5 ] ); + res_Q6 = SKP_SMLAWB( res_Q6, buf_ptr[ 9 ], interpol_ptr[ 6 ] ); + res_Q6 = SKP_SMLAWB( res_Q6, buf_ptr[ 8 ], interpol_ptr[ 7 ] ); + + /* Scale down, saturate and store in output array */ + *out++ = (opus_int16)SKP_SAT16( SKP_RSHIFT_ROUND( res_Q6, 6 ) ); + } + return out; +} + + +/* Resample with a 2x downsampler (optional), a 2nd order AR filter followed by FIR interpolation */ +void silk_resampler_private_down_FIR( + void *SS, /* I/O: Resampler state */ + opus_int16 out[], /* O: Output signal */ + const opus_int16 in[], /* I: Input signal */ + opus_int32 inLen /* I: Number of input samples */ +) +{ + silk_resampler_state_struct *S = (silk_resampler_state_struct *)SS; + opus_int32 nSamplesIn; + opus_int32 max_index_Q16, index_increment_Q16; + opus_int16 buf1[ RESAMPLER_MAX_BATCH_SIZE_IN / 2 ]; + opus_int32 buf2[ RESAMPLER_MAX_BATCH_SIZE_IN + RESAMPLER_DOWN_ORDER_FIR ]; + const opus_int16 *FIR_Coefs; + + /* Copy buffered samples to start of buffer */ + SKP_memcpy( buf2, S->sFIR, RESAMPLER_DOWN_ORDER_FIR * sizeof( opus_int32 ) ); + + FIR_Coefs = &S->Coefs[ 2 ]; + + /* Iterate over blocks of frameSizeIn input samples */ + index_increment_Q16 = S->invRatio_Q16; + while( 1 ) { + nSamplesIn = SKP_min( inLen, S->batchSize ); + + if( S->input2x == 1 ) { + /* Downsample 2x */ + silk_resampler_down2( S->sDown2, buf1, in, nSamplesIn ); + + nSamplesIn = SKP_RSHIFT32( nSamplesIn, 1 ); + + /* Second-order AR filter (output in Q8) */ + silk_resampler_private_AR2( S->sIIR, &buf2[ RESAMPLER_DOWN_ORDER_FIR ], buf1, S->Coefs, nSamplesIn ); + } else { + /* Second-order AR filter (output in Q8) */ + silk_resampler_private_AR2( S->sIIR, &buf2[ RESAMPLER_DOWN_ORDER_FIR ], in, S->Coefs, nSamplesIn ); + } + + max_index_Q16 = SKP_LSHIFT32( nSamplesIn, 16 ); + + /* Interpolate filtered signal */ + if( S->FIR_Fracs == 1 ) { + out = silk_resampler_private_down_FIR_INTERPOL0(out, buf2, FIR_Coefs, max_index_Q16, index_increment_Q16); + } else { + out = silk_resampler_private_down_FIR_INTERPOL1(out, buf2, FIR_Coefs, max_index_Q16, index_increment_Q16, S->FIR_Fracs); + } + + in += nSamplesIn << S->input2x; + inLen -= nSamplesIn << S->input2x; + + if( inLen > S->input2x ) { + /* More iterations to do; copy last part of filtered signal to beginning of buffer */ + SKP_memcpy( buf2, &buf2[ nSamplesIn ], RESAMPLER_DOWN_ORDER_FIR * sizeof( opus_int32 ) ); + } else { + break; + } + } + + /* Copy last part of filtered signal to the state for the next call */ + SKP_memcpy( S->sFIR, &buf2[ nSamplesIn ], RESAMPLER_DOWN_ORDER_FIR * sizeof( opus_int32 ) ); +} + diff --git a/silk/silk_resampler_private_up2_HQ.c b/silk/silk_resampler_private_up2_HQ.c index 5a03a8b10..e33f87d03 100644 --- a/silk/silk_resampler_private_up2_HQ.c +++ b/silk/silk_resampler_private_up2_HQ.c @@ -1,109 +1,109 @@ -/*********************************************************************** -Copyright (c) 2006-2011, Skype Limited. All rights reserved. -Redistribution and use in source and binary forms, with or without -modification, (subject to the limitations in the disclaimer below) -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 Skype Limited, nor the names of specific -contributors, may be used to endorse or promote products derived from -this software without specific prior written permission. -NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED -BY THIS LICENSE. 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. -***********************************************************************/ - -#include "silk_SigProc_FIX.h" -#include "silk_resampler_private.h" - -/* Upsample by a factor 2, high quality */ -/* Uses 2nd order allpass filters for the 2x upsampling, followed by a */ -/* notch filter just above Nyquist. */ -void silk_resampler_private_up2_HQ( - opus_int32 *S, /* I/O: Resampler state [ 6 ] */ - opus_int16 *out, /* O: Output signal [ 2 * len ] */ - const opus_int16 *in, /* I: Input signal [ len ] */ - opus_int32 len /* I: Number of INPUT samples */ -) -{ - opus_int32 k; - opus_int32 in32, out32_1, out32_2, Y, X; - - SKP_assert( silk_resampler_up2_hq_0[ 0 ] > 0 ); - SKP_assert( silk_resampler_up2_hq_0[ 1 ] < 0 ); - SKP_assert( silk_resampler_up2_hq_1[ 0 ] > 0 ); - SKP_assert( silk_resampler_up2_hq_1[ 1 ] < 0 ); - - /* Internal variables and state are in Q10 format */ - for( k = 0; k < len; k++ ) { - /* Convert to Q10 */ - in32 = SKP_LSHIFT( (opus_int32)in[ k ], 10 ); - - /* First all-pass section for even output sample */ - Y = SKP_SUB32( in32, S[ 0 ] ); - X = SKP_SMULWB( Y, silk_resampler_up2_hq_0[ 0 ] ); - out32_1 = SKP_ADD32( S[ 0 ], X ); - S[ 0 ] = SKP_ADD32( in32, X ); - - /* Second all-pass section for even output sample */ - Y = SKP_SUB32( out32_1, S[ 1 ] ); - X = SKP_SMLAWB( Y, Y, silk_resampler_up2_hq_0[ 1 ] ); - out32_2 = SKP_ADD32( S[ 1 ], X ); - S[ 1 ] = SKP_ADD32( out32_1, X ); - - /* Biquad notch filter */ - out32_2 = SKP_SMLAWB( out32_2, S[ 5 ], silk_resampler_up2_hq_notch[ 2 ] ); - out32_2 = SKP_SMLAWB( out32_2, S[ 4 ], silk_resampler_up2_hq_notch[ 1 ] ); - out32_1 = SKP_SMLAWB( out32_2, S[ 4 ], silk_resampler_up2_hq_notch[ 0 ] ); - S[ 5 ] = SKP_SUB32( out32_2, S[ 5 ] ); - - /* Apply gain in Q15, convert back to int16 and store to output */ - out[ 2 * k ] = (opus_int16)SKP_SAT16( SKP_RSHIFT32( - SKP_SMLAWB( 256, out32_1, silk_resampler_up2_hq_notch[ 3 ] ), 9 ) ); - - /* First all-pass section for odd output sample */ - Y = SKP_SUB32( in32, S[ 2 ] ); - X = SKP_SMULWB( Y, silk_resampler_up2_hq_1[ 0 ] ); - out32_1 = SKP_ADD32( S[ 2 ], X ); - S[ 2 ] = SKP_ADD32( in32, X ); - - /* Second all-pass section for odd output sample */ - Y = SKP_SUB32( out32_1, S[ 3 ] ); - X = SKP_SMLAWB( Y, Y, silk_resampler_up2_hq_1[ 1 ] ); - out32_2 = SKP_ADD32( S[ 3 ], X ); - S[ 3 ] = SKP_ADD32( out32_1, X ); - - /* Biquad notch filter */ - out32_2 = SKP_SMLAWB( out32_2, S[ 4 ], silk_resampler_up2_hq_notch[ 2 ] ); - out32_2 = SKP_SMLAWB( out32_2, S[ 5 ], silk_resampler_up2_hq_notch[ 1 ] ); - out32_1 = SKP_SMLAWB( out32_2, S[ 5 ], silk_resampler_up2_hq_notch[ 0 ] ); - S[ 4 ] = SKP_SUB32( out32_2, S[ 4 ] ); - - /* Apply gain in Q15, convert back to int16 and store to output */ - out[ 2 * k + 1 ] = (opus_int16)SKP_SAT16( SKP_RSHIFT32( - SKP_SMLAWB( 256, out32_1, silk_resampler_up2_hq_notch[ 3 ] ), 9 ) ); - } -} - -void silk_resampler_private_up2_HQ_wrapper( - void *SS, /* I/O: Resampler state (unused) */ - opus_int16 *out, /* O: Output signal [ 2 * len ] */ - const opus_int16 *in, /* I: Input signal [ len ] */ - opus_int32 len /* I: Number of input samples */ -) -{ - silk_resampler_state_struct *S = (silk_resampler_state_struct *)SS; - silk_resampler_private_up2_HQ( S->sIIR, out, in, len ); -} +/*********************************************************************** +Copyright (c) 2006-2011, Skype Limited. All rights reserved. +Redistribution and use in source and binary forms, with or without +modification, (subject to the limitations in the disclaimer below) +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 Skype Limited, nor the names of specific +contributors, may be used to endorse or promote products derived from +this software without specific prior written permission. +NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED +BY THIS LICENSE. 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. +***********************************************************************/ + +#include "silk_SigProc_FIX.h" +#include "silk_resampler_private.h" + +/* Upsample by a factor 2, high quality */ +/* Uses 2nd order allpass filters for the 2x upsampling, followed by a */ +/* notch filter just above Nyquist. */ +void silk_resampler_private_up2_HQ( + opus_int32 *S, /* I/O: Resampler state [ 6 ] */ + opus_int16 *out, /* O: Output signal [ 2 * len ] */ + const opus_int16 *in, /* I: Input signal [ len ] */ + opus_int32 len /* I: Number of INPUT samples */ +) +{ + opus_int32 k; + opus_int32 in32, out32_1, out32_2, Y, X; + + SKP_assert( silk_resampler_up2_hq_0[ 0 ] > 0 ); + SKP_assert( silk_resampler_up2_hq_0[ 1 ] < 0 ); + SKP_assert( silk_resampler_up2_hq_1[ 0 ] > 0 ); + SKP_assert( silk_resampler_up2_hq_1[ 1 ] < 0 ); + + /* Internal variables and state are in Q10 format */ + for( k = 0; k < len; k++ ) { + /* Convert to Q10 */ + in32 = SKP_LSHIFT( (opus_int32)in[ k ], 10 ); + + /* First all-pass section for even output sample */ + Y = SKP_SUB32( in32, S[ 0 ] ); + X = SKP_SMULWB( Y, silk_resampler_up2_hq_0[ 0 ] ); + out32_1 = SKP_ADD32( S[ 0 ], X ); + S[ 0 ] = SKP_ADD32( in32, X ); + + /* Second all-pass section for even output sample */ + Y = SKP_SUB32( out32_1, S[ 1 ] ); + X = SKP_SMLAWB( Y, Y, silk_resampler_up2_hq_0[ 1 ] ); + out32_2 = SKP_ADD32( S[ 1 ], X ); + S[ 1 ] = SKP_ADD32( out32_1, X ); + + /* Biquad notch filter */ + out32_2 = SKP_SMLAWB( out32_2, S[ 5 ], silk_resampler_up2_hq_notch[ 2 ] ); + out32_2 = SKP_SMLAWB( out32_2, S[ 4 ], silk_resampler_up2_hq_notch[ 1 ] ); + out32_1 = SKP_SMLAWB( out32_2, S[ 4 ], silk_resampler_up2_hq_notch[ 0 ] ); + S[ 5 ] = SKP_SUB32( out32_2, S[ 5 ] ); + + /* Apply gain in Q15, convert back to int16 and store to output */ + out[ 2 * k ] = (opus_int16)SKP_SAT16( SKP_RSHIFT32( + SKP_SMLAWB( 256, out32_1, silk_resampler_up2_hq_notch[ 3 ] ), 9 ) ); + + /* First all-pass section for odd output sample */ + Y = SKP_SUB32( in32, S[ 2 ] ); + X = SKP_SMULWB( Y, silk_resampler_up2_hq_1[ 0 ] ); + out32_1 = SKP_ADD32( S[ 2 ], X ); + S[ 2 ] = SKP_ADD32( in32, X ); + + /* Second all-pass section for odd output sample */ + Y = SKP_SUB32( out32_1, S[ 3 ] ); + X = SKP_SMLAWB( Y, Y, silk_resampler_up2_hq_1[ 1 ] ); + out32_2 = SKP_ADD32( S[ 3 ], X ); + S[ 3 ] = SKP_ADD32( out32_1, X ); + + /* Biquad notch filter */ + out32_2 = SKP_SMLAWB( out32_2, S[ 4 ], silk_resampler_up2_hq_notch[ 2 ] ); + out32_2 = SKP_SMLAWB( out32_2, S[ 5 ], silk_resampler_up2_hq_notch[ 1 ] ); + out32_1 = SKP_SMLAWB( out32_2, S[ 5 ], silk_resampler_up2_hq_notch[ 0 ] ); + S[ 4 ] = SKP_SUB32( out32_2, S[ 4 ] ); + + /* Apply gain in Q15, convert back to int16 and store to output */ + out[ 2 * k + 1 ] = (opus_int16)SKP_SAT16( SKP_RSHIFT32( + SKP_SMLAWB( 256, out32_1, silk_resampler_up2_hq_notch[ 3 ] ), 9 ) ); + } +} + +void silk_resampler_private_up2_HQ_wrapper( + void *SS, /* I/O: Resampler state (unused) */ + opus_int16 *out, /* O: Output signal [ 2 * len ] */ + const opus_int16 *in, /* I: Input signal [ len ] */ + opus_int32 len /* I: Number of input samples */ +) +{ + silk_resampler_state_struct *S = (silk_resampler_state_struct *)SS; + silk_resampler_private_up2_HQ( S->sIIR, out, in, len ); +} diff --git a/silk/silk_resampler_private_up4.c b/silk/silk_resampler_private_up4.c index bfbba9cc4..ce575e49f 100644 --- a/silk/silk_resampler_private_up4.c +++ b/silk/silk_resampler_private_up4.c @@ -1,73 +1,73 @@ -/*********************************************************************** -Copyright (c) 2006-2011, Skype Limited. All rights reserved. -Redistribution and use in source and binary forms, with or without -modification, (subject to the limitations in the disclaimer below) -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 Skype Limited, nor the names of specific -contributors, may be used to endorse or promote products derived from -this software without specific prior written permission. -NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED -BY THIS LICENSE. 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. -***********************************************************************/ - -#include "silk_SigProc_FIX.h" -#include "silk_resampler_private.h" - -/* Upsample by a factor 4, Note: low quality, only use with output sampling rates above 96 kHz. */ -void silk_resampler_private_up4( - opus_int32 *S, /* I/O: State vector [ 2 ] */ - opus_int16 *out, /* O: Output signal [ 4 * len ] */ - const opus_int16 *in, /* I: Input signal [ len ] */ - opus_int32 len /* I: Number of INPUT samples */ -) -{ - opus_int32 k; - opus_int32 in32, out32, Y, X; - opus_int16 out16; - - SKP_assert( silk_resampler_up2_lq_0 > 0 ); - SKP_assert( silk_resampler_up2_lq_1 < 0 ); - - /* Internal variables and state are in Q10 format */ - for( k = 0; k < len; k++ ) { - /* Convert to Q10 */ - in32 = SKP_LSHIFT( (opus_int32)in[ k ], 10 ); - - /* All-pass section for even output sample */ - Y = SKP_SUB32( in32, S[ 0 ] ); - X = SKP_SMULWB( Y, silk_resampler_up2_lq_0 ); - out32 = SKP_ADD32( S[ 0 ], X ); - S[ 0 ] = SKP_ADD32( in32, X ); - - /* Convert back to int16 and store to output */ - out16 = (opus_int16)SKP_SAT16( SKP_RSHIFT_ROUND( out32, 10 ) ); - out[ 4 * k ] = out16; - out[ 4 * k + 1 ] = out16; - - /* All-pass section for odd output sample */ - Y = SKP_SUB32( in32, S[ 1 ] ); - X = SKP_SMLAWB( Y, Y, silk_resampler_up2_lq_1 ); - out32 = SKP_ADD32( S[ 1 ], X ); - S[ 1 ] = SKP_ADD32( in32, X ); - - /* Convert back to int16 and store to output */ - out16 = (opus_int16)SKP_SAT16( SKP_RSHIFT_ROUND( out32, 10 ) ); - out[ 4 * k + 2 ] = out16; - out[ 4 * k + 3 ] = out16; - } -} +/*********************************************************************** +Copyright (c) 2006-2011, Skype Limited. All rights reserved. +Redistribution and use in source and binary forms, with or without +modification, (subject to the limitations in the disclaimer below) +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 Skype Limited, nor the names of specific +contributors, may be used to endorse or promote products derived from +this software without specific prior written permission. +NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED +BY THIS LICENSE. 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. +***********************************************************************/ + +#include "silk_SigProc_FIX.h" +#include "silk_resampler_private.h" + +/* Upsample by a factor 4, Note: low quality, only use with output sampling rates above 96 kHz. */ +void silk_resampler_private_up4( + opus_int32 *S, /* I/O: State vector [ 2 ] */ + opus_int16 *out, /* O: Output signal [ 4 * len ] */ + const opus_int16 *in, /* I: Input signal [ len ] */ + opus_int32 len /* I: Number of INPUT samples */ +) +{ + opus_int32 k; + opus_int32 in32, out32, Y, X; + opus_int16 out16; + + SKP_assert( silk_resampler_up2_lq_0 > 0 ); + SKP_assert( silk_resampler_up2_lq_1 < 0 ); + + /* Internal variables and state are in Q10 format */ + for( k = 0; k < len; k++ ) { + /* Convert to Q10 */ + in32 = SKP_LSHIFT( (opus_int32)in[ k ], 10 ); + + /* All-pass section for even output sample */ + Y = SKP_SUB32( in32, S[ 0 ] ); + X = SKP_SMULWB( Y, silk_resampler_up2_lq_0 ); + out32 = SKP_ADD32( S[ 0 ], X ); + S[ 0 ] = SKP_ADD32( in32, X ); + + /* Convert back to int16 and store to output */ + out16 = (opus_int16)SKP_SAT16( SKP_RSHIFT_ROUND( out32, 10 ) ); + out[ 4 * k ] = out16; + out[ 4 * k + 1 ] = out16; + + /* All-pass section for odd output sample */ + Y = SKP_SUB32( in32, S[ 1 ] ); + X = SKP_SMLAWB( Y, Y, silk_resampler_up2_lq_1 ); + out32 = SKP_ADD32( S[ 1 ], X ); + S[ 1 ] = SKP_ADD32( in32, X ); + + /* Convert back to int16 and store to output */ + out16 = (opus_int16)SKP_SAT16( SKP_RSHIFT_ROUND( out32, 10 ) ); + out[ 4 * k + 2 ] = out16; + out[ 4 * k + 3 ] = out16; + } +} diff --git a/silk/silk_resampler_rom.c b/silk/silk_resampler_rom.c index de6000ab4..eb72b1754 100644 --- a/silk/silk_resampler_rom.c +++ b/silk/silk_resampler_rom.c @@ -1,258 +1,258 @@ -/*********************************************************************** -Copyright (c) 2006-2011, Skype Limited. All rights reserved. -Redistribution and use in source and binary forms, with or without -modification, (subject to the limitations in the disclaimer below) -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 Skype Limited, nor the names of specific -contributors, may be used to endorse or promote products derived from -this software without specific prior written permission. -NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED -BY THIS LICENSE. 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. -***********************************************************************/ - -/* Filter coefficients for IIR/FIR polyphase resampling * - * Total size: < 600 Words (1.2 kB) */ - -#include "silk_resampler_private.h" - -/* Tables for 2x downsampler */ -const opus_int16 silk_resampler_down2_0 = 9872; -const opus_int16 silk_resampler_down2_1 = 39809 - 65536; - -/* Tables for 2x upsampler, low quality */ -const opus_int16 silk_resampler_up2_lq_0 = 8102; -const opus_int16 silk_resampler_up2_lq_1 = 36783 - 65536; - -/* Tables for 2x upsampler, high quality */ -const opus_int16 silk_resampler_up2_hq_0[ 2 ] = { 4280, 33727 - 65536 }; -const opus_int16 silk_resampler_up2_hq_1[ 2 ] = { 16295, 54015 - 65536 }; -const opus_int16 silk_resampler_up2_hq_notch[ 4 ] = { 6554, -3932, 6554, 30573 }; - -/* Tables with IIR and FIR coefficients for fractional downsamplers (90 Words) */ -SKP_DWORD_ALIGN const opus_int16 silk_Resampler_3_4_COEFS[ 2 + 3 * RESAMPLER_DOWN_ORDER_FIR / 2 ] = { - -20253, -13986, - 86, 7, -151, 368, -542, 232, 11041, 21904, - 39, 90, -181, 216, -17, -877, 6408, 19695, - 2, 113, -108, 2, 314, -977, 2665, 15787, -}; - -SKP_DWORD_ALIGN const opus_int16 silk_Resampler_2_3_COEFS[ 2 + 2 * RESAMPLER_DOWN_ORDER_FIR / 2 ] = { - -13997, -14120, - 60, -174, 71, 298, -800, 659, 9238, 17461, - 48, -40, -150, 314, -155, -845, 4188, 14293, -}; - -SKP_DWORD_ALIGN const opus_int16 silk_Resampler_1_2_COEFS[ 2 + RESAMPLER_DOWN_ORDER_FIR / 2 ] = { - 1233, -14293, - -91, 162, 169, -342, -505, 1332, 5281, 8742, -}; - -SKP_DWORD_ALIGN const opus_int16 silk_Resampler_3_8_COEFS[ 2 + 3 * RESAMPLER_DOWN_ORDER_FIR / 2 ] = { - 12634, -14550, - 246, -175, -326, -113, 764, 2209, 3664, 4402, - 171, 3, -301, -258, 391, 1693, 3227, 4272, - 88, 138, -236, -327, 95, 1203, 2733, 4022, -}; - -SKP_DWORD_ALIGN const opus_int16 silk_Resampler_1_3_COEFS[ 2 + RESAMPLER_DOWN_ORDER_FIR / 2 ] = { - 16306, -14409, - 99, -201, -220, -16, 572, 1483, 2433, 3043, -}; - -SKP_DWORD_ALIGN const opus_int16 silk_Resampler_2_3_COEFS_LQ[ 2 + 2 * 2 ] = { - -2797, -6507, - 4697, 10739, - 1567, 8276, -}; - -SKP_DWORD_ALIGN const opus_int16 silk_Resampler_1_3_COEFS_LQ[ 2 + 3 ] = { - 16777, -9792, - 890, 1614, 2148, -}; - - -/* Tables with coefficients for 4th order ARMA filter (35 Words), in a packed format: */ -/* { B1_Q14[1], B2_Q14[1], -A1_Q14[1], -A1_Q14[2], -A2_Q14[1], -A2_Q14[2], gain_Q16 } */ -/* where it is assumed that B*_Q14[0], B*_Q14[2], A*_Q14[0] are all 16384 */ -SKP_DWORD_ALIGN const opus_int16 silk_Resampler_320_441_ARMA4_COEFS[ 7 ] = { - 31454, 24746, -9706, -3386, -17911, -13243, 24797 -}; - -SKP_DWORD_ALIGN const opus_int16 silk_Resampler_240_441_ARMA4_COEFS[ 7 ] = { - 28721, 11254, 3189, -2546, -1495, -12618, 11562 -}; - -SKP_DWORD_ALIGN const opus_int16 silk_Resampler_160_441_ARMA4_COEFS[ 7 ] = { - 23492, -6457, 14358, -4856, 14654, -13008, 4456 -}; - -SKP_DWORD_ALIGN const opus_int16 silk_Resampler_120_441_ARMA4_COEFS[ 7 ] = { - 19311, -15569, 19489, -6950, 21441, -13559, 2370 -}; - -SKP_DWORD_ALIGN const opus_int16 silk_Resampler_80_441_ARMA4_COEFS[ 7 ] = { - 13248, -23849, 24126, -9486, 26806, -14286, 1065 -}; - -/* Table with interplation fractions of 1/288 : 2/288 : 287/288 (432 Words) */ -SKP_DWORD_ALIGN const opus_int16 silk_resampler_frac_FIR_144[ 144 ][ RESAMPLER_ORDER_FIR_144 / 2 ] = { - { -25, 58, 32526}, - { -8, -69, 32461}, - { 8, -195, 32393}, - { 25, -318, 32321}, - { 41, -439, 32244}, - { 57, -557, 32163}, - { 72, -673, 32079}, - { 88, -787, 31990}, - { 103, -899, 31897}, - { 118, -1009, 31801}, - { 133, -1116, 31700}, - { 148, -1221, 31596}, - { 162, -1324, 31488}, - { 177, -1424, 31376}, - { 191, -1522, 31260}, - { 205, -1618, 31140}, - { 218, -1712, 31017}, - { 231, -1803, 30890}, - { 245, -1893, 30759}, - { 257, -1980, 30625}, - { 270, -2065, 30487}, - { 282, -2147, 30346}, - { 295, -2228, 30201}, - { 306, -2306, 30052}, - { 318, -2382, 29900}, - { 330, -2456, 29745}, - { 341, -2528, 29586}, - { 352, -2597, 29424}, - { 362, -2664, 29259}, - { 373, -2730, 29090}, - { 383, -2793, 28918}, - { 393, -2854, 28743}, - { 402, -2912, 28565}, - { 411, -2969, 28384}, - { 421, -3024, 28199}, - { 429, -3076, 28012}, - { 438, -3126, 27822}, - { 446, -3175, 27628}, - { 454, -3221, 27432}, - { 462, -3265, 27233}, - { 469, -3307, 27031}, - { 476, -3348, 26826}, - { 483, -3386, 26619}, - { 490, -3422, 26409}, - { 496, -3456, 26196}, - { 502, -3488, 25981}, - { 508, -3518, 25763}, - { 514, -3547, 25543}, - { 519, -3573, 25320}, - { 524, -3597, 25095}, - { 529, -3620, 24867}, - { 533, -3640, 24637}, - { 538, -3659, 24405}, - { 541, -3676, 24171}, - { 545, -3691, 23934}, - { 548, -3704, 23696}, - { 552, -3716, 23455}, - { 554, -3726, 23212}, - { 557, -3733, 22967}, - { 559, -3740, 22721}, - { 561, -3744, 22472}, - { 563, -3747, 22222}, - { 565, -3748, 21970}, - { 566, -3747, 21716}, - { 567, -3745, 21460}, - { 568, -3741, 21203}, - { 568, -3735, 20944}, - { 568, -3728, 20684}, - { 568, -3719, 20422}, - { 568, -3708, 20159}, - { 568, -3697, 19894}, - { 567, -3683, 19628}, - { 566, -3668, 19361}, - { 564, -3652, 19093}, - { 563, -3634, 18823}, - { 561, -3614, 18552}, - { 559, -3594, 18280}, - { 557, -3571, 18008}, - { 554, -3548, 17734}, - { 552, -3523, 17459}, - { 549, -3497, 17183}, - { 546, -3469, 16907}, - { 542, -3440, 16630}, - { 539, -3410, 16352}, - { 535, -3379, 16074}, - { 531, -3346, 15794}, - { 527, -3312, 15515}, - { 522, -3277, 15235}, - { 517, -3241, 14954}, - { 513, -3203, 14673}, - { 507, -3165, 14392}, - { 502, -3125, 14110}, - { 497, -3085, 13828}, - { 491, -3043, 13546}, - { 485, -3000, 13264}, - { 479, -2957, 12982}, - { 473, -2912, 12699}, - { 466, -2867, 12417}, - { 460, -2820, 12135}, - { 453, -2772, 11853}, - { 446, -2724, 11571}, - { 439, -2675, 11289}, - { 432, -2625, 11008}, - { 424, -2574, 10727}, - { 417, -2522, 10446}, - { 409, -2470, 10166}, - { 401, -2417, 9886}, - { 393, -2363, 9607}, - { 385, -2309, 9328}, - { 376, -2253, 9050}, - { 368, -2198, 8773}, - { 359, -2141, 8497}, - { 351, -2084, 8221}, - { 342, -2026, 7946}, - { 333, -1968, 7672}, - { 324, -1910, 7399}, - { 315, -1850, 7127}, - { 305, -1791, 6856}, - { 296, -1731, 6586}, - { 286, -1670, 6317}, - { 277, -1609, 6049}, - { 267, -1548, 5783}, - { 257, -1486, 5517}, - { 247, -1424, 5254}, - { 237, -1362, 4991}, - { 227, -1300, 4730}, - { 217, -1237, 4470}, - { 207, -1174, 4212}, - { 197, -1110, 3956}, - { 187, -1047, 3701}, - { 176, -984, 3448}, - { 166, -920, 3196}, - { 155, -856, 2946}, - { 145, -792, 2698}, - { 134, -728, 2452}, - { 124, -664, 2207}, - { 113, -600, 1965}, - { 102, -536, 1724}, - { 92, -472, 1486}, - { 81, -408, 1249}, - { 70, -345, 1015}, - { 60, -281, 783}, - { 49, -217, 553}, - { 38, -154, 325}, -}; +/*********************************************************************** +Copyright (c) 2006-2011, Skype Limited. All rights reserved. +Redistribution and use in source and binary forms, with or without +modification, (subject to the limitations in the disclaimer below) +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 Skype Limited, nor the names of specific +contributors, may be used to endorse or promote products derived from +this software without specific prior written permission. +NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED +BY THIS LICENSE. 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. +***********************************************************************/ + +/* Filter coefficients for IIR/FIR polyphase resampling * + * Total size: < 600 Words (1.2 kB) */ + +#include "silk_resampler_private.h" + +/* Tables for 2x downsampler */ +const opus_int16 silk_resampler_down2_0 = 9872; +const opus_int16 silk_resampler_down2_1 = 39809 - 65536; + +/* Tables for 2x upsampler, low quality */ +const opus_int16 silk_resampler_up2_lq_0 = 8102; +const opus_int16 silk_resampler_up2_lq_1 = 36783 - 65536; + +/* Tables for 2x upsampler, high quality */ +const opus_int16 silk_resampler_up2_hq_0[ 2 ] = { 4280, 33727 - 65536 }; +const opus_int16 silk_resampler_up2_hq_1[ 2 ] = { 16295, 54015 - 65536 }; +const opus_int16 silk_resampler_up2_hq_notch[ 4 ] = { 6554, -3932, 6554, 30573 }; + +/* Tables with IIR and FIR coefficients for fractional downsamplers (90 Words) */ +SKP_DWORD_ALIGN const opus_int16 silk_Resampler_3_4_COEFS[ 2 + 3 * RESAMPLER_DOWN_ORDER_FIR / 2 ] = { + -20253, -13986, + 86, 7, -151, 368, -542, 232, 11041, 21904, + 39, 90, -181, 216, -17, -877, 6408, 19695, + 2, 113, -108, 2, 314, -977, 2665, 15787, +}; + +SKP_DWORD_ALIGN const opus_int16 silk_Resampler_2_3_COEFS[ 2 + 2 * RESAMPLER_DOWN_ORDER_FIR / 2 ] = { + -13997, -14120, + 60, -174, 71, 298, -800, 659, 9238, 17461, + 48, -40, -150, 314, -155, -845, 4188, 14293, +}; + +SKP_DWORD_ALIGN const opus_int16 silk_Resampler_1_2_COEFS[ 2 + RESAMPLER_DOWN_ORDER_FIR / 2 ] = { + 1233, -14293, + -91, 162, 169, -342, -505, 1332, 5281, 8742, +}; + +SKP_DWORD_ALIGN const opus_int16 silk_Resampler_3_8_COEFS[ 2 + 3 * RESAMPLER_DOWN_ORDER_FIR / 2 ] = { + 12634, -14550, + 246, -175, -326, -113, 764, 2209, 3664, 4402, + 171, 3, -301, -258, 391, 1693, 3227, 4272, + 88, 138, -236, -327, 95, 1203, 2733, 4022, +}; + +SKP_DWORD_ALIGN const opus_int16 silk_Resampler_1_3_COEFS[ 2 + RESAMPLER_DOWN_ORDER_FIR / 2 ] = { + 16306, -14409, + 99, -201, -220, -16, 572, 1483, 2433, 3043, +}; + +SKP_DWORD_ALIGN const opus_int16 silk_Resampler_2_3_COEFS_LQ[ 2 + 2 * 2 ] = { + -2797, -6507, + 4697, 10739, + 1567, 8276, +}; + +SKP_DWORD_ALIGN const opus_int16 silk_Resampler_1_3_COEFS_LQ[ 2 + 3 ] = { + 16777, -9792, + 890, 1614, 2148, +}; + + +/* Tables with coefficients for 4th order ARMA filter (35 Words), in a packed format: */ +/* { B1_Q14[1], B2_Q14[1], -A1_Q14[1], -A1_Q14[2], -A2_Q14[1], -A2_Q14[2], gain_Q16 } */ +/* where it is assumed that B*_Q14[0], B*_Q14[2], A*_Q14[0] are all 16384 */ +SKP_DWORD_ALIGN const opus_int16 silk_Resampler_320_441_ARMA4_COEFS[ 7 ] = { + 31454, 24746, -9706, -3386, -17911, -13243, 24797 +}; + +SKP_DWORD_ALIGN const opus_int16 silk_Resampler_240_441_ARMA4_COEFS[ 7 ] = { + 28721, 11254, 3189, -2546, -1495, -12618, 11562 +}; + +SKP_DWORD_ALIGN const opus_int16 silk_Resampler_160_441_ARMA4_COEFS[ 7 ] = { + 23492, -6457, 14358, -4856, 14654, -13008, 4456 +}; + +SKP_DWORD_ALIGN const opus_int16 silk_Resampler_120_441_ARMA4_COEFS[ 7 ] = { + 19311, -15569, 19489, -6950, 21441, -13559, 2370 +}; + +SKP_DWORD_ALIGN const opus_int16 silk_Resampler_80_441_ARMA4_COEFS[ 7 ] = { + 13248, -23849, 24126, -9486, 26806, -14286, 1065 +}; + +/* Table with interplation fractions of 1/288 : 2/288 : 287/288 (432 Words) */ +SKP_DWORD_ALIGN const opus_int16 silk_resampler_frac_FIR_144[ 144 ][ RESAMPLER_ORDER_FIR_144 / 2 ] = { + { -25, 58, 32526}, + { -8, -69, 32461}, + { 8, -195, 32393}, + { 25, -318, 32321}, + { 41, -439, 32244}, + { 57, -557, 32163}, + { 72, -673, 32079}, + { 88, -787, 31990}, + { 103, -899, 31897}, + { 118, -1009, 31801}, + { 133, -1116, 31700}, + { 148, -1221, 31596}, + { 162, -1324, 31488}, + { 177, -1424, 31376}, + { 191, -1522, 31260}, + { 205, -1618, 31140}, + { 218, -1712, 31017}, + { 231, -1803, 30890}, + { 245, -1893, 30759}, + { 257, -1980, 30625}, + { 270, -2065, 30487}, + { 282, -2147, 30346}, + { 295, -2228, 30201}, + { 306, -2306, 30052}, + { 318, -2382, 29900}, + { 330, -2456, 29745}, + { 341, -2528, 29586}, + { 352, -2597, 29424}, + { 362, -2664, 29259}, + { 373, -2730, 29090}, + { 383, -2793, 28918}, + { 393, -2854, 28743}, + { 402, -2912, 28565}, + { 411, -2969, 28384}, + { 421, -3024, 28199}, + { 429, -3076, 28012}, + { 438, -3126, 27822}, + { 446, -3175, 27628}, + { 454, -3221, 27432}, + { 462, -3265, 27233}, + { 469, -3307, 27031}, + { 476, -3348, 26826}, + { 483, -3386, 26619}, + { 490, -3422, 26409}, + { 496, -3456, 26196}, + { 502, -3488, 25981}, + { 508, -3518, 25763}, + { 514, -3547, 25543}, + { 519, -3573, 25320}, + { 524, -3597, 25095}, + { 529, -3620, 24867}, + { 533, -3640, 24637}, + { 538, -3659, 24405}, + { 541, -3676, 24171}, + { 545, -3691, 23934}, + { 548, -3704, 23696}, + { 552, -3716, 23455}, + { 554, -3726, 23212}, + { 557, -3733, 22967}, + { 559, -3740, 22721}, + { 561, -3744, 22472}, + { 563, -3747, 22222}, + { 565, -3748, 21970}, + { 566, -3747, 21716}, + { 567, -3745, 21460}, + { 568, -3741, 21203}, + { 568, -3735, 20944}, + { 568, -3728, 20684}, + { 568, -3719, 20422}, + { 568, -3708, 20159}, + { 568, -3697, 19894}, + { 567, -3683, 19628}, + { 566, -3668, 19361}, + { 564, -3652, 19093}, + { 563, -3634, 18823}, + { 561, -3614, 18552}, + { 559, -3594, 18280}, + { 557, -3571, 18008}, + { 554, -3548, 17734}, + { 552, -3523, 17459}, + { 549, -3497, 17183}, + { 546, -3469, 16907}, + { 542, -3440, 16630}, + { 539, -3410, 16352}, + { 535, -3379, 16074}, + { 531, -3346, 15794}, + { 527, -3312, 15515}, + { 522, -3277, 15235}, + { 517, -3241, 14954}, + { 513, -3203, 14673}, + { 507, -3165, 14392}, + { 502, -3125, 14110}, + { 497, -3085, 13828}, + { 491, -3043, 13546}, + { 485, -3000, 13264}, + { 479, -2957, 12982}, + { 473, -2912, 12699}, + { 466, -2867, 12417}, + { 460, -2820, 12135}, + { 453, -2772, 11853}, + { 446, -2724, 11571}, + { 439, -2675, 11289}, + { 432, -2625, 11008}, + { 424, -2574, 10727}, + { 417, -2522, 10446}, + { 409, -2470, 10166}, + { 401, -2417, 9886}, + { 393, -2363, 9607}, + { 385, -2309, 9328}, + { 376, -2253, 9050}, + { 368, -2198, 8773}, + { 359, -2141, 8497}, + { 351, -2084, 8221}, + { 342, -2026, 7946}, + { 333, -1968, 7672}, + { 324, -1910, 7399}, + { 315, -1850, 7127}, + { 305, -1791, 6856}, + { 296, -1731, 6586}, + { 286, -1670, 6317}, + { 277, -1609, 6049}, + { 267, -1548, 5783}, + { 257, -1486, 5517}, + { 247, -1424, 5254}, + { 237, -1362, 4991}, + { 227, -1300, 4730}, + { 217, -1237, 4470}, + { 207, -1174, 4212}, + { 197, -1110, 3956}, + { 187, -1047, 3701}, + { 176, -984, 3448}, + { 166, -920, 3196}, + { 155, -856, 2946}, + { 145, -792, 2698}, + { 134, -728, 2452}, + { 124, -664, 2207}, + { 113, -600, 1965}, + { 102, -536, 1724}, + { 92, -472, 1486}, + { 81, -408, 1249}, + { 70, -345, 1015}, + { 60, -281, 783}, + { 49, -217, 553}, + { 38, -154, 325}, +}; diff --git a/silk/silk_resampler_rom.h b/silk/silk_resampler_rom.h index f5b82c67c..d3a5bdd4d 100644 --- a/silk/silk_resampler_rom.h +++ b/silk/silk_resampler_rom.h @@ -1,79 +1,79 @@ -/*********************************************************************** -Copyright (c) 2006-2011, Skype Limited. All rights reserved. -Redistribution and use in source and binary forms, with or without -modification, (subject to the limitations in the disclaimer below) -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 Skype Limited, nor the names of specific -contributors, may be used to endorse or promote products derived from -this software without specific prior written permission. -NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED -BY THIS LICENSE. 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. -***********************************************************************/ - -#ifndef _SILK_FIX_RESAMPLER_ROM_H_ -#define _SILK_FIX_RESAMPLER_ROM_H_ - -#ifdef __cplusplus -extern "C" -{ -#endif - -#include "silk_typedef.h" -#include "silk_resampler_structs.h" - -#define RESAMPLER_DOWN_ORDER_FIR 16 -#define RESAMPLER_ORDER_FIR_144 6 - - -/* Tables for 2x downsampler. Values above 32767 intentionally wrap to a negative value. */ -extern const opus_int16 silk_resampler_down2_0; -extern const opus_int16 silk_resampler_down2_1; - -/* Tables for 2x upsampler, low quality. Values above 32767 intentionally wrap to a negative value. */ -extern const opus_int16 silk_resampler_up2_lq_0; -extern const opus_int16 silk_resampler_up2_lq_1; - -/* Tables for 2x upsampler, high quality. Values above 32767 intentionally wrap to a negative value. */ -extern const opus_int16 silk_resampler_up2_hq_0[ 2 ]; -extern const opus_int16 silk_resampler_up2_hq_1[ 2 ]; -extern const opus_int16 silk_resampler_up2_hq_notch[ 4 ]; - -/* Tables with IIR and FIR coefficients for fractional downsamplers */ -extern const opus_int16 silk_Resampler_3_4_COEFS[ 2 + 3 * RESAMPLER_DOWN_ORDER_FIR / 2 ]; -extern const opus_int16 silk_Resampler_2_3_COEFS[ 2 + 2 * RESAMPLER_DOWN_ORDER_FIR / 2 ]; -extern const opus_int16 silk_Resampler_1_2_COEFS[ 2 + RESAMPLER_DOWN_ORDER_FIR / 2 ]; -extern const opus_int16 silk_Resampler_3_8_COEFS[ 2 + 3 * RESAMPLER_DOWN_ORDER_FIR / 2 ]; -extern const opus_int16 silk_Resampler_1_3_COEFS[ 2 + RESAMPLER_DOWN_ORDER_FIR / 2 ]; -extern const opus_int16 silk_Resampler_2_3_COEFS_LQ[ 2 + 2 * 2 ]; -extern const opus_int16 silk_Resampler_1_3_COEFS_LQ[ 2 + 3 ]; - -/* Tables with coefficients for 4th order ARMA filter */ -extern const opus_int16 silk_Resampler_320_441_ARMA4_COEFS[ 7 ]; -extern const opus_int16 silk_Resampler_240_441_ARMA4_COEFS[ 7 ]; -extern const opus_int16 silk_Resampler_160_441_ARMA4_COEFS[ 7 ]; -extern const opus_int16 silk_Resampler_120_441_ARMA4_COEFS[ 7 ]; -extern const opus_int16 silk_Resampler_80_441_ARMA4_COEFS[ 7 ]; - -/* Table with interplation fractions of 1/288 : 2/288 : 287/288 (432 Words) */ -extern const opus_int16 silk_resampler_frac_FIR_144[ 144 ][ RESAMPLER_ORDER_FIR_144 / 2 ]; - -#ifdef __cplusplus -} -#endif - -#endif // _SILK_FIX_RESAMPLER_ROM_H_ +/*********************************************************************** +Copyright (c) 2006-2011, Skype Limited. All rights reserved. +Redistribution and use in source and binary forms, with or without +modification, (subject to the limitations in the disclaimer below) +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 Skype Limited, nor the names of specific +contributors, may be used to endorse or promote products derived from +this software without specific prior written permission. +NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED +BY THIS LICENSE. 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. +***********************************************************************/ + +#ifndef _SILK_FIX_RESAMPLER_ROM_H_ +#define _SILK_FIX_RESAMPLER_ROM_H_ + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include "silk_typedef.h" +#include "silk_resampler_structs.h" + +#define RESAMPLER_DOWN_ORDER_FIR 16 +#define RESAMPLER_ORDER_FIR_144 6 + + +/* Tables for 2x downsampler. Values above 32767 intentionally wrap to a negative value. */ +extern const opus_int16 silk_resampler_down2_0; +extern const opus_int16 silk_resampler_down2_1; + +/* Tables for 2x upsampler, low quality. Values above 32767 intentionally wrap to a negative value. */ +extern const opus_int16 silk_resampler_up2_lq_0; +extern const opus_int16 silk_resampler_up2_lq_1; + +/* Tables for 2x upsampler, high quality. Values above 32767 intentionally wrap to a negative value. */ +extern const opus_int16 silk_resampler_up2_hq_0[ 2 ]; +extern const opus_int16 silk_resampler_up2_hq_1[ 2 ]; +extern const opus_int16 silk_resampler_up2_hq_notch[ 4 ]; + +/* Tables with IIR and FIR coefficients for fractional downsamplers */ +extern const opus_int16 silk_Resampler_3_4_COEFS[ 2 + 3 * RESAMPLER_DOWN_ORDER_FIR / 2 ]; +extern const opus_int16 silk_Resampler_2_3_COEFS[ 2 + 2 * RESAMPLER_DOWN_ORDER_FIR / 2 ]; +extern const opus_int16 silk_Resampler_1_2_COEFS[ 2 + RESAMPLER_DOWN_ORDER_FIR / 2 ]; +extern const opus_int16 silk_Resampler_3_8_COEFS[ 2 + 3 * RESAMPLER_DOWN_ORDER_FIR / 2 ]; +extern const opus_int16 silk_Resampler_1_3_COEFS[ 2 + RESAMPLER_DOWN_ORDER_FIR / 2 ]; +extern const opus_int16 silk_Resampler_2_3_COEFS_LQ[ 2 + 2 * 2 ]; +extern const opus_int16 silk_Resampler_1_3_COEFS_LQ[ 2 + 3 ]; + +/* Tables with coefficients for 4th order ARMA filter */ +extern const opus_int16 silk_Resampler_320_441_ARMA4_COEFS[ 7 ]; +extern const opus_int16 silk_Resampler_240_441_ARMA4_COEFS[ 7 ]; +extern const opus_int16 silk_Resampler_160_441_ARMA4_COEFS[ 7 ]; +extern const opus_int16 silk_Resampler_120_441_ARMA4_COEFS[ 7 ]; +extern const opus_int16 silk_Resampler_80_441_ARMA4_COEFS[ 7 ]; + +/* Table with interplation fractions of 1/288 : 2/288 : 287/288 (432 Words) */ +extern const opus_int16 silk_resampler_frac_FIR_144[ 144 ][ RESAMPLER_ORDER_FIR_144 / 2 ]; + +#ifdef __cplusplus +} +#endif + +#endif // _SILK_FIX_RESAMPLER_ROM_H_ diff --git a/silk/silk_resampler_structs.h b/silk/silk_resampler_structs.h index 090ea99b1..4ef40f6c2 100644 --- a/silk/silk_resampler_structs.h +++ b/silk/silk_resampler_structs.h @@ -1,70 +1,70 @@ -/*********************************************************************** -Copyright (c) 2006-2011, Skype Limited. All rights reserved. -Redistribution and use in source and binary forms, with or without -modification, (subject to the limitations in the disclaimer below) -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 Skype Limited, nor the names of specific -contributors, may be used to endorse or promote products derived from -this software without specific prior written permission. -NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED -BY THIS LICENSE. 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. -***********************************************************************/ - -#ifndef SILK_RESAMPLER_STRUCTS_H -#define SILK_RESAMPLER_STRUCTS_H - -#ifdef __cplusplus -extern "C" { -#endif - -/* Flag to enable support for input/output sampling rates above 48 kHz. Turn off for embedded devices */ -#define RESAMPLER_SUPPORT_ABOVE_48KHZ 1 - -#define SILK_RESAMPLER_MAX_FIR_ORDER 16 -#define SILK_RESAMPLER_MAX_IIR_ORDER 6 - - -typedef struct _silk_resampler_state_struct{ - opus_int32 sIIR[ SILK_RESAMPLER_MAX_IIR_ORDER ]; /* this must be the first element of this struct */ - opus_int32 sFIR[ SILK_RESAMPLER_MAX_FIR_ORDER ]; - opus_int32 sDown2[ 2 ]; - void (*resampler_function)( void *, opus_int16 *, const opus_int16 *, opus_int32 ); - void (*up2_function)( opus_int32 *, opus_int16 *, const opus_int16 *, opus_int32 ); - opus_int32 batchSize; - opus_int32 invRatio_Q16; - opus_int32 FIR_Fracs; - opus_int32 input2x; - const opus_int16 *Coefs; -#if RESAMPLER_SUPPORT_ABOVE_48KHZ - opus_int32 sDownPre[ 2 ]; - opus_int32 sUpPost[ 2 ]; - void (*down_pre_function)( opus_int32 *, opus_int16 *, const opus_int16 *, opus_int32 ); - void (*up_post_function)( opus_int32 *, opus_int16 *, const opus_int16 *, opus_int32 ); - opus_int32 batchSizePrePost; - opus_int32 ratio_Q16; - opus_int32 nPreDownsamplers; - opus_int32 nPostUpsamplers; -#endif - opus_int32 magic_number; -} silk_resampler_state_struct; - -#ifdef __cplusplus -} -#endif -#endif // SILK_RESAMPLER_STRUCTS_H - +/*********************************************************************** +Copyright (c) 2006-2011, Skype Limited. All rights reserved. +Redistribution and use in source and binary forms, with or without +modification, (subject to the limitations in the disclaimer below) +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 Skype Limited, nor the names of specific +contributors, may be used to endorse or promote products derived from +this software without specific prior written permission. +NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED +BY THIS LICENSE. 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. +***********************************************************************/ + +#ifndef SILK_RESAMPLER_STRUCTS_H +#define SILK_RESAMPLER_STRUCTS_H + +#ifdef __cplusplus +extern "C" { +#endif + +/* Flag to enable support for input/output sampling rates above 48 kHz. Turn off for embedded devices */ +#define RESAMPLER_SUPPORT_ABOVE_48KHZ 1 + +#define SILK_RESAMPLER_MAX_FIR_ORDER 16 +#define SILK_RESAMPLER_MAX_IIR_ORDER 6 + + +typedef struct _silk_resampler_state_struct{ + opus_int32 sIIR[ SILK_RESAMPLER_MAX_IIR_ORDER ]; /* this must be the first element of this struct */ + opus_int32 sFIR[ SILK_RESAMPLER_MAX_FIR_ORDER ]; + opus_int32 sDown2[ 2 ]; + void (*resampler_function)( void *, opus_int16 *, const opus_int16 *, opus_int32 ); + void (*up2_function)( opus_int32 *, opus_int16 *, const opus_int16 *, opus_int32 ); + opus_int32 batchSize; + opus_int32 invRatio_Q16; + opus_int32 FIR_Fracs; + opus_int32 input2x; + const opus_int16 *Coefs; +#if RESAMPLER_SUPPORT_ABOVE_48KHZ + opus_int32 sDownPre[ 2 ]; + opus_int32 sUpPost[ 2 ]; + void (*down_pre_function)( opus_int32 *, opus_int16 *, const opus_int16 *, opus_int32 ); + void (*up_post_function)( opus_int32 *, opus_int16 *, const opus_int16 *, opus_int32 ); + opus_int32 batchSizePrePost; + opus_int32 ratio_Q16; + opus_int32 nPreDownsamplers; + opus_int32 nPostUpsamplers; +#endif + opus_int32 magic_number; +} silk_resampler_state_struct; + +#ifdef __cplusplus +} +#endif +#endif // SILK_RESAMPLER_STRUCTS_H + diff --git a/silk/silk_resampler_up2.c b/silk/silk_resampler_up2.c index b50184c7d..aa950e9d5 100644 --- a/silk/silk_resampler_up2.c +++ b/silk/silk_resampler_up2.c @@ -1,67 +1,67 @@ -/*********************************************************************** -Copyright (c) 2006-2011, Skype Limited. All rights reserved. -Redistribution and use in source and binary forms, with or without -modification, (subject to the limitations in the disclaimer below) -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 Skype Limited, nor the names of specific -contributors, may be used to endorse or promote products derived from -this software without specific prior written permission. -NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED -BY THIS LICENSE. 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. -***********************************************************************/ - -#include "silk_SigProc_FIX.h" -#include "silk_resampler_rom.h" - -/* Upsample by a factor 2, low quality */ -void silk_resampler_up2( - opus_int32 *S, /* I/O: State vector [ 2 ] */ - opus_int16 *out, /* O: Output signal [ 2 * len ] */ - const opus_int16 *in, /* I: Input signal [ len ] */ - opus_int32 len /* I: Number of input samples */ -) -{ - opus_int32 k; - opus_int32 in32, out32, Y, X; - - SKP_assert( silk_resampler_up2_lq_0 > 0 ); - SKP_assert( silk_resampler_up2_lq_1 < 0 ); - /* Internal variables and state are in Q10 format */ - for( k = 0; k < len; k++ ) { - /* Convert to Q10 */ - in32 = SKP_LSHIFT( (opus_int32)in[ k ], 10 ); - - /* All-pass section for even output sample */ - Y = SKP_SUB32( in32, S[ 0 ] ); - X = SKP_SMULWB( Y, silk_resampler_up2_lq_0 ); - out32 = SKP_ADD32( S[ 0 ], X ); - S[ 0 ] = SKP_ADD32( in32, X ); - - /* Convert back to int16 and store to output */ - out[ 2 * k ] = (opus_int16)SKP_SAT16( SKP_RSHIFT_ROUND( out32, 10 ) ); - - /* All-pass section for odd output sample */ - Y = SKP_SUB32( in32, S[ 1 ] ); - X = SKP_SMLAWB( Y, Y, silk_resampler_up2_lq_1 ); - out32 = SKP_ADD32( S[ 1 ], X ); - S[ 1 ] = SKP_ADD32( in32, X ); - - /* Convert back to int16 and store to output */ - out[ 2 * k + 1 ] = (opus_int16)SKP_SAT16( SKP_RSHIFT_ROUND( out32, 10 ) ); - } -} +/*********************************************************************** +Copyright (c) 2006-2011, Skype Limited. All rights reserved. +Redistribution and use in source and binary forms, with or without +modification, (subject to the limitations in the disclaimer below) +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 Skype Limited, nor the names of specific +contributors, may be used to endorse or promote products derived from +this software without specific prior written permission. +NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED +BY THIS LICENSE. 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. +***********************************************************************/ + +#include "silk_SigProc_FIX.h" +#include "silk_resampler_rom.h" + +/* Upsample by a factor 2, low quality */ +void silk_resampler_up2( + opus_int32 *S, /* I/O: State vector [ 2 ] */ + opus_int16 *out, /* O: Output signal [ 2 * len ] */ + const opus_int16 *in, /* I: Input signal [ len ] */ + opus_int32 len /* I: Number of input samples */ +) +{ + opus_int32 k; + opus_int32 in32, out32, Y, X; + + SKP_assert( silk_resampler_up2_lq_0 > 0 ); + SKP_assert( silk_resampler_up2_lq_1 < 0 ); + /* Internal variables and state are in Q10 format */ + for( k = 0; k < len; k++ ) { + /* Convert to Q10 */ + in32 = SKP_LSHIFT( (opus_int32)in[ k ], 10 ); + + /* All-pass section for even output sample */ + Y = SKP_SUB32( in32, S[ 0 ] ); + X = SKP_SMULWB( Y, silk_resampler_up2_lq_0 ); + out32 = SKP_ADD32( S[ 0 ], X ); + S[ 0 ] = SKP_ADD32( in32, X ); + + /* Convert back to int16 and store to output */ + out[ 2 * k ] = (opus_int16)SKP_SAT16( SKP_RSHIFT_ROUND( out32, 10 ) ); + + /* All-pass section for odd output sample */ + Y = SKP_SUB32( in32, S[ 1 ] ); + X = SKP_SMLAWB( Y, Y, silk_resampler_up2_lq_1 ); + out32 = SKP_ADD32( S[ 1 ], X ); + S[ 1 ] = SKP_ADD32( in32, X ); + + /* Convert back to int16 and store to output */ + out[ 2 * k + 1 ] = (opus_int16)SKP_SAT16( SKP_RSHIFT_ROUND( out32, 10 ) ); + } +} diff --git a/silk/silk_scale_copy_vector16.c b/silk/silk_scale_copy_vector16.c index 56cf1861e..25c8bf9ae 100644 --- a/silk/silk_scale_copy_vector16.c +++ b/silk/silk_scale_copy_vector16.c @@ -1,45 +1,45 @@ -/*********************************************************************** -Copyright (c) 2006-2011, Skype Limited. All rights reserved. -Redistribution and use in source and binary forms, with or without -modification, (subject to the limitations in the disclaimer below) -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 Skype Limited, nor the names of specific -contributors, may be used to endorse or promote products derived from -this software without specific prior written permission. -NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED -BY THIS LICENSE. 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. -***********************************************************************/ - -#include "silk_SigProc_FIX.h" - -/* Copy and multiply a vector by a constant */ -void silk_scale_copy_vector16( - opus_int16 *data_out, - const opus_int16 *data_in, - opus_int32 gain_Q16, /* (I): gain in Q16 */ - const opus_int dataSize /* (I): length */ -) -{ - opus_int i; - opus_int32 tmp32; - - for( i = 0; i < dataSize; i++ ) { - tmp32 = SKP_SMULWB( gain_Q16, data_in[ i ] ); - data_out[ i ] = (opus_int16)SKP_CHECK_FIT16( tmp32 ); - } -} +/*********************************************************************** +Copyright (c) 2006-2011, Skype Limited. All rights reserved. +Redistribution and use in source and binary forms, with or without +modification, (subject to the limitations in the disclaimer below) +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 Skype Limited, nor the names of specific +contributors, may be used to endorse or promote products derived from +this software without specific prior written permission. +NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED +BY THIS LICENSE. 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. +***********************************************************************/ + +#include "silk_SigProc_FIX.h" + +/* Copy and multiply a vector by a constant */ +void silk_scale_copy_vector16( + opus_int16 *data_out, + const opus_int16 *data_in, + opus_int32 gain_Q16, /* (I): gain in Q16 */ + const opus_int dataSize /* (I): length */ +) +{ + opus_int i; + opus_int32 tmp32; + + for( i = 0; i < dataSize; i++ ) { + tmp32 = SKP_SMULWB( gain_Q16, data_in[ i ] ); + data_out[ i ] = (opus_int16)SKP_CHECK_FIT16( tmp32 ); + } +} diff --git a/silk/silk_scale_vector.c b/silk/silk_scale_vector.c index 371fcb08b..b028d9c0b 100644 --- a/silk/silk_scale_vector.c +++ b/silk/silk_scale_vector.c @@ -1,42 +1,42 @@ -/*********************************************************************** -Copyright (c) 2006-2011, Skype Limited. All rights reserved. -Redistribution and use in source and binary forms, with or without -modification, (subject to the limitations in the disclaimer below) -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 Skype Limited, nor the names of specific -contributors, may be used to endorse or promote products derived from -this software without specific prior written permission. -NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED -BY THIS LICENSE. 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. -***********************************************************************/ - -#include "silk_SigProc_FIX.h" - -/* Multiply a vector by a constant */ -void silk_scale_vector32_Q26_lshift_18( - opus_int32 *data1, /* (I/O): Q0/Q18 */ - opus_int32 gain_Q26, /* (I): Q26 */ - opus_int dataSize /* (I): length */ -) -{ - opus_int i; - - for( i = 0; i < dataSize; i++ ) { - data1[ i ] = (opus_int32)SKP_CHECK_FIT32( SKP_RSHIFT64( SKP_SMULL( data1[ i ], gain_Q26 ), 8 ) );// OUTPUT: Q18 - } -} +/*********************************************************************** +Copyright (c) 2006-2011, Skype Limited. All rights reserved. +Redistribution and use in source and binary forms, with or without +modification, (subject to the limitations in the disclaimer below) +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 Skype Limited, nor the names of specific +contributors, may be used to endorse or promote products derived from +this software without specific prior written permission. +NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED +BY THIS LICENSE. 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. +***********************************************************************/ + +#include "silk_SigProc_FIX.h" + +/* Multiply a vector by a constant */ +void silk_scale_vector32_Q26_lshift_18( + opus_int32 *data1, /* (I/O): Q0/Q18 */ + opus_int32 gain_Q26, /* (I): Q26 */ + opus_int dataSize /* (I): length */ +) +{ + opus_int i; + + for( i = 0; i < dataSize; i++ ) { + data1[ i ] = (opus_int32)SKP_CHECK_FIT32( SKP_RSHIFT64( SKP_SMULL( data1[ i ], gain_Q26 ), 8 ) );// OUTPUT: Q18 + } +} diff --git a/silk/silk_schur.c b/silk/silk_schur.c index 57ebd4b20..d8dc047da 100644 --- a/silk/silk_schur.c +++ b/silk/silk_schur.c @@ -1,86 +1,86 @@ -/*********************************************************************** -Copyright (c) 2006-2011, Skype Limited. All rights reserved. -Redistribution and use in source and binary forms, with or without -modification, (subject to the limitations in the disclaimer below) -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 Skype Limited, nor the names of specific -contributors, may be used to endorse or promote products derived from -this software without specific prior written permission. -NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED -BY THIS LICENSE. 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. -***********************************************************************/ - -#include "silk_SigProc_FIX.h" - -/* Faster than schur64(), but much less accurate. */ -/* uses SMLAWB(), requiring armv5E and higher. */ -opus_int32 silk_schur( /* O: Returns residual energy */ - opus_int16 *rc_Q15, /* O: reflection coefficients [order] Q15 */ - const opus_int32 *c, /* I: correlations [order+1] */ - const opus_int32 order /* I: prediction order */ -) -{ - opus_int k, n, lz; - opus_int32 C[ SILK_MAX_ORDER_LPC + 1 ][ 2 ]; - opus_int32 Ctmp1, Ctmp2, rc_tmp_Q15; - - /* Get number of leading zeros */ - lz = silk_CLZ32( c[ 0 ] ); - - /* Copy correlations and adjust level to Q30 */ - if( lz < 2 ) { - /* lz must be 1, so shift one to the right */ - for( k = 0; k < order + 1; k++ ) { - C[ k ][ 0 ] = C[ k ][ 1 ] = SKP_RSHIFT( c[ k ], 1 ); - } - } else if( lz > 2 ) { - /* Shift to the left */ - lz -= 2; - for( k = 0; k < order + 1; k++ ) { - C[ k ][ 0 ] = C[ k ][ 1 ] = SKP_LSHIFT( c[ k ], lz ); - } - } else { - /* No need to shift */ - for( k = 0; k < order + 1; k++ ) { - C[ k ][ 0 ] = C[ k ][ 1 ] = c[ k ]; - } - } - - for( k = 0; k < order; k++ ) { - - /* Get reflection coefficient */ - rc_tmp_Q15 = -SKP_DIV32_16( C[ k + 1 ][ 0 ], SKP_max_32( SKP_RSHIFT( C[ 0 ][ 1 ], 15 ), 1 ) ); - - /* Clip (shouldn't happen for properly conditioned inputs) */ - rc_tmp_Q15 = SKP_SAT16( rc_tmp_Q15 ); - - /* Store */ - rc_Q15[ k ] = ( opus_int16 )rc_tmp_Q15; - - /* Update correlations */ - for( n = 0; n < order - k; n++ ) { - Ctmp1 = C[ n + k + 1 ][ 0 ]; - Ctmp2 = C[ n ][ 1 ]; - C[ n + k + 1 ][ 0 ] = SKP_SMLAWB( Ctmp1, SKP_LSHIFT( Ctmp2, 1 ), rc_tmp_Q15 ); - C[ n ][ 1 ] = SKP_SMLAWB( Ctmp2, SKP_LSHIFT( Ctmp1, 1 ), rc_tmp_Q15 ); - } - } - - /* return residual energy */ - return C[ 0 ][ 1 ]; -} +/*********************************************************************** +Copyright (c) 2006-2011, Skype Limited. All rights reserved. +Redistribution and use in source and binary forms, with or without +modification, (subject to the limitations in the disclaimer below) +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 Skype Limited, nor the names of specific +contributors, may be used to endorse or promote products derived from +this software without specific prior written permission. +NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED +BY THIS LICENSE. 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. +***********************************************************************/ + +#include "silk_SigProc_FIX.h" + +/* Faster than schur64(), but much less accurate. */ +/* uses SMLAWB(), requiring armv5E and higher. */ +opus_int32 silk_schur( /* O: Returns residual energy */ + opus_int16 *rc_Q15, /* O: reflection coefficients [order] Q15 */ + const opus_int32 *c, /* I: correlations [order+1] */ + const opus_int32 order /* I: prediction order */ +) +{ + opus_int k, n, lz; + opus_int32 C[ SILK_MAX_ORDER_LPC + 1 ][ 2 ]; + opus_int32 Ctmp1, Ctmp2, rc_tmp_Q15; + + /* Get number of leading zeros */ + lz = silk_CLZ32( c[ 0 ] ); + + /* Copy correlations and adjust level to Q30 */ + if( lz < 2 ) { + /* lz must be 1, so shift one to the right */ + for( k = 0; k < order + 1; k++ ) { + C[ k ][ 0 ] = C[ k ][ 1 ] = SKP_RSHIFT( c[ k ], 1 ); + } + } else if( lz > 2 ) { + /* Shift to the left */ + lz -= 2; + for( k = 0; k < order + 1; k++ ) { + C[ k ][ 0 ] = C[ k ][ 1 ] = SKP_LSHIFT( c[ k ], lz ); + } + } else { + /* No need to shift */ + for( k = 0; k < order + 1; k++ ) { + C[ k ][ 0 ] = C[ k ][ 1 ] = c[ k ]; + } + } + + for( k = 0; k < order; k++ ) { + + /* Get reflection coefficient */ + rc_tmp_Q15 = -SKP_DIV32_16( C[ k + 1 ][ 0 ], SKP_max_32( SKP_RSHIFT( C[ 0 ][ 1 ], 15 ), 1 ) ); + + /* Clip (shouldn't happen for properly conditioned inputs) */ + rc_tmp_Q15 = SKP_SAT16( rc_tmp_Q15 ); + + /* Store */ + rc_Q15[ k ] = ( opus_int16 )rc_tmp_Q15; + + /* Update correlations */ + for( n = 0; n < order - k; n++ ) { + Ctmp1 = C[ n + k + 1 ][ 0 ]; + Ctmp2 = C[ n ][ 1 ]; + C[ n + k + 1 ][ 0 ] = SKP_SMLAWB( Ctmp1, SKP_LSHIFT( Ctmp2, 1 ), rc_tmp_Q15 ); + C[ n ][ 1 ] = SKP_SMLAWB( Ctmp2, SKP_LSHIFT( Ctmp1, 1 ), rc_tmp_Q15 ); + } + } + + /* return residual energy */ + return C[ 0 ][ 1 ]; +} diff --git a/silk/silk_schur64.c b/silk/silk_schur64.c index 02e93a777..4f6591d5a 100644 --- a/silk/silk_schur64.c +++ b/silk/silk_schur64.c @@ -1,71 +1,71 @@ -/*********************************************************************** -Copyright (c) 2006-2011, Skype Limited. All rights reserved. -Redistribution and use in source and binary forms, with or without -modification, (subject to the limitations in the disclaimer below) -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 Skype Limited, nor the names of specific -contributors, may be used to endorse or promote products derived from -this software without specific prior written permission. -NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED -BY THIS LICENSE. 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. -***********************************************************************/ - -#include "silk_SigProc_FIX.h" - -/* Slower than schur(), but more accurate. */ -/* Uses SMULL(), available on armv4 */ -opus_int32 silk_schur64( /* O: Returns residual energy */ - opus_int32 rc_Q16[], /* O: Reflection coefficients [order] Q16 */ - const opus_int32 c[], /* I: Correlations [order+1] */ - opus_int32 order /* I: Prediction order */ -) -{ - opus_int k, n; - opus_int32 C[ SILK_MAX_ORDER_LPC + 1 ][ 2 ]; - opus_int32 Ctmp1_Q30, Ctmp2_Q30, rc_tmp_Q31; - - /* Check for invalid input */ - if( c[ 0 ] <= 0 ) { - SKP_memset( rc_Q16, 0, order * sizeof( opus_int32 ) ); - return 0; - } - - for( k = 0; k < order + 1; k++ ) { - C[ k ][ 0 ] = C[ k ][ 1 ] = c[ k ]; - } - - for( k = 0; k < order; k++ ) { - /* Get reflection coefficient: divide two Q30 values and get result in Q31 */ - rc_tmp_Q31 = silk_DIV32_varQ( -C[ k + 1 ][ 0 ], C[ 0 ][ 1 ], 31 ); - - /* Save the output */ - rc_Q16[ k ] = SKP_RSHIFT_ROUND( rc_tmp_Q31, 15 ); - - /* Update correlations */ - for( n = 0; n < order - k; n++ ) { - Ctmp1_Q30 = C[ n + k + 1 ][ 0 ]; - Ctmp2_Q30 = C[ n ][ 1 ]; - - /* Multiply and add the highest int32 */ - C[ n + k + 1 ][ 0 ] = Ctmp1_Q30 + SKP_SMMUL( SKP_LSHIFT( Ctmp2_Q30, 1 ), rc_tmp_Q31 ); - C[ n ][ 1 ] = Ctmp2_Q30 + SKP_SMMUL( SKP_LSHIFT( Ctmp1_Q30, 1 ), rc_tmp_Q31 ); - } - } - - return( C[ 0 ][ 1 ] ); -} +/*********************************************************************** +Copyright (c) 2006-2011, Skype Limited. All rights reserved. +Redistribution and use in source and binary forms, with or without +modification, (subject to the limitations in the disclaimer below) +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 Skype Limited, nor the names of specific +contributors, may be used to endorse or promote products derived from +this software without specific prior written permission. +NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED +BY THIS LICENSE. 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. +***********************************************************************/ + +#include "silk_SigProc_FIX.h" + +/* Slower than schur(), but more accurate. */ +/* Uses SMULL(), available on armv4 */ +opus_int32 silk_schur64( /* O: Returns residual energy */ + opus_int32 rc_Q16[], /* O: Reflection coefficients [order] Q16 */ + const opus_int32 c[], /* I: Correlations [order+1] */ + opus_int32 order /* I: Prediction order */ +) +{ + opus_int k, n; + opus_int32 C[ SILK_MAX_ORDER_LPC + 1 ][ 2 ]; + opus_int32 Ctmp1_Q30, Ctmp2_Q30, rc_tmp_Q31; + + /* Check for invalid input */ + if( c[ 0 ] <= 0 ) { + SKP_memset( rc_Q16, 0, order * sizeof( opus_int32 ) ); + return 0; + } + + for( k = 0; k < order + 1; k++ ) { + C[ k ][ 0 ] = C[ k ][ 1 ] = c[ k ]; + } + + for( k = 0; k < order; k++ ) { + /* Get reflection coefficient: divide two Q30 values and get result in Q31 */ + rc_tmp_Q31 = silk_DIV32_varQ( -C[ k + 1 ][ 0 ], C[ 0 ][ 1 ], 31 ); + + /* Save the output */ + rc_Q16[ k ] = SKP_RSHIFT_ROUND( rc_tmp_Q31, 15 ); + + /* Update correlations */ + for( n = 0; n < order - k; n++ ) { + Ctmp1_Q30 = C[ n + k + 1 ][ 0 ]; + Ctmp2_Q30 = C[ n ][ 1 ]; + + /* Multiply and add the highest int32 */ + C[ n + k + 1 ][ 0 ] = Ctmp1_Q30 + SKP_SMMUL( SKP_LSHIFT( Ctmp2_Q30, 1 ), rc_tmp_Q31 ); + C[ n ][ 1 ] = Ctmp2_Q30 + SKP_SMMUL( SKP_LSHIFT( Ctmp1_Q30, 1 ), rc_tmp_Q31 ); + } + } + + return( C[ 0 ][ 1 ] ); +} diff --git a/silk/silk_shell_coder.c b/silk/silk_shell_coder.c index d226b33cf..e94859907 100644 --- a/silk/silk_shell_coder.c +++ b/silk/silk_shell_coder.c @@ -1,147 +1,147 @@ -/*********************************************************************** -Copyright (c) 2006-2011, Skype Limited. All rights reserved. -Redistribution and use in source and binary forms, with or without -modification, (subject to the limitations in the disclaimer below) -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 Skype Limited, nor the names of specific -contributors, may be used to endorse or promote products derived from -this software without specific prior written permission. -NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED -BY THIS LICENSE. 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. -***********************************************************************/ - -#include "silk_main.h" - -/* shell coder; pulse-subframe length is hardcoded */ - -SKP_INLINE void combine_pulses( - opus_int *out, /* O: combined pulses vector [len] */ - const opus_int *in, /* I: input vector [2 * len] */ - const opus_int len /* I: number of OUTPUT samples */ -) -{ - opus_int k; - for( k = 0; k < len; k++ ) { - out[ k ] = in[ 2 * k ] + in[ 2 * k + 1 ]; - } -} - -SKP_INLINE void encode_split( - ec_enc *psRangeEnc, /* I/O compressor data structure */ - const opus_int p_child1, /* I: pulse amplitude of first child subframe */ - const opus_int p, /* I: pulse amplitude of current subframe */ - const opus_uint8 *shell_table /* I: table of shell cdfs */ -) -{ - if( p > 0 ) { - ec_enc_icdf( psRangeEnc, p_child1, &shell_table[ silk_shell_code_table_offsets[ p ] ], 8 ); - } -} - -SKP_INLINE void decode_split( - opus_int *p_child1, /* O: pulse amplitude of first child subframe */ - opus_int *p_child2, /* O: pulse amplitude of second child subframe */ - ec_dec *psRangeDec, /* I/O Compressor data structure */ - const opus_int p, /* I: pulse amplitude of current subframe */ - const opus_uint8 *shell_table /* I: table of shell cdfs */ -) -{ - if( p > 0 ) { - p_child1[ 0 ] = ec_dec_icdf( psRangeDec, &shell_table[ silk_shell_code_table_offsets[ p ] ], 8 ); - p_child2[ 0 ] = p - p_child1[ 0 ]; - } else { - p_child1[ 0 ] = 0; - p_child2[ 0 ] = 0; - } -} - -/* Shell encoder, operates on one shell code frame of 16 pulses */ -void silk_shell_encoder( - ec_enc *psRangeEnc, /* I/O compressor data structure */ - const opus_int *pulses0 /* I data: nonnegative pulse amplitudes */ -) -{ - opus_int pulses1[ 8 ], pulses2[ 4 ], pulses3[ 2 ], pulses4[ 1 ]; - - /* this function operates on one shell code frame of 16 pulses */ - SKP_assert( SHELL_CODEC_FRAME_LENGTH == 16 ); - - /* tree representation per pulse-subframe */ - combine_pulses( pulses1, pulses0, 8 ); - combine_pulses( pulses2, pulses1, 4 ); - combine_pulses( pulses3, pulses2, 2 ); - combine_pulses( pulses4, pulses3, 1 ); - - encode_split( psRangeEnc, pulses3[ 0 ], pulses4[ 0 ], silk_shell_code_table3 ); - - encode_split( psRangeEnc, pulses2[ 0 ], pulses3[ 0 ], silk_shell_code_table2 ); - - encode_split( psRangeEnc, pulses1[ 0 ], pulses2[ 0 ], silk_shell_code_table1 ); - encode_split( psRangeEnc, pulses0[ 0 ], pulses1[ 0 ], silk_shell_code_table0 ); - encode_split( psRangeEnc, pulses0[ 2 ], pulses1[ 1 ], silk_shell_code_table0 ); - - encode_split( psRangeEnc, pulses1[ 2 ], pulses2[ 1 ], silk_shell_code_table1 ); - encode_split( psRangeEnc, pulses0[ 4 ], pulses1[ 2 ], silk_shell_code_table0 ); - encode_split( psRangeEnc, pulses0[ 6 ], pulses1[ 3 ], silk_shell_code_table0 ); - - encode_split( psRangeEnc, pulses2[ 2 ], pulses3[ 1 ], silk_shell_code_table2 ); - - encode_split( psRangeEnc, pulses1[ 4 ], pulses2[ 2 ], silk_shell_code_table1 ); - encode_split( psRangeEnc, pulses0[ 8 ], pulses1[ 4 ], silk_shell_code_table0 ); - encode_split( psRangeEnc, pulses0[ 10 ], pulses1[ 5 ], silk_shell_code_table0 ); - - encode_split( psRangeEnc, pulses1[ 6 ], pulses2[ 3 ], silk_shell_code_table1 ); - encode_split( psRangeEnc, pulses0[ 12 ], pulses1[ 6 ], silk_shell_code_table0 ); - encode_split( psRangeEnc, pulses0[ 14 ], pulses1[ 7 ], silk_shell_code_table0 ); -} - - -/* Shell decoder, operates on one shell code frame of 16 pulses */ -void silk_shell_decoder( - opus_int *pulses0, /* O data: nonnegative pulse amplitudes */ - ec_dec *psRangeDec, /* I/O Compressor data structure */ - const opus_int pulses4 /* I number of pulses per pulse-subframe */ -) -{ - opus_int pulses3[ 2 ], pulses2[ 4 ], pulses1[ 8 ]; - - /* this function operates on one shell code frame of 16 pulses */ - SKP_assert( SHELL_CODEC_FRAME_LENGTH == 16 ); - - decode_split( &pulses3[ 0 ], &pulses3[ 1 ], psRangeDec, pulses4, silk_shell_code_table3 ); - - decode_split( &pulses2[ 0 ], &pulses2[ 1 ], psRangeDec, pulses3[ 0 ], silk_shell_code_table2 ); - - decode_split( &pulses1[ 0 ], &pulses1[ 1 ], psRangeDec, pulses2[ 0 ], silk_shell_code_table1 ); - decode_split( &pulses0[ 0 ], &pulses0[ 1 ], psRangeDec, pulses1[ 0 ], silk_shell_code_table0 ); - decode_split( &pulses0[ 2 ], &pulses0[ 3 ], psRangeDec, pulses1[ 1 ], silk_shell_code_table0 ); - - decode_split( &pulses1[ 2 ], &pulses1[ 3 ], psRangeDec, pulses2[ 1 ], silk_shell_code_table1 ); - decode_split( &pulses0[ 4 ], &pulses0[ 5 ], psRangeDec, pulses1[ 2 ], silk_shell_code_table0 ); - decode_split( &pulses0[ 6 ], &pulses0[ 7 ], psRangeDec, pulses1[ 3 ], silk_shell_code_table0 ); - - decode_split( &pulses2[ 2 ], &pulses2[ 3 ], psRangeDec, pulses3[ 1 ], silk_shell_code_table2 ); - - decode_split( &pulses1[ 4 ], &pulses1[ 5 ], psRangeDec, pulses2[ 2 ], silk_shell_code_table1 ); - decode_split( &pulses0[ 8 ], &pulses0[ 9 ], psRangeDec, pulses1[ 4 ], silk_shell_code_table0 ); - decode_split( &pulses0[ 10 ], &pulses0[ 11 ], psRangeDec, pulses1[ 5 ], silk_shell_code_table0 ); - - decode_split( &pulses1[ 6 ], &pulses1[ 7 ], psRangeDec, pulses2[ 3 ], silk_shell_code_table1 ); - decode_split( &pulses0[ 12 ], &pulses0[ 13 ], psRangeDec, pulses1[ 6 ], silk_shell_code_table0 ); - decode_split( &pulses0[ 14 ], &pulses0[ 15 ], psRangeDec, pulses1[ 7 ], silk_shell_code_table0 ); -} +/*********************************************************************** +Copyright (c) 2006-2011, Skype Limited. All rights reserved. +Redistribution and use in source and binary forms, with or without +modification, (subject to the limitations in the disclaimer below) +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 Skype Limited, nor the names of specific +contributors, may be used to endorse or promote products derived from +this software without specific prior written permission. +NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED +BY THIS LICENSE. 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. +***********************************************************************/ + +#include "silk_main.h" + +/* shell coder; pulse-subframe length is hardcoded */ + +SKP_INLINE void combine_pulses( + opus_int *out, /* O: combined pulses vector [len] */ + const opus_int *in, /* I: input vector [2 * len] */ + const opus_int len /* I: number of OUTPUT samples */ +) +{ + opus_int k; + for( k = 0; k < len; k++ ) { + out[ k ] = in[ 2 * k ] + in[ 2 * k + 1 ]; + } +} + +SKP_INLINE void encode_split( + ec_enc *psRangeEnc, /* I/O compressor data structure */ + const opus_int p_child1, /* I: pulse amplitude of first child subframe */ + const opus_int p, /* I: pulse amplitude of current subframe */ + const opus_uint8 *shell_table /* I: table of shell cdfs */ +) +{ + if( p > 0 ) { + ec_enc_icdf( psRangeEnc, p_child1, &shell_table[ silk_shell_code_table_offsets[ p ] ], 8 ); + } +} + +SKP_INLINE void decode_split( + opus_int *p_child1, /* O: pulse amplitude of first child subframe */ + opus_int *p_child2, /* O: pulse amplitude of second child subframe */ + ec_dec *psRangeDec, /* I/O Compressor data structure */ + const opus_int p, /* I: pulse amplitude of current subframe */ + const opus_uint8 *shell_table /* I: table of shell cdfs */ +) +{ + if( p > 0 ) { + p_child1[ 0 ] = ec_dec_icdf( psRangeDec, &shell_table[ silk_shell_code_table_offsets[ p ] ], 8 ); + p_child2[ 0 ] = p - p_child1[ 0 ]; + } else { + p_child1[ 0 ] = 0; + p_child2[ 0 ] = 0; + } +} + +/* Shell encoder, operates on one shell code frame of 16 pulses */ +void silk_shell_encoder( + ec_enc *psRangeEnc, /* I/O compressor data structure */ + const opus_int *pulses0 /* I data: nonnegative pulse amplitudes */ +) +{ + opus_int pulses1[ 8 ], pulses2[ 4 ], pulses3[ 2 ], pulses4[ 1 ]; + + /* this function operates on one shell code frame of 16 pulses */ + SKP_assert( SHELL_CODEC_FRAME_LENGTH == 16 ); + + /* tree representation per pulse-subframe */ + combine_pulses( pulses1, pulses0, 8 ); + combine_pulses( pulses2, pulses1, 4 ); + combine_pulses( pulses3, pulses2, 2 ); + combine_pulses( pulses4, pulses3, 1 ); + + encode_split( psRangeEnc, pulses3[ 0 ], pulses4[ 0 ], silk_shell_code_table3 ); + + encode_split( psRangeEnc, pulses2[ 0 ], pulses3[ 0 ], silk_shell_code_table2 ); + + encode_split( psRangeEnc, pulses1[ 0 ], pulses2[ 0 ], silk_shell_code_table1 ); + encode_split( psRangeEnc, pulses0[ 0 ], pulses1[ 0 ], silk_shell_code_table0 ); + encode_split( psRangeEnc, pulses0[ 2 ], pulses1[ 1 ], silk_shell_code_table0 ); + + encode_split( psRangeEnc, pulses1[ 2 ], pulses2[ 1 ], silk_shell_code_table1 ); + encode_split( psRangeEnc, pulses0[ 4 ], pulses1[ 2 ], silk_shell_code_table0 ); + encode_split( psRangeEnc, pulses0[ 6 ], pulses1[ 3 ], silk_shell_code_table0 ); + + encode_split( psRangeEnc, pulses2[ 2 ], pulses3[ 1 ], silk_shell_code_table2 ); + + encode_split( psRangeEnc, pulses1[ 4 ], pulses2[ 2 ], silk_shell_code_table1 ); + encode_split( psRangeEnc, pulses0[ 8 ], pulses1[ 4 ], silk_shell_code_table0 ); + encode_split( psRangeEnc, pulses0[ 10 ], pulses1[ 5 ], silk_shell_code_table0 ); + + encode_split( psRangeEnc, pulses1[ 6 ], pulses2[ 3 ], silk_shell_code_table1 ); + encode_split( psRangeEnc, pulses0[ 12 ], pulses1[ 6 ], silk_shell_code_table0 ); + encode_split( psRangeEnc, pulses0[ 14 ], pulses1[ 7 ], silk_shell_code_table0 ); +} + + +/* Shell decoder, operates on one shell code frame of 16 pulses */ +void silk_shell_decoder( + opus_int *pulses0, /* O data: nonnegative pulse amplitudes */ + ec_dec *psRangeDec, /* I/O Compressor data structure */ + const opus_int pulses4 /* I number of pulses per pulse-subframe */ +) +{ + opus_int pulses3[ 2 ], pulses2[ 4 ], pulses1[ 8 ]; + + /* this function operates on one shell code frame of 16 pulses */ + SKP_assert( SHELL_CODEC_FRAME_LENGTH == 16 ); + + decode_split( &pulses3[ 0 ], &pulses3[ 1 ], psRangeDec, pulses4, silk_shell_code_table3 ); + + decode_split( &pulses2[ 0 ], &pulses2[ 1 ], psRangeDec, pulses3[ 0 ], silk_shell_code_table2 ); + + decode_split( &pulses1[ 0 ], &pulses1[ 1 ], psRangeDec, pulses2[ 0 ], silk_shell_code_table1 ); + decode_split( &pulses0[ 0 ], &pulses0[ 1 ], psRangeDec, pulses1[ 0 ], silk_shell_code_table0 ); + decode_split( &pulses0[ 2 ], &pulses0[ 3 ], psRangeDec, pulses1[ 1 ], silk_shell_code_table0 ); + + decode_split( &pulses1[ 2 ], &pulses1[ 3 ], psRangeDec, pulses2[ 1 ], silk_shell_code_table1 ); + decode_split( &pulses0[ 4 ], &pulses0[ 5 ], psRangeDec, pulses1[ 2 ], silk_shell_code_table0 ); + decode_split( &pulses0[ 6 ], &pulses0[ 7 ], psRangeDec, pulses1[ 3 ], silk_shell_code_table0 ); + + decode_split( &pulses2[ 2 ], &pulses2[ 3 ], psRangeDec, pulses3[ 1 ], silk_shell_code_table2 ); + + decode_split( &pulses1[ 4 ], &pulses1[ 5 ], psRangeDec, pulses2[ 2 ], silk_shell_code_table1 ); + decode_split( &pulses0[ 8 ], &pulses0[ 9 ], psRangeDec, pulses1[ 4 ], silk_shell_code_table0 ); + decode_split( &pulses0[ 10 ], &pulses0[ 11 ], psRangeDec, pulses1[ 5 ], silk_shell_code_table0 ); + + decode_split( &pulses1[ 6 ], &pulses1[ 7 ], psRangeDec, pulses2[ 3 ], silk_shell_code_table1 ); + decode_split( &pulses0[ 12 ], &pulses0[ 13 ], psRangeDec, pulses1[ 6 ], silk_shell_code_table0 ); + decode_split( &pulses0[ 14 ], &pulses0[ 15 ], psRangeDec, pulses1[ 7 ], silk_shell_code_table0 ); +} diff --git a/silk/silk_sigm_Q15.c b/silk/silk_sigm_Q15.c index 8785c4557..023fef6b1 100644 --- a/silk/silk_sigm_Q15.c +++ b/silk/silk_sigm_Q15.c @@ -1,70 +1,70 @@ -/*********************************************************************** -Copyright (c) 2006-2011, Skype Limited. All rights reserved. -Redistribution and use in source and binary forms, with or without -modification, (subject to the limitations in the disclaimer below) -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 Skype Limited, nor the names of specific -contributors, may be used to endorse or promote products derived from -this software without specific prior written permission. -NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED -BY THIS LICENSE. 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. -***********************************************************************/ - -/* Approximate sigmoid function */ - -#include "silk_SigProc_FIX.h" - -/* fprintf(1, '%d, ', round(1024 * ([1 ./ (1 + exp(-(1:5))), 1] - 1 ./ (1 + exp(-(0:5)))))); */ -static const opus_int32 sigm_LUT_slope_Q10[ 6 ] = { - 237, 153, 73, 30, 12, 7 -}; -/* fprintf(1, '%d, ', round(32767 * 1 ./ (1 + exp(-(0:5))))); */ -static const opus_int32 sigm_LUT_pos_Q15[ 6 ] = { - 16384, 23955, 28861, 31213, 32178, 32548 -}; -/* fprintf(1, '%d, ', round(32767 * 1 ./ (1 + exp((0:5))))); */ -static const opus_int32 sigm_LUT_neg_Q15[ 6 ] = { - 16384, 8812, 3906, 1554, 589, 219 -}; - -opus_int silk_sigm_Q15( opus_int in_Q5 ) -{ - opus_int ind; - - if( in_Q5 < 0 ) { - /* Negative input */ - in_Q5 = -in_Q5; - if( in_Q5 >= 6 * 32 ) { - return 0; /* Clip */ - } else { - /* Linear interpolation of look up table */ - ind = SKP_RSHIFT( in_Q5, 5 ); - return( sigm_LUT_neg_Q15[ ind ] - SKP_SMULBB( sigm_LUT_slope_Q10[ ind ], in_Q5 & 0x1F ) ); - } - } else { - /* Positive input */ - if( in_Q5 >= 6 * 32 ) { - return 32767; /* clip */ - } else { - /* Linear interpolation of look up table */ - ind = SKP_RSHIFT( in_Q5, 5 ); - return( sigm_LUT_pos_Q15[ ind ] + SKP_SMULBB( sigm_LUT_slope_Q10[ ind ], in_Q5 & 0x1F ) ); - } - } -} - +/*********************************************************************** +Copyright (c) 2006-2011, Skype Limited. All rights reserved. +Redistribution and use in source and binary forms, with or without +modification, (subject to the limitations in the disclaimer below) +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 Skype Limited, nor the names of specific +contributors, may be used to endorse or promote products derived from +this software without specific prior written permission. +NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED +BY THIS LICENSE. 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. +***********************************************************************/ + +/* Approximate sigmoid function */ + +#include "silk_SigProc_FIX.h" + +/* fprintf(1, '%d, ', round(1024 * ([1 ./ (1 + exp(-(1:5))), 1] - 1 ./ (1 + exp(-(0:5)))))); */ +static const opus_int32 sigm_LUT_slope_Q10[ 6 ] = { + 237, 153, 73, 30, 12, 7 +}; +/* fprintf(1, '%d, ', round(32767 * 1 ./ (1 + exp(-(0:5))))); */ +static const opus_int32 sigm_LUT_pos_Q15[ 6 ] = { + 16384, 23955, 28861, 31213, 32178, 32548 +}; +/* fprintf(1, '%d, ', round(32767 * 1 ./ (1 + exp((0:5))))); */ +static const opus_int32 sigm_LUT_neg_Q15[ 6 ] = { + 16384, 8812, 3906, 1554, 589, 219 +}; + +opus_int silk_sigm_Q15( opus_int in_Q5 ) +{ + opus_int ind; + + if( in_Q5 < 0 ) { + /* Negative input */ + in_Q5 = -in_Q5; + if( in_Q5 >= 6 * 32 ) { + return 0; /* Clip */ + } else { + /* Linear interpolation of look up table */ + ind = SKP_RSHIFT( in_Q5, 5 ); + return( sigm_LUT_neg_Q15[ ind ] - SKP_SMULBB( sigm_LUT_slope_Q10[ ind ], in_Q5 & 0x1F ) ); + } + } else { + /* Positive input */ + if( in_Q5 >= 6 * 32 ) { + return 32767; /* clip */ + } else { + /* Linear interpolation of look up table */ + ind = SKP_RSHIFT( in_Q5, 5 ); + return( sigm_LUT_pos_Q15[ ind ] + SKP_SMULBB( sigm_LUT_slope_Q10[ ind ], in_Q5 & 0x1F ) ); + } + } +} + diff --git a/silk/silk_sort.c b/silk/silk_sort.c index 3bec458d5..a327c6388 100644 --- a/silk/silk_sort.c +++ b/silk/silk_sort.c @@ -1,147 +1,147 @@ -/*********************************************************************** -Copyright (c) 2006-2011, Skype Limited. All rights reserved. -Redistribution and use in source and binary forms, with or without -modification, (subject to the limitations in the disclaimer below) -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 Skype Limited, nor the names of specific -contributors, may be used to endorse or promote products derived from -this software without specific prior written permission. -NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED -BY THIS LICENSE. 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. -***********************************************************************/ - -/* Insertion sort (fast for already almost sorted arrays): */ -/* Best case: O(n) for an already sorted array */ -/* Worst case: O(n^2) for an inversely sorted array */ -/* */ -/* Shell short: http://en.wikipedia.org/wiki/Shell_sort */ - -#include "silk_SigProc_FIX.h" - -void silk_insertion_sort_increasing( - opus_int32 *a, /* I/O: Unsorted / Sorted vector */ - opus_int *idx, /* O: Index vector for the sorted elements */ - const opus_int L, /* I: Vector length */ - const opus_int K /* I: Number of correctly sorted positions */ -) -{ - opus_int32 value; - opus_int i, j; - - /* Safety checks */ - SKP_assert( K > 0 ); - SKP_assert( L > 0 ); - SKP_assert( L >= K ); - - /* Write start indices in index vector */ - for( i = 0; i < K; i++ ) { - idx[ i ] = i; - } - - /* Sort vector elements by value, increasing order */ - for( i = 1; i < K; i++ ) { - value = a[ i ]; - for( j = i - 1; ( j >= 0 ) && ( value < a[ j ] ); j-- ) { - a[ j + 1 ] = a[ j ]; /* Shift value */ - idx[ j + 1 ] = idx[ j ]; /* Shift index */ - } - a[ j + 1 ] = value; /* Write value */ - idx[ j + 1 ] = i; /* Write index */ - } - - /* If less than L values are asked for, check the remaining values, */ - /* but only spend CPU to ensure that the K first values are correct */ - for( i = K; i < L; i++ ) { - value = a[ i ]; - if( value < a[ K - 1 ] ) { - for( j = K - 2; ( j >= 0 ) && ( value < a[ j ] ); j-- ) { - a[ j + 1 ] = a[ j ]; /* Shift value */ - idx[ j + 1 ] = idx[ j ]; /* Shift index */ - } - a[ j + 1 ] = value; /* Write value */ - idx[ j + 1 ] = i; /* Write index */ - } - } -} - -void silk_insertion_sort_decreasing_int16( - opus_int16 *a, /* I/O: Unsorted / Sorted vector */ - opus_int *idx, /* O: Index vector for the sorted elements */ - const opus_int L, /* I: Vector length */ - const opus_int K /* I: Number of correctly sorted positions */ -) -{ - opus_int i, j; - opus_int value; - - /* Safety checks */ - SKP_assert( K > 0 ); - SKP_assert( L > 0 ); - SKP_assert( L >= K ); - - /* Write start indices in index vector */ - for( i = 0; i < K; i++ ) { - idx[ i ] = i; - } - - /* Sort vector elements by value, decreasing order */ - for( i = 1; i < K; i++ ) { - value = a[ i ]; - for( j = i - 1; ( j >= 0 ) && ( value > a[ j ] ); j-- ) { - a[ j + 1 ] = a[ j ]; /* Shift value */ - idx[ j + 1 ] = idx[ j ]; /* Shift index */ - } - a[ j + 1 ] = value; /* Write value */ - idx[ j + 1 ] = i; /* Write index */ - } - - /* If less than L values are asked for, check the remaining values, */ - /* but only spend CPU to ensure that the K first values are correct */ - for( i = K; i < L; i++ ) { - value = a[ i ]; - if( value > a[ K - 1 ] ) { - for( j = K - 2; ( j >= 0 ) && ( value > a[ j ] ); j-- ) { - a[ j + 1 ] = a[ j ]; /* Shift value */ - idx[ j + 1 ] = idx[ j ]; /* Shift index */ - } - a[ j + 1 ] = value; /* Write value */ - idx[ j + 1 ] = i; /* Write index */ - } - } -} - -void silk_insertion_sort_increasing_all_values_int16( - opus_int16 *a, /* I/O: Unsorted / Sorted vector */ - const opus_int L /* I: Vector length */ -) -{ - opus_int value; - opus_int i, j; - - /* Safety checks */ - SKP_assert( L > 0 ); - - /* Sort vector elements by value, increasing order */ - for( i = 1; i < L; i++ ) { - value = a[ i ]; - for( j = i - 1; ( j >= 0 ) && ( value < a[ j ] ); j-- ) { - a[ j + 1 ] = a[ j ]; /* Shift value */ - } - a[ j + 1 ] = value; /* Write value */ - } -} +/*********************************************************************** +Copyright (c) 2006-2011, Skype Limited. All rights reserved. +Redistribution and use in source and binary forms, with or without +modification, (subject to the limitations in the disclaimer below) +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 Skype Limited, nor the names of specific +contributors, may be used to endorse or promote products derived from +this software without specific prior written permission. +NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED +BY THIS LICENSE. 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. +***********************************************************************/ + +/* Insertion sort (fast for already almost sorted arrays): */ +/* Best case: O(n) for an already sorted array */ +/* Worst case: O(n^2) for an inversely sorted array */ +/* */ +/* Shell short: http://en.wikipedia.org/wiki/Shell_sort */ + +#include "silk_SigProc_FIX.h" + +void silk_insertion_sort_increasing( + opus_int32 *a, /* I/O: Unsorted / Sorted vector */ + opus_int *idx, /* O: Index vector for the sorted elements */ + const opus_int L, /* I: Vector length */ + const opus_int K /* I: Number of correctly sorted positions */ +) +{ + opus_int32 value; + opus_int i, j; + + /* Safety checks */ + SKP_assert( K > 0 ); + SKP_assert( L > 0 ); + SKP_assert( L >= K ); + + /* Write start indices in index vector */ + for( i = 0; i < K; i++ ) { + idx[ i ] = i; + } + + /* Sort vector elements by value, increasing order */ + for( i = 1; i < K; i++ ) { + value = a[ i ]; + for( j = i - 1; ( j >= 0 ) && ( value < a[ j ] ); j-- ) { + a[ j + 1 ] = a[ j ]; /* Shift value */ + idx[ j + 1 ] = idx[ j ]; /* Shift index */ + } + a[ j + 1 ] = value; /* Write value */ + idx[ j + 1 ] = i; /* Write index */ + } + + /* If less than L values are asked for, check the remaining values, */ + /* but only spend CPU to ensure that the K first values are correct */ + for( i = K; i < L; i++ ) { + value = a[ i ]; + if( value < a[ K - 1 ] ) { + for( j = K - 2; ( j >= 0 ) && ( value < a[ j ] ); j-- ) { + a[ j + 1 ] = a[ j ]; /* Shift value */ + idx[ j + 1 ] = idx[ j ]; /* Shift index */ + } + a[ j + 1 ] = value; /* Write value */ + idx[ j + 1 ] = i; /* Write index */ + } + } +} + +void silk_insertion_sort_decreasing_int16( + opus_int16 *a, /* I/O: Unsorted / Sorted vector */ + opus_int *idx, /* O: Index vector for the sorted elements */ + const opus_int L, /* I: Vector length */ + const opus_int K /* I: Number of correctly sorted positions */ +) +{ + opus_int i, j; + opus_int value; + + /* Safety checks */ + SKP_assert( K > 0 ); + SKP_assert( L > 0 ); + SKP_assert( L >= K ); + + /* Write start indices in index vector */ + for( i = 0; i < K; i++ ) { + idx[ i ] = i; + } + + /* Sort vector elements by value, decreasing order */ + for( i = 1; i < K; i++ ) { + value = a[ i ]; + for( j = i - 1; ( j >= 0 ) && ( value > a[ j ] ); j-- ) { + a[ j + 1 ] = a[ j ]; /* Shift value */ + idx[ j + 1 ] = idx[ j ]; /* Shift index */ + } + a[ j + 1 ] = value; /* Write value */ + idx[ j + 1 ] = i; /* Write index */ + } + + /* If less than L values are asked for, check the remaining values, */ + /* but only spend CPU to ensure that the K first values are correct */ + for( i = K; i < L; i++ ) { + value = a[ i ]; + if( value > a[ K - 1 ] ) { + for( j = K - 2; ( j >= 0 ) && ( value > a[ j ] ); j-- ) { + a[ j + 1 ] = a[ j ]; /* Shift value */ + idx[ j + 1 ] = idx[ j ]; /* Shift index */ + } + a[ j + 1 ] = value; /* Write value */ + idx[ j + 1 ] = i; /* Write index */ + } + } +} + +void silk_insertion_sort_increasing_all_values_int16( + opus_int16 *a, /* I/O: Unsorted / Sorted vector */ + const opus_int L /* I: Vector length */ +) +{ + opus_int value; + opus_int i, j; + + /* Safety checks */ + SKP_assert( L > 0 ); + + /* Sort vector elements by value, increasing order */ + for( i = 1; i < L; i++ ) { + value = a[ i ]; + for( j = i - 1; ( j >= 0 ) && ( value < a[ j ] ); j-- ) { + a[ j + 1 ] = a[ j ]; /* Shift value */ + } + a[ j + 1 ] = value; /* Write value */ + } +} diff --git a/silk/silk_stereo_LR_to_MS.c b/silk/silk_stereo_LR_to_MS.c index c69310d08..69da18a35 100644 --- a/silk/silk_stereo_LR_to_MS.c +++ b/silk/silk_stereo_LR_to_MS.c @@ -1,177 +1,177 @@ -/*********************************************************************** -Copyright (c) 2006-2011, Skype Limited. All rights reserved. -Redistribution and use in source and binary forms, with or without -modification, (subject to the limitations in the disclaimer below) -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 Skype Limited, nor the names of specific -contributors, may be used to endorse or promote products derived from -this software without specific prior written permission. -NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED -BY THIS LICENSE. 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. -***********************************************************************/ - -#include "silk_main.h" - -/* Convert Left/Right stereo signal to adaptive Mid/Side representation */ -void silk_stereo_LR_to_MS( - stereo_enc_state *state, /* I/O State */ - opus_int16 x1[], /* I/O Left input signal, becomes mid signal */ - opus_int16 x2[], /* I/O Right input signal, becomes side signal */ - opus_int8 ix[ 2 ][ 4 ], /* O Quantization indices */ - opus_int32 mid_side_rates_bps[], /* O Bitrates for mid and side signals */ - opus_int32 total_rate_bps, /* I Total bitrate */ - opus_int prev_speech_act_Q8, /* I Speech activity level in previous frame */ - opus_int fs_kHz, /* I Sample rate (kHz) */ - opus_int frame_length /* I Number of samples */ -) -{ - opus_int n, is10msFrame, denom_Q16, delta0_Q13, delta1_Q13; - opus_int32 sum, diff, smooth_coef_Q16, pred_Q13[ 2 ], pred0_Q13, pred1_Q13; - opus_int32 LP_ratio_Q14, HP_ratio_Q14, frac_Q16, frac_3_Q16, min_mid_rate_bps, width_Q14, w_Q24, deltaw_Q24; - opus_int16 side[ MAX_FRAME_LENGTH + 2 ]; - opus_int16 LP_mid[ MAX_FRAME_LENGTH ], HP_mid[ MAX_FRAME_LENGTH ]; - opus_int16 LP_side[ MAX_FRAME_LENGTH ], HP_side[ MAX_FRAME_LENGTH ]; - opus_int16 *mid = &x1[ -2 ]; - - /* Convert to basic mid/side signals */ - for( n = 0; n < frame_length + 2; n++ ) { - sum = x1[ n - 2 ] + (opus_int32)x2[ n - 2 ]; - diff = x1[ n - 2 ] - (opus_int32)x2[ n - 2 ]; - mid[ n ] = (opus_int16)SKP_RSHIFT_ROUND( sum, 1 ); - side[ n ] = (opus_int16)SKP_SAT16( SKP_RSHIFT_ROUND( diff, 1 ) ); - } - - /* Buffering */ - SKP_memcpy( mid, state->sMid, 2 * sizeof( opus_int16 ) ); - SKP_memcpy( side, state->sSide, 2 * sizeof( opus_int16 ) ); - SKP_memcpy( state->sMid, &mid[ frame_length ], 2 * sizeof( opus_int16 ) ); - SKP_memcpy( state->sSide, &side[ frame_length ], 2 * sizeof( opus_int16 ) ); - - /* LP and HP filter mid signal */ - for( n = 0; n < frame_length; n++ ) { - sum = SKP_RSHIFT_ROUND( SKP_ADD_LSHIFT( mid[ n ] + mid[ n + 2 ], mid[ n + 1 ], 1 ), 2 ); - LP_mid[ n ] = sum; - HP_mid[ n ] = mid[ n + 1 ] - sum; - } - - /* LP and HP filter side signal */ - for( n = 0; n < frame_length; n++ ) { - sum = SKP_RSHIFT_ROUND( SKP_ADD_LSHIFT( side[ n ] + side[ n + 2 ], side[ n + 1 ], 1 ), 2 ); - LP_side[ n ] = sum; - HP_side[ n ] = side[ n + 1 ] - sum; - } - - /* Find energies and predictors */ - is10msFrame = frame_length == 10 * fs_kHz; - smooth_coef_Q16 = is10msFrame ? - SILK_FIX_CONST( STEREO_RATIO_SMOOTH_COEF / 2, 16 ) : - SILK_FIX_CONST( STEREO_RATIO_SMOOTH_COEF, 16 ); - smooth_coef_Q16 = SKP_SMULWB( SKP_SMULBB( prev_speech_act_Q8 , prev_speech_act_Q8 ), smooth_coef_Q16 ); - - pred_Q13[ 0 ] = silk_stereo_find_predictor( &LP_ratio_Q14, LP_mid, LP_side, &state->mid_side_amp_Q0[ 0 ], frame_length, smooth_coef_Q16 ); - pred_Q13[ 1 ] = silk_stereo_find_predictor( &HP_ratio_Q14, HP_mid, HP_side, &state->mid_side_amp_Q0[ 2 ], frame_length, smooth_coef_Q16 ); - /* Ratio of the norms of residual and mid signals */ - frac_Q16 = SKP_SMLABB( HP_ratio_Q14, LP_ratio_Q14, 3 ); - frac_Q16 = SKP_min( frac_Q16, SILK_FIX_CONST( 1, 16 ) ); - - /* Determine bitrate distribution between mid and side, and possibly reduce stereo width */ - total_rate_bps -= is10msFrame ? 1200 : 600; /* Subtract approximate bitrate for coding stereo parameters */ - min_mid_rate_bps = SKP_SMLABB( 2000, fs_kHz, 900 ); - SKP_assert( min_mid_rate_bps < 32767 ); - /* Default bitrate distribution: 8 parts for Mid and (5+3*frac) parts for Side. so: mid_rate = ( 8 / ( 13 + 3 * frac ) ) * total_ rate */ - frac_3_Q16 = SKP_MUL( 3, frac_Q16 ); - mid_side_rates_bps[ 0 ] = silk_DIV32_varQ( total_rate_bps, SILK_FIX_CONST( 8 + 5, 16 ) + frac_3_Q16, 16+3 ); - /* If Mid bitrate below minimum, reduce stereo width */ - if( mid_side_rates_bps[ 0 ] < min_mid_rate_bps ) { - mid_side_rates_bps[ 0 ] = min_mid_rate_bps; - mid_side_rates_bps[ 1 ] = total_rate_bps - mid_side_rates_bps[ 0 ]; - /* width = 4 * ( 2 * side_rate - min_rate ) / ( ( 1 + 3 * frac ) * min_rate ) */ - width_Q14 = silk_DIV32_varQ( SKP_LSHIFT( mid_side_rates_bps[ 1 ], 1 ) - min_mid_rate_bps, - SKP_SMULWB( SILK_FIX_CONST( 1, 16 ) + frac_3_Q16, min_mid_rate_bps ), 14+2 ); - width_Q14 = SKP_LIMIT( width_Q14, 0, SILK_FIX_CONST( 1, 14 ) ); - } else { - mid_side_rates_bps[ 1 ] = total_rate_bps - mid_side_rates_bps[ 0 ]; - width_Q14 = SILK_FIX_CONST( 1, 14 ); - } - - /* Smoother */ - state->smth_width_Q14 = (opus_int16)SKP_SMLAWB( state->smth_width_Q14, width_Q14 - state->smth_width_Q14, smooth_coef_Q16 ); - - /* Reduce predictors */ - pred_Q13[ 0 ] = SKP_RSHIFT( SKP_SMULBB( state->smth_width_Q14, pred_Q13[ 0 ] ), 14 ); - pred_Q13[ 1 ] = SKP_RSHIFT( SKP_SMULBB( state->smth_width_Q14, pred_Q13[ 1 ] ), 14 ); - - ix[ 0 ][ 3 ] = 0; - if( state->width_prev_Q14 == 0 && - ( 8 * total_rate_bps < 13 * min_mid_rate_bps || SKP_SMULWB( frac_Q16, state->smth_width_Q14 ) < SILK_FIX_CONST( 0.05, 14 ) ) ) - { - width_Q14 = 0; - /* Only encode mid channel */ - mid_side_rates_bps[ 0 ] = total_rate_bps; - mid_side_rates_bps[ 1 ] = 0; - ix[ 0 ][ 3 ] = 1; - } else if( state->width_prev_Q14 != 0 && - ( 8 * total_rate_bps < 11 * min_mid_rate_bps || SKP_SMULWB( frac_Q16, state->smth_width_Q14 ) < SILK_FIX_CONST( 0.02, 14 ) ) ) - { - width_Q14 = 0; - } else if( state->smth_width_Q14 > SILK_FIX_CONST( 0.95, 14 ) ) { - width_Q14 = SILK_FIX_CONST( 1, 14 ); - } else { - width_Q14 = state->smth_width_Q14; - } - -#if 0 - DEBUG_STORE_DATA( midside.dat, &mid_side_rates_bps[ 0 ], 8 ); - DEBUG_STORE_DATA( norms0.pcm, &state->mid_side_amp_Q0[0], 8 ); - DEBUG_STORE_DATA( norms1.pcm, &state->mid_side_amp_Q0[2], 8 ); - DEBUG_STORE_DATA( width.pcm, &width_Q14, 4 ); -#endif - - /* Quantize predictors */ - silk_stereo_quant_pred( state, pred_Q13, ix ); - - /* Interpolate predictors and subtract prediction from side channel */ - pred0_Q13 = -state->pred_prev_Q13[ 0 ]; - pred1_Q13 = -state->pred_prev_Q13[ 1 ]; - w_Q24 = SKP_LSHIFT( state->width_prev_Q14, 10 ); - denom_Q16 = SKP_DIV32_16( 1 << 16, STEREO_INTERP_LEN_MS * fs_kHz ); - delta0_Q13 = -SKP_RSHIFT_ROUND( SKP_SMULBB( pred_Q13[ 0 ] - state->pred_prev_Q13[ 0 ], denom_Q16 ), 16 ); - delta1_Q13 = -SKP_RSHIFT_ROUND( SKP_SMULBB( pred_Q13[ 1 ] - state->pred_prev_Q13[ 1 ], denom_Q16 ), 16 ); - deltaw_Q24 = SKP_LSHIFT( SKP_SMULWB( width_Q14 - state->width_prev_Q14, denom_Q16 ), 10 ); - for( n = 0; n < STEREO_INTERP_LEN_MS * fs_kHz; n++ ) { - pred0_Q13 += delta0_Q13; - pred1_Q13 += delta1_Q13; - w_Q24 += deltaw_Q24; - sum = SKP_LSHIFT( SKP_ADD_LSHIFT( mid[ n ] + mid[ n + 2 ], mid[ n + 1 ], 1 ), 9 ); /* Q11 */ - sum = SKP_SMLAWB( SKP_SMULWB( w_Q24, side[ n + 1 ] ), sum, pred0_Q13 ); /* Q8 */ - sum = SKP_SMLAWB( sum, SKP_LSHIFT( ( opus_int32 )mid[ n + 1 ], 11 ), pred1_Q13 ); /* Q8 */ - x2[ n - 1 ] = (opus_int16)SKP_SAT16( SKP_RSHIFT_ROUND( sum, 8 ) ); - } - pred0_Q13 = -pred_Q13[ 0 ]; - pred1_Q13 = -pred_Q13[ 1 ]; - w_Q24 = SKP_LSHIFT( width_Q14, 10 ); - for( n = STEREO_INTERP_LEN_MS * fs_kHz; n < frame_length; n++ ) { - sum = SKP_LSHIFT( SKP_ADD_LSHIFT( mid[ n ] + mid[ n + 2 ], mid[ n + 1 ], 1 ), 9 ); /* Q11 */ - sum = SKP_SMLAWB( SKP_SMULWB( w_Q24, side[ n + 1 ] ), sum, pred0_Q13 ); /* Q8 */ - sum = SKP_SMLAWB( sum, SKP_LSHIFT( ( opus_int32 )mid[ n + 1 ], 11 ), pred1_Q13 ); /* Q8 */ - x2[ n - 1 ] = (opus_int16)SKP_SAT16( SKP_RSHIFT_ROUND( sum, 8 ) ); - } - state->pred_prev_Q13[ 0 ] = (opus_int16)pred_Q13[ 0 ]; - state->pred_prev_Q13[ 1 ] = (opus_int16)pred_Q13[ 1 ]; - state->width_prev_Q14 = (opus_int16)width_Q14; -} +/*********************************************************************** +Copyright (c) 2006-2011, Skype Limited. All rights reserved. +Redistribution and use in source and binary forms, with or without +modification, (subject to the limitations in the disclaimer below) +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 Skype Limited, nor the names of specific +contributors, may be used to endorse or promote products derived from +this software without specific prior written permission. +NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED +BY THIS LICENSE. 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. +***********************************************************************/ + +#include "silk_main.h" + +/* Convert Left/Right stereo signal to adaptive Mid/Side representation */ +void silk_stereo_LR_to_MS( + stereo_enc_state *state, /* I/O State */ + opus_int16 x1[], /* I/O Left input signal, becomes mid signal */ + opus_int16 x2[], /* I/O Right input signal, becomes side signal */ + opus_int8 ix[ 2 ][ 4 ], /* O Quantization indices */ + opus_int32 mid_side_rates_bps[], /* O Bitrates for mid and side signals */ + opus_int32 total_rate_bps, /* I Total bitrate */ + opus_int prev_speech_act_Q8, /* I Speech activity level in previous frame */ + opus_int fs_kHz, /* I Sample rate (kHz) */ + opus_int frame_length /* I Number of samples */ +) +{ + opus_int n, is10msFrame, denom_Q16, delta0_Q13, delta1_Q13; + opus_int32 sum, diff, smooth_coef_Q16, pred_Q13[ 2 ], pred0_Q13, pred1_Q13; + opus_int32 LP_ratio_Q14, HP_ratio_Q14, frac_Q16, frac_3_Q16, min_mid_rate_bps, width_Q14, w_Q24, deltaw_Q24; + opus_int16 side[ MAX_FRAME_LENGTH + 2 ]; + opus_int16 LP_mid[ MAX_FRAME_LENGTH ], HP_mid[ MAX_FRAME_LENGTH ]; + opus_int16 LP_side[ MAX_FRAME_LENGTH ], HP_side[ MAX_FRAME_LENGTH ]; + opus_int16 *mid = &x1[ -2 ]; + + /* Convert to basic mid/side signals */ + for( n = 0; n < frame_length + 2; n++ ) { + sum = x1[ n - 2 ] + (opus_int32)x2[ n - 2 ]; + diff = x1[ n - 2 ] - (opus_int32)x2[ n - 2 ]; + mid[ n ] = (opus_int16)SKP_RSHIFT_ROUND( sum, 1 ); + side[ n ] = (opus_int16)SKP_SAT16( SKP_RSHIFT_ROUND( diff, 1 ) ); + } + + /* Buffering */ + SKP_memcpy( mid, state->sMid, 2 * sizeof( opus_int16 ) ); + SKP_memcpy( side, state->sSide, 2 * sizeof( opus_int16 ) ); + SKP_memcpy( state->sMid, &mid[ frame_length ], 2 * sizeof( opus_int16 ) ); + SKP_memcpy( state->sSide, &side[ frame_length ], 2 * sizeof( opus_int16 ) ); + + /* LP and HP filter mid signal */ + for( n = 0; n < frame_length; n++ ) { + sum = SKP_RSHIFT_ROUND( SKP_ADD_LSHIFT( mid[ n ] + mid[ n + 2 ], mid[ n + 1 ], 1 ), 2 ); + LP_mid[ n ] = sum; + HP_mid[ n ] = mid[ n + 1 ] - sum; + } + + /* LP and HP filter side signal */ + for( n = 0; n < frame_length; n++ ) { + sum = SKP_RSHIFT_ROUND( SKP_ADD_LSHIFT( side[ n ] + side[ n + 2 ], side[ n + 1 ], 1 ), 2 ); + LP_side[ n ] = sum; + HP_side[ n ] = side[ n + 1 ] - sum; + } + + /* Find energies and predictors */ + is10msFrame = frame_length == 10 * fs_kHz; + smooth_coef_Q16 = is10msFrame ? + SILK_FIX_CONST( STEREO_RATIO_SMOOTH_COEF / 2, 16 ) : + SILK_FIX_CONST( STEREO_RATIO_SMOOTH_COEF, 16 ); + smooth_coef_Q16 = SKP_SMULWB( SKP_SMULBB( prev_speech_act_Q8 , prev_speech_act_Q8 ), smooth_coef_Q16 ); + + pred_Q13[ 0 ] = silk_stereo_find_predictor( &LP_ratio_Q14, LP_mid, LP_side, &state->mid_side_amp_Q0[ 0 ], frame_length, smooth_coef_Q16 ); + pred_Q13[ 1 ] = silk_stereo_find_predictor( &HP_ratio_Q14, HP_mid, HP_side, &state->mid_side_amp_Q0[ 2 ], frame_length, smooth_coef_Q16 ); + /* Ratio of the norms of residual and mid signals */ + frac_Q16 = SKP_SMLABB( HP_ratio_Q14, LP_ratio_Q14, 3 ); + frac_Q16 = SKP_min( frac_Q16, SILK_FIX_CONST( 1, 16 ) ); + + /* Determine bitrate distribution between mid and side, and possibly reduce stereo width */ + total_rate_bps -= is10msFrame ? 1200 : 600; /* Subtract approximate bitrate for coding stereo parameters */ + min_mid_rate_bps = SKP_SMLABB( 2000, fs_kHz, 900 ); + SKP_assert( min_mid_rate_bps < 32767 ); + /* Default bitrate distribution: 8 parts for Mid and (5+3*frac) parts for Side. so: mid_rate = ( 8 / ( 13 + 3 * frac ) ) * total_ rate */ + frac_3_Q16 = SKP_MUL( 3, frac_Q16 ); + mid_side_rates_bps[ 0 ] = silk_DIV32_varQ( total_rate_bps, SILK_FIX_CONST( 8 + 5, 16 ) + frac_3_Q16, 16+3 ); + /* If Mid bitrate below minimum, reduce stereo width */ + if( mid_side_rates_bps[ 0 ] < min_mid_rate_bps ) { + mid_side_rates_bps[ 0 ] = min_mid_rate_bps; + mid_side_rates_bps[ 1 ] = total_rate_bps - mid_side_rates_bps[ 0 ]; + /* width = 4 * ( 2 * side_rate - min_rate ) / ( ( 1 + 3 * frac ) * min_rate ) */ + width_Q14 = silk_DIV32_varQ( SKP_LSHIFT( mid_side_rates_bps[ 1 ], 1 ) - min_mid_rate_bps, + SKP_SMULWB( SILK_FIX_CONST( 1, 16 ) + frac_3_Q16, min_mid_rate_bps ), 14+2 ); + width_Q14 = SKP_LIMIT( width_Q14, 0, SILK_FIX_CONST( 1, 14 ) ); + } else { + mid_side_rates_bps[ 1 ] = total_rate_bps - mid_side_rates_bps[ 0 ]; + width_Q14 = SILK_FIX_CONST( 1, 14 ); + } + + /* Smoother */ + state->smth_width_Q14 = (opus_int16)SKP_SMLAWB( state->smth_width_Q14, width_Q14 - state->smth_width_Q14, smooth_coef_Q16 ); + + /* Reduce predictors */ + pred_Q13[ 0 ] = SKP_RSHIFT( SKP_SMULBB( state->smth_width_Q14, pred_Q13[ 0 ] ), 14 ); + pred_Q13[ 1 ] = SKP_RSHIFT( SKP_SMULBB( state->smth_width_Q14, pred_Q13[ 1 ] ), 14 ); + + ix[ 0 ][ 3 ] = 0; + if( state->width_prev_Q14 == 0 && + ( 8 * total_rate_bps < 13 * min_mid_rate_bps || SKP_SMULWB( frac_Q16, state->smth_width_Q14 ) < SILK_FIX_CONST( 0.05, 14 ) ) ) + { + width_Q14 = 0; + /* Only encode mid channel */ + mid_side_rates_bps[ 0 ] = total_rate_bps; + mid_side_rates_bps[ 1 ] = 0; + ix[ 0 ][ 3 ] = 1; + } else if( state->width_prev_Q14 != 0 && + ( 8 * total_rate_bps < 11 * min_mid_rate_bps || SKP_SMULWB( frac_Q16, state->smth_width_Q14 ) < SILK_FIX_CONST( 0.02, 14 ) ) ) + { + width_Q14 = 0; + } else if( state->smth_width_Q14 > SILK_FIX_CONST( 0.95, 14 ) ) { + width_Q14 = SILK_FIX_CONST( 1, 14 ); + } else { + width_Q14 = state->smth_width_Q14; + } + +#if 0 + DEBUG_STORE_DATA( midside.dat, &mid_side_rates_bps[ 0 ], 8 ); + DEBUG_STORE_DATA( norms0.pcm, &state->mid_side_amp_Q0[0], 8 ); + DEBUG_STORE_DATA( norms1.pcm, &state->mid_side_amp_Q0[2], 8 ); + DEBUG_STORE_DATA( width.pcm, &width_Q14, 4 ); +#endif + + /* Quantize predictors */ + silk_stereo_quant_pred( state, pred_Q13, ix ); + + /* Interpolate predictors and subtract prediction from side channel */ + pred0_Q13 = -state->pred_prev_Q13[ 0 ]; + pred1_Q13 = -state->pred_prev_Q13[ 1 ]; + w_Q24 = SKP_LSHIFT( state->width_prev_Q14, 10 ); + denom_Q16 = SKP_DIV32_16( 1 << 16, STEREO_INTERP_LEN_MS * fs_kHz ); + delta0_Q13 = -SKP_RSHIFT_ROUND( SKP_SMULBB( pred_Q13[ 0 ] - state->pred_prev_Q13[ 0 ], denom_Q16 ), 16 ); + delta1_Q13 = -SKP_RSHIFT_ROUND( SKP_SMULBB( pred_Q13[ 1 ] - state->pred_prev_Q13[ 1 ], denom_Q16 ), 16 ); + deltaw_Q24 = SKP_LSHIFT( SKP_SMULWB( width_Q14 - state->width_prev_Q14, denom_Q16 ), 10 ); + for( n = 0; n < STEREO_INTERP_LEN_MS * fs_kHz; n++ ) { + pred0_Q13 += delta0_Q13; + pred1_Q13 += delta1_Q13; + w_Q24 += deltaw_Q24; + sum = SKP_LSHIFT( SKP_ADD_LSHIFT( mid[ n ] + mid[ n + 2 ], mid[ n + 1 ], 1 ), 9 ); /* Q11 */ + sum = SKP_SMLAWB( SKP_SMULWB( w_Q24, side[ n + 1 ] ), sum, pred0_Q13 ); /* Q8 */ + sum = SKP_SMLAWB( sum, SKP_LSHIFT( ( opus_int32 )mid[ n + 1 ], 11 ), pred1_Q13 ); /* Q8 */ + x2[ n - 1 ] = (opus_int16)SKP_SAT16( SKP_RSHIFT_ROUND( sum, 8 ) ); + } + pred0_Q13 = -pred_Q13[ 0 ]; + pred1_Q13 = -pred_Q13[ 1 ]; + w_Q24 = SKP_LSHIFT( width_Q14, 10 ); + for( n = STEREO_INTERP_LEN_MS * fs_kHz; n < frame_length; n++ ) { + sum = SKP_LSHIFT( SKP_ADD_LSHIFT( mid[ n ] + mid[ n + 2 ], mid[ n + 1 ], 1 ), 9 ); /* Q11 */ + sum = SKP_SMLAWB( SKP_SMULWB( w_Q24, side[ n + 1 ] ), sum, pred0_Q13 ); /* Q8 */ + sum = SKP_SMLAWB( sum, SKP_LSHIFT( ( opus_int32 )mid[ n + 1 ], 11 ), pred1_Q13 ); /* Q8 */ + x2[ n - 1 ] = (opus_int16)SKP_SAT16( SKP_RSHIFT_ROUND( sum, 8 ) ); + } + state->pred_prev_Q13[ 0 ] = (opus_int16)pred_Q13[ 0 ]; + state->pred_prev_Q13[ 1 ] = (opus_int16)pred_Q13[ 1 ]; + state->width_prev_Q14 = (opus_int16)width_Q14; +} diff --git a/silk/silk_stereo_MS_to_LR.c b/silk/silk_stereo_MS_to_LR.c index 807fb351b..4a2577c45 100644 --- a/silk/silk_stereo_MS_to_LR.c +++ b/silk/silk_stereo_MS_to_LR.c @@ -1,81 +1,81 @@ -/*********************************************************************** -Copyright (c) 2006-2011, Skype Limited. All rights reserved. -Redistribution and use in source and binary forms, with or without -modification, (subject to the limitations in the disclaimer below) -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 Skype Limited, nor the names of specific -contributors, may be used to endorse or promote products derived from -this software without specific prior written permission. -NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED -BY THIS LICENSE. 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. -***********************************************************************/ - -#include "silk_main.h" - -/* Convert adaptive Mid/Side representation to Left/Right stereo signal */ -void silk_stereo_MS_to_LR( - stereo_dec_state *state, /* I/O State */ - opus_int16 x1[], /* I/O Left input signal, becomes mid signal */ - opus_int16 x2[], /* I/O Right input signal, becomes side signal */ - const opus_int32 pred_Q13[], /* I Predictors */ - opus_int fs_kHz, /* I Samples rate (kHz) */ - opus_int frame_length /* I Number of samples */ -) -{ - opus_int n, denom_Q16, delta0_Q13, delta1_Q13; - opus_int32 sum, diff, pred0_Q13, pred1_Q13; - - /* Buffering */ - SKP_memcpy( x1, state->sMid, 2 * sizeof( opus_int16 ) ); - SKP_memcpy( x2, state->sSide, 2 * sizeof( opus_int16 ) ); - SKP_memcpy( state->sMid, &x1[ frame_length ], 2 * sizeof( opus_int16 ) ); - SKP_memcpy( state->sSide, &x2[ frame_length ], 2 * sizeof( opus_int16 ) ); - - /* Interpolate predictors and add prediction to side channel */ - pred0_Q13 = state->pred_prev_Q13[ 0 ]; - pred1_Q13 = state->pred_prev_Q13[ 1 ]; - denom_Q16 = SKP_DIV32_16( 1 << 16, STEREO_INTERP_LEN_MS * fs_kHz ); - delta0_Q13 = SKP_RSHIFT_ROUND( SKP_SMULBB( pred_Q13[ 0 ] - state->pred_prev_Q13[ 0 ], denom_Q16 ), 16 ); - delta1_Q13 = SKP_RSHIFT_ROUND( SKP_SMULBB( pred_Q13[ 1 ] - state->pred_prev_Q13[ 1 ], denom_Q16 ), 16 ); - for( n = 0; n < STEREO_INTERP_LEN_MS * fs_kHz; n++ ) { - pred0_Q13 += delta0_Q13; - pred1_Q13 += delta1_Q13; - sum = SKP_LSHIFT( SKP_ADD_LSHIFT( x1[ n ] + x1[ n + 2 ], x1[ n + 1 ], 1 ), 9 ); /* Q11 */ - sum = SKP_SMLAWB( SKP_LSHIFT( ( opus_int32 )x2[ n + 1 ], 8 ), sum, pred0_Q13 ); /* Q8 */ - sum = SKP_SMLAWB( sum, SKP_LSHIFT( ( opus_int32 )x1[ n + 1 ], 11 ), pred1_Q13 ); /* Q8 */ - x2[ n + 1 ] = (opus_int16)SKP_SAT16( SKP_RSHIFT_ROUND( sum, 8 ) ); - } - pred0_Q13 = pred_Q13[ 0 ]; - pred1_Q13 = pred_Q13[ 1 ]; - for( n = STEREO_INTERP_LEN_MS * fs_kHz; n < frame_length; n++ ) { - sum = SKP_LSHIFT( SKP_ADD_LSHIFT( x1[ n ] + x1[ n + 2 ], x1[ n + 1 ], 1 ), 9 ); /* Q11 */ - sum = SKP_SMLAWB( SKP_LSHIFT( ( opus_int32 )x2[ n + 1 ], 8 ), sum, pred0_Q13 ); /* Q8 */ - sum = SKP_SMLAWB( sum, SKP_LSHIFT( ( opus_int32 )x1[ n + 1 ], 11 ), pred1_Q13 ); /* Q8 */ - x2[ n + 1 ] = (opus_int16)SKP_SAT16( SKP_RSHIFT_ROUND( sum, 8 ) ); - } - state->pred_prev_Q13[ 0 ] = pred_Q13[ 0 ]; - state->pred_prev_Q13[ 1 ] = pred_Q13[ 1 ]; - - /* Convert to left/right signals */ - for( n = 0; n < frame_length; n++ ) { - sum = x1[ n + 1 ] + (opus_int32)x2[ n + 1 ]; - diff = x1[ n + 1 ] - (opus_int32)x2[ n + 1 ]; - x1[ n + 1 ] = (opus_int16)SKP_SAT16( sum ); - x2[ n + 1 ] = (opus_int16)SKP_SAT16( diff ); - } -} +/*********************************************************************** +Copyright (c) 2006-2011, Skype Limited. All rights reserved. +Redistribution and use in source and binary forms, with or without +modification, (subject to the limitations in the disclaimer below) +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 Skype Limited, nor the names of specific +contributors, may be used to endorse or promote products derived from +this software without specific prior written permission. +NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED +BY THIS LICENSE. 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. +***********************************************************************/ + +#include "silk_main.h" + +/* Convert adaptive Mid/Side representation to Left/Right stereo signal */ +void silk_stereo_MS_to_LR( + stereo_dec_state *state, /* I/O State */ + opus_int16 x1[], /* I/O Left input signal, becomes mid signal */ + opus_int16 x2[], /* I/O Right input signal, becomes side signal */ + const opus_int32 pred_Q13[], /* I Predictors */ + opus_int fs_kHz, /* I Samples rate (kHz) */ + opus_int frame_length /* I Number of samples */ +) +{ + opus_int n, denom_Q16, delta0_Q13, delta1_Q13; + opus_int32 sum, diff, pred0_Q13, pred1_Q13; + + /* Buffering */ + SKP_memcpy( x1, state->sMid, 2 * sizeof( opus_int16 ) ); + SKP_memcpy( x2, state->sSide, 2 * sizeof( opus_int16 ) ); + SKP_memcpy( state->sMid, &x1[ frame_length ], 2 * sizeof( opus_int16 ) ); + SKP_memcpy( state->sSide, &x2[ frame_length ], 2 * sizeof( opus_int16 ) ); + + /* Interpolate predictors and add prediction to side channel */ + pred0_Q13 = state->pred_prev_Q13[ 0 ]; + pred1_Q13 = state->pred_prev_Q13[ 1 ]; + denom_Q16 = SKP_DIV32_16( 1 << 16, STEREO_INTERP_LEN_MS * fs_kHz ); + delta0_Q13 = SKP_RSHIFT_ROUND( SKP_SMULBB( pred_Q13[ 0 ] - state->pred_prev_Q13[ 0 ], denom_Q16 ), 16 ); + delta1_Q13 = SKP_RSHIFT_ROUND( SKP_SMULBB( pred_Q13[ 1 ] - state->pred_prev_Q13[ 1 ], denom_Q16 ), 16 ); + for( n = 0; n < STEREO_INTERP_LEN_MS * fs_kHz; n++ ) { + pred0_Q13 += delta0_Q13; + pred1_Q13 += delta1_Q13; + sum = SKP_LSHIFT( SKP_ADD_LSHIFT( x1[ n ] + x1[ n + 2 ], x1[ n + 1 ], 1 ), 9 ); /* Q11 */ + sum = SKP_SMLAWB( SKP_LSHIFT( ( opus_int32 )x2[ n + 1 ], 8 ), sum, pred0_Q13 ); /* Q8 */ + sum = SKP_SMLAWB( sum, SKP_LSHIFT( ( opus_int32 )x1[ n + 1 ], 11 ), pred1_Q13 ); /* Q8 */ + x2[ n + 1 ] = (opus_int16)SKP_SAT16( SKP_RSHIFT_ROUND( sum, 8 ) ); + } + pred0_Q13 = pred_Q13[ 0 ]; + pred1_Q13 = pred_Q13[ 1 ]; + for( n = STEREO_INTERP_LEN_MS * fs_kHz; n < frame_length; n++ ) { + sum = SKP_LSHIFT( SKP_ADD_LSHIFT( x1[ n ] + x1[ n + 2 ], x1[ n + 1 ], 1 ), 9 ); /* Q11 */ + sum = SKP_SMLAWB( SKP_LSHIFT( ( opus_int32 )x2[ n + 1 ], 8 ), sum, pred0_Q13 ); /* Q8 */ + sum = SKP_SMLAWB( sum, SKP_LSHIFT( ( opus_int32 )x1[ n + 1 ], 11 ), pred1_Q13 ); /* Q8 */ + x2[ n + 1 ] = (opus_int16)SKP_SAT16( SKP_RSHIFT_ROUND( sum, 8 ) ); + } + state->pred_prev_Q13[ 0 ] = pred_Q13[ 0 ]; + state->pred_prev_Q13[ 1 ] = pred_Q13[ 1 ]; + + /* Convert to left/right signals */ + for( n = 0; n < frame_length; n++ ) { + sum = x1[ n + 1 ] + (opus_int32)x2[ n + 1 ]; + diff = x1[ n + 1 ] - (opus_int32)x2[ n + 1 ]; + x1[ n + 1 ] = (opus_int16)SKP_SAT16( sum ); + x2[ n + 1 ] = (opus_int16)SKP_SAT16( diff ); + } +} diff --git a/silk/silk_stereo_decode_pred.c b/silk/silk_stereo_decode_pred.c index 7906f3e60..40641104d 100644 --- a/silk/silk_stereo_decode_pred.c +++ b/silk/silk_stereo_decode_pred.c @@ -1,63 +1,63 @@ -/*********************************************************************** -Copyright (c) 2006-2011, Skype Limited. All rights reserved. -Redistribution and use in source and binary forms, with or without -modification, (subject to the limitations in the disclaimer below) -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 Skype Limited, nor the names of specific -contributors, may be used to endorse or promote products derived from -this software without specific prior written permission. -NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED -BY THIS LICENSE. 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. -***********************************************************************/ - -#include "silk_main.h" - -/* Decode mid/side predictors */ -void silk_stereo_decode_pred( - ec_dec *psRangeDec, /* I/O Compressor data structure */ - opus_int *decode_only_mid, /* O Flag that only mid channel has been coded */ - opus_int32 pred_Q13[] /* O Predictors */ -) -{ - opus_int n, ix[ 2 ][ 3 ]; - opus_int32 low_Q13, step_Q13; - - /* Entropy decoding */ - n = ec_dec_icdf( psRangeDec, silk_stereo_pred_joint_iCDF, 8 ); - ix[ 0 ][ 2 ] = SKP_DIV32_16( n, 5 ); - ix[ 1 ][ 2 ] = n - 5 * ix[ 0 ][ 2 ]; - for( n = 0; n < 2; n++ ) { - ix[ n ][ 0 ] = ec_dec_icdf( psRangeDec, silk_uniform3_iCDF, 8 ); - ix[ n ][ 1 ] = ec_dec_icdf( psRangeDec, silk_uniform5_iCDF, 8 ); - } - - /* Dequantize */ - for( n = 0; n < 2; n++ ) { - ix[ n ][ 0 ] += 3 * ix[ n ][ 2 ]; - low_Q13 = silk_stereo_pred_quant_Q13[ ix[ n ][ 0 ] ]; - step_Q13 = SKP_SMULWB( silk_stereo_pred_quant_Q13[ ix[ n ][ 0 ] + 1 ] - low_Q13, - SILK_FIX_CONST( 0.5 / STEREO_QUANT_SUB_STEPS, 16 ) ); - pred_Q13[ n ] = SKP_SMLABB( low_Q13, step_Q13, 2 * ix[ n ][ 1 ] + 1 ); - } - - /* Subtract second from first predictor (helps when actually applying these) */ - pred_Q13[ 0 ] -= pred_Q13[ 1 ]; - - /* Decode flag that only mid channel is coded */ - *decode_only_mid = ec_dec_icdf( psRangeDec, silk_stereo_only_code_mid_iCDF, 8 ); -} +/*********************************************************************** +Copyright (c) 2006-2011, Skype Limited. All rights reserved. +Redistribution and use in source and binary forms, with or without +modification, (subject to the limitations in the disclaimer below) +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 Skype Limited, nor the names of specific +contributors, may be used to endorse or promote products derived from +this software without specific prior written permission. +NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED +BY THIS LICENSE. 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. +***********************************************************************/ + +#include "silk_main.h" + +/* Decode mid/side predictors */ +void silk_stereo_decode_pred( + ec_dec *psRangeDec, /* I/O Compressor data structure */ + opus_int *decode_only_mid, /* O Flag that only mid channel has been coded */ + opus_int32 pred_Q13[] /* O Predictors */ +) +{ + opus_int n, ix[ 2 ][ 3 ]; + opus_int32 low_Q13, step_Q13; + + /* Entropy decoding */ + n = ec_dec_icdf( psRangeDec, silk_stereo_pred_joint_iCDF, 8 ); + ix[ 0 ][ 2 ] = SKP_DIV32_16( n, 5 ); + ix[ 1 ][ 2 ] = n - 5 * ix[ 0 ][ 2 ]; + for( n = 0; n < 2; n++ ) { + ix[ n ][ 0 ] = ec_dec_icdf( psRangeDec, silk_uniform3_iCDF, 8 ); + ix[ n ][ 1 ] = ec_dec_icdf( psRangeDec, silk_uniform5_iCDF, 8 ); + } + + /* Dequantize */ + for( n = 0; n < 2; n++ ) { + ix[ n ][ 0 ] += 3 * ix[ n ][ 2 ]; + low_Q13 = silk_stereo_pred_quant_Q13[ ix[ n ][ 0 ] ]; + step_Q13 = SKP_SMULWB( silk_stereo_pred_quant_Q13[ ix[ n ][ 0 ] + 1 ] - low_Q13, + SILK_FIX_CONST( 0.5 / STEREO_QUANT_SUB_STEPS, 16 ) ); + pred_Q13[ n ] = SKP_SMLABB( low_Q13, step_Q13, 2 * ix[ n ][ 1 ] + 1 ); + } + + /* Subtract second from first predictor (helps when actually applying these) */ + pred_Q13[ 0 ] -= pred_Q13[ 1 ]; + + /* Decode flag that only mid channel is coded */ + *decode_only_mid = ec_dec_icdf( psRangeDec, silk_stereo_only_code_mid_iCDF, 8 ); +} diff --git a/silk/silk_stereo_encode_pred.c b/silk/silk_stereo_encode_pred.c index adb34d534..40e4042d4 100644 --- a/silk/silk_stereo_encode_pred.c +++ b/silk/silk_stereo_encode_pred.c @@ -1,51 +1,51 @@ -/*********************************************************************** -Copyright (c) 2006-2011, Skype Limited. All rights reserved. -Redistribution and use in source and binary forms, with or without -modification, (subject to the limitations in the disclaimer below) -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 Skype Limited, nor the names of specific -contributors, may be used to endorse or promote products derived from -this software without specific prior written permission. -NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED -BY THIS LICENSE. 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. -***********************************************************************/ - -#include "silk_main.h" - -/* Entropy code the mid/side quantization indices */ -void silk_stereo_encode_pred( - ec_enc *psRangeEnc, /* I/O Compressor data structure */ - opus_int8 ix[ 2 ][ 4 ] /* I Quantization indices */ -) -{ - opus_int n; - - /* Entropy coding */ - n = 5 * ix[ 0 ][ 2 ] + ix[ 1 ][ 2 ]; - SKP_assert( n < 25 ); - ec_enc_icdf( psRangeEnc, n, silk_stereo_pred_joint_iCDF, 8 ); - for( n = 0; n < 2; n++ ) { - SKP_assert( ix[ n ][ 0 ] < 3 ); - SKP_assert( ix[ n ][ 1 ] < STEREO_QUANT_SUB_STEPS ); - ec_enc_icdf( psRangeEnc, ix[ n ][ 0 ], silk_uniform3_iCDF, 8 ); - ec_enc_icdf( psRangeEnc, ix[ n ][ 1 ], silk_uniform5_iCDF, 8 ); - } - - /* Encode flag that only mid channel is coded */ - ec_enc_icdf( psRangeEnc, ix[ 0 ][ 3 ], silk_stereo_only_code_mid_iCDF, 8 ); -} +/*********************************************************************** +Copyright (c) 2006-2011, Skype Limited. All rights reserved. +Redistribution and use in source and binary forms, with or without +modification, (subject to the limitations in the disclaimer below) +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 Skype Limited, nor the names of specific +contributors, may be used to endorse or promote products derived from +this software without specific prior written permission. +NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED +BY THIS LICENSE. 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. +***********************************************************************/ + +#include "silk_main.h" + +/* Entropy code the mid/side quantization indices */ +void silk_stereo_encode_pred( + ec_enc *psRangeEnc, /* I/O Compressor data structure */ + opus_int8 ix[ 2 ][ 4 ] /* I Quantization indices */ +) +{ + opus_int n; + + /* Entropy coding */ + n = 5 * ix[ 0 ][ 2 ] + ix[ 1 ][ 2 ]; + SKP_assert( n < 25 ); + ec_enc_icdf( psRangeEnc, n, silk_stereo_pred_joint_iCDF, 8 ); + for( n = 0; n < 2; n++ ) { + SKP_assert( ix[ n ][ 0 ] < 3 ); + SKP_assert( ix[ n ][ 1 ] < STEREO_QUANT_SUB_STEPS ); + ec_enc_icdf( psRangeEnc, ix[ n ][ 0 ], silk_uniform3_iCDF, 8 ); + ec_enc_icdf( psRangeEnc, ix[ n ][ 1 ], silk_uniform5_iCDF, 8 ); + } + + /* Encode flag that only mid channel is coded */ + ec_enc_icdf( psRangeEnc, ix[ 0 ][ 3 ], silk_stereo_only_code_mid_iCDF, 8 ); +} diff --git a/silk/silk_stereo_find_predictor.c b/silk/silk_stereo_find_predictor.c index 7a00dae5a..0aae4036f 100644 --- a/silk/silk_stereo_find_predictor.c +++ b/silk/silk_stereo_find_predictor.c @@ -1,69 +1,69 @@ -/*********************************************************************** -Copyright (c) 2006-2011, Skype Limited. All rights reserved. -Redistribution and use in source and binary forms, with or without -modification, (subject to the limitations in the disclaimer below) -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 Skype Limited, nor the names of specific -contributors, may be used to endorse or promote products derived from -this software without specific prior written permission. -NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED -BY THIS LICENSE. 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. -***********************************************************************/ - -#include "silk_main.h" - -/* Find least-squares prediction gain for one signal based on another and quantize it */ -opus_int32 silk_stereo_find_predictor( /* O Returns predictor in Q13 */ - opus_int32 *ratio_Q14, /* O Ratio of residual and mid energies */ - const opus_int16 x[], /* I Basis signal */ - const opus_int16 y[], /* I Target signal */ - opus_int32 mid_res_amp_Q0[], /* I/O Smoothed mid, residual norms */ - opus_int length, /* I Number of samples */ - opus_int smooth_coef_Q16 /* I Smoothing coefficient */ -) -{ - opus_int scale, scale1, scale2; - opus_int32 nrgx, nrgy, corr, pred_Q13; - - /* Find predictor */ - silk_sum_sqr_shift( &nrgx, &scale1, x, length ); - silk_sum_sqr_shift( &nrgy, &scale2, y, length ); - scale = SKP_max( scale1, scale2 ); - scale = scale + ( scale & 1 ); /* make even */ - nrgy = SKP_RSHIFT32( nrgy, scale - scale2 ); - nrgx = SKP_RSHIFT32( nrgx, scale - scale1 ); - nrgx = SKP_max( nrgx, 1 ); - corr = silk_inner_prod_aligned_scale( x, y, scale, length ); - pred_Q13 = silk_DIV32_varQ( corr, nrgx, 13 ); - pred_Q13 = SKP_SAT16( pred_Q13 ); - - /* Smoothed mid and residual norms */ - SKP_assert( smooth_coef_Q16 < 32768 ); - scale = SKP_RSHIFT( scale, 1 ); - mid_res_amp_Q0[ 0 ] = SKP_SMLAWB( mid_res_amp_Q0[ 0 ], SKP_LSHIFT( silk_SQRT_APPROX( nrgx ), scale ) - mid_res_amp_Q0[ 0 ], - smooth_coef_Q16 ); - nrgy = SKP_SUB_LSHIFT32( nrgy, SKP_SMULWB( corr, pred_Q13 ), 3 ); - mid_res_amp_Q0[ 1 ] = SKP_SMLAWB( mid_res_amp_Q0[ 1 ], SKP_LSHIFT( silk_SQRT_APPROX( nrgy ), scale ) - mid_res_amp_Q0[ 1 ], - smooth_coef_Q16 ); - - /* Ratio of smoothed residual and mid norms */ - *ratio_Q14 = silk_DIV32_varQ( mid_res_amp_Q0[ 1 ], SKP_max( mid_res_amp_Q0[ 0 ], 1 ), 14 ); - *ratio_Q14 = SKP_LIMIT( *ratio_Q14, 0, 32767 ); - - return pred_Q13; -} +/*********************************************************************** +Copyright (c) 2006-2011, Skype Limited. All rights reserved. +Redistribution and use in source and binary forms, with or without +modification, (subject to the limitations in the disclaimer below) +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 Skype Limited, nor the names of specific +contributors, may be used to endorse or promote products derived from +this software without specific prior written permission. +NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED +BY THIS LICENSE. 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. +***********************************************************************/ + +#include "silk_main.h" + +/* Find least-squares prediction gain for one signal based on another and quantize it */ +opus_int32 silk_stereo_find_predictor( /* O Returns predictor in Q13 */ + opus_int32 *ratio_Q14, /* O Ratio of residual and mid energies */ + const opus_int16 x[], /* I Basis signal */ + const opus_int16 y[], /* I Target signal */ + opus_int32 mid_res_amp_Q0[], /* I/O Smoothed mid, residual norms */ + opus_int length, /* I Number of samples */ + opus_int smooth_coef_Q16 /* I Smoothing coefficient */ +) +{ + opus_int scale, scale1, scale2; + opus_int32 nrgx, nrgy, corr, pred_Q13; + + /* Find predictor */ + silk_sum_sqr_shift( &nrgx, &scale1, x, length ); + silk_sum_sqr_shift( &nrgy, &scale2, y, length ); + scale = SKP_max( scale1, scale2 ); + scale = scale + ( scale & 1 ); /* make even */ + nrgy = SKP_RSHIFT32( nrgy, scale - scale2 ); + nrgx = SKP_RSHIFT32( nrgx, scale - scale1 ); + nrgx = SKP_max( nrgx, 1 ); + corr = silk_inner_prod_aligned_scale( x, y, scale, length ); + pred_Q13 = silk_DIV32_varQ( corr, nrgx, 13 ); + pred_Q13 = SKP_SAT16( pred_Q13 ); + + /* Smoothed mid and residual norms */ + SKP_assert( smooth_coef_Q16 < 32768 ); + scale = SKP_RSHIFT( scale, 1 ); + mid_res_amp_Q0[ 0 ] = SKP_SMLAWB( mid_res_amp_Q0[ 0 ], SKP_LSHIFT( silk_SQRT_APPROX( nrgx ), scale ) - mid_res_amp_Q0[ 0 ], + smooth_coef_Q16 ); + nrgy = SKP_SUB_LSHIFT32( nrgy, SKP_SMULWB( corr, pred_Q13 ), 3 ); + mid_res_amp_Q0[ 1 ] = SKP_SMLAWB( mid_res_amp_Q0[ 1 ], SKP_LSHIFT( silk_SQRT_APPROX( nrgy ), scale ) - mid_res_amp_Q0[ 1 ], + smooth_coef_Q16 ); + + /* Ratio of smoothed residual and mid norms */ + *ratio_Q14 = silk_DIV32_varQ( mid_res_amp_Q0[ 1 ], SKP_max( mid_res_amp_Q0[ 0 ], 1 ), 14 ); + *ratio_Q14 = SKP_LIMIT( *ratio_Q14, 0, 32767 ); + + return pred_Q13; +} diff --git a/silk/silk_stereo_quant_pred.c b/silk/silk_stereo_quant_pred.c index e9f0c8544..cfe1ae67b 100644 --- a/silk/silk_stereo_quant_pred.c +++ b/silk/silk_stereo_quant_pred.c @@ -1,70 +1,70 @@ -/*********************************************************************** -Copyright (c) 2006-2011, Skype Limited. All rights reserved. -Redistribution and use in source and binary forms, with or without -modification, (subject to the limitations in the disclaimer below) -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 Skype Limited, nor the names of specific -contributors, may be used to endorse or promote products derived from -this software without specific prior written permission. -NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED -BY THIS LICENSE. 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. -***********************************************************************/ - -#include "silk_main.h" - -/* Quantize mid/side predictors */ -void silk_stereo_quant_pred( - stereo_enc_state *state, /* I/O State */ - opus_int32 pred_Q13[], /* I/O Predictors (out: quantized) */ - opus_int8 ix[ 2 ][ 4 ] /* O Quantization indices */ -) -{ - opus_int i, j, n; - opus_int32 low_Q13, step_Q13, lvl_Q13, err_min_Q13, err_Q13, quant_pred_Q13 = 0; - - /* Quantize */ - for( n = 0; n < 2; n++ ) { - /* Brute-force search over quantization levels */ - err_min_Q13 = SKP_int32_MAX; - for( i = 0; i < STEREO_QUANT_TAB_SIZE - 1; i++ ) { - low_Q13 = silk_stereo_pred_quant_Q13[ i ]; - step_Q13 = SKP_SMULWB( silk_stereo_pred_quant_Q13[ i + 1 ] - low_Q13, - SILK_FIX_CONST( 0.5 / STEREO_QUANT_SUB_STEPS, 16 ) ); - for( j = 0; j < STEREO_QUANT_SUB_STEPS; j++ ) { - lvl_Q13 = SKP_SMLABB( low_Q13, step_Q13, 2 * j + 1 ); - err_Q13 = SKP_abs( pred_Q13[ n ] - lvl_Q13 ); - if( err_Q13 < err_min_Q13 ) { - err_min_Q13 = err_Q13; - quant_pred_Q13 = lvl_Q13; - ix[ n ][ 0 ] = i; - ix[ n ][ 1 ] = j; - } else { - /* Error increasing, so we're past the optimum */ - goto done; - } - } - } - done: - ix[ n ][ 2 ] = SKP_DIV32_16( ix[ n ][ 0 ], 3 ); - ix[ n ][ 0 ] -= ix[ n ][ 2 ] * 3; - pred_Q13[ n ] = quant_pred_Q13; - } - - /* Subtract second from first predictor (helps when actually applying these) */ - pred_Q13[ 0 ] -= pred_Q13[ 1 ]; -} +/*********************************************************************** +Copyright (c) 2006-2011, Skype Limited. All rights reserved. +Redistribution and use in source and binary forms, with or without +modification, (subject to the limitations in the disclaimer below) +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 Skype Limited, nor the names of specific +contributors, may be used to endorse or promote products derived from +this software without specific prior written permission. +NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED +BY THIS LICENSE. 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. +***********************************************************************/ + +#include "silk_main.h" + +/* Quantize mid/side predictors */ +void silk_stereo_quant_pred( + stereo_enc_state *state, /* I/O State */ + opus_int32 pred_Q13[], /* I/O Predictors (out: quantized) */ + opus_int8 ix[ 2 ][ 4 ] /* O Quantization indices */ +) +{ + opus_int i, j, n; + opus_int32 low_Q13, step_Q13, lvl_Q13, err_min_Q13, err_Q13, quant_pred_Q13 = 0; + + /* Quantize */ + for( n = 0; n < 2; n++ ) { + /* Brute-force search over quantization levels */ + err_min_Q13 = SKP_int32_MAX; + for( i = 0; i < STEREO_QUANT_TAB_SIZE - 1; i++ ) { + low_Q13 = silk_stereo_pred_quant_Q13[ i ]; + step_Q13 = SKP_SMULWB( silk_stereo_pred_quant_Q13[ i + 1 ] - low_Q13, + SILK_FIX_CONST( 0.5 / STEREO_QUANT_SUB_STEPS, 16 ) ); + for( j = 0; j < STEREO_QUANT_SUB_STEPS; j++ ) { + lvl_Q13 = SKP_SMLABB( low_Q13, step_Q13, 2 * j + 1 ); + err_Q13 = SKP_abs( pred_Q13[ n ] - lvl_Q13 ); + if( err_Q13 < err_min_Q13 ) { + err_min_Q13 = err_Q13; + quant_pred_Q13 = lvl_Q13; + ix[ n ][ 0 ] = i; + ix[ n ][ 1 ] = j; + } else { + /* Error increasing, so we're past the optimum */ + goto done; + } + } + } + done: + ix[ n ][ 2 ] = SKP_DIV32_16( ix[ n ][ 0 ], 3 ); + ix[ n ][ 0 ] -= ix[ n ][ 2 ] * 3; + pred_Q13[ n ] = quant_pred_Q13; + } + + /* Subtract second from first predictor (helps when actually applying these) */ + pred_Q13[ 0 ] -= pred_Q13[ 1 ]; +} diff --git a/silk/silk_structs.h b/silk/silk_structs.h index 7a205792e..3d9fdef8f 100644 --- a/silk/silk_structs.h +++ b/silk/silk_structs.h @@ -1,327 +1,327 @@ -/*********************************************************************** -Copyright (c) 2006-2011, Skype Limited. All rights reserved. -Redistribution and use in source and binary forms, with or without -modification, (subject to the limitations in the disclaimer below) -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 Skype Limited, nor the names of specific -contributors, may be used to endorse or promote products derived from -this software without specific prior written permission. -NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED -BY THIS LICENSE. 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. -***********************************************************************/ - -#ifndef SILK_STRUCTS_H -#define SILK_STRUCTS_H - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include "silk_typedef.h" -#include "silk_SigProc_FIX.h" -#include "silk_define.h" -#include "entenc.h" -#include "entdec.h" - -#ifdef __cplusplus -extern "C" -{ -#endif - -/************************************/ -/* Noise shaping quantization state */ -/************************************/ -typedef struct { - opus_int16 xq[ 2 * MAX_FRAME_LENGTH ]; /* Buffer for quantized output signal */ - opus_int32 sLTP_shp_Q10[ 2 * MAX_FRAME_LENGTH ]; - opus_int32 sLPC_Q14[ MAX_SUB_FRAME_LENGTH + NSQ_LPC_BUF_LENGTH ]; - opus_int32 sAR2_Q14[ MAX_SHAPE_LPC_ORDER ]; - opus_int32 sLF_AR_shp_Q12; - opus_int lagPrev; - opus_int sLTP_buf_idx; - opus_int sLTP_shp_buf_idx; - opus_int32 rand_seed; - opus_int32 prev_inv_gain_Q16; - opus_int rewhite_flag; -} silk_nsq_state; - -/********************************/ -/* VAD state */ -/********************************/ -typedef struct { - opus_int32 AnaState[ 2 ]; /* Analysis filterbank state: 0-8 kHz */ - opus_int32 AnaState1[ 2 ]; /* Analysis filterbank state: 0-4 kHz */ - opus_int32 AnaState2[ 2 ]; /* Analysis filterbank state: 0-2 kHz */ - opus_int32 XnrgSubfr[ VAD_N_BANDS ]; /* Subframe energies */ - opus_int32 NrgRatioSmth_Q8[ VAD_N_BANDS ]; /* Smoothed energy level in each band */ - opus_int16 HPstate; /* State of differentiator in the lowest band */ - opus_int32 NL[ VAD_N_BANDS ]; /* Noise energy level in each band */ - opus_int32 inv_NL[ VAD_N_BANDS ]; /* Inverse noise energy level in each band */ - opus_int32 NoiseLevelBias[ VAD_N_BANDS ]; /* Noise level estimator bias/offset */ - opus_int32 counter; /* Frame counter used in the initial phase */ -} silk_VAD_state; - -/* Variable cut-off low-pass filter state */ -typedef struct { - opus_int32 In_LP_State[ 2 ]; /* Low pass filter state */ - opus_int32 transition_frame_no; /* Counter which is mapped to a cut-off frequency */ - opus_int mode; /* Operating mode, <0: switch down, >0: switch up; 0: do nothing */ -} silk_LP_state; - -/* Structure containing NLSF codebook */ -typedef struct { - const opus_int16 nVectors; - const opus_int16 order; - const opus_int16 quantStepSize_Q16; - const opus_int16 invQuantStepSize_Q6; - const opus_uint8 *CB1_NLSF_Q8; - const opus_uint8 *CB1_iCDF; - const opus_uint8 *pred_Q8; - const opus_uint8 *ec_sel; - const opus_uint8 *ec_iCDF; - const opus_uint8 *ec_Rates_Q5; - const opus_int16 *deltaMin_Q15; -} silk_NLSF_CB_struct; - -typedef struct { - opus_int16 pred_prev_Q13[ 2 ]; - opus_int16 sMid[ 2 ]; - opus_int16 sSide[ 2 ]; - opus_int32 mid_side_amp_Q0[ 4 ]; - opus_int16 smth_width_Q14; - opus_int16 width_prev_Q14; - opus_int8 ix[ MAX_FRAMES_PER_PACKET ][ 2 ][ 4 ]; -} stereo_enc_state; - -typedef struct { - opus_int16 pred_prev_Q13[ 2 ]; - opus_int16 sMid[ 2 ]; - opus_int16 sSide[ 2 ]; -} stereo_dec_state; - -typedef struct { - opus_int8 GainsIndices[ MAX_NB_SUBFR ]; - opus_int8 LTPIndex[ MAX_NB_SUBFR ]; - opus_int8 NLSFIndices[ MAX_LPC_ORDER + 1 ]; - opus_int16 lagIndex; - opus_int8 contourIndex; - opus_int8 signalType; - opus_int8 quantOffsetType; - opus_int8 NLSFInterpCoef_Q2; - opus_int8 PERIndex; - opus_int8 LTP_scaleIndex; - opus_int8 Seed; -} SideInfoIndices; - -/********************************/ -/* Encoder state */ -/********************************/ -typedef struct { - opus_int32 In_HP_State[ 2 ]; /* High pass filter state */ - opus_int32 variable_HP_smth1_Q15; /* State of first smoother */ - opus_int32 variable_HP_smth2_Q15; /* State of second smoother */ - opus_int HP_cutoff_Hz; /* Fixed cutoff frequency (if zero: adaptive) */ - silk_LP_state sLP; /* Low pass filter state */ - silk_VAD_state sVAD; /* Voice activity detector state */ - silk_nsq_state sNSQ; /* Noise Shape Quantizer State */ - opus_int16 prev_NLSFq_Q15[ MAX_LPC_ORDER ];/* Previously quantized NLSF vector */ - opus_int speech_activity_Q8; /* Speech activity */ - opus_int allow_bandwidth_switch; /* Flag indicating that switching of internal bandwidth is allowed */ - opus_int8 LBRRprevLastGainIndex; - opus_int8 prevSignalType; - opus_int prevLag; - opus_int pitch_LPC_win_length; - opus_int max_pitch_lag; /* Highest possible pitch lag (samples) */ - opus_int32 API_fs_Hz; /* API sampling frequency (Hz) */ - opus_int32 prev_API_fs_Hz; /* Previous API sampling frequency (Hz) */ - opus_int maxInternal_fs_Hz; /* Maximum internal sampling frequency (Hz) */ - opus_int minInternal_fs_Hz; /* Minimum internal sampling frequency (Hz) */ - opus_int desiredInternal_fs_Hz; /* Soft request for internal sampling frequency (Hz) */ - opus_int fs_kHz; /* Internal sampling frequency (kHz) */ - opus_int nb_subfr; /* Number of 5 ms subframes in a frame */ - opus_int frame_length; /* Frame length (samples) */ - opus_int subfr_length; /* Subframe length (samples) */ - opus_int ltp_mem_length; /* Length of LTP memory */ - opus_int la_pitch; /* Look-ahead for pitch analysis (samples) */ - opus_int la_shape; /* Look-ahead for noise shape analysis (samples) */ - opus_int shapeWinLength; /* Window length for noise shape analysis (samples) */ - opus_int32 TargetRate_bps; /* Target bitrate (bps) */ - opus_int PacketSize_ms; /* Number of milliseconds to put in each packet */ - opus_int PacketLoss_perc; /* Packet loss rate measured by farend */ - opus_int32 frameCounter; - opus_int Complexity; /* Complexity setting */ - opus_int nStatesDelayedDecision; /* Number of states in delayed decision quantization */ - opus_int useInterpolatedNLSFs; /* Flag for using NLSF interpolation */ - opus_int shapingLPCOrder; /* Filter order for noise shaping filters */ - opus_int predictLPCOrder; /* Filter order for prediction filters */ - opus_int pitchEstimationComplexity; /* Complexity level for pitch estimator */ - opus_int pitchEstimationLPCOrder; /* Whitening filter order for pitch estimator */ - opus_int32 pitchEstimationThreshold_Q16; /* Threshold for pitch estimator */ - opus_int LTPQuantLowComplexity; /* Flag for low complexity LTP quantization */ - opus_int mu_LTP_Q9; /* Rate-distortion tradeoff in LTP quantization */ - opus_int NLSF_MSVQ_Survivors; /* Number of survivors in NLSF MSVQ */ - opus_int first_frame_after_reset; /* Flag for deactivating NLSF interp. and fluc. reduction after resets */ - opus_int controlled_since_last_payload; /* Flag for ensuring codec_control only runs once per packet */ - opus_int warping_Q16; /* Warping parameter for warped noise shaping */ - opus_int useCBR; /* Flag to enable constant bitrate */ - opus_int prefillFlag; /* Flag to indicate that only buffers are prefilled, no coding */ - const opus_uint8 *pitch_lag_low_bits_iCDF; /* Pointer to iCDF table for low bits of pitch lag index */ - const opus_uint8 *pitch_contour_iCDF; /* Pointer to iCDF table for pitch contour index */ - const silk_NLSF_CB_struct *psNLSF_CB; /* Pointer to NLSF codebook */ - opus_int input_quality_bands_Q15[ VAD_N_BANDS ]; - opus_int input_tilt_Q15; - opus_int SNR_dB_Q7; /* Quality setting */ - - opus_int8 VAD_flags[ MAX_FRAMES_PER_PACKET ]; - opus_int8 LBRR_flag; - opus_int LBRR_flags[ MAX_FRAMES_PER_PACKET ]; - - SideInfoIndices indices; - opus_int8 pulses[ MAX_FRAME_LENGTH ]; - - /* Input/output buffering */ - opus_int16 inputBuf__[ MAX_FRAME_LENGTH + 2 ]; /* Buffer containing input signal */ - opus_int16 *inputBuf; /* Points to second element of above buffer */ - opus_int inputBufIx; - opus_int nFramesPerPacket; - opus_int nFramesEncoded; /* Number of frames analyzed in current packet */ - - opus_int nChannelsAPI; - opus_int nChannelsInternal; - opus_int channelNb; - - /* Parameters For LTP scaling Control */ - opus_int frames_since_onset; - - /* Specifically for entropy coding */ - opus_int ec_prevSignalType; - opus_int16 ec_prevLagIndex; - - silk_resampler_state_struct resampler_state; - - /* DTX */ - opus_int useDTX; /* Flag to enable DTX */ - opus_int inDTX; /* Flag to signal DTX period */ - opus_int noSpeechCounter; /* Counts concecutive nonactive frames, used by DTX */ - - /* Inband Low Bitrate Redundancy (LBRR) data */ - opus_int useInBandFEC; /* Saves the API setting for query */ - opus_int LBRR_enabled; /* Depends on useInBandFRC, bitrate and packet loss rate */ - opus_int LBRR_GainIncreases; /* Gains increment for coding LBRR frames */ - SideInfoIndices indices_LBRR[ MAX_FRAMES_PER_PACKET ]; - opus_int8 pulses_LBRR[ MAX_FRAMES_PER_PACKET ][ MAX_FRAME_LENGTH ]; -} silk_encoder_state; - - -/* Struct for Packet Loss Concealment */ -typedef struct { - opus_int32 pitchL_Q8; /* Pitch lag to use for voiced concealment */ - opus_int16 LTPCoef_Q14[ LTP_ORDER ]; /* LTP coeficients to use for voiced concealment */ - opus_int16 prevLPC_Q12[ MAX_LPC_ORDER ]; - opus_int last_frame_lost; /* Was previous frame lost */ - opus_int32 rand_seed; /* Seed for unvoiced signal generation */ - opus_int16 randScale_Q14; /* Scaling of unvoiced random signal */ - opus_int32 conc_energy; - opus_int conc_energy_shift; - opus_int16 prevLTP_scale_Q14; - opus_int32 prevGain_Q16[ MAX_NB_SUBFR ]; - opus_int fs_kHz; -} silk_PLC_struct; - -/* Struct for CNG */ -typedef struct { - opus_int32 CNG_exc_buf_Q10[ MAX_FRAME_LENGTH ]; - opus_int16 CNG_smth_NLSF_Q15[ MAX_LPC_ORDER ]; - opus_int32 CNG_synth_state[ MAX_LPC_ORDER ]; - opus_int32 CNG_smth_Gain_Q16; - opus_int32 rand_seed; - opus_int fs_kHz; -} silk_CNG_struct; - -/********************************/ -/* Decoder state */ -/********************************/ -typedef struct { - opus_int32 prev_inv_gain_Q16; - opus_int32 sLTP_Q16[ 2 * MAX_FRAME_LENGTH ]; - opus_int32 sLPC_Q14[ MAX_SUB_FRAME_LENGTH + MAX_LPC_ORDER ]; - opus_int32 exc_Q10[ MAX_FRAME_LENGTH ]; - opus_int16 outBuf[ 2 * MAX_FRAME_LENGTH ]; /* Buffer for output signal */ - opus_int lagPrev; /* Previous Lag */ - opus_int8 LastGainIndex; /* Previous gain index */ - opus_int fs_kHz; /* Sampling frequency in kHz */ - opus_int32 prev_API_sampleRate; /* Previous API sample frequency (Hz) */ - opus_int nb_subfr; /* Number of 5 ms subframes in a frame */ - opus_int frame_length; /* Frame length (samples) */ - opus_int subfr_length; /* Subframe length (samples) */ - opus_int ltp_mem_length; /* Length of LTP memory */ - opus_int LPC_order; /* LPC order */ - opus_int16 prevNLSF_Q15[ MAX_LPC_ORDER ]; /* Used to interpolate LSFs */ - opus_int first_frame_after_reset; /* Flag for deactivating NLSF interp. and fluc. reduction after resets */ - const opus_uint8 *pitch_lag_low_bits_iCDF; /* Pointer to iCDF table for low bits of pitch lag index */ - const opus_uint8 *pitch_contour_iCDF; /* Pointer to iCDF table for pitch contour index */ - - /* For buffering payload in case of more frames per packet */ - opus_int nFramesDecoded; - opus_int nFramesPerPacket; - - /* Specifically for entropy coding */ - opus_int ec_prevSignalType; - opus_int16 ec_prevLagIndex; - - opus_int VAD_flags[ MAX_FRAMES_PER_PACKET ]; - opus_int LBRR_flag; - opus_int LBRR_flags[ MAX_FRAMES_PER_PACKET ]; - - silk_resampler_state_struct resampler_state; - - const silk_NLSF_CB_struct *psNLSF_CB; /* Pointer to NLSF codebook */ - - /* Quantization indices */ - SideInfoIndices indices; - - /* CNG state */ - silk_CNG_struct sCNG; - - /* Stuff used for PLC */ - opus_int lossCnt; - opus_int prevSignalType; - - silk_PLC_struct sPLC; - -} silk_decoder_state; - -/************************/ -/* Decoder control */ -/************************/ -typedef struct { - /* prediction and coding parameters */ - opus_int pitchL[ MAX_NB_SUBFR ]; - opus_int32 Gains_Q16[ MAX_NB_SUBFR ]; - /* holds interpolated and final coefficients, 4-byte aligned */ - SKP_DWORD_ALIGN opus_int16 PredCoef_Q12[ 2 ][ MAX_LPC_ORDER ]; - opus_int16 LTPCoef_Q14[ LTP_ORDER * MAX_NB_SUBFR ]; - opus_int LTP_scale_Q14; -} silk_decoder_control; - - -#ifdef __cplusplus -} -#endif - -#endif +/*********************************************************************** +Copyright (c) 2006-2011, Skype Limited. All rights reserved. +Redistribution and use in source and binary forms, with or without +modification, (subject to the limitations in the disclaimer below) +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 Skype Limited, nor the names of specific +contributors, may be used to endorse or promote products derived from +this software without specific prior written permission. +NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED +BY THIS LICENSE. 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. +***********************************************************************/ + +#ifndef SILK_STRUCTS_H +#define SILK_STRUCTS_H + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "silk_typedef.h" +#include "silk_SigProc_FIX.h" +#include "silk_define.h" +#include "entenc.h" +#include "entdec.h" + +#ifdef __cplusplus +extern "C" +{ +#endif + +/************************************/ +/* Noise shaping quantization state */ +/************************************/ +typedef struct { + opus_int16 xq[ 2 * MAX_FRAME_LENGTH ]; /* Buffer for quantized output signal */ + opus_int32 sLTP_shp_Q10[ 2 * MAX_FRAME_LENGTH ]; + opus_int32 sLPC_Q14[ MAX_SUB_FRAME_LENGTH + NSQ_LPC_BUF_LENGTH ]; + opus_int32 sAR2_Q14[ MAX_SHAPE_LPC_ORDER ]; + opus_int32 sLF_AR_shp_Q12; + opus_int lagPrev; + opus_int sLTP_buf_idx; + opus_int sLTP_shp_buf_idx; + opus_int32 rand_seed; + opus_int32 prev_inv_gain_Q16; + opus_int rewhite_flag; +} silk_nsq_state; + +/********************************/ +/* VAD state */ +/********************************/ +typedef struct { + opus_int32 AnaState[ 2 ]; /* Analysis filterbank state: 0-8 kHz */ + opus_int32 AnaState1[ 2 ]; /* Analysis filterbank state: 0-4 kHz */ + opus_int32 AnaState2[ 2 ]; /* Analysis filterbank state: 0-2 kHz */ + opus_int32 XnrgSubfr[ VAD_N_BANDS ]; /* Subframe energies */ + opus_int32 NrgRatioSmth_Q8[ VAD_N_BANDS ]; /* Smoothed energy level in each band */ + opus_int16 HPstate; /* State of differentiator in the lowest band */ + opus_int32 NL[ VAD_N_BANDS ]; /* Noise energy level in each band */ + opus_int32 inv_NL[ VAD_N_BANDS ]; /* Inverse noise energy level in each band */ + opus_int32 NoiseLevelBias[ VAD_N_BANDS ]; /* Noise level estimator bias/offset */ + opus_int32 counter; /* Frame counter used in the initial phase */ +} silk_VAD_state; + +/* Variable cut-off low-pass filter state */ +typedef struct { + opus_int32 In_LP_State[ 2 ]; /* Low pass filter state */ + opus_int32 transition_frame_no; /* Counter which is mapped to a cut-off frequency */ + opus_int mode; /* Operating mode, <0: switch down, >0: switch up; 0: do nothing */ +} silk_LP_state; + +/* Structure containing NLSF codebook */ +typedef struct { + const opus_int16 nVectors; + const opus_int16 order; + const opus_int16 quantStepSize_Q16; + const opus_int16 invQuantStepSize_Q6; + const opus_uint8 *CB1_NLSF_Q8; + const opus_uint8 *CB1_iCDF; + const opus_uint8 *pred_Q8; + const opus_uint8 *ec_sel; + const opus_uint8 *ec_iCDF; + const opus_uint8 *ec_Rates_Q5; + const opus_int16 *deltaMin_Q15; +} silk_NLSF_CB_struct; + +typedef struct { + opus_int16 pred_prev_Q13[ 2 ]; + opus_int16 sMid[ 2 ]; + opus_int16 sSide[ 2 ]; + opus_int32 mid_side_amp_Q0[ 4 ]; + opus_int16 smth_width_Q14; + opus_int16 width_prev_Q14; + opus_int8 ix[ MAX_FRAMES_PER_PACKET ][ 2 ][ 4 ]; +} stereo_enc_state; + +typedef struct { + opus_int16 pred_prev_Q13[ 2 ]; + opus_int16 sMid[ 2 ]; + opus_int16 sSide[ 2 ]; +} stereo_dec_state; + +typedef struct { + opus_int8 GainsIndices[ MAX_NB_SUBFR ]; + opus_int8 LTPIndex[ MAX_NB_SUBFR ]; + opus_int8 NLSFIndices[ MAX_LPC_ORDER + 1 ]; + opus_int16 lagIndex; + opus_int8 contourIndex; + opus_int8 signalType; + opus_int8 quantOffsetType; + opus_int8 NLSFInterpCoef_Q2; + opus_int8 PERIndex; + opus_int8 LTP_scaleIndex; + opus_int8 Seed; +} SideInfoIndices; + +/********************************/ +/* Encoder state */ +/********************************/ +typedef struct { + opus_int32 In_HP_State[ 2 ]; /* High pass filter state */ + opus_int32 variable_HP_smth1_Q15; /* State of first smoother */ + opus_int32 variable_HP_smth2_Q15; /* State of second smoother */ + opus_int HP_cutoff_Hz; /* Fixed cutoff frequency (if zero: adaptive) */ + silk_LP_state sLP; /* Low pass filter state */ + silk_VAD_state sVAD; /* Voice activity detector state */ + silk_nsq_state sNSQ; /* Noise Shape Quantizer State */ + opus_int16 prev_NLSFq_Q15[ MAX_LPC_ORDER ];/* Previously quantized NLSF vector */ + opus_int speech_activity_Q8; /* Speech activity */ + opus_int allow_bandwidth_switch; /* Flag indicating that switching of internal bandwidth is allowed */ + opus_int8 LBRRprevLastGainIndex; + opus_int8 prevSignalType; + opus_int prevLag; + opus_int pitch_LPC_win_length; + opus_int max_pitch_lag; /* Highest possible pitch lag (samples) */ + opus_int32 API_fs_Hz; /* API sampling frequency (Hz) */ + opus_int32 prev_API_fs_Hz; /* Previous API sampling frequency (Hz) */ + opus_int maxInternal_fs_Hz; /* Maximum internal sampling frequency (Hz) */ + opus_int minInternal_fs_Hz; /* Minimum internal sampling frequency (Hz) */ + opus_int desiredInternal_fs_Hz; /* Soft request for internal sampling frequency (Hz) */ + opus_int fs_kHz; /* Internal sampling frequency (kHz) */ + opus_int nb_subfr; /* Number of 5 ms subframes in a frame */ + opus_int frame_length; /* Frame length (samples) */ + opus_int subfr_length; /* Subframe length (samples) */ + opus_int ltp_mem_length; /* Length of LTP memory */ + opus_int la_pitch; /* Look-ahead for pitch analysis (samples) */ + opus_int la_shape; /* Look-ahead for noise shape analysis (samples) */ + opus_int shapeWinLength; /* Window length for noise shape analysis (samples) */ + opus_int32 TargetRate_bps; /* Target bitrate (bps) */ + opus_int PacketSize_ms; /* Number of milliseconds to put in each packet */ + opus_int PacketLoss_perc; /* Packet loss rate measured by farend */ + opus_int32 frameCounter; + opus_int Complexity; /* Complexity setting */ + opus_int nStatesDelayedDecision; /* Number of states in delayed decision quantization */ + opus_int useInterpolatedNLSFs; /* Flag for using NLSF interpolation */ + opus_int shapingLPCOrder; /* Filter order for noise shaping filters */ + opus_int predictLPCOrder; /* Filter order for prediction filters */ + opus_int pitchEstimationComplexity; /* Complexity level for pitch estimator */ + opus_int pitchEstimationLPCOrder; /* Whitening filter order for pitch estimator */ + opus_int32 pitchEstimationThreshold_Q16; /* Threshold for pitch estimator */ + opus_int LTPQuantLowComplexity; /* Flag for low complexity LTP quantization */ + opus_int mu_LTP_Q9; /* Rate-distortion tradeoff in LTP quantization */ + opus_int NLSF_MSVQ_Survivors; /* Number of survivors in NLSF MSVQ */ + opus_int first_frame_after_reset; /* Flag for deactivating NLSF interp. and fluc. reduction after resets */ + opus_int controlled_since_last_payload; /* Flag for ensuring codec_control only runs once per packet */ + opus_int warping_Q16; /* Warping parameter for warped noise shaping */ + opus_int useCBR; /* Flag to enable constant bitrate */ + opus_int prefillFlag; /* Flag to indicate that only buffers are prefilled, no coding */ + const opus_uint8 *pitch_lag_low_bits_iCDF; /* Pointer to iCDF table for low bits of pitch lag index */ + const opus_uint8 *pitch_contour_iCDF; /* Pointer to iCDF table for pitch contour index */ + const silk_NLSF_CB_struct *psNLSF_CB; /* Pointer to NLSF codebook */ + opus_int input_quality_bands_Q15[ VAD_N_BANDS ]; + opus_int input_tilt_Q15; + opus_int SNR_dB_Q7; /* Quality setting */ + + opus_int8 VAD_flags[ MAX_FRAMES_PER_PACKET ]; + opus_int8 LBRR_flag; + opus_int LBRR_flags[ MAX_FRAMES_PER_PACKET ]; + + SideInfoIndices indices; + opus_int8 pulses[ MAX_FRAME_LENGTH ]; + + /* Input/output buffering */ + opus_int16 inputBuf__[ MAX_FRAME_LENGTH + 2 ]; /* Buffer containing input signal */ + opus_int16 *inputBuf; /* Points to second element of above buffer */ + opus_int inputBufIx; + opus_int nFramesPerPacket; + opus_int nFramesEncoded; /* Number of frames analyzed in current packet */ + + opus_int nChannelsAPI; + opus_int nChannelsInternal; + opus_int channelNb; + + /* Parameters For LTP scaling Control */ + opus_int frames_since_onset; + + /* Specifically for entropy coding */ + opus_int ec_prevSignalType; + opus_int16 ec_prevLagIndex; + + silk_resampler_state_struct resampler_state; + + /* DTX */ + opus_int useDTX; /* Flag to enable DTX */ + opus_int inDTX; /* Flag to signal DTX period */ + opus_int noSpeechCounter; /* Counts concecutive nonactive frames, used by DTX */ + + /* Inband Low Bitrate Redundancy (LBRR) data */ + opus_int useInBandFEC; /* Saves the API setting for query */ + opus_int LBRR_enabled; /* Depends on useInBandFRC, bitrate and packet loss rate */ + opus_int LBRR_GainIncreases; /* Gains increment for coding LBRR frames */ + SideInfoIndices indices_LBRR[ MAX_FRAMES_PER_PACKET ]; + opus_int8 pulses_LBRR[ MAX_FRAMES_PER_PACKET ][ MAX_FRAME_LENGTH ]; +} silk_encoder_state; + + +/* Struct for Packet Loss Concealment */ +typedef struct { + opus_int32 pitchL_Q8; /* Pitch lag to use for voiced concealment */ + opus_int16 LTPCoef_Q14[ LTP_ORDER ]; /* LTP coeficients to use for voiced concealment */ + opus_int16 prevLPC_Q12[ MAX_LPC_ORDER ]; + opus_int last_frame_lost; /* Was previous frame lost */ + opus_int32 rand_seed; /* Seed for unvoiced signal generation */ + opus_int16 randScale_Q14; /* Scaling of unvoiced random signal */ + opus_int32 conc_energy; + opus_int conc_energy_shift; + opus_int16 prevLTP_scale_Q14; + opus_int32 prevGain_Q16[ MAX_NB_SUBFR ]; + opus_int fs_kHz; +} silk_PLC_struct; + +/* Struct for CNG */ +typedef struct { + opus_int32 CNG_exc_buf_Q10[ MAX_FRAME_LENGTH ]; + opus_int16 CNG_smth_NLSF_Q15[ MAX_LPC_ORDER ]; + opus_int32 CNG_synth_state[ MAX_LPC_ORDER ]; + opus_int32 CNG_smth_Gain_Q16; + opus_int32 rand_seed; + opus_int fs_kHz; +} silk_CNG_struct; + +/********************************/ +/* Decoder state */ +/********************************/ +typedef struct { + opus_int32 prev_inv_gain_Q16; + opus_int32 sLTP_Q16[ 2 * MAX_FRAME_LENGTH ]; + opus_int32 sLPC_Q14[ MAX_SUB_FRAME_LENGTH + MAX_LPC_ORDER ]; + opus_int32 exc_Q10[ MAX_FRAME_LENGTH ]; + opus_int16 outBuf[ 2 * MAX_FRAME_LENGTH ]; /* Buffer for output signal */ + opus_int lagPrev; /* Previous Lag */ + opus_int8 LastGainIndex; /* Previous gain index */ + opus_int fs_kHz; /* Sampling frequency in kHz */ + opus_int32 prev_API_sampleRate; /* Previous API sample frequency (Hz) */ + opus_int nb_subfr; /* Number of 5 ms subframes in a frame */ + opus_int frame_length; /* Frame length (samples) */ + opus_int subfr_length; /* Subframe length (samples) */ + opus_int ltp_mem_length; /* Length of LTP memory */ + opus_int LPC_order; /* LPC order */ + opus_int16 prevNLSF_Q15[ MAX_LPC_ORDER ]; /* Used to interpolate LSFs */ + opus_int first_frame_after_reset; /* Flag for deactivating NLSF interp. and fluc. reduction after resets */ + const opus_uint8 *pitch_lag_low_bits_iCDF; /* Pointer to iCDF table for low bits of pitch lag index */ + const opus_uint8 *pitch_contour_iCDF; /* Pointer to iCDF table for pitch contour index */ + + /* For buffering payload in case of more frames per packet */ + opus_int nFramesDecoded; + opus_int nFramesPerPacket; + + /* Specifically for entropy coding */ + opus_int ec_prevSignalType; + opus_int16 ec_prevLagIndex; + + opus_int VAD_flags[ MAX_FRAMES_PER_PACKET ]; + opus_int LBRR_flag; + opus_int LBRR_flags[ MAX_FRAMES_PER_PACKET ]; + + silk_resampler_state_struct resampler_state; + + const silk_NLSF_CB_struct *psNLSF_CB; /* Pointer to NLSF codebook */ + + /* Quantization indices */ + SideInfoIndices indices; + + /* CNG state */ + silk_CNG_struct sCNG; + + /* Stuff used for PLC */ + opus_int lossCnt; + opus_int prevSignalType; + + silk_PLC_struct sPLC; + +} silk_decoder_state; + +/************************/ +/* Decoder control */ +/************************/ +typedef struct { + /* prediction and coding parameters */ + opus_int pitchL[ MAX_NB_SUBFR ]; + opus_int32 Gains_Q16[ MAX_NB_SUBFR ]; + /* holds interpolated and final coefficients, 4-byte aligned */ + SKP_DWORD_ALIGN opus_int16 PredCoef_Q12[ 2 ][ MAX_LPC_ORDER ]; + opus_int16 LTPCoef_Q14[ LTP_ORDER * MAX_NB_SUBFR ]; + opus_int LTP_scale_Q14; +} silk_decoder_control; + + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/silk/silk_sum_sqr_shift.c b/silk/silk_sum_sqr_shift.c index 1b9f83e6b..2296d1b0b 100644 --- a/silk/silk_sum_sqr_shift.c +++ b/silk/silk_sum_sqr_shift.c @@ -1,81 +1,81 @@ -/*********************************************************************** -Copyright (c) 2006-2011, Skype Limited. All rights reserved. -Redistribution and use in source and binary forms, with or without -modification, (subject to the limitations in the disclaimer below) -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 Skype Limited, nor the names of specific -contributors, may be used to endorse or promote products derived from -this software without specific prior written permission. -NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED -BY THIS LICENSE. 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. -***********************************************************************/ - -#include "silk_SigProc_FIX.h" - -/* Compute number of bits to right shift the sum of squares of a vector */ -/* of int16s to make it fit in an int32 */ -void silk_sum_sqr_shift( - opus_int32 *energy, /* O Energy of x, after shifting to the right */ - opus_int *shift, /* O Number of bits right shift applied to energy */ - const opus_int16 *x, /* I Input vector */ - opus_int len /* I Length of input vector */ -) -{ - opus_int i, shft; - opus_int32 nrg_tmp, nrg; - - nrg = 0; - shft = 0; - len--; - for( i = 0; i < len; i += 2 ) { - nrg = SKP_SMLABB_ovflw( nrg, x[ i ], x[ i ] ); - nrg = SKP_SMLABB_ovflw( nrg, x[ i + 1 ], x[ i + 1 ] ); - if( nrg < 0 ) { - /* Scale down */ - nrg = (opus_int32)SKP_RSHIFT_uint( (opus_uint32)nrg, 2 ); - shft = 2; - break; - } - } - for( ; i < len; i += 2 ) { - nrg_tmp = SKP_SMULBB( x[ i ], x[ i ] ); - nrg_tmp = SKP_SMLABB_ovflw( nrg_tmp, x[ i + 1 ], x[ i + 1 ] ); - nrg = (opus_int32)SKP_ADD_RSHIFT_uint( nrg, (opus_uint32)nrg_tmp, shft ); - if( nrg < 0 ) { - /* Scale down */ - nrg = (opus_int32)SKP_RSHIFT_uint( (opus_uint32)nrg, 2 ); - shft += 2; - } - } - if( i == len ) { - /* One sample left to process */ - nrg_tmp = SKP_SMULBB( x[ i ], x[ i ] ); - nrg = (opus_int32)SKP_ADD_RSHIFT_uint( nrg, nrg_tmp, shft ); - } - - /* Make sure to have at least one extra leading zero (two leading zeros in total) */ - if( nrg & 0xC0000000 ) { - nrg = SKP_RSHIFT_uint( (opus_uint32)nrg, 2 ); - shft += 2; - } - - /* Output arguments */ - *shift = shft; - *energy = nrg; -} - +/*********************************************************************** +Copyright (c) 2006-2011, Skype Limited. All rights reserved. +Redistribution and use in source and binary forms, with or without +modification, (subject to the limitations in the disclaimer below) +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 Skype Limited, nor the names of specific +contributors, may be used to endorse or promote products derived from +this software without specific prior written permission. +NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED +BY THIS LICENSE. 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. +***********************************************************************/ + +#include "silk_SigProc_FIX.h" + +/* Compute number of bits to right shift the sum of squares of a vector */ +/* of int16s to make it fit in an int32 */ +void silk_sum_sqr_shift( + opus_int32 *energy, /* O Energy of x, after shifting to the right */ + opus_int *shift, /* O Number of bits right shift applied to energy */ + const opus_int16 *x, /* I Input vector */ + opus_int len /* I Length of input vector */ +) +{ + opus_int i, shft; + opus_int32 nrg_tmp, nrg; + + nrg = 0; + shft = 0; + len--; + for( i = 0; i < len; i += 2 ) { + nrg = SKP_SMLABB_ovflw( nrg, x[ i ], x[ i ] ); + nrg = SKP_SMLABB_ovflw( nrg, x[ i + 1 ], x[ i + 1 ] ); + if( nrg < 0 ) { + /* Scale down */ + nrg = (opus_int32)SKP_RSHIFT_uint( (opus_uint32)nrg, 2 ); + shft = 2; + break; + } + } + for( ; i < len; i += 2 ) { + nrg_tmp = SKP_SMULBB( x[ i ], x[ i ] ); + nrg_tmp = SKP_SMLABB_ovflw( nrg_tmp, x[ i + 1 ], x[ i + 1 ] ); + nrg = (opus_int32)SKP_ADD_RSHIFT_uint( nrg, (opus_uint32)nrg_tmp, shft ); + if( nrg < 0 ) { + /* Scale down */ + nrg = (opus_int32)SKP_RSHIFT_uint( (opus_uint32)nrg, 2 ); + shft += 2; + } + } + if( i == len ) { + /* One sample left to process */ + nrg_tmp = SKP_SMULBB( x[ i ], x[ i ] ); + nrg = (opus_int32)SKP_ADD_RSHIFT_uint( nrg, nrg_tmp, shft ); + } + + /* Make sure to have at least one extra leading zero (two leading zeros in total) */ + if( nrg & 0xC0000000 ) { + nrg = SKP_RSHIFT_uint( (opus_uint32)nrg, 2 ); + shft += 2; + } + + /* Output arguments */ + *shift = shft; + *energy = nrg; +} + diff --git a/silk/silk_table_LSF_cos.c b/silk/silk_table_LSF_cos.c index ff5ebf731..6082254e3 100644 --- a/silk/silk_table_LSF_cos.c +++ b/silk/silk_table_LSF_cos.c @@ -1,66 +1,66 @@ -/*********************************************************************** -Copyright (c) 2006-2011, Skype Limited. All rights reserved. -Redistribution and use in source and binary forms, with or without -modification, (subject to the limitations in the disclaimer below) -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 Skype Limited, nor the names of specific -contributors, may be used to endorse or promote products derived from -this software without specific prior written permission. -NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED -BY THIS LICENSE. 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. -***********************************************************************/ - -#include "silk_tables.h" - -/* Cosine approximation table for LSF conversion */ -/* Q12 values (even) */ -const opus_int16 silk_LSFCosTab_FIX_Q12[ LSF_COS_TAB_SZ_FIX + 1 ] = { - 8192, 8190, 8182, 8170, - 8152, 8130, 8104, 8072, - 8034, 7994, 7946, 7896, - 7840, 7778, 7714, 7644, - 7568, 7490, 7406, 7318, - 7226, 7128, 7026, 6922, - 6812, 6698, 6580, 6458, - 6332, 6204, 6070, 5934, - 5792, 5648, 5502, 5352, - 5198, 5040, 4880, 4718, - 4552, 4382, 4212, 4038, - 3862, 3684, 3502, 3320, - 3136, 2948, 2760, 2570, - 2378, 2186, 1990, 1794, - 1598, 1400, 1202, 1002, - 802, 602, 402, 202, - 0, -202, -402, -602, - -802, -1002, -1202, -1400, - -1598, -1794, -1990, -2186, - -2378, -2570, -2760, -2948, - -3136, -3320, -3502, -3684, - -3862, -4038, -4212, -4382, - -4552, -4718, -4880, -5040, - -5198, -5352, -5502, -5648, - -5792, -5934, -6070, -6204, - -6332, -6458, -6580, -6698, - -6812, -6922, -7026, -7128, - -7226, -7318, -7406, -7490, - -7568, -7644, -7714, -7778, - -7840, -7896, -7946, -7994, - -8034, -8072, -8104, -8130, - -8152, -8170, -8182, -8190, - -8192 -}; +/*********************************************************************** +Copyright (c) 2006-2011, Skype Limited. All rights reserved. +Redistribution and use in source and binary forms, with or without +modification, (subject to the limitations in the disclaimer below) +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 Skype Limited, nor the names of specific +contributors, may be used to endorse or promote products derived from +this software without specific prior written permission. +NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED +BY THIS LICENSE. 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. +***********************************************************************/ + +#include "silk_tables.h" + +/* Cosine approximation table for LSF conversion */ +/* Q12 values (even) */ +const opus_int16 silk_LSFCosTab_FIX_Q12[ LSF_COS_TAB_SZ_FIX + 1 ] = { + 8192, 8190, 8182, 8170, + 8152, 8130, 8104, 8072, + 8034, 7994, 7946, 7896, + 7840, 7778, 7714, 7644, + 7568, 7490, 7406, 7318, + 7226, 7128, 7026, 6922, + 6812, 6698, 6580, 6458, + 6332, 6204, 6070, 5934, + 5792, 5648, 5502, 5352, + 5198, 5040, 4880, 4718, + 4552, 4382, 4212, 4038, + 3862, 3684, 3502, 3320, + 3136, 2948, 2760, 2570, + 2378, 2186, 1990, 1794, + 1598, 1400, 1202, 1002, + 802, 602, 402, 202, + 0, -202, -402, -602, + -802, -1002, -1202, -1400, + -1598, -1794, -1990, -2186, + -2378, -2570, -2760, -2948, + -3136, -3320, -3502, -3684, + -3862, -4038, -4212, -4382, + -4552, -4718, -4880, -5040, + -5198, -5352, -5502, -5648, + -5792, -5934, -6070, -6204, + -6332, -6458, -6580, -6698, + -6812, -6922, -7026, -7128, + -7226, -7318, -7406, -7490, + -7568, -7644, -7714, -7778, + -7840, -7896, -7946, -7994, + -8034, -8072, -8104, -8130, + -8152, -8170, -8182, -8190, + -8192 +}; diff --git a/silk/silk_tables.h b/silk/silk_tables.h index 2739ac32b..d412152f2 100644 --- a/silk/silk_tables.h +++ b/silk/silk_tables.h @@ -1,120 +1,120 @@ -/*********************************************************************** -Copyright (c) 2006-2011, Skype Limited. All rights reserved. -Redistribution and use in source and binary forms, with or without -modification, (subject to the limitations in the disclaimer below) -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 Skype Limited, nor the names of specific -contributors, may be used to endorse or promote products derived from -this software without specific prior written permission. -NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED -BY THIS LICENSE. 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. -***********************************************************************/ - -#ifndef SILK_TABLES_H -#define SILK_TABLES_H - -#include "silk_define.h" -#include "silk_structs.h" - -#ifdef __cplusplus -extern "C" -{ -#endif - -/* entropy coding tables */ -extern const opus_uint8 silk_gain_iCDF[ 3 ][ N_LEVELS_QGAIN / 8 ]; /* 24 */ -extern const opus_uint8 silk_delta_gain_iCDF[ MAX_DELTA_GAIN_QUANT - MIN_DELTA_GAIN_QUANT + 1 ]; /* 41 */ - -extern const opus_uint8 silk_pitch_lag_iCDF[ 2 * ( PITCH_EST_MAX_LAG_MS - PITCH_EST_MIN_LAG_MS ) ]; /* 32 */ -extern const opus_uint8 silk_pitch_delta_iCDF[ 21 ]; /* 21 */ -extern const opus_uint8 silk_pitch_contour_iCDF[ 34 ]; /* 34 */ -extern const opus_uint8 silk_pitch_contour_NB_iCDF[ 11 ]; /* 11 */ -extern const opus_uint8 silk_pitch_contour_10_ms_iCDF[ 12 ]; /* 12 */ -extern const opus_uint8 silk_pitch_contour_10_ms_NB_iCDF[ 3 ]; /* 3 */ - -extern const opus_uint8 silk_pulses_per_block_iCDF[ N_RATE_LEVELS ][ MAX_PULSES + 2 ]; /* 180 */ -extern const opus_uint8 silk_pulses_per_block_BITS_Q5[ N_RATE_LEVELS - 1 ][ MAX_PULSES + 2 ]; /* 162 */ - -extern const opus_uint8 silk_rate_levels_iCDF[ 2 ][ N_RATE_LEVELS - 1 ]; /* 18 */ -extern const opus_uint8 silk_rate_levels_BITS_Q5[ 2 ][ N_RATE_LEVELS - 1 ]; /* 18 */ - -extern const opus_uint8 silk_max_pulses_table[ 4 ]; /* 4 */ - -extern const opus_uint8 silk_shell_code_table0[ 152 ]; /* 152 */ -extern const opus_uint8 silk_shell_code_table1[ 152 ]; /* 152 */ -extern const opus_uint8 silk_shell_code_table2[ 152 ]; /* 152 */ -extern const opus_uint8 silk_shell_code_table3[ 152 ]; /* 152 */ -extern const opus_uint8 silk_shell_code_table_offsets[ MAX_PULSES + 1 ]; /* 17 */ - -extern const opus_uint8 silk_lsb_iCDF[ 2 ]; /* 2 */ - -extern const opus_uint8 silk_sign_iCDF[ 36 ]; /* 36 */ - -extern const opus_uint8 silk_uniform3_iCDF[ 3 ]; /* 3 */ -extern const opus_uint8 silk_uniform4_iCDF[ 4 ]; /* 4 */ -extern const opus_uint8 silk_uniform5_iCDF[ 5 ]; /* 5 */ -extern const opus_uint8 silk_uniform6_iCDF[ 6 ]; /* 6 */ -extern const opus_uint8 silk_uniform8_iCDF[ 8 ]; /* 8 */ - -extern const opus_uint8 silk_NLSF_EXT_iCDF[ 7 ]; /* 7 */ - -extern const opus_uint8 silk_LTP_per_index_iCDF[ 3 ]; /* 3 */ -extern const opus_uint8 * const silk_LTP_gain_iCDF_ptrs[ NB_LTP_CBKS ]; /* 3 */ -extern const opus_uint8 * const silk_LTP_gain_BITS_Q5_ptrs[ NB_LTP_CBKS ]; /* 3 */ -extern const opus_int16 silk_LTP_gain_middle_avg_RD_Q14; -extern const opus_int8 * const silk_LTP_vq_ptrs_Q7[ NB_LTP_CBKS ]; /* 168 */ -extern const opus_int8 silk_LTP_vq_sizes[ NB_LTP_CBKS ]; /* 3 */ - -extern const opus_uint8 silk_LTPscale_iCDF[ 3 ]; /* 4 */ -extern const opus_int16 silk_LTPScales_table_Q14[ 3 ]; - -extern const opus_uint8 silk_type_offset_VAD_iCDF[ 4 ]; /* 4 */ -extern const opus_uint8 silk_type_offset_no_VAD_iCDF[ 2 ]; /* 2 */ - -extern const opus_int16 silk_stereo_pred_quant_Q13[ STEREO_QUANT_TAB_SIZE ]; /* 32 */ -extern const opus_uint8 silk_stereo_pred_joint_iCDF[ 25 ]; /* 25 */ -extern const opus_uint8 silk_stereo_only_code_mid_iCDF[ 2 ]; /* 2 */ - -extern const opus_uint8 * const silk_LBRR_flags_iCDF_ptr[ 2 ]; /* 10 */ - -extern const opus_uint8 silk_NLSF_interpolation_factor_iCDF[ 5 ]; /* 5 */ - -extern const silk_NLSF_CB_struct silk_NLSF_CB_WB; -extern const silk_NLSF_CB_struct silk_NLSF_CB_NB_MB; - -/* Piece-wise linear mapping from bitrate in kbps to coding quality in dB SNR */ -extern const opus_int32 silk_TargetRate_table_NB[ TARGET_RATE_TAB_SZ ]; -extern const opus_int32 silk_TargetRate_table_MB[ TARGET_RATE_TAB_SZ ]; -extern const opus_int32 silk_TargetRate_table_WB[ TARGET_RATE_TAB_SZ ]; -extern const opus_int16 silk_SNR_table_Q1[ TARGET_RATE_TAB_SZ ]; - -/* Quantization offsets */ -extern const opus_int16 silk_Quantization_Offsets_Q10[ 2 ][ 2 ]; - -/* Interpolation points for filter coefficients used in the bandwidth transition smoother */ -extern const opus_int32 silk_Transition_LP_B_Q28[ TRANSITION_INT_NUM ][ TRANSITION_NB ]; -extern const opus_int32 silk_Transition_LP_A_Q28[ TRANSITION_INT_NUM ][ TRANSITION_NA ]; - -/* Rom table with cosine values */ -extern const opus_int16 silk_LSFCosTab_FIX_Q12[ LSF_COS_TAB_SZ_FIX + 1 ]; - -#ifdef __cplusplus -} -#endif - -#endif +/*********************************************************************** +Copyright (c) 2006-2011, Skype Limited. All rights reserved. +Redistribution and use in source and binary forms, with or without +modification, (subject to the limitations in the disclaimer below) +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 Skype Limited, nor the names of specific +contributors, may be used to endorse or promote products derived from +this software without specific prior written permission. +NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED +BY THIS LICENSE. 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. +***********************************************************************/ + +#ifndef SILK_TABLES_H +#define SILK_TABLES_H + +#include "silk_define.h" +#include "silk_structs.h" + +#ifdef __cplusplus +extern "C" +{ +#endif + +/* entropy coding tables */ +extern const opus_uint8 silk_gain_iCDF[ 3 ][ N_LEVELS_QGAIN / 8 ]; /* 24 */ +extern const opus_uint8 silk_delta_gain_iCDF[ MAX_DELTA_GAIN_QUANT - MIN_DELTA_GAIN_QUANT + 1 ]; /* 41 */ + +extern const opus_uint8 silk_pitch_lag_iCDF[ 2 * ( PITCH_EST_MAX_LAG_MS - PITCH_EST_MIN_LAG_MS ) ]; /* 32 */ +extern const opus_uint8 silk_pitch_delta_iCDF[ 21 ]; /* 21 */ +extern const opus_uint8 silk_pitch_contour_iCDF[ 34 ]; /* 34 */ +extern const opus_uint8 silk_pitch_contour_NB_iCDF[ 11 ]; /* 11 */ +extern const opus_uint8 silk_pitch_contour_10_ms_iCDF[ 12 ]; /* 12 */ +extern const opus_uint8 silk_pitch_contour_10_ms_NB_iCDF[ 3 ]; /* 3 */ + +extern const opus_uint8 silk_pulses_per_block_iCDF[ N_RATE_LEVELS ][ MAX_PULSES + 2 ]; /* 180 */ +extern const opus_uint8 silk_pulses_per_block_BITS_Q5[ N_RATE_LEVELS - 1 ][ MAX_PULSES + 2 ]; /* 162 */ + +extern const opus_uint8 silk_rate_levels_iCDF[ 2 ][ N_RATE_LEVELS - 1 ]; /* 18 */ +extern const opus_uint8 silk_rate_levels_BITS_Q5[ 2 ][ N_RATE_LEVELS - 1 ]; /* 18 */ + +extern const opus_uint8 silk_max_pulses_table[ 4 ]; /* 4 */ + +extern const opus_uint8 silk_shell_code_table0[ 152 ]; /* 152 */ +extern const opus_uint8 silk_shell_code_table1[ 152 ]; /* 152 */ +extern const opus_uint8 silk_shell_code_table2[ 152 ]; /* 152 */ +extern const opus_uint8 silk_shell_code_table3[ 152 ]; /* 152 */ +extern const opus_uint8 silk_shell_code_table_offsets[ MAX_PULSES + 1 ]; /* 17 */ + +extern const opus_uint8 silk_lsb_iCDF[ 2 ]; /* 2 */ + +extern const opus_uint8 silk_sign_iCDF[ 36 ]; /* 36 */ + +extern const opus_uint8 silk_uniform3_iCDF[ 3 ]; /* 3 */ +extern const opus_uint8 silk_uniform4_iCDF[ 4 ]; /* 4 */ +extern const opus_uint8 silk_uniform5_iCDF[ 5 ]; /* 5 */ +extern const opus_uint8 silk_uniform6_iCDF[ 6 ]; /* 6 */ +extern const opus_uint8 silk_uniform8_iCDF[ 8 ]; /* 8 */ + +extern const opus_uint8 silk_NLSF_EXT_iCDF[ 7 ]; /* 7 */ + +extern const opus_uint8 silk_LTP_per_index_iCDF[ 3 ]; /* 3 */ +extern const opus_uint8 * const silk_LTP_gain_iCDF_ptrs[ NB_LTP_CBKS ]; /* 3 */ +extern const opus_uint8 * const silk_LTP_gain_BITS_Q5_ptrs[ NB_LTP_CBKS ]; /* 3 */ +extern const opus_int16 silk_LTP_gain_middle_avg_RD_Q14; +extern const opus_int8 * const silk_LTP_vq_ptrs_Q7[ NB_LTP_CBKS ]; /* 168 */ +extern const opus_int8 silk_LTP_vq_sizes[ NB_LTP_CBKS ]; /* 3 */ + +extern const opus_uint8 silk_LTPscale_iCDF[ 3 ]; /* 4 */ +extern const opus_int16 silk_LTPScales_table_Q14[ 3 ]; + +extern const opus_uint8 silk_type_offset_VAD_iCDF[ 4 ]; /* 4 */ +extern const opus_uint8 silk_type_offset_no_VAD_iCDF[ 2 ]; /* 2 */ + +extern const opus_int16 silk_stereo_pred_quant_Q13[ STEREO_QUANT_TAB_SIZE ]; /* 32 */ +extern const opus_uint8 silk_stereo_pred_joint_iCDF[ 25 ]; /* 25 */ +extern const opus_uint8 silk_stereo_only_code_mid_iCDF[ 2 ]; /* 2 */ + +extern const opus_uint8 * const silk_LBRR_flags_iCDF_ptr[ 2 ]; /* 10 */ + +extern const opus_uint8 silk_NLSF_interpolation_factor_iCDF[ 5 ]; /* 5 */ + +extern const silk_NLSF_CB_struct silk_NLSF_CB_WB; +extern const silk_NLSF_CB_struct silk_NLSF_CB_NB_MB; + +/* Piece-wise linear mapping from bitrate in kbps to coding quality in dB SNR */ +extern const opus_int32 silk_TargetRate_table_NB[ TARGET_RATE_TAB_SZ ]; +extern const opus_int32 silk_TargetRate_table_MB[ TARGET_RATE_TAB_SZ ]; +extern const opus_int32 silk_TargetRate_table_WB[ TARGET_RATE_TAB_SZ ]; +extern const opus_int16 silk_SNR_table_Q1[ TARGET_RATE_TAB_SZ ]; + +/* Quantization offsets */ +extern const opus_int16 silk_Quantization_Offsets_Q10[ 2 ][ 2 ]; + +/* Interpolation points for filter coefficients used in the bandwidth transition smoother */ +extern const opus_int32 silk_Transition_LP_B_Q28[ TRANSITION_INT_NUM ][ TRANSITION_NB ]; +extern const opus_int32 silk_Transition_LP_A_Q28[ TRANSITION_INT_NUM ][ TRANSITION_NA ]; + +/* Rom table with cosine values */ +extern const opus_int16 silk_LSFCosTab_FIX_Q12[ LSF_COS_TAB_SZ_FIX + 1 ]; + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/silk/silk_tables_LTP.c b/silk/silk_tables_LTP.c index e86253db1..7c3af0146 100644 --- a/silk/silk_tables_LTP.c +++ b/silk/silk_tables_LTP.c @@ -1,268 +1,268 @@ -/*********************************************************************** -Copyright (c) 2006-2011, Skype Limited. All rights reserved. -Redistribution and use in source and binary forms, with or without -modification, (subject to the limitations in the disclaimer below) -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 Skype Limited, nor the names of specific -contributors, may be used to endorse or promote products derived from -this software without specific prior written permission. -NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED -BY THIS LICENSE. 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. -***********************************************************************/ - -#include "silk_tables.h" - -const opus_uint8 silk_LTP_per_index_iCDF[3] = { - 179, 99, 0 -}; - -const opus_uint8 silk_LTP_gain_iCDF_0[8] = { - 71, 56, 43, 30, 21, 12, 6, 0 -}; - -const opus_uint8 silk_LTP_gain_iCDF_1[16] = { - 199, 165, 144, 124, 109, 96, 84, 71, - 61, 51, 42, 32, 23, 15, 8, 0 -}; - -const opus_uint8 silk_LTP_gain_iCDF_2[32] = { - 241, 225, 211, 199, 187, 175, 164, 153, - 142, 132, 123, 114, 105, 96, 88, 80, - 72, 64, 57, 50, 44, 38, 33, 29, - 24, 20, 16, 12, 9, 5, 2, 0 -}; - -const opus_int16 silk_LTP_gain_middle_avg_RD_Q14 = 12304; - -const opus_uint8 silk_LTP_gain_BITS_Q5_0[8] = { - 15, 131, 138, 138, 155, 155, 173, 173 -}; - -const opus_uint8 silk_LTP_gain_BITS_Q5_1[16] = { - 69, 93, 115, 118, 131, 138, 141, 138, - 150, 150, 155, 150, 155, 160, 166, 160 -}; - -const opus_uint8 silk_LTP_gain_BITS_Q5_2[32] = { - 131, 128, 134, 141, 141, 141, 145, 145, - 145, 150, 155, 155, 155, 155, 160, 160, - 160, 160, 166, 166, 173, 173, 182, 192, - 182, 192, 192, 192, 205, 192, 205, 224 -}; - -const opus_uint8 * const silk_LTP_gain_iCDF_ptrs[NB_LTP_CBKS] = { - silk_LTP_gain_iCDF_0, - silk_LTP_gain_iCDF_1, - silk_LTP_gain_iCDF_2 -}; - -const opus_uint8 * const silk_LTP_gain_BITS_Q5_ptrs[NB_LTP_CBKS] = { - silk_LTP_gain_BITS_Q5_0, - silk_LTP_gain_BITS_Q5_1, - silk_LTP_gain_BITS_Q5_2 -}; - -const opus_int8 silk_LTP_gain_vq_0[8][5] = -{ -{ - 4, 6, 24, 7, 5 -}, -{ - 0, 0, 2, 0, 0 -}, -{ - 12, 28, 41, 13, -4 -}, -{ - -9, 15, 42, 25, 14 -}, -{ - 1, -2, 62, 41, -9 -}, -{ - -10, 37, 65, -4, 3 -}, -{ - -6, 4, 66, 7, -8 -}, -{ - 16, 14, 38, -3, 33 -} -}; - -const opus_int8 silk_LTP_gain_vq_1[16][5] = -{ -{ - 13, 22, 39, 23, 12 -}, -{ - -1, 36, 64, 27, -6 -}, -{ - -7, 10, 55, 43, 17 -}, -{ - 1, 1, 8, 1, 1 -}, -{ - 6, -11, 74, 53, -9 -}, -{ - -12, 55, 76, -12, 8 -}, -{ - -3, 3, 93, 27, -4 -}, -{ - 26, 39, 59, 3, -8 -}, -{ - 2, 0, 77, 11, 9 -}, -{ - -8, 22, 44, -6, 7 -}, -{ - 40, 9, 26, 3, 9 -}, -{ - -7, 20, 101, -7, 4 -}, -{ - 3, -8, 42, 26, 0 -}, -{ - -15, 33, 68, 2, 23 -}, -{ - -2, 55, 46, -2, 15 -}, -{ - 3, -1, 21, 16, 41 -} -}; - -const opus_int8 silk_LTP_gain_vq_2[32][5] = -{ -{ - -6, 27, 61, 39, 5 -}, -{ - -11, 42, 88, 4, 1 -}, -{ - -2, 60, 65, 6, -4 -}, -{ - -1, -5, 73, 56, 1 -}, -{ - -9, 19, 94, 29, -9 -}, -{ - 0, 12, 99, 6, 4 -}, -{ - 8, -19, 102, 46, -13 -}, -{ - 3, 2, 13, 3, 2 -}, -{ - 9, -21, 84, 72, -18 -}, -{ - -11, 46, 104, -22, 8 -}, -{ - 18, 38, 48, 23, 0 -}, -{ - -16, 70, 83, -21, 11 -}, -{ - 5, -11, 117, 22, -8 -}, -{ - -6, 23, 117, -12, 3 -}, -{ - 3, -8, 95, 28, 4 -}, -{ - -10, 15, 77, 60, -15 -}, -{ - -1, 4, 124, 2, -4 -}, -{ - 3, 38, 84, 24, -25 -}, -{ - 2, 13, 42, 13, 31 -}, -{ - 21, -4, 56, 46, -1 -}, -{ - -1, 35, 79, -13, 19 -}, -{ - -7, 65, 88, -9, -14 -}, -{ - 20, 4, 81, 49, -29 -}, -{ - 20, 0, 75, 3, -17 -}, -{ - 5, -9, 44, 92, -8 -}, -{ - 1, -3, 22, 69, 31 -}, -{ - -6, 95, 41, -12, 5 -}, -{ - 39, 67, 16, -4, 1 -}, -{ - 0, -6, 120, 55, -36 -}, -{ - -13, 44, 122, 4, -24 -}, -{ - 81, 5, 11, 3, 7 -}, -{ - 2, 0, 9, 10, 88 -} -}; - -const opus_int8 * const silk_LTP_vq_ptrs_Q7[NB_LTP_CBKS] = { - (opus_int8 *)&silk_LTP_gain_vq_0[0][0], - (opus_int8 *)&silk_LTP_gain_vq_1[0][0], - (opus_int8 *)&silk_LTP_gain_vq_2[0][0] -}; - -const opus_int8 silk_LTP_vq_sizes[NB_LTP_CBKS] = { - 8, 16, 32 -}; +/*********************************************************************** +Copyright (c) 2006-2011, Skype Limited. All rights reserved. +Redistribution and use in source and binary forms, with or without +modification, (subject to the limitations in the disclaimer below) +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 Skype Limited, nor the names of specific +contributors, may be used to endorse or promote products derived from +this software without specific prior written permission. +NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED +BY THIS LICENSE. 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. +***********************************************************************/ + +#include "silk_tables.h" + +const opus_uint8 silk_LTP_per_index_iCDF[3] = { + 179, 99, 0 +}; + +const opus_uint8 silk_LTP_gain_iCDF_0[8] = { + 71, 56, 43, 30, 21, 12, 6, 0 +}; + +const opus_uint8 silk_LTP_gain_iCDF_1[16] = { + 199, 165, 144, 124, 109, 96, 84, 71, + 61, 51, 42, 32, 23, 15, 8, 0 +}; + +const opus_uint8 silk_LTP_gain_iCDF_2[32] = { + 241, 225, 211, 199, 187, 175, 164, 153, + 142, 132, 123, 114, 105, 96, 88, 80, + 72, 64, 57, 50, 44, 38, 33, 29, + 24, 20, 16, 12, 9, 5, 2, 0 +}; + +const opus_int16 silk_LTP_gain_middle_avg_RD_Q14 = 12304; + +const opus_uint8 silk_LTP_gain_BITS_Q5_0[8] = { + 15, 131, 138, 138, 155, 155, 173, 173 +}; + +const opus_uint8 silk_LTP_gain_BITS_Q5_1[16] = { + 69, 93, 115, 118, 131, 138, 141, 138, + 150, 150, 155, 150, 155, 160, 166, 160 +}; + +const opus_uint8 silk_LTP_gain_BITS_Q5_2[32] = { + 131, 128, 134, 141, 141, 141, 145, 145, + 145, 150, 155, 155, 155, 155, 160, 160, + 160, 160, 166, 166, 173, 173, 182, 192, + 182, 192, 192, 192, 205, 192, 205, 224 +}; + +const opus_uint8 * const silk_LTP_gain_iCDF_ptrs[NB_LTP_CBKS] = { + silk_LTP_gain_iCDF_0, + silk_LTP_gain_iCDF_1, + silk_LTP_gain_iCDF_2 +}; + +const opus_uint8 * const silk_LTP_gain_BITS_Q5_ptrs[NB_LTP_CBKS] = { + silk_LTP_gain_BITS_Q5_0, + silk_LTP_gain_BITS_Q5_1, + silk_LTP_gain_BITS_Q5_2 +}; + +const opus_int8 silk_LTP_gain_vq_0[8][5] = +{ +{ + 4, 6, 24, 7, 5 +}, +{ + 0, 0, 2, 0, 0 +}, +{ + 12, 28, 41, 13, -4 +}, +{ + -9, 15, 42, 25, 14 +}, +{ + 1, -2, 62, 41, -9 +}, +{ + -10, 37, 65, -4, 3 +}, +{ + -6, 4, 66, 7, -8 +}, +{ + 16, 14, 38, -3, 33 +} +}; + +const opus_int8 silk_LTP_gain_vq_1[16][5] = +{ +{ + 13, 22, 39, 23, 12 +}, +{ + -1, 36, 64, 27, -6 +}, +{ + -7, 10, 55, 43, 17 +}, +{ + 1, 1, 8, 1, 1 +}, +{ + 6, -11, 74, 53, -9 +}, +{ + -12, 55, 76, -12, 8 +}, +{ + -3, 3, 93, 27, -4 +}, +{ + 26, 39, 59, 3, -8 +}, +{ + 2, 0, 77, 11, 9 +}, +{ + -8, 22, 44, -6, 7 +}, +{ + 40, 9, 26, 3, 9 +}, +{ + -7, 20, 101, -7, 4 +}, +{ + 3, -8, 42, 26, 0 +}, +{ + -15, 33, 68, 2, 23 +}, +{ + -2, 55, 46, -2, 15 +}, +{ + 3, -1, 21, 16, 41 +} +}; + +const opus_int8 silk_LTP_gain_vq_2[32][5] = +{ +{ + -6, 27, 61, 39, 5 +}, +{ + -11, 42, 88, 4, 1 +}, +{ + -2, 60, 65, 6, -4 +}, +{ + -1, -5, 73, 56, 1 +}, +{ + -9, 19, 94, 29, -9 +}, +{ + 0, 12, 99, 6, 4 +}, +{ + 8, -19, 102, 46, -13 +}, +{ + 3, 2, 13, 3, 2 +}, +{ + 9, -21, 84, 72, -18 +}, +{ + -11, 46, 104, -22, 8 +}, +{ + 18, 38, 48, 23, 0 +}, +{ + -16, 70, 83, -21, 11 +}, +{ + 5, -11, 117, 22, -8 +}, +{ + -6, 23, 117, -12, 3 +}, +{ + 3, -8, 95, 28, 4 +}, +{ + -10, 15, 77, 60, -15 +}, +{ + -1, 4, 124, 2, -4 +}, +{ + 3, 38, 84, 24, -25 +}, +{ + 2, 13, 42, 13, 31 +}, +{ + 21, -4, 56, 46, -1 +}, +{ + -1, 35, 79, -13, 19 +}, +{ + -7, 65, 88, -9, -14 +}, +{ + 20, 4, 81, 49, -29 +}, +{ + 20, 0, 75, 3, -17 +}, +{ + 5, -9, 44, 92, -8 +}, +{ + 1, -3, 22, 69, 31 +}, +{ + -6, 95, 41, -12, 5 +}, +{ + 39, 67, 16, -4, 1 +}, +{ + 0, -6, 120, 55, -36 +}, +{ + -13, 44, 122, 4, -24 +}, +{ + 81, 5, 11, 3, 7 +}, +{ + 2, 0, 9, 10, 88 +} +}; + +const opus_int8 * const silk_LTP_vq_ptrs_Q7[NB_LTP_CBKS] = { + (opus_int8 *)&silk_LTP_gain_vq_0[0][0], + (opus_int8 *)&silk_LTP_gain_vq_1[0][0], + (opus_int8 *)&silk_LTP_gain_vq_2[0][0] +}; + +const opus_int8 silk_LTP_vq_sizes[NB_LTP_CBKS] = { + 8, 16, 32 +}; diff --git a/silk/silk_tables_NLSF_CB_NB_MB.c b/silk/silk_tables_NLSF_CB_NB_MB.c index ed566d856..263ebcbb2 100644 --- a/silk/silk_tables_NLSF_CB_NB_MB.c +++ b/silk/silk_tables_NLSF_CB_NB_MB.c @@ -1,155 +1,155 @@ -/*********************************************************************** -Copyright (c) 2006-2011, Skype Limited. All rights reserved. -Redistribution and use in source and binary forms, with or without -modification, (subject to the limitations in the disclaimer below) -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 Skype Limited, nor the names of specific -contributors, may be used to endorse or promote products derived from -this software without specific prior written permission. -NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED -BY THIS LICENSE. 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. -***********************************************************************/ - -#include "silk_structs.h" - -const opus_uint8 silk_NLSF_CB1_NB_MB_Q8[ 320 ] = { - 12, 35, 60, 83, 108, 132, 157, 180, - 206, 228, 15, 32, 55, 77, 101, 125, - 151, 175, 201, 225, 19, 42, 66, 89, - 114, 137, 162, 184, 209, 230, 12, 25, - 50, 72, 97, 120, 147, 172, 200, 223, - 26, 44, 69, 90, 114, 135, 159, 180, - 205, 225, 13, 22, 53, 80, 106, 130, - 156, 180, 205, 228, 15, 25, 44, 64, - 90, 115, 142, 168, 196, 222, 19, 24, - 62, 82, 100, 120, 145, 168, 190, 214, - 22, 31, 50, 79, 103, 120, 151, 170, - 203, 227, 21, 29, 45, 65, 106, 124, - 150, 171, 196, 224, 30, 49, 75, 97, - 121, 142, 165, 186, 209, 229, 19, 25, - 52, 70, 93, 116, 143, 166, 192, 219, - 26, 34, 62, 75, 97, 118, 145, 167, - 194, 217, 25, 33, 56, 70, 91, 113, - 143, 165, 196, 223, 21, 34, 51, 72, - 97, 117, 145, 171, 196, 222, 20, 29, - 50, 67, 90, 117, 144, 168, 197, 221, - 22, 31, 48, 66, 95, 117, 146, 168, - 196, 222, 24, 33, 51, 77, 116, 134, - 158, 180, 200, 224, 21, 28, 70, 87, - 106, 124, 149, 170, 194, 217, 26, 33, - 53, 64, 83, 117, 152, 173, 204, 225, - 27, 34, 65, 95, 108, 129, 155, 174, - 210, 225, 20, 26, 72, 99, 113, 131, - 154, 176, 200, 219, 34, 43, 61, 78, - 93, 114, 155, 177, 205, 229, 23, 29, - 54, 97, 124, 138, 163, 179, 209, 229, - 30, 38, 56, 89, 118, 129, 158, 178, - 200, 231, 21, 29, 49, 63, 85, 111, - 142, 163, 193, 222, 27, 48, 77, 103, - 133, 158, 179, 196, 215, 232, 29, 47, - 74, 99, 124, 151, 176, 198, 220, 237, - 33, 42, 61, 76, 93, 121, 155, 174, - 207, 225, 29, 53, 87, 112, 136, 154, - 170, 188, 208, 227, 24, 30, 52, 84, - 131, 150, 166, 186, 203, 229, 37, 48, - 64, 84, 104, 118, 156, 177, 201, 230 -}; - -const opus_uint8 silk_NLSF_CB1_iCDF_NB_MB[ 64 ] = { - 212, 178, 148, 129, 108, 96, 85, 82, - 79, 77, 61, 59, 57, 56, 51, 49, - 48, 45, 42, 41, 40, 38, 36, 34, - 31, 30, 21, 12, 10, 3, 1, 0, - 255, 245, 244, 236, 233, 225, 217, 203, - 190, 176, 175, 161, 149, 136, 125, 114, - 102, 91, 81, 71, 60, 52, 43, 35, - 28, 20, 19, 18, 12, 11, 5, 0 -}; - -const opus_uint8 silk_NLSF_CB2_SELECT_NB_MB[ 160 ] = { - 16, 0, 0, 0, 0, 99, 66, 36, - 36, 34, 36, 34, 34, 34, 34, 83, - 69, 36, 52, 34, 116, 102, 70, 68, - 68, 176, 102, 68, 68, 34, 65, 85, - 68, 84, 36, 116, 141, 152, 139, 170, - 132, 187, 184, 216, 137, 132, 249, 168, - 185, 139, 104, 102, 100, 68, 68, 178, - 218, 185, 185, 170, 244, 216, 187, 187, - 170, 244, 187, 187, 219, 138, 103, 155, - 184, 185, 137, 116, 183, 155, 152, 136, - 132, 217, 184, 184, 170, 164, 217, 171, - 155, 139, 244, 169, 184, 185, 170, 164, - 216, 223, 218, 138, 214, 143, 188, 218, - 168, 244, 141, 136, 155, 170, 168, 138, - 220, 219, 139, 164, 219, 202, 216, 137, - 168, 186, 246, 185, 139, 116, 185, 219, - 185, 138, 100, 100, 134, 100, 102, 34, - 68, 68, 100, 68, 168, 203, 221, 218, - 168, 167, 154, 136, 104, 70, 164, 246, - 171, 137, 139, 137, 155, 218, 219, 139 -}; - -const opus_uint8 silk_NLSF_CB2_iCDF_NB_MB[ 72 ] = { - 255, 254, 253, 238, 14, 3, 2, 1, - 0, 255, 254, 252, 218, 35, 3, 2, - 1, 0, 255, 254, 250, 208, 59, 4, - 2, 1, 0, 255, 254, 246, 194, 71, - 10, 2, 1, 0, 255, 252, 236, 183, - 82, 8, 2, 1, 0, 255, 252, 235, - 180, 90, 17, 2, 1, 0, 255, 248, - 224, 171, 97, 30, 4, 1, 0, 255, - 254, 236, 173, 95, 37, 7, 1, 0 -}; - -const opus_uint8 silk_NLSF_CB2_BITS_NB_MB_Q5[ 72 ] = { - 255, 255, 255, 131, 6, 145, 255, 255, - 255, 255, 255, 236, 93, 15, 96, 255, - 255, 255, 255, 255, 194, 83, 25, 71, - 221, 255, 255, 255, 255, 162, 73, 34, - 66, 162, 255, 255, 255, 210, 126, 73, - 43, 57, 173, 255, 255, 255, 201, 125, - 71, 48, 58, 130, 255, 255, 255, 166, - 110, 73, 57, 62, 104, 210, 255, 255, - 251, 123, 65, 55, 68, 100, 171, 255 -}; - -const opus_uint8 silk_NLSF_PRED_NB_MB_Q8[ 18 ] = { - 179, 138, 140, 148, 151, 149, 153, 151, - 163, 116, 67, 82, 59, 92, 72, 100, - 89, 92 -}; - -const opus_int16 silk_NLSF_DELTA_MIN_NB_MB_Q15[ 11 ] = { - 250, 3, 6, 3, 3, 3, 4, 3, - 3, 3, 461 -}; - -const silk_NLSF_CB_struct silk_NLSF_CB_NB_MB = -{ - 32, - 10, - SILK_FIX_CONST( 0.18, 16 ), - SILK_FIX_CONST( 1.0 / 0.18, 6 ), - silk_NLSF_CB1_NB_MB_Q8, - silk_NLSF_CB1_iCDF_NB_MB, - silk_NLSF_PRED_NB_MB_Q8, - silk_NLSF_CB2_SELECT_NB_MB, - silk_NLSF_CB2_iCDF_NB_MB, - silk_NLSF_CB2_BITS_NB_MB_Q5, - silk_NLSF_DELTA_MIN_NB_MB_Q15, -}; +/*********************************************************************** +Copyright (c) 2006-2011, Skype Limited. All rights reserved. +Redistribution and use in source and binary forms, with or without +modification, (subject to the limitations in the disclaimer below) +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 Skype Limited, nor the names of specific +contributors, may be used to endorse or promote products derived from +this software without specific prior written permission. +NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED +BY THIS LICENSE. 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. +***********************************************************************/ + +#include "silk_structs.h" + +const opus_uint8 silk_NLSF_CB1_NB_MB_Q8[ 320 ] = { + 12, 35, 60, 83, 108, 132, 157, 180, + 206, 228, 15, 32, 55, 77, 101, 125, + 151, 175, 201, 225, 19, 42, 66, 89, + 114, 137, 162, 184, 209, 230, 12, 25, + 50, 72, 97, 120, 147, 172, 200, 223, + 26, 44, 69, 90, 114, 135, 159, 180, + 205, 225, 13, 22, 53, 80, 106, 130, + 156, 180, 205, 228, 15, 25, 44, 64, + 90, 115, 142, 168, 196, 222, 19, 24, + 62, 82, 100, 120, 145, 168, 190, 214, + 22, 31, 50, 79, 103, 120, 151, 170, + 203, 227, 21, 29, 45, 65, 106, 124, + 150, 171, 196, 224, 30, 49, 75, 97, + 121, 142, 165, 186, 209, 229, 19, 25, + 52, 70, 93, 116, 143, 166, 192, 219, + 26, 34, 62, 75, 97, 118, 145, 167, + 194, 217, 25, 33, 56, 70, 91, 113, + 143, 165, 196, 223, 21, 34, 51, 72, + 97, 117, 145, 171, 196, 222, 20, 29, + 50, 67, 90, 117, 144, 168, 197, 221, + 22, 31, 48, 66, 95, 117, 146, 168, + 196, 222, 24, 33, 51, 77, 116, 134, + 158, 180, 200, 224, 21, 28, 70, 87, + 106, 124, 149, 170, 194, 217, 26, 33, + 53, 64, 83, 117, 152, 173, 204, 225, + 27, 34, 65, 95, 108, 129, 155, 174, + 210, 225, 20, 26, 72, 99, 113, 131, + 154, 176, 200, 219, 34, 43, 61, 78, + 93, 114, 155, 177, 205, 229, 23, 29, + 54, 97, 124, 138, 163, 179, 209, 229, + 30, 38, 56, 89, 118, 129, 158, 178, + 200, 231, 21, 29, 49, 63, 85, 111, + 142, 163, 193, 222, 27, 48, 77, 103, + 133, 158, 179, 196, 215, 232, 29, 47, + 74, 99, 124, 151, 176, 198, 220, 237, + 33, 42, 61, 76, 93, 121, 155, 174, + 207, 225, 29, 53, 87, 112, 136, 154, + 170, 188, 208, 227, 24, 30, 52, 84, + 131, 150, 166, 186, 203, 229, 37, 48, + 64, 84, 104, 118, 156, 177, 201, 230 +}; + +const opus_uint8 silk_NLSF_CB1_iCDF_NB_MB[ 64 ] = { + 212, 178, 148, 129, 108, 96, 85, 82, + 79, 77, 61, 59, 57, 56, 51, 49, + 48, 45, 42, 41, 40, 38, 36, 34, + 31, 30, 21, 12, 10, 3, 1, 0, + 255, 245, 244, 236, 233, 225, 217, 203, + 190, 176, 175, 161, 149, 136, 125, 114, + 102, 91, 81, 71, 60, 52, 43, 35, + 28, 20, 19, 18, 12, 11, 5, 0 +}; + +const opus_uint8 silk_NLSF_CB2_SELECT_NB_MB[ 160 ] = { + 16, 0, 0, 0, 0, 99, 66, 36, + 36, 34, 36, 34, 34, 34, 34, 83, + 69, 36, 52, 34, 116, 102, 70, 68, + 68, 176, 102, 68, 68, 34, 65, 85, + 68, 84, 36, 116, 141, 152, 139, 170, + 132, 187, 184, 216, 137, 132, 249, 168, + 185, 139, 104, 102, 100, 68, 68, 178, + 218, 185, 185, 170, 244, 216, 187, 187, + 170, 244, 187, 187, 219, 138, 103, 155, + 184, 185, 137, 116, 183, 155, 152, 136, + 132, 217, 184, 184, 170, 164, 217, 171, + 155, 139, 244, 169, 184, 185, 170, 164, + 216, 223, 218, 138, 214, 143, 188, 218, + 168, 244, 141, 136, 155, 170, 168, 138, + 220, 219, 139, 164, 219, 202, 216, 137, + 168, 186, 246, 185, 139, 116, 185, 219, + 185, 138, 100, 100, 134, 100, 102, 34, + 68, 68, 100, 68, 168, 203, 221, 218, + 168, 167, 154, 136, 104, 70, 164, 246, + 171, 137, 139, 137, 155, 218, 219, 139 +}; + +const opus_uint8 silk_NLSF_CB2_iCDF_NB_MB[ 72 ] = { + 255, 254, 253, 238, 14, 3, 2, 1, + 0, 255, 254, 252, 218, 35, 3, 2, + 1, 0, 255, 254, 250, 208, 59, 4, + 2, 1, 0, 255, 254, 246, 194, 71, + 10, 2, 1, 0, 255, 252, 236, 183, + 82, 8, 2, 1, 0, 255, 252, 235, + 180, 90, 17, 2, 1, 0, 255, 248, + 224, 171, 97, 30, 4, 1, 0, 255, + 254, 236, 173, 95, 37, 7, 1, 0 +}; + +const opus_uint8 silk_NLSF_CB2_BITS_NB_MB_Q5[ 72 ] = { + 255, 255, 255, 131, 6, 145, 255, 255, + 255, 255, 255, 236, 93, 15, 96, 255, + 255, 255, 255, 255, 194, 83, 25, 71, + 221, 255, 255, 255, 255, 162, 73, 34, + 66, 162, 255, 255, 255, 210, 126, 73, + 43, 57, 173, 255, 255, 255, 201, 125, + 71, 48, 58, 130, 255, 255, 255, 166, + 110, 73, 57, 62, 104, 210, 255, 255, + 251, 123, 65, 55, 68, 100, 171, 255 +}; + +const opus_uint8 silk_NLSF_PRED_NB_MB_Q8[ 18 ] = { + 179, 138, 140, 148, 151, 149, 153, 151, + 163, 116, 67, 82, 59, 92, 72, 100, + 89, 92 +}; + +const opus_int16 silk_NLSF_DELTA_MIN_NB_MB_Q15[ 11 ] = { + 250, 3, 6, 3, 3, 3, 4, 3, + 3, 3, 461 +}; + +const silk_NLSF_CB_struct silk_NLSF_CB_NB_MB = +{ + 32, + 10, + SILK_FIX_CONST( 0.18, 16 ), + SILK_FIX_CONST( 1.0 / 0.18, 6 ), + silk_NLSF_CB1_NB_MB_Q8, + silk_NLSF_CB1_iCDF_NB_MB, + silk_NLSF_PRED_NB_MB_Q8, + silk_NLSF_CB2_SELECT_NB_MB, + silk_NLSF_CB2_iCDF_NB_MB, + silk_NLSF_CB2_BITS_NB_MB_Q5, + silk_NLSF_DELTA_MIN_NB_MB_Q15, +}; diff --git a/silk/silk_tables_NLSF_CB_WB.c b/silk/silk_tables_NLSF_CB_WB.c index 06a95b55c..d00f6ab49 100644 --- a/silk/silk_tables_NLSF_CB_WB.c +++ b/silk/silk_tables_NLSF_CB_WB.c @@ -1,194 +1,194 @@ -/*********************************************************************** -Copyright (c) 2006-2011, Skype Limited. All rights reserved. -Redistribution and use in source and binary forms, with or without -modification, (subject to the limitations in the disclaimer below) -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 Skype Limited, nor the names of specific -contributors, may be used to endorse or promote products derived from -this software without specific prior written permission. -NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED -BY THIS LICENSE. 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. -***********************************************************************/ - -#include "silk_structs.h" - -const opus_uint8 silk_NLSF_CB1_WB_Q8[ 512 ] = { - 7, 23, 38, 54, 69, 85, 100, 116, - 131, 147, 162, 178, 193, 208, 223, 239, - 13, 25, 41, 55, 69, 83, 98, 112, - 127, 142, 157, 171, 187, 203, 220, 236, - 15, 21, 34, 51, 61, 78, 92, 106, - 126, 136, 152, 167, 185, 205, 225, 240, - 10, 21, 36, 50, 63, 79, 95, 110, - 126, 141, 157, 173, 189, 205, 221, 237, - 17, 20, 37, 51, 59, 78, 89, 107, - 123, 134, 150, 164, 184, 205, 224, 240, - 10, 15, 32, 51, 67, 81, 96, 112, - 129, 142, 158, 173, 189, 204, 220, 236, - 8, 21, 37, 51, 65, 79, 98, 113, - 126, 138, 155, 168, 179, 192, 209, 218, - 12, 15, 34, 55, 63, 78, 87, 108, - 118, 131, 148, 167, 185, 203, 219, 236, - 16, 19, 32, 36, 56, 79, 91, 108, - 118, 136, 154, 171, 186, 204, 220, 237, - 11, 28, 43, 58, 74, 89, 105, 120, - 135, 150, 165, 180, 196, 211, 226, 241, - 6, 16, 33, 46, 60, 75, 92, 107, - 123, 137, 156, 169, 185, 199, 214, 225, - 11, 19, 30, 44, 57, 74, 89, 105, - 121, 135, 152, 169, 186, 202, 218, 234, - 12, 19, 29, 46, 57, 71, 88, 100, - 120, 132, 148, 165, 182, 199, 216, 233, - 17, 23, 35, 46, 56, 77, 92, 106, - 123, 134, 152, 167, 185, 204, 222, 237, - 14, 17, 45, 53, 63, 75, 89, 107, - 115, 132, 151, 171, 188, 206, 221, 240, - 9, 16, 29, 40, 56, 71, 88, 103, - 119, 137, 154, 171, 189, 205, 222, 237, - 16, 19, 36, 48, 57, 76, 87, 105, - 118, 132, 150, 167, 185, 202, 218, 236, - 12, 17, 29, 54, 71, 81, 94, 104, - 126, 136, 149, 164, 182, 201, 221, 237, - 15, 28, 47, 62, 79, 97, 115, 129, - 142, 155, 168, 180, 194, 208, 223, 238, - 8, 14, 30, 45, 62, 78, 94, 111, - 127, 143, 159, 175, 192, 207, 223, 239, - 17, 30, 49, 62, 79, 92, 107, 119, - 132, 145, 160, 174, 190, 204, 220, 235, - 14, 19, 36, 45, 61, 76, 91, 108, - 121, 138, 154, 172, 189, 205, 222, 238, - 12, 18, 31, 45, 60, 76, 91, 107, - 123, 138, 154, 171, 187, 204, 221, 236, - 13, 17, 31, 43, 53, 70, 83, 103, - 114, 131, 149, 167, 185, 203, 220, 237, - 17, 22, 35, 42, 58, 78, 93, 110, - 125, 139, 155, 170, 188, 206, 224, 240, - 8, 15, 34, 50, 67, 83, 99, 115, - 131, 146, 162, 178, 193, 209, 224, 239, - 13, 16, 41, 66, 73, 86, 95, 111, - 128, 137, 150, 163, 183, 206, 225, 241, - 17, 25, 37, 52, 63, 75, 92, 102, - 119, 132, 144, 160, 175, 191, 212, 231, - 19, 31, 49, 65, 83, 100, 117, 133, - 147, 161, 174, 187, 200, 213, 227, 242, - 18, 31, 52, 68, 88, 103, 117, 126, - 138, 149, 163, 177, 192, 207, 223, 239, - 16, 29, 47, 61, 76, 90, 106, 119, - 133, 147, 161, 176, 193, 209, 224, 240, - 15, 21, 35, 50, 61, 73, 86, 97, - 110, 119, 129, 141, 175, 198, 218, 237 -}; - -const opus_uint8 silk_NLSF_CB1_iCDF_WB[ 64 ] = { - 225, 204, 201, 184, 183, 175, 158, 154, - 153, 135, 119, 115, 113, 110, 109, 99, - 98, 95, 79, 68, 52, 50, 48, 45, - 43, 32, 31, 27, 18, 10, 3, 0, - 255, 251, 235, 230, 212, 201, 196, 182, - 167, 166, 163, 151, 138, 124, 110, 104, - 90, 78, 76, 70, 69, 57, 45, 34, - 24, 21, 11, 6, 5, 4, 3, 0 -}; - -const opus_uint8 silk_NLSF_CB2_SELECT_WB[ 256 ] = { - 0, 0, 0, 0, 0, 0, 0, 1, - 100, 102, 102, 68, 68, 36, 34, 96, - 164, 107, 158, 185, 180, 185, 139, 102, - 64, 66, 36, 34, 34, 0, 1, 32, - 208, 139, 141, 191, 152, 185, 155, 104, - 96, 171, 104, 166, 102, 102, 102, 132, - 1, 0, 0, 0, 0, 16, 16, 0, - 80, 109, 78, 107, 185, 139, 103, 101, - 208, 212, 141, 139, 173, 153, 123, 103, - 36, 0, 0, 0, 0, 0, 0, 1, - 48, 0, 0, 0, 0, 0, 0, 32, - 68, 135, 123, 119, 119, 103, 69, 98, - 68, 103, 120, 118, 118, 102, 71, 98, - 134, 136, 157, 184, 182, 153, 139, 134, - 208, 168, 248, 75, 189, 143, 121, 107, - 32, 49, 34, 34, 34, 0, 17, 2, - 210, 235, 139, 123, 185, 137, 105, 134, - 98, 135, 104, 182, 100, 183, 171, 134, - 100, 70, 68, 70, 66, 66, 34, 131, - 64, 166, 102, 68, 36, 2, 1, 0, - 134, 166, 102, 68, 34, 34, 66, 132, - 212, 246, 158, 139, 107, 107, 87, 102, - 100, 219, 125, 122, 137, 118, 103, 132, - 114, 135, 137, 105, 171, 106, 50, 34, - 164, 214, 141, 143, 185, 151, 121, 103, - 192, 34, 0, 0, 0, 0, 0, 1, - 208, 109, 74, 187, 134, 249, 159, 137, - 102, 110, 154, 118, 87, 101, 119, 101, - 0, 2, 0, 36, 36, 66, 68, 35, - 96, 164, 102, 100, 36, 0, 2, 33, - 167, 138, 174, 102, 100, 84, 2, 2, - 100, 107, 120, 119, 36, 197, 24, 0 -}; - -const opus_uint8 silk_NLSF_CB2_iCDF_WB[ 72 ] = { - 255, 254, 253, 244, 12, 3, 2, 1, - 0, 255, 254, 252, 224, 38, 3, 2, - 1, 0, 255, 254, 251, 209, 57, 4, - 2, 1, 0, 255, 254, 244, 195, 69, - 4, 2, 1, 0, 255, 251, 232, 184, - 84, 7, 2, 1, 0, 255, 254, 240, - 186, 86, 14, 2, 1, 0, 255, 254, - 239, 178, 91, 30, 5, 1, 0, 255, - 248, 227, 177, 100, 19, 2, 1, 0 -}; - -const opus_uint8 silk_NLSF_CB2_BITS_WB_Q5[ 72 ] = { - 255, 255, 255, 156, 4, 154, 255, 255, - 255, 255, 255, 227, 102, 15, 92, 255, - 255, 255, 255, 255, 213, 83, 24, 72, - 236, 255, 255, 255, 255, 150, 76, 33, - 63, 214, 255, 255, 255, 190, 121, 77, - 43, 55, 185, 255, 255, 255, 245, 137, - 71, 43, 59, 139, 255, 255, 255, 255, - 131, 66, 50, 66, 107, 194, 255, 255, - 166, 116, 76, 55, 53, 125, 255, 255 -}; - -const opus_uint8 silk_NLSF_PRED_WB_Q8[ 30 ] = { - 175, 148, 160, 176, 178, 173, 174, 164, - 177, 174, 196, 182, 198, 192, 182, 68, - 62, 66, 60, 72, 117, 85, 90, 118, - 136, 151, 142, 160, 142, 155 -}; - -const opus_int16 silk_NLSF_DELTA_MIN_WB_Q15[ 17 ] = { - 100, 3, 40, 3, 3, 3, 5, 14, - 14, 10, 11, 3, 8, 9, 7, 3, - 347 -}; - -const silk_NLSF_CB_struct silk_NLSF_CB_WB = -{ - 32, - 16, - SILK_FIX_CONST( 0.15, 16 ), - SILK_FIX_CONST( 1.0 / 0.15, 6 ), - silk_NLSF_CB1_WB_Q8, - silk_NLSF_CB1_iCDF_WB, - silk_NLSF_PRED_WB_Q8, - silk_NLSF_CB2_SELECT_WB, - silk_NLSF_CB2_iCDF_WB, - silk_NLSF_CB2_BITS_WB_Q5, - silk_NLSF_DELTA_MIN_WB_Q15, -}; - +/*********************************************************************** +Copyright (c) 2006-2011, Skype Limited. All rights reserved. +Redistribution and use in source and binary forms, with or without +modification, (subject to the limitations in the disclaimer below) +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 Skype Limited, nor the names of specific +contributors, may be used to endorse or promote products derived from +this software without specific prior written permission. +NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED +BY THIS LICENSE. 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. +***********************************************************************/ + +#include "silk_structs.h" + +const opus_uint8 silk_NLSF_CB1_WB_Q8[ 512 ] = { + 7, 23, 38, 54, 69, 85, 100, 116, + 131, 147, 162, 178, 193, 208, 223, 239, + 13, 25, 41, 55, 69, 83, 98, 112, + 127, 142, 157, 171, 187, 203, 220, 236, + 15, 21, 34, 51, 61, 78, 92, 106, + 126, 136, 152, 167, 185, 205, 225, 240, + 10, 21, 36, 50, 63, 79, 95, 110, + 126, 141, 157, 173, 189, 205, 221, 237, + 17, 20, 37, 51, 59, 78, 89, 107, + 123, 134, 150, 164, 184, 205, 224, 240, + 10, 15, 32, 51, 67, 81, 96, 112, + 129, 142, 158, 173, 189, 204, 220, 236, + 8, 21, 37, 51, 65, 79, 98, 113, + 126, 138, 155, 168, 179, 192, 209, 218, + 12, 15, 34, 55, 63, 78, 87, 108, + 118, 131, 148, 167, 185, 203, 219, 236, + 16, 19, 32, 36, 56, 79, 91, 108, + 118, 136, 154, 171, 186, 204, 220, 237, + 11, 28, 43, 58, 74, 89, 105, 120, + 135, 150, 165, 180, 196, 211, 226, 241, + 6, 16, 33, 46, 60, 75, 92, 107, + 123, 137, 156, 169, 185, 199, 214, 225, + 11, 19, 30, 44, 57, 74, 89, 105, + 121, 135, 152, 169, 186, 202, 218, 234, + 12, 19, 29, 46, 57, 71, 88, 100, + 120, 132, 148, 165, 182, 199, 216, 233, + 17, 23, 35, 46, 56, 77, 92, 106, + 123, 134, 152, 167, 185, 204, 222, 237, + 14, 17, 45, 53, 63, 75, 89, 107, + 115, 132, 151, 171, 188, 206, 221, 240, + 9, 16, 29, 40, 56, 71, 88, 103, + 119, 137, 154, 171, 189, 205, 222, 237, + 16, 19, 36, 48, 57, 76, 87, 105, + 118, 132, 150, 167, 185, 202, 218, 236, + 12, 17, 29, 54, 71, 81, 94, 104, + 126, 136, 149, 164, 182, 201, 221, 237, + 15, 28, 47, 62, 79, 97, 115, 129, + 142, 155, 168, 180, 194, 208, 223, 238, + 8, 14, 30, 45, 62, 78, 94, 111, + 127, 143, 159, 175, 192, 207, 223, 239, + 17, 30, 49, 62, 79, 92, 107, 119, + 132, 145, 160, 174, 190, 204, 220, 235, + 14, 19, 36, 45, 61, 76, 91, 108, + 121, 138, 154, 172, 189, 205, 222, 238, + 12, 18, 31, 45, 60, 76, 91, 107, + 123, 138, 154, 171, 187, 204, 221, 236, + 13, 17, 31, 43, 53, 70, 83, 103, + 114, 131, 149, 167, 185, 203, 220, 237, + 17, 22, 35, 42, 58, 78, 93, 110, + 125, 139, 155, 170, 188, 206, 224, 240, + 8, 15, 34, 50, 67, 83, 99, 115, + 131, 146, 162, 178, 193, 209, 224, 239, + 13, 16, 41, 66, 73, 86, 95, 111, + 128, 137, 150, 163, 183, 206, 225, 241, + 17, 25, 37, 52, 63, 75, 92, 102, + 119, 132, 144, 160, 175, 191, 212, 231, + 19, 31, 49, 65, 83, 100, 117, 133, + 147, 161, 174, 187, 200, 213, 227, 242, + 18, 31, 52, 68, 88, 103, 117, 126, + 138, 149, 163, 177, 192, 207, 223, 239, + 16, 29, 47, 61, 76, 90, 106, 119, + 133, 147, 161, 176, 193, 209, 224, 240, + 15, 21, 35, 50, 61, 73, 86, 97, + 110, 119, 129, 141, 175, 198, 218, 237 +}; + +const opus_uint8 silk_NLSF_CB1_iCDF_WB[ 64 ] = { + 225, 204, 201, 184, 183, 175, 158, 154, + 153, 135, 119, 115, 113, 110, 109, 99, + 98, 95, 79, 68, 52, 50, 48, 45, + 43, 32, 31, 27, 18, 10, 3, 0, + 255, 251, 235, 230, 212, 201, 196, 182, + 167, 166, 163, 151, 138, 124, 110, 104, + 90, 78, 76, 70, 69, 57, 45, 34, + 24, 21, 11, 6, 5, 4, 3, 0 +}; + +const opus_uint8 silk_NLSF_CB2_SELECT_WB[ 256 ] = { + 0, 0, 0, 0, 0, 0, 0, 1, + 100, 102, 102, 68, 68, 36, 34, 96, + 164, 107, 158, 185, 180, 185, 139, 102, + 64, 66, 36, 34, 34, 0, 1, 32, + 208, 139, 141, 191, 152, 185, 155, 104, + 96, 171, 104, 166, 102, 102, 102, 132, + 1, 0, 0, 0, 0, 16, 16, 0, + 80, 109, 78, 107, 185, 139, 103, 101, + 208, 212, 141, 139, 173, 153, 123, 103, + 36, 0, 0, 0, 0, 0, 0, 1, + 48, 0, 0, 0, 0, 0, 0, 32, + 68, 135, 123, 119, 119, 103, 69, 98, + 68, 103, 120, 118, 118, 102, 71, 98, + 134, 136, 157, 184, 182, 153, 139, 134, + 208, 168, 248, 75, 189, 143, 121, 107, + 32, 49, 34, 34, 34, 0, 17, 2, + 210, 235, 139, 123, 185, 137, 105, 134, + 98, 135, 104, 182, 100, 183, 171, 134, + 100, 70, 68, 70, 66, 66, 34, 131, + 64, 166, 102, 68, 36, 2, 1, 0, + 134, 166, 102, 68, 34, 34, 66, 132, + 212, 246, 158, 139, 107, 107, 87, 102, + 100, 219, 125, 122, 137, 118, 103, 132, + 114, 135, 137, 105, 171, 106, 50, 34, + 164, 214, 141, 143, 185, 151, 121, 103, + 192, 34, 0, 0, 0, 0, 0, 1, + 208, 109, 74, 187, 134, 249, 159, 137, + 102, 110, 154, 118, 87, 101, 119, 101, + 0, 2, 0, 36, 36, 66, 68, 35, + 96, 164, 102, 100, 36, 0, 2, 33, + 167, 138, 174, 102, 100, 84, 2, 2, + 100, 107, 120, 119, 36, 197, 24, 0 +}; + +const opus_uint8 silk_NLSF_CB2_iCDF_WB[ 72 ] = { + 255, 254, 253, 244, 12, 3, 2, 1, + 0, 255, 254, 252, 224, 38, 3, 2, + 1, 0, 255, 254, 251, 209, 57, 4, + 2, 1, 0, 255, 254, 244, 195, 69, + 4, 2, 1, 0, 255, 251, 232, 184, + 84, 7, 2, 1, 0, 255, 254, 240, + 186, 86, 14, 2, 1, 0, 255, 254, + 239, 178, 91, 30, 5, 1, 0, 255, + 248, 227, 177, 100, 19, 2, 1, 0 +}; + +const opus_uint8 silk_NLSF_CB2_BITS_WB_Q5[ 72 ] = { + 255, 255, 255, 156, 4, 154, 255, 255, + 255, 255, 255, 227, 102, 15, 92, 255, + 255, 255, 255, 255, 213, 83, 24, 72, + 236, 255, 255, 255, 255, 150, 76, 33, + 63, 214, 255, 255, 255, 190, 121, 77, + 43, 55, 185, 255, 255, 255, 245, 137, + 71, 43, 59, 139, 255, 255, 255, 255, + 131, 66, 50, 66, 107, 194, 255, 255, + 166, 116, 76, 55, 53, 125, 255, 255 +}; + +const opus_uint8 silk_NLSF_PRED_WB_Q8[ 30 ] = { + 175, 148, 160, 176, 178, 173, 174, 164, + 177, 174, 196, 182, 198, 192, 182, 68, + 62, 66, 60, 72, 117, 85, 90, 118, + 136, 151, 142, 160, 142, 155 +}; + +const opus_int16 silk_NLSF_DELTA_MIN_WB_Q15[ 17 ] = { + 100, 3, 40, 3, 3, 3, 5, 14, + 14, 10, 11, 3, 8, 9, 7, 3, + 347 +}; + +const silk_NLSF_CB_struct silk_NLSF_CB_WB = +{ + 32, + 16, + SILK_FIX_CONST( 0.15, 16 ), + SILK_FIX_CONST( 1.0 / 0.15, 6 ), + silk_NLSF_CB1_WB_Q8, + silk_NLSF_CB1_iCDF_WB, + silk_NLSF_PRED_WB_Q8, + silk_NLSF_CB2_SELECT_WB, + silk_NLSF_CB2_iCDF_WB, + silk_NLSF_CB2_BITS_WB_Q5, + silk_NLSF_DELTA_MIN_WB_Q15, +}; + diff --git a/silk/silk_tables_gain.c b/silk/silk_tables_gain.c index cda087a1d..eb45ca1cd 100644 --- a/silk/silk_tables_gain.c +++ b/silk/silk_tables_gain.c @@ -1,59 +1,59 @@ -/*********************************************************************** -Copyright (c) 2006-2011, Skype Limited. All rights reserved. -Redistribution and use in source and binary forms, with or without -modification, (subject to the limitations in the disclaimer below) -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 Skype Limited, nor the names of specific -contributors, may be used to endorse or promote products derived from -this software without specific prior written permission. -NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED -BY THIS LICENSE. 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. -***********************************************************************/ - -#include "silk_tables.h" - -#ifdef __cplusplus -extern "C" -{ -#endif - -const opus_uint8 silk_gain_iCDF[ 3 ][ N_LEVELS_QGAIN / 8 ] = -{ -{ - 224, 112, 44, 15, 3, 2, 1, 0 -}, -{ - 254, 237, 192, 132, 70, 23, 4, 0 -}, -{ - 255, 252, 226, 155, 61, 11, 2, 0 -} -}; - -const opus_uint8 silk_delta_gain_iCDF[ MAX_DELTA_GAIN_QUANT - MIN_DELTA_GAIN_QUANT + 1 ] = { - 250, 245, 234, 203, 71, 50, 42, 38, - 35, 33, 31, 29, 28, 27, 26, 25, - 24, 23, 22, 21, 20, 19, 18, 17, - 16, 15, 14, 13, 12, 11, 10, 9, - 8, 7, 6, 5, 4, 3, 2, 1, - 0 -}; - -#ifdef __cplusplus -} -#endif +/*********************************************************************** +Copyright (c) 2006-2011, Skype Limited. All rights reserved. +Redistribution and use in source and binary forms, with or without +modification, (subject to the limitations in the disclaimer below) +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 Skype Limited, nor the names of specific +contributors, may be used to endorse or promote products derived from +this software without specific prior written permission. +NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED +BY THIS LICENSE. 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. +***********************************************************************/ + +#include "silk_tables.h" + +#ifdef __cplusplus +extern "C" +{ +#endif + +const opus_uint8 silk_gain_iCDF[ 3 ][ N_LEVELS_QGAIN / 8 ] = +{ +{ + 224, 112, 44, 15, 3, 2, 1, 0 +}, +{ + 254, 237, 192, 132, 70, 23, 4, 0 +}, +{ + 255, 252, 226, 155, 61, 11, 2, 0 +} +}; + +const opus_uint8 silk_delta_gain_iCDF[ MAX_DELTA_GAIN_QUANT - MIN_DELTA_GAIN_QUANT + 1 ] = { + 250, 245, 234, 203, 71, 50, 42, 38, + 35, 33, 31, 29, 28, 27, 26, 25, + 24, 23, 22, 21, 20, 19, 18, 17, + 16, 15, 14, 13, 12, 11, 10, 9, + 8, 7, 6, 5, 4, 3, 2, 1, + 0 +}; + +#ifdef __cplusplus +} +#endif diff --git a/silk/silk_tables_other.c b/silk/silk_tables_other.c index b7d3ad9d3..29380c5ca 100644 --- a/silk/silk_tables_other.c +++ b/silk/silk_tables_other.c @@ -1,134 +1,134 @@ -/*********************************************************************** -Copyright (c) 2006-2011, Skype Limited. All rights reserved. -Redistribution and use in source and binary forms, with or without -modification, (subject to the limitations in the disclaimer below) -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 Skype Limited, nor the names of specific -contributors, may be used to endorse or promote products derived from -this software without specific prior written permission. -NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED -BY THIS LICENSE. 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. -***********************************************************************/ - -#include "silk_structs.h" -#include "silk_define.h" -#include "silk_tables.h" - -#ifdef __cplusplus -extern "C" -{ -#endif - -/* Piece-wise linear mapping from bitrate in kbps to coding quality in dB SNR */ -const opus_int32 silk_TargetRate_table_NB[ TARGET_RATE_TAB_SZ ] = { - 0, 8000, 9400, 11500, 13500, 17500, 25000, MAX_TARGET_RATE_BPS -}; -const opus_int32 silk_TargetRate_table_MB[ TARGET_RATE_TAB_SZ ] = { - 0, 9000, 12000, 14500, 18500, 24500, 35500, MAX_TARGET_RATE_BPS -}; -const opus_int32 silk_TargetRate_table_WB[ TARGET_RATE_TAB_SZ ] = { - 0, 10500, 14000, 17000, 21500, 28500, 42000, MAX_TARGET_RATE_BPS -}; -const opus_int16 silk_SNR_table_Q1[ TARGET_RATE_TAB_SZ ] = { - 19, 29, 35, 39, 44, 50, 60, 80 -}; - -/* Tables for stereo predictor coding */ -const opus_int16 silk_stereo_pred_quant_Q13[ STEREO_QUANT_TAB_SIZE ] = { - -13732, -10050, -8266, -7526, -6500, -5000, -2950, -820, - 820, 2950, 5000, 6500, 7526, 8266, 10050, 13732 -}; -const opus_uint8 silk_stereo_pred_joint_iCDF[ 25 ] = { - 249, 247, 246, 245, 244, - 234, 210, 202, 201, 200, - 197, 174, 82, 59, 56, - 55, 54, 46, 22, 12, - 11, 10, 9, 7, 0 -}; -const opus_uint8 silk_stereo_only_code_mid_iCDF[ 2 ] = { 64, 0 }; - -/* Tables for LBRR flags */ -const opus_uint8 silk_LBRR_flags_2_iCDF[ 3 ] = { 203, 150, 0 }; -const opus_uint8 silk_LBRR_flags_3_iCDF[ 7 ] = { 215, 195, 166, 125, 110, 82, 0 }; -const opus_uint8 * const silk_LBRR_flags_iCDF_ptr[ 2 ] = { - silk_LBRR_flags_2_iCDF, - silk_LBRR_flags_3_iCDF -}; - -/* Table for LSB coding */ -const opus_uint8 silk_lsb_iCDF[ 2 ] = { 120, 0 }; - -/* Tables for LTPScale */ -const opus_uint8 silk_LTPscale_iCDF[ 3 ] = { 128, 64, 0 }; - -/* Tables for signal type and offset coding */ -const opus_uint8 silk_type_offset_VAD_iCDF[ 4 ] = { - 232, 158, 10, 0 -}; -const opus_uint8 silk_type_offset_no_VAD_iCDF[ 2 ] = { - 230, 0 -}; - -/* Tables for NLSF interpolation factor */ -const opus_uint8 silk_NLSF_interpolation_factor_iCDF[ 5 ] = { 243, 221, 192, 181, 0 }; - -/* Quantization offsets */ -const opus_int16 silk_Quantization_Offsets_Q10[ 2 ][ 2 ] = { - { OFFSET_UVL_Q10, OFFSET_UVH_Q10 }, { OFFSET_VL_Q10, OFFSET_VH_Q10 } -}; - -/* Table for LTPScale */ -const opus_int16 silk_LTPScales_table_Q14[ 3 ] = { 15565, 12288, 8192 }; - -/* Uniform entropy tables */ -const opus_uint8 silk_uniform3_iCDF[ 3 ] = { 171, 85, 0 }; -const opus_uint8 silk_uniform4_iCDF[ 4 ] = { 192, 128, 64, 0 }; -const opus_uint8 silk_uniform5_iCDF[ 5 ] = { 205, 154, 102, 51, 0 }; -const opus_uint8 silk_uniform6_iCDF[ 6 ] = { 213, 171, 128, 85, 43, 0 }; -const opus_uint8 silk_uniform8_iCDF[ 8 ] = { 224, 192, 160, 128, 96, 64, 32, 0 }; - -const opus_uint8 silk_NLSF_EXT_iCDF[ 7 ] = { 100, 40, 16, 7, 3, 1, 0 }; - -/* Elliptic/Cauer filters designed with 0.1 dB passband ripple, - 80 dB minimum stopband attenuation, and - [0.95 : 0.15 : 0.35] normalized cut off frequencies. */ - -/* Interpolation points for filter coefficients used in the bandwidth transition smoother */ -const opus_int32 silk_Transition_LP_B_Q28[ TRANSITION_INT_NUM ][ TRANSITION_NB ] = -{ -{ 250767114, 501534038, 250767114 }, -{ 209867381, 419732057, 209867381 }, -{ 170987846, 341967853, 170987846 }, -{ 131531482, 263046905, 131531482 }, -{ 89306658, 178584282, 89306658 } -}; - -/* Interpolation points for filter coefficients used in the bandwidth transition smoother */ -const opus_int32 silk_Transition_LP_A_Q28[ TRANSITION_INT_NUM ][ TRANSITION_NA ] = -{ -{ 506393414, 239854379 }, -{ 411067935, 169683996 }, -{ 306733530, 116694253 }, -{ 185807084, 77959395 }, -{ 35497197, 57401098 } -}; - -#ifdef __cplusplus -} -#endif - +/*********************************************************************** +Copyright (c) 2006-2011, Skype Limited. All rights reserved. +Redistribution and use in source and binary forms, with or without +modification, (subject to the limitations in the disclaimer below) +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 Skype Limited, nor the names of specific +contributors, may be used to endorse or promote products derived from +this software without specific prior written permission. +NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED +BY THIS LICENSE. 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. +***********************************************************************/ + +#include "silk_structs.h" +#include "silk_define.h" +#include "silk_tables.h" + +#ifdef __cplusplus +extern "C" +{ +#endif + +/* Piece-wise linear mapping from bitrate in kbps to coding quality in dB SNR */ +const opus_int32 silk_TargetRate_table_NB[ TARGET_RATE_TAB_SZ ] = { + 0, 8000, 9400, 11500, 13500, 17500, 25000, MAX_TARGET_RATE_BPS +}; +const opus_int32 silk_TargetRate_table_MB[ TARGET_RATE_TAB_SZ ] = { + 0, 9000, 12000, 14500, 18500, 24500, 35500, MAX_TARGET_RATE_BPS +}; +const opus_int32 silk_TargetRate_table_WB[ TARGET_RATE_TAB_SZ ] = { + 0, 10500, 14000, 17000, 21500, 28500, 42000, MAX_TARGET_RATE_BPS +}; +const opus_int16 silk_SNR_table_Q1[ TARGET_RATE_TAB_SZ ] = { + 19, 29, 35, 39, 44, 50, 60, 80 +}; + +/* Tables for stereo predictor coding */ +const opus_int16 silk_stereo_pred_quant_Q13[ STEREO_QUANT_TAB_SIZE ] = { + -13732, -10050, -8266, -7526, -6500, -5000, -2950, -820, + 820, 2950, 5000, 6500, 7526, 8266, 10050, 13732 +}; +const opus_uint8 silk_stereo_pred_joint_iCDF[ 25 ] = { + 249, 247, 246, 245, 244, + 234, 210, 202, 201, 200, + 197, 174, 82, 59, 56, + 55, 54, 46, 22, 12, + 11, 10, 9, 7, 0 +}; +const opus_uint8 silk_stereo_only_code_mid_iCDF[ 2 ] = { 64, 0 }; + +/* Tables for LBRR flags */ +const opus_uint8 silk_LBRR_flags_2_iCDF[ 3 ] = { 203, 150, 0 }; +const opus_uint8 silk_LBRR_flags_3_iCDF[ 7 ] = { 215, 195, 166, 125, 110, 82, 0 }; +const opus_uint8 * const silk_LBRR_flags_iCDF_ptr[ 2 ] = { + silk_LBRR_flags_2_iCDF, + silk_LBRR_flags_3_iCDF +}; + +/* Table for LSB coding */ +const opus_uint8 silk_lsb_iCDF[ 2 ] = { 120, 0 }; + +/* Tables for LTPScale */ +const opus_uint8 silk_LTPscale_iCDF[ 3 ] = { 128, 64, 0 }; + +/* Tables for signal type and offset coding */ +const opus_uint8 silk_type_offset_VAD_iCDF[ 4 ] = { + 232, 158, 10, 0 +}; +const opus_uint8 silk_type_offset_no_VAD_iCDF[ 2 ] = { + 230, 0 +}; + +/* Tables for NLSF interpolation factor */ +const opus_uint8 silk_NLSF_interpolation_factor_iCDF[ 5 ] = { 243, 221, 192, 181, 0 }; + +/* Quantization offsets */ +const opus_int16 silk_Quantization_Offsets_Q10[ 2 ][ 2 ] = { + { OFFSET_UVL_Q10, OFFSET_UVH_Q10 }, { OFFSET_VL_Q10, OFFSET_VH_Q10 } +}; + +/* Table for LTPScale */ +const opus_int16 silk_LTPScales_table_Q14[ 3 ] = { 15565, 12288, 8192 }; + +/* Uniform entropy tables */ +const opus_uint8 silk_uniform3_iCDF[ 3 ] = { 171, 85, 0 }; +const opus_uint8 silk_uniform4_iCDF[ 4 ] = { 192, 128, 64, 0 }; +const opus_uint8 silk_uniform5_iCDF[ 5 ] = { 205, 154, 102, 51, 0 }; +const opus_uint8 silk_uniform6_iCDF[ 6 ] = { 213, 171, 128, 85, 43, 0 }; +const opus_uint8 silk_uniform8_iCDF[ 8 ] = { 224, 192, 160, 128, 96, 64, 32, 0 }; + +const opus_uint8 silk_NLSF_EXT_iCDF[ 7 ] = { 100, 40, 16, 7, 3, 1, 0 }; + +/* Elliptic/Cauer filters designed with 0.1 dB passband ripple, + 80 dB minimum stopband attenuation, and + [0.95 : 0.15 : 0.35] normalized cut off frequencies. */ + +/* Interpolation points for filter coefficients used in the bandwidth transition smoother */ +const opus_int32 silk_Transition_LP_B_Q28[ TRANSITION_INT_NUM ][ TRANSITION_NB ] = +{ +{ 250767114, 501534038, 250767114 }, +{ 209867381, 419732057, 209867381 }, +{ 170987846, 341967853, 170987846 }, +{ 131531482, 263046905, 131531482 }, +{ 89306658, 178584282, 89306658 } +}; + +/* Interpolation points for filter coefficients used in the bandwidth transition smoother */ +const opus_int32 silk_Transition_LP_A_Q28[ TRANSITION_INT_NUM ][ TRANSITION_NA ] = +{ +{ 506393414, 239854379 }, +{ 411067935, 169683996 }, +{ 306733530, 116694253 }, +{ 185807084, 77959395 }, +{ 35497197, 57401098 } +}; + +#ifdef __cplusplus +} +#endif + diff --git a/silk/silk_tables_pitch_lag.c b/silk/silk_tables_pitch_lag.c index f534df53d..09d269d3b 100644 --- a/silk/silk_tables_pitch_lag.c +++ b/silk/silk_tables_pitch_lag.c @@ -1,65 +1,65 @@ -/*********************************************************************** -Copyright (c) 2006-2011, Skype Limited. All rights reserved. -Redistribution and use in source and binary forms, with or without -modification, (subject to the limitations in the disclaimer below) -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 Skype Limited, nor the names of specific -contributors, may be used to endorse or promote products derived from -this software without specific prior written permission. -NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED -BY THIS LICENSE. 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. -***********************************************************************/ - -#include "silk_tables.h" - -const opus_uint8 silk_pitch_lag_iCDF[ 2 * ( PITCH_EST_MAX_LAG_MS - PITCH_EST_MIN_LAG_MS ) ] = { - 253, 250, 244, 233, 212, 182, 150, 131, - 120, 110, 98, 85, 72, 60, 49, 40, - 32, 25, 19, 15, 13, 11, 9, 8, - 7, 6, 5, 4, 3, 2, 1, 0 -}; - -const opus_uint8 silk_pitch_delta_iCDF[21] = { - 210, 208, 206, 203, 199, 193, 183, 168, - 142, 104, 74, 52, 37, 27, 20, 14, - 10, 6, 4, 2, 0 -}; - -const opus_uint8 silk_pitch_contour_iCDF[34] = { - 223, 201, 183, 167, 152, 138, 124, 111, - 98, 88, 79, 70, 62, 56, 50, 44, - 39, 35, 31, 27, 24, 21, 18, 16, - 14, 12, 10, 8, 6, 4, 3, 2, - 1, 0 -}; - -const opus_uint8 silk_pitch_contour_NB_iCDF[11] = { - 188, 176, 155, 138, 119, 97, 67, 43, - 26, 10, 0 -}; - -const opus_uint8 silk_pitch_contour_10_ms_iCDF[12] = { - 165, 119, 80, 61, 47, 35, 27, 20, - 14, 9, 4, 0 -}; - -const opus_uint8 silk_pitch_contour_10_ms_NB_iCDF[3] = { - 113, 63, 0 -}; - - +/*********************************************************************** +Copyright (c) 2006-2011, Skype Limited. All rights reserved. +Redistribution and use in source and binary forms, with or without +modification, (subject to the limitations in the disclaimer below) +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 Skype Limited, nor the names of specific +contributors, may be used to endorse or promote products derived from +this software without specific prior written permission. +NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED +BY THIS LICENSE. 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. +***********************************************************************/ + +#include "silk_tables.h" + +const opus_uint8 silk_pitch_lag_iCDF[ 2 * ( PITCH_EST_MAX_LAG_MS - PITCH_EST_MIN_LAG_MS ) ] = { + 253, 250, 244, 233, 212, 182, 150, 131, + 120, 110, 98, 85, 72, 60, 49, 40, + 32, 25, 19, 15, 13, 11, 9, 8, + 7, 6, 5, 4, 3, 2, 1, 0 +}; + +const opus_uint8 silk_pitch_delta_iCDF[21] = { + 210, 208, 206, 203, 199, 193, 183, 168, + 142, 104, 74, 52, 37, 27, 20, 14, + 10, 6, 4, 2, 0 +}; + +const opus_uint8 silk_pitch_contour_iCDF[34] = { + 223, 201, 183, 167, 152, 138, 124, 111, + 98, 88, 79, 70, 62, 56, 50, 44, + 39, 35, 31, 27, 24, 21, 18, 16, + 14, 12, 10, 8, 6, 4, 3, 2, + 1, 0 +}; + +const opus_uint8 silk_pitch_contour_NB_iCDF[11] = { + 188, 176, 155, 138, 119, 97, 67, 43, + 26, 10, 0 +}; + +const opus_uint8 silk_pitch_contour_10_ms_iCDF[12] = { + 165, 119, 80, 61, 47, 35, 27, 20, + 14, 9, 4, 0 +}; + +const opus_uint8 silk_pitch_contour_10_ms_NB_iCDF[3] = { + 113, 63, 0 +}; + + diff --git a/silk/silk_tables_pulses_per_block.c b/silk/silk_tables_pulses_per_block.c index 21685d36f..0f519e1c5 100644 --- a/silk/silk_tables_pulses_per_block.c +++ b/silk/silk_tables_pulses_per_block.c @@ -1,259 +1,259 @@ -/*********************************************************************** -Copyright (c) 2006-2011, Skype Limited. All rights reserved. -Redistribution and use in source and binary forms, with or without -modification, (subject to the limitations in the disclaimer below) -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 Skype Limited, nor the names of specific -contributors, may be used to endorse or promote products derived from -this software without specific prior written permission. -NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED -BY THIS LICENSE. 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. -***********************************************************************/ - -#include "silk_tables.h" - -const opus_uint8 silk_max_pulses_table[ 4 ] = { - 8, 10, 12, 16 -}; - -const opus_uint8 silk_pulses_per_block_iCDF[ 10 ][ 18 ] = { -{ - 125, 51, 26, 18, 15, 12, 11, 10, - 9, 8, 7, 6, 5, 4, 3, 2, - 1, 0 -}, -{ - 198, 105, 45, 22, 15, 12, 11, 10, - 9, 8, 7, 6, 5, 4, 3, 2, - 1, 0 -}, -{ - 213, 162, 116, 83, 59, 43, 32, 24, - 18, 15, 12, 9, 7, 6, 5, 3, - 2, 0 -}, -{ - 239, 187, 116, 59, 28, 16, 11, 10, - 9, 8, 7, 6, 5, 4, 3, 2, - 1, 0 -}, -{ - 250, 229, 188, 135, 86, 51, 30, 19, - 13, 10, 8, 6, 5, 4, 3, 2, - 1, 0 -}, -{ - 249, 235, 213, 185, 156, 128, 103, 83, - 66, 53, 42, 33, 26, 21, 17, 13, - 10, 0 -}, -{ - 254, 249, 235, 206, 164, 118, 77, 46, - 27, 16, 10, 7, 5, 4, 3, 2, - 1, 0 -}, -{ - 255, 253, 249, 239, 220, 191, 156, 119, - 85, 57, 37, 23, 15, 10, 6, 4, - 2, 0 -}, -{ - 255, 253, 251, 246, 237, 223, 203, 179, - 152, 124, 98, 75, 55, 40, 29, 21, - 15, 0 -}, -{ - 255, 254, 253, 247, 220, 162, 106, 67, - 42, 28, 18, 12, 9, 6, 4, 3, - 2, 0 -} -}; - -const opus_uint8 silk_pulses_per_block_BITS_Q5[ 9 ][ 18 ] = { -{ - 31, 57, 107, 160, 205, 205, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255 -}, -{ - 69, 47, 67, 111, 166, 205, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255 -}, -{ - 82, 74, 79, 95, 109, 128, 145, 160, - 173, 205, 205, 205, 224, 255, 255, 224, - 255, 224 -}, -{ - 125, 74, 59, 69, 97, 141, 182, 255, - 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255 -}, -{ - 173, 115, 85, 73, 76, 92, 115, 145, - 173, 205, 224, 224, 255, 255, 255, 255, - 255, 255 -}, -{ - 166, 134, 113, 102, 101, 102, 107, 118, - 125, 138, 145, 155, 166, 182, 192, 192, - 205, 150 -}, -{ - 224, 182, 134, 101, 83, 79, 85, 97, - 120, 145, 173, 205, 224, 255, 255, 255, - 255, 255 -}, -{ - 255, 224, 192, 150, 120, 101, 92, 89, - 93, 102, 118, 134, 160, 182, 192, 224, - 224, 224 -}, -{ - 255, 224, 224, 182, 155, 134, 118, 109, - 104, 102, 106, 111, 118, 131, 145, 160, - 173, 131 -} -}; - -const opus_uint8 silk_rate_levels_iCDF[ 2 ][ 9 ] = -{ -{ - 241, 190, 178, 132, 87, 74, 41, 14, - 0 -}, -{ - 223, 193, 157, 140, 106, 57, 39, 18, - 0 -} -}; - -const opus_uint8 silk_rate_levels_BITS_Q5[ 2 ][ 9 ] = -{ -{ - 131, 74, 141, 79, 80, 138, 95, 104, - 134 -}, -{ - 95, 99, 91, 125, 93, 76, 123, 115, - 123 -} -}; - -const opus_uint8 silk_shell_code_table0[ 152 ] = { - 128, 0, 214, 42, 0, 235, 128, 21, - 0, 244, 184, 72, 11, 0, 248, 214, - 128, 42, 7, 0, 248, 225, 170, 80, - 25, 5, 0, 251, 236, 198, 126, 54, - 18, 3, 0, 250, 238, 211, 159, 82, - 35, 15, 5, 0, 250, 231, 203, 168, - 128, 88, 53, 25, 6, 0, 252, 238, - 216, 185, 148, 108, 71, 40, 18, 4, - 0, 253, 243, 225, 199, 166, 128, 90, - 57, 31, 13, 3, 0, 254, 246, 233, - 212, 183, 147, 109, 73, 44, 23, 10, - 2, 0, 255, 250, 240, 223, 198, 166, - 128, 90, 58, 33, 16, 6, 1, 0, - 255, 251, 244, 231, 210, 181, 146, 110, - 75, 46, 25, 12, 5, 1, 0, 255, - 253, 248, 238, 221, 196, 164, 128, 92, - 60, 35, 18, 8, 3, 1, 0, 255, - 253, 249, 242, 229, 208, 180, 146, 110, - 76, 48, 27, 14, 7, 3, 1, 0 -}; - -const opus_uint8 silk_shell_code_table1[ 152 ] = { - 129, 0, 207, 50, 0, 236, 129, 20, - 0, 245, 185, 72, 10, 0, 249, 213, - 129, 42, 6, 0, 250, 226, 169, 87, - 27, 4, 0, 251, 233, 194, 130, 62, - 20, 4, 0, 250, 236, 207, 160, 99, - 47, 17, 3, 0, 255, 240, 217, 182, - 131, 81, 41, 11, 1, 0, 255, 254, - 233, 201, 159, 107, 61, 20, 2, 1, - 0, 255, 249, 233, 206, 170, 128, 86, - 50, 23, 7, 1, 0, 255, 250, 238, - 217, 186, 148, 108, 70, 39, 18, 6, - 1, 0, 255, 252, 243, 226, 200, 166, - 128, 90, 56, 30, 13, 4, 1, 0, - 255, 252, 245, 231, 209, 180, 146, 110, - 76, 47, 25, 11, 4, 1, 0, 255, - 253, 248, 237, 219, 194, 163, 128, 93, - 62, 37, 19, 8, 3, 1, 0, 255, - 254, 250, 241, 226, 205, 177, 145, 111, - 79, 51, 30, 15, 6, 2, 1, 0 -}; - -const opus_uint8 silk_shell_code_table2[ 152 ] = { - 129, 0, 203, 54, 0, 234, 129, 23, - 0, 245, 184, 73, 10, 0, 250, 215, - 129, 41, 5, 0, 252, 232, 173, 86, - 24, 3, 0, 253, 240, 200, 129, 56, - 15, 2, 0, 253, 244, 217, 164, 94, - 38, 10, 1, 0, 253, 245, 226, 189, - 132, 71, 27, 7, 1, 0, 253, 246, - 231, 203, 159, 105, 56, 23, 6, 1, - 0, 255, 248, 235, 213, 179, 133, 85, - 47, 19, 5, 1, 0, 255, 254, 243, - 221, 194, 159, 117, 70, 37, 12, 2, - 1, 0, 255, 254, 248, 234, 208, 171, - 128, 85, 48, 22, 8, 2, 1, 0, - 255, 254, 250, 240, 220, 189, 149, 107, - 67, 36, 16, 6, 2, 1, 0, 255, - 254, 251, 243, 227, 201, 166, 128, 90, - 55, 29, 13, 5, 2, 1, 0, 255, - 254, 252, 246, 234, 213, 183, 147, 109, - 73, 43, 22, 10, 4, 2, 1, 0 -}; - -const opus_uint8 silk_shell_code_table3[ 152 ] = { - 130, 0, 200, 58, 0, 231, 130, 26, - 0, 244, 184, 76, 12, 0, 249, 214, - 130, 43, 6, 0, 252, 232, 173, 87, - 24, 3, 0, 253, 241, 203, 131, 56, - 14, 2, 0, 254, 246, 221, 167, 94, - 35, 8, 1, 0, 254, 249, 232, 193, - 130, 65, 23, 5, 1, 0, 255, 251, - 239, 211, 162, 99, 45, 15, 4, 1, - 0, 255, 251, 243, 223, 186, 131, 74, - 33, 11, 3, 1, 0, 255, 252, 245, - 230, 202, 158, 105, 57, 24, 8, 2, - 1, 0, 255, 253, 247, 235, 214, 179, - 132, 84, 44, 19, 7, 2, 1, 0, - 255, 254, 250, 240, 223, 196, 159, 112, - 69, 36, 15, 6, 2, 1, 0, 255, - 254, 253, 245, 231, 209, 176, 136, 93, - 55, 27, 11, 3, 2, 1, 0, 255, - 254, 253, 252, 239, 221, 194, 158, 117, - 76, 42, 18, 4, 3, 2, 1, 0 -}; - -const opus_uint8 silk_shell_code_table_offsets[ 17 ] = { - 0, 0, 2, 5, 9, 14, 20, 27, - 35, 44, 54, 65, 77, 90, 104, 119, - 135 -}; - -const opus_uint8 silk_sign_iCDF[ 36 ] = { - 49, 67, 77, 82, 93, 99, 11, 18, - 24, 31, 36, 45, 46, 66, 78, 87, - 94, 104, 14, 21, 32, 42, 51, 66, - 94, 104, 109, 112, 115, 118, 53, 69, - 80, 88, 95, 102 -}; +/*********************************************************************** +Copyright (c) 2006-2011, Skype Limited. All rights reserved. +Redistribution and use in source and binary forms, with or without +modification, (subject to the limitations in the disclaimer below) +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 Skype Limited, nor the names of specific +contributors, may be used to endorse or promote products derived from +this software without specific prior written permission. +NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED +BY THIS LICENSE. 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. +***********************************************************************/ + +#include "silk_tables.h" + +const opus_uint8 silk_max_pulses_table[ 4 ] = { + 8, 10, 12, 16 +}; + +const opus_uint8 silk_pulses_per_block_iCDF[ 10 ][ 18 ] = { +{ + 125, 51, 26, 18, 15, 12, 11, 10, + 9, 8, 7, 6, 5, 4, 3, 2, + 1, 0 +}, +{ + 198, 105, 45, 22, 15, 12, 11, 10, + 9, 8, 7, 6, 5, 4, 3, 2, + 1, 0 +}, +{ + 213, 162, 116, 83, 59, 43, 32, 24, + 18, 15, 12, 9, 7, 6, 5, 3, + 2, 0 +}, +{ + 239, 187, 116, 59, 28, 16, 11, 10, + 9, 8, 7, 6, 5, 4, 3, 2, + 1, 0 +}, +{ + 250, 229, 188, 135, 86, 51, 30, 19, + 13, 10, 8, 6, 5, 4, 3, 2, + 1, 0 +}, +{ + 249, 235, 213, 185, 156, 128, 103, 83, + 66, 53, 42, 33, 26, 21, 17, 13, + 10, 0 +}, +{ + 254, 249, 235, 206, 164, 118, 77, 46, + 27, 16, 10, 7, 5, 4, 3, 2, + 1, 0 +}, +{ + 255, 253, 249, 239, 220, 191, 156, 119, + 85, 57, 37, 23, 15, 10, 6, 4, + 2, 0 +}, +{ + 255, 253, 251, 246, 237, 223, 203, 179, + 152, 124, 98, 75, 55, 40, 29, 21, + 15, 0 +}, +{ + 255, 254, 253, 247, 220, 162, 106, 67, + 42, 28, 18, 12, 9, 6, 4, 3, + 2, 0 +} +}; + +const opus_uint8 silk_pulses_per_block_BITS_Q5[ 9 ][ 18 ] = { +{ + 31, 57, 107, 160, 205, 205, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255 +}, +{ + 69, 47, 67, 111, 166, 205, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255 +}, +{ + 82, 74, 79, 95, 109, 128, 145, 160, + 173, 205, 205, 205, 224, 255, 255, 224, + 255, 224 +}, +{ + 125, 74, 59, 69, 97, 141, 182, 255, + 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255 +}, +{ + 173, 115, 85, 73, 76, 92, 115, 145, + 173, 205, 224, 224, 255, 255, 255, 255, + 255, 255 +}, +{ + 166, 134, 113, 102, 101, 102, 107, 118, + 125, 138, 145, 155, 166, 182, 192, 192, + 205, 150 +}, +{ + 224, 182, 134, 101, 83, 79, 85, 97, + 120, 145, 173, 205, 224, 255, 255, 255, + 255, 255 +}, +{ + 255, 224, 192, 150, 120, 101, 92, 89, + 93, 102, 118, 134, 160, 182, 192, 224, + 224, 224 +}, +{ + 255, 224, 224, 182, 155, 134, 118, 109, + 104, 102, 106, 111, 118, 131, 145, 160, + 173, 131 +} +}; + +const opus_uint8 silk_rate_levels_iCDF[ 2 ][ 9 ] = +{ +{ + 241, 190, 178, 132, 87, 74, 41, 14, + 0 +}, +{ + 223, 193, 157, 140, 106, 57, 39, 18, + 0 +} +}; + +const opus_uint8 silk_rate_levels_BITS_Q5[ 2 ][ 9 ] = +{ +{ + 131, 74, 141, 79, 80, 138, 95, 104, + 134 +}, +{ + 95, 99, 91, 125, 93, 76, 123, 115, + 123 +} +}; + +const opus_uint8 silk_shell_code_table0[ 152 ] = { + 128, 0, 214, 42, 0, 235, 128, 21, + 0, 244, 184, 72, 11, 0, 248, 214, + 128, 42, 7, 0, 248, 225, 170, 80, + 25, 5, 0, 251, 236, 198, 126, 54, + 18, 3, 0, 250, 238, 211, 159, 82, + 35, 15, 5, 0, 250, 231, 203, 168, + 128, 88, 53, 25, 6, 0, 252, 238, + 216, 185, 148, 108, 71, 40, 18, 4, + 0, 253, 243, 225, 199, 166, 128, 90, + 57, 31, 13, 3, 0, 254, 246, 233, + 212, 183, 147, 109, 73, 44, 23, 10, + 2, 0, 255, 250, 240, 223, 198, 166, + 128, 90, 58, 33, 16, 6, 1, 0, + 255, 251, 244, 231, 210, 181, 146, 110, + 75, 46, 25, 12, 5, 1, 0, 255, + 253, 248, 238, 221, 196, 164, 128, 92, + 60, 35, 18, 8, 3, 1, 0, 255, + 253, 249, 242, 229, 208, 180, 146, 110, + 76, 48, 27, 14, 7, 3, 1, 0 +}; + +const opus_uint8 silk_shell_code_table1[ 152 ] = { + 129, 0, 207, 50, 0, 236, 129, 20, + 0, 245, 185, 72, 10, 0, 249, 213, + 129, 42, 6, 0, 250, 226, 169, 87, + 27, 4, 0, 251, 233, 194, 130, 62, + 20, 4, 0, 250, 236, 207, 160, 99, + 47, 17, 3, 0, 255, 240, 217, 182, + 131, 81, 41, 11, 1, 0, 255, 254, + 233, 201, 159, 107, 61, 20, 2, 1, + 0, 255, 249, 233, 206, 170, 128, 86, + 50, 23, 7, 1, 0, 255, 250, 238, + 217, 186, 148, 108, 70, 39, 18, 6, + 1, 0, 255, 252, 243, 226, 200, 166, + 128, 90, 56, 30, 13, 4, 1, 0, + 255, 252, 245, 231, 209, 180, 146, 110, + 76, 47, 25, 11, 4, 1, 0, 255, + 253, 248, 237, 219, 194, 163, 128, 93, + 62, 37, 19, 8, 3, 1, 0, 255, + 254, 250, 241, 226, 205, 177, 145, 111, + 79, 51, 30, 15, 6, 2, 1, 0 +}; + +const opus_uint8 silk_shell_code_table2[ 152 ] = { + 129, 0, 203, 54, 0, 234, 129, 23, + 0, 245, 184, 73, 10, 0, 250, 215, + 129, 41, 5, 0, 252, 232, 173, 86, + 24, 3, 0, 253, 240, 200, 129, 56, + 15, 2, 0, 253, 244, 217, 164, 94, + 38, 10, 1, 0, 253, 245, 226, 189, + 132, 71, 27, 7, 1, 0, 253, 246, + 231, 203, 159, 105, 56, 23, 6, 1, + 0, 255, 248, 235, 213, 179, 133, 85, + 47, 19, 5, 1, 0, 255, 254, 243, + 221, 194, 159, 117, 70, 37, 12, 2, + 1, 0, 255, 254, 248, 234, 208, 171, + 128, 85, 48, 22, 8, 2, 1, 0, + 255, 254, 250, 240, 220, 189, 149, 107, + 67, 36, 16, 6, 2, 1, 0, 255, + 254, 251, 243, 227, 201, 166, 128, 90, + 55, 29, 13, 5, 2, 1, 0, 255, + 254, 252, 246, 234, 213, 183, 147, 109, + 73, 43, 22, 10, 4, 2, 1, 0 +}; + +const opus_uint8 silk_shell_code_table3[ 152 ] = { + 130, 0, 200, 58, 0, 231, 130, 26, + 0, 244, 184, 76, 12, 0, 249, 214, + 130, 43, 6, 0, 252, 232, 173, 87, + 24, 3, 0, 253, 241, 203, 131, 56, + 14, 2, 0, 254, 246, 221, 167, 94, + 35, 8, 1, 0, 254, 249, 232, 193, + 130, 65, 23, 5, 1, 0, 255, 251, + 239, 211, 162, 99, 45, 15, 4, 1, + 0, 255, 251, 243, 223, 186, 131, 74, + 33, 11, 3, 1, 0, 255, 252, 245, + 230, 202, 158, 105, 57, 24, 8, 2, + 1, 0, 255, 253, 247, 235, 214, 179, + 132, 84, 44, 19, 7, 2, 1, 0, + 255, 254, 250, 240, 223, 196, 159, 112, + 69, 36, 15, 6, 2, 1, 0, 255, + 254, 253, 245, 231, 209, 176, 136, 93, + 55, 27, 11, 3, 2, 1, 0, 255, + 254, 253, 252, 239, 221, 194, 158, 117, + 76, 42, 18, 4, 3, 2, 1, 0 +}; + +const opus_uint8 silk_shell_code_table_offsets[ 17 ] = { + 0, 0, 2, 5, 9, 14, 20, 27, + 35, 44, 54, 65, 77, 90, 104, 119, + 135 +}; + +const opus_uint8 silk_sign_iCDF[ 36 ] = { + 49, 67, 77, 82, 93, 99, 11, 18, + 24, 31, 36, 45, 46, 66, 78, 87, + 94, 104, 14, 21, 32, 42, 51, 66, + 94, 104, 109, 112, 115, 118, 53, 69, + 80, 88, 95, 102 +}; diff --git a/silk/silk_tuning_parameters.h b/silk/silk_tuning_parameters.h index 946d691a2..ea7f349d0 100644 --- a/silk/silk_tuning_parameters.h +++ b/silk/silk_tuning_parameters.h @@ -1,170 +1,170 @@ -/*********************************************************************** -Copyright (c) 2006-2011, Skype Limited. All rights reserved. -Redistribution and use in source and binary forms, with or without -modification, (subject to the limitations in the disclaimer below) -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 Skype Limited, nor the names of specific -contributors, may be used to endorse or promote products derived from -this software without specific prior written permission. -NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED -BY THIS LICENSE. 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. -***********************************************************************/ - -#ifndef SILK_TUNING_PARAMETERS_H -#define SILK_TUNING_PARAMETERS_H - -#ifdef __cplusplus -extern "C" -{ -#endif - -/* Decay time for bitreservoir */ -#define BITRESERVOIR_DECAY_TIME_MS 500 - -/*******************/ -/* Pitch estimator */ -/*******************/ - -/* Level of noise floor for whitening filter LPC analysis in pitch analysis */ -#define FIND_PITCH_WHITE_NOISE_FRACTION 1e-3f - -/* Bandwidth expansion for whitening filter in pitch analysis */ -#define FIND_PITCH_BANDWITH_EXPANSION 0.99f - -/*********************/ -/* Linear prediction */ -/*********************/ - -/* LPC analysis defines: regularization and bandwidth expansion */ -#define FIND_LPC_COND_FAC 2.5e-5f -#define FIND_LPC_CHIRP 0.99995f -#define FIND_LPC_CHIRP_FIRST_FRAME 0.96f - -/* LTP analysis defines */ -#define FIND_LTP_COND_FAC 1e-5f -#define LTP_DAMPING 0.01f -#define LTP_SMOOTHING 0.1f - -/* LTP quantization settings */ -#define MU_LTP_QUANT_NB 0.03f -#define MU_LTP_QUANT_MB 0.025f -#define MU_LTP_QUANT_WB 0.02f - -/***********************/ -/* High pass filtering */ -/***********************/ - -/* Smoothing parameters for low end of pitch frequency range estimation */ -#define VARIABLE_HP_SMTH_COEF1 0.1f -#define VARIABLE_HP_SMTH_COEF2 0.015f -#define VARIABLE_HP_MAX_DELTA_FREQ 0.4f - -/* Min and max cut-off frequency values (-3 dB points) */ -#define VARIABLE_HP_MIN_CUTOFF_HZ 60 -#define VARIABLE_HP_MAX_CUTOFF_HZ 100 - -/***********/ -/* Various */ -/***********/ - -/* VAD threshold */ -#define SPEECH_ACTIVITY_DTX_THRES 0.05f - -/* Speech Activity LBRR enable threshold */ -#define LBRR_SPEECH_ACTIVITY_THRES 0.3f - -/*************************/ -/* Perceptual parameters */ -/*************************/ - -/* reduction in coding SNR during low speech activity */ -#define BG_SNR_DECR_dB 2.0f - -/* factor for reducing quantization noise during voiced speech */ -#define HARM_SNR_INCR_dB 2.0f - -/* factor for reducing quantization noise for unvoiced sparse signals */ -#define SPARSE_SNR_INCR_dB 2.0f - -/* threshold for sparseness measure above which to use lower quantization offset during unvoiced */ -#define SPARSENESS_THRESHOLD_QNT_OFFSET 0.75f - -/* warping control */ -#define WARPING_MULTIPLIER 0.015f - -/* fraction added to first autocorrelation value */ -#define SHAPE_WHITE_NOISE_FRACTION 1e-5f - -/* noise shaping filter chirp factor */ -#define BANDWIDTH_EXPANSION 0.95f - -/* difference between chirp factors for analysis and synthesis noise shaping filters at low bitrates */ -#define LOW_RATE_BANDWIDTH_EXPANSION_DELTA 0.01f - -/* extra harmonic boosting (signal shaping) at low bitrates */ -#define LOW_RATE_HARMONIC_BOOST 0.1f - -/* extra harmonic boosting (signal shaping) for noisy input signals */ -#define LOW_INPUT_QUALITY_HARMONIC_BOOST 0.1f - -/* harmonic noise shaping */ -#define HARMONIC_SHAPING 0.3f - -/* extra harmonic noise shaping for high bitrates or noisy input */ -#define HIGH_RATE_OR_LOW_QUALITY_HARMONIC_SHAPING 0.2f - -/* parameter for shaping noise towards higher frequencies */ -#define HP_NOISE_COEF 0.25f - -/* parameter for shaping noise even more towards higher frequencies during voiced speech */ -#define HARM_HP_NOISE_COEF 0.35f - -/* parameter for applying a high-pass tilt to the input signal */ -#define INPUT_TILT 0.05f - -/* parameter for extra high-pass tilt to the input signal at high rates */ -#define HIGH_RATE_INPUT_TILT 0.1f - -/* parameter for reducing noise at the very low frequencies */ -#define LOW_FREQ_SHAPING 4.0f - -/* less reduction of noise at the very low frequencies for signals with low SNR at low frequencies */ -#define LOW_QUALITY_LOW_FREQ_SHAPING_DECR 0.5f - -/* subframe smoothing coefficient for HarmBoost, HarmShapeGain, Tilt (lower -> more smoothing) */ -#define SUBFR_SMTH_COEF 0.4f - -/* parameters defining the R/D tradeoff in the residual quantizer */ -#define LAMBDA_OFFSET 1.2f -#define LAMBDA_SPEECH_ACT -0.2f -#define LAMBDA_DELAYED_DECISIONS -0.05f -#define LAMBDA_INPUT_QUALITY -0.1f -#define LAMBDA_CODING_QUALITY -0.2f -#define LAMBDA_QUANT_OFFSET 0.8f - -/* Compensation in bitrate calculations for 10 ms modes */ -#define REDUCE_BITRATE_10_MS_BPS 2200 - -/* Maximum time before allowing a bandwidth transition */ -#define MAX_BANDWIDTH_SWITCH_DELAY_MS 5000 - -#ifdef __cplusplus -} -#endif - -#endif // SILK_TUNING_PARAMETERS_H +/*********************************************************************** +Copyright (c) 2006-2011, Skype Limited. All rights reserved. +Redistribution and use in source and binary forms, with or without +modification, (subject to the limitations in the disclaimer below) +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 Skype Limited, nor the names of specific +contributors, may be used to endorse or promote products derived from +this software without specific prior written permission. +NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED +BY THIS LICENSE. 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. +***********************************************************************/ + +#ifndef SILK_TUNING_PARAMETERS_H +#define SILK_TUNING_PARAMETERS_H + +#ifdef __cplusplus +extern "C" +{ +#endif + +/* Decay time for bitreservoir */ +#define BITRESERVOIR_DECAY_TIME_MS 500 + +/*******************/ +/* Pitch estimator */ +/*******************/ + +/* Level of noise floor for whitening filter LPC analysis in pitch analysis */ +#define FIND_PITCH_WHITE_NOISE_FRACTION 1e-3f + +/* Bandwidth expansion for whitening filter in pitch analysis */ +#define FIND_PITCH_BANDWITH_EXPANSION 0.99f + +/*********************/ +/* Linear prediction */ +/*********************/ + +/* LPC analysis defines: regularization and bandwidth expansion */ +#define FIND_LPC_COND_FAC 2.5e-5f +#define FIND_LPC_CHIRP 0.99995f +#define FIND_LPC_CHIRP_FIRST_FRAME 0.96f + +/* LTP analysis defines */ +#define FIND_LTP_COND_FAC 1e-5f +#define LTP_DAMPING 0.01f +#define LTP_SMOOTHING 0.1f + +/* LTP quantization settings */ +#define MU_LTP_QUANT_NB 0.03f +#define MU_LTP_QUANT_MB 0.025f +#define MU_LTP_QUANT_WB 0.02f + +/***********************/ +/* High pass filtering */ +/***********************/ + +/* Smoothing parameters for low end of pitch frequency range estimation */ +#define VARIABLE_HP_SMTH_COEF1 0.1f +#define VARIABLE_HP_SMTH_COEF2 0.015f +#define VARIABLE_HP_MAX_DELTA_FREQ 0.4f + +/* Min and max cut-off frequency values (-3 dB points) */ +#define VARIABLE_HP_MIN_CUTOFF_HZ 60 +#define VARIABLE_HP_MAX_CUTOFF_HZ 100 + +/***********/ +/* Various */ +/***********/ + +/* VAD threshold */ +#define SPEECH_ACTIVITY_DTX_THRES 0.05f + +/* Speech Activity LBRR enable threshold */ +#define LBRR_SPEECH_ACTIVITY_THRES 0.3f + +/*************************/ +/* Perceptual parameters */ +/*************************/ + +/* reduction in coding SNR during low speech activity */ +#define BG_SNR_DECR_dB 2.0f + +/* factor for reducing quantization noise during voiced speech */ +#define HARM_SNR_INCR_dB 2.0f + +/* factor for reducing quantization noise for unvoiced sparse signals */ +#define SPARSE_SNR_INCR_dB 2.0f + +/* threshold for sparseness measure above which to use lower quantization offset during unvoiced */ +#define SPARSENESS_THRESHOLD_QNT_OFFSET 0.75f + +/* warping control */ +#define WARPING_MULTIPLIER 0.015f + +/* fraction added to first autocorrelation value */ +#define SHAPE_WHITE_NOISE_FRACTION 1e-5f + +/* noise shaping filter chirp factor */ +#define BANDWIDTH_EXPANSION 0.95f + +/* difference between chirp factors for analysis and synthesis noise shaping filters at low bitrates */ +#define LOW_RATE_BANDWIDTH_EXPANSION_DELTA 0.01f + +/* extra harmonic boosting (signal shaping) at low bitrates */ +#define LOW_RATE_HARMONIC_BOOST 0.1f + +/* extra harmonic boosting (signal shaping) for noisy input signals */ +#define LOW_INPUT_QUALITY_HARMONIC_BOOST 0.1f + +/* harmonic noise shaping */ +#define HARMONIC_SHAPING 0.3f + +/* extra harmonic noise shaping for high bitrates or noisy input */ +#define HIGH_RATE_OR_LOW_QUALITY_HARMONIC_SHAPING 0.2f + +/* parameter for shaping noise towards higher frequencies */ +#define HP_NOISE_COEF 0.25f + +/* parameter for shaping noise even more towards higher frequencies during voiced speech */ +#define HARM_HP_NOISE_COEF 0.35f + +/* parameter for applying a high-pass tilt to the input signal */ +#define INPUT_TILT 0.05f + +/* parameter for extra high-pass tilt to the input signal at high rates */ +#define HIGH_RATE_INPUT_TILT 0.1f + +/* parameter for reducing noise at the very low frequencies */ +#define LOW_FREQ_SHAPING 4.0f + +/* less reduction of noise at the very low frequencies for signals with low SNR at low frequencies */ +#define LOW_QUALITY_LOW_FREQ_SHAPING_DECR 0.5f + +/* subframe smoothing coefficient for HarmBoost, HarmShapeGain, Tilt (lower -> more smoothing) */ +#define SUBFR_SMTH_COEF 0.4f + +/* parameters defining the R/D tradeoff in the residual quantizer */ +#define LAMBDA_OFFSET 1.2f +#define LAMBDA_SPEECH_ACT -0.2f +#define LAMBDA_DELAYED_DECISIONS -0.05f +#define LAMBDA_INPUT_QUALITY -0.1f +#define LAMBDA_CODING_QUALITY -0.2f +#define LAMBDA_QUANT_OFFSET 0.8f + +/* Compensation in bitrate calculations for 10 ms modes */ +#define REDUCE_BITRATE_10_MS_BPS 2200 + +/* Maximum time before allowing a bandwidth transition */ +#define MAX_BANDWIDTH_SWITCH_DELAY_MS 5000 + +#ifdef __cplusplus +} +#endif + +#endif // SILK_TUNING_PARAMETERS_H diff --git a/silk/silk_typedef.h b/silk/silk_typedef.h index 14ebcdfdb..502abf388 100644 --- a/silk/silk_typedef.h +++ b/silk/silk_typedef.h @@ -1,89 +1,89 @@ -/*********************************************************************** -Copyright (c) 2006-2011, Skype Limited. All rights reserved. -Redistribution and use in source and binary forms, with or without -modification, (subject to the limitations in the disclaimer below) -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 Skype Limited, nor the names of specific -contributors, may be used to endorse or promote products derived from -this software without specific prior written permission. -NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED -BY THIS LICENSE. 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. -***********************************************************************/ - -#ifndef _SILK_TYPEDEF_H_ -#define _SILK_TYPEDEF_H_ - -#include "opus_types.h" - -#ifndef SKP_USE_DOUBLE_PRECISION_FLOATS -#define SKP_USE_DOUBLE_PRECISION_FLOATS 0 -#endif - -#include <float.h> -#if defined( __GNUC__ ) -#include <stdint.h> -#endif - -#define SKP_int_ptr_size intptr_t - -#if SKP_USE_DOUBLE_PRECISION_FLOATS -# define SKP_float double -# define SKP_float_MAX DBL_MAX -#else -# define SKP_float float -# define SKP_float_MAX FLT_MAX -#endif - -#define SKP_INLINE static __inline - -#ifdef _WIN32 -# define SKP_STR_CASEINSENSITIVE_COMPARE(x, y) _stricmp(x, y) -#else -# define SKP_STR_CASEINSENSITIVE_COMPARE(x, y) strcasecmp(x, y) -#endif - -#define SKP_int64_MAX ((opus_int64)0x7FFFFFFFFFFFFFFFLL) // 2^63 - 1 -#define SKP_int64_MIN ((opus_int64)0x8000000000000000LL) // -2^63 -#define SKP_int32_MAX 0x7FFFFFFF // 2^31 - 1 = 2147483647 -#define SKP_int32_MIN ((opus_int32)0x80000000) // -2^31 = -2147483648 -#define SKP_int16_MAX 0x7FFF // 2^15 - 1 = 32767 -#define SKP_int16_MIN ((opus_int16)0x8000) // -2^15 = -32768 -#define SKP_int8_MAX 0x7F // 2^7 - 1 = 127 -#define SKP_int8_MIN ((opus_int8)0x80) // -2^7 = -128 - -#define SKP_uint32_MAX 0xFFFFFFFF // 2^32 - 1 = 4294967295 -#define SKP_uint32_MIN 0x00000000 -#define SKP_uint16_MAX 0xFFFF // 2^16 - 1 = 65535 -#define SKP_uint16_MIN 0x0000 -#define SKP_uint8_MAX 0xFF // 2^8 - 1 = 255 -#define SKP_uint8_MIN 0x00 - -#define SKP_TRUE 1 -#define SKP_FALSE 0 - -/* assertions */ -#if (defined _WIN32 && !defined _WINCE && !defined(__GNUC__) && !defined(NO_ASSERTS)) -# ifndef SKP_assert -# include <crtdbg.h> /* ASSERTE() */ -# define SKP_assert(COND) _ASSERTE(COND) -# endif -#else -# define SKP_assert(COND) -#endif - -#endif +/*********************************************************************** +Copyright (c) 2006-2011, Skype Limited. All rights reserved. +Redistribution and use in source and binary forms, with or without +modification, (subject to the limitations in the disclaimer below) +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 Skype Limited, nor the names of specific +contributors, may be used to endorse or promote products derived from +this software without specific prior written permission. +NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED +BY THIS LICENSE. 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. +***********************************************************************/ + +#ifndef _SILK_TYPEDEF_H_ +#define _SILK_TYPEDEF_H_ + +#include "opus_types.h" + +#ifndef SKP_USE_DOUBLE_PRECISION_FLOATS +#define SKP_USE_DOUBLE_PRECISION_FLOATS 0 +#endif + +#include <float.h> +#if defined( __GNUC__ ) +#include <stdint.h> +#endif + +#define SKP_int_ptr_size intptr_t + +#if SKP_USE_DOUBLE_PRECISION_FLOATS +# define SKP_float double +# define SKP_float_MAX DBL_MAX +#else +# define SKP_float float +# define SKP_float_MAX FLT_MAX +#endif + +#define SKP_INLINE static __inline + +#ifdef _WIN32 +# define SKP_STR_CASEINSENSITIVE_COMPARE(x, y) _stricmp(x, y) +#else +# define SKP_STR_CASEINSENSITIVE_COMPARE(x, y) strcasecmp(x, y) +#endif + +#define SKP_int64_MAX ((opus_int64)0x7FFFFFFFFFFFFFFFLL) // 2^63 - 1 +#define SKP_int64_MIN ((opus_int64)0x8000000000000000LL) // -2^63 +#define SKP_int32_MAX 0x7FFFFFFF // 2^31 - 1 = 2147483647 +#define SKP_int32_MIN ((opus_int32)0x80000000) // -2^31 = -2147483648 +#define SKP_int16_MAX 0x7FFF // 2^15 - 1 = 32767 +#define SKP_int16_MIN ((opus_int16)0x8000) // -2^15 = -32768 +#define SKP_int8_MAX 0x7F // 2^7 - 1 = 127 +#define SKP_int8_MIN ((opus_int8)0x80) // -2^7 = -128 + +#define SKP_uint32_MAX 0xFFFFFFFF // 2^32 - 1 = 4294967295 +#define SKP_uint32_MIN 0x00000000 +#define SKP_uint16_MAX 0xFFFF // 2^16 - 1 = 65535 +#define SKP_uint16_MIN 0x0000 +#define SKP_uint8_MAX 0xFF // 2^8 - 1 = 255 +#define SKP_uint8_MIN 0x00 + +#define SKP_TRUE 1 +#define SKP_FALSE 0 + +/* assertions */ +#if (defined _WIN32 && !defined _WINCE && !defined(__GNUC__) && !defined(NO_ASSERTS)) +# ifndef SKP_assert +# include <crtdbg.h> /* ASSERTE() */ +# define SKP_assert(COND) _ASSERTE(COND) +# endif +#else +# define SKP_assert(COND) +#endif + +#endif -- GitLab