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 
ph_disp_reset(ph_dispState * state)208 Word16 ph_disp_reset(ph_dispState *state)
209 {
210     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 
ph_disp_lock(ph_dispState * state)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 
ph_disp_release(ph_dispState * state)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 
ph_disp(ph_dispState * state,enum Mode mode,Word16 x[],Word16 cbGain,Word16 ltpGain,Word16 inno[],Word16 pitch_fac,Word16 tmp_shift,Flag * pOverflow)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     Word16 i, i1;
671     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     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