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);