1 /* ------------------------------------------------------------------
2 * Copyright (C) 1998-2009 PacketVideo
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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
14 * See the License for the specific language governing permissions
15 * and limitations under the License.
16 * -------------------------------------------------------------------
18 /****************************************************************************************
19 Portions of this file are derived from the following 3GPP standard:
22 ANSI-C code for the Adaptive Multi-Rate (AMR) speech codec
23 Available from http://www.3gpp.org
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 ****************************************************************************************/
30 ------------------------------------------------------------------------------
39 ------------------------------------------------------------------------------
42 This file contains the function that performs adaptive post-filtering on the
43 synthesized speech. It also contains the functions that initialize, reset,
44 and exit the post-filtering function.
46 ------------------------------------------------------------------------------
49 /*----------------------------------------------------------------------------
51 ----------------------------------------------------------------------------*/
55 #include "basicop_malloc.h"
64 /*----------------------------------------------------------------------------
66 ; Define module specific macros here
67 ----------------------------------------------------------------------------*/
69 /*----------------------------------------------------------------------------
71 ; Include all pre-processor statements here. Include conditional
72 ; compile variables also.
73 ----------------------------------------------------------------------------*/
74 #define L_H 22 /* size of truncated impulse response of A(z/g1)/A(z/g2) */
76 /*----------------------------------------------------------------------------
77 ; LOCAL FUNCTION DEFINITIONS
78 ; Function Prototype declaration
79 ----------------------------------------------------------------------------*/
81 /*----------------------------------------------------------------------------
82 ; LOCAL VARIABLE DEFINITIONS
83 ; Variable declaration - defined here and used outside this module
84 ----------------------------------------------------------------------------*/
86 /* Spectral expansion factors */
87 static const Word16 gamma3_MR122[M] =
89 22938, 16057, 11240, 7868, 5508,
90 3856, 2699, 1889, 1322, 925
93 static const Word16 gamma3[M] =
95 18022, 9912, 5451, 2998, 1649, 907, 499, 274, 151, 83
98 static const Word16 gamma4_MR122[M] =
100 24576, 18432, 13824, 10368, 7776,
101 5832, 4374, 3281, 2461, 1846
104 static const Word16 gamma4[M] =
106 22938, 16057, 11240, 7868, 5508, 3856, 2699, 1889, 1322, 925
109 /*----------------------------------------------------------------------------
110 ; EXTERNAL FUNCTION REFERENCES
111 ; Declare functions defined elsewhere and referenced in this module
112 ----------------------------------------------------------------------------*/
114 /*----------------------------------------------------------------------------
115 ; EXTERNAL VARIABLES REFERENCES
116 ; Declare variables used in this module but defined elsewhere
117 ----------------------------------------------------------------------------*/
120 ------------------------------------------------------------------------------
121 FUNCTION NAME: Post_Filter_reset
122 ------------------------------------------------------------------------------
123 INPUT AND OUTPUT DEFINITIONS
126 state = pointer to structure of type Post_FilterState
129 fields of the structure pointed to by state is initialized to zero
132 return_value = 0, if reset was successful; -1, otherwise (int)
134 Global Variables Used:
137 Local Variables Needed:
140 ------------------------------------------------------------------------------
143 This function initializes the state memory used by the Post_Filter function
146 ------------------------------------------------------------------------------
151 ------------------------------------------------------------------------------
154 pstfilt.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
156 ------------------------------------------------------------------------------
159 int Post_Filter_reset (Post_FilterState *state)
161 if (state == (Post_FilterState *) NULL){
162 fprintf(stderr, "Post_Filter_reset: invalid parameter\n");
166 Set_zero (state->mem_syn_pst, M);
167 Set_zero (state->res2, L_SUBFR);
168 Set_zero (state->synth_buf, L_FRAME + M);
169 agc_reset(state->agc_state);
170 preemphasis_reset(state->preemph_state);
175 ------------------------------------------------------------------------------
177 [State any special notes, constraints or cautions for users of this function]
179 ------------------------------------------------------------------------------
182 Word16 Post_Filter_reset(Post_FilterState *state)
184 if (state == (Post_FilterState *) NULL)
186 /*fprintf(stderr, "Post_Filter_reset: invalid parameter\n"); */
190 oscl_memset(state->mem_syn_pst, 0, sizeof(Word16)*M);
191 oscl_memset(state->res2, 0, sizeof(Word16)*L_SUBFR);
192 oscl_memset(state->synth_buf, 0, sizeof(Word16)*(L_FRAME + M));
193 agc_reset(&(state->agc_state));
194 preemphasis_reset(&(state->preemph_state));
199 /****************************************************************************/
202 ------------------------------------------------------------------------------
203 FUNCTION NAME: Post_Filter
204 ------------------------------------------------------------------------------
205 INPUT AND OUTPUT DEFINITIONS
208 st = pointer to a structure of type Post_FilterState
210 syn = pointer to a buffer containing synthesized speech; upon
211 exiting this function, it will contain the post-filtered
213 Az_4 = pointer to the interpolated LPC parameters for all subframes
214 pOverflow = pointer to overflow indicator of type Flag
217 fields of the structure pointed to by st contains the updated field
219 syn buffer contains the post-filtered synthesized speech
220 pOverflow = 1 if overflow occurrs in the math functions called else
224 return_value = 0 (int)
226 Global Variables Used:
229 Local Variables Needed:
232 ------------------------------------------------------------------------------
235 This function performs the post-filtering on the synthesized speech. The
236 post-filtering process is described as follows:
237 (1) inverse filtering of syn[] through A(z/0.7) to get res2[]
238 (2) tilt compensation filtering; 1 - MU*k*z^-1
239 (3) synthesis filtering through 1/A(z/0.75)
240 (4) adaptive gain control
242 ------------------------------------------------------------------------------
247 ------------------------------------------------------------------------------
250 pstfilt.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
252 ------------------------------------------------------------------------------
256 Post_FilterState *st, // i/o : post filter states
257 enum Mode mode, // i : AMR mode
258 Word16 *syn, // i/o : synthesis speech (postfiltered is output)
259 Word16 *Az_4 // i : interpolated LPC parameters in all subfr.
262 *-------------------------------------------------------------------*
263 * Declaration of parameters *
264 *-------------------------------------------------------------------*
266 Word16 Ap3[MP1], Ap4[MP1]; // bandwidth expanded LP parameters
267 Word16 *Az; // pointer to Az_4:
268 // LPC parameters in each subframe
269 Word16 i_subfr; // index for beginning of subframe
275 Word16 *syn_work = &st->synth_buf[M];
278 *-----------------------------------------------------*
280 *-----------------------------------------------------*
282 Copy (syn, syn_work , L_FRAME);
286 for (i_subfr = 0; i_subfr < L_FRAME; i_subfr += L_SUBFR)
288 // Find weighted filter coefficients Ap3[] and ap[4]
290 if (sub(mode, MR122) == 0 || sub(mode, MR102) == 0)
292 Weight_Ai (Az, gamma3_MR122, Ap3);
293 Weight_Ai (Az, gamma4_MR122, Ap4);
297 Weight_Ai (Az, gamma3, Ap3);
298 Weight_Ai (Az, gamma4, Ap4);
301 // filtering of synthesis speech by A(z/0.7) to find res2[]
303 Residu (Ap3, &syn_work[i_subfr], st->res2, L_SUBFR);
305 // tilt compensation filter
307 // impulse response of A(z/0.7)/A(z/0.75)
309 Copy (Ap3, h, M + 1);
310 Set_zero (&h[M + 1], L_H - M - 1);
311 Syn_filt (Ap4, h, h, L_H, &h[M + 1], 0);
313 // 1st correlation of h[]
315 L_tmp = L_mult (h[0], h[0]);
316 for (i = 1; i < L_H; i++)
318 L_tmp = L_mac (L_tmp, h[i], h[i]);
320 temp1 = extract_h (L_tmp);
322 L_tmp = L_mult (h[0], h[1]);
323 for (i = 1; i < L_H - 1; i++)
325 L_tmp = L_mac (L_tmp, h[i], h[i + 1]);
327 temp2 = extract_h (L_tmp);
335 temp2 = mult (temp2, MU);
336 temp2 = div_s (temp2, temp1);
339 preemphasis (st->preemph_state, st->res2, temp2, L_SUBFR);
341 // filtering through 1/A(z/0.75)
343 Syn_filt (Ap4, st->res2, &syn[i_subfr], L_SUBFR, st->mem_syn_pst, 1);
345 // scale output to input
347 agc (st->agc_state, &syn_work[i_subfr], &syn[i_subfr],
353 // update syn_work[] buffer
355 Copy (&syn_work[L_FRAME - M], &syn_work[-M], M);
360 ------------------------------------------------------------------------------
362 [State any special notes, constraints or cautions for users of this function]
364 ------------------------------------------------------------------------------
368 Post_FilterState *st, /* i/o : post filter states */
369 enum Mode mode, /* i : AMR mode */
370 Word16 *syn, /* i/o : synthesis speech (postfiltered is output) */
371 Word16 *Az_4, /* i : interpolated LPC parameters in all subfr. */
376 Word16 Ap4[MP1]; /* bandwidth expanded LP parameters */
377 Word16 *Az; /* pointer to Az_4: */
378 /* LPC parameters in each subframe */
379 register Word16 i_subfr; /* index for beginning of subframe */
387 Word16 *syn_work = &st->synth_buf[M];
390 /*-----------------------------------------------------*
392 *-----------------------------------------------------*/
394 oscl_memmove((void *)syn_work , syn, L_FRAME*sizeof(*syn));
398 for (i_subfr = 0; i_subfr < L_FRAME; i_subfr += L_SUBFR)
400 /* Find weighted filter coefficients Ap3[] and ap[4] */
402 if (mode == MR122 || mode == MR102)
404 Weight_Ai(Az, gamma3_MR122, Ap3);
405 Weight_Ai(Az, gamma4_MR122, Ap4);
409 Weight_Ai(Az, gamma3, Ap3);
410 Weight_Ai(Az, gamma4, Ap4);
413 /* filtering of synthesis speech by A(z/0.7) to find res2[] */
415 Residu(Ap3, &syn_work[i_subfr], st->res2, L_SUBFR);
417 /* tilt compensation filter */
419 /* impulse response of A(z/0.7)/A(z/0.75) */
421 oscl_memmove((void *)h, Ap3, (M + 1)*sizeof(*Ap3));
422 oscl_memset(&h[M + 1], 0, sizeof(Word16)*(L_H - M - 1));
423 Syn_filt(Ap4, h, h, L_H, &h[M + 1], 0);
425 /* 1st correlation of h[] */
429 for (i = L_H - 1; i >= 0; i--)
431 L_tmp2 = ((Word32) h[i]) * h[i];
433 if (L_tmp2 != (Word32) 0x40000000L)
435 L_tmp2 = L_tmp2 << 1;
444 L_tmp = L_add(L_tmp, L_tmp2, pOverflow);
446 temp1 = (Word16)(L_tmp >> 16);
450 for (i = L_H - 2; i >= 0; i--)
452 L_tmp2 = ((Word32) h[i]) * h[i + 1];
454 if (L_tmp2 != (Word32) 0x40000000L)
456 L_tmp2 = L_tmp2 << 1;
465 L_tmp = L_add(L_tmp, L_tmp2, pOverflow);
467 temp2 = (Word16)(L_tmp >> 16);
475 L_tmp = (((Word32) temp2) * MU) >> 15;
477 /* Sign-extend product */
478 if (L_tmp & (Word32) 0x00010000L)
480 L_tmp = L_tmp | (Word32) 0xffff0000L;
482 temp2 = (Word16) L_tmp;
484 temp2 = div_s(temp2, temp1);
487 preemphasis(&(st->preemph_state), st->res2, temp2, L_SUBFR, pOverflow);
489 /* filtering through 1/A(z/0.75) */
491 Syn_filt(Ap4, st->res2, &syn[i_subfr], L_SUBFR, st->mem_syn_pst, 1);
493 /* scale output to input */
495 agc(&(st->agc_state), &syn_work[i_subfr], &syn[i_subfr],
496 AGC_FAC, L_SUBFR, pOverflow);
501 /* update syn_work[] buffer */
503 oscl_memmove((void *)&syn_work[-M], &syn_work[L_FRAME - M], M*sizeof(*syn_work));