tns.c revision b3f9759c8c9437c45b9a34519ce2ea38a8314d4e
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
40static const Word32 TNS_PARCOR_THRESH = 0x0ccccccd; /* 0.1*(1 << 31) */
41/* Limit bands to > 2.0 kHz */
42static unsigned short tnsMinBandNumberLong[12] =
43{ 11, 12, 15, 16, 17, 20, 25, 26, 24, 28, 30, 31 };
44static 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/**************************************/
50static unsigned short tnsMaxBandsLongMainLow[12] =
51{ 31, 31, 34, 40, 42, 51, 46, 46, 42, 42, 42, 39 };
52
53static unsigned short tnsMaxBandsShortMainLow[12] =
54{ 9, 9, 10, 14, 14, 14, 14, 14, 14, 14, 14, 14 };
55
56
57static 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
66void AutoCorrelation(const Word16 input[], Word32 corr[],
67                            Word16 samples, Word16 corrCoeff);
68static Word16 AutoToParcor(Word32 workBuffer[], Word32 reflCoeff[], Word16 numOfCoeff);
69
70static Word16 CalcTnsFilter(const Word16* signal, const Word32 window[], Word16 numOfLines,
71                                              Word16 tnsOrder, Word32 parcor[]);
72
73
74static void Parcor2Index(const Word32 parcor[], Word16 index[], Word16 order,
75                         Word16 bitsPerCoeff);
76
77static void Index2Parcor(const Word16 index[], Word32 parcor[], Word16 order,
78                         Word16 bitsPerCoeff);
79
80
81
82static 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*/
94static 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*/
135Word16 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*/
202Word16 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*/
268Word32 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*****************************************************************************/
357void 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*****************************************************************************/
393Word16 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*****************************************************************************/
504static 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
607static 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
647void 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*****************************************************************************/
690static 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
746static 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
760static 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*****************************************************************************/
783static 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*****************************************************************************/
807static 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*****************************************************************************/
833static 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*****************************************************************************/
869static 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*****************************************************************************/
894void 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