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/lsp_az.c 32 Funtions: Get_lsp_pol 33 Lsp_Az 34 35 ------------------------------------------------------------------------------ 36 REVISION HISTORY 37 38 Description: Updated template used to PV coding template. First attempt at 39 optimizing C code. 40 41 Description: Deleted all Local stores needed/modified. Optimized Lsp_Az 42 function by getting rid of call to L_shr_r function. 43 44 Description: Updated file per comments gathered from Phase 2/3 review. 45 46 Description: Added setting of Overflow flag in the inlined code. 47 48 Description: 1. Optimized Lsp_Az function code. 49 2. Changed Input/Output definitions by adding Word type. 50 51 Description: Made changes based on review meeting. 52 1. Removed pseudocode. 53 54 Description: Synchronized file with UMTS version 3.2.0. Updated coding 55 template. Removed unnecessary include files. 56 57 Description: Replaced basic_op.h and oper_32b.h with the header files of the 58 math functions used in the file. 59 60 Description: Modified to pass overflow flag through to L_add and L_sub. The 61 flag is passed back to the calling function by pointer reference. 62 63 Description: Removed the id line since it was removed in the header file by 64 Ken. 65 66 Description: Added the write-only variable, pOverflow, to the inputs section. 67 68 Description: For lsp_az() and Get_lsp_pol() 69 1. Eliminated unused include files. 70 2. Replaced array addressing by pointers 71 3. Eliminated math operations that unnecessary checked for 72 saturation, in some cases this by shifting before adding and 73 in other cases by evaluating the operands 74 4. Unrolled loops to speed up processing 75 5. Replaced mpy_32_16 by multpilcations in place 76 6. Eliminated if-else statements for sign extension when 77 right-shifting 78 79 Description: Added casting to eliminate warnings, and eliminated include 80 files that now are chosen by OSCL definitions 81 82 Description: Replaced "int" and/or "char" with defined types. 83 Added proper casting (Word32) to some left shifting operations 84 85 Who: Date: 86 Description: 87 88 ------------------------------------------------------------------------------ 89 MODULE DESCRIPTION 90 91 This file contains functions that convert line spectral pairs (LSP) to 92 linear predictive (LP) coefficients (filter order = 10). The functions 93 included in this file include Get_lsp_pol, which finds the coefficients of 94 F1(z) and F2(z), and Lsp_Az, which converts LSP to LPC by multiplying 95 F1(z) by 1+z^(-1) and F2(z) by 1-z^(-1), then calculating A(z) = (F1(z) + 96 F2(z))/2. 97 98 ------------------------------------------------------------------------------ 99 */ 100 101 /*---------------------------------------------------------------------------- 102 ; INCLUDES 103 ----------------------------------------------------------------------------*/ 104 #include "lsp_az.h" 105 106 /*---------------------------------------------------------------------------- 107 ; MACROS 108 ; Define module specific macros here 109 ----------------------------------------------------------------------------*/ 110 111 /*---------------------------------------------------------------------------- 112 ; DEFINES 113 ; Include all pre-processor statements here. Include conditional 114 ; compile variables also. 115 ----------------------------------------------------------------------------*/ 116 117 /*---------------------------------------------------------------------------- 118 ; LOCAL FUNCTION DEFINITIONS 119 ; Function Prototype declaration 120 ----------------------------------------------------------------------------*/ 121 122 /*---------------------------------------------------------------------------- 123 ; LOCAL VARIABLE DEFINITIONS 124 ; Variable declaration - defined here and used outside this module 125 ----------------------------------------------------------------------------*/ 126 127 128 /* 129 ------------------------------------------------------------------------------ 130 FUNCTION NAME: Get_lsp_pol 131 ------------------------------------------------------------------------------ 132 INPUT AND OUTPUT DEFINITIONS 133 134 Inputs: 135 lsp = pointer to the buffer containing the line spectral pairs (LSP) 136 of type Word16 137 f = pointer to the polynomial of type Word32 to be generated 138 139 pOverflow = pointer set in case where one of the operations overflows. 140 [data type Pointer to Flag] 141 142 Outputs: 143 buffer pointed to by f contains the polynomial generated 144 145 pOverflow = pointer set in case where one of the operations overflows. 146 [data type Pointer to Flag] 147 148 Returns: 149 None 150 151 Global Variables Used: 152 None 153 154 Local Variables Needed: 155 None 156 157 ------------------------------------------------------------------------------ 158 FUNCTION DESCRIPTION 159 160 This function finds the polynomial F1(z) or F2(z) from the LSPs. If the LSP 161 vector is passed at address 0, F1(z) is computed and if it is passed at 162 address 1, F2(z) is computed. 163 164 This is performed by expanding the product polynomials: 165 166 F1(z) = product ( 1 - 2 lsp[i] z^-1 + z^-2 ) 167 i=0,2,4,6,8 168 F2(z) = product ( 1 - 2 lsp[i] z^-1 + z^-2 ) 169 i=1,3,5,7,9 170 171 where lsp[] is the LSP vector in the cosine domain. 172 173 The expansion is performed using the following recursion: 174 175 f[0] = 1 176 b = -2.0 * lsp[0] 177 f[1] = b 178 for i=2 to 5 do 179 b = -2.0 * lsp[2*i-2]; 180 for j=i-1 down to 2 do 181 f[j] = f[j] + b*f[j-1] + f[j-2]; 182 f[1] = f[1] + b; 183 184 ------------------------------------------------------------------------------ 185 REQUIREMENTS 186 187 None 188 189 ------------------------------------------------------------------------------ 190 REFERENCES 191 192 lsp_az.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001 193 194 ------------------------------------------------------------------------------ 195 PSEUDO-CODE 196 197 static void Get_lsp_pol (Word16 *lsp, Word32 *f) 198 { 199 Word16 i, j, hi, lo; 200 Word32 t0; 201 202 // f[0] = 1.0; 203 *f = L_mult (4096, 2048); 204 f++; 205 *f = L_msu ((Word32) 0, *lsp, 512); // f[1] = -2.0 * lsp[0]; 206 f++; 207 lsp += 2; // Advance lsp pointer 208 209 for (i = 2; i <= 5; i++) 210 { 211 *f = f[-2]; 212 213 for (j = 1; j < i; j++, f--) 214 { 215 L_Extract (f[-1], &hi, &lo); 216 t0 = Mpy_32_16 (hi, lo, *lsp); // t0 = f[-1] * lsp 217 t0 = L_shl (t0, 1); 218 *f = L_add (*f, f[-2]); // *f += f[-2] 219 *f = L_sub (*f, t0); // *f -= t0 220 } 221 *f = L_msu (*f, *lsp, 512); // *f -= lsp<<9 222 f += i; // Advance f pointer 223 lsp += 2; // Advance lsp pointer 224 } 225 226 return; 227 } 228 229 ------------------------------------------------------------------------------ 230 RESOURCES USED [optional] 231 232 When the code is written for a specific target processor the 233 the resources used should be documented below. 234 235 HEAP MEMORY USED: x bytes 236 237 STACK MEMORY USED: x bytes 238 239 CLOCK CYCLES: (cycle count equation for this function) + (variable 240 used to represent cycle count for each subroutine 241 called) 242 where: (cycle count variable) = cycle count for [subroutine 243 name] 244 245 ------------------------------------------------------------------------------ 246 CAUTION [optional] 247 [State any special notes, constraints or cautions for users of this function] 248 249 ------------------------------------------------------------------------------ 250 */ 251 252 static void Get_lsp_pol( 253 Word16 *lsp, 254 Word32 *f, 255 Flag *pOverflow) 256 { 257 register Word16 i; 258 register Word16 j; 259 260 Word16 hi; 261 Word16 lo; 262 Word32 t0; 263 OSCL_UNUSED_ARG(pOverflow); 264 265 /* f[0] = 1.0; */ 266 *f++ = (Word32) 0x01000000; 267 *f++ = (Word32) - *(lsp++) << 10; /* f[1] = -2.0 * lsp[0]; */ 268 lsp++; /* Advance lsp pointer */ 269 270 for (i = 2; i <= 5; i++) 271 { 272 *f = *(f - 2); 273 274 for (j = 1; j < i; j++) 275 { 276 hi = (Word16)(*(f - 1) >> 16); 277 278 lo = (Word16)((*(f - 1) >> 1) - ((Word32) hi << 15)); 279 280 t0 = ((Word32)hi * *lsp); 281 t0 += ((Word32)lo * *lsp) >> 15; 282 283 *(f) += *(f - 2); /* *f += f[-2] */ 284 *(f--) -= t0 << 2; /* *f -= t0 */ 285 286 } 287 288 *f -= (Word32)(*lsp++) << 10; 289 290 f += i; 291 lsp++; 292 } 293 294 return; 295 } 296 297 /****************************************************************************/ 298 299 300 /* 301 ------------------------------------------------------------------------------ 302 FUNCTION NAME: Get_lsp_pol_wrapper 303 ------------------------------------------------------------------------------ 304 INPUT AND OUTPUT DEFINITIONS 305 306 Inputs: 307 lsp = pointer to the buffer containing the line spectral pairs (LSP) 308 of type Word16 309 f = pointer to the polynomial of type Word32 to be generated 310 311 pOverflow = pointer set in case where one of the operations overflows. 312 [data type Pointer to Flag] 313 314 Outputs: 315 buffer pointed to by f contains the polynomial generated 316 317 pOverflow = pointer set in case where one of the operations overflows. 318 [data type Pointer to Flag] 319 320 Returns: 321 None 322 323 Global Variables Used: 324 None 325 326 Local Variables Needed: 327 None 328 329 ------------------------------------------------------------------------------ 330 FUNCTION DESCRIPTION 331 332 This function provides external access to the static function Get_lsp_pol. 333 334 ------------------------------------------------------------------------------ 335 REQUIREMENTS 336 337 None 338 339 ------------------------------------------------------------------------------ 340 REFERENCES 341 342 None 343 344 ------------------------------------------------------------------------------ 345 PSEUDO-CODE 346 347 CALL Get_lsp_pol(lsp = lsp_ptr 348 f = f_ptr ) 349 MODIFYING(nothing) 350 RETURNING(nothing) 351 352 ------------------------------------------------------------------------------ 353 RESOURCES USED [optional] 354 355 When the code is written for a specific target processor the 356 the resources used should be documented below. 357 358 HEAP MEMORY USED: x bytes 359 360 STACK MEMORY USED: x bytes 361 362 CLOCK CYCLES: (cycle count equation for this function) + (variable 363 used to represent cycle count for each subroutine 364 called) 365 where: (cycle count variable) = cycle count for [subroutine 366 name] 367 368 ------------------------------------------------------------------------------ 369 CAUTION [optional] 370 [State any special notes, constraints or cautions for users of this function] 371 372 ------------------------------------------------------------------------------ 373 */ 374 375 void Get_lsp_pol_wrapper( 376 Word16 *lsp, 377 Word32 *f, 378 Flag *pOverflow) 379 { 380 /*---------------------------------------------------------------------------- 381 CALL Get_lsp_pol(lsp = lsp_ptr 382 f = f_ptr ) 383 ----------------------------------------------------------------------------*/ 384 Get_lsp_pol(lsp, f, pOverflow); 385 386 /*---------------------------------------------------------------------------- 387 MODIFYING(nothing) 388 RETURNING(nothing) 389 ----------------------------------------------------------------------------*/ 390 return; 391 } 392 393 /****************************************************************************/ 394 395 396 /* 397 ------------------------------------------------------------------------------ 398 FUNCTION NAME: Lsp_Az 399 ------------------------------------------------------------------------------ 400 INPUT AND OUTPUT DEFINITIONS 401 402 Inputs: 403 lsp = pointer to the buffer containing the line spectral pairs (LSP) 404 of type Word16 405 406 a = pointer to the buffer containing Linear Predictive (LP) 407 coefficients of type Word16 to be generated 408 409 pOverflow = pointer set in case where one of the operations overflows. 410 [data type Pointer to Flag] 411 412 Local Stores/Buffers/Pointers Needed: 413 None 414 415 Global Stores/Buffers/Pointers Needed: 416 None 417 418 Outputs: 419 pOverflow = pointer set in case where one of the operations overflows. 420 [data type Pointer to Flag] 421 422 Pointers and Buffers Modified: 423 a buffer contains the generated Linear Predictive (LP) coefficients 424 425 Local Stores Modified: 426 None 427 428 Global Stores Modified: 429 None 430 431 ------------------------------------------------------------------------------ 432 FUNCTION DESCRIPTION 433 434 This function converts from the line spectral pairs (LSP) to LP coefficients 435 for a 10th order filter. 436 437 This is done by: 438 (1) Find the coefficients of F1(z) and F2(z) (see Get_lsp_pol) 439 (2) Multiply F1(z) by 1+z^{-1} and F2(z) by 1-z^{-1} 440 (3) A(z) = ( F1(z) + F2(z) ) / 2 441 442 ------------------------------------------------------------------------------ 443 REQUIREMENTS 444 445 None 446 447 ------------------------------------------------------------------------------ 448 REFERENCES 449 450 lsp_az.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001 451 452 ------------------------------------------------------------------------------ 453 PSEUDO-CODE 454 455 void Lsp_Az ( 456 Word16 lsp[], // (i) : line spectral frequencies 457 Word16 a[] // (o) : predictor coefficients (order = 10) 458 ) 459 { 460 Word16 i, j; 461 Word32 f1[6], f2[6]; 462 Word32 t0; 463 464 Get_lsp_pol (&lsp[0], f1); 465 Get_lsp_pol (&lsp[1], f2); 466 467 for (i = 5; i > 0; i--) 468 { 469 f1[i] = L_add (f1[i], f1[i - 1]); // f1[i] += f1[i-1]; 470 f2[i] = L_sub (f2[i], f2[i - 1]); // f2[i] -= f2[i-1]; 471 } 472 473 a[0] = 4096; 474 for (i = 1, j = 10; i <= 5; i++, j--) 475 { 476 t0 = L_add (f1[i], f2[i]); // f1[i] + f2[i] 477 a[i] = extract_l (L_shr_r (t0, 13)); 478 t0 = L_sub (f1[i], f2[i]); // f1[i] - f2[i] 479 a[j] = extract_l (L_shr_r (t0, 13)); 480 } 481 482 return; 483 } 484 485 ------------------------------------------------------------------------------ 486 RESOURCES USED [optional] 487 488 When the code is written for a specific target processor the 489 the resources used should be documented below. 490 491 HEAP MEMORY USED: x bytes 492 493 STACK MEMORY USED: x bytes 494 495 CLOCK CYCLES: (cycle count equation for this function) + (variable 496 used to represent cycle count for each subroutine 497 called) 498 where: (cycle count variable) = cycle count for [subroutine 499 name] 500 501 ------------------------------------------------------------------------------ 502 CAUTION [optional] 503 [State any special notes, constraints or cautions for users of this function] 504 505 ------------------------------------------------------------------------------ 506 */ 507 508 void Lsp_Az( 509 Word16 lsp[], /* (i) : line spectral frequencies */ 510 Word16 a[], /* (o) : predictor coefficients (order = 10) */ 511 Flag *pOverflow /* (o) : overflow flag */ 512 ) 513 { 514 register Word16 i; 515 register Word16 j; 516 517 Word32 f1[6]; 518 Word32 f2[6]; 519 Word32 t0; 520 Word32 t1; 521 Word16 *p_a = &a[0]; 522 Word32 *p_f1; 523 Word32 *p_f2; 524 525 Get_lsp_pol(&lsp[0], f1, pOverflow); 526 527 Get_lsp_pol(&lsp[1], f2, pOverflow); 528 529 p_f1 = &f1[5]; 530 p_f2 = &f2[5]; 531 532 for (i = 5; i > 0; i--) 533 { 534 *(p_f1--) += f1[i-1]; 535 *(p_f2--) -= f2[i-1]; 536 } 537 538 *(p_a++) = 4096; 539 p_f1 = &f1[1]; 540 p_f2 = &f2[1]; 541 542 for (i = 1, j = 10; i <= 5; i++, j--) 543 { 544 t0 = *(p_f1) + *(p_f2); /* f1[i] + f2[i] */ 545 t1 = *(p_f1++) - *(p_f2++); /* f1[i] - f2[i] */ 546 547 t0 = t0 + ((Word32) 1 << 12); 548 t1 = t1 + ((Word32) 1 << 12); 549 550 *(p_a++) = (Word16)(t0 >> 13); 551 a[j] = (Word16)(t1 >> 13); 552 } 553 554 return; 555 } 556