📄 enc_tf.c
字号:
for (ismp=0; ismp<block_size_samples; ismp++){
sig_tmp[ismp+block_size_samples*max_ch+top] =
DTimeSigLookAheadBuf[i_ch][ismp];
}
}
/* automatic switching module */
winSwitch(sig_tmp, &block_type[0], ntt_InitFlag);
for (ismp=0; ismp<block_size_samples*2*max_ch; ismp++){
sig_tmp[ismp-block_size_samples*max_ch] = sig_tmp[ismp];
}
ntt_InitFlag = 0;
}
/* Multiple channels not really supported yet. */
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_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[bitrate_idx][srate_idx];
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;
break;
default:
no_sub_win = 1;
sub_win_size = block_size_samples;
quantInfo[chanNum].max_sfb = max_sfb_l[bitrate_idx][srate_idx];
quantInfo[chanNum].num_window_groups = 1;
quantInfo[chanNum].window_group_length[0]=1;
break;
}
}
}
{
int chanNum;
for (chanNum=0;chanNum<max_ch;chanNum++) {
/* Count number of bits used for gain_control_data */
used_bits += WriteGainControlData(&quantInfo[chanNum], /* quantInfo contains packed gain control data */
NULL, /* NULL BsBitStream. Only counting bits, no need to write yet */
0); /* Zero write flag means don't write */
}
}
/******************************************************************************************************************************
*
* T/F mapping
*
******************************************************************************************************************************/
{
int chanNum, i, b;
double cut_div = sampling_rate/2/cut_off[bitrate_idx][srate_idx];
int cut_bin = (int)BLOCK_LEN_LONG/cut_div+0.5;
int cut_bin_s = (int)BLOCK_LEN_SHORT/cut_div+0.5;
for (chanNum=0;chanNum<max_ch;chanNum++) {
buffer2freq(
DTimeSigBuf[chanNum],
spectral_line_vector[chanNum],
overlap_buffer[chanNum],
block_type[chanNum],
quantInfo[chanNum].window_shape,
block_size_samples,
block_size_samples/2,
block_size_samples/short_win_in_long,
MOVERLAPPED
);
/* Frequency cut-off. */
if (block_type[chanNum] == ONLY_SHORT_WINDOW) {
for (b = 0; b < 8; b++)
for (i = cut_bin_s; i < 128; i++)
spectral_line_vector[chanNum][(b*128)+i] = 0.0;
} else {
for (i = cut_bin; i < 1024; i++)
spectral_line_vector[chanNum][i] = 0.0;
}
}
}
/******************************************************************************************************************************
*
* adapt ratios of psychoacoustic module to codec scale factor bands
*
******************************************************************************************************************************/
{
int chanNum;
for (chanNum=0;chanNum<max_ch;chanNum++) {
/* Save p_ratio from psychoacoustic model for next frame. */
/* Psycho model is using a look-ahead window for block switching */
memcpy( (char*)p_ratio_long[!psychNum][chanNum], (char*)chpo_long[chanNum].p_ratio, (NSFB_LONG)*sizeof(double) );
memcpy( (char*)p_ratio_short[!psychNum][chanNum],(char*)chpo_short[chanNum][0].p_ratio,(MAX_SHORT_WINDOWS*NSFB_SHORT)*sizeof(double) );
}
}
{
int par_set;
int chanNum;
for (chanNum=0;chanNum<max_ch;chanNum++) {
par_set = 0;
switch( block_type[chanNum] ) {
case ONLY_LONG_WINDOW :
memcpy( (char*)sfb_width_table[chanNum], (char*)chpo_long[chanNum].cb_width, (NSFB_LONG+1)*sizeof(int) );
nr_of_sfb[chanNum] = chpo_long[chanNum].no_of_cb;
p_ratio[chanNum] = p_ratio_long[psychNum][chanNum];
par_set = 1;
break;
case LONG_SHORT_WINDOW :
memcpy( (char*)sfb_width_table[chanNum], (char*)chpo_long[chanNum].cb_width, (NSFB_LONG+1)*sizeof(int) );
nr_of_sfb[chanNum] = chpo_long[chanNum].no_of_cb;
p_ratio[chanNum] = p_ratio_long[psychNum][chanNum];
par_set = 1;
break;
case ONLY_SHORT_WINDOW :
memcpy( (char*)sfb_width_table[chanNum], (char*)chpo_short[chanNum][0].cb_width, (NSFB_SHORT+1)*sizeof(int) );
nr_of_sfb[chanNum] = chpo_short[chanNum][0].no_of_cb;
p_ratio[chanNum] = p_ratio_short[psychNum][chanNum];
par_set = 1;
break;
case SHORT_LONG_WINDOW :
memcpy( (char*)sfb_width_table[chanNum], (char*)chpo_long[chanNum].cb_width, (NSFB_LONG+1)*sizeof(int) );
nr_of_sfb[chanNum] = chpo_long[chanNum].no_of_cb;
p_ratio[chanNum] = p_ratio_long[psychNum][chanNum];
par_set = 1;
break;
default:
break;
}
/* to prevent undefined ptr just use a meaningful value to allow for experiments with the mechanism above */
if( !par_set) {
memcpy( (char*)sfb_width_table[chanNum], (char*)chpo_long[chanNum].cb_width, (NSFB_LONG+1)*sizeof(int) );
nr_of_sfb[chanNum] = chpo_long[chanNum].no_of_cb;
p_ratio[chanNum] = p_ratio_long[psychNum][chanNum];
}
}
}
{
int chanNum;
for (chanNum=0;chanNum<max_ch;chanNum++) {
/* Construct sf band offset table */
int offset=0;
int sfb;
for (sfb=0;sfb<nr_of_sfb[chanNum];sfb++) {
sfb_offset_table[chanNum][sfb] = offset;
offset+=sfb_width_table[chanNum][sfb];
}
sfb_offset_table[chanNum][nr_of_sfb[chanNum]]=offset;
}
}
/******************************************************************************************************************************
*
* quantization and coding
*
******************************************************************************************************************************/
{
int padding_limit = max_bitreservoir_bits;
int maxNumBitsByteAligned;
int chanNum;
int numWindows;
int windowLength;
int j,w;
int bandNumber;
int numFillBits;
int bitsLeftAfterFill;
/* bit budget */
num_bits_available = (long)(average_bits + available_bitreservoir_bits - used_bits);
/* find the largest byte-aligned section with fewer bits than num_bits_available */
maxNumBitsByteAligned = ((num_bits_available >> 3) << 3);
/* Compute how many reservoir bits can be used and still be able to byte */
/* align without exceeding num_bits_available, and have room for an ID_END marker */
available_bitreservoir_bits = maxNumBitsByteAligned - LEN_SE_ID - average_bits;
#if 0 // Not needed now, there are no SMR values anyway
for (chanNum=0;chanNum<max_ch;chanNum++) {
/* Compute energy in each scalefactor band of each window */
numWindows = (block_type[chanNum]==ONLY_SHORT_WINDOW) ? short_win_in_long : 1;
windowLength = block_size_samples/numWindows;
bandNumber=0;
for (w=0;w<numWindows;w++) {
int offset=0;
int sfb;
j = w*windowLength;
/* Only compute energy up to max_sfb */
for(sfb=0; sfb< quantInfo[chanNum].max_sfb; sfb++ ) {
/* calculate scale factor band energy */
int width,i;
energy[chanNum][bandNumber] = 0.0;
width=sfb_width_table[chanNum][sfb];
for(i=offset; i<(offset+width); i++ ) {
double dtmp = spectral_line_vector[chanNum][j++];
energy[chanNum][bandNumber] += dtmp*dtmp;
}
bandNumber++;
offset+=width;
}
}
} /* for (chanNum... */
#endif
/******************************************/
/* Perform TNS analysis and filtering */
/******************************************/
for (chanNum=0;chanNum<max_ch;chanNum++) {
error = TnsEncode(nr_of_sfb[chanNum], /* Number of bands per window */
quantInfo[chanNum].max_sfb, /* max_sfb */
block_type[chanNum],
sfb_offset_table[chanNum],
spectral_line_vector[chanNum],
&tnsInfo[chanNum]);
if (error == MBERROR)
return MBERROR;
}
/***********************************************************************/
/* If prediction is used, compute predictor info and residual spectrum */
/***********************************************************************/
for (chanNum=0;chanNum<max_ch;chanNum++) {
#if 0 // No prediction, gives no big gain.
if (qc_select == AAC_PRED) {
int numPredBands;
max_pred_sfb = 40;
numPredBands = min(max_pred_sfb,nr_of_sfb[chanNum]);
PredCalcPrediction( spectral_line_vector[chanNum],
reconstructed_spectrum[chanNum],
(int)block_type[chanNum],
numPredBands,
sfb_width_table[chanNum],
&(quantInfo[chanNum].pred_global_flag),
quantInfo[chanNum].pred_sfb_flag,
&(quantInfo[chanNum].reset_group_number),
chanNum);
} else
#endif
{
quantInfo[chanNum].pred_global_flag = 0;
}
} /* for(chanNum... */
/************************************************/
/* Call the AAC quantization and coding module. */
/************************************************/
for (chanNum = 0; chanNum < max_ch; chanNum++) {
int bitsToUse;
bitsToUse = (int)((average_bits - used_bits)/max_ch);
bitsToUse += (int)(0.2*available_bitreservoir_bits/max_ch);
error = tf_encode_spectrum_aac( &spectral_line_vector[chanNum],
&p_ratio[chanNum],
&allowed_distortion[chanNum],
&energy[chanNum],
&block_type[chanNum],
&sfb_width_table[chanNum],
&nr_of_sfb[chanNum],
bitsToUse,
available_bitreservoir_bits,
padding_limit,
fixed_stream, /*tmp_stream,*/
NULL,
1, /* nr of audio channels */
&reconstructed_spectrum[chanNum],
useShortWindows,
aacAllowScalefacs,
&quantInfo[chanNum],
&(channelInfo[chanNum]),
varBitRate,
bit_rate);
if (error == MBERROR)
return error;
}
#if 0 // No prediction
/* If short window, reconstruction not needed for prediction */
for (chanNum=0;chanNum<max_ch;chanNum++) {
if ((block_type[chanNum]==ONLY_SHORT_WINDOW)) {
int sind;
for (sind=0;sind<1024;sind++) {
reconstructed_spectrum[chanNum][sind]=0.0;
}
}
}
#endif
/**********************************/
/* Write out all encoded channels */
/**********************************/
for (chanNum=0;chanNum<max_ch;chanNum++) {
if (channelInfo[chanNum].present) {
/* Write out a single_channel_element */
if (!channelInfo[chanNum].cpe) {
/* Write out sce */ /* BugFix by YT '+=' sould be '=' */
used_bits = WriteSCE(&quantInfo[chanNum], /* Quantization information */
channelInfo[chanNum].tag,
fixed_stream, /* Bitstream */
1); /* Write flag, 1 means write */
} else {
if (channelInfo[chanNum].ch_is_left) {
/* Write out cpe */
used_bits = WriteCPE(&quantInfo[chanNum], /* Quantization information,left */
&quantInfo[channelInfo[chanNum].paired_ch], /* Right */
channelInfo[chanNum].tag,
channelInfo[chanNum].common_window, /* common window */
&(channelInfo[chanNum].ms_info),
fixed_stream, /* Bitstream */
1); /* Write flag, 1 means write */
}
} /* if (!channelInfo[chanNum].cpe) else */
} /* if (chann...*/
} /* for (chanNum...*/
/* Compute how many fill bits are needed to avoid overflowing bit reservoir */
/* Save room for ID_END terminator */
if (used_bits < (minBitsNoOverflow - LEN_SE_ID) ) {
numFillBits = minBitsNoOverflow - LEN_SE_ID - used_bits;
} else {
numFillBits = 0;
}
/* Write AAC fill_elements, smallest fill element is 7 bits. */
/* Function may leave up to 6 bits left after fill, so tell it to fill a few extra */
numFillBits += 6;
bitsLeftAfterFill=WriteAACFillBits(fixed_stream,numFillBits);
used_bits += (numFillBits - bitsLeftAfterFill);
/* Write ID_END terminator */
BsPutBit(fixed_stream,ID_END,LEN_SE_ID);
used_bits += LEN_SE_ID;
/* Now byte align the bitstream */
used_bits += ByteAlign(fixed_stream);
} /* Quantization and coding block */
return MBNO_ERROR;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -