diff --git a/neo/sound/efxlib.h b/neo/sound/efxlib.h index c77d6e45..a49e4029 100644 --- a/neo/sound/efxlib.h +++ b/neo/sound/efxlib.h @@ -8,8 +8,17 @@ #include "idlib/Str.h" #include "idlib/Lexer.h" #include "idlib/Heap.h" +#include "framework/Common.h" #include "sound/sound.h" +#define EFX_VERBOSE 0 + +#if EFX_VERBOSE +#define EFXprintf(...) do { common->Printf(__VA_ARGS__); } while (false) +#else +#define EFXprintf(...) do { } while (false) +#endif + struct idSoundEffect { idSoundEffect(); ~idSoundEffect(); diff --git a/neo/sound/snd_efxfile.cpp b/neo/sound/snd_efxfile.cpp index 75227404..28280532 100644 --- a/neo/sound/snd_efxfile.cpp +++ b/neo/sound/snd_efxfile.cpp @@ -40,7 +40,7 @@ idSoundEffect::idSoundEffect() : } idSoundEffect::~idSoundEffect() { - if (effect) + if (soundSystemLocal.alIsEffect(effect)) soundSystemLocal.alDeleteEffects(1, &effect); } @@ -50,12 +50,16 @@ bool idSoundEffect::alloc() { ALenum e; soundSystemLocal.alGenEffects(1, &effect); - if ((e = alGetError()) != AL_NO_ERROR) { + e = alGetError(); + if (e != AL_NO_ERROR) { + common->Warning("idSoundEffect::alloc: alGenEffects failed: 0x%x", e); return false; } soundSystemLocal.alEffecti(effect, AL_EFFECT_TYPE, AL_EFFECT_EAXREVERB); - if ((e = alGetError()) != AL_NO_ERROR) { + e = alGetError(); + if (e != AL_NO_ERROR) { + common->Warning("idSoundEffect::alloc: alEffecti failed: 0x%x", e); return false; } @@ -111,6 +115,43 @@ bool idEFXFile::FindEffect( idStr &name, ALuint *effect ) { idEFXFile::ReadEffect =============== */ +#define efxi(param, value) \ + do { \ + ALint _v = value; \ + EFXprintf("alEffecti(" #param ", %d)\n", _v); \ + soundSystemLocal.alEffecti(effect->effect, param, _v); \ + err = alGetError(); \ + if (err != AL_NO_ERROR) \ + common->Warning("alEffecti(" # param ", %d) " \ + "failed: 0x%x", _v, err); \ + } while (false) + +#define efxf(param, value) \ + do { \ + ALfloat _v = value; \ + EFXprintf("alEffectf(" #param ", %.3f)\n", _v); \ + soundSystemLocal.alEffectf(effect->effect, param, _v); \ + err = alGetError(); \ + if (err != AL_NO_ERROR) \ + common->Warning("alEffectf(" # param ", %.3f) " \ + "failed: 0x%x", _v, err); \ + } while (false) + +#define efxfv(param, value0, value1, value2) \ + do { \ + ALfloat _v[3]; \ + _v[0] = value0; \ + _v[1] = value1; \ + _v[2] = value2; \ + EFXprintf("alEffectfv(" #param ", %.3f, %.3f, %.3f)\n", \ + _v[0], _v[1], _v[2]); \ + soundSystemLocal.alEffectfv(effect->effect, param, _v); \ + err = alGetError(); \ + if (err != AL_NO_ERROR) \ + common->Warning("alEffectfv(" # param ", %.3f, %.3f, %.3f) " \ + "failed: 0x%x", _v[0], _v[1], _v[2], err); \ + } while (false) + bool idEFXFile::ReadEffect( idLexer &src, idSoundEffect *effect ) { idToken name, token; @@ -136,6 +177,10 @@ bool idEFXFile::ReadEffect( idLexer &src, idSoundEffect *effect ) { return false; } + ALenum err; + alGetError(); + EFXprintf("Loading EFX effect '%s' (#%u)\n", name.c_str(), effect->effect); + do { if ( !src.ReadToken( &token ) ) { src.Error( "idEFXFile::ReadEffect: EOF without closing brace" ); @@ -147,72 +192,59 @@ bool idEFXFile::ReadEffect( idLexer &src, idSoundEffect *effect ) { break; } - ALuint e = effect->effect; - - // mappings taken from - // http://repo.or.cz/w/dsound-openal.git/blob/HEAD:/primary.c#l1795 - // which are marked with a FIXME, so this is maybe not 100% correct if ( token == "environment" ) { // <+KittyCat> the "environment" token should be ignored (efx has nothing equatable to it) src.ParseInt(); } else if ( token == "environment size" ) { float size = src.ParseFloat(); - soundSystemLocal.alEffectf(e, AL_EAXREVERB_DENSITY, ((size < 2.0f) ? (size - 1.0f) : 1.0f)); + efxf(AL_EAXREVERB_DENSITY, (size < 2.0f) ? (size - 1.0f) : 1.0f); } else if ( token == "environment diffusion" ) { - soundSystemLocal.alEffectf(e, AL_EAXREVERB_DIFFUSION, src.ParseFloat()); + efxf(AL_EAXREVERB_DIFFUSION, src.ParseFloat()); } else if ( token == "room" ) { - soundSystemLocal.alEffectf(e, AL_EAXREVERB_GAIN, mB_to_gain(src.ParseInt())); + efxf(AL_EAXREVERB_GAIN, mB_to_gain(src.ParseInt())); } else if ( token == "room hf" ) { - soundSystemLocal.alEffectf(e, AL_EAXREVERB_GAINHF, mB_to_gain(src.ParseInt())); + efxf(AL_EAXREVERB_GAINHF, mB_to_gain(src.ParseInt())); } else if ( token == "room lf" ) { - soundSystemLocal.alEffectf(e, AL_EAXREVERB_GAINLF, mB_to_gain(src.ParseInt())); + efxf(AL_EAXREVERB_GAINLF, mB_to_gain(src.ParseInt())); } else if ( token == "decay time" ) { - soundSystemLocal.alEffectf(e, AL_EAXREVERB_DECAY_TIME, src.ParseFloat()); + efxf(AL_EAXREVERB_DECAY_TIME, src.ParseFloat()); } else if ( token == "decay hf ratio" ) { - soundSystemLocal.alEffectf(e, AL_EAXREVERB_DECAY_HFRATIO, src.ParseFloat()); + efxf(AL_EAXREVERB_DECAY_HFRATIO, src.ParseFloat()); } else if ( token == "decay lf ratio" ) { - soundSystemLocal.alEffectf(e, AL_EAXREVERB_DECAY_LFRATIO, src.ParseFloat()); + efxf(AL_EAXREVERB_DECAY_LFRATIO, src.ParseFloat()); } else if ( token == "reflections" ) { - soundSystemLocal.alEffectf(e, AL_EAXREVERB_REFLECTIONS_GAIN, mB_to_gain(src.ParseInt())); + efxf(AL_EAXREVERB_REFLECTIONS_GAIN, mB_to_gain(src.ParseInt())); } else if ( token == "reflections delay" ) { - soundSystemLocal.alEffectf(e, AL_EAXREVERB_REFLECTIONS_DELAY, src.ParseFloat()); + efxf(AL_EAXREVERB_REFLECTIONS_DELAY, src.ParseFloat()); } else if ( token == "reflections pan" ) { - float fv[3]; - fv[0] = src.ParseFloat(); - fv[1] = src.ParseFloat(); - fv[2] = src.ParseFloat(); - soundSystemLocal.alEffectfv(e, AL_EAXREVERB_REFLECTIONS_PAN, fv); + efxfv(AL_EAXREVERB_REFLECTIONS_PAN, src.ParseFloat(), src.ParseFloat(), src.ParseFloat()); } else if ( token == "reverb" ) { - soundSystemLocal.alEffectf(e, AL_EAXREVERB_LATE_REVERB_GAIN, mB_to_gain(src.ParseInt())); + efxf(AL_EAXREVERB_LATE_REVERB_GAIN, mB_to_gain(src.ParseInt())); } else if ( token == "reverb delay" ) { - soundSystemLocal.alEffectf(e, AL_EAXREVERB_LATE_REVERB_DELAY, src.ParseFloat()); + efxf(AL_EAXREVERB_LATE_REVERB_DELAY, src.ParseFloat()); } else if ( token == "reverb pan" ) { - float fv[3]; - fv[0] = src.ParseFloat(); - fv[1] = src.ParseFloat(); - fv[2] = src.ParseFloat(); - soundSystemLocal.alEffectfv(e, AL_EAXREVERB_LATE_REVERB_PAN, fv); + efxfv(AL_EAXREVERB_LATE_REVERB_PAN, src.ParseFloat(), src.ParseFloat(), src.ParseFloat()); } else if ( token == "echo time" ) { - soundSystemLocal.alEffectf(e, AL_EAXREVERB_ECHO_TIME, src.ParseFloat()); + efxf(AL_EAXREVERB_ECHO_TIME, src.ParseFloat()); } else if ( token == "echo depth" ) { - soundSystemLocal.alEffectf(e, AL_EAXREVERB_ECHO_DEPTH, src.ParseFloat()); + efxf(AL_EAXREVERB_ECHO_DEPTH, src.ParseFloat()); } else if ( token == "modulation time" ) { - soundSystemLocal.alEffectf(e, AL_EAXREVERB_MODULATION_TIME, src.ParseFloat()); + efxf(AL_EAXREVERB_MODULATION_TIME, src.ParseFloat()); } else if ( token == "modulation depth" ) { - soundSystemLocal.alEffectf(e, AL_EAXREVERB_MODULATION_DEPTH, src.ParseFloat()); + efxf(AL_EAXREVERB_MODULATION_DEPTH, src.ParseFloat()); } else if ( token == "air absorption hf" ) { - soundSystemLocal.alEffectf(e, AL_EAXREVERB_AIR_ABSORPTION_GAINHF, mB_to_gain(src.ParseFloat())); + efxf(AL_EAXREVERB_AIR_ABSORPTION_GAINHF, mB_to_gain(src.ParseFloat())); } else if ( token == "hf reference" ) { - soundSystemLocal.alEffectf(e, AL_EAXREVERB_HFREFERENCE, src.ParseFloat()); + efxf(AL_EAXREVERB_HFREFERENCE, src.ParseFloat()); } else if ( token == "lf reference" ) { - soundSystemLocal.alEffectf(e, AL_EAXREVERB_LFREFERENCE, src.ParseFloat()); + efxf(AL_EAXREVERB_LFREFERENCE, src.ParseFloat()); } else if ( token == "room rolloff factor" ) { - soundSystemLocal.alEffectf(e, AL_EAXREVERB_ROOM_ROLLOFF_FACTOR, src.ParseFloat()); + efxf(AL_EAXREVERB_ROOM_ROLLOFF_FACTOR, src.ParseFloat()); } else if ( token == "flags" ) { src.ReadTokenOnLine( &token ); unsigned int flags = token.GetUnsignedLongValue(); - soundSystemLocal.alEffecti(e, AL_EAXREVERB_DECAY_HFLIMIT, (flags & 0x20) ? AL_TRUE : AL_FALSE); + efxi(AL_EAXREVERB_DECAY_HFLIMIT, (flags & 0x20) ? AL_TRUE : AL_FALSE); // the other SCALE flags have no equivalent in efx } else { src.ReadTokenOnLine( &token ); diff --git a/neo/sound/snd_local.h b/neo/sound/snd_local.h index ed9c773a..77f6700e 100644 --- a/neo/sound/snd_local.h +++ b/neo/sound/snd_local.h @@ -732,11 +732,13 @@ public: LPALGENEFFECTS alGenEffects; LPALDELETEEFFECTS alDeleteEffects; + LPALISEFFECT alIsEffect; LPALEFFECTI alEffecti; LPALEFFECTF alEffectf; LPALEFFECTFV alEffectfv; LPALGENAUXILIARYEFFECTSLOTS alGenAuxiliaryEffectSlots; LPALDELETEAUXILIARYEFFECTSLOTS alDeleteAuxiliaryEffectSlots; + LPALISAUXILIARYEFFECTSLOT alIsAuxiliaryEffectSlot; LPALAUXILIARYEFFECTSLOTI alAuxiliaryEffectSloti; idEFXFile EFXDatabase; diff --git a/neo/sound/snd_system.cpp b/neo/sound/snd_system.cpp index 5ffd1c2f..3c69064b 100644 --- a/neo/sound/snd_system.cpp +++ b/neo/sound/snd_system.cpp @@ -345,11 +345,13 @@ void idSoundSystemLocal::Init() { alGenEffects = (LPALGENEFFECTS)alGetProcAddress("alGenEffects"); alDeleteEffects = (LPALDELETEEFFECTS)alGetProcAddress("alDeleteEffects"); + alIsEffect = (LPALISEFFECT)alGetProcAddress("alIsEffect"); alEffecti = (LPALEFFECTI)alGetProcAddress("alEffecti"); alEffectf = (LPALEFFECTF)alGetProcAddress("alEffectf"); alEffectfv = (LPALEFFECTFV)alGetProcAddress("alEffectfv"); alGenAuxiliaryEffectSlots = (LPALGENAUXILIARYEFFECTSLOTS)alGetProcAddress("alGenAuxiliaryEffectSlots"); alDeleteAuxiliaryEffectSlots = (LPALDELETEAUXILIARYEFFECTSLOTS)alGetProcAddress("alDeleteAuxiliaryEffectSlots"); + alIsAuxiliaryEffectSlot = (LPALISAUXILIARYEFFECTSLOT)alGetProcAddress("alIsAuxiliaryEffectSlot");; alAuxiliaryEffectSloti = (LPALAUXILIARYEFFECTSLOTI)alGetProcAddress("alAuxiliaryEffectSloti"); } else { common->Printf( "OpenAL: EFX extension not found\n" ); @@ -358,11 +360,13 @@ void idSoundSystemLocal::Init() { alGenEffects = NULL; alDeleteEffects = NULL; + alIsEffect = NULL; alEffecti = NULL; alEffectf = NULL; alEffectfv = NULL; alGenAuxiliaryEffectSlots = NULL; alDeleteAuxiliaryEffectSlots = NULL; + alIsAuxiliaryEffectSlot = NULL; alAuxiliaryEffectSloti = NULL; } diff --git a/neo/sound/snd_world.cpp b/neo/sound/snd_world.cpp index 35f95a56..deb5dda3 100644 --- a/neo/sound/snd_world.cpp +++ b/neo/sound/snd_world.cpp @@ -49,14 +49,14 @@ void idSoundWorldLocal::Init( idRenderWorld *renderWorld ) { listenerArea = 0; listenerAreaName = "Undefined"; - if (idSoundSystemLocal::useEFXReverb) { + if (idSoundSystemLocal::useEFXReverb && !soundSystemLocal.alIsAuxiliaryEffectSlot(listenerSlot)) { alGetError(); soundSystemLocal.alGenAuxiliaryEffectSlots(1, &listenerSlot); ALuint e = alGetError(); if (e != AL_NO_ERROR) { - common->Warning("idSoundWorldLocal::Init: alGenAuxiliaryEffectSlots failed: %u", e); - listenerSlot = 0; + common->Warning("idSoundWorldLocal::Init: alGenAuxiliaryEffectSlots failed: 0x%x", e); + listenerSlot = AL_EFFECTSLOT_NULL; } } @@ -118,9 +118,10 @@ void idSoundWorldLocal::Shutdown() { AVIClose(); - if (idSoundSystemLocal::useEFXReverb && listenerSlot) { + if (idSoundSystemLocal::useEFXReverb && soundSystemLocal.alIsAuxiliaryEffectSlot(listenerSlot)) { + soundSystemLocal.alAuxiliaryEffectSloti(listenerSlot, AL_EFFECTSLOT_EFFECT, AL_EFFECTSLOT_NULL); soundSystemLocal.alDeleteAuxiliaryEffectSlots(1, &listenerSlot); - listenerSlot = 0; + listenerSlot = AL_EFFECTSLOT_NULL; } for ( i = 0; i < emitters.Num(); i++ ) { @@ -465,23 +466,25 @@ void idSoundWorldLocal::MixLoop( int current44kHz, int numSpeakers, float *final alListenerfv( AL_POSITION, listenerPosition ); alListenerfv( AL_ORIENTATION, listenerOrientation ); - if (idSoundSystemLocal::useEFXReverb) { - if ( soundSystemLocal.efxloaded ) { - ALuint effect; - idStr defaultStr( "default" ); - idStr listenerAreaStr( listenerArea ); + if (idSoundSystemLocal::useEFXReverb && soundSystemLocal.efxloaded) { + ALuint effect = 0; + idStr s(listenerArea); - soundSystemLocal.EFXDatabase.FindEffect( listenerAreaStr, &effect ); - if (!effect) - soundSystemLocal.EFXDatabase.FindEffect( listenerAreaName, &effect ); - if (!effect) - soundSystemLocal.EFXDatabase.FindEffect( defaultStr, &effect ); + bool found = soundSystemLocal.EFXDatabase.FindEffect(s, &effect); + if (!found) { + s = listenerAreaName; + found = soundSystemLocal.EFXDatabase.FindEffect(s, &effect); + } + if (!found) { + s = "default"; + found = soundSystemLocal.EFXDatabase.FindEffect(s, &effect); + } - // only update if change in settings - if ( listenerEffect != effect ) { - listenerEffect = effect; - soundSystemLocal.alAuxiliaryEffectSloti(listenerSlot, AL_EFFECTSLOT_EFFECT, effect); - } + // only update if change in settings + if (found && listenerEffect != effect) { + EFXprintf("Switching to EFX '%s' (#%u)\n", s.c_str(), effect); + listenerEffect = effect; + soundSystemLocal.alAuxiliaryEffectSloti(listenerSlot, AL_EFFECTSLOT_EFFECT, effect); } } @@ -1748,12 +1751,8 @@ void idSoundWorldLocal::AddChannelContribution( idSoundEmitterLocal *sound, idSo #endif alSourcef( chan->openalSource, AL_PITCH, ( slowmoActive && !chan->disallowSlow ) ? ( slowmoSpeed ) : ( 1.0f ) ); - if (idSoundSystemLocal::useEFXReverb) { - if (listenerSlot) - alSource3i(chan->openalSource, AL_AUXILIARY_SEND_FILTER, listenerSlot, 0, AL_FILTER_NULL); - else - alSource3i(chan->openalSource, AL_AUXILIARY_SEND_FILTER, AL_EFFECTSLOT_NULL, 0, AL_FILTER_NULL); - } + if (idSoundSystemLocal::useEFXReverb) + alSource3i(chan->openalSource, AL_AUXILIARY_SEND_FILTER, listenerSlot, 0, AL_FILTER_NULL); #if 0 // TODO how to port this to efx? long lOcclusion = ( enviroSuitActive ? -1150 : 0);