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