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