tns.c
资源名称:NETVIDEO.rar [点击查看]
上传用户:sun1608
上传日期:2007-02-02
资源大小:6116k
文件大小:18k
源码类别:
流媒体/Mpeg4/MP4
开发平台:
Visual C++
- /*
- * FAAC - Freeware Advanced Audio Coder
- * Copyright (C) 2001 Menno Bakker
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- * $Id: tns.c,v 1.5 2001/06/04 23:02:24 wmay Exp $
- */
- #include <math.h>
- #include "frame.h"
- #include "coder.h"
- #include "bitstream.h"
- #include "tns.h"
- #include "util.h"
- /***********************************************/
- /* TNS Profile/Frequency Dependent Parameters */
- /***********************************************/
- static unsigned long tnsSupportedSamplingRates[13] =
- { 96000,88200,64000,48000,44100,32000,24000,22050,16000,12000,11025,8000,0 };
- /* Limit bands to > 2.0 kHz */
- static unsigned short tnsMinBandNumberLong[12] =
- { 11, 12, 15, 16, 17, 20, 25, 26, 24, 28, 30, 31 };
- static unsigned short tnsMinBandNumberShort[12] =
- { 2, 2, 2, 3, 3, 4, 6, 6, 8, 10, 10, 12 };
- /**************************************/
- /* Main/Low Profile TNS Parameters */
- /**************************************/
- static unsigned short tnsMaxBandsLongMainLow[12] =
- { 31, 31, 34, 40, 42, 51, 46, 46, 42, 42, 42, 39 };
- static unsigned short tnsMaxBandsShortMainLow[12] =
- { 9, 9, 10, 14, 14, 14, 14, 14, 14, 14, 14, 14 };
- static unsigned short tnsMaxOrderLongMain = 20;
- static unsigned short tnsMaxOrderLongLow = 12;
- static unsigned short tnsMaxOrderShortMainLow = 7;
- /*****************************************************/
- /* InitTns: */
- /*****************************************************/
- void TnsInit(faacEncHandle hEncoder)
- {
- unsigned int channel;
- int fsIndex = hEncoder->sampleRateIdx;
- int profile = hEncoder->config.aacObjectType;
- for (channel = 0; channel < hEncoder->numChannels; channel++) {
- TnsInfo *tnsInfo = &hEncoder->coderInfo[channel].tnsInfo;
- switch( profile ) {
- case MAIN:
- case LTP:
- tnsInfo->tnsMaxBandsLong = tnsMaxBandsLongMainLow[fsIndex];
- tnsInfo->tnsMaxBandsShort = tnsMaxBandsShortMainLow[fsIndex];
- if (hEncoder->config.mpegVersion == 1) { /* MPEG2 */
- tnsInfo->tnsMaxOrderLong = tnsMaxOrderLongMain;
- } else { /* MPEG4 */
- if (fsIndex <= 5) /* fs > 32000Hz */
- tnsInfo->tnsMaxOrderLong = 12;
- else
- tnsInfo->tnsMaxOrderLong = 20;
- }
- tnsInfo->tnsMaxOrderShort = tnsMaxOrderShortMainLow;
- break;
- case LOW :
- tnsInfo->tnsMaxBandsLong = tnsMaxBandsLongMainLow[fsIndex];
- tnsInfo->tnsMaxBandsShort = tnsMaxBandsShortMainLow[fsIndex];
- if (hEncoder->config.mpegVersion == 1) { /* MPEG2 */
- tnsInfo->tnsMaxOrderLong = tnsMaxOrderLongLow;
- } else { /* MPEG4 */
- if (fsIndex <= 5) /* fs > 32000Hz */
- tnsInfo->tnsMaxOrderLong = 12;
- else
- tnsInfo->tnsMaxOrderLong = 20;
- }
- tnsInfo->tnsMaxOrderShort = tnsMaxOrderShortMainLow;
- break;
- }
- tnsInfo->tnsMinBandNumberLong = tnsMinBandNumberLong[fsIndex];
- tnsInfo->tnsMinBandNumberShort = tnsMinBandNumberShort[fsIndex];
- }
- }
- /*****************************************************/
- /* TnsEncode: */
- /*****************************************************/
- void TnsEncode(TnsInfo* tnsInfo, /* TNS info */
- int numberOfBands, /* Number of bands per window */
- int maxSfb, /* max_sfb */
- enum WINDOW_TYPE blockType, /* block type */
- int* sfbOffsetTable, /* Scalefactor band offset table */
- double* spec) /* Spectral data array */
- {
- int numberOfWindows,windowSize;
- int startBand,stopBand,order; /* Bands over which to apply TNS */
- int lengthInBands; /* Length to filter, in bands */
- int w;
- int startIndex,length;
- double gain;
- switch( blockType ) {
- case ONLY_SHORT_WINDOW :
- /* TNS not used for short blocks currently */
- tnsInfo->tnsDataPresent = 0;
- return;
- numberOfWindows = MAX_SHORT_WINDOWS;
- windowSize = BLOCK_LEN_SHORT;
- startBand = tnsInfo->tnsMinBandNumberShort;
- stopBand = numberOfBands;
- lengthInBands = stopBand-startBand;
- order = tnsInfo->tnsMaxOrderShort;
- startBand = min(startBand,tnsInfo->tnsMaxBandsShort);
- stopBand = min(stopBand,tnsInfo->tnsMaxBandsShort);
- break;
- default:
- numberOfWindows = 1;
- windowSize = BLOCK_LEN_SHORT;
- startBand = tnsInfo->tnsMinBandNumberLong;
- stopBand = numberOfBands;
- lengthInBands = stopBand - startBand;
- order = tnsInfo->tnsMaxOrderLong;
- startBand = min(startBand,tnsInfo->tnsMaxBandsLong);
- stopBand = min(stopBand,tnsInfo->tnsMaxBandsLong);
- break;
- }
- /* Make sure that start and stop bands < maxSfb */
- /* Make sure that start and stop bands >= 0 */
- startBand = min(startBand,maxSfb);
- stopBand = min(stopBand,maxSfb);
- startBand = max(startBand,0);
- stopBand = max(stopBand,0);
- tnsInfo->tnsDataPresent = 0; /* default TNS not used */
- /* Perform analysis and filtering for each window */
- for (w=0;w<numberOfWindows;w++) {
- TnsWindowData* windowData = &tnsInfo->windowData[w];
- TnsFilterData* tnsFilter = windowData->tnsFilter;
- double* k = tnsFilter->kCoeffs; /* reflection coeffs */
- double* a = tnsFilter->aCoeffs; /* prediction coeffs */
- windowData->numFilters=0;
- windowData->coefResolution = DEF_TNS_COEFF_RES;
- startIndex = w * windowSize + sfbOffsetTable[startBand];
- length = sfbOffsetTable[stopBand] - sfbOffsetTable[startBand];
- gain = LevinsonDurbin(order,length,&spec[startIndex],k);
- if (gain>DEF_TNS_GAIN_THRESH) { /* Use TNS */
- int truncatedOrder;
- windowData->numFilters++;
- tnsInfo->tnsDataPresent=1;
- tnsFilter->direction = 0;
- tnsFilter->coefCompress = 0;
- tnsFilter->length = lengthInBands;
- QuantizeReflectionCoeffs(order,DEF_TNS_COEFF_RES,k,tnsFilter->index);
- truncatedOrder = TruncateCoeffs(order,DEF_TNS_COEFF_THRESH,k);
- tnsFilter->order = truncatedOrder;
- StepUp(truncatedOrder,k,a); /* Compute predictor coefficients */
- TnsInvFilter(length,&spec[startIndex],tnsFilter); /* Filter */
- }
- }
- }
- /*****************************************************/
- /* TnsEncodeFilterOnly: */
- /* This is a stripped-down version of TnsEncode() */
- /* which performs TNS analysis filtering only */
- /*****************************************************/
- void TnsEncodeFilterOnly(TnsInfo* tnsInfo, /* TNS info */
- int numberOfBands, /* Number of bands per window */
- int maxSfb, /* max_sfb */
- enum WINDOW_TYPE blockType, /* block type */
- int* sfbOffsetTable, /* Scalefactor band offset table */
- double* spec) /* Spectral data array */
- {
- int numberOfWindows,windowSize;
- int startBand,stopBand; /* Bands over which to apply TNS */
- int w;
- int startIndex,length;
- switch( blockType ) {
- case ONLY_SHORT_WINDOW :
- numberOfWindows = MAX_SHORT_WINDOWS;
- windowSize = BLOCK_LEN_SHORT;
- startBand = tnsInfo->tnsMinBandNumberShort;
- stopBand = numberOfBands;
- startBand = min(startBand,tnsInfo->tnsMaxBandsShort);
- stopBand = min(stopBand,tnsInfo->tnsMaxBandsShort);
- break;
- default:
- numberOfWindows = 1;
- windowSize = BLOCK_LEN_LONG;
- startBand = tnsInfo->tnsMinBandNumberLong;
- stopBand = numberOfBands;
- startBand = min(startBand,tnsInfo->tnsMaxBandsLong);
- stopBand = min(stopBand,tnsInfo->tnsMaxBandsLong);
- break;
- }
- /* Make sure that start and stop bands < maxSfb */
- /* Make sure that start and stop bands >= 0 */
- startBand = min(startBand,maxSfb);
- stopBand = min(stopBand,maxSfb);
- startBand = max(startBand,0);
- stopBand = max(stopBand,0);
- /* Perform filtering for each window */
- for(w=0;w<numberOfWindows;w++)
- {
- TnsWindowData* windowData = &tnsInfo->windowData[w];
- TnsFilterData* tnsFilter = windowData->tnsFilter;
- startIndex = w * windowSize + sfbOffsetTable[startBand];
- length = sfbOffsetTable[stopBand] - sfbOffsetTable[startBand];
- if (tnsInfo->tnsDataPresent && windowData->numFilters) { /* Use TNS */
- TnsInvFilter(length,&spec[startIndex],tnsFilter);
- }
- }
- }
- /*****************************************************/
- /* TnsDecodeFilterOnly: */
- /* This is a stripped-down version of TnsEncode() */
- /* which performs TNS synthesis filtering only */
- /*****************************************************/
- void TnsDecodeFilterOnly(TnsInfo* tnsInfo, /* TNS info */
- int numberOfBands, /* Number of bands per window */
- int maxSfb, /* max_sfb */
- enum WINDOW_TYPE blockType, /* block type */
- int* sfbOffsetTable, /* Scalefactor band offset table */
- double* spec) /* Spectral data array */
- {
- int numberOfWindows,windowSize;
- int startBand,stopBand; /* Bands over which to apply TNS */
- int w;
- int startIndex,length;
- switch( blockType ) {
- case ONLY_SHORT_WINDOW :
- numberOfWindows = MAX_SHORT_WINDOWS;
- windowSize = BLOCK_LEN_SHORT;
- startBand = tnsInfo->tnsMinBandNumberShort;
- stopBand = numberOfBands;
- startBand = min(startBand,tnsInfo->tnsMaxBandsShort);
- stopBand = min(stopBand,tnsInfo->tnsMaxBandsShort);
- break;
- default:
- numberOfWindows = 1;
- windowSize = BLOCK_LEN_LONG;
- startBand = tnsInfo->tnsMinBandNumberLong;
- stopBand = numberOfBands;
- startBand = min(startBand,tnsInfo->tnsMaxBandsLong);
- stopBand = min(stopBand,tnsInfo->tnsMaxBandsLong);
- break;
- }
- /* Make sure that start and stop bands < maxSfb */
- /* Make sure that start and stop bands >= 0 */
- startBand = min(startBand,maxSfb);
- stopBand = min(stopBand,maxSfb);
- startBand = max(startBand,0);
- stopBand = max(stopBand,0);
- /* Perform filtering for each window */
- for(w=0;w<numberOfWindows;w++)
- {
- TnsWindowData* windowData = &tnsInfo->windowData[w];
- TnsFilterData* tnsFilter = windowData->tnsFilter;
- startIndex = w * windowSize + sfbOffsetTable[startBand];
- length = sfbOffsetTable[stopBand] - sfbOffsetTable[startBand];
- if (tnsInfo->tnsDataPresent && windowData->numFilters) { /* Use TNS */
- TnsFilter(length,&spec[startIndex],tnsFilter);
- }
- }
- }
- /*****************************************************/
- /* TnsFilter: */
- /* Filter the given spec with specified length */
- /* using the coefficients specified in filter. */
- /* Not that the order and direction are specified */
- /* withing the TNS_FILTER_DATA structure. */
- /*****************************************************/
- static void TnsFilter(int length,double* spec,TnsFilterData* filter)
- {
- int i,j,k=0;
- int order=filter->order;
- double* a=filter->aCoeffs;
- /* Determine loop parameters for given direction */
- if (filter->direction) {
- /* Startup, initial state is zero */
- for (i=length-2;i>(length-1-order);i--) {
- k++;
- for (j=1;j<=k;j++) {
- spec[i]-=spec[i+j]*a[j];
- }
- }
- /* Now filter completely inplace */
- for (i=length-1-order;i>=0;i--) {
- for (j=1;j<=order;j++) {
- spec[i]-=spec[i+j]*a[j];
- }
- }
- } else {
- /* Startup, initial state is zero */
- for (i=1;i<order;i++) {
- for (j=1;j<=i;j++) {
- spec[i]-=spec[i-j]*a[j];
- }
- }
- /* Now filter completely inplace */
- for (i=order;i<length;i++) {
- for (j=1;j<=order;j++) {
- spec[i]-=spec[i-j]*a[j];
- }
- }
- }
- }
- /********************************************************/
- /* TnsInvFilter: */
- /* Inverse filter the given spec with specified */
- /* length using the coefficients specified in filter. */
- /* Not that the order and direction are specified */
- /* withing the TNS_FILTER_DATA structure. */
- /********************************************************/
- static void TnsInvFilter(int length,double* spec,TnsFilterData* filter)
- {
- int i,j,k=0;
- int order=filter->order;
- double* a=filter->aCoeffs;
- double* temp;
- temp = (double *)AllocMemory(length * sizeof (double));
- /* Determine loop parameters for given direction */
- if (filter->direction) {
- /* Startup, initial state is zero */
- temp[length-1]=spec[length-1];
- for (i=length-2;i>(length-1-order);i--) {
- temp[i]=spec[i];
- k++;
- for (j=1;j<=k;j++) {
- spec[i]+=temp[i+j]*a[j];
- }
- }
- /* Now filter the rest */
- for (i=length-1-order;i>=0;i--) {
- temp[i]=spec[i];
- for (j=1;j<=order;j++) {
- spec[i]+=temp[i+j]*a[j];
- }
- }
- } else {
- /* Startup, initial state is zero */
- temp[0]=spec[0];
- for (i=1;i<order;i++) {
- temp[i]=spec[i];
- for (j=1;j<=i;j++) {
- spec[i]+=temp[i-j]*a[j];
- }
- }
- /* Now filter the rest */
- for (i=order;i<length;i++) {
- temp[i]=spec[i];
- for (j=1;j<=order;j++) {
- spec[i]+=temp[i-j]*a[j];
- }
- }
- }
- if (temp) FreeMemory(temp);
- }
- /*****************************************************/
- /* TruncateCoeffs: */
- /* Truncate the given reflection coeffs by zeroing */
- /* coefficients in the tail with absolute value */
- /* less than the specified threshold. Return the */
- /* truncated filter order. */
- /*****************************************************/
- static int TruncateCoeffs(int fOrder,double threshold,double* kArray)
- {
- int i;
- for (i = fOrder; i >= 0; i--) {
- kArray[i] = (fabs(kArray[i])>threshold) ? kArray[i] : 0.0;
- if (kArray[i]!=0.0) return i;
- }
- return 0;
- }
- /*****************************************************/
- /* QuantizeReflectionCoeffs: */
- /* Quantize the given array of reflection coeffs */
- /* to the specified resolution in bits. */
- /*****************************************************/
- static void QuantizeReflectionCoeffs(int fOrder,
- int coeffRes,
- double* kArray,
- int* indexArray)
- {
- double iqfac,iqfac_m;
- int i;
- iqfac = ((1<<(coeffRes-1))-0.5)/(M_PI/2);
- iqfac_m = ((1<<(coeffRes-1))+0.5)/(M_PI/2);
- /* Quantize and inverse quantize */
- for (i=1;i<=fOrder;i++) {
- indexArray[i] = (int)(0.5+(asin(kArray[i])*((kArray[i]>=0)?iqfac:iqfac_m)));
- kArray[i] = sin((double)indexArray[i]/((indexArray[i]>=0)?iqfac:iqfac_m));
- }
- }
- /*****************************************************/
- /* Autocorrelation, */
- /* Compute the autocorrelation function */
- /* estimate for the given data. */
- /*****************************************************/
- static void Autocorrelation(int maxOrder, /* Maximum autocorr order */
- int dataSize, /* Size of the data array */
- double* data, /* Data array */
- double* rArray) /* Autocorrelation array */
- {
- int order,index;
- for (order=0;order<=maxOrder;order++) {
- rArray[order]=0.0;
- for (index=0;index<dataSize;index++) {
- rArray[order]+=data[index]*data[index+order];
- }
- dataSize--;
- }
- }
- /*****************************************************/
- /* LevinsonDurbin: */
- /* Compute the reflection coefficients for the */
- /* given data using LevinsonDurbin recursion. */
- /* Return the prediction gain. */
- /*****************************************************/
- static double LevinsonDurbin(int fOrder, /* Filter order */
- int dataSize, /* Size of the data array */
- double* data, /* Data array */
- double* kArray) /* Reflection coeff array */
- {
- int order,i;
- double signal;
- double error, kTemp; /* Prediction error */
- double aArray1[TNS_MAX_ORDER+1]; /* Predictor coeff array */
- double aArray2[TNS_MAX_ORDER+1]; /* Predictor coeff array 2 */
- double rArray[TNS_MAX_ORDER+1]; /* Autocorrelation coeffs */
- double* aPtr = aArray1; /* Ptr to aArray1 */
- double* aLastPtr = aArray2; /* Ptr to aArray2 */
- double* aTemp;
- /* Compute autocorrelation coefficients */
- Autocorrelation(fOrder,dataSize,data,rArray);
- signal=rArray[0]; /* signal energy */
- /* Set up pointers to current and last iteration */
- /* predictor coefficients. */
- aPtr = aArray1;
- aLastPtr = aArray2;
- /* If there is no signal energy, return */
- if (!signal) {
- kArray[0]=1.0;
- for (order=1;order<=fOrder;order++) {
- kArray[order]=0.0;
- }
- return 0;
- } else {
- /* Set up first iteration */
- kArray[0]=1.0;
- aPtr[0]=1.0; /* Ptr to predictor coeffs, current iteration*/
- aLastPtr[0]=1.0; /* Ptr to predictor coeffs, last iteration */
- error=rArray[0];
- /* Now perform recursion */
- for (order=1;order<=fOrder;order++) {
- kTemp = aLastPtr[0]*rArray[order-0];
- for (i=1;i<order;i++) {
- kTemp += aLastPtr[i]*rArray[order-i];
- }
- kTemp = -kTemp/error;
- kArray[order]=kTemp;
- aPtr[order]=kTemp;
- for (i=1;i<order;i++) {
- aPtr[i] = aLastPtr[i] + kTemp*aLastPtr[order-i];
- }
- error = error * (1 - kTemp*kTemp);
- /* Now make current iteration the last one */
- aTemp=aLastPtr;
- aLastPtr=aPtr; /* Current becomes last */
- aPtr=aTemp; /* Last becomes current */
- }
- return signal/error; /* return the gain */
- }
- }
- /*****************************************************/
- /* StepUp: */
- /* Convert reflection coefficients into */
- /* predictor coefficients. */
- /*****************************************************/
- static void StepUp(int fOrder,double* kArray,double* aArray)
- {
- double aTemp[TNS_MAX_ORDER+2];
- int i,order;
- aArray[0]=1.0;
- aTemp[0]=1.0;
- for (order=1;order<=fOrder;order++) {
- aArray[order]=0.0;
- for (i=1;i<=order;i++) {
- aTemp[i] = aArray[i] + kArray[order]*aArray[order-i];
- }
- for (i=1;i<=order;i++) {
- aArray[i]=aTemp[i];
- }
- }
- }