1
0
mirror of https://gitlab.com/OpenMW/openmw.git synced 2025-01-27 03:35:27 +00:00

Use a separate map for say sounds

Also restores lip movement
This commit is contained in:
Chris Robinson 2015-11-23 04:00:10 -08:00
parent 9d0018e1bc
commit 3fdc3c4ea9
2 changed files with 121 additions and 53 deletions

View File

@ -92,6 +92,10 @@ namespace MWSound
SoundManager::~SoundManager() SoundManager::~SoundManager()
{ {
mUnderwaterSound.reset();
mActiveSounds.clear();
mActiveSaySounds.clear();
mMusic.reset();
if(mOutput->isInitialized()) if(mOutput->isInitialized())
{ {
NameBufferMap::iterator sfxiter = mSoundBuffers.begin(); NameBufferMap::iterator sfxiter = mSoundBuffers.begin();
@ -109,9 +113,6 @@ namespace MWSound
sfxiter->second.mHandle = 0; sfxiter->second.mHandle = 0;
} }
} }
mUnderwaterSound.reset();
mActiveSounds.clear();
mMusic.reset();
mOutput.reset(); mOutput.reset();
} }
@ -224,21 +225,6 @@ namespace MWSound
return volume; return volume;
} }
bool SoundManager::isPlaying(const MWWorld::Ptr &ptr, const std::string &id) const
{
SoundMap::const_iterator snditer = mActiveSounds.find(ptr);
if(snditer != mActiveSounds.end())
{
SoundNamePairList::const_iterator sndname = snditer->second.begin();
for(;sndname != snditer->second.end();++sndname)
{
if(sndname->second == id && sndname->first->isPlaying())
return true;
}
}
return false;
}
void SoundManager::stopMusic() void SoundManager::stopMusic()
{ {
@ -325,13 +311,15 @@ namespace MWSound
startRandomTitle(); startRandomTitle();
} }
void SoundManager::say(const MWWorld::Ptr &ptr, const std::string &filename) void SoundManager::say(const MWWorld::Ptr &ptr, const std::string &filename)
{ {
if(!mOutput->isInitialized()) if(!mOutput->isInitialized())
return; return;
try try
{ {
const Sound_Buffer *sfx = lookupVoice(Misc::StringUtils::lowerCase(filename)); std::string voicefile = Misc::StringUtils::lowerCase(filename);
const Sound_Buffer *sfx = lookupVoice(voicefile);
float basevol = volumeFromType(Play_TypeVoice); float basevol = volumeFromType(Play_TypeVoice);
const ESM::Position &pos = ptr.getRefData().getPosition(); const ESM::Position &pos = ptr.getRefData().getPosition();
const osg::Vec3f objpos(pos.asVec3()); const osg::Vec3f objpos(pos.asVec3());
@ -339,7 +327,7 @@ namespace MWSound
MWBase::SoundPtr sound = mOutput->playSound3D(sfx->mHandle, MWBase::SoundPtr sound = mOutput->playSound3D(sfx->mHandle,
objpos, sfx->mVolume, basevol, 1.0f, sfx->mMinDist, sfx->mMaxDist, Play_Normal|Play_TypeVoice, 0 objpos, sfx->mVolume, basevol, 1.0f, sfx->mMinDist, sfx->mMaxDist, Play_Normal|Play_TypeVoice, 0
); );
mActiveSounds[ptr].push_back(std::make_pair(sound, std::string("_say_sound"))); mActiveSaySounds[ptr] = std::make_pair(sound, voicefile);
} }
catch(std::exception &e) catch(std::exception &e)
{ {
@ -349,14 +337,15 @@ namespace MWSound
float SoundManager::getSaySoundLoudness(const MWWorld::Ptr &ptr) const float SoundManager::getSaySoundLoudness(const MWWorld::Ptr &ptr) const
{ {
SoundMap::const_iterator snditer = mActiveSounds.find(ptr); SaySoundMap::const_iterator snditer = mActiveSaySounds.find(ptr);
if(snditer != mActiveSounds.end()) if(snditer != mActiveSaySounds.end())
{ {
SoundNamePairList::const_iterator sndname = snditer->second.begin(); NameBufferMap::const_iterator sfxiter = mVoiceSoundBuffers.find(snditer->second.second);
for(;sndname != snditer->second.end();++sndname) if(sfxiter != mVoiceSoundBuffers.end())
{ {
if(sndname->second == "_say_sound") float sec = snditer->second.first->getTimeOffset();
return 0.0f; if(snditer->second.first->isPlaying())
return sfxiter->second.mLoudness.getLoudnessAtTime(sec);
} }
} }
@ -369,13 +358,14 @@ namespace MWSound
return; return;
try try
{ {
const Sound_Buffer *sfx = lookupVoice(Misc::StringUtils::lowerCase(filename)); std::string voicefile = Misc::StringUtils::lowerCase(filename);
const Sound_Buffer *sfx = lookupVoice(voicefile);
float basevol = volumeFromType(Play_TypeVoice); float basevol = volumeFromType(Play_TypeVoice);
MWBase::SoundPtr sound = mOutput->playSound(sfx->mHandle, MWBase::SoundPtr sound = mOutput->playSound(sfx->mHandle,
sfx->mVolume, basevol, 1.0f, Play_Normal|Play_TypeVoice, 0 sfx->mVolume, basevol, 1.0f, Play_Normal|Play_TypeVoice, 0
); );
mActiveSounds[MWWorld::Ptr()].push_back(std::make_pair(sound, std::string("_say_sound"))); mActiveSaySounds[MWWorld::Ptr()] = std::make_pair(sound, voicefile);
} }
catch(std::exception &e) catch(std::exception &e)
{ {
@ -385,26 +375,22 @@ namespace MWSound
bool SoundManager::sayDone(const MWWorld::Ptr &ptr) const bool SoundManager::sayDone(const MWWorld::Ptr &ptr) const
{ {
return !isPlaying(ptr, "_say_sound"); SaySoundMap::const_iterator snditer = mActiveSaySounds.find(ptr);
if(snditer != mActiveSaySounds.end())
{
if(snditer->second.first->isPlaying())
return false;
}
return true;
} }
void SoundManager::stopSay(const MWWorld::Ptr &ptr) void SoundManager::stopSay(const MWWorld::Ptr &ptr)
{ {
SoundMap::iterator snditer = mActiveSounds.find(ptr); SaySoundMap::iterator snditer = mActiveSaySounds.find(ptr);
if(snditer != mActiveSounds.end()) if(snditer != mActiveSaySounds.end())
{ {
SoundNamePairList::iterator sndname = snditer->second.begin(); snditer->second.first->stop();
for(;sndname != snditer->second.end();++sndname) mActiveSaySounds.erase(snditer);
{
if(sndname->second != "_say_sound")
continue;
sndname->first->stop();
snditer->second.erase(sndname);
if(snditer->second.empty())
mActiveSounds.erase(snditer);
return;
}
} }
} }
@ -426,6 +412,21 @@ namespace MWSound
} }
bool SoundManager::isPlaying(const MWWorld::Ptr &ptr, const std::string &id) const
{
SoundMap::const_iterator snditer = mActiveSounds.find(ptr);
if(snditer != mActiveSounds.end())
{
SoundNamePairList::const_iterator sndname = snditer->second.begin();
for(;sndname != snditer->second.end();++sndname)
{
if(sndname->second == id && sndname->first->isPlaying())
return true;
}
}
return false;
}
MWBase::SoundPtr SoundManager::playSound(const std::string& soundId, float volume, float pitch, PlayType type, PlayMode mode, float offset) MWBase::SoundPtr SoundManager::playSound(const std::string& soundId, float volume, float pitch, PlayType type, PlayMode mode, float offset)
{ {
MWBase::SoundPtr sound; MWBase::SoundPtr sound;
@ -573,6 +574,19 @@ namespace MWSound
else else
++snditer; ++snditer;
} }
SaySoundMap::iterator sayiter = mActiveSaySounds.begin();
while(sayiter != mActiveSaySounds.end())
{
if(sayiter->first != MWWorld::Ptr() &&
sayiter->first != MWMechanics::getPlayer() &&
sayiter->first.getCell() == cell)
{
sayiter->second.first->stop();
mActiveSaySounds.erase(sayiter++);
}
else
++sayiter;
}
} }
void SoundManager::stopSound(const std::string& soundId) void SoundManager::stopSound(const std::string& soundId)
@ -740,7 +754,8 @@ namespace MWSound
SoundNamePairList::iterator sndname = snditer->second.begin(); SoundNamePairList::iterator sndname = snditer->second.begin();
while(sndname != snditer->second.end()) while(sndname != snditer->second.end())
{ {
if(!sndname->first->isPlaying()) MWBase::SoundPtr sound = sndname->first;
if(!sound->isPlaying())
{ {
sndname = snditer->second.erase(sndname); sndname = snditer->second.erase(sndname);
continue; continue;
@ -751,9 +766,9 @@ namespace MWSound
{ {
const ESM::Position &pos = ptr.getRefData().getPosition(); const ESM::Position &pos = ptr.getRefData().getPosition();
const osg::Vec3f objpos(pos.asVec3()); const osg::Vec3f objpos(pos.asVec3());
sndname->first->setPosition(objpos); sound->setPosition(objpos);
if ((sndname->first->mFlags & Play_RemoveAtDistance) if ((sound->mFlags & Play_RemoveAtDistance)
&& (mListenerPos - ptr.getRefData().getPosition().asVec3()).length2() > 2000*2000) && (mListenerPos - ptr.getRefData().getPosition().asVec3()).length2() > 2000*2000)
{ {
sndname = snditer->second.erase(sndname); sndname = snditer->second.erase(sndname);
@ -762,16 +777,16 @@ namespace MWSound
} }
//update fade out //update fade out
if(sndname->first->mFadeOutTime > 0.0f) if(sound->mFadeOutTime > 0.0f)
{ {
float soundDuration = duration; float soundDuration = duration;
if(soundDuration > sndname->first->mFadeOutTime) if(soundDuration > sound->mFadeOutTime)
soundDuration = sndname->first->mFadeOutTime; soundDuration = sound->mFadeOutTime;
sndname->first->setVolume(sndname->first->mVolume sound->setVolume(sound->mVolume - soundDuration/sound->mFadeOutTime*sound->mVolume);
- soundDuration / sndname->first->mFadeOutTime * sndname->first->mVolume); sound->mFadeOutTime -= soundDuration;
sndname->first->mFadeOutTime -= soundDuration;
} }
sndname->first->update(); sound->update();
++sndname; ++sndname;
} }
if(snditer->second.empty()) if(snditer->second.empty())
@ -779,6 +794,45 @@ namespace MWSound
else else
++snditer; ++snditer;
} }
SaySoundMap::iterator sayiter = mActiveSaySounds.begin();
while(sayiter != mActiveSaySounds.end())
{
MWBase::SoundPtr sound = sayiter->second.first;
if(!sound->isPlaying())
{
mActiveSaySounds.erase(sayiter++);
continue;
}
const MWWorld::Ptr &ptr = sayiter->first;
if(!ptr.isEmpty())
{
const ESM::Position &pos = ptr.getRefData().getPosition();
const osg::Vec3f objpos(pos.asVec3());
sound->setPosition(objpos);
if ((sound->mFlags & Play_RemoveAtDistance)
&& (mListenerPos - ptr.getRefData().getPosition().asVec3()).length2() > 2000*2000)
{
mActiveSaySounds.erase(sayiter++);
continue;
}
}
//update fade out
if(sound->mFadeOutTime > 0.0f)
{
float soundDuration = duration;
if(soundDuration > sound->mFadeOutTime)
soundDuration = sound->mFadeOutTime;
sound->setVolume(sound->mVolume - soundDuration/sound->mFadeOutTime*sound->mVolume);
sound->mFadeOutTime -= soundDuration;
}
sound->update();
++sayiter;
}
} }
void SoundManager::update(float duration) void SoundManager::update(float duration)
@ -841,6 +895,13 @@ namespace MWSound
mActiveSounds.erase(snditer); mActiveSounds.erase(snditer);
mActiveSounds[updated] = sndlist; mActiveSounds[updated] = sndlist;
} }
SaySoundMap::iterator sayiter = mActiveSaySounds.find(old);
if(sayiter != mActiveSaySounds.end())
{
SoundNamePair sndlist = sayiter->second;
mActiveSaySounds.erase(sayiter);
mActiveSaySounds[updated] = sndlist;
}
} }
// Default readAll implementation, for decoders that can't do anything // Default readAll implementation, for decoders that can't do anything
@ -918,6 +979,10 @@ namespace MWSound
sndname->first->stop(); sndname->first->stop();
} }
mActiveSounds.clear(); mActiveSounds.clear();
SaySoundMap::iterator sayiter = mActiveSaySounds.begin();
for(;sayiter != mActiveSaySounds.end();++sayiter)
sayiter->second.first->stop();
mActiveSaySounds.clear();
stopMusic(); stopMusic();
} }
} }

View File

@ -58,6 +58,9 @@ namespace MWSound
typedef std::map<MWWorld::Ptr,SoundNamePairList> SoundMap; typedef std::map<MWWorld::Ptr,SoundNamePairList> SoundMap;
SoundMap mActiveSounds; SoundMap mActiveSounds;
typedef std::map<MWWorld::Ptr,SoundNamePair> SaySoundMap;
SaySoundMap mActiveSaySounds;
MWBase::SoundPtr mUnderwaterSound; MWBase::SoundPtr mUnderwaterSound;
bool mListenerUnderwater; bool mListenerUnderwater;