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

📄 enc_tf.c

📁 AAC音频解码算法程序
💻 C
📖 第 1 页 / 共 2 页
字号:

#include <math.h>
#include <stdlib.h>
#include <memory.h>
#include "aacenc.h"
#include "bitstream.h"
#include "interface.h" 
#include "enc.h"
#include "block.h"
#include "tf_main.h"
#include "psych.h"
#include "mc_enc.h"
#include "ms.h"
#include "is.h"
#include "aac_qc.h"
#include "all.h"
#include "aac_se_enc.h"
#include "nok_ltp_enc.h"

#define SQRT2 sqrt(2)

/* AAC tables */

/* First attempt at supporting multiple sampling rates   *
 * and bitrates correctly.                               */

/* Tables for maximum nomber of scalefactor bands */
/* Needs more fine-tuning. Only the values for 44.1kHz have been changed
   on lower bitrates. */
int max_sfb_s[] = { 12, 12, 12, 13, 14, 13, 15, 15, 15, 15, 15, 15 };
int max_sfb_l[] = { 49, 49, 47, 48, 49, 51, 47, 47, 43, 43, 43, 40 };


int     block_size_samples = 1024;  /* nr of samples per block in one! audio channel */
int     short_win_in_long  = 8;
int     max_ch;    /* no of of audio channels */
double *spectral_line_vector[MAX_TIME_CHANNELS];
double *reconstructed_spectrum[MAX_TIME_CHANNELS];
double *overlap_buffer[MAX_TIME_CHANNELS];
double *DTimeSigBuf[MAX_TIME_CHANNELS];
double *DTimeSigLookAheadBuf[MAX_TIME_CHANNELS+2];
double *nok_tmp_DTimeSigBuf[MAX_TIME_CHANNELS]; /* temporary fix to the buffer size problem. */

/* variables used by the T/F mapping */
enum QC_MOD_SELECT qc_select = AAC_QC;                   /* later f(encPara) */
enum AAC_PROFILE profile = MAIN;
enum WINDOW_TYPE block_type[MAX_TIME_CHANNELS];
enum WINDOW_TYPE desired_block_type;
enum WINDOW_TYPE next_desired_block_type;

/* Additional variables for AAC */
int aacAllowScalefacs = 1;              /* Allow AAC scalefactors to be nonconstant */
TNS_INFO tnsInfo[MAX_TIME_CHANNELS];
NOK_LT_PRED_STATUS nok_lt_status[MAX_TIME_CHANNELS];

AACQuantInfo quantInfo[MAX_TIME_CHANNELS];               /* Info structure for AAC quantization and coding */

/* Channel information */
Ch_Info channelInfo[MAX_TIME_CHANNELS];

/* AAC shorter windows 960-480-120 */
int useShortWindows=0;  /* don't use shorter windows */

// TEMPORARY HACK

int srate_idx;

int sampling_rate;
int bit_rate;

// END OF HACK


/* EncTfFree() */
/* Free memory allocated by t/f-based encoder core. */

void EncTfFree (void)
{
	int chanNum;

	for (chanNum=0;chanNum<MAX_TIME_CHANNELS;chanNum++) {
		if (DTimeSigBuf[chanNum]) free(DTimeSigBuf[chanNum]);
		if (spectral_line_vector[chanNum]) free(spectral_line_vector[chanNum]);

		if (reconstructed_spectrum[chanNum]) free(reconstructed_spectrum[chanNum]);
		if (overlap_buffer[chanNum]) free(overlap_buffer[chanNum]);
		if (nok_lt_status[chanNum].delay) free(nok_lt_status[chanNum].delay);
		if (nok_tmp_DTimeSigBuf[chanNum]) free(nok_tmp_DTimeSigBuf[chanNum]);
	}
	for (chanNum=0;chanNum<MAX_TIME_CHANNELS+2;chanNum++) {
		if (DTimeSigLookAheadBuf[chanNum]) free(DTimeSigLookAheadBuf[chanNum]);
	}
}


