Home | History | Annotate | Download | only in src
      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 
    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 
    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     register Word16 i_subfr;    /* index for beginning of subframe  */
    452     Word16 h[L_H];
    453 
    454     register 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