xref: /aosp_15_r20/frameworks/av/media/module/codecs/amrnb/common/src/syn_filt.cpp (revision ec779b8e0859a360c3d303172224686826e6e0e1)
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 */
Syn_filt(Word16 a[],Word16 x[],Word16 y[],Word16 lg,Word16 mem[],Word16 update)248 void Syn_filt(
249     Word16 a[],     /* (i)   : a[M+1] prediction coefficients   (M=10)  */
250     Word16 x[],     /* (i)   : input signal                             */
251     Word16 y[],     /* (o)   : output signal                            */
252     Word16 lg,      /* (i)   : size of filtering   (40)                 */
253     Word16 mem[],   /* (i/o) : memory associated with this filtering.   */
254     Word16 update   /* (i)   : 0=no update, 1=update of memory.         */
255 )
256 {
257     Word16 i, j;
258     Word32 s1;
259     Word32 s2;
260     Word16 tmp[2*M]; /* This is usually done by memory allocation (lg+M) */
261     Word16 *yy;
262 
263     Word16 *p_a;
264     Word16 *p_yy1;
265     Word16 *p_y;
266     Word16 *p_x;
267     Word16 temp;
268     /* Copy mem[] to yy[] */
269 
270     yy = tmp;
271 
272     memcpy(yy, mem, M*sizeof(Word16));
273 
274     yy = yy + M;
275 
276     /* Do the filtering. */
277 
278     p_y  = y;
279     p_x  = x;
280     p_yy1 = &yy[-1];
281 
282     for (i = M >> 1; i != 0; i--)
283     {
284         p_a  = a;
285 
286         s1 = amrnb_fxp_mac_16_by_16bb((Word32) * (p_x++), (Word32) * (p_a), 0x00000800L);
287         s2 = amrnb_fxp_mac_16_by_16bb((Word32) * (p_x++), (Word32) * (p_a++), 0x00000800L);
288         s1 = amrnb_fxp_msu_16_by_16bb((Word32) * (p_a++), (Word32) * (p_yy1), s1);
289 
290         for (j = (M >> 1) - 2; j != 0; j--)
291         {
292             s2 = amrnb_fxp_msu_16_by_16bb((Word32) * (p_a), (Word32) * (p_yy1--), s2);
293             s1 = amrnb_fxp_msu_16_by_16bb((Word32) * (p_a++), (Word32) * (p_yy1), s1);
294             s2 = amrnb_fxp_msu_16_by_16bb((Word32) * (p_a), (Word32) * (p_yy1--), s2);
295             s1 = amrnb_fxp_msu_16_by_16bb((Word32) * (p_a++), (Word32) * (p_yy1), s1);
296             s2 = amrnb_fxp_msu_16_by_16bb((Word32) * (p_a), (Word32) * (p_yy1--), s2);
297             s1 = amrnb_fxp_msu_16_by_16bb((Word32) * (p_a++), (Word32) * (p_yy1), s1);
298         }
299 
300         /* check for overflow on s1 */
301         if ((UWord32)(s1 - 0xf8000000L) < 0x0fffffffL)
302         {
303             temp = (Word16)(s1 >> 12);
304         }
305         else if (s1 > 0x07ffffffL)
306         {
307             temp = MAX_16;
308         }
309         else
310         {
311             temp = MIN_16;
312         }
313 
314         s2 = amrnb_fxp_msu_16_by_16bb((Word32)a[1], (Word32)temp, s2);
315 
316         *(yy++)  = temp;
317         *(p_y++) = temp;
318 
319         p_yy1 = yy;
320 
321         /* check for overflow on s2 */
322         if ((UWord32)(s2 - 0xf8000000L) < 0x0fffffffL)
323         {
324             temp = (Word16)(s2 >> 12);
325         }
326         else if (s2 > 0x07ffffffL)
327         {
328             temp = MAX_16;
329         }
330         else
331         {
332             temp = MIN_16;
333         }
334 
335         *(yy++)  = temp;
336         *(p_y++) = temp;
337     }
338 
339     p_yy1 = &y[M-1];
340 
341     for (i = (lg - M) >> 1; i != 0; i--)
342     {
343         p_a  = a;
344 
345         s1 = amrnb_fxp_mac_16_by_16bb((Word32) * (p_x++), (Word32) * (p_a), 0x00000800L);
346         s2 = amrnb_fxp_mac_16_by_16bb((Word32) * (p_x++), (Word32) * (p_a++), 0x00000800L);
347         s1 = amrnb_fxp_msu_16_by_16bb((Word32) * (p_a++), (Word32) * (p_yy1), s1);
348 
349         for (j = (M >> 1) - 2; j != 0; j--)
350         {
351             s2 = amrnb_fxp_msu_16_by_16bb((Word32) * (p_a), (Word32) * (p_yy1--), s2);
352             s1 = amrnb_fxp_msu_16_by_16bb((Word32) * (p_a++), (Word32) * (p_yy1), s1);
353             s2 = amrnb_fxp_msu_16_by_16bb((Word32) * (p_a), (Word32) * (p_yy1--), s2);
354             s1 = amrnb_fxp_msu_16_by_16bb((Word32) * (p_a++), (Word32) * (p_yy1), s1);
355             s2 = amrnb_fxp_msu_16_by_16bb((Word32) * (p_a), (Word32) * (p_yy1--), s2);
356             s1 = amrnb_fxp_msu_16_by_16bb((Word32) * (p_a++), (Word32) * (p_yy1), s1);
357         }
358 
359         if ((UWord32)(s1 - 0xf8000000L) < 0x0fffffffL)
360         {
361             temp = (Word16)(s1 >> 12);
362         }
363         else if (s1 > 0x07ffffffL)
364         {
365             temp = MAX_16;
366         }
367         else
368         {
369             temp = MIN_16;
370         }
371 
372         s2 = amrnb_fxp_msu_16_by_16bb((Word32)a[1], (Word32)temp, s2);
373 
374         *(p_y++) = temp;
375         p_yy1 = p_y;
376 
377         if ((UWord32)(s2 - 0xf8000000L) < 0x0fffffffL)
378         {
379             *(p_y++) = (Word16)(s2 >> 12);
380         }
381         else if (s2 > 0x07ffffffL)
382         {
383             *(p_y++) = MAX_16;
384         }
385         else
386         {
387             *(p_y++) = MIN_16;
388         }
389     }
390 
391     /* Update of memory if update==1 */
392     if (update != 0)
393     {
394         memcpy(mem, &y[lg-M], M*sizeof(Word16));
395     }
396 
397     return;
398 }
399