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;