• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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  Pathname: ./audio/gsm-amr/c/src/syn_filt.c
31 
32 ------------------------------------------------------------------------------
33  REVISION HISTORY
34 
35  Description: Making changes based on comments from the review meeting.
36 
37  Description: Added typedef to Input/Output Definition section.
38 
39  Description: Synchronized file with UMTS version 3.2.0. Updated coding
40               template.
41 
42  Description: Fixed typecasting issue with the TI C compiler.
43 
44  Description: Modified FOR loops to count down.
45 
46  Description: Modified FOR loop to count up again so that the correct values
47               are stored in the tmp buffer. Updated copyright year.
48 
49  Description:
50         - Modified for loop and introduced pointers to avoid adding
51           offsets
52         - Eliminated check for saturation given that the max values of input
53           data and coefficients will not saturate the multiply and
54           accumulation
55         - eliminated memcpy to update history buffer in every pass. This is
56           done now just updating the pointers.
57 
58  Description:
59               1. Eliminated unused include files.
60               2. Unrolled loops to process twice as many samples as before,
61                  this saves on memory accesses to the vector coeff. a[] and
62                  elements in the history buffer of this recursive filter
63 
64  Description:
65               1. Added overflow check inside both loops. (this is needed just
66                  to satisfy bit exactness on the decoder, a faster
67                  implementation will add an extra shift, do the same,
68                  but will not be bit exact, and it may have better audio
69                  quality because will avoid clipping)
70               2. Added include file for constant definitions
71 
72  Description:  Replaced OSCL mem type functions and eliminated include
73                files that now are chosen by OSCL definitions
74 
75  Description:  Replaced "int" and/or "char" with OSCL defined types.
76 
77  Description: Changed round function name to pv_round to avoid conflict with
78               round function in C standard library.
79 
80  Description: Using fxp_arithmetic.h that includes inline assembly functions
81               for ARM and linux-arm.
82 
83  Description: Replacing fxp_arithmetic.h with basic_op.h.
84 
85  Who:                           Date:
86  Description:
87 
88 ------------------------------------------------------------------------------
89 */
90 
91 /*----------------------------------------------------------------------------
92 ; INCLUDES
93 ----------------------------------------------------------------------------*/
94 
95 #include <string.h>
96 
97 #include    "syn_filt.h"
98 #include    "cnst.h"
99 #include    "basic_op.h"
100 
101 #include    "basic_op.h"
102 
103 /*----------------------------------------------------------------------------
104 ; MACROS
105 ; Define module specific macros here
106 ----------------------------------------------------------------------------*/
107 
108 
109 /*----------------------------------------------------------------------------
110 ; DEFINES
111 ; Include all pre-processor statements here. Include conditional
112 ; compile variables also.
113 ----------------------------------------------------------------------------*/
114 
115 /*----------------------------------------------------------------------------
116 ; LOCAL FUNCTION DEFINITIONS
117 ; Function Prototype declaration
118 ----------------------------------------------------------------------------*/
119 
120 /*----------------------------------------------------------------------------
121 ; LOCAL STORE/BUFFER/POINTER DEFINITIONS
122 ; Variable declaration - defined here and used outside this module
123 ----------------------------------------------------------------------------*/
124 
125 
126 /*
127 ------------------------------------------------------------------------------
128  FUNCTION NAME: Syn_filt
129 ------------------------------------------------------------------------------
130  INPUT AND OUTPUT DEFINITIONS
131 
132  Inputs:
133     a = buffer containing the prediction coefficients (Word16)  max 2^12
134     x = input signal buffer (Word16)                            max 2^15
135     y = output signal buffer (Word16)
136     lg = size of filtering (Word16)
137     mem = memory buffer associated with this filtering (Word16)
138     update = flag to indicate memory update; 0=no update, 1=update memory
139              (Word16)
140 
141  Outputs:
142     mem buffer is changed to be the last M data points of the output signal
143       if update was set to 1
144     y buffer contains the newly calculated filter output
145 
146  Returns:
147     None
148 
149  Global Variables Used:
150     None
151 
152  Local Variables Needed:
153     None
154 
155 ------------------------------------------------------------------------------
156  FUNCTION DESCRIPTION
157 
158  Perform synthesis filtering through 1/A(z)
159 
160 ------------------------------------------------------------------------------
161  REQUIREMENTS
162 
163  None
164 
165 ------------------------------------------------------------------------------
166  REFERENCES
167 
168  syn_filt.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
169 
170 ------------------------------------------------------------------------------
171  PSEUDO-CODE
172 
173 void Syn_filt (
174     Word16 a[],     // (i)     : a[M+1] prediction coefficients   (M=10)
175     Word16 x[],     // (i)     : input signal
176     Word16 y[],     // (o)     : output signal
177     Word16 lg,      // (i)     : size of filtering
178     Word16 mem[],   // (i/o)   : memory associated with this filtering.
179     Word16 update   // (i)     : 0=no update, 1=update of memory.
180 )
181 {
182     Word16 i, j;
183     Word32 s;
184     Word16 tmp[80];   // This is usually done by memory allocation (lg+M)
185     Word16 *yy;
186 
187     // Copy mem[] to yy[]
188 
189     yy = tmp;
190 
191     for (i = 0; i < M; i++)
192     {
193         *yy++ = mem[i];
194     }
195 
196     // Do the filtering.
197 
198     for (i = 0; i < lg; i++)
199     {
200         s = L_mult (x[i], a[0]);
201         for (j = 1; j <= M; j++)
202         {
203             s = L_msu (s, a[j], yy[-j]);
204         }
205         s = L_shl (s, 3);
206         *yy++ = pv_round (s);
207     }
208 
209     for (i = 0; i < lg; i++)
210     {
211         y[i] = tmp[i + M];
212     }
213 
214     // Update of memory if update==1
215 
216     if (update != 0)
217     {
218         for (i = 0; i < M; i++)
219         {
220             mem[i] = y[lg - M + i];
221         }
222     }
223     return;
224 }
225 
226 ------------------------------------------------------------------------------
227  RESOURCES USED [optional]
228 
229  When the code is written for a specific target processor the
230  the resources used should be documented below.
231 
232  HEAP MEMORY USED: x bytes
233 
234  STACK MEMORY USED: x bytes
235 
236  CLOCK CYCLES: (cycle count equation for this function) + (variable
237                 used to represent cycle count for each subroutine
238                 called)
239      where: (cycle count variable) = cycle count for [subroutine
240                                      name]
241 
242 ------------------------------------------------------------------------------
243  CAUTION [optional]
244  [State any special notes, constraints or cautions for users of this function]
245 
246 ------------------------------------------------------------------------------
247 */
248 #ifdef __clang__
249 __attribute__((no_sanitize("integer")))
250 #endif
Syn_filt(Word16 a[],Word16 x[],Word16 y[],Word16 lg,Word16 mem[],Word16 update)251 void Syn_filt(
252     Word16 a[],     /* (i)   : a[M+1] prediction coefficients   (M=10)  */
253     Word16 x[],     /* (i)   : input signal                             */
254     Word16 y[],     /* (o)   : output signal                            */
255     Word16 lg,      /* (i)   : size of filtering   (40)                 */
256     Word16 mem[],   /* (i/o) : memory associated with this filtering.   */
257     Word16 update   /* (i)   : 0=no update, 1=update of memory.         */
258 )
259 {
260     Word16 i, j;
261     Word32 s1;
262     Word32 s2;
263     Word16 tmp[2*M]; /* This is usually done by memory allocation (lg+M) */
264     Word16 *yy;
265 
266     Word16 *p_a;
267     Word16 *p_yy1;
268     Word16 *p_y;
269     Word16 *p_x;
270     Word16 temp;
271     /* Copy mem[] to yy[] */
272 
273     yy = tmp;
274 
275     memcpy(yy, mem, M*sizeof(Word16));
276 
277     yy = yy + M;
278 
279     /* Do the filtering. */
280 
281     p_y  = y;
282     p_x  = x;
283     p_yy1 = &yy[-1];
284 
285     for (i = M >> 1; i != 0; i--)
286     {
287         p_a  = a;
288 
289         s1 = amrnb_fxp_mac_16_by_16bb((Word32) * (p_x++), (Word32) * (p_a), 0x00000800L);
290         s2 = amrnb_fxp_mac_16_by_16bb((Word32) * (p_x++), (Word32) * (p_a++), 0x00000800L);
291         s1 = amrnb_fxp_msu_16_by_16bb((Word32) * (p_a++), (Word32) * (p_yy1), s1);
292 
293         for (j = (M >> 1) - 2; j != 0; j--)
294         {
295             s2 = amrnb_fxp_msu_16_by_16bb((Word32) * (p_a), (Word32) * (p_yy1--), s2);
296             s1 = amrnb_fxp_msu_16_by_16bb((Word32) * (p_a++), (Word32) * (p_yy1), s1);
297             s2 = amrnb_fxp_msu_16_by_16bb((Word32) * (p_a), (Word32) * (p_yy1--), s2);
298             s1 = amrnb_fxp_msu_16_by_16bb((Word32) * (p_a++), (Word32) * (p_yy1), s1);
299             s2 = amrnb_fxp_msu_16_by_16bb((Word32) * (p_a), (Word32) * (p_yy1--), s2);
300             s1 = amrnb_fxp_msu_16_by_16bb((Word32) * (p_a++), (Word32) * (p_yy1), s1);
301         }
302 
303         /* check for overflow on s1 */
304         if ((UWord32)(s1 - 0xf8000000L) < 0x0fffffffL)
305         {
306             temp = (Word16)(s1 >> 12);
307         }
308         else if (s1 > 0x07ffffffL)
309         {
310             temp = MAX_16;
311         }
312         else
313         {
314             temp = MIN_16;
315         }
316 
317         s2 = amrnb_fxp_msu_16_by_16bb((Word32)a[1], (Word32)temp, s2);
318 
319         *(yy++)  = temp;
320         *(p_y++) = temp;
321 
322         p_yy1 = yy;
323 
324         /* check for overflow on s2 */
325         if ((UWord32)(s2 - 0xf8000000L) < 0x0fffffffL)
326         {
327             temp = (Word16)(s2 >> 12);
328         }
329         else if (s2 > 0x07ffffffL)
330         {
331             temp = MAX_16;
332         }
333         else
334         {
335             temp = MIN_16;
336         }
337 
338         *(yy++)  = temp;
339         *(p_y++) = temp;
340     }
341 
342     p_yy1 = &y[M-1];
343 
344     for (i = (lg - M) >> 1; i != 0; i--)
345     {
346         p_a  = a;
347 
348         s1 = amrnb_fxp_mac_16_by_16bb((Word32) * (p_x++), (Word32) * (p_a), 0x00000800L);
349         s2 = amrnb_fxp_mac_16_by_16bb((Word32) * (p_x++), (Word32) * (p_a++), 0x00000800L);
350         s1 = amrnb_fxp_msu_16_by_16bb((Word32) * (p_a++), (Word32) * (p_yy1), s1);
351 
352         for (j = (M >> 1) - 2; j != 0; j--)
353         {
354             s2 = amrnb_fxp_msu_16_by_16bb((Word32) * (p_a), (Word32) * (p_yy1--), s2);
355             s1 = amrnb_fxp_msu_16_by_16bb((Word32) * (p_a++), (Word32) * (p_yy1), s1);
356             s2 = amrnb_fxp_msu_16_by_16bb((Word32) * (p_a), (Word32) * (p_yy1--), s2);
357             s1 = amrnb_fxp_msu_16_by_16bb((Word32) * (p_a++), (Word32) * (p_yy1), s1);
358             s2 = amrnb_fxp_msu_16_by_16bb((Word32) * (p_a), (Word32) * (p_yy1--), s2);
359             s1 = amrnb_fxp_msu_16_by_16bb((Word32) * (p_a++), (Word32) * (p_yy1), s1);
360         }
361 
362         if ((UWord32)(s1 - 0xf8000000L) < 0x0fffffffL)
363         {
364             temp = (Word16)(s1 >> 12);
365         }
366         else if (s1 > 0x07ffffffL)
367         {
368             temp = MAX_16;
369         }
370         else
371         {
372             temp = MIN_16;
373         }
374 
375         s2 = amrnb_fxp_msu_16_by_16bb((Word32)a[1], (Word32)temp, s2);
376 
377         *(p_y++) = temp;
378         p_yy1 = p_y;
379 
380         if ((UWord32)(s2 - 0xf8000000L) < 0x0fffffffL)
381         {
382             *(p_y++) = (Word16)(s2 >> 12);
383         }
384         else if (s2 > 0x07ffffffL)
385         {
386             *(p_y++) = MAX_16;
387         }
388         else
389         {
390             *(p_y++) = MIN_16;
391         }
392     }
393 
394     /* Update of memory if update==1 */
395     if (update != 0)
396     {
397         memcpy(mem, &y[lg-M], M*sizeof(Word16));
398     }
399 
400     return;
401 }
402