tns.c revision 41050cdb033641ddf26831d9272c0930f7b40a2d
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
38static const Word32 TNS_PARCOR_THRESH = 0x0ccccccd; /* 0.1*(1 << 31) */
39/* Limit bands to > 2.0 kHz */
40static unsigned short tnsMinBandNumberLong[12] =
41{ 11, 12, 15, 16, 17, 20, 25, 26, 24, 28, 30, 31 };
42static 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/**************************************/
48static unsigned short tnsMaxBandsLongMainLow[12] =
49{ 31, 31, 34, 40, 42, 51, 46, 46, 42, 42, 42, 39 };
50
51static unsigned short tnsMaxBandsShortMainLow[12] =
52{ 9, 9, 10, 14, 14, 14, 14, 14, 14, 14, 14, 14 };
53
54
55static 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
64void AutoCorrelation(const Word16 input[], Word32 corr[],
65                            Word16 samples, Word16 corrCoeff);
66static Word16 AutoToParcor(Word32 workBuffer[], Word32 reflCoeff[], Word16 numOfCoeff);
67
68static Word16 CalcTnsFilter(const Word16* signal, const Word32 window[], Word16 numOfLines,
69                                              Word16 tnsOrder, Word32 parcor[]);
70
71
72static void Parcor2Index(const Word32 parcor[], Word16 index[], Word16 order,
73                         Word16 bitsPerCoeff);
74
75static void Index2Parcor(const Word16 index[], Word32 parcor[], Word16 order,
76                         Word16 bitsPerCoeff);
77
78
79
80static 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*/
92static 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*/
133Word16 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*/
200Word16 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*/
266Word32 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*****************************************************************************/
355void 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*****************************************************************************/
391Word16 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*****************************************************************************/
506static 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*****************************************************************************/
532static 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
635static 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
673void 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*****************************************************************************/
716static 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
772static 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
786static 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*****************************************************************************/
809static 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*****************************************************************************/
833static 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*****************************************************************************/
859static 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*****************************************************************************/
895static 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*****************************************************************************/
920void 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