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/pstfilt.c
35 Functions:
36 Post_Filter_reset
37 Post_Filter
38
39 Date: 04/14/2000
40
41 ------------------------------------------------------------------------------
42 REVISION HISTORY
43
44 Description: Changed template used to PV coding template. First attempt at
45 optimizing C code.
46
47 Description: Updated file per comments gathered from Phase 2/3 review.
48
49 Description: Added setting of Overflow flag in inlined code.
50
51 Description: Synchronized file with UMTS version 3.2.0. Updated coding
52 template. Removed unnecessary include files.
53
54 Description: Replaced basic_op.h with the header file of the math functions
55 used in the file.
56
57 Description: Made the following changes per comments from Phase 2/3 review:
58 1. Updated copyright year.
59 2. Modified FOR loops to count down.
60 3. Fixed typecasting issue with TI C compiler.
61 4. Added "break" statement after overflow condition occurs.
62
63 Description: Removed the functions pstfilt_init and pstfilt_exit.
64 The pst_filt related structure is no longer dynamically allocated.
65
66 Description: Modified code for EPOC changes where pOverflow is passed in
67 rather than allowing overflow to be a global variable.
68
69 Description: Replaced OSCL mem type functions and eliminated include
70 files that now are chosen by OSCL definitions
71
72 Description: Replaced "int" and/or "char" with defined types.
73 Added proper casting (Word32) to some left shifting operations
74
75 Description:
76
77 ------------------------------------------------------------------------------
78 MODULE DESCRIPTION
79
80 This file contains the function that performs adaptive post-filtering on the
81 synthesized speech. It also contains the functions that initialize, reset,
82 and exit the post-filtering function.
83
84 ------------------------------------------------------------------------------
85 */
86
87 /*----------------------------------------------------------------------------
88 ; INCLUDES
89 ----------------------------------------------------------------------------*/
90 #include <string.h>
91
92 #include "pstfilt.h"
93 #include "typedef.h"
94 #include "mode.h"
95 #include "basicop_malloc.h"
96 #include "basic_op.h"
97 #include "weight_a.h"
98 #include "residu.h"
99 #include "copy.h"
100 #include "syn_filt.h"
101 #include "preemph.h"
102 #include "cnst.h"
103
104 /*----------------------------------------------------------------------------
105 ; MACROS
106 ; Define module specific macros here
107 ----------------------------------------------------------------------------*/
108
109 /*----------------------------------------------------------------------------
110 ; DEFINES
111 ; Include all pre-processor statements here. Include conditional
112 ; compile variables also.
113 ----------------------------------------------------------------------------*/
114 #define L_H 22 /* size of truncated impulse response of A(z/g1)/A(z/g2) */
115
116 /*----------------------------------------------------------------------------
117 ; LOCAL FUNCTION DEFINITIONS
118 ; Function Prototype declaration
119 ----------------------------------------------------------------------------*/
120
121 /*----------------------------------------------------------------------------
122 ; LOCAL VARIABLE DEFINITIONS
123 ; Variable declaration - defined here and used outside this module
124 ----------------------------------------------------------------------------*/
125
126 /* Spectral expansion factors */
127 static const Word16 gamma3_MR122[M] =
128 {
129 22938, 16057, 11240, 7868, 5508,
130 3856, 2699, 1889, 1322, 925
131 };
132
133 static const Word16 gamma3[M] =
134 {
135 18022, 9912, 5451, 2998, 1649, 907, 499, 274, 151, 83
136 };
137
138 static const Word16 gamma4_MR122[M] =
139 {
140 24576, 18432, 13824, 10368, 7776,
141 5832, 4374, 3281, 2461, 1846
142 };
143
144 static const Word16 gamma4[M] =
145 {
146 22938, 16057, 11240, 7868, 5508, 3856, 2699, 1889, 1322, 925
147 };
148
149 /*----------------------------------------------------------------------------
150 ; EXTERNAL FUNCTION REFERENCES
151 ; Declare functions defined elsewhere and referenced in this module
152 ----------------------------------------------------------------------------*/
153
154 /*----------------------------------------------------------------------------
155 ; EXTERNAL VARIABLES REFERENCES
156 ; Declare variables used in this module but defined elsewhere
157 ----------------------------------------------------------------------------*/
158
159 /*
160 ------------------------------------------------------------------------------
161 FUNCTION NAME: Post_Filter_reset
162 ------------------------------------------------------------------------------
163 INPUT AND OUTPUT DEFINITIONS
164
165 Inputs:
166 state = pointer to structure of type Post_FilterState
167
168 Outputs:
169 fields of the structure pointed to by state is initialized to zero
170
171 Returns:
172 return_value = 0, if reset was successful; -1, otherwise (int)
173
174 Global Variables Used:
175 None
176
177 Local Variables Needed:
178 None
179
180 ------------------------------------------------------------------------------
181 FUNCTION DESCRIPTION
182
183 This function initializes the state memory used by the Post_Filter function
184 to zero.
185
186 ------------------------------------------------------------------------------
187 REQUIREMENTS
188
189 None
190
191 ------------------------------------------------------------------------------
192 REFERENCES
193
194 pstfilt.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
195
196 ------------------------------------------------------------------------------
197 PSEUDO-CODE
198
199 int Post_Filter_reset (Post_FilterState *state)
200 {
201 if (state == (Post_FilterState *) NULL){
202 fprintf(stderr, "Post_Filter_reset: invalid parameter\n");
203 return -1;
204 }
205
206 Set_zero (state->mem_syn_pst, M);
207 Set_zero (state->res2, L_SUBFR);
208 Set_zero (state->synth_buf, L_FRAME + M);
209 agc_reset(state->agc_state);
210 preemphasis_reset(state->preemph_state);
211
212 return 0;
213 }
214
215 ------------------------------------------------------------------------------
216 RESOURCES USED [optional]
217
218 When the code is written for a specific target processor the
219 the resources used should be documented below.
220
221 HEAP MEMORY USED: x bytes
222
223 STACK MEMORY USED: x bytes
224
225 CLOCK CYCLES: (cycle count equation for this function) + (variable
226 used to represent cycle count for each subroutine
227 called)
228 where: (cycle count variable) = cycle count for [subroutine
229 name]
230
231 ------------------------------------------------------------------------------
232 CAUTION [optional]
233 [State any special notes, constraints or cautions for users of this function]
234
235 ------------------------------------------------------------------------------
236 */
237
Post_Filter_reset(Post_FilterState * state)238 Word16 Post_Filter_reset(Post_FilterState *state)
239 {
240 if (state == (Post_FilterState *) NULL)
241 {
242 /*fprintf(stderr, "Post_Filter_reset: invalid parameter\n"); */
243 return(-1);
244 }
245
246 memset(state->mem_syn_pst, 0, sizeof(Word16)*M);
247 memset(state->res2, 0, sizeof(Word16)*L_SUBFR);
248 memset(state->synth_buf, 0, sizeof(Word16)*(L_FRAME + M));
249 agc_reset(&(state->agc_state));
250 preemphasis_reset(&(state->preemph_state));
251
252 return(0);
253 }
254
255 /****************************************************************************/
256
257 /*
258 ------------------------------------------------------------------------------
259 FUNCTION NAME: Post_Filter
260 ------------------------------------------------------------------------------
261 INPUT AND OUTPUT DEFINITIONS
262
263 Inputs:
264 st = pointer to a structure of type Post_FilterState
265 mode = AMR mode
266 syn = pointer to a buffer containing synthesized speech; upon
267 exiting this function, it will contain the post-filtered
268 synthesized speech
269 Az_4 = pointer to the interpolated LPC parameters for all subframes
270 pOverflow = pointer to overflow indicator of type Flag
271
272 Outputs:
273 fields of the structure pointed to by st contains the updated field
274 values
275 syn buffer contains the post-filtered synthesized speech
276 pOverflow = 1 if overflow occurrs in the math functions called else
277 it is zero.
278
279 Returns:
280 return_value = 0 (int)
281
282 Global Variables Used:
283 None
284
285 Local Variables Needed:
286 None
287
288 ------------------------------------------------------------------------------
289 FUNCTION DESCRIPTION
290
291 This function performs the post-filtering on the synthesized speech. The
292 post-filtering process is described as follows:
293 (1) inverse filtering of syn[] through A(z/0.7) to get res2[]
294 (2) tilt compensation filtering; 1 - MU*k*z^-1
295 (3) synthesis filtering through 1/A(z/0.75)
296 (4) adaptive gain control
297
298 ------------------------------------------------------------------------------
299 REQUIREMENTS
300
301 None
302
303 ------------------------------------------------------------------------------
304 REFERENCES
305
306 pstfilt.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
307
308 ------------------------------------------------------------------------------
309 PSEUDO-CODE
310
311 int Post_Filter (
312 Post_FilterState *st, // i/o : post filter states
313 enum Mode mode, // i : AMR mode
314 Word16 *syn, // i/o : synthesis speech (postfiltered is output)
315 Word16 *Az_4 // i : interpolated LPC parameters in all subfr.
316 )
317 {
318 *-------------------------------------------------------------------*
319 * Declaration of parameters *
320 *-------------------------------------------------------------------*
321
322 Word16 Ap3[MP1], Ap4[MP1]; // bandwidth expanded LP parameters
323 Word16 *Az; // pointer to Az_4:
324 // LPC parameters in each subframe
325 Word16 i_subfr; // index for beginning of subframe
326 Word16 h[L_H];
327
328 Word16 i;
329 Word16 temp1, temp2;
330 Word32 L_tmp;
331 Word16 *syn_work = &st->synth_buf[M];
332
333
334 *-----------------------------------------------------*
335 * Post filtering *
336 *-----------------------------------------------------*
337
338 Copy (syn, syn_work , L_FRAME);
339
340 Az = Az_4;
341
342 for (i_subfr = 0; i_subfr < L_FRAME; i_subfr += L_SUBFR)
343 {
344 // Find weighted filter coefficients Ap3[] and ap[4]
345
346 if (sub(mode, MR122) == 0 || sub(mode, MR102) == 0)
347 {
348 Weight_Ai (Az, gamma3_MR122, Ap3);
349 Weight_Ai (Az, gamma4_MR122, Ap4);
350 }
351 else
352 {
353 Weight_Ai (Az, gamma3, Ap3);
354 Weight_Ai (Az, gamma4, Ap4);
355 }
356
357 // filtering of synthesis speech by A(z/0.7) to find res2[]
358
359 Residu (Ap3, &syn_work[i_subfr], st->res2, L_SUBFR);
360
361 // tilt compensation filter
362
363 // impulse response of A(z/0.7)/A(z/0.75)
364
365 Copy (Ap3, h, M + 1);
366 Set_zero (&h[M + 1], L_H - M - 1);
367 Syn_filt (Ap4, h, h, L_H, &h[M + 1], 0);
368
369 // 1st correlation of h[]
370
371 L_tmp = L_mult (h[0], h[0]);
372 for (i = 1; i < L_H; i++)
373 {
374 L_tmp = L_mac (L_tmp, h[i], h[i]);
375 }
376 temp1 = extract_h (L_tmp);
377
378 L_tmp = L_mult (h[0], h[1]);
379 for (i = 1; i < L_H - 1; i++)
380 {
381 L_tmp = L_mac (L_tmp, h[i], h[i + 1]);
382 }
383 temp2 = extract_h (L_tmp);
384
385 if (temp2 <= 0)
386 {
387 temp2 = 0;
388 }
389 else
390 {
391 temp2 = mult (temp2, MU);
392 temp2 = div_s (temp2, temp1);
393 }
394
395 preemphasis (st->preemph_state, st->res2, temp2, L_SUBFR);
396
397 // filtering through 1/A(z/0.75)
398
399 Syn_filt (Ap4, st->res2, &syn[i_subfr], L_SUBFR, st->mem_syn_pst, 1);
400
401 // scale output to input
402
403 agc (st->agc_state, &syn_work[i_subfr], &syn[i_subfr],
404 AGC_FAC, L_SUBFR);
405
406 Az += MP1;
407 }
408
409 // update syn_work[] buffer
410
411 Copy (&syn_work[L_FRAME - M], &syn_work[-M], M);
412
413 return 0;
414 }
415
416 ------------------------------------------------------------------------------
417 RESOURCES USED [optional]
418
419 When the code is written for a specific target processor the
420 the resources used should be documented below.
421
422 HEAP MEMORY USED: x bytes
423
424 STACK MEMORY USED: x bytes
425
426 CLOCK CYCLES: (cycle count equation for this function) + (variable
427 used to represent cycle count for each subroutine
428 called)
429 where: (cycle count variable) = cycle count for [subroutine
430 name]
431
432 ------------------------------------------------------------------------------
433 CAUTION [optional]
434 [State any special notes, constraints or cautions for users of this function]
435
436 ------------------------------------------------------------------------------
437 */
438
Post_Filter(Post_FilterState * st,enum Mode mode,Word16 * syn,Word16 * Az_4,Flag * pOverflow)439 void Post_Filter(
440 Post_FilterState *st, /* i/o : post filter states */
441 enum Mode mode, /* i : AMR mode */
442 Word16 *syn, /* i/o : synthesis speech (postfiltered is output) */
443 Word16 *Az_4, /* i : interpolated LPC parameters in all subfr. */
444 Flag *pOverflow
445 )
446 {
447 Word16 Ap3[MP1];
448 Word16 Ap4[MP1]; /* bandwidth expanded LP parameters */
449 Word16 *Az; /* pointer to Az_4: */
450 /* LPC parameters in each subframe */
451 Word16 i_subfr; /* index for beginning of subframe */
452 Word16 h[L_H];
453
454 Word16 i;
455 Word16 temp1;
456 Word16 temp2;
457 Word32 L_tmp;
458 Word32 L_tmp2;
459 Word16 *syn_work = &st->synth_buf[M];
460
461
462 /*-----------------------------------------------------*
463 * Post filtering *
464 *-----------------------------------------------------*/
465
466 Copy(syn, syn_work , L_FRAME);
467
468 Az = Az_4;
469
470 for (i_subfr = 0; i_subfr < L_FRAME; i_subfr += L_SUBFR)
471 {
472 /* Find weighted filter coefficients Ap3[] and ap[4] */
473
474 if (mode == MR122 || mode == MR102)
475 {
476 Weight_Ai(Az, gamma3_MR122, Ap3);
477 Weight_Ai(Az, gamma4_MR122, Ap4);
478 }
479 else
480 {
481 Weight_Ai(Az, gamma3, Ap3);
482 Weight_Ai(Az, gamma4, Ap4);
483 }
484
485 /* filtering of synthesis speech by A(z/0.7) to find res2[] */
486
487 Residu(Ap3, &syn_work[i_subfr], st->res2, L_SUBFR);
488
489 /* tilt compensation filter */
490
491 /* impulse response of A(z/0.7)/A(z/0.75) */
492
493 Copy(Ap3, h, M + 1);
494 memset(&h[M + 1], 0, sizeof(Word16)*(L_H - M - 1));
495 Syn_filt(Ap4, h, h, L_H, &h[M + 1], 0);
496
497 /* 1st correlation of h[] */
498
499 L_tmp = 0;
500
501 for (i = L_H - 1; i >= 0; i--)
502 {
503 L_tmp2 = ((Word32) h[i]) * h[i];
504
505 if (L_tmp2 != (Word32) 0x40000000L)
506 {
507 L_tmp2 = L_tmp2 << 1;
508 }
509 else
510 {
511 *pOverflow = 1;
512 L_tmp2 = MAX_32;
513 break;
514 }
515
516 L_tmp = L_add(L_tmp, L_tmp2, pOverflow);
517 }
518 temp1 = (Word16)(L_tmp >> 16);
519
520 L_tmp = 0;
521
522 for (i = L_H - 2; i >= 0; i--)
523 {
524 L_tmp2 = ((Word32) h[i]) * h[i + 1];
525
526 if (L_tmp2 != (Word32) 0x40000000L)
527 {
528 L_tmp2 = L_tmp2 << 1;
529 }
530 else
531 {
532 *pOverflow = 1;
533 L_tmp2 = MAX_32;
534 break;
535 }
536
537 L_tmp = L_add(L_tmp, L_tmp2, pOverflow);
538 }
539 temp2 = (Word16)(L_tmp >> 16);
540
541 if (temp2 <= 0)
542 {
543 temp2 = 0;
544 }
545 else
546 {
547 L_tmp = (((Word32) temp2) * MU) >> 15;
548
549 /* Sign-extend product */
550 if (L_tmp & (Word32) 0x00010000L)
551 {
552 L_tmp = L_tmp | (Word32) 0xffff0000L;
553 }
554 temp2 = (Word16) L_tmp;
555
556 temp2 = div_s(temp2, temp1);
557 }
558
559 preemphasis(&(st->preemph_state), st->res2, temp2, L_SUBFR, pOverflow);
560
561 /* filtering through 1/A(z/0.75) */
562
563 Syn_filt(Ap4, st->res2, &syn[i_subfr], L_SUBFR, st->mem_syn_pst, 1);
564
565 /* scale output to input */
566
567 agc(&(st->agc_state), &syn_work[i_subfr], &syn[i_subfr],
568 AGC_FAC, L_SUBFR, pOverflow);
569
570 Az += MP1;
571 }
572
573 /* update syn_work[] buffer */
574
575 Copy(&syn_work[L_FRAME - M], &syn_work[-M], M);
576
577 return;
578 }
579