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