From f9e18cd966bf7431b186a80e4d558350cd31a7f8 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Tue, 24 Nov 2015 01:40:14 -0800 Subject: [PATCH] Prepare all Sound_Buffer objects when one is needed This simply sets up the Sound record data to be used by the sound output. The actual audio buffers, stored in the Sound_Handle, are still loaded on-demand. --- apps/openmw/mwsound/soundmanagerimp.cpp | 112 ++++++++++++++---------- apps/openmw/mwsound/soundmanagerimp.hpp | 7 ++ 2 files changed, 74 insertions(+), 45 deletions(-) diff --git a/apps/openmw/mwsound/soundmanagerimp.cpp b/apps/openmw/mwsound/soundmanagerimp.cpp index d74b0bc6d..2c33cb2b7 100644 --- a/apps/openmw/mwsound/soundmanagerimp.cpp +++ b/apps/openmw/mwsound/soundmanagerimp.cpp @@ -118,62 +118,84 @@ namespace MWSound return DecoderPtr(new DEFAULT_DECODER (mVFS)); } - // Lookup a soundid for its sound data (resource name, local volume, - // minRange and maxRange. The returned pointer is only valid temporarily. - Sound_Buffer *SoundManager::lookup(const std::string &soundId) + void SoundManager::insertSound(const std::string &soundId, const ESM::Sound *sound) { - Sound_Buffer *sfx; BufferKeyList::iterator bufkey = std::lower_bound(mBufferKeys.begin(), mBufferKeys.end(), soundId); if(bufkey != mBufferKeys.end() && *bufkey == soundId) - sfx = &mSoundBuffers[std::distance(mBufferKeys.begin(), bufkey)]; + { + std::cerr<< "Duplicate sound record \""<getStore().get().find("fAudioDefaultMinDistance")->getFloat(); + static const float fAudioDefaultMaxDistance = world->getStore().get().find("fAudioDefaultMaxDistance")->getFloat(); + static const float fAudioMinDistanceMult = world->getStore().get().find("fAudioMinDistanceMult")->getFloat(); + static const float fAudioMaxDistanceMult = world->getStore().get().find("fAudioMaxDistanceMult")->getFloat(); + float volume, min, max; + + volume = static_cast(pow(10.0, (sound->mData.mVolume / 255.0*3348.0 - 3348.0) / 2000.0)); + if(sound->mData.mMinRange == 0 && sound->mData.mMaxRange == 0) + { + min = fAudioDefaultMinDistance; + max = fAudioDefaultMaxDistance; + } else { - // TODO: We could process all available ESM::Sound records on init - // to pre-fill a non-resizing list, which would allow subsystems to - // reference sounds by index instead of string. - MWBase::World* world = MWBase::Environment::get().getWorld(); - const ESM::Sound *snd = world->getStore().get().find(soundId); + min = sound->mData.mMinRange; + max = sound->mData.mMaxRange; + } - float volume, min, max; - volume = static_cast(pow(10.0, (snd->mData.mVolume / 255.0*3348.0 - 3348.0) / 2000.0)); + min *= fAudioMinDistanceMult; + max *= fAudioMaxDistanceMult; + min = std::max(min, 1.0f); + max = std::max(min, max); - if(snd->mData.mMinRange == 0 && snd->mData.mMaxRange == 0) - { - static const float fAudioDefaultMinDistance = world->getStore().get().find("fAudioDefaultMinDistance")->getFloat(); - static const float fAudioDefaultMaxDistance = world->getStore().get().find("fAudioDefaultMaxDistance")->getFloat(); - min = fAudioDefaultMinDistance; - max = fAudioDefaultMaxDistance; - } - else - { - min = snd->mData.mMinRange; - max = snd->mData.mMaxRange; - } + Sound_Buffer *sfx; + bufkey = mBufferKeys.insert(bufkey, soundId); + try { + BufferKeyList::difference_type id; + id = std::distance(mBufferKeys.begin(), bufkey); + mSoundBuffers.insert(mSoundBuffers.begin()+id, + Sound_Buffer("Sound/"+sound->mSound, volume, min, max) + ); + sfx = &mSoundBuffers[id]; + } + catch(...) { + mBufferKeys.erase(bufkey); + throw; + } - static const float fAudioMinDistanceMult = world->getStore().get().find("fAudioMinDistanceMult")->getFloat(); - static const float fAudioMaxDistanceMult = world->getStore().get().find("fAudioMaxDistanceMult")->getFloat(); - min *= fAudioMinDistanceMult; - max *= fAudioMaxDistanceMult; - min = std::max(min, 1.0f); - max = std::max(min, max); - - bufkey = mBufferKeys.insert(bufkey, soundId); - try { - BufferKeyList::difference_type id; - id = std::distance(mBufferKeys.begin(), bufkey); - mSoundBuffers.insert(mSoundBuffers.begin()+id, - Sound_Buffer("Sound/"+snd->mSound, volume, min, max) - ); - sfx = &mSoundBuffers[id]; - } - catch(...) { - mBufferKeys.erase(bufkey); - throw; - } + mVFS->normalizeFilename(sfx->mResourceName); + } - mVFS->normalizeFilename(sfx->mResourceName); + // Lookup a soundid for its sound data (resource name, local volume, + // minRange and maxRange). + Sound_Buffer *SoundManager::lookup(const std::string &soundId) + { + Sound_Buffer *sfx; + BufferKeyList::iterator bufkey = std::lower_bound(mBufferKeys.begin(), mBufferKeys.end(), soundId); + if(bufkey == mBufferKeys.end() || *bufkey != soundId) + { + if(mBufferKeys.empty()) + { + MWBase::World *world = MWBase::Environment::get().getWorld(); + MWWorld::Store::iterator iter = world->getStore().get().begin(); + MWWorld::Store::iterator end = world->getStore().get().end(); + size_t storesize = world->getStore().get().getSize(); + mBufferKeys.reserve(storesize); + mSoundBuffers.reserve(storesize); + for(;iter != end;++iter) + insertSound(Misc::StringUtils::lowerCase(iter->mId), &*iter); + + bufkey = std::lower_bound(mBufferKeys.begin(), mBufferKeys.end(), soundId); + } + if(bufkey == mBufferKeys.end() || *bufkey != soundId) + throw std::runtime_error("Sound "+soundId+" not found"); } + sfx = &mSoundBuffers[std::distance(mBufferKeys.begin(), bufkey)]; + if(!sfx->mHandle) { sfx->mHandle = mOutput->loadSound(sfx->mResourceName); diff --git a/apps/openmw/mwsound/soundmanagerimp.hpp b/apps/openmw/mwsound/soundmanagerimp.hpp index 082e04678..5e8d0d8f8 100644 --- a/apps/openmw/mwsound/soundmanagerimp.hpp +++ b/apps/openmw/mwsound/soundmanagerimp.hpp @@ -17,6 +17,11 @@ namespace VFS class Manager; } +namespace ESM +{ + struct Sound; +} + namespace MWSound { class Sound_Output; @@ -80,6 +85,8 @@ namespace MWSound int mPausedSoundTypes; + void insertSound(const std::string &soundId, const ESM::Sound *sound); + Sound_Buffer *lookup(const std::string &soundId); // Ensure the loudness/"lip" data is loaded void loadVoice(const std::string &voicefile);