• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 */
FreqToBandWithRounding(Word32 freq,Word32 fs,Word16 numOfBands,const Word16 * bandStartOffset)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 */
InitTnsConfigurationLong(Word32 bitRate,Word32 sampleRate,Word16 channels,TNS_CONFIG * tC,PSY_CONFIGURATION_LONG * pC,Word16 active)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 __unused;
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 */
InitTnsConfigurationShort(Word32 bitRate,Word32 sampleRate,Word16 channels,TNS_CONFIG * tC,PSY_CONFIGURATION_SHORT * pC,Word16 active)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 __unused;
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 */
TnsDetect(TNS_DATA * tnsData,TNS_CONFIG tC,Word32 * pScratchTns,const Word16 sfbOffset[],Word32 * spectrum,Word16 subBlockNumber,Word16 blockType,Word32 * sfbEnergy)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 *****************************************************************************/
TnsSync(TNS_DATA * tnsDataDest,const TNS_DATA * tnsDataSrc,const TNS_CONFIG tC,const Word16 subBlockNumber,const Word16 blockType)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 *****************************************************************************/
TnsEncode(TNS_INFO * tnsInfo,TNS_DATA * tnsData,Word16 numOfSfb,TNS_CONFIG tC,Word16 lowPassLine,Word32 * spectrum,Word16 subBlockNumber,Word16 blockType)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: CalcWeightedSpectrum
501 * description: Calculate weighted spectrum for LPC calculation
502 *
503 *****************************************************************************/
CalcWeightedSpectrum(const Word32 spectrum[],Word16 weightedSpectrum[],Word32 * sfbEnergy,const Word16 * sfbOffset,Word16 lpcStartLine,Word16 lpcStopLine,Word16 lpcStartBand,Word16 lpcStopBand,Word32 * pWork32)504 static void CalcWeightedSpectrum(const Word32  spectrum[],         /*!< input spectrum */
505                                  Word16        weightedSpectrum[],
506                                  Word32       *sfbEnergy,          /*!< sfb energies */
507                                  const Word16 *sfbOffset,
508                                  Word16        lpcStartLine,
509                                  Word16        lpcStopLine,
510                                  Word16        lpcStartBand,
511                                  Word16        lpcStopBand,
512                                  Word32       *pWork32)
513 {
514     #define INT_BITS_SCAL 1<<(INT_BITS/2)
515 
516     Word32 i, sfb, shift;
517     Word32 maxShift;
518     Word32 tmp_s, tmp2_s;
519     Word32 tmp, tmp2;
520     Word32 maxWS;
521     Word32 tnsSfbMean[MAX_SFB];    /* length [lpcStopBand-lpcStartBand] should be sufficient here */
522 
523     maxWS = 0;
524 
525     /* calc 1.0*2^-INT_BITS/2/sqrt(en) */
526     for( sfb = lpcStartBand; sfb < lpcStopBand; sfb++) {
527 
528       tmp2 = sfbEnergy[sfb] - 2;
529       if( tmp2 > 0) {
530         tmp = rsqrt(sfbEnergy[sfb], INT_BITS);
531 		if(tmp > INT_BITS_SCAL)
532 		{
533 			shift =  norm_l(tmp);
534 			tmp = Div_32( INT_BITS_SCAL << shift, tmp << shift );
535 		}
536 		else
537 		{
538 			tmp = 0x7fffffff;
539 		}
540       }
541       else {
542         tmp = 0x7fffffff;
543       }
544       tnsSfbMean[sfb] = tmp;
545     }
546 
547     /* spread normalized values from sfbs to lines */
548     sfb = lpcStartBand;
549     tmp = tnsSfbMean[sfb];
550     for ( i=lpcStartLine; i<lpcStopLine; i++){
551       tmp_s = sfbOffset[sfb + 1] - i;
552       if ( tmp_s == 0 ) {
553         sfb = sfb + 1;
554         tmp2_s = sfb + 1 - lpcStopBand;
555         if (tmp2_s <= 0) {
556           tmp = tnsSfbMean[sfb];
557         }
558       }
559       pWork32[i] = tmp;
560     }
561     /*filter down*/
562     for (i=(lpcStopLine - 2); i>=lpcStartLine; i--){
563         pWork32[i] = (pWork32[i] + pWork32[i + 1]) >> 1;
564     }
565     /* filter up */
566     for (i=(lpcStartLine + 1); i<lpcStopLine; i++){
567        pWork32[i] = (pWork32[i] + pWork32[i - 1]) >> 1;
568     }
569 
570     /* weight and normalize */
571     for (i=lpcStartLine; i<lpcStopLine; i++){
572       pWork32[i] = MULHIGH(pWork32[i], spectrum[i]);
573       maxWS |= L_abs(pWork32[i]);
574     }
575     maxShift = norm_l(maxWS);
576 
577 	maxShift = 16 - maxShift;
578     if(maxShift >= 0)
579 	{
580 		for (i=lpcStartLine; i<lpcStopLine; i++){
581 			weightedSpectrum[i] = pWork32[i] >> maxShift;
582 		}
583     }
584 	else
585 	{
586 		maxShift = -maxShift;
587 		for (i=lpcStartLine; i<lpcStopLine; i++){
588 			weightedSpectrum[i] = saturate(pWork32[i] << maxShift);
589 		}
590 	}
591 }
592 
593 
594 
595 
596 /*****************************************************************************
597 *
598 * function name: CalcTnsFilter
599 * description:  LPC calculation for one TNS filter
600 * returns:      prediction gain
601 * input:        signal spectrum, acf window, no. of spectral lines,
602 *                max. TNS order, ptr. to reflection ocefficients
603 * output:       reflection coefficients
604 *(half) window size must be larger than tnsOrder !!*
605 ******************************************************************************/
606 
CalcTnsFilter(const Word16 * signal,const Word32 window[],Word16 numOfLines,Word16 tnsOrder,Word32 parcor[])607 static Word16 CalcTnsFilter(const Word16 *signal,
608                             const Word32 window[],
609                             Word16 numOfLines,
610                             Word16 tnsOrder,
611                             Word32 parcor[])
612 {
613   Word32 parcorWorkBuffer[2*TNS_MAX_ORDER+1];
614   Word32 predictionGain;
615   Word32 i;
616   Word32 tnsOrderPlus1 = tnsOrder + 1;
617 
618   UNUSED(window);
619 
620   assert(tnsOrder <= TNS_MAX_ORDER);      /* remove asserts later? (btg) */
621 
622   for(i=0;i<tnsOrder;i++) {
623     parcor[i] = 0;
624   }
625 
626   AutoCorrelation(signal, parcorWorkBuffer, numOfLines, tnsOrderPlus1);
627 
628   /* early return if signal is very low: signal prediction off, with zero parcor coeffs */
629   if (parcorWorkBuffer[0] == 0)
630     return 0;
631 
632   predictionGain = AutoToParcor(parcorWorkBuffer, parcor, tnsOrder);
633 
634   return(predictionGain);
635 }
636 
637 /*****************************************************************************
638 *
639 * function name: AutoCorrelation
640 * description:  calc. autocorrelation (acf)
641 * returns:      -
642 * input:        input values, no. of input values, no. of acf values
643 * output:       acf values
644 *
645 *****************************************************************************/
646 #ifndef ARMV5E
AutoCorrelation(const Word16 input[],Word32 corr[],Word16 samples,Word16 corrCoeff)647 void AutoCorrelation(const Word16		 input[],
648                             Word32       corr[],
649                             Word16       samples,
650                             Word16       corrCoeff) {
651   Word32 i, j, isamples;
652   Word32 accu;
653   Word32 scf;
654 
655   scf = 10 - 1;
656 
657   isamples = samples;
658   /* calc first corrCoef:  R[0] = sum { t[i] * t[i] } ; i = 0..N-1 */
659   accu = 0;
660   for(j=0; j<isamples; j++) {
661     accu = L_add(accu, ((input[j] * input[j]) >> scf));
662   }
663   corr[0] = accu;
664 
665   /* early termination if all corr coeffs are likely going to be zero */
666   if(corr[0] == 0) return ;
667 
668   /* calc all other corrCoef:  R[j] = sum { t[i] * t[i+j] } ; i = 0..(N-j-1), j=1..p */
669   for(i=1; i<corrCoeff; i++) {
670     isamples = isamples - 1;
671     accu = 0;
672     for(j=0; j<isamples; j++) {
673       accu = L_add(accu, ((input[j] * input[j+i]) >> scf));
674     }
675     corr[i] = accu;
676   }
677 }
678 #endif
679 
680 /*****************************************************************************
681 *
682 * function name: AutoToParcor
683 * description:  conversion autocorrelation to reflection coefficients
684 * returns:      prediction gain
685 * input:        <order+1> input values, no. of output values (=order),
686 *               ptr. to workbuffer (required size: 2*order)
687 * output:       <order> reflection coefficients
688 *
689 *****************************************************************************/
AutoToParcor(Word32 workBuffer[],Word32 reflCoeff[],Word16 numOfCoeff)690 static Word16 AutoToParcor(Word32 workBuffer[], Word32 reflCoeff[], Word16 numOfCoeff) {
691 
692   Word32 i, j, shift;
693   Word32 *pWorkBuffer; /* temp pointer */
694   Word32 predictionGain = 0;
695   Word32 num, denom;
696   Word32 temp, workBuffer0;
697 
698 
699   num = workBuffer[0];
700   temp = workBuffer[numOfCoeff];
701 
702   for(i=0; i<numOfCoeff-1; i++) {
703     workBuffer[i + numOfCoeff] = workBuffer[i + 1];
704   }
705   workBuffer[i + numOfCoeff] = temp;
706 
707   for(i=0; i<numOfCoeff; i++) {
708     Word32 refc;
709 
710 
711     if (workBuffer[0] < L_abs(workBuffer[i + numOfCoeff])) {
712       return 0 ;
713     }
714 	shift = norm_l(workBuffer[0]);
715 	workBuffer0 = Div_32(1 << shift, workBuffer[0] << shift);
716     /* calculate refc = -workBuffer[numOfCoeff+i] / workBuffer[0]; -1 <= refc < 1 */
717 	refc = L_negate(fixmul(workBuffer[numOfCoeff + i], workBuffer0));
718 
719     reflCoeff[i] = refc;
720 
721     pWorkBuffer = &(workBuffer[numOfCoeff]);
722 
723     for(j=i; j<numOfCoeff; j++) {
724       Word32 accu1, accu2;
725       accu1 = L_add(pWorkBuffer[j], fixmul(refc, workBuffer[j - i]));
726       accu2 = L_add(workBuffer[j - i], fixmul(refc, pWorkBuffer[j]));
727       pWorkBuffer[j] = accu1;
728       workBuffer[j - i] = accu2;
729     }
730   }
731 
732   denom = MULHIGH(workBuffer[0], NORM_COEF);
733 
734   if (denom != 0) {
735     Word32 temp;
736 	shift = norm_l(denom);
737 	temp = Div_32(1 << shift, denom << shift);
738     predictionGain = fixmul(num, temp);
739   }
740 
741   return extract_l(predictionGain);
742 }
743 
744 
745 
Search3(Word32 parcor)746 static Word16 Search3(Word32 parcor)
747 {
748   Word32 index = 0;
749   Word32 i;
750   Word32 temp;
751 
752   for (i=0;i<8;i++) {
753     temp = L_sub( parcor, tnsCoeff3Borders[i]);
754     if (temp > 0)
755       index=i;
756   }
757   return extract_l(index - 4);
758 }
759 
Search4(Word32 parcor)760 static Word16 Search4(Word32 parcor)
761 {
762   Word32 index = 0;
763   Word32 i;
764   Word32 temp;
765 
766 
767   for (i=0;i<16;i++) {
768     temp = L_sub(parcor, tnsCoeff4Borders[i]);
769     if (temp > 0)
770       index=i;
771   }
772   return extract_l(index - 8);
773 }
774 
775 
776 
777 /*****************************************************************************
778 *
779 * functionname: Parcor2Index
780 * description:  quantization index for reflection coefficients
781 *
782 *****************************************************************************/
Parcor2Index(const Word32 parcor[],Word16 index[],Word16 order,Word16 bitsPerCoeff)783 static void Parcor2Index(const Word32 parcor[],   /*!< parcor coefficients */
784                          Word16 index[],          /*!< quantized coeff indices */
785                          Word16 order,            /*!< filter order */
786                          Word16 bitsPerCoeff) {   /*!< quantizer resolution */
787   Word32 i;
788   Word32 temp;
789 
790   for(i=0; i<order; i++) {
791     temp = bitsPerCoeff - 3;
792     if (temp == 0) {
793       index[i] = Search3(parcor[i]);
794     }
795     else {
796       index[i] = Search4(parcor[i]);
797     }
798   }
799 }
800 
801 /*****************************************************************************
802 *
803 * functionname: Index2Parcor
804 * description:  Inverse quantization for reflection coefficients
805 *
806 *****************************************************************************/
Index2Parcor(const Word16 index[],Word32 parcor[],Word16 order,Word16 bitsPerCoeff)807 static void Index2Parcor(const Word16 index[],  /*!< quantized values */
808                          Word32 parcor[],       /*!< ptr. to reflection coefficients (output) */
809                          Word16 order,          /*!< no. of coefficients */
810                          Word16 bitsPerCoeff)   /*!< quantizer resolution */
811 {
812   Word32 i;
813   Word32 temp;
814 
815   for (i=0; i<order; i++) {
816     temp = bitsPerCoeff - 4;
817     if ( temp == 0 ) {
818         parcor[i] = tnsCoeff4[index[i] + 8];
819     }
820     else {
821         parcor[i] = tnsCoeff3[index[i] + 4];
822     }
823   }
824 }
825 
826 /*****************************************************************************
827 *
828 * functionname: FIRLattice
829 * description:  in place lattice filtering of spectral data
830 * returns:		pointer to modified data
831 *
832 *****************************************************************************/
FIRLattice(Word16 order,Word32 x,Word32 * state_par,const Word32 * coef_par)833 static Word32 FIRLattice(Word16 order,           /*!< filter order */
834                          Word32 x,               /*!< spectral data */
835                          Word32 *state_par,      /*!< filter states */
836                          const Word32 *coef_par) /*!< filter coefficients */
837 {
838    Word32 i;
839    Word32 accu,tmp,tmpSave;
840 
841    x = x >> 1;
842    tmpSave = x;
843 
844    for (i=0; i<(order - 1); i++) {
845 
846      tmp = L_add(fixmul(coef_par[i], x), state_par[i]);
847      x   = L_add(fixmul(coef_par[i], state_par[i]), x);
848 
849      state_par[i] = tmpSave;
850      tmpSave = tmp;
851   }
852 
853   /* last stage: only need half operations */
854   accu = fixmul(state_par[order - 1], coef_par[(order - 1)]);
855   state_par[(order - 1)] = tmpSave;
856 
857   x = L_add(accu, x);
858   x = L_add(x, x);
859 
860   return x;
861 }
862 
863 /*****************************************************************************
864 *
865 * functionname: AnalysisFilterLattice
866 * description:  filters spectral lines with TNS filter
867 *
868 *****************************************************************************/
AnalysisFilterLattice(const Word32 signal[],Word16 numOfLines,const Word32 parCoeff[],Word16 order,Word32 output[])869 static void AnalysisFilterLattice(const  Word32 signal[],  /*!< input spectrum */
870                                   Word16 numOfLines,       /*!< no. of lines */
871                                   const  Word32 parCoeff[],/*!< PARC coefficients */
872                                   Word16 order,            /*!< filter order */
873                                   Word32 output[])         /*!< filtered signal values */
874 {
875 
876   Word32 state_par[TNS_MAX_ORDER];
877   Word32 j;
878 
879   for ( j=0; j<TNS_MAX_ORDER; j++ ) {
880     state_par[j] = 0;
881   }
882 
883   for(j=0; j<numOfLines; j++) {
884     output[j] = FIRLattice(order,signal[j],state_par,parCoeff);
885   }
886 }
887 
888 /*****************************************************************************
889 *
890 * functionname: ApplyTnsMultTableToRatios
891 * description:  Change thresholds according to tns
892 *
893 *****************************************************************************/
ApplyTnsMultTableToRatios(Word16 startCb,Word16 stopCb,TNS_SUBBLOCK_INFO subInfo,Word32 * thresholds)894 void ApplyTnsMultTableToRatios(Word16 startCb,
895                                Word16 stopCb,
896                                TNS_SUBBLOCK_INFO subInfo, /*!< TNS subblock info */
897                                Word32 *thresholds)        /*!< thresholds (modified) */
898 {
899   Word32 i;
900   if (subInfo.tnsActive) {
901     for(i=startCb; i<stopCb; i++) {
902       /* thresholds[i] * 0.25 */
903       thresholds[i] = (thresholds[i] >> 2);
904     }
905   }
906 }
907