From 3f350c5cb28b179a1a91bbed500a59433ea2bc6f Mon Sep 17 00:00:00 2001 From: Joseph Davies Date: Wed, 15 Oct 2014 13:00:02 -0700 Subject: [PATCH 1/2] Restore EAX effects through OpenAL's EFX. --- Sources/Plasma/Apps/plClient/plClient.cpp | 2 +- .../pfConsole/pfAudioConsoleCommands.cpp | 2 +- .../FeatureLib/pfPython/pyAudioControl.cpp | 2 +- .../pfPython/pyAudioControlGlue.cpp | 6 +- .../Plasma/PubUtilLib/plAudio/CMakeLists.txt | 3 + .../PubUtilLib/plAudio/plAudioSystem.cpp | 16 +- .../plAudio/plAudioSystem_Private.h | 3 - .../PubUtilLib/plAudio/plDSoundBuffer.cpp | 4 +- .../PubUtilLib/plAudio/plDSoundBuffer.h | 8 +- .../PubUtilLib/plAudio/plEAXEffects.cpp | 292 ++++++------------ .../Plasma/PubUtilLib/plAudio/plEAXEffects.h | 114 +++---- .../PubUtilLib/plAudio/plEAXListenerMod.cpp | 227 +++++++++----- .../PubUtilLib/plAudio/plEAXListenerMod.h | 22 +- .../PubUtilLib/plAudio/plEAXStructures.h | 2 + .../Tools/MaxComponent/plAudioComponents.cpp | 139 ++++++--- 15 files changed, 435 insertions(+), 407 deletions(-) diff --git a/Sources/Plasma/Apps/plClient/plClient.cpp b/Sources/Plasma/Apps/plClient/plClient.cpp index 140ec6f493..9141e37b26 100644 --- a/Sources/Plasma/Apps/plClient/plClient.cpp +++ b/Sources/Plasma/Apps/plClient/plClient.cpp @@ -2078,7 +2078,7 @@ void plClient::IDetectAudioVideoSettings() } else { stream = plEncryptedStream::OpenEncryptedFileWrite(audioIniFile); WriteBool(stream, "Audio.Initialize", true); - WriteBool(stream, "Audio.UseEAX", false); + WriteBool(stream, "Audio.UseEAX", true); WriteInt(stream, "Audio.SetPriorityCutoff", 6); WriteInt(stream, "Audio.MuteAll", false); WriteInt(stream, "Audio.SetChannelVolume SoundFX", 1); diff --git a/Sources/Plasma/FeatureLib/pfConsole/pfAudioConsoleCommands.cpp b/Sources/Plasma/FeatureLib/pfConsole/pfAudioConsoleCommands.cpp index 92ad6e13ae..777517e8b9 100644 --- a/Sources/Plasma/FeatureLib/pfConsole/pfAudioConsoleCommands.cpp +++ b/Sources/Plasma/FeatureLib/pfConsole/pfAudioConsoleCommands.cpp @@ -97,7 +97,7 @@ PF_CONSOLE_CMD(Audio, Enable, "bool on", "Switch Audio on or off at runtime") plgAudioSys::Activate( on ); } -PF_CONSOLE_CMD(Audio, UseEAX, "bool on", "Enable EAX sound acceleration (requires hardware acceleration)") +PF_CONSOLE_CMD(Audio, UseEAX, "bool on", "Enable EFX environmental sound") { bool on = params[0]; plgAudioSys::EnableEAX( on ); diff --git a/Sources/Plasma/FeatureLib/pfPython/pyAudioControl.cpp b/Sources/Plasma/FeatureLib/pfPython/pyAudioControl.cpp index 3c9c4768af..76af600a35 100644 --- a/Sources/Plasma/FeatureLib/pfPython/pyAudioControl.cpp +++ b/Sources/Plasma/FeatureLib/pfPython/pyAudioControl.cpp @@ -213,7 +213,7 @@ void pyAudioControl::SetTwoStageLOD(bool state) plSound::SetLoadFromDiskOnDemand(!state); } -// Enable EAX sound acceleration (requires hardware acceleration) +// Enable EFX environmental sound void pyAudioControl::UseEAXAcceleration(bool state) { plgAudioSys::EnableEAX(state); diff --git a/Sources/Plasma/FeatureLib/pfPython/pyAudioControlGlue.cpp b/Sources/Plasma/FeatureLib/pfPython/pyAudioControlGlue.cpp index 51bbdaa493..0994ac9844 100644 --- a/Sources/Plasma/FeatureLib/pfPython/pyAudioControlGlue.cpp +++ b/Sources/Plasma/FeatureLib/pfPython/pyAudioControlGlue.cpp @@ -401,9 +401,9 @@ PYTHON_START_METHODS_TABLE(ptAudioControl) PYTHON_METHOD(ptAudioControl, setLoadOnDemand, "Params: state\nEnables or disables the load on demand for sounds."), PYTHON_METHOD(ptAudioControl, setTwoStageLOD, "Params: state\nEnables or disables two-stage LOD, where sounds can be loaded into RAM but not into sound buffers.\n" "...Less of a performance hit, harder on memory."), - PYTHON_METHOD(ptAudioControl, useEAXAcceleration, "Params: state\nEnables or disables EAX sound acceleration (requires hardware acceleration)."), - PYTHON_METHOD_NOARGS(ptAudioControl, isUsingEAXAcceleration, "Is EAX sound acceleration enabled? Returns 1 if true otherwise returns 0."), - PYTHON_METHOD_NOARGS(ptAudioControl, isEAXSupported, "Is EAX acceleration supported by the current device?"), + PYTHON_METHOD(ptAudioControl, useEAXAcceleration, "Params: state\nEnables or disables EFX environmental sound."), + PYTHON_METHOD_NOARGS(ptAudioControl, isUsingEAXAcceleration, "Is EFX environmental sound enabled? Returns 1 if true otherwise returns 0."), + PYTHON_METHOD_NOARGS(ptAudioControl, isEAXSupported, "Is EFX environmental sound supported by the current device?"), PYTHON_BASIC_METHOD(ptAudioControl, muteAll, "Mutes all sounds."), PYTHON_BASIC_METHOD(ptAudioControl, unmuteAll, "Unmutes all sounds."), PYTHON_METHOD_NOARGS(ptAudioControl, isMuted, "Are all sounds muted? Returns 1 if true otherwise returns 0."), diff --git a/Sources/Plasma/PubUtilLib/plAudio/CMakeLists.txt b/Sources/Plasma/PubUtilLib/plAudio/CMakeLists.txt index 4627a404e9..30b427a3ce 100644 --- a/Sources/Plasma/PubUtilLib/plAudio/CMakeLists.txt +++ b/Sources/Plasma/PubUtilLib/plAudio/CMakeLists.txt @@ -67,5 +67,8 @@ target_link_libraries(plAudio pnFactory ) +target_compile_definitions(plAudio + PRIVATE AL_ALEXT_PROTOTYPES) + source_group("Source Files" FILES ${plAudio_SOURCES}) source_group("Header Files" FILES ${plAudio_HEADERS}) diff --git a/Sources/Plasma/PubUtilLib/plAudio/plAudioSystem.cpp b/Sources/Plasma/PubUtilLib/plAudio/plAudioSystem.cpp index ffe6fe4e2d..dcd7ea95e3 100644 --- a/Sources/Plasma/PubUtilLib/plAudio/plAudioSystem.cpp +++ b/Sources/Plasma/PubUtilLib/plAudio/plAudioSystem.cpp @@ -42,9 +42,6 @@ You can contact Cyan Worlds, Inc. by email legal@cyan.com #include "HeadSpin.h" #include #include -#ifdef EAX_SDK_AVAILABLE -#include -#endif #include #include @@ -74,7 +71,7 @@ You can contact Cyan Worlds, Inc. by email legal@cyan.com ST::string kDefaultDeviceMagic = ST_LITERAL("(Default Device)"); #define FADE_TIME 3 -#define MAX_NUM_SOURCES 128 +#define MAX_NUM_SOURCES 256 #define UPDATE_TIME_MS 100 plProfile_CreateTimer("EAX Update", "Sound", SoundEAXUpdate); @@ -304,6 +301,7 @@ bool plAudioSystem::Init() plStatusLog::AddLineSF("audio.log", "OpenAL version: {}", alGetString(AL_VERSION)); plStatusLog::AddLineSF("audio.log", "OpenAL renderer: {}", alGetString(AL_RENDERER)); plStatusLog::AddLineSF("audio.log", "OpenAL extensions: {}", alGetString(AL_EXTENSIONS)); + plStatusLog::AddLineSF("audio.log", "OpenAL context extensions: {}", alcGetString(fPlaybackDevice, ALC_EXTENSIONS)); plStatusLog::AddLineS("audio.log", plStatusLog::kGreen, "ASYS: Detecting caps..."); // Detect maximum number of voices that can be created. @@ -323,15 +321,15 @@ bool plAudioSystem::Init() plStatusLog::AddLineSF("audio.log", "Max Number of sources: {}", fMaxNumSources); SetMaxNumberOfActiveSounds(); - // TODO: Detect EAX support. Not adding this in now until the replacement is implemented. + // TODO: Detect EFX support. - // attempt to init the EAX listener. + // attempt to init the EFX listener. if (plgAudioSys::fEnableEAX) { - fUsingEAX = plEAXListener::GetInstance().Init(); + fUsingEAX = plEAXListener::GetInstance().Init(fPlaybackDevice); if (fUsingEAX) - plStatusLog::AddLineS("audio.log", plStatusLog::kGreen, "ASYS: EAX support detected and enabled."); + plStatusLog::AddLineS("audio.log", plStatusLog::kGreen, "ASYS: EFX support detected and enabled."); else - plStatusLog::AddLineS("audio.log", plStatusLog::kRed, "ASYS: EAX support NOT detected. EAX effects disabled."); + plStatusLog::AddLineS("audio.log", plStatusLog::kRed, "ASYS: EFX support NOT detected. EAX effects disabled."); } else { fUsingEAX = false; } diff --git a/Sources/Plasma/PubUtilLib/plAudio/plAudioSystem_Private.h b/Sources/Plasma/PubUtilLib/plAudio/plAudioSystem_Private.h index e10c426e6a..adf19667da 100644 --- a/Sources/Plasma/PubUtilLib/plAudio/plAudioSystem_Private.h +++ b/Sources/Plasma/PubUtilLib/plAudio/plAudioSystem_Private.h @@ -47,9 +47,6 @@ You can contact Cyan Worlds, Inc. by email legal@cyan.com #include #include #include -#ifdef EAX_SDK_AVAILABLE -#include -#endif #include #include diff --git a/Sources/Plasma/PubUtilLib/plAudio/plDSoundBuffer.cpp b/Sources/Plasma/PubUtilLib/plAudio/plDSoundBuffer.cpp index df75310dde..9537ed0c34 100644 --- a/Sources/Plasma/PubUtilLib/plAudio/plDSoundBuffer.cpp +++ b/Sources/Plasma/PubUtilLib/plAudio/plDSoundBuffer.cpp @@ -50,7 +50,6 @@ You can contact Cyan Worlds, Inc. by email legal@cyan.com #include "HeadSpin.h" #include "hsThread.h" #include "plDSoundBuffer.h" -#include #include "plgDispatch.h" #include "plAudioSystem.h" @@ -59,9 +58,10 @@ You can contact Cyan Worlds, Inc. by email legal@cyan.com #include "plEAXEffects.h" #include "plProfile.h" - #include "plStatusLog/plStatusLog.h" +#include + uint32_t plDSoundBuffer::fNumBuffers = 0; plProfile_CreateCounterNoReset( "Playing", "Sound", SoundPlaying ); plProfile_CreateCounterNoReset( "Allocated", "Sound", NumAllocated ); diff --git a/Sources/Plasma/PubUtilLib/plAudio/plDSoundBuffer.h b/Sources/Plasma/PubUtilLib/plAudio/plDSoundBuffer.h index d409a9a409..1969d7fccf 100644 --- a/Sources/Plasma/PubUtilLib/plAudio/plDSoundBuffer.h +++ b/Sources/Plasma/PubUtilLib/plAudio/plDSoundBuffer.h @@ -39,6 +39,7 @@ You can contact Cyan Worlds, Inc. by email legal@cyan.com Mead, WA 99021 *==LICENSE==*/ + ////////////////////////////////////////////////////////////////////////////// // // // plDSoundBuffer - Simple wrapper class for a DirectSound buffer. // @@ -56,15 +57,12 @@ You can contact Cyan Worlds, Inc. by email legal@cyan.com #define STREAMING_BUFFERS 16 #define STREAM_BUFFER_SIZE 4608*4 -//#define VOICE_BUFFERS 4 -//#define VOICE_BUFFER_SIZE 4608 - class plWAVHeader; class plAudioFileReader; -// Ported to OpenAL from DirectSound May 2006. Idealy the openal sources would be seperate from this class. -// OpenAl sound buffer, and source. +// Ported to OpenAL from DirectSound May 2006. Ideally the OpenAL sources would be separate from this class. +// OpenAL sound buffer, and source. class plDSoundBuffer { public: diff --git a/Sources/Plasma/PubUtilLib/plAudio/plEAXEffects.cpp b/Sources/Plasma/PubUtilLib/plAudio/plEAXEffects.cpp index 11cbaca6c5..a1cacb91b6 100644 --- a/Sources/Plasma/PubUtilLib/plAudio/plEAXEffects.cpp +++ b/Sources/Plasma/PubUtilLib/plAudio/plEAXEffects.cpp @@ -39,9 +39,10 @@ You can contact Cyan Worlds, Inc. by email legal@cyan.com Mead, WA 99021 *==LICENSE==*/ + ////////////////////////////////////////////////////////////////////////////// // // -// plEAXEffects - Various classes and wrappers to support EAX // +// plEAXEffects - Various classes and wrappers to support EAX/EFX // // acceleration. // // // ////////////////////////////////////////////////////////////////////////////// @@ -50,60 +51,33 @@ You can contact Cyan Worlds, Inc. by email legal@cyan.com #include "hsWindows.h" #include "hsThread.h" -#ifndef EAX_SDK_AVAILABLE -# include "plEAXStructures.h" -#endif - #include "plEAXEffects.h" +#include "plEAXStructures.h" #include "plAudioCore/plAudioCore.h" #include "plDSoundBuffer.h" #include "plEAXListenerMod.h" #include "hsStream.h" #include "plAudioSystem.h" -#include - -#ifdef EAX_SDK_AVAILABLE -#include -#include -#include -#endif -#include "plStatusLog/plStatusLog.h" -#define DebugLog if (myLog) myLog->AddLine +#include -#ifdef EAX_SDK_AVAILABLE -static EAXGet s_EAXGet; -static EAXSet s_EAXSet; -#endif +#include "plStatusLog/plStatusLog.h" +#define DebugLog if (myLog) myLog->AddLineF //// GetInstance ///////////////////////////////////////////////////////////// -plEAXListener &plEAXListener::GetInstance() +plEAXListener &plEAXListener::GetInstance() { static plEAXListener instance; return instance; } -//// Constructor/Destructor ////////////////////////////////////////////////// - -plEAXListener::plEAXListener() -{ - fInited = false; - ClearProcessCache(); -} - -plEAXListener::~plEAXListener() -{ - Shutdown(); -} - //// Init //////////////////////////////////////////////////////////////////// -bool plEAXListener::Init() +bool plEAXListener::Init(ALCdevice *alDevice) { -#ifdef EAX_SDK_AVAILABLE - if( fInited ) + if(fInited) return true; if(!alIsExtensionPresent((ALchar *)"EAX4.0")) // is eax 4 supported @@ -117,33 +91,27 @@ bool plEAXListener::Init() { plStatusLog::AddLineS("audio.log", "EAX 4 Emulated supported"); } + } else { + ALCint iVerMajor, iVerMinor; + alcGetIntegerv(alDevice, ALC_EFX_MAJOR_VERSION, 1, &iVerMajor); + alcGetIntegerv(alDevice, ALC_EFX_MAJOR_VERSION, 1, &iVerMinor); + + plStatusLog::AddLineSF("audio.log", "EFX v{}.{} available.", iVerMajor, iVerMinor); } - else - { - plStatusLog::AddLineS("audio.log", "EAX 4 available"); - } - + // EAX is supported - s_EAXGet = (EAXGet)alGetProcAddress((ALchar *)"EAXGet"); - s_EAXSet = (EAXSet)alGetProcAddress((ALchar *)"EAXSet"); - if(!s_EAXGet || ! s_EAXSet) - { - IFail( "EAX initialization failed", true ); - return false; - } fInited = true; -#if 1 try { // Make an EAX call here to prevent problems on WDM driver unsigned int lRoom = -10000; - SetGlobalEAXProperty(DSPROPSETID_EAX_ListenerProperties, DSPROPERTY_EAXLISTENER_ROOM, &lRoom, sizeof( unsigned int )); + //SetGlobalEAXProperty(DSPROPSETID_EAX_ListenerProperties, DSPROPERTY_EAXLISTENER_ROOM, &lRoom, sizeof( unsigned int )); } catch (std::exception &e) { - plStatusLog::AddLineS("audio.log", "Unable to set EAX Property Set ({}), disabling EAX...", e.what()); + plStatusLog::AddLineSF("audio.log", "Unable to set EAX Property Set ({}), disabling EAX...", e.what()); plgAudioSys::EnableEAX(false); return false; } @@ -153,39 +121,27 @@ bool plEAXListener::Init() plgAudioSys::EnableEAX(false); return false; } -#endif ClearProcessCache(); return true; -#else /* !EAX_SDK_AVAILABLE */ - plStatusLog::AddLineS("audio.log", "EAX disabled in this build"); - return false; -#endif } //// Shutdown //////////////////////////////////////////////////////////////// -void plEAXListener::Shutdown() +void plEAXListener::Shutdown() { - if( !fInited ) + if(!fInited) return; -#ifdef EAX_SDK_AVAILABLE - s_EAXSet = nullptr; - s_EAXGet = nullptr; -#endif IRelease(); } - - +/* bool plEAXListener::SetGlobalEAXProperty(GUID guid, unsigned long ulProperty, void *pData, unsigned long ulDataSize ) { if(fInited) { -#ifdef EAX_SDK_AVAILABLE return s_EAXSet(&guid, ulProperty, 0, pData, ulDataSize) == AL_NO_ERROR; -#endif } return false; } @@ -194,56 +150,48 @@ bool plEAXListener::GetGlobalEAXProperty(GUID guid, unsigned long ulProperty, vo { if(fInited) { -#ifdef EAX_SDK_AVAILABLE return s_EAXGet(&guid, ulProperty, 0, pData, ulDataSize) == AL_NO_ERROR; -#endif } return false; } bool plEAXSource::SetSourceEAXProperty(unsigned source, GUID guid, unsigned long ulProperty, void *pData, unsigned long ulDataSize) { -#ifdef EAX_SDK_AVAILABLE return s_EAXSet(&guid, ulProperty, source, pData, ulDataSize) == AL_NO_ERROR; -#else return false; -#endif } bool plEAXSource::GetSourceEAXProperty(unsigned source, GUID guid, unsigned long ulProperty, void *pData, unsigned long ulDataSize) { -#ifdef EAX_SDK_AVAILABLE return s_EAXGet(&guid, ulProperty, source, pData, ulDataSize) == AL_NO_ERROR; -#else return false; -#endif -} +}*/ //// IRelease //////////////////////////////////////////////////////////////// -void plEAXListener::IRelease() +void plEAXListener::IRelease() { fInited = false; } //// IFail /////////////////////////////////////////////////////////////////// -void plEAXListener::IFail( bool major ) +void plEAXListener::IFail(bool fatal) { - plStatusLog::AddLineS( "audio.log", plStatusLog::kRed, - "ERROR in plEAXListener: Could not set global eax params"); + plStatusLog::AddLineS("audio.log", plStatusLog::kRed, + "ERROR in plEAXListener: Could not set global eax params"); - if( major ) + if(fatal) IRelease(); } -void plEAXListener::IFail( const char *msg, bool major ) +void plEAXListener::IFail(const char *msg, bool fatal) { - plStatusLog::AddLineSF( "audio.log", plStatusLog::kRed, - "ERROR in plEAXListener: {}", msg ); + plStatusLog::AddLineSF("audio.log", plStatusLog::kRed, + "ERROR in plEAXListener: {}", msg); - if( major ) + if(fatal) IRelease(); } @@ -251,7 +199,7 @@ void plEAXListener::IFail( const char *msg, bool major ) // Mutes the given properties, so if you have some props that you want // half strength, this function will do it for ya. -void plEAXListener::IMuteProperties( EAXREVERBPROPERTIES *props, float percent ) +void plEAXListener::IMuteProperties(EFXEAXREVERBPROPERTIES *props, float percent) { // We only mute the room, roomHF and roomLF, since those control the overall effect // application. All three are a direct linear blend as defined by eax-util.cpp, so @@ -259,22 +207,16 @@ void plEAXListener::IMuteProperties( EAXREVERBPROPERTIES *props, float percen float invPercent = 1.f - percent; - // The old way, as dictated by EAX sample code... -#ifdef EAX_SDK_AVAILABLE - props->lRoom = (int)( ( (float)EAXLISTENER_MINROOM * invPercent ) + ( (float)props->lRoom * percent ) ); -#endif - // The new way, as suggested by EAX guys... -// props->lRoom = (int)( 2000.f * log( invPercent ) ) + props->lRoom; - -// props->lRoomLF = (int)( ( (float)EAXLISTENER_MINROOMLF * invPercent ) + ( (float)props->lRoomLF * percent ) ); -// props->lRoomHF = (int)( ( (float)EAXLISTENER_MINROOMHF * invPercent ) + ( (float)props->lRoomHF * percent ) ); + props->flGain = (int)(2000.f * log(invPercent)) + props->flGain; + props->flGainLF = (int)(((float)AL_EAXREVERB_MIN_GAINLF * invPercent) + ((float)props->flGainLF * percent)); + props->flGainHF = (int)(((float)AL_EAXREVERB_MIN_GAINHF * invPercent) + ((float)props->flGainHF * percent)); } //// ClearProcessCache /////////////////////////////////////////////////////// // Clears the cache settings used to speed up ProcessMods(). Call whenever // the list of mods changed. -void plEAXListener::ClearProcessCache() +void plEAXListener::ClearProcessCache() { fLastBigRegion = nullptr; fLastModCount = -1; @@ -287,21 +229,18 @@ void plEAXListener::ClearProcessCache() // to a region iff it's the only region from the last pass that had a // strength > 0. The reason we can't do our trick before is because even if // we have a region w/ strength 1, another region might power up from 1 and -// thus suddenly alter the total reverb settings. Thus, the only time we +// thus suddenly alter the total reverb settings. Thus, the only time we // can wisely skip is if our current big region == fLastBigRegion *and* // the total strength is the same. -void plEAXListener::ProcessMods(const std::set& modArray ) +void plEAXListener::ProcessMods(const std::set& modArray) { -#ifdef EAX_SDK_AVAILABLE - int i; float totalStrength; bool firstOne; plEAXListenerMod *thisBigRegion = nullptr; - EAXLISTENERPROPERTIES finalProps; - static int oldTime = timeGetTime(); // Get starting time - int newTime; + EFXEAXREVERBPROPERTIES finalProps; + static auto oldTime = std::chrono::steady_clock::now(); // Get starting time bool bMorphing = false; static plStatusLog *myLog = nullptr; @@ -317,20 +256,16 @@ void plEAXListener::ProcessMods(const std::set& modArray ) if (myLog != nullptr) myLog->Clear(); - if( modArray.size() != fLastModCount ) + if(modArray.size() != fLastModCount) { - DebugLog( "Clearing cache..." ); + DebugLog("Clearing cache..."); ClearProcessCache(); // Code path changed, clear the entire cache fLastModCount = modArray.size(); } - else - { - DebugLog( "" ); - } if( modArray.size() > 0 ) { - DebugLog( "{} regions to calc", modArray.size() ); + DebugLog("{} regions to calc", modArray.size()); // Reset and find a new one if applicable thisBigRegion = nullptr; @@ -341,7 +276,7 @@ void plEAXListener::ProcessMods(const std::set& modArray ) for (auto mod : modArray) { float strength = mod->GetStrength(); - DebugLog( "{4.2f} - {}", strength, mod->GetKey()->GetUoid().GetObjectName() ); + DebugLog("{4.2f} - {}", strength, mod->GetKey()->GetUoid().GetObjectName()); if( strength > 0.f ) { // fLastBigRegion will point to a region iff it's the only region w/ strength > 0 @@ -353,18 +288,18 @@ void plEAXListener::ProcessMods(const std::set& modArray ) if( firstOne ) { // First one, just init to it - memcpy( &finalProps, mod->GetListenerProps(), sizeof( finalProps ) ); + memcpy(&finalProps, mod->GetListenerProps(), sizeof(finalProps)); totalStrength = strength; firstOne = false; } else { float scale = strength / ( totalStrength + strength ); - EAX3ListenerInterpolate( &finalProps, mod->GetListenerProps(), scale, &finalProps, false ); + //EAX3ListenerInterpolate( &finalProps, mod->GetListenerProps(), scale, &finalProps, false ); totalStrength += strength; bMorphing = true; } - + if( totalStrength >= 1.f ) break; } @@ -377,15 +312,16 @@ void plEAXListener::ProcessMods(const std::set& modArray ) if( fLastWasEmpty ) return; - memcpy( &finalProps, &EAX30_ORIGINAL_PRESETS[ ORIGINAL_GENERIC ], sizeof( EAXLISTENERPROPERTIES ) ); - finalProps.lRoom = EAXLISTENER_MINROOM; -// finalProps.lRoomLF = EAXLISTENER_MINROOMLF; -// finalProps.lRoomHF = EAXLISTENER_MINROOMHF; + //memcpy( &finalProps, &EAX30_ORIGINAL_PRESETS[ ORIGINAL_GENERIC ], sizeof( EAXLISTENERPROPERTIES ) ); + finalProps = EFX_REVERB_PRESET_GENERIC; + finalProps.flGain = AL_EAXREVERB_MIN_GAIN; + finalProps.flGainLF = AL_EAXREVERB_MIN_GAINLF; + finalProps.flGainHF = AL_EAXREVERB_MIN_GAINHF; fLastWasEmpty = true; fLastBigRegion = nullptr; fLastSingleStrength = -1.f; } - else + else { fLastWasEmpty = false; @@ -411,33 +347,32 @@ void plEAXListener::ProcessMods(const std::set& modArray ) if( fLastWasEmpty ) return; - memcpy( &finalProps, &EAX30_ORIGINAL_PRESETS[ ORIGINAL_GENERIC ], sizeof( EAXLISTENERPROPERTIES ) ); - finalProps.lRoom = EAXLISTENER_MINROOM; -// finalProps.lRoomLF = EAXLISTENER_MINROOMLF; -// finalProps.lRoomHF = EAXLISTENER_MINROOMHF; + finalProps = EFX_REVERB_PRESET_GENERIC; + finalProps.flGain = AL_EAXREVERB_MIN_GAIN; + finalProps.flGainLF = AL_EAXREVERB_MIN_GAINLF; + finalProps.flGainHF = AL_EAXREVERB_MIN_GAINHF; fLastWasEmpty = true; } - // if were morphing between regions, do 10th of a second check, otherwise just let it + // if were morphing between regions, do 10th of a second check, otherwise just let it // change due to opt out(caching) feature. if(bMorphing) { - newTime = timeGetTime(); + auto newTime = std::chrono::steady_clock::now(); // Update, at most, ten times per second - if((newTime - oldTime) < 100) return; - + if((newTime - oldTime) < std::chrono::duration(100)) + return; + oldTime = newTime; // update time } -//finalProps.flAirAbsorptionHF *= 0.3048f; // Convert to feet - //DebugLog( "** Updating property set **" ); + finalProps.flAirAbsorptionGainHF *= 0.3048f; // Convert to feet - if(!SetGlobalEAXProperty(DSPROPSETID_EAX_ListenerProperties, DSPROPERTY_EAXLISTENER_ALLPARAMETERS, &finalProps, sizeof( finalProps ))) - { + //if(!SetGlobalEAXProperty(DSPROPSETID_EAX_ListenerProperties, DSPROPERTY_EAXLISTENER_ALLPARAMETERS, &finalProps, sizeof( finalProps ))) + //{ IFail( false ); - } -#endif /* EAX_SDK_AVAILABLE */ + //} } @@ -445,21 +380,10 @@ void plEAXListener::ProcessMods(const std::set& modArray ) //// Source Settings ///////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////// -//// Constructor/Destructor ////////////////////////////////////////////////// - -plEAXSourceSettings::plEAXSourceSettings() -{ - fDirtyParams = kAll; - Enable( false ); -} - -plEAXSourceSettings::~plEAXSourceSettings() -{ -} //// Read/Write/Set ////////////////////////////////////////////////////////// -void plEAXSourceSettings::Read( hsStream *s ) +void plEAXSourceSettings::Read( hsStream *s ) { fEnabled = s->ReadBool(); if( fEnabled ) @@ -470,7 +394,7 @@ void plEAXSourceSettings::Read( hsStream *s ) fRoomHFAuto = s->ReadBool(); fOutsideVolHF = s->ReadLE16(); - + fAirAbsorptionFactor = s->ReadLEFloat(); fRoomRolloffFactor = s->ReadLEFloat(); fDopplerFactor = s->ReadLEFloat(); @@ -499,7 +423,7 @@ void plEAXSourceSettings::Write( hsStream *s ) s->WriteBool( fRoomHFAuto ); s->WriteLE16( fOutsideVolHF ); - + s->WriteLEFloat( fAirAbsorptionFactor ); s->WriteLEFloat( fRoomRolloffFactor ); s->WriteLEFloat( fDopplerFactor ); @@ -526,13 +450,8 @@ void plEAXSourceSettings::Enable( bool e ) fEnabled = e; if( !e ) { -#ifdef EAX_SDK_AVAILABLE - fRoom = EAXBUFFER_MINROOM; - fRoomHF = EAXBUFFER_MINROOMHF; -#else fRoom = 0; fRoomHF = 0; -#endif fRoomAuto = true; fRoomHFAuto = true; @@ -585,7 +504,7 @@ void plEAXSourceSettings::IRecalcSofts( uint8_t whichOnes ) percent = fOcclusionSoftValue; invPercent = 1.f - percent; - int16_t occ = (int16_t)( ( (float)fSoftStarts.GetOcclusion() * invPercent ) + ( (float)fSoftEnds.GetOcclusion() * percent ) ); + int16_t occ = (int16_t)( ( (float)fSoftStarts.GetOcclusion() * invPercent ) + ( (float)fSoftEnds.GetOcclusion() * percent ) ); float lfRatio = (float)( ( fSoftStarts.GetOcclusionLFRatio() * invPercent ) + ( fSoftEnds.GetOcclusionLFRatio() * percent ) ); float roomRatio = (float)( ( fSoftStarts.GetOcclusionRoomRatio() * invPercent ) + ( fSoftEnds.GetOcclusionRoomRatio() * percent ) ); float directRatio = (float)( ( fSoftStarts.GetOcclusionDirectRatio() * invPercent ) + ( fSoftEnds.GetOcclusionDirectRatio() * percent ) ); @@ -631,18 +550,7 @@ void plEAXSourceSoftSettings::SetOcclusion( int16_t occ, float lfRatio, float fOcclusionDirectRatio = directRatio; } -//// Constructor/Destructor ////////////////////////////////////////////////// -plEAXSource::plEAXSource() -{ - fInit = false; - -} - -plEAXSource::~plEAXSource() -{ - Release(); -} //// Init/Release //////////////////////////////////////////////////////////// @@ -666,55 +574,53 @@ bool plEAXSource::IsValid() const //// SetFrom ///////////////////////////////////////////////////////////////// -void plEAXSource::SetFrom( plEAXSourceSettings *settings, unsigned source, bool force ) +void plEAXSource::SetFrom(plEAXSourceSettings *settings, unsigned source, bool force) { -#if EAX_SDK_AVAILABLE uint32_t dirtyParams; - if(source == 0 || !fInit) + if(source == 0 || !fInit) return; - if( force ) + if(force) dirtyParams = plEAXSourceSettings::kAll; else dirtyParams = settings->fDirtyParams; - + // Do the params - if( dirtyParams & plEAXSourceSettings::kRoom ) + if (dirtyParams & plEAXSourceSettings::kRoom) { - SetSourceEAXProperty(source, DSPROPSETID_EAX_BufferProperties, DSPROPERTY_EAXBUFFER_ROOM, &settings->fRoom, sizeof(settings->fRoom)); - SetSourceEAXProperty(source, DSPROPSETID_EAX_BufferProperties, DSPROPERTY_EAXBUFFER_ROOMHF, &settings->fRoomHF, sizeof(settings->fRoomHF)); + alSourcef(source, AL_EAXREVERB_GAIN, settings->fRoom); + alSourcef(source, AL_EAXREVERB_GAINHF, settings->fRoomHF); } - if( dirtyParams & plEAXSourceSettings::kOutsideVolHF ) + if(dirtyParams & plEAXSourceSettings::kOutsideVolHF) { - SetSourceEAXProperty(source, DSPROPSETID_EAX_BufferProperties, DSPROPERTY_EAXBUFFER_OUTSIDEVOLUMEHF, &settings->fOutsideVolHF, sizeof(settings->fOutsideVolHF)); + alSourcef(source, AL_CONE_OUTER_GAINHF, settings->fOutsideVolHF); } - - if( dirtyParams & plEAXSourceSettings::kFactors ) + + if (dirtyParams & plEAXSourceSettings::kFactors) { - SetSourceEAXProperty(source, DSPROPSETID_EAX_BufferProperties, DSPROPERTY_EAXBUFFER_DOPPLERFACTOR, &settings->fDopplerFactor, sizeof(settings->fDopplerFactor)); - SetSourceEAXProperty(source, DSPROPSETID_EAX_BufferProperties, DSPROPERTY_EAXBUFFER_ROLLOFFFACTOR, &settings->fRolloffFactor, sizeof(settings->fRolloffFactor)); - SetSourceEAXProperty(source, DSPROPSETID_EAX_BufferProperties, DSPROPERTY_EAXBUFFER_ROOMROLLOFFFACTOR, &settings->fRoomRolloffFactor, sizeof(settings->fRoomRolloffFactor)); - SetSourceEAXProperty(source, DSPROPSETID_EAX_BufferProperties, DSPROPERTY_EAXBUFFER_AIRABSORPTIONFACTOR, &settings->fAirAbsorptionFactor, sizeof(settings->fAirAbsorptionFactor)); + alSourcef(source, AL_DOPPLER_FACTOR, settings->fDopplerFactor); + alSourcef(source, AL_EAXREVERB_ROOM_ROLLOFF_FACTOR, settings->fRoomRolloffFactor); + alSourcef(source, AL_EAXREVERB_AIR_ABSORPTION_GAINHF, settings->fAirAbsorptionFactor); } - if( dirtyParams & plEAXSourceSettings::kOcclusion ) + if(dirtyParams & plEAXSourceSettings::kOcclusion) { - SetSourceEAXProperty(source, DSPROPSETID_EAX_BufferProperties, DSPROPERTY_EAXBUFFER_OCCLUSION, &settings->GetCurrSofts().fOcclusion, sizeof(settings->GetCurrSofts().fOcclusion)); - SetSourceEAXProperty(source, DSPROPSETID_EAX_BufferProperties, DSPROPERTY_EAXBUFFER_OCCLUSIONLFRATIO, &settings->GetCurrSofts().fOcclusionLFRatio, sizeof(settings->GetCurrSofts().fOcclusionLFRatio)); - SetSourceEAXProperty(source, DSPROPSETID_EAX_BufferProperties, DSPROPERTY_EAXBUFFER_OCCLUSIONROOMRATIO, &settings->GetCurrSofts().fOcclusionRoomRatio, sizeof(settings->GetCurrSofts().fOcclusionRoomRatio)); - SetSourceEAXProperty(source, DSPROPSETID_EAX_BufferProperties, DSPROPERTY_EAXBUFFER_OCCLUSIONDIRECTRATIO, &settings->GetCurrSofts().fOcclusionDirectRatio, sizeof(settings->GetCurrSofts().fOcclusionDirectRatio)); + // EFX doesn't support the high-level EAX Occlusion properties, so we'll have to calculate it ourselves. + //alSourcef(source, , settings->); + //SetSourceEAXProperty(source, DSPROPSETID_EAX_BufferProperties, DSPROPERTY_EAXBUFFER_OCCLUSION, &settings->GetCurrSofts().fOcclusion, sizeof(settings->GetCurrSofts().fOcclusion)); + //SetSourceEAXProperty(source, DSPROPSETID_EAX_BufferProperties, DSPROPERTY_EAXBUFFER_OCCLUSIONLFRATIO, &settings->GetCurrSofts().fOcclusionLFRatio, sizeof(settings->GetCurrSofts().fOcclusionLFRatio)); + //SetSourceEAXProperty(source, DSPROPSETID_EAX_BufferProperties, DSPROPERTY_EAXBUFFER_OCCLUSIONROOMRATIO, &settings->GetCurrSofts().fOcclusionRoomRatio, sizeof(settings->GetCurrSofts().fOcclusionRoomRatio)); + //SetSourceEAXProperty(source, DSPROPSETID_EAX_BufferProperties, DSPROPERTY_EAXBUFFER_OCCLUSIONDIRECTRATIO, &settings->GetCurrSofts().fOcclusionDirectRatio, sizeof(settings->GetCurrSofts().fOcclusionDirectRatio)); } -#endif /* EAX_SDK_AVAILABLE */ settings->ClearDirtyParams(); // Do all the flags in one pass -#ifdef EAX_SDK_AVAILABLE DWORD flags; - - if( GetSourceEAXProperty( source, DSPROPSETID_EAX_BufferProperties, DSPROPERTY_EAXBUFFER_FLAGS, &flags, sizeof( DWORD )) ) + /* + if (GetSourceEAXProperty(source, DSPROPSETID_EAX_BufferProperties, DSPROPERTY_EAXBUFFER_FLAGS, &flags, sizeof(DWORD))) { if( settings->GetRoomAuto() ) flags |= EAXBUFFERFLAGS_ROOMAUTO; @@ -726,15 +632,13 @@ void plEAXSource::SetFrom( plEAXSourceSettings *settings, unsigned source, bo else flags &= ~EAXBUFFERFLAGS_ROOMHFAUTO; - if( SetSourceEAXProperty( source, DSPROPSETID_EAX_BufferProperties, DSPROPERTY_EAXBUFFER_FLAGS, &flags, sizeof( DWORD ) ) ) + if( SetSourceEAXProperty( source, DSPROPSETID_EAX_BufferProperties, DSPROPERTY_EAXBUFFER_FLAGS, &flags, sizeof( DWORD ) ) ) { return; // All worked, return here - } - + } + // Flag setting failed somehow - hsAssert( false, "Unable to set EAX buffer flags" ); + hsAssert( false, "Unable to set EFX buffer flags" ); } -#endif /* EAX_SDK_AVAILABLE */ + */ } - - diff --git a/Sources/Plasma/PubUtilLib/plAudio/plEAXEffects.h b/Sources/Plasma/PubUtilLib/plAudio/plEAXEffects.h index 10f5ed0427..70f382bdd2 100644 --- a/Sources/Plasma/PubUtilLib/plAudio/plEAXEffects.h +++ b/Sources/Plasma/PubUtilLib/plAudio/plEAXEffects.h @@ -39,6 +39,7 @@ You can contact Cyan Worlds, Inc. by email legal@cyan.com Mead, WA 99021 *==LICENSE==*/ + ////////////////////////////////////////////////////////////////////////////// // // // plEAXEffects - Various classes and wrappers to support EAX // @@ -49,9 +50,11 @@ You can contact Cyan Worlds, Inc. by email legal@cyan.com #ifndef _plEAXEffects_h #define _plEAXEffects_h +#include +#include +#include #include "HeadSpin.h" -#include //// Listener Settings Class Definition /////////////////////////////////////// @@ -59,48 +62,33 @@ You can contact Cyan Worlds, Inc. by email legal@cyan.com class plDSoundBuffer; class plEAXListenerMod; -#ifdef EAX_SDK_AVAILABLE -typedef struct _EAXREVERBPROPERTIES EAXREVERBPROPERTIES; -#else -#include "plEAXStructures.h" -#endif - -#if HS_BUILD_FOR_WIN32 - typedef struct _GUID GUID; -#else - typedef char* GUID; -#endif - class plEAXListener { public: - ~plEAXListener(); - static plEAXListener &GetInstance(); + ~plEAXListener() { Shutdown(); } + static plEAXListener &GetInstance(); - bool Init(); + bool Init(ALCdevice *alDevice); void Shutdown(); - bool SetGlobalEAXProperty(GUID guid, unsigned long ulProperty, void *pData, unsigned long ulDataSize ); - bool GetGlobalEAXProperty(GUID guid, unsigned long ulProperty, void *pData, unsigned long ulDataSize ); - - void ProcessMods(const std::set& modArray ); + void ProcessMods(const std::set& modArray); void ClearProcessCache(); protected: - plEAXListener(); - void IFail( bool major ); - void IFail( const char *msg, bool major ); + plEAXListener() : fInited() { ClearProcessCache(); } + void IFail(bool fatal); + void IFail(const char *msg, bool fatal); void IRelease(); - void IMuteProperties( EAXREVERBPROPERTIES *props, float percent ); + void IMuteProperties(EFXEAXREVERBPROPERTIES *props, float percent); - bool fInited; + bool fInited; // Cache info - int32_t fLastModCount; - bool fLastWasEmpty; - float fLastSingleStrength; - plEAXListenerMod *fLastBigRegion; + int32_t fLastModCount; + bool fLastWasEmpty; + float fLastSingleStrength; + plEAXListenerMod *fLastBigRegion; }; @@ -112,19 +100,19 @@ class hsStream; class plEAXSourceSoftSettings { public: - int16_t fOcclusion; + int16_t fOcclusion; float fOcclusionLFRatio, fOcclusionRoomRatio, fOcclusionDirectRatio; - void Read( hsStream *s ); - void Write( hsStream *s ); + void Read( hsStream *s ); + void Write( hsStream *s ); - void SetOcclusion( int16_t occ, float lfRatio, float roomRatio, float directRatio ); - int16_t GetOcclusion() const { return fOcclusion; } + void SetOcclusion( int16_t occ, float lfRatio, float roomRatio, float directRatio ); + int16_t GetOcclusion() const { return fOcclusion; } float GetOcclusionLFRatio() const { return fOcclusionLFRatio; } float GetOcclusionRoomRatio() const { return fOcclusionRoomRatio; } float GetOcclusionDirectRatio() const { return fOcclusionDirectRatio; } - void Reset(); + void Reset(); }; //// Buffer Settings Class Definition ///////////////////////////////////////// @@ -134,8 +122,8 @@ class plEAXSource; class plEAXSourceSettings { public: - plEAXSourceSettings(); - virtual ~plEAXSourceSettings(); + plEAXSourceSettings() : fDirtyParams(kAll) { Enable(false); } + virtual ~plEAXSourceSettings() { } void Read( hsStream *s ); void Write( hsStream *s ); @@ -144,42 +132,42 @@ class plEAXSourceSettings bool IsEnabled() const { return fEnabled; } void SetRoomParams( int16_t room, int16_t roomHF, bool roomAuto, bool roomHFAuto ); - int16_t GetRoom() const { return fRoom; } - int16_t GetRoomHF() const { return fRoomHF; } + int16_t GetRoom() const { return fRoom; } + int16_t GetRoomHF() const { return fRoomHF; } bool GetRoomAuto() const { return fRoomAuto; } bool GetRoomHFAuto() const { return fRoomHFAuto; } void SetOutsideVolHF( int16_t vol ); - int16_t GetOutsideVolHF() const { return fOutsideVolHF; } + int16_t GetOutsideVolHF() const { return fOutsideVolHF; } - void SetFactors( float airAbsorption, float roomRolloff, float doppler, float rolloff ); - float GetAirAbsorptionFactor() const { return fAirAbsorptionFactor; } - float GetRoomRolloffFactor() const { return fRoomRolloffFactor; } - float GetDopplerFactor() const { return fDopplerFactor; } - float GetRolloffFactor() const { return fRolloffFactor; } + void SetFactors( float airAbsorption, float roomRolloff, float doppler, float rolloff ); + float GetAirAbsorptionFactor() const { return fAirAbsorptionFactor; } + float GetRoomRolloffFactor() const { return fRoomRolloffFactor; } + float GetDopplerFactor() const { return fDopplerFactor; } + float GetRolloffFactor() const { return fRolloffFactor; } plEAXSourceSoftSettings &GetSoftStarts() { return fSoftStarts; } plEAXSourceSoftSettings &GetSoftEnds() { return fSoftEnds; } plEAXSourceSoftSettings &GetCurrSofts() { return fCurrSoftValues; } - void SetOcclusionSoftValue( float value ); - float GetOcclusionSoftValue() const { return fOcclusionSoftValue; } + void SetOcclusionSoftValue( float value ); + float GetOcclusionSoftValue() const { return fOcclusionSoftValue; } - void ClearDirtyParams() const { fDirtyParams = 0; } + void ClearDirtyParams() const { fDirtyParams = 0; } protected: friend class plEAXSource; friend class plEAXSourceSoftSettings; - bool fEnabled; - int16_t fRoom, fRoomHF; - bool fRoomAuto, fRoomHFAuto; - int16_t fOutsideVolHF; - float fAirAbsorptionFactor, fRoomRolloffFactor, fDopplerFactor, fRolloffFactor; + bool fEnabled; + int16_t fRoom, fRoomHF; + bool fRoomAuto, fRoomHFAuto; + int16_t fOutsideVolHF; + float fAirAbsorptionFactor, fRoomRolloffFactor, fDopplerFactor, fRolloffFactor; + float fOcclusionSoftValue; + mutable uint32_t fDirtyParams; plEAXSourceSoftSettings fSoftStarts, fSoftEnds, fCurrSoftValues; - float fOcclusionSoftValue; - mutable uint32_t fDirtyParams; enum ParamSets { @@ -201,18 +189,16 @@ class plEAXSource friend class plEAXSourceSettings; friend class plEAXSourceSoftSettings; - plEAXSource(); - virtual ~plEAXSource(); + plEAXSource() : fInit(false) {} + virtual ~plEAXSource() { Release(); }; - void Init( plDSoundBuffer *parent ); - void Release(); - bool IsValid() const; - bool SetSourceEAXProperty(unsigned source, GUID guid, unsigned long ulProperty, void *pData, unsigned long ulDataSize); - bool GetSourceEAXProperty(unsigned source, GUID guid, unsigned long ulProperty, void *pData, unsigned long ulDataSize); - void SetFrom( plEAXSourceSettings *settings, unsigned source, bool force = false ); + void Init( plDSoundBuffer *parent ); + void Release(); + bool IsValid() const; + void SetFrom(plEAXSourceSettings *settings, unsigned source, bool force = false); private: - bool fInit; + bool fInit; }; #endif //_plEAXEffects_h diff --git a/Sources/Plasma/PubUtilLib/plAudio/plEAXListenerMod.cpp b/Sources/Plasma/PubUtilLib/plAudio/plEAXListenerMod.cpp index 6cef7f3023..4a3b2b9110 100644 --- a/Sources/Plasma/PubUtilLib/plAudio/plEAXListenerMod.cpp +++ b/Sources/Plasma/PubUtilLib/plAudio/plEAXListenerMod.cpp @@ -39,17 +39,16 @@ You can contact Cyan Worlds, Inc. by email legal@cyan.com Mead, WA 99021 *==LICENSE==*/ + ////////////////////////////////////////////////////////////////////////////// // // // plEAXListenerMod // // // ////////////////////////////////////////////////////////////////////////////// -#ifndef EAX_SDK_AVAILABLE -#include "plEAXStructures.h" -#endif #include "HeadSpin.h" #include "plEAXListenerMod.h" +#include "plEAXStructures.h" #include "plIntersect/plSoftVolume.h" #include "hsResMgr.h" #include "plgDispatch.h" @@ -57,19 +56,14 @@ You can contact Cyan Worlds, Inc. by email legal@cyan.com #include "pnMessage/plAudioSysMsg.h" #include "pnMessage/plRefMsg.h" -#ifdef EAX_SDK_AVAILABLE -#include -#endif +#include plEAXListenerMod::plEAXListenerMod() - : fSoftRegion(), fRegistered(), fGetsMessages() + : fListenerProps(new EFXEAXREVERBPROPERTIES), + fSoftRegion(nullptr), fRegistered(false), fGetsMessages(false) { - fListenerProps = new EAXREVERBPROPERTIES; - -#ifdef EAX_SDK_AVAILABLE - memcpy( fListenerProps, &REVERB_ORIGINAL_PRESETS[ ORIGINAL_GENERIC ], sizeof( EAXREVERBPROPERTIES ) ); -#endif + *fListenerProps = EFX_REVERB_PRESET_GENERIC; } plEAXListenerMod::~plEAXListenerMod() @@ -78,16 +72,15 @@ plEAXListenerMod::~plEAXListenerMod() IUnRegister(); // Unregister for audioSys messages - if( fGetsMessages ) - { - plgDispatch::Dispatch()->UnRegisterForExactType( plAudioSysMsg::Index(), GetKey() ); + if(fGetsMessages) { + plgDispatch::Dispatch()->UnRegisterForExactType(plAudioSysMsg::Index(), GetKey()); fGetsMessages = false; } delete fListenerProps; } -void plEAXListenerMod::IRegister() +void plEAXListenerMod::IRegister() { if( !fGetsMessages ) { @@ -107,7 +100,7 @@ void plEAXListenerMod::IRegister() } } -void plEAXListenerMod::IUnRegister() +void plEAXListenerMod::IUnRegister() { if (!fRegistered || GetKey() == nullptr) return; @@ -163,7 +156,7 @@ bool plEAXListenerMod::MsgReceive( plMessage* pMsg ) return plSingleModifier::MsgReceive( pMsg ); } - + void plEAXListenerMod::Read( hsStream* s, hsResMgr* mgr ) { plSingleModifier::Read( s, mgr ); @@ -171,31 +164,36 @@ void plEAXListenerMod::Read( hsStream* s, hsResMgr* mgr ) // Read in the soft region mgr->ReadKeyNotifyMe( s, new plGenRefMsg( GetKey(), plRefMsg::kOnCreate, 0, kRefSoftRegion ), plRefFlags::kActiveRef ); + EAXREVERBPROPERTIES* eaxListenerProps = new EAXREVERBPROPERTIES; + // Read the listener params - fListenerProps->ulEnvironment = s->ReadLE32(); - fListenerProps->flEnvironmentSize = s->ReadLEFloat(); - fListenerProps->flEnvironmentDiffusion = s->ReadLEFloat(); - fListenerProps->lRoom = s->ReadLE32(); - fListenerProps->lRoomHF = s->ReadLE32(); - fListenerProps->lRoomLF = s->ReadLE32(); - fListenerProps->flDecayTime = s->ReadLEFloat(); - fListenerProps->flDecayHFRatio = s->ReadLEFloat(); - fListenerProps->flDecayLFRatio = s->ReadLEFloat(); - fListenerProps->lReflections = s->ReadLE32(); - fListenerProps->flReflectionsDelay = s->ReadLEFloat(); - //fListenerProps->vReflectionsPan; // early reflections panning vector - fListenerProps->lReverb = s->ReadLE32(); // late reverberation level relative to room effect - fListenerProps->flReverbDelay = s->ReadLEFloat(); - //fListenerProps->vReverbPan; // late reverberation panning vector - fListenerProps->flEchoTime = s->ReadLEFloat(); - fListenerProps->flEchoDepth = s->ReadLEFloat(); - fListenerProps->flModulationTime = s->ReadLEFloat(); - fListenerProps->flModulationDepth = s->ReadLEFloat(); - fListenerProps->flAirAbsorptionHF = s->ReadLEFloat(); - fListenerProps->flHFReference = s->ReadLEFloat(); - fListenerProps->flLFReference = s->ReadLEFloat(); - fListenerProps->flRoomRolloffFactor = s->ReadLEFloat(); - fListenerProps->ulFlags = s->ReadLE32(); + eaxListenerProps->ulEnvironment = s->ReadLE32(); + eaxListenerProps->flEnvironmentSize = s->ReadLEFloat(); + eaxListenerProps->flEnvironmentDiffusion = s->ReadLEFloat(); + eaxListenerProps->lRoom = s->ReadLEFloat(); + eaxListenerProps->lRoomHF = s->ReadLEFloat(); + eaxListenerProps->lRoomLF = s->ReadLEFloat(); + eaxListenerProps->flDecayTime = s->ReadLEFloat(); + eaxListenerProps->flDecayHFRatio = s->ReadLEFloat(); + eaxListenerProps->flDecayLFRatio = s->ReadLEFloat(); + eaxListenerProps->lReflections = s->ReadLEFloat(); + eaxListenerProps->flReflectionsDelay = s->ReadLEFloat(); + //eaxListenerProps->vReflectionsPan; // early reflections panning vector + eaxListenerProps->lReverb = s->ReadLEFloat(); // late reverberation level relative to room effect + eaxListenerProps->flReverbDelay = s->ReadLEFloat(); + //eaxListenerProps->vReverbPan; // late reverberation panning vector + eaxListenerProps->flEchoTime = s->ReadLEFloat(); + eaxListenerProps->flEchoDepth = s->ReadLEFloat(); + eaxListenerProps->flModulationTime = s->ReadLEFloat(); + eaxListenerProps->flModulationDepth = s->ReadLEFloat(); + eaxListenerProps->flAirAbsorptionHF = s->ReadLEFloat(); + eaxListenerProps->flHFReference = s->ReadLEFloat(); + eaxListenerProps->flLFReference = s->ReadLEFloat(); + eaxListenerProps->flRoomRolloffFactor = s->ReadLEFloat(); + eaxListenerProps->ulFlags = s->ReadLE32(); + + ConvertEAXToEFX(eaxListenerProps, fListenerProps); + delete eaxListenerProps; // Done reading, time to tell the audio sys we exist IRegister(); @@ -208,45 +206,130 @@ void plEAXListenerMod::Write( hsStream* s, hsResMgr* mgr ) // Write the soft region key mgr->WriteKey( s, fSoftRegion ); + + EAXREVERBPROPERTIES* eaxListenerProps = new EAXREVERBPROPERTIES; + ConvertEFXToEAX(fListenerProps, eaxListenerProps); + // Write the listener params - s->WriteLE32((uint32_t)fListenerProps->ulEnvironment); - s->WriteLEFloat( fListenerProps->flEnvironmentSize ); - s->WriteLEFloat( fListenerProps->flEnvironmentDiffusion ); - s->WriteLE32((int32_t)fListenerProps->lRoom); - s->WriteLE32((int32_t)fListenerProps->lRoomHF); - s->WriteLE32((int32_t)fListenerProps->lRoomLF); - s->WriteLEFloat( fListenerProps->flDecayTime ); - s->WriteLEFloat( fListenerProps->flDecayHFRatio ); - s->WriteLEFloat( fListenerProps->flDecayLFRatio ); - s->WriteLE32((int32_t)fListenerProps->lReflections); - s->WriteLEFloat( fListenerProps->flReflectionsDelay ); - //s->WriteLEFloat( fListenerProps->vReflectionsPan; // early reflections panning vector - s->WriteLE32((int32_t)fListenerProps->lReverb); // late reverberation level relative to room effect - s->WriteLEFloat( fListenerProps->flReverbDelay ); - //s->WriteLEFloat( fListenerProps->vReverbPan; // late reverberation panning vector - s->WriteLEFloat( fListenerProps->flEchoTime ); - s->WriteLEFloat( fListenerProps->flEchoDepth ); - s->WriteLEFloat( fListenerProps->flModulationTime ); - s->WriteLEFloat( fListenerProps->flModulationDepth ); - s->WriteLEFloat( fListenerProps->flAirAbsorptionHF ); - s->WriteLEFloat( fListenerProps->flHFReference ); - s->WriteLEFloat( fListenerProps->flLFReference ); - s->WriteLEFloat( fListenerProps->flRoomRolloffFactor ); - s->WriteLE32((uint32_t)fListenerProps->ulFlags); + s->WriteLE32((uint32_t)eaxListenerProps->ulEnvironment); + s->WriteLEFloat(eaxListenerProps->flEnvironmentSize); + s->WriteLEFloat(eaxListenerProps->flEnvironmentDiffusion); + s->WriteLE32((int32_t)eaxListenerProps->lRoom); + s->WriteLE32((int32_t)eaxListenerProps->lRoomHF); + s->WriteLE32((int32_t)eaxListenerProps->lRoomLF); + s->WriteLEFloat(eaxListenerProps->flDecayTime); + s->WriteLEFloat(eaxListenerProps->flDecayHFRatio); + s->WriteLEFloat(eaxListenerProps->flDecayLFRatio); + s->WriteLE32((int32_t)eaxListenerProps->lReflections); + s->WriteLEFloat(eaxListenerProps->flReflectionsDelay); + //s->WriteLEFloat( eaxListenerProps->vReflectionsPan; // early reflections panning vector + s->WriteLE32((int32_t)eaxListenerProps->lReverb); // late reverberation level relative to room effect + s->WriteLEFloat(eaxListenerProps->flReverbDelay); + //s->WriteLEFloat( eaxListenerProps->vReverbPan; // late reverberation panning vector + s->WriteLEFloat(eaxListenerProps->flEchoTime); + s->WriteLEFloat(eaxListenerProps->flEchoDepth); + s->WriteLEFloat(eaxListenerProps->flModulationTime); + s->WriteLEFloat(eaxListenerProps->flModulationDepth); + s->WriteLEFloat(eaxListenerProps->flAirAbsorptionHF); + s->WriteLEFloat(eaxListenerProps->flHFReference); + s->WriteLEFloat(eaxListenerProps->flLFReference); + s->WriteLEFloat(eaxListenerProps->flRoomRolloffFactor); + s->WriteLE32((uint32_t)eaxListenerProps->ulFlags); + + delete eaxListenerProps; } - -void plEAXListenerMod::SetFromPreset( uint32_t preset ) +void plEAXListenerMod::SetFromEFXPreset(EFXEAXREVERBPROPERTIES preset) { -#ifdef EAX_SDK_AVAILABLE - memcpy( fListenerProps, &REVERB_ORIGINAL_PRESETS[ preset ], sizeof( EAXREVERBPROPERTIES ) ); -#endif + *fListenerProps = preset; } -float plEAXListenerMod::GetStrength() +float plEAXListenerMod::GetStrength() { if (fSoftRegion == nullptr) return 0.f; return fSoftRegion->GetListenerStrength(); } + + +/* Helper functions for converting to EFX from deprecated EAX values */ + +inline float mB_to_gain(float mb) +{ + return powf(10.0f, mb / 2000.0f); +} + +inline float gain_to_mB(float gain) +{ + return 2000.0f * log10f(gain); +} + +void plEAXListenerMod::ConvertEAXToEFX(const EAXREVERBPROPERTIES* eax, + EFXEAXREVERBPROPERTIES* efx) +{ + float density; + + density = powf(eax->flEnvironmentSize, 3.0f) / 16.0f; + efx->flDensity = (density > 1.0f) ? 1.0f : density; + efx->flDiffusion = eax->flEnvironmentDiffusion; + efx->flGain = mB_to_gain(eax->lRoom); + efx->flGainHF = mB_to_gain(eax->lRoomHF); + efx->flGainLF = mB_to_gain(eax->lRoomLF); + efx->flDecayTime = eax->flDecayTime; + efx->flDecayHFRatio = eax->flDecayHFRatio; + efx->flDecayLFRatio = eax->flDecayLFRatio; + efx->flReflectionsGain = mB_to_gain(eax->lReflections); + efx->flReflectionsDelay = eax->flReflectionsDelay; + efx->flReflectionsPan[0] = eax->vReflectionsPan.x; + efx->flReflectionsPan[1] = eax->vReflectionsPan.y; + efx->flReflectionsPan[2] = eax->vReflectionsPan.z; + efx->flLateReverbGain = mB_to_gain(eax->lReverb); + efx->flLateReverbDelay = eax->flReverbDelay; + efx->flLateReverbPan[0] = eax->vReverbPan.x; + efx->flLateReverbPan[1] = eax->vReverbPan.y; + efx->flLateReverbPan[2] = eax->vReverbPan.z; + efx->flEchoTime = eax->flEchoTime; + efx->flEchoDepth = eax->flEchoDepth; + efx->flModulationTime = eax->flModulationTime; + efx->flModulationDepth = eax->flModulationDepth; + efx->flAirAbsorptionGainHF = mB_to_gain(eax->flAirAbsorptionHF); + efx->flHFReference = eax->flHFReference; + efx->flLFReference = eax->flLFReference; + efx->flRoomRolloffFactor = eax->flRoomRolloffFactor; + efx->iDecayHFLimit = + (eax->ulFlags & EAXLISTENERFLAGS_DECAYHFLIMIT) ? 1 : 0; +} + +void plEAXListenerMod::ConvertEFXToEAX(const EFXEAXREVERBPROPERTIES* efx, + EAXREVERBPROPERTIES* eax) +{ + eax->flEnvironmentSize = cbrtf(16.0f * efx->flDensity); + eax->flEnvironmentDiffusion = efx->flDiffusion; + eax->lRoom = gain_to_mB(efx->flGain); + eax->lRoomHF = gain_to_mB(efx->flGainHF); + eax->lRoomLF = gain_to_mB(efx->flGainLF); + eax->flDecayTime = efx->flDecayTime; + eax->flDecayHFRatio = efx->flDecayHFRatio; + eax->flDecayLFRatio = efx->flDecayLFRatio; + eax->lReflections = gain_to_mB(efx->flReflectionsGain); + eax->flReflectionsDelay = efx->flReflectionsDelay; + eax->vReflectionsPan.x = efx->flReflectionsPan[0]; + eax->vReflectionsPan.y = efx->flReflectionsPan[1]; + eax->vReflectionsPan.z = efx->flReflectionsPan[2]; + eax->lReverb = gain_to_mB(efx->flLateReverbGain); + eax->flReverbDelay = efx->flLateReverbDelay; + eax->vReverbPan.x = efx->flLateReverbPan[0]; + eax->vReverbPan.y = efx->flLateReverbPan[1]; + eax->vReverbPan.z = efx->flLateReverbPan[2]; + eax->flEchoTime = efx->flEchoTime; + eax->flEchoDepth = efx->flEchoDepth; + eax->flModulationTime = efx->flModulationTime; + eax->flModulationDepth = efx->flModulationDepth; + eax->flAirAbsorptionHF = gain_to_mB(efx->flAirAbsorptionGainHF); + eax->flHFReference = efx->flHFReference; + eax->flLFReference = efx->flLFReference; + eax->flRoomRolloffFactor = efx->flRoomRolloffFactor; + if (efx->iDecayHFLimit == 1) + eax->ulFlags |= EAXLISTENERFLAGS_DECAYHFLIMIT; +} diff --git a/Sources/Plasma/PubUtilLib/plAudio/plEAXListenerMod.h b/Sources/Plasma/PubUtilLib/plAudio/plEAXListenerMod.h index 2d52f04d53..d65d8bef0a 100644 --- a/Sources/Plasma/PubUtilLib/plAudio/plEAXListenerMod.h +++ b/Sources/Plasma/PubUtilLib/plAudio/plEAXListenerMod.h @@ -39,6 +39,7 @@ You can contact Cyan Worlds, Inc. by email legal@cyan.com Mead, WA 99021 *==LICENSE==*/ + ////////////////////////////////////////////////////////////////////////////// // // // plEAXListenerMod Header // @@ -51,14 +52,12 @@ You can contact Cyan Worlds, Inc. by email legal@cyan.com #include "pnModifier/plSingleModifier.h" +#include +#include + class plMessage; class plSoftVolume; - -#ifdef EAX_SDK_AVAILABLE typedef struct _EAXREVERBPROPERTIES EAXREVERBPROPERTIES; -#else -#include "plEAXStructures.h" -#endif class plEAXListenerMod : public plSingleModifier { @@ -80,13 +79,16 @@ class plEAXListenerMod : public plSingleModifier void Write(hsStream* s, hsResMgr* mgr) override; float GetStrength(); - EAXREVERBPROPERTIES * GetListenerProps() { return fListenerProps; } - void SetFromPreset( uint32_t preset ); + EFXEAXREVERBPROPERTIES *GetListenerProps() { return fListenerProps; } + void SetFromEFXPreset(EFXEAXREVERBPROPERTIES preset); + + static void ConvertEAXToEFX(const EAXREVERBPROPERTIES* eax, EFXEAXREVERBPROPERTIES* efx); + static void ConvertEFXToEAX(const EFXEAXREVERBPROPERTIES* efx, EAXREVERBPROPERTIES* eax); protected: - plSoftVolume *fSoftRegion; - EAXREVERBPROPERTIES *fListenerProps; - bool fRegistered, fGetsMessages; + plSoftVolume *fSoftRegion; + EFXEAXREVERBPROPERTIES *fListenerProps; + bool fRegistered, fGetsMessages; void IRegister(); void IUnRegister(); diff --git a/Sources/Plasma/PubUtilLib/plAudio/plEAXStructures.h b/Sources/Plasma/PubUtilLib/plAudio/plEAXStructures.h index 7cdf7e2912..71b1728741 100644 --- a/Sources/Plasma/PubUtilLib/plAudio/plEAXStructures.h +++ b/Sources/Plasma/PubUtilLib/plAudio/plEAXStructures.h @@ -77,4 +77,6 @@ typedef struct _EAXREVERBPROPERTIES unsigned long ulFlags; } EAXREVERBPROPERTIES, *LPEAXREVERBPROPERTIES; +#define EAXLISTENERFLAGS_DECAYHFLIMIT 0x20 + #endif //plEAXStructures_h_inc diff --git a/Sources/Tools/MaxComponent/plAudioComponents.cpp b/Sources/Tools/MaxComponent/plAudioComponents.cpp index 305e94e6e1..2c0e366de2 100644 --- a/Sources/Tools/MaxComponent/plAudioComponents.cpp +++ b/Sources/Tools/MaxComponent/plAudioComponents.cpp @@ -109,15 +109,12 @@ You can contact Cyan Worlds, Inc. by email legal@cyan.com // EAX stuff #include "plAudio/plEAXListenerMod.h" -#ifdef EAX_SDK_AVAILABLE -# include -# include -#endif +#include "plAudio/plEAXStructures.h" #include "plResMgr/plLocalization.h" #include "plPhysical/plPhysicalSndGroup.h" -// EAX3 values which eax4 no longer defines, but we still need. +// EAX3 values which EAX4 no longer defines, but we still need. // Single window material preset #define EAX_MATERIAL_SINGLEWINDOW (-2800) #define EAX_MATERIAL_SINGLEWINDOWLF 0.71f @@ -158,6 +155,66 @@ You can contact Cyan Worlds, Inc. by email legal@cyan.com #define EAX_MATERIAL_CURTAINLF 0.15f #define EAX_MATERIAL_CURTAINROOMRATIO 1.00f +#define EAX_NUM_LEGACY_PRESETS 26 +const char* EAX_LEGACY_PRESET_NAMES[EAX_NUM_LEGACY_PRESETS] = +{ + "Generic", + "Padded Cell", + "Room", + "Bathroom", + "Living Room", + "Stone Room", + "Auditorium", + "Concert Hall", + "Cave", + "Arena", + "Hangar", + "Carpetted Hallway", + "Hallway", + "Stone Corridor", + "Alley", + "Forest", + "City", + "Mountains", + "Quarry", + "Plain", + "Parking Lot", + "Sewer Pipe", + "Underwater", + "Drugged", + "Dizzy", + "Psychotic" +}; + +EFXEAXREVERBPROPERTIES EAX_LEGACY_PRESETS[EAX_NUM_LEGACY_PRESETS] = { + EFX_REVERB_PRESET_GENERIC, + EFX_REVERB_PRESET_PADDEDCELL, + EFX_REVERB_PRESET_ROOM, + EFX_REVERB_PRESET_BATHROOM, + EFX_REVERB_PRESET_LIVINGROOM, + EFX_REVERB_PRESET_STONEROOM, + EFX_REVERB_PRESET_AUDITORIUM, + EFX_REVERB_PRESET_CONCERTHALL, + EFX_REVERB_PRESET_CAVE, + EFX_REVERB_PRESET_ARENA, + EFX_REVERB_PRESET_HANGAR, + EFX_REVERB_PRESET_CARPETEDHALLWAY, + EFX_REVERB_PRESET_HALLWAY, + EFX_REVERB_PRESET_STONECORRIDOR, + EFX_REVERB_PRESET_ALLEY, + EFX_REVERB_PRESET_FOREST, + EFX_REVERB_PRESET_CITY, + EFX_REVERB_PRESET_MOUNTAINS, + EFX_REVERB_PRESET_QUARRY, + EFX_REVERB_PRESET_PLAIN, + EFX_REVERB_PRESET_PARKINGLOT, + EFX_REVERB_PRESET_SEWERPIPE, + EFX_REVERB_PRESET_UNDERWATER, + EFX_REVERB_PRESET_DRUGGED, + EFX_REVERB_PRESET_DIZZY, + EFX_REVERB_PRESET_PSYCHOTIC +}; + void DummyCodeIncludeFuncAudio() {} @@ -2795,11 +2852,8 @@ class plEAXListenerDlgProc : public plSingleCompSelProc HWND comboBox = GetDlgItem( hWnd, IDC_EAX_PRESET_COMBO ); ComboBox_ResetContent( comboBox ); -#ifdef EAX_SDK_AVAILABLE - for( int i = 0; i < /*sizeof( EAX30_ORIGINAL_PRESETS ) - / sizeof( EAXLISTENERPROPERTIES )*/26 ; i++ ) - ComboBox_AddString( comboBox, EAX30_ORIGINAL_PRESET_NAMES[ i ] ); -#endif + for( int i = 0; i < EAX_NUM_LEGACY_PRESETS; i++ ) + ComboBox_AddString(comboBox, EAX_LEGACY_PRESET_NAMES[i]); ComboBox_SetCurSel( comboBox, pb->GetInt( (ParamID)plEAXListenerComponent::kRefPreset ) ); @@ -2934,42 +2988,43 @@ bool plEAXListenerComponent::Convert(plMaxNode *node, plErrorMsg *errMsg) // Add the soft region hsgResMgr::ResMgr()->AddViaNotify( softKey, new plGenRefMsg( listener->GetKey(), plRefMsg::kOnCreate, 0, plEAXListenerMod::kRefSoftRegion ), plRefFlags::kActiveRef ); -#ifdef EAX_SDK_AVAILABLE // Set up the parameters of the listener mod - EAXLISTENERPROPERTIES *listenerProps = listener->GetListenerProps(); - if( fCompPB->GetInt( (ParamID)kRefWhichSettings ) == 0 ) - { + if(fCompPB->GetInt( (ParamID)kRefWhichSettings ) == 0) { // Set params based on a preset - listener->SetFromPreset( fCompPB->GetInt( (ParamID)kRefPreset ) ); - } - else - { + listener->SetFromEFXPreset(EAX_LEGACY_PRESETS[fCompPB->GetInt((ParamID)kRefPreset)]); + } else { + // Set params based on artist selections + EAXREVERBPROPERTIES *eaxProps = new EAXREVERBPROPERTIES; + // Get the raw params - listenerProps->flEnvironmentSize = fCompPB->GetFloat( (ParamID)kRefEnvironmentSize ); - listenerProps->flEnvironmentDiffusion = fCompPB->GetFloat( (ParamID)kRefEnvironmentDiffusion ); - listenerProps->lRoom = fCompPB->GetInt( (ParamID)kRefRoom ); - listenerProps->lRoomHF = fCompPB->GetInt( (ParamID)kRefRoomHF ); - listenerProps->lRoomLF = fCompPB->GetInt( (ParamID)kRefRoomLF ); - listenerProps->flDecayTime = fCompPB->GetFloat( (ParamID)kRefDecayTime ); - listenerProps->flDecayHFRatio = fCompPB->GetFloat( (ParamID)kRefDecayHFRatio ); - listenerProps->flDecayLFRatio = fCompPB->GetFloat( (ParamID)kRefDecayLFRatio ); - listenerProps->lReflections = fCompPB->GetInt( (ParamID)kRefReflections ); - listenerProps->flReflectionsDelay = fCompPB->GetFloat( (ParamID)kRefReflectionsDelay ); - //listenerProps->vReflectionsPan; // early reflections panning vector - listenerProps->lReverb = fCompPB->GetInt( (ParamID)kRefReverb ); // late reverberation level relative to room effect - listenerProps->flReverbDelay = fCompPB->GetFloat( (ParamID)kRefReverbDelay ); - //listenerProps->vReverbPan; // late reverberation panning vector - listenerProps->flEchoTime = fCompPB->GetFloat( (ParamID)kRefEchoTime ); - listenerProps->flEchoDepth = fCompPB->GetFloat( (ParamID)kRefEchoDepth ); - listenerProps->flModulationTime = fCompPB->GetFloat( (ParamID)kRefModulationTime ); - listenerProps->flModulationDepth = fCompPB->GetFloat( (ParamID)kRefModulationDepth ); - listenerProps->flAirAbsorptionHF = fCompPB->GetFloat( (ParamID)kRefAirAbsorptionHF ); - listenerProps->flHFReference = fCompPB->GetFloat( (ParamID)kRefHFReference ); - listenerProps->flLFReference = fCompPB->GetFloat( (ParamID)kRefLFReference ); - listenerProps->flRoomRolloffFactor = fCompPB->GetFloat( (ParamID)kRefRoomRolloffFactor ); - listenerProps->ulFlags = fCompPB->GetInt( (ParamID)kRefFlags ); + eaxProps->flEnvironmentSize = fCompPB->GetFloat( (ParamID)kRefEnvironmentSize ); + eaxProps->flEnvironmentDiffusion = fCompPB->GetFloat( (ParamID)kRefEnvironmentDiffusion ); + eaxProps->lRoom = fCompPB->GetInt( (ParamID)kRefRoom ); + eaxProps->lRoomHF = fCompPB->GetInt( (ParamID)kRefRoomHF ); + eaxProps->lRoomLF = fCompPB->GetInt( (ParamID)kRefRoomLF ); + eaxProps->flDecayTime = fCompPB->GetFloat( (ParamID)kRefDecayTime ); + eaxProps->flDecayHFRatio = fCompPB->GetFloat( (ParamID)kRefDecayHFRatio ); + eaxProps->flDecayLFRatio = fCompPB->GetFloat( (ParamID)kRefDecayLFRatio ); + eaxProps->lReflections = fCompPB->GetInt( (ParamID)kRefReflections ); + eaxProps->flReflectionsDelay = fCompPB->GetFloat( (ParamID)kRefReflectionsDelay ); + //eaxProps->vReflectionsPan; // early reflections panning vector + eaxProps->lReverb = fCompPB->GetInt( (ParamID)kRefReverb ); // late reverberation level relative to room effect + eaxProps->flReverbDelay = fCompPB->GetFloat( (ParamID)kRefReverbDelay ); + //eaxProps->vReverbPan; // late reverberation panning vector + eaxProps->flEchoTime = fCompPB->GetFloat( (ParamID)kRefEchoTime ); + eaxProps->flEchoDepth = fCompPB->GetFloat( (ParamID)kRefEchoDepth ); + eaxProps->flModulationTime = fCompPB->GetFloat( (ParamID)kRefModulationTime ); + eaxProps->flModulationDepth = fCompPB->GetFloat( (ParamID)kRefModulationDepth ); + eaxProps->flAirAbsorptionHF = fCompPB->GetFloat( (ParamID)kRefAirAbsorptionHF ); + eaxProps->flHFReference = fCompPB->GetFloat( (ParamID)kRefHFReference ); + eaxProps->flLFReference = fCompPB->GetFloat( (ParamID)kRefLFReference ); + eaxProps->flRoomRolloffFactor = fCompPB->GetFloat( (ParamID)kRefRoomRolloffFactor ); + eaxProps->ulFlags = fCompPB->GetInt( (ParamID)kRefFlags ); + + // Convert to EFX and store them + plEAXListenerMod::ConvertEAXToEFX(eaxProps, listener->GetListenerProps()); + delete eaxProps; } -#endif return true; } From 17388ef88871be0d3826b3434ca541fc1c59698b Mon Sep 17 00:00:00 2001 From: Joseph Davies Date: Thu, 7 Oct 2021 17:30:08 -0700 Subject: [PATCH 2/2] Reimplement EAX Occlusion for OpenAL's EAX. --- .../PubUtilLib/plAudio/plEAXEffects.cpp | 139 +++++++++--------- .../Plasma/PubUtilLib/plAudio/plEAXEffects.h | 4 +- 2 files changed, 69 insertions(+), 74 deletions(-) diff --git a/Sources/Plasma/PubUtilLib/plAudio/plEAXEffects.cpp b/Sources/Plasma/PubUtilLib/plAudio/plEAXEffects.cpp index a1cacb91b6..375dd66b63 100644 --- a/Sources/Plasma/PubUtilLib/plAudio/plEAXEffects.cpp +++ b/Sources/Plasma/PubUtilLib/plAudio/plEAXEffects.cpp @@ -65,6 +65,48 @@ You can contact Cyan Worlds, Inc. by email legal@cyan.com #define DebugLog if (myLog) myLog->AddLineF + + +ALboolean SetEFXEAXReverbProperties(EFXEAXREVERBPROPERTIES * pEFXEAXReverb, ALuint uiEffect) +{ + ALboolean bReturn = AL_FALSE; + + if (pEFXEAXReverb) + { + // Clear AL Error code + alGetError(); + + alEffectf(uiEffect, AL_EAXREVERB_DENSITY, pEFXEAXReverb->flDensity); + alEffectf(uiEffect, AL_EAXREVERB_DIFFUSION, pEFXEAXReverb->flDiffusion); + alEffectf(uiEffect, AL_EAXREVERB_GAIN, pEFXEAXReverb->flGain); + alEffectf(uiEffect, AL_EAXREVERB_GAINHF, pEFXEAXReverb->flGainHF); + alEffectf(uiEffect, AL_EAXREVERB_GAINLF, pEFXEAXReverb->flGainLF); + alEffectf(uiEffect, AL_EAXREVERB_DECAY_TIME, pEFXEAXReverb->flDecayTime); + alEffectf(uiEffect, AL_EAXREVERB_DECAY_HFRATIO, pEFXEAXReverb->flDecayHFRatio); + alEffectf(uiEffect, AL_EAXREVERB_DECAY_LFRATIO, pEFXEAXReverb->flDecayLFRatio); + alEffectf(uiEffect, AL_EAXREVERB_REFLECTIONS_GAIN, pEFXEAXReverb->flReflectionsGain); + alEffectf(uiEffect, AL_EAXREVERB_REFLECTIONS_DELAY, pEFXEAXReverb->flReflectionsDelay); + alEffectfv(uiEffect, AL_EAXREVERB_REFLECTIONS_PAN, pEFXEAXReverb->flReflectionsPan); + alEffectf(uiEffect, AL_EAXREVERB_LATE_REVERB_GAIN, pEFXEAXReverb->flLateReverbGain); + alEffectf(uiEffect, AL_EAXREVERB_LATE_REVERB_DELAY, pEFXEAXReverb->flLateReverbDelay); + alEffectfv(uiEffect, AL_EAXREVERB_LATE_REVERB_PAN, pEFXEAXReverb->flLateReverbPan); + alEffectf(uiEffect, AL_EAXREVERB_ECHO_TIME, pEFXEAXReverb->flEchoTime); + alEffectf(uiEffect, AL_EAXREVERB_ECHO_DEPTH, pEFXEAXReverb->flEchoDepth); + alEffectf(uiEffect, AL_EAXREVERB_MODULATION_TIME, pEFXEAXReverb->flModulationTime); + alEffectf(uiEffect, AL_EAXREVERB_MODULATION_DEPTH, pEFXEAXReverb->flModulationDepth); + alEffectf(uiEffect, AL_EAXREVERB_AIR_ABSORPTION_GAINHF, pEFXEAXReverb->flAirAbsorptionGainHF); + alEffectf(uiEffect, AL_EAXREVERB_HFREFERENCE, pEFXEAXReverb->flHFReference); + alEffectf(uiEffect, AL_EAXREVERB_LFREFERENCE, pEFXEAXReverb->flLFReference); + alEffectf(uiEffect, AL_EAXREVERB_ROOM_ROLLOFF_FACTOR, pEFXEAXReverb->flRoomRolloffFactor); + alEffecti(uiEffect, AL_EAXREVERB_DECAY_HFLIMIT, pEFXEAXReverb->iDecayHFLimit); + + if (alGetError() == AL_NO_ERROR) + bReturn = AL_TRUE; + } + + return bReturn; +} + //// GetInstance ///////////////////////////////////////////////////////////// plEAXListener &plEAXListener::GetInstance() @@ -80,17 +122,10 @@ bool plEAXListener::Init(ALCdevice *alDevice) if(fInited) return true; - if(!alIsExtensionPresent((ALchar *)"EAX4.0")) // is eax 4 supported + if(!alcIsExtensionPresent(alDevice, (ALchar *)"ALC_EXT_EFX")) { - if(!alIsExtensionPresent((ALchar *) "EAX4.0Emulated")) // is an earlier version of eax supported - { - plStatusLog::AddLineS("audio.log", "EAX not supported"); - return false; - } - else - { - plStatusLog::AddLineS("audio.log", "EAX 4 Emulated supported"); - } + plStatusLog::AddLineS("audio.log", "EFX not supported"); + return false; } else { ALCint iVerMajor, iVerMinor; alcGetIntegerv(alDevice, ALC_EFX_MAJOR_VERSION, 1, &iVerMajor); @@ -98,32 +133,11 @@ bool plEAXListener::Init(ALCdevice *alDevice) plStatusLog::AddLineSF("audio.log", "EFX v{}.{} available.", iVerMajor, iVerMinor); } + ClearProcessCache(); - // EAX is supported + // EFX is supported fInited = true; - try - { - // Make an EAX call here to prevent problems on WDM driver - unsigned int lRoom = -10000; - - //SetGlobalEAXProperty(DSPROPSETID_EAX_ListenerProperties, DSPROPERTY_EAXLISTENER_ROOM, &lRoom, sizeof( unsigned int )); - } - catch (std::exception &e) - { - plStatusLog::AddLineSF("audio.log", "Unable to set EAX Property Set ({}), disabling EAX...", e.what()); - plgAudioSys::EnableEAX(false); - return false; - } - catch (...) - { - plStatusLog::AddLineS("audio.log", "Unable to set EAX Property Set, disabling EAX..."); - plgAudioSys::EnableEAX(false); - return false; - } - - ClearProcessCache(); - return true; } @@ -136,37 +150,6 @@ void plEAXListener::Shutdown() IRelease(); } -/* -bool plEAXListener::SetGlobalEAXProperty(GUID guid, unsigned long ulProperty, void *pData, unsigned long ulDataSize ) -{ - if(fInited) - { - return s_EAXSet(&guid, ulProperty, 0, pData, ulDataSize) == AL_NO_ERROR; - } - return false; -} - -bool plEAXListener::GetGlobalEAXProperty(GUID guid, unsigned long ulProperty, void *pData, unsigned long ulDataSize) -{ - if(fInited) - { - return s_EAXGet(&guid, ulProperty, 0, pData, ulDataSize) == AL_NO_ERROR; - } - return false; -} - -bool plEAXSource::SetSourceEAXProperty(unsigned source, GUID guid, unsigned long ulProperty, void *pData, unsigned long ulDataSize) -{ - return s_EAXSet(&guid, ulProperty, source, pData, ulDataSize) == AL_NO_ERROR; - return false; -} - -bool plEAXSource::GetSourceEAXProperty(unsigned source, GUID guid, unsigned long ulProperty, void *pData, unsigned long ulDataSize) -{ - return s_EAXGet(&guid, ulProperty, source, pData, ulDataSize) == AL_NO_ERROR; - return false; -}*/ - //// IRelease //////////////////////////////////////////////////////////////// @@ -180,7 +163,7 @@ void plEAXListener::IRelease() void plEAXListener::IFail(bool fatal) { plStatusLog::AddLineS("audio.log", plStatusLog::kRed, - "ERROR in plEAXListener: Could not set global eax params"); + "ERROR in plEAXListener: Could not set global EAX params"); if(fatal) IRelease(); @@ -312,7 +295,6 @@ void plEAXListener::ProcessMods(const std::set& modArray) if( fLastWasEmpty ) return; - //memcpy( &finalProps, &EAX30_ORIGINAL_PRESETS[ ORIGINAL_GENERIC ], sizeof( EAXLISTENERPROPERTIES ) ); finalProps = EFX_REVERB_PRESET_GENERIC; finalProps.flGain = AL_EAXREVERB_MIN_GAIN; finalProps.flGainLF = AL_EAXREVERB_MIN_GAINLF; @@ -368,11 +350,9 @@ void plEAXListener::ProcessMods(const std::set& modArray) } finalProps.flAirAbsorptionGainHF *= 0.3048f; // Convert to feet - - //if(!SetGlobalEAXProperty(DSPROPSETID_EAX_ListenerProperties, DSPROPERTY_EAXLISTENER_ALLPARAMETERS, &finalProps, sizeof( finalProps ))) - //{ - IFail( false ); - //} + if (SetEFXEAXReverbProperties(&finalProps, 0) == AL_FALSE) { + IFail(false); + } } @@ -524,6 +504,9 @@ void plEAXSourceSoftSettings::Reset() fOcclusionLFRatio = 0.25f; fOcclusionRoomRatio = 1.5f; fOcclusionDirectRatio = 1.f; + + fExclusion = 0; + fExclusionLFRatio = 1.0f; } void plEAXSourceSoftSettings::Read( hsStream *s ) @@ -551,7 +534,6 @@ void plEAXSourceSoftSettings::SetOcclusion( int16_t occ, float lfRatio, float } - //// Init/Release //////////////////////////////////////////////////////////// void plEAXSource::Init( plDSoundBuffer *parent ) @@ -607,6 +589,19 @@ void plEAXSource::SetFrom(plEAXSourceSettings *settings, unsigned source, bool f if(dirtyParams & plEAXSourceSettings::kOcclusion) { // EFX doesn't support the high-level EAX Occlusion properties, so we'll have to calculate it ourselves. + float dryoccl = std::max(settings->GetCurrSofts().fOcclusionLFRatio + settings->GetCurrSofts().fOcclusionDirectRatio - 1.0f, + settings->GetCurrSofts().fOcclusionLFRatio * settings->GetCurrSofts().fOcclusionDirectRatio) * + settings->GetCurrSofts().fOcclusion; + + float dryocclhf = settings->GetCurrSofts().fOcclusion * settings->GetCurrSofts().fOcclusionDirectRatio; + + float room_mb = settings->fRoom + settings->GetCurrSofts().fExclusion * settings->GetCurrSofts().fExclusionLFRatio + + std::max(settings->GetCurrSofts().fOcclusionLFRatio + settings->GetCurrSofts().fOcclusionRoomRatio - 1.0f, + settings->GetCurrSofts().fOcclusionLFRatio * settings->GetCurrSofts().fOcclusionRoomRatio) * settings->GetCurrSofts().fOcclusion; + float room_mbhf = settings->fRoomHF + settings->GetCurrSofts().fExclusion + + settings->GetCurrSofts().fOcclusion * settings->GetCurrSofts().fOcclusionRoomRatio; + + //alFilterf(); //alSourcef(source, , settings->); //SetSourceEAXProperty(source, DSPROPSETID_EAX_BufferProperties, DSPROPERTY_EAXBUFFER_OCCLUSION, &settings->GetCurrSofts().fOcclusion, sizeof(settings->GetCurrSofts().fOcclusion)); //SetSourceEAXProperty(source, DSPROPSETID_EAX_BufferProperties, DSPROPERTY_EAXBUFFER_OCCLUSIONLFRATIO, &settings->GetCurrSofts().fOcclusionLFRatio, sizeof(settings->GetCurrSofts().fOcclusionLFRatio)); diff --git a/Sources/Plasma/PubUtilLib/plAudio/plEAXEffects.h b/Sources/Plasma/PubUtilLib/plAudio/plEAXEffects.h index 70f382bdd2..158a9c0b8f 100644 --- a/Sources/Plasma/PubUtilLib/plAudio/plEAXEffects.h +++ b/Sources/Plasma/PubUtilLib/plAudio/plEAXEffects.h @@ -100,8 +100,8 @@ class hsStream; class plEAXSourceSoftSettings { public: - int16_t fOcclusion; - float fOcclusionLFRatio, fOcclusionRoomRatio, fOcclusionDirectRatio; + int16_t fOcclusion, fExclusion; + float fOcclusionLFRatio, fOcclusionRoomRatio, fOcclusionDirectRatio, fExclusionLFRatio; void Read( hsStream *s ); void Write( hsStream *s );