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/agc.c
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
125static 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 RESOURCES USED [optional]
147
148 When the code is written for a specific target processor the
149 the resources used should be documented below.
150
151 HEAP MEMORY USED: x bytes
152
153 STACK MEMORY USED: x bytes
154
155 CLOCK CYCLES: (cycle count equation for this function) + (variable
156                used to represent cycle count for each subroutine
157                called)
158     where: (cycle count variable) = cycle count for [subroutine
159                                     name]
160
161------------------------------------------------------------------------------
162 CAUTION [optional]
163 [State any special notes, constraints or cautions for users of this function]
164
165------------------------------------------------------------------------------
166*/
167
168static Word32 energy_old(       /* o : return energy of signal      */
169    Word16 in[],        /* i : input signal (length l_trm)  */
170    Word16 l_trm,       /* i : signal length                */
171    Flag   *pOverflow   /* overflow: flag to indicate overflow */
172)
173
174{
175    Word32  s = 0;
176    Word16  i;
177    Word16  temp;
178
179    for (i = 0; i < l_trm; i++)
180    {
181        temp = in[i] >> 2;
182        s = L_mac(s, temp, temp, pOverflow);
183    }
184
185    return(s);
186}
187
188/*----------------------------------------------------------------------------*/
189/*
190------------------------------------------------------------------------------
191 FUNCTION NAME: energy_old__Wrapper
192------------------------------------------------------------------------------
193 INPUT AND OUTPUT DEFINITIONS
194
195 Inputs:
196    in = input signal (Word16)
197    l_trm = input signal length (Word16)
198    pOverflow = address of overflow (Flag)
199 Outputs:
200    pOverflow -> 1 if the energy computation saturates
201
202 Returns:
203    s = return energy of signal (Word32)
204
205 Global Variables Used:
206    None.
207
208 Local Variables Needed:
209    None.
210
211------------------------------------------------------------------------------
212 FUNCTION DESCRIPTION
213
214 This function provides external access to the static function energy_old.
215
216------------------------------------------------------------------------------
217 REQUIREMENTS
218
219 None
220
221------------------------------------------------------------------------------
222 REFERENCES
223
224 None
225
226------------------------------------------------------------------------------
227 PSEUDO-CODE
228
229 CALL energy_old (  in = in
230            l_trm = l_trm
231            pOverflow = pOverflow )
232   MODIFYING(nothing)
233   RETURNING(energy_old_value = s)
234
235------------------------------------------------------------------------------
236 RESOURCES USED [optional]
237
238 When the code is written for a specific target processor the
239 the resources used should be documented below.
240
241 HEAP MEMORY USED: x bytes
242
243 STACK MEMORY USED: x bytes
244
245 CLOCK CYCLES: (cycle count equation for this function) + (variable
246                used to represent cycle count for each subroutine
247                called)
248     where: (cycle count variable) = cycle count for [subroutine
249                                     name]
250
251------------------------------------------------------------------------------
252 CAUTION [optional]
253 [State any special notes, constraints or cautions for users of this function]
254
255------------------------------------------------------------------------------
256*/
257
258Word32 energy_old_Wrapper(Word16 in[], Word16 l_trm, Flag *pOverflow)
259{
260    Word32 energy_old_value;
261
262    /*----------------------------------------------------------------------------
263     CALL energy_old (  in = in
264                l_trm = l_trm
265                pOverflow = pOverflow )
266
267      MODIFYING(nothing)
268       RETURNING(energy_old_value = s)
269    ----------------------------------------------------------------------------*/
270    energy_old_value = energy_old(in, l_trm, pOverflow);
271    return(energy_old_value);
272}
273/*--------------------------------------------------------------------------*/
274
275/*
276-----------------------------------------------------------------------------
277 FUNCTION NAME: energy_new
278------------------------------------------------------------------------------
279 INPUT AND OUTPUT DEFINITIONS
280
281 Inputs:
282    in = input signal
283    l_trm = input signal length
284    pOverflow = address of overflow (Flag)
285
286 Outputs:
287    pOverflow -> 1 if the energy computation saturates
288
289 Returns:
290    s = return energy of signal
291
292 Global Variables Used:
293    None.
294
295 Local Variables Needed:
296    None.
297
298------------------------------------------------------------------------------
299 FUNCTION DESCRIPTION
300
301 Returns the energy of the signal.
302
303------------------------------------------------------------------------------
304 REQUIREMENTS
305
306 None.
307
308------------------------------------------------------------------------------
309 REFERENCES
310
311 agc.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
312
313------------------------------------------------------------------------------
314 PSEUDO-CODE
315
316static Word32 energy_new( // o : return energy of signal
317    Word16 in[],          // i : input signal (length l_trm)
318    Word16 l_trm )        // i : signal length
319
320{
321    Word32 s;
322    Word16 i;
323    Flag ov_save;
324
325    ov_save = Overflow;            //save overflow flag in case energy_old
326                                   // must be called
327    s = L_mult(in[0], in[0]);
328    for (i = 1; i < l_trm; i++)
329    {
330        s = L_mac(s, in[i], in[i]);
331    }
332
333    // check for overflow
334    if (L_sub (s, MAX_32) == 0L)
335    {
336        Overflow = ov_save; // restore overflow flag
337        s = energy_old (in, l_trm); // function result
338    }
339    else
340    {
341       s = L_shr(s, 4);
342    }
343
344    return(s);
345}
346
347------------------------------------------------------------------------------
348 RESOURCES USED [optional]
349
350 When the code is written for a specific target processor the
351 the resources used should be documented below.
352
353 HEAP MEMORY USED: x bytes
354
355 STACK MEMORY USED: x bytes
356
357 CLOCK CYCLES: (cycle count equation for this function) + (variable
358                used to represent cycle count for each subroutine
359                called)
360     where: (cycle count variable) = cycle count for [subroutine
361                                     name]
362
363------------------------------------------------------------------------------
364 CAUTION [optional]
365 [State any special notes, constraints or cautions for users of this function]
366
367------------------------------------------------------------------------------
368*/
369
370static Word32 energy_new(       /* o : return energy of signal      */
371    Word16 in[],        /* i : input signal (length l_trm)  */
372    Word16 l_trm,       /* i : signal length                */
373    Flag *pOverflow     /* i : overflow flag                */
374)
375
376{
377    Word32  s = 0;
378    Word16  i;
379    Flag    ov_save;
380
381    ov_save = *(pOverflow);  /* save overflow flag in case energy_old */
382    /* must be called                        */
383
384
385    for (i = 0; i < l_trm; i++)
386    {
387        s = L_mac(s, in[i], in[i], pOverflow);
388    }
389
390    /* check for overflow */
391    if (s != MAX_32)
392    {
393        /* s is a sum of squares, so it won't be negative */
394        s = s >> 4;
395    }
396    else
397    {
398        *(pOverflow) = ov_save;  /* restore overflow flag */
399        s = energy_old(in, l_trm, pOverflow);   /* function result */
400    }
401
402    return (s);
403}
404
405/*--------------------------------------------------------------------------*/
406/*
407------------------------------------------------------------------------------
408 FUNCTION NAME: energy_new__Wrapper
409------------------------------------------------------------------------------
410 INPUT AND OUTPUT DEFINITIONS
411
412 Inputs:
413    in = input signal (Word16)
414    l_trm = input signal length (Word16)
415    overflow = address of overflow (Flag)
416
417 Outputs:
418    pOverflow -> 1 if the energy computation saturates
419
420 Returns:
421    s = return energy of signal (Word32)
422
423 Global Variables Used:
424    None.
425
426 Local Variables Needed:
427    None.
428
429------------------------------------------------------------------------------
430 FUNCTION DESCRIPTION
431
432 This function provides external access to the static function energy_new.
433
434------------------------------------------------------------------------------
435 REQUIREMENTS
436
437 None
438
439------------------------------------------------------------------------------
440 REFERENCES
441
442 None
443
444------------------------------------------------------------------------------
445 PSEUDO-CODE
446
447 CALL energy_new (  in = in
448            l_trm = l_trm
449            pOverflow = pOverflow )
450
451   MODIFYING(nothing)
452
453   RETURNING(energy_new_value = s)
454
455------------------------------------------------------------------------------
456 RESOURCES USED [optional]
457
458 When the code is written for a specific target processor the
459 the resources used should be documented below.
460
461 HEAP MEMORY USED: x bytes
462
463 STACK MEMORY USED: x bytes
464
465 CLOCK CYCLES: (cycle count equation for this function) + (variable
466                used to represent cycle count for each subroutine
467                called)
468     where: (cycle count variable) = cycle count for [subroutine
469                                     name]
470
471------------------------------------------------------------------------------
472 CAUTION [optional]
473 [State any special notes, constraints or cautions for users of this function]
474
475------------------------------------------------------------------------------
476*/
477
478Word32 energy_new_Wrapper(Word16 in[], Word16 l_trm, Flag *pOverflow)
479{
480    Word32 energy_new_value;
481
482    /*----------------------------------------------------------------------------
483     CALL energy_new (  in = in
484                l_trm = l_trm
485                pOverflow = pOverflow )
486
487       MODIFYING(nothing)
488       RETURNING(energy_new_value = s)
489
490    ----------------------------------------------------------------------------*/
491    energy_new_value = energy_new(in, l_trm, pOverflow);
492
493    return(energy_new_value);
494
495}
496
497/*--------------------------------------------------------------------------*/
498
499
500
501/*
502------------------------------------------------------------------------------
503 FUNCTION NAME: agc_reset
504------------------------------------------------------------------------------
505 INPUT AND OUTPUT DEFINITIONS
506
507 Inputs:
508    state = pointer to a structure of type agcState
509
510 Outputs:
511    Structure pointed to by state is initialized to zeros
512
513 Returns:
514    Returns 0 if memory was successfully initialized,
515        otherwise returns -1.
516
517 Global Variables Used:
518    None.
519
520 Local Variables Needed:
521    None.
522
523------------------------------------------------------------------------------
524 FUNCTION DESCRIPTION
525
526 Reset of agc (i.e. set state memory to 1.0).
527
528------------------------------------------------------------------------------
529 REQUIREMENTS
530
531 None.
532
533------------------------------------------------------------------------------
534 REFERENCES
535
536 agc.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
537
538------------------------------------------------------------------------------
539 PSEUDO-CODE
540
541int agc_reset (agcState *state)
542{
543  if (state == (agcState *) NULL)
544  {
545      fprintf(stderr, "agc_reset: invalid parameter\n");
546      return -1;
547  }
548
549  state->past_gain = 4096;   // initial value of past_gain = 1.0
550
551  return 0;
552}
553
554------------------------------------------------------------------------------
555 RESOURCES USED [optional]
556
557 When the code is written for a specific target processor the
558 the resources used should be documented below.
559
560 HEAP MEMORY USED: x bytes
561
562 STACK MEMORY USED: x bytes
563
564 CLOCK CYCLES: (cycle count equation for this function) + (variable
565                used to represent cycle count for each subroutine
566                called)
567     where: (cycle count variable) = cycle count for [subroutine
568                                     name]
569
570------------------------------------------------------------------------------
571 CAUTION [optional]
572 [State any special notes, constraints or cautions for users of this function]
573
574------------------------------------------------------------------------------
575*/
576
577Word16 agc_reset(agcState *state)
578{
579    if (state == (agcState *) NULL)
580    {
581        /* fprintf(stderr, "agc_reset: invalid parameter\n"); */
582        return(-1);
583    }
584
585    state->past_gain = 4096;   /* initial value of past_gain = 1.0  */
586
587    return(0);
588}
589
590/*--------------------------------------------------------------------------*/
591
592/*
593------------------------------------------------------------------------------
594 FUNCTION NAME: agc
595------------------------------------------------------------------------------
596 INPUT AND OUTPUT DEFINITIONS
597
598 Inputs:
599    st = pointer to agc state
600    sig_in = pointer to a buffer containing the postfilter input signal
601    sig_out = pointer to a buffer containing the postfilter output signal
602    agc_fac = AGC factor
603    l_trm = subframe size
604    pOverflow = pointer to the overflow flag
605
606 Outputs:
607    st->past_gain = gain
608    buffer pointed to by sig_out contains the new postfilter output signal
609    pOverflow -> 1 if the agc computation saturates
610
611 Returns:
612    return = 0
613
614 Global Variables Used:
615    none.
616
617 Local Variables Needed:
618    none.
619
620------------------------------------------------------------------------------
621 FUNCTION DESCRIPTION
622
623 Scales the postfilter output on a subframe basis using:
624
625     sig_out[n] = sig_out[n] * gain[n]
626     gain[n] = agc_fac * gain[n-1] + (1 - agc_fac) g_in/g_out
627
628 where: gain[n] = gain at the nth sample given by
629        g_in/g_out = square root of the ratio of energy at
630                     the input and output of the postfilter.
631
632------------------------------------------------------------------------------
633 REQUIREMENTS
634
635 None.
636
637------------------------------------------------------------------------------
638 REFERENCES
639
640 agc.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
641
642------------------------------------------------------------------------------
643 PSEUDO-CODE
644
645int agc (
646    agcState *st,      // i/o : agc state
647    Word16 *sig_in,    // i   : postfilter input signal  (l_trm)
648    Word16 *sig_out,   // i/o : postfilter output signal (l_trm)
649    Word16 agc_fac,    // i   : AGC factor
650    Word16 l_trm       // i   : subframe size
651)
652{
653    Word16 i, exp;
654    Word16 gain_in, gain_out, g0, gain;
655    Word32 s;
656
657    // calculate gain_out with exponent
658    s = energy_new(sig_out, l_trm); // function result
659
660    if (s == 0)
661    {
662        st->past_gain = 0;
663        return 0;
664    }
665    exp = sub (norm_l (s), 1);
666    gain_out = pv_round (L_shl (s, exp));
667
668    // calculate gain_in with exponent
669    s = energy_new(sig_in, l_trm); // function result
670
671    if (s == 0)
672    {
673        g0 = 0;
674    }
675    else
676    {
677        i = norm_l (s);
678        gain_in = pv_round (L_shl (s, i));
679        exp = sub (exp, i);
680
681         *---------------------------------------------------*
682         *  g0 = (1-agc_fac) * sqrt(gain_in/gain_out);       *
683         *---------------------------------------------------*
684
685        s = L_deposit_l (div_s (gain_out, gain_in));
686        s = L_shl (s, 7);       // s = gain_out / gain_in
687        s = L_shr (s, exp);     // add exponent
688
689        s = Inv_sqrt (s); // function result
690        i = pv_round (L_shl (s, 9));
691
692        // g0 = i * (1-agc_fac)
693        g0 = mult (i, sub (32767, agc_fac));
694    }
695
696    // compute gain[n] = agc_fac * gain[n-1]
697                        + (1-agc_fac) * sqrt(gain_in/gain_out)
698    // sig_out[n] = gain[n] * sig_out[n]
699
700    gain = st->past_gain;
701
702    for (i = 0; i < l_trm; i++)
703    {
704        gain = mult (gain, agc_fac);
705        gain = add (gain, g0);
706        sig_out[i] = extract_h (L_shl (L_mult (sig_out[i], gain), 3));
707    }
708
709    st->past_gain = gain;
710
711    return 0;
712}
713
714------------------------------------------------------------------------------
715 RESOURCES USED [optional]
716
717 When the code is written for a specific target processor the
718 the resources used should be documented below.
719
720 HEAP MEMORY USED: x bytes
721
722 STACK MEMORY USED: x bytes
723
724 CLOCK CYCLES: (cycle count equation for this function) + (variable
725                used to represent cycle count for each subroutine
726                called)
727     where: (cycle count variable) = cycle count for [subroutine
728                                     name]
729
730------------------------------------------------------------------------------
731 CAUTION [optional]
732 [State any special notes, constraints or cautions for users of this function]
733
734------------------------------------------------------------------------------
735*/
736
737void agc(
738    agcState *st,      /* i/o : agc state                        */
739    Word16 *sig_in,    /* i   : postfilter input signal  (l_trm) */
740    Word16 *sig_out,   /* i/o : postfilter output signal (l_trm) */
741    Word16 agc_fac,    /* i   : AGC factor                       */
742    Word16 l_trm,      /* i   : subframe size                    */
743    Flag *pOverflow    /* i   : overflow Flag                    */
744
745)
746
747{
748    Word16  i;
749    Word16  exp;
750    Word16  gain_in;
751    Word16  gain_out;
752    Word16  g0;
753    Word16  gain;
754    Word32  s;
755    Word32  L_temp;
756    Word16  temp;
757
758    Word16 *p_sig_out;
759
760    /* calculate gain_out with exponent */
761    s = energy_new(sig_out, l_trm, pOverflow);  /* function result */
762
763    if (s == 0)
764    {
765        st->past_gain = 0;
766        return;
767    }
768    exp = norm_l(s) - 1;
769
770    L_temp = L_shl(s, exp, pOverflow);
771    gain_out = pv_round(L_temp, pOverflow);
772
773    /* calculate gain_in with exponent */
774    s = energy_new(sig_in, l_trm, pOverflow);    /* function result */
775
776    if (s == 0)
777    {
778        g0 = 0;
779    }
780    else
781    {
782        i = norm_l(s);
783
784        /* L_temp = L_shl(s, i, pOverflow); */
785        L_temp = s << i;
786
787        gain_in = pv_round(L_temp, pOverflow);
788
789        exp -= i;
790
791        /*---------------------------------------------------*
792         *  g0 = (1-agc_fac) * sqrt(gain_in/gain_out);       *
793         *---------------------------------------------------*/
794
795        /* s = gain_out / gain_in */
796        temp = div_s(gain_out, gain_in);
797
798        /* s = L_deposit_l (temp); */
799        s = (Word32) temp;
800        s = s << 7;
801        s = L_shr(s, exp, pOverflow);      /* add exponent */
802
803        s = Inv_sqrt(s, pOverflow);    /* function result */
804        L_temp = s << 9;
805
806        i = (Word16)((L_temp + (Word32) 0x00008000L) >> 16);
807
808        /* g0 = i * (1-agc_fac) */
809        temp = 32767 - agc_fac;
810
811        g0 = (Word16)(((Word32) i * temp) >> 15);
812
813    }
814
815    /* compute gain[n] = agc_fac * gain[n-1]
816                        + (1-agc_fac) * sqrt(gain_in/gain_out) */
817    /* sig_out[n] = gain[n] * sig_out[n]                        */
818
819    gain = st->past_gain;
820    p_sig_out = sig_out;
821
822    for (i = 0; i < l_trm; i++)
823    {
824        /* gain = mult (gain, agc_fac, pOverflow); */
825        gain = (Word16)(((Word32) gain * agc_fac) >> 15);
826
827        /* gain = add (gain, g0, pOverflow); */
828        gain += g0;
829
830        /* L_temp = L_mult (sig_out[i], gain, pOverflow); */
831        L_temp = ((Word32)(*(p_sig_out)) * gain) << 1;
832
833        *(p_sig_out++) = (Word16)(L_temp >> 13);
834    }
835
836    st->past_gain = gain;
837
838    return;
839}
840
841/*--------------------------------------------------------------------------*/
842
843/*
844------------------------------------------------------------------------------
845 FUNCTION NAME: agc2
846------------------------------------------------------------------------------
847 INPUT AND OUTPUT DEFINITIONS
848
849 Inputs:
850    sig_in = pointer to a buffer containing the postfilter input signal
851    sig_out = pointer to a buffer containing the postfilter output signal
852    l_trm = subframe size
853    pOverflow = pointer to overflow flag
854
855 Outputs:
856    sig_out points to a buffer containing the new scaled output signal.
857    pOverflow -> 1 if the agc computation saturates
858
859 Returns:
860    None.
861
862 Global Variables Used:
863    None.
864
865 Local Variables Needed:
866    None.
867
868------------------------------------------------------------------------------
869 FUNCTION DESCRIPTION
870
871 Scales the excitation on a subframe basis.
872
873------------------------------------------------------------------------------
874 REQUIREMENTS
875
876 None.
877
878------------------------------------------------------------------------------
879 REFERENCES
880
881 agc.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
882
883------------------------------------------------------------------------------
884 PSEUDO-CODE
885
886void agc2 (
887 Word16 *sig_in,        // i   : postfilter input signal
888 Word16 *sig_out,       // i/o : postfilter output signal
889 Word16 l_trm           // i   : subframe size
890)
891{
892    Word16 i, exp;
893    Word16 gain_in, gain_out, g0;
894    Word32 s;
895
896    // calculate gain_out with exponent
897    s = energy_new(sig_out, l_trm); // function result
898
899    if (s == 0)
900    {
901        return;
902    }
903    exp = sub (norm_l (s), 1);
904    gain_out = pv_round (L_shl (s, exp));
905
906    // calculate gain_in with exponent
907    s = energy_new(sig_in, l_trm); // function result
908
909    if (s == 0)
910    {
911        g0 = 0;
912    }
913    else
914    {
915        i = norm_l (s);
916        gain_in = pv_round (L_shl (s, i));
917        exp = sub (exp, i);
918
919         *---------------------------------------------------*
920         *  g0 = sqrt(gain_in/gain_out);                     *
921         *---------------------------------------------------*
922
923        s = L_deposit_l (div_s (gain_out, gain_in));
924        s = L_shl (s, 7);       // s = gain_out / gain_in
925        s = L_shr (s, exp);     // add exponent
926
927        s = Inv_sqrt (s); // function result
928        g0 = pv_round (L_shl (s, 9));
929    }
930
931    // sig_out(n) = gain(n) sig_out(n)
932
933    for (i = 0; i < l_trm; i++)
934    {
935        sig_out[i] = extract_h (L_shl (L_mult (sig_out[i], g0), 3));
936    }
937
938    return;
939}
940------------------------------------------------------------------------------
941 RESOURCES USED [optional]
942
943 When the code is written for a specific target processor the
944 the resources used should be documented below.
945
946 HEAP MEMORY USED: x bytes
947
948 STACK MEMORY USED: x bytes
949
950 CLOCK CYCLES: (cycle count equation for this function) + (variable
951                used to represent cycle count for each subroutine
952                called)
953     where: (cycle count variable) = cycle count for [subroutine
954                                     name]
955
956------------------------------------------------------------------------------
957 CAUTION [optional]
958 [State any special notes, constraints or cautions for users of this function]
959
960------------------------------------------------------------------------------
961*/
962
963void agc2(
964    Word16 *sig_in,        /* i   : postfilter input signal  */
965    Word16 *sig_out,       /* i/o : postfilter output signal */
966    Word16 l_trm,          /* i   : subframe size            */
967    Flag   *pOverflow      /* i   : overflow flag            */
968)
969
970{
971    Word16  i;
972    Word16  exp;
973    Word16  gain_in;
974    Word16  gain_out;
975    Word16  g0;
976    Word32  s;
977    Word32  L_temp;
978    Word16  temp;
979
980    /* calculate gain_out with exponent */
981    s = energy_new(sig_out, l_trm, pOverflow); /* function result */
982
983    if (s == 0)
984    {
985        return;
986    }
987    exp = norm_l(s) - 1;
988    L_temp = L_shl(s, exp, pOverflow);
989    gain_out = pv_round(L_temp, pOverflow);
990
991    /* calculate gain_in with exponent */
992    s = energy_new(sig_in, l_trm, pOverflow); /* function result */
993
994    if (s == 0)
995    {
996        g0 = 0;
997    }
998    else
999    {
1000        i = norm_l(s);
1001        L_temp = L_shl(s, i, pOverflow);
1002        gain_in = pv_round(L_temp, pOverflow);
1003        exp -= i;
1004
1005        /*---------------------------------------------------*
1006         *  g0 = sqrt(gain_in/gain_out);                     *
1007         *---------------------------------------------------*/
1008
1009        /* s = gain_out / gain_in */
1010        temp = div_s(gain_out, gain_in);
1011
1012        /* s = L_deposit_l (temp); */
1013        s = (Word32)temp;
1014
1015        if (s > (Word32) 0x00FFFFFFL)
1016        {
1017            s = MAX_32;
1018        }
1019        else if (s < (Word32) 0xFF000000L)
1020        {
1021            s = MIN_32;
1022        }
1023        else
1024        {
1025            s = s << 7;
1026        }
1027        s = L_shr(s, exp, pOverflow);      /* add exponent */
1028
1029        s = Inv_sqrt(s, pOverflow);    /* function result */
1030
1031        if (s > (Word32) 0x003FFFFFL)
1032        {
1033            L_temp = MAX_32;
1034        }
1035        else if (s < (Word32) 0xFFC00000L)
1036        {
1037            L_temp = MIN_32;
1038        }
1039        else
1040        {
1041            L_temp = s << 9;
1042        }
1043        g0 = pv_round(L_temp, pOverflow);
1044    }
1045
1046    /* sig_out(n) = gain(n) sig_out(n) */
1047
1048    for (i = l_trm - 1; i >= 0; i--)
1049    {
1050        L_temp = L_mult(sig_out[i], g0, pOverflow);
1051        if (L_temp > (Word32) 0x0FFFFFFFL)
1052        {
1053            sig_out[i] = MAX_16;
1054        }
1055        else if (L_temp < (Word32) 0xF0000000L)
1056        {
1057            sig_out[i] = MIN_16;
1058        }
1059        else
1060        {
1061            sig_out[i] = (Word16)(L_temp >> 13);
1062        }
1063    }
1064
1065    return;
1066}
1067