1 /* 2 ** Copyright 2003-2010, VisualOn, Inc. 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 express or implied. 13 ** See the License for the specific language governing permissions and 14 ** limitations under the License. 15 */ 16 /******************************************************************************* 17 File: tns.c 18 19 Content: Definition TNS tools functions 20 21 *******************************************************************************/ 22 23 #include "basic_op.h" 24 #include "oper_32b.h" 25 #include "assert.h" 26 #include "aac_rom.h" 27 #include "psy_const.h" 28 #include "tns.h" 29 #include "tns_param.h" 30 #include "psy_configuration.h" 31 #include "tns_func.h" 32 33 #define UNUSED(x) (void)(x) 34 35 #define TNS_MODIFY_BEGIN 2600 /* Hz */ 36 #define RATIO_PATCH_LOWER_BORDER 380 /* Hz */ 37 #define TNS_GAIN_THRESH 141 /* 1.41*100 */ 38 #define NORM_COEF 0x028f5c28 39 40 static const Word32 TNS_PARCOR_THRESH = 0x0ccccccd; /* 0.1*(1 << 31) */ 41 /* Limit bands to > 2.0 kHz */ 42 static unsigned short tnsMinBandNumberLong[12] = 43 { 11, 12, 15, 16, 17, 20, 25, 26, 24, 28, 30, 31 }; 44 static unsigned short tnsMinBandNumberShort[12] = 45 { 2, 2, 2, 3, 3, 4, 6, 6, 8, 10, 10, 12 }; 46 47 /**************************************/ 48 /* Main/Low Profile TNS Parameters */ 49 /**************************************/ 50 static unsigned short tnsMaxBandsLongMainLow[12] = 51 { 31, 31, 34, 40, 42, 51, 46, 46, 42, 42, 42, 39 }; 52 53 static unsigned short tnsMaxBandsShortMainLow[12] = 54 { 9, 9, 10, 14, 14, 14, 14, 14, 14, 14, 14, 14 }; 55 56 57 static void CalcWeightedSpectrum(const Word32 spectrum[], 58 Word16 weightedSpectrum[], 59 Word32* sfbEnergy, 60 const Word16* sfbOffset, Word16 lpcStartLine, 61 Word16 lpcStopLine, Word16 lpcStartBand,Word16 lpcStopBand, 62 Word32 *pWork32); 63 64 65 66 void AutoCorrelation(const Word16 input[], Word32 corr[], 67 Word16 samples, Word16 corrCoeff); 68 static Word16 AutoToParcor(Word32 workBuffer[], Word32 reflCoeff[], Word16 numOfCoeff); 69 70 static Word16 CalcTnsFilter(const Word16* signal, const Word32 window[], Word16 numOfLines, 71 Word16 tnsOrder, Word32 parcor[]); 72 73 74 static void Parcor2Index(const Word32 parcor[], Word16 index[], Word16 order, 75 Word16 bitsPerCoeff); 76 77 static void Index2Parcor(const Word16 index[], Word32 parcor[], Word16 order, 78 Word16 bitsPerCoeff); 79 80 81 82 static void AnalysisFilterLattice(const Word32 signal[], Word16 numOfLines, 83 const Word32 parCoeff[], Word16 order, 84 Word32 output[]); 85 86 87 /** 88 * 89 * function name: FreqToBandWithRounding 90 * description: Retrieve index of nearest band border 91 * returnt: index 92 * 93 */ 94 static Word16 FreqToBandWithRounding(Word32 freq, /*!< frequency in Hertz */ 95 Word32 fs, /*!< Sampling frequency in Hertz */ 96 Word16 numOfBands, /*!< total number of bands */ 97 const Word16 *bandStartOffset) /*!< table of band borders */ 98 { 99 Word32 lineNumber, band; 100 Word32 temp, shift; 101 102 /* assert(freq >= 0); */ 103 shift = norm_l(fs); 104 lineNumber = (extract_l(fixmul((bandStartOffset[numOfBands] << 2),Div_32(freq << shift,fs << shift))) + 1) >> 1; 105 106 /* freq > fs/2 */ 107 temp = lineNumber - bandStartOffset[numOfBands] ; 108 if (temp >= 0) 109 return numOfBands; 110 111 /* find band the line number lies in */ 112 for (band=0; band<numOfBands; band++) { 113 temp = bandStartOffset[band + 1] - lineNumber; 114 if (temp > 0) break; 115 } 116 117 temp = (lineNumber - bandStartOffset[band]); 118 temp = (temp - (bandStartOffset[band + 1] - lineNumber)); 119 if ( temp > 0 ) 120 { 121 band = band + 1; 122 } 123 124 return extract_l(band); 125 } 126 127 128 /** 129 * 130 * function name: InitTnsConfigurationLong 131 * description: Fill TNS_CONFIG structure with sensible content for long blocks 132 * returns: 0 if success 133 * 134 */ 135 Word16 InitTnsConfigurationLong(Word32 bitRate, /*!< bitrate */ 136 Word32 sampleRate, /*!< Sampling frequency */ 137 Word16 channels, /*!< number of channels */ 138 TNS_CONFIG *tC, /*!< TNS Config struct (modified) */ 139 PSY_CONFIGURATION_LONG *pC, /*!< psy config struct */ 140 Word16 active) /*!< tns active flag */ 141 { 142 143 Word32 bitratePerChannel; 144 tC->maxOrder = TNS_MAX_ORDER; 145 tC->tnsStartFreq = 1275; 146 tC->coefRes = 4; 147 148 /* to avoid integer division */ 149 if ( sub(channels,2) == 0 ) { 150 bitratePerChannel = bitRate >> 1; 151 } 152 else { 153 bitratePerChannel = bitRate; 154 } 155 156 tC->tnsMaxSfb = tnsMaxBandsLongMainLow[pC->sampRateIdx]; 157 158 tC->tnsActive = active; 159 160 /* now calc band and line borders */ 161 tC->tnsStopBand = min(pC->sfbCnt, tC->tnsMaxSfb); 162 tC->tnsStopLine = pC->sfbOffset[tC->tnsStopBand]; 163 164 tC->tnsStartBand = FreqToBandWithRounding(tC->tnsStartFreq, sampleRate, 165 pC->sfbCnt, (const Word16*)pC->sfbOffset); 166 167 tC->tnsModifyBeginCb = FreqToBandWithRounding(TNS_MODIFY_BEGIN, 168 sampleRate, 169 pC->sfbCnt, 170 (const Word16*)pC->sfbOffset); 171 172 tC->tnsRatioPatchLowestCb = FreqToBandWithRounding(RATIO_PATCH_LOWER_BORDER, 173 sampleRate, 174 pC->sfbCnt, 175 (const Word16*)pC->sfbOffset); 176 177 178 tC->tnsStartLine = pC->sfbOffset[tC->tnsStartBand]; 179 180 tC->lpcStopBand = tnsMaxBandsLongMainLow[pC->sampRateIdx]; 181 tC->lpcStopBand = min(tC->lpcStopBand, pC->sfbActive); 182 183 tC->lpcStopLine = pC->sfbOffset[tC->lpcStopBand]; 184 185 tC->lpcStartBand = tnsMinBandNumberLong[pC->sampRateIdx]; 186 187 tC->lpcStartLine = pC->sfbOffset[tC->lpcStartBand]; 188 189 tC->threshold = TNS_GAIN_THRESH; 190 191 192 return(0); 193 } 194 195 /** 196 * 197 * function name: InitTnsConfigurationShort 198 * description: Fill TNS_CONFIG structure with sensible content for short blocks 199 * returns: 0 if success 200 * 201 */ 202 Word16 InitTnsConfigurationShort(Word32 bitRate, /*!< bitrate */ 203 Word32 sampleRate, /*!< Sampling frequency */ 204 Word16 channels, /*!< number of channels */ 205 TNS_CONFIG *tC, /*!< TNS Config struct (modified) */ 206 PSY_CONFIGURATION_SHORT *pC, /*!< psy config struct */ 207 Word16 active) /*!< tns active flag */ 208 { 209 Word32 bitratePerChannel; 210 tC->maxOrder = TNS_MAX_ORDER_SHORT; 211 tC->tnsStartFreq = 2750; 212 tC->coefRes = 3; 213 214 /* to avoid integer division */ 215 if ( sub(channels,2) == 0 ) { 216 bitratePerChannel = L_shr(bitRate,1); 217 } 218 else { 219 bitratePerChannel = bitRate; 220 } 221 222 tC->tnsMaxSfb = tnsMaxBandsShortMainLow[pC->sampRateIdx]; 223 224 tC->tnsActive = active; 225 226 /* now calc band and line borders */ 227 tC->tnsStopBand = min(pC->sfbCnt, tC->tnsMaxSfb); 228 tC->tnsStopLine = pC->sfbOffset[tC->tnsStopBand]; 229 230 tC->tnsStartBand=FreqToBandWithRounding(tC->tnsStartFreq, sampleRate, 231 pC->sfbCnt, (const Word16*)pC->sfbOffset); 232 233 tC->tnsModifyBeginCb = FreqToBandWithRounding(TNS_MODIFY_BEGIN, 234 sampleRate, 235 pC->sfbCnt, 236 (const Word16*)pC->sfbOffset); 237 238 tC->tnsRatioPatchLowestCb = FreqToBandWithRounding(RATIO_PATCH_LOWER_BORDER, 239 sampleRate, 240 pC->sfbCnt, 241 (const Word16*)pC->sfbOffset); 242 243 244 tC->tnsStartLine = pC->sfbOffset[tC->tnsStartBand]; 245 246 tC->lpcStopBand = tnsMaxBandsShortMainLow[pC->sampRateIdx]; 247 248 tC->lpcStopBand = min(tC->lpcStopBand, pC->sfbActive); 249 250 tC->lpcStopLine = pC->sfbOffset[tC->lpcStopBand]; 251 252 tC->lpcStartBand = tnsMinBandNumberShort[pC->sampRateIdx]; 253 254 tC->lpcStartLine = pC->sfbOffset[tC->lpcStartBand]; 255 256 tC->threshold = TNS_GAIN_THRESH; 257 258 return(0); 259 } 260 261 /** 262 * 263 * function name: TnsDetect 264 * description: Calculate TNS filter and decide on TNS usage 265 * returns: 0 if success 266 * 267 */ 268 Word32 TnsDetect(TNS_DATA* tnsData, /*!< tns data structure (modified) */ 269 TNS_CONFIG tC, /*!< tns config structure */ 270 Word32* pScratchTns, /*!< pointer to scratch space */ 271 const Word16 sfbOffset[], /*!< scalefactor size and table */ 272 Word32* spectrum, /*!< spectral data */ 273 Word16 subBlockNumber, /*!< subblock num */ 274 Word16 blockType, /*!< blocktype (long or short) */ 275 Word32 * sfbEnergy) /*!< sfb-wise energy */ 276 { 277 278 Word32 predictionGain; 279 Word32 temp; 280 Word32* pWork32 = &pScratchTns[subBlockNumber >> 8]; 281 Word16* pWeightedSpectrum = (Word16 *)&pScratchTns[subBlockNumber >> 8]; 282 283 284 if (tC.tnsActive) { 285 CalcWeightedSpectrum(spectrum, 286 pWeightedSpectrum, 287 sfbEnergy, 288 sfbOffset, 289 tC.lpcStartLine, 290 tC.lpcStopLine, 291 tC.lpcStartBand, 292 tC.lpcStopBand, 293 pWork32); 294 295 temp = blockType - SHORT_WINDOW; 296 if ( temp != 0 ) { 297 predictionGain = CalcTnsFilter( &pWeightedSpectrum[tC.lpcStartLine], 298 tC.acfWindow, 299 tC.lpcStopLine - tC.lpcStartLine, 300 tC.maxOrder, 301 tnsData->dataRaw.tnsLong.subBlockInfo.parcor); 302 303 304 temp = predictionGain - tC.threshold; 305 if ( temp > 0 ) { 306 tnsData->dataRaw.tnsLong.subBlockInfo.tnsActive = 1; 307 } 308 else { 309 tnsData->dataRaw.tnsLong.subBlockInfo.tnsActive = 0; 310 } 311 312 tnsData->dataRaw.tnsLong.subBlockInfo.predictionGain = predictionGain; 313 } 314 else{ 315 316 predictionGain = CalcTnsFilter( &pWeightedSpectrum[tC.lpcStartLine], 317 tC.acfWindow, 318 tC.lpcStopLine - tC.lpcStartLine, 319 tC.maxOrder, 320 tnsData->dataRaw.tnsShort.subBlockInfo[subBlockNumber].parcor); 321 322 temp = predictionGain - tC.threshold; 323 if ( temp > 0 ) { 324 tnsData->dataRaw.tnsShort.subBlockInfo[subBlockNumber].tnsActive = 1; 325 } 326 else { 327 tnsData->dataRaw.tnsShort.subBlockInfo[subBlockNumber].tnsActive = 0; 328 } 329 330 tnsData->dataRaw.tnsShort.subBlockInfo[subBlockNumber].predictionGain = predictionGain; 331 } 332 333 } 334 else{ 335 336 temp = blockType - SHORT_WINDOW; 337 if ( temp != 0 ) { 338 tnsData->dataRaw.tnsLong.subBlockInfo.tnsActive = 0; 339 tnsData->dataRaw.tnsLong.subBlockInfo.predictionGain = 0; 340 } 341 else { 342 tnsData->dataRaw.tnsShort.subBlockInfo[subBlockNumber].tnsActive = 0; 343 tnsData->dataRaw.tnsShort.subBlockInfo[subBlockNumber].predictionGain = 0; 344 } 345 } 346 347 return(0); 348 } 349 350 351 /***************************************************************************** 352 * 353 * function name: TnsSync 354 * description: update tns parameter 355 * 356 *****************************************************************************/ 357 void TnsSync(TNS_DATA *tnsDataDest, 358 const TNS_DATA *tnsDataSrc, 359 const TNS_CONFIG tC, 360 const Word16 subBlockNumber, 361 const Word16 blockType) 362 { 363 TNS_SUBBLOCK_INFO *sbInfoDest; 364 const TNS_SUBBLOCK_INFO *sbInfoSrc; 365 Word32 i, temp; 366 367 temp = blockType - SHORT_WINDOW; 368 if ( temp != 0 ) { 369 sbInfoDest = &tnsDataDest->dataRaw.tnsLong.subBlockInfo; 370 sbInfoSrc = &tnsDataSrc->dataRaw.tnsLong.subBlockInfo; 371 } 372 else { 373 sbInfoDest = &tnsDataDest->dataRaw.tnsShort.subBlockInfo[subBlockNumber]; 374 sbInfoSrc = &tnsDataSrc->dataRaw.tnsShort.subBlockInfo[subBlockNumber]; 375 } 376 377 if (100*abs_s(sbInfoDest->predictionGain - sbInfoSrc->predictionGain) < 378 (3 * sbInfoDest->predictionGain)) { 379 sbInfoDest->tnsActive = sbInfoSrc->tnsActive; 380 for ( i=0; i< tC.maxOrder; i++) { 381 sbInfoDest->parcor[i] = sbInfoSrc->parcor[i]; 382 } 383 } 384 } 385 386 /***************************************************************************** 387 * 388 * function name: TnsEncode 389 * description: do TNS filtering 390 * returns: 0 if success 391 * 392 *****************************************************************************/ 393 Word16 TnsEncode(TNS_INFO* tnsInfo, /*!< tns info structure (modified) */ 394 TNS_DATA* tnsData, /*!< tns data structure (modified) */ 395 Word16 numOfSfb, /*!< number of scale factor bands */ 396 TNS_CONFIG tC, /*!< tns config structure */ 397 Word16 lowPassLine, /*!< lowpass line */ 398 Word32* spectrum, /*!< spectral data (modified) */ 399 Word16 subBlockNumber, /*!< subblock num */ 400 Word16 blockType) /*!< blocktype (long or short) */ 401 { 402 Word32 i; 403 Word32 temp_s; 404 Word32 temp; 405 TNS_SUBBLOCK_INFO *psubBlockInfo; 406 407 temp_s = blockType - SHORT_WINDOW; 408 if ( temp_s != 0) { 409 psubBlockInfo = &tnsData->dataRaw.tnsLong.subBlockInfo; 410 if (psubBlockInfo->tnsActive == 0) { 411 tnsInfo->tnsActive[subBlockNumber] = 0; 412 return(0); 413 } 414 else { 415 416 Parcor2Index(psubBlockInfo->parcor, 417 tnsInfo->coef, 418 tC.maxOrder, 419 tC.coefRes); 420 421 Index2Parcor(tnsInfo->coef, 422 psubBlockInfo->parcor, 423 tC.maxOrder, 424 tC.coefRes); 425 426 for (i=tC.maxOrder - 1; i>=0; i--) { 427 temp = psubBlockInfo->parcor[i] - TNS_PARCOR_THRESH; 428 if ( temp > 0 ) 429 break; 430 temp = psubBlockInfo->parcor[i] + TNS_PARCOR_THRESH; 431 if ( temp < 0 ) 432 break; 433 } 434 tnsInfo->order[subBlockNumber] = i + 1; 435 436 437 tnsInfo->tnsActive[subBlockNumber] = 1; 438 for (i=subBlockNumber+1; i<TRANS_FAC; i++) { 439 tnsInfo->tnsActive[i] = 0; 440 } 441 tnsInfo->coefRes[subBlockNumber] = tC.coefRes; 442 tnsInfo->length[subBlockNumber] = numOfSfb - tC.tnsStartBand; 443 444 445 AnalysisFilterLattice(&(spectrum[tC.tnsStartLine]), 446 (min(tC.tnsStopLine,lowPassLine) - tC.tnsStartLine), 447 psubBlockInfo->parcor, 448 tnsInfo->order[subBlockNumber], 449 &(spectrum[tC.tnsStartLine])); 450 451 } 452 } /* if (blockType!=SHORT_WINDOW) */ 453 else /*short block*/ { 454 psubBlockInfo = &tnsData->dataRaw.tnsShort.subBlockInfo[subBlockNumber]; 455 if (psubBlockInfo->tnsActive == 0) { 456 tnsInfo->tnsActive[subBlockNumber] = 0; 457 return(0); 458 } 459 else { 460 461 Parcor2Index(psubBlockInfo->parcor, 462 &tnsInfo->coef[subBlockNumber*TNS_MAX_ORDER_SHORT], 463 tC.maxOrder, 464 tC.coefRes); 465 466 Index2Parcor(&tnsInfo->coef[subBlockNumber*TNS_MAX_ORDER_SHORT], 467 psubBlockInfo->parcor, 468 tC.maxOrder, 469 tC.coefRes); 470 for (i=(tC.maxOrder - 1); i>=0; i--) { 471 temp = psubBlockInfo->parcor[i] - TNS_PARCOR_THRESH; 472 if ( temp > 0 ) 473 break; 474 475 temp = psubBlockInfo->parcor[i] + TNS_PARCOR_THRESH; 476 if ( temp < 0 ) 477 break; 478 } 479 tnsInfo->order[subBlockNumber] = i + 1; 480 481 tnsInfo->tnsActive[subBlockNumber] = 1; 482 tnsInfo->coefRes[subBlockNumber] = tC.coefRes; 483 tnsInfo->length[subBlockNumber] = numOfSfb - tC.tnsStartBand; 484 485 486 AnalysisFilterLattice(&(spectrum[tC.tnsStartLine]), (tC.tnsStopLine - tC.tnsStartLine), 487 psubBlockInfo->parcor, 488 tnsInfo->order[subBlockNumber], 489 &(spectrum[tC.tnsStartLine])); 490 491 } 492 } 493 494 return(0); 495 } 496 497 498 /***************************************************************************** 499 * 500 * function name: m_pow2_cordic 501 * description: Iterative power function 502 * 503 * Calculates pow(2.0,x-1.0*(scale+1)) with INT_BITS bit precision 504 * using modified cordic algorithm 505 * returns: the result of pow2 506 * 507 *****************************************************************************/ 508 static Word32 m_pow2_cordic(Word32 x, Word16 scale) 509 { 510 Word32 k; 511 512 Word32 accu_y = 0x40000000; 513 accu_y = L_shr(accu_y,scale); 514 515 for(k=1; k<INT_BITS; k++) { 516 const Word32 z = m_log2_table[k]; 517 518 while(L_sub(x,z) >= 0) { 519 520 x = L_sub(x, z); 521 accu_y = L_add(accu_y, (accu_y >> k)); 522 } 523 } 524 return(accu_y); 525 } 526 527 528 /***************************************************************************** 529 * 530 * function name: CalcWeightedSpectrum 531 * description: Calculate weighted spectrum for LPC calculation 532 * 533 *****************************************************************************/ 534 static void CalcWeightedSpectrum(const Word32 spectrum[], /*!< input spectrum */ 535 Word16 weightedSpectrum[], 536 Word32 *sfbEnergy, /*!< sfb energies */ 537 const Word16 *sfbOffset, 538 Word16 lpcStartLine, 539 Word16 lpcStopLine, 540 Word16 lpcStartBand, 541 Word16 lpcStopBand, 542 Word32 *pWork32) 543 { 544 #define INT_BITS_SCAL 1<<(INT_BITS/2) 545 546 Word32 i, sfb, shift; 547 Word32 maxShift; 548 Word32 tmp_s, tmp2_s; 549 Word32 tmp, tmp2; 550 Word32 maxWS; 551 Word32 tnsSfbMean[MAX_SFB]; /* length [lpcStopBand-lpcStartBand] should be sufficient here */ 552 553 maxWS = 0; 554 555 /* calc 1.0*2^-INT_BITS/2/sqrt(en) */ 556 for( sfb = lpcStartBand; sfb < lpcStopBand; sfb++) { 557 558 tmp2 = sfbEnergy[sfb] - 2; 559 if( tmp2 > 0) { 560 tmp = rsqrt(sfbEnergy[sfb], INT_BITS); 561 if(tmp > INT_BITS_SCAL) 562 { 563 shift = norm_l(tmp); 564 tmp = Div_32( INT_BITS_SCAL << shift, tmp << shift ); 565 } 566 else 567 { 568 tmp = 0x7fffffff; 569 } 570 } 571 else { 572 tmp = 0x7fffffff; 573 } 574 tnsSfbMean[sfb] = tmp; 575 } 576 577 /* spread normalized values from sfbs to lines */ 578 sfb = lpcStartBand; 579 tmp = tnsSfbMean[sfb]; 580 for ( i=lpcStartLine; i<lpcStopLine; i++){ 581 tmp_s = sfbOffset[sfb + 1] - i; 582 if ( tmp_s == 0 ) { 583 sfb = sfb + 1; 584 tmp2_s = sfb + 1 - lpcStopBand; 585 if (tmp2_s <= 0) { 586 tmp = tnsSfbMean[sfb]; 587 } 588 } 589 pWork32[i] = tmp; 590 } 591 /*filter down*/ 592 for (i=(lpcStopLine - 2); i>=lpcStartLine; i--){ 593 pWork32[i] = (pWork32[i] + pWork32[i + 1]) >> 1; 594 } 595 /* filter up */ 596 for (i=(lpcStartLine + 1); i<lpcStopLine; i++){ 597 pWork32[i] = (pWork32[i] + pWork32[i - 1]) >> 1; 598 } 599 600 /* weight and normalize */ 601 for (i=lpcStartLine; i<lpcStopLine; i++){ 602 pWork32[i] = MULHIGH(pWork32[i], spectrum[i]); 603 maxWS |= L_abs(pWork32[i]); 604 } 605 maxShift = norm_l(maxWS); 606 607 maxShift = 16 - maxShift; 608 if(maxShift >= 0) 609 { 610 for (i=lpcStartLine; i<lpcStopLine; i++){ 611 weightedSpectrum[i] = pWork32[i] >> maxShift; 612 } 613 } 614 else 615 { 616 maxShift = -maxShift; 617 for (i=lpcStartLine; i<lpcStopLine; i++){ 618 weightedSpectrum[i] = saturate(pWork32[i] << maxShift); 619 } 620 } 621 } 622 623 624 625 626 /***************************************************************************** 627 * 628 * function name: CalcTnsFilter 629 * description: LPC calculation for one TNS filter 630 * returns: prediction gain 631 * input: signal spectrum, acf window, no. of spectral lines, 632 * max. TNS order, ptr. to reflection ocefficients 633 * output: reflection coefficients 634 *(half) window size must be larger than tnsOrder !!* 635 ******************************************************************************/ 636 637 static Word16 CalcTnsFilter(const Word16 *signal, 638 const Word32 window[], 639 Word16 numOfLines, 640 Word16 tnsOrder, 641 Word32 parcor[]) 642 { 643 Word32 parcorWorkBuffer[2*TNS_MAX_ORDER+1]; 644 Word32 predictionGain; 645 Word32 i; 646 Word32 tnsOrderPlus1 = tnsOrder + 1; 647 648 UNUSED(window); 649 650 assert(tnsOrder <= TNS_MAX_ORDER); /* remove asserts later? (btg) */ 651 652 for(i=0;i<tnsOrder;i++) { 653 parcor[i] = 0; 654 } 655 656 AutoCorrelation(signal, parcorWorkBuffer, numOfLines, tnsOrderPlus1); 657 658 /* early return if signal is very low: signal prediction off, with zero parcor coeffs */ 659 if (parcorWorkBuffer[0] == 0) 660 return 0; 661 662 predictionGain = AutoToParcor(parcorWorkBuffer, parcor, tnsOrder); 663 664 return(predictionGain); 665 } 666 667 /***************************************************************************** 668 * 669 * function name: AutoCorrelation 670 * description: calc. autocorrelation (acf) 671 * returns: - 672 * input: input values, no. of input values, no. of acf values 673 * output: acf values 674 * 675 *****************************************************************************/ 676 #ifndef ARMV5E 677 void AutoCorrelation(const Word16 input[], 678 Word32 corr[], 679 Word16 samples, 680 Word16 corrCoeff) { 681 Word32 i, j, isamples; 682 Word32 accu; 683 Word32 scf; 684 685 scf = 10 - 1; 686 687 isamples = samples; 688 /* calc first corrCoef: R[0] = sum { t[i] * t[i] } ; i = 0..N-1 */ 689 accu = 0; 690 for(j=0; j<isamples; j++) { 691 accu = L_add(accu, ((input[j] * input[j]) >> scf)); 692 } 693 corr[0] = accu; 694 695 /* early termination if all corr coeffs are likely going to be zero */ 696 if(corr[0] == 0) return ; 697 698 /* calc all other corrCoef: R[j] = sum { t[i] * t[i+j] } ; i = 0..(N-j-1), j=1..p */ 699 for(i=1; i<corrCoeff; i++) { 700 isamples = isamples - 1; 701 accu = 0; 702 for(j=0; j<isamples; j++) { 703 accu = L_add(accu, ((input[j] * input[j+i]) >> scf)); 704 } 705 corr[i] = accu; 706 } 707 } 708 #endif 709 710 /***************************************************************************** 711 * 712 * function name: AutoToParcor 713 * description: conversion autocorrelation to reflection coefficients 714 * returns: prediction gain 715 * input: <order+1> input values, no. of output values (=order), 716 * ptr. to workbuffer (required size: 2*order) 717 * output: <order> reflection coefficients 718 * 719 *****************************************************************************/ 720 static Word16 AutoToParcor(Word32 workBuffer[], Word32 reflCoeff[], Word16 numOfCoeff) { 721 722 Word32 i, j, shift; 723 Word32 *pWorkBuffer; /* temp pointer */ 724 Word32 predictionGain = 0; 725 Word32 num, denom; 726 Word32 temp, workBuffer0; 727 728 729 num = workBuffer[0]; 730 temp = workBuffer[numOfCoeff]; 731 732 for(i=0; i<numOfCoeff-1; i++) { 733 workBuffer[i + numOfCoeff] = workBuffer[i + 1]; 734 } 735 workBuffer[i + numOfCoeff] = temp; 736 737 for(i=0; i<numOfCoeff; i++) { 738 Word32 refc; 739 740 741 if (workBuffer[0] < L_abs(workBuffer[i + numOfCoeff])) { 742 return 0 ; 743 } 744 shift = norm_l(workBuffer[0]); 745 workBuffer0 = Div_32(1 << shift, workBuffer[0] << shift); 746 /* calculate refc = -workBuffer[numOfCoeff+i] / workBuffer[0]; -1 <= refc < 1 */ 747 refc = L_negate(fixmul(workBuffer[numOfCoeff + i], workBuffer0)); 748 749 reflCoeff[i] = refc; 750 751 pWorkBuffer = &(workBuffer[numOfCoeff]); 752 753 for(j=i; j<numOfCoeff; j++) { 754 Word32 accu1, accu2; 755 accu1 = L_add(pWorkBuffer[j], fixmul(refc, workBuffer[j - i])); 756 accu2 = L_add(workBuffer[j - i], fixmul(refc, pWorkBuffer[j])); 757 pWorkBuffer[j] = accu1; 758 workBuffer[j - i] = accu2; 759 } 760 } 761 762 denom = MULHIGH(workBuffer[0], NORM_COEF); 763 764 if (denom != 0) { 765 Word32 temp; 766 shift = norm_l(denom); 767 temp = Div_32(1 << shift, denom << shift); 768 predictionGain = fixmul(num, temp); 769 } 770 771 return extract_l(predictionGain); 772 } 773 774 775 776 static Word16 Search3(Word32 parcor) 777 { 778 Word32 index = 0; 779 Word32 i; 780 Word32 temp; 781 782 for (i=0;i<8;i++) { 783 temp = L_sub( parcor, tnsCoeff3Borders[i]); 784 if (temp > 0) 785 index=i; 786 } 787 return extract_l(index - 4); 788 } 789 790 static Word16 Search4(Word32 parcor) 791 { 792 Word32 index = 0; 793 Word32 i; 794 Word32 temp; 795 796 797 for (i=0;i<16;i++) { 798 temp = L_sub(parcor, tnsCoeff4Borders[i]); 799 if (temp > 0) 800 index=i; 801 } 802 return extract_l(index - 8); 803 } 804 805 806 807 /***************************************************************************** 808 * 809 * functionname: Parcor2Index 810 * description: quantization index for reflection coefficients 811 * 812 *****************************************************************************/ 813 static void Parcor2Index(const Word32 parcor[], /*!< parcor coefficients */ 814 Word16 index[], /*!< quantized coeff indices */ 815 Word16 order, /*!< filter order */ 816 Word16 bitsPerCoeff) { /*!< quantizer resolution */ 817 Word32 i; 818 Word32 temp; 819 820 for(i=0; i<order; i++) { 821 temp = bitsPerCoeff - 3; 822 if (temp == 0) { 823 index[i] = Search3(parcor[i]); 824 } 825 else { 826 index[i] = Search4(parcor[i]); 827 } 828 } 829 } 830 831 /***************************************************************************** 832 * 833 * functionname: Index2Parcor 834 * description: Inverse quantization for reflection coefficients 835 * 836 *****************************************************************************/ 837 static void Index2Parcor(const Word16 index[], /*!< quantized values */ 838 Word32 parcor[], /*!< ptr. to reflection coefficients (output) */ 839 Word16 order, /*!< no. of coefficients */ 840 Word16 bitsPerCoeff) /*!< quantizer resolution */ 841 { 842 Word32 i; 843 Word32 temp; 844 845 for (i=0; i<order; i++) { 846 temp = bitsPerCoeff - 4; 847 if ( temp == 0 ) { 848 parcor[i] = tnsCoeff4[index[i] + 8]; 849 } 850 else { 851 parcor[i] = tnsCoeff3[index[i] + 4]; 852 } 853 } 854 } 855 856 /***************************************************************************** 857 * 858 * functionname: FIRLattice 859 * description: in place lattice filtering of spectral data 860 * returns: pointer to modified data 861 * 862 *****************************************************************************/ 863 static Word32 FIRLattice(Word16 order, /*!< filter order */ 864 Word32 x, /*!< spectral data */ 865 Word32 *state_par, /*!< filter states */ 866 const Word32 *coef_par) /*!< filter coefficients */ 867 { 868 Word32 i; 869 Word32 accu,tmp,tmpSave; 870 871 x = x >> 1; 872 tmpSave = x; 873 874 for (i=0; i<(order - 1); i++) { 875 876 tmp = L_add(fixmul(coef_par[i], x), state_par[i]); 877 x = L_add(fixmul(coef_par[i], state_par[i]), x); 878 879 state_par[i] = tmpSave; 880 tmpSave = tmp; 881 } 882 883 /* last stage: only need half operations */ 884 accu = fixmul(state_par[order - 1], coef_par[(order - 1)]); 885 state_par[(order - 1)] = tmpSave; 886 887 x = L_add(accu, x); 888 x = L_add(x, x); 889 890 return x; 891 } 892 893 /***************************************************************************** 894 * 895 * functionname: AnalysisFilterLattice 896 * description: filters spectral lines with TNS filter 897 * 898 *****************************************************************************/ 899 static void AnalysisFilterLattice(const Word32 signal[], /*!< input spectrum */ 900 Word16 numOfLines, /*!< no. of lines */ 901 const Word32 parCoeff[],/*!< PARC coefficients */ 902 Word16 order, /*!< filter order */ 903 Word32 output[]) /*!< filtered signal values */ 904 { 905 906 Word32 state_par[TNS_MAX_ORDER]; 907 Word32 j; 908 909 for ( j=0; j<TNS_MAX_ORDER; j++ ) { 910 state_par[j] = 0; 911 } 912 913 for(j=0; j<numOfLines; j++) { 914 output[j] = FIRLattice(order,signal[j],state_par,parCoeff); 915 } 916 } 917 918 /***************************************************************************** 919 * 920 * functionname: ApplyTnsMultTableToRatios 921 * description: Change thresholds according to tns 922 * 923 *****************************************************************************/ 924 void ApplyTnsMultTableToRatios(Word16 startCb, 925 Word16 stopCb, 926 TNS_SUBBLOCK_INFO subInfo, /*!< TNS subblock info */ 927 Word32 *thresholds) /*!< thresholds (modified) */ 928 { 929 Word32 i; 930 if (subInfo.tnsActive) { 931 for(i=startCb; i<stopCb; i++) { 932 /* thresholds[i] * 0.25 */ 933 thresholds[i] = (thresholds[i] >> 2); 934 } 935 } 936 } 937