Apply reverb and a low-pass filter when underwater

This replaces the pitch-shift effect when available.
This commit is contained in:
Chris Robinson 2017-09-12 20:20:23 -07:00
parent 27eeaf90d0
commit edfba68eb5
2 changed files with 93 additions and 12 deletions

View file

@ -698,7 +698,7 @@ void OpenAL_Output::init(const std::string &devname)
{ {
std::cout<< "Low-pass filter supported" <<std::endl; std::cout<< "Low-pass filter supported" <<std::endl;
alFilterf(mWaterFilter, AL_LOWPASS_GAIN, 0.9f); alFilterf(mWaterFilter, AL_LOWPASS_GAIN, 0.9f);
alFilterf(mWaterFilter, AL_LOWPASS_GAINHF, 0.01f); alFilterf(mWaterFilter, AL_LOWPASS_GAINHF, 0.125f);
} }
else else
{ {
@ -709,18 +709,34 @@ void OpenAL_Output::init(const std::string &devname)
} }
alGenAuxiliaryEffectSlots(1, &mEffectSlot); alGenAuxiliaryEffectSlots(1, &mEffectSlot);
alGenEffects(1, &mWaterEffect); alGetError();
alGenEffects(1, &mDefaultEffect);
if(alGetError() == AL_NO_ERROR) if(alGetError() == AL_NO_ERROR)
{ {
alEffecti(mWaterEffect, AL_EFFECT_TYPE, AL_EFFECT_EAXREVERB); alEffecti(mDefaultEffect, AL_EFFECT_TYPE, AL_EFFECT_EAXREVERB);
if(alGetError() == AL_NO_ERROR) if(alGetError() == AL_NO_ERROR)
std::cout<< "EAX Reverb supported" <<std::endl; std::cout<< "EAX Reverb supported" <<std::endl;
else else
{ {
alEffecti(mWaterEffect, AL_EFFECT_TYPE, AL_EFFECT_REVERB); alEffecti(mDefaultEffect, AL_EFFECT_TYPE, AL_EFFECT_REVERB);
if(alGetError() == AL_NO_ERROR) if(alGetError() == AL_NO_ERROR)
std::cout<< "Standard Reverb supported" <<std::endl; std::cout<< "Standard Reverb supported" <<std::endl;
} }
EFXEAXREVERBPROPERTIES props = EFX_REVERB_PRESET_GENERIC;
props.flGain = 0.0f;
LoadEffect(mDefaultEffect, props);
}
alGenEffects(1, &mWaterEffect);
if(alGetError() == AL_NO_ERROR)
{
alEffecti(mWaterEffect, AL_EFFECT_TYPE, AL_EFFECT_EAXREVERB);
if(alGetError() != AL_NO_ERROR)
{
alEffecti(mWaterEffect, AL_EFFECT_TYPE, AL_EFFECT_REVERB);
alGetError();
}
LoadEffect(mWaterEffect, EFX_REVERB_PRESET_UNDERWATER); LoadEffect(mWaterEffect, EFX_REVERB_PRESET_UNDERWATER);
} }
@ -745,6 +761,9 @@ void OpenAL_Output::deinit()
if(mEffectSlot) if(mEffectSlot)
alDeleteAuxiliaryEffectSlots(1, &mEffectSlot); alDeleteAuxiliaryEffectSlots(1, &mEffectSlot);
mEffectSlot = 0; mEffectSlot = 0;
if(mDefaultEffect)
alDeleteEffects(1, &mDefaultEffect);
mDefaultEffect = 0;
if(mWaterEffect) if(mWaterEffect)
alDeleteEffects(1, &mWaterEffect); alDeleteEffects(1, &mWaterEffect);
mWaterEffect = 0; mWaterEffect = 0;
@ -954,11 +973,27 @@ void OpenAL_Output::initCommon2D(ALuint source, const osg::Vec3f &pos, ALfloat g
alSourcei(source, AL_SOURCE_RELATIVE, AL_TRUE); alSourcei(source, AL_SOURCE_RELATIVE, AL_TRUE);
alSourcei(source, AL_LOOPING, loop ? AL_TRUE : AL_FALSE); alSourcei(source, AL_LOOPING, loop ? AL_TRUE : AL_FALSE);
if(useenv && mListenerEnv == Env_Underwater) if(useenv)
{
if(mWaterFilter)
alSourcei(source, AL_DIRECT_FILTER,
(mListenerEnv == Env_Underwater) ? mWaterFilter : AL_FILTER_NULL
);
else if(mListenerEnv == Env_Underwater)
{ {
gain *= 0.9f; gain *= 0.9f;
pitch *= 0.7f; pitch *= 0.7f;
} }
if(mEffectSlot)
alSource3i(source, AL_AUXILIARY_SEND_FILTER, mEffectSlot, 0, AL_FILTER_NULL);
}
else
{
if(mWaterFilter)
alSourcei(source, AL_DIRECT_FILTER, AL_FILTER_NULL);
if(mEffectSlot)
alSource3i(source, AL_AUXILIARY_SEND_FILTER, AL_EFFECTSLOT_NULL, 0, AL_FILTER_NULL);
}
alSourcef(source, AL_GAIN, gain); alSourcef(source, AL_GAIN, gain);
alSourcef(source, AL_PITCH, pitch); alSourcef(source, AL_PITCH, pitch);
@ -977,11 +1012,27 @@ void OpenAL_Output::initCommon3D(ALuint source, const osg::Vec3f &pos, ALfloat m
if((pos - mListenerPos).length2() > maxdist*maxdist) if((pos - mListenerPos).length2() > maxdist*maxdist)
gain = 0.0f; gain = 0.0f;
if(useenv && mListenerEnv == Env_Underwater) if(useenv)
{
if(mWaterFilter)
alSourcei(source, AL_DIRECT_FILTER,
(mListenerEnv == Env_Underwater) ? mWaterFilter : AL_FILTER_NULL
);
else if(mListenerEnv == Env_Underwater)
{ {
gain *= 0.9f; gain *= 0.9f;
pitch *= 0.7f; pitch *= 0.7f;
} }
if(mEffectSlot)
alSource3i(source, AL_AUXILIARY_SEND_FILTER, mEffectSlot, 0, AL_FILTER_NULL);
}
else
{
if(mWaterFilter)
alSourcei(source, AL_DIRECT_FILTER, AL_FILTER_NULL);
if(mEffectSlot)
alSource3i(source, AL_AUXILIARY_SEND_FILTER, AL_EFFECTSLOT_NULL, 0, AL_FILTER_NULL);
}
alSourcef(source, AL_GAIN, gain); alSourcef(source, AL_GAIN, gain);
alSourcef(source, AL_PITCH, pitch); alSourcef(source, AL_PITCH, pitch);
@ -997,7 +1048,7 @@ void OpenAL_Output::updateCommon(ALuint source, const osg::Vec3f& pos, ALfloat m
if((pos - mListenerPos).length2() > maxdist*maxdist) if((pos - mListenerPos).length2() > maxdist*maxdist)
gain = 0.0f; gain = 0.0f;
} }
if(useenv && mListenerEnv == Env_Underwater) if(useenv && mListenerEnv == Env_Underwater && !mWaterFilter)
{ {
gain *= 0.9f; gain *= 0.9f;
pitch *= 0.7f; pitch *= 0.7f;
@ -1256,10 +1307,39 @@ void OpenAL_Output::updateListener(const osg::Vec3f &pos, const osg::Vec3f &atdi
}; };
alListenerfv(AL_POSITION, pos.ptr()); alListenerfv(AL_POSITION, pos.ptr());
alListenerfv(AL_ORIENTATION, orient); alListenerfv(AL_ORIENTATION, orient);
if(env != mListenerEnv) if(env != mListenerEnv)
{ {
// Speed of sound in water is 1484m/s, and in air is 343.3m/s (roughly) // Speed of sound in water is 1484m/s, and in air is 343.3m/s (roughly)
alSpeedOfSound(((env == Env_Underwater) ? 1484.0f : 343.3f) * UnitsPerMeter); alSpeedOfSound(((env == Env_Underwater) ? 1484.0f : 343.3f) * UnitsPerMeter);
// Update active sources with the environment's direct filter
if(mWaterFilter)
{
ALuint filter = (env == Env_Underwater) ? mWaterFilter : AL_FILTER_NULL;
std::for_each(mActiveSounds.cbegin(), mActiveSounds.cend(),
[filter](const SoundVec::value_type &item) -> void
{
if(item->getUseEnv())
alSourcei(GET_PTRID(item->mHandle), AL_DIRECT_FILTER, filter);
}
);
std::for_each(mActiveStreams.cbegin(), mActiveStreams.cend(),
[filter](const StreamVec::value_type &item) -> void
{
if(item->getUseEnv())
alSourcei(
reinterpret_cast<OpenAL_SoundStream*>(item->mHandle)->mSource,
AL_DIRECT_FILTER, filter
);
}
);
}
// Update the environment effect
if(mEffectSlot)
alAuxiliaryEffectSloti(mEffectSlot, AL_EFFECTSLOT_EFFECT,
(env == Env_Underwater) ? mWaterEffect : mDefaultEffect
);
} }
throwALerror(); throwALerror();
} }
@ -1323,7 +1403,7 @@ void OpenAL_Output::resumeSounds(int types)
OpenAL_Output::OpenAL_Output(SoundManager &mgr) OpenAL_Output::OpenAL_Output(SoundManager &mgr)
: Sound_Output(mgr), mDevice(0), mContext(0) : Sound_Output(mgr), mDevice(0), mContext(0)
, mListenerPos(0.0f, 0.0f, 0.0f), mListenerEnv(Env_Normal) , mListenerPos(0.0f, 0.0f, 0.0f), mListenerEnv(Env_Normal)
, mWaterFilter(0), mWaterEffect(0), mEffectSlot(0) , mWaterFilter(0), mWaterEffect(0), mDefaultEffect(0), mEffectSlot(0)
, mStreamThread(new StreamThread) , mStreamThread(new StreamThread)
{ {
} }

View file

@ -40,6 +40,7 @@ namespace MWSound
ALuint mWaterFilter; ALuint mWaterFilter;
ALuint mWaterEffect; ALuint mWaterEffect;
ALuint mDefaultEffect;
ALuint mEffectSlot; ALuint mEffectSlot;
struct StreamThread; struct StreamThread;