mirror of
https://github.com/OpenMW/openmw.git
synced 2025-01-21 08:23:53 +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
|
namespace
|
||||||
{
|
{
|
||||||
constexpr float sMinUpdateInterval = 1.0f / 30.0f;
|
constexpr float sMinUpdateInterval = 1.0f / 30.0f;
|
||||||
|
constexpr float sSfxFadeInDuration = 1.0f;
|
||||||
|
constexpr float sSfxFadeOutDuration = 1.0f;
|
||||||
|
|
||||||
WaterSoundUpdaterSettings makeWaterSoundUpdaterSettings()
|
WaterSoundUpdaterSettings makeWaterSoundUpdaterSettings()
|
||||||
{
|
{
|
||||||
|
@ -47,6 +49,17 @@ namespace MWSound
|
||||||
|
|
||||||
return settings;
|
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
|
// For combining PlayMode and Type flags
|
||||||
|
@ -517,7 +530,8 @@ namespace MWSound
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
||||||
const osg::Vec3f objpos(ptr.getRefData().getPosition().asVec3());
|
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;
|
return nullptr;
|
||||||
|
|
||||||
// Look up the sound in the ESM data
|
// Look up the sound in the ESM data
|
||||||
|
@ -548,6 +562,7 @@ namespace MWSound
|
||||||
params.mPos = objpos;
|
params.mPos = objpos;
|
||||||
params.mVolume = volume * sfx->getVolume();
|
params.mVolume = volume * sfx->getVolume();
|
||||||
params.mBaseVolume = volumeFromType(type);
|
params.mBaseVolume = volumeFromType(type);
|
||||||
|
params.mFadeVolume = initialFadeVolume(squaredDist, sfx, type, mode);
|
||||||
params.mPitch = pitch;
|
params.mPitch = pitch;
|
||||||
params.mMinDistance = sfx->getMinDist();
|
params.mMinDistance = sfx->getMinDist();
|
||||||
params.mMaxDistance = sfx->getMaxDist();
|
params.mMaxDistance = sfx->getMaxDist();
|
||||||
|
@ -576,12 +591,15 @@ namespace MWSound
|
||||||
Sound_Buffer *sfx = mSoundBuffers.load(Misc::StringUtils::lowerCase(soundId));
|
Sound_Buffer *sfx = mSoundBuffers.load(Misc::StringUtils::lowerCase(soundId));
|
||||||
if(!sfx) return nullptr;
|
if(!sfx) return nullptr;
|
||||||
|
|
||||||
|
const float squaredDist = (mListenerPos - initialPos).length2();
|
||||||
|
|
||||||
SoundPtr sound = getSoundRef();
|
SoundPtr sound = getSoundRef();
|
||||||
sound->init([&] {
|
sound->init([&] {
|
||||||
SoundParams params;
|
SoundParams params;
|
||||||
params.mPos = initialPos;
|
params.mPos = initialPos;
|
||||||
params.mVolume = volume * sfx->getVolume();
|
params.mVolume = volume * sfx->getVolume();
|
||||||
params.mBaseVolume = volumeFromType(type);
|
params.mBaseVolume = volumeFromType(type);
|
||||||
|
params.mFadeVolume = initialFadeVolume(squaredDist, sfx, type, mode);
|
||||||
params.mPitch = pitch;
|
params.mPitch = pitch;
|
||||||
params.mMinDistance = sfx->getMinDist();
|
params.mMinDistance = sfx->getMinDist();
|
||||||
params.mMaxDistance = sfx->getMaxDist();
|
params.mMaxDistance = sfx->getMaxDist();
|
||||||
|
@ -830,6 +848,28 @@ namespace MWSound
|
||||||
return {WaterSoundAction::DoNothing, nullptr};
|
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)
|
void SoundManager::updateSounds(float duration)
|
||||||
{
|
{
|
||||||
// We update active say sounds map for specific actors here
|
// We update active say sounds map for specific actors here
|
||||||
|
@ -884,17 +924,12 @@ namespace MWSound
|
||||||
{
|
{
|
||||||
Sound *sound = sndidx->first.get();
|
Sound *sound = sndidx->first.get();
|
||||||
|
|
||||||
if(!ptr.isEmpty() && sound->getIs3D())
|
if (sound->getIs3D())
|
||||||
{
|
{
|
||||||
const ESM::Position &pos = ptr.getRefData().getPosition();
|
if (!ptr.isEmpty())
|
||||||
const osg::Vec3f objpos(pos.asVec3());
|
sound->setPosition(ptr.getRefData().getPosition().asVec3());
|
||||||
sound->setPosition(objpos);
|
|
||||||
|
|
||||||
if(sound->getDistanceCull())
|
cull3DSound(sound);
|
||||||
{
|
|
||||||
if((mListenerPos - objpos).length2() > 2000*2000)
|
|
||||||
mOutput->finishSound(sound);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!sound->updateFade(duration) || !mOutput->isSoundPlaying(sound))
|
if(!sound->updateFade(duration) || !mOutput->isSoundPlaying(sound))
|
||||||
|
@ -924,17 +959,15 @@ namespace MWSound
|
||||||
{
|
{
|
||||||
MWWorld::ConstPtr ptr = sayiter->first;
|
MWWorld::ConstPtr ptr = sayiter->first;
|
||||||
Stream *sound = sayiter->second.get();
|
Stream *sound = sayiter->second.get();
|
||||||
if(!ptr.isEmpty() && sound->getIs3D())
|
if (sound->getIs3D())
|
||||||
|
{
|
||||||
|
if (!ptr.isEmpty())
|
||||||
{
|
{
|
||||||
MWBase::World *world = MWBase::Environment::get().getWorld();
|
MWBase::World *world = MWBase::Environment::get().getWorld();
|
||||||
const osg::Vec3f pos = world->getActorHeadTransform(ptr).getTrans();
|
sound->setPosition(world->getActorHeadTransform(ptr).getTrans());
|
||||||
sound->setPosition(pos);
|
|
||||||
|
|
||||||
if(sound->getDistanceCull())
|
|
||||||
{
|
|
||||||
if((mListenerPos - pos).length2() > 2000*2000)
|
|
||||||
mOutput->finishStream(sound);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
cull3DSound(sound);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!sound->updateFade(duration) || !mOutput->isStreamPlaying(sound))
|
if(!sound->updateFade(duration) || !mOutput->isStreamPlaying(sound))
|
||||||
|
|
|
@ -34,6 +34,7 @@ namespace MWSound
|
||||||
{
|
{
|
||||||
class Sound_Output;
|
class Sound_Output;
|
||||||
struct Sound_Decoder;
|
struct Sound_Decoder;
|
||||||
|
class SoundBase;
|
||||||
class Sound;
|
class Sound;
|
||||||
class Stream;
|
class Stream;
|
||||||
|
|
||||||
|
@ -111,6 +112,8 @@ namespace MWSound
|
||||||
void advanceMusic(const std::string& filename);
|
void advanceMusic(const std::string& filename);
|
||||||
void startRandomTitle();
|
void startRandomTitle();
|
||||||
|
|
||||||
|
void cull3DSound(SoundBase *sound);
|
||||||
|
|
||||||
void updateSounds(float duration);
|
void updateSounds(float duration);
|
||||||
void updateRegionSound(float duration);
|
void updateRegionSound(float duration);
|
||||||
void updateWaterSound();
|
void updateWaterSound();
|
||||||
|
|
Loading…
Reference in a new issue