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/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 
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  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 
energy_old(Word16 in[],Word16 l_trm,Flag * pOverflow)168 static 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 
energy_old_Wrapper(Word16 in[],Word16 l_trm,Flag * pOverflow)258 Word32 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 
316 static 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 
energy_new(Word16 in[],Word16 l_trm,Flag * pOverflow)370 static 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 
energy_new_Wrapper(Word16 in[],Word16 l_trm,Flag * pOverflow)478 Word32 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 
541 int 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 
agc_reset(agcState * state)577 Word16 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 
645 int 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 
agc(agcState * st,Word16 * sig_in,Word16 * sig_out,Word16 agc_fac,Word16 l_trm,Flag * pOverflow)737 void 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 
886 void 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 
agc2(Word16 * sig_in,Word16 * sig_out,Word16 l_trm,Flag * pOverflow)963 void 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