1 /* 2 * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved. 3 * 4 * Use of this source code is governed by a BSD-style license 5 * that can be found in the LICENSE file in the root of the source 6 * tree. An additional intellectual property rights grant can be found 7 * in the file PATENTS. All contributing project authors may 8 * be found in the AUTHORS file in the root of the source tree. 9 */ 10 11 /* 12 * code_LPC_UB.c 13 * 14 * This file contains definition of functions used to 15 * encode LPC parameters (Shape & gain) of the upper band. 16 * 17 */ 18 19 #include "encode_lpc_swb.h" 20 21 #include <math.h> 22 #include <stdio.h> 23 #include <string.h> 24 25 #include "lpc_gain_swb_tables.h" 26 #include "lpc_shape_swb12_tables.h" 27 #include "lpc_shape_swb16_tables.h" 28 #include "settings.h" 29 #include "webrtc/typedefs.h" 30 31 /****************************************************************************** 32 * WebRtcIsac_RemoveLarMean() 33 * 34 * Remove the means from LAR coefficients. 35 * 36 * Input: 37 * -lar : pointer to lar vectors. LAR vectors are 38 * concatenated. 39 * -bandwidth : indicates if the given LAR vectors belong 40 * to SWB-12kHz or SWB-16kHz. 41 * 42 * Output: 43 * -lar : pointer to mean-removed LAR:s. 44 * 45 * 46 */ 47 int16_t 48 WebRtcIsac_RemoveLarMean( 49 double* lar, 50 int16_t bandwidth) 51 { 52 int16_t coeffCntr; 53 int16_t vecCntr; 54 int16_t numVec; 55 const double* meanLAR; 56 switch(bandwidth) 57 { 58 case isac12kHz: 59 { 60 numVec = UB_LPC_VEC_PER_FRAME; 61 meanLAR = WebRtcIsac_kMeanLarUb12; 62 break; 63 } 64 case isac16kHz: 65 { 66 numVec = UB16_LPC_VEC_PER_FRAME; 67 meanLAR = WebRtcIsac_kMeanLarUb16; 68 break; 69 } 70 default: 71 return -1; 72 } 73 74 for(vecCntr = 0; vecCntr < numVec; vecCntr++) 75 { 76 for(coeffCntr = 0; coeffCntr < UB_LPC_ORDER; coeffCntr++) 77 { 78 // REMOVE MEAN 79 *lar++ -= meanLAR[coeffCntr]; 80 } 81 } 82 return 0; 83 } 84 85 /****************************************************************************** 86 * WebRtcIsac_DecorrelateIntraVec() 87 * 88 * Remove the correlation amonge the components of LAR vectors. If LAR vectors 89 * of one frame are put in a matrix where each column is a LAR vector of a 90 * sub-frame, then this is equivalent to multiplying the LAR matrix with 91 * a decorrelting mtrix from left. 92 * 93 * Input: 94 * -inLar : pointer to mean-removed LAR vecrtors. 95 * -bandwidth : indicates if the given LAR vectors belong 96 * to SWB-12kHz or SWB-16kHz. 97 * 98 * Output: 99 * -out : decorrelated LAR vectors. 100 */ 101 int16_t 102 WebRtcIsac_DecorrelateIntraVec( 103 const double* data, 104 double* out, 105 int16_t bandwidth) 106 { 107 const double* ptrData; 108 const double* ptrRow; 109 int16_t rowCntr; 110 int16_t colCntr; 111 int16_t larVecCntr; 112 int16_t numVec; 113 const double* decorrMat; 114 switch(bandwidth) 115 { 116 case isac12kHz: 117 { 118 decorrMat = &WebRtcIsac_kIntraVecDecorrMatUb12[0][0]; 119 numVec = UB_LPC_VEC_PER_FRAME; 120 break; 121 } 122 case isac16kHz: 123 { 124 decorrMat = &WebRtcIsac_kIintraVecDecorrMatUb16[0][0]; 125 numVec = UB16_LPC_VEC_PER_FRAME; 126 break; 127 } 128 default: 129 return -1; 130 } 131 132 // 133 // decorrMat * data 134 // 135 // data is assumed to contain 'numVec' of LAR 136 // vectors (mean removed) each of dimension 'UB_LPC_ORDER' 137 // concatenated one after the other. 138 // 139 140 ptrData = data; 141 for(larVecCntr = 0; larVecCntr < numVec; larVecCntr++) 142 { 143 for(rowCntr = 0; rowCntr < UB_LPC_ORDER; rowCntr++) 144 { 145 ptrRow = &decorrMat[rowCntr * UB_LPC_ORDER]; 146 *out = 0; 147 for(colCntr = 0; colCntr < UB_LPC_ORDER; colCntr++) 148 { 149 *out += ptrData[colCntr] * ptrRow[colCntr]; 150 } 151 out++; 152 } 153 ptrData += UB_LPC_ORDER; 154 } 155 return 0; 156 } 157 158 /****************************************************************************** 159 * WebRtcIsac_DecorrelateInterVec() 160 * 161 * Remover the correlation among mean-removed LAR vectors. If LAR vectors 162 * of one frame are put in a matrix where each column is a LAR vector of a 163 * sub-frame, then this is equivalent to multiplying the LAR matrix with 164 * a decorrelting mtrix from right. 165 * 166 * Input: 167 * -data : pointer to matrix of LAR vectors. The matrix 168 * is stored column-wise. 169 * -bandwidth : indicates if the given LAR vectors belong 170 * to SWB-12kHz or SWB-16kHz. 171 * 172 * Output: 173 * -out : decorrelated LAR vectors. 174 */ 175 int16_t 176 WebRtcIsac_DecorrelateInterVec( 177 const double* data, 178 double* out, 179 int16_t bandwidth) 180 { 181 int16_t coeffCntr; 182 int16_t rowCntr; 183 int16_t colCntr; 184 const double* decorrMat; 185 int16_t interVecDim; 186 187 switch(bandwidth) 188 { 189 case isac12kHz: 190 { 191 decorrMat = &WebRtcIsac_kInterVecDecorrMatUb12[0][0]; 192 interVecDim = UB_LPC_VEC_PER_FRAME; 193 break; 194 } 195 case isac16kHz: 196 { 197 decorrMat = &WebRtcIsac_kInterVecDecorrMatUb16[0][0]; 198 interVecDim = UB16_LPC_VEC_PER_FRAME; 199 break; 200 } 201 default: 202 return -1; 203 } 204 205 // 206 // data * decorrMat 207 // 208 // data is of size 'interVecDim' * 'UB_LPC_ORDER' 209 // That is 'interVecDim' of LAR vectors (mean removed) 210 // in columns each of dimension 'UB_LPC_ORDER'. 211 // matrix is stored column-wise. 212 // 213 214 for(coeffCntr = 0; coeffCntr < UB_LPC_ORDER; coeffCntr++) 215 { 216 for(colCntr = 0; colCntr < interVecDim; colCntr++) 217 { 218 out[coeffCntr + colCntr * UB_LPC_ORDER] = 0; 219 for(rowCntr = 0; rowCntr < interVecDim; rowCntr++) 220 { 221 out[coeffCntr + colCntr * UB_LPC_ORDER] += 222 data[coeffCntr + rowCntr * UB_LPC_ORDER] * 223 decorrMat[rowCntr * interVecDim + colCntr]; 224 } 225 } 226 } 227 return 0; 228 } 229 230 /****************************************************************************** 231 * WebRtcIsac_QuantizeUncorrLar() 232 * 233 * Quantize the uncorrelated parameters. 234 * 235 * Input: 236 * -data : uncorrelated LAR vectors. 237 * -bandwidth : indicates if the given LAR vectors belong 238 * to SWB-12kHz or SWB-16kHz. 239 * 240 * Output: 241 * -data : quantized version of the input. 242 * -idx : pointer to quantization indices. 243 */ 244 double 245 WebRtcIsac_QuantizeUncorrLar( 246 double* data, 247 int* recIdx, 248 int16_t bandwidth) 249 { 250 int16_t cntr; 251 int32_t idx; 252 int16_t interVecDim; 253 const double* leftRecPoint; 254 double quantizationStepSize; 255 const int16_t* numQuantCell; 256 switch(bandwidth) 257 { 258 case isac12kHz: 259 { 260 leftRecPoint = WebRtcIsac_kLpcShapeLeftRecPointUb12; 261 quantizationStepSize = WebRtcIsac_kLpcShapeQStepSizeUb12; 262 numQuantCell = WebRtcIsac_kLpcShapeNumRecPointUb12; 263 interVecDim = UB_LPC_VEC_PER_FRAME; 264 break; 265 } 266 case isac16kHz: 267 { 268 leftRecPoint = WebRtcIsac_kLpcShapeLeftRecPointUb16; 269 quantizationStepSize = WebRtcIsac_kLpcShapeQStepSizeUb16; 270 numQuantCell = WebRtcIsac_kLpcShapeNumRecPointUb16; 271 interVecDim = UB16_LPC_VEC_PER_FRAME; 272 break; 273 } 274 default: 275 return -1; 276 } 277 278 // 279 // Quantize the parametrs. 280 // 281 for(cntr = 0; cntr < UB_LPC_ORDER * interVecDim; cntr++) 282 { 283 idx = (int32_t)floor((*data - leftRecPoint[cntr]) / 284 quantizationStepSize + 0.5); 285 if(idx < 0) 286 { 287 idx = 0; 288 } 289 else if(idx >= numQuantCell[cntr]) 290 { 291 idx = numQuantCell[cntr] - 1; 292 } 293 294 *data++ = leftRecPoint[cntr] + idx * quantizationStepSize; 295 *recIdx++ = idx; 296 } 297 return 0; 298 } 299 300 301 /****************************************************************************** 302 * WebRtcIsac_DequantizeLpcParam() 303 * 304 * Get the quantized value of uncorrelated LARs given the quantization indices. 305 * 306 * Input: 307 * -idx : pointer to quantiztion indices. 308 * -bandwidth : indicates if the given LAR vectors belong 309 * to SWB-12kHz or SWB-16kHz. 310 * 311 * Output: 312 * -out : pointer to quantized values. 313 */ 314 int16_t 315 WebRtcIsac_DequantizeLpcParam( 316 const int* idx, 317 double* out, 318 int16_t bandwidth) 319 { 320 int16_t cntr; 321 int16_t interVecDim; 322 const double* leftRecPoint; 323 double quantizationStepSize; 324 325 switch(bandwidth) 326 { 327 case isac12kHz: 328 { 329 leftRecPoint = WebRtcIsac_kLpcShapeLeftRecPointUb12; 330 quantizationStepSize = WebRtcIsac_kLpcShapeQStepSizeUb12; 331 interVecDim = UB_LPC_VEC_PER_FRAME; 332 break; 333 } 334 case isac16kHz: 335 { 336 leftRecPoint = WebRtcIsac_kLpcShapeLeftRecPointUb16; 337 quantizationStepSize = WebRtcIsac_kLpcShapeQStepSizeUb16; 338 interVecDim = UB16_LPC_VEC_PER_FRAME; 339 break; 340 } 341 default: 342 return -1; 343 } 344 345 // 346 // Dequantize given the quantization indices 347 // 348 349 for(cntr = 0; cntr < UB_LPC_ORDER * interVecDim; cntr++) 350 { 351 *out++ = leftRecPoint[cntr] + *idx++ * quantizationStepSize; 352 } 353 return 0; 354 } 355 356 357 /****************************************************************************** 358 * WebRtcIsac_CorrelateIntraVec() 359 * 360 * This is the inverse of WebRtcIsac_DecorrelateIntraVec(). 361 * 362 * Input: 363 * -data : uncorrelated parameters. 364 * -bandwidth : indicates if the given LAR vectors belong 365 * to SWB-12kHz or SWB-16kHz. 366 * 367 * Output: 368 * -out : correlated parametrs. 369 */ 370 int16_t 371 WebRtcIsac_CorrelateIntraVec( 372 const double* data, 373 double* out, 374 int16_t bandwidth) 375 { 376 int16_t vecCntr; 377 int16_t rowCntr; 378 int16_t colCntr; 379 int16_t numVec; 380 const double* ptrData; 381 const double* intraVecDecorrMat; 382 383 switch(bandwidth) 384 { 385 case isac12kHz: 386 { 387 numVec = UB_LPC_VEC_PER_FRAME; 388 intraVecDecorrMat = &WebRtcIsac_kIntraVecDecorrMatUb12[0][0]; 389 break; 390 } 391 case isac16kHz: 392 { 393 numVec = UB16_LPC_VEC_PER_FRAME; 394 intraVecDecorrMat = &WebRtcIsac_kIintraVecDecorrMatUb16[0][0]; 395 break; 396 } 397 default: 398 return -1; 399 } 400 401 402 ptrData = data; 403 for(vecCntr = 0; vecCntr < numVec; vecCntr++) 404 { 405 for(colCntr = 0; colCntr < UB_LPC_ORDER; colCntr++) 406 { 407 *out = 0; 408 for(rowCntr = 0; rowCntr < UB_LPC_ORDER; rowCntr++) 409 { 410 *out += ptrData[rowCntr] * 411 intraVecDecorrMat[rowCntr * UB_LPC_ORDER + colCntr]; 412 } 413 out++; 414 } 415 ptrData += UB_LPC_ORDER; 416 } 417 return 0; 418 } 419 420 /****************************************************************************** 421 * WebRtcIsac_CorrelateInterVec() 422 * 423 * This is the inverse of WebRtcIsac_DecorrelateInterVec(). 424 * 425 * Input: 426 * -data 427 * -bandwidth : indicates if the given LAR vectors belong 428 * to SWB-12kHz or SWB-16kHz. 429 * 430 * Output: 431 * -out : correlated parametrs. 432 */ 433 int16_t 434 WebRtcIsac_CorrelateInterVec( 435 const double* data, 436 double* out, 437 int16_t bandwidth) 438 { 439 int16_t coeffCntr; 440 int16_t rowCntr; 441 int16_t colCntr; 442 int16_t interVecDim; 443 double myVec[UB16_LPC_VEC_PER_FRAME] = {0.0}; 444 const double* interVecDecorrMat; 445 446 switch(bandwidth) 447 { 448 case isac12kHz: 449 { 450 interVecDim = UB_LPC_VEC_PER_FRAME; 451 interVecDecorrMat = &WebRtcIsac_kInterVecDecorrMatUb12[0][0]; 452 break; 453 } 454 case isac16kHz: 455 { 456 interVecDim = UB16_LPC_VEC_PER_FRAME; 457 interVecDecorrMat = &WebRtcIsac_kInterVecDecorrMatUb16[0][0]; 458 break; 459 } 460 default: 461 return -1; 462 } 463 464 for(coeffCntr = 0; coeffCntr < UB_LPC_ORDER; coeffCntr++) 465 { 466 for(rowCntr = 0; rowCntr < interVecDim; rowCntr++) 467 { 468 myVec[rowCntr] = 0; 469 for(colCntr = 0; colCntr < interVecDim; colCntr++) 470 { 471 myVec[rowCntr] += data[coeffCntr + colCntr * UB_LPC_ORDER] * //*ptrData * 472 interVecDecorrMat[rowCntr * interVecDim + colCntr]; 473 //ptrData += UB_LPC_ORDER; 474 } 475 } 476 477 for(rowCntr = 0; rowCntr < interVecDim; rowCntr++) 478 { 479 out[coeffCntr + rowCntr * UB_LPC_ORDER] = myVec[rowCntr]; 480 } 481 } 482 return 0; 483 } 484 485 /****************************************************************************** 486 * WebRtcIsac_AddLarMean() 487 * 488 * This is the inverse of WebRtcIsac_RemoveLarMean() 489 * 490 * Input: 491 * -data : pointer to mean-removed LAR:s. 492 * -bandwidth : indicates if the given LAR vectors belong 493 * to SWB-12kHz or SWB-16kHz. 494 * 495 * Output: 496 * -data : pointer to LARs. 497 */ 498 int16_t 499 WebRtcIsac_AddLarMean( 500 double* data, 501 int16_t bandwidth) 502 { 503 int16_t coeffCntr; 504 int16_t vecCntr; 505 int16_t numVec; 506 const double* meanLAR; 507 508 switch(bandwidth) 509 { 510 case isac12kHz: 511 { 512 numVec = UB_LPC_VEC_PER_FRAME; 513 meanLAR = WebRtcIsac_kMeanLarUb12; 514 break; 515 } 516 case isac16kHz: 517 { 518 numVec = UB16_LPC_VEC_PER_FRAME; 519 meanLAR = WebRtcIsac_kMeanLarUb16; 520 break; 521 } 522 default: 523 return -1; 524 } 525 526 for(vecCntr = 0; vecCntr < numVec; vecCntr++) 527 { 528 for(coeffCntr = 0; coeffCntr < UB_LPC_ORDER; coeffCntr++) 529 { 530 *data++ += meanLAR[coeffCntr]; 531 } 532 } 533 return 0; 534 } 535 536 /****************************************************************************** 537 * WebRtcIsac_ToLogDomainRemoveMean() 538 * 539 * Transform the LPC gain to log domain then remove the mean value. 540 * 541 * Input: 542 * -lpcGain : pointer to LPC Gain, expecting 6 LPC gains 543 * 544 * Output: 545 * -lpcGain : mean-removed in log domain. 546 */ 547 int16_t 548 WebRtcIsac_ToLogDomainRemoveMean( 549 double* data) 550 { 551 int16_t coeffCntr; 552 for(coeffCntr = 0; coeffCntr < UB_LPC_GAIN_DIM; coeffCntr++) 553 { 554 data[coeffCntr] = log(data[coeffCntr]) - WebRtcIsac_kMeanLpcGain; 555 } 556 return 0; 557 } 558 559 560 /****************************************************************************** 561 * WebRtcIsac_DecorrelateLPGain() 562 * 563 * Decorrelate LPC gains. There are 6 LPC Gains per frame. This is like 564 * multiplying gain vector with decorrelating matrix. 565 * 566 * Input: 567 * -data : LPC gain in log-domain with mean removed. 568 * 569 * Output: 570 * -out : decorrelated parameters. 571 */ 572 int16_t WebRtcIsac_DecorrelateLPGain( 573 const double* data, 574 double* out) 575 { 576 int16_t rowCntr; 577 int16_t colCntr; 578 579 for(colCntr = 0; colCntr < UB_LPC_GAIN_DIM; colCntr++) 580 { 581 *out = 0; 582 for(rowCntr = 0; rowCntr < UB_LPC_GAIN_DIM; rowCntr++) 583 { 584 *out += data[rowCntr] * WebRtcIsac_kLpcGainDecorrMat[rowCntr][colCntr]; 585 } 586 out++; 587 } 588 return 0; 589 } 590 591 /****************************************************************************** 592 * WebRtcIsac_QuantizeLpcGain() 593 * 594 * Quantize the decorrelated log-domain gains. 595 * 596 * Input: 597 * -lpcGain : uncorrelated LPC gains. 598 * 599 * Output: 600 * -idx : quantization indices 601 * -lpcGain : quantized value of the inpt. 602 */ 603 double WebRtcIsac_QuantizeLpcGain( 604 double* data, 605 int* idx) 606 { 607 int16_t coeffCntr; 608 for(coeffCntr = 0; coeffCntr < UB_LPC_GAIN_DIM; coeffCntr++) 609 { 610 *idx = (int)floor((*data - WebRtcIsac_kLeftRecPointLpcGain[coeffCntr]) / 611 WebRtcIsac_kQSizeLpcGain + 0.5); 612 613 if(*idx < 0) 614 { 615 *idx = 0; 616 } 617 else if(*idx >= WebRtcIsac_kNumQCellLpcGain[coeffCntr]) 618 { 619 *idx = WebRtcIsac_kNumQCellLpcGain[coeffCntr] - 1; 620 } 621 *data = WebRtcIsac_kLeftRecPointLpcGain[coeffCntr] + *idx * 622 WebRtcIsac_kQSizeLpcGain; 623 624 data++; 625 idx++; 626 } 627 return 0; 628 } 629 630 /****************************************************************************** 631 * WebRtcIsac_DequantizeLpcGain() 632 * 633 * Get the quantized values given the quantization indices. 634 * 635 * Input: 636 * -idx : pointer to quantization indices. 637 * 638 * Output: 639 * -lpcGains : quantized values of the given parametes. 640 */ 641 int16_t WebRtcIsac_DequantizeLpcGain( 642 const int* idx, 643 double* out) 644 { 645 int16_t coeffCntr; 646 for(coeffCntr = 0; coeffCntr < UB_LPC_GAIN_DIM; coeffCntr++) 647 { 648 *out = WebRtcIsac_kLeftRecPointLpcGain[coeffCntr] + *idx * 649 WebRtcIsac_kQSizeLpcGain; 650 out++; 651 idx++; 652 } 653 return 0; 654 } 655 656 /****************************************************************************** 657 * WebRtcIsac_CorrelateLpcGain() 658 * 659 * This is the inverse of WebRtcIsac_DecorrelateLPGain(). 660 * 661 * Input: 662 * -data : decorrelated parameters. 663 * 664 * Output: 665 * -out : correlated parameters. 666 */ 667 int16_t WebRtcIsac_CorrelateLpcGain( 668 const double* data, 669 double* out) 670 { 671 int16_t rowCntr; 672 int16_t colCntr; 673 674 for(rowCntr = 0; rowCntr < UB_LPC_GAIN_DIM; rowCntr++) 675 { 676 *out = 0; 677 for(colCntr = 0; colCntr < UB_LPC_GAIN_DIM; colCntr++) 678 { 679 *out += WebRtcIsac_kLpcGainDecorrMat[rowCntr][colCntr] * data[colCntr]; 680 } 681 out++; 682 } 683 684 return 0; 685 } 686 687 688 /****************************************************************************** 689 * WebRtcIsac_AddMeanToLinearDomain() 690 * 691 * This is the inverse of WebRtcIsac_ToLogDomainRemoveMean(). 692 * 693 * Input: 694 * -lpcGain : LPC gain in log-domain & mean removed 695 * 696 * Output: 697 * -lpcGain : LPC gain in normal domain. 698 */ 699 int16_t WebRtcIsac_AddMeanToLinearDomain( 700 double* lpcGains) 701 { 702 int16_t coeffCntr; 703 for(coeffCntr = 0; coeffCntr < UB_LPC_GAIN_DIM; coeffCntr++) 704 { 705 lpcGains[coeffCntr] = exp(lpcGains[coeffCntr] + WebRtcIsac_kMeanLpcGain); 706 } 707 return 0; 708 } 709