1e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard/*
2e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard ** Copyright 2003-2010, VisualOn, Inc.
3e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard **
4e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard ** Licensed under the Apache License, Version 2.0 (the "License");
5e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard ** you may not use this file except in compliance with the License.
6e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard ** You may obtain a copy of the License at
7e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard **
8e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard **     http://www.apache.org/licenses/LICENSE-2.0
9e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard **
10e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard ** Unless required by applicable law or agreed to in writing, software
11e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard ** distributed under the License is distributed on an "AS IS" BASIS,
12e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard ** See the License for the specific language governing permissions and
14e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard ** limitations under the License.
15e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard */
16e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard/*******************************************************************************
17e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard	File:		tns.c
18e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard
19e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard	Content:	Definition TNS tools functions
20e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard
21956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong*******************************************************************************/
22956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
23e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard#include "basic_op.h"
24e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard#include "oper_32b.h"
25956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong#include "assert.h"
26956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong#include "aac_rom.h"
27956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong#include "psy_const.h"
28956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong#include "tns.h"
29956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong#include "tns_param.h"
30956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong#include "psy_configuration.h"
31956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong#include "tns_func.h"
32956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
3384333e0475bc911adc16417f4ca327c975cf6c36Andreas Huber#define UNUSED(x) (void)(x)
3484333e0475bc911adc16417f4ca327c975cf6c36Andreas Huber
35956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong#define TNS_MODIFY_BEGIN         2600  /* Hz */
36956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong#define RATIO_PATCH_LOWER_BORDER 380   /* Hz */
37e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard#define TNS_GAIN_THRESH			 141   /* 1.41*100 */
38e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard#define NORM_COEF				 0x028f5c28
39e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard
40e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgardstatic const Word32 TNS_PARCOR_THRESH = 0x0ccccccd; /* 0.1*(1 << 31) */
41e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard/* Limit bands to > 2.0 kHz */
42e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgardstatic unsigned short tnsMinBandNumberLong[12] =
43e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard{ 11, 12, 15, 16, 17, 20, 25, 26, 24, 28, 30, 31 };
44e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgardstatic unsigned short tnsMinBandNumberShort[12] =
45e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard{ 2, 2, 2, 3, 3, 4, 6, 6, 8, 10, 10, 12 };
46e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard
47e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard/**************************************/
48e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard/* Main/Low Profile TNS Parameters    */
49e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard/**************************************/
50e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgardstatic unsigned short tnsMaxBandsLongMainLow[12] =
51e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard{ 31, 31, 34, 40, 42, 51, 46, 46, 42, 42, 42, 39 };
52e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard
53e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgardstatic unsigned short tnsMaxBandsShortMainLow[12] =
54956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong{ 9, 9, 10, 14, 14, 14, 14, 14, 14, 14, 14, 14 };
55956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
56956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
57956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dongstatic void CalcWeightedSpectrum(const Word32 spectrum[],
58956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                                 Word16 weightedSpectrum[],
59956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                                 Word32* sfbEnergy,
60956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                                 const Word16* sfbOffset, Word16 lpcStartLine,
61956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                                 Word16 lpcStopLine, Word16 lpcStartBand,Word16 lpcStopBand,
62956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                                 Word32 *pWork32);
63956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
64956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
65956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
66956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dongvoid AutoCorrelation(const Word16 input[], Word32 corr[],
67956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                            Word16 samples, Word16 corrCoeff);
68956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dongstatic Word16 AutoToParcor(Word32 workBuffer[], Word32 reflCoeff[], Word16 numOfCoeff);
69956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
70956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dongstatic Word16 CalcTnsFilter(const Word16* signal, const Word32 window[], Word16 numOfLines,
71956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                                              Word16 tnsOrder, Word32 parcor[]);
72956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
73956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
74956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dongstatic void Parcor2Index(const Word32 parcor[], Word16 index[], Word16 order,
75956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                         Word16 bitsPerCoeff);
76956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
77956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dongstatic void Index2Parcor(const Word16 index[], Word32 parcor[], Word16 order,
78956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                         Word16 bitsPerCoeff);
79956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
80956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
81956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
82956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dongstatic void AnalysisFilterLattice(const Word32 signal[], Word16 numOfLines,
83956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                                  const Word32 parCoeff[], Word16 order,
84956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                                  Word32 output[]);
85956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
86956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
87956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong/**
88956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong*
89956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* function name: FreqToBandWithRounding
90956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* description:  Retrieve index of nearest band border
91956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* returnt:		index
92956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong*
93956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong*/
94956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dongstatic Word16 FreqToBandWithRounding(Word32 freq,                   /*!< frequency in Hertz */
95956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                                     Word32 fs,                     /*!< Sampling frequency in Hertz */
96956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                                     Word16 numOfBands,             /*!< total number of bands */
97956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                                     const Word16 *bandStartOffset) /*!< table of band borders */
98956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong{
99956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  Word32 lineNumber, band;
100956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  Word32 temp, shift;
101956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
102956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  /*  assert(freq >= 0);  */
103956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  shift = norm_l(fs);
104956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  lineNumber = (extract_l(fixmul((bandStartOffset[numOfBands] << 2),Div_32(freq << shift,fs << shift))) + 1) >> 1;
105b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard
106956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  /* freq > fs/2 */
107b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard  temp = lineNumber - bandStartOffset[numOfBands] ;
108956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  if (temp >= 0)
109956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong    return numOfBands;
110956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
111956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  /* find band the line number lies in */
112956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  for (band=0; band<numOfBands; band++) {
113b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard    temp = bandStartOffset[band + 1] - lineNumber;
114956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong    if (temp > 0) break;
115956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  }
116956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
117956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  temp = (lineNumber - bandStartOffset[band]);
118b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard  temp = (temp - (bandStartOffset[band + 1] - lineNumber));
119956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  if ( temp > 0 )
120956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  {
121956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong    band = band + 1;
122956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  }
123956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
124956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  return extract_l(band);
125956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong}
126956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
127956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
128956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong/**
129956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong*
130956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* function name: InitTnsConfigurationLong
131956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* description:  Fill TNS_CONFIG structure with sensible content for long blocks
132956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* returns:		0 if success
133956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong*
134956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong*/
135956c553ab0ce72f8074ad0fda2ffd66a0305700cJames DongWord16 InitTnsConfigurationLong(Word32 bitRate,          /*!< bitrate */
136956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                                Word32 sampleRate,          /*!< Sampling frequency */
137956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                                Word16 channels,            /*!< number of channels */
138956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                                TNS_CONFIG *tC,             /*!< TNS Config struct (modified) */
139956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                                PSY_CONFIGURATION_LONG *pC, /*!< psy config struct */
140956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                                Word16 active)              /*!< tns active flag */
141956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong{
142956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
143956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  Word32 bitratePerChannel;
144b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard  tC->maxOrder     = TNS_MAX_ORDER;
145956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  tC->tnsStartFreq = 1275;
146b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard  tC->coefRes      = 4;
147b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard
148956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  /* to avoid integer division */
149b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard  if ( sub(channels,2) == 0 ) {
150b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard    bitratePerChannel = bitRate >> 1;
151956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  }
152956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  else {
153b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard    bitratePerChannel = bitRate;
154956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  }
155956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
156956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  tC->tnsMaxSfb = tnsMaxBandsLongMainLow[pC->sampRateIdx];
157956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
158b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard  tC->tnsActive = active;
159956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
160956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  /* now calc band and line borders */
161956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  tC->tnsStopBand = min(pC->sfbCnt, tC->tnsMaxSfb);
162b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard  tC->tnsStopLine = pC->sfbOffset[tC->tnsStopBand];
163956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
164956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  tC->tnsStartBand = FreqToBandWithRounding(tC->tnsStartFreq, sampleRate,
165956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                                            pC->sfbCnt, (const Word16*)pC->sfbOffset);
166956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
167956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  tC->tnsModifyBeginCb = FreqToBandWithRounding(TNS_MODIFY_BEGIN,
168956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                                                sampleRate,
169956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                                                pC->sfbCnt,
170956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                                                (const Word16*)pC->sfbOffset);
171956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
172956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  tC->tnsRatioPatchLowestCb = FreqToBandWithRounding(RATIO_PATCH_LOWER_BORDER,
173956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                                                     sampleRate,
174956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                                                     pC->sfbCnt,
175956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                                                     (const Word16*)pC->sfbOffset);
176956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
177956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
178b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard  tC->tnsStartLine = pC->sfbOffset[tC->tnsStartBand];
179956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
180956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  tC->lpcStopBand = tnsMaxBandsLongMainLow[pC->sampRateIdx];
181956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  tC->lpcStopBand = min(tC->lpcStopBand, pC->sfbActive);
182956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
183b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard  tC->lpcStopLine = pC->sfbOffset[tC->lpcStopBand];
184b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard
185956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  tC->lpcStartBand = tnsMinBandNumberLong[pC->sampRateIdx];
186956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
187b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard  tC->lpcStartLine = pC->sfbOffset[tC->lpcStartBand];
188956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
189b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard  tC->threshold = TNS_GAIN_THRESH;
190956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
191956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
192956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  return(0);
193956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong}
194956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
195956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong/**
196956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong*
197956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* function name: InitTnsConfigurationShort
198956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* description:  Fill TNS_CONFIG structure with sensible content for short blocks
199956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* returns:		0 if success
200956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong*
201956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong*/
202956c553ab0ce72f8074ad0fda2ffd66a0305700cJames DongWord16 InitTnsConfigurationShort(Word32 bitRate,              /*!< bitrate */
203956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                                 Word32 sampleRate,           /*!< Sampling frequency */
204956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                                 Word16 channels,             /*!< number of channels */
205956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                                 TNS_CONFIG *tC,              /*!< TNS Config struct (modified) */
206956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                                 PSY_CONFIGURATION_SHORT *pC, /*!< psy config struct */
207956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                                 Word16 active)               /*!< tns active flag */
208956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong{
209956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  Word32 bitratePerChannel;
210956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  tC->maxOrder     = TNS_MAX_ORDER_SHORT;
211956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  tC->tnsStartFreq = 2750;
212b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard  tC->coefRes      = 3;
213b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard
214956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  /* to avoid integer division */
215956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  if ( sub(channels,2) == 0 ) {
216b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard    bitratePerChannel = L_shr(bitRate,1);
217956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  }
218956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  else {
219b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard    bitratePerChannel = bitRate;
220956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  }
221956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
222956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  tC->tnsMaxSfb = tnsMaxBandsShortMainLow[pC->sampRateIdx];
223956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
224b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard  tC->tnsActive = active;
225956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
226956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  /* now calc band and line borders */
227956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  tC->tnsStopBand = min(pC->sfbCnt, tC->tnsMaxSfb);
228b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard  tC->tnsStopLine = pC->sfbOffset[tC->tnsStopBand];
229956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
230956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  tC->tnsStartBand=FreqToBandWithRounding(tC->tnsStartFreq, sampleRate,
231956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                                          pC->sfbCnt, (const Word16*)pC->sfbOffset);
232956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
233956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  tC->tnsModifyBeginCb = FreqToBandWithRounding(TNS_MODIFY_BEGIN,
234956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                                                sampleRate,
235956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                                                pC->sfbCnt,
236956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                                                (const Word16*)pC->sfbOffset);
237956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
238956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  tC->tnsRatioPatchLowestCb = FreqToBandWithRounding(RATIO_PATCH_LOWER_BORDER,
239956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                                                     sampleRate,
240956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                                                     pC->sfbCnt,
241956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                                                     (const Word16*)pC->sfbOffset);
242956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
243956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
244b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard  tC->tnsStartLine = pC->sfbOffset[tC->tnsStartBand];
245956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
246e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard  tC->lpcStopBand = tnsMaxBandsShortMainLow[pC->sampRateIdx];
247956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
248956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  tC->lpcStopBand = min(tC->lpcStopBand, pC->sfbActive);
249956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
250b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard  tC->lpcStopLine = pC->sfbOffset[tC->lpcStopBand];
251956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
252e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard  tC->lpcStartBand = tnsMinBandNumberShort[pC->sampRateIdx];
253956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
254b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard  tC->lpcStartLine = pC->sfbOffset[tC->lpcStartBand];
255956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
256b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard  tC->threshold = TNS_GAIN_THRESH;
257956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
258956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  return(0);
259956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong}
260956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
261956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong/**
262956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong*
263956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* function name: TnsDetect
264b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard* description:  Calculate TNS filter and decide on TNS usage
265956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* returns:		0 if success
266956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong*
267956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong*/
268956c553ab0ce72f8074ad0fda2ffd66a0305700cJames DongWord32 TnsDetect(TNS_DATA* tnsData,        /*!< tns data structure (modified) */
269956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                 TNS_CONFIG tC,            /*!< tns config structure */
270956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                 Word32* pScratchTns,      /*!< pointer to scratch space */
271956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                 const Word16 sfbOffset[], /*!< scalefactor size and table */
272956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                 Word32* spectrum,         /*!< spectral data */
273956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                 Word16 subBlockNumber,    /*!< subblock num */
274956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                 Word16 blockType,         /*!< blocktype (long or short) */
275956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                 Word32 * sfbEnergy)       /*!< sfb-wise energy */
276956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong{
277956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
278956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  Word32  predictionGain;
279956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  Word32  temp;
280956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  Word32* pWork32 = &pScratchTns[subBlockNumber >> 8];
281956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  Word16* pWeightedSpectrum = (Word16 *)&pScratchTns[subBlockNumber >> 8];
282956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
283b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard
284956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  if (tC.tnsActive) {
285956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong    CalcWeightedSpectrum(spectrum,
286956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                         pWeightedSpectrum,
287956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                         sfbEnergy,
288956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                         sfbOffset,
289956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                         tC.lpcStartLine,
290956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                         tC.lpcStopLine,
291956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                         tC.lpcStartBand,
292956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                         tC.lpcStopBand,
293956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                         pWork32);
294956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
295b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard    temp = blockType - SHORT_WINDOW;
296956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong    if ( temp != 0 ) {
297956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong        predictionGain = CalcTnsFilter( &pWeightedSpectrum[tC.lpcStartLine],
298956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                                        tC.acfWindow,
299956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                                        tC.lpcStopLine - tC.lpcStartLine,
300956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                                        tC.maxOrder,
301956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                                        tnsData->dataRaw.tnsLong.subBlockInfo.parcor);
302956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
303956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
304b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard        temp = predictionGain - tC.threshold;
305956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong        if ( temp > 0 ) {
306b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard          tnsData->dataRaw.tnsLong.subBlockInfo.tnsActive = 1;
307956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong        }
308956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong        else {
309b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard          tnsData->dataRaw.tnsLong.subBlockInfo.tnsActive = 0;
310956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong        }
311956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
312b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard        tnsData->dataRaw.tnsLong.subBlockInfo.predictionGain = predictionGain;
313956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong    }
314956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong    else{
315956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
316956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong        predictionGain = CalcTnsFilter( &pWeightedSpectrum[tC.lpcStartLine],
317956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                                        tC.acfWindow,
318956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                                        tC.lpcStopLine - tC.lpcStartLine,
319956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                                        tC.maxOrder,
320956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                                        tnsData->dataRaw.tnsShort.subBlockInfo[subBlockNumber].parcor);
321956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
322b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard        temp = predictionGain - tC.threshold;
323956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong        if ( temp > 0 ) {
324b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard          tnsData->dataRaw.tnsShort.subBlockInfo[subBlockNumber].tnsActive = 1;
325956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong        }
326956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong        else {
327b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard          tnsData->dataRaw.tnsShort.subBlockInfo[subBlockNumber].tnsActive = 0;
328956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong        }
329956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
330b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard        tnsData->dataRaw.tnsShort.subBlockInfo[subBlockNumber].predictionGain = predictionGain;
331956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong    }
332956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
333956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  }
334956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  else{
335956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
336b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard    temp = blockType - SHORT_WINDOW;
337956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong    if ( temp != 0 ) {
338b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard        tnsData->dataRaw.tnsLong.subBlockInfo.tnsActive = 0;
339b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard        tnsData->dataRaw.tnsLong.subBlockInfo.predictionGain = 0;
340956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong    }
341956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong    else {
342b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard        tnsData->dataRaw.tnsShort.subBlockInfo[subBlockNumber].tnsActive = 0;
343b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard        tnsData->dataRaw.tnsShort.subBlockInfo[subBlockNumber].predictionGain = 0;
344956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong    }
345956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  }
346956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
347956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  return(0);
348956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong}
349956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
350956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
351956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong/*****************************************************************************
352956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong*
353956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* function name: TnsSync
354956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* description: update tns parameter
355956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong*
356956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong*****************************************************************************/
357956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dongvoid TnsSync(TNS_DATA *tnsDataDest,
358956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong             const TNS_DATA *tnsDataSrc,
359956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong             const TNS_CONFIG tC,
360956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong             const Word16 subBlockNumber,
361956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong             const Word16 blockType)
362956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong{
363956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong   TNS_SUBBLOCK_INFO *sbInfoDest;
364956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong   const TNS_SUBBLOCK_INFO *sbInfoSrc;
365956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong   Word32 i, temp;
366956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
367b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard   temp =  blockType - SHORT_WINDOW;
368956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong   if ( temp != 0 ) {
369b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard      sbInfoDest = &tnsDataDest->dataRaw.tnsLong.subBlockInfo;
370b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard      sbInfoSrc  = &tnsDataSrc->dataRaw.tnsLong.subBlockInfo;
371956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong   }
372956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong   else {
373b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard      sbInfoDest = &tnsDataDest->dataRaw.tnsShort.subBlockInfo[subBlockNumber];
374b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard      sbInfoSrc  = &tnsDataSrc->dataRaw.tnsShort.subBlockInfo[subBlockNumber];
375956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong   }
376956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
377956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong   if (100*abs_s(sbInfoDest->predictionGain - sbInfoSrc->predictionGain) <
378956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong       (3 * sbInfoDest->predictionGain)) {
379b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard      sbInfoDest->tnsActive = sbInfoSrc->tnsActive;
380956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong      for ( i=0; i< tC.maxOrder; i++) {
381b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard        sbInfoDest->parcor[i] = sbInfoSrc->parcor[i];
382956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong      }
383956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong   }
384956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong}
385956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
386956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong/*****************************************************************************
387956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong*
388956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* function name: TnsEncode
389956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* description: do TNS filtering
390956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* returns:     0 if success
391956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong*
392956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong*****************************************************************************/
393956c553ab0ce72f8074ad0fda2ffd66a0305700cJames DongWord16 TnsEncode(TNS_INFO* tnsInfo,     /*!< tns info structure (modified) */
394956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                 TNS_DATA* tnsData,     /*!< tns data structure (modified) */
395956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                 Word16 numOfSfb,       /*!< number of scale factor bands */
396956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                 TNS_CONFIG tC,         /*!< tns config structure */
397956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                 Word16 lowPassLine,    /*!< lowpass line */
398956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                 Word32* spectrum,      /*!< spectral data (modified) */
399956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                 Word16 subBlockNumber, /*!< subblock num */
400956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                 Word16 blockType)      /*!< blocktype (long or short) */
401956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong{
402956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  Word32 i;
403956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  Word32 temp_s;
404e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard  Word32 temp;
405956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  TNS_SUBBLOCK_INFO *psubBlockInfo;
406956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
407b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard  temp_s = blockType - SHORT_WINDOW;
408b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard  if ( temp_s != 0) {
409e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard    psubBlockInfo = &tnsData->dataRaw.tnsLong.subBlockInfo;
410956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong	if (psubBlockInfo->tnsActive == 0) {
411b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard      tnsInfo->tnsActive[subBlockNumber] = 0;
412956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong      return(0);
413956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong    }
414956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong    else {
415956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
416956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong      Parcor2Index(psubBlockInfo->parcor,
417956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                   tnsInfo->coef,
418956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                   tC.maxOrder,
419956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                   tC.coefRes);
420956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
421956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong      Index2Parcor(tnsInfo->coef,
422956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                   psubBlockInfo->parcor,
423956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                   tC.maxOrder,
424956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                   tC.coefRes);
425956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
426956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong      for (i=tC.maxOrder - 1; i>=0; i--)  {
427b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard        temp = psubBlockInfo->parcor[i] - TNS_PARCOR_THRESH;
428956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong        if ( temp > 0 )
429956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong          break;
430b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard        temp = psubBlockInfo->parcor[i] + TNS_PARCOR_THRESH;
431956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong        if ( temp < 0 )
432956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong          break;
433956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong      }
434b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard      tnsInfo->order[subBlockNumber] = i + 1;
435956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
436956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
437b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard      tnsInfo->tnsActive[subBlockNumber] = 1;
438956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong      for (i=subBlockNumber+1; i<TRANS_FAC; i++) {
439b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard        tnsInfo->tnsActive[i] = 0;
440956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong      }
441b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard      tnsInfo->coefRes[subBlockNumber] = tC.coefRes;
442b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard      tnsInfo->length[subBlockNumber] = numOfSfb - tC.tnsStartBand;
443956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
444956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
445956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong      AnalysisFilterLattice(&(spectrum[tC.tnsStartLine]),
446956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                            (min(tC.tnsStopLine,lowPassLine) - tC.tnsStartLine),
447956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                            psubBlockInfo->parcor,
448956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                            tnsInfo->order[subBlockNumber],
449956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                            &(spectrum[tC.tnsStartLine]));
450956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
451956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong    }
452956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  }     /* if (blockType!=SHORT_WINDOW) */
453b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard  else /*short block*/ {
454e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard    psubBlockInfo = &tnsData->dataRaw.tnsShort.subBlockInfo[subBlockNumber];
455956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong	if (psubBlockInfo->tnsActive == 0) {
456b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard      tnsInfo->tnsActive[subBlockNumber] = 0;
457956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong      return(0);
458956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong    }
459956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong    else {
460956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
461956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong      Parcor2Index(psubBlockInfo->parcor,
462956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                   &tnsInfo->coef[subBlockNumber*TNS_MAX_ORDER_SHORT],
463956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                   tC.maxOrder,
464956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                   tC.coefRes);
465956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
466956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong      Index2Parcor(&tnsInfo->coef[subBlockNumber*TNS_MAX_ORDER_SHORT],
467956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                   psubBlockInfo->parcor,
468956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                   tC.maxOrder,
469956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                   tC.coefRes);
470956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong      for (i=(tC.maxOrder - 1); i>=0; i--)  {
471b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard        temp = psubBlockInfo->parcor[i] - TNS_PARCOR_THRESH;
472956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong         if ( temp > 0 )
473956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong          break;
474956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
475b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard        temp = psubBlockInfo->parcor[i] + TNS_PARCOR_THRESH;
476956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong        if ( temp < 0 )
477956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong          break;
478956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong      }
479b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard      tnsInfo->order[subBlockNumber] = i + 1;
480956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
481b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard      tnsInfo->tnsActive[subBlockNumber] = 1;
482b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard      tnsInfo->coefRes[subBlockNumber] = tC.coefRes;
483b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard      tnsInfo->length[subBlockNumber] = numOfSfb - tC.tnsStartBand;
484956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
485956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
486956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong      AnalysisFilterLattice(&(spectrum[tC.tnsStartLine]), (tC.tnsStopLine - tC.tnsStartLine),
487956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                 psubBlockInfo->parcor,
488956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                 tnsInfo->order[subBlockNumber],
489956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                 &(spectrum[tC.tnsStartLine]));
490956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
491956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong    }
492956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  }
493956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
494956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  return(0);
495956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong}
496956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
497956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
498956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong/*****************************************************************************
499956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong*
500956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* function name: m_pow2_cordic
501956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* description: Iterative power function
502956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong*
503956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong*	Calculates pow(2.0,x-1.0*(scale+1)) with INT_BITS bit precision
504956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong*	using modified cordic algorithm
505956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* returns:     the result of pow2
506956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong*
507956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong*****************************************************************************/
508956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dongstatic Word32 m_pow2_cordic(Word32 x, Word16 scale)
509956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong{
510956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  Word32 k;
511956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
512b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard  Word32 accu_y = 0x40000000;
513956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  accu_y = L_shr(accu_y,scale);
514956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
515956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  for(k=1; k<INT_BITS; k++) {
516b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard    const Word32 z = m_log2_table[k];
517956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
518956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong    while(L_sub(x,z) >= 0) {
519b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard
520956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong      x = L_sub(x, z);
521956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong      accu_y = L_add(accu_y, (accu_y >> k));
522956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong    }
523956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  }
524956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  return(accu_y);
525956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong}
526956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
527956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
528956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong/*****************************************************************************
529956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong*
530956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* function name: CalcWeightedSpectrum
531956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* description: Calculate weighted spectrum for LPC calculation
532956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong*
533956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong*****************************************************************************/
534956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dongstatic void CalcWeightedSpectrum(const Word32  spectrum[],         /*!< input spectrum */
535956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                                 Word16        weightedSpectrum[],
536956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                                 Word32       *sfbEnergy,          /*!< sfb energies */
537956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                                 const Word16 *sfbOffset,
538956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                                 Word16        lpcStartLine,
539956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                                 Word16        lpcStopLine,
540956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                                 Word16        lpcStartBand,
541956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                                 Word16        lpcStopBand,
542956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                                 Word32       *pWork32)
543956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong{
544956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong    #define INT_BITS_SCAL 1<<(INT_BITS/2)
545956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
546956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong    Word32 i, sfb, shift;
547956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong    Word32 maxShift;
548956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong    Word32 tmp_s, tmp2_s;
549956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong    Word32 tmp, tmp2;
550956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong    Word32 maxWS;
551956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong    Word32 tnsSfbMean[MAX_SFB];    /* length [lpcStopBand-lpcStartBand] should be sufficient here */
552956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
553b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard    maxWS = 0;
554b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard
555956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong    /* calc 1.0*2^-INT_BITS/2/sqrt(en) */
556956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong    for( sfb = lpcStartBand; sfb < lpcStopBand; sfb++) {
557956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
558b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard      tmp2 = sfbEnergy[sfb] - 2;
559956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong      if( tmp2 > 0) {
560956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong        tmp = rsqrt(sfbEnergy[sfb], INT_BITS);
561b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard		if(tmp > INT_BITS_SCAL)
562e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard		{
563e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard			shift =  norm_l(tmp);
564b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard			tmp = Div_32( INT_BITS_SCAL << shift, tmp << shift );
565956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong		}
566956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong		else
567956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong		{
568b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard			tmp = 0x7fffffff;
569956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong		}
570956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong      }
571956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong      else {
572b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard        tmp = 0x7fffffff;
573b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard      }
574b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard      tnsSfbMean[sfb] = tmp;
575956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong    }
576956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
577956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong    /* spread normalized values from sfbs to lines */
578b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard    sfb = lpcStartBand;
579b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard    tmp = tnsSfbMean[sfb];
580956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong    for ( i=lpcStartLine; i<lpcStopLine; i++){
581b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard      tmp_s = sfbOffset[sfb + 1] - i;
582956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong      if ( tmp_s == 0 ) {
583956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong        sfb = sfb + 1;
584b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard        tmp2_s = sfb + 1 - lpcStopBand;
585956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong        if (tmp2_s <= 0) {
586b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard          tmp = tnsSfbMean[sfb];
587956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong        }
588956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong      }
589b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard      pWork32[i] = tmp;
590956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong    }
591956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong    /*filter down*/
592956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong    for (i=(lpcStopLine - 2); i>=lpcStartLine; i--){
593956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong        pWork32[i] = (pWork32[i] + pWork32[i + 1]) >> 1;
594956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong    }
595956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong    /* filter up */
596956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong    for (i=(lpcStartLine + 1); i<lpcStopLine; i++){
597956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong       pWork32[i] = (pWork32[i] + pWork32[i - 1]) >> 1;
598956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong    }
599956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
600956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong    /* weight and normalize */
601956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong    for (i=lpcStartLine; i<lpcStopLine; i++){
602b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard      pWork32[i] = MULHIGH(pWork32[i], spectrum[i]);
603b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard      maxWS |= L_abs(pWork32[i]);
604956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong    }
605956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong    maxShift = norm_l(maxWS);
606e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard
607e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard	maxShift = 16 - maxShift;
608e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard    if(maxShift >= 0)
609e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard	{
610e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard		for (i=lpcStartLine; i<lpcStopLine; i++){
611e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard			weightedSpectrum[i] = pWork32[i] >> maxShift;
612e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard		}
613e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard    }
614e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard	else
615e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard	{
616e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard		maxShift = -maxShift;
617e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard		for (i=lpcStartLine; i<lpcStopLine; i++){
618e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard			weightedSpectrum[i] = saturate(pWork32[i] << maxShift);
619e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard		}
620956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong	}
621956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong}
622956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
623956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
624956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
625956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
626956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong/*****************************************************************************
627956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong*
628956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* function name: CalcTnsFilter
629956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* description:  LPC calculation for one TNS filter
630956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* returns:      prediction gain
631956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* input:        signal spectrum, acf window, no. of spectral lines,
632956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong*                max. TNS order, ptr. to reflection ocefficients
633956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* output:       reflection coefficients
634956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong*(half) window size must be larger than tnsOrder !!*
635956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong******************************************************************************/
636956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
637956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dongstatic Word16 CalcTnsFilter(const Word16 *signal,
638956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                            const Word32 window[],
639956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                            Word16 numOfLines,
640956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                            Word16 tnsOrder,
641956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                            Word32 parcor[])
642956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong{
643956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  Word32 parcorWorkBuffer[2*TNS_MAX_ORDER+1];
644956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  Word32 predictionGain;
645956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  Word32 i;
646956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  Word32 tnsOrderPlus1 = tnsOrder + 1;
647956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
64884333e0475bc911adc16417f4ca327c975cf6c36Andreas Huber  UNUSED(window);
64984333e0475bc911adc16417f4ca327c975cf6c36Andreas Huber
650956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  assert(tnsOrder <= TNS_MAX_ORDER);      /* remove asserts later? (btg) */
651956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
652956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  for(i=0;i<tnsOrder;i++) {
653b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard    parcor[i] = 0;
654956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  }
655956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
656956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  AutoCorrelation(signal, parcorWorkBuffer, numOfLines, tnsOrderPlus1);
657956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
658956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  /* early return if signal is very low: signal prediction off, with zero parcor coeffs */
659956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  if (parcorWorkBuffer[0] == 0)
660956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong    return 0;
661956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
662956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  predictionGain = AutoToParcor(parcorWorkBuffer, parcor, tnsOrder);
663956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
664956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  return(predictionGain);
665956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong}
666956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
667956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong/*****************************************************************************
668956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong*
669956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* function name: AutoCorrelation
670956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* description:  calc. autocorrelation (acf)
671956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* returns:      -
672956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* input:        input values, no. of input values, no. of acf values
673956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* output:       acf values
674956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong*
675956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong*****************************************************************************/
676e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard#ifndef ARMV5E
677956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dongvoid AutoCorrelation(const Word16		 input[],
678956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                            Word32       corr[],
679956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                            Word16       samples,
680956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                            Word16       corrCoeff) {
681956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  Word32 i, j, isamples;
682956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  Word32 accu;
683956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  Word32 scf;
684956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
685b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard  scf = 10 - 1;
686e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard
687956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  isamples = samples;
688956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  /* calc first corrCoef:  R[0] = sum { t[i] * t[i] } ; i = 0..N-1 */
689b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard  accu = 0;
690956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  for(j=0; j<isamples; j++) {
691e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard    accu = L_add(accu, ((input[j] * input[j]) >> scf));
692956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  }
693b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard  corr[0] = accu;
694956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
695956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  /* early termination if all corr coeffs are likely going to be zero */
696956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  if(corr[0] == 0) return ;
697956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
698956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  /* calc all other corrCoef:  R[j] = sum { t[i] * t[i+j] } ; i = 0..(N-j-1), j=1..p */
699956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  for(i=1; i<corrCoeff; i++) {
700956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong    isamples = isamples - 1;
701b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard    accu = 0;
702956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong    for(j=0; j<isamples; j++) {
703e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard      accu = L_add(accu, ((input[j] * input[j+i]) >> scf));
704956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong    }
705b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard    corr[i] = accu;
706956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  }
707b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard}
708956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong#endif
709956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
710956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong/*****************************************************************************
711956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong*
712956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* function name: AutoToParcor
713956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* description:  conversion autocorrelation to reflection coefficients
714956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* returns:      prediction gain
715956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* input:        <order+1> input values, no. of output values (=order),
716956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong*               ptr. to workbuffer (required size: 2*order)
717956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* output:       <order> reflection coefficients
718956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong*
719956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong*****************************************************************************/
720956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dongstatic Word16 AutoToParcor(Word32 workBuffer[], Word32 reflCoeff[], Word16 numOfCoeff) {
721956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
722956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  Word32 i, j, shift;
723956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  Word32 *pWorkBuffer; /* temp pointer */
724956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  Word32 predictionGain = 0;
725956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  Word32 num, denom;
726956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  Word32 temp, workBuffer0;
727956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
728b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard
729b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard  num = workBuffer[0];
730b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard  temp = workBuffer[numOfCoeff];
731956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
732956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  for(i=0; i<numOfCoeff-1; i++) {
733b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard    workBuffer[i + numOfCoeff] = workBuffer[i + 1];
734956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  }
735b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard  workBuffer[i + numOfCoeff] = temp;
736b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard
737956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  for(i=0; i<numOfCoeff; i++) {
738956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong    Word32 refc;
739956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
740b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard
741956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong    if (workBuffer[0] < L_abs(workBuffer[i + numOfCoeff])) {
742956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong      return 0 ;
743956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong    }
744e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard	shift = norm_l(workBuffer[0]);
745956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong	workBuffer0 = Div_32(1 << shift, workBuffer[0] << shift);
746956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong    /* calculate refc = -workBuffer[numOfCoeff+i] / workBuffer[0]; -1 <= refc < 1 */
747956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong	refc = L_negate(fixmul(workBuffer[numOfCoeff + i], workBuffer0));
748956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
749b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard    reflCoeff[i] = refc;
750956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
751b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard    pWorkBuffer = &(workBuffer[numOfCoeff]);
752956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
753956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong    for(j=i; j<numOfCoeff; j++) {
754956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong      Word32 accu1, accu2;
755956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong      accu1 = L_add(pWorkBuffer[j], fixmul(refc, workBuffer[j - i]));
756956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong      accu2 = L_add(workBuffer[j - i], fixmul(refc, pWorkBuffer[j]));
757b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard      pWorkBuffer[j] = accu1;
758b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard      workBuffer[j - i] = accu2;
759956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong    }
760956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  }
761956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
762956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  denom = MULHIGH(workBuffer[0], NORM_COEF);
763b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard
764956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  if (denom != 0) {
765e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard    Word32 temp;
766e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard	shift = norm_l(denom);
767956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong	temp = Div_32(1 << shift, denom << shift);
768956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong    predictionGain = fixmul(num, temp);
769956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  }
770956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
771956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  return extract_l(predictionGain);
772956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong}
773956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
774956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
775956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
776956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dongstatic Word16 Search3(Word32 parcor)
777956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong{
778956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  Word32 index = 0;
779956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  Word32 i;
780956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  Word32 temp;
781b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard
782956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  for (i=0;i<8;i++) {
783b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard    temp = L_sub( parcor, tnsCoeff3Borders[i]);
784956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong    if (temp > 0)
785b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard      index=i;
786956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  }
787956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  return extract_l(index - 4);
788956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong}
789956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
790956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dongstatic Word16 Search4(Word32 parcor)
791956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong{
792956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  Word32 index = 0;
793956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  Word32 i;
794956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  Word32 temp;
795b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard
796956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
797956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  for (i=0;i<16;i++) {
798b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard    temp = L_sub(parcor, tnsCoeff4Borders[i]);
799956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong    if (temp > 0)
800b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard      index=i;
801956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  }
802956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  return extract_l(index - 8);
803956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong}
804956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
805956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
806956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
807956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong/*****************************************************************************
808956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong*
809956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* functionname: Parcor2Index
810956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* description:  quantization index for reflection coefficients
811956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong*
812956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong*****************************************************************************/
813956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dongstatic void Parcor2Index(const Word32 parcor[],   /*!< parcor coefficients */
814956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                         Word16 index[],          /*!< quantized coeff indices */
815956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                         Word16 order,            /*!< filter order */
816956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                         Word16 bitsPerCoeff) {   /*!< quantizer resolution */
817956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  Word32 i;
818956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  Word32 temp;
819956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
820956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  for(i=0; i<order; i++) {
821b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard    temp = bitsPerCoeff - 3;
822956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong    if (temp == 0) {
823b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard      index[i] = Search3(parcor[i]);
824b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard    }
825956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong    else {
826b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard      index[i] = Search4(parcor[i]);
827956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong    }
828956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  }
829956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong}
830956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
831956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong/*****************************************************************************
832956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong*
833956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* functionname: Index2Parcor
834956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* description:  Inverse quantization for reflection coefficients
835956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong*
836956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong*****************************************************************************/
837956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dongstatic void Index2Parcor(const Word16 index[],  /*!< quantized values */
838956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                         Word32 parcor[],       /*!< ptr. to reflection coefficients (output) */
839956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                         Word16 order,          /*!< no. of coefficients */
840956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                         Word16 bitsPerCoeff)   /*!< quantizer resolution */
841956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong{
842956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  Word32 i;
843956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  Word32 temp;
844956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
845956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  for (i=0; i<order; i++) {
846b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard    temp = bitsPerCoeff - 4;
847956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong    if ( temp == 0 ) {
848b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard        parcor[i] = tnsCoeff4[index[i] + 8];
849956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong    }
850956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong    else {
851b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard        parcor[i] = tnsCoeff3[index[i] + 4];
852956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong    }
853956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  }
854956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong}
855956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
856956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong/*****************************************************************************
857956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong*
858956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* functionname: FIRLattice
859956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* description:  in place lattice filtering of spectral data
860956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* returns:		pointer to modified data
861956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong*
862956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong*****************************************************************************/
863956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dongstatic Word32 FIRLattice(Word16 order,           /*!< filter order */
864956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                         Word32 x,               /*!< spectral data */
865956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                         Word32 *state_par,      /*!< filter states */
866956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                         const Word32 *coef_par) /*!< filter coefficients */
867956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong{
868956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong   Word32 i;
869956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong   Word32 accu,tmp,tmpSave;
870956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
871956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong   x = x >> 1;
872b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard   tmpSave = x;
873956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
874956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong   for (i=0; i<(order - 1); i++) {
875956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
876956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong     tmp = L_add(fixmul(coef_par[i], x), state_par[i]);
877956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong     x   = L_add(fixmul(coef_par[i], state_par[i]), x);
878956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
879b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard     state_par[i] = tmpSave;
880b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard     tmpSave = tmp;
881956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  }
882956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
883956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  /* last stage: only need half operations */
884956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  accu = fixmul(state_par[order - 1], coef_par[(order - 1)]);
885b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard  state_par[(order - 1)] = tmpSave;
886956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
887956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  x = L_add(accu, x);
888956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  x = L_add(x, x);
889956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
890956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  return x;
891956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong}
892956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
893956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong/*****************************************************************************
894956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong*
895956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* functionname: AnalysisFilterLattice
896956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* description:  filters spectral lines with TNS filter
897956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong*
898956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong*****************************************************************************/
899956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dongstatic void AnalysisFilterLattice(const  Word32 signal[],  /*!< input spectrum */
900956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                                  Word16 numOfLines,       /*!< no. of lines */
901956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                                  const  Word32 parCoeff[],/*!< PARC coefficients */
902956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                                  Word16 order,            /*!< filter order */
903956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                                  Word32 output[])         /*!< filtered signal values */
904956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong{
905956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
906956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  Word32 state_par[TNS_MAX_ORDER];
907956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  Word32 j;
908956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
909956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  for ( j=0; j<TNS_MAX_ORDER; j++ ) {
910b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard    state_par[j] = 0;
911956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  }
912956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
913956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  for(j=0; j<numOfLines; j++) {
914b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard    output[j] = FIRLattice(order,signal[j],state_par,parCoeff);
915956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  }
916956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong}
917956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
918956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong/*****************************************************************************
919956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong*
920956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* functionname: ApplyTnsMultTableToRatios
921956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* description:  Change thresholds according to tns
922956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong*
923956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong*****************************************************************************/
924956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dongvoid ApplyTnsMultTableToRatios(Word16 startCb,
925956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                               Word16 stopCb,
926956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                               TNS_SUBBLOCK_INFO subInfo, /*!< TNS subblock info */
927956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                               Word32 *thresholds)        /*!< thresholds (modified) */
928956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong{
929b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard  Word32 i;
930956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  if (subInfo.tnsActive) {
931956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong    for(i=startCb; i<stopCb; i++) {
932956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong      /* thresholds[i] * 0.25 */
933b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard      thresholds[i] = (thresholds[i] >> 2);
934956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong    }
935956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  }
936956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong}
937