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 <stdlib.h>
33#include "main_FLP.h"
34
35/************************************************/
36/* LPC analysis filter                          */
37/* NB! State is kept internally and the         */
38/* filter always starts with zero state         */
39/* first Order output samples are set to zero   */
40/************************************************/
41
42/* 16th order LPC analysis filter, does not write first 16 samples */
43static OPUS_INLINE void silk_LPC_analysis_filter16_FLP(
44          silk_float                 r_LPC[],            /* O    LPC residual signal                     */
45    const silk_float                 PredCoef[],         /* I    LPC coefficients                        */
46    const silk_float                 s[],                /* I    Input signal                            */
47    const opus_int                   length              /* I    Length of input signal                  */
48)
49{
50    opus_int   ix;
51    silk_float LPC_pred;
52    const silk_float *s_ptr;
53
54    for( ix = 16; ix < length; ix++ ) {
55        s_ptr = &s[ix - 1];
56
57        /* short-term prediction */
58        LPC_pred = s_ptr[  0 ]  * PredCoef[ 0 ]  +
59                   s_ptr[ -1 ]  * PredCoef[ 1 ]  +
60                   s_ptr[ -2 ]  * PredCoef[ 2 ]  +
61                   s_ptr[ -3 ]  * PredCoef[ 3 ]  +
62                   s_ptr[ -4 ]  * PredCoef[ 4 ]  +
63                   s_ptr[ -5 ]  * PredCoef[ 5 ]  +
64                   s_ptr[ -6 ]  * PredCoef[ 6 ]  +
65                   s_ptr[ -7 ]  * PredCoef[ 7 ]  +
66                   s_ptr[ -8 ]  * PredCoef[ 8 ]  +
67                   s_ptr[ -9 ]  * PredCoef[ 9 ]  +
68                   s_ptr[ -10 ] * PredCoef[ 10 ] +
69                   s_ptr[ -11 ] * PredCoef[ 11 ] +
70                   s_ptr[ -12 ] * PredCoef[ 12 ] +
71                   s_ptr[ -13 ] * PredCoef[ 13 ] +
72                   s_ptr[ -14 ] * PredCoef[ 14 ] +
73                   s_ptr[ -15 ] * PredCoef[ 15 ];
74
75        /* prediction error */
76        r_LPC[ix] = s_ptr[ 1 ] - LPC_pred;
77    }
78}
79
80/* 12th order LPC analysis filter, does not write first 12 samples */
81static OPUS_INLINE void silk_LPC_analysis_filter12_FLP(
82          silk_float                 r_LPC[],            /* O    LPC residual signal                     */
83    const silk_float                 PredCoef[],         /* I    LPC coefficients                        */
84    const silk_float                 s[],                /* I    Input signal                            */
85    const opus_int                   length              /* I    Length of input signal                  */
86)
87{
88    opus_int   ix;
89    silk_float LPC_pred;
90    const silk_float *s_ptr;
91
92    for( ix = 12; ix < length; ix++ ) {
93        s_ptr = &s[ix - 1];
94
95        /* short-term prediction */
96        LPC_pred = s_ptr[  0 ]  * PredCoef[ 0 ]  +
97                   s_ptr[ -1 ]  * PredCoef[ 1 ]  +
98                   s_ptr[ -2 ]  * PredCoef[ 2 ]  +
99                   s_ptr[ -3 ]  * PredCoef[ 3 ]  +
100                   s_ptr[ -4 ]  * PredCoef[ 4 ]  +
101                   s_ptr[ -5 ]  * PredCoef[ 5 ]  +
102                   s_ptr[ -6 ]  * PredCoef[ 6 ]  +
103                   s_ptr[ -7 ]  * PredCoef[ 7 ]  +
104                   s_ptr[ -8 ]  * PredCoef[ 8 ]  +
105                   s_ptr[ -9 ]  * PredCoef[ 9 ]  +
106                   s_ptr[ -10 ] * PredCoef[ 10 ] +
107                   s_ptr[ -11 ] * PredCoef[ 11 ];
108
109        /* prediction error */
110        r_LPC[ix] = s_ptr[ 1 ] - LPC_pred;
111    }
112}
113
114/* 10th order LPC analysis filter, does not write first 10 samples */
115static OPUS_INLINE void silk_LPC_analysis_filter10_FLP(
116          silk_float                 r_LPC[],            /* O    LPC residual signal                     */
117    const silk_float                 PredCoef[],         /* I    LPC coefficients                        */
118    const silk_float                 s[],                /* I    Input signal                            */
119    const opus_int                   length              /* I    Length of input signal                  */
120)
121{
122    opus_int   ix;
123    silk_float LPC_pred;
124    const silk_float *s_ptr;
125
126    for( ix = 10; ix < length; ix++ ) {
127        s_ptr = &s[ix - 1];
128
129        /* short-term prediction */
130        LPC_pred = s_ptr[  0 ] * PredCoef[ 0 ]  +
131                   s_ptr[ -1 ] * PredCoef[ 1 ]  +
132                   s_ptr[ -2 ] * PredCoef[ 2 ]  +
133                   s_ptr[ -3 ] * PredCoef[ 3 ]  +
134                   s_ptr[ -4 ] * PredCoef[ 4 ]  +
135                   s_ptr[ -5 ] * PredCoef[ 5 ]  +
136                   s_ptr[ -6 ] * PredCoef[ 6 ]  +
137                   s_ptr[ -7 ] * PredCoef[ 7 ]  +
138                   s_ptr[ -8 ] * PredCoef[ 8 ]  +
139                   s_ptr[ -9 ] * PredCoef[ 9 ];
140
141        /* prediction error */
142        r_LPC[ix] = s_ptr[ 1 ] - LPC_pred;
143    }
144}
145
146/* 8th order LPC analysis filter, does not write first 8 samples */
147static OPUS_INLINE void silk_LPC_analysis_filter8_FLP(
148          silk_float                 r_LPC[],            /* O    LPC residual signal                     */
149    const silk_float                 PredCoef[],         /* I    LPC coefficients                        */
150    const silk_float                 s[],                /* I    Input signal                            */
151    const opus_int                   length              /* I    Length of input signal                  */
152)
153{
154    opus_int   ix;
155    silk_float LPC_pred;
156    const silk_float *s_ptr;
157
158    for( ix = 8; ix < length; ix++ ) {
159        s_ptr = &s[ix - 1];
160
161        /* short-term prediction */
162        LPC_pred = s_ptr[  0 ] * PredCoef[ 0 ]  +
163                   s_ptr[ -1 ] * PredCoef[ 1 ]  +
164                   s_ptr[ -2 ] * PredCoef[ 2 ]  +
165                   s_ptr[ -3 ] * PredCoef[ 3 ]  +
166                   s_ptr[ -4 ] * PredCoef[ 4 ]  +
167                   s_ptr[ -5 ] * PredCoef[ 5 ]  +
168                   s_ptr[ -6 ] * PredCoef[ 6 ]  +
169                   s_ptr[ -7 ] * PredCoef[ 7 ];
170
171        /* prediction error */
172        r_LPC[ix] = s_ptr[ 1 ] - LPC_pred;
173    }
174}
175
176/* 6th order LPC analysis filter, does not write first 6 samples */
177static OPUS_INLINE void silk_LPC_analysis_filter6_FLP(
178          silk_float                 r_LPC[],            /* O    LPC residual signal                     */
179    const silk_float                 PredCoef[],         /* I    LPC coefficients                        */
180    const silk_float                 s[],                /* I    Input signal                            */
181    const opus_int                   length              /* I    Length of input signal                  */
182)
183{
184    opus_int   ix;
185    silk_float LPC_pred;
186    const silk_float *s_ptr;
187
188    for( ix = 6; ix < length; ix++ ) {
189        s_ptr = &s[ix - 1];
190
191        /* short-term prediction */
192        LPC_pred = s_ptr[  0 ] * PredCoef[ 0 ]  +
193                   s_ptr[ -1 ] * PredCoef[ 1 ]  +
194                   s_ptr[ -2 ] * PredCoef[ 2 ]  +
195                   s_ptr[ -3 ] * PredCoef[ 3 ]  +
196                   s_ptr[ -4 ] * PredCoef[ 4 ]  +
197                   s_ptr[ -5 ] * PredCoef[ 5 ];
198
199        /* prediction error */
200        r_LPC[ix] = s_ptr[ 1 ] - LPC_pred;
201    }
202}
203
204/************************************************/
205/* LPC analysis filter                          */
206/* NB! State is kept internally and the         */
207/* filter always starts with zero state         */
208/* first Order output samples are set to zero   */
209/************************************************/
210void silk_LPC_analysis_filter_FLP(
211    silk_float                      r_LPC[],                            /* O    LPC residual signal                         */
212    const silk_float                PredCoef[],                         /* I    LPC coefficients                            */
213    const silk_float                s[],                                /* I    Input signal                                */
214    const opus_int                  length,                             /* I    Length of input signal                      */
215    const opus_int                  Order                               /* I    LPC order                                   */
216)
217{
218    silk_assert( Order <= length );
219
220    switch( Order ) {
221        case 6:
222            silk_LPC_analysis_filter6_FLP(  r_LPC, PredCoef, s, length );
223        break;
224
225        case 8:
226            silk_LPC_analysis_filter8_FLP(  r_LPC, PredCoef, s, length );
227        break;
228
229        case 10:
230            silk_LPC_analysis_filter10_FLP( r_LPC, PredCoef, s, length );
231        break;
232
233        case 12:
234            silk_LPC_analysis_filter12_FLP( r_LPC, PredCoef, s, length );
235        break;
236
237        case 16:
238            silk_LPC_analysis_filter16_FLP( r_LPC, PredCoef, s, length );
239        break;
240
241        default:
242            silk_assert( 0 );
243        break;
244    }
245
246    /* Set first Order output samples to zero */
247    silk_memset( r_LPC, 0, Order * sizeof( silk_float ) );
248}
249
250