mirror of
https://github.com/libretro/scummvm.git
synced 2024-12-15 14:18:37 +00:00
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
This commit is contained in:
parent
42745b188e
commit
cb40356a7b
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
223
sound/vorbis.cpp
223
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;
|
||||
}
|
||||
|
||||
@ -145,123 +144,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
|
||||
|
Loading…
Reference in New Issue
Block a user