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/agc.c
     35  Funtions: energy_old
     36            energy_new
     37            agc_init
     38            agc_reset
     39            agc_exit
     40            agc
     41            agc2
     42 
     43 ------------------------------------------------------------------------------
     44  MODULE DESCRIPTION
     45 
     46  This set of modules scale the excitation level and output of the speech
     47  signals.
     48 
     49 ------------------------------------------------------------------------------
     50 */
     51 
     52 
     53 /*----------------------------------------------------------------------------
     54 ; INCLUDES
     55 ----------------------------------------------------------------------------*/
     56 
     57 #include    "agc.h"
     58 #include    "cnst.h"
     59 #include    "inv_sqrt.h"
     60 #include    "basic_op.h"
     61 
     62 /*----------------------------------------------------------------------------
     63 ; MACROS
     64 ; Define module specific macros here
     65 ----------------------------------------------------------------------------*/
     66 
     67 
     68 /*----------------------------------------------------------------------------
     69 ; DEFINES
     70 ; Include all pre-processor statements here. Include conditional
     71 ; compile variables also.
     72 ----------------------------------------------------------------------------*/
     73 
     74 /*----------------------------------------------------------------------------
     75 ; LOCAL FUNCTION DEFINITIONS
     76 ; Function Prototype declaration
     77 ----------------------------------------------------------------------------*/
     78 
     79 /*----------------------------------------------------------------------------
     80 ; LOCAL VARIABLE DEFINITIONS
     81 ; Variable declaration - defined here and used outside this module
     82 ----------------------------------------------------------------------------*/
     83 
     84 /*
     85 ------------------------------------------------------------------------------
     86  FUNCTION NAME: energy_old
     87 ------------------------------------------------------------------------------
     88  INPUT AND OUTPUT DEFINITIONS
     89 
     90  Inputs:
     91     in = input signal (Word16)
     92     l_trm = input signal length (Word16)
     93     pOverflow = address of overflow (Flag)
     94 
     95  Outputs:
     96     pOverflow -> 1 if the energy computation saturates
     97 
     98  Returns:
     99     s = return energy of signal (Word32)
    100 
    101  Global Variables Used:
    102     None.
    103 
    104  Local Variables Needed:
    105     None.
    106 
    107 ------------------------------------------------------------------------------
    108  FUNCTION DESCRIPTION
    109 
    110  Returns the energy of the signal.
    111 
    112 ------------------------------------------------------------------------------
    113  REQUIREMENTS
    114 
    115  None.
    116 
    117 ------------------------------------------------------------------------------
    118  REFERENCES
    119 
    120  agc.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
    121 
    122 ------------------------------------------------------------------------------
    123  PSEUDO-CODE
    124 
    125 static Word32 energy_old( // o : return energy of signal
    126     Word16 in[],          // i : input signal (length l_trm)
    127     Word16 l_trm          // i : signal length
    128 )
    129 {
    130     Word32 s;
    131     Word16 i, temp;
    132 
    133     temp = shr (in[0], 2);
    134     s = L_mult (temp, temp);
    135 
    136     for (i = 1; i < l_trm; i++)
    137     {
    138         temp = shr (in[i], 2);
    139         s = L_mac (s, temp, temp);
    140     }
    141 
    142     return s;
    143 }
    144 
    145 ------------------------------------------------------------------------------
    146  RESOURCES USED [optional]
    147 
    148  When the code is written for a specific target processor the
    149  the resources used should be documented below.
    150 
    151  HEAP MEMORY USED: x bytes
    152 
    153  STACK MEMORY USED: x bytes
    154 
    155  CLOCK CYCLES: (cycle count equation for this function) + (variable
    156                 used to represent cycle count for each subroutine
    157                 called)
    158      where: (cycle count variable) = cycle count for [subroutine
    159                                      name]
    160 
    161 ------------------------------------------------------------------------------
    162  CAUTION [optional]
    163  [State any special notes, constraints or cautions for users of this function]
    164 
    165 ------------------------------------------------------------------------------
    166 */
    167 
    168 static Word32 energy_old(       /* o : return energy of signal      */
    169     Word16 in[],        /* i : input signal (length l_trm)  */
    170     Word16 l_trm,       /* i : signal length                */
    171     Flag   *pOverflow   /* overflow: flag to indicate overflow */
    172 )
    173 
    174 {
    175     Word32  s = 0;
    176     Word16  i;
    177     Word16  temp;
    178 
    179     for (i = 0; i < l_trm; i++)
    180     {
    181         temp = in[i] >> 2;
    182         s = L_mac(s, temp, temp, pOverflow);
    183     }
    184 
    185     return(s);
    186 }
    187 
    188 /*----------------------------------------------------------------------------*/
    189 /*
    190 ------------------------------------------------------------------------------
    191  FUNCTION NAME: energy_old__Wrapper
    192 ------------------------------------------------------------------------------
    193  INPUT AND OUTPUT DEFINITIONS
    194 
    195  Inputs:
    196     in = input signal (Word16)
    197     l_trm = input signal length (Word16)
    198     pOverflow = address of overflow (Flag)
    199  Outputs:
    200     pOverflow -> 1 if the energy computation saturates
    201 
    202  Returns:
    203     s = return energy of signal (Word32)
    204 
    205  Global Variables Used:
    206     None.
    207 
    208  Local Variables Needed:
    209     None.
    210 
    211 ------------------------------------------------------------------------------
    212  FUNCTION DESCRIPTION
    213 
    214  This function provides external access to the static function energy_old.
    215 
    216 ------------------------------------------------------------------------------
    217  REQUIREMENTS
    218 
    219  None
    220 
    221 ------------------------------------------------------------------------------
    222  REFERENCES
    223 
    224  None
    225 
    226 ------------------------------------------------------------------------------
    227  PSEUDO-CODE
    228 
    229  CALL energy_old (  in = in
    230             l_trm = l_trm
    231             pOverflow = pOverflow )
    232    MODIFYING(nothing)
    233    RETURNING(energy_old_value = s)
    234 
    235 ------------------------------------------------------------------------------
    236  RESOURCES USED [optional]
    237 
    238  When the code is written for a specific target processor the
    239  the resources used should be documented below.
    240 
    241  HEAP MEMORY USED: x bytes
    242 
    243  STACK MEMORY USED: x bytes
    244 
    245  CLOCK CYCLES: (cycle count equation for this function) + (variable
    246                 used to represent cycle count for each subroutine
    247                 called)
    248      where: (cycle count variable) = cycle count for [subroutine
    249                                      name]
    250 
    251 ------------------------------------------------------------------------------
    252  CAUTION [optional]
    253  [State any special notes, constraints or cautions for users of this function]
    254 
    255 ------------------------------------------------------------------------------
    256 */
    257 
    258 Word32 energy_old_Wrapper(Word16 in[], Word16 l_trm, Flag *pOverflow)
    259 {
    260     Word32 energy_old_value;
    261 
    262     /*----------------------------------------------------------------------------
    263      CALL energy_old (  in = in
    264                 l_trm = l_trm
    265                 pOverflow = pOverflow )
    266 
    267       MODIFYING(nothing)
    268        RETURNING(energy_old_value = s)
    269     ----------------------------------------------------------------------------*/
    270     energy_old_value = energy_old(in, l_trm, pOverflow);
    271     return(energy_old_value);
    272 }
    273 /*--------------------------------------------------------------------------*/
    274 
    275 /*
    276 -----------------------------------------------------------------------------
    277  FUNCTION NAME: energy_new
    278 ------------------------------------------------------------------------------
    279  INPUT AND OUTPUT DEFINITIONS
    280 
    281  Inputs:
    282     in = input signal
    283     l_trm = input signal length
    284     pOverflow = address of overflow (Flag)
    285 
    286  Outputs:
    287     pOverflow -> 1 if the energy computation saturates
    288 
    289  Returns:
    290     s = return energy of signal
    291 
    292  Global Variables Used:
    293     None.
    294 
    295  Local Variables Needed:
    296     None.
    297 
    298 ------------------------------------------------------------------------------
    299  FUNCTION DESCRIPTION
    300 
    301  Returns the energy of the signal.
    302 
    303 ------------------------------------------------------------------------------
    304  REQUIREMENTS
    305 
    306  None.
    307 
    308 ------------------------------------------------------------------------------
    309  REFERENCES
    310 
    311  agc.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
    312 
    313 ------------------------------------------------------------------------------
    314  PSEUDO-CODE
    315 
    316 static Word32 energy_new( // o : return energy of signal
    317     Word16 in[],          // i : input signal (length l_trm)
    318     Word16 l_trm )        // i : signal length
    319 
    320 {
    321     Word32 s;
    322     Word16 i;
    323     Flag ov_save;
    324 
    325     ov_save = Overflow;            //save overflow flag in case energy_old
    326                                    // must be called
    327     s = L_mult(in[0], in[0]);
    328     for (i = 1; i < l_trm; i++)
    329     {
    330         s = L_mac(s, in[i], in[i]);
    331     }
    332 
    333     // check for overflow
    334     if (L_sub (s, MAX_32) == 0L)
    335     {
    336         Overflow = ov_save; // restore overflow flag
    337         s = energy_old (in, l_trm); // function result
    338     }
    339     else
    340     {
    341        s = L_shr(s, 4);
    342     }
    343 
    344     return(s);
    345 }
    346 
    347 ------------------------------------------------------------------------------
    348  RESOURCES USED [optional]
    349 
    350  When the code is written for a specific target processor the
    351  the resources used should be documented below.
    352 
    353  HEAP MEMORY USED: x bytes
    354 
    355  STACK MEMORY USED: x bytes
    356 
    357  CLOCK CYCLES: (cycle count equation for this function) + (variable
    358                 used to represent cycle count for each subroutine
    359                 called)
    360      where: (cycle count variable) = cycle count for [subroutine
    361                                      name]
    362 
    363 ------------------------------------------------------------------------------
    364  CAUTION [optional]
    365  [State any special notes, constraints or cautions for users of this function]
    366 
    367 ------------------------------------------------------------------------------
    368 */
    369 
    370 static Word32 energy_new(       /* o : return energy of signal      */
    371     Word16 in[],        /* i : input signal (length l_trm)  */
    372     Word16 l_trm,       /* i : signal length                */
    373     Flag *pOverflow     /* i : overflow flag                */
    374 )
    375 
    376 {
    377     Word32  s = 0;
    378     Word16  i;
    379     Flag    ov_save;
    380 
    381     ov_save = *(pOverflow);  /* save overflow flag in case energy_old */
    382     /* must be called                        */
    383 
    384 
    385     for (i = 0; i < l_trm; i++)
    386     {
    387         s = L_mac(s, in[i], in[i], pOverflow);
    388     }
    389 
    390     /* check for overflow */
    391     if (s != MAX_32)
    392     {
    393         /* s is a sum of squares, so it won't be negative */
    394         s = s >> 4;
    395     }
    396     else
    397     {
    398         *(pOverflow) = ov_save;  /* restore overflow flag */
    399         s = energy_old(in, l_trm, pOverflow);   /* function result */
    400     }
    401 
    402     return (s);
    403 }
    404 
    405 /*--------------------------------------------------------------------------*/
    406 /*
    407 ------------------------------------------------------------------------------
    408  FUNCTION NAME: energy_new__Wrapper
    409 ------------------------------------------------------------------------------
    410  INPUT AND OUTPUT DEFINITIONS
    411 
    412  Inputs:
    413     in = input signal (Word16)
    414     l_trm = input signal length (Word16)
    415     overflow = address of overflow (Flag)
    416 
    417  Outputs:
    418     pOverflow -> 1 if the energy computation saturates
    419 
    420  Returns:
    421     s = return energy of signal (Word32)
    422 
    423  Global Variables Used:
    424     None.
    425 
    426  Local Variables Needed:
    427     None.
    428 
    429 ------------------------------------------------------------------------------
    430  FUNCTION DESCRIPTION
    431 
    432  This function provides external access to the static function energy_new.
    433 
    434 ------------------------------------------------------------------------------
    435  REQUIREMENTS
    436 
    437  None
    438 
    439 ------------------------------------------------------------------------------
    440  REFERENCES
    441 
    442  None
    443 
    444 ------------------------------------------------------------------------------
    445  PSEUDO-CODE
    446 
    447  CALL energy_new (  in = in
    448             l_trm = l_trm
    449             pOverflow = pOverflow )
    450 
    451    MODIFYING(nothing)
    452 
    453    RETURNING(energy_new_value = s)
    454 
    455 ------------------------------------------------------------------------------
    456  RESOURCES USED [optional]
    457 
    458  When the code is written for a specific target processor the
    459  the resources used should be documented below.
    460 
    461  HEAP MEMORY USED: x bytes
    462 
    463  STACK MEMORY USED: x bytes
    464 
    465  CLOCK CYCLES: (cycle count equation for this function) + (variable
    466                 used to represent cycle count for each subroutine
    467                 called)
    468      where: (cycle count variable) = cycle count for [subroutine
    469                                      name]
    470 
    471 ------------------------------------------------------------------------------
    472  CAUTION [optional]
    473  [State any special notes, constraints or cautions for users of this function]
    474 
    475 ------------------------------------------------------------------------------
    476 */
    477 
    478 Word32 energy_new_Wrapper(Word16 in[], Word16 l_trm, Flag *pOverflow)
    479 {
    480     Word32 energy_new_value;
    481 
    482     /*----------------------------------------------------------------------------
    483      CALL energy_new (  in = in
    484                 l_trm = l_trm
    485                 pOverflow = pOverflow )
    486 
    487        MODIFYING(nothing)
    488        RETURNING(energy_new_value = s)
    489 
    490     ----------------------------------------------------------------------------*/
    491     energy_new_value = energy_new(in, l_trm, pOverflow);
    492 
    493     return(energy_new_value);
    494 
    495 }
    496 
    497 /*--------------------------------------------------------------------------*/
    498 
    499 
    500 
    501 /*
    502 ------------------------------------------------------------------------------
    503  FUNCTION NAME: agc_reset
    504 ------------------------------------------------------------------------------
    505  INPUT AND OUTPUT DEFINITIONS
    506 
    507  Inputs:
    508     state = pointer to a structure of type agcState
    509 
    510  Outputs:
    511     Structure pointed to by state is initialized to zeros
    512 
    513  Returns:
    514     Returns 0 if memory was successfully initialized,
    515         otherwise returns -1.
    516 
    517  Global Variables Used:
    518     None.
    519 
    520  Local Variables Needed:
    521     None.
    522 
    523 ------------------------------------------------------------------------------
    524  FUNCTION DESCRIPTION
    525 
    526  Reset of agc (i.e. set state memory to 1.0).
    527 
    528 ------------------------------------------------------------------------------
    529  REQUIREMENTS
    530 
    531  None.
    532 
    533 ------------------------------------------------------------------------------
    534  REFERENCES
    535 
    536  agc.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
    537 
    538 ------------------------------------------------------------------------------
    539  PSEUDO-CODE
    540 
    541 int agc_reset (agcState *state)
    542 {
    543   if (state == (agcState *) NULL)
    544   {
    545       fprintf(stderr, "agc_reset: invalid parameter\n");
    546       return -1;
    547   }
    548 
    549   state->past_gain = 4096;   // initial value of past_gain = 1.0
    550 
    551   return 0;
    552 }
    553 
    554 ------------------------------------------------------------------------------
    555  RESOURCES USED [optional]
    556 
    557  When the code is written for a specific target processor the
    558  the resources used should be documented below.
    559 
    560  HEAP MEMORY USED: x bytes
    561 
    562  STACK MEMORY USED: x bytes
    563 
    564  CLOCK CYCLES: (cycle count equation for this function) + (variable
    565                 used to represent cycle count for each subroutine
    566                 called)
    567      where: (cycle count variable) = cycle count for [subroutine
    568                                      name]
    569 
    570 ------------------------------------------------------------------------------
    571  CAUTION [optional]
    572  [State any special notes, constraints or cautions for users of this function]
    573 
    574 ------------------------------------------------------------------------------
    575 */
    576 
    577 Word16 agc_reset(agcState *state)
    578 {
    579     if (state == (agcState *) NULL)
    580     {
    581         /* fprintf(stderr, "agc_reset: invalid parameter\n"); */
    582         return(-1);
    583     }
    584 
    585     state->past_gain = 4096;   /* initial value of past_gain = 1.0  */
    586 
    587     return(0);
    588 }
    589 
    590 /*--------------------------------------------------------------------------*/
    591 
    592 /*
    593 ------------------------------------------------------------------------------
    594  FUNCTION NAME: agc
    595 ------------------------------------------------------------------------------
    596  INPUT AND OUTPUT DEFINITIONS
    597 
    598  Inputs:
    599     st = pointer to agc state
    600     sig_in = pointer to a buffer containing the postfilter input signal
    601     sig_out = pointer to a buffer containing the postfilter output signal
    602     agc_fac = AGC factor
    603     l_trm = subframe size
    604     pOverflow = pointer to the overflow flag
    605 
    606  Outputs:
    607     st->past_gain = gain
    608     buffer pointed to by sig_out contains the new postfilter output signal
    609     pOverflow -> 1 if the agc computation saturates
    610 
    611  Returns:
    612     return = 0
    613 
    614  Global Variables Used:
    615     none.
    616 
    617  Local Variables Needed:
    618     none.
    619 
    620 ------------------------------------------------------------------------------
    621  FUNCTION DESCRIPTION
    622 
    623  Scales the postfilter output on a subframe basis using:
    624 
    625      sig_out[n] = sig_out[n] * gain[n]
    626      gain[n] = agc_fac * gain[n-1] + (1 - agc_fac) g_in/g_out
    627 
    628  where: gain[n] = gain at the nth sample given by
    629         g_in/g_out = square root of the ratio of energy at
    630                      the input and output of the postfilter.
    631 
    632 ------------------------------------------------------------------------------
    633  REQUIREMENTS
    634 
    635  None.
    636 
    637 ------------------------------------------------------------------------------
    638  REFERENCES
    639 
    640  agc.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
    641 
    642 ------------------------------------------------------------------------------
    643  PSEUDO-CODE
    644 
    645 int agc (
    646     agcState *st,      // i/o : agc state
    647     Word16 *sig_in,    // i   : postfilter input signal  (l_trm)
    648     Word16 *sig_out,   // i/o : postfilter output signal (l_trm)
    649     Word16 agc_fac,    // i   : AGC factor
    650     Word16 l_trm       // i   : subframe size
    651 )
    652 {
    653     Word16 i, exp;
    654     Word16 gain_in, gain_out, g0, gain;
    655     Word32 s;
    656 
    657     // calculate gain_out with exponent
    658     s = energy_new(sig_out, l_trm); // function result
    659 
    660     if (s == 0)
    661     {
    662         st->past_gain = 0;
    663         return 0;
    664     }
    665     exp = sub (norm_l (s), 1);
    666     gain_out = pv_round (L_shl (s, exp));
    667 
    668     // calculate gain_in with exponent
    669     s = energy_new(sig_in, l_trm); // function result
    670 
    671     if (s == 0)
    672     {
    673         g0 = 0;
    674     }
    675     else
    676     {
    677         i = norm_l (s);
    678         gain_in = pv_round (L_shl (s, i));
    679         exp = sub (exp, i);
    680 
    681          *---------------------------------------------------*
    682          *  g0 = (1-agc_fac) * sqrt(gain_in/gain_out);       *
    683          *---------------------------------------------------*
    684 
    685         s = L_deposit_l (div_s (gain_out, gain_in));
    686         s = L_shl (s, 7);       // s = gain_out / gain_in
    687         s = L_shr (s, exp);     // add exponent
    688 
    689         s = Inv_sqrt (s); // function result
    690         i = pv_round (L_shl (s, 9));
    691 
    692         // g0 = i * (1-agc_fac)
    693         g0 = mult (i, sub (32767, agc_fac));
    694     }
    695 
    696     // compute gain[n] = agc_fac * gain[n-1]
    697                         + (1-agc_fac) * sqrt(gain_in/gain_out)
    698     // sig_out[n] = gain[n] * sig_out[n]
    699 
    700     gain = st->past_gain;
    701 
    702     for (i = 0; i < l_trm; i++)
    703     {
    704         gain = mult (gain, agc_fac);
    705         gain = add (gain, g0);
    706         sig_out[i] = extract_h (L_shl (L_mult (sig_out[i], gain), 3));
    707     }
    708 
    709     st->past_gain = gain;
    710 
    711     return 0;
    712 }
    713 
    714 ------------------------------------------------------------------------------
    715  RESOURCES USED [optional]
    716 
    717  When the code is written for a specific target processor the
    718  the resources used should be documented below.
    719 
    720  HEAP MEMORY USED: x bytes
    721 
    722  STACK MEMORY USED: x bytes
    723 
    724  CLOCK CYCLES: (cycle count equation for this function) + (variable
    725                 used to represent cycle count for each subroutine
    726                 called)
    727      where: (cycle count variable) = cycle count for [subroutine
    728                                      name]
    729 
    730 ------------------------------------------------------------------------------
    731  CAUTION [optional]
    732  [State any special notes, constraints or cautions for users of this function]
    733 
    734 ------------------------------------------------------------------------------
    735 */
    736 
    737 void agc(
    738     agcState *st,      /* i/o : agc state                        */
    739     Word16 *sig_in,    /* i   : postfilter input signal  (l_trm) */
    740     Word16 *sig_out,   /* i/o : postfilter output signal (l_trm) */
    741     Word16 agc_fac,    /* i   : AGC factor                       */
    742     Word16 l_trm,      /* i   : subframe size                    */
    743     Flag *pOverflow    /* i   : overflow Flag                    */
    744 
    745 )
    746 
    747 {
    748     Word16  i;
    749     Word16  exp;
    750     Word16  gain_in;
    751     Word16  gain_out;
    752     Word16  g0;
    753     Word16  gain;
    754     Word32  s;
    755     Word32  L_temp;
    756     Word16  temp;
    757 
    758     Word16 *p_sig_out;
    759 
    760     /* calculate gain_out with exponent */
    761     s = energy_new(sig_out, l_trm, pOverflow);  /* function result */
    762 
    763     if (s == 0)
    764     {
    765         st->past_gain = 0;
    766         return;
    767     }
    768     exp = norm_l(s) - 1;
    769 
    770     L_temp = L_shl(s, exp, pOverflow);
    771     gain_out = pv_round(L_temp, pOverflow);
    772 
    773     /* calculate gain_in with exponent */
    774     s = energy_new(sig_in, l_trm, pOverflow);    /* function result */
    775 
    776     if (s == 0)
    777     {
    778         g0 = 0;
    779     }
    780     else
    781     {
    782         i = norm_l(s);
    783 
    784         /* L_temp = L_shl(s, i, pOverflow); */
    785         L_temp = s << i;
    786 
    787         gain_in = pv_round(L_temp, pOverflow);
    788 
    789         exp -= i;
    790 
    791         /*---------------------------------------------------*
    792          *  g0 = (1-agc_fac) * sqrt(gain_in/gain_out);       *
    793          *---------------------------------------------------*/
    794 
    795         /* s = gain_out / gain_in */
    796         temp = div_s(gain_out, gain_in);
    797 
    798         /* s = L_deposit_l (temp); */
    799         s = (Word32) temp;
    800         s = s << 7;
    801         s = L_shr(s, exp, pOverflow);      /* add exponent */
    802 
    803         s = Inv_sqrt(s, pOverflow);    /* function result */
    804         L_temp = s << 9;
    805 
    806         i = (Word16)((L_temp + (Word32) 0x00008000L) >> 16);
    807 
    808         /* g0 = i * (1-agc_fac) */
    809         temp = 32767 - agc_fac;
    810 
    811         g0 = (Word16)(((Word32) i * temp) >> 15);
    812 
    813     }
    814 
    815     /* compute gain[n] = agc_fac * gain[n-1]
    816                         + (1-agc_fac) * sqrt(gain_in/gain_out) */
    817     /* sig_out[n] = gain[n] * sig_out[n]                        */
    818 
    819     gain = st->past_gain;
    820     p_sig_out = sig_out;
    821 
    822     for (i = 0; i < l_trm; i++)
    823     {
    824         /* gain = mult (gain, agc_fac, pOverflow); */
    825         gain = (Word16)(((Word32) gain * agc_fac) >> 15);
    826 
    827         /* gain = add (gain, g0, pOverflow); */
    828         gain += g0;
    829 
    830         /* L_temp = L_mult (sig_out[i], gain, pOverflow); */
    831         L_temp = ((Word32)(*(p_sig_out)) * gain) << 1;
    832 
    833         *(p_sig_out++) = (Word16)(L_temp >> 13);
    834     }
    835 
    836     st->past_gain = gain;
    837 
    838     return;
    839 }
    840 
    841 /*--------------------------------------------------------------------------*/
    842 
    843 /*
    844 ------------------------------------------------------------------------------
    845  FUNCTION NAME: agc2
    846 ------------------------------------------------------------------------------
    847  INPUT AND OUTPUT DEFINITIONS
    848 
    849  Inputs:
    850     sig_in = pointer to a buffer containing the postfilter input signal
    851     sig_out = pointer to a buffer containing the postfilter output signal
    852     l_trm = subframe size
    853     pOverflow = pointer to overflow flag
    854 
    855  Outputs:
    856     sig_out points to a buffer containing the new scaled output signal.
    857     pOverflow -> 1 if the agc computation saturates
    858 
    859  Returns:
    860     None.
    861 
    862  Global Variables Used:
    863     None.
    864 
    865  Local Variables Needed:
    866     None.
    867 
    868 ------------------------------------------------------------------------------
    869  FUNCTION DESCRIPTION
    870 
    871  Scales the excitation on a subframe basis.
    872 
    873 ------------------------------------------------------------------------------
    874  REQUIREMENTS
    875 
    876  None.
    877 
    878 ------------------------------------------------------------------------------
    879  REFERENCES
    880 
    881  agc.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
    882 
    883 ------------------------------------------------------------------------------
    884  PSEUDO-CODE
    885 
    886 void agc2 (
    887  Word16 *sig_in,        // i   : postfilter input signal
    888  Word16 *sig_out,       // i/o : postfilter output signal
    889  Word16 l_trm           // i   : subframe size
    890 )
    891 {
    892     Word16 i, exp;
    893     Word16 gain_in, gain_out, g0;
    894     Word32 s;
    895 
    896     // calculate gain_out with exponent
    897     s = energy_new(sig_out, l_trm); // function result
    898 
    899     if (s == 0)
    900     {
    901         return;
    902     }
    903     exp = sub (norm_l (s), 1);
    904     gain_out = pv_round (L_shl (s, exp));
    905 
    906     // calculate gain_in with exponent
    907     s = energy_new(sig_in, l_trm); // function result
    908 
    909     if (s == 0)
    910     {
    911         g0 = 0;
    912     }
    913     else
    914     {
    915         i = norm_l (s);
    916         gain_in = pv_round (L_shl (s, i));
    917         exp = sub (exp, i);
    918 
    919          *---------------------------------------------------*
    920          *  g0 = sqrt(gain_in/gain_out);                     *
    921          *---------------------------------------------------*
    922 
    923         s = L_deposit_l (div_s (gain_out, gain_in));
    924         s = L_shl (s, 7);       // s = gain_out / gain_in
    925         s = L_shr (s, exp);     // add exponent
    926 
    927         s = Inv_sqrt (s); // function result
    928         g0 = pv_round (L_shl (s, 9));
    929     }
    930 
    931     // sig_out(n) = gain(n) sig_out(n)
    932 
    933     for (i = 0; i < l_trm; i++)
    934     {
    935         sig_out[i] = extract_h (L_shl (L_mult (sig_out[i], g0), 3));
    936     }
    937 
    938     return;
    939 }
    940 ------------------------------------------------------------------------------
    941  RESOURCES USED [optional]
    942 
    943  When the code is written for a specific target processor the
    944  the resources used should be documented below.
    945 
    946  HEAP MEMORY USED: x bytes
    947 
    948  STACK MEMORY USED: x bytes
    949 
    950  CLOCK CYCLES: (cycle count equation for this function) + (variable
    951                 used to represent cycle count for each subroutine
    952                 called)
    953      where: (cycle count variable) = cycle count for [subroutine
    954                                      name]
    955 
    956 ------------------------------------------------------------------------------
    957  CAUTION [optional]
    958  [State any special notes, constraints or cautions for users of this function]
    959 
    960 ------------------------------------------------------------------------------
    961 */
    962 
    963 void agc2(
    964     Word16 *sig_in,        /* i   : postfilter input signal  */
    965     Word16 *sig_out,       /* i/o : postfilter output signal */
    966     Word16 l_trm,          /* i   : subframe size            */
    967     Flag   *pOverflow      /* i   : overflow flag            */
    968 )
    969 
    970 {
    971     Word16  i;
    972     Word16  exp;
    973     Word16  gain_in;
    974     Word16  gain_out;
    975     Word16  g0;
    976     Word32  s;
    977     Word32  L_temp;
    978     Word16  temp;
    979 
    980     /* calculate gain_out with exponent */
    981     s = energy_new(sig_out, l_trm, pOverflow); /* function result */
    982 
    983     if (s == 0)
    984     {
    985         return;
    986     }
    987     exp = norm_l(s) - 1;
    988     L_temp = L_shl(s, exp, pOverflow);
    989     gain_out = pv_round(L_temp, pOverflow);
    990 
    991     /* calculate gain_in with exponent */
    992     s = energy_new(sig_in, l_trm, pOverflow); /* function result */
    993 
    994     if (s == 0)
    995     {
    996         g0 = 0;
    997     }
    998     else
    999     {
   1000         i = norm_l(s);
   1001         L_temp = L_shl(s, i, pOverflow);
   1002         gain_in = pv_round(L_temp, pOverflow);
   1003         exp -= i;
   1004 
   1005         /*---------------------------------------------------*
   1006          *  g0 = sqrt(gain_in/gain_out);                     *
   1007          *---------------------------------------------------*/
   1008 
   1009         /* s = gain_out / gain_in */
   1010         temp = div_s(gain_out, gain_in);
   1011 
   1012         /* s = L_deposit_l (temp); */
   1013         s = (Word32)temp;
   1014 
   1015         if (s > (Word32) 0x00FFFFFFL)
   1016         {
   1017             s = MAX_32;
   1018         }
   1019         else if (s < (Word32) 0xFF000000L)
   1020         {
   1021             s = MIN_32;
   1022         }
   1023         else
   1024         {
   1025             s = s << 7;
   1026         }
   1027         s = L_shr(s, exp, pOverflow);      /* add exponent */
   1028 
   1029         s = Inv_sqrt(s, pOverflow);    /* function result */
   1030 
   1031         if (s > (Word32) 0x003FFFFFL)
   1032         {
   1033             L_temp = MAX_32;
   1034         }
   1035         else if (s < (Word32) 0xFFC00000L)
   1036         {
   1037             L_temp = MIN_32;
   1038         }
   1039         else
   1040         {
   1041             L_temp = s << 9;
   1042         }
   1043         g0 = pv_round(L_temp, pOverflow);
   1044     }
   1045 
   1046     /* sig_out(n) = gain(n) sig_out(n) */
   1047 
   1048     for (i = l_trm - 1; i >= 0; i--)
   1049     {
   1050         L_temp = L_mult(sig_out[i], g0, pOverflow);
   1051         if (L_temp > (Word32) 0x0FFFFFFFL)
   1052         {
   1053             sig_out[i] = MAX_16;
   1054         }
   1055         else if (L_temp < (Word32) 0xF0000000L)
   1056         {
   1057             sig_out[i] = MIN_16;
   1058         }
   1059         else
   1060         {
   1061             sig_out[i] = (Word16)(L_temp >> 13);
   1062         }
   1063     }
   1064 
   1065     return;
   1066 }
   1067