diff options
-rw-r--r-- | engines/scumm/he/sound_he.cpp | 20 | ||||
-rw-r--r-- | engines/scumm/sound.cpp | 103 | ||||
-rw-r--r-- | engines/scumm/sound.h | 5 |
3 files changed, 79 insertions, 49 deletions
diff --git a/engines/scumm/he/sound_he.cpp b/engines/scumm/he/sound_he.cpp index 5c15a85929..85e2a2f1dd 100644 --- a/engines/scumm/he/sound_he.cpp +++ b/engines/scumm/he/sound_he.cpp @@ -770,24 +770,30 @@ void SoundHE::startHETalkSound(uint32 offset) { if (ConfMan.getBool("speech_mute")) return; - assert(_sfxFile); - if (!_sfxFile->isOpen()) { + if (_sfxFilename.empty()) { // This happens in the Pajama Sam's Lost & Found demo, on the // main menu screen, so don't make it a fatal error. - warning("startHETalkSound: Speech file is not open"); + warning("startHETalkSound: Speech file is not found"); return; } + ScummFile file; + if (!_vm->openFile(file, _sfxFilename)) { + warning("startHETalkSound: Could not open speech file %s", _sfxFilename.c_str()); + return; + } + file.setEnc(_sfxFileEncByte); + _sfxMode |= 2; _vm->_res->nukeResource(rtSound, 1); - _sfxFile->seek(offset + 4, SEEK_SET); - size = _sfxFile->readUint32BE(); - _sfxFile->seek(offset, SEEK_SET); + file.seek(offset + 4, SEEK_SET); + size = file.readUint32BE(); + file.seek(offset, SEEK_SET); _vm->_res->createResource(rtSound, 1, size); ptr = _vm->getResourceAddress(rtSound, 1); - _sfxFile->read(ptr, size); + file.read(ptr, size); int channel = (_vm->VAR_TALK_CHANNEL != 0xFF) ? _vm->VAR(_vm->VAR_TALK_CHANNEL) : 0; addSoundToQueue2(1, 0, channel, 0); diff --git a/engines/scumm/sound.cpp b/engines/scumm/sound.cpp index 8178fc2636..f058ef1a2c 100644 --- a/engines/scumm/sound.cpp +++ b/engines/scumm/sound.cpp @@ -23,6 +23,8 @@ #include "common/config-manager.h" #include "common/timer.h" #include "common/util.h" +#include "common/ptr.h" +#include "common/substream.h" #include "scumm/actor.h" #include "scumm/file.h" @@ -62,7 +64,8 @@ Sound::Sound(ScummEngine *parent, Audio::Mixer *mixer) _mixer(mixer), _soundQuePos(0), _soundQue2Pos(0), - _sfxFile(0), + _sfxFilename(), + _sfxFileEncByte(0), _offsetTable(0), _numSoundEffects(0), _soundMode(kVOCMode), @@ -91,7 +94,6 @@ Sound::Sound(ScummEngine *parent, Audio::Mixer *mixer) Sound::~Sound() { stopCDTimer(); g_system->getAudioCDManager()->stop(); - delete _sfxFile; } void Sound::addSoundToQueue(int sound, int heOffset, int heChannel, int heFlags) { @@ -490,6 +492,7 @@ void Sound::startTalkSound(uint32 offset, uint32 b, int mode, Audio::SoundHandle int num = 0, i; int size = 0; int id = -1; + Common::ScopedPtr<ScummFile> file; if (_vm->_game.id == GID_CMI) { _sfxMode |= mode; @@ -523,25 +526,29 @@ void Sound::startTalkSound(uint32 offset, uint32 b, int mode, Audio::SoundHandle return; } - _sfxFile->close(); + file.reset(new ScummFile()); + if (!file) + error("startTalkSound: Out of memory"); + sprintf(filename, "audio/%s.%u/%u.voc", roomname, offset, b); - _vm->openFile(*_sfxFile, filename); - if (!_sfxFile->isOpen()) { + if (!_vm->openFile(*file, filename)) { sprintf(filename, "audio/%s_%u/%u.voc", roomname, offset, b); - _vm->openFile(*_sfxFile, filename); + _vm->openFile(*file, filename); } - if (!_sfxFile->isOpen()) { + + if (!file->isOpen()) { sprintf(filename, "%u.%u.voc", offset, b); - _vm->openFile(*_sfxFile, filename); + _vm->openFile(*file, filename); } - if (!_sfxFile->isOpen()) { + + if (!file->isOpen()) { warning("startTalkSound: dig demo: voc file not found"); return; } } else { - if (!_sfxFile->isOpen()) { - warning("startTalkSound: SFX file is not open"); + if (_sfxFilename.empty()) { + warning("startTalkSound: SFX file not found"); return; } @@ -581,11 +588,30 @@ void Sound::startTalkSound(uint32 offset, uint32 b, int mode, Audio::SoundHandle size = -1; } - _sfxFile->seek(offset, SEEK_SET); + file.reset(new ScummFile()); + if (!file) + error("startTalkSound: Out of memory"); + + if (!_vm->openFile(*file, _sfxFilename)) { + warning("startTalkSound: could not open sfx file %s", _sfxFilename.c_str()); + return; + } + + file->setEnc(_sfxFileEncByte); + file->seek(offset, SEEK_SET); assert(num + 1 < (int)ARRAYSIZE(_mouthSyncTimes)); for (i = 0; i < num; i++) - _mouthSyncTimes[i] = _sfxFile->readUint16BE(); + _mouthSyncTimes[i] = file->readUint16BE(); + + // Adjust offset to account for the mouth sync times. It is noteworthy + // that we do not adjust the size here for compressed streams, since + // they only set size to the size of the compressed sound data. + offset += num * 2; + // TODO: In case we ever set up the size for VOC streams, we should + // really check whether the size contains the _mouthSyncTimes. + //if (_soundMode == kVOCMode) + // size -= num * 2; _mouthSyncTimes[i] = 0xFFFF; _sfxMode |= mode; @@ -601,9 +627,7 @@ void Sound::startTalkSound(uint32 offset, uint32 b, int mode, Audio::SoundHandle #ifdef USE_MAD { assert(size > 0); - Common::SeekableReadStream *tmp = _sfxFile->readStream(size); - assert(tmp); - input = Audio::makeMP3Stream(tmp, DisposeAfterUse::YES); + input = Audio::makeMP3Stream(new Common::SeekableSubReadStream(file.release(), offset, offset + size, DisposeAfterUse::YES), DisposeAfterUse::YES); } #endif break; @@ -611,9 +635,7 @@ void Sound::startTalkSound(uint32 offset, uint32 b, int mode, Audio::SoundHandle #ifdef USE_VORBIS { assert(size > 0); - Common::SeekableReadStream *tmp = _sfxFile->readStream(size); - assert(tmp); - input = Audio::makeVorbisStream(tmp, DisposeAfterUse::YES); + input = Audio::makeVorbisStream(new Common::SeekableSubReadStream(file.release(), offset, offset + size, DisposeAfterUse::YES), DisposeAfterUse::YES); } #endif break; @@ -621,14 +643,12 @@ void Sound::startTalkSound(uint32 offset, uint32 b, int mode, Audio::SoundHandle #ifdef USE_FLAC { assert(size > 0); - Common::SeekableReadStream *tmp = _sfxFile->readStream(size); - assert(tmp); - input = Audio::makeFLACStream(tmp, DisposeAfterUse::YES); + input = Audio::makeFLACStream(new Common::SeekableSubReadStream(file.release(), offset, offset + size, DisposeAfterUse::YES), DisposeAfterUse::YES); } #endif break; default: - input = Audio::makeVOCStream(_sfxFile, Audio::FLAG_UNSIGNED); + input = Audio::makeVOCStream(file.release(), Audio::FLAG_UNSIGNED, DisposeAfterUse::YES); break; } @@ -848,12 +868,10 @@ void Sound::talkSound(uint32 a, uint32 b, int mode, int channel) { } void Sound::setupSound() { - delete _sfxFile; - - _sfxFile = openSfxFile(); + setupSfxFile(); if (_vm->_game.id == GID_FT) { - _vm->VAR(_vm->VAR_VOICE_BUNDLE_LOADED) = _sfxFile->isOpen(); + _vm->VAR(_vm->VAR_VOICE_BUNDLE_LOADED) = _sfxFilename.empty() ? 0 : 1; } } @@ -885,7 +903,7 @@ void Sound::pauseSounds(bool pause) { } } -BaseScummFile *Sound::openSfxFile() { +void Sound::setupSfxFile() { struct SoundFileExtensions { const char *ext; SoundMode mode; @@ -905,8 +923,10 @@ BaseScummFile *Sound::openSfxFile() { { 0, kVOCMode } }; - ScummFile *file = new ScummFile(); + ScummFile file; _offsetTable = NULL; + _sfxFileEncByte = 0; + _sfxFilename.clear(); /* Try opening the file <baseName>.sou first, e.g. tentacle.sou. * That way, you can keep .sou files for multiple games in the @@ -931,15 +951,20 @@ BaseScummFile *Sound::openSfxFile() { tmp = basename[0] + "tlk"; } - if (file->open(tmp) && _vm->_game.heversion <= 74) - file->setEnc(0x69); + if (file.open(tmp)) + _sfxFilename = tmp; + + if (_vm->_game.heversion <= 74) + _sfxFileEncByte = 0x69; + _soundMode = kVOCMode; } else { - for (uint j = 0; j < 2 && !file->isOpen(); ++j) { + for (uint j = 0; j < 2 && !file.isOpen(); ++j) { for (int i = 0; extensions[i].ext; ++i) { tmp = basename[j] + extensions[i].ext; - if (_vm->openFile(*file, tmp)) { + if (_vm->openFile(file, tmp)) { _soundMode = extensions[i].mode; + _sfxFilename = tmp; break; } } @@ -963,23 +988,21 @@ BaseScummFile *Sound::openSfxFile() { */ int size, compressed_offset; MP3OffsetTable *cur; - compressed_offset = file->readUint32BE(); + compressed_offset = file.readUint32BE(); _offsetTable = (MP3OffsetTable *) malloc(compressed_offset); _numSoundEffects = compressed_offset / 16; size = compressed_offset; cur = _offsetTable; while (size > 0) { - cur->org_offset = file->readUint32BE(); - cur->new_offset = file->readUint32BE() + compressed_offset + 4; /* The + 4 is to take into accound the 'size' field */ - cur->num_tags = file->readUint32BE(); - cur->compressed_size = file->readUint32BE(); + cur->org_offset = file.readUint32BE(); + cur->new_offset = file.readUint32BE() + compressed_offset + 4; /* The + 4 is to take into accound the 'size' field */ + cur->num_tags = file.readUint32BE(); + cur->compressed_size = file.readUint32BE(); size -= 4 * 4; cur++; } } - - return file; } bool Sound::isSfxFinished() const { diff --git a/engines/scumm/sound.h b/engines/scumm/sound.h index e9a37ac9fa..48f28d51ff 100644 --- a/engines/scumm/sound.h +++ b/engines/scumm/sound.h @@ -69,7 +69,8 @@ protected: int16 flags; } _soundQue2[10]; - BaseScummFile *_sfxFile; + Common::String _sfxFilename; + byte _sfxFileEncByte; SoundMode _soundMode; MP3OffsetTable *_offsetTable; // For compressed audio int _numSoundEffects; // For compressed audio @@ -126,7 +127,7 @@ public: void saveLoadWithSerializer(Serializer *ser); protected: - BaseScummFile *openSfxFile(); + void setupSfxFile(); bool isSfxFinished() const; void processSfxQueues(); |