1/* ------------------------------------------------------------------
2 * Copyright (C) 1998-2009 PacketVideo
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
13 * express or implied.
14 * See the License for the specific language governing permissions
15 * and limitations under the License.
16 * -------------------------------------------------------------------
17 */
18/****************************************************************************************
19Portions of this file are derived from the following 3GPP standard:
20
21    3GPP TS 26.073
22    ANSI-C code for the Adaptive Multi-Rate (AMR) speech codec
23    Available from http://www.3gpp.org
24
25(C) 2004, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
26Permission to distribute, modify and use this file under the standard license
27terms listed above has been obtained from the copyright holder.
28****************************************************************************************/
29/*
30------------------------------------------------------------------------------
31
32
33
34 Pathname: ./audio/gsm-amr/c/src/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
165int 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
208Word16 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
270void 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
299void 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
347void 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
376void 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
438void 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
654void 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