mirror of
https://github.com/TES3MP/openmw-tes3mp.git
synced 2025-02-21 11:09:41 +00:00
Merge pull request #2951 from elsid/sound_object_pool
Store SoundManager sounds and streams in object pool
This commit is contained in:
commit
67c2f0b26c
3 changed files with 179 additions and 144 deletions
|
@ -58,9 +58,6 @@ namespace MWSound
|
||||||
, mWaterSoundUpdater(makeWaterSoundUpdaterSettings())
|
, mWaterSoundUpdater(makeWaterSoundUpdaterSettings())
|
||||||
, mSoundBuffers(new SoundBufferList::element_type())
|
, mSoundBuffers(new SoundBufferList::element_type())
|
||||||
, mBufferCacheSize(0)
|
, mBufferCacheSize(0)
|
||||||
, mSounds(new std::deque<Sound>())
|
|
||||||
, mStreams(new std::deque<Stream>())
|
|
||||||
, mMusic(nullptr)
|
|
||||||
, mListenerUnderwater(false)
|
, mListenerUnderwater(false)
|
||||||
, mListenerPos(0,0,0)
|
, mListenerPos(0,0,0)
|
||||||
, mListenerDir(1,0,0)
|
, mListenerDir(1,0,0)
|
||||||
|
@ -268,39 +265,17 @@ namespace MWSound
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
Sound *SoundManager::getSoundRef()
|
SoundPtr SoundManager::getSoundRef()
|
||||||
{
|
{
|
||||||
Sound *ret;
|
return mSounds.get();
|
||||||
if(!mUnusedSounds.empty())
|
|
||||||
{
|
|
||||||
ret = mUnusedSounds.back();
|
|
||||||
mUnusedSounds.pop_back();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
mSounds->emplace_back();
|
|
||||||
ret = &mSounds->back();
|
|
||||||
}
|
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Stream *SoundManager::getStreamRef()
|
StreamPtr SoundManager::getStreamRef()
|
||||||
{
|
{
|
||||||
Stream *ret;
|
return mStreams.get();
|
||||||
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)
|
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();
|
||||||
|
@ -312,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)
|
||||||
{
|
|
||||||
mUnusedStreams.push_back(sound);
|
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
|
||||||
return sound;
|
return sound;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -342,8 +314,7 @@ namespace MWSound
|
||||||
{
|
{
|
||||||
if(mMusic)
|
if(mMusic)
|
||||||
{
|
{
|
||||||
mOutput->finishStream(mMusic);
|
mOutput->finishStream(mMusic.get());
|
||||||
mUnusedStreams.push_back(mMusic);
|
|
||||||
mMusic = nullptr;
|
mMusic = nullptr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -363,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)
|
||||||
|
@ -413,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)
|
||||||
|
@ -496,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
|
||||||
|
@ -507,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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -527,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
|
||||||
|
@ -538,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;
|
||||||
}
|
}
|
||||||
|
@ -550,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;
|
||||||
}
|
}
|
||||||
|
@ -558,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;
|
||||||
}
|
}
|
||||||
|
@ -571,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());
|
||||||
mUnusedStreams.push_back(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());
|
||||||
mUnusedStreams.push_back(snditer->second);
|
|
||||||
mActiveSaySounds.erase(snditer);
|
mActiveSaySounds.erase(snditer);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -591,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()))
|
||||||
{
|
|
||||||
mUnusedStreams.push_back(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);
|
||||||
mUnusedStreams.push_back(stream);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
double SoundManager::getTrackTimeDelay(Stream *stream)
|
double SoundManager::getTrackTimeDelay(Stream *stream)
|
||||||
|
@ -620,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;
|
||||||
|
@ -631,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))
|
||||||
{
|
|
||||||
mUnusedSounds.push_back(sound);
|
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
|
||||||
|
|
||||||
if(sfx->mUses++ == 0)
|
if(sfx->mUses++ == 0)
|
||||||
{
|
{
|
||||||
|
@ -645,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,
|
||||||
|
@ -668,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)
|
||||||
{
|
|
||||||
mUnusedSounds.push_back(sound);
|
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
|
||||||
|
|
||||||
if(sfx->mUses++ == 0)
|
if(sfx->mUses++ == 0)
|
||||||
{
|
{
|
||||||
|
@ -692,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,
|
||||||
|
@ -707,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))
|
||||||
{
|
|
||||||
mUnusedSounds.push_back(sound);
|
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
|
||||||
|
|
||||||
if(sfx->mUses++ == 0)
|
if(sfx->mUses++ == 0)
|
||||||
{
|
{
|
||||||
|
@ -722,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)
|
||||||
|
@ -740,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());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -762,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)
|
||||||
|
@ -779,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());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -819,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;
|
||||||
|
@ -936,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;
|
||||||
|
@ -962,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++);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1003,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();
|
||||||
|
@ -1023,10 +986,9 @@ namespace MWSound
|
||||||
if(!mOutput->isSoundPlaying(sound))
|
if(!mOutput->isSoundPlaying(sound))
|
||||||
{
|
{
|
||||||
mOutput->finishSound(sound);
|
mOutput->finishSound(sound);
|
||||||
mUnusedSounds.push_back(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);
|
||||||
|
@ -1050,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();
|
||||||
|
@ -1067,7 +1029,6 @@ namespace MWSound
|
||||||
if(!mOutput->isStreamPlaying(sound))
|
if(!mOutput->isStreamPlaying(sound))
|
||||||
{
|
{
|
||||||
mOutput->finishStream(sound);
|
mOutput->finishStream(sound);
|
||||||
mUnusedStreams.push_back(sound);
|
|
||||||
mActiveSaySounds.erase(sayiter++);
|
mActiveSaySounds.erase(sayiter++);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -1082,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);
|
||||||
|
@ -1113,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)
|
||||||
{
|
{
|
||||||
|
@ -1150,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();
|
||||||
}
|
}
|
||||||
|
@ -1204,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));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1291,8 +1252,7 @@ namespace MWSound
|
||||||
{
|
{
|
||||||
for(SoundBufferRefPair &sndbuf : snd.second)
|
for(SoundBufferRefPair &sndbuf : snd.second)
|
||||||
{
|
{
|
||||||
mOutput->finishSound(sndbuf.first);
|
mOutput->finishSound(sndbuf.first.get());
|
||||||
mUnusedSounds.push_back(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);
|
||||||
|
@ -1303,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);
|
|
||||||
mUnusedStreams.push_back(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);
|
|
||||||
mUnusedStreams.push_back(snd.second);
|
|
||||||
}
|
|
||||||
mActiveSaySounds.clear();
|
mActiveSaySounds.clear();
|
||||||
|
|
||||||
for(Stream *sound : mActiveTracks)
|
for(StreamPtr& sound : mActiveTracks)
|
||||||
{
|
mOutput->finishStream(sound.get());
|
||||||
mOutput->finishStream(sound);
|
|
||||||
mUnusedStreams.push_back(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);
|
||||||
|
|
|
@ -9,7 +9,7 @@
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
|
|
||||||
#include <components/settings/settings.hpp>
|
#include <components/settings/settings.hpp>
|
||||||
|
#include <components/misc/objectpool.hpp>
|
||||||
#include <components/fallback/fallback.hpp>
|
#include <components/fallback/fallback.hpp>
|
||||||
|
|
||||||
#include "../mwbase/soundmanager.hpp"
|
#include "../mwbase/soundmanager.hpp"
|
||||||
|
@ -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;
|
||||||
|
@ -79,25 +82,23 @@ namespace MWSound
|
||||||
typedef std::deque<Sound_Buffer*> SoundList;
|
typedef std::deque<Sound_Buffer*> SoundList;
|
||||||
SoundList mUnusedBuffers;
|
SoundList mUnusedBuffers;
|
||||||
|
|
||||||
std::unique_ptr<std::deque<Sound>> mSounds;
|
Misc::ObjectPool<Sound> mSounds;
|
||||||
std::vector<Sound*> mUnusedSounds;
|
|
||||||
|
|
||||||
std::unique_ptr<std::deque<Stream>> mStreams;
|
Misc::ObjectPool<Stream> mStreams;
|
||||||
std::vector<Stream*> mUnusedStreams;
|
|
||||||
|
|
||||||
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;
|
||||||
|
@ -127,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);
|
||||||
|
|
83
components/misc/objectpool.hpp
Normal file
83
components/misc/objectpool.hpp
Normal file
|
@ -0,0 +1,83 @@
|
||||||
|
#ifndef OPENMW_COMPONENTS_MISC_OBJECTPOOL_H
|
||||||
|
#define OPENMW_COMPONENTS_MISC_OBJECTPOOL_H
|
||||||
|
|
||||||
|
#include <deque>
|
||||||
|
#include <memory>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
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>
|
||||||
|
class ObjectPool
|
||||||
|
{
|
||||||
|
friend class ObjectPtrDeleter<T>;
|
||||||
|
|
||||||
|
public:
|
||||||
|
ObjectPool()
|
||||||
|
: mObjects(std::make_unique<std::deque<T>>()) {}
|
||||||
|
|
||||||
|
ObjectPtr<T> get()
|
||||||
|
{
|
||||||
|
T* object;
|
||||||
|
|
||||||
|
if (!mUnused.empty())
|
||||||
|
{
|
||||||
|
object = mUnused.back();
|
||||||
|
mUnused.pop_back();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
mObjects->emplace_back();
|
||||||
|
object = &mObjects->back();
|
||||||
|
}
|
||||||
|
|
||||||
|
return ObjectPtr<T>(object, ObjectPtrDeleter<T>(*this));
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::unique_ptr<std::deque<T>> mObjects;
|
||||||
|
std::vector<T*> mUnused;
|
||||||
|
|
||||||
|
void recycle(T* object)
|
||||||
|
{
|
||||||
|
mUnused.push_back(object);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
Loading…
Reference in a new issue