shithub: aacenc

Download patch

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 */