Git init
[external/opencore-amr.git] / opencore / codecs_v2 / audio / gsm_amr / amr_nb / dec / src / agc.cpp
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
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
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
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
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
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
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
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) 0xFF000000L)
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) 0xFFC00000L)
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) 0xF0000000L)
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 }