📄 enc_tf.c
字号:
#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 + -