diff --git a/apps/openmw/mwsound/soundmanagerimp.cpp b/apps/openmw/mwsound/soundmanagerimp.cpp index c7e504770..f19f298e1 100644 --- a/apps/openmw/mwsound/soundmanagerimp.cpp +++ b/apps/openmw/mwsound/soundmanagerimp.cpp @@ -119,15 +119,8 @@ namespace MWSound return DecoderPtr(new DEFAULT_DECODER (mVFS)); } - void SoundManager::insertSound(const std::string &soundId, const ESM::Sound *sound) + Sound_Buffer *SoundManager::insertSound(const std::string &soundId, const ESM::Sound *sound) { - BufferKeyList::iterator bufkey = std::lower_bound(mBufferKeys.begin(), mBufferKeys.end(), soundId); - if(bufkey != mBufferKeys.end() && *bufkey == soundId) - { - std::cerr<< "Duplicate sound record \""<getStore().get().find("fAudioDefaultMinDistance")->getFloat(); static const float fAudioDefaultMaxDistance = world->getStore().get().find("fAudioDefaultMaxDistance")->getFloat(); @@ -152,63 +145,39 @@ namespace MWSound min = std::max(min, 1.0f); max = std::max(min, max); - 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; - } - + Sound_Buffer *sfx = &*mSoundBuffers.insert(mSoundBuffers.end(), + Sound_Buffer("Sound/"+sound->mSound, volume, min, max) + ); mVFS->normalizeFilename(sfx->mResourceName); - } - - size_t SoundManager::lookupId(const std::string &soundId) - { - BufferKeyList::iterator bufkey = std::lower_bound(mBufferKeys.begin(), mBufferKeys.end(), soundId); - if(bufkey != mBufferKeys.end() && *bufkey == soundId) - return std::distance(mBufferKeys.begin(), bufkey); - 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) - return std::distance(mBufferKeys.begin(), bufkey); - } + mBufferNameMap.insert(std::make_pair(soundId, sfx)); - throw std::runtime_error("Sound "+soundId+" not found"); + return sfx; } - size_t SoundManager::lookupId(const std::string& soundId) const + // Lookup a soundId for its sound data (resource name, local volume, + // minRange, and maxRange) + Sound_Buffer *SoundManager::lookupSound(const std::string &soundId) const { - BufferKeyList::const_iterator bufkey = std::lower_bound(mBufferKeys.begin(), mBufferKeys.end(), soundId); - if(bufkey != mBufferKeys.end() && *bufkey == soundId) - return std::distance(mBufferKeys.begin(), bufkey); - - throw std::runtime_error("Sound "+soundId+" not found"); + NameBufferMap::const_iterator snd = mBufferNameMap.find(soundId); + if(snd != mBufferNameMap.end()) return snd->second; + return 0; } - // Lookup a sfxid for its sound data (resource name, local volume, - // minRange, and maxRange). - Sound_Buffer *SoundManager::lookup(size_t sfxid) + // Lookup a soundId for its sound data (resource name, local volume, + // minRange, and maxRange), and ensure it's ready for use. + Sound_Buffer *SoundManager::loadSound(const std::string &soundId) { - Sound_Buffer *sfx = &mSoundBuffers[sfxid]; + Sound_Buffer *sfx; + NameBufferMap::const_iterator snd = mBufferNameMap.find(soundId); + if(snd != mBufferNameMap.end()) + sfx = snd->second; + else + { + MWBase::World *world = MWBase::Environment::get().getWorld(); + const ESM::Sound *sound = world->getStore().get().find(soundId); + sfx = insertSound(soundId, sound); + } if(!sfx->mHandle) { @@ -223,7 +192,7 @@ namespace MWSound std::cerr<< "No unused sound buffers to free, using "<getSoundDataSize(unused->mHandle); mOutput->unloadSound(unused->mHandle); @@ -231,19 +200,12 @@ namespace MWSound mUnusedBuffers.pop_back(); } - mUnusedBuffers.push_front(sfxid); + mUnusedBuffers.push_front(sfx); } return sfx; } - // Lookup a soundid for its sound data (resource name, local volume, - // minRange, and maxRange). - Sound_Buffer *SoundManager::lookup(const std::string &soundId) - { - return lookup(lookupId(soundId)); - } - DecoderPtr SoundManager::loadVoice(const std::string &voicefile) { DecoderPtr decoder = getDecoder(); @@ -511,8 +473,7 @@ namespace MWSound return sound; try { - size_t sfxid = lookupId(Misc::StringUtils::lowerCase(soundId)); - Sound_Buffer *sfx = lookup(sfxid); + Sound_Buffer *sfx = loadSound(Misc::StringUtils::lowerCase(soundId)); float basevol = volumeFromType(type); sound = mOutput->playSound(sfx->mHandle, @@ -520,11 +481,11 @@ namespace MWSound ); if(sfx->mUses++ == 0) { - SoundList::iterator iter = std::find(mUnusedBuffers.begin(), mUnusedBuffers.end(), sfxid); + SoundList::iterator iter = std::find(mUnusedBuffers.begin(), mUnusedBuffers.end(), sfx); if(iter != mUnusedBuffers.end()) mUnusedBuffers.erase(iter); } - mActiveSounds[MWWorld::Ptr()].push_back(std::make_pair(sound, sfxid)); + mActiveSounds[MWWorld::Ptr()].push_back(std::make_pair(sound, sfx)); } catch(std::exception&) { @@ -542,8 +503,7 @@ namespace MWSound try { // Look up the sound in the ESM data - size_t sfxid = lookupId(Misc::StringUtils::lowerCase(soundId)); - Sound_Buffer *sfx = lookup(sfxid); + Sound_Buffer *sfx = loadSound(Misc::StringUtils::lowerCase(soundId)); float basevol = volumeFromType(type); const ESM::Position &pos = ptr.getRefData().getPosition(); const osg::Vec3f objpos(pos.asVec3()); @@ -556,11 +516,11 @@ namespace MWSound ); if(sfx->mUses++ == 0) { - SoundList::iterator iter = std::find(mUnusedBuffers.begin(), mUnusedBuffers.end(), sfxid); + SoundList::iterator iter = std::find(mUnusedBuffers.begin(), mUnusedBuffers.end(), sfx); if(iter != mUnusedBuffers.end()) mUnusedBuffers.erase(iter); } - mActiveSounds[ptr].push_back(std::make_pair(sound, sfxid)); + mActiveSounds[ptr].push_back(std::make_pair(sound, sfx)); } catch(std::exception&) { @@ -578,8 +538,7 @@ namespace MWSound try { // Look up the sound in the ESM data - size_t sfxid = lookupId(Misc::StringUtils::lowerCase(soundId)); - Sound_Buffer *sfx = lookup(sfxid); + Sound_Buffer *sfx = loadSound(Misc::StringUtils::lowerCase(soundId)); float basevol = volumeFromType(type); sound = mOutput->playSound3D(sfx->mHandle, @@ -587,11 +546,11 @@ namespace MWSound ); if(sfx->mUses++ == 0) { - SoundList::iterator iter = std::find(mUnusedBuffers.begin(), mUnusedBuffers.end(), sfxid); + SoundList::iterator iter = std::find(mUnusedBuffers.begin(), mUnusedBuffers.end(), sfx); if(iter != mUnusedBuffers.end()) mUnusedBuffers.erase(iter); } - mActiveSounds[MWWorld::Ptr()].push_back(std::make_pair(sound, sfxid)); + mActiveSounds[MWWorld::Ptr()].push_back(std::make_pair(sound, sfx)); } catch(std::exception &) { @@ -605,11 +564,11 @@ namespace MWSound SoundMap::iterator snditer = mActiveSounds.find(ptr); if(snditer != mActiveSounds.end()) { - size_t sfxid = lookupId(Misc::StringUtils::lowerCase(soundId)); - SoundIndexPairList::iterator sndidx = snditer->second.begin(); + Sound_Buffer *sfx = loadSound(Misc::StringUtils::lowerCase(soundId)); + SoundBufferRefPairList::iterator sndidx = snditer->second.begin(); for(;sndidx != snditer->second.end();++sndidx) { - if(sndidx->second == sfxid) + if(sndidx->second == sfx) sndidx->first->stop(); } } @@ -620,7 +579,7 @@ namespace MWSound SoundMap::iterator snditer = mActiveSounds.find(ptr); if(snditer != mActiveSounds.end()) { - SoundIndexPairList::iterator sndidx = snditer->second.begin(); + SoundBufferRefPairList::iterator sndidx = snditer->second.begin(); for(;sndidx != snditer->second.end();++sndidx) sndidx->first->stop(); } @@ -635,7 +594,7 @@ namespace MWSound snditer->first != MWMechanics::getPlayer() && snditer->first.getCell() == cell) { - SoundIndexPairList::iterator sndidx = snditer->second.begin(); + SoundBufferRefPairList::iterator sndidx = snditer->second.begin(); for(;sndidx != snditer->second.end();++sndidx) sndidx->first->stop(); } @@ -659,11 +618,11 @@ namespace MWSound SoundMap::iterator snditer = mActiveSounds.find(MWWorld::Ptr()); if(snditer != mActiveSounds.end()) { - size_t sfxid = lookupId(Misc::StringUtils::lowerCase(soundId)); - SoundIndexPairList::iterator sndidx = snditer->second.begin(); + Sound_Buffer *sfx = loadSound(Misc::StringUtils::lowerCase(soundId)); + SoundBufferRefPairList::iterator sndidx = snditer->second.begin(); for(;sndidx != snditer->second.end();++sndidx) { - if(sndidx->second == sfxid) + if(sndidx->second == sfx) sndidx->first->stop(); } } @@ -675,11 +634,11 @@ namespace MWSound SoundMap::iterator snditer = mActiveSounds.find(ptr); if(snditer != mActiveSounds.end()) { - size_t sfxid = lookupId(Misc::StringUtils::lowerCase(soundId)); - SoundIndexPairList::iterator sndidx = snditer->second.begin(); + Sound_Buffer *sfx = loadSound(Misc::StringUtils::lowerCase(soundId)); + SoundBufferRefPairList::iterator sndidx = snditer->second.begin(); for(;sndidx != snditer->second.end();++sndidx) { - if(sndidx->second == sfxid) + if(sndidx->second == sfx) sndidx->first->setFadeout(duration); } } @@ -690,11 +649,11 @@ namespace MWSound SoundMap::const_iterator snditer = mActiveSounds.find(ptr); if(snditer != mActiveSounds.end()) { - size_t sfxid = lookupId(Misc::StringUtils::lowerCase(soundId)); - SoundIndexPairList::const_iterator sndidx = snditer->second.begin(); + Sound_Buffer *sfx = lookupSound(Misc::StringUtils::lowerCase(soundId)); + SoundBufferRefPairList::const_iterator sndidx = snditer->second.begin(); for(;sndidx != snditer->second.end();++sndidx) { - if(sndidx->second == sfxid && sndidx->first->isPlaying()) + if(sndidx->second == sfx && sndidx->first->isPlaying()) return true; } } @@ -825,14 +784,14 @@ namespace MWSound SoundMap::iterator snditer = mActiveSounds.begin(); while(snditer != mActiveSounds.end()) { - SoundIndexPairList::iterator sndidx = snditer->second.begin(); + SoundBufferRefPairList::iterator sndidx = snditer->second.begin(); while(sndidx != snditer->second.end()) { if(!updateSound(sndidx->first, snditer->first, duration)) { - Sound_Buffer *sfx = &mSoundBuffers[sndidx->second]; + Sound_Buffer *sfx = sndidx->second; if(sfx->mUses-- == 1) - mUnusedBuffers.push_front(sndidx->second); + mUnusedBuffers.push_front(sfx); sndidx = snditer->second.erase(sndidx); } else @@ -916,7 +875,7 @@ namespace MWSound SoundMap::iterator snditer = mActiveSounds.begin(); for(;snditer != mActiveSounds.end();++snditer) { - SoundIndexPairList::iterator sndidx = snditer->second.begin(); + SoundBufferRefPairList::iterator sndidx = snditer->second.begin(); for(;sndidx != snditer->second.end();++sndidx) { MWBase::SoundPtr sound = sndidx->first; @@ -956,7 +915,7 @@ namespace MWSound SoundMap::iterator snditer = mActiveSounds.find(old); if(snditer != mActiveSounds.end()) { - SoundIndexPairList sndlist = snditer->second; + SoundBufferRefPairList sndlist = snditer->second; mActiveSounds.erase(snditer); mActiveSounds[updated] = sndlist; } @@ -1039,13 +998,13 @@ namespace MWSound SoundMap::iterator snditer = mActiveSounds.begin(); for(;snditer != mActiveSounds.end();++snditer) { - SoundIndexPairList::iterator sndidx = snditer->second.begin(); + SoundBufferRefPairList::iterator sndidx = snditer->second.begin(); for(;sndidx != snditer->second.end();++sndidx) { sndidx->first->stop(); - Sound_Buffer *sfx = &mSoundBuffers[sndidx->second]; + Sound_Buffer *sfx = sndidx->second; if(sfx->mUses-- == 1) - mUnusedBuffers.push_front(sndidx->second); + mUnusedBuffers.push_front(sfx); } } mActiveSounds.clear(); diff --git a/apps/openmw/mwsound/soundmanagerimp.hpp b/apps/openmw/mwsound/soundmanagerimp.hpp index 15fdd86cf..cdf35189f 100644 --- a/apps/openmw/mwsound/soundmanagerimp.hpp +++ b/apps/openmw/mwsound/soundmanagerimp.hpp @@ -51,28 +51,29 @@ namespace MWSound float mVoiceVolume; float mFootstepsVolume; - 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; + typedef std::deque SoundBufferList; + // List of sound buffers, grown as needed. New enties are added to the + // back, allowing existing Sound_Buffer references/pointers to remain + // valid. SoundBufferList mSoundBuffers; size_t mBufferCacheSize; + typedef std::map NameBufferMap; + NameBufferMap mBufferNameMap; + typedef std::map NameLoudnessMap; NameLoudnessMap mVoiceLipBuffers; // NOTE: unused buffers are stored in front-newest order. - typedef std::deque SoundList; + typedef std::deque SoundList; SoundList mUnusedBuffers; boost::shared_ptr mMusic; std::string mCurrentPlaylist; - typedef std::pair SoundIndexPair; - typedef std::vector SoundIndexPairList; - typedef std::map SoundMap; + typedef std::pair SoundBufferRefPair; + typedef std::vector SoundBufferRefPairList; + typedef std::map SoundMap; SoundMap mActiveSounds; typedef std::pair SoundNamePair; @@ -88,12 +89,10 @@ namespace MWSound int mPausedSoundTypes; - void insertSound(const std::string &soundId, const ESM::Sound *sound); + Sound_Buffer *insertSound(const std::string &soundId, const ESM::Sound *sound); - size_t lookupId(const std::string &soundId); - size_t lookupId(const std::string &soundId) const; - Sound_Buffer *lookup(size_t sfxid); - Sound_Buffer *lookup(const std::string &soundId); + Sound_Buffer *lookupSound(const std::string &soundId) const; + Sound_Buffer *loadSound(const std::string &soundId); // Ensures the loudness/"lip" data is loaded, and returns a decoder to // start streaming