aboutsummaryrefslogtreecommitdiff
path: root/engines/agos/sound.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'engines/agos/sound.cpp')
-rw-r--r--engines/agos/sound.cpp326
1 files changed, 132 insertions, 194 deletions
diff --git a/engines/agos/sound.cpp b/engines/agos/sound.cpp
index 4917aefa4d..85c449eafc 100644
--- a/engines/agos/sound.cpp
+++ b/engines/agos/sound.cpp
@@ -22,9 +22,9 @@
#include "common/file.h"
#include "common/memstream.h"
-#include "common/ptr.h"
#include "common/textconsole.h"
#include "common/util.h"
+#include "common/substream.h"
#include "agos/agos.h"
#include "agos/sound.h"
@@ -44,34 +44,39 @@ namespace AGOS {
class BaseSound : Common::NonCopyable {
protected:
- Common::DisposablePtr<Common::File> _file;
+ const Common::String _filename;
uint32 *_offsets;
Audio::Mixer *_mixer;
bool _freeOffsets;
+ Common::SeekableReadStream *getSoundStream(uint sound) const;
public:
- BaseSound(Audio::Mixer *mixer, Common::File *file, uint32 base, bool bigEndian, DisposeAfterUse::Flag disposeFileAfterUse = DisposeAfterUse::YES);
- BaseSound(Audio::Mixer *mixer, Common::File *file, uint32 *offsets, DisposeAfterUse::Flag disposeFileAfterUse = DisposeAfterUse::YES);
+ BaseSound(Audio::Mixer *mixer, const Common::String &filename, uint32 base, bool bigEndian);
+ BaseSound(Audio::Mixer *mixer, const Common::String &filename, uint32 *offsets);
virtual ~BaseSound();
void playSound(uint sound, Audio::Mixer::SoundType type, Audio::SoundHandle *handle, bool loop, int vol = 0) {
playSound(sound, sound, type, handle, loop, vol);
}
- virtual void playSound(uint sound, uint loopSound, Audio::Mixer::SoundType type, Audio::SoundHandle *handle, bool loop, int vol = 0) = 0;
+ virtual void playSound(uint sound, uint loopSound, Audio::Mixer::SoundType type, Audio::SoundHandle *handle, bool loop, int vol = 0);
virtual Audio::AudioStream *makeAudioStream(uint sound) = 0;
};
-BaseSound::BaseSound(Audio::Mixer *mixer, Common::File *file, uint32 base, bool bigEndian, DisposeAfterUse::Flag disposeFileAfterUse)
- : _mixer(mixer), _file(file, disposeFileAfterUse) {
+BaseSound::BaseSound(Audio::Mixer *mixer, const Common::String &filename, uint32 base, bool bigEndian)
+ : _mixer(mixer), _filename(filename), _offsets(NULL) {
uint res = 0;
uint32 size;
- _file->seek(base + sizeof(uint32), SEEK_SET);
+ Common::File file;
+ if (!file.open(_filename))
+ error("BaseSound: Could not open file \"%s\"", filename.c_str());
+
+ file.seek(base + sizeof(uint32), SEEK_SET);
if (bigEndian)
- size = _file->readUint32BE();
+ size = file.readUint32BE();
else
- size = _file->readUint32LE();
+ size = file.readUint32LE();
// The Feeble Files uses set amount of voice offsets
if (size == 0)
@@ -82,24 +87,20 @@ BaseSound::BaseSound(Audio::Mixer *mixer, Common::File *file, uint32 base, bool
_offsets = (uint32 *)malloc(size + sizeof(uint32));
_freeOffsets = true;
- _file->seek(base, SEEK_SET);
+ file.seek(base, SEEK_SET);
for (uint i = 0; i < res; i++) {
if (bigEndian)
- _offsets[i] = base + _file->readUint32BE();
+ _offsets[i] = base + file.readUint32BE();
else
- _offsets[i] = base + _file->readUint32LE();
+ _offsets[i] = base + file.readUint32LE();
}
- // only needed for mp3
- _offsets[res] = _file->size();
+ _offsets[res] = file.size();
}
-BaseSound::BaseSound(Audio::Mixer *mixer, Common::File *file, uint32 *offsets, DisposeAfterUse::Flag disposeFileAfterUse)
- : _mixer(mixer), _file(file, disposeFileAfterUse) {
-
- _offsets = offsets;
- _freeOffsets = false;
+BaseSound::BaseSound(Audio::Mixer *mixer, const Common::String &filename, uint32 *offsets)
+ : _mixer(mixer), _filename(filename), _offsets(offsets), _freeOffsets(false) {
}
BaseSound::~BaseSound() {
@@ -107,6 +108,23 @@ BaseSound::~BaseSound() {
free(_offsets);
}
+Common::SeekableReadStream *BaseSound::getSoundStream(uint sound) const {
+ if (_offsets == NULL)
+ return NULL;
+
+ Common::File *file = new Common::File();
+ if (!file->open(_filename)) {
+ warning("BaseSound::getSoundStream: Could not open file \"%s\"", _filename.c_str());
+ return NULL;
+ }
+
+ int i = 1;
+ while (_offsets[sound + i] == _offsets[sound])
+ i++;
+
+ return new Common::SeekableSubReadStream(file, _offsets[sound], _offsets[sound + i], DisposeAfterUse::YES);
+}
+
///////////////////////////////////////////////////////////////////////////////
#pragma mark -
@@ -218,26 +236,25 @@ static void convertPan(int &pan) {
///////////////////////////////////////////////////////////////////////////////
#pragma mark -
+// TODO: Move to a better place?
+void BaseSound::playSound(uint sound, uint loopSound, Audio::Mixer::SoundType type, Audio::SoundHandle *handle, bool loop, int vol) {
+ convertVolume(vol);
+ _mixer->playStream(type, handle, new LoopingAudioStream(this, sound, loopSound, loop), -1, vol);
+}
+
class WavSound : public BaseSound {
public:
- WavSound(Audio::Mixer *mixer, Common::File *file, uint32 base = 0, DisposeAfterUse::Flag disposeFileAfterUse = DisposeAfterUse::YES)
- : BaseSound(mixer, file, base, false, disposeFileAfterUse) {}
- WavSound(Audio::Mixer *mixer, Common::File *file, uint32 *offsets) : BaseSound(mixer, file, offsets) {}
+ WavSound(Audio::Mixer *mixer, const Common::String &filename, uint32 base = 0)
+ : BaseSound(mixer, filename, base, false) {}
+ WavSound(Audio::Mixer *mixer, const Common::String &filename, uint32 *offsets) : BaseSound(mixer, filename, offsets) {}
Audio::AudioStream *makeAudioStream(uint sound);
- void playSound(uint sound, uint loopSound, Audio::Mixer::SoundType type, Audio::SoundHandle *handle, bool loop, int vol = 0);
};
Audio::AudioStream *WavSound::makeAudioStream(uint sound) {
- if (_offsets == NULL)
+ Common::SeekableReadStream *tmp = getSoundStream(sound);
+ if (!tmp)
return NULL;
-
- _file->seek(_offsets[sound], SEEK_SET);
- return Audio::makeWAVStream(_file.get(), DisposeAfterUse::NO);
-}
-
-void WavSound::playSound(uint sound, uint loopSound, Audio::Mixer::SoundType type, Audio::SoundHandle *handle, bool loop, int vol) {
- convertVolume(vol);
- _mixer->playStream(type, handle, new LoopingAudioStream(this, sound, loopSound, loop), -1, vol);
+ return Audio::makeWAVStream(tmp, DisposeAfterUse::YES);
}
///////////////////////////////////////////////////////////////////////////////
@@ -246,21 +263,16 @@ void WavSound::playSound(uint sound, uint loopSound, Audio::Mixer::SoundType typ
class VocSound : public BaseSound {
const byte _flags;
public:
- VocSound(Audio::Mixer *mixer, Common::File *file, bool isUnsigned, uint32 base = 0, bool bigEndian = false, DisposeAfterUse::Flag disposeFileAfterUse = DisposeAfterUse::YES)
- : BaseSound(mixer, file, base, bigEndian, disposeFileAfterUse), _flags(isUnsigned ? Audio::FLAG_UNSIGNED : 0) {}
+ VocSound(Audio::Mixer *mixer, const Common::String &filename, bool isUnsigned, uint32 base = 0, bool bigEndian = false)
+ : BaseSound(mixer, filename, base, bigEndian), _flags(isUnsigned ? Audio::FLAG_UNSIGNED : 0) {}
Audio::AudioStream *makeAudioStream(uint sound);
- void playSound(uint sound, uint loopSound, Audio::Mixer::SoundType type, Audio::SoundHandle *handle, bool loop, int vol = 0);
};
Audio::AudioStream *VocSound::makeAudioStream(uint sound) {
- assert(_offsets);
- _file->seek(_offsets[sound], SEEK_SET);
- return Audio::makeVOCStream(_file.get(), _flags);
-}
-
-void VocSound::playSound(uint sound, uint loopSound, Audio::Mixer::SoundType type, Audio::SoundHandle *handle, bool loop, int vol) {
- convertVolume(vol);
- _mixer->playStream(type, handle, new LoopingAudioStream(this, sound, loopSound, loop), -1, vol);
+ Common::SeekableReadStream *tmp = getSoundStream(sound);
+ if (!tmp)
+ return NULL;
+ return Audio::makeVOCStream(tmp, _flags, DisposeAfterUse::YES);
}
///////////////////////////////////////////////////////////////////////////////
@@ -270,8 +282,8 @@ void VocSound::playSound(uint sound, uint loopSound, Audio::Mixer::SoundType typ
class RawSound : public BaseSound {
const byte _flags;
public:
- RawSound(Audio::Mixer *mixer, Common::File *file, bool isUnsigned)
- : BaseSound(mixer, file, 0, SOUND_BIG_ENDIAN), _flags(isUnsigned ? Audio::FLAG_UNSIGNED : 0) {}
+ RawSound(Audio::Mixer *mixer, const Common::String &filename, bool isUnsigned)
+ : BaseSound(mixer, filename, 0, SOUND_BIG_ENDIAN), _flags(isUnsigned ? Audio::FLAG_UNSIGNED : 0) {}
Audio::AudioStream *makeAudioStream(uint sound);
void playSound(uint sound, uint loopSound, Audio::Mixer::SoundType type, Audio::SoundHandle *handle, bool loop, int vol = 0);
};
@@ -280,14 +292,15 @@ Audio::AudioStream *RawSound::makeAudioStream(uint sound) {
if (_offsets == NULL)
return NULL;
- _file->seek(_offsets[sound], SEEK_SET);
-
- uint size = _file->readUint32BE();
- byte *buffer = (byte *)malloc(size);
- assert(buffer);
- _file->read(buffer, size);
-
- return Audio::makeRawStream(buffer, size, 22050, _flags);
+ Common::File *file = new Common::File();
+ if (!file->open(_filename)) {
+ warning("RawSound::makeAudioStream: Could not open file \"%s\"", _filename.c_str());
+ return NULL;
+ }
+
+ file->seek(_offsets[sound], SEEK_SET);
+ uint size = file->readUint32BE();
+ return Audio::makeRawStream(new Common::SeekableSubReadStream(file, _offsets[sound] + 4, _offsets[sound] + 4 + size, DisposeAfterUse::YES), 22050, _flags, DisposeAfterUse::YES);
}
void RawSound::playSound(uint sound, uint loopSound, Audio::Mixer::SoundType type, Audio::SoundHandle *handle, bool loop, int vol) {
@@ -298,40 +311,15 @@ void RawSound::playSound(uint sound, uint loopSound, Audio::Mixer::SoundType typ
///////////////////////////////////////////////////////////////////////////////
#pragma mark -
-class CompressedSound : public BaseSound {
-public:
- CompressedSound(Audio::Mixer *mixer, Common::File *file, uint32 base) : BaseSound(mixer, file, base, false) {}
-
- Common::SeekableReadStream *loadStream(uint sound) const {
- if (_offsets == NULL)
- return NULL;
-
- _file->seek(_offsets[sound], SEEK_SET);
-
- int i = 1;
- while (_offsets[sound + i] == _offsets[sound])
- i++;
-
- uint32 size = _offsets[sound + i] - _offsets[sound];
-
- return _file->readStream(size);
- }
-
- void playSound(uint sound, uint loopSound, Audio::Mixer::SoundType type, Audio::SoundHandle *handle, bool loop, int vol = 0) {
- convertVolume(vol);
- _mixer->playStream(type, handle, new LoopingAudioStream(this, sound, loopSound, loop), -1, vol);
- }
-};
-
///////////////////////////////////////////////////////////////////////////////
#pragma mark -
#ifdef USE_MAD
-class MP3Sound : public CompressedSound {
+class MP3Sound : public BaseSound {
public:
- MP3Sound(Audio::Mixer *mixer, Common::File *file, uint32 base = 0) : CompressedSound(mixer, file, base) {}
+ MP3Sound(Audio::Mixer *mixer, const Common::String &filename, uint32 base = 0) : BaseSound(mixer, filename, base, false) {}
Audio::AudioStream *makeAudioStream(uint sound) {
- Common::SeekableReadStream *tmp = loadStream(sound);
+ Common::SeekableReadStream *tmp = getSoundStream(sound);
if (!tmp)
return NULL;
return Audio::makeMP3Stream(tmp, DisposeAfterUse::YES);
@@ -343,11 +331,11 @@ public:
#pragma mark -
#ifdef USE_VORBIS
-class VorbisSound : public CompressedSound {
+class VorbisSound : public BaseSound {
public:
- VorbisSound(Audio::Mixer *mixer, Common::File *file, uint32 base = 0) : CompressedSound(mixer, file, base) {}
+ VorbisSound(Audio::Mixer *mixer, const Common::String &filename, uint32 base = 0) : BaseSound(mixer, filename, base, false) {}
Audio::AudioStream *makeAudioStream(uint sound) {
- Common::SeekableReadStream *tmp = loadStream(sound);
+ Common::SeekableReadStream *tmp = getSoundStream(sound);
if (!tmp)
return NULL;
return Audio::makeVorbisStream(tmp, DisposeAfterUse::YES);
@@ -359,11 +347,11 @@ public:
#pragma mark -
#ifdef USE_FLAC
-class FLACSound : public CompressedSound {
+class FLACSound : public BaseSound {
public:
- FLACSound(Audio::Mixer *mixer, Common::File *file, uint32 base = 0) : CompressedSound(mixer, file, base) {}
+ FLACSound(Audio::Mixer *mixer, const Common::String &filename, uint32 base = 0) : BaseSound(mixer, filename, base, false) {}
Audio::AudioStream *makeAudioStream(uint sound) {
- Common::SeekableReadStream *tmp = loadStream(sound);
+ Common::SeekableReadStream *tmp = getSoundStream(sound);
if (!tmp)
return NULL;
return Audio::makeFLACStream(tmp, DisposeAfterUse::YES);
@@ -374,25 +362,23 @@ public:
///////////////////////////////////////////////////////////////////////////////
#pragma mark -
-static CompressedSound *makeCompressedSound(Audio::Mixer *mixer, Common::File *file, const Common::String &basename) {
+static BaseSound *makeSound(Audio::Mixer *mixer, const Common::String &basename) {
#ifdef USE_FLAC
- file->open(basename + ".fla");
- if (file->isOpen()) {
- return new FLACSound(mixer, file);
- }
+ if (Common::File::exists(basename + ".fla"))
+ return new FLACSound(mixer, basename + ".fla");
#endif
#ifdef USE_VORBIS
- file->open(basename + ".ogg");
- if (file->isOpen()) {
- return new VorbisSound(mixer, file);
- }
+ if (Common::File::exists(basename + ".ogg"))
+ return new VorbisSound(mixer, basename + ".ogg");
#endif
#ifdef USE_MAD
- file->open(basename + ".mp3");
- if (file->isOpen()) {
- return new MP3Sound(mixer, file);
- }
+ if (Common::File::exists(basename + ".mp3"))
+ return new MP3Sound(mixer, basename + ".mp3");
#endif
+ if (Common::File::exists(basename + ".wav"))
+ return new WavSound(mixer, basename + ".wav");
+ if (Common::File::exists(basename + ".voc"))
+ return new VocSound(mixer, basename + ".voc", true);
return 0;
}
@@ -441,90 +427,59 @@ Sound::~Sound() {
void Sound::loadVoiceFile(const GameSpecificSettings *gss) {
// Game versions which use separate voice files
- if (_vm->getGameType() == GType_FF || _vm->getGameId() == GID_SIMON1CD32)
+ if (_hasVoiceFile || _vm->getGameType() == GType_FF || _vm->getGameId() == GID_SIMON1CD32)
return;
+ _voice = makeSound(_mixer, gss->speech_filename);
+ _hasVoiceFile = (_voice != 0);
- char filename[16];
- Common::File *file = new Common::File();
+ if (_hasVoiceFile)
+ return;
- if (!_hasVoiceFile) {
- _voice = makeCompressedSound(_mixer, file, gss->speech_filename);
- _hasVoiceFile = (_voice != 0);
- }
- if (!_hasVoiceFile && _vm->getGameType() == GType_SIMON2) {
+ if (_vm->getGameType() == GType_SIMON2) {
// for simon2 mac/amiga, only read index file
- file->open("voices.idx");
- if (file->isOpen() == true) {
- int end = file->size();
+ Common::File file;
+ if (file.open("voices.idx")) {
+ int end = file.size();
_filenums = (uint16 *)malloc((end / 6 + 1) * 2);
_offsets = (uint32 *)malloc((end / 6 + 1) * 4);
for (int i = 1; i <= end / 6; i++) {
- _filenums[i] = file->readUint16BE();
- _offsets[i] = file->readUint32BE();
+ _filenums[i] = file.readUint16BE();
+ _offsets[i] = file.readUint32BE();
}
+
_hasVoiceFile = true;
- }
- }
- if (!_hasVoiceFile) {
- sprintf(filename, "%s.wav", gss->speech_filename);
- file->open(filename);
- if (file->isOpen()) {
- _hasVoiceFile = true;
- _voice = new WavSound(_mixer, file);
+ return;
}
}
const bool dataIsUnsigned = true;
- if (!_hasVoiceFile) {
- sprintf(filename, "%s.voc", gss->speech_filename);
- file->open(filename);
- if (file->isOpen()) {
- _hasVoiceFile = true;
- _voice = new VocSound(_mixer, file, dataIsUnsigned);
- }
- }
- if (!_hasVoiceFile) {
- sprintf(filename, "%s", gss->speech_filename);
- file->open(filename);
- if (file->isOpen()) {
- _hasVoiceFile = true;
- if (_vm->getGameType() == GType_PP)
- _voice = new WavSound(_mixer, file);
- else
- _voice = new VocSound(_mixer, file, dataIsUnsigned);
- }
+ if (Common::File::exists(gss->speech_filename)) {
+ _hasVoiceFile = true;
+ if (_vm->getGameType() == GType_PP)
+ _voice = new WavSound(_mixer, gss->speech_filename);
+ else
+ _voice = new VocSound(_mixer, gss->speech_filename, dataIsUnsigned);
}
}
void Sound::loadSfxFile(const GameSpecificSettings *gss) {
- char filename[16];
- Common::File *file = new Common::File();
+ if (_hasEffectsFile)
+ return;
- if (!_hasEffectsFile) {
- _effects = makeCompressedSound(_mixer, file, gss->effects_filename);
- _hasEffectsFile = (_effects != 0);
- }
+ _effects = makeSound(_mixer, gss->effects_filename);
+ _hasEffectsFile = (_effects != 0);
+
+ if (_hasEffectsFile)
+ return;
const bool dataIsUnsigned = true;
- if (!_hasEffectsFile) {
- sprintf(filename, "%s.voc", gss->effects_filename);
- file->open(filename);
- if (file->isOpen()) {
- _hasEffectsFile = true;
- _effects = new VocSound(_mixer, file, dataIsUnsigned);
- }
- }
- if (!_hasEffectsFile) {
- sprintf(filename, "%s", gss->effects_filename);
- file->open(filename);
- if (file->isOpen()) {
- _hasEffectsFile = true;
- _effects = new VocSound(_mixer, file, dataIsUnsigned);
- }
+ if (Common::File::exists(gss->effects_filename)) {
+ _hasEffectsFile = true;
+ _effects = new VocSound(_mixer, gss->effects_filename, dataIsUnsigned);
}
}
@@ -535,10 +490,7 @@ void Sound::readSfxFile(const Common::String &filename) {
_mixer->stopHandle(_effectsHandle);
- Common::File *file = new Common::File();
- file->open(filename);
-
- if (file->isOpen() == false) {
+ if (!Common::File::exists(filename)) {
error("readSfxFile: Can't load sfx file %s", filename.c_str());
}
@@ -546,37 +498,34 @@ void Sound::readSfxFile(const Common::String &filename) {
delete _effects;
if (_vm->getGameId() == GID_SIMON1CD32) {
- _effects = new VocSound(_mixer, file, dataIsUnsigned, 0, SOUND_BIG_ENDIAN);
+ _effects = new VocSound(_mixer, filename, dataIsUnsigned, 0, SOUND_BIG_ENDIAN);
} else
- _effects = new WavSound(_mixer, file);
+ _effects = new WavSound(_mixer, filename);
}
// This method is only used by Simon2
-void Sound::loadSfxTable(Common::File *gameFile, uint32 base) {
+void Sound::loadSfxTable(const char *gameFilename, uint32 base) {
stopAll();
delete _effects;
const bool dataIsUnsigned = true;
if (_vm->getPlatform() == Common::kPlatformWindows)
- _effects = new WavSound(_mixer, gameFile, base, DisposeAfterUse::NO);
+ _effects = new WavSound(_mixer, gameFilename, base);
else
- _effects = new VocSound(_mixer, gameFile, dataIsUnsigned, base, false, DisposeAfterUse::NO);
+ _effects = new VocSound(_mixer, gameFilename, dataIsUnsigned, base, false);
}
// This method is only used by Simon1 Amiga CD32
void Sound::readVoiceFile(const Common::String &filename) {
_mixer->stopHandle(_voiceHandle);
- Common::File *file = new Common::File();
- file->open(filename);
-
- if (file->isOpen() == false)
+ if (!Common::File::exists(filename))
error("readVoiceFile: Can't load voice file %s", filename.c_str());
const bool dataIsUnsigned = false;
delete _voice;
- _voice = new RawSound(_mixer, file, dataIsUnsigned);
+ _voice = new RawSound(_mixer, filename, dataIsUnsigned);
}
void Sound::playVoice(uint sound) {
@@ -587,13 +536,11 @@ void Sound::playVoice(uint sound) {
char filename[16];
_lastVoiceFile = _filenums[sound];
sprintf(filename, "voices%d.dat", _filenums[sound]);
- Common::File *file = new Common::File();
- file->open(filename);
- if (file->isOpen() == false)
+ if (!Common::File::exists(filename))
error("playVoice: Can't load voice file %s", filename);
delete _voice;
- _voice = new WavSound(_mixer, file, _offsets);
+ _voice = new WavSound(_mixer, filename, _offsets);
}
}
@@ -794,22 +741,13 @@ void Sound::switchVoiceFile(const GameSpecificSettings *gss, uint disc) {
_lastVoiceFile = disc;
char filename[16];
- Common::File *file = new Common::File();
- if (!_hasVoiceFile) {
- sprintf(filename, "%s%u", gss->speech_filename, disc);
- _voice = makeCompressedSound(_mixer, file, filename);
- _hasVoiceFile = (_voice != 0);
- }
- if (!_hasVoiceFile) {
- sprintf(filename, "%s%u.wav", gss->speech_filename, disc);
- file->open(filename);
- if (file->isOpen() == false) {
- error("switchVoiceFile: Can't load voice file %s", filename);
- }
- _hasVoiceFile = true;
- _voice = new WavSound(_mixer, file);
- }
+ sprintf(filename, "%s%u", gss->speech_filename, disc);
+ _voice = makeSound(_mixer, filename);
+ _hasVoiceFile = (_voice != 0);
+
+ if (!_hasVoiceFile)
+ error("switchVoiceFile: Can't load voice file %s", filename);
}
} // End of namespace AGOS