/*****************************************************************************************
 ***
 *** Function: EncTfInit
 ***
 *** Purpose:  Initialize the T/F-part and the macro blocks of the T/F part of the VM
 ***
 *** Description:
 *** 
 ***
 *** Parameters:
 ***
 ***
 *** Return Value:
 ***
 *** **** MPEG-4 VM ****
 ***
 ****************************************************************************************/

void EncTfInit (faacAACConfig *ac, int VBR_setting)
{
	int chanNum, i;
	int SampleRates[] = {
		96000,88200,64000,48000,44100,32000,24000,22050,16000,12000,11025,8000,0
	};
	int BitRates[] = {
		64000,80000,96000,112000,128000,160000,192000,224000,256000,0
	};

	sampling_rate = ac->out_sampling_rate;
	bit_rate = ac->bit_rate;

	for (i = 0; ; i++)
	{
		if (SampleRates[i] == sampling_rate) {
			srate_idx = i;
			break;
		}
	}

	profile = MAIN;
	qc_select = AAC_PRED;           /* enable prediction */

	if (ac->profile == LOW) {
		profile = LOW;
		qc_select = AAC_QC;          /* disable prediction */
	}

	if (ac->use_PNS)
		pns_sfb_start = 0;
	else
		pns_sfb_start = 60;

	/* set the return values */
	max_ch = ac->channels;

	/* some global initializations */
	for (chanNum=0;chanNum<MAX_TIME_CHANNELS;chanNum++) {
		DTimeSigBuf[chanNum]            = (double*)malloc(block_size_samples*sizeof(double));
		spectral_line_vector[chanNum]   = (double*)malloc(2*block_size_samples*sizeof(double));

		reconstructed_spectrum[chanNum] = (double*)malloc(block_size_samples*sizeof(double));
		memset(reconstructed_spectrum[chanNum], 0, block_size_samples*sizeof(double));
		overlap_buffer[chanNum] = (double*)malloc(sizeof(double)*block_size_samples);
		memset(overlap_buffer[chanNum],0,(block_size_samples)*sizeof(double));
		block_type[chanNum] = ONLY_LONG_WINDOW;
		nok_lt_status[chanNum].delay =  (int*)malloc(MAX_SHORT_WINDOWS*sizeof(int));
		nok_tmp_DTimeSigBuf[chanNum]  = (double*)malloc(2*block_size_samples*sizeof(double));
		memset(nok_tmp_DTimeSigBuf[chanNum],0,(2*block_size_samples)*sizeof(double));
	}
	for (chanNum=0;chanNum<MAX_TIME_CHANNELS+2;chanNum++) {
		DTimeSigLookAheadBuf[chanNum]   = (double*)malloc((block_size_samples)*sizeof(double));
		memset(DTimeSigLookAheadBuf[chanNum],0,(block_size_samples)*sizeof(double));
	}

	/* initialize psychoacoustic module */
	EncTf_psycho_acoustic_init();

	/* initialize spectrum processing */
	/* initialize quantization and coding */
	tf_init_encode_spectrum_aac(0);

	/* Init TNS */
	for (chanNum=0;chanNum<MAX_TIME_CHANNELS;chanNum++) {
		TnsInit(sampling_rate,profile,&tnsInfo[chanNum]);
		quantInfo[chanNum].tnsInfo = &tnsInfo[chanNum];         /* Set pointer to TNS data */
	}

	/* Init LTP predictor */
	for (chanNum=0;chanNum<MAX_TIME_CHANNELS;chanNum++) {
		nok_init_lt_pred (&nok_lt_status[chanNum]);
		quantInfo[chanNum].ltpInfo = &nok_lt_status[chanNum];  /* Set pointer to LTP data */
	}
}

