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