From ece2adbdcd3e485bc45efa0fba04f8c4907e65d1 Mon Sep 17 00:00:00 2001 From: dhewg Date: Sun, 8 Jan 2012 21:53:51 +0100 Subject: [PATCH] Port EAX to EFX First attempt at porting the EAX reverb code to EFX. This only works when the ALC_EXT_EFX extension is supported by the OpenAL vendor (which is not the case for the OSX supplied framework, use OpenAL soft instead). The current stable version of OpenAL Soft (v1.13 as of this writing) can barely handle this additional workload, current master is highly recommended when using this feature. --- neo/framework/BuildDefines.h | 4 - neo/framework/Session_menu.cpp | 4 +- neo/sound/efxlib.h | 49 ++----- neo/sound/snd_cache.cpp | 4 - neo/sound/snd_efxfile.cpp | 252 ++++++++++++++++++--------------- neo/sound/snd_local.h | 30 ++-- neo/sound/snd_system.cpp | 120 ++++++---------- neo/sound/snd_world.cpp | 65 +++++---- neo/sound/sound.h | 4 +- 9 files changed, 245 insertions(+), 287 deletions(-) diff --git a/neo/framework/BuildDefines.h b/neo/framework/BuildDefines.h index 78171b6c..4b8ed7fa 100644 --- a/neo/framework/BuildDefines.h +++ b/neo/framework/BuildDefines.h @@ -104,10 +104,6 @@ If you have questions concerning this license or the applicable additional terms # endif #endif -#ifndef ID_OPENAL_EAX -# define ID_OPENAL_EAX 0 -#endif - // async network /* diff --git a/neo/framework/Session_menu.cpp b/neo/framework/Session_menu.cpp index 10df1ddd..b476108e 100644 --- a/neo/framework/Session_menu.cpp +++ b/neo/framework/Session_menu.cpp @@ -888,8 +888,8 @@ void idSessionLocal::HandleMainMenuCommands( const char *menuCommand ) { } if ( !vcmd.Icmp( "eax" ) ) { if ( cvarSystem->GetCVarBool( "s_useEAXReverb" ) ) { - int eax = soundSystem->IsEAXAvailable(); - switch ( eax ) { + int efx = soundSystem->IsEFXAvailable(); + switch ( efx ) { case 1: // when you restart MessageBox( MSG_OK, common->GetLanguageDict()->GetString( "#str_04137" ), common->GetLanguageDict()->GetString( "#str_07231" ), true ); diff --git a/neo/sound/efxlib.h b/neo/sound/efxlib.h index 1b0ff7e0..c77d6e45 100644 --- a/neo/sound/efxlib.h +++ b/neo/sound/efxlib.h @@ -4,62 +4,35 @@ #ifndef __EFXLIBH #define __EFXLIBH -#if ID_OPENAL_EAX -#include -#endif - #include "idlib/containers/List.h" #include "idlib/Str.h" #include "idlib/Lexer.h" #include "idlib/Heap.h" #include "sound/sound.h" -/////////////////////////////////////////////////////////// -// Class definitions. -class idSoundEffect -{ -public: - idSoundEffect() { - }; - ~idSoundEffect() { - if ( data && datasize ) { - Mem_Free( data ); - data = NULL; - } - } +struct idSoundEffect { + idSoundEffect(); + ~idSoundEffect(); + + bool alloc(); idStr name; - int datasize; - void *data; + ALuint effect; }; -class idEFXFile -{ -private: - -protected: - // Protected data members. - -public: - // Public data members. - -private: - +class idEFXFile { public: idEFXFile(); ~idEFXFile(); - bool FindEffect( idStr &name, idSoundEffect **effect, int *index ); - bool ReadEffect( idLexer &lexer, idSoundEffect *effect ); + bool FindEffect( idStr &name, ALuint *effect ); bool LoadFile( const char *filename, bool OSPath = false ); - void UnloadFile( void ); void Clear( void ); +private: + bool ReadEffect( idLexer &lexer, idSoundEffect *effect ); + idListeffects; }; -/////////////////////////////////////////////////////////// - - - #endif // __EFXLIBH diff --git a/neo/sound/snd_cache.cpp b/neo/sound/snd_cache.cpp index 83cf3a81..4079da9d 100644 --- a/neo/sound/snd_cache.cpp +++ b/neo/sound/snd_cache.cpp @@ -524,11 +524,7 @@ void idSoundSample::Load( void ) { // OGG decompressed at load time (when smaller than s_decompressionLimit seconds, 6 seconds by default) if ( objectInfo.wFormatTag == WAVE_FORMAT_TAG_OGG ) { -#if !ID_OPENAL_EAX if ( ( objectSize < ( ( int ) objectInfo.nSamplesPerSec * idSoundSystemLocal::s_decompressionLimit.GetInteger() ) ) ) { -#else - if ( ( alIsExtensionPresent( ID_ALCHAR "EAX-RAM" ) == AL_TRUE ) && ( objectSize < ( ( int ) objectInfo.nSamplesPerSec * idSoundSystemLocal::s_decompressionLimit.GetInteger() ) ) ) { -#endif alGetError(); alGenBuffers( 1, &openalBuffer ); if ( alGetError() != AL_NO_ERROR ) diff --git a/neo/sound/snd_efxfile.cpp b/neo/sound/snd_efxfile.cpp index 1132e61a..5d177eb3 100644 --- a/neo/sound/snd_efxfile.cpp +++ b/neo/sound/snd_efxfile.cpp @@ -30,12 +30,40 @@ If you have questions concerning this license or the applicable additional terms #include "sound/snd_local.h" +idSoundEffect::idSoundEffect() : + effect(0) { +} + +idSoundEffect::~idSoundEffect() { + if (effect) + soundSystemLocal.alDeleteEffects(1, &effect); +} + +bool idSoundEffect::alloc() { + alGetError(); + + ALenum e; + + soundSystemLocal.alGenEffects(1, &effect); + if ((e = alGetError()) != AL_NO_ERROR) { + return false; + } + + soundSystemLocal.alEffecti(effect, AL_EFFECT_TYPE, AL_EFFECT_EAXREVERB); + if ((e = alGetError()) != AL_NO_ERROR) { + return false; + } + + return true; +} + /* =============== idEFXFile::idEFXFile =============== */ -idEFXFile::idEFXFile( void ) { } +idEFXFile::idEFXFile( void ) { +} /* =============== @@ -60,16 +88,16 @@ idEFXFile::~idEFXFile( void ) { idEFXFile::FindEffect =============== */ -bool idEFXFile::FindEffect( idStr &name, idSoundEffect **effect, int *index ) { +bool idEFXFile::FindEffect( idStr &name, ALuint *effect ) { int i; for ( i = 0; i < effects.Num(); i++ ) { - if ( ( effects[i] ) && ( effects[i]->name == name ) ) { - *effect = effects[i]; - *index = i; + if ( effects[i]->name == name ) { + *effect = effects[i]->effect; return true; } } + return false; } @@ -79,117 +107,111 @@ idEFXFile::ReadEffect =============== */ bool idEFXFile::ReadEffect( idLexer &src, idSoundEffect *effect ) { -#if ID_OPENAL_EAX idToken name, token; if ( !src.ReadToken( &token ) ) return false; // reverb effect - if ( token == "reverb" ) { - EAXREVERBPROPERTIES *reverb = ( EAXREVERBPROPERTIES * )Mem_Alloc( sizeof( EAXREVERBPROPERTIES ) ); - if ( reverb ) { - src.ReadTokenOnLine( &token ); - name = token; - - if ( !src.ReadToken( &token ) ) { - Mem_Free( reverb ); - return false; - } - - if ( token != "{" ) { - src.Error( "idEFXFile::ReadEffect: { not found, found %s", token.c_str() ); - Mem_Free( reverb ); - return false; - } - - do { - if ( !src.ReadToken( &token ) ) { - src.Error( "idEFXFile::ReadEffect: EOF without closing brace" ); - Mem_Free( reverb ); - return false; - } - - if ( token == "}" ) { - effect->name = name; - effect->data = ( void * )reverb; - effect->datasize = sizeof( EAXREVERBPROPERTIES ); - break; - } - - if ( token == "environment" ) { - src.ReadTokenOnLine( &token ); - reverb->ulEnvironment = token.GetUnsignedLongValue(); - } else if ( token == "environment size" ) { - reverb->flEnvironmentSize = src.ParseFloat(); - } else if ( token == "environment diffusion" ) { - reverb->flEnvironmentDiffusion = src.ParseFloat(); - } else if ( token == "room" ) { - reverb->lRoom = src.ParseInt(); - } else if ( token == "room hf" ) { - reverb->lRoomHF = src.ParseInt(); - } else if ( token == "room lf" ) { - reverb->lRoomLF = src.ParseInt(); - } else if ( token == "decay time" ) { - reverb->flDecayTime = src.ParseFloat(); - } else if ( token == "decay hf ratio" ) { - reverb->flDecayHFRatio = src.ParseFloat(); - } else if ( token == "decay lf ratio" ) { - reverb->flDecayLFRatio = src.ParseFloat(); - } else if ( token == "reflections" ) { - reverb->lReflections = src.ParseInt(); - } else if ( token == "reflections delay" ) { - reverb->flReflectionsDelay = src.ParseFloat(); - } else if ( token == "reflections pan" ) { - reverb->vReflectionsPan.x = src.ParseFloat(); - reverb->vReflectionsPan.y = src.ParseFloat(); - reverb->vReflectionsPan.z = src.ParseFloat(); - } else if ( token == "reverb" ) { - reverb->lReverb = src.ParseInt(); - } else if ( token == "reverb delay" ) { - reverb->flReverbDelay = src.ParseFloat(); - } else if ( token == "reverb pan" ) { - reverb->vReverbPan.x = src.ParseFloat(); - reverb->vReverbPan.y = src.ParseFloat(); - reverb->vReverbPan.z = src.ParseFloat(); - } else if ( token == "echo time" ) { - reverb->flEchoTime = src.ParseFloat(); - } else if ( token == "echo depth" ) { - reverb->flEchoDepth = src.ParseFloat(); - } else if ( token == "modulation time" ) { - reverb->flModulationTime = src.ParseFloat(); - } else if ( token == "modulation depth" ) { - reverb->flModulationDepth = src.ParseFloat(); - } else if ( token == "air absorption hf" ) { - reverb->flAirAbsorptionHF = src.ParseFloat(); - } else if ( token == "hf reference" ) { - reverb->flHFReference = src.ParseFloat(); - } else if ( token == "lf reference" ) { - reverb->flLFReference = src.ParseFloat(); - } else if ( token == "room rolloff factor" ) { - reverb->flRoomRolloffFactor = src.ParseFloat(); - } else if ( token == "flags" ) { - src.ReadTokenOnLine( &token ); - reverb->ulFlags = token.GetUnsignedLongValue(); - } else { - src.ReadTokenOnLine( &token ); - src.Error( "idEFXFile::ReadEffect: Invalid parameter in reverb definition" ); - Mem_Free( reverb ); - } - } while ( 1 ); - - return true; - } - } else { + if ( token != "reverb" ) { // other effect (not supported at the moment) src.Error( "idEFXFile::ReadEffect: Unknown effect definition" ); + + return false; } -#endif - return false; + src.ReadTokenOnLine( &token ); + name = token; + + if ( !src.ReadToken( &token ) ) + return false; + + if ( token != "{" ) { + src.Error( "idEFXFile::ReadEffect: { not found, found %s", token.c_str() ); + return false; + } + + do { + if ( !src.ReadToken( &token ) ) { + src.Error( "idEFXFile::ReadEffect: EOF without closing brace" ); + return false; + } + + if ( token == "}" ) { + effect->name = name; + 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" ) { + soundSystemLocal.alEffecti(e, AL_EAXREVERB_GAIN, src.ParseInt()); + } else if ( token == "environment size" ) { + soundSystemLocal.alEffectf(e, AL_EAXREVERB_DENSITY, src.ParseFloat()); + } else if ( token == "environment diffusion" ) { + soundSystemLocal.alEffectf(e, AL_EAXREVERB_DIFFUSION, src.ParseFloat()); + } else if ( token == "room" ) { + soundSystemLocal.alEffecti(e, AL_EAXREVERB_GAIN, src.ParseInt()); + } else if ( token == "room hf" ) { + soundSystemLocal.alEffecti(e, AL_EAXREVERB_GAINHF, src.ParseInt()); + } else if ( token == "room lf" ) { + soundSystemLocal.alEffecti(e, AL_EAXREVERB_GAINLF, src.ParseInt()); + } else if ( token == "decay time" ) { + soundSystemLocal.alEffectf(e, AL_EAXREVERB_DECAY_TIME, src.ParseFloat()); + } else if ( token == "decay hf ratio" ) { + soundSystemLocal.alEffectf(e, AL_EAXREVERB_DECAY_HFRATIO, src.ParseFloat()); + } else if ( token == "decay lf ratio" ) { + soundSystemLocal.alEffectf(e, AL_EAXREVERB_DECAY_LFRATIO, src.ParseFloat()); + } else if ( token == "reflections" ) { + soundSystemLocal.alEffecti(e, AL_EAXREVERB_REFLECTIONS_GAIN, src.ParseInt()); + } else if ( token == "reflections delay" ) { + soundSystemLocal.alEffectf(e, 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); + } else if ( token == "reverb" ) { + soundSystemLocal.alEffecti(e, AL_EAXREVERB_LATE_REVERB_GAIN, src.ParseInt()); + } else if ( token == "reverb delay" ) { + soundSystemLocal.alEffectf(e, 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); + } else if ( token == "echo time" ) { + soundSystemLocal.alEffectf(e, AL_EAXREVERB_ECHO_TIME, src.ParseFloat()); + } else if ( token == "echo depth" ) { + soundSystemLocal.alEffectf(e, AL_EAXREVERB_ECHO_DEPTH, src.ParseFloat()); + } else if ( token == "modulation time" ) { + soundSystemLocal.alEffectf(e, AL_EAXREVERB_MODULATION_TIME, src.ParseFloat()); + } else if ( token == "modulation depth" ) { + soundSystemLocal.alEffectf(e, AL_EAXREVERB_MODULATION_DEPTH, src.ParseFloat()); + } else if ( token == "air absorption hf" ) { + soundSystemLocal.alEffectf(e, AL_EAXREVERB_AIR_ABSORPTION_GAINHF, src.ParseFloat()); + } else if ( token == "hf reference" ) { + soundSystemLocal.alEffectf(e, AL_EAXREVERB_HFREFERENCE, src.ParseFloat()); + } else if ( token == "lf reference" ) { + soundSystemLocal.alEffectf(e, AL_EAXREVERB_LFREFERENCE, src.ParseFloat()); + } else if ( token == "room rolloff factor" ) { + soundSystemLocal.alEffectf(e, AL_EAXREVERB_ROOM_ROLLOFF_FACTOR, src.ParseFloat()); + } else if ( token == "flags" ) { + src.ParseInt(); // TODO no idea what to do with this + } else { + src.ReadTokenOnLine( &token ); + src.Error( "idEFXFile::ReadEffect: Invalid parameter in reverb definition" ); + } + } while ( 1 ); + + return true; } - /* =============== idEFXFile::LoadFile @@ -215,20 +237,18 @@ bool idEFXFile::LoadFile( const char *filename, bool OSPath ) { while ( !src.EndOfFile() ) { idSoundEffect *effect = new idSoundEffect; - if ( ReadEffect( src, effect ) ) { - effects.Append( effect ); + + if (!effect->alloc()) { + delete effect; + Clear(); + return false; } + + if (ReadEffect(src, effect)) + effects.Append(effect); + else + delete effect; }; return true; } - - -/* -=============== -idEFXFile::UnloadFile -=============== -*/ -void idEFXFile::UnloadFile( void ) { - Clear(); -} diff --git a/neo/sound/snd_local.h b/neo/sound/snd_local.h index 34b00ebf..ed9c773a 100644 --- a/neo/sound/snd_local.h +++ b/neo/sound/snd_local.h @@ -33,15 +33,18 @@ If you have questions concerning this license or the applicable additional terms #ifdef _WIN32 #include #include +#include // broken OpenAL SDK ? #define ID_ALCHAR (ALubyte *) #elif defined( MACOS_X ) #include #include +#include #define ID_ALCHAR #else #include #include +#include #define ID_ALCHAR #endif @@ -595,7 +598,8 @@ public: idVec3 listenerQU; // position in "quake units" int listenerArea; idStr listenerAreaName; - int listenerEnvironmentID; + ALuint listenerEffect; + ALuint listenerSlot; int gameMsec; int game44kHz; @@ -679,7 +683,7 @@ public: virtual void PrintMemInfo( MemInfo_t *mi ); - virtual int IsEAXAvailable( void ); + virtual int IsEFXAvailable( void ); //------------------------- @@ -725,19 +729,22 @@ public: ALCcontext *openalContext; ALsizei openalSourceCount; openalSource_t openalSources[256]; -#if ID_OPENAL_EAX - EAXSet alEAXSet; - EAXGet alEAXGet; - EAXSetBufferMode alEAXSetBufferMode; - EAXGetBufferMode alEAXGetBufferMode; -#endif + + LPALGENEFFECTS alGenEffects; + LPALDELETEEFFECTS alDeleteEffects; + LPALEFFECTI alEffecti; + LPALEFFECTF alEffectf; + LPALEFFECTFV alEffectfv; + LPALGENAUXILIARYEFFECTSLOTS alGenAuxiliaryEffectSlots; + LPALDELETEAUXILIARYEFFECTSLOTS alDeleteAuxiliaryEffectSlots; + LPALAUXILIARYEFFECTSLOTI alAuxiliaryEffectSloti; + idEFXFile EFXDatabase; bool efxloaded; // latches - static bool useEAXReverb; + static bool useEFXReverb; // mark available during initialization, or through an explicit test - static int EAXAvailable; - + static int EFXAvailable; static idCVar s_noSound; static idCVar s_quadraticFalloff; @@ -767,7 +774,6 @@ public: static idCVar s_libOpenAL; static idCVar s_useOpenAL; static idCVar s_useEAXReverb; - static idCVar s_muteEAXReverb; static idCVar s_decompressionLimit; static idCVar s_slowAttenuate; diff --git a/neo/sound/snd_system.cpp b/neo/sound/snd_system.cpp index 72cb4f2b..5ffd1c2f 100644 --- a/neo/sound/snd_system.cpp +++ b/neo/sound/snd_system.cpp @@ -69,22 +69,19 @@ idCVar idSoundSystemLocal::s_enviroSuitVolumeScale( "s_enviroSuitVolumeScale", " idCVar idSoundSystemLocal::s_skipHelltimeFX( "s_skipHelltimeFX", "0", CVAR_SOUND | CVAR_BOOL, "" ); #if ID_OPENAL -// off by default. OpenAL DLL gets loaded on-demand idCVar idSoundSystemLocal::s_libOpenAL( "s_libOpenAL", "openal32.dll", CVAR_SOUND | CVAR_ARCHIVE, "Deprecated, kept for compability" ); idCVar idSoundSystemLocal::s_useOpenAL( "s_useOpenAL", "0", CVAR_SOUND | CVAR_BOOL | CVAR_ARCHIVE, "Deprecated, kept for compability" ); -idCVar idSoundSystemLocal::s_useEAXReverb( "s_useEAXReverb", "0", CVAR_SOUND | CVAR_BOOL | CVAR_ARCHIVE, "use EAX reverb" ); -idCVar idSoundSystemLocal::s_muteEAXReverb( "s_muteEAXReverb", "0", CVAR_SOUND | CVAR_BOOL, "mute eax reverb" ); +idCVar idSoundSystemLocal::s_useEAXReverb( "s_useEAXReverb", "0", CVAR_SOUND | CVAR_BOOL | CVAR_ARCHIVE, "use EFX reverb" ); idCVar idSoundSystemLocal::s_decompressionLimit( "s_decompressionLimit", "6", CVAR_SOUND | CVAR_INTEGER | CVAR_ARCHIVE, "specifies maximum uncompressed sample length in seconds" ); #else idCVar idSoundSystemLocal::s_libOpenAL( "s_libOpenAL", "openal32.dll", CVAR_SOUND | CVAR_ARCHIVE, "OpenAL is not supported in this build" ); idCVar idSoundSystemLocal::s_useOpenAL( "s_useOpenAL", "0", CVAR_SOUND | CVAR_BOOL | CVAR_ROM, "OpenAL is not supported in this build" ); -idCVar idSoundSystemLocal::s_useEAXReverb( "s_useEAXReverb", "0", CVAR_SOUND | CVAR_BOOL | CVAR_ROM, "EAX not available in this build" ); -idCVar idSoundSystemLocal::s_muteEAXReverb( "s_muteEAXReverb", "0", CVAR_SOUND | CVAR_BOOL | CVAR_ROM, "mute eax reverb" ); +idCVar idSoundSystemLocal::s_useEAXReverb( "s_useEAXReverb", "0", CVAR_SOUND | CVAR_BOOL | CVAR_ROM, "EFX not available in this build" ); idCVar idSoundSystemLocal::s_decompressionLimit( "s_decompressionLimit", "6", CVAR_SOUND | CVAR_INTEGER | CVAR_ROM, "specifies maximum uncompressed sample length in seconds" ); #endif -bool idSoundSystemLocal::useEAXReverb = false; -int idSoundSystemLocal::EAXAvailable = -1; +bool idSoundSystemLocal::useEFXReverb = false; +int idSoundSystemLocal::EFXAvailable = -1; idSoundSystemLocal soundSystemLocal; idSoundSystem *soundSystem = &soundSystemLocal; @@ -161,9 +158,6 @@ void ListSounds_f( const idCmdArgs &args ) { common->Printf( "%8d total sounds\n", totalSounds ); common->Printf( "%8d total samples loaded\n", totalSamples ); common->Printf( "%8d kB total system memory used\n", totalMemory >> 10 ); -#if ID_OPENAL - common->Printf( "%8d kB total OpenAL audio memory used\n", ( alGetInteger( alGetEnumValue( "AL_EAX_RAM_SIZE" ) ) - alGetInteger( alGetEnumValue( "AL_EAX_RAM_FREE" ) ) ) >> 10 ); -#endif } /* @@ -330,9 +324,9 @@ void idSoundSystemLocal::Init() { // set up openal device and context common->StartupVariable( "s_useOpenAL", true ); - common->StartupVariable( "s_useEAXReverb", true ); common->Printf( "Setup OpenAL device and context... " ); + openalDevice = alcOpenDevice( NULL ); openalContext = alcCreateContext( openalDevice, NULL ); alcMakeContextCurrent( openalContext ); @@ -344,38 +338,33 @@ void idSoundSystemLocal::Init() { common->Printf( "AL_RENDERER: %s\n", alGetString(AL_RENDERER)); common->Printf( "AL_EXTENSIONS: %s\n", alGetString(AL_EXTENSIONS)); -#if ID_OPENAL_EAX - // try to obtain EAX extensions - if ( idSoundSystemLocal::s_useEAXReverb.GetBool() && alIsExtensionPresent( ID_ALCHAR "EAX4.0" ) ) { - alEAXSet = (EAXSet)alGetProcAddress( ID_ALCHAR "EAXSet" ); - alEAXGet = (EAXGet)alGetProcAddress( ID_ALCHAR "EAXGet" ); - common->Printf( "OpenAL: found EAX 4.0 extension\n" ); - EAXAvailable = 1; - } else { - common->Printf( "OpenAL: EAX 4.0 extension not found\n" ); - idSoundSystemLocal::s_useEAXReverb.SetBool( false ); - alEAXSet = (EAXSet)NULL; - alEAXGet = (EAXGet)NULL; - EAXAvailable = 0; - } -#else - common->Printf("OpenAL: EAX 4.0 not supported in this build\n"); - idSoundSystemLocal::s_useEAXReverb.SetBool( false ); - EAXAvailable = 0; -#endif + // try to obtain EFX extensions + if (alcIsExtensionPresent(openalDevice, "ALC_EXT_EFX")) { + common->Printf( "OpenAL: found EFX extension\n" ); + EFXAvailable = 1; -#if ID_OPENAL_EAX - // try to obtain EAX-RAM extension - not required for operation - if ( alIsExtensionPresent( ID_ALCHAR "EAX-RAM" ) == AL_TRUE ) { - alEAXSetBufferMode = (EAXSetBufferMode)alGetProcAddress( ID_ALCHAR "EAXSetBufferMode" ); - alEAXGetBufferMode = (EAXGetBufferMode)alGetProcAddress( ID_ALCHAR "EAXGetBufferMode" ); - common->Printf( "OpenAL: found EAX-RAM extension, %dkB\\%dkB\n", alGetInteger( alGetEnumValue( ID_ALCHAR "AL_EAX_RAM_FREE" ) ) / 1024, alGetInteger( alGetEnumValue( ID_ALCHAR "AL_EAX_RAM_SIZE" ) ) / 1024 ); + alGenEffects = (LPALGENEFFECTS)alGetProcAddress("alGenEffects"); + alDeleteEffects = (LPALDELETEEFFECTS)alGetProcAddress("alDeleteEffects"); + alEffecti = (LPALEFFECTI)alGetProcAddress("alEffecti"); + alEffectf = (LPALEFFECTF)alGetProcAddress("alEffectf"); + alEffectfv = (LPALEFFECTFV)alGetProcAddress("alEffectfv"); + alGenAuxiliaryEffectSlots = (LPALGENAUXILIARYEFFECTSLOTS)alGetProcAddress("alGenAuxiliaryEffectSlots"); + alDeleteAuxiliaryEffectSlots = (LPALDELETEAUXILIARYEFFECTSLOTS)alGetProcAddress("alDeleteAuxiliaryEffectSlots"); + alAuxiliaryEffectSloti = (LPALAUXILIARYEFFECTSLOTI)alGetProcAddress("alAuxiliaryEffectSloti"); } else { - alEAXSetBufferMode = (EAXSetBufferMode)NULL; - alEAXGetBufferMode = (EAXGetBufferMode)NULL; - common->Printf( "OpenAL: no EAX-RAM extension\n" ); + common->Printf( "OpenAL: EFX extension not found\n" ); + EFXAvailable = 0; + idSoundSystemLocal::s_useEAXReverb.SetBool( false ); + + alGenEffects = NULL; + alDeleteEffects = NULL; + alEffecti = NULL; + alEffectf = NULL; + alEffectfv = NULL; + alGenAuxiliaryEffectSlots = NULL; + alDeleteAuxiliaryEffectSlots = NULL; + alAuxiliaryEffectSloti = NULL; } -#endif ALuint handle; openalSourceCount = 0; @@ -403,11 +392,13 @@ void idSoundSystemLocal::Init() { common->Printf( "OpenAL: found %s\n", alcGetString( openalDevice, ALC_DEVICE_SPECIFIER ) ); common->Printf( "OpenAL: found %d hardware voices\n", openalSourceCount ); + common->Printf( "ALC_EXTENSIONS: %s\n", alcGetString(openalDevice, ALC_EXTENSIONS)); // adjust source count to allow for at least eight stereo sounds to play openalSourceCount -= 8; - useEAXReverb = idSoundSystemLocal::s_useEAXReverb.GetBool(); + useEFXReverb = idSoundSystemLocal::s_useEAXReverb.GetBool(); + efxloaded = false; cmdSystem->AddCommand( "listSounds", ListSounds_f, CMD_FL_SOUND, "lists all sounds" ); cmdSystem->AddCommand( "listSoundDecoders", ListSoundDecoders_f, CMD_FL_SOUND, "list active sound decoders" ); @@ -427,7 +418,7 @@ idSoundSystemLocal::Shutdown void idSoundSystemLocal::Shutdown() { ShutdownHW(); - // EAX or not, the list needs to be cleared + // EFX or not, the list needs to be cleared EFXDatabase.Clear(); efxloaded = false; @@ -991,7 +982,7 @@ void idSoundSystemLocal::BeginLevelLoad() { soundCache->BeginLevelLoad(); if ( efxloaded ) { - EFXDatabase.UnloadFile(); + EFXDatabase.Clear(); efxloaded = false; } } @@ -1007,7 +998,9 @@ void idSoundSystemLocal::EndLevelLoad( const char *mapstring ) { } soundCache->EndLevelLoad(); -#if ID_OPENAL_EAX + if (!useEFXReverb) + return; + idStr efxname( "efxs/" ); idStr mapname( mapstring ); @@ -1022,7 +1015,6 @@ void idSoundSystemLocal::EndLevelLoad( const char *mapstring ) { } else { common->Printf("sound: missing %s\n", efxname.c_str() ); } -#endif } /* @@ -1120,13 +1112,7 @@ void idSoundSystemLocal::FreeOpenALSource( ALuint handle ) { if ( openalSources[i].chan ) { openalSources[i].chan->openalSource = 0; } -#if ID_OPENAL_EAX - // Reset source EAX ROOM level when freeing stereo source - if ( openalSources[i].stereo && alEAXSet ) { - long Room = EAXSOURCE_DEFAULTROOM; - alEAXSet( &EAXPROPERTYID_EAX_Source, EAXSOURCE_ROOM, openalSources[i].handle, &Room, sizeof(Room)); - } -#endif + // Initialize structure openalSources[i].startTime = 0; openalSources[i].chan = NULL; @@ -1300,35 +1286,13 @@ void idSoundSystemLocal::PrintMemInfo( MemInfo_t *mi ) { /* =============== -idSoundSystemLocal::IsEAXAvailable +idSoundSystemLocal::IsEFXAvailable =============== */ -int idSoundSystemLocal::IsEAXAvailable( void ) { -#if !ID_OPENAL || !ID_OPENAL_EAX +int idSoundSystemLocal::IsEFXAvailable( void ) { +#if !ID_OPENAL return -1; #else - ALCdevice *device; - ALCcontext *context; - - if ( EAXAvailable != -1 ) { - return EAXAvailable; - } - - // when dynamically loading the OpenAL subsystem, we need to get a context before alIsExtensionPresent would work - device = alcOpenDevice( NULL ); - context = alcCreateContext( device, NULL ); - alcMakeContextCurrent( context ); - if ( alIsExtensionPresent( ID_ALCHAR "EAX4.0" ) ) { - alcMakeContextCurrent( NULL ); - alcDestroyContext( context ); - alcCloseDevice( device ); - EAXAvailable = 1; - return 1; - } - alcMakeContextCurrent( NULL ); - alcDestroyContext( context ); - alcCloseDevice( device ); - EAXAvailable = 0; - return 0; + return EFXAvailable; #endif } diff --git a/neo/sound/snd_world.cpp b/neo/sound/snd_world.cpp index f8e2fb96..35f95a56 100644 --- a/neo/sound/snd_world.cpp +++ b/neo/sound/snd_world.cpp @@ -48,7 +48,17 @@ void idSoundWorldLocal::Init( idRenderWorld *renderWorld ) { listenerQU.Zero(); listenerArea = 0; listenerAreaName = "Undefined"; - listenerEnvironmentID = -2; + + if (idSoundSystemLocal::useEFXReverb) { + alGetError(); + + soundSystemLocal.alGenAuxiliaryEffectSlots(1, &listenerSlot); + ALuint e = alGetError(); + if (e != AL_NO_ERROR) { + common->Warning("idSoundWorldLocal::Init: alGenAuxiliaryEffectSlots failed: %u", e); + listenerSlot = 0; + } + } gameMsec = 0; game44kHz = 0; @@ -108,6 +118,11 @@ void idSoundWorldLocal::Shutdown() { AVIClose(); + if (idSoundSystemLocal::useEFXReverb && listenerSlot) { + soundSystemLocal.alDeleteAuxiliaryEffectSlots(1, &listenerSlot); + listenerSlot = 0; + } + for ( i = 0; i < emitters.Num(); i++ ) { if ( emitters[i] ) { delete emitters[i]; @@ -450,39 +465,25 @@ void idSoundWorldLocal::MixLoop( int current44kHz, int numSpeakers, float *final alListenerfv( AL_POSITION, listenerPosition ); alListenerfv( AL_ORIENTATION, listenerOrientation ); -#if ID_OPENAL_EAX - if ( soundSystemLocal.s_useEAXReverb.GetBool() ) { + if (idSoundSystemLocal::useEFXReverb) { if ( soundSystemLocal.efxloaded ) { - idSoundEffect *effect = NULL; - int EnvironmentID = -1; + ALuint effect; idStr defaultStr( "default" ); idStr listenerAreaStr( listenerArea ); - soundSystemLocal.EFXDatabase.FindEffect( listenerAreaStr, &effect, &EnvironmentID ); + soundSystemLocal.EFXDatabase.FindEffect( listenerAreaStr, &effect ); if (!effect) - soundSystemLocal.EFXDatabase.FindEffect( listenerAreaName, &effect, &EnvironmentID ); + soundSystemLocal.EFXDatabase.FindEffect( listenerAreaName, &effect ); if (!effect) - soundSystemLocal.EFXDatabase.FindEffect( defaultStr, &effect, &EnvironmentID ); + soundSystemLocal.EFXDatabase.FindEffect( defaultStr, &effect ); // only update if change in settings - if ( soundSystemLocal.s_muteEAXReverb.GetBool() || ( listenerEnvironmentID != EnvironmentID ) ) { - EAXREVERBPROPERTIES EnvironmentParameters; - - // get area reverb setting from EAX Manager - if ( ( effect ) && ( effect->data) && ( memcpy( &EnvironmentParameters, effect->data, effect->datasize ) ) ) { - if ( soundSystemLocal.s_muteEAXReverb.GetBool() ) { - EnvironmentParameters.lRoom = -10000; - EnvironmentID = -2; - } - if ( soundSystemLocal.alEAXSet ) { - soundSystemLocal.alEAXSet( &EAXPROPERTYID_EAX_FXSlot0, EAXREVERB_ALLPARAMETERS, 0, &EnvironmentParameters, sizeof( EnvironmentParameters ) ); - } - } - listenerEnvironmentID = EnvironmentID; + if ( listenerEffect != effect ) { + listenerEffect = effect; + soundSystemLocal.alAuxiliaryEffectSloti(listenerSlot, AL_EFFECTSLOT_EFFECT, effect); } } } -#endif // debugging option to mute all but a single soundEmitter if ( idSoundSystemLocal::s_singleEmitter.GetInteger() > 0 && idSoundSystemLocal::s_singleEmitter.GetInteger() < emitters.Num() ) { @@ -1741,13 +1742,20 @@ void idSoundWorldLocal::AddChannelContribution( idSoundEmitterLocal *sound, idSo alSourcef( chan->openalSource, AL_GAIN, ( volume ) < ( 1.0f ) ? ( volume ) : ( 1.0f ) ); } alSourcei( chan->openalSource, AL_LOOPING, ( looping && chan->soundShader->entries[0]->hardwareBuffer ) ? AL_TRUE : AL_FALSE ); -// TODO is this correct? (was: "!defined(MACOS_X)") -#if ID_OPENAL_EAX +#if 1 alSourcef( chan->openalSource, AL_REFERENCE_DISTANCE, mind ); alSourcef( chan->openalSource, AL_MAX_DISTANCE, maxd ); #endif alSourcef( chan->openalSource, AL_PITCH, ( slowmoActive && !chan->disallowSlow ) ? ( slowmoSpeed ) : ( 1.0f ) ); -#if ID_OPENAL_EAX + + 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 0 // TODO how to port this to efx? long lOcclusion = ( enviroSuitActive ? -1150 : 0); if ( soundSystemLocal.alEAXSet ) { soundSystemLocal.alEAXSet( &EAXPROPERTYID_EAX_Source, EAXSOURCE_OCCLUSION, chan->openalSource, &lOcclusion, sizeof(lOcclusion) ); @@ -1770,11 +1778,6 @@ void idSoundWorldLocal::AddChannelContribution( idSoundEmitterLocal *sound, idSo chan->lastopenalStreamingBuffer[1] = chan->openalStreamingBuffer[1]; chan->lastopenalStreamingBuffer[2] = chan->openalStreamingBuffer[2]; alGenBuffers( 3, &chan->openalStreamingBuffer[0] ); -#if ID_OPENAL_EAX - if ( soundSystemLocal.alEAXSetBufferMode ) { - soundSystemLocal.alEAXSetBufferMode( 3, &chan->openalStreamingBuffer[0], alGetEnumValue( ID_ALCHAR "AL_STORAGE_ACCESSIBLE" ) ); - } -#endif buffers[0] = chan->openalStreamingBuffer[0]; buffers[1] = chan->openalStreamingBuffer[1]; buffers[2] = chan->openalStreamingBuffer[2]; diff --git a/neo/sound/sound.h b/neo/sound/sound.h index d94e3611..b4fb2fa0 100644 --- a/neo/sound/sound.h +++ b/neo/sound/sound.h @@ -341,8 +341,8 @@ public: // prints memory info virtual void PrintMemInfo( MemInfo_t *mi ) = 0; - // is EAX support present - -1: disabled at compile time, 0: no suitable hardware, 1: ok, 2: failed to load OpenAL DLL - virtual int IsEAXAvailable( void ) = 0; + // is EFX support present - -1: disabled at compile time, 0: no suitable hardware, 1: ok + virtual int IsEFXAvailable( void ) = 0; }; extern idSoundSystem *soundSystem;