📄 tns.c
字号:
/**********************************************************************This software module was originally developed by Texas Instrumentsand edited by in the course ofdevelopment of the MPEG-2 NBC/MPEG-4 Audio standardISO/IEC 13818-7, 14496-1,2 and 3. This software module is animplementation of a part of one or more MPEG-2 NBC/MPEG-4 Audio toolsas specified by the MPEG-2 NBC/MPEG-4 Audio standard. ISO/IEC givesusers of the MPEG-2 NBC/MPEG-4 Audio standards free license to thissoftware module or modifications thereof for use in hardware orsoftware products claiming conformance to the MPEG-2 NBC/ MPEG-4 Audiostandards. Those intending to use this software module in hardware orsoftware products are advised that this use may infringe existingpatents. The original developer of this software module and his/hercompany, the subsequent editors and their companies, and ISO/IEC haveno liability for use of this software module or modifications thereofin an implementation. Copyright is not released for non MPEG-2NBC/MPEG-4 Audio conforming products. The original developer retainsfull right to use the code for his/her own purpose, assign or donatethe code to a third party and to inhibit third party from using thecode for non MPEG-2 NBC/MPEG-4 Audio conforming products. Thiscopyright notice must be included in all copies or derivative works.Copyright (c) 1997.**********************************************************************//* * $Id: tns.c,v 1.1 2006/02/23 14:30:26 kevin-fu 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;/*************************//* Function prototypes *//*************************/static void Autocorrelation(int maxOrder, /* Maximum autocorr order */ int dataSize, /* Size of the data array */ double* data, /* Data array */ double* rArray); /* Autocorrelation array */static double LevinsonDurbin(int maxOrder, /* Maximum filter order */ int dataSize, /* Size of the data array */ double* data, /* Data array */ double* kArray); /* Reflection coeff array */static void StepUp(int fOrder, double* kArray, double* aArray);static void QuantizeReflectionCoeffs(int fOrder,int coeffRes,double* rArray,int* indexArray);static int TruncateCoeffs(int fOrder,double threshold,double* kArray);static void TnsFilter(int length,double* spec,TnsFilterData* filter);static void TnsInvFilter(int length,double* spec,TnsFilterData* filter);/*****************************************************//* 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:
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -