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 ------------------------------------------------------------------------------
31 
32 
33 
34  Pathname: ./audio/gsm-amr/c/src/post_pro.c
35  Functions:
36            Post_Process_reset
37            Post_Process
38 
39      Date: 04/03/2000
40 
41 ------------------------------------------------------------------------------
42  REVISION HISTORY
43 
44  Description: Updated template used to PV coding template. First attempt at
45           optimizing C code.
46 
47  Description: Deleted variables listed in the Local Stores Needed/Modified
48           sections. Optimized the "else" portion of the first "if"
49           statement in Post_Process function.
50 
51  Description: Made grouping more explicit in the calculation of
52           signal[i] << 1 in the Post_Process function.
53 
54  Description: Added setting of Overflow flag in inlined code.
55 
56  Description: Synchronized file with UMTS version 3.2.0. Updated coding
57               template. Removed unnecessary include files.
58 
59  Description: Replaced basic_op.h with the header file of the math functions
60               used in the file.
61 
62  Description: Made the following changes per comments from Phase 2/3 review:
63               1. Updated copyright year.
64               2. Fixed typecasting issue with TI C compiler.
65               3. Used short-hand notation for math operations, e.g., "+=",
66                  in the code.
67 
68  Description: Removed the functions post_pro_init and post_pro_exit.
69  The post_pro related structure is no longer dynamically allocated.
70 
71  Description: Added pOverflow as a passed in variable as per changes needed
72               for the EPOC release.
73 
74  Description: Optimized file to reduce clock cycle usage. Updated copyright
75               year and removed unused files in Include section.
76 
77  Description:  Replaced OSCL mem type functions and eliminated include
78                files that now are chosen by OSCL definitions
79 
80  Description:  Replaced "int" and/or "char" with OSCL defined types.
81 
82  Description: Changed round function name to pv_round to avoid conflict with
83               round function in C standard library.
84 
85  Description:
86 
87 ------------------------------------------------------------------------------
88  MODULE DESCRIPTION
89 
90  This file contains the function that performs post-processing on the output
91  speech. Post-processing include filtering the output speech through a second
92  order high pass filter with cutoff frequency of 60 Hz, and up-scaling the
93  output speech by a factor of 2. In addition to the post-processing function
94  itself, a post-processing initialization function, post-processing reset
95  function, and post-processing exit function are also included in this file.
96 
97 ------------------------------------------------------------------------------
98 */
99 
100 
101 /*----------------------------------------------------------------------------
102 ; INCLUDES
103 ----------------------------------------------------------------------------*/
104 #include "post_pro.h"
105 #include "typedef.h"
106 #include "basic_op.h"
107 
108 /*----------------------------------------------------------------------------
109 ; MACROS
110 ; Define module specific macros here
111 ----------------------------------------------------------------------------*/
112 
113 
114 /*----------------------------------------------------------------------------
115 ; DEFINES
116 ; Include all pre-processor statements here. Include conditional
117 ; compile variables also.
118 ----------------------------------------------------------------------------*/
119 
120 /*----------------------------------------------------------------------------
121 ; LOCAL FUNCTION DEFINITIONS
122 ; Function Prototype declaration
123 ----------------------------------------------------------------------------*/
124 
125 /*----------------------------------------------------------------------------
126 ; LOCAL VARIABLE DEFINITIONS
127 ; Variable declaration - defined here and used outside this module
128 ----------------------------------------------------------------------------*/
129 
130 /* filter coefficients (fc = 60 Hz) */
131 static const Word16 b[3] = {7699, -15398, 7699};
132 static const Word16 a[3] = {8192, 15836, -7667};
133 
134 /*
135 ------------------------------------------------------------------------------
136  FUNCTION NAME: Post_Process_reset
137 ------------------------------------------------------------------------------
138  INPUT AND OUTPUT DEFINITIONS
139 
140  Inputs:
141     state = pointer to a structure of type Post_ProcessState
142 
143  Outputs:
144     structure pointed to by state will have all its fields initialized
145       to zero
146 
147  Returns:
148     return_value = 0, if reset was successful; -1, otherwise (int)
149 
150  Global Variables Used:
151     None
152 
153  Local Variables Needed:
154     None
155 
156 ------------------------------------------------------------------------------
157  FUNCTION DESCRIPTION
158 
159  This function initializes state memory to zero.
160 
161 ------------------------------------------------------------------------------
162  REQUIREMENTS
163 
164  None
165 
166 ------------------------------------------------------------------------------
167  REFERENCES
168 
169  post_pro.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
170 
171 ------------------------------------------------------------------------------
172  PSEUDO-CODE
173 
174 int Post_Process_reset (Post_ProcessState *state)
175 {
176   if (state == (Post_ProcessState *) NULL){
177       fprint(stderr, "Post_Process_reset: invalid parameter\n");
178       return -1;
179   }
180 
181   state->y2_hi = 0;
182   state->y2_lo = 0;
183   state->y1_hi = 0;
184   state->y1_lo = 0;
185   state->x0 = 0;
186   state->x1 = 0;
187 
188   return 0;
189 }
190 ------------------------------------------------------------------------------
191  RESOURCES USED [optional]
192 
193  When the code is written for a specific target processor the
194  the resources used should be documented below.
195 
196  HEAP MEMORY USED: x bytes
197 
198  STACK MEMORY USED: x bytes
199 
200  CLOCK CYCLES: (cycle count equation for this function) + (variable
201                 used to represent cycle count for each subroutine
202                 called)
203      where: (cycle count variable) = cycle count for [subroutine
204                                      name]
205 
206 ------------------------------------------------------------------------------
207  CAUTION [optional]
208  [State any special notes, constraints or cautions for users of this function]
209 
210 ------------------------------------------------------------------------------
211 */
212 
Post_Process_reset(Post_ProcessState * state)213 Word16 Post_Process_reset(Post_ProcessState *state)
214 {
215     if (state == (Post_ProcessState *) NULL)
216     {
217         /*  fprint(stderr, "Post_Process_reset: invalid parameter\n");  */
218         return(-1);
219     }
220 
221     state->y2_hi = 0;
222     state->y2_lo = 0;
223     state->y1_hi = 0;
224     state->y1_lo = 0;
225     state->x0 = 0;
226     state->x1 = 0;
227 
228     return(0);
229 }
230 
231 /****************************************************************************/
232 
233 /*
234 ------------------------------------------------------------------------------
235  FUNCTION NAME: Post_Process
236 ------------------------------------------------------------------------------
237  INPUT AND OUTPUT DEFINITIONS
238 
239  Inputs:
240     st = pointer to a structure of type Post_ProcessState
241     signal = buffer containing the input signal (Word16)
242     lg = length of the input signal (Word16)
243     pOverflow = pointer to overflow indicator of type Flag
244 
245  Outputs:
246     structure pointed to by st contains new filter input and output values
247     signal buffer contains the HP filtered and up-scaled input signal
248     pOverflow points to 1 if overflow occurs in the math functions called
249               else it points to 0.
250 
251  Returns:
252     return_value = 0 (int)
253 
254  Global Variables Used:
255     a = buffer containing filter coefficients
256     b = buffer containing filter coefficients
257 
258  Local Variables Needed:
259     None
260 
261 ------------------------------------------------------------------------------
262  FUNCTION DESCRIPTION
263 
264  This function performs post-processing on the output speech signal. First,
265  the output speech goes through a second order high pass filter with a
266  cutoff frequency of 60 Hz. Then, the filtered output speech is multiplied
267  by a factor of 2. The algorithm implemented follows the following difference
268  equation:
269 
270  y[i] = b[0]*x[i]*2 + b[1]*x[i-1]*2 + b[2]*x[i-2]*2 + a[1]*y[i-1] + a[2]*y[i-2];
271 
272 ------------------------------------------------------------------------------
273  REQUIREMENTS
274 
275  None
276 
277 ------------------------------------------------------------------------------
278  REFERENCES
279 
280  post_pro.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
281 
282 ------------------------------------------------------------------------------
283  PSEUDO-CODE
284 
285 int Post_Process (
286     Post_ProcessState *st,  //i/o : post process state
287     Word16 signal[],        //i/o : signal
288     Word16 lg               //i   : length of signal
289     )
290 {
291     Word16 i, x2;
292     Word32 L_tmp;
293 
294     for (i = 0; i < lg; i++)
295     {
296         x2 = st->x1;
297         st->x1 = st->x0;
298         st->x0 = signal[i];
299 
300         // y[i] = b[0]*x[i]*2 + b[1]*x[i-1]*2 + b140[2]*x[i-2]/2
301         //                    + a[1]*y[i-1] + a[2] * y[i-2];
302 
303         L_tmp = Mpy_32_16 (st->y1_hi, st->y1_lo, a[1]);
304         L_tmp = L_add (L_tmp, Mpy_32_16 (st->y2_hi, st->y2_lo, a[2]));
305         L_tmp = L_mac (L_tmp, st->x0, b[0]);
306         L_tmp = L_mac (L_tmp, st->x1, b[1]);
307         L_tmp = L_mac (L_tmp, x2, b[2]);
308         L_tmp = L_shl (L_tmp, 2);
309 
310         //Multiplication by two of output speech with saturation.
311         signal[i] = pv_round(L_shl(L_tmp, 1));
312 
313         st->y2_hi = st->y1_hi;
314         st->y2_lo = st->y1_lo;
315         L_Extract (L_tmp, &st->y1_hi, &st->y1_lo);
316     }
317 
318     return 0;
319 }
320 
321 ------------------------------------------------------------------------------
322  RESOURCES USED [optional]
323 
324  When the code is written for a specific target processor the
325  the resources used should be documented below.
326 
327  HEAP MEMORY USED: x bytes
328 
329  STACK MEMORY USED: x bytes
330 
331  CLOCK CYCLES: (cycle count equation for this function) + (variable
332                 used to represent cycle count for each subroutine
333                 called)
334      where: (cycle count variable) = cycle count for [subroutine
335                                      name]
336 
337 ------------------------------------------------------------------------------
338  CAUTION [optional]
339  [State any special notes, constraints or cautions for users of this function]
340 
341 ------------------------------------------------------------------------------
342 */
343 
Post_Process(Post_ProcessState * st,Word16 signal[],Word16 lg,Flag * pOverflow)344 void Post_Process(
345     Post_ProcessState *st,  /* i/o : post process state                   */
346     Word16 signal[],        /* i/o : signal                               */
347     Word16 lg,              /* i   : length of signal                     */
348     Flag   *pOverflow
349 )
350 {
351     Word16 i, x2;
352     Word32 L_tmp;
353 
354     Word16 *p_signal;
355     Word16 c_a1 = a[1];
356     Word16 c_a2 = a[2];
357     Word16 c_b0 = b[0];
358     Word16 c_b1 = b[1];
359     Word16 c_b2 = b[2];
360 
361     p_signal = &signal[0];
362 
363     for (i = 0; i < lg; i++)
364     {
365         x2 = st->x1;
366         st->x1 = st->x0;
367         st->x0 = *(p_signal);
368 
369         /*  y[i] = b[0]*x[i]*2 + b[1]*x[i-1]*2 + b140[2]*x[i-2]/2  */
370         /*                     + a[1]*y[i-1] + a[2] * y[i-2];      */
371 
372         L_tmp = ((Word32) st->y1_hi) * c_a1;
373         L_tmp += (((Word32) st->y1_lo) * c_a1) >> 15;
374         L_tmp += ((Word32) st->y2_hi) * c_a2;
375         L_tmp += (((Word32) st->y2_lo) * c_a2) >> 15;
376         L_tmp += ((Word32) st->x0) * c_b0;
377         L_tmp += ((Word32) st->x1) * c_b1;
378         L_tmp += ((Word32) x2) * c_b2;
379         L_tmp = L_shl(L_tmp, 3, pOverflow);
380 
381 
382         /* Multiplication by two of output speech with saturation. */
383 
384         *(p_signal++) = pv_round(L_shl(L_tmp, 1, pOverflow), pOverflow);
385 
386         st->y2_hi = st->y1_hi;
387         st->y2_lo = st->y1_lo;
388 
389         st->y1_hi = (Word16)(L_tmp >> 16);
390         st->y1_lo = (Word16)((L_tmp >> 1) - ((Word32) st->y1_hi << 15));
391 
392     }
393 
394     return;
395 }
396