Version update 1.2.0 -> 1.3.0 (fix crash on 64bit)
[platform/upstream/opencore-amr.git] / opencore / codecs_v2 / audio / gsm_amr / amr_nb / common / src / syn_filt.cpp
1 /* ------------------------------------------------------------------
2  * Copyright (C) 1998-2009 PacketVideo
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
13  * express or implied.
14  * See the License for the specific language governing permissions
15  * and limitations under the License.
16  * -------------------------------------------------------------------
17  */
18 /****************************************************************************************
19 Portions of this file are derived from the following 3GPP standard:
20
21     3GPP TS 26.073
22     ANSI-C code for the Adaptive Multi-Rate (AMR) speech codec
23     Available from http://www.3gpp.org
24
25 (C) 2004, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
26 Permission to distribute, modify and use this file under the standard license
27 terms listed above has been obtained from the copyright holder.
28 ****************************************************************************************/
29 /*
30  Filename: syn_filt.cpp
31
32 ------------------------------------------------------------------------------
33 */
34
35 /*----------------------------------------------------------------------------
36 ; INCLUDES
37 ----------------------------------------------------------------------------*/
38 #include    "syn_filt.h"
39 #include    "cnst.h"
40 #include    "basic_op.h"
41 #include    "oscl_mem.h"
42
43 #include    "basic_op.h"
44
45 /*----------------------------------------------------------------------------
46 ; MACROS
47 ; Define module specific macros here
48 ----------------------------------------------------------------------------*/
49
50
51 /*----------------------------------------------------------------------------
52 ; DEFINES
53 ; Include all pre-processor statements here. Include conditional
54 ; compile variables also.
55 ----------------------------------------------------------------------------*/
56
57 /*----------------------------------------------------------------------------
58 ; LOCAL FUNCTION DEFINITIONS
59 ; Function Prototype declaration
60 ----------------------------------------------------------------------------*/
61
62 /*----------------------------------------------------------------------------
63 ; LOCAL STORE/BUFFER/POINTER DEFINITIONS
64 ; Variable declaration - defined here and used outside this module
65 ----------------------------------------------------------------------------*/
66
67
68 /*
69 ------------------------------------------------------------------------------
70  FUNCTION NAME: Syn_filt
71 ------------------------------------------------------------------------------
72  INPUT AND OUTPUT DEFINITIONS
73
74  Inputs:
75     a = buffer containing the prediction coefficients (Word16)  max 2^12
76     x = input signal buffer (Word16)                            max 2^15
77     y = output signal buffer (Word16)
78     lg = size of filtering (Word16)
79     mem = memory buffer associated with this filtering (Word16)
80     update = flag to indicate memory update; 0=no update, 1=update memory
81              (Word16)
82
83  Outputs:
84     mem buffer is changed to be the last M data points of the output signal
85       if update was set to 1
86     y buffer contains the newly calculated filter output
87
88  Returns:
89     None
90
91  Global Variables Used:
92     None
93
94  Local Variables Needed:
95     None
96
97 ------------------------------------------------------------------------------
98  FUNCTION DESCRIPTION
99
100  Perform synthesis filtering through 1/A(z)
101
102 ------------------------------------------------------------------------------
103  REQUIREMENTS
104
105  None
106
107 ------------------------------------------------------------------------------
108  REFERENCES
109
110  syn_filt.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
111
112 ------------------------------------------------------------------------------
113  PSEUDO-CODE
114
115 void Syn_filt (
116     Word16 a[],     // (i)     : a[M+1] prediction coefficients   (M=10)
117     Word16 x[],     // (i)     : input signal
118     Word16 y[],     // (o)     : output signal
119     Word16 lg,      // (i)     : size of filtering
120     Word16 mem[],   // (i/o)   : memory associated with this filtering.
121     Word16 update   // (i)     : 0=no update, 1=update of memory.
122 )
123 {
124     Word16 i, j;
125     Word32 s;
126     Word16 tmp[80];   // This is usually done by memory allocation (lg+M)
127     Word16 *yy;
128
129     // Copy mem[] to yy[]
130
131     yy = tmp;
132
133     for (i = 0; i < M; i++)
134     {
135         *yy++ = mem[i];
136     }
137
138     // Do the filtering.
139
140     for (i = 0; i < lg; i++)
141     {
142         s = L_mult (x[i], a[0]);
143         for (j = 1; j <= M; j++)
144         {
145             s = L_msu (s, a[j], yy[-j]);
146         }
147         s = L_shl (s, 3);
148         *yy++ = pv_round (s);
149     }
150
151     for (i = 0; i < lg; i++)
152     {
153         y[i] = tmp[i + M];
154     }
155
156     // Update of memory if update==1
157
158     if (update != 0)
159     {
160         for (i = 0; i < M; i++)
161         {
162             mem[i] = y[lg - M + i];
163         }
164     }
165     return;
166 }
167
168 ------------------------------------------------------------------------------
169  CAUTION [optional]
170  [State any special notes, constraints or cautions for users of this function]
171
172 ------------------------------------------------------------------------------
173 */
174
175 OSCL_EXPORT_REF void Syn_filt(
176     Word16 a[],     /* (i)   : a[M+1] prediction coefficients   (M=10)  */
177     Word16 x[],     /* (i)   : input signal                             */
178     Word16 y[],     /* (o)   : output signal                            */
179     Word16 lg,      /* (i)   : size of filtering   (40)                 */
180     Word16 mem[],   /* (i/o) : memory associated with this filtering.   */
181     Word16 update   /* (i)   : 0=no update, 1=update of memory.         */
182 )
183 {
184     Word16 i, j;
185     Word32 s1;
186     Word32 s2;
187     Word16 tmp[2*M]; /* This is usually done by memory allocation (lg+M) */
188     Word16 *yy;
189
190     Word16 *p_a;
191     Word16 *p_yy1;
192     Word16 *p_y;
193     Word16 *p_x;
194     Word16 temp;
195     /* Copy mem[] to yy[] */
196
197     yy = tmp;
198
199     oscl_memcpy(yy, mem, M*sizeof(Word16));
200
201     yy = yy + M;
202
203     /* Do the filtering. */
204
205     p_y  = y;
206     p_x  = x;
207     p_yy1 = &yy[-1];
208
209     for (i = M >> 1; i != 0; i--)
210     {
211         p_a  = a;
212
213         s1 = amrnb_fxp_mac_16_by_16bb((Word32) * (p_x++), (Word32) * (p_a), 0x00000800L);
214         s2 = amrnb_fxp_mac_16_by_16bb((Word32) * (p_x++), (Word32) * (p_a++), 0x00000800L);
215         s1 = amrnb_fxp_msu_16_by_16bb((Word32) * (p_a++), (Word32) * (p_yy1), s1);
216
217         for (j = (M >> 1) - 2; j != 0; j--)
218         {
219             s2 = amrnb_fxp_msu_16_by_16bb((Word32) * (p_a), (Word32) * (p_yy1--), s2);
220             s1 = amrnb_fxp_msu_16_by_16bb((Word32) * (p_a++), (Word32) * (p_yy1), s1);
221             s2 = amrnb_fxp_msu_16_by_16bb((Word32) * (p_a), (Word32) * (p_yy1--), s2);
222             s1 = amrnb_fxp_msu_16_by_16bb((Word32) * (p_a++), (Word32) * (p_yy1), s1);
223             s2 = amrnb_fxp_msu_16_by_16bb((Word32) * (p_a), (Word32) * (p_yy1--), s2);
224             s1 = amrnb_fxp_msu_16_by_16bb((Word32) * (p_a++), (Word32) * (p_yy1), s1);
225         }
226
227         /* check for overflow on s1 */
228         if ((UWord32)(s1 + 134217728) < 0x0fffffffL)
229         {
230             temp = (Word16)(s1 >> 12);
231         }
232         else if (s1 > 0x07ffffffL)
233         {
234             temp = MAX_16;
235         }
236         else
237         {
238             temp = MIN_16;
239         }
240
241         s2 = amrnb_fxp_msu_16_by_16bb((Word32)a[1], (Word32)temp, s2);
242
243         *(yy++)  = temp;
244         *(p_y++) = temp;
245
246         p_yy1 = yy;
247
248         /* check for overflow on s2 */
249         if ((UWord32)(s2 + 134217728) < 0x0fffffffL)
250         {
251             temp = (Word16)(s2 >> 12);
252         }
253         else if (s2 > 0x07ffffffL)
254         {
255             temp = MAX_16;
256         }
257         else
258         {
259             temp = MIN_16;
260         }
261
262         *(yy++)  = temp;
263         *(p_y++) = temp;
264     }
265
266     p_yy1 = &y[M-1];
267
268     for (i = (lg - M) >> 1; i != 0; i--)
269     {
270         p_a  = a;
271
272         s1 = amrnb_fxp_mac_16_by_16bb((Word32) * (p_x++), (Word32) * (p_a), 0x00000800L);
273         s2 = amrnb_fxp_mac_16_by_16bb((Word32) * (p_x++), (Word32) * (p_a++), 0x00000800L);
274         s1 = amrnb_fxp_msu_16_by_16bb((Word32) * (p_a++), (Word32) * (p_yy1), s1);
275
276         for (j = (M >> 1) - 2; j != 0; j--)
277         {
278             s2 = amrnb_fxp_msu_16_by_16bb((Word32) * (p_a), (Word32) * (p_yy1--), s2);
279             s1 = amrnb_fxp_msu_16_by_16bb((Word32) * (p_a++), (Word32) * (p_yy1), s1);
280             s2 = amrnb_fxp_msu_16_by_16bb((Word32) * (p_a), (Word32) * (p_yy1--), s2);
281             s1 = amrnb_fxp_msu_16_by_16bb((Word32) * (p_a++), (Word32) * (p_yy1), s1);
282             s2 = amrnb_fxp_msu_16_by_16bb((Word32) * (p_a), (Word32) * (p_yy1--), s2);
283             s1 = amrnb_fxp_msu_16_by_16bb((Word32) * (p_a++), (Word32) * (p_yy1), s1);
284         }
285
286         if ((UWord32)(s1 + 134217728) < 0x0fffffffL)
287         {
288             temp = (Word16)(s1 >> 12);
289         }
290         else if (s1 > 0x07ffffffL)
291         {
292             temp = MAX_16;
293         }
294         else
295         {
296             temp = MIN_16;
297         }
298
299         s2 = amrnb_fxp_msu_16_by_16bb((Word32)a[1], (Word32)temp, s2);
300
301         *(p_y++) = temp;
302         p_yy1 = p_y;
303
304         if ((UWord32)(s2 + 134217728) < 0x0fffffffL)
305         {
306             *(p_y++) = (Word16)(s2 >> 12);
307         }
308         else if (s2 > 0x07ffffffL)
309         {
310             *(p_y++) = MAX_16;
311         }
312         else
313         {
314             *(p_y++) = MIN_16;
315         }
316     }
317
318     /* Update of memory if update==1 */
319     if (update != 0)
320     {
321         oscl_memcpy(mem, &y[lg-M], M*sizeof(Word16));
322     }
323
324     return;
325 }