1/***********************************************************************
2Copyright (c) 2006-2011, Skype Limited. All rights reserved.
3Redistribution and use in source and binary forms, with or without
4modification, are permitted provided that the following conditions
5are met:
6- Redistributions of source code must retain the above copyright notice,
7this list of conditions and the following disclaimer.
8- Redistributions in binary form must reproduce the above copyright
9notice, this list of conditions and the following disclaimer in the
10documentation and/or other materials provided with the distribution.
11- Neither the name of Internet Society, IETF or IETF Trust, nor the
12names of specific contributors, may be used to endorse or promote
13products derived from this software without specific prior written
14permission.
15THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
16AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
19LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
20CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
21SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
22INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
23CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
24ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
25POSSIBILITY OF SUCH DAMAGE.
26***********************************************************************/
27
28#ifdef HAVE_CONFIG_H
29#include "config.h"
30#endif
31
32#include "main_FIX.h"
33#include "stack_alloc.h"
34#include "tuning_parameters.h"
35
36/* Prefilter for finding Quantizer input signal */
37static OPUS_INLINE void silk_prefilt_FIX(
38    silk_prefilter_state_FIX    *P,                         /* I/O  state                               */
39    opus_int32                  st_res_Q12[],               /* I    short term residual signal          */
40    opus_int32                  xw_Q3[],                    /* O    prefiltered signal                  */
41    opus_int32                  HarmShapeFIRPacked_Q12,     /* I    Harmonic shaping coeficients        */
42    opus_int                    Tilt_Q14,                   /* I    Tilt shaping coeficient             */
43    opus_int32                  LF_shp_Q14,                 /* I    Low-frequancy shaping coeficients   */
44    opus_int                    lag,                        /* I    Lag for harmonic shaping            */
45    opus_int                    length                      /* I    Length of signals                   */
46);
47
48void silk_warped_LPC_analysis_filter_FIX(
49          opus_int32            state[],                    /* I/O  State [order + 1]                   */
50          opus_int32            res_Q2[],                   /* O    Residual signal [length]            */
51    const opus_int16            coef_Q13[],                 /* I    Coefficients [order]                */
52    const opus_int16            input[],                    /* I    Input signal [length]               */
53    const opus_int16            lambda_Q16,                 /* I    Warping factor                      */
54    const opus_int              length,                     /* I    Length of input signal              */
55    const opus_int              order                       /* I    Filter order (even)                 */
56)
57{
58    opus_int     n, i;
59    opus_int32   acc_Q11, tmp1, tmp2;
60
61    /* Order must be even */
62    silk_assert( ( order & 1 ) == 0 );
63
64    for( n = 0; n < length; n++ ) {
65        /* Output of lowpass section */
66        tmp2 = silk_SMLAWB( state[ 0 ], state[ 1 ], lambda_Q16 );
67        state[ 0 ] = silk_LSHIFT( input[ n ], 14 );
68        /* Output of allpass section */
69        tmp1 = silk_SMLAWB( state[ 1 ], state[ 2 ] - tmp2, lambda_Q16 );
70        state[ 1 ] = tmp2;
71        acc_Q11 = silk_RSHIFT( order, 1 );
72        acc_Q11 = silk_SMLAWB( acc_Q11, tmp2, coef_Q13[ 0 ] );
73        /* Loop over allpass sections */
74        for( i = 2; i < order; i += 2 ) {
75            /* Output of allpass section */
76            tmp2 = silk_SMLAWB( state[ i ], state[ i + 1 ] - tmp1, lambda_Q16 );
77            state[ i ] = tmp1;
78            acc_Q11 = silk_SMLAWB( acc_Q11, tmp1, coef_Q13[ i - 1 ] );
79            /* Output of allpass section */
80            tmp1 = silk_SMLAWB( state[ i + 1 ], state[ i + 2 ] - tmp2, lambda_Q16 );
81            state[ i + 1 ] = tmp2;
82            acc_Q11 = silk_SMLAWB( acc_Q11, tmp2, coef_Q13[ i ] );
83        }
84        state[ order ] = tmp1;
85        acc_Q11 = silk_SMLAWB( acc_Q11, tmp1, coef_Q13[ order - 1 ] );
86        res_Q2[ n ] = silk_LSHIFT( (opus_int32)input[ n ], 2 ) - silk_RSHIFT_ROUND( acc_Q11, 9 );
87    }
88}
89
90void silk_prefilter_FIX(
91    silk_encoder_state_FIX          *psEnc,                                 /* I/O  Encoder state                                                               */
92    const silk_encoder_control_FIX  *psEncCtrl,                             /* I    Encoder control                                                             */
93    opus_int32                      xw_Q3[],                                /* O    Weighted signal                                                             */
94    const opus_int16                x[]                                     /* I    Speech signal                                                               */
95)
96{
97    silk_prefilter_state_FIX *P = &psEnc->sPrefilt;
98    opus_int   j, k, lag;
99    opus_int32 tmp_32;
100    const opus_int16 *AR1_shp_Q13;
101    const opus_int16 *px;
102    opus_int32 *pxw_Q3;
103    opus_int   HarmShapeGain_Q12, Tilt_Q14;
104    opus_int32 HarmShapeFIRPacked_Q12, LF_shp_Q14;
105    VARDECL( opus_int32, x_filt_Q12 );
106    VARDECL( opus_int32, st_res_Q2 );
107    opus_int16 B_Q10[ 2 ];
108    SAVE_STACK;
109
110    /* Set up pointers */
111    px  = x;
112    pxw_Q3 = xw_Q3;
113    lag = P->lagPrev;
114    ALLOC( x_filt_Q12, psEnc->sCmn.subfr_length, opus_int32 );
115    ALLOC( st_res_Q2, psEnc->sCmn.subfr_length, opus_int32 );
116    for( k = 0; k < psEnc->sCmn.nb_subfr; k++ ) {
117        /* Update Variables that change per sub frame */
118        if( psEnc->sCmn.indices.signalType == TYPE_VOICED ) {
119            lag = psEncCtrl->pitchL[ k ];
120        }
121
122        /* Noise shape parameters */
123        HarmShapeGain_Q12 = silk_SMULWB( (opus_int32)psEncCtrl->HarmShapeGain_Q14[ k ], 16384 - psEncCtrl->HarmBoost_Q14[ k ] );
124        silk_assert( HarmShapeGain_Q12 >= 0 );
125        HarmShapeFIRPacked_Q12  =                          silk_RSHIFT( HarmShapeGain_Q12, 2 );
126        HarmShapeFIRPacked_Q12 |= silk_LSHIFT( (opus_int32)silk_RSHIFT( HarmShapeGain_Q12, 1 ), 16 );
127        Tilt_Q14    = psEncCtrl->Tilt_Q14[   k ];
128        LF_shp_Q14  = psEncCtrl->LF_shp_Q14[ k ];
129        AR1_shp_Q13 = &psEncCtrl->AR1_Q13[   k * MAX_SHAPE_LPC_ORDER ];
130
131        /* Short term FIR filtering*/
132        silk_warped_LPC_analysis_filter_FIX( P->sAR_shp, st_res_Q2, AR1_shp_Q13, px,
133            psEnc->sCmn.warping_Q16, psEnc->sCmn.subfr_length, psEnc->sCmn.shapingLPCOrder );
134
135        /* Reduce (mainly) low frequencies during harmonic emphasis */
136        B_Q10[ 0 ] = silk_RSHIFT_ROUND( psEncCtrl->GainsPre_Q14[ k ], 4 );
137        tmp_32 = silk_SMLABB( SILK_FIX_CONST( INPUT_TILT, 26 ), psEncCtrl->HarmBoost_Q14[ k ], HarmShapeGain_Q12 );   /* Q26 */
138        tmp_32 = silk_SMLABB( tmp_32, psEncCtrl->coding_quality_Q14, SILK_FIX_CONST( HIGH_RATE_INPUT_TILT, 12 ) );    /* Q26 */
139        tmp_32 = silk_SMULWB( tmp_32, -psEncCtrl->GainsPre_Q14[ k ] );                                                /* Q24 */
140        tmp_32 = silk_RSHIFT_ROUND( tmp_32, 14 );                                                                     /* Q10 */
141        B_Q10[ 1 ]= silk_SAT16( tmp_32 );
142        x_filt_Q12[ 0 ] = silk_MLA( silk_MUL( st_res_Q2[ 0 ], B_Q10[ 0 ] ), P->sHarmHP_Q2, B_Q10[ 1 ] );
143        for( j = 1; j < psEnc->sCmn.subfr_length; j++ ) {
144            x_filt_Q12[ j ] = silk_MLA( silk_MUL( st_res_Q2[ j ], B_Q10[ 0 ] ), st_res_Q2[ j - 1 ], B_Q10[ 1 ] );
145        }
146        P->sHarmHP_Q2 = st_res_Q2[ psEnc->sCmn.subfr_length - 1 ];
147
148        silk_prefilt_FIX( P, x_filt_Q12, pxw_Q3, HarmShapeFIRPacked_Q12, Tilt_Q14, LF_shp_Q14, lag, psEnc->sCmn.subfr_length );
149
150        px  += psEnc->sCmn.subfr_length;
151        pxw_Q3 += psEnc->sCmn.subfr_length;
152    }
153
154    P->lagPrev = psEncCtrl->pitchL[ psEnc->sCmn.nb_subfr - 1 ];
155    RESTORE_STACK;
156}
157
158/* Prefilter for finding Quantizer input signal */
159static OPUS_INLINE void silk_prefilt_FIX(
160    silk_prefilter_state_FIX    *P,                         /* I/O  state                               */
161    opus_int32                  st_res_Q12[],               /* I    short term residual signal          */
162    opus_int32                  xw_Q3[],                    /* O    prefiltered signal                  */
163    opus_int32                  HarmShapeFIRPacked_Q12,     /* I    Harmonic shaping coeficients        */
164    opus_int                    Tilt_Q14,                   /* I    Tilt shaping coeficient             */
165    opus_int32                  LF_shp_Q14,                 /* I    Low-frequancy shaping coeficients   */
166    opus_int                    lag,                        /* I    Lag for harmonic shaping            */
167    opus_int                    length                      /* I    Length of signals                   */
168)
169{
170    opus_int   i, idx, LTP_shp_buf_idx;
171    opus_int32 n_LTP_Q12, n_Tilt_Q10, n_LF_Q10;
172    opus_int32 sLF_MA_shp_Q12, sLF_AR_shp_Q12;
173    opus_int16 *LTP_shp_buf;
174
175    /* To speed up use temp variables instead of using the struct */
176    LTP_shp_buf     = P->sLTP_shp;
177    LTP_shp_buf_idx = P->sLTP_shp_buf_idx;
178    sLF_AR_shp_Q12  = P->sLF_AR_shp_Q12;
179    sLF_MA_shp_Q12  = P->sLF_MA_shp_Q12;
180
181    for( i = 0; i < length; i++ ) {
182        if( lag > 0 ) {
183            /* unrolled loop */
184            silk_assert( HARM_SHAPE_FIR_TAPS == 3 );
185            idx = lag + LTP_shp_buf_idx;
186            n_LTP_Q12 = silk_SMULBB(            LTP_shp_buf[ ( idx - HARM_SHAPE_FIR_TAPS / 2 - 1) & LTP_MASK ], HarmShapeFIRPacked_Q12 );
187            n_LTP_Q12 = silk_SMLABT( n_LTP_Q12, LTP_shp_buf[ ( idx - HARM_SHAPE_FIR_TAPS / 2    ) & LTP_MASK ], HarmShapeFIRPacked_Q12 );
188            n_LTP_Q12 = silk_SMLABB( n_LTP_Q12, LTP_shp_buf[ ( idx - HARM_SHAPE_FIR_TAPS / 2 + 1) & LTP_MASK ], HarmShapeFIRPacked_Q12 );
189        } else {
190            n_LTP_Q12 = 0;
191        }
192
193        n_Tilt_Q10 = silk_SMULWB( sLF_AR_shp_Q12, Tilt_Q14 );
194        n_LF_Q10   = silk_SMLAWB( silk_SMULWT( sLF_AR_shp_Q12, LF_shp_Q14 ), sLF_MA_shp_Q12, LF_shp_Q14 );
195
196        sLF_AR_shp_Q12 = silk_SUB32( st_res_Q12[ i ], silk_LSHIFT( n_Tilt_Q10, 2 ) );
197        sLF_MA_shp_Q12 = silk_SUB32( sLF_AR_shp_Q12,  silk_LSHIFT( n_LF_Q10,   2 ) );
198
199        LTP_shp_buf_idx = ( LTP_shp_buf_idx - 1 ) & LTP_MASK;
200        LTP_shp_buf[ LTP_shp_buf_idx ] = (opus_int16)silk_SAT16( silk_RSHIFT_ROUND( sLF_MA_shp_Q12, 12 ) );
201
202        xw_Q3[i] = silk_RSHIFT_ROUND( silk_SUB32( sLF_MA_shp_Q12, n_LTP_Q12 ), 9 );
203    }
204
205    /* Copy temp variable back to state */
206    P->sLF_AR_shp_Q12   = sLF_AR_shp_Q12;
207    P->sLF_MA_shp_Q12   = sLF_MA_shp_Q12;
208    P->sLTP_shp_buf_idx = LTP_shp_buf_idx;
209}
210