Home | History | Annotate | Download | only in src
      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