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/ph_disp.c
     35  Functions:
     36             ph_disp_reset
     37             ph_disp_lock
     38             ph_disp_release
     39             ph_disp
     40 
     41      Date: 04/05/2000
     42 
     43 ------------------------------------------------------------------------------
     44  REVISION HISTORY
     45 
     46  Description: Changed template used to PV coding template. First attempt at
     47           optimizing C code.
     48 
     49  Description: Updated file per comments gathered from Phase 2/3 review.
     50 
     51  Description: Clarified grouping in the equation to calculated L_temp from the
     52           product of state->prevCbGain and ONFACTPLUS1 in the ph_disp
     53           function.
     54 
     55  Description: Added setting of Overflow flag in inlined code.
     56 
     57  Description: Synchronized file with UMTS version 3.2.0. Updated coding
     58               coding template. Removed unnecessary include files.
     59 
     60  Description: Replaced basic_op.h with the header file of the math functions
     61               used in the file.
     62 
     63  Description: Removed the functions ph_disp_init and ph_disp_exit.
     64  The ph_disp related structure is no longer dynamically allocated.
     65 
     66  Description: Pass in pointer to overflow flag for EPOC compatibility.
     67               Change code for ph_disp() function to reflect this. Remove
     68               inclusion of ph_disp.tab. This table will now be referenced
     69               externally.
     70 
     71  Description: Optimized ph_disp() to reduce clock cycle usage. Updated
     72               copyright year and removed unused files in Include section.
     73 
     74  Description:  Replaced OSCL mem type functions and eliminated include
     75                files that now are chosen by OSCL definitions
     76 
     77  Description:  Replaced "int" and/or "char" with defined types.
     78                Added proper casting (Word32) to some left shifting operations
     79 
     80  Description: Changed round function name to pv_round to avoid conflict with
     81               round function in C standard library.
     82 
     83  Description:
     84 
     85 ------------------------------------------------------------------------------
     86  MODULE DESCRIPTION
     87 
     88  This file contains the function that performs adaptive phase dispersion of
     89  the excitation signal. The phase dispersion initialization, reset, and
     90  exit functions are included in this file, as well as, the phase dispersion
     91  lock and release functions.
     92 
     93 ------------------------------------------------------------------------------
     94 */
     95 
     96 /*----------------------------------------------------------------------------
     97 ; INCLUDES
     98 ----------------------------------------------------------------------------*/
     99 #include "ph_disp.h"
    100 #include "typedef.h"
    101 #include "basic_op.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 
    115 /*----------------------------------------------------------------------------
    116 ; LOCAL FUNCTION DEFINITIONS
    117 ; Function Prototype declaration
    118 ----------------------------------------------------------------------------*/
    119 
    120 /*----------------------------------------------------------------------------
    121 ; LOCAL VARIABLE DEFINITIONS
    122 ; Variable declaration - defined here and used outside this module
    123 ----------------------------------------------------------------------------*/
    124 
    125 
    126 /*
    127 ------------------------------------------------------------------------------
    128  FUNCTION NAME: ph_disp_reset
    129 ------------------------------------------------------------------------------
    130  INPUT AND OUTPUT DEFINITIONS
    131 
    132  Inputs:
    133     state = pointer to a structure of type ph_dispState
    134 
    135  Outputs:
    136     Structure pointed to by state is initialized to zeros
    137 
    138  Returns:
    139     return_value = 0, if reset was successful; -1, otherwise (int)
    140 
    141  Global Variables Used:
    142     None
    143 
    144  Local Variables Needed:
    145     None
    146 
    147 ------------------------------------------------------------------------------
    148  FUNCTION DESCRIPTION
    149 
    150  This function resets the variables used by the phase dispersion function.
    151 
    152 ------------------------------------------------------------------------------
    153  REQUIREMENTS
    154 
    155  None
    156 
    157 ------------------------------------------------------------------------------
    158  REFERENCES
    159 
    160  ph_disp.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
    161 
    162 ------------------------------------------------------------------------------
    163  PSEUDO-CODE
    164 
    165 int ph_disp_reset (ph_dispState *state)
    166 {
    167   Word16 i;
    168 
    169    if (state == (ph_dispState *) NULL){
    170       fprint(stderr, "ph_disp_reset: invalid parameter\n");
    171       return -1;
    172    }
    173    for (i=0; i<PHDGAINMEMSIZE; i++)
    174    {
    175        state->gainMem[i] = 0;
    176    }
    177    state->prevState = 0;
    178    state->prevCbGain = 0;
    179    state->lockFull = 0;
    180    state->onset = 0;          // assume no onset in start
    181 
    182    return 0;
    183 }
    184 
    185 ------------------------------------------------------------------------------
    186  RESOURCES USED [optional]
    187 
    188  When the code is written for a specific target processor the
    189  the resources used should be documented below.
    190 
    191  HEAP MEMORY USED: x bytes
    192 
    193  STACK MEMORY USED: x bytes
    194 
    195  CLOCK CYCLES: (cycle count equation for this function) + (variable
    196                 used to represent cycle count for each subroutine
    197                 called)
    198      where: (cycle count variable) = cycle count for [subroutine
    199                                      name]
    200 
    201 ------------------------------------------------------------------------------
    202  CAUTION [optional]
    203  [State any special notes, constraints or cautions for users of this function]
    204 
    205 ------------------------------------------------------------------------------
    206 */
    207 
    208 Word16 ph_disp_reset(ph_dispState *state)
    209 {
    210     register Word16 i;
    211 
    212     if (state == (ph_dispState *) NULL)
    213     {
    214         /*  fprint(stderr, "ph_disp_reset: invalid parameter\n");  */
    215         return(-1);
    216     }
    217     for (i = 0; i < PHDGAINMEMSIZE; i++)
    218     {
    219         state->gainMem[i] = 0;
    220     }
    221     state->prevState = 0;
    222     state->prevCbGain = 0;
    223     state->lockFull = 0;
    224     state->onset = 0;          /* assume no onset in start */
    225 
    226     return(0);
    227 }
    228 
    229 /****************************************************************************/
    230 
    231 /*
    232 ------------------------------------------------------------------------------
    233  FUNCTION NAME: ph_disp_lock
    234 ------------------------------------------------------------------------------
    235  INPUT AND OUTPUT DEFINITIONS
    236 
    237  Inputs:
    238     state = pointer to a structure of type ph_dispState
    239 
    240  Outputs:
    241     lockFull field of the structure pointed to by state is set to 1
    242 
    243  Returns:
    244     None
    245 
    246  Global Variables Used:
    247     None
    248 
    249  Local Variables Needed:
    250     None
    251 
    252 ------------------------------------------------------------------------------
    253  FUNCTION DESCRIPTION
    254 
    255  This function sets the lockFull flag to indicate a lock condition.
    256 
    257 ------------------------------------------------------------------------------
    258  REQUIREMENTS
    259 
    260  None
    261 
    262 ------------------------------------------------------------------------------
    263  REFERENCES
    264 
    265  ph_disp.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
    266 
    267 ------------------------------------------------------------------------------
    268  PSEUDO-CODE
    269 
    270 void ph_disp_lock (ph_dispState *state)
    271 {
    272   state->lockFull = 1;
    273   return;
    274 }
    275 
    276 ------------------------------------------------------------------------------
    277  RESOURCES USED [optional]
    278 
    279  When the code is written for a specific target processor the
    280  the resources used should be documented below.
    281 
    282  HEAP MEMORY USED: x bytes
    283 
    284  STACK MEMORY USED: x bytes
    285 
    286  CLOCK CYCLES: (cycle count equation for this function) + (variable
    287                 used to represent cycle count for each subroutine
    288                 called)
    289      where: (cycle count variable) = cycle count for [subroutine
    290                                      name]
    291 
    292 ------------------------------------------------------------------------------
    293  CAUTION [optional]
    294  [State any special notes, constraints or cautions for users of this function]
    295 
    296 ------------------------------------------------------------------------------
    297 */
    298 
    299 void ph_disp_lock(ph_dispState *state)
    300 {
    301     state->lockFull = 1;
    302 
    303     return;
    304 }
    305 
    306 /****************************************************************************/
    307 
    308 /*
    309 ------------------------------------------------------------------------------
    310  FUNCTION NAME: ph_disp_release
    311 ------------------------------------------------------------------------------
    312  INPUT AND OUTPUT DEFINITIONS
    313 
    314  Inputs:
    315     state = pointer to a structure of type ph_dispState
    316 
    317  Outputs:
    318     lockFull field of the structure pointed to by state is set to 0
    319 
    320  Returns:
    321     None
    322 
    323  Global Variables Used:
    324     None
    325 
    326  Local Variables Needed:
    327     None
    328 
    329 ------------------------------------------------------------------------------
    330  FUNCTION DESCRIPTION
    331 
    332  This function clears the lockFull flag to indicate an unlocked state.
    333 
    334 ------------------------------------------------------------------------------
    335  REQUIREMENTS
    336 
    337  None
    338 
    339 ------------------------------------------------------------------------------
    340  REFERENCES
    341 
    342  ph_disp.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
    343 
    344 ------------------------------------------------------------------------------
    345  PSEUDO-CODE
    346 
    347 void ph_disp_release (ph_dispState *state)
    348 {
    349   state->lockFull = 0;
    350   return;
    351 }
    352 
    353 ------------------------------------------------------------------------------
    354  RESOURCES USED [optional]
    355 
    356  When the code is written for a specific target processor the
    357  the resources used should be documented below.
    358 
    359  HEAP MEMORY USED: x bytes
    360 
    361  STACK MEMORY USED: x bytes
    362 
    363  CLOCK CYCLES: (cycle count equation for this function) + (variable
    364                 used to represent cycle count for each subroutine
    365                 called)
    366      where: (cycle count variable) = cycle count for [subroutine
    367                                      name]
    368 
    369 ------------------------------------------------------------------------------
    370  CAUTION [optional]
    371  [State any special notes, constraints or cautions for users of this function]
    372 
    373 ------------------------------------------------------------------------------
    374 */
    375 
    376 void ph_disp_release(ph_dispState *state)
    377 {
    378     state->lockFull = 0;
    379 
    380     return;
    381 }
    382 
    383 /****************************************************************************/
    384 
    385 /*
    386 ------------------------------------------------------------------------------
    387  FUNCTION NAME: ph_disp
    388 ------------------------------------------------------------------------------
    389  INPUT AND OUTPUT DEFINITIONS
    390 
    391  Inputs:
    392     state = pointer to a structure of type ph_dispState
    393     mode = codec mode (enum Mode)
    394     x = LTP excitation signal buffer (Word16)
    395     cbGain = codebook gain (Word16)
    396     ltpGain = LTP gain (Word16)
    397     inno = innovation buffer (Word16)
    398     pitch_fac = pitch factor used to scale the LTP excitation (Word16)
    399     tmp_shift = shift factor applied to sum of scaled LTP excitation and
    400                 innovation before rounding (Word16)
    401     pOverflow = pointer to overflow indicator (Flag)
    402 
    403  Outputs:
    404     structure pointed to by state contains the updated gainMem array,
    405       prevState, prevCbGain, and onset fields
    406     x buffer contains the new excitation signal
    407     inno buffer contains the new innovation signal
    408     pOverflow -> 1 if there is overflow
    409 
    410  Returns:
    411     None
    412 
    413  Global Variables Used:
    414     None
    415 
    416  Local Variables Needed:
    417     None
    418 
    419 ------------------------------------------------------------------------------
    420  FUNCTION DESCRIPTION
    421 
    422  This function performs adaptive phase dispersion, i.e., forming of total
    423  excitation for the synthesis part of the decoder.
    424 
    425 ------------------------------------------------------------------------------
    426  REQUIREMENTS
    427 
    428  None
    429 
    430 ------------------------------------------------------------------------------
    431  REFERENCES
    432 
    433  ph_disp.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
    434 
    435 ------------------------------------------------------------------------------
    436  PSEUDO-CODE
    437 
    438 void ph_disp (
    439       ph_dispState *state, // i/o     : State struct
    440       enum Mode mode,      // i       : codec mode
    441       Word16 x[],          // i/o Q0  : in:  LTP excitation signal
    442                            //           out: total excitation signal
    443       Word16 cbGain,       // i   Q1  : Codebook gain
    444       Word16 ltpGain,      // i   Q14 : LTP gain
    445       Word16 inno[],       // i/o Q13 : Innovation vector (Q12 for 12.2)
    446       Word16 pitch_fac,    // i   Q14 : pitch factor used to scale the
    447                                         LTP excitation (Q13 for 12.2)
    448       Word16 tmp_shift     // i   Q0  : shift factor applied to sum of
    449                                         scaled LTP ex & innov. before
    450                                         rounding
    451 )
    452 {
    453    Word16 i, i1;
    454    Word16 tmp1;
    455    Word32 L_temp;
    456    Word16 impNr;           // indicator for amount of disp./filter used
    457 
    458    Word16 inno_sav[L_SUBFR];
    459    Word16 ps_poss[L_SUBFR];
    460    Word16 j, nze, nPulse, ppos;
    461    const Word16 *ph_imp;   // Pointer to phase dispersion filter
    462 
    463    // Update LTP gain memory
    464    for (i = PHDGAINMEMSIZE-1; i > 0; i--)
    465    {
    466        state->gainMem[i] = state->gainMem[i-1];
    467    }
    468    state->gainMem[0] = ltpGain;
    469 
    470    // basic adaption of phase dispersion
    471    if (sub(ltpGain, PHDTHR2LTP) < 0) {    // if (ltpGain < 0.9)
    472        if (sub(ltpGain, PHDTHR1LTP) > 0)
    473        {  // if (ltpGain > 0.6
    474           impNr = 1; // medium dispersion
    475        }
    476        else
    477        {
    478           impNr = 0; // maximum dispersion
    479        }
    480    }
    481    else
    482    {
    483       impNr = 2; // no dispersion
    484    }
    485 
    486    // onset indicator
    487    // onset = (cbGain  > onFact * cbGainMem[0])
    488    tmp1 = pv_round(L_shl(L_mult(state->prevCbGain, ONFACTPLUS1), 2));
    489    if (sub(cbGain, tmp1) > 0)
    490    {
    491        state->onset = ONLENGTH;
    492    }
    493    else
    494    {
    495        if (state->onset > 0)
    496        {
    497            state->onset = sub (state->onset, 1);
    498        }
    499    }
    500 
    501    // if not onset, check ltpGain buffer and use max phase dispersion if
    502       half or more of the ltpGain-parameters say so
    503    if (state->onset == 0)
    504    {
    505        // Check LTP gain memory and set filter accordingly
    506        i1 = 0;
    507        for (i = 0; i < PHDGAINMEMSIZE; i++)
    508        {
    509            if (sub(state->gainMem[i], PHDTHR1LTP) < 0)
    510            {
    511                i1 = add (i1, 1);
    512            }
    513        }
    514        if (sub(i1, 2) > 0)
    515        {
    516            impNr = 0;
    517        }
    518 
    519    }
    520    // Restrict decrease in phase dispersion to one step if not onset
    521    if ((sub(impNr, add(state->prevState, 1)) > 0) && (state->onset == 0))
    522    {
    523        impNr = sub (impNr, 1);
    524    }
    525    // if onset, use one step less phase dispersion
    526    if((sub(impNr, 2) < 0) && (state->onset > 0))
    527    {
    528        impNr = add (impNr, 1);
    529    }
    530 
    531    // disable for very low levels
    532    if(sub(cbGain, 10) < 0)
    533    {
    534        impNr = 2;
    535    }
    536 
    537    if(sub(state->lockFull, 1) == 0)
    538    {
    539        impNr = 0;
    540    }
    541 
    542    // update static memory
    543    state->prevState = impNr;
    544    state->prevCbGain = cbGain;
    545 
    546    // do phase dispersion for all modes but 12.2 and 7.4;
    547    // don't modify the innovation if impNr >=2 (= no phase disp)
    548    if (sub(mode, MR122) != 0 &&
    549        sub(mode, MR102) != 0 &&
    550        sub(mode, MR74) != 0 &&
    551        sub(impNr, 2) < 0)
    552    {
    553        // track pulse positions, save innovation,
    554           and initialize new innovation
    555        nze = 0;
    556        for (i = 0; i < L_SUBFR; i++)
    557        {
    558            if (inno[i] != 0)
    559            {
    560                ps_poss[nze] = i;
    561                nze = add (nze, 1);
    562            }
    563            inno_sav[i] = inno[i];
    564            inno[i] = 0;
    565        }
    566        // Choose filter corresponding to codec mode and dispersion criterium
    567        if (sub (mode, MR795) == 0)
    568        {
    569            if (impNr == 0)
    570            {
    571                ph_imp = ph_imp_low_MR795;
    572            }
    573            else
    574            {
    575                ph_imp = ph_imp_mid_MR795;
    576            }
    577        }
    578        else
    579        {
    580            if (impNr == 0)
    581            {
    582                ph_imp = ph_imp_low;
    583            }
    584            else
    585            {
    586                ph_imp = ph_imp_mid;
    587            }
    588        }
    589 
    590        // Do phase dispersion of innovation
    591        for (nPulse = 0; nPulse < nze; nPulse++)
    592        {
    593            ppos = ps_poss[nPulse];
    594 
    595            // circular convolution with impulse response
    596            j = 0;
    597            for (i = ppos; i < L_SUBFR; i++)
    598            {
    599                // inno[i1] += inno_sav[ppos] * ph_imp[i1-ppos]
    600                tmp1 = mult(inno_sav[ppos], ph_imp[j++]);
    601                inno[i] = add(inno[i], tmp1);
    602            }
    603 
    604            for (i = 0; i < ppos; i++)
    605            {
    606                // inno[i] += inno_sav[ppos] * ph_imp[L_SUBFR-ppos+i]
    607                tmp1 = mult(inno_sav[ppos], ph_imp[j++]);
    608                inno[i] = add(inno[i], tmp1);
    609            }
    610        }
    611    }
    612 
    613    // compute total excitation for synthesis part of decoder
    614    // (using modified innovation if phase dispersion is active)
    615    for (i = 0; i < L_SUBFR; i++)
    616    {
    617        // x[i] = gain_pit*x[i] + cbGain*code[i];
    618        L_temp = L_mult (        x[i],    pitch_fac);
    619                                                 // 12.2: Q0 * Q13
    620                                                 //  7.4: Q0 * Q14
    621        L_temp = L_mac  (L_temp, inno[i], cbGain);
    622                                                 // 12.2: Q12 * Q1
    623                                                 //  7.4: Q13 * Q1
    624        L_temp = L_shl (L_temp, tmp_shift);                 // Q16
    625        x[i] = pv_round (L_temp);
    626    }
    627 
    628    return;
    629 }
    630 
    631 ------------------------------------------------------------------------------
    632  RESOURCES USED [optional]
    633 
    634  When the code is written for a specific target processor the
    635  the resources used should be documented below.
    636 
    637  HEAP MEMORY USED: x bytes
    638 
    639  STACK MEMORY USED: x bytes
    640 
    641  CLOCK CYCLES: (cycle count equation for this function) + (variable
    642                 used to represent cycle count for each subroutine
    643                 called)
    644      where: (cycle count variable) = cycle count for [subroutine
    645                                      name]
    646 
    647 ------------------------------------------------------------------------------
    648  CAUTION [optional]
    649  [State any special notes, constraints or cautions for users of this function]
    650 
    651 ------------------------------------------------------------------------------
    652 */
    653 
    654 void ph_disp(
    655     ph_dispState *state,    /* i/o     : State struct                       */
    656     enum Mode mode,         /* i       : codec mode                         */
    657     Word16 x[],             /* i/o Q0  : in:  LTP excitation signal         */
    658     /*           out: total excitation signal       */
    659     Word16 cbGain,          /* i   Q1  : Codebook gain                      */
    660     Word16 ltpGain,         /* i   Q14 : LTP gain                           */
    661     Word16 inno[],          /* i/o Q13 : Innovation vector (Q12 for 12.2)   */
    662     Word16 pitch_fac,       /* i   Q14 : pitch factor used to scale the
    663                                          LTP excitation (Q13 for 12.2)      */
    664     Word16 tmp_shift,       /* i   Q0  : shift factor applied to sum of
    665                                          scaled LTP ex & innov. before
    666                                          rounding                           */
    667     Flag   *pOverflow       /* i/o     : oveflow indicator                  */
    668 )
    669 {
    670     register Word16 i, i1;
    671     register Word16 tmp1;
    672     Word32 L_temp;
    673     Word32 L_temp2;
    674     Word16 impNr;           /* indicator for amount of disp./filter used */
    675 
    676     Word16 inno_sav[L_SUBFR];
    677     Word16 ps_poss[L_SUBFR];
    678     register Word16 nze, nPulse;
    679     Word16 ppos;
    680     const Word16 *ph_imp;   /* Pointer to phase dispersion filter */
    681 
    682     Word16 *p_inno;
    683     Word16 *p_inno_sav;
    684     Word16 *p_x;
    685     const Word16 *p_ph_imp;
    686     Word16 c_inno_sav;
    687 
    688     /* Update LTP gain memory */
    689     /* Unrolled FOR loop below since PHDGAINMEMSIZE is assumed to stay */
    690     /* the same.                                                       */
    691     /* for (i = PHDGAINMEMSIZE-1; i > 0; i--)                          */
    692     /* {                                                               */
    693     /*    state->gainMem[i] = state->gainMem[i-1];                     */
    694     /* }                                                               */
    695     state->gainMem[4] = state->gainMem[3];
    696     state->gainMem[3] = state->gainMem[2];
    697     state->gainMem[2] = state->gainMem[1];
    698     state->gainMem[1] = state->gainMem[0];
    699     state->gainMem[0] = ltpGain;
    700 
    701     /* basic adaption of phase dispersion */
    702 
    703     if (ltpGain < PHDTHR2LTP)    /* if (ltpGain < 0.9) */
    704     {
    705         if (ltpGain > PHDTHR1LTP)
    706         {  /* if (ltpGain > 0.6 */
    707             impNr = 1; /* medium dispersion */
    708         }
    709         else
    710         {
    711             impNr = 0; /* maximum dispersion */
    712         }
    713     }
    714     else
    715     {
    716         impNr = 2; /* no dispersion */
    717     }
    718 
    719     /* onset indicator */
    720     /* onset = (cbGain  > onFact * cbGainMem[0]) */
    721 
    722     L_temp = ((Word32) state->prevCbGain * ONFACTPLUS1) << 1;
    723 
    724     /* (L_temp << 2) calculation with saturation check */
    725     if (L_temp > (Word32) 0X1fffffffL)
    726     {
    727         *pOverflow = 1;
    728         L_temp = MAX_32;
    729     }
    730     else if (L_temp < (Word32) 0xe0000000L)
    731     {
    732         *pOverflow = 1;
    733         L_temp = MIN_32;
    734     }
    735     else
    736     {
    737         L_temp <<= 2;
    738     }
    739 
    740     tmp1 = pv_round(L_temp, pOverflow);
    741 
    742     if (cbGain > tmp1)
    743     {
    744         state->onset = ONLENGTH;
    745     }
    746     else
    747     {
    748 
    749         if (state->onset > 0)
    750         {
    751             state->onset -= 1;
    752         }
    753     }
    754 
    755     /* if not onset, check ltpGain buffer and use max phase dispersion if
    756        half or more of the ltpGain-parameters say so */
    757     if (state->onset == 0)
    758     {
    759         /* Check LTP gain memory and set filter accordingly */
    760         i1 = 0;
    761         for (i = 0; i < PHDGAINMEMSIZE; i++)
    762         {
    763             if (state->gainMem[i] < PHDTHR1LTP)
    764             {
    765                 i1 += 1;
    766             }
    767         }
    768 
    769         if (i1 > 2)
    770         {
    771             impNr = 0;
    772         }
    773     }
    774     /* Restrict decrease in phase dispersion to one step if not onset */
    775     if ((impNr > ((state->prevState) + 1)) && (state->onset == 0))
    776     {
    777         impNr -= 1;
    778     }
    779 
    780     /* if onset, use one step less phase dispersion */
    781     if ((impNr < 2) && (state->onset > 0))
    782     {
    783         impNr += 1;
    784     }
    785 
    786     /* disable for very low levels */
    787     if (cbGain < 10)
    788     {
    789         impNr = 2;
    790     }
    791 
    792     if (state->lockFull == 1)
    793     {
    794         impNr = 0;
    795     }
    796 
    797     /* update static memory */
    798     state->prevState = impNr;
    799     state->prevCbGain = cbGain;
    800 
    801     /* do phase dispersion for all modes but 12.2 and 7.4;
    802        don't modify the innovation if impNr >=2 (= no phase disp) */
    803     if ((mode != MR122) && (mode != MR102) && (mode != MR74) && (impNr < 2))
    804     {
    805         /* track pulse positions, save innovation,
    806            and initialize new innovation          */
    807         nze = 0;
    808         p_inno = &inno[0];
    809         p_inno_sav = &inno_sav[0];
    810 
    811         for (i = 0; i < L_SUBFR; i++)
    812         {
    813             if (*(p_inno) != 0)
    814             {
    815                 ps_poss[nze] = i;
    816                 nze += 1;
    817             }
    818             *(p_inno_sav++) = *(p_inno);
    819             *(p_inno++) = 0;
    820         }
    821 
    822         /* Choose filter corresponding to codec mode and dispersion criterium */
    823         if (mode == MR795)
    824         {
    825             if (impNr == 0)
    826             {
    827                 ph_imp = ph_imp_low_MR795;
    828             }
    829             else
    830             {
    831                 ph_imp = ph_imp_mid_MR795;
    832             }
    833         }
    834         else
    835         {
    836             if (impNr == 0)
    837             {
    838                 ph_imp = ph_imp_low;
    839             }
    840             else
    841             {
    842                 ph_imp = ph_imp_mid;
    843             }
    844         }
    845 
    846         /* Do phase dispersion of innovation */
    847         for (nPulse = 0; nPulse < nze; nPulse++)
    848         {
    849             ppos = ps_poss[nPulse];
    850 
    851             /* circular convolution with impulse response */
    852             c_inno_sav = inno_sav[ppos];
    853             p_inno = &inno[ppos];
    854             p_ph_imp = ph_imp;
    855 
    856             for (i = ppos; i < L_SUBFR; i++)
    857             {
    858                 /* inno[i1] += inno_sav[ppos] * ph_imp[i1-ppos] */
    859                 L_temp = ((Word32) c_inno_sav * *(p_ph_imp++)) >> 15;
    860                 tmp1 = (Word16) L_temp;
    861                 *(p_inno) = add(*(p_inno), tmp1, pOverflow);
    862                 p_inno += 1;
    863             }
    864 
    865             p_inno = &inno[0];
    866 
    867             for (i = 0; i < ppos; i++)
    868             {
    869                 /* inno[i] += inno_sav[ppos] * ph_imp[L_SUBFR-ppos+i] */
    870                 L_temp = ((Word32) c_inno_sav * *(p_ph_imp++)) >> 15;
    871                 tmp1 = (Word16) L_temp;
    872                 *(p_inno) = add(*(p_inno), tmp1, pOverflow);
    873                 p_inno += 1;
    874             }
    875         }
    876     }
    877 
    878     /* compute total excitation for synthesis part of decoder
    879        (using modified innovation if phase dispersion is active) */
    880     p_inno = &inno[0];
    881     p_x = &x[0];
    882 
    883     for (i = 0; i < L_SUBFR; i++)
    884     {
    885         /* x[i] = gain_pit*x[i] + cbGain*code[i]; */
    886         L_temp = L_mult(x[i], pitch_fac, pOverflow);
    887         /* 12.2: Q0 * Q13 */
    888         /*  7.4: Q0 * Q14 */
    889         L_temp2 = ((Word32) * (p_inno++) * cbGain) << 1;
    890         L_temp = L_add(L_temp, L_temp2, pOverflow);
    891         /* 12.2: Q12 * Q1 */
    892         /*  7.4: Q13 * Q1 */
    893         L_temp = L_shl(L_temp, tmp_shift, pOverflow);                  /* Q16 */
    894         *(p_x++) = pv_round(L_temp, pOverflow);
    895     }
    896 
    897     return;
    898 }
    899