Add monster.sog support, patch #629362
Enable ogg support by default in mingw builds and link in ogg lib svn-id: r5333
This commit is contained in:
parent
d5473c6f5a
commit
a0734ef3f9
5 changed files with 138 additions and 17 deletions
|
@ -36,8 +36,8 @@ DEFINES += -DUSE_MAD
|
||||||
LIBS += -lmad
|
LIBS += -lmad
|
||||||
|
|
||||||
# Uncomment this to activate the Ogg Vorbis lib for compressed sound files
|
# Uncomment this to activate the Ogg Vorbis lib for compressed sound files
|
||||||
# DEFINES += -DUSE_VORBIS
|
DEFINES += -DUSE_VORBIS
|
||||||
# LIBS += -lvorbisfile -lvorbis
|
LIBS += -lvorbisfile -lvorbis -logg
|
||||||
|
|
||||||
# Uncomment this to activate extended debugging support in Simon
|
# Uncomment this to activate extended debugging support in Simon
|
||||||
DEFINES += -DSIMONDEBUG
|
DEFINES += -DSIMONDEBUG
|
||||||
|
|
120
scumm/sound.cpp
120
scumm/sound.cpp
|
@ -738,16 +738,24 @@ int Sound::startSfxSound(File *file, int file_size) {
|
||||||
int rate, comp;
|
int rate, comp;
|
||||||
byte *data;
|
byte *data;
|
||||||
|
|
||||||
#ifdef USE_MAD
|
#ifdef COMPRESSED_SOUND_FILE
|
||||||
if (file_size > 0) {
|
if (file_size > 0) {
|
||||||
data = (byte *)calloc(file_size + MAD_BUFFER_GUARD, 1);
|
int alloc_size = file_size;
|
||||||
|
#ifdef USE_MAD
|
||||||
|
if (! _vorbis_mode)
|
||||||
|
alloc_size += MAD_BUFFER_GUARD;
|
||||||
|
#endif
|
||||||
|
data = (byte *)calloc(alloc_size, 1);
|
||||||
|
|
||||||
if (file->read(data, file_size) != (uint)file_size) {
|
if (file->read(data, file_size) != (uint)file_size) {
|
||||||
/* no need to free the memory since error will shut down */
|
/* no need to free the memory since error will shut down */
|
||||||
error("startSfxSound: cannot read %d bytes", size);
|
error("startSfxSound: cannot read %d bytes", size);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
return playSfxSound_MP3(data, file_size);
|
if (_vorbis_mode)
|
||||||
|
return playSfxSound_Vorbis(data, file_size);
|
||||||
|
else
|
||||||
|
return playSfxSound_MP3(data, file_size);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
if (file->read(ident, 8) != 8)
|
if (file->read(ident, 8) != 8)
|
||||||
|
@ -805,10 +813,25 @@ File * Sound::openSfxFile() {
|
||||||
#ifdef COMPRESSED_SOUND_FILE
|
#ifdef COMPRESSED_SOUND_FILE
|
||||||
offset_table = NULL;
|
offset_table = NULL;
|
||||||
|
|
||||||
|
#ifdef USE_MAD
|
||||||
sprintf(buf, "%s.so3", _scumm->_exe_name);
|
sprintf(buf, "%s.so3", _scumm->_exe_name);
|
||||||
if (!file->open(buf, _scumm->getGameDataPath())) {
|
if (!file->open(buf, _scumm->getGameDataPath())) {
|
||||||
file->open("monster.so3", _scumm->getGameDataPath());
|
file->open("monster.so3", _scumm->getGameDataPath());
|
||||||
}
|
}
|
||||||
|
if (file->isOpen())
|
||||||
|
_vorbis_mode = false;
|
||||||
|
else
|
||||||
|
#endif
|
||||||
|
#ifdef USE_VORBIS
|
||||||
|
{
|
||||||
|
sprintf(buf, "%s.sog", _scumm->_exe_name);
|
||||||
|
if (!file->open(buf, _scumm->getGameDataPath()))
|
||||||
|
file->open("monster.sog", _scumm->getGameDataPath());
|
||||||
|
if (file->isOpen())
|
||||||
|
_vorbis_mode = true;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
if (file->isOpen() == true) {
|
if (file->isOpen() == true) {
|
||||||
/* Now load the 'offset' index in memory to be able to find the MP3 data
|
/* Now load the 'offset' index in memory to be able to find the MP3 data
|
||||||
|
|
||||||
|
@ -1124,6 +1147,91 @@ int Sound::playSfxSound_MP3(void *sound, uint32 size) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef USE_VORBIS
|
||||||
|
// Provide a virtual file to vorbisfile based on preloaded data
|
||||||
|
struct data_file_info {
|
||||||
|
char *data;
|
||||||
|
uint32 size;
|
||||||
|
int curr_pos;
|
||||||
|
};
|
||||||
|
|
||||||
|
static size_t read_data(void *ptr, size_t size, size_t nmemb, void *datasource) {
|
||||||
|
data_file_info *f = (data_file_info *) datasource;
|
||||||
|
|
||||||
|
nmemb *= size;
|
||||||
|
if (f->curr_pos < 0)
|
||||||
|
return (size_t) -1;
|
||||||
|
if (f->curr_pos > (int) f->size)
|
||||||
|
nmemb = 0;
|
||||||
|
else if (f->curr_pos + nmemb > f->size)
|
||||||
|
nmemb = f->size - f->curr_pos;
|
||||||
|
|
||||||
|
memcpy(ptr, f->data + f->curr_pos, nmemb);
|
||||||
|
f->curr_pos += nmemb;
|
||||||
|
return nmemb / size;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int seek_data(void *datasource, ogg_int64_t offset, int whence) {
|
||||||
|
data_file_info *f = (data_file_info *) datasource;
|
||||||
|
|
||||||
|
switch (whence) {
|
||||||
|
case SEEK_SET:
|
||||||
|
f->curr_pos = offset;
|
||||||
|
break;
|
||||||
|
case SEEK_CUR:
|
||||||
|
f->curr_pos += offset;
|
||||||
|
break;
|
||||||
|
case SEEK_END:
|
||||||
|
f->curr_pos = f->size + offset;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return f->curr_pos;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int close_data(void *datasource) {
|
||||||
|
data_file_info *f = (data_file_info *) datasource;
|
||||||
|
|
||||||
|
free(f->data);
|
||||||
|
delete f;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static long tell_data(void *datasource) {
|
||||||
|
data_file_info *f = (data_file_info *) datasource;
|
||||||
|
|
||||||
|
return f->curr_pos;
|
||||||
|
}
|
||||||
|
|
||||||
|
static ov_callbacks data_wrap = {
|
||||||
|
read_data, seek_data, close_data, tell_data
|
||||||
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
|
int Sound::playSfxSound_Vorbis(void *sound, uint32 size) {
|
||||||
|
#ifdef USE_VORBIS
|
||||||
|
if (_soundsPaused)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
OggVorbis_File *ov_file = new OggVorbis_File;
|
||||||
|
data_file_info *f = new data_file_info;
|
||||||
|
f->data = (char *) sound;
|
||||||
|
f->size = size;
|
||||||
|
f->curr_pos = 0;
|
||||||
|
|
||||||
|
if (ov_open_callbacks((void *) f, ov_file, NULL, 0, data_wrap) < 0) {
|
||||||
|
warning("Invalid file format");
|
||||||
|
delete ov_file;
|
||||||
|
delete f;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return _scumm->_mixer->playVorbis(NULL, ov_file, 0, false);
|
||||||
|
#endif
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
// We use a real timer in an attempt to get better sync with CD tracks. This is
|
// We use a real timer in an attempt to get better sync with CD tracks. This is
|
||||||
// necessary for games like Loom CD.
|
// necessary for games like Loom CD.
|
||||||
|
|
||||||
|
@ -1525,8 +1633,10 @@ Sound::VorbisTrackInfo::VorbisTrackInfo(File *file) {
|
||||||
}
|
}
|
||||||
|
|
||||||
int Sound::VorbisTrackInfo::play(SoundMixer *mixer, int start, int delay) {
|
int Sound::VorbisTrackInfo::play(SoundMixer *mixer, int start, int delay) {
|
||||||
ov_time_seek(&_ov_file, start / 75.0);
|
ov_pcm_seek(&_ov_file, start * ov_info(&_ov_file, -1)->rate / 75);
|
||||||
return mixer->playVorbisCDTrack(NULL, &_ov_file, delay / 75.0);
|
return mixer->playVorbis(NULL, &_ov_file,
|
||||||
|
delay * ov_info(&_ov_file, -1)->rate / 75,
|
||||||
|
true);
|
||||||
}
|
}
|
||||||
|
|
||||||
Sound::VorbisTrackInfo::~VorbisTrackInfo() {
|
Sound::VorbisTrackInfo::~VorbisTrackInfo() {
|
||||||
|
|
|
@ -68,6 +68,7 @@ enum {
|
||||||
#ifdef COMPRESSED_SOUND_FILE
|
#ifdef COMPRESSED_SOUND_FILE
|
||||||
MP3OffsetTable *offset_table; // SO3 MP3 compressed audio
|
MP3OffsetTable *offset_table; // SO3 MP3 compressed audio
|
||||||
int num_sound_effects; // SO3 MP3 compressed audio
|
int num_sound_effects; // SO3 MP3 compressed audio
|
||||||
|
bool _vorbis_mode; // true if using SOG, false if using SO3
|
||||||
|
|
||||||
#define CACHE_TRACKS 10
|
#define CACHE_TRACKS 10
|
||||||
|
|
||||||
|
@ -171,6 +172,7 @@ public:
|
||||||
byte * readCreativeVocFile(byte * ptr, uint32 & size, uint32 & rate, uint32 & loops);
|
byte * readCreativeVocFile(byte * ptr, uint32 & size, uint32 & rate, uint32 & loops);
|
||||||
int playSfxSound(void *sound, uint32 size, uint rate, bool isUnsigned);
|
int playSfxSound(void *sound, uint32 size, uint rate, bool isUnsigned);
|
||||||
int playSfxSound_MP3(void *sound, uint32 size);
|
int playSfxSound_MP3(void *sound, uint32 size);
|
||||||
|
int playSfxSound_Vorbis(void *sound, uint32 size);
|
||||||
|
|
||||||
int readCDTimer();
|
int readCDTimer();
|
||||||
void startCDTimer();
|
void startCDTimer();
|
||||||
|
|
|
@ -145,10 +145,10 @@ int SoundMixer::playMP3CDTrack(PlayingSoundHandle * handle, File * file, mad_tim
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef USE_VORBIS
|
#ifdef USE_VORBIS
|
||||||
int SoundMixer::playVorbisCDTrack(PlayingSoundHandle * handle, OggVorbis_File * ov_file, double duration) {
|
int SoundMixer::playVorbis(PlayingSoundHandle * handle, OggVorbis_File * ov_file, int duration, bool is_cd_track) {
|
||||||
for (int i = _beginSlots; i != NUM_CHANNELS; i++) {
|
for (int i = _beginSlots; i != NUM_CHANNELS; i++) {
|
||||||
if (_channels[i] == NULL) {
|
if (_channels[i] == NULL) {
|
||||||
return insertAt(handle, i, new ChannelVorbis(this, ov_file, duration));
|
return insertAt(handle, i, new ChannelVorbis(this, ov_file, duration, is_cd_track));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -977,16 +977,17 @@ void SoundMixer::ChannelMP3CDMusic::realDestroy() {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef USE_VORBIS
|
#ifdef USE_VORBIS
|
||||||
SoundMixer::ChannelVorbis::ChannelVorbis(SoundMixer * mixer, OggVorbis_File * ov_file, double duration) {
|
SoundMixer::ChannelVorbis::ChannelVorbis(SoundMixer * mixer, OggVorbis_File * ov_file, int duration, bool is_cd_track) {
|
||||||
_mixer = mixer;
|
_mixer = mixer;
|
||||||
_ov_file = ov_file;
|
_ov_file = ov_file;
|
||||||
|
|
||||||
if (duration)
|
if (duration)
|
||||||
_end_pos = ov_time_tell(ov_file) + duration;
|
_end_pos = ov_pcm_tell(ov_file) + duration;
|
||||||
else
|
else
|
||||||
_end_pos = 0;
|
_end_pos = 0;
|
||||||
|
|
||||||
_eof_flag = false;
|
_eof_flag = false;
|
||||||
|
_is_cd_track = is_cd_track;
|
||||||
_toBeDestroyed = false;
|
_toBeDestroyed = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1005,7 +1006,8 @@ void SoundMixer::ChannelVorbis::mix(int16 * data, uint len) {
|
||||||
uint len_left = len * channels * 2;
|
uint len_left = len * channels * 2;
|
||||||
int16 *samples = new int16[len_left / 2];
|
int16 *samples = new int16[len_left / 2];
|
||||||
char *read_pos = (char *) samples;
|
char *read_pos = (char *) samples;
|
||||||
int volume = _mixer->_musicVolume;
|
int volume = _is_cd_track ? _mixer->_musicVolume :
|
||||||
|
_mixer->_volumeTable[1];
|
||||||
|
|
||||||
// Read the samples
|
// Read the samples
|
||||||
while (len_left > 0) {
|
while (len_left > 0) {
|
||||||
|
@ -1021,6 +1023,10 @@ void SoundMixer::ChannelVorbis::mix(int16 * data, uint len) {
|
||||||
memset(read_pos, 0, len_left);
|
memset(read_pos, 0, len_left);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
else if (result == OV_HOLE) {
|
||||||
|
// Possibly recoverable, just warn about it
|
||||||
|
warning("Corrupted data in Vorbis file");
|
||||||
|
}
|
||||||
else if (result < 0) {
|
else if (result < 0) {
|
||||||
debug(1, "Decode error %d in Vorbis file", result);
|
debug(1, "Decode error %d in Vorbis file", result);
|
||||||
// Don't delete it yet, that causes problems in
|
// Don't delete it yet, that causes problems in
|
||||||
|
@ -1045,6 +1051,9 @@ void SoundMixer::ChannelVorbis::mix(int16 * data, uint len) {
|
||||||
}
|
}
|
||||||
|
|
||||||
delete [] samples;
|
delete [] samples;
|
||||||
|
|
||||||
|
if (_eof_flag && ! _is_cd_track)
|
||||||
|
realDestroy();
|
||||||
}
|
}
|
||||||
|
|
||||||
void SoundMixer::ChannelVorbis::realDestroy() {
|
void SoundMixer::ChannelVorbis::realDestroy() {
|
||||||
|
@ -1054,7 +1063,7 @@ void SoundMixer::ChannelVorbis::realDestroy() {
|
||||||
|
|
||||||
bool SoundMixer::ChannelVorbis::soundFinished() {
|
bool SoundMixer::ChannelVorbis::soundFinished() {
|
||||||
return _eof_flag || (_end_pos > 0 &&
|
return _eof_flag || (_end_pos > 0 &&
|
||||||
ov_time_tell(_ov_file) >= _end_pos);
|
ov_pcm_tell(_ov_file) >= _end_pos);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -146,11 +146,11 @@ private:
|
||||||
class ChannelVorbis : public Channel {
|
class ChannelVorbis : public Channel {
|
||||||
SoundMixer * _mixer;
|
SoundMixer * _mixer;
|
||||||
OggVorbis_File * _ov_file;
|
OggVorbis_File * _ov_file;
|
||||||
double _end_pos;
|
int _end_pos;
|
||||||
bool _eof_flag;
|
bool _eof_flag, _is_cd_track;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
ChannelVorbis(SoundMixer * mixer, OggVorbis_File * ov_file, double duration);
|
ChannelVorbis(SoundMixer * mixer, OggVorbis_File * ov_file, int duration, bool is_cd_track);
|
||||||
|
|
||||||
void mix(int16 * data, uint len);
|
void mix(int16 * data, uint len);
|
||||||
void realDestroy();
|
void realDestroy();
|
||||||
|
@ -212,7 +212,7 @@ public:
|
||||||
int playMP3CDTrack(PlayingSoundHandle * handle, File * file, mad_timer_t duration);
|
int playMP3CDTrack(PlayingSoundHandle * handle, File * file, mad_timer_t duration);
|
||||||
#endif
|
#endif
|
||||||
#ifdef USE_VORBIS
|
#ifdef USE_VORBIS
|
||||||
int playVorbisCDTrack(PlayingSoundHandle * handle, OggVorbis_File * ov_file, double duration);
|
int playVorbis(PlayingSoundHandle * handle, OggVorbis_File * ov_file, int duration, bool is_cd_track);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Premix procedure, useful when using fmopl adlib */
|
/* Premix procedure, useful when using fmopl adlib */
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue