shithub: aacenc

Download patch

ref: d7dbf2b7cf98d98c8daf835f97509eb9b0e9ddd4
parent: abd42b5a145fe513b01082cc200543b86b5e29e9
author: menno <menno>
date: Sat Aug 16 11:06:07 EDT 2003

Case:
- More input options
- MP4 output

--- a/frontend/faac.dsp
+++ b/frontend/faac.dsp
@@ -42,7 +42,7 @@
 # PROP Ignore_Export_Lib 0
 # PROP Target_Dir ""
 # ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
-# ADD CPP /nologo /MD /W3 /O2 /I "../include" /I "../common/libsndfile/src" /I "../common/getopt" /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
+# ADD CPP /nologo /MD /W3 /O2 /I "../include" /I "../common/libsndfile/src" /I "../common/getopt" /I "../../faad2/common/mp4v2" /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
 # ADD BASE RSC /l 0x413 /d "NDEBUG"
 # ADD RSC /l 0x413 /d "NDEBUG"
 BSC32=bscmake.exe
@@ -50,7 +50,7 @@
 # ADD BSC32 /nologo
 LINK32=xilink6.exe
 # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
-# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib ws2_32.lib /nologo /subsystem:console /machine:I386
 # SUBTRACT LINK32 /profile /debug /nodefaultlib
 
 !ELSEIF  "$(CFG)" == "faac - Win32 Debug"
@@ -67,7 +67,7 @@
 # PROP Ignore_Export_Lib 0
 # PROP Target_Dir ""
 # ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
-# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /I "../include" /I "../common/libsndfile/src" /I "../common/getopt" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
+# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /I "../include" /I "../common/libsndfile/src" /I "../common/getopt" /I "../../faad2/common/mp4v2" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
 # ADD BASE RSC /l 0x413 /d "_DEBUG"
 # ADD RSC /l 0x413 /d "_DEBUG"
 BSC32=bscmake.exe
@@ -75,7 +75,7 @@
 # ADD BSC32 /nologo
 LINK32=xilink6.exe
 # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
-# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib ws2_32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
 
 !ENDIF 
 
--- a/frontend/faac.dsw
+++ b/frontend/faac.dsw
@@ -17,11 +17,26 @@
     Begin Project Dependency
     Project_Dep_Name libsndfile
     End Project Dependency
