shithub: aacdec

Download patch

ref: cbe4880728c45081b70ee1b731a8a89dbc065269
parent: 7fdb7f1ee9faa796a2a615fe2450273c6340ef53
author: menno <menno>
date: Wed Sep 3 16:19:29 EDT 2003

faad: gapless playback

--- a/frontend/audio.c
+++ b/frontend/audio.c
@@ -22,7 +22,7 @@
 ** Commercial non-GPL licensing of this software is possible.
 ** For more info contact Ahead Software through Mpeg4AAClicense@nero.com.
 **
-** $Id: audio.c,v 1.18 2003/08/14 18:06:05 menno Exp $
+** $Id: audio.c,v 1.19 2003/09/03 20:19:29 menno Exp $
 **/
 
 #ifdef _WIN32
@@ -97,8 +97,9 @@
     return aufile;
 }
 
-int write_audio_file(audio_file *aufile, void *sample_buffer, int samples)
+int write_audio_file(audio_file *aufile, void *sample_buffer, int samples, int offset)
 {
+    char *buf = (char *)sample_buffer;
     switch (aufile->outputFormat)
     {
     case FAAD_FMT_16BIT:
@@ -106,13 +107,13 @@
     case FAAD_FMT_16BIT_L_SHAPE:
     case FAAD_FMT_16BIT_M_SHAPE:
     case FAAD_FMT_16BIT_H_SHAPE:
-        return write_audio_16bit(aufile, sample_buffer, samples);
+        return write_audio_16bit(aufile, buf + offset*2, samples);
     case FAAD_FMT_24BIT:
-        return write_audio_24bit(aufile, sample_buffer, samples);
+        return write_audio_24bit(aufile, buf + offset*4, samples);
     case FAAD_FMT_32BIT:
-        return write_audio_32bit(aufile, sample_buffer, samples);
+        return write_audio_32bit(aufile, buf + offset*4, samples);
     case FAAD_FMT_FLOAT:
-        return write_audio_float(aufile, sample_buffer, samples);
+        return write_audio_float(aufile, buf + offset*4, samples);
     default:
         return 0;
     }
--- a/frontend/audio.h
+++ b/frontend/audio.h
@@ -22,7 +22,7 @@
 ** Commercial non-GPL licensing of this software is possible.
 ** For more info contact Ahead Software through Mpeg4AAClicense@nero.com.
 **
-** $Id: audio.h,v 1.9 2003/07/29 08:20:11 menno Exp $
+** $Id: audio.h,v 1.10 2003/09/03 20:19:29 menno Exp $
 **/
 
 #ifndef AUDIO_H_INCLUDED
@@ -51,7 +51,7 @@
 
 audio_file *open_audio_file(char *infile, int samplerate, int channels,
                             int outputFormat, int fileType, long channelMask);
-int write_audio_file(audio_file *aufile, void *sample_buffer, int samples);
+int write_audio_file(audio_file *aufile, void *sample_buffer, int samples, int offset);
 void close_audio_file(audio_file *aufile);
 static int write_wav_header(audio_file *aufile);
 static int write_wav_extensible_header(audio_file *aufile, long channelMask);
--- a/frontend/main.c
+++ b/frontend/main.c
@@ -22,7 +22,7 @@
 ** Commercial non-GPL licensing of this software is possible.
 ** For more info contact Ahead Software through Mpeg4AAClicense@nero.com.
 **
-** $Id: main.c,v 1.44 2003/08/02 18:07:39 menno Exp $
+** $Id: main.c,v 1.45 2003/09/03 20:19:29 menno Exp $
 **/
 
 #ifdef _WIN32
@@ -290,6 +290,7 @@
     fprintf(stdout, "        23: LD (Low Delay) object type.\n");
     fprintf(stdout, " -d    Down matrix 5.1 to 2 channels\n");
     fprintf(stdout, " -w    Write output to stdio instead of a file.\n");
+    fprintf(stdout, " -g    Disable gapless decoding.\n");
     fprintf(stdout, "Example:\n");
     fprintf(stdout, "       faad infile.aac\n");
     fprintf(stdout, "       faad infile.mp4\n");
@@ -506,7 +507,7 @@
 
         if ((frameInfo.error == 0) && (frameInfo.samples > 0))
         {
-            write_audio_file(aufile, sample_buffer, frameInfo.samples);
+            write_audio_file(aufile, sample_buffer, frameInfo.samples, 0);
         }
 
         /* fill buffer */
@@ -573,7 +574,7 @@
 };
 
 int decodeMP4file(char *mp4file, char *sndfile, int to_stdout,
-                  int outputFormat, int fileType, int downMatrix, int infoOnly)
+                  int outputFormat, int fileType, int downMatrix, int noGapless, int infoOnly)
 {
     int track;
     unsigned long samplerate;
@@ -597,6 +598,12 @@
 
     int first_time = 1;
 
+    /* for gapless decoding */
+    unsigned int useAacLength = 1;
+    unsigned int framesize;
+    unsigned int initial = 1;
+    unsigned long timescale;
+
     hDecoder = faacDecOpen();
 
     /* Set configuration */
@@ -649,6 +656,25 @@
         MP4Close(infile);
         return 1;
     }
+
+    if (!noGapless)
+    {
+        mp4AudioSpecificConfig mp4ASC;
+
+        timescale = MP4GetTrackTimeScale(infile, track);
+        framesize = 1024;
+        useAacLength = 0;
+
+        if (buffer)
+        {
+            if (AudioSpecificConfig(buffer, buffer_size, &mp4ASC) >= 0)
+            {
+                if (mp4ASC.frameLengthFlag == 1) framesize = 960;
+                if (mp4ASC.sbr_present_flag == 1) framesize *= 2;
+            }
+        }
+    }
+
     if (buffer) free(buffer);
 
     numSamples = MP4GetTrackNumberOfSamples(infile, track);
@@ -656,6 +682,9 @@
     for (sampleId = 1; sampleId <= numSamples; sampleId++)
     {
         int rc;
+        MP4Duration dur;
+        unsigned int sample_count;
+        unsigned int delay = 0;
 
         /* get acces unit from MP4 file */
         buffer = NULL;
@@ -662,7 +691,7 @@
         buffer_size = 0;
 
         rc = MP4ReadSample(infile, track, sampleId, &buffer, &buffer_size,
-            NULL, NULL, NULL, NULL);
+            NULL, &dur, NULL, NULL);
         if (rc == 0)
         {
             fprintf(stderr, "Reading from MP4 file failed.\n");
@@ -675,6 +704,28 @@
 
         if (buffer) free(buffer);
 
+        if (!noGapless)
+        {
+            if (useAacLength || (timescale != samplerate)) {
+                sample_count = frameInfo.samples;
+            } else {
+                sample_count = (unsigned int)(dur * frameInfo.channels);
+
+                if (!useAacLength && !initial && (sampleId < numSamples/2) && (sample_count != frameInfo.samples))
+                {
+                    fprintf(stderr, "MP4 seems to have incorrect frame duration, using values from AAC data.\n");
+                    useAacLength = 1;
+                }
+            }
+
+            if (initial && (sample_count < framesize*frameInfo.channels))
+                delay = frameInfo.samples - sample_count;
+        }
+        else
+        {
+            sample_count = frameInfo.samples;
+        }
+
         /* open the sound file now that the number of channels are known */
         if (first_time && !frameInfo.error)
         {
@@ -702,6 +753,8 @@
             first_time = 0;
         }
 
+        if (sample_count > 0) initial = 0;
+
         percent = min((int)(sampleId*100)/numSamples, 100);
         if (percent > old_percent)
         {
@@ -713,9 +766,9 @@
 #endif
         }
 
-        if ((frameInfo.error == 0) && (frameInfo.samples > 0))
+        if ((frameInfo.error == 0) && (sample_count > 0))
         {
-            write_audio_file(aufile, sample_buffer, frameInfo.samples);
+            write_audio_file(aufile, sample_buffer, sample_count, delay);
         }
 
         if (frameInfo.error > 0)
@@ -749,6 +802,7 @@
     int outfile_set = 0;
     int showHelp = 0;
     int mp4file = 0;
+    int noGapless = 0;
     char *fnp;
     char aacFileName[255];
     char audioFileName[255];
@@ -789,10 +843,11 @@
             { "downmix",    0, 0, 'd' },
             { "info",       0, 0, 'i' },
             { "stdio",      0, 0, 'w' },
+            { "stdio",      0, 0, 'g' },
             { "help",       0, 0, 'h' }
         };
 
-        c = getopt_long(argc, argv, "o:s:f:b:l:wdhi",
+        c = getopt_long(argc, argv, "o:s:f:b:l:wgdhi",
             long_options, &option_index);
 
         if (c == -1)
@@ -862,6 +917,9 @@
         case 'w':
             writeToStdio = 1;
             break;
+        case 'g':
+            noGapless = 1;
+            break;
         case 'i':
             infoOnly = 1;
             break;
@@ -914,7 +972,7 @@
     if (mp4file)
     {
         result = decodeMP4file(aacFileName, audioFileName, writeToStdio,
-            outputFormat, format, downMatrix, infoOnly);
+            outputFormat, format, downMatrix, noGapless, infoOnly);
     } else {
         result = decodeAACfile(aacFileName, audioFileName, writeToStdio,
             def_srate, object_type, outputFormat, format, downMatrix, infoOnly);