pstfilt.cpp revision 2d0ac425564ff9882ebaac5267d1a04d4af67d00
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------------------------------------------------------------------------------
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 */
127static const Word16 gamma3_MR122[M] =
128{
129    22938, 16057, 11240, 7868, 5508,
130    3856, 2699, 1889, 1322, 925
131};
132
133static const Word16 gamma3[M] =
134{
135    18022, 9912, 5451, 2998, 1649, 907, 499, 274, 151, 83
136};
137
138static const Word16 gamma4_MR122[M] =
139{
140    24576, 18432, 13824, 10368, 7776,
141    5832, 4374, 3281, 2461, 1846
142};
143
144static 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
199int 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
238Word16 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
311int 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
439void 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