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 33956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong#define TNS_MODIFY_BEGIN 2600 /* Hz */ 34956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong#define RATIO_PATCH_LOWER_BORDER 380 /* Hz */ 35e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard#define TNS_GAIN_THRESH 141 /* 1.41*100 */ 36e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard#define NORM_COEF 0x028f5c28 37e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard 38e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgardstatic const Word32 TNS_PARCOR_THRESH = 0x0ccccccd; /* 0.1*(1 << 31) */ 39e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard/* Limit bands to > 2.0 kHz */ 40e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgardstatic unsigned short tnsMinBandNumberLong[12] = 41e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard{ 11, 12, 15, 16, 17, 20, 25, 26, 24, 28, 30, 31 }; 42e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgardstatic unsigned short tnsMinBandNumberShort[12] = 43e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard{ 2, 2, 2, 3, 3, 4, 6, 6, 8, 10, 10, 12 }; 44e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard 45e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard/**************************************/ 46e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard/* Main/Low Profile TNS Parameters */ 47e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard/**************************************/ 48e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgardstatic unsigned short tnsMaxBandsLongMainLow[12] = 49e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard{ 31, 31, 34, 40, 42, 51, 46, 46, 42, 42, 42, 39 }; 50e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard 51e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgardstatic unsigned short tnsMaxBandsShortMainLow[12] = 52956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong{ 9, 9, 10, 14, 14, 14, 14, 14, 14, 14, 14, 14 }; 53956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 54956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 55956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dongstatic void CalcWeightedSpectrum(const Word32 spectrum[], 56956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong Word16 weightedSpectrum[], 57956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong Word32* sfbEnergy, 58956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong const Word16* sfbOffset, Word16 lpcStartLine, 59956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong Word16 lpcStopLine, Word16 lpcStartBand,Word16 lpcStopBand, 60956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong Word32 *pWork32); 61956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 62956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 63956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 64956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dongvoid AutoCorrelation(const Word16 input[], Word32 corr[], 65956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong Word16 samples, Word16 corrCoeff); 66956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dongstatic Word16 AutoToParcor(Word32 workBuffer[], Word32 reflCoeff[], Word16 numOfCoeff); 67956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 68956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dongstatic Word16 CalcTnsFilter(const Word16* signal, const Word32 window[], Word16 numOfLines, 69956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong Word16 tnsOrder, Word32 parcor[]); 70956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 71956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 72956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dongstatic void Parcor2Index(const Word32 parcor[], Word16 index[], Word16 order, 73956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong Word16 bitsPerCoeff); 74956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 75956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dongstatic void Index2Parcor(const Word16 index[], Word32 parcor[], Word16 order, 76956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong Word16 bitsPerCoeff); 77956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 78956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 79956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 80956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dongstatic void AnalysisFilterLattice(const Word32 signal[], Word16 numOfLines, 81956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong const Word32 parCoeff[], Word16 order, 82956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong Word32 output[]); 83956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 84956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 85956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong/** 86956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* 87956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* function name: FreqToBandWithRounding 88956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* description: Retrieve index of nearest band border 89956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* returnt: index 90956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* 91956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong*/ 92956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dongstatic Word16 FreqToBandWithRounding(Word32 freq, /*!< frequency in Hertz */ 93956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong Word32 fs, /*!< Sampling frequency in Hertz */ 94956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong Word16 numOfBands, /*!< total number of bands */ 95956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong const Word16 *bandStartOffset) /*!< table of band borders */ 96956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong{ 97956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong Word32 lineNumber, band; 98956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong Word32 temp, shift; 99956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 100956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong /* assert(freq >= 0); */ 101956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong shift = norm_l(fs); 102956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong lineNumber = (extract_l(fixmul((bandStartOffset[numOfBands] << 2),Div_32(freq << shift,fs << shift))) + 1) >> 1; 103b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard 104956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong /* freq > fs/2 */ 105b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard temp = lineNumber - bandStartOffset[numOfBands] ; 106956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong if (temp >= 0) 107956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong return numOfBands; 108956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 109956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong /* find band the line number lies in */ 110956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong for (band=0; band<numOfBands; band++) { 111b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard temp = bandStartOffset[band + 1] - lineNumber; 112956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong if (temp > 0) break; 113956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong } 114956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 115956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong temp = (lineNumber - bandStartOffset[band]); 116b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard temp = (temp - (bandStartOffset[band + 1] - lineNumber)); 117956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong if ( temp > 0 ) 118956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong { 119956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong band = band + 1; 120956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong } 121956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 122956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong return extract_l(band); 123956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong} 124956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 125956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 126956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong/** 127956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* 128956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* function name: InitTnsConfigurationLong 129956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* description: Fill TNS_CONFIG structure with sensible content for long blocks 130956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* returns: 0 if success 131956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* 132956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong*/ 133956c553ab0ce72f8074ad0fda2ffd66a0305700cJames DongWord16 InitTnsConfigurationLong(Word32 bitRate, /*!< bitrate */ 134956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong Word32 sampleRate, /*!< Sampling frequency */ 135956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong Word16 channels, /*!< number of channels */ 136956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong TNS_CONFIG *tC, /*!< TNS Config struct (modified) */ 137956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong PSY_CONFIGURATION_LONG *pC, /*!< psy config struct */ 138956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong Word16 active) /*!< tns active flag */ 139956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong{ 140956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 141956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong Word32 bitratePerChannel; 142b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard tC->maxOrder = TNS_MAX_ORDER; 143956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong tC->tnsStartFreq = 1275; 144b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard tC->coefRes = 4; 145b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard 146956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong /* to avoid integer division */ 147b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard if ( sub(channels,2) == 0 ) { 148b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard bitratePerChannel = bitRate >> 1; 149956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong } 150956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong else { 151b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard bitratePerChannel = bitRate; 152956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong } 153956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 154956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong tC->tnsMaxSfb = tnsMaxBandsLongMainLow[pC->sampRateIdx]; 155956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 156b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard tC->tnsActive = active; 157956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 158956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong /* now calc band and line borders */ 159956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong tC->tnsStopBand = min(pC->sfbCnt, tC->tnsMaxSfb); 160b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard tC->tnsStopLine = pC->sfbOffset[tC->tnsStopBand]; 161956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 162956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong tC->tnsStartBand = FreqToBandWithRounding(tC->tnsStartFreq, sampleRate, 163956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong pC->sfbCnt, (const Word16*)pC->sfbOffset); 164956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 165956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong tC->tnsModifyBeginCb = FreqToBandWithRounding(TNS_MODIFY_BEGIN, 166956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong sampleRate, 167956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong pC->sfbCnt, 168956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong (const Word16*)pC->sfbOffset); 169956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 170956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong tC->tnsRatioPatchLowestCb = FreqToBandWithRounding(RATIO_PATCH_LOWER_BORDER, 171956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong sampleRate, 172956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong pC->sfbCnt, 173956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong (const Word16*)pC->sfbOffset); 174956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 175956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 176b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard tC->tnsStartLine = pC->sfbOffset[tC->tnsStartBand]; 177956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 178956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong tC->lpcStopBand = tnsMaxBandsLongMainLow[pC->sampRateIdx]; 179956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong tC->lpcStopBand = min(tC->lpcStopBand, pC->sfbActive); 180956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 181b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard tC->lpcStopLine = pC->sfbOffset[tC->lpcStopBand]; 182b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard 183956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong tC->lpcStartBand = tnsMinBandNumberLong[pC->sampRateIdx]; 184956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 185b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard tC->lpcStartLine = pC->sfbOffset[tC->lpcStartBand]; 186956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 187b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard tC->threshold = TNS_GAIN_THRESH; 188956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 189956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 190956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong return(0); 191956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong} 192956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 193956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong/** 194956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* 195956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* function name: InitTnsConfigurationShort 196956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* description: Fill TNS_CONFIG structure with sensible content for short blocks 197956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* returns: 0 if success 198956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* 199956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong*/ 200956c553ab0ce72f8074ad0fda2ffd66a0305700cJames DongWord16 InitTnsConfigurationShort(Word32 bitRate, /*!< bitrate */ 201956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong Word32 sampleRate, /*!< Sampling frequency */ 202956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong Word16 channels, /*!< number of channels */ 203956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong TNS_CONFIG *tC, /*!< TNS Config struct (modified) */ 204956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong PSY_CONFIGURATION_SHORT *pC, /*!< psy config struct */ 205956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong Word16 active) /*!< tns active flag */ 206956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong{ 207956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong Word32 bitratePerChannel; 208956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong tC->maxOrder = TNS_MAX_ORDER_SHORT; 209956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong tC->tnsStartFreq = 2750; 210b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard tC->coefRes = 3; 211b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard 212956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong /* to avoid integer division */ 213956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong if ( sub(channels,2) == 0 ) { 214b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard bitratePerChannel = L_shr(bitRate,1); 215956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong } 216956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong else { 217b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard bitratePerChannel = bitRate; 218956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong } 219956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 220956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong tC->tnsMaxSfb = tnsMaxBandsShortMainLow[pC->sampRateIdx]; 221956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 222b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard tC->tnsActive = active; 223956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 224956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong /* now calc band and line borders */ 225956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong tC->tnsStopBand = min(pC->sfbCnt, tC->tnsMaxSfb); 226b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard tC->tnsStopLine = pC->sfbOffset[tC->tnsStopBand]; 227956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 228956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong tC->tnsStartBand=FreqToBandWithRounding(tC->tnsStartFreq, sampleRate, 229956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong pC->sfbCnt, (const Word16*)pC->sfbOffset); 230956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 231956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong tC->tnsModifyBeginCb = FreqToBandWithRounding(TNS_MODIFY_BEGIN, 232956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong sampleRate, 233956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong pC->sfbCnt, 234956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong (const Word16*)pC->sfbOffset); 235956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 236956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong tC->tnsRatioPatchLowestCb = FreqToBandWithRounding(RATIO_PATCH_LOWER_BORDER, 237956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong sampleRate, 238956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong pC->sfbCnt, 239956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong (const Word16*)pC->sfbOffset); 240956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 241956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 242b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard tC->tnsStartLine = pC->sfbOffset[tC->tnsStartBand]; 243956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 244e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard tC->lpcStopBand = tnsMaxBandsShortMainLow[pC->sampRateIdx]; 245956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 246956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong tC->lpcStopBand = min(tC->lpcStopBand, pC->sfbActive); 247956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 248b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard tC->lpcStopLine = pC->sfbOffset[tC->lpcStopBand]; 249956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 250e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard tC->lpcStartBand = tnsMinBandNumberShort[pC->sampRateIdx]; 251956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 252b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard tC->lpcStartLine = pC->sfbOffset[tC->lpcStartBand]; 253956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 254b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard tC->threshold = TNS_GAIN_THRESH; 255956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 256956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong return(0); 257956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong} 258956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 259956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong/** 260956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* 261956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* function name: TnsDetect 262b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard* description: Calculate TNS filter and decide on TNS usage 263956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* returns: 0 if success 264956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* 265956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong*/ 266956c553ab0ce72f8074ad0fda2ffd66a0305700cJames DongWord32 TnsDetect(TNS_DATA* tnsData, /*!< tns data structure (modified) */ 267956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong TNS_CONFIG tC, /*!< tns config structure */ 268956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong Word32* pScratchTns, /*!< pointer to scratch space */ 269956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong const Word16 sfbOffset[], /*!< scalefactor size and table */ 270956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong Word32* spectrum, /*!< spectral data */ 271956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong Word16 subBlockNumber, /*!< subblock num */ 272956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong Word16 blockType, /*!< blocktype (long or short) */ 273956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong Word32 * sfbEnergy) /*!< sfb-wise energy */ 274956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong{ 275956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 276956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong Word32 predictionGain; 277956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong Word32 temp; 278956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong Word32* pWork32 = &pScratchTns[subBlockNumber >> 8]; 279956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong Word16* pWeightedSpectrum = (Word16 *)&pScratchTns[subBlockNumber >> 8]; 280956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 281b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard 282956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong if (tC.tnsActive) { 283956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong CalcWeightedSpectrum(spectrum, 284956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong pWeightedSpectrum, 285956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong sfbEnergy, 286956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong sfbOffset, 287956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong tC.lpcStartLine, 288956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong tC.lpcStopLine, 289956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong tC.lpcStartBand, 290956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong tC.lpcStopBand, 291956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong pWork32); 292956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 293b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard temp = blockType - SHORT_WINDOW; 294956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong if ( temp != 0 ) { 295956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong predictionGain = CalcTnsFilter( &pWeightedSpectrum[tC.lpcStartLine], 296956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong tC.acfWindow, 297956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong tC.lpcStopLine - tC.lpcStartLine, 298956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong tC.maxOrder, 299956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong tnsData->dataRaw.tnsLong.subBlockInfo.parcor); 300956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 301956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 302b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard temp = predictionGain - tC.threshold; 303956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong if ( temp > 0 ) { 304b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard tnsData->dataRaw.tnsLong.subBlockInfo.tnsActive = 1; 305956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong } 306956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong else { 307b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard tnsData->dataRaw.tnsLong.subBlockInfo.tnsActive = 0; 308956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong } 309956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 310b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard tnsData->dataRaw.tnsLong.subBlockInfo.predictionGain = predictionGain; 311956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong } 312956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong else{ 313956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 314956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong predictionGain = CalcTnsFilter( &pWeightedSpectrum[tC.lpcStartLine], 315956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong tC.acfWindow, 316956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong tC.lpcStopLine - tC.lpcStartLine, 317956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong tC.maxOrder, 318956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong tnsData->dataRaw.tnsShort.subBlockInfo[subBlockNumber].parcor); 319956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 320b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard temp = predictionGain - tC.threshold; 321956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong if ( temp > 0 ) { 322b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard tnsData->dataRaw.tnsShort.subBlockInfo[subBlockNumber].tnsActive = 1; 323956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong } 324956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong else { 325b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard tnsData->dataRaw.tnsShort.subBlockInfo[subBlockNumber].tnsActive = 0; 326956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong } 327956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 328b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard tnsData->dataRaw.tnsShort.subBlockInfo[subBlockNumber].predictionGain = predictionGain; 329956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong } 330956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 331956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong } 332956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong else{ 333956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 334b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard temp = blockType - SHORT_WINDOW; 335956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong if ( temp != 0 ) { 336b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard tnsData->dataRaw.tnsLong.subBlockInfo.tnsActive = 0; 337b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard tnsData->dataRaw.tnsLong.subBlockInfo.predictionGain = 0; 338956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong } 339956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong else { 340b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard tnsData->dataRaw.tnsShort.subBlockInfo[subBlockNumber].tnsActive = 0; 341b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard tnsData->dataRaw.tnsShort.subBlockInfo[subBlockNumber].predictionGain = 0; 342956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong } 343956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong } 344956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 345956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong return(0); 346956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong} 347956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 348956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 349956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong/***************************************************************************** 350956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* 351956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* function name: TnsSync 352956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* description: update tns parameter 353956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* 354956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong*****************************************************************************/ 355956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dongvoid TnsSync(TNS_DATA *tnsDataDest, 356956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong const TNS_DATA *tnsDataSrc, 357956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong const TNS_CONFIG tC, 358956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong const Word16 subBlockNumber, 359956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong const Word16 blockType) 360956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong{ 361956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong TNS_SUBBLOCK_INFO *sbInfoDest; 362956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong const TNS_SUBBLOCK_INFO *sbInfoSrc; 363956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong Word32 i, temp; 364956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 365b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard temp = blockType - SHORT_WINDOW; 366956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong if ( temp != 0 ) { 367b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard sbInfoDest = &tnsDataDest->dataRaw.tnsLong.subBlockInfo; 368b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard sbInfoSrc = &tnsDataSrc->dataRaw.tnsLong.subBlockInfo; 369956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong } 370956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong else { 371b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard sbInfoDest = &tnsDataDest->dataRaw.tnsShort.subBlockInfo[subBlockNumber]; 372b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard sbInfoSrc = &tnsDataSrc->dataRaw.tnsShort.subBlockInfo[subBlockNumber]; 373956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong } 374956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 375956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong if (100*abs_s(sbInfoDest->predictionGain - sbInfoSrc->predictionGain) < 376956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong (3 * sbInfoDest->predictionGain)) { 377b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard sbInfoDest->tnsActive = sbInfoSrc->tnsActive; 378956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong for ( i=0; i< tC.maxOrder; i++) { 379b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard sbInfoDest->parcor[i] = sbInfoSrc->parcor[i]; 380956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong } 381956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong } 382956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong} 383956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 384956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong/***************************************************************************** 385956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* 386956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* function name: TnsEncode 387956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* description: do TNS filtering 388956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* returns: 0 if success 389956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* 390956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong*****************************************************************************/ 391956c553ab0ce72f8074ad0fda2ffd66a0305700cJames DongWord16 TnsEncode(TNS_INFO* tnsInfo, /*!< tns info structure (modified) */ 392956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong TNS_DATA* tnsData, /*!< tns data structure (modified) */ 393956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong Word16 numOfSfb, /*!< number of scale factor bands */ 394956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong TNS_CONFIG tC, /*!< tns config structure */ 395956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong Word16 lowPassLine, /*!< lowpass line */ 396956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong Word32* spectrum, /*!< spectral data (modified) */ 397956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong Word16 subBlockNumber, /*!< subblock num */ 398956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong Word16 blockType) /*!< blocktype (long or short) */ 399956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong{ 400956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong Word32 i; 401956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong Word32 temp_s; 402e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard Word32 temp; 403956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong TNS_SUBBLOCK_INFO *psubBlockInfo; 404956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 405b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard temp_s = blockType - SHORT_WINDOW; 406b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard if ( temp_s != 0) { 407e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard psubBlockInfo = &tnsData->dataRaw.tnsLong.subBlockInfo; 408956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong if (psubBlockInfo->tnsActive == 0) { 409b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard tnsInfo->tnsActive[subBlockNumber] = 0; 410956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong return(0); 411956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong } 412956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong else { 413956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 414956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong Parcor2Index(psubBlockInfo->parcor, 415956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong tnsInfo->coef, 416956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong tC.maxOrder, 417956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong tC.coefRes); 418956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 419956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong Index2Parcor(tnsInfo->coef, 420956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong psubBlockInfo->parcor, 421956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong tC.maxOrder, 422956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong tC.coefRes); 423956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 424956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong for (i=tC.maxOrder - 1; i>=0; i--) { 425b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard temp = psubBlockInfo->parcor[i] - TNS_PARCOR_THRESH; 426956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong if ( temp > 0 ) 427956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong break; 428b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard temp = psubBlockInfo->parcor[i] + TNS_PARCOR_THRESH; 429956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong if ( temp < 0 ) 430956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong break; 431956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong } 432b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard tnsInfo->order[subBlockNumber] = i + 1; 433956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 434956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 435b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard tnsInfo->tnsActive[subBlockNumber] = 1; 436956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong for (i=subBlockNumber+1; i<TRANS_FAC; i++) { 437b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard tnsInfo->tnsActive[i] = 0; 438956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong } 439b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard tnsInfo->coefRes[subBlockNumber] = tC.coefRes; 440b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard tnsInfo->length[subBlockNumber] = numOfSfb - tC.tnsStartBand; 441956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 442956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 443956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong AnalysisFilterLattice(&(spectrum[tC.tnsStartLine]), 444956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong (min(tC.tnsStopLine,lowPassLine) - tC.tnsStartLine), 445956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong psubBlockInfo->parcor, 446956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong tnsInfo->order[subBlockNumber], 447956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong &(spectrum[tC.tnsStartLine])); 448956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 449956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong } 450956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong } /* if (blockType!=SHORT_WINDOW) */ 451b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard else /*short block*/ { 452e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard psubBlockInfo = &tnsData->dataRaw.tnsShort.subBlockInfo[subBlockNumber]; 453956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong if (psubBlockInfo->tnsActive == 0) { 454b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard tnsInfo->tnsActive[subBlockNumber] = 0; 455956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong return(0); 456956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong } 457956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong else { 458956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 459956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong Parcor2Index(psubBlockInfo->parcor, 460956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong &tnsInfo->coef[subBlockNumber*TNS_MAX_ORDER_SHORT], 461956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong tC.maxOrder, 462956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong tC.coefRes); 463956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 464956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong Index2Parcor(&tnsInfo->coef[subBlockNumber*TNS_MAX_ORDER_SHORT], 465956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong psubBlockInfo->parcor, 466956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong tC.maxOrder, 467956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong tC.coefRes); 468956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong for (i=(tC.maxOrder - 1); i>=0; i--) { 469b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard temp = psubBlockInfo->parcor[i] - TNS_PARCOR_THRESH; 470956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong if ( temp > 0 ) 471956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong break; 472956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 473b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard temp = psubBlockInfo->parcor[i] + TNS_PARCOR_THRESH; 474956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong if ( temp < 0 ) 475956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong break; 476956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong } 477b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard tnsInfo->order[subBlockNumber] = i + 1; 478956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 479b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard tnsInfo->tnsActive[subBlockNumber] = 1; 480b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard tnsInfo->coefRes[subBlockNumber] = tC.coefRes; 481b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard tnsInfo->length[subBlockNumber] = numOfSfb - tC.tnsStartBand; 482956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 483956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 484956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong AnalysisFilterLattice(&(spectrum[tC.tnsStartLine]), (tC.tnsStopLine - tC.tnsStartLine), 485956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong psubBlockInfo->parcor, 486956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong tnsInfo->order[subBlockNumber], 487956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong &(spectrum[tC.tnsStartLine])); 488956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 489956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong } 490956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong } 491956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 492956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong return(0); 493956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong} 494956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 495956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 496956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong/***************************************************************************** 497956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* 498956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* function name: m_pow2_cordic 499956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* description: Iterative power function 500956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* 501956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* Calculates pow(2.0,x-1.0*(scale+1)) with INT_BITS bit precision 502956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* using modified cordic algorithm 503956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* returns: the result of pow2 504956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* 505956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong*****************************************************************************/ 506956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dongstatic Word32 m_pow2_cordic(Word32 x, Word16 scale) 507956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong{ 508956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong Word32 k; 509956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 510b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard Word32 accu_y = 0x40000000; 511956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong accu_y = L_shr(accu_y,scale); 512956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 513956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong for(k=1; k<INT_BITS; k++) { 514b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard const Word32 z = m_log2_table[k]; 515956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 516956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong while(L_sub(x,z) >= 0) { 517b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard 518956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong x = L_sub(x, z); 519956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong accu_y = L_add(accu_y, (accu_y >> k)); 520956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong } 521956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong } 522956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong return(accu_y); 523956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong} 524956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 525956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 526956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong/***************************************************************************** 527956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* 528956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* function name: CalcWeightedSpectrum 529956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* description: Calculate weighted spectrum for LPC calculation 530956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* 531956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong*****************************************************************************/ 532956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dongstatic void CalcWeightedSpectrum(const Word32 spectrum[], /*!< input spectrum */ 533956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong Word16 weightedSpectrum[], 534956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong Word32 *sfbEnergy, /*!< sfb energies */ 535956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong const Word16 *sfbOffset, 536956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong Word16 lpcStartLine, 537956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong Word16 lpcStopLine, 538956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong Word16 lpcStartBand, 539956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong Word16 lpcStopBand, 540956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong Word32 *pWork32) 541956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong{ 542956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong #define INT_BITS_SCAL 1<<(INT_BITS/2) 543956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 544956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong Word32 i, sfb, shift; 545956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong Word32 maxShift; 546956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong Word32 tmp_s, tmp2_s; 547956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong Word32 tmp, tmp2; 548956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong Word32 maxWS; 549956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong Word32 tnsSfbMean[MAX_SFB]; /* length [lpcStopBand-lpcStartBand] should be sufficient here */ 550956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 551b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard maxWS = 0; 552b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard 553956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong /* calc 1.0*2^-INT_BITS/2/sqrt(en) */ 554956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong for( sfb = lpcStartBand; sfb < lpcStopBand; sfb++) { 555956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 556b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard tmp2 = sfbEnergy[sfb] - 2; 557956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong if( tmp2 > 0) { 558956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong tmp = rsqrt(sfbEnergy[sfb], INT_BITS); 559b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard if(tmp > INT_BITS_SCAL) 560e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard { 561e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard shift = norm_l(tmp); 562b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard tmp = Div_32( INT_BITS_SCAL << shift, tmp << shift ); 563956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong } 564956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong else 565956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong { 566b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard tmp = 0x7fffffff; 567956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong } 568956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong } 569956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong else { 570b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard tmp = 0x7fffffff; 571b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard } 572b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard tnsSfbMean[sfb] = tmp; 573956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong } 574956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 575956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong /* spread normalized values from sfbs to lines */ 576b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard sfb = lpcStartBand; 577b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard tmp = tnsSfbMean[sfb]; 578956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong for ( i=lpcStartLine; i<lpcStopLine; i++){ 579b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard tmp_s = sfbOffset[sfb + 1] - i; 580956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong if ( tmp_s == 0 ) { 581956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong sfb = sfb + 1; 582b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard tmp2_s = sfb + 1 - lpcStopBand; 583956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong if (tmp2_s <= 0) { 584b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard tmp = tnsSfbMean[sfb]; 585956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong } 586956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong } 587b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard pWork32[i] = tmp; 588956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong } 589956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong /*filter down*/ 590956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong for (i=(lpcStopLine - 2); i>=lpcStartLine; i--){ 591956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong pWork32[i] = (pWork32[i] + pWork32[i + 1]) >> 1; 592956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong } 593956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong /* filter up */ 594956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong for (i=(lpcStartLine + 1); i<lpcStopLine; i++){ 595956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong pWork32[i] = (pWork32[i] + pWork32[i - 1]) >> 1; 596956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong } 597956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 598956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong /* weight and normalize */ 599956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong for (i=lpcStartLine; i<lpcStopLine; i++){ 600b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard pWork32[i] = MULHIGH(pWork32[i], spectrum[i]); 601b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard maxWS |= L_abs(pWork32[i]); 602956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong } 603956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong maxShift = norm_l(maxWS); 604e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard 605e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard maxShift = 16 - maxShift; 606e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard if(maxShift >= 0) 607e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard { 608e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard for (i=lpcStartLine; i<lpcStopLine; i++){ 609e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard weightedSpectrum[i] = pWork32[i] >> maxShift; 610e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard } 611e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard } 612e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard else 613e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard { 614e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard maxShift = -maxShift; 615e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard for (i=lpcStartLine; i<lpcStopLine; i++){ 616e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard weightedSpectrum[i] = saturate(pWork32[i] << maxShift); 617e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard } 618956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong } 619956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong} 620956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 621956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 622956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 623956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 624956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong/***************************************************************************** 625956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* 626956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* function name: CalcTnsFilter 627956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* description: LPC calculation for one TNS filter 628956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* returns: prediction gain 629956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* input: signal spectrum, acf window, no. of spectral lines, 630956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* max. TNS order, ptr. to reflection ocefficients 631956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* output: reflection coefficients 632956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong*(half) window size must be larger than tnsOrder !!* 633956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong******************************************************************************/ 634956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 635956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dongstatic Word16 CalcTnsFilter(const Word16 *signal, 636956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong const Word32 window[], 637956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong Word16 numOfLines, 638956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong Word16 tnsOrder, 639956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong Word32 parcor[]) 640956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong{ 641956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong Word32 parcorWorkBuffer[2*TNS_MAX_ORDER+1]; 642956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong Word32 predictionGain; 643956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong Word32 i; 644956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong Word32 tnsOrderPlus1 = tnsOrder + 1; 645956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 646956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong assert(tnsOrder <= TNS_MAX_ORDER); /* remove asserts later? (btg) */ 647956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 648956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong for(i=0;i<tnsOrder;i++) { 649b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard parcor[i] = 0; 650956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong } 651956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 652956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong AutoCorrelation(signal, parcorWorkBuffer, numOfLines, tnsOrderPlus1); 653956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 654956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong /* early return if signal is very low: signal prediction off, with zero parcor coeffs */ 655956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong if (parcorWorkBuffer[0] == 0) 656956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong return 0; 657956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 658956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong predictionGain = AutoToParcor(parcorWorkBuffer, parcor, tnsOrder); 659956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 660956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong return(predictionGain); 661956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong} 662956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 663956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong/***************************************************************************** 664956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* 665956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* function name: AutoCorrelation 666956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* description: calc. autocorrelation (acf) 667956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* returns: - 668956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* input: input values, no. of input values, no. of acf values 669956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* output: acf values 670956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* 671956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong*****************************************************************************/ 672e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard#ifndef ARMV5E 673956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dongvoid AutoCorrelation(const Word16 input[], 674956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong Word32 corr[], 675956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong Word16 samples, 676956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong Word16 corrCoeff) { 677956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong Word32 i, j, isamples; 678956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong Word32 accu; 679956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong Word32 scf; 680956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 681b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard scf = 10 - 1; 682e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard 683956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong isamples = samples; 684956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong /* calc first corrCoef: R[0] = sum { t[i] * t[i] } ; i = 0..N-1 */ 685b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard accu = 0; 686956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong for(j=0; j<isamples; j++) { 687e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard accu = L_add(accu, ((input[j] * input[j]) >> scf)); 688956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong } 689b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard corr[0] = accu; 690956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 691956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong /* early termination if all corr coeffs are likely going to be zero */ 692956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong if(corr[0] == 0) return ; 693956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 694956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong /* calc all other corrCoef: R[j] = sum { t[i] * t[i+j] } ; i = 0..(N-j-1), j=1..p */ 695956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong for(i=1; i<corrCoeff; i++) { 696956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong isamples = isamples - 1; 697b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard accu = 0; 698956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong for(j=0; j<isamples; j++) { 699e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard accu = L_add(accu, ((input[j] * input[j+i]) >> scf)); 700956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong } 701b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard corr[i] = accu; 702956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong } 703b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard} 704956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong#endif 705956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 706956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong/***************************************************************************** 707956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* 708956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* function name: AutoToParcor 709956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* description: conversion autocorrelation to reflection coefficients 710956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* returns: prediction gain 711956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* input: <order+1> input values, no. of output values (=order), 712956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* ptr. to workbuffer (required size: 2*order) 713956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* output: <order> reflection coefficients 714956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* 715956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong*****************************************************************************/ 716956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dongstatic Word16 AutoToParcor(Word32 workBuffer[], Word32 reflCoeff[], Word16 numOfCoeff) { 717956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 718956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong Word32 i, j, shift; 719956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong Word32 *pWorkBuffer; /* temp pointer */ 720956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong Word32 predictionGain = 0; 721956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong Word32 num, denom; 722956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong Word32 temp, workBuffer0; 723956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 724b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard 725b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard num = workBuffer[0]; 726b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard temp = workBuffer[numOfCoeff]; 727956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 728956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong for(i=0; i<numOfCoeff-1; i++) { 729b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard workBuffer[i + numOfCoeff] = workBuffer[i + 1]; 730956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong } 731b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard workBuffer[i + numOfCoeff] = temp; 732b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard 733956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong for(i=0; i<numOfCoeff; i++) { 734956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong Word32 refc; 735956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 736b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard 737956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong if (workBuffer[0] < L_abs(workBuffer[i + numOfCoeff])) { 738956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong return 0 ; 739956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong } 740e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard shift = norm_l(workBuffer[0]); 741956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong workBuffer0 = Div_32(1 << shift, workBuffer[0] << shift); 742956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong /* calculate refc = -workBuffer[numOfCoeff+i] / workBuffer[0]; -1 <= refc < 1 */ 743956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong refc = L_negate(fixmul(workBuffer[numOfCoeff + i], workBuffer0)); 744956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 745b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard reflCoeff[i] = refc; 746956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 747b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard pWorkBuffer = &(workBuffer[numOfCoeff]); 748956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 749956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong for(j=i; j<numOfCoeff; j++) { 750956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong Word32 accu1, accu2; 751956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong accu1 = L_add(pWorkBuffer[j], fixmul(refc, workBuffer[j - i])); 752956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong accu2 = L_add(workBuffer[j - i], fixmul(refc, pWorkBuffer[j])); 753b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard pWorkBuffer[j] = accu1; 754b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard workBuffer[j - i] = accu2; 755956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong } 756956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong } 757956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 758956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong denom = MULHIGH(workBuffer[0], NORM_COEF); 759b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard 760956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong if (denom != 0) { 761e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard Word32 temp; 762e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard shift = norm_l(denom); 763956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong temp = Div_32(1 << shift, denom << shift); 764956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong predictionGain = fixmul(num, temp); 765956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong } 766956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 767956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong return extract_l(predictionGain); 768956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong} 769956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 770956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 771956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 772956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dongstatic Word16 Search3(Word32 parcor) 773956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong{ 774956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong Word32 index = 0; 775956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong Word32 i; 776956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong Word32 temp; 777b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard 778956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong for (i=0;i<8;i++) { 779b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard temp = L_sub( parcor, tnsCoeff3Borders[i]); 780956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong if (temp > 0) 781b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard index=i; 782956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong } 783956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong return extract_l(index - 4); 784956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong} 785956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 786956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dongstatic Word16 Search4(Word32 parcor) 787956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong{ 788956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong Word32 index = 0; 789956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong Word32 i; 790956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong Word32 temp; 791b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard 792956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 793956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong for (i=0;i<16;i++) { 794b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard temp = L_sub(parcor, tnsCoeff4Borders[i]); 795956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong if (temp > 0) 796b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard index=i; 797956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong } 798956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong return extract_l(index - 8); 799956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong} 800956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 801956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 802956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 803956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong/***************************************************************************** 804956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* 805956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* functionname: Parcor2Index 806956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* description: quantization index for reflection coefficients 807956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* 808956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong*****************************************************************************/ 809956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dongstatic void Parcor2Index(const Word32 parcor[], /*!< parcor coefficients */ 810956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong Word16 index[], /*!< quantized coeff indices */ 811956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong Word16 order, /*!< filter order */ 812956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong Word16 bitsPerCoeff) { /*!< quantizer resolution */ 813956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong Word32 i; 814956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong Word32 temp; 815956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 816956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong for(i=0; i<order; i++) { 817b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard temp = bitsPerCoeff - 3; 818956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong if (temp == 0) { 819b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard index[i] = Search3(parcor[i]); 820b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard } 821956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong else { 822b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard index[i] = Search4(parcor[i]); 823956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong } 824956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong } 825956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong} 826956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 827956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong/***************************************************************************** 828956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* 829956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* functionname: Index2Parcor 830956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* description: Inverse quantization for reflection coefficients 831956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* 832956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong*****************************************************************************/ 833956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dongstatic void Index2Parcor(const Word16 index[], /*!< quantized values */ 834956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong Word32 parcor[], /*!< ptr. to reflection coefficients (output) */ 835956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong Word16 order, /*!< no. of coefficients */ 836956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong Word16 bitsPerCoeff) /*!< quantizer resolution */ 837956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong{ 838956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong Word32 i; 839956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong Word32 temp; 840956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 841956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong for (i=0; i<order; i++) { 842b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard temp = bitsPerCoeff - 4; 843956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong if ( temp == 0 ) { 844b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard parcor[i] = tnsCoeff4[index[i] + 8]; 845956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong } 846956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong else { 847b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard parcor[i] = tnsCoeff3[index[i] + 4]; 848956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong } 849956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong } 850956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong} 851956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 852956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong/***************************************************************************** 853956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* 854956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* functionname: FIRLattice 855956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* description: in place lattice filtering of spectral data 856956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* returns: pointer to modified data 857956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* 858956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong*****************************************************************************/ 859956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dongstatic Word32 FIRLattice(Word16 order, /*!< filter order */ 860956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong Word32 x, /*!< spectral data */ 861956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong Word32 *state_par, /*!< filter states */ 862956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong const Word32 *coef_par) /*!< filter coefficients */ 863956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong{ 864956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong Word32 i; 865956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong Word32 accu,tmp,tmpSave; 866956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 867956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong x = x >> 1; 868b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard tmpSave = x; 869956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 870956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong for (i=0; i<(order - 1); i++) { 871956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 872956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong tmp = L_add(fixmul(coef_par[i], x), state_par[i]); 873956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong x = L_add(fixmul(coef_par[i], state_par[i]), x); 874956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 875b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard state_par[i] = tmpSave; 876b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard tmpSave = tmp; 877956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong } 878956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 879956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong /* last stage: only need half operations */ 880956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong accu = fixmul(state_par[order - 1], coef_par[(order - 1)]); 881b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard state_par[(order - 1)] = tmpSave; 882956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 883956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong x = L_add(accu, x); 884956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong x = L_add(x, x); 885956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 886956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong return x; 887956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong} 888956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 889956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong/***************************************************************************** 890956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* 891956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* functionname: AnalysisFilterLattice 892956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* description: filters spectral lines with TNS filter 893956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* 894956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong*****************************************************************************/ 895956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dongstatic void AnalysisFilterLattice(const Word32 signal[], /*!< input spectrum */ 896956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong Word16 numOfLines, /*!< no. of lines */ 897956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong const Word32 parCoeff[],/*!< PARC coefficients */ 898956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong Word16 order, /*!< filter order */ 899956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong Word32 output[]) /*!< filtered signal values */ 900956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong{ 901956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 902956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong Word32 state_par[TNS_MAX_ORDER]; 903956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong Word32 j; 904956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 905956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong for ( j=0; j<TNS_MAX_ORDER; j++ ) { 906b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard state_par[j] = 0; 907956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong } 908956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 909956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong for(j=0; j<numOfLines; j++) { 910b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard output[j] = FIRLattice(order,signal[j],state_par,parCoeff); 911956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong } 912956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong} 913956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 914956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong/***************************************************************************** 915956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* 916956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* functionname: ApplyTnsMultTableToRatios 917956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* description: Change thresholds according to tns 918956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* 919956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong*****************************************************************************/ 920956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dongvoid ApplyTnsMultTableToRatios(Word16 startCb, 921956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong Word16 stopCb, 922956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong TNS_SUBBLOCK_INFO subInfo, /*!< TNS subblock info */ 923956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong Word32 *thresholds) /*!< thresholds (modified) */ 924956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong{ 925b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard Word32 i; 926956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong if (subInfo.tnsActive) { 927956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong for(i=startCb; i<stopCb; i++) { 928956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong /* thresholds[i] * 0.25 */ 929b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard thresholds[i] = (thresholds[i] >> 2); 930956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong } 931956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong } 932956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong} 933