From 6c3953766e97a5d8be561d76cb119c05b668a791 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Tue, 24 Nov 2015 00:03:54 -0800 Subject: [PATCH] Use separate lists for the sound name and its buffer This should make sound lookup a bit more efficient, especially when an integer ID can be used. --- apps/openmw/mwsound/soundmanagerimp.cpp | 82 +++++++++++++++---------- apps/openmw/mwsound/soundmanagerimp.hpp | 9 ++- 2 files changed, 57 insertions(+), 34 deletions(-) diff --git a/apps/openmw/mwsound/soundmanagerimp.cpp b/apps/openmw/mwsound/soundmanagerimp.cpp index bafd3aa1e..d74b0bc6d 100644 --- a/apps/openmw/mwsound/soundmanagerimp.cpp +++ b/apps/openmw/mwsound/soundmanagerimp.cpp @@ -101,12 +101,12 @@ namespace MWSound clear(); if(mOutput->isInitialized()) { - NameBufferMap::iterator sfxiter = mSoundBuffers.begin(); + SoundBufferList::iterator sfxiter = mSoundBuffers.begin(); for(;sfxiter != mSoundBuffers.end();++sfxiter) { - if(sfxiter->second.mHandle) - mOutput->unloadSound(sfxiter->second.mHandle); - sfxiter->second.mHandle = 0; + if(sfxiter->mHandle) + mOutput->unloadSound(sfxiter->mHandle); + sfxiter->mHandle = 0; } } mOutput.reset(); @@ -122,11 +122,11 @@ namespace MWSound // minRange and maxRange. The returned pointer is only valid temporarily. Sound_Buffer *SoundManager::lookup(const std::string &soundId) { - NameBufferMap::iterator sfxiter = mSoundBuffers.find(soundId); - if(sfxiter != mSoundBuffers.end() && sfxiter->second.mHandle) - return &sfxiter->second; - - if(sfxiter == mSoundBuffers.end()) + 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)]; + else { // TODO: We could process all available ESM::Sound records on init // to pre-fill a non-resizing list, which would allow subsystems to @@ -157,31 +157,45 @@ namespace MWSound min = std::max(min, 1.0f); max = std::max(min, max); - sfxiter = mSoundBuffers.insert(std::make_pair( - soundId, Sound_Buffer("Sound/"+snd->mSound, volume, min, max) - )).first; - mVFS->normalizeFilename(sfxiter->second.mResourceName); - } + 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; + } - Sound_Buffer *sfx = &sfxiter->second; - sfx->mHandle = mOutput->loadSound(sfx->mResourceName); - mBufferCacheSize += mOutput->getSoundDataSize(sfx->mHandle); + mVFS->normalizeFilename(sfx->mResourceName); + } - // NOTE: Max sound buffer cache size is 15MB. Make configurable? - while(mBufferCacheSize > 15*1024*1024) + if(!sfx->mHandle) { - if(mUnusedBuffers.empty()) + sfx->mHandle = mOutput->loadSound(sfx->mResourceName); + mBufferCacheSize += mOutput->getSoundDataSize(sfx->mHandle); + + // NOTE: Max sound buffer cache size is 15MB. Make configurable? + while(mBufferCacheSize > 15*1024*1024) { - std::cerr<< "No unused sound buffers to free, using "<getSoundDataSize(unused->mHandle); + mOutput->unloadSound(unused->mHandle); + mUnusedBuffers.erase(iter); } - SoundSet::iterator iter = mUnusedBuffers.begin(); - sfxiter = mSoundBuffers.find(*iter); - mBufferCacheSize -= mOutput->getSoundDataSize(sfxiter->second.mHandle); - mOutput->unloadSound(sfxiter->second.mHandle); - mUnusedBuffers.erase(iter); + mUnusedBuffers.insert(soundId); } - mUnusedBuffers.insert(soundId); return sfx; } @@ -773,8 +787,10 @@ namespace MWSound { if(!updateSound(sndname->first, snditer->first, duration)) { - NameBufferMap::iterator sfxiter = mSoundBuffers.find(sndname->second); - if(sfxiter->second.mReferences-- == 1) + BufferKeyList::iterator bufkey = std::lower_bound(mBufferKeys.begin(), mBufferKeys.end(), + sndname->second); + Sound_Buffer *sfx = &mSoundBuffers[std::distance(mBufferKeys.begin(), bufkey)]; + if(sfx->mReferences-- == 1) mUnusedBuffers.insert(sndname->second); sndname = snditer->second.erase(sndname); } @@ -981,8 +997,10 @@ namespace MWSound for(;sndname != snditer->second.end();++sndname) { sndname->first->stop(); - NameBufferMap::iterator sfxiter = mSoundBuffers.find(sndname->second); - if(sfxiter->second.mReferences-- == 1) + BufferKeyList::iterator bufkey = std::lower_bound(mBufferKeys.begin(), mBufferKeys.end(), + sndname->second); + Sound_Buffer *sfx = &mSoundBuffers[std::distance(mBufferKeys.begin(), bufkey)]; + if(sfx->mReferences-- == 1) mUnusedBuffers.insert(sndname->second); } } diff --git a/apps/openmw/mwsound/soundmanagerimp.hpp b/apps/openmw/mwsound/soundmanagerimp.hpp index 00c0af7b2..082e04678 100644 --- a/apps/openmw/mwsound/soundmanagerimp.hpp +++ b/apps/openmw/mwsound/soundmanagerimp.hpp @@ -45,8 +45,13 @@ namespace MWSound float mVoiceVolume; float mFootstepsVolume; - typedef std::map NameBufferMap; - NameBufferMap mSoundBuffers; + typedef std::vector BufferKeyList; + typedef std::vector SoundBufferList; + // Each mBufferKeys index has a corresponding entry in mSoundBuffers. + // That is, if string "foo" is at index 10 in mBufferKeys, index 10 in + // mSoundBuffers contains the Sound_Buffer for "foo". + BufferKeyList mBufferKeys; + SoundBufferList mSoundBuffers; size_t mBufferCacheSize; typedef std::map NameLoudnessMap;