diff --git a/apps/openmw/mwsound/soundmanagerimp.cpp b/apps/openmw/mwsound/soundmanagerimp.cpp index 71ed96ac9b..eed935e61b 100644 --- a/apps/openmw/mwsound/soundmanagerimp.cpp +++ b/apps/openmw/mwsound/soundmanagerimp.cpp @@ -58,7 +58,6 @@ namespace MWSound , mWaterSoundUpdater(makeWaterSoundUpdaterSettings()) , mSoundBuffers(new SoundBufferList::element_type()) , mBufferCacheSize(0) - , mMusic(nullptr) , mListenerUnderwater(false) , mListenerPos(0,0,0) , mListenerDir(1,0,0) @@ -266,17 +265,17 @@ namespace MWSound return nullptr; } - Sound *SoundManager::getSoundRef() + SoundPtr SoundManager::getSoundRef() { return mSounds.get(); } - Stream *SoundManager::getStreamRef() + StreamPtr SoundManager::getStreamRef() { return mStreams.get(); } - Stream *SoundManager::playVoice(DecoderPtr decoder, const osg::Vec3f &pos, bool playlocal) + StreamPtr SoundManager::playVoice(DecoderPtr decoder, const osg::Vec3f &pos, bool playlocal) { MWBase::World* world = MWBase::Environment::get().getWorld(); static const float fAudioMinDistanceMult = world->getStore().get().find("fAudioMinDistanceMult")->mValue.getFloat(); @@ -288,23 +287,20 @@ namespace MWSound bool played; float basevol = volumeFromType(Type::Voice); - Stream *sound = getStreamRef(); + StreamPtr sound = getStreamRef(); if(playlocal) { sound->init(1.0f, basevol, 1.0f, PlayMode::NoEnv|Type::Voice|Play_2D); - played = mOutput->streamSound(decoder, sound, true); + played = mOutput->streamSound(decoder, sound.get(), true); } else { sound->init(pos, 1.0f, basevol, 1.0f, minDistance, maxDistance, PlayMode::Normal|Type::Voice|Play_3D); - played = mOutput->streamSound3D(decoder, sound, true); + played = mOutput->streamSound3D(decoder, sound.get(), true); } if(!played) - { - mStreams.recycle(sound); return nullptr; - } return sound; } @@ -318,8 +314,7 @@ namespace MWSound { if(mMusic) { - mOutput->finishStream(mMusic); - mStreams.recycle(mMusic); + mOutput->finishStream(mMusic.get()); mMusic = nullptr; } } @@ -339,7 +334,7 @@ namespace MWSound mMusic = getStreamRef(); mMusic->init(1.0f, volumeFromType(Type::Music), 1.0f, PlayMode::NoEnv|Type::Music|Play_2D); - mOutput->streamSound(decoder, mMusic); + mOutput->streamSound(decoder, mMusic.get()); } void SoundManager::advanceMusic(const std::string& filename) @@ -389,7 +384,7 @@ namespace MWSound bool SoundManager::isMusicPlaying() { - return mMusic && mOutput->isStreamPlaying(mMusic); + return mMusic && mOutput->isStreamPlaying(mMusic.get()); } void SoundManager::playPlaylist(const std::string &playlist) @@ -472,10 +467,10 @@ namespace MWSound const osg::Vec3f pos = world->getActorHeadTransform(ptr).getTrans(); stopSay(ptr); - Stream *sound = playVoice(decoder, pos, (ptr == MWMechanics::getPlayer())); + StreamPtr sound = playVoice(decoder, pos, (ptr == MWMechanics::getPlayer())); if(!sound) return; - mSaySoundsQueue.emplace(ptr, sound); + mSaySoundsQueue.emplace(ptr, std::move(sound)); } float SoundManager::getSaySoundLoudness(const MWWorld::ConstPtr &ptr) const @@ -483,7 +478,7 @@ namespace MWSound SaySoundMap::const_iterator snditer = mActiveSaySounds.find(ptr); if(snditer != mActiveSaySounds.end()) { - Stream *sound = snditer->second; + Stream *sound = snditer->second.get(); return mOutput->getStreamLoudness(sound); } @@ -503,10 +498,10 @@ namespace MWSound return; stopSay(MWWorld::ConstPtr()); - Stream *sound = playVoice(decoder, osg::Vec3f(), true); + StreamPtr sound = playVoice(decoder, osg::Vec3f(), true); if(!sound) return; - mActiveSaySounds.insert(std::make_pair(MWWorld::ConstPtr(), sound)); + mActiveSaySounds.emplace(MWWorld::ConstPtr(), std::move(sound)); } bool SoundManager::sayDone(const MWWorld::ConstPtr &ptr) const @@ -514,7 +509,7 @@ namespace MWSound SaySoundMap::const_iterator snditer = mActiveSaySounds.find(ptr); if(snditer != mActiveSaySounds.end()) { - if(mOutput->isStreamPlaying(snditer->second)) + if(mOutput->isStreamPlaying(snditer->second.get())) return false; return true; } @@ -526,7 +521,7 @@ namespace MWSound SaySoundMap::const_iterator snditer = mSaySoundsQueue.find(ptr); if(snditer != mSaySoundsQueue.end()) { - if(mOutput->isStreamPlaying(snditer->second)) + if(mOutput->isStreamPlaying(snditer->second.get())) return true; return false; } @@ -534,7 +529,7 @@ namespace MWSound snditer = mActiveSaySounds.find(ptr); if(snditer != mActiveSaySounds.end()) { - if(mOutput->isStreamPlaying(snditer->second)) + if(mOutput->isStreamPlaying(snditer->second.get())) return true; return false; } @@ -547,16 +542,14 @@ namespace MWSound SaySoundMap::iterator snditer = mSaySoundsQueue.find(ptr); if(snditer != mSaySoundsQueue.end()) { - mOutput->finishStream(snditer->second); - mStreams.recycle(snditer->second); + mOutput->finishStream(snditer->second.get()); mSaySoundsQueue.erase(snditer); } snditer = mActiveSaySounds.find(ptr); if(snditer != mActiveSaySounds.end()) { - mOutput->finishStream(snditer->second); - mStreams.recycle(snditer->second); + mOutput->finishStream(snditer->second.get()); mActiveSaySounds.erase(snditer); } } @@ -567,27 +560,24 @@ namespace MWSound if(!mOutput->isInitialized()) return nullptr; - Stream *track = getStreamRef(); + StreamPtr track = getStreamRef(); track->init(1.0f, volumeFromType(type), 1.0f, PlayMode::NoEnv|type|Play_2D); - if(!mOutput->streamSound(decoder, track)) - { - mStreams.recycle(track); + if(!mOutput->streamSound(decoder, track.get())) return nullptr; - } - mActiveTracks.insert( - std::lower_bound(mActiveTracks.begin(), mActiveTracks.end(), track), track - ); - return track; + Stream* result = track.get(); + const auto it = std::lower_bound(mActiveTracks.begin(), mActiveTracks.end(), track); + mActiveTracks.insert(it, std::move(track)); + return result; } void SoundManager::stopTrack(Stream *stream) { mOutput->finishStream(stream); - TrackList::iterator iter = std::lower_bound(mActiveTracks.begin(), mActiveTracks.end(), stream); - if(iter != mActiveTracks.end() && *iter == stream) + TrackList::iterator iter = std::lower_bound(mActiveTracks.begin(), mActiveTracks.end(), stream, + [] (const StreamPtr& lhs, Stream* rhs) { return lhs.get() < rhs; }); + if(iter != mActiveTracks.end() && iter->get() == stream) mActiveTracks.erase(iter); - mStreams.recycle(stream); } double SoundManager::getTrackTimeDelay(Stream *stream) @@ -596,7 +586,7 @@ namespace MWSound } - Sound *SoundManager::playSound(const std::string& soundId, float volume, float pitch, Type type, PlayMode mode, float offset) + Sound* SoundManager::playSound(const std::string& soundId, float volume, float pitch, Type type, PlayMode mode, float offset) { if(!mOutput->isInitialized()) return nullptr; @@ -607,13 +597,10 @@ namespace MWSound // Only one copy of given sound can be played at time, so stop previous copy stopSound(sfx, MWWorld::ConstPtr()); - Sound *sound = getSoundRef(); + SoundPtr sound = getSoundRef(); sound->init(volume * sfx->mVolume, volumeFromType(type), pitch, mode|type|Play_2D); - if(!mOutput->playSound(sound, sfx->mHandle, offset)) - { - mSounds.recycle(sound); + if(!mOutput->playSound(sound.get(), sfx->mHandle, offset)) return nullptr; - } if(sfx->mUses++ == 0) { @@ -621,8 +608,9 @@ namespace MWSound if(iter != mUnusedBuffers.end()) mUnusedBuffers.erase(iter); } - mActiveSounds[MWWorld::ConstPtr()].push_back(std::make_pair(sound, sfx)); - return sound; + Sound* result = sound.get(); + mActiveSounds[MWWorld::ConstPtr()].emplace_back(std::move(sound), sfx); + return result; } Sound *SoundManager::playSound3D(const MWWorld::ConstPtr &ptr, const std::string& soundId, @@ -644,23 +632,20 @@ namespace MWSound stopSound(sfx, ptr); bool played; - Sound *sound = getSoundRef(); + SoundPtr sound = getSoundRef(); if(!(mode&PlayMode::NoPlayerLocal) && ptr == MWMechanics::getPlayer()) { sound->init(volume * sfx->mVolume, volumeFromType(type), pitch, mode|type|Play_2D); - played = mOutput->playSound(sound, sfx->mHandle, offset); + played = mOutput->playSound(sound.get(), sfx->mHandle, offset); } else { sound->init(objpos, volume * sfx->mVolume, volumeFromType(type), pitch, sfx->mMinDist, sfx->mMaxDist, mode|type|Play_3D); - played = mOutput->playSound3D(sound, sfx->mHandle, offset); + played = mOutput->playSound3D(sound.get(), sfx->mHandle, offset); } if(!played) - { - mSounds.recycle(sound); return nullptr; - } if(sfx->mUses++ == 0) { @@ -668,8 +653,9 @@ namespace MWSound if(iter != mUnusedBuffers.end()) mUnusedBuffers.erase(iter); } - mActiveSounds[ptr].push_back(std::make_pair(sound, sfx)); - return sound; + Sound* result = sound.get(); + mActiveSounds[ptr].emplace_back(std::move(sound), sfx); + return result; } Sound *SoundManager::playSound3D(const osg::Vec3f& initialPos, const std::string& soundId, @@ -683,14 +669,11 @@ namespace MWSound Sound_Buffer *sfx = loadSound(Misc::StringUtils::lowerCase(soundId)); if(!sfx) return nullptr; - Sound *sound = getSoundRef(); + SoundPtr sound = getSoundRef(); sound->init(initialPos, volume * sfx->mVolume, volumeFromType(type), pitch, sfx->mMinDist, sfx->mMaxDist, mode|type|Play_3D); - if(!mOutput->playSound3D(sound, sfx->mHandle, offset)) - { - mSounds.recycle(sound); + if(!mOutput->playSound3D(sound.get(), sfx->mHandle, offset)) return nullptr; - } if(sfx->mUses++ == 0) { @@ -698,8 +681,9 @@ namespace MWSound if(iter != mUnusedBuffers.end()) mUnusedBuffers.erase(iter); } - mActiveSounds[MWWorld::ConstPtr()].push_back(std::make_pair(sound, sfx)); - return sound; + Sound* result = sound.get(); + mActiveSounds[MWWorld::ConstPtr()].emplace_back(std::move(sound), sfx); + return result; } void SoundManager::stopSound(Sound *sound) @@ -716,7 +700,7 @@ namespace MWSound for(SoundBufferRefPair &snd : snditer->second) { if(snd.second == sfx) - mOutput->finishSound(snd.first); + mOutput->finishSound(snd.first.get()); } } } @@ -738,14 +722,14 @@ namespace MWSound if(snditer != mActiveSounds.end()) { for(SoundBufferRefPair &snd : snditer->second) - mOutput->finishSound(snd.first); + mOutput->finishSound(snd.first.get()); } SaySoundMap::iterator sayiter = mSaySoundsQueue.find(ptr); if(sayiter != mSaySoundsQueue.end()) - mOutput->finishStream(sayiter->second); + mOutput->finishStream(sayiter->second.get()); sayiter = mActiveSaySounds.find(ptr); if(sayiter != mActiveSaySounds.end()) - mOutput->finishStream(sayiter->second); + mOutput->finishStream(sayiter->second.get()); } void SoundManager::stopSound(const MWWorld::CellStore *cell) @@ -755,20 +739,20 @@ namespace MWSound if(!snd.first.isEmpty() && snd.first != MWMechanics::getPlayer() && snd.first.getCell() == cell) { for(SoundBufferRefPair &sndbuf : snd.second) - mOutput->finishSound(sndbuf.first); + mOutput->finishSound(sndbuf.first.get()); } } for(SaySoundMap::value_type &snd : mSaySoundsQueue) { if(!snd.first.isEmpty() && snd.first != MWMechanics::getPlayer() && snd.first.getCell() == cell) - mOutput->finishStream(snd.second); + mOutput->finishStream(snd.second.get()); } for(SaySoundMap::value_type &snd : mActiveSaySounds) { if(!snd.first.isEmpty() && snd.first != MWMechanics::getPlayer() && snd.first.getCell() == cell) - mOutput->finishStream(snd.second); + mOutput->finishStream(snd.second.get()); } } @@ -795,7 +779,7 @@ namespace MWSound Sound_Buffer *sfx = lookupSound(Misc::StringUtils::lowerCase(soundId)); return std::find_if(snditer->second.cbegin(), snditer->second.cend(), [this,sfx](const SoundBufferRefPair &snd) -> bool - { return snd.second == sfx && mOutput->isSoundPlaying(snd.first); } + { return snd.second == sfx && mOutput->isSoundPlaying(snd.first.get()); } ) != snditer->second.cend(); } return false; @@ -912,7 +896,7 @@ namespace MWSound const auto pairiter = std::find_if( snditer->second.begin(), snditer->second.end(), [this](const SoundBufferRefPairList::value_type &item) -> bool - { return mNearWaterSound == item.first; } + { return mNearWaterSound == item.first.get(); } ); if (pairiter != snditer->second.end() && pairiter->second != sfx) soundIdChanged = true; @@ -938,7 +922,11 @@ namespace MWSound SaySoundMap::iterator queuesayiter = mSaySoundsQueue.begin(); while (queuesayiter != mSaySoundsQueue.end()) { - mActiveSaySounds[queuesayiter->first] = queuesayiter->second; + const auto dst = mActiveSaySounds.find(queuesayiter->first); + if (dst == mActiveSaySounds.end()) + mActiveSaySounds.emplace(queuesayiter->first, std::move(queuesayiter->second)); + else + dst->second = std::move(queuesayiter->second); mSaySoundsQueue.erase(queuesayiter++); } @@ -979,10 +967,9 @@ namespace MWSound SoundBufferRefPairList::iterator sndidx = snditer->second.begin(); while(sndidx != snditer->second.end()) { - Sound *sound; - Sound_Buffer *sfx; + Sound *sound = sndidx->first.get(); + Sound_Buffer *sfx = sndidx->second; - std::tie(sound, sfx) = *sndidx; if(!ptr.isEmpty() && sound->getIs3D()) { const ESM::Position &pos = ptr.getRefData().getPosition(); @@ -999,10 +986,9 @@ namespace MWSound if(!mOutput->isSoundPlaying(sound)) { mOutput->finishSound(sound); - mSounds.recycle(sound); - if(sound == mUnderwaterSound) + if (sound == mUnderwaterSound) mUnderwaterSound = nullptr; - if(sound == mNearWaterSound) + if (sound == mNearWaterSound) mNearWaterSound = nullptr; if(sfx->mUses-- == 1) mUnusedBuffers.push_front(sfx); @@ -1026,7 +1012,7 @@ namespace MWSound while(sayiter != mActiveSaySounds.end()) { MWWorld::ConstPtr ptr = sayiter->first; - Stream *sound = sayiter->second; + Stream *sound = sayiter->second.get(); if(!ptr.isEmpty() && sound->getIs3D()) { MWBase::World *world = MWBase::Environment::get().getWorld(); @@ -1043,7 +1029,6 @@ namespace MWSound if(!mOutput->isStreamPlaying(sound)) { mOutput->finishStream(sound); - mStreams.recycle(sound); mActiveSaySounds.erase(sayiter++); } else @@ -1058,7 +1043,7 @@ namespace MWSound TrackList::iterator trkiter = mActiveTracks.begin(); for(;trkiter != mActiveTracks.end();++trkiter) { - Stream *sound = *trkiter; + Stream *sound = trkiter->get(); if(!mOutput->isStreamPlaying(sound)) { mOutput->finishStream(sound); @@ -1089,7 +1074,7 @@ namespace MWSound { mMusic->updateFade(duration); - mOutput->updateStream(mMusic); + mOutput->updateStream(mMusic.get()); if (mMusic->getRealVolume() <= 0.f) { @@ -1126,32 +1111,32 @@ namespace MWSound { for(SoundBufferRefPair &sndbuf : snd.second) { - Sound *sound = sndbuf.first; + Sound *sound = sndbuf.first.get(); sound->setBaseVolume(volumeFromType(sound->getPlayType())); mOutput->updateSound(sound); } } for(SaySoundMap::value_type &snd : mActiveSaySounds) { - Stream *sound = snd.second; + Stream *sound = snd.second.get(); sound->setBaseVolume(volumeFromType(sound->getPlayType())); mOutput->updateStream(sound); } for(SaySoundMap::value_type &snd : mSaySoundsQueue) { - Stream *sound = snd.second; + Stream *sound = snd.second.get(); sound->setBaseVolume(volumeFromType(sound->getPlayType())); mOutput->updateStream(sound); } - for(Stream *sound : mActiveTracks) + for (const StreamPtr& sound : mActiveTracks) { sound->setBaseVolume(volumeFromType(sound->getPlayType())); - mOutput->updateStream(sound); + mOutput->updateStream(sound.get()); } if(mMusic) { mMusic->setBaseVolume(volumeFromType(mMusic->getPlayType())); - mOutput->updateStream(mMusic); + mOutput->updateStream(mMusic.get()); } mOutput->finishUpdate(); } @@ -1180,17 +1165,17 @@ namespace MWSound SaySoundMap::iterator sayiter = mSaySoundsQueue.find(old); if(sayiter != mSaySoundsQueue.end()) { - Stream *stream = sayiter->second; + StreamPtr stream = std::move(sayiter->second); mSaySoundsQueue.erase(sayiter); - mSaySoundsQueue.emplace(updated, stream); + mSaySoundsQueue.emplace(updated, std::move(stream)); } sayiter = mActiveSaySounds.find(old); if(sayiter != mActiveSaySounds.end()) { - Stream *stream = sayiter->second; + StreamPtr stream = std::move(sayiter->second); mActiveSaySounds.erase(sayiter); - mActiveSaySounds.emplace(updated, stream); + mActiveSaySounds.emplace(updated, std::move(stream)); } } @@ -1267,8 +1252,7 @@ namespace MWSound { for(SoundBufferRefPair &sndbuf : snd.second) { - mOutput->finishSound(sndbuf.first); - mSounds.recycle(sndbuf.first); + mOutput->finishSound(sndbuf.first.get()); Sound_Buffer *sfx = sndbuf.second; if(sfx->mUses-- == 1) mUnusedBuffers.push_front(sfx); @@ -1279,24 +1263,15 @@ namespace MWSound mNearWaterSound = nullptr; for(SaySoundMap::value_type &snd : mSaySoundsQueue) - { - mOutput->finishStream(snd.second); - mStreams.recycle(snd.second); - } + mOutput->finishStream(snd.second.get()); mSaySoundsQueue.clear(); for(SaySoundMap::value_type &snd : mActiveSaySounds) - { - mOutput->finishStream(snd.second); - mStreams.recycle(snd.second); - } + mOutput->finishStream(snd.second.get()); mActiveSaySounds.clear(); - for(Stream *sound : mActiveTracks) - { - mOutput->finishStream(sound); - mStreams.recycle(sound); - } + for(StreamPtr& sound : mActiveTracks) + mOutput->finishStream(sound.get()); mActiveTracks.clear(); mPlaybackPaused = false; std::fill(std::begin(mPausedSoundTypes), std::end(mPausedSoundTypes), 0); diff --git a/apps/openmw/mwsound/soundmanagerimp.hpp b/apps/openmw/mwsound/soundmanagerimp.hpp index e03bd7b1f4..b3f612d7d6 100644 --- a/apps/openmw/mwsound/soundmanagerimp.hpp +++ b/apps/openmw/mwsound/soundmanagerimp.hpp @@ -48,6 +48,9 @@ namespace MWSound Play_3D = 1<<31 }; + using SoundPtr = Misc::ObjectPtr; + using StreamPtr = Misc::ObjectPtr; + class SoundManager : public MWBase::SoundManager { const VFS::Manager* mVFS; @@ -83,19 +86,19 @@ namespace MWSound Misc::ObjectPool mStreams; - typedef std::pair SoundBufferRefPair; + typedef std::pair SoundBufferRefPair; typedef std::vector SoundBufferRefPairList; typedef std::map SoundMap; SoundMap mActiveSounds; - typedef std::map SaySoundMap; + typedef std::map SaySoundMap; SaySoundMap mSaySoundsQueue; SaySoundMap mActiveSaySounds; - typedef std::vector TrackList; + typedef std::vector TrackList; TrackList mActiveTracks; - Stream *mMusic; + StreamPtr mMusic; std::string mCurrentPlaylist; bool mListenerUnderwater; @@ -125,10 +128,10 @@ namespace MWSound // returns a decoder to start streaming, or nullptr if the sound was not found DecoderPtr loadVoice(const std::string &voicefile); - Sound *getSoundRef(); - Stream *getStreamRef(); + SoundPtr getSoundRef(); + StreamPtr getStreamRef(); - Stream *playVoice(DecoderPtr decoder, const osg::Vec3f &pos, bool playlocal); + StreamPtr playVoice(DecoderPtr decoder, const osg::Vec3f &pos, bool playlocal); void streamMusicFull(const std::string& filename); void advanceMusic(const std::string& filename); diff --git a/components/misc/objectpool.hpp b/components/misc/objectpool.hpp index 97a0553313..b3dae6a4f5 100644 --- a/components/misc/objectpool.hpp +++ b/components/misc/objectpool.hpp @@ -7,14 +7,51 @@ namespace Misc { + template + class ObjectPool; + + template + class ObjectPtrDeleter + { + public: + ObjectPtrDeleter(std::nullptr_t) + : mPool(nullptr) {} + + ObjectPtrDeleter(ObjectPool& pool) + : mPool(&pool) {} + + void operator()(T* object) const + { + mPool->recycle(object); + } + + private: + ObjectPool* mPool; + }; + + template + struct ObjectPtr final : std::unique_ptr> + { + using std::unique_ptr>::unique_ptr; + using std::unique_ptr>::operator=; + + ObjectPtr() + : ObjectPtr(nullptr) {} + + ObjectPtr(std::nullptr_t) + : std::unique_ptr>(nullptr, nullptr) {} + }; + template class ObjectPool { + friend class ObjectPtrDeleter; + public: ObjectPool() : mObjects(std::make_unique>()) {} - T* get() + ObjectPtr get() { T* object; @@ -29,17 +66,17 @@ namespace Misc object = &mObjects->back(); } - return object; + return ObjectPtr(object, ObjectPtrDeleter(*this)); } + private: + std::unique_ptr> mObjects; + std::vector mUnused; + void recycle(T* object) { mUnused.push_back(object); } - - private: - std::unique_ptr> mObjects; - std::vector mUnused; }; }