1 /* ------------------------------------------------------------------
2 * Copyright (C) 1998-2009 PacketVideo
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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
14 * See the License for the specific language governing permissions
15 * and limitations under the License.
16 * -------------------------------------------------------------------
18 /****************************************************************************************
19 Portions of this file are derived from the following 3GPP standard:
22 ANSI-C code for the Adaptive Multi-Rate (AMR) speech codec
23 Available from http://www.3gpp.org
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 ****************************************************************************************/
30 ------------------------------------------------------------------------------
43 ------------------------------------------------------------------------------
46 This set of modules scale the excitation level and output of the speech
49 ------------------------------------------------------------------------------
53 /*----------------------------------------------------------------------------
55 ----------------------------------------------------------------------------*/
62 /*----------------------------------------------------------------------------
64 ; Define module specific macros here
65 ----------------------------------------------------------------------------*/
68 /*----------------------------------------------------------------------------
70 ; Include all pre-processor statements here. Include conditional
71 ; compile variables also.
72 ----------------------------------------------------------------------------*/
74 /*----------------------------------------------------------------------------
75 ; LOCAL FUNCTION DEFINITIONS
76 ; Function Prototype declaration
77 ----------------------------------------------------------------------------*/
79 /*----------------------------------------------------------------------------
80 ; LOCAL VARIABLE DEFINITIONS
81 ; Variable declaration - defined here and used outside this module
82 ----------------------------------------------------------------------------*/
85 ------------------------------------------------------------------------------
86 FUNCTION NAME: energy_old
87 ------------------------------------------------------------------------------
88 INPUT AND OUTPUT DEFINITIONS
91 in = input signal (Word16)
92 l_trm = input signal length (Word16)
93 pOverflow = address of overflow (Flag)
96 pOverflow -> 1 if the energy computation saturates
99 s = return energy of signal (Word32)
101 Global Variables Used:
104 Local Variables Needed:
107 ------------------------------------------------------------------------------
110 Returns the energy of the signal.
112 ------------------------------------------------------------------------------
117 ------------------------------------------------------------------------------
120 agc.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
122 ------------------------------------------------------------------------------
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
133 temp = shr (in[0], 2);
134 s = L_mult (temp, temp);
136 for (i = 1; i < l_trm; i++)
138 temp = shr (in[i], 2);
139 s = L_mac (s, temp, temp);
145 ------------------------------------------------------------------------------
147 [State any special notes, constraints or cautions for users of this function]
149 ------------------------------------------------------------------------------
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 */
163 for (i = 0; i < l_trm; i++)
166 s = L_mac(s, temp, temp, pOverflow);
172 /*----------------------------------------------------------------------------*/
174 ------------------------------------------------------------------------------
175 FUNCTION NAME: energy_old__Wrapper
176 ------------------------------------------------------------------------------
177 INPUT AND OUTPUT DEFINITIONS
180 in = input signal (Word16)
181 l_trm = input signal length (Word16)
182 pOverflow = address of overflow (Flag)
184 pOverflow -> 1 if the energy computation saturates
187 s = return energy of signal (Word32)
189 Global Variables Used:
192 Local Variables Needed:
195 ------------------------------------------------------------------------------
198 This function provides external access to the static function energy_old.
200 ------------------------------------------------------------------------------
205 ------------------------------------------------------------------------------
210 ------------------------------------------------------------------------------
213 CALL energy_old ( in = in
215 pOverflow = pOverflow )
217 RETURNING(energy_old_value = s)
219 ------------------------------------------------------------------------------
221 [State any special notes, constraints or cautions for users of this function]
223 ------------------------------------------------------------------------------
226 Word32 energy_old_Wrapper(Word16 in[], Word16 l_trm, Flag *pOverflow)
228 Word32 energy_old_value;
230 /*----------------------------------------------------------------------------
231 CALL energy_old ( in = in
233 pOverflow = pOverflow )
236 RETURNING(energy_old_value = s)
237 ----------------------------------------------------------------------------*/
238 energy_old_value = energy_old(in, l_trm, pOverflow);
239 return(energy_old_value);
241 /*--------------------------------------------------------------------------*/
244 -----------------------------------------------------------------------------
245 FUNCTION NAME: energy_new
246 ------------------------------------------------------------------------------
247 INPUT AND OUTPUT DEFINITIONS
251 l_trm = input signal length
252 pOverflow = address of overflow (Flag)
255 pOverflow -> 1 if the energy computation saturates
258 s = return energy of signal
260 Global Variables Used:
263 Local Variables Needed:
266 ------------------------------------------------------------------------------
269 Returns the energy of the signal.
271 ------------------------------------------------------------------------------
276 ------------------------------------------------------------------------------
279 agc.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
281 ------------------------------------------------------------------------------
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
293 ov_save = Overflow; //save overflow flag in case energy_old
295 s = L_mult(in[0], in[0]);
296 for (i = 1; i < l_trm; i++)
298 s = L_mac(s, in[i], in[i]);
301 // check for overflow
302 if (L_sub (s, MAX_32) == 0L)
304 Overflow = ov_save; // restore overflow flag
305 s = energy_old (in, l_trm); // function result
315 ------------------------------------------------------------------------------
317 [State any special notes, constraints or cautions for users of this function]
319 ------------------------------------------------------------------------------
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 */
333 ov_save = *(pOverflow); /* save overflow flag in case energy_old */
337 for (i = 0; i < l_trm; i++)
339 s = L_mac(s, in[i], in[i], pOverflow);
342 /* check for overflow */
345 /* s is a sum of squares, so it won't be negative */
350 *(pOverflow) = ov_save; /* restore overflow flag */
351 s = energy_old(in, l_trm, pOverflow); /* function result */
357 /*--------------------------------------------------------------------------*/
359 ------------------------------------------------------------------------------
360 FUNCTION NAME: energy_new__Wrapper
361 ------------------------------------------------------------------------------
362 INPUT AND OUTPUT DEFINITIONS
365 in = input signal (Word16)
366 l_trm = input signal length (Word16)
367 overflow = address of overflow (Flag)
370 pOverflow -> 1 if the energy computation saturates
373 s = return energy of signal (Word32)
375 Global Variables Used:
378 Local Variables Needed:
381 ------------------------------------------------------------------------------
384 This function provides external access to the static function energy_new.
386 ------------------------------------------------------------------------------
391 ------------------------------------------------------------------------------
396 ------------------------------------------------------------------------------
399 CALL energy_new ( in = in
401 pOverflow = pOverflow )
405 RETURNING(energy_new_value = s)
407 ------------------------------------------------------------------------------
409 [State any special notes, constraints or cautions for users of this function]
411 ------------------------------------------------------------------------------
414 Word32 energy_new_Wrapper(Word16 in[], Word16 l_trm, Flag *pOverflow)
416 Word32 energy_new_value;
418 /*----------------------------------------------------------------------------
419 CALL energy_new ( in = in
421 pOverflow = pOverflow )
424 RETURNING(energy_new_value = s)
426 ----------------------------------------------------------------------------*/
427 energy_new_value = energy_new(in, l_trm, pOverflow);
429 return(energy_new_value);
433 /*--------------------------------------------------------------------------*/
438 ------------------------------------------------------------------------------
439 FUNCTION NAME: agc_reset
440 ------------------------------------------------------------------------------
441 INPUT AND OUTPUT DEFINITIONS
444 state = pointer to a structure of type agcState
447 Structure pointed to by state is initialized to zeros
450 Returns 0 if memory was successfully initialized,
451 otherwise returns -1.
453 Global Variables Used:
456 Local Variables Needed:
459 ------------------------------------------------------------------------------
462 Reset of agc (i.e. set state memory to 1.0).
464 ------------------------------------------------------------------------------
469 ------------------------------------------------------------------------------
472 agc.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
474 ------------------------------------------------------------------------------
477 int agc_reset (agcState *state)
479 if (state == (agcState *) NULL)
481 fprintf(stderr, "agc_reset: invalid parameter\n");
485 state->past_gain = 4096; // initial value of past_gain = 1.0
490 ------------------------------------------------------------------------------
492 [State any special notes, constraints or cautions for users of this function]
494 ------------------------------------------------------------------------------
497 Word16 agc_reset(agcState *state)
499 if (state == (agcState *) NULL)
501 /* fprintf(stderr, "agc_reset: invalid parameter\n"); */
505 state->past_gain = 4096; /* initial value of past_gain = 1.0 */
510 /*--------------------------------------------------------------------------*/
513 ------------------------------------------------------------------------------
515 ------------------------------------------------------------------------------
516 INPUT AND OUTPUT DEFINITIONS
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
523 l_trm = subframe size
524 pOverflow = pointer to the overflow flag
528 buffer pointed to by sig_out contains the new postfilter output signal
529 pOverflow -> 1 if the agc computation saturates
534 Global Variables Used:
537 Local Variables Needed:
540 ------------------------------------------------------------------------------
543 Scales the postfilter output on a subframe basis using:
545 sig_out[n] = sig_out[n] * gain[n]
546 gain[n] = agc_fac * gain[n-1] + (1 - agc_fac) g_in/g_out
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.
552 ------------------------------------------------------------------------------
557 ------------------------------------------------------------------------------
560 agc.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
562 ------------------------------------------------------------------------------
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
574 Word16 gain_in, gain_out, g0, gain;
577 // calculate gain_out with exponent
578 s = energy_new(sig_out, l_trm); // function result
585 exp = sub (norm_l (s), 1);
586 gain_out = pv_round (L_shl (s, exp));
588 // calculate gain_in with exponent
589 s = energy_new(sig_in, l_trm); // function result
598 gain_in = pv_round (L_shl (s, i));
601 *---------------------------------------------------*
602 * g0 = (1-agc_fac) * sqrt(gain_in/gain_out); *
603 *---------------------------------------------------*
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
609 s = Inv_sqrt (s); // function result
610 i = pv_round (L_shl (s, 9));
612 // g0 = i * (1-agc_fac)
613 g0 = mult (i, sub (32767, agc_fac));
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]
620 gain = st->past_gain;
622 for (i = 0; i < l_trm; i++)
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));
629 st->past_gain = gain;
634 ------------------------------------------------------------------------------
636 [State any special notes, constraints or cautions for users of this function]
638 ------------------------------------------------------------------------------
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 */
664 /* calculate gain_out with exponent */
665 s = energy_new(sig_out, l_trm, pOverflow); /* function result */
674 L_temp = L_shl(s, exp, pOverflow);
675 gain_out = pv_round(L_temp, pOverflow);
677 /* calculate gain_in with exponent */
678 s = energy_new(sig_in, l_trm, pOverflow); /* function result */
688 /* L_temp = L_shl(s, i, pOverflow); */
691 gain_in = pv_round(L_temp, pOverflow);
695 /*---------------------------------------------------*
696 * g0 = (1-agc_fac) * sqrt(gain_in/gain_out); *
697 *---------------------------------------------------*/
699 /* s = gain_out / gain_in */
700 temp = div_s(gain_out, gain_in);
702 /* s = L_deposit_l (temp); */
705 s = L_shr(s, exp, pOverflow); /* add exponent */
707 s = Inv_sqrt(s, pOverflow); /* function result */
710 i = (Word16)((L_temp + (Word32) 0x00008000L) >> 16);
712 /* g0 = i * (1-agc_fac) */
713 temp = 32767 - agc_fac;
715 g0 = (Word16)(((Word32) i * temp) >> 15);
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] */
723 gain = st->past_gain;
726 for (i = 0; i < l_trm; i++)
728 /* gain = mult (gain, agc_fac, pOverflow); */
729 gain = (Word16)(((Word32) gain * agc_fac) >> 15);
731 /* gain = add (gain, g0, pOverflow); */
734 /* L_temp = L_mult (sig_out[i], gain, pOverflow); */
735 L_temp = ((Word32)(*(p_sig_out)) * gain) << 1;
737 *(p_sig_out++) = (Word16)(L_temp >> 13);
740 st->past_gain = gain;
745 /*--------------------------------------------------------------------------*/
748 ------------------------------------------------------------------------------
750 ------------------------------------------------------------------------------
751 INPUT AND OUTPUT DEFINITIONS
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
760 sig_out points to a buffer containing the new scaled output signal.
761 pOverflow -> 1 if the agc computation saturates
766 Global Variables Used:
769 Local Variables Needed:
772 ------------------------------------------------------------------------------
775 Scales the excitation on a subframe basis.
777 ------------------------------------------------------------------------------
782 ------------------------------------------------------------------------------
785 agc.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
787 ------------------------------------------------------------------------------
791 Word16 *sig_in, // i : postfilter input signal
792 Word16 *sig_out, // i/o : postfilter output signal
793 Word16 l_trm // i : subframe size
797 Word16 gain_in, gain_out, g0;
800 // calculate gain_out with exponent
801 s = energy_new(sig_out, l_trm); // function result
807 exp = sub (norm_l (s), 1);
808 gain_out = pv_round (L_shl (s, exp));
810 // calculate gain_in with exponent
811 s = energy_new(sig_in, l_trm); // function result
820 gain_in = pv_round (L_shl (s, i));
823 *---------------------------------------------------*
824 * g0 = sqrt(gain_in/gain_out); *
825 *---------------------------------------------------*
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
831 s = Inv_sqrt (s); // function result
832 g0 = pv_round (L_shl (s, 9));
835 // sig_out(n) = gain(n) sig_out(n)
837 for (i = 0; i < l_trm; i++)
839 sig_out[i] = extract_h (L_shl (L_mult (sig_out[i], g0), 3));
844 ------------------------------------------------------------------------------
846 [State any special notes, constraints or cautions for users of this function]
848 ------------------------------------------------------------------------------
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 */
868 /* calculate gain_out with exponent */
869 s = energy_new(sig_out, l_trm, pOverflow); /* function result */
876 L_temp = L_shl(s, exp, pOverflow);
877 gain_out = pv_round(L_temp, pOverflow);
879 /* calculate gain_in with exponent */
880 s = energy_new(sig_in, l_trm, pOverflow); /* function result */
889 L_temp = L_shl(s, i, pOverflow);
890 gain_in = pv_round(L_temp, pOverflow);
893 /*---------------------------------------------------*
894 * g0 = sqrt(gain_in/gain_out); *
895 *---------------------------------------------------*/
897 /* s = gain_out / gain_in */
898 temp = div_s(gain_out, gain_in);
900 /* s = L_deposit_l (temp); */
903 if (s > (Word32) 0x00FFFFFFL)
907 else if (s < (Word32) - 16777216)
915 s = L_shr(s, exp, pOverflow); /* add exponent */
917 s = Inv_sqrt(s, pOverflow); /* function result */
919 if (s > (Word32) 0x003FFFFFL)
923 else if (s < (Word32) - 4194304)
931 g0 = pv_round(L_temp, pOverflow);
934 /* sig_out(n) = gain(n) sig_out(n) */
936 for (i = l_trm - 1; i >= 0; i--)
938 L_temp = L_mult(sig_out[i], g0, pOverflow);
939 if (L_temp > (Word32) 0x0FFFFFFFL)
943 else if (L_temp < (Word32) - 268435456)
949 sig_out[i] = (Word16)(L_temp >> 13);