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/****************************************************************************************
19Portions 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)
26Permission to distribute, modify and use this file under the standard license
27terms 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
173void 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
251void 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