/*****************************************************************************************
 ***
 *** Function:    EncTfFrame
 ***
 *** Purpose:     processes a block of time signal input samples into a bitstream
 ***              based on T/F encoding 
 ***
 *** Description:
 *** 
 ***
 *** Parameters:
 ***
 ***
 *** Return Value:  returns the number of used bits
 ***
 *** **** MPEG-4 VM ****
 ***
 ****************************************************************************************/

int EncTfFrame (faacAACStream *as, BsBitStream  *fixed_stream)
{
	int used_bits;
	int error;

	/* Energy array (computed before prediction for long windows) */
	double energy[MAX_TIME_CHANNELS][MAX_SCFAC_BANDS];

	/* determine the function parameters used earlier:   HP 21-aug-96 */
	int          average_bits = as->frame_bits;
	int          available_bitreservoir_bits = as->available_bits-as->frame_bits;

	/* actual amount of bits currently in the bit reservoir */
	/* it is the job of this module to determine 
	the no of bits to use in addition to average_block_bits
	max. available: average_block_bits + available_bitreservoir_bits */
	int max_bitreservoir_bits = 8184;

	/* max. allowed amount of bits in the reservoir  (used to avoid padding bits) */
	long num_bits_available;

	double *p_ratio[MAX_TIME_CHANNELS], allowed_distortion[MAX_TIME_CHANNELS][MAX_SCFAC_BANDS];
	double p_ratio_long[MAX_TIME_CHANNELS][MAX_SCFAC_BANDS];
	double p_ratio_short[MAX_TIME_CHANNELS][MAX_SCFAC_BANDS];
	int    nr_of_sfb[MAX_TIME_CHANNELS], sfb_width_table[MAX_TIME_CHANNELS][MAX_SCFAC_BANDS];
	int sfb_offset_table[MAX_TIME_CHANNELS][MAX_SCFAC_BANDS+1];

	int no_sub_win, sub_win_size;

	/* structures holding the output of the psychoacoustic model */
	CH_PSYCH_OUTPUT_LONG chpo_long[MAX_TIME_CHANNELS+2];
	CH_PSYCH_OUTPUT_SHORT chpo_short[MAX_TIME_CHANNELS+2][MAX_SHORT_WINDOWS];

	{
		/* store input data in look ahead buffer which may be necessary for the window switching decision */
		int i;
		int chanNum;
		
		for (chanNum=0;chanNum<max_ch;chanNum++) {
			for( i=0; i<block_size_samples; i++ ) {
				/* temporary fix: a linear buffer for LTP containing the whole time frame */
				nok_tmp_DTimeSigBuf[chanNum][i] = DTimeSigBuf[chanNum][i];
				nok_tmp_DTimeSigBuf[chanNum][block_size_samples + i] = DTimeSigLookAheadBuf[chanNum][i];
			}
			for( i=0; i<block_size_samples; i++ ) {
				/* last frame input data are encoded now */
				DTimeSigBuf[chanNum][i] = DTimeSigLookAheadBuf[chanNum][i];
				DTimeSigLookAheadBuf[chanNum][i] = as->inputBuffer[chanNum][i];
			} /* end for(i ..) */
		} /* end for(chanNum ... ) */

		for (chanNum=2;chanNum<4;chanNum++) {
			if (chanNum == 2) {
				for(i = 0; i < block_size_samples; i++){
					DTimeSigLookAheadBuf[chanNum][i] = (DTimeSigLookAheadBuf[0][i]+DTimeSigLookAheadBuf[1][i])/SQRT2;
				}
			} else {
				for(i = 0; i < block_size_samples; i++){
					DTimeSigLookAheadBuf[chanNum][i] = (DTimeSigLookAheadBuf[0][i]-DTimeSigLookAheadBuf[1][i])/SQRT2;
				}
			}
		}

	}

	if (fixed_stream == NULL) {
		psy_fill_lookahead(DTimeSigLookAheadBuf, max_ch+2);

		return FNO_ERROR; /* quick'n'dirty fix for encoder startup    HP 21-aug-96 */
	}

	/* Keep track of number of bits used */
	used_bits = 0;

	/***********************************************************************/
	/* Determine channel elements      */
	/***********************************************************************/
	DetermineChInfo(channelInfo,max_ch);

	/******************************************************************************************************************************
	*
	* psychoacoustic
	*
	******************************************************************************************************************************/
	{
		int chanNum;
		for (chanNum=0;chanNum<max_ch+2;chanNum++) {

			EncTf_psycho_acoustic(
				sampling_rate,
				chanNum,
				&DTimeSigLookAheadBuf[chanNum],
				&next_desired_block_type,
		/*		(int)qc_select,
				block_size_samples,   */
				chpo_long,
				chpo_short
				);
		}
	}

	/******************************************************************************************************************************
	*
	* block_switch processing 
	*
	******************************************************************************************************************************/
	{
		int chanNum = 0;
		/* A few definitions:                                                      */
		/*   block_type:  Initially, the block_type used in the previous frame.    */
		/*                Will be set to the block_type to use this frame.         */
		/*                A block type will be selected to ensure a meaningful     */
		/*                window transition.                                       */
		/*   next_desired_block_type:  Block_type (LONG or SHORT) which the psycho */
		/*                model wants to use next frame.  The psycho model is      */
		/*                using a look-ahead buffer.                               */
		/*   desired_block_type:  Block_type (LONG or SHORT) which the psycho      */
		/*                previously wanted to use.  It is the desired block_type  */
		/*                for this frame.                                          */
		if ( (block_type[chanNum]==ONLY_SHORT_WINDOW)||(block_type[chanNum]==LONG_SHORT_WINDOW) ) {
			if ( (desired_block_type==ONLY_LONG_WINDOW)&&(next_desired_block_type==ONLY_LONG_WINDOW) ) {
				block_type[chanNum]=SHORT_LONG_WINDOW;
			} else {
				block_type[chanNum]=ONLY_SHORT_WINDOW;
			}
		} else if (next_desired_block_type==ONLY_SHORT_WINDOW) {
			block_type[chanNum]=LONG_SHORT_WINDOW;
		} else {
			block_type[chanNum]=ONLY_LONG_WINDOW;
		}
		desired_block_type=next_desired_block_type;
	}

//	printf("%d %d\n", block_type[0], block_type[1]);
//	block_type[0] = ONLY_LONG_WINDOW;
//	block_type[1] = ONLY_LONG_WINDOW;
//	block_type[0] = ONLY_SHORT_WINDOW;
//	block_type[1] = ONLY_SHORT_WINDOW;
	block_type[1] = block_type[0];

	{
		int chanNum;

		for (chanNum=0;chanNum<max_ch;chanNum++) {

			/* Set window shape paremeter in quantInfo */
//			quantInfo[chanNum].window_shape = WS_DOLBY;
			quantInfo[chanNum].window_shape = WS_FHG;

			switch( block_type[chanNum] ) {
			case ONLY_SHORT_WINDOW  :
				no_sub_win   = short_win_in_long;
				sub_win_size = block_size_samples/short_win_in_long;
				quantInfo[chanNum].max_sfb = max_sfb_s[srate_idx];
#if 0
				quantInfo[chanNum].num_window_groups = 4;
				quantInfo[chanNum].window_group_length[0] = 1;
				quantInfo[chanNum].window_group_length[1] = 2;
				quantInfo[chanNum].window_group_length[2] = 3;
				quantInfo[chanNum].window_group_length[3] = 2;
#else
				quantInfo[chanNum].num_window_groups = 1;
				quantInfo[chanNum].window_group_length[0] = 8;
				quantInfo[chanNum].window_group_length[1] = 0;
				quantInfo[chanNum].window_group_length[2] = 0;
				quantInfo[chanNum].window_group_length[3] = 0;
				quantInfo[chanNum].window_group_length[4] = 0;
				quantInfo[chanNum].window_group_length[5] = 0;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -