From 1fe60dd8e23ffe34c6ddad66b4829f3a4253e38f Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Mon, 11 Sep 2017 21:33:18 -0700 Subject: [PATCH] Replace some shared_ptrs with pointers to deque entries --- apps/openmw/mwbase/soundmanager.hpp | 29 ++-- apps/openmw/mwsound/movieaudiofactory.cpp | 12 +- apps/openmw/mwsound/openal_output.cpp | 26 +-- apps/openmw/mwsound/openal_output.hpp | 33 ++-- apps/openmw/mwsound/sound.hpp | 46 +++-- apps/openmw/mwsound/sound_output.hpp | 29 ++-- apps/openmw/mwsound/soundmanagerimp.cpp | 202 ++++++++++++++-------- apps/openmw/mwsound/soundmanagerimp.hpp | 44 +++-- apps/openmw/mwworld/projectilemanager.cpp | 6 +- apps/openmw/mwworld/projectilemanager.hpp | 2 +- apps/openmw/mwworld/weather.cpp | 8 +- apps/openmw/mwworld/weather.hpp | 2 +- 12 files changed, 262 insertions(+), 177 deletions(-) diff --git a/apps/openmw/mwbase/soundmanager.hpp b/apps/openmw/mwbase/soundmanager.hpp index 9aa4bafdf..9986564cd 100644 --- a/apps/openmw/mwbase/soundmanager.hpp +++ b/apps/openmw/mwbase/soundmanager.hpp @@ -22,8 +22,8 @@ namespace MWSound namespace MWBase { - typedef std::shared_ptr SoundPtr; - typedef std::shared_ptr SoundStreamPtr; + using Sound = MWSound::Sound; + using SoundStream = MWSound::Stream; /// \brief Interface for sound manager (implemented in MWSound) class SoundManager @@ -106,34 +106,35 @@ namespace MWBase /// and get an average loudness value (scale [0,1]) at the current time position. /// If the actor is not saying anything, returns 0. - virtual SoundStreamPtr playTrack(const MWSound::DecoderPtr& decoder, PlayType type) = 0; + virtual SoundStream *playTrack(const MWSound::DecoderPtr& decoder, PlayType type) = 0; ///< Play a 2D audio track, using a custom decoder - virtual void stopTrack(SoundStreamPtr stream) = 0; + virtual void stopTrack(SoundStream *stream) = 0; ///< Stop the given audio track from playing - virtual double getTrackTimeDelay(SoundStreamPtr stream) = 0; + virtual double getTrackTimeDelay(SoundStream *stream) = 0; ///< Retives the time delay, in seconds, of the audio track (must be a sound /// returned by \ref playTrack). Only intended to be called by the track /// decoder's read method. - virtual SoundPtr playSound(const std::string& soundId, float volume, float pitch, - PlayType type=Play_TypeSfx, PlayMode mode=Play_Normal, - float offset=0) = 0; + virtual Sound *playSound(const std::string& soundId, float volume, float pitch, + PlayType type=Play_TypeSfx, PlayMode mode=Play_Normal, + float offset=0) = 0; ///< Play a sound, independently of 3D-position ///< @param offset Number of seconds into the sound to start playback. - virtual MWBase::SoundPtr playSound3D(const MWWorld::ConstPtr &reference, const std::string& soundId, - float volume, float pitch, PlayType type=Play_TypeSfx, - PlayMode mode=Play_Normal, float offset=0) = 0; + virtual Sound *playSound3D(const MWWorld::ConstPtr &reference, const std::string& soundId, + float volume, float pitch, PlayType type=Play_TypeSfx, + PlayMode mode=Play_Normal, float offset=0) = 0; ///< Play a 3D sound attached to an MWWorld::Ptr. Will be updated automatically with the Ptr's position, unless Play_NoTrack is specified. ///< @param offset Number of seconds into the sound to start playback. - virtual MWBase::SoundPtr playSound3D(const osg::Vec3f& initialPos, const std::string& soundId, - float volume, float pitch, PlayType type=Play_TypeSfx, PlayMode mode=Play_Normal, float offset=0) = 0; + virtual Sound *playSound3D(const osg::Vec3f& initialPos, const std::string& soundId, + float volume, float pitch, PlayType type=Play_TypeSfx, + PlayMode mode=Play_Normal, float offset=0) = 0; ///< Play a 3D sound at \a initialPos. If the sound should be moving, it must be updated using Sound::setPosition. - virtual void stopSound(SoundPtr sound) = 0; + virtual void stopSound(Sound *sound) = 0; ///< Stop the given sound from playing virtual void stopSound3D(const MWWorld::ConstPtr &reference, const std::string& soundId) = 0; diff --git a/apps/openmw/mwsound/movieaudiofactory.cpp b/apps/openmw/mwsound/movieaudiofactory.cpp index 2d7f3a969..9c9b442c7 100644 --- a/apps/openmw/mwsound/movieaudiofactory.cpp +++ b/apps/openmw/mwsound/movieaudiofactory.cpp @@ -37,7 +37,7 @@ namespace MWSound { public: MovieAudioDecoder(Video::VideoState *videoState) - : Video::MovieAudioDecoder(videoState) + : Video::MovieAudioDecoder(videoState), mAudioTrack(nullptr) { mDecoderBridge.reset(new MWSoundDecoderBridge(this)); } @@ -85,13 +85,13 @@ namespace MWSound public: ~MovieAudioDecoder() { - if(mAudioTrack.get()) + if(mAudioTrack) MWBase::Environment::get().getSoundManager()->stopTrack(mAudioTrack); - mAudioTrack.reset(); + mAudioTrack = nullptr; mDecoderBridge.reset(); } - MWBase::SoundStreamPtr mAudioTrack; + MWBase::SoundStream *mAudioTrack; std::shared_ptr mDecoderBridge; }; @@ -162,8 +162,8 @@ namespace MWSound decoder->setupFormat(); MWBase::SoundManager *sndMgr = MWBase::Environment::get().getSoundManager(); - MWBase::SoundStreamPtr sound = sndMgr->playTrack(decoder->mDecoderBridge, MWBase::SoundManager::Play_TypeMovie); - if (!sound.get()) + MWBase::SoundStream *sound = sndMgr->playTrack(decoder->mDecoderBridge, MWBase::SoundManager::Play_TypeMovie); + if (!sound) { decoder.reset(); return decoder; diff --git a/apps/openmw/mwsound/openal_output.cpp b/apps/openmw/mwsound/openal_output.cpp index 042795a8c..0e000f8d8 100644 --- a/apps/openmw/mwsound/openal_output.cpp +++ b/apps/openmw/mwsound/openal_output.cpp @@ -841,7 +841,7 @@ void OpenAL_Output::updateCommon(ALuint source, const osg::Vec3f& pos, ALfloat m } -void OpenAL_Output::playSound(MWBase::SoundPtr sound, Sound_Handle data, float offset) +void OpenAL_Output::playSound(Sound *sound, Sound_Handle data, float offset) { ALuint source; @@ -871,7 +871,7 @@ void OpenAL_Output::playSound(MWBase::SoundPtr sound, Sound_Handle data, float o sound->mHandle = MAKE_PTRID(source); } -void OpenAL_Output::playSound3D(MWBase::SoundPtr sound, Sound_Handle data, float offset) +void OpenAL_Output::playSound3D(Sound *sound, Sound_Handle data, float offset) { ALuint source; @@ -902,7 +902,7 @@ void OpenAL_Output::playSound3D(MWBase::SoundPtr sound, Sound_Handle data, float sound->mHandle = MAKE_PTRID(source); } -void OpenAL_Output::finishSound(MWBase::SoundPtr sound) +void OpenAL_Output::finishSound(Sound *sound) { if(!sound->mHandle) return; ALuint source = GET_PTRID(sound->mHandle); @@ -918,7 +918,7 @@ void OpenAL_Output::finishSound(MWBase::SoundPtr sound) mActiveSounds.erase(std::find(mActiveSounds.begin(), mActiveSounds.end(), sound)); } -bool OpenAL_Output::isSoundPlaying(MWBase::SoundPtr sound) +bool OpenAL_Output::isSoundPlaying(Sound *sound) { if(!sound->mHandle) return false; ALuint source = GET_PTRID(sound->mHandle); @@ -930,7 +930,7 @@ bool OpenAL_Output::isSoundPlaying(MWBase::SoundPtr sound) return state == AL_PLAYING || state == AL_PAUSED; } -void OpenAL_Output::updateSound(MWBase::SoundPtr sound) +void OpenAL_Output::updateSound(Sound *sound) { if(!sound->mHandle) return; ALuint source = GET_PTRID(sound->mHandle); @@ -940,7 +940,7 @@ void OpenAL_Output::updateSound(MWBase::SoundPtr sound) } -void OpenAL_Output::streamSound(DecoderPtr decoder, MWBase::SoundStreamPtr sound) +void OpenAL_Output::streamSound(DecoderPtr decoder, Stream *sound) { OpenAL_SoundStream *stream = 0; ALuint source; @@ -971,7 +971,7 @@ void OpenAL_Output::streamSound(DecoderPtr decoder, MWBase::SoundStreamPtr sound sound->mHandle = stream; } -void OpenAL_Output::streamSound3D(DecoderPtr decoder, MWBase::SoundStreamPtr sound, bool getLoudnessData) +void OpenAL_Output::streamSound3D(DecoderPtr decoder, Stream *sound, bool getLoudnessData) { OpenAL_SoundStream *stream = 0; ALuint source; @@ -1002,7 +1002,7 @@ void OpenAL_Output::streamSound3D(DecoderPtr decoder, MWBase::SoundStreamPtr sou sound->mHandle = stream; } -void OpenAL_Output::finishStream(MWBase::SoundStreamPtr sound) +void OpenAL_Output::finishStream(Stream *sound) { if(!sound->mHandle) return; OpenAL_SoundStream *stream = reinterpret_cast(sound->mHandle); @@ -1023,14 +1023,14 @@ void OpenAL_Output::finishStream(MWBase::SoundStreamPtr sound) delete stream; } -double OpenAL_Output::getStreamDelay(MWBase::SoundStreamPtr sound) +double OpenAL_Output::getStreamDelay(Stream *sound) { if(!sound->mHandle) return 0.0; OpenAL_SoundStream *stream = reinterpret_cast(sound->mHandle); return stream->getStreamDelay(); } -double OpenAL_Output::getStreamOffset(MWBase::SoundStreamPtr sound) +double OpenAL_Output::getStreamOffset(Stream *sound) { if(!sound->mHandle) return 0.0; OpenAL_SoundStream *stream = reinterpret_cast(sound->mHandle); @@ -1038,7 +1038,7 @@ double OpenAL_Output::getStreamOffset(MWBase::SoundStreamPtr sound) return stream->getStreamOffset(); } -float OpenAL_Output::getStreamLoudness(MWBase::SoundStreamPtr sound) +float OpenAL_Output::getStreamLoudness(Stream *sound) { if(!sound->mHandle) return 0.0; OpenAL_SoundStream *stream = reinterpret_cast(sound->mHandle); @@ -1046,7 +1046,7 @@ float OpenAL_Output::getStreamLoudness(MWBase::SoundStreamPtr sound) return stream->getCurrentLoudness(); } -bool OpenAL_Output::isStreamPlaying(MWBase::SoundStreamPtr sound) +bool OpenAL_Output::isStreamPlaying(Stream *sound) { if(!sound->mHandle) return false; OpenAL_SoundStream *stream = reinterpret_cast(sound->mHandle); @@ -1054,7 +1054,7 @@ bool OpenAL_Output::isStreamPlaying(MWBase::SoundStreamPtr sound) return stream->isPlaying(); } -void OpenAL_Output::updateStream(MWBase::SoundStreamPtr sound) +void OpenAL_Output::updateStream(Stream *sound) { if(!sound->mHandle) return; OpenAL_SoundStream *stream = reinterpret_cast(sound->mHandle); diff --git a/apps/openmw/mwsound/openal_output.hpp b/apps/openmw/mwsound/openal_output.hpp index ea3f393ff..cb943d87e 100644 --- a/apps/openmw/mwsound/openal_output.hpp +++ b/apps/openmw/mwsound/openal_output.hpp @@ -15,6 +15,7 @@ namespace MWSound { class SoundManager; class Sound; + class Stream; class OpenAL_Output : public Sound_Output { @@ -24,9 +25,9 @@ namespace MWSound typedef std::deque IDDq; IDDq mFreeSources; - typedef std::vector SoundVec; + typedef std::vector SoundVec; SoundVec mActiveSounds; - typedef std::vector StreamVec; + typedef std::vector StreamVec; StreamVec mActiveStreams; osg::Vec3f mListenerPos; @@ -56,20 +57,20 @@ namespace MWSound virtual void unloadSound(Sound_Handle data); virtual size_t getSoundDataSize(Sound_Handle data) const; - virtual void playSound(MWBase::SoundPtr sound, Sound_Handle data, float offset); - virtual void playSound3D(MWBase::SoundPtr sound, Sound_Handle data, float offset); - virtual void finishSound(MWBase::SoundPtr sound); - virtual bool isSoundPlaying(MWBase::SoundPtr sound); - virtual void updateSound(MWBase::SoundPtr sound); - - virtual void streamSound(DecoderPtr decoder, MWBase::SoundStreamPtr sound); - virtual void streamSound3D(DecoderPtr decoder, MWBase::SoundStreamPtr sound, bool getLoudnessData); - virtual void finishStream(MWBase::SoundStreamPtr sound); - virtual double getStreamDelay(MWBase::SoundStreamPtr sound); - virtual double getStreamOffset(MWBase::SoundStreamPtr sound); - virtual float getStreamLoudness(MWBase::SoundStreamPtr sound); - virtual bool isStreamPlaying(MWBase::SoundStreamPtr sound); - virtual void updateStream(MWBase::SoundStreamPtr sound); + virtual void playSound(Sound *sound, Sound_Handle data, float offset); + virtual void playSound3D(Sound *sound, Sound_Handle data, float offset); + virtual void finishSound(Sound *sound); + virtual bool isSoundPlaying(Sound *sound); + virtual void updateSound(Sound *sound); + + virtual void streamSound(DecoderPtr decoder, Stream *sound); + virtual void streamSound3D(DecoderPtr decoder, Stream *sound, bool getLoudnessData); + virtual void finishStream(Stream *sound); + virtual double getStreamDelay(Stream *sound); + virtual double getStreamOffset(Stream *sound); + virtual float getStreamLoudness(Stream *sound); + virtual bool isStreamPlaying(Stream *sound); + virtual void updateStream(Stream *sound); virtual void startUpdate(); virtual void finishUpdate(); diff --git a/apps/openmw/mwsound/sound.hpp b/apps/openmw/mwsound/sound.hpp index 8c663fb1e..9a3fc4e75 100644 --- a/apps/openmw/mwsound/sound.hpp +++ b/apps/openmw/mwsound/sound.hpp @@ -54,15 +54,36 @@ namespace MWSound bool getDistanceCull() const { return mFlags&MWBase::SoundManager::Play_RemoveAtDistance; } bool getIs3D() const { return mFlags&Play_3D; } - Sound(const osg::Vec3f& pos, float vol, float basevol, float pitch, float mindist, float maxdist, int flags) - : mPos(pos), mVolume(vol), mBaseVolume(basevol), mPitch(pitch) - , mMinDistance(mindist), mMaxDistance(maxdist), mFlags(flags) - , mFadeOutTime(0.0f), mHandle(0) - { } - Sound(float vol, float basevol, float pitch, int flags) - : mPos(0.0f, 0.0f, 0.0f), mVolume(vol), mBaseVolume(basevol), mPitch(pitch) - , mMinDistance(1.0f), mMaxDistance(1000.0f), mFlags(flags) - , mFadeOutTime(0.0f), mHandle(0) + void init(const osg::Vec3f& pos, float vol, float basevol, float pitch, float mindist, float maxdist, int flags) + { + mPos = pos; + mVolume = vol; + mBaseVolume = basevol; + mPitch = pitch; + mMinDistance = mindist; + mMaxDistance = maxdist; + mFlags = flags; + mFadeOutTime = 0.0f; + mHandle = nullptr; + } + + void init(float vol, float basevol, float pitch, int flags) + { + mPos = osg::Vec3f(0.0f, 0.0f, 0.0f); + mVolume = vol; + mBaseVolume = basevol; + mPitch = pitch; + mMinDistance = 1.0f; + mMaxDistance = 1000.0f; + mFlags = flags; + mFadeOutTime = 0.0f; + mHandle = nullptr; + } + + Sound() + : mPos(0.0f, 0.0f, 0.0f), mVolume(1.0f), mBaseVolume(1.0f), mPitch(1.0f) + , mMinDistance(1.0f), mMaxDistance(1000.0f), mFlags(0), mFadeOutTime(0.0f) + , mHandle(0) { } }; @@ -72,12 +93,7 @@ namespace MWSound Stream(const Stream &rhs); public: - Stream(const osg::Vec3f& pos, float vol, float basevol, float pitch, float mindist, float maxdist, int flags) - : Sound(pos, vol, basevol, pitch, mindist, maxdist, flags) - { } - Stream(float vol, float basevol, float pitch, int flags) - : Sound(vol, basevol, pitch, flags) - { } + Stream() { } }; } diff --git a/apps/openmw/mwsound/sound_output.hpp b/apps/openmw/mwsound/sound_output.hpp index e34d888ee..907a601b5 100644 --- a/apps/openmw/mwsound/sound_output.hpp +++ b/apps/openmw/mwsound/sound_output.hpp @@ -12,6 +12,7 @@ namespace MWSound class SoundManager; struct Sound_Decoder; class Sound; + class Stream; // An opaque handle for the implementation's sound buffers. typedef void *Sound_Handle; @@ -34,20 +35,20 @@ namespace MWSound virtual void unloadSound(Sound_Handle data) = 0; virtual size_t getSoundDataSize(Sound_Handle data) const = 0; - virtual void playSound(MWBase::SoundPtr sound, Sound_Handle data, float offset) = 0; - virtual void playSound3D(MWBase::SoundPtr sound, Sound_Handle data, float offset) = 0; - virtual void finishSound(MWBase::SoundPtr sound) = 0; - virtual bool isSoundPlaying(MWBase::SoundPtr sound) = 0; - virtual void updateSound(MWBase::SoundPtr sound) = 0; - - virtual void streamSound(DecoderPtr decoder, MWBase::SoundStreamPtr sound) = 0; - virtual void streamSound3D(DecoderPtr decoder, MWBase::SoundStreamPtr sound, bool getLoudnessData) = 0; - virtual void finishStream(MWBase::SoundStreamPtr sound) = 0; - virtual double getStreamDelay(MWBase::SoundStreamPtr sound) = 0; - virtual double getStreamOffset(MWBase::SoundStreamPtr sound) = 0; - virtual float getStreamLoudness(MWBase::SoundStreamPtr sound) = 0; - virtual bool isStreamPlaying(MWBase::SoundStreamPtr sound) = 0; - virtual void updateStream(MWBase::SoundStreamPtr sound) = 0; + virtual void playSound(Sound *sound, Sound_Handle data, float offset) = 0; + virtual void playSound3D(Sound *sound, Sound_Handle data, float offset) = 0; + virtual void finishSound(Sound *sound) = 0; + virtual bool isSoundPlaying(Sound *sound) = 0; + virtual void updateSound(Sound *sound) = 0; + + virtual void streamSound(DecoderPtr decoder, Stream *sound) = 0; + virtual void streamSound3D(DecoderPtr decoder, Stream *sound, bool getLoudnessData) = 0; + virtual void finishStream(Stream *sound) = 0; + virtual double getStreamDelay(Stream *sound) = 0; + virtual double getStreamOffset(Stream *sound) = 0; + virtual float getStreamLoudness(Stream *sound) = 0; + virtual bool isStreamPlaying(Stream *sound) = 0; + virtual void updateStream(Stream *sound) = 0; virtual void startUpdate() = 0; virtual void finishUpdate() = 0; diff --git a/apps/openmw/mwsound/soundmanagerimp.cpp b/apps/openmw/mwsound/soundmanagerimp.cpp index 15b95b233..f8b753a18 100644 --- a/apps/openmw/mwsound/soundmanagerimp.cpp +++ b/apps/openmw/mwsound/soundmanagerimp.cpp @@ -46,11 +46,16 @@ namespace MWSound , mFootstepsVolume(1.0f) , mSoundBuffers(new SoundBufferList::element_type()) , mBufferCacheSize(0) + , mSounds(new std::deque()) + , mStreams(new std::deque()) + , mMusic(nullptr) , mListenerUnderwater(false) , mListenerPos(0,0,0) , mListenerDir(1,0,0) , mListenerUp(0,0,1) , mPausedSoundTypes(0) + , mUnderwaterSound(nullptr) + , mNearWaterSound(nullptr) { mMasterVolume = Settings::Manager::getFloat("master volume", "Sound"); mMasterVolume = std::min(std::max(mMasterVolume, 0.0f), 1.0f); @@ -246,7 +251,39 @@ namespace MWSound return decoder; } - MWBase::SoundStreamPtr SoundManager::playVoice(DecoderPtr decoder, const osg::Vec3f &pos, bool playlocal) + Sound *SoundManager::getSoundRef() + { + Sound *ret; + if(!mUnusedSounds.empty()) + { + ret = mUnusedSounds.back(); + mUnusedSounds.pop_back(); + } + else + { + mSounds->emplace_back(); + ret = &mSounds->back(); + } + return ret; + } + + Stream *SoundManager::getStreamRef() + { + Stream *ret; + if(!mUnusedStreams.empty()) + { + ret = mUnusedStreams.back(); + mUnusedStreams.pop_back(); + } + else + { + mStreams->emplace_back(); + ret = &mStreams->back(); + } + return ret; + } + + Stream *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")->getFloat(); @@ -256,17 +293,17 @@ namespace MWSound static float minDistance = std::max(fAudioVoiceDefaultMinDistance * fAudioMinDistanceMult, 1.0f); static float maxDistance = std::max(fAudioVoiceDefaultMaxDistance * fAudioMaxDistanceMult, minDistance); - MWBase::SoundStreamPtr sound; float basevol = volumeFromType(Play_TypeVoice); + Stream *sound = getStreamRef(); if(playlocal) { - sound.reset(new Stream(1.0f, basevol, 1.0f, Play_NoEnv|Play_TypeVoice|Play_2D)); + sound->init(1.0f, basevol, 1.0f, Play_NoEnv|Play_TypeVoice|Play_2D); mOutput->streamSound(decoder, sound); } else { - sound.reset(new Stream(pos, 1.0f, basevol, 1.0f, minDistance, maxDistance, - Play_Normal|Play_TypeVoice|Play_3D)); + sound->init(pos, 1.0f, basevol, 1.0f, minDistance, maxDistance, + Play_Normal|Play_TypeVoice|Play_3D); mOutput->streamSound3D(decoder, sound, true); } return sound; @@ -301,8 +338,11 @@ namespace MWSound void SoundManager::stopMusic() { if(mMusic) + { mOutput->finishStream(mMusic); - mMusic.reset(); + mUnusedStreams.push_back(mMusic); + mMusic = nullptr; + } } void SoundManager::streamMusicFull(const std::string& filename) @@ -317,13 +357,16 @@ namespace MWSound DecoderPtr decoder = getDecoder(); decoder->open(filename); - mMusic.reset(new Stream(1.0f, volumeFromType(Play_TypeMusic), 1.0f, - Play_NoEnv|Play_TypeMusic|Play_2D)); + mMusic = getStreamRef(); + mMusic->init(1.0f, volumeFromType(Play_TypeMusic), 1.0f, + Play_NoEnv|Play_TypeMusic|Play_2D); mOutput->streamSound(decoder, mMusic); } catch(std::exception &e) { std::cout << "Music Error: " << e.what() << "\n"; - mMusic.reset(); + if(mMusic) + mUnusedStreams.push_back(mMusic); + mMusic = nullptr; } } @@ -421,15 +464,8 @@ namespace MWSound MWBase::World *world = MWBase::Environment::get().getWorld(); const osg::Vec3f pos = world->getActorHeadTransform(ptr).getTrans(); - SaySoundMap::iterator oldIt = mActiveSaySounds.find(ptr); - if (oldIt != mActiveSaySounds.end()) - { - mOutput->finishStream(oldIt->second); - mActiveSaySounds.erase(oldIt); - } - - MWBase::SoundStreamPtr sound = playVoice(decoder, pos, (ptr == MWMechanics::getPlayer())); - + stopSay(ptr); + Stream *sound = playVoice(decoder, pos, (ptr == MWMechanics::getPlayer())); mActiveSaySounds.insert(std::make_pair(ptr, sound)); } catch(std::exception &e) @@ -443,7 +479,7 @@ namespace MWSound SaySoundMap::const_iterator snditer = mActiveSaySounds.find(ptr); if(snditer != mActiveSaySounds.end()) { - MWBase::SoundStreamPtr sound = snditer->second; + Stream *sound = snditer->second; return mOutput->getStreamLoudness(sound); } @@ -461,13 +497,7 @@ namespace MWSound mVFS->normalizeFilename(voicefile); DecoderPtr decoder = loadVoice(voicefile); - SaySoundMap::iterator oldIt = mActiveSaySounds.find(MWWorld::ConstPtr()); - if (oldIt != mActiveSaySounds.end()) - { - mOutput->finishStream(oldIt->second); - mActiveSaySounds.erase(oldIt); - } - + stopSay(MWWorld::ConstPtr()); mActiveSaySounds.insert(std::make_pair(MWWorld::ConstPtr(), playVoice(decoder, osg::Vec3f(), true))); } @@ -495,19 +525,20 @@ namespace MWSound if(snditer != mActiveSaySounds.end()) { mOutput->finishStream(snditer->second); + mUnusedStreams.push_back(snditer->second); mActiveSaySounds.erase(snditer); } } - MWBase::SoundStreamPtr SoundManager::playTrack(const DecoderPtr& decoder, PlayType type) + Stream *SoundManager::playTrack(const DecoderPtr& decoder, PlayType type) { - MWBase::SoundStreamPtr track; if(!mOutput->isInitialized()) - return track; + return nullptr; + Stream *track = getStreamRef(); try { - track.reset(new Stream(1.0f, volumeFromType(type), 1.0f, Play_NoEnv|type|Play_2D)); + track->init(1.0f, volumeFromType(type), 1.0f, Play_NoEnv|type|Play_2D); mOutput->streamSound(decoder, track); TrackList::iterator iter = std::lower_bound(mActiveTracks.begin(), mActiveTracks.end(), track); @@ -516,35 +547,40 @@ namespace MWSound catch(std::exception &e) { std::cout <<"Sound Error: "<finishStream(stream); TrackList::iterator iter = std::lower_bound(mActiveTracks.begin(), mActiveTracks.end(), stream); if(iter != mActiveTracks.end() && *iter == stream) mActiveTracks.erase(iter); + mUnusedStreams.push_back(stream); } - double SoundManager::getTrackTimeDelay(MWBase::SoundStreamPtr stream) + double SoundManager::getTrackTimeDelay(Stream *stream) { return mOutput->getStreamDelay(stream); } - MWBase::SoundPtr SoundManager::playSound(const std::string& soundId, float volume, float pitch, PlayType type, PlayMode mode, float offset) + Sound *SoundManager::playSound(const std::string& soundId, float volume, float pitch, PlayType type, PlayMode mode, float offset) { - MWBase::SoundPtr sound; if(!mOutput->isInitialized()) - return sound; + return nullptr; + Sound *sound = nullptr; try { Sound_Buffer *sfx = loadSound(Misc::StringUtils::lowerCase(soundId)); float basevol = volumeFromType(type); - sound.reset(new Sound(volume * sfx->mVolume, basevol, pitch, mode|type|Play_2D)); + sound = getSoundRef(); + sound->init(volume * sfx->mVolume, basevol, pitch, mode|type|Play_2D); mOutput->playSound(sound, sfx->mHandle, offset); if(sfx->mUses++ == 0) { @@ -557,17 +593,20 @@ namespace MWSound catch(std::exception&) { //std::cout <<"Sound Error: "<isInitialized()) - return sound; + return nullptr; + Sound *sound = nullptr; try { // Look up the sound in the ESM data @@ -577,20 +616,21 @@ namespace MWSound const osg::Vec3f objpos(pos.asVec3()); if((mode&Play_RemoveAtDistance) && (mListenerPos-objpos).length2() > 2000*2000) - return MWBase::SoundPtr(); + return nullptr; // Only one copy of given sound can be played at time on ptr, so stop previous copy stopSound3D(ptr, soundId); + sound = getSoundRef(); if(!(mode&Play_NoPlayerLocal) && ptr == MWMechanics::getPlayer()) { - sound.reset(new Sound(volume * sfx->mVolume, basevol, pitch, mode|type|Play_2D)); + sound->init(volume * sfx->mVolume, basevol, pitch, mode|type|Play_2D); mOutput->playSound(sound, sfx->mHandle, offset); } else { - sound.reset(new Sound(objpos, volume * sfx->mVolume, basevol, pitch, - sfx->mMinDist, sfx->mMaxDist, mode|type|Play_3D)); + sound->init(objpos, volume * sfx->mVolume, basevol, pitch, + sfx->mMinDist, sfx->mMaxDist, mode|type|Play_3D); mOutput->playSound3D(sound, sfx->mHandle, offset); } if(sfx->mUses++ == 0) @@ -604,25 +644,29 @@ namespace MWSound catch(std::exception&) { //std::cout <<"Sound Error: "<isInitialized()) - return sound; + return nullptr; + Sound *sound = nullptr; try { // Look up the sound in the ESM data Sound_Buffer *sfx = loadSound(Misc::StringUtils::lowerCase(soundId)); float basevol = volumeFromType(type); - sound.reset(new Sound(initialPos, volume * sfx->mVolume, basevol, pitch, - sfx->mMinDist, sfx->mMaxDist, mode|type|Play_3D)); + sound = getSoundRef(); + sound->init(initialPos, volume * sfx->mVolume, basevol, pitch, + sfx->mMinDist, sfx->mMaxDist, mode|type|Play_3D); mOutput->playSound3D(sound, sfx->mHandle, offset); if(sfx->mUses++ == 0) { @@ -635,14 +679,16 @@ namespace MWSound catch(std::exception &) { //std::cout <<"Sound Error: "<finishSound(sound); } @@ -675,7 +721,7 @@ namespace MWSound void SoundManager::stopSound(const MWWorld::CellStore *cell) { SoundMap::iterator snditer = mActiveSounds.begin(); - while(snditer != mActiveSounds.end()) + for(;snditer != mActiveSounds.end();++snditer) { if(snditer->first != MWWorld::ConstPtr() && snditer->first != MWMechanics::getPlayer() && @@ -685,18 +731,14 @@ namespace MWSound for(;sndidx != snditer->second.end();++sndidx) mOutput->finishSound(sndidx->first); } - ++snditer; } SaySoundMap::iterator sayiter = mActiveSaySounds.begin(); - while(sayiter != mActiveSaySounds.end()) + for(;sayiter != mActiveSaySounds.end();++sayiter) { if(sayiter->first != MWWorld::ConstPtr() && sayiter->first != MWMechanics::getPlayer() && sayiter->first.getCell() == cell) - { mOutput->finishStream(sayiter->second); - } - ++sayiter; } } @@ -885,7 +927,7 @@ namespace MWSound if (volume == 0.0f) { mOutput->finishSound(mNearWaterSound); - mNearWaterSound.reset(); + mNearWaterSound = nullptr; } else { @@ -939,7 +981,7 @@ namespace MWSound else if(mUnderwaterSound) { mOutput->finishSound(mUnderwaterSound); - mUnderwaterSound.reset(); + mUnderwaterSound = nullptr; } mOutput->startUpdate(); @@ -960,7 +1002,7 @@ namespace MWSound while(sndidx != snditer->second.end()) { MWWorld::ConstPtr ptr = snditer->first; - MWBase::SoundPtr sound = sndidx->first; + Sound *sound = sndidx->first; if(!ptr.isEmpty() && sound->getIs3D()) { const ESM::Position &pos = ptr.getRefData().getPosition(); @@ -977,6 +1019,11 @@ namespace MWSound if(!mOutput->isSoundPlaying(sound)) { mOutput->finishSound(sound); + mUnusedSounds.push_back(sound); + if(sound == mUnderwaterSound) + mUnderwaterSound = nullptr; + if(sound == mNearWaterSound) + mNearWaterSound = nullptr; Sound_Buffer *sfx = sndidx->second; if(sfx->mUses-- == 1) mUnusedBuffers.push_front(sfx); @@ -1000,7 +1047,7 @@ namespace MWSound while(sayiter != mActiveSaySounds.end()) { MWWorld::ConstPtr ptr = sayiter->first; - MWBase::SoundStreamPtr sound = sayiter->second; + Stream *sound = sayiter->second; if(!ptr.isEmpty() && sound->getIs3D()) { MWBase::World *world = MWBase::Environment::get().getWorld(); @@ -1017,6 +1064,7 @@ namespace MWSound if(!mOutput->isStreamPlaying(sound)) { mOutput->finishStream(sound); + mUnusedStreams.push_back(sound); mActiveSaySounds.erase(sayiter++); } else @@ -1031,10 +1079,11 @@ namespace MWSound TrackList::iterator trkiter = mActiveTracks.begin(); for(;trkiter != mActiveTracks.end();++trkiter) { - MWBase::SoundStreamPtr sound = *trkiter; + Stream *sound = *trkiter; if(!mOutput->isStreamPlaying(sound)) { mOutput->finishStream(sound); + mUnusedStreams.push_back(sound); trkiter = mActiveTracks.erase(trkiter); } else @@ -1049,7 +1098,7 @@ namespace MWSound if(mListenerUnderwater) { // Play underwater sound (after updating sounds) - if(!(mUnderwaterSound && mOutput->isSoundPlaying(mUnderwaterSound))) + if(!mUnderwaterSound) mUnderwaterSound = playSound("Underwater", 1.0f, 1.0f, Play_TypeSfx, Play_LoopNoEnv); } mOutput->finishUpdate(); @@ -1105,7 +1154,7 @@ namespace MWSound SoundBufferRefPairList::iterator sndidx = snditer->second.begin(); for(;sndidx != snditer->second.end();++sndidx) { - MWBase::SoundPtr sound = sndidx->first; + Sound *sound = sndidx->first; sound->setBaseVolume(volumeFromType(sound->getPlayType())); mOutput->updateSound(sound); } @@ -1113,14 +1162,14 @@ namespace MWSound SaySoundMap::iterator sayiter = mActiveSaySounds.begin(); for(;sayiter != mActiveSaySounds.end();++sayiter) { - MWBase::SoundStreamPtr sound = sayiter->second; + Stream *sound = sayiter->second; sound->setBaseVolume(volumeFromType(sound->getPlayType())); mOutput->updateStream(sound); } TrackList::iterator trkiter = mActiveTracks.begin(); for(;trkiter != mActiveTracks.end();++trkiter) { - MWBase::SoundStreamPtr sound = *trkiter; + Stream *sound = *trkiter; sound->setBaseVolume(volumeFromType(sound->getPlayType())); mOutput->updateStream(sound); } @@ -1153,7 +1202,7 @@ namespace MWSound SaySoundMap::iterator sayiter = mActiveSaySounds.find(old); if(sayiter != mActiveSaySounds.end()) { - MWBase::SoundStreamPtr stream = sayiter->second; + Stream *stream = sayiter->second; mActiveSaySounds.erase(sayiter); mActiveSaySounds[updated] = stream; } @@ -1233,6 +1282,7 @@ namespace MWSound for(;sndidx != snditer->second.end();++sndidx) { mOutput->finishSound(sndidx->first); + mUnusedSounds.push_back(sndidx->first); Sound_Buffer *sfx = sndidx->second; if(sfx->mUses-- == 1) mUnusedBuffers.push_front(sfx); @@ -1241,14 +1291,20 @@ namespace MWSound mActiveSounds.clear(); SaySoundMap::iterator sayiter = mActiveSaySounds.begin(); for(;sayiter != mActiveSaySounds.end();++sayiter) + { mOutput->finishStream(sayiter->second); + mUnusedStreams.push_back(sayiter->second); + } mActiveSaySounds.clear(); TrackList::iterator trkiter = mActiveTracks.begin(); for(;trkiter != mActiveTracks.end();++trkiter) + { mOutput->finishStream(*trkiter); + mUnusedStreams.push_back(*trkiter); + } mActiveTracks.clear(); - mUnderwaterSound.reset(); - mNearWaterSound.reset(); + mUnderwaterSound = nullptr; + mNearWaterSound = nullptr; stopMusic(); } } diff --git a/apps/openmw/mwsound/soundmanagerimp.hpp b/apps/openmw/mwsound/soundmanagerimp.hpp index 691e52932..836c3f228 100644 --- a/apps/openmw/mwsound/soundmanagerimp.hpp +++ b/apps/openmw/mwsound/soundmanagerimp.hpp @@ -29,6 +29,7 @@ namespace MWSound class Sound_Output; struct Sound_Decoder; class Sound; + class Stream; class Sound_Buffer; enum Environment { @@ -81,18 +82,24 @@ namespace MWSound typedef std::deque SoundList; SoundList mUnusedBuffers; - typedef std::pair SoundBufferRefPair; + std::unique_ptr> mSounds; + std::vector mUnusedSounds; + + std::unique_ptr> mStreams; + std::vector mUnusedStreams; + + typedef std::pair SoundBufferRefPair; typedef std::vector SoundBufferRefPairList; typedef std::map SoundMap; SoundMap mActiveSounds; - typedef std::map SaySoundMap; + typedef std::map SaySoundMap; SaySoundMap mActiveSaySounds; - typedef std::vector TrackList; + typedef std::vector TrackList; TrackList mActiveTracks; - MWBase::SoundStreamPtr mMusic; + Stream *mMusic; std::string mCurrentPlaylist; bool mListenerUnderwater; @@ -102,8 +109,8 @@ namespace MWSound int mPausedSoundTypes; - MWBase::SoundPtr mUnderwaterSound; - MWBase::SoundPtr mNearWaterSound; + Sound *mUnderwaterSound; + Sound *mNearWaterSound; Sound_Buffer *insertSound(const std::string &soundId, const ESM::Sound *sound); @@ -113,7 +120,10 @@ namespace MWSound // returns a decoder to start streaming DecoderPtr loadVoice(const std::string &voicefile); - MWBase::SoundStreamPtr playVoice(DecoderPtr decoder, const osg::Vec3f &pos, bool playlocal); + Sound *getSoundRef(); + Stream *getStreamRef(); + + Stream *playVoice(DecoderPtr decoder, const osg::Vec3f &pos, bool playlocal); void streamMusicFull(const std::string& filename); void advanceMusic(const std::string& filename); @@ -176,33 +186,33 @@ namespace MWSound /// and get an average loudness value (scale [0,1]) at the current time position. /// If the actor is not saying anything, returns 0. - virtual MWBase::SoundStreamPtr playTrack(const DecoderPtr& decoder, PlayType type); + virtual Stream *playTrack(const DecoderPtr& decoder, PlayType type); ///< Play a 2D audio track, using a custom decoder - virtual void stopTrack(MWBase::SoundStreamPtr stream); + virtual void stopTrack(Stream *stream); ///< Stop the given audio track from playing - virtual double getTrackTimeDelay(MWBase::SoundStreamPtr stream); + virtual double getTrackTimeDelay(Stream *stream); ///< Retives the time delay, in seconds, of the audio track (must be a sound /// returned by \ref playTrack). Only intended to be called by the track /// decoder's read method. - virtual MWBase::SoundPtr playSound(const std::string& soundId, float volume, float pitch, PlayType type=Play_TypeSfx, PlayMode mode=Play_Normal, float offset=0); + virtual Sound *playSound(const std::string& soundId, float volume, float pitch, PlayType type=Play_TypeSfx, PlayMode mode=Play_Normal, float offset=0); ///< Play a sound, independently of 3D-position ///< @param offset Number of seconds into the sound to start playback. - virtual MWBase::SoundPtr playSound3D(const MWWorld::ConstPtr &reference, const std::string& soundId, - float volume, float pitch, PlayType type=Play_TypeSfx, - PlayMode mode=Play_Normal, float offset=0); + virtual Sound *playSound3D(const MWWorld::ConstPtr &reference, const std::string& soundId, + float volume, float pitch, PlayType type=Play_TypeSfx, + PlayMode mode=Play_Normal, float offset=0); ///< Play a 3D sound attached to an MWWorld::Ptr. Will be updated automatically with the Ptr's position, unless Play_NoTrack is specified. ///< @param offset Number of seconds into the sound to start playback. - virtual MWBase::SoundPtr playSound3D(const osg::Vec3f& initialPos, const std::string& soundId, - float volume, float pitch, PlayType type, PlayMode mode, float offset=0); + virtual Sound *playSound3D(const osg::Vec3f& initialPos, const std::string& soundId, + float volume, float pitch, PlayType type, PlayMode mode, float offset=0); ///< Play a 3D sound at \a initialPos. If the sound should be moving, it must be updated using Sound::setPosition. ///< @param offset Number of seconds into the sound to start playback. - virtual void stopSound(MWBase::SoundPtr sound); + virtual void stopSound(Sound *sound); ///< Stop the given sound from playing /// @note no-op if \a sound is null diff --git a/apps/openmw/mwworld/projectilemanager.cpp b/apps/openmw/mwworld/projectilemanager.cpp index 5afdce700..64d601563 100644 --- a/apps/openmw/mwworld/projectilemanager.cpp +++ b/apps/openmw/mwworld/projectilemanager.cpp @@ -283,7 +283,7 @@ namespace MWWorld MWBase::SoundManager *sndMgr = MWBase::Environment::get().getSoundManager(); for (size_t it = 0; it != state.mSoundIds.size(); it++) { - MWBase::SoundPtr sound = sndMgr->playSound3D(pos, state.mSoundIds.at(it), 1.0f, 1.0f, MWBase::SoundManager::Play_TypeSfx, MWBase::SoundManager::Play_Loop); + MWBase::Sound *sound = sndMgr->playSound3D(pos, state.mSoundIds.at(it), 1.0f, 1.0f, MWBase::SoundManager::Play_TypeSfx, MWBase::SoundManager::Play_Loop); if (sound) state.mSounds.push_back(sound); } @@ -584,8 +584,8 @@ namespace MWWorld for (size_t soundIter = 0; soundIter != state.mSoundIds.size(); soundIter++) { - MWBase::SoundPtr sound = sndMgr->playSound3D(esm.mPosition, state.mSoundIds.at(soundIter), 1.0f, 1.0f, - MWBase::SoundManager::Play_TypeSfx, MWBase::SoundManager::Play_Loop); + MWBase::Sound *sound = sndMgr->playSound3D(esm.mPosition, state.mSoundIds.at(soundIter), 1.0f, 1.0f, + MWBase::SoundManager::Play_TypeSfx, MWBase::SoundManager::Play_Loop); if (sound) state.mSounds.push_back(sound); } diff --git a/apps/openmw/mwworld/projectilemanager.hpp b/apps/openmw/mwworld/projectilemanager.hpp index bfa4980e9..c7025a3a0 100644 --- a/apps/openmw/mwworld/projectilemanager.hpp +++ b/apps/openmw/mwworld/projectilemanager.hpp @@ -103,7 +103,7 @@ namespace MWWorld bool mStack; - std::vector mSounds; + std::vector mSounds; std::vector mSoundIds; }; diff --git a/apps/openmw/mwworld/weather.cpp b/apps/openmw/mwworld/weather.cpp index eaf88d45a..c4b46961c 100644 --- a/apps/openmw/mwworld/weather.cpp +++ b/apps/openmw/mwworld/weather.cpp @@ -531,7 +531,7 @@ WeatherManager::WeatherManager(MWRender::RenderingManager& rendering, const Fall , mQueuedWeather(0) , mRegions() , mResult() - , mAmbientSound() + , mAmbientSound(nullptr) , mPlayingSoundID() { mTimeSettings.mNightStart = mSunsetTime + mSunsetDuration; @@ -735,15 +735,15 @@ void WeatherManager::update(float duration, bool paused) mPlayingSoundID = mResult.mAmbientLoopSoundID; } - if (mAmbientSound.get()) + else if (mAmbientSound) mAmbientSound->setVolume(mResult.mAmbientSoundVolume); } void WeatherManager::stopSounds() { - if (mAmbientSound.get()) + if (mAmbientSound) MWBase::Environment::get().getSoundManager()->stopSound(mAmbientSound); - mAmbientSound.reset(); + mAmbientSound = nullptr; mPlayingSoundID.clear(); } diff --git a/apps/openmw/mwworld/weather.hpp b/apps/openmw/mwworld/weather.hpp index 044200757..84a6c5105 100644 --- a/apps/openmw/mwworld/weather.hpp +++ b/apps/openmw/mwworld/weather.hpp @@ -288,7 +288,7 @@ namespace MWWorld std::map mRegions; MWRender::WeatherResult mResult; - MWBase::SoundPtr mAmbientSound; + MWBase::Sound *mAmbientSound; std::string mPlayingSoundID; void addWeather(const std::string& name,