diff options
author | Johannes Schickel | 2011-11-02 23:56:45 +0100 |
---|---|---|
committer | Johannes Schickel | 2011-11-06 13:33:55 +0100 |
commit | 09708f7224cc388ef45ec570a477a8ace0e61bec (patch) | |
tree | bf560850c9ff6b8bccd70f86f665bd137c850f1b | |
parent | 9fa9f68789ef51e078cb8631e06bead13cae13f2 (diff) | |
download | scummvm-rg350-09708f7224cc388ef45ec570a477a8ace0e61bec.tar.gz scummvm-rg350-09708f7224cc388ef45ec570a477a8ace0e61bec.tar.bz2 scummvm-rg350-09708f7224cc388ef45ec570a477a8ace0e61bec.zip |
SCUMM: Stream sfx/voice sounds from mouster.sou.
This fixes sound corruption when using the new VOC streaming code. It also
reduces the runtime memory needed for compressed sound files slightly, since
it does not preload them into memory anymore. This comes at the expense of one
file descriptor needed per sfx being played though.
Thanks to Kirben for his review and feedback.
-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(); |