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