aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMax Horn2007-02-20 23:40:46 +0000
committerMax Horn2007-02-20 23:40:46 +0000
commitcb40356a7bd34f3ad3c32ea6fea86f52545746f3 (patch)
treec2bf011af478b68a4bcba3fb6a1ac3a63f6ef9c4
parent42745b188eb239b726ebfc086e6964247859890f (diff)
downloadscummvm-rg350-cb40356a7bd34f3ad3c32ea6fea86f52545746f3.tar.gz
scummvm-rg350-cb40356a7bd34f3ad3c32ea6fea86f52545746f3.tar.bz2
scummvm-rg350-cb40356a7bd34f3ad3c32ea6fea86f52545746f3.zip
Revamed the Ogg Vorbis & FLAC DigitalTrackInfo subclasses to work similar to the MP3 one (i.e. only open the data file when about to play)
svn-id: r25757
-rw-r--r--sound/flac.cpp72
-rw-r--r--sound/mp3.cpp26
-rw-r--r--sound/vorbis.cpp223
3 files changed, 153 insertions, 168 deletions
diff --git a/sound/flac.cpp b/sound/flac.cpp
index 94398a6946..b68393fffc 100644
--- a/sound/flac.cpp
+++ b/sound/flac.cpp
@@ -874,41 +874,57 @@ void FlacInputStream::callWrapError(const ::FLAC__SeekableStreamDecoder *decoder
class FlacTrackInfo : public DigitalTrackInfo {
private:
- File *_file;
- FlacInputStream *_firstStream; // avoid having to open the Stream twice the first time
+ Common::String _filename;
+ bool _errorFlag;
public:
- FlacTrackInfo(File *file);
- ~FlacTrackInfo();
- bool error() { return _file == NULL; }
+ FlacTrackInfo(const char *filename);
+ bool error() { return _errorFlag; }
void play(Audio::Mixer *mixer, Audio::SoundHandle *handle, int startFrame, int duration);
};
-FlacTrackInfo::FlacTrackInfo(File *file) : _file(NULL), _firstStream(NULL) {
- FlacInputStream *tempStream = new FlacInputStream(file);
- /* first time the file will be tested, but not used */
- if (tempStream->init()) {
- _firstStream = tempStream;
- _file = file;
- } else
- delete tempStream;
+FlacTrackInfo::FlacTrackInfo(const char *filename) :
+ _filename(filename),
+ _errorFlag(false) {
+
+ // Try to open the file
+ Common::File file;
+ if (!file.open(_filename)) {
+ _errorFlag = true;
+ return;
+ }
+
+ // Next, try to create a FlacInputStream from it
+ FlacInputStream *tempStream = new FlacInputStream(&file);
+
+ // If initialising the stream fails, we set the error flag
+ if (!tempStream || !tempStream->init())
+ _errorFlag = true;
+
+ delete tempStream;
}
void FlacTrackInfo::play(Audio::Mixer *mixer, Audio::SoundHandle *handle, int startFrame, int duration) {
+ assert(!_errorFlag);
+
if (error()) {
debug(1, "FlacTrackInfo::play: invalid state, method should not been called");
}
- FlacInputStream *flac;
-
- if (_firstStream != NULL) {
- flac = _firstStream;
- _firstStream = NULL;
- } else {
- flac = new FlacInputStream(_file);
- flac->init();
+ // Open the file
+ Common::File *file = new Common::File();
+ if (!file || !file->open(_filename)) {
+ warning("FlacTrackInfo::play: failed to open '%s'", _filename.c_str());
+ delete file;
+ return;
}
+ // Create an AudioStream from the file
+ FlacInputStream *flac = new FlacInputStream(file);
+ flac->init();
+ file->decRef();
+
+ // Seek to the correct start position and start playback
if (flac->isStreamDecoderReady()) {
const FLAC__StreamMetadata_StreamInfo &info = flac->getStreamInfo();
if (duration)
@@ -921,38 +937,30 @@ void FlacTrackInfo::play(Audio::Mixer *mixer, Audio::SoundHandle *handle, int st
return;
}
// startSample is beyond the existing Samples
- debug(1, "FlacTrackInfo: Audiostream %s could not seek to frame %d (ca %d secs)", _file->name(), startFrame, startFrame/75);
+ debug(1, "FlacTrackInfo: Audiostream %s could not seek to frame %d (ca %d secs)", _filename.c_str(), startFrame, startFrame/75);
flac->finish();
}
delete flac;
}
-FlacTrackInfo::~FlacTrackInfo() {
- delete _firstStream;
- delete _file;
-}
-
DigitalTrackInfo* getFlacTrack(int track) {
assert(track >= 1);
char trackName[4][32];
- File *file = new File();
sprintf(trackName[0], "track%d.flac", track);
sprintf(trackName[1], "track%02d.flac", track);
sprintf(trackName[2], "track%d.fla", track);
sprintf(trackName[3], "track%02d.fla", track);
-
for (int i = 0; i < 4; ++i) {
- if (file->open(trackName[i])) {
- FlacTrackInfo *trackInfo = new FlacTrackInfo(file);
+ if (Common::File::exists(trackName[i])) {
+ FlacTrackInfo *trackInfo = new FlacTrackInfo(trackName[i]);
if (!trackInfo->error())
return trackInfo;
delete trackInfo;
}
}
- delete file;
return NULL;
}
diff --git a/sound/mp3.cpp b/sound/mp3.cpp
index 1ac43cdfd5..7fbcb44b5f 100644
--- a/sound/mp3.cpp
+++ b/sound/mp3.cpp
@@ -167,7 +167,7 @@ void MP3InputStream::decodeMP3Data() {
if (_stream.error == MAD_ERROR_BUFLEN) {
break; // Read more data
} else if (MAD_RECOVERABLE(_stream.error)) {
- debug(1, "MP3InputStream: Recoverable error in mad_header_decode (%s)", mad_stream_errorstr(&_stream));
+ debug(6, "MP3InputStream: Recoverable error in mad_header_decode (%s)", mad_stream_errorstr(&_stream));
continue;
} else {
warning("MP3InputStream: Unrecoverable error in mad_header_decode (%s)", mad_stream_errorstr(&_stream));
@@ -193,8 +193,10 @@ void MP3InputStream::decodeMP3Data() {
if (_stream.error == MAD_ERROR_BUFLEN) {
break; // Read more data
} else if (MAD_RECOVERABLE(_stream.error)) {
- // FIXME: should we do anything here?
- debug(1, "MP3InputStream: Recoverable error in mad_frame_decode (%s)", mad_stream_errorstr(&_stream));
+ // Note: we will occasionally see MAD_ERROR_BADDATAPTR errors here.
+ // These are normal and expected (caused by our frame skipping (i.e. "seeking")
+ // code above).
+ debug(6, "MP3InputStream: Recoverable error in mad_frame_decode (%s)", mad_stream_errorstr(&_stream));
continue;
} else {
warning("MP3InputStream: Unrecoverable error in mad_frame_decode (%s)", mad_stream_errorstr(&_stream));
@@ -351,27 +353,27 @@ MP3TrackInfo::MP3TrackInfo(const char *filename) :
_filename(filename),
_errorFlag(false) {
- Common::File file;
-
// Try to open the file
+ Common::File file;
if (!file.open(_filename)) {
_errorFlag = true;
return;
}
- // Next, try to create a MP3InputStream from it
-
- MP3InputStream *mp3Stream = new MP3InputStream(&file, false);
+ // Next, try to create an MP3InputStream from it
+ MP3InputStream *tempStream = new MP3InputStream(&file, false);
// If we see EOS here then that means that not (enough) valid input
// data was given.
- _errorFlag = mp3Stream->endOfData();
+ _errorFlag = tempStream->endOfData();
// Clean up again
- delete mp3Stream;
+ delete tempStream;
}
void MP3TrackInfo::play(Audio::Mixer *mixer, Audio::SoundHandle *handle, int startFrame, int duration) {
+ assert(!_errorFlag);
+
mad_timer_t start;
mad_timer_t end;
@@ -389,12 +391,14 @@ void MP3TrackInfo::play(Audio::Mixer *mixer, Audio::SoundHandle *handle, int sta
Common::File *file = new Common::File();
if (!file || !file->open(_filename)) {
warning("MP3TrackInfo::play: failed to open '%s'", _filename.c_str());
+ delete file;
return;
}
- // Play it
+ // ... create an AudioStream ...
MP3InputStream *input = new MP3InputStream(file, true, start, end);
+ // ... and play it
mixer->playInputStream(Audio::Mixer::kMusicSoundType, handle, input);
}
diff --git a/sound/vorbis.cpp b/sound/vorbis.cpp
index 7f9fd8d41c..7df6fbee8b 100644
--- a/sound/vorbis.cpp
+++ b/sound/vorbis.cpp
@@ -46,8 +46,6 @@ using Common::File;
namespace Audio {
-static AudioStream *makeVorbisStream(OggVorbis_File *file, int duration);
-
// These are wrapper functions to allow using a File object to
// provide data to the OggVorbis_File object.
@@ -129,8 +127,9 @@ static int seek_wrap(void *datasource, ogg_int64_t offset, int whence) {
static int close_wrap(void *datasource) {
file_info *f = (file_info *) datasource;
- f->file->decRef();
+ delete f->file;
delete f;
+
return 0;
}
@@ -146,123 +145,6 @@ static ov_callbacks g_File_wrap = {
#pragma mark -
-#pragma mark --- Ogg Vorbis Audio CD emulation ---
-#pragma mark -
-
-class VorbisTrackInfo : public DigitalTrackInfo {
-private:
- File *_file;
- OggVorbis_File _ov_file;
- bool _error_flag;
-
-public:
- VorbisTrackInfo(File *file);
- ~VorbisTrackInfo();
- bool openTrack();
- bool error() { return _error_flag; }
- void play(Audio::Mixer *mixer, Audio::SoundHandle *handle, int startFrame, int duration);
-};
-
-
-VorbisTrackInfo::VorbisTrackInfo(File *file) {
-//debug(5, "" __FILE__ ":%i", __LINE__);
-
- _file = file;
- if (openTrack()) {
- warning("Invalid file format");
- _error_flag = true;
- _file = 0;
- } else {
- _error_flag = false;
- _file->incRef();
- ov_clear(&_ov_file);
- }
-}
-
-bool VorbisTrackInfo::openTrack() {
-//debug(5, "" __FILE__ ":%i", __LINE__);
- assert(_file);
-
- file_info *f = new file_info;
-
-#if defined(__SYMBIAN32__)
- // Symbian can't share filehandles between different threads.
- // So create a new file and seek that to the other filehandles position
- f->file = new File;
- f->file->open(_file->name());
- f->file->seek(_file->pos());
-#else
- f->file = _file;
-#endif
-
- f->start = 0;
- f->len = _file->size();
- f->curr_pos = 0;
- _file->seek(0);
-
- bool err = (ov_open_callbacks((void *) f, &_ov_file, NULL, 0, g_File_wrap) < 0);
- if (err) {
-#ifdef __SYMBIAN32__
- delete f->file;
-#endif
- delete f;
- } else {
-#ifndef __SYMBIAN32__
- _file->incRef();
-#endif
- }
-
- return err;
-}
-
-VorbisTrackInfo::~VorbisTrackInfo() {
-//debug(5, "" __FILE__ ":%i", __LINE__);
- if (! _error_flag) {
- ov_clear(&_ov_file);
- _file->decRef();
- }
-}
-
-void VorbisTrackInfo::play(Audio::Mixer *mixer, Audio::SoundHandle *handle, int startFrame, int duration) {
-//debug(5, "" __FILE__ ":%i", __LINE__);
- bool err = openTrack(); err=err;//satisfy unused variable
- assert(!err);
-
-#ifdef USE_TREMOR // In Tremor, the ov_time_seek() and ov_time_seek_page() calls take seeking positions in milliseconds as 64 bit integers, rather than in seconds as doubles as in Vorbisfile.
-#if defined(__SYMBIAN32__) && defined(__GCC32__) // SumthinWicked says: fixing "relocation truncated to fit: ARM_26 __fixdfdi" during linking on GCC, see portdefs.h
- ov_time_seek(&_ov_file, (ogg_int64_t)scumm_fixdfdi(startFrame / 75.0 * 1000));
-#else
- ov_time_seek(&_ov_file, (ogg_int64_t)(startFrame / 75.0 * 1000));
-#endif
-#else
- ov_time_seek(&_ov_file, startFrame / 75.0);
-#endif
-
- AudioStream *input = makeVorbisStream(&_ov_file, duration * ov_info(&_ov_file, -1)->rate / 75);
- mixer->playInputStream(Audio::Mixer::kMusicSoundType, handle, input);
-}
-
-DigitalTrackInfo *getVorbisTrack(int track) {
- char trackName[2][32];
- File *file = new File();
-
- sprintf(trackName[0], "track%d.ogg", track);
- sprintf(trackName[1], "track%02d.ogg", track);
-
- for (int i = 0; i < 2; ++i) {
- if (file->open(trackName[i])) {
- VorbisTrackInfo *trackInfo = new VorbisTrackInfo(file);
- file->decRef();
- if (!trackInfo->error())
- return trackInfo;
- delete trackInfo;
- }
- }
- delete file;
- return NULL;
-}
-
-#pragma mark -
#pragma mark --- Ogg Vorbis stream ---
#pragma mark -
@@ -376,11 +258,6 @@ void VorbisInputStream::refill() {
_bufferEnd = (int16 *)read_pos;
}
-static AudioStream *makeVorbisStream(OggVorbis_File *file, int duration) {
-//debug(5, "" __FILE__ ":%i", __LINE__);
- return new VorbisInputStream(file, duration, false);
-}
-
AudioStream *makeVorbisStream(File *file, uint32 size) {
//debug(5, "" __FILE__ ":%i", __LINE__);
OggVorbis_File *ov_file = new OggVorbis_File;
@@ -413,6 +290,102 @@ AudioStream *makeVorbisStream(File *file, uint32 size) {
}
+#pragma mark -
+#pragma mark --- Ogg Vorbis Audio CD emulation ---
+#pragma mark -
+
+class VorbisTrackInfo : public DigitalTrackInfo {
+private:
+ Common::String _filename;
+ bool _errorFlag;
+
+public:
+ VorbisTrackInfo(const char *filename);
+ bool openTrack(OggVorbis_File *ovFile);
+ bool error() { return _errorFlag; }
+ void play(Audio::Mixer *mixer, Audio::SoundHandle *handle, int startFrame, int duration);
+};
+
+
+VorbisTrackInfo::VorbisTrackInfo(const char *filename) :
+ _filename(filename),
+ _errorFlag(false) {
+
+ OggVorbis_File ov_file;
+ _errorFlag = openTrack(&ov_file);
+
+ if (!_errorFlag)
+ ov_clear(&ov_file);
+}
+
+bool VorbisTrackInfo::openTrack(OggVorbis_File *ovFile) {
+ bool err;
+
+ file_info *f = new file_info;
+ assert(f);
+ f->file = new File;
+ assert(f->file);
+
+ err = !f->file->open(_filename);
+
+ if (!err) {
+ f->start = 0;
+ f->len = f->file->size();
+ f->curr_pos = 0;
+
+ err = (ov_open_callbacks((void *) f, ovFile, NULL, 0, g_File_wrap) < 0);
+ }
+
+ if (err) {
+ delete f->file;
+ delete f;
+ }
+
+ return err;
+}
+
+void VorbisTrackInfo::play(Audio::Mixer *mixer, Audio::SoundHandle *handle, int startFrame, int duration) {
+ OggVorbis_File *ovFile = new OggVorbis_File;
+ bool err = openTrack(ovFile);
+ assert(!err);
+
+#ifdef USE_TREMOR
+ // In Tremor, the ov_time_seek() and ov_time_seek_page() calls take seeking
+ // positions in milliseconds as 64 bit integers, rather than in seconds as
+ // doubles as in Vorbisfile.
+#if defined(__SYMBIAN32__) && defined(__GCC32__)
+ // SumthinWicked says: fixing "relocation truncated to fit: ARM_26 __fixdfdi" during linking on GCC, see portdefs.h
+ ov_time_seek(ovFile, (ogg_int64_t)scumm_fixdfdi(startFrame / 75.0 * 1000));
+#else
+ ov_time_seek(ovFile, (ogg_int64_t)(startFrame / 75.0 * 1000));
+#endif
+#else
+ ov_time_seek(ovFile, startFrame / 75.0);
+#endif
+
+ AudioStream *input = new VorbisInputStream(ovFile, duration * ov_info(ovFile, -1)->rate / 75, true);
+ mixer->playInputStream(Audio::Mixer::kMusicSoundType, handle, input);
+}
+
+DigitalTrackInfo *getVorbisTrack(int track) {
+ char trackName[2][32];
+
+ sprintf(trackName[0], "track%d.ogg", track);
+ sprintf(trackName[1], "track%02d.ogg", track);
+
+ for (int i = 0; i < 2; ++i) {
+ if (Common::File::exists(trackName[i])) {
+ VorbisTrackInfo *trackInfo = new VorbisTrackInfo(trackName[i]);
+ if (!trackInfo->error())
+ return trackInfo;
+ delete trackInfo;
+ }
+ }
+ return NULL;
+}
+
+
+
} // End of namespace Audio
#endif // #ifdef USE_VORBIS