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