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.
This commit is contained in:
dhewg 2012-01-08 21:53:51 +01:00
parent 1ce658e835
commit ece2adbdcd
9 changed files with 245 additions and 287 deletions

View file

@ -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
/*

View file

@ -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 );

View file

@ -4,62 +4,35 @@
#ifndef __EFXLIBH
#define __EFXLIBH
#if ID_OPENAL_EAX
#include <eax4.h>
#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 );
idList<idSoundEffect *>effects;
};
///////////////////////////////////////////////////////////
#endif // __EFXLIBH

View file

@ -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 )

View file

@ -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();
}

View file

@ -33,15 +33,18 @@ If you have questions concerning this license or the applicable additional terms
#ifdef _WIN32
#include <al.h>
#include <alc.h>
#include <alext.h>
// broken OpenAL SDK ?
#define ID_ALCHAR (ALubyte *)
#elif defined( MACOS_X )
#include <OpenAL/al.h>
#include <OpenAL/alc.h>
#include <OpenAL/alext.h>
#define ID_ALCHAR
#else
#include <AL/al.h>
#include <AL/alc.h>
#include <AL/alext.h>
#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;

View file

@ -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
}

View file

@ -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];

View file

@ -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;