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