+    Begin Project Dependency
+    Project_Dep_Name libmp4v2_st
+    End Project Dependency
 }}}
 
 ###############################################################################
 
 Project: "libfaac"=..\LIBFAAC\libfaac.dsp - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Project: "libmp4v2_st"=..\..\faad2\common\mp4v2\libmp4v2_st60.dsp - Package Owner=<4>
 
 Package=<5>
 {{{
--- a/frontend/input.c
+++ b/frontend/input.c
@@ -16,7 +16,7 @@
  * License along with this library; if not, write to the Free Software
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  *
- * $Id: input.c,v 1.8 2003/07/28 17:12:57 menno Exp $
+ * $Id: input.c,v 1.10 2003/08/17 19:38:15 menno Exp $
  */
 
 #ifdef HAVE_CONFIG_H
@@ -27,6 +27,7 @@
 #include <stdlib.h>
 
 #ifdef WIN32
+#include <io.h>
 #include <fcntl.h>
 #endif
 
@@ -60,6 +61,7 @@
 riffsub_t;
 
 #define WAVE_FORMAT_PCM		1
+#define WAVE_FORMAT_FLOAT	3
 #define WAVE_FORMAT_EXTENSIBLE	0xfffe
 typedef struct
 {
@@ -163,22 +165,22 @@
       for (skip = riffsub.len; skip > 0; skip--)
 	fgetc(wave_f);
     }
-    if (UINT16(wave.Format.wFormatTag) != WAVE_FORMAT_PCM)
+    if (UINT16(wave.Format.wFormatTag) != WAVE_FORMAT_PCM && UINT16(wave.Format.wFormatTag) != WAVE_FORMAT_FLOAT)
     {
       if (UINT16(wave.Format.wFormatTag) == WAVE_FORMAT_EXTENSIBLE)
       {
-	if (UINT16(wave.Format.cbSize) < 22) // struct too small
-	  return NULL;
-	if (memcmp(wave.SubFormat, waveformat_pcm_guid, 16))
-	{
+        if (UINT16(wave.Format.cbSize) < 22) // struct too small
+          return NULL;
+        if (memcmp(wave.SubFormat, waveformat_pcm_guid, 16))
+        {
           unsuperr(name);
-	  return NULL;
-	}
+          return NULL;
+        }
       }
       else
       {
-	unsuperr(name);
-	return NULL;
+        unsuperr(name);
+        return NULL;
       }
     }
   }
@@ -186,6 +188,7 @@
   sndf = malloc(sizeof(*sndf));
   memset(sndf, 0, sizeof(*sndf));
   sndf->f = wave_f;
+  sndf->isfloat = (UINT16(wave.Format.wFormatTag) == WAVE_FORMAT_FLOAT);
   if (rawinput)
   {
     sndf->bigendian = 1;
@@ -224,6 +227,117 @@
     for (chn = 0; chn < channels; chn++)
       buf[i * channels + chn] = tmp[map[chn]];
   }
+}
+
+size_t wav_read_float32(pcmfile_t *sndf, float *buf, size_t num, int *map)
+{
+  size_t i = 0;
+  unsigned char bufi[8];
+
+  if ((sndf->samplebytes > 8) || (sndf->samplebytes < 1))
+    return 0;
+
+  while (i<num) {
+    if (fread(bufi, sndf->samplebytes, 1, sndf->f) != 1)
+      break;
+
+    if (sndf->isfloat)
+    {
+      switch (sndf->samplebytes) {
+      case 4:
+        buf[i] = (*(float *)&bufi) * (float)32768;
+        break;
+
+      case 8:
+        buf[i] = (float)((*(double *)&bufi) * (float)32768);
+        break;
+
+      default:
+        return 0;
+      }
+    }
+    else
+    {
+      // convert to 32 bit float
+      // fix endianness
+      switch (sndf->samplebytes) {
+      case 1:
+        /* this is endian clean */
+        buf[i] = ((float)bufi[0] - 128) * (float)256;
+        break;
+
+      case 2:
+#ifdef WORDS_BIGENDIAN
+        if (!sndf->bigendian)
+#else
+        if (sndf->bigendian)
+#endif
+        {
+          // swap bytes
+          int16_t s = ((int16_t *)bufi)[0];
+          s = SWAP16(s);
+          buf[i] = (float)s;
+        }
+        else
+        {
+          // no swap
+          int s = ((int16_t *)bufi)[0];
+          buf[i] = (float)s;
+        }
+        break;
+
+      case 3:
+        if (!sndf->bigendian)
+        {
+          int s = bufi[0] | (bufi[1] << 8) | (bufi[2] << 16);
+
+          // fix sign
+          if (s & 0x800000)
+            s |= 0xff000000;
+
+          buf[i] = (float)s / 256;
+        }
+        else // big endian input
+        {
+          int s = (bufi[0] << 16) | (bufi[1] << 8) | bufi[2];
+
+          // fix sign
+          if (s & 0x800000)
+            s |= 0xff000000;
+
+          buf[i] = (float)s / 256;
+        }
+        break;
+
+      case 4:
+#ifdef WORDS_BIGENDIAN
+        if (!sndf->bigendian)
+#else
+        if (sndf->bigendian)
+#endif
+        {
+          // swap bytes
+          int s = *(int *)&bufi;
+          buf[i] = (float)SWAP32(s) / 65536;
+        }
+        else
+        {
+          int s = *(int *)&bufi;
+          buf[i] = (float)s / 65536;
+        }
+        break;
+
+      default:
+        return 0;
+      }
+    }
+    i++;
+  }
+
+  if (map)
+    chan_remap((int32_t *)buf, sndf->channels, i / sndf->channels, map);
+
+  return i;
 }
 
 size_t wav_read_int24(pcmfile_t *sndf, int32_t *buf, size_t num, int *map)
--- a/frontend/input.h
+++ b/frontend/input.h
@@ -16,7 +16,7 @@
  * License along with this library; if not, write to the Free Software
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  *
- * $Id: input.h,v 1.3 2003/07/10 19:18:58 knik Exp $
+ * $Id: input.h,v 1.5 2003/08/17 19:38:15 menno Exp $
  */
 
 #ifndef _INPUT_H
@@ -64,9 +64,11 @@
   int samplerate;
   int samples;
   int bigendian;
+  int isfloat;
 } pcmfile_t;
 
 pcmfile_t *wav_open_read(const char *path, int rawchans);
+size_t wav_read_float32(pcmfile_t *sndf, float *buf, size_t num, int *map);
 size_t wav_read_int24(pcmfile_t *sndf, int32_t *buf, size_t num, int *map);
 int wav_close(pcmfile_t *file);
 
--- a/frontend/main.c
+++ b/frontend/main.c
@@ -16,9 +16,11 @@
  * License along with this library; if not, write to the Free Software
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  *
- * $Id: main.c,v 1.41 2003/08/15 11:43:14 knik Exp $
+ * $Id: main.c,v 1.42 2003/08/16 15:06:07 menno Exp $
  */
 
+#include <mp4.h>
+
 #ifdef HAVE_CONFIG_H
 #include "config.h"
 #endif
@@ -134,7 +136,8 @@
     char *audioFileName;
     char *aacFileName;
 
-    int32_t *pcmbuf;
+    //int32_t *pcmbuf;
+    float *floatbuf;
     int *chanmap = NULL;
 
     unsigned char *bitbuf;
@@ -147,6 +150,12 @@
 
     FILE *outfile;
 
+    MP4FileHandle MP4hFile = MP4_INVALID_FILE_HANDLE;
+    MP4TrackId MP4track = 0;
+    int mp4 = 0;
+    u_int64_t total_samples = 0;
+    u_int64_t encoded_samples = 0;
+
     // get faac version
     hEncoder = faacEncOpen(44100, 2, &samplesInput, &maxBytesOutput);
     myFormat = faacEncGetCurrentConfiguration(hEncoder);
@@ -181,12 +190,13 @@
             { "pcmsamplebits", 1, 0, 'B'},
             { "pcmchannels", 1, 0, 'C'},
             { "addsilent", 1, 0, 300},
+            { "createmp4", 0, 0, 'w'},
             { 0, 0, 0, 0}
         };
       int c = -1;
       int option_index = 0;
 
-      c = getopt_long(argc, argv, "a:m:o:rnc:q:PR:B:C:I:",
+      c = getopt_long(argc, argv, "a:m:o:rnwc:q:PR:B:C:I:",
             long_options, &option_index);
 
         if (c == -1)
@@ -298,6 +308,9 @@
 	case 300:
 	  sscanf(optarg, "%u", &addsilent);
 	  break;
+    case 'w':
+      mp4 = 1;
+      break;
         case '?':
             break;
         default:
@@ -325,9 +338,10 @@
 	printf("  -r     RAW AAC output file.\n");
 	printf("  -P     Raw PCM input mode (default 44100Hz 16bit stereo).\n");
 	printf("  -R     Raw PCM input rate.\n");
-	printf("  -B     Raw PCM input sample size (16 default or 8bits).\n");
+	printf("  -B     Raw PCM input sample size (8, 16 (default), 24 or 32bits).\n");
 	printf("  -C     Raw PCM input channels.\n");
 	printf("  -I <C,LF> Input channel config, default is 3,4 (Center third, LF fourth)\n");
+    printf("  -w     Wrap AAC data in MP4 container\n");
 	printf("  --addsilent <n> Add n silent frames at the end of output (default=%d)\n",
 	       addsilent);
 	//printf("More details on FAAC usage can be found in the faac.html file.\n");
@@ -360,12 +374,10 @@
         return 1;
     }
 
-    /* open the aac output file */
-    outfile = fopen(aacFileName, "wb");
-    if (!outfile)
+    if (mp4)
     {
-        fprintf(stderr, "Couldn't create output file %s\n", aacFileName);
-        return 1;
+        mpegVersion = MPEG4;
+        useAdts = 0;
     }
 
     /* open the encoder library */
@@ -372,7 +384,8 @@
     hEncoder = faacEncOpen(infile->samplerate, infile->channels,
 			   &samplesInput, &maxBytesOutput);
 
-    pcmbuf = (int32_t *)malloc(samplesInput*sizeof(int32_t));
+    //pcmbuf = (int32_t *)malloc(samplesInput*sizeof(int32_t));
+    floatbuf = (float *)malloc(samplesInput*sizeof(float));
     bitbuf = (unsigned char*)malloc(maxBytesOutput*sizeof(unsigned char));
     chanmap = mkChanMap(infile->channels, chanC, chanLF);
     if (chanmap)
@@ -396,6 +409,7 @@
     myFormat->aacObjectType = objectType;
     myFormat->mpegVersion = mpegVersion;
     myFormat->useTns = useTns;
+    if (infile->channels >= 6) myFormat->useLfe = 1;
     myFormat->allowMidside = useMidSide;
     if (bitRate)
       myFormat->bitRate = bitRate;
@@ -403,11 +417,42 @@
     if (quantqual > 0)
       myFormat->quantqual = quantqual;
     myFormat->outputFormat = useAdts;
+    myFormat->inputFormat = FAAC_INPUT_FLOAT;
     if (!faacEncSetConfiguration(hEncoder, myFormat)) {
         fprintf(stderr, "Unsupported output format!\n");
+        if (mp4) MP4Close(MP4hFile);
         return 1;
     }
 
+    /* initialize MP4 creation */
+    if (mp4) {
+        u_int8_t *ASC = 0;
+        u_int32_t ASCLength = 0;
+
+        MP4hFile = MP4Create(aacFileName, 0, 0, 0);
+        if (MP4hFile == MP4_INVALID_FILE_HANDLE) {
+            fprintf(stderr, "Couldn't create output file %s\n", aacFileName);
+            return 1;
+        }
+
+        MP4SetTimeScale(MP4hFile, 90000);
+        MP4track = MP4AddAudioTrack(MP4hFile, infile->samplerate, MP4_INVALID_DURATION, MP4_MPEG4_AUDIO_TYPE);
+        MP4SetAudioProfileLevel(MP4hFile, 0x0F);
+        //MP4AV_AacGetConfiguration(&ASC, &ASCLength, (u_int8_t)objectType, (u_int32_t)infile->samplerate, (u_int8_t)infile->channels);
+        faacEncGetDecoderSpecificInfo(hEncoder, &ASC, &ASCLength);
+        MP4SetTrackESConfiguration(MP4hFile, MP4track, ASC, ASCLength);
+    }
+    else
+    {
+        /* open the aac output file */
+        outfile = fopen(aacFileName, "wb");
+        if (!outfile)
+        {
+            fprintf(stderr, "Couldn't create output file %s\n", aacFileName);
+            return 1;
+        }
+    }
+
     cutOff = myFormat->bandWidth;
     quantqual = myFormat->quantqual;
     bitRate = myFormat->bitRate;
@@ -435,7 +480,7 @@
       fprintf(stderr, " + M/S");
     fprintf(stderr, "\n");
 
-    if (outfile)
+    if (outfile || MP4hFile != MP4_INVALID_FILE_HANDLE)
     {
     int showcnt = 0;
 #ifdef _WIN32
@@ -459,14 +504,18 @@
         {
             int bytesWritten;
 
-	    samplesRead = wav_read_int24(infile, pcmbuf, samplesInput, chanmap);
+	    //samplesRead = wav_read_int24(infile, pcmbuf, samplesInput, chanmap);
+	    samplesRead = wav_read_float32(infile, floatbuf, samplesInput, chanmap);
 
+        total_samples += samplesRead / infile->channels;
+
 	    if (!samplesRead)
 	    {
 	      if (addsilent)
 	      {
 		addsilent--;
-		memset(pcmbuf, 0, samplesInput * sizeof(*pcmbuf));
+		//memset(pcmbuf, 0, samplesInput * sizeof(*pcmbuf));
+		memset(floatbuf, 0, samplesInput * sizeof(*floatbuf));
 		samplesRead = samplesInput;
 	      }
 	    }
@@ -473,7 +522,8 @@
 
             /* call the actual encoding routine */
             bytesWritten = faacEncEncode(hEncoder,
-                pcmbuf,
+                //pcmbuf,
+                floatbuf,
                 samplesRead,
                 bitbuf,
                 maxBytesOutput);
@@ -546,13 +596,33 @@
                 break ;
             }
 
-            /* write bitstream to aac file */
-            fwrite(bitbuf, 1, bytesWritten, outfile);
+            if (bytesWritten > 0)
+            {
+                unsigned int samples = ((total_samples - encoded_samples) < (samplesInput/infile->channels))
+                    ? (total_samples - encoded_samples)
+                    : (samplesInput/infile->channels);
+
+                if (mp4)
+                {
+                    /* write bitstream to mp4 file */
+                    MP4WriteSample(MP4hFile, MP4track, bitbuf, bytesWritten, samples, 0, 1);
+                }
+                else
+                {
+                    /* write bitstream to aac file */
+                    fwrite(bitbuf, 1, bytesWritten, outfile);
+                }
+
+                encoded_samples += samples;
+            }
         }
     fprintf(stderr, "\n\n");
 
         /* clean up */
-        fclose(outfile);
+        if (mp4)
+            MP4Close(MP4hFile);
+        else
+            fclose(outfile);
     }
 
     faacEncClose(hEncoder);
@@ -559,7 +629,8 @@
 
     wav_close(infile);
 
-    if (pcmbuf) free(pcmbuf);
+    //if (pcmbuf) free(pcmbuf);
+    if (floatbuf) free(floatbuf);
     if (bitbuf) free(bitbuf);
 
     return 0;
@@ -567,6 +638,11 @@
 
 /*
 $Log: main.c,v $
+Revision 1.42  2003/08/16 15:06:07  menno
+Case:
+- More input options
+- MP4 output
+
 Revision 1.41  2003/08/15 11:43:14  knik
 Option to add a number of silent frames at the end of output.
 Small TNS option fix.