mirror of
https://github.com/OpenMW/openmw.git
synced 2025-01-31 15:45:35 +00:00
Fade out sound sources that are no longer close
* Handle culling of all sound sources in a separate function cull3DSound * Add two new settings Sound::sfx fade in duration and Sound::sfx fade out duration
This commit is contained in:
parent
1583252dd8
commit
6f2e311c58
2 changed files with 54 additions and 18 deletions
|
@ -33,6 +33,8 @@ namespace MWSound
|
|||
namespace
|
||||
{
|
||||
constexpr float sMinUpdateInterval = 1.0f / 30.0f;
|
||||
constexpr float sSfxFadeInDuration = 1.0f;
|
||||
constexpr float sSfxFadeOutDuration = 1.0f;
|
||||
|
||||
WaterSoundUpdaterSettings makeWaterSoundUpdaterSettings()
|
||||
{
|
||||
|
@ -47,6 +49,17 @@ namespace MWSound
|
|||
|
||||
return settings;
|
||||
}
|
||||
|
||||
float initialFadeVolume(float squaredDist, Sound_Buffer *sfx, Type type, PlayMode mode)
|
||||
{
|
||||
// If a sound is farther away than its maximum distance, start playing it with a zero fade volume.
|
||||
// It can still become audible once the player moves closer.
|
||||
const float maxDist = sfx->getMaxDist();
|
||||
if (squaredDist > (maxDist * maxDist))
|
||||
return 0.0f;
|
||||
|
||||
return 1.0;
|
||||
}
|
||||
}
|
||||
|
||||
// For combining PlayMode and Type flags
|
||||
|
@ -517,7 +530,8 @@ namespace MWSound
|
|||
return nullptr;
|
||||
|
||||
const osg::Vec3f objpos(ptr.getRefData().getPosition().asVec3());
|
||||
if ((mode & PlayMode::RemoveAtDistance) && (mListenerPos - objpos).length2() > 2000 * 2000)
|
||||
const float squaredDist = (mListenerPos - objpos).length2();
|
||||
if ((mode & PlayMode::RemoveAtDistance) && squaredDist > 2000 * 2000)
|
||||
return nullptr;
|
||||
|
||||
// Look up the sound in the ESM data
|
||||
|
@ -548,6 +562,7 @@ namespace MWSound
|
|||
params.mPos = objpos;
|
||||
params.mVolume = volume * sfx->getVolume();
|
||||
params.mBaseVolume = volumeFromType(type);
|
||||
params.mFadeVolume = initialFadeVolume(squaredDist, sfx, type, mode);
|
||||
params.mPitch = pitch;
|
||||
params.mMinDistance = sfx->getMinDist();
|
||||
params.mMaxDistance = sfx->getMaxDist();
|
||||
|
@ -576,12 +591,15 @@ namespace MWSound
|
|||
Sound_Buffer *sfx = mSoundBuffers.load(Misc::StringUtils::lowerCase(soundId));
|
||||
if(!sfx) return nullptr;
|
||||
|
||||
const float squaredDist = (mListenerPos - initialPos).length2();
|
||||
|
||||
SoundPtr sound = getSoundRef();
|
||||
sound->init([&] {
|
||||
SoundParams params;
|
||||
params.mPos = initialPos;
|
||||
params.mVolume = volume * sfx->getVolume();
|
||||
params.mBaseVolume = volumeFromType(type);
|
||||
params.mFadeVolume = initialFadeVolume(squaredDist, sfx, type, mode);
|
||||
params.mPitch = pitch;
|
||||
params.mMinDistance = sfx->getMinDist();
|
||||
params.mMaxDistance = sfx->getMaxDist();
|
||||
|
@ -830,6 +848,28 @@ namespace MWSound
|
|||
return {WaterSoundAction::DoNothing, nullptr};
|
||||
}
|
||||
|
||||
void SoundManager::cull3DSound(SoundBase *sound)
|
||||
{
|
||||
// Hard-coded distance of 2000.0f is from vanilla Morrowind
|
||||
const float maxDist = sound->getDistanceCull() ? 2000.0f : sound->getMaxDistance();
|
||||
const float squaredMaxDist = maxDist * maxDist;
|
||||
|
||||
const osg::Vec3f pos = sound->getPosition();
|
||||
const float squaredDist = (mListenerPos - pos).length2();
|
||||
|
||||
if (squaredDist > squaredMaxDist)
|
||||
{
|
||||
// If getDistanceCull() is set, delete the sound after it has faded out
|
||||
sound->setFade(sSfxFadeOutDuration, 0.0f, Play_FadeExponential | (sound->getDistanceCull() ? Play_StopAtFadeEnd : 0));
|
||||
}
|
||||
else
|
||||
{
|
||||
// Fade sounds back in once they are in range
|
||||
sound->setFade(sSfxFadeInDuration, 1.0f, Play_FadeExponential);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void SoundManager::updateSounds(float duration)
|
||||
{
|
||||
// We update active say sounds map for specific actors here
|
||||
|
@ -884,17 +924,12 @@ namespace MWSound
|
|||
{
|
||||
Sound *sound = sndidx->first.get();
|
||||
|
||||
if(!ptr.isEmpty() && sound->getIs3D())
|
||||
if (sound->getIs3D())
|
||||
{
|
||||
const ESM::Position &pos = ptr.getRefData().getPosition();
|
||||
const osg::Vec3f objpos(pos.asVec3());
|
||||
sound->setPosition(objpos);
|
||||
if (!ptr.isEmpty())
|
||||
sound->setPosition(ptr.getRefData().getPosition().asVec3());
|
||||
|
||||
if(sound->getDistanceCull())
|
||||
{
|
||||
if((mListenerPos - objpos).length2() > 2000*2000)
|
||||
mOutput->finishSound(sound);
|
||||
}
|
||||
cull3DSound(sound);
|
||||
}
|
||||
|
||||
if(!sound->updateFade(duration) || !mOutput->isSoundPlaying(sound))
|
||||
|
@ -924,17 +959,15 @@ namespace MWSound
|
|||
{
|
||||
MWWorld::ConstPtr ptr = sayiter->first;
|
||||
Stream *sound = sayiter->second.get();
|
||||
if(!ptr.isEmpty() && sound->getIs3D())
|
||||
if (sound->getIs3D())
|
||||
{
|
||||
MWBase::World *world = MWBase::Environment::get().getWorld();
|
||||
const osg::Vec3f pos = world->getActorHeadTransform(ptr).getTrans();
|
||||
sound->setPosition(pos);
|
||||
|
||||
if(sound->getDistanceCull())
|
||||
if (!ptr.isEmpty())
|
||||
{
|
||||
if((mListenerPos - pos).length2() > 2000*2000)
|
||||
mOutput->finishStream(sound);
|
||||
MWBase::World *world = MWBase::Environment::get().getWorld();
|
||||
sound->setPosition(world->getActorHeadTransform(ptr).getTrans());
|
||||
}
|
||||
|
||||
cull3DSound(sound);
|
||||
}
|
||||
|
||||
if(!sound->updateFade(duration) || !mOutput->isStreamPlaying(sound))
|
||||
|
|
|
@ -34,6 +34,7 @@ namespace MWSound
|
|||
{
|
||||
class Sound_Output;
|
||||
struct Sound_Decoder;
|
||||
class SoundBase;
|
||||
class Sound;
|
||||
class Stream;
|
||||
|
||||
|
@ -111,6 +112,8 @@ namespace MWSound
|
|||
void advanceMusic(const std::string& filename);
|
||||
void startRandomTitle();
|
||||
|
||||
void cull3DSound(SoundBase *sound);
|
||||
|
||||
void updateSounds(float duration);
|
||||
void updateRegionSound(float duration);
|
||||
void updateWaterSound();
|
||||
|
|
Loading…
Reference in a new issue