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/c2_11pf.c 35 Functions: 36 code_2i40_11bits 37 search_2i40 38 build_code 39 40 Date: 01/28/2002 41 42 ------------------------------------------------------------------------------ 43 REVISION HISTORY 44 45 Description: Modified to pass overflow flag through to basic math function. 46 The flag is passed back to the calling function by pointer reference. 47 48 Description: Fixed tabs prior to optimization to make diff'ing easier. 49 Optimized search_2i40() to reduce clock cycle usage. 50 51 Description: Optimized build_code() to reduce clock cycle usage. 52 53 Description: Changed function name to pv_round to avoid conflict with 54 round function in C standard library. 55 56 Description: Added casting to eliminate warnings 57 58 Description: Replaced "int" and/or "char" with OSCL defined types. 59 60 Description: 61 62 ------------------------------------------------------------------------------ 63 MODULE DESCRIPTION 64 65 ************************************************************************* 66 * 67 * FUNCTION: code_2i40_11bits() 68 * 69 * PURPOSE: Searches a 11 bit algebraic codebook containing 2 pulses 70 * in a frame of 40 samples. 71 * 72 * DESCRIPTION: 73 * The code length is 40, containing 2 nonzero pulses: i0...i1. 74 * All pulses can have two possible amplitudes: +1 or -1. 75 * Pulse i0 can have 2x8=16 possible positions, pulse i1 can have 76 * 4x8=32 positions. 77 * 78 * i0 : 1, 6, 11, 16, 21, 26, 31, 36. 79 * 3, 8, 13, 18, 23, 28, 33, 38. 80 * i1 : 0, 5, 10, 15, 20, 25, 30, 35. 81 * 1, 6, 11, 16, 21, 26, 31, 36. 82 * 2, 7, 12, 17, 22, 27, 32, 37. 83 * 4, 9, 14, 19, 24, 29, 34, 39. 84 * 85 ************************************************************************* 86 ------------------------------------------------------------------------------ 87 */ 88 89 /*---------------------------------------------------------------------------- 90 ; INCLUDES 91 ----------------------------------------------------------------------------*/ 92 #include "c2_11pf.h" 93 #include "typedef.h" 94 #include "basic_op.h" 95 #include "inv_sqrt.h" 96 #include "cnst.h" 97 #include "cor_h.h" 98 #include "set_sign.h" 99 100 /*---------------------------------------------------------------------------- 101 ; MACROS 102 ; Define module specific macros here 103 ----------------------------------------------------------------------------*/ 104 105 /*---------------------------------------------------------------------------- 106 ; DEFINES 107 ; Include all pre-processor statements here. Include conditional 108 ; compile variables also. 109 ----------------------------------------------------------------------------*/ 110 #define NB_PULSE 2 111 112 #define _1_2 (Word16)(32768L/2) 113 #define _1_4 (Word16)(32768L/4) 114 #define _1_8 (Word16)(32768L/8) 115 #define _1_16 (Word16)(32768L/16) 116 117 /*---------------------------------------------------------------------------- 118 ; LOCAL FUNCTION DEFINITIONS 119 ; Function Prototype declaration 120 ----------------------------------------------------------------------------*/ 121 static void search_2i40( 122 Word16 dn[], /* i : correlation between target and h[] */ 123 Word16 rr[][L_CODE],/* i : matrix of autocorrelation */ 124 Word16 codvec[], /* o : algebraic codebook vector */ 125 Flag * pOverflow 126 ); 127 128 static Word16 build_code( 129 Word16 codvec[], /* i : algebraic codebook vector */ 130 Word16 dn_sign[], /* i : sign of dn[] */ 131 Word16 cod[], /* o : algebraic (fixed) codebook excitation */ 132 Word16 h[], /* i : impulse response of weighted synthesis filter */ 133 Word16 y[], /* o : filtered fixed codebook excitation */ 134 Word16 sign[], /* o : sign of 2 pulses */ 135 Flag * pOverflow 136 ); 137 138 /*---------------------------------------------------------------------------- 139 ; LOCAL VARIABLE DEFINITIONS 140 ; Variable declaration - defined here and used outside this module 141 ----------------------------------------------------------------------------*/ 142 143 const Word16 startPos1[2] = {1, 3}; 144 const Word16 startPos2[4] = {0, 1, 2, 4}; 145 146 /* 147 ------------------------------------------------------------------------------ 148 FUNCTION NAME: code_2i40_11bits 149 ------------------------------------------------------------------------------ 150 INPUT AND OUTPUT DEFINITIONS 151 152 Inputs: 153 x, target vector, array of type Word16 154 h, impulse response of weighted synthesis filter, array of type Word16 155 T0, Pitch lag, variable of type Word16 156 pitch_sharp, Last quantized pitch gain, variable of type Word16 157 158 Outputs: 159 code[], Innovative codebook, array of type Word16 160 y[], filtered fixed codebook excitation, array of type Word16 161 sign, Signs of 2 pulses, pointer of type Word16 * 162 pOverflow Flag set when overflow occurs, pointer of type Flag * 163 164 Returns: 165 index 166 167 Global Variables Used: 168 None 169 170 Local Variables Needed: 171 None 172 173 ------------------------------------------------------------------------------ 174 FUNCTION DESCRIPTION 175 176 Searches a 11 bit algebraic codebook containing 2 pulses 177 in a frame of 40 samples. 178 179 The code length is 40, containing 2 nonzero pulses: i0...i1. 180 All pulses can have two possible amplitudes: +1 or -1. 181 Pulse i0 can have 2x8=16 possible positions, pulse i1 can have 182 4x8=32 positions. 183 184 i0 : 1, 6, 11, 16, 21, 26, 31, 36. 185 3, 8, 13, 18, 23, 28, 33, 38. 186 i1 : 0, 5, 10, 15, 20, 25, 30, 35. 187 1, 6, 11, 16, 21, 26, 31, 36. 188 2, 7, 12, 17, 22, 27, 32, 37. 189 4, 9, 14, 19, 24, 29, 34, 39. 190 191 ------------------------------------------------------------------------------ 192 REQUIREMENTS 193 194 None 195 196 ------------------------------------------------------------------------------ 197 REFERENCES 198 199 c2_11pf.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001 200 201 ------------------------------------------------------------------------------ 202 PSEUDO-CODE 203 204 205 ------------------------------------------------------------------------------ 206 RESOURCES USED [optional] 207 208 When the code is written for a specific target processor the 209 the resources used should be documented below. 210 211 HEAP MEMORY USED: x bytes 212 213 STACK MEMORY USED: x bytes 214 215 CLOCK CYCLES: (cycle count equation for this function) + (variable 216 used to represent cycle count for each subroutine 217 called) 218 where: (cycle count variable) = cycle count for [subroutine 219 name] 220 221 ------------------------------------------------------------------------------ 222 CAUTION [optional] 223 [State any special notes, constraints or cautions for users of this function] 224 225 ------------------------------------------------------------------------------ 226 */ 227 Word16 code_2i40_11bits( 228 Word16 x[], /* i : target vector */ 229 Word16 h[], /* i : impulse response of weighted synthesis filter */ 230 /* h[-L_subfr..-1] must be set to zero. */ 231 Word16 T0, /* i : Pitch lag */ 232 Word16 pitch_sharp, /* i : Last quantized pitch gain */ 233 Word16 code[], /* o : Innovative codebook */ 234 Word16 y[], /* o : filtered fixed codebook excitation */ 235 Word16 * sign, /* o : Signs of 2 pulses */ 236 Flag * pOverflow /* o : Flag set when overflow occurs */ 237 ) 238 { 239 Word16 codvec[NB_PULSE]; 240 Word16 dn[L_CODE]; 241 Word16 dn2[L_CODE]; 242 Word16 dn_sign[L_CODE]; 243 244 Word16 rr[L_CODE][L_CODE]; 245 246 Word16 i; 247 Word16 index; 248 Word16 sharp; 249 Word16 tempWord; 250 251 sharp = pitch_sharp << 1; 252 253 if (T0 < L_CODE) 254 { 255 for (i = T0; i < L_CODE; i++) 256 { 257 tempWord = 258 mult( 259 h[i - T0], 260 sharp, 261 pOverflow); 262 263 h[i] = 264 add( 265 h[i], 266 tempWord, 267 pOverflow); 268 } 269 270 } 271 272 cor_h_x( 273 h, 274 x, 275 dn, 276 1, 277 pOverflow); 278 279 set_sign( 280 dn, 281 dn_sign, 282 dn2, 283 8); /* dn2[] not used in this codebook search */ 284 285 cor_h( 286 h, 287 dn_sign, 288 rr, 289 pOverflow); 290 291 search_2i40( 292 dn, 293 rr, 294 codvec, 295 pOverflow); 296 297 /* function result */ 298 299 index = 300 build_code( 301 codvec, 302 dn_sign, 303 code, 304 h, 305 y, 306 sign, 307 pOverflow); 308 309 /* 310 * Compute innovation vector gain. 311 * Include fixed-gain pitch contribution into code[]. 312 */ 313 314 if (T0 < L_CODE) 315 { 316 for (i = T0; i < L_CODE; i++) 317 { 318 tempWord = 319 mult( 320 code[i - T0], 321 sharp, 322 pOverflow); 323 324 code[i] = 325 add( 326 code[i], 327 tempWord, 328 pOverflow); 329 } 330 } 331 332 return index; 333 } 334 335 /****************************************************************************/ 336 337 338 /* 339 ------------------------------------------------------------------------------ 340 FUNCTION NAME: search_2i40 341 ------------------------------------------------------------------------------ 342 INPUT AND OUTPUT DEFINITIONS 343 344 Inputs: 345 dn, correlation between target and h[], array of type Word16 346 rr, matrix of autocorrelation, double-array of type Word16 347 348 Outputs: 349 codvec[], algebraic codebook vector, array of type Word16 350 pOverflow, Flag set when overflow occurs, pointer of type Flag * 351 352 Returns: 353 None 354 355 Global Variables Used: 356 None 357 358 Local Variables Needed: 359 None 360 361 ------------------------------------------------------------------------------ 362 FUNCTION DESCRIPTION 363 364 Search the best codevector; determine positions of the 2 pulses 365 in the 40-sample frame. 366 367 ------------------------------------------------------------------------------ 368 REQUIREMENTS 369 370 None 371 372 ------------------------------------------------------------------------------ 373 REFERENCES 374 375 c2_11pf.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001 376 377 ------------------------------------------------------------------------------ 378 PSEUDO-CODE 379 380 381 ------------------------------------------------------------------------------ 382 RESOURCES USED [optional] 383 384 When the code is written for a specific target processor the 385 the resources used should be documented below. 386 387 HEAP MEMORY USED: x bytes 388 389 STACK MEMORY USED: x bytes 390 391 CLOCK CYCLES: (cycle count equation for this function) + (variable 392 used to represent cycle count for each subroutine 393 called) 394 where: (cycle count variable) = cycle count for [subroutine 395 name] 396 397 ------------------------------------------------------------------------------ 398 CAUTION [optional] 399 [State any special notes, constraints or cautions for users of this function] 400 401 ------------------------------------------------------------------------------ 402 */ 403 404 static void search_2i40( 405 Word16 dn[], /* i : correlation between target and h[] */ 406 Word16 rr[][L_CODE], /* i : matrix of autocorrelation */ 407 Word16 codvec[], /* o : algebraic codebook vector */ 408 Flag * pOverflow /* o : Flag set when overflow occurs */ 409 ) 410 { 411 Word16 i0; 412 Word16 i1; 413 Word16 ix = 0; /* initialization only needed to keep gcc silent */ 414 Word16 track1; 415 Word16 track2; 416 Word16 ipos[NB_PULSE]; 417 418 Word16 psk; 419 Word16 ps0; 420 Word16 ps1; 421 Word16 sq; 422 Word16 sq1; 423 424 Word16 alpk; 425 Word16 alp; 426 Word16 alp_16; 427 428 Word32 s; 429 Word32 alp0; 430 Word32 alp1; 431 432 Word16 i; 433 Word16 *p_codvec = &codvec[0]; 434 435 psk = -1; 436 alpk = 1; 437 438 for (i = 0; i < NB_PULSE; i++) 439 { 440 *(p_codvec++) = i; 441 } 442 443 /*------------------------------------------------------------------* 444 * main loop: try 2x4 tracks. * 445 *------------------------------------------------------------------*/ 446 447 for (track1 = 0; track1 < 2; track1++) 448 { 449 for (track2 = 0; track2 < 4; track2++) 450 { 451 /* fix starting position */ 452 ipos[0] = startPos1[track1]; 453 ipos[1] = startPos2[track2]; 454 455 /*----------------------------------------------------------------* 456 * i0 loop: try 8 positions. * 457 *----------------------------------------------------------------*/ 458 for (i0 = ipos[0]; i0 < L_CODE; i0 += STEP) 459 { 460 ps0 = dn[i0]; 461 462 /* alp0 = L_mult(rr[i0][i0], _1_4, pOverflow); */ 463 alp0 = (Word32) rr[i0][i0] << 14; 464 465 /*-------------------------------------------------------------* 466 * i1 loop: 8 positions. * 467 *-------------------------------------------------------------*/ 468 469 sq = -1; 470 alp = 1; 471 ix = ipos[1]; 472 473 /*---------------------------------------------------------------* 474 * These index have low complexity address computation because * 475 * they are, in fact, pointers with fixed increment. For example,* 476 * "rr[i0][i2]" is a pointer initialized to "&rr[i0][ipos[2]]" * 477 * and incremented by "STEP". * 478 *---------------------------------------------------------------*/ 479 480 for (i1 = ipos[1]; i1 < L_CODE; i1 += STEP) 481 { 482 /* idx increment = STEP */ 483 ps1 = add(ps0, dn[i1], pOverflow); 484 485 /* alp1 = alp0 + rr[i0][i1] + 1/2*rr[i1][i1]; */ 486 487 /* idx incr = STEP */ 488 /* alp1 = L_mac(alp0, rr[i1][i1], _1_4, pOverflow); */ 489 alp1 = alp0 + ((Word32) rr[i1][i1] << 14); 490 491 /* idx incr = STEP */ 492 /* alp1 = L_mac(alp1, rr[i0][i1], _1_2, pOverflow); */ 493 alp1 += (Word32) rr[i0][i1] << 15; 494 495 /* sq1 = mult(ps1, ps1, pOverflow); */ 496 sq1 = (Word16)(((Word32) ps1 * ps1) >> 15); 497 498 /* alp_16 = pv_round(alp1, pOverflow); */ 499 alp_16 = (Word16)((alp1 + (Word32) 0x00008000L) >> 16); 500 501 /* s = L_mult(alp, sq1, pOverflow); */ 502 s = ((Word32) alp * sq1) << 1; 503 504 /* s =L_msu(s, sq, alp_16, pOverflow); */ 505 s -= (((Word32) sq * alp_16) << 1); 506 507 if (s > 0) 508 { 509 sq = sq1; 510 alp = alp_16; 511 ix = i1; 512 } 513 514 } /* for (i1 = ipos[1]; i1 < L_CODE; i1 += STEP) */ 515 516 /* memorize codevector if this one is better than the last one. */ 517 518 /* s = L_mult(alpk, sq, pOverflow); */ 519 s = ((Word32) alpk * sq) << 1; 520 521 /* s = L_msu(s, psk, alp, pOverflow); */ 522 s -= (((Word32) psk * alp) << 1); 523 524 if (s > 0) 525 { 526 psk = sq; 527 alpk = alp; 528 p_codvec = &codvec[0]; 529 530 *(p_codvec++) = i0; 531 *(p_codvec) = ix; 532 } 533 534 } /* for (i0 = ipos[0]; i0 < L_CODE; i0 += STEP) */ 535 536 } /* for (track2 = 0; track2 < 4; track2++) */ 537 538 } /* for (track1 = 0; track1 < 2; track1++) */ 539 540 return; 541 542 } /* search_2i40 */ 543 544 /****************************************************************************/ 545 546 547 /* 548 ------------------------------------------------------------------------------ 549 FUNCTION NAME: build_code 550 ------------------------------------------------------------------------------ 551 INPUT AND OUTPUT DEFINITIONS 552 553 Inputs: 554 codvec, position of pulses, array of type Word16 555 dn_sign, sign of pulses, array of type Word16 556 h, impulse response of weighted synthesis filter, Word16 array 557 558 Outputs: 559 560 cod, innovative code vector, array of type Word16 561 y[], filtered innovative code, array of type Word16 562 sign[], sign of 2 pulses, array of type Word16 563 pOverflow, Flag set when overflow occurs, pointer of type Flag * 564 565 Returns: 566 567 Global Variables Used: 568 None 569 570 Local Variables Needed: 571 None 572 573 ------------------------------------------------------------------------------ 574 FUNCTION DESCRIPTION 575 576 Builds the codeword, the filtered codeword and index of the 577 codevector, based on the signs and positions of 2 pulses. 578 579 ------------------------------------------------------------------------------ 580 REQUIREMENTS 581 582 None 583 584 ------------------------------------------------------------------------------ 585 REFERENCES 586 587 c2_11pf.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001 588 589 ------------------------------------------------------------------------------ 590 PSEUDO-CODE 591 592 ------------------------------------------------------------------------------ 593 RESOURCES USED [optional] 594 595 When the code is written for a specific target processor the 596 the resources used should be documented below. 597 598 HEAP MEMORY USED: x bytes 599 600 STACK MEMORY USED: x bytes 601 602 CLOCK CYCLES: (cycle count equation for this function) + (variable 603 used to represent cycle count for each subroutine 604 called) 605 where: (cycle count variable) = cycle count for [subroutine 606 name] 607 608 ------------------------------------------------------------------------------ 609 CAUTION [optional] 610 [State any special notes, constraints or cautions for users of this function] 611 612 ------------------------------------------------------------------------------ 613 */ 614 static Word16 build_code( 615 Word16 codvec[], /* i : position of pulses */ 616 Word16 dn_sign[], /* i : sign of pulses */ 617 Word16 cod[], /* o : innovative code vector */ 618 Word16 h[], /* i : impulse response of weighted synthesis filter */ 619 Word16 y[], /* o : filtered innovative code */ 620 Word16 sign[], /* o : sign of 2 pulses */ 621 Flag * pOverflow /* o : Flag set when overflow occurs */ 622 ) 623 { 624 Word16 i; 625 Word16 j; 626 Word16 k; 627 Word16 track; 628 Word16 index; 629 Word16 _sign[NB_PULSE]; 630 Word16 indx; 631 Word16 rsign; 632 Word16 tempWord; 633 634 Word16 *p0; 635 Word16 *p1; 636 637 Word32 s; 638 639 for (i = 0; i < L_CODE; i++) 640 { 641 cod[i] = 0; 642 } 643 644 indx = 0; 645 rsign = 0; 646 647 for (k = 0; k < NB_PULSE; k++) 648 { 649 i = codvec[k]; /* read pulse position */ 650 j = dn_sign[i]; /* read sign */ 651 652 /* index = pos/5 */ 653 /* index = mult(i, 6554, pOverflow); */ 654 index = (Word16)(((Word32) i * 6554) >> 15); 655 656 /* track = pos%5 */ 657 /* tempWord = 658 L_mult( 659 index, 660 5, 661 pOverflow); */ 662 tempWord = ((Word32) index * 5) << 1; 663 664 /* tempWord = 665 L_shr( 666 tempWord, 667 1, 668 pOverflow); */ 669 tempWord >>= 1; 670 671 672 /* track = 673 sub( 674 i, 675 tempWord, 676 pOverflow); */ 677 track = i - tempWord; 678 679 tempWord = track; 680 681 if (tempWord == 0) 682 { 683 track = 1; 684 685 /* index = 686 shl( 687 index, 688 6, 689 pOverflow); */ 690 index <<= 6; 691 } 692 else if (track == 1) 693 { 694 tempWord = k; 695 696 if (tempWord == 0) 697 { 698 track = 0; 699 /* index = 700 shl( 701 index, 702 1, 703 pOverflow); */ 704 index <<= 1; 705 } 706 else 707 { 708 track = 1; 709 710 /* tempWord = 711 shl( 712 index, 713 6, 714 pOverflow); */ 715 tempWord = index << 6; 716 717 /* index = 718 add( 719 tempWord, 720 16, 721 pOverflow); */ 722 index = tempWord + 16; 723 } 724 } 725 else if (track == 2) 726 { 727 track = 1; 728 729 /* tempWord = 730 shl( 731 index, 732 6, 733 pOverflow); */ 734 tempWord = index << 6; 735 736 /* index = 737 add( 738 tempWord, 739 32, 740 pOverflow); */ 741 index = tempWord + 32; 742 } 743 else if (track == 3) 744 { 745 track = 0; 746 747 /* tempWord = 748 shl( 749 index, 750 1, 751 pOverflow); */ 752 tempWord = index << 1; 753 754 /* index = 755 add( 756 tempWord, 757 1, 758 pOverflow); */ 759 index = tempWord + 1; 760 } 761 else if (track == 4) 762 { 763 track = 1; 764 765 /* tempWord = 766 shl( 767 index, 768 6, 769 pOverflow); */ 770 tempWord = index << 6; 771 772 /* index = 773 add( 774 tempWord, 775 48, 776 pOverflow); */ 777 index = tempWord + 48; 778 } 779 780 if (j > 0) 781 { 782 cod[i] = 8191; 783 _sign[k] = 32767; 784 785 tempWord = 786 shl( 787 1, 788 track, 789 pOverflow); 790 791 rsign = 792 add( 793 rsign, 794 tempWord, 795 pOverflow); 796 } 797 else 798 { 799 cod[i] = -8192; 800 _sign[k] = (Word16) - 32768L; 801 } 802 803 indx = 804 add( 805 indx, 806 index, 807 pOverflow); 808 } 809 *sign = rsign; 810 811 p0 = h - codvec[0]; 812 p1 = h - codvec[1]; 813 814 for (i = 0; i < L_CODE; i++) 815 { 816 s = 0; 817 818 s = 819 L_mac( 820 s, 821 *p0++, 822 _sign[0], 823 pOverflow); 824 825 s = 826 L_mac( 827 s, 828 *p1++, 829 _sign[1], 830 pOverflow); 831 832 y[i] = 833 pv_round( 834 s, 835 pOverflow); 836 } 837 838 return indx; 839 } 840 841 842