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 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