ref: 88c21b018c8eb827016538ae1c338941e2a70afd
parent: dee659a7e1b92e45dee87c67cca7d99d620cf3b8
author: menno <menno>
date: Sun Oct 1 10:47:28 EDT 2000
Encoder LFE fixup. Should be working now, but no way to test it yet.
--- a/aacenc.h
+++ b/aacenc.h
@@ -16,6 +16,7 @@
#define PNS 11
#define IN_SAMPLING_RATE 12
#define NUMBER_OF_CHANNELS 13
+#define LFE_PRESENT 14
#define MAIN_PROFILE 0
#define LOW_PROFILE 1
@@ -34,6 +35,9 @@
#define USE_LTP 1
#define NO_LTP 0
+#define USE_LFE 1
+#define NO_LFE 0
+
#define USE_PNS 1
#define NO_PNS 0
@@ -64,7 +68,7 @@
int in_sampling_rate;
int frame_bits;
int available_bits;
- int header_type;
+ int header_type;
int use_MS;
int use_TNS;
int use_LTP;
@@ -78,12 +82,13 @@
int cut_off;
int bit_rate;
int raw_audio;
- SNDFILE *in_file;
- FILE *out_file;
- unsigned char *bitBuffer;
- int bitBufferSize;
- short *sampleBuffer;
+ SNDFILE *in_file;
+ FILE *out_file;
+ unsigned char *bitBuffer;
+ int bitBufferSize;
+ short *sampleBuffer;
int samplesToRead;
+ int lfePresent;
} faacAACStream;
#ifndef FAAC_DLL
--- a/enc_tf.c
+++ b/enc_tf.c
@@ -247,7 +247,7 @@
/***********************************************************************/
/* Determine channel elements */
/***********************************************************************/
- DetermineChInfo(channelInfo, max_ch);
+ DetermineChInfo(channelInfo, max_ch, as->lfePresent);
/***********************************************************************/
@@ -487,6 +487,21 @@
}
}
+
+ /************************************************************************
+ Set upper spectral coefficients to zero for LFE
+ ************************************************************************/
+ {
+ int chanNum;
+ for (chanNum=0;chanNum<max_ch;chanNum++) {
+ if (channelInfo[chanNum].lfe) {
+ int i;
+ for (i=13;i<sfb_offset_table[chanNum][nr_of_sfb[chanNum]];i++)
+ spectral_line_vector[chanNum][i] = 0;
+ }
+ }
+ }
+
/*****************************************************************************
* quantization and coding
*****************************************************************************/
@@ -512,15 +527,19 @@
/* Perform TNS analysis and filtering */
/******************************************/
for (chanNum=0;chanNum<max_ch;chanNum++) {
- error = TnsEncode(nr_of_sfb[chanNum], /* Number of bands per window */
+ if (!channelInfo[chanNum].lfe) {
+ 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],
- as->use_TNS);
- if (error == FERROR)
- return FERROR;
+ block_type[chanNum],
+ sfb_offset_table[chanNum],
+ spectral_line_vector[chanNum],
+ &tnsInfo[chanNum],
+ as->use_TNS);
+ if (error == FERROR)
+ return FERROR;
+ } else {
+ tnsInfo[chanNum].tnsDataPresent=0; /* TNS not used for LFE */
+ }
}
/*******************************************************************************/
@@ -527,7 +546,8 @@
/* If LTP prediction is used, compute LTP predictor info and residual spectrum */
/*******************************************************************************/
for(chanNum=0;chanNum<max_ch;chanNum++) {
- if(as->use_LTP && (block_type[chanNum] != ONLY_SHORT_WINDOW)) {
+ if(as->use_LTP && channelInfo[chanNum].present &&
+ (!channelInfo[chanNum].lfe) && (block_type[chanNum] != ONLY_SHORT_WINDOW)) {
if(channelInfo[chanNum].cpe) {
if(channelInfo[chanNum].ch_is_left) {
int i;
@@ -600,8 +620,24 @@
/************************************************/
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);
+ if (!as->lfePresent) {
+ bitsToUse = (int)((average_bits - used_bits)/max_ch);
+ bitsToUse += (int)(0.2*available_bitreservoir_bits/max_ch);
+ } else {
+ /* Calculation of reduced bitrate for LFE */
+ double lfeBitRatio = 0.14; /* ratio of LFE bits to bits of one SCE */
+ int lfeBits = max(200,(int)((average_bits - used_bits) * lfeBitRatio / (max_ch - 1))); /* number of bits for LFE */
+
+ if (channelInfo[chanNum].lfe) {
+ bitsToUse = lfeBits;
+ bitsToUse += (int)(0.2*available_bitreservoir_bits
+ * lfeBitRatio / (max_ch - 1));
+ } else {
+ bitsToUse = (int)((average_bits - used_bits - lfeBits) / (max_ch - 1));
+ bitsToUse += (int)(0.2*available_bitreservoir_bits
+ * (1 - lfeBitRatio / (max_ch - 1)) / (max_ch - 1));
+ }
+ }
error = tf_encode_spectrum_aac(&spectral_line_vector[chanNum],
&p_ratio[chanNum],
@@ -645,12 +681,14 @@
/**********************************************************/
if(as->use_LTP)
for (chanNum=0;chanNum<max_ch;chanNum++) {
- nok_ltp_reconstruct(reconstructed_spectrum[chanNum],
- block_type[chanNum],
- WS_SIN,
- &sfb_offset_table[chanNum][0],
- nr_of_sfb[chanNum],
- &nok_lt_status[chanNum]);
+ if (!channelInfo[chanNum].lfe) { /* no reconstruction needed for LFE channel*/
+ nok_ltp_reconstruct(reconstructed_spectrum[chanNum],
+ block_type[chanNum],
+ WS_SIN,
+ &sfb_offset_table[chanNum][0],
+ nr_of_sfb[chanNum],
+ &nok_lt_status[chanNum]);
+ }
}
@@ -665,11 +703,19 @@
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 */
- 0); /* Write flag, 1 means write */
+ if (channelInfo[chanNum].lfe) {
+ /* Write out lfe */
+ used_bits += WriteLFE(&quantInfo[chanNum], /* Quantization information */
+ channelInfo[chanNum].tag,
+ fixed_stream, /* Bitstream */
+ 0); /* Write flag, 1 means write */
+ } else {
+ /* Write out sce */
+ used_bits += WriteSCE(&quantInfo[chanNum], /* Quantization information */
+ channelInfo[chanNum].tag,
+ fixed_stream, /* Bitstream */
+ 0); /* Write flag, 1 means write */
+ }
}
else {
if (channelInfo[chanNum].ch_is_left) {
@@ -716,11 +762,19 @@
if (channelInfo[chanNum].present) {
/* Write out a single_channel_element */
if (!channelInfo[chanNum].cpe) {
- /* Write out sce */
- WriteSCE(&quantInfo[chanNum], /* Quantization information */
- channelInfo[chanNum].tag,
- fixed_stream, /* Bitstream */
- 1); /* Write flag, 1 means write */
+ if (channelInfo[chanNum].lfe) {
+ /* Write out lfe */
+ WriteLFE(&quantInfo[chanNum], /* Quantization information */
+ channelInfo[chanNum].tag,
+ fixed_stream, /* Bitstream */
+ 1); /* Write flag, 1 means write */
+ } else {
+ /* Write out sce */
+ WriteSCE(&quantInfo[chanNum], /* Quantization information */
+ channelInfo[chanNum].tag,
+ fixed_stream, /* Bitstream */
+ 1); /* Write flag, 1 means write */
+ }
}
else {
if (channelInfo[chanNum].ch_is_left) {
--- a/encoder.c
+++ b/encoder.c
@@ -388,6 +388,7 @@
as->use_TNS = 1;
as->use_LTP = 1;
as->use_PNS = 0;
+ as->lfePresent = 0;
as->cut_off = 0;
as->bit_rate = 128000;
as->out_sampling_rate = 0;
@@ -427,6 +428,9 @@
case PNS:
as->use_PNS = value;
break;
+ case LFE_PRESENT:
+ as->lfePresent = value;
+ break;
case IN_SAMPLING_RATE:
as->in_sampling_rate = value;
break;
--- a/faac.c
+++ b/faac.c
@@ -63,6 +63,7 @@
printf(" -nm Don't use mid/side stereo coding.\n");
printf(" The default for MS is intelligent switching.\n");
printf(" -np Don't use LTP (Long Term Prediction).\n");
+ printf(" -lfe Use LFE (Low Frequency Enhancement) channel.\n");
printf(" -oX Set output directory.\n");
printf(" -sX Set output sampling rate.\n");
printf(" -cX Set cut-off frequency.\n");
@@ -188,6 +189,9 @@
break;
case 'c': case 'C':
faac_SetParam(as,CUT_OFF,atoi(&argv[i][2]));
+ break;
+ case 'l': case 'L':
+ faac_SetParam(as,LFE_PRESENT,USE_LFE);
break;
case 'o': case 'O':
out_dir_set = 1;
--- a/mc_enc.c
+++ b/mc_enc.c
@@ -1,7 +1,7 @@
#include "mc_enc.h"
-void DetermineChInfo(Ch_Info* chInfo, int numChannels/*, int lfePresent*/) {
+void DetermineChInfo(Ch_Info* chInfo, int numChannels, int lfePresent) {
/* If LFE present */
/* Num channels # of SCE's # of CPE's #of LFE's */
@@ -65,22 +65,20 @@
numChannelsLeft--;
}
- /* Is there another channel left ? If -lf switched then lfe else sce */
+ /* Is there another channel left ? */
if (numChannelsLeft) {
-/* if (lfePresent) {
+ if (lfePresent) {
chInfo[numChannels-numChannelsLeft].present = 1;
chInfo[numChannels-numChannelsLeft].tag=lfeTag++;
chInfo[numChannels-numChannelsLeft].cpe=0;
chInfo[numChannels-numChannelsLeft].lfe=1;
- } else { */
+ } else {
chInfo[numChannels-numChannelsLeft].present = 1;
chInfo[numChannels-numChannelsLeft].tag=sceTag++;
chInfo[numChannels-numChannelsLeft].cpe=0;
chInfo[numChannels-numChannelsLeft].lfe=0;
-// }
+ }
numChannelsLeft--;
- } else {
-// if (lfePresent) CommonExit(1,"no LFE channel detected");
}
}
--- a/mc_enc.h
+++ b/mc_enc.h
@@ -5,7 +5,7 @@
#include "all.h"
-void DetermineChInfo(Ch_Info* chInfo, int numChannels/*, int lfePresent*/);
+void DetermineChInfo(Ch_Info* chInfo, int numChannels, int lfePresent);
#endif
--- a/psych.c
+++ b/psych.c
@@ -630,7 +630,27 @@
memcpy(p_chpo_short[rightChan][i].use_ms, psy_stvar_short[rightChan].use_ms[i], NSFB_SHORT*sizeof(int));
}
- } else if (channelInfo[chanNum].lfe) { /* LFE */ /* not yet finished */
+ } else if (channelInfo[chanNum].lfe) { /* LFE */
+
+ // LFE psych ratios are set to -24 dB
+ for (i = 0; i < 4; i++) {
+ psy_stvar_long[chanNum].ismr[i] = 0.004; /* -24 dB */
+ }
+ for (i = 4; i < NSFB_LONG; i++) {
+ psy_stvar_long[chanNum].ismr[i] = 1.0; /* -24 dB */
+ }
+ p_chpo_long[chanNum].p_ratio = psy_stvar_long[chanNum].ismr;
+
+ block_type[chanNum] = ONLY_LONG_WINDOW;
+
+ // set the scalefactor band values
+ p_chpo_long[chanNum].cb_width = p_sri->cb_width_long;
+ p_chpo_long[chanNum].no_of_cb = p_sri->num_cb_long;
+ for( i=0; i<MAX_SHORT_WINDOWS; i++ ) {
+ p_chpo_short[chanNum][i].p_ratio = psy_stvar_short[chanNum].ismr[i];
+ p_chpo_short[chanNum][i].cb_width = p_sri->cb_width_short;
+ p_chpo_short[chanNum][i].no_of_cb = p_sri->num_cb_short;
+ }
} else { /* SCE */