1885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org/*********************************************************************** 2885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.orgCopyright (c) 2006-2011, Skype Limited. All rights reserved. 3885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.orgRedistribution and use in source and binary forms, with or without 4885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.orgmodification, are permitted provided that the following conditions 5885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.orgare met: 6885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org- Redistributions of source code must retain the above copyright notice, 7885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.orgthis list of conditions and the following disclaimer. 8885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org- Redistributions in binary form must reproduce the above copyright 9885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.orgnotice, this list of conditions and the following disclaimer in the 10885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.orgdocumentation and/or other materials provided with the distribution. 11e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org- Neither the name of Internet Society, IETF or IETF Trust, nor the 12885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.orgnames of specific contributors, may be used to endorse or promote 13885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.orgproducts derived from this software without specific prior written 14885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.orgpermission. 15e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.orgTHIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 16885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.orgAND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.orgIMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.orgARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 19885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.orgLIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 20885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.orgCONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 21885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.orgSUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 22885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.orgINTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 23885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.orgCONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 24885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.orgARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 25885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.orgPOSSIBILITY OF SUCH DAMAGE. 26885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org***********************************************************************/ 27885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org 28885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org#ifdef HAVE_CONFIG_H 29885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org#include "config.h" 30885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org#endif 31885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org 32885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org#include "main_FIX.h" 33e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org#include "stack_alloc.h" 34885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org 35885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.orgvoid silk_find_pred_coefs_FIX( 36885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org silk_encoder_state_FIX *psEnc, /* I/O encoder state */ 37885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org silk_encoder_control_FIX *psEncCtrl, /* I/O encoder control */ 38885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org const opus_int16 res_pitch[], /* I Residual from pitch analysis */ 39885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org const opus_int16 x[], /* I Speech signal */ 40885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org opus_int condCoding /* I The type of conditional coding to use */ 41885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org) 42885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org{ 43885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org opus_int i; 44885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org opus_int32 invGains_Q16[ MAX_NB_SUBFR ], local_gains[ MAX_NB_SUBFR ], Wght_Q15[ MAX_NB_SUBFR ]; 45885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org opus_int16 NLSF_Q15[ MAX_LPC_ORDER ]; 46885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org const opus_int16 *x_ptr; 47e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org opus_int16 *x_pre_ptr; 48e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org VARDECL( opus_int16, LPC_in_pre ); 49885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org opus_int32 tmp, min_gain_Q16, minInvGain_Q30; 50885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org opus_int LTP_corrs_rshift[ MAX_NB_SUBFR ]; 51e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org SAVE_STACK; 52885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org 53885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org /* weighting for weighted least squares */ 54885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org min_gain_Q16 = silk_int32_MAX >> 6; 55885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org for( i = 0; i < psEnc->sCmn.nb_subfr; i++ ) { 56885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org min_gain_Q16 = silk_min( min_gain_Q16, psEncCtrl->Gains_Q16[ i ] ); 57885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org } 58885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org for( i = 0; i < psEnc->sCmn.nb_subfr; i++ ) { 59885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org /* Divide to Q16 */ 60885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org silk_assert( psEncCtrl->Gains_Q16[ i ] > 0 ); 61885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org /* Invert and normalize gains, and ensure that maximum invGains_Q16 is within range of a 16 bit int */ 62885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org invGains_Q16[ i ] = silk_DIV32_varQ( min_gain_Q16, psEncCtrl->Gains_Q16[ i ], 16 - 2 ); 63885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org 64885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org /* Ensure Wght_Q15 a minimum value 1 */ 65885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org invGains_Q16[ i ] = silk_max( invGains_Q16[ i ], 363 ); 66885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org 67885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org /* Square the inverted gains */ 68885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org silk_assert( invGains_Q16[ i ] == silk_SAT16( invGains_Q16[ i ] ) ); 69885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org tmp = silk_SMULWB( invGains_Q16[ i ], invGains_Q16[ i ] ); 70885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org Wght_Q15[ i ] = silk_RSHIFT( tmp, 1 ); 71885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org 72885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org /* Invert the inverted and normalized gains */ 73885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org local_gains[ i ] = silk_DIV32( ( (opus_int32)1 << 16 ), invGains_Q16[ i ] ); 74885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org } 75885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org 76e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org ALLOC( LPC_in_pre, 77e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org psEnc->sCmn.nb_subfr * psEnc->sCmn.predictLPCOrder 78e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org + psEnc->sCmn.frame_length, opus_int16 ); 79885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org if( psEnc->sCmn.indices.signalType == TYPE_VOICED ) { 80e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org VARDECL( opus_int32, WLTP ); 81e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org 82885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org /**********/ 83885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org /* VOICED */ 84885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org /**********/ 85885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org silk_assert( psEnc->sCmn.ltp_mem_length - psEnc->sCmn.predictLPCOrder >= psEncCtrl->pitchL[ 0 ] + LTP_ORDER / 2 ); 86885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org 87e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org ALLOC( WLTP, psEnc->sCmn.nb_subfr * LTP_ORDER * LTP_ORDER, opus_int32 ); 88e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org 89885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org /* LTP analysis */ 90885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org silk_find_LTP_FIX( psEncCtrl->LTPCoef_Q14, WLTP, &psEncCtrl->LTPredCodGain_Q7, 91885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org res_pitch, psEncCtrl->pitchL, Wght_Q15, psEnc->sCmn.subfr_length, 92885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org psEnc->sCmn.nb_subfr, psEnc->sCmn.ltp_mem_length, LTP_corrs_rshift ); 93885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org 94885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org /* Quantize LTP gain parameters */ 95885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org silk_quant_LTP_gains( psEncCtrl->LTPCoef_Q14, psEnc->sCmn.indices.LTPIndex, &psEnc->sCmn.indices.PERIndex, 963c3902f0ac13428394f14f78f0fab05ef3468d69tlegrand@google.com &psEnc->sCmn.sum_log_gain_Q7, WLTP, psEnc->sCmn.mu_LTP_Q9, psEnc->sCmn.LTPQuantLowComplexity, psEnc->sCmn.nb_subfr); 97885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org 98885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org /* Control LTP scaling */ 99885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org silk_LTP_scale_ctrl_FIX( psEnc, psEncCtrl, condCoding ); 100885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org 101885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org /* Create LTP residual */ 102885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org silk_LTP_analysis_filter_FIX( LPC_in_pre, x - psEnc->sCmn.predictLPCOrder, psEncCtrl->LTPCoef_Q14, 103885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org psEncCtrl->pitchL, invGains_Q16, psEnc->sCmn.subfr_length, psEnc->sCmn.nb_subfr, psEnc->sCmn.predictLPCOrder ); 104885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org 105885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org } else { 106885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org /************/ 107885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org /* UNVOICED */ 108885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org /************/ 109885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org /* Create signal with prepended subframes, scaled by inverse gains */ 110885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org x_ptr = x - psEnc->sCmn.predictLPCOrder; 111885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org x_pre_ptr = LPC_in_pre; 112885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org for( i = 0; i < psEnc->sCmn.nb_subfr; i++ ) { 113885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org silk_scale_copy_vector16( x_pre_ptr, x_ptr, invGains_Q16[ i ], 114885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org psEnc->sCmn.subfr_length + psEnc->sCmn.predictLPCOrder ); 115885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org x_pre_ptr += psEnc->sCmn.subfr_length + psEnc->sCmn.predictLPCOrder; 116885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org x_ptr += psEnc->sCmn.subfr_length; 117885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org } 118885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org 119885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org silk_memset( psEncCtrl->LTPCoef_Q14, 0, psEnc->sCmn.nb_subfr * LTP_ORDER * sizeof( opus_int16 ) ); 120885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org psEncCtrl->LTPredCodGain_Q7 = 0; 1213c3902f0ac13428394f14f78f0fab05ef3468d69tlegrand@google.com psEnc->sCmn.sum_log_gain_Q7 = 0; 122885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org } 123885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org 124885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org /* Limit on total predictive coding gain */ 125885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org if( psEnc->sCmn.first_frame_after_reset ) { 126885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org minInvGain_Q30 = SILK_FIX_CONST( 1.0f / MAX_PREDICTION_POWER_GAIN_AFTER_RESET, 30 ); 127885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org } else { 128885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org minInvGain_Q30 = silk_log2lin( silk_SMLAWB( 16 << 7, (opus_int32)psEncCtrl->LTPredCodGain_Q7, SILK_FIX_CONST( 1.0 / 3, 16 ) ) ); /* Q16 */ 129885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org minInvGain_Q30 = silk_DIV32_varQ( minInvGain_Q30, 130885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org silk_SMULWW( SILK_FIX_CONST( MAX_PREDICTION_POWER_GAIN, 0 ), 131885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org silk_SMLAWB( SILK_FIX_CONST( 0.25, 18 ), SILK_FIX_CONST( 0.75, 18 ), psEncCtrl->coding_quality_Q14 ) ), 14 ); 132885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org } 133885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org 134885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org /* LPC_in_pre contains the LTP-filtered input for voiced, and the unfiltered input for unvoiced */ 135885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org silk_find_LPC_FIX( &psEnc->sCmn, NLSF_Q15, LPC_in_pre, minInvGain_Q30 ); 136885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org 137885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org /* Quantize LSFs */ 138885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org silk_process_NLSFs( &psEnc->sCmn, psEncCtrl->PredCoef_Q12, NLSF_Q15, psEnc->sCmn.prev_NLSFq_Q15 ); 139885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org 140885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org /* Calculate residual energy using quantized LPC coefficients */ 141885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org silk_residual_energy_FIX( psEncCtrl->ResNrg, psEncCtrl->ResNrgQ, LPC_in_pre, psEncCtrl->PredCoef_Q12, local_gains, 142885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org psEnc->sCmn.subfr_length, psEnc->sCmn.nb_subfr, psEnc->sCmn.predictLPCOrder ); 143885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org 144885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org /* Copy to prediction struct for use in next frame for interpolation */ 145885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org silk_memcpy( psEnc->sCmn.prev_NLSFq_Q15, NLSF_Q15, sizeof( psEnc->sCmn.prev_NLSFq_Q15 ) ); 146e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org RESTORE_STACK; 147885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org} 148