mirror of
https://gitlab.com/OpenMW/openmw.git
synced 2025-03-23 19:20:56 +00:00
Merge branch 'astoecke-fix-6354-sfx-distance-attenuation' into 'master'
Fade sounds when performing distance-based culling (Fixes #6354) Closes #6354 See merge request OpenMW/openmw!1341
This commit is contained in:
commit
295ebbebbd
@ -68,6 +68,7 @@
|
|||||||
Bug #6323: Wyrmhaven: Alboin doesn't follower the player character out of his house
|
Bug #6323: Wyrmhaven: Alboin doesn't follower the player character out of his house
|
||||||
Bug #6326: Detect Enchantment/Key should detect items in unresolved containers
|
Bug #6326: Detect Enchantment/Key should detect items in unresolved containers
|
||||||
Bug #6347: PlaceItem/PlaceItemCell/PlaceAt should work with levelled creatures
|
Bug #6347: PlaceItem/PlaceItemCell/PlaceAt should work with levelled creatures
|
||||||
|
Bug #6354: SFX abruptly cut off after crossing max distance; implement soft fading of sound effects
|
||||||
Bug #6363: Some scripts in Morrowland fail to work
|
Bug #6363: Some scripts in Morrowland fail to work
|
||||||
Bug #6376: Creatures should be able to use torches
|
Bug #6376: Creatures should be able to use torches
|
||||||
Feature #890: OpenMW-CS: Column filtering
|
Feature #890: OpenMW-CS: Column filtering
|
||||||
|
@ -1109,13 +1109,8 @@ void OpenAL_Output::initCommon3D(ALuint source, const osg::Vec3f &pos, ALfloat m
|
|||||||
alSource3f(source, AL_VELOCITY, 0.0f, 0.0f, 0.0f);
|
alSource3f(source, AL_VELOCITY, 0.0f, 0.0f, 0.0f);
|
||||||
}
|
}
|
||||||
|
|
||||||
void OpenAL_Output::updateCommon(ALuint source, const osg::Vec3f& pos, ALfloat maxdist, ALfloat gain, ALfloat pitch, bool useenv, bool is3d)
|
void OpenAL_Output::updateCommon(ALuint source, const osg::Vec3f& pos, ALfloat maxdist, ALfloat gain, ALfloat pitch, bool useenv)
|
||||||
{
|
{
|
||||||
if(is3d)
|
|
||||||
{
|
|
||||||
if((pos - mListenerPos).length2() > maxdist*maxdist)
|
|
||||||
gain = 0.0f;
|
|
||||||
}
|
|
||||||
if(useenv && mListenerEnv == Env_Underwater && !mWaterFilter)
|
if(useenv && mListenerEnv == Env_Underwater && !mWaterFilter)
|
||||||
{
|
{
|
||||||
gain *= 0.9f;
|
gain *= 0.9f;
|
||||||
@ -1243,7 +1238,7 @@ void OpenAL_Output::updateSound(Sound *sound)
|
|||||||
ALuint source = GET_PTRID(sound->mHandle);
|
ALuint source = GET_PTRID(sound->mHandle);
|
||||||
|
|
||||||
updateCommon(source, sound->getPosition(), sound->getMaxDistance(), sound->getRealVolume(),
|
updateCommon(source, sound->getPosition(), sound->getMaxDistance(), sound->getRealVolume(),
|
||||||
sound->getPitch(), sound->getUseEnv(), sound->getIs3D());
|
sound->getPitch(), sound->getUseEnv());
|
||||||
getALError();
|
getALError();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1369,7 +1364,7 @@ void OpenAL_Output::updateStream(Stream *sound)
|
|||||||
ALuint source = stream->mSource;
|
ALuint source = stream->mSource;
|
||||||
|
|
||||||
updateCommon(source, sound->getPosition(), sound->getMaxDistance(), sound->getRealVolume(),
|
updateCommon(source, sound->getPosition(), sound->getMaxDistance(), sound->getRealVolume(),
|
||||||
sound->getPitch(), sound->getUseEnv(), sound->getIs3D());
|
sound->getPitch(), sound->getUseEnv());
|
||||||
getALError();
|
getALError();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -53,7 +53,7 @@ namespace MWSound
|
|||||||
void initCommon2D(ALuint source, const osg::Vec3f &pos, ALfloat gain, ALfloat pitch, bool loop, bool useenv);
|
void initCommon2D(ALuint source, const osg::Vec3f &pos, ALfloat gain, ALfloat pitch, bool loop, bool useenv);
|
||||||
void initCommon3D(ALuint source, const osg::Vec3f &pos, ALfloat mindist, ALfloat maxdist, ALfloat gain, ALfloat pitch, bool loop, bool useenv);
|
void initCommon3D(ALuint source, const osg::Vec3f &pos, ALfloat mindist, ALfloat maxdist, ALfloat gain, ALfloat pitch, bool loop, bool useenv);
|
||||||
|
|
||||||
void updateCommon(ALuint source, const osg::Vec3f &pos, ALfloat maxdist, ALfloat gain, ALfloat pitch, bool useenv, bool is3d);
|
void updateCommon(ALuint source, const osg::Vec3f &pos, ALfloat maxdist, ALfloat gain, ALfloat pitch, bool useenv);
|
||||||
|
|
||||||
OpenAL_Output& operator=(const OpenAL_Output &rhs);
|
OpenAL_Output& operator=(const OpenAL_Output &rhs);
|
||||||
OpenAL_Output(const OpenAL_Output &rhs);
|
OpenAL_Output(const OpenAL_Output &rhs);
|
||||||
|
@ -11,7 +11,11 @@ namespace MWSound
|
|||||||
enum PlayModeEx
|
enum PlayModeEx
|
||||||
{
|
{
|
||||||
Play_2D = 0,
|
Play_2D = 0,
|
||||||
|
Play_StopAtFadeEnd = 1 << 28,
|
||||||
|
Play_FadeExponential = 1 << 29,
|
||||||
|
Play_InFade = 1 << 30,
|
||||||
Play_3D = 1 << 31,
|
Play_3D = 1 << 31,
|
||||||
|
Play_FadeFlagsMask = (Play_StopAtFadeEnd | Play_FadeExponential),
|
||||||
};
|
};
|
||||||
|
|
||||||
// For testing individual PlayMode flags
|
// For testing individual PlayMode flags
|
||||||
@ -21,13 +25,15 @@ namespace MWSound
|
|||||||
struct SoundParams
|
struct SoundParams
|
||||||
{
|
{
|
||||||
osg::Vec3f mPos;
|
osg::Vec3f mPos;
|
||||||
float mVolume = 1;
|
float mVolume = 1.0f;
|
||||||
float mBaseVolume = 1;
|
float mBaseVolume = 1.0f;
|
||||||
float mPitch = 1;
|
float mPitch = 1.0f;
|
||||||
float mMinDistance = 1;
|
float mMinDistance = 1.0f;
|
||||||
float mMaxDistance = 1000;
|
float mMaxDistance = 1000.0f;
|
||||||
int mFlags = 0;
|
int mFlags = 0;
|
||||||
float mFadeOutTime = 0;
|
float mFadeVolume = 1.0f;
|
||||||
|
float mFadeTarget = 0.0f;
|
||||||
|
float mFadeStep = 0.0f;
|
||||||
};
|
};
|
||||||
|
|
||||||
class SoundBase {
|
class SoundBase {
|
||||||
@ -46,19 +52,97 @@ namespace MWSound
|
|||||||
void setPosition(const osg::Vec3f &pos) { mParams.mPos = pos; }
|
void setPosition(const osg::Vec3f &pos) { mParams.mPos = pos; }
|
||||||
void setVolume(float volume) { mParams.mVolume = volume; }
|
void setVolume(float volume) { mParams.mVolume = volume; }
|
||||||
void setBaseVolume(float volume) { mParams.mBaseVolume = volume; }
|
void setBaseVolume(float volume) { mParams.mBaseVolume = volume; }
|
||||||
void setFadeout(float duration) { mParams.mFadeOutTime = duration; }
|
void setFadeout(float duration) { setFade(duration, 0.0, Play_StopAtFadeEnd); }
|
||||||
void updateFade(float duration)
|
|
||||||
{
|
/// Fade to the given linear gain within the specified amount of time.
|
||||||
if (mParams.mFadeOutTime > 0.0f)
|
/// Note that the fade gain is independent of the sound volume.
|
||||||
|
///
|
||||||
|
/// \param duration specifies the duration of the fade. For *linear*
|
||||||
|
/// fades (default) this will be exactly the time at which the desired
|
||||||
|
/// volume is reached. Let v0 be the initial volume, v1 be the target
|
||||||
|
/// volume, and t0 be the initial time. Then the volume over time is
|
||||||
|
/// given as
|
||||||
|
///
|
||||||
|
/// v(t) = v0 + (v1 - v0) * (t - t0) / duration if t <= t0 + duration
|
||||||
|
/// v(t) = v1 if t > t0 + duration
|
||||||
|
///
|
||||||
|
/// For *exponential* fades this determines the time-constant of the
|
||||||
|
/// exponential process describing the fade. In particular, we guarantee
|
||||||
|
/// that we reach v0 + 0.99 * (v1 - v0) within the given duration.
|
||||||
|
///
|
||||||
|
/// v(t) = v1 + (v0 - v1) * exp(-4.6 * (t0 - t) / duration)
|
||||||
|
///
|
||||||
|
/// where -4.6 is approximately log(1%) (i.e., -40 dB).
|
||||||
|
///
|
||||||
|
/// This interpolation mode is meant for environmental sound effects to
|
||||||
|
/// achieve less jarring transitions.
|
||||||
|
///
|
||||||
|
/// \param targetVolume is the linear gain that should be reached at
|
||||||
|
/// the end of the fade.
|
||||||
|
///
|
||||||
|
/// \param flags may be a combination of Play_FadeExponential and
|
||||||
|
/// Play_StopAtFadeEnd. If Play_StopAtFadeEnd is set, stops the sound
|
||||||
|
/// once the fade duration has passed or the target volume has been
|
||||||
|
/// reached. If Play_FadeExponential is set, enables the exponential
|
||||||
|
/// fade mode (see above).
|
||||||
|
void setFade(float duration, float targetVolume, int flags = 0) {
|
||||||
|
// Approximation of log(1%) (i.e., -40 dB).
|
||||||
|
constexpr float minus40Decibel = -4.6f;
|
||||||
|
|
||||||
|
// Do nothing if already at the target, unless we need to trigger a stop event
|
||||||
|
if ((mParams.mFadeVolume == targetVolume) && !(flags & Play_StopAtFadeEnd))
|
||||||
|
return;
|
||||||
|
|
||||||
|
mParams.mFadeTarget = targetVolume;
|
||||||
|
mParams.mFlags = (mParams.mFlags & ~Play_FadeFlagsMask) | (flags & Play_FadeFlagsMask) | Play_InFade;
|
||||||
|
if (duration > 0.0f)
|
||||||
{
|
{
|
||||||
float soundDuration = std::min(duration, mParams.mFadeOutTime);
|
if (mParams.mFlags & Play_FadeExponential)
|
||||||
mParams.mVolume *= (mParams.mFadeOutTime - soundDuration) / mParams.mFadeOutTime;
|
mParams.mFadeStep = -minus40Decibel / duration;
|
||||||
mParams.mFadeOutTime -= soundDuration;
|
else
|
||||||
|
mParams.mFadeStep = (mParams.mFadeTarget - mParams.mFadeVolume) / duration;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
mParams.mFadeVolume = mParams.mFadeTarget;
|
||||||
|
mParams.mFadeStep = 0.0f;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Updates the internal fading logic.
|
||||||
|
///
|
||||||
|
/// \param dt is the time in seconds since the last call to update.
|
||||||
|
///
|
||||||
|
/// \return true if the sound is still active, false if the sound has
|
||||||
|
/// reached a fading destination that was marked with Play_StopAtFadeEnd.
|
||||||
|
bool updateFade(float dt)
|
||||||
|
{
|
||||||
|
// Mark fade as done at this volume difference (-80dB when fading to zero)
|
||||||
|
constexpr float minVolumeDifference = 1e-4f;
|
||||||
|
|
||||||
|
if (!getInFade())
|
||||||
|
return true;
|
||||||
|
|
||||||
|
// Perform the actual fade operation
|
||||||
|
const float deltaBefore = mParams.mFadeTarget - mParams.mFadeVolume;
|
||||||
|
if (mParams.mFlags & Play_FadeExponential)
|
||||||
|
mParams.mFadeVolume += mParams.mFadeStep * deltaBefore * dt;
|
||||||
|
else
|
||||||
|
mParams.mFadeVolume += mParams.mFadeStep * dt;
|
||||||
|
const float deltaAfter = mParams.mFadeTarget - mParams.mFadeVolume;
|
||||||
|
|
||||||
|
// Abort fade if we overshot or reached the minimum difference
|
||||||
|
if ((std::signbit(deltaBefore) != std::signbit(deltaAfter)) || (std::abs(deltaAfter) < minVolumeDifference))
|
||||||
|
{
|
||||||
|
mParams.mFadeVolume = mParams.mFadeTarget;
|
||||||
|
mParams.mFlags &= ~Play_InFade;
|
||||||
|
}
|
||||||
|
|
||||||
|
return getInFade() || !(mParams.mFlags & Play_StopAtFadeEnd);
|
||||||
|
}
|
||||||
|
|
||||||
const osg::Vec3f &getPosition() const { return mParams.mPos; }
|
const osg::Vec3f &getPosition() const { return mParams.mPos; }
|
||||||
float getRealVolume() const { return mParams.mVolume * mParams.mBaseVolume; }
|
float getRealVolume() const { return mParams.mVolume * mParams.mBaseVolume * mParams.mFadeVolume; }
|
||||||
float getPitch() const { return mParams.mPitch; }
|
float getPitch() const { return mParams.mPitch; }
|
||||||
float getMinDistance() const { return mParams.mMinDistance; }
|
float getMinDistance() const { return mParams.mMinDistance; }
|
||||||
float getMaxDistance() const { return mParams.mMaxDistance; }
|
float getMaxDistance() const { return mParams.mMaxDistance; }
|
||||||
@ -69,6 +153,7 @@ namespace MWSound
|
|||||||
bool getIsLooping() const { return mParams.mFlags & MWSound::PlayMode::Loop; }
|
bool getIsLooping() const { return mParams.mFlags & MWSound::PlayMode::Loop; }
|
||||||
bool getDistanceCull() const { return mParams.mFlags & MWSound::PlayMode::RemoveAtDistance; }
|
bool getDistanceCull() const { return mParams.mFlags & MWSound::PlayMode::RemoveAtDistance; }
|
||||||
bool getIs3D() const { return mParams.mFlags & Play_3D; }
|
bool getIs3D() const { return mParams.mFlags & Play_3D; }
|
||||||
|
bool getInFade() const { return mParams.mFlags & Play_InFade; }
|
||||||
|
|
||||||
void init(const SoundParams& params)
|
void init(const SoundParams& params)
|
||||||
{
|
{
|
||||||
|
@ -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,24 @@ 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;
|
||||||
|
|
||||||
|
// This is a *heuristic* that causes environment sounds to fade in. The idea is the following:
|
||||||
|
// - Only looped sounds playing through the effects channel are environment sounds
|
||||||
|
// - Do not fade in sounds if the player is already so close that the sound plays at maximum volume
|
||||||
|
const float minDist = sfx->getMinDist();
|
||||||
|
if ((squaredDist > (minDist * minDist)) && (type == Type::Sfx) && (mode & PlayMode::Loop))
|
||||||
|
return 0.0f;
|
||||||
|
|
||||||
|
return 1.0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// For combining PlayMode and Type flags
|
// For combining PlayMode and Type flags
|
||||||
@ -517,7 +537,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 +569,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 +598,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();
|
||||||
@ -777,10 +802,10 @@ namespace MWSound
|
|||||||
break;
|
break;
|
||||||
case WaterSoundAction::SetVolume:
|
case WaterSoundAction::SetVolume:
|
||||||
mNearWaterSound->setVolume(update.mVolume * sfx->getVolume());
|
mNearWaterSound->setVolume(update.mVolume * sfx->getVolume());
|
||||||
|
mNearWaterSound->setFade(sSfxFadeInDuration, 1.0f, Play_FadeExponential);
|
||||||
break;
|
break;
|
||||||
case WaterSoundAction::FinishSound:
|
case WaterSoundAction::FinishSound:
|
||||||
mOutput->finishSound(mNearWaterSound);
|
mNearWaterSound->setFade(sSfxFadeOutDuration, 0.0f, Play_FadeExponential | Play_StopAtFadeEnd);
|
||||||
mNearWaterSound = nullptr;
|
|
||||||
break;
|
break;
|
||||||
case WaterSoundAction::PlaySound:
|
case WaterSoundAction::PlaySound:
|
||||||
if (mNearWaterSound)
|
if (mNearWaterSound)
|
||||||
@ -830,6 +855,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,20 +931,15 @@ 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(!mOutput->isSoundPlaying(sound))
|
if(!sound->updateFade(duration) || !mOutput->isSoundPlaying(sound))
|
||||||
{
|
{
|
||||||
mOutput->finishSound(sound);
|
mOutput->finishSound(sound);
|
||||||
if (sound == mUnderwaterSound)
|
if (sound == mUnderwaterSound)
|
||||||
@ -909,8 +951,6 @@ namespace MWSound
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
sound->updateFade(duration);
|
|
||||||
|
|
||||||
mOutput->updateSound(sound);
|
mOutput->updateSound(sound);
|
||||||
++sndidx;
|
++sndidx;
|
||||||
}
|
}
|
||||||
@ -926,28 +966,24 @@ 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())
|
||||||
{
|
{
|
||||||
MWBase::World *world = MWBase::Environment::get().getWorld();
|
if (!ptr.isEmpty())
|
||||||
const osg::Vec3f pos = world->getActorHeadTransform(ptr).getTrans();
|
|
||||||
sound->setPosition(pos);
|
|
||||||
|
|
||||||
if(sound->getDistanceCull())
|
|
||||||
{
|
{
|
||||||
if((mListenerPos - pos).length2() > 2000*2000)
|
MWBase::World *world = MWBase::Environment::get().getWorld();
|
||||||
mOutput->finishStream(sound);
|
sound->setPosition(world->getActorHeadTransform(ptr).getTrans());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
cull3DSound(sound);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!mOutput->isStreamPlaying(sound))
|
if(!sound->updateFade(duration) || !mOutput->isStreamPlaying(sound))
|
||||||
{
|
{
|
||||||
mOutput->finishStream(sound);
|
mOutput->finishStream(sound);
|
||||||
mActiveSaySounds.erase(sayiter++);
|
sayiter = mActiveSaySounds.erase(sayiter);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
sound->updateFade(duration);
|
|
||||||
|
|
||||||
mOutput->updateStream(sound);
|
mOutput->updateStream(sound);
|
||||||
++sayiter;
|
++sayiter;
|
||||||
}
|
}
|
||||||
|
@ -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…
x
Reference in New Issue
Block a user