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