Use RAII for object ptr from pool

pull/2951/head
elsid 5 years ago
parent 6ca29c6107
commit 02f9b44f01
No known key found for this signature in database
GPG Key ID: B845CB9FEE18AB40

@ -58,7 +58,6 @@ namespace MWSound
, mWaterSoundUpdater(makeWaterSoundUpdaterSettings()) , mWaterSoundUpdater(makeWaterSoundUpdaterSettings())
, mSoundBuffers(new SoundBufferList::element_type()) , mSoundBuffers(new SoundBufferList::element_type())
, mBufferCacheSize(0) , mBufferCacheSize(0)
, mMusic(nullptr)
, mListenerUnderwater(false) , mListenerUnderwater(false)
, mListenerPos(0,0,0) , mListenerPos(0,0,0)
, mListenerDir(1,0,0) , mListenerDir(1,0,0)
@ -266,17 +265,17 @@ namespace MWSound
return nullptr; return nullptr;
} }
Sound *SoundManager::getSoundRef() SoundPtr SoundManager::getSoundRef()
{ {
return mSounds.get(); return mSounds.get();
} }
Stream *SoundManager::getStreamRef() StreamPtr SoundManager::getStreamRef()
{ {
return mStreams.get(); 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(); MWBase::World* world = MWBase::Environment::get().getWorld();
static const float fAudioMinDistanceMult = world->getStore().get<ESM::GameSetting>().find("fAudioMinDistanceMult")->mValue.getFloat(); static const float fAudioMinDistanceMult = world->getStore().get<ESM::GameSetting>().find("fAudioMinDistanceMult")->mValue.getFloat();
@ -288,23 +287,20 @@ namespace MWSound
bool played; bool played;
float basevol = volumeFromType(Type::Voice); float basevol = volumeFromType(Type::Voice);
Stream *sound = getStreamRef(); StreamPtr sound = getStreamRef();
if(playlocal) if(playlocal)
{ {
sound->init(1.0f, basevol, 1.0f, PlayMode::NoEnv|Type::Voice|Play_2D); 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 else
{ {
sound->init(pos, 1.0f, basevol, 1.0f, minDistance, maxDistance, sound->init(pos, 1.0f, basevol, 1.0f, minDistance, maxDistance,
PlayMode::Normal|Type::Voice|Play_3D); PlayMode::Normal|Type::Voice|Play_3D);
played = mOutput->streamSound3D(decoder, sound, true); played = mOutput->streamSound3D(decoder, sound.get(), true);
} }
if(!played) if(!played)
{
mStreams.recycle(sound);
return nullptr; return nullptr;
}
return sound; return sound;
} }
@ -318,8 +314,7 @@ namespace MWSound
{ {
if(mMusic) if(mMusic)
{ {
mOutput->finishStream(mMusic); mOutput->finishStream(mMusic.get());
mStreams.recycle(mMusic);
mMusic = nullptr; mMusic = nullptr;
} }
} }
@ -339,7 +334,7 @@ namespace MWSound
mMusic = getStreamRef(); mMusic = getStreamRef();
mMusic->init(1.0f, volumeFromType(Type::Music), 1.0f, mMusic->init(1.0f, volumeFromType(Type::Music), 1.0f,
PlayMode::NoEnv|Type::Music|Play_2D); PlayMode::NoEnv|Type::Music|Play_2D);
mOutput->streamSound(decoder, mMusic); mOutput->streamSound(decoder, mMusic.get());
} }
void SoundManager::advanceMusic(const std::string& filename) void SoundManager::advanceMusic(const std::string& filename)
@ -389,7 +384,7 @@ namespace MWSound
bool SoundManager::isMusicPlaying() bool SoundManager::isMusicPlaying()
{ {
return mMusic && mOutput->isStreamPlaying(mMusic); return mMusic && mOutput->isStreamPlaying(mMusic.get());
} }
void SoundManager::playPlaylist(const std::string &playlist) void SoundManager::playPlaylist(const std::string &playlist)
@ -472,10 +467,10 @@ namespace MWSound
const osg::Vec3f pos = world->getActorHeadTransform(ptr).getTrans(); const osg::Vec3f pos = world->getActorHeadTransform(ptr).getTrans();
stopSay(ptr); stopSay(ptr);
Stream *sound = playVoice(decoder, pos, (ptr == MWMechanics::getPlayer())); StreamPtr sound = playVoice(decoder, pos, (ptr == MWMechanics::getPlayer()));
if(!sound) return; if(!sound) return;
mSaySoundsQueue.emplace(ptr, sound); mSaySoundsQueue.emplace(ptr, std::move(sound));
} }
float SoundManager::getSaySoundLoudness(const MWWorld::ConstPtr &ptr) const float SoundManager::getSaySoundLoudness(const MWWorld::ConstPtr &ptr) const
@ -483,7 +478,7 @@ namespace MWSound
SaySoundMap::const_iterator snditer = mActiveSaySounds.find(ptr); SaySoundMap::const_iterator snditer = mActiveSaySounds.find(ptr);
if(snditer != mActiveSaySounds.end()) if(snditer != mActiveSaySounds.end())
{ {
Stream *sound = snditer->second; Stream *sound = snditer->second.get();
return mOutput->getStreamLoudness(sound); return mOutput->getStreamLoudness(sound);
} }
@ -503,10 +498,10 @@ namespace MWSound
return; return;
stopSay(MWWorld::ConstPtr()); stopSay(MWWorld::ConstPtr());
Stream *sound = playVoice(decoder, osg::Vec3f(), true); StreamPtr sound = playVoice(decoder, osg::Vec3f(), true);
if(!sound) return; 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 bool SoundManager::sayDone(const MWWorld::ConstPtr &ptr) const
@ -514,7 +509,7 @@ namespace MWSound
SaySoundMap::const_iterator snditer = mActiveSaySounds.find(ptr); SaySoundMap::const_iterator snditer = mActiveSaySounds.find(ptr);
if(snditer != mActiveSaySounds.end()) if(snditer != mActiveSaySounds.end())
{ {
if(mOutput->isStreamPlaying(snditer->second)) if(mOutput->isStreamPlaying(snditer->second.get()))
return false; return false;
return true; return true;
} }
@ -526,7 +521,7 @@ namespace MWSound
SaySoundMap::const_iterator snditer = mSaySoundsQueue.find(ptr); SaySoundMap::const_iterator snditer = mSaySoundsQueue.find(ptr);
if(snditer != mSaySoundsQueue.end()) if(snditer != mSaySoundsQueue.end())
{ {
if(mOutput->isStreamPlaying(snditer->second)) if(mOutput->isStreamPlaying(snditer->second.get()))
return true; return true;
return false; return false;
} }
@ -534,7 +529,7 @@ namespace MWSound
snditer = mActiveSaySounds.find(ptr); snditer = mActiveSaySounds.find(ptr);
if(snditer != mActiveSaySounds.end()) if(snditer != mActiveSaySounds.end())
{ {
if(mOutput->isStreamPlaying(snditer->second)) if(mOutput->isStreamPlaying(snditer->second.get()))
return true; return true;
return false; return false;
} }
@ -547,16 +542,14 @@ namespace MWSound
SaySoundMap::iterator snditer = mSaySoundsQueue.find(ptr); SaySoundMap::iterator snditer = mSaySoundsQueue.find(ptr);
if(snditer != mSaySoundsQueue.end()) if(snditer != mSaySoundsQueue.end())
{ {
mOutput->finishStream(snditer->second); mOutput->finishStream(snditer->second.get());
mStreams.recycle(snditer->second);
mSaySoundsQueue.erase(snditer); mSaySoundsQueue.erase(snditer);
} }
snditer = mActiveSaySounds.find(ptr); snditer = mActiveSaySounds.find(ptr);
if(snditer != mActiveSaySounds.end()) if(snditer != mActiveSaySounds.end())
{ {
mOutput->finishStream(snditer->second); mOutput->finishStream(snditer->second.get());
mStreams.recycle(snditer->second);
mActiveSaySounds.erase(snditer); mActiveSaySounds.erase(snditer);
} }
} }
@ -567,27 +560,24 @@ namespace MWSound
if(!mOutput->isInitialized()) if(!mOutput->isInitialized())
return nullptr; return nullptr;
Stream *track = getStreamRef(); StreamPtr track = getStreamRef();
track->init(1.0f, volumeFromType(type), 1.0f, PlayMode::NoEnv|type|Play_2D); track->init(1.0f, volumeFromType(type), 1.0f, PlayMode::NoEnv|type|Play_2D);
if(!mOutput->streamSound(decoder, track)) if(!mOutput->streamSound(decoder, track.get()))
{
mStreams.recycle(track);
return nullptr; return nullptr;
}
mActiveTracks.insert( Stream* result = track.get();
std::lower_bound(mActiveTracks.begin(), mActiveTracks.end(), track), track const auto it = std::lower_bound(mActiveTracks.begin(), mActiveTracks.end(), track);
); mActiveTracks.insert(it, std::move(track));
return track; return result;
} }
void SoundManager::stopTrack(Stream *stream) void SoundManager::stopTrack(Stream *stream)
{ {
mOutput->finishStream(stream); mOutput->finishStream(stream);
TrackList::iterator iter = std::lower_bound(mActiveTracks.begin(), mActiveTracks.end(), stream); TrackList::iterator iter = std::lower_bound(mActiveTracks.begin(), mActiveTracks.end(), stream,
if(iter != mActiveTracks.end() && *iter == stream) [] (const StreamPtr& lhs, Stream* rhs) { return lhs.get() < rhs; });
if(iter != mActiveTracks.end() && iter->get() == stream)
mActiveTracks.erase(iter); mActiveTracks.erase(iter);
mStreams.recycle(stream);
} }
double SoundManager::getTrackTimeDelay(Stream *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()) if(!mOutput->isInitialized())
return nullptr; return nullptr;
@ -607,13 +597,10 @@ namespace MWSound
// Only one copy of given sound can be played at time, so stop previous copy // Only one copy of given sound can be played at time, so stop previous copy
stopSound(sfx, MWWorld::ConstPtr()); stopSound(sfx, MWWorld::ConstPtr());
Sound *sound = getSoundRef(); SoundPtr sound = getSoundRef();
sound->init(volume * sfx->mVolume, volumeFromType(type), pitch, mode|type|Play_2D); sound->init(volume * sfx->mVolume, volumeFromType(type), pitch, mode|type|Play_2D);
if(!mOutput->playSound(sound, sfx->mHandle, offset)) if(!mOutput->playSound(sound.get(), sfx->mHandle, offset))
{
mSounds.recycle(sound);
return nullptr; return nullptr;
}
if(sfx->mUses++ == 0) if(sfx->mUses++ == 0)
{ {
@ -621,8 +608,9 @@ namespace MWSound
if(iter != mUnusedBuffers.end()) if(iter != mUnusedBuffers.end())
mUnusedBuffers.erase(iter); mUnusedBuffers.erase(iter);
} }
mActiveSounds[MWWorld::ConstPtr()].push_back(std::make_pair(sound, sfx)); Sound* result = sound.get();
return sound; mActiveSounds[MWWorld::ConstPtr()].emplace_back(std::move(sound), sfx);
return result;
} }
Sound *SoundManager::playSound3D(const MWWorld::ConstPtr &ptr, const std::string& soundId, Sound *SoundManager::playSound3D(const MWWorld::ConstPtr &ptr, const std::string& soundId,
@ -644,23 +632,20 @@ namespace MWSound
stopSound(sfx, ptr); stopSound(sfx, ptr);
bool played; bool played;
Sound *sound = getSoundRef(); SoundPtr sound = getSoundRef();
if(!(mode&PlayMode::NoPlayerLocal) && ptr == MWMechanics::getPlayer()) if(!(mode&PlayMode::NoPlayerLocal) && ptr == MWMechanics::getPlayer())
{ {
sound->init(volume * sfx->mVolume, volumeFromType(type), pitch, mode|type|Play_2D); 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 else
{ {
sound->init(objpos, volume * sfx->mVolume, volumeFromType(type), pitch, sound->init(objpos, volume * sfx->mVolume, volumeFromType(type), pitch,
sfx->mMinDist, sfx->mMaxDist, mode|type|Play_3D); 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) if(!played)
{
mSounds.recycle(sound);
return nullptr; return nullptr;
}
if(sfx->mUses++ == 0) if(sfx->mUses++ == 0)
{ {
@ -668,8 +653,9 @@ namespace MWSound
if(iter != mUnusedBuffers.end()) if(iter != mUnusedBuffers.end())
mUnusedBuffers.erase(iter); mUnusedBuffers.erase(iter);
} }
mActiveSounds[ptr].push_back(std::make_pair(sound, sfx)); Sound* result = sound.get();
return sound; mActiveSounds[ptr].emplace_back(std::move(sound), sfx);
return result;
} }
Sound *SoundManager::playSound3D(const osg::Vec3f& initialPos, const std::string& soundId, 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)); Sound_Buffer *sfx = loadSound(Misc::StringUtils::lowerCase(soundId));
if(!sfx) return nullptr; if(!sfx) return nullptr;
Sound *sound = getSoundRef(); SoundPtr sound = getSoundRef();
sound->init(initialPos, volume * sfx->mVolume, volumeFromType(type), pitch, sound->init(initialPos, volume * sfx->mVolume, volumeFromType(type), pitch,
sfx->mMinDist, sfx->mMaxDist, mode|type|Play_3D); sfx->mMinDist, sfx->mMaxDist, mode|type|Play_3D);
if(!mOutput->playSound3D(sound, sfx->mHandle, offset)) if(!mOutput->playSound3D(sound.get(), sfx->mHandle, offset))
{
mSounds.recycle(sound);
return nullptr; return nullptr;
}
if(sfx->mUses++ == 0) if(sfx->mUses++ == 0)
{ {
@ -698,8 +681,9 @@ namespace MWSound
if(iter != mUnusedBuffers.end()) if(iter != mUnusedBuffers.end())
mUnusedBuffers.erase(iter); mUnusedBuffers.erase(iter);
} }
mActiveSounds[MWWorld::ConstPtr()].push_back(std::make_pair(sound, sfx)); Sound* result = sound.get();
return sound; mActiveSounds[MWWorld::ConstPtr()].emplace_back(std::move(sound), sfx);
return result;
} }
void SoundManager::stopSound(Sound *sound) void SoundManager::stopSound(Sound *sound)
@ -716,7 +700,7 @@ namespace MWSound
for(SoundBufferRefPair &snd : snditer->second) for(SoundBufferRefPair &snd : snditer->second)
{ {
if(snd.second == sfx) if(snd.second == sfx)
mOutput->finishSound(snd.first); mOutput->finishSound(snd.first.get());
} }
} }
} }
@ -738,14 +722,14 @@ namespace MWSound
if(snditer != mActiveSounds.end()) if(snditer != mActiveSounds.end())
{ {
for(SoundBufferRefPair &snd : snditer->second) for(SoundBufferRefPair &snd : snditer->second)
mOutput->finishSound(snd.first); mOutput->finishSound(snd.first.get());
} }
SaySoundMap::iterator sayiter = mSaySoundsQueue.find(ptr); SaySoundMap::iterator sayiter = mSaySoundsQueue.find(ptr);
if(sayiter != mSaySoundsQueue.end()) if(sayiter != mSaySoundsQueue.end())
mOutput->finishStream(sayiter->second); mOutput->finishStream(sayiter->second.get());
sayiter = mActiveSaySounds.find(ptr); sayiter = mActiveSaySounds.find(ptr);
if(sayiter != mActiveSaySounds.end()) if(sayiter != mActiveSaySounds.end())
mOutput->finishStream(sayiter->second); mOutput->finishStream(sayiter->second.get());
} }
void SoundManager::stopSound(const MWWorld::CellStore *cell) 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) if(!snd.first.isEmpty() && snd.first != MWMechanics::getPlayer() && snd.first.getCell() == cell)
{ {
for(SoundBufferRefPair &sndbuf : snd.second) for(SoundBufferRefPair &sndbuf : snd.second)
mOutput->finishSound(sndbuf.first); mOutput->finishSound(sndbuf.first.get());
} }
} }
for(SaySoundMap::value_type &snd : mSaySoundsQueue) for(SaySoundMap::value_type &snd : mSaySoundsQueue)
{ {
if(!snd.first.isEmpty() && snd.first != MWMechanics::getPlayer() && snd.first.getCell() == cell) 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) for(SaySoundMap::value_type &snd : mActiveSaySounds)
{ {
if(!snd.first.isEmpty() && snd.first != MWMechanics::getPlayer() && snd.first.getCell() == cell) 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)); Sound_Buffer *sfx = lookupSound(Misc::StringUtils::lowerCase(soundId));
return std::find_if(snditer->second.cbegin(), snditer->second.cend(), return std::find_if(snditer->second.cbegin(), snditer->second.cend(),
[this,sfx](const SoundBufferRefPair &snd) -> bool [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(); ) != snditer->second.cend();
} }
return false; return false;
@ -912,7 +896,7 @@ namespace MWSound
const auto pairiter = std::find_if( const auto pairiter = std::find_if(
snditer->second.begin(), snditer->second.end(), snditer->second.begin(), snditer->second.end(),
[this](const SoundBufferRefPairList::value_type &item) -> bool [this](const SoundBufferRefPairList::value_type &item) -> bool
{ return mNearWaterSound == item.first; } { return mNearWaterSound == item.first.get(); }
); );
if (pairiter != snditer->second.end() && pairiter->second != sfx) if (pairiter != snditer->second.end() && pairiter->second != sfx)
soundIdChanged = true; soundIdChanged = true;
@ -938,7 +922,11 @@ namespace MWSound
SaySoundMap::iterator queuesayiter = mSaySoundsQueue.begin(); SaySoundMap::iterator queuesayiter = mSaySoundsQueue.begin();
while (queuesayiter != mSaySoundsQueue.end()) 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++); mSaySoundsQueue.erase(queuesayiter++);
} }
@ -979,10 +967,9 @@ namespace MWSound
SoundBufferRefPairList::iterator sndidx = snditer->second.begin(); SoundBufferRefPairList::iterator sndidx = snditer->second.begin();
while(sndidx != snditer->second.end()) while(sndidx != snditer->second.end())
{ {
Sound *sound; Sound *sound = sndidx->first.get();
Sound_Buffer *sfx; Sound_Buffer *sfx = sndidx->second;
std::tie(sound, sfx) = *sndidx;
if(!ptr.isEmpty() && sound->getIs3D()) if(!ptr.isEmpty() && sound->getIs3D())
{ {
const ESM::Position &pos = ptr.getRefData().getPosition(); const ESM::Position &pos = ptr.getRefData().getPosition();
@ -999,10 +986,9 @@ namespace MWSound
if(!mOutput->isSoundPlaying(sound)) if(!mOutput->isSoundPlaying(sound))
{ {
mOutput->finishSound(sound); mOutput->finishSound(sound);
mSounds.recycle(sound); if (sound == mUnderwaterSound)
if(sound == mUnderwaterSound)
mUnderwaterSound = nullptr; mUnderwaterSound = nullptr;
if(sound == mNearWaterSound) if (sound == mNearWaterSound)
mNearWaterSound = nullptr; mNearWaterSound = nullptr;
if(sfx->mUses-- == 1) if(sfx->mUses-- == 1)
mUnusedBuffers.push_front(sfx); mUnusedBuffers.push_front(sfx);
@ -1026,7 +1012,7 @@ namespace MWSound
while(sayiter != mActiveSaySounds.end()) while(sayiter != mActiveSaySounds.end())
{ {
MWWorld::ConstPtr ptr = sayiter->first; MWWorld::ConstPtr ptr = sayiter->first;
Stream *sound = sayiter->second; Stream *sound = sayiter->second.get();
if(!ptr.isEmpty() && sound->getIs3D()) if(!ptr.isEmpty() && sound->getIs3D())
{ {
MWBase::World *world = MWBase::Environment::get().getWorld(); MWBase::World *world = MWBase::Environment::get().getWorld();
@ -1043,7 +1029,6 @@ namespace MWSound
if(!mOutput->isStreamPlaying(sound)) if(!mOutput->isStreamPlaying(sound))
{ {
mOutput->finishStream(sound); mOutput->finishStream(sound);
mStreams.recycle(sound);
mActiveSaySounds.erase(sayiter++); mActiveSaySounds.erase(sayiter++);
} }
else else
@ -1058,7 +1043,7 @@ namespace MWSound
TrackList::iterator trkiter = mActiveTracks.begin(); TrackList::iterator trkiter = mActiveTracks.begin();
for(;trkiter != mActiveTracks.end();++trkiter) for(;trkiter != mActiveTracks.end();++trkiter)
{ {
Stream *sound = *trkiter; Stream *sound = trkiter->get();
if(!mOutput->isStreamPlaying(sound)) if(!mOutput->isStreamPlaying(sound))
{ {
mOutput->finishStream(sound); mOutput->finishStream(sound);
@ -1089,7 +1074,7 @@ namespace MWSound
{ {
mMusic->updateFade(duration); mMusic->updateFade(duration);
mOutput->updateStream(mMusic); mOutput->updateStream(mMusic.get());
if (mMusic->getRealVolume() <= 0.f) if (mMusic->getRealVolume() <= 0.f)
{ {
@ -1126,32 +1111,32 @@ namespace MWSound
{ {
for(SoundBufferRefPair &sndbuf : snd.second) for(SoundBufferRefPair &sndbuf : snd.second)
{ {
Sound *sound = sndbuf.first; Sound *sound = sndbuf.first.get();
sound->setBaseVolume(volumeFromType(sound->getPlayType())); sound->setBaseVolume(volumeFromType(sound->getPlayType()));
mOutput->updateSound(sound); mOutput->updateSound(sound);
} }
} }
for(SaySoundMap::value_type &snd : mActiveSaySounds) for(SaySoundMap::value_type &snd : mActiveSaySounds)
{ {
Stream *sound = snd.second; Stream *sound = snd.second.get();
sound->setBaseVolume(volumeFromType(sound->getPlayType())); sound->setBaseVolume(volumeFromType(sound->getPlayType()));
mOutput->updateStream(sound); mOutput->updateStream(sound);
} }
for(SaySoundMap::value_type &snd : mSaySoundsQueue) for(SaySoundMap::value_type &snd : mSaySoundsQueue)
{ {
Stream *sound = snd.second; Stream *sound = snd.second.get();
sound->setBaseVolume(volumeFromType(sound->getPlayType())); sound->setBaseVolume(volumeFromType(sound->getPlayType()));
mOutput->updateStream(sound); mOutput->updateStream(sound);
} }
for(Stream *sound : mActiveTracks) for (const StreamPtr& sound : mActiveTracks)
{ {
sound->setBaseVolume(volumeFromType(sound->getPlayType())); sound->setBaseVolume(volumeFromType(sound->getPlayType()));
mOutput->updateStream(sound); mOutput->updateStream(sound.get());
} }
if(mMusic) if(mMusic)
{ {
mMusic->setBaseVolume(volumeFromType(mMusic->getPlayType())); mMusic->setBaseVolume(volumeFromType(mMusic->getPlayType()));
mOutput->updateStream(mMusic); mOutput->updateStream(mMusic.get());
} }
mOutput->finishUpdate(); mOutput->finishUpdate();
} }
@ -1180,17 +1165,17 @@ namespace MWSound
SaySoundMap::iterator sayiter = mSaySoundsQueue.find(old); SaySoundMap::iterator sayiter = mSaySoundsQueue.find(old);
if(sayiter != mSaySoundsQueue.end()) if(sayiter != mSaySoundsQueue.end())
{ {
Stream *stream = sayiter->second; StreamPtr stream = std::move(sayiter->second);
mSaySoundsQueue.erase(sayiter); mSaySoundsQueue.erase(sayiter);
mSaySoundsQueue.emplace(updated, stream); mSaySoundsQueue.emplace(updated, std::move(stream));
} }
sayiter = mActiveSaySounds.find(old); sayiter = mActiveSaySounds.find(old);
if(sayiter != mActiveSaySounds.end()) if(sayiter != mActiveSaySounds.end())
{ {
Stream *stream = sayiter->second; StreamPtr stream = std::move(sayiter->second);
mActiveSaySounds.erase(sayiter); mActiveSaySounds.erase(sayiter);
mActiveSaySounds.emplace(updated, stream); mActiveSaySounds.emplace(updated, std::move(stream));
} }
} }
@ -1267,8 +1252,7 @@ namespace MWSound
{ {
for(SoundBufferRefPair &sndbuf : snd.second) for(SoundBufferRefPair &sndbuf : snd.second)
{ {
mOutput->finishSound(sndbuf.first); mOutput->finishSound(sndbuf.first.get());
mSounds.recycle(sndbuf.first);
Sound_Buffer *sfx = sndbuf.second; Sound_Buffer *sfx = sndbuf.second;
if(sfx->mUses-- == 1) if(sfx->mUses-- == 1)
mUnusedBuffers.push_front(sfx); mUnusedBuffers.push_front(sfx);
@ -1279,24 +1263,15 @@ namespace MWSound
mNearWaterSound = nullptr; mNearWaterSound = nullptr;
for(SaySoundMap::value_type &snd : mSaySoundsQueue) for(SaySoundMap::value_type &snd : mSaySoundsQueue)
{ mOutput->finishStream(snd.second.get());
mOutput->finishStream(snd.second);
mStreams.recycle(snd.second);
}
mSaySoundsQueue.clear(); mSaySoundsQueue.clear();
for(SaySoundMap::value_type &snd : mActiveSaySounds) for(SaySoundMap::value_type &snd : mActiveSaySounds)
{ mOutput->finishStream(snd.second.get());
mOutput->finishStream(snd.second);
mStreams.recycle(snd.second);
}
mActiveSaySounds.clear(); mActiveSaySounds.clear();
for(Stream *sound : mActiveTracks) for(StreamPtr& sound : mActiveTracks)
{ mOutput->finishStream(sound.get());
mOutput->finishStream(sound);
mStreams.recycle(sound);
}
mActiveTracks.clear(); mActiveTracks.clear();
mPlaybackPaused = false; mPlaybackPaused = false;
std::fill(std::begin(mPausedSoundTypes), std::end(mPausedSoundTypes), 0); std::fill(std::begin(mPausedSoundTypes), std::end(mPausedSoundTypes), 0);

@ -48,6 +48,9 @@ namespace MWSound
Play_3D = 1<<31 Play_3D = 1<<31
}; };
using SoundPtr = Misc::ObjectPtr<Sound>;
using StreamPtr = Misc::ObjectPtr<Stream>;
class SoundManager : public MWBase::SoundManager class SoundManager : public MWBase::SoundManager
{ {
const VFS::Manager* mVFS; const VFS::Manager* mVFS;
@ -83,19 +86,19 @@ namespace MWSound
Misc::ObjectPool<Stream> mStreams; Misc::ObjectPool<Stream> mStreams;
typedef std::pair<MWBase::Sound*,Sound_Buffer*> SoundBufferRefPair; typedef std::pair<SoundPtr, Sound_Buffer*> SoundBufferRefPair;
typedef std::vector<SoundBufferRefPair> SoundBufferRefPairList; typedef std::vector<SoundBufferRefPair> SoundBufferRefPairList;
typedef std::map<MWWorld::ConstPtr,SoundBufferRefPairList> SoundMap; typedef std::map<MWWorld::ConstPtr,SoundBufferRefPairList> SoundMap;
SoundMap mActiveSounds; SoundMap mActiveSounds;
typedef std::map<MWWorld::ConstPtr,Stream*> SaySoundMap; typedef std::map<MWWorld::ConstPtr, StreamPtr> SaySoundMap;
SaySoundMap mSaySoundsQueue; SaySoundMap mSaySoundsQueue;
SaySoundMap mActiveSaySounds; SaySoundMap mActiveSaySounds;
typedef std::vector<Stream*> TrackList; typedef std::vector<StreamPtr> TrackList;
TrackList mActiveTracks; TrackList mActiveTracks;
Stream *mMusic; StreamPtr mMusic;
std::string mCurrentPlaylist; std::string mCurrentPlaylist;
bool mListenerUnderwater; bool mListenerUnderwater;
@ -125,10 +128,10 @@ namespace MWSound
// returns a decoder to start streaming, or nullptr if the sound was not found // returns a decoder to start streaming, or nullptr if the sound was not found
DecoderPtr loadVoice(const std::string &voicefile); DecoderPtr loadVoice(const std::string &voicefile);
Sound *getSoundRef(); SoundPtr getSoundRef();
Stream *getStreamRef(); 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 streamMusicFull(const std::string& filename);
void advanceMusic(const std::string& filename); void advanceMusic(const std::string& filename);

@ -7,14 +7,51 @@
namespace Misc namespace Misc
{ {
template <class T>
class ObjectPool;
template <class T>
class ObjectPtrDeleter
{
public:
ObjectPtrDeleter(std::nullptr_t)
: mPool(nullptr) {}
ObjectPtrDeleter(ObjectPool<T>& pool)
: mPool(&pool) {}
void operator()(T* object) const
{
mPool->recycle(object);
}
private:
ObjectPool<T>* mPool;
};
template <class T>
struct ObjectPtr final : std::unique_ptr<T, ObjectPtrDeleter<T>>
{
using std::unique_ptr<T, ObjectPtrDeleter<T>>::unique_ptr;
using std::unique_ptr<T, ObjectPtrDeleter<T>>::operator=;
ObjectPtr()
: ObjectPtr(nullptr) {}
ObjectPtr(std::nullptr_t)
: std::unique_ptr<T, ObjectPtrDeleter<T>>(nullptr, nullptr) {}
};
template <class T> template <class T>
class ObjectPool class ObjectPool
{ {
friend class ObjectPtrDeleter<T>;
public: public:
ObjectPool() ObjectPool()
: mObjects(std::make_unique<std::deque<T>>()) {} : mObjects(std::make_unique<std::deque<T>>()) {}
T* get() ObjectPtr<T> get()
{ {
T* object; T* object;
@ -29,17 +66,17 @@ namespace Misc
object = &mObjects->back(); object = &mObjects->back();
} }
return object; return ObjectPtr<T>(object, ObjectPtrDeleter<T>(*this));
} }
private:
std::unique_ptr<std::deque<T>> mObjects;
std::vector<T*> mUnused;
void recycle(T* object) void recycle(T* object)
{ {
mUnused.push_back(object); mUnused.push_back(object);
} }
private:
std::unique_ptr<std::deque<T>> mObjects;
std::vector<T*> mUnused;
}; };
} }

Loading…
Cancel
Save