From 78776638d37a0081171e93acef2acda4a30bbc7c Mon Sep 17 00:00:00 2001 From: Benjamin Haisch Date: Tue, 13 Jan 2009 16:18:22 +0000 Subject: [PATCH] Reworked the sound energy code svn-id: r35845 --- engines/made/made.h | 4 ++++ engines/made/resource.cpp | 9 ++++++--- engines/made/resource.h | 4 ++++ engines/made/scriptfuncs.cpp | 29 ++++++++++++++++------------- engines/made/sound.cpp | 31 +++++++++++++++++++++++-------- engines/made/sound.h | 9 +++++++-- 6 files changed, 60 insertions(+), 26 deletions(-) diff --git a/engines/made/made.h b/engines/made/made.h index 6446e9c4e2b..297c2536989 100644 --- a/engines/made/made.h +++ b/engines/made/made.h @@ -45,6 +45,8 @@ #include "engines/engine.h" +#include "made/sound.h" + namespace Made { enum MadeGameID { @@ -115,6 +117,8 @@ public: int _soundRate; bool _autoStopSound; + uint _soundEnergyIndex; + SoundEnergyArray *_soundEnergyArray; // 2 = LGOP2, Manhole N&E // 3 = Return to Zork diff --git a/engines/made/resource.cpp b/engines/made/resource.cpp index bfd94ea86ff..d549dca70f6 100644 --- a/engines/made/resource.cpp +++ b/engines/made/resource.cpp @@ -157,8 +157,8 @@ SoundResource::SoundResource() : _soundSize(0), _soundData(NULL) { } SoundResource::~SoundResource() { - if (_soundData) - delete[] _soundData; + delete[] _soundData; + delete _soundEnergyArray; } void SoundResource::load(byte *source, int size) { @@ -169,7 +169,10 @@ void SoundResource::load(byte *source, int size) { _soundSize = chunkCount * chunkSize; _soundData = new byte[_soundSize]; - decompressSound(source + 14, _soundData, chunkSize, chunkCount); + _soundEnergyArray = new SoundEnergyArray; + + decompressSound(source + 14, _soundData, chunkSize, chunkCount, _soundEnergyArray); + } Audio::AudioStream *SoundResource::getAudioStream(int soundRate, bool loop) { diff --git a/engines/made/resource.h b/engines/made/resource.h index db327d6a3c9..9151b2ad979 100644 --- a/engines/made/resource.h +++ b/engines/made/resource.h @@ -33,6 +33,8 @@ #include "graphics/surface.h" #include "sound/audiostream.h" +#include "made/sound.h" + namespace Made { const int kMaxResourceCacheCount = 100; @@ -104,9 +106,11 @@ public: ~SoundResource(); void load(byte *source, int size); Audio::AudioStream *getAudioStream(int soundRate, bool loop = false); + SoundEnergyArray *getSoundEnergyArray() const { return _soundEnergyArray; } protected: byte *_soundData; int _soundSize; + SoundEnergyArray *_soundEnergyArray; }; class MenuResource : public Resource { diff --git a/engines/made/scriptfuncs.cpp b/engines/made/scriptfuncs.cpp index deb1b700ca0..da6f8cf1f99 100644 --- a/engines/made/scriptfuncs.cpp +++ b/engines/made/scriptfuncs.cpp @@ -237,8 +237,11 @@ int16 ScriptFunctions::sfPlaySound(int16 argc, int16 *argv) { _vm->_autoStopSound = (argv[0] == 1); } if (soundNum > 0) { + SoundResource *soundRes = _vm->_res->getSound(soundNum); _vm->_mixer->playInputStream(Audio::Mixer::kPlainSoundType, &_audioStreamHandle, - _vm->_res->getSound(soundNum)->getAudioStream(_vm->_soundRate, false)); + soundRes->getAudioStream(_vm->_soundRate, false)); + _vm->_soundEnergyArray = soundRes->getSoundEnergyArray(); + _vm->_soundEnergyIndex = 0; } return 0; } @@ -616,20 +619,20 @@ int16 ScriptFunctions::sfGetSoundEnergy(int16 argc, int16 *argv) { // This is called while in-game voices are played to animate // mouths when NPCs are talking - // FIXME: the mouth animations are out of sync. This occurs - // because the original unpacked sounds on the fly, whereas - // in ScummVM we unpack them when they're loaded. In ScummVM, - // the "sound energy" values are stored in an array (used as - // a stack), which means that sfGetSoundEnergy can empty that - // array prematurely. A proper fix would be to figure out - // when a value should be popped from the sound energy stack, - // or to unpack sounds on the fly like the original does - int result = 0; - if (soundEnergy.size() > 0) { - result = *soundEnergy.begin(); - soundEnergy.pop_front(); + + if (_vm->_mixer->isSoundHandleActive(_audioStreamHandle) && _vm->_soundEnergyArray && + _vm->_soundEnergyIndex < _vm->_soundEnergyArray->size()) { + + uint32 position = (_vm->_soundRate / 1000) * _vm->_mixer->getSoundElapsedTime(_audioStreamHandle); + SoundEnergyItem *soundEnergyItem = &_vm->_soundEnergyArray->operator[](_vm->_soundEnergyIndex); + + result = soundEnergyItem->energy; + + if (position >= soundEnergyItem->position) + _vm->_soundEnergyIndex++; } + return result; } diff --git a/engines/made/sound.cpp b/engines/made/sound.cpp index 5bf35ce0afb..3088ca73612 100644 --- a/engines/made/sound.cpp +++ b/engines/made/sound.cpp @@ -31,9 +31,7 @@ namespace Made { -Common::List soundEnergy; - -void decompressSound(byte *source, byte *dest, uint16 chunkSize, uint16 chunkCount) { +void decompressSound(byte *source, byte *dest, uint16 chunkSize, uint16 chunkCount, SoundEnergyArray *soundEnergyArray) { int16 prevSample = 0, workSample = 0; byte soundBuffer[1025]; @@ -45,6 +43,8 @@ void decompressSound(byte *source, byte *dest, uint16 chunkSize, uint16 chunkCou uint16 ofs = 0; uint16 i = 0, l = 0; byte val; + + SoundEnergyItem soundEnergyItem; const int modeValues[3][4] = { { 2, 8, 0x01, 1}, @@ -52,7 +52,10 @@ void decompressSound(byte *source, byte *dest, uint16 chunkSize, uint16 chunkCou {16, 2, 0x0F, 4} }; - soundEnergy.clear(); + soundEnergyItem.position = 0; + + if (soundEnergyArray) + soundEnergyArray->clear(); while (chunkCount--) { deltaType = (*source) >> 6; @@ -71,8 +74,12 @@ void decompressSound(byte *source, byte *dest, uint16 chunkSize, uint16 chunkCou case 0: memset(soundBuffer, 0x80, workChunkSize); - workSample = 0; - soundEnergy.push_back(0); + workSample = 0; + + soundEnergyItem.energy = 0; + if (soundEnergyArray) + soundEnergyArray->push_back(soundEnergyItem); + break; case 1: @@ -99,14 +106,21 @@ void decompressSound(byte *source, byte *dest, uint16 chunkSize, uint16 chunkCou } } - soundEnergy.push_back(type - 1); + soundEnergyItem.energy = type - 1; + if (soundEnergyArray) + soundEnergyArray->push_back(soundEnergyItem); + break; case 5: for (i = 0; i < workChunkSize; i++) soundBuffer[i] = *source++; workSample = soundBuffer[workChunkSize - 1] - 128; - soundEnergy.push_back(type - 1); + + soundEnergyItem.energy = type - 1; + if (soundEnergyArray) + soundEnergyArray->push_back(soundEnergyItem); + break; default: @@ -137,6 +151,7 @@ void decompressSound(byte *source, byte *dest, uint16 chunkSize, uint16 chunkCou prevSample = workSample; memcpy(dest, soundBuffer, chunkSize); dest += chunkSize; + soundEnergyItem.position += chunkSize; } diff --git a/engines/made/sound.h b/engines/made/sound.h index 195c566066d..02e046ed2e3 100644 --- a/engines/made/sound.h +++ b/engines/made/sound.h @@ -33,9 +33,14 @@ namespace Made { -extern Common::List soundEnergy; +struct SoundEnergyItem { + uint32 position; + byte energy; +}; -void decompressSound(byte *source, byte *dest, uint16 chunkSize, uint16 chunkCount); +typedef Common::Array SoundEnergyArray; + +void decompressSound(byte *source, byte *dest, uint16 chunkSize, uint16 chunkCount, SoundEnergyArray *soundEnergyArray = NULL); } // End of namespace Made