📄 tns.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);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -