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 Pathname: ./audio/gsm-amr/c/src/q_plsf_3.c 32 Funtions: Vq_subvec4 33 Test_Vq_subvec4 34 Vq_subvec3 35 Test_Vq_subvec3 36 Q_plsf_3 37 38 ------------------------------------------------------------------------------ 39 REVISION HISTORY 40 41 Description: Updated template used to PV coding template. First attempt at 42 optimizing C code. 43 44 Description: Updated modules per Phase 2/3 review comments. Updated 45 Vq_subvec3 pseudo-code to reflect the new restructured code. 46 47 Description: Added setting of Overflow flag in inlined code. 48 49 Description: Synchronized file with UMTS version 3.2.0. Updated coding 50 template. Removed unnecessary include files. 51 52 Description: Replaced basic_op.h with the header file of the math functions 53 used in the file. 54 55 Description: Made the following changes per comments from Phase 2/3 review: 56 1. Fixed typecasting issue with TI C compiler. 57 2. Optimized IF stament in Vq_subvec3() function. 58 3. Updated copyright year. 59 60 Description: Removed redundancy in the Vq_subvec4 function. 61 62 Description: Updated to accept new parameter, Flag *pOverflow. 63 64 Description: Per review comments, added pOverflow flag description 65 to the input/outputs section. 66 67 Description: Corrected missed Overflow global variables -- changed to 68 proper pOverflow. 69 70 Description: Optimized all functions to further reduce clock cycle usage. 71 Updated copyright year. 72 73 Description: Added left shift by 1 in line 1050 of Q_plsf_3(). 74 75 Description: Replaced OSCL mem type functions and eliminated include 76 files that now are chosen by OSCL definitions 77 78 Description: Replaced "int" and/or "char" with OSCL defined types. 79 80 Description: Added #ifdef __cplusplus around extern'ed table. 81 82 Who: Date: 83 Description: 84 85 ------------------------------------------------------------------------------ 86 MODULE DESCRIPTION 87 88 This file contains the functions that perform the quantization of LSF 89 parameters with first order MA prediction and split by 3 vector 90 quantization (split-VQ). 91 92 ------------------------------------------------------------------------------ 93 */ 94 95 /*---------------------------------------------------------------------------- 96 ; INCLUDES 97 ----------------------------------------------------------------------------*/ 98 #include "q_plsf.h" 99 #include "typedef.h" 100 #include "lsp_lsf.h" 101 #include "reorder.h" 102 #include "lsfwt.h" 103 #include "oscl_mem.h" 104 105 /*--------------------------------------------------------------------------*/ 106 #ifdef __cplusplus 107 extern "C" 108 { 109 #endif 110 111 /*---------------------------------------------------------------------------- 112 ; MACROS 113 ; Define module specific macros here 114 ----------------------------------------------------------------------------*/ 115 116 /*---------------------------------------------------------------------------- 117 ; DEFINES 118 ; Include all pre-processor statements here. Include conditional 119 ; compile variables also. 120 ----------------------------------------------------------------------------*/ 121 #define PAST_RQ_INIT_SIZE 8 122 123 /*---------------------------------------------------------------------------- 124 ; LOCAL FUNCTION DEFINITIONS 125 ; Function Prototype declaration 126 ----------------------------------------------------------------------------*/ 127 128 /*---------------------------------------------------------------------------- 129 ; LOCAL VARIABLE DEFINITIONS 130 ; Variable declaration - defined here and used outside this module 131 ----------------------------------------------------------------------------*/ 132 133 /*---------------------------------------------------------------------------- 134 ; EXTERNAL GLOBAL STORE/BUFFER/POINTER REFERENCES 135 ; Declare variables used in this module but defined elsewhere 136 ----------------------------------------------------------------------------*/ 137 /* Codebooks of LSF prediction residual */ 138 extern const Word16 mean_lsf_3[]; 139 140 extern const Word16 pred_fac_3[]; 141 142 extern const Word16 dico1_lsf_3[]; 143 extern const Word16 dico2_lsf_3[]; 144 extern const Word16 dico3_lsf_3[]; 145 146 extern const Word16 mr515_3_lsf[]; 147 extern const Word16 mr795_1_lsf[]; 148 149 extern const Word16 past_rq_init[]; 150 151 /*--------------------------------------------------------------------------*/ 152 #ifdef __cplusplus 153 } 154 #endif 155 156 /* 157 ------------------------------------------------------------------------------ 158 FUNCTION NAME: Vq_subvec4 159 ------------------------------------------------------------------------------ 160 INPUT AND OUTPUT DEFINITIONS 161 162 Inputs: 163 lsf_r1 = pointer to the first LSF residual vector (Q15) (Word16) 164 dico = pointer to the quantization codebook (Q15) (const Word16) 165 wf1 = pointer to the first LSF weighting factor (Q13) (Word16) 166 dico_size = size of quantization codebook (Q0) (Word16) 167 168 Outputs: 169 buffer pointed to by lsf_r1 contains the selected vector 170 pOverflow -- pointer to Flag -- Flag set when overflow occurs 171 172 Returns: 173 index = quantization index (Q0) (Word16) 174 175 Global Variables Used: 176 None 177 178 Local Variables Needed: 179 None 180 181 ------------------------------------------------------------------------------ 182 FUNCTION DESCRIPTION 183 184 This function performs the quantization of a 4-dimensional subvector. 185 186 ------------------------------------------------------------------------------ 187 REQUIREMENTS 188 189 None 190 191 ------------------------------------------------------------------------------ 192 REFERENCES 193 194 q_plsf_3.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001 195 196 ------------------------------------------------------------------------------ 197 PSEUDO-CODE 198 199 static Word16 200 Vq_subvec4( // o: quantization index, Q0 201 Word16 * lsf_r1, // i: 1st LSF residual vector, Q15 202 Word16 * dico, // i: quantization codebook, Q15 203 Word16 * wf1, // i: 1st LSF weighting factors, Q13 204 Word16 dico_size) // i: size of quantization codebook, Q0 205 { 206 Word16 i, index = 0; 207 Word16 *p_dico, temp; 208 Word32 dist_min, dist; 209 210 dist_min = MAX_32; 211 p_dico = dico; 212 213 for (i = 0; i < dico_size; i++) 214 { 215 temp = sub (lsf_r1[0], *p_dico++); 216 temp = mult (wf1[0], temp); 217 dist = L_mult (temp, temp); 218 219 temp = sub (lsf_r1[1], *p_dico++); 220 temp = mult (wf1[1], temp); 221 dist = L_mac (dist, temp, temp); 222 223 temp = sub (lsf_r1[2], *p_dico++); 224 temp = mult (wf1[2], temp); 225 dist = L_mac (dist, temp, temp); 226 227 temp = sub (lsf_r1[3], *p_dico++); 228 temp = mult (wf1[3], temp); 229 dist = L_mac (dist, temp, temp); 230 231 232 if (L_sub (dist, dist_min) < (Word32) 0) 233 { 234 dist_min = dist; 235 index = i; 236 } 237 } 238 239 // Reading the selected vector 240 241 p_dico = &dico[shl (index, 2)]; 242 lsf_r1[0] = *p_dico++; 243 lsf_r1[1] = *p_dico++; 244 lsf_r1[2] = *p_dico++; 245 lsf_r1[3] = *p_dico; 246 247 return index; 248 249 } 250 251 ------------------------------------------------------------------------------ 252 RESOURCES USED [optional] 253 254 When the code is written for a specific target processor the 255 the resources used should be documented below. 256 257 HEAP MEMORY USED: x bytes 258 259 STACK MEMORY USED: x bytes 260 261 CLOCK CYCLES: (cycle count equation for this function) + (variable 262 used to represent cycle count for each subroutine 263 called) 264 where: (cycle count variable) = cycle count for [subroutine 265 name] 266 267 ------------------------------------------------------------------------------ 268 CAUTION [optional] 269 [State any special notes, constraints or cautions for users of this function] 270 271 ------------------------------------------------------------------------------ 272 */ 273 274 static Word16 Vq_subvec4( /* o: quantization index, Q0 */ 275 Word16 * lsf_r1, /* i: 1st LSF residual vector, Q15 */ 276 const Word16 * dico, /* i: quantization codebook, Q15 */ 277 Word16 * wf1, /* i: 1st LSF weighting factors, Q13 */ 278 Word16 dico_size, /* i: size of quantization codebook, Q0 */ 279 Flag *pOverflow /* o : Flag set when overflow occurs */ 280 ) 281 { 282 register Word16 i; 283 Word16 temp; 284 const Word16 *p_dico; 285 Word16 index = 0; 286 Word32 dist_min; 287 Word32 dist; 288 289 Word16 lsf_r1_0; 290 Word16 lsf_r1_1; 291 Word16 lsf_r1_2; 292 Word16 lsf_r1_3; 293 294 Word16 wf1_0; 295 Word16 wf1_1; 296 Word16 wf1_2; 297 Word16 wf1_3; 298 299 OSCL_UNUSED_ARG(pOverflow); 300 301 dist_min = MAX_32; 302 p_dico = dico; 303 304 lsf_r1_0 = lsf_r1[0]; 305 lsf_r1_1 = lsf_r1[1]; 306 lsf_r1_2 = lsf_r1[2]; 307 lsf_r1_3 = lsf_r1[3]; 308 309 wf1_0 = wf1[0]; 310 wf1_1 = wf1[1]; 311 wf1_2 = wf1[2]; 312 wf1_3 = wf1[3]; 313 314 for (i = 0; i < dico_size; i++) 315 { 316 temp = lsf_r1_0 - (*p_dico++); 317 temp = (Word16)((((Word32) wf1_0) * temp) >> 15); 318 dist = ((Word32) temp) * temp; 319 320 temp = lsf_r1_1 - (*p_dico++); 321 temp = (Word16)((((Word32) wf1_1) * temp) >> 15); 322 dist += ((Word32) temp) * temp; 323 324 temp = lsf_r1_2 - (*p_dico++); 325 temp = (Word16)((((Word32) wf1_2) * temp) >> 15); 326 dist += ((Word32) temp) * temp; 327 328 temp = lsf_r1_3 - (*p_dico++); 329 temp = (Word16)((((Word32) wf1_3) * temp) >> 15); 330 dist += ((Word32) temp) * temp; 331 332 if (dist < dist_min) 333 { 334 dist_min = dist; 335 index = i; 336 } 337 } 338 339 /* Reading the selected vector */ 340 341 p_dico = dico + (index << 2); 342 *lsf_r1++ = *p_dico++; 343 *lsf_r1++ = *p_dico++; 344 *lsf_r1++ = *p_dico++; 345 *lsf_r1 = *p_dico; 346 347 return(index); 348 349 } 350 351 /****************************************************************************/ 352 353 354 /* 355 ------------------------------------------------------------------------------ 356 FUNCTION NAME: Test_Vq_subvec4 357 ------------------------------------------------------------------------------ 358 INPUT AND OUTPUT DEFINITIONS 359 360 Inputs: 361 lsf_r1 = pointer to the first LSF residual vector (Q15) (Word16) 362 dico = pointer to the quantization codebook (Q15) (const Word16) 363 wf1 = pointer to the first LSF weighting factor (Q13) (Word16) 364 dico_size = size of quantization codebook (Q0) (Word16) 365 366 Outputs: 367 buffer pointed to by lsf_r1 contains the selected vector 368 pOverflow -- pointer to Flag -- Flag set when overflow occurs 369 370 Returns: 371 index = quantization index (Q0) (Word16) 372 373 Global Variables Used: 374 None 375 376 Local Variables Needed: 377 None 378 379 ------------------------------------------------------------------------------ 380 FUNCTION DESCRIPTION 381 382 This function calls the static function Vq_subvec4. It is used for testing 383 purposes only 384 385 ------------------------------------------------------------------------------ 386 REQUIREMENTS 387 388 None 389 390 ------------------------------------------------------------------------------ 391 REFERENCES 392 393 None 394 395 ------------------------------------------------------------------------------ 396 PSEUDO-CODE 397 398 399 CALL Vq_subvec4(lsf_r1 = lsf_r1 400 dico = dico 401 wf1 = wf1 402 dico_size = dico_size) 403 MODIFYING(nothing) 404 RETURNING(index = tst_index4) 405 406 ------------------------------------------------------------------------------ 407 RESOURCES USED [optional] 408 409 When the code is written for a specific target processor the 410 the resources used should be documented below. 411 412 HEAP MEMORY USED: x bytes 413 414 STACK MEMORY USED: x bytes 415 416 CLOCK CYCLES: (cycle count equation for this function) + (variable 417 used to represent cycle count for each subroutine 418 called) 419 where: (cycle count variable) = cycle count for [subroutine 420 name] 421 422 ------------------------------------------------------------------------------ 423 CAUTION [optional] 424 [State any special notes, constraints or cautions for users of this function] 425 426 ------------------------------------------------------------------------------ 427 */ 428 429 Word16 Test_Vq_subvec4( 430 Word16 * lsf_r1, 431 const Word16 * dico, 432 Word16 * wf1, 433 Word16 dico_size, 434 Flag *pOverflow) 435 { 436 Word16 tst_index4 = 0; 437 438 /*------------------------------------------------------------------------ 439 CALL Vq_subvec4(lsf_r1 = lsf_r1 440 dico = dico 441 wf1 = wf1 442 dico_size = dico_size) 443 MODIFYING(nothing) 444 RETURNING(index = index) 445 ------------------------------------------------------------------------*/ 446 tst_index4 = 447 Vq_subvec4( 448 lsf_r1, 449 dico, 450 wf1, 451 dico_size, 452 pOverflow); 453 454 return(tst_index4); 455 456 } 457 458 /****************************************************************************/ 459 460 /* 461 ------------------------------------------------------------------------------ 462 FUNCTION NAME: Vq_subvec3 463 ------------------------------------------------------------------------------ 464 INPUT AND OUTPUT DEFINITIONS 465 466 Inputs: 467 lsf_r1 = pointer to the first LSF residual vector (Q15) (Word16) 468 dico = pointer to the quantization codebook (Q15) (const Word16) 469 wf1 = pointer to the first LSF weighting factor (Q13) (Word16) 470 dico_size = size of quantization codebook (Q0) (Word16) 471 use_half = flag to indicate use of every second entry in the 472 codebook (Flag) 473 474 Outputs: 475 buffer pointed to by lsf_r1 contains the selected vector 476 pOverflow -- pointer to Flag -- Flag set when overflow occurs 477 478 Returns: 479 index = quantization index (Q0) (Word16) 480 481 Global Variables Used: 482 None 483 484 Local Variables Needed: 485 None 486 487 ------------------------------------------------------------------------------ 488 FUNCTION DESCRIPTION 489 490 This function performs the quantization of a 3 dimensional subvector. 491 492 ------------------------------------------------------------------------------ 493 REQUIREMENTS 494 495 None 496 497 ------------------------------------------------------------------------------ 498 REFERENCES 499 500 q_plsf_3.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001 501 502 ------------------------------------------------------------------------------ 503 PSEUDO-CODE 504 505 static Word16 506 Vq_subvec3( // o: quantization index, Q0 507 Word16 * lsf_r1, // i: 1st LSF residual vector, Q15 508 Word16 * dico, // i: quantization codebook, Q15 509 Word16 * wf1, // i: 1st LSF weighting factors, Q13 510 Word16 dico_size, // i: size of quantization codebook, Q0 511 Flag use_half) // i: use every second entry in codebook 512 { 513 Word16 i, index = 0; 514 Word16 *p_dico, temp; 515 Word32 dist_min, dist; 516 517 dist_min = MAX_32; 518 p_dico = dico; 519 520 if (use_half == 0) { 521 for (i = 0; i < dico_size; i++) 522 { 523 temp = sub(lsf_r1[0], *p_dico++); 524 temp = mult(wf1[0], temp); 525 dist = L_mult(temp, temp); 526 527 temp = sub(lsf_r1[1], *p_dico++); 528 temp = mult(wf1[1], temp); 529 dist = L_mac(dist, temp, temp); 530 531 temp = sub(lsf_r1[2], *p_dico++); 532 temp = mult(wf1[2], temp); 533 dist = L_mac(dist, temp, temp); 534 535 if (L_sub(dist, dist_min) < (Word32) 0) { 536 dist_min = dist; 537 index = i; 538 } 539 } 540 p_dico = &dico[add(index, add(index, index))]; 541 } 542 else 543 { 544 for (i = 0; i < dico_size; i++) 545 { 546 temp = sub(lsf_r1[0], *p_dico++); 547 temp = mult(wf1[0], temp); 548 dist = L_mult(temp, temp); 549 550 temp = sub(lsf_r1[1], *p_dico++); 551 temp = mult(wf1[1], temp); 552 dist = L_mac(dist, temp, temp); 553 554 temp = sub(lsf_r1[2], *p_dico++); 555 temp = mult(wf1[2], temp); 556 dist = L_mac(dist, temp, temp); 557 558 if (L_sub(dist, dist_min) < (Word32) 0) 559 { 560 dist_min = dist; 561 index = i; 562 } 563 p_dico = p_dico + 3; add(0,0); 564 } 565 p_dico = &dico[shl(add(index, add(index, index)),1)]; 566 } 567 568 569 // Reading the selected vector 570 lsf_r1[0] = *p_dico++; 571 lsf_r1[1] = *p_dico++; 572 lsf_r1[2] = *p_dico++; 573 574 return index; 575 } 576 577 ------------------------------------------------------------------------------ 578 RESOURCES USED [optional] 579 580 When the code is written for a specific target processor the 581 the resources used should be documented below. 582 583 HEAP MEMORY USED: x bytes 584 585 STACK MEMORY USED: x bytes 586 587 CLOCK CYCLES: (cycle count equation for this function) + (variable 588 used to represent cycle count for each subroutine 589 called) 590 where: (cycle count variable) = cycle count for [subroutine 591 name] 592 593 ------------------------------------------------------------------------------ 594 CAUTION [optional] 595 [State any special notes, constraints or cautions for users of this function] 596 597 ------------------------------------------------------------------------------ 598 */ 599 600 static Word16 Vq_subvec3( /* o: quantization index, Q0 */ 601 Word16 * lsf_r1, /* i: 1st LSF residual vector, Q15 */ 602 const Word16 * dico, /* i: quantization codebook, Q15 */ 603 Word16 * wf1, /* i: 1st LSF weighting factors, Q13 */ 604 Word16 dico_size, /* i: size of quantization codebook, Q0 */ 605 Flag use_half, /* i: use every second entry in codebook */ 606 Flag *pOverflow) /* o : Flag set when overflow occurs */ 607 { 608 register Word16 i; 609 Word16 temp; 610 611 const Word16 *p_dico; 612 613 Word16 p_dico_index = 0; 614 Word16 index = 0; 615 616 Word32 dist_min; 617 Word32 dist; 618 619 Word16 lsf_r1_0; 620 Word16 lsf_r1_1; 621 Word16 lsf_r1_2; 622 623 Word16 wf1_0; 624 Word16 wf1_1; 625 Word16 wf1_2; 626 627 OSCL_UNUSED_ARG(pOverflow); 628 629 dist_min = MAX_32; 630 p_dico = dico; 631 632 lsf_r1_0 = lsf_r1[0]; 633 lsf_r1_1 = lsf_r1[1]; 634 lsf_r1_2 = lsf_r1[2]; 635 636 wf1_0 = wf1[0]; 637 wf1_1 = wf1[1]; 638 wf1_2 = wf1[2]; 639 640 if (use_half != 0) 641 { 642 p_dico_index = 3; 643 } 644 645 for (i = 0; i < dico_size; i++) 646 { 647 temp = lsf_r1_0 - (*p_dico++); 648 temp = (Word16)((((Word32) wf1_0) * temp) >> 15); 649 dist = ((Word32) temp) * temp; 650 651 temp = lsf_r1_1 - (*p_dico++); 652 temp = (Word16)((((Word32) wf1_1) * temp) >> 15); 653 dist += ((Word32) temp) * temp; 654 655 temp = lsf_r1_2 - (*p_dico++); 656 temp = (Word16)((((Word32) wf1_2) * temp) >> 15); 657 dist += ((Word32) temp) * temp; 658 659 if (dist < dist_min) 660 { 661 dist_min = dist; 662 index = i; 663 } 664 665 p_dico = p_dico + p_dico_index; 666 } 667 668 p_dico = dico + (3 * index); 669 670 if (use_half != 0) 671 { 672 p_dico += (3 * index); 673 } 674 675 /* Reading the selected vector */ 676 *lsf_r1++ = *p_dico++; 677 *lsf_r1++ = *p_dico++; 678 *lsf_r1 = *p_dico; 679 680 return(index); 681 } 682 683 /****************************************************************************/ 684 685 686 /* 687 ------------------------------------------------------------------------------ 688 FUNCTION NAME: Test_Vq_subvec3 689 ------------------------------------------------------------------------------ 690 INPUT AND OUTPUT DEFINITIONS 691 692 Inputs: 693 lsf_r1 = pointer to the first LSF residual vector (Q15) (Word16) 694 dico = pointer to the quantization codebook (Q15) (const Word16) 695 wf1 = pointer to the first LSF weighting factor (Q13) (Word16) 696 dico_size = size of quantization codebook (Q0) (Word16) 697 use_half = flag to indicate use of every second entry in the 698 codebook (Flag) 699 700 Outputs: 701 buffer pointed to by lsf_r1 contains the selected vector 702 pOverflow -- pointer to Flag -- Flag set when overflow occurs 703 704 Returns: 705 index = quantization index (Q0) (Word16) 706 707 Global Variables Used: 708 None 709 710 Local Variables Needed: 711 None 712 713 ------------------------------------------------------------------------------ 714 FUNCTION DESCRIPTION 715 716 This function calls the static function Vq_subvec3. It is used for testing 717 purposes only 718 719 ------------------------------------------------------------------------------ 720 REQUIREMENTS 721 722 None 723 724 ------------------------------------------------------------------------------ 725 REFERENCES 726 727 None 728 729 ------------------------------------------------------------------------------ 730 PSEUDO-CODE 731 732 CALL Vq_subvec3(lsf_r1 = lsf_r1 733 dico = dico 734 wf1 = wf1 735 dico_size = dico_size 736 use_half = use_half) 737 MODIFYING(nothing) 738 RETURNING(index = tst_index3) 739 740 ------------------------------------------------------------------------------ 741 RESOURCES USED [optional] 742 743 When the code is written for a specific target processor the 744 the resources used should be documented below. 745 746 HEAP MEMORY USED: x bytes 747 748 STACK MEMORY USED: x bytes 749 750 CLOCK CYCLES: (cycle count equation for this function) + (variable 751 used to represent cycle count for each subroutine 752 called) 753 where: (cycle count variable) = cycle count for [subroutine 754 name] 755 756 ------------------------------------------------------------------------------ 757 CAUTION [optional] 758 [State any special notes, constraints or cautions for users of this function] 759 760 ------------------------------------------------------------------------------ 761 */ 762 763 Word16 Test_Vq_subvec3( 764 Word16 * lsf_r1, 765 const Word16 * dico, 766 Word16 * wf1, 767 Word16 dico_size, 768 Flag use_half, 769 Flag *pOverflow) 770 { 771 Word16 tst_index3 = 0; 772 773 /*------------------------------------------------------------------------ 774 CALL Vq_subvec3(lsf_r1 = lsf_r1 775 dico = dico 776 wf1 = wf1 777 dico_size = dico_size 778 use_half = use_half) 779 MODIFYING(nothing) 780 RETURNING(index = index) 781 ------------------------------------------------------------------------*/ 782 tst_index3 = 783 Vq_subvec3( 784 lsf_r1, 785 dico, 786 wf1, 787 dico_size, 788 use_half, 789 pOverflow); 790 791 return(tst_index3); 792 793 } 794 795 /****************************************************************************/ 796 797 798 /* 799 ------------------------------------------------------------------------------ 800 FUNCTION NAME: Q_plsf_3 801 ------------------------------------------------------------------------------ 802 INPUT AND OUTPUT DEFINITIONS 803 804 Inputs: 805 st = pointer to structures of type Q_plsfState (Q_plsfState) 806 mode = coder mode (enum) 807 lsp1 = pointer to the first LSP vector (Word16) 808 lsp1_q = pointer to the quantized first LSP vector (Word16) 809 indice = pointer to the quantization indices of 3 vectors (Word16) 810 pred_init_i = pointer to the index of the initial value for 811 MA prediction in DTX mode (Word16) 812 813 Outputs: 814 lsp1_q points to a vector containing the new quantized LSPs 815 indice points to the new quantization indices of 3 vectors 816 pred_init_i points to the new initial index for MA prediction 817 in DTX mode 818 past_rq field of structure pointed to by st contains the current 819 quantized LSF parameters 820 pOverflow -- pointer to Flag -- Flag set when overflow occurs 821 822 Returns: 823 None 824 825 Global Variables Used: 826 pred_fac = table containing prediction factors (const Word16) 827 dico1_lsf = quantization table for split_MQ of 2 sets of LSFs 828 in a 20 ms frame (const Word16) 829 dico2_lsf = quantization table for split_MQ of 2 sets of LSFs 830 in a 20 ms frame (const Word16) 831 dico3_lsf = quantization table for split_MQ of 2 sets of LSFs 832 in a 20 ms frame (const Word16) 833 mr515_3_lsf = third codebook for MR475 and MR515 modes (const Word16) 834 mr795_1_lsf = first codebook for MR795 mode (const Word16) 835 mean_lsf = table of mean LSFs (const Word16) 836 past_rq_init = initalization table for MA predictor in DTX mode 837 (const Word16) 838 839 840 Local Variables Needed: 841 None 842 843 ------------------------------------------------------------------------------ 844 FUNCTION DESCRIPTION 845 846 This function performs quantization of LSF parameters with 1st order MA 847 prediction and split by 3 vector quantization (split-VQ) 848 849 ------------------------------------------------------------------------------ 850 REQUIREMENTS 851 852 None 853 854 ------------------------------------------------------------------------------ 855 REFERENCES 856 857 q_plsf_3.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001 858 859 ------------------------------------------------------------------------------ 860 PSEUDO-CODE 861 862 void Q_plsf_3( 863 Q_plsfState *st, // i/o: state struct 864 enum Mode mode, // i : coder mode 865 Word16 *lsp1, // i : 1st LSP vector Q15 866 Word16 *lsp1_q, // o : quantized 1st LSP vector Q15 867 Word16 *indice, // o : quantization indices of 3 vectors Q0 868 Word16 *pred_init_i // o : init index for MA prediction in DTX mode 869 ) 870 { 871 Word16 i, j; 872 Word16 lsf1[M], wf1[M], lsf_p[M], lsf_r1[M]; 873 Word16 lsf1_q[M]; 874 875 Word32 L_pred_init_err; 876 Word32 L_min_pred_init_err; 877 Word16 temp_r1[M]; 878 Word16 temp_p[M]; 879 880 // convert LSFs to normalize frequency domain 0..16384 881 882 Lsp_lsf(lsp1, lsf1, M); 883 884 // compute LSF weighting factors (Q13) 885 886 Lsf_wt(lsf1, wf1); 887 888 // Compute predicted LSF and prediction error 889 if (test(), sub(mode, MRDTX) != 0) 890 { 891 for (i = 0; i < M; i++) 892 { 893 lsf_p[i] = add(mean_lsf[i], 894 mult(st->past_rq[i], 895 pred_fac[i])); 896 lsf_r1[i] = sub(lsf1[i], lsf_p[i]); 897 } 898 } 899 else 900 { 901 // DTX mode, search the init vector that yields 902 // lowest prediction resuidual energy 903 *pred_init_i = 0; 904 L_min_pred_init_err = 0x7fffffff; // 2^31 - 1 905 for (j = 0; j < PAST_RQ_INIT_SIZE; j++) 906 { 907 L_pred_init_err = 0; 908 for (i = 0; i < M; i++) 909 { 910 temp_p[i] = add(mean_lsf[i], past_rq_init[j*M+i]); 911 temp_r1[i] = sub(lsf1[i],temp_p[i]); 912 L_pred_init_err = L_mac(L_pred_init_err, temp_r1[i], temp_r1[i]); 913 } // next i 914 915 916 if (L_sub(L_pred_init_err, L_min_pred_init_err) < (Word32) 0) 917 { 918 L_min_pred_init_err = L_pred_init_err; 919 Copy(temp_r1, lsf_r1, M); 920 Copy(temp_p, lsf_p, M); 921 // Set zerom 922 Copy(&past_rq_init[j*M], st->past_rq, M); 923 *pred_init_i = j; 924 } // endif 925 } // next j 926 } // endif MRDTX 927 928 //---- Split-VQ of prediction error ---- 929 if (sub (mode, MR475) == 0 || sub (mode, MR515) == 0) 930 { // MR475, MR515 931 932 933 indice[0] = Vq_subvec3(&lsf_r1[0], dico1_lsf, &wf1[0], DICO1_SIZE, 0); 934 935 indice[1] = Vq_subvec3(&lsf_r1[3], dico2_lsf, &wf1[3], DICO2_SIZE/2, 1); 936 937 indice[2] = Vq_subvec4(&lsf_r1[6], mr515_3_lsf, &wf1[6], MR515_3_SIZE); 938 939 } 940 else if (sub (mode, MR795) == 0) 941 { // MR795 942 943 944 indice[0] = Vq_subvec3(&lsf_r1[0], mr795_1_lsf, &wf1[0], MR795_1_SIZE, 0); 945 946 indice[1] = Vq_subvec3(&lsf_r1[3], dico2_lsf, &wf1[3], DICO2_SIZE, 0); 947 948 indice[2] = Vq_subvec4(&lsf_r1[6], dico3_lsf, &wf1[6], DICO3_SIZE); 949 950 } 951 else 952 { // MR59, MR67, MR74, MR102 , MRDTX 953 954 955 indice[0] = Vq_subvec3(&lsf_r1[0], dico1_lsf, &wf1[0], DICO1_SIZE, 0); 956 957 indice[1] = Vq_subvec3(&lsf_r1[3], dico2_lsf, &wf1[3], DICO2_SIZE, 0); 958 959 indice[2] = Vq_subvec4(&lsf_r1[6], dico3_lsf, &wf1[6], DICO3_SIZE); 960 961 } 962 963 964 // Compute quantized LSFs and update the past quantized residual 965 966 for (i = 0; i < M; i++) 967 { 968 lsf1_q[i] = add(lsf_r1[i], lsf_p[i]); 969 st->past_rq[i] = lsf_r1[i]; 970 } 971 972 // verification that LSFs has mimimum distance of LSF_GAP Hz 973 974 Reorder_lsf(lsf1_q, LSF_GAP, M); 975 976 // convert LSFs to the cosine domain 977 978 Lsf_lsp(lsf1_q, lsp1_q, M); 979 } 980 981 ------------------------------------------------------------------------------ 982 RESOURCES USED [optional] 983 984 When the code is written for a specific target processor the 985 the resources used should be documented below. 986 987 HEAP MEMORY USED: x bytes 988 989 STACK MEMORY USED: x bytes 990 991 CLOCK CYCLES: (cycle count equation for this function) + (variable 992 used to represent cycle count for each subroutine 993 called) 994 where: (cycle count variable) = cycle count for [subroutine 995 name] 996 997 ------------------------------------------------------------------------------ 998 CAUTION [optional] 999 [State any special notes, constraints or cautions for users of this function] 1000 1001 ------------------------------------------------------------------------------ 1002 */ 1003 1004 void Q_plsf_3( 1005 Q_plsfState *st, /* i/o: state struct */ 1006 enum Mode mode, /* i : coder mode */ 1007 Word16 *lsp1, /* i : 1st LSP vector Q15 */ 1008 Word16 *lsp1_q, /* o : quantized 1st LSP vector Q15 */ 1009 Word16 *indice, /* o : quantization indices of 3 vectors Q0 */ 1010 Word16 *pred_init_i,/* o : init index for MA prediction in DTX mode */ 1011 Flag *pOverflow /* o : Flag set when overflow occurs */ 1012 ) 1013 { 1014 register Word16 i, j; 1015 Word16 lsf1[M]; 1016 Word16 wf1[M]; 1017 Word16 lsf_p[M]; 1018 Word16 lsf_r1[M]; 1019 Word16 lsf1_q[M]; 1020 1021 Word32 L_pred_init_err; 1022 Word32 L_min_pred_init_err; 1023 Word32 L_temp; 1024 Word16 temp_r1[M]; 1025 Word16 temp_p[M]; 1026 Word16 temp; 1027 1028 /* convert LSFs to normalize frequency domain 0..16384 */ 1029 1030 Lsp_lsf( 1031 lsp1, 1032 lsf1, 1033 M, 1034 pOverflow); 1035 1036 /* compute LSF weighting factors (Q13) */ 1037 1038 Lsf_wt( 1039 lsf1, 1040 wf1, 1041 pOverflow); 1042 1043 /* Compute predicted LSF and prediction error */ 1044 if (mode != MRDTX) 1045 { 1046 for (i = 0; i < M; i++) 1047 { 1048 temp = (Word16)((((Word32) st->past_rq[i]) * 1049 (*(pred_fac_3 + i))) >> 15); 1050 1051 *(lsf_p + i) = *(mean_lsf_3 + i) + temp; 1052 1053 *(lsf_r1 + i) = *(lsf1 + i) - *(lsf_p + i); 1054 } 1055 } 1056 else 1057 { 1058 /* DTX mode, search the init vector that yields */ 1059 /* lowest prediction resuidual energy */ 1060 *pred_init_i = 0; 1061 L_min_pred_init_err = 0x7fffffff; /* 2^31 - 1 */ 1062 1063 for (j = 0; j < PAST_RQ_INIT_SIZE; j++) 1064 { 1065 L_pred_init_err = 0; 1066 for (i = 0; i < M; i++) 1067 { 1068 *(temp_p + i) = *(mean_lsf_3 + i) + *(past_rq_init + j * M + i); 1069 1070 *(temp_r1 + i) = *(lsf1 + i) - *(temp_p + i); 1071 1072 L_temp = ((Word32) * (temp_r1 + i)) * *(temp_r1 + i); 1073 1074 L_pred_init_err = L_pred_init_err + (L_temp << 1); 1075 1076 } /* next i */ 1077 1078 1079 if (L_pred_init_err < L_min_pred_init_err) 1080 { 1081 L_min_pred_init_err = L_pred_init_err; 1082 1083 oscl_memcpy( 1084 lsf_r1, 1085 temp_r1, 1086 M*sizeof(Word16)); 1087 1088 oscl_memcpy( 1089 lsf_p, 1090 temp_p, 1091 M*sizeof(Word16)); 1092 1093 /* Set zerom */ 1094 oscl_memcpy( 1095 st->past_rq, 1096 &past_rq_init[j*M], 1097 M*sizeof(Word16)); 1098 1099 *pred_init_i = j; 1100 1101 } /* endif */ 1102 } /* next j */ 1103 } /* endif MRDTX */ 1104 1105 /*---- Split-VQ of prediction error ----*/ 1106 if ((mode == MR475) || (mode == MR515)) 1107 { /* MR475, MR515 */ 1108 1109 *indice = 1110 Vq_subvec3( 1111 lsf_r1, 1112 dico1_lsf_3, 1113 wf1, 1114 DICO1_SIZE, 1115 0, 1116 pOverflow); 1117 1118 *(indice + 1) = 1119 Vq_subvec3( 1120 lsf_r1 + 3, 1121 dico2_lsf_3, 1122 wf1 + 3, 1123 DICO2_SIZE / 2, 1124 1, 1125 pOverflow); 1126 1127 *(indice + 2) = 1128 Vq_subvec4( 1129 lsf_r1 + 6, 1130 mr515_3_lsf, 1131 wf1 + 6, 1132 MR515_3_SIZE, 1133 pOverflow); 1134 1135 } 1136 else if (mode == MR795) 1137 { /* MR795 */ 1138 1139 *indice = 1140 Vq_subvec3( 1141 lsf_r1, 1142 mr795_1_lsf, 1143 wf1, 1144 MR795_1_SIZE, 1145 0, 1146 pOverflow); 1147 1148 *(indice + 1) = 1149 Vq_subvec3( 1150 lsf_r1 + 3, 1151 dico2_lsf_3, 1152 wf1 + 3, 1153 DICO2_SIZE, 1154 0, 1155 pOverflow); 1156 1157 *(indice + 2) = 1158 Vq_subvec4( 1159 lsf_r1 + 6, 1160 dico3_lsf_3, 1161 wf1 + 6, 1162 DICO3_SIZE, 1163 pOverflow); 1164 1165 } 1166 else 1167 { /* MR59, MR67, MR74, MR102 , MRDTX */ 1168 1169 *indice = 1170 Vq_subvec3( 1171 lsf_r1, 1172 dico1_lsf_3, 1173 wf1, 1174 DICO1_SIZE, 1175 0, 1176 pOverflow); 1177 1178 *(indice + 1) = 1179 Vq_subvec3( 1180 lsf_r1 + 3, 1181 dico2_lsf_3, 1182 wf1 + 3, 1183 DICO2_SIZE, 1184 0, 1185 pOverflow); 1186 1187 *(indice + 2) = 1188 Vq_subvec4( 1189 lsf_r1 + 6, 1190 dico3_lsf_3, 1191 wf1 + 6, 1192 DICO3_SIZE, 1193 pOverflow); 1194 1195 } 1196 1197 1198 /* Compute quantized LSFs and update the past quantized residual */ 1199 1200 for (i = 0; i < M; i++) 1201 { 1202 *(lsf1_q + i) = *(lsf_r1 + i) + *(lsf_p + i); 1203 st->past_rq[i] = *(lsf_r1 + i); 1204 } 1205 1206 /* verification that LSFs has mimimum distance of LSF_GAP Hz */ 1207 1208 Reorder_lsf( 1209 lsf1_q, 1210 LSF_GAP, 1211 M, 1212 pOverflow); 1213 1214 /* convert LSFs to the cosine domain */ 1215 1216 Lsf_lsp( 1217 lsf1_q, 1218 lsp1_q, 1219 M, 1220 pOverflow); 1221 1222 return; 1223 1224 } 1225