⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 tns.c

📁 《Visual C++小波变换技术与工程实践》作者:靳济芳。书上的代码。第3章:语音的去噪处理
💻 C
📖 第 1 页 / 共 2 页
字号:
/*
 * 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 + -