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 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 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 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 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 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 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 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