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