OpenAL is enabled, EAX fixes and removed DirectSound completely.

This commit is contained in:
Justin Marshall
2026-05-22 10:57:43 -07:00
parent 01d10ecca8
commit 06ea7e7297
20 changed files with 809 additions and 4667 deletions
+21 -25
View File
@@ -355,20 +355,18 @@ void idSoundSample::MakeDefault( void ) {
ncd[i*2+1] = sample;
}
if ( idSoundSystemLocal::useOpenAL ) {
alGetError();
alGenBuffers( 1, &openalBuffer );
if ( alGetError() != AL_NO_ERROR ) {
common->Error( "idSoundCache: error generating OpenAL hardware buffer" );
}
alGetError();
alBufferData( openalBuffer, objectInfo.nChannels==1?AL_FORMAT_MONO16:AL_FORMAT_STEREO16, nonCacheData, objectMemSize, objectInfo.nSamplesPerSec );
if ( alGetError() != AL_NO_ERROR ) {
common->Error( "idSoundCache: error loading data into OpenAL hardware buffer" );
} else {
hardwareBuffer = true;
}
alGetError();
alGenBuffers( 1, &openalBuffer );
if ( alGetError() != AL_NO_ERROR ) {
common->Error( "idSoundCache: error generating OpenAL hardware buffer" );
}
alGetError();
alBufferData( openalBuffer, objectInfo.nChannels==1?AL_FORMAT_MONO16:AL_FORMAT_STEREO16, nonCacheData, objectMemSize, objectInfo.nSamplesPerSec );
if ( alGetError() != AL_NO_ERROR ) {
common->Error( "idSoundCache: error loading data into OpenAL hardware buffer" );
} else {
hardwareBuffer = true;
}
defaultSound = true;
@@ -486,9 +484,8 @@ void idSoundSample::Load( void ) {
CheckForDownSample();
// create hardware audio buffers
if ( idSoundSystemLocal::useOpenAL ) {
// PCM loads directly
if ( objectInfo.wFormatTag == WAVE_FORMAT_TAG_PCM ) {
// PCM loads directly
if ( objectInfo.wFormatTag == WAVE_FORMAT_TAG_PCM ) {
alGetError();
alGenBuffers( 1, &openalBuffer );
if ( alGetError() != AL_NO_ERROR )
@@ -526,8 +523,8 @@ 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 ) {
// OGG decompressed at load time (when smaller than s_decompressionLimit seconds, 6 seconds by default)
if ( objectInfo.wFormatTag == WAVE_FORMAT_TAG_OGG ) {
#if defined(MACOS_X)
if ( ( objectSize < ( ( int ) objectInfo.nSamplesPerSec * idSoundSystemLocal::s_decompressionLimit.GetInteger() ) ) ) {
#else
@@ -610,11 +607,10 @@ void idSoundSample::Load( void ) {
}
}
// Free memory if sample was loaded into hardware
if ( hardwareBuffer ) {
soundCacheAllocator.Free( nonCacheData );
nonCacheData = NULL;
}
// Free memory if sample was loaded into hardware
if ( hardwareBuffer ) {
soundCacheAllocator.Free( nonCacheData );
nonCacheData = NULL;
}
fh.Close();
@@ -628,7 +624,7 @@ idSoundSample::PurgeSoundSample
void idSoundSample::PurgeSoundSample() {
purged = true;
if ( hardwareBuffer && idSoundSystemLocal::useOpenAL ) {
if ( hardwareBuffer ) {
alGetError();
alDeleteBuffers( 1, &openalBuffer );
if ( alGetError() != AL_NO_ERROR ) {
+23
View File
@@ -88,6 +88,29 @@ bool idEFXFile::ReadEffect( idLexer &src, idSoundEffect *effect ) {
if ( token == "reverb" ) {
EAXREVERBPROPERTIES *reverb = ( EAXREVERBPROPERTIES * )Mem_Alloc( sizeof( EAXREVERBPROPERTIES ) );
if ( reverb ) {
memset( reverb, 0, sizeof( EAXREVERBPROPERTIES ) );
reverb->ulEnvironment = EAXREVERB_DEFAULTENVIRONMENT;
reverb->flEnvironmentSize = EAXREVERB_DEFAULTENVIRONMENTSIZE;
reverb->flEnvironmentDiffusion = EAXREVERB_DEFAULTENVIRONMENTDIFFUSION;
reverb->lRoom = EAXREVERB_DEFAULTROOM;
reverb->lRoomHF = EAXREVERB_DEFAULTROOMHF;
reverb->lRoomLF = EAXREVERB_DEFAULTROOMLF;
reverb->flDecayTime = EAXREVERB_DEFAULTDECAYTIME;
reverb->flDecayHFRatio = EAXREVERB_DEFAULTDECAYHFRATIO;
reverb->flDecayLFRatio = EAXREVERB_DEFAULTDECAYLFRATIO;
reverb->lReflections = EAXREVERB_DEFAULTREFLECTIONS;
reverb->flReflectionsDelay = EAXREVERB_DEFAULTREFLECTIONSDELAY;
reverb->lReverb = EAXREVERB_DEFAULTREVERB;
reverb->flReverbDelay = EAXREVERB_DEFAULTREVERBDELAY;
reverb->flEchoTime = EAXREVERB_DEFAULTECHOTIME;
reverb->flEchoDepth = EAXREVERB_DEFAULTECHODEPTH;
reverb->flModulationTime = EAXREVERB_DEFAULTMODULATIONTIME;
reverb->flModulationDepth = EAXREVERB_DEFAULTMODULATIONDEPTH;
reverb->flAirAbsorptionHF = EAXREVERB_DEFAULTAIRABSORPTIONHF;
reverb->flHFReference = EAXREVERB_DEFAULTHFREFERENCE;
reverb->flLFReference = EAXREVERB_DEFAULTLFREFERENCE;
reverb->flRoomRolloffFactor = EAXREVERB_DEFAULTROOMROLLOFFFACTOR;
reverb->ulFlags = EAXREVERB_DEFAULTFLAGS;
src.ReadTokenOnLine( &token );
name = token;
+17 -20
View File
@@ -222,28 +222,25 @@ idSoundChannel::ALStop
===================
*/
void idSoundChannel::ALStop( void ) {
if ( idSoundSystemLocal::useOpenAL ) {
if ( alIsSource( openalSource ) ) {
alSourceStop( openalSource );
alSourcei( openalSource, AL_BUFFER, 0 );
soundSystemLocal.FreeOpenALSource( openalSource );
}
if ( alIsSource( openalSource ) ) {
alSourceStop( openalSource );
alSourcei( openalSource, AL_BUFFER, 0 );
soundSystemLocal.FreeOpenALSource( openalSource );
if ( openalStreamingBuffer[0] && openalStreamingBuffer[1] && openalStreamingBuffer[2] ) {
alGetError();
alDeleteBuffers( 3, &openalStreamingBuffer[0] );
if ( alGetError() == AL_NO_ERROR ) {
openalStreamingBuffer[0] = openalStreamingBuffer[1] = openalStreamingBuffer[2] = 0;
}
}
if ( openalStreamingBuffer[0] && openalStreamingBuffer[1] && openalStreamingBuffer[2] ) {
alGetError();
alDeleteBuffers( 3, &openalStreamingBuffer[0] );
if ( alGetError() == AL_NO_ERROR ) {
openalStreamingBuffer[0] = openalStreamingBuffer[1] = openalStreamingBuffer[2] = 0;
}
}
if ( lastopenalStreamingBuffer[0] && lastopenalStreamingBuffer[1] && lastopenalStreamingBuffer[2] ) {
alGetError();
alDeleteBuffers( 3, &lastopenalStreamingBuffer[0] );
if ( alGetError() == AL_NO_ERROR ) {
lastopenalStreamingBuffer[0] = lastopenalStreamingBuffer[1] = lastopenalStreamingBuffer[2] = 0;
}
if ( lastopenalStreamingBuffer[0] && lastopenalStreamingBuffer[1] && lastopenalStreamingBuffer[2] ) {
alGetError();
alDeleteBuffers( 3, &lastopenalStreamingBuffer[0] );
if ( alGetError() == AL_NO_ERROR ) {
lastopenalStreamingBuffer[0] = lastopenalStreamingBuffer[1] = lastopenalStreamingBuffer[2] = 0;
}
}
}
@@ -452,7 +449,7 @@ void idSoundEmitterLocal::CheckForCompletion( int current44kHzTime ) {
if ( !( chan->parms.soundShaderFlags & SSF_LOOPING ) ) {
ALint state = AL_PLAYING;
if ( idSoundSystemLocal::useOpenAL && alIsSource( chan->openalSource ) ) {
if ( alIsSource( chan->openalSource ) ) {
alGetSourcei( chan->openalSource, AL_SOURCE_STATE, &state );
}
idSlowChannel slow = GetSlowChannel( chan );
+95 -3
View File
@@ -45,8 +45,79 @@ If you have questions concerning this license or the applicable additional terms
#include <AL/alc.h>
#define ID_ALCHAR
#endif
#ifndef OPENAL
#define OPENAL
#endif
#include "../openal/include/efxlib.h"
#ifndef AL_EFFECT_TYPE
#define AL_EFFECT_TYPE 0x8001
#define AL_EFFECT_NULL 0x0000
#define AL_EFFECT_REVERB 0x0001
#define AL_EFFECT_EAXREVERB 0x8000
#define AL_EFFECTSLOT_EFFECT 0x0001
#define AL_EFFECTSLOT_GAIN 0x0002
#define AL_EFFECTSLOT_AUXILIARY_SEND_AUTO 0x0003
#define AL_AUXILIARY_SEND_FILTER 0x20006
#define AL_DIRECT_FILTER 0x20005
#define AL_FILTER_TYPE 0x8001
#define AL_FILTER_NULL 0x0000
#define AL_FILTER_LOWPASS 0x0001
#define AL_LOWPASS_GAIN 0x0001
#define AL_LOWPASS_GAINHF 0x0002
#define AL_REVERB_DENSITY 0x0001
#define AL_REVERB_DIFFUSION 0x0002
#define AL_REVERB_GAIN 0x0003
#define AL_REVERB_GAINHF 0x0004
#define AL_REVERB_DECAY_TIME 0x0005
#define AL_REVERB_DECAY_HFRATIO 0x0006
#define AL_REVERB_REFLECTIONS_GAIN 0x0007
#define AL_REVERB_REFLECTIONS_DELAY 0x0008
#define AL_REVERB_LATE_REVERB_GAIN 0x0009
#define AL_REVERB_LATE_REVERB_DELAY 0x000A
#define AL_REVERB_AIR_ABSORPTION_GAINHF 0x000B
#define AL_REVERB_ROOM_ROLLOFF_FACTOR 0x000C
#define AL_REVERB_DECAY_HFLIMIT 0x000D
#define AL_EAXREVERB_DENSITY 0x0001
#define AL_EAXREVERB_DIFFUSION 0x0002
#define AL_EAXREVERB_GAIN 0x0003
#define AL_EAXREVERB_GAINHF 0x0004
#define AL_EAXREVERB_GAINLF 0x0005
#define AL_EAXREVERB_DECAY_TIME 0x0006
#define AL_EAXREVERB_DECAY_HFRATIO 0x0007
#define AL_EAXREVERB_DECAY_LFRATIO 0x0008
#define AL_EAXREVERB_REFLECTIONS_GAIN 0x0009
#define AL_EAXREVERB_REFLECTIONS_DELAY 0x000A
#define AL_EAXREVERB_REFLECTIONS_PAN 0x000B
#define AL_EAXREVERB_LATE_REVERB_GAIN 0x000C
#define AL_EAXREVERB_LATE_REVERB_DELAY 0x000D
#define AL_EAXREVERB_LATE_REVERB_PAN 0x000E
#define AL_EAXREVERB_ECHO_TIME 0x000F
#define AL_EAXREVERB_ECHO_DEPTH 0x0010
#define AL_EAXREVERB_MODULATION_TIME 0x0011
#define AL_EAXREVERB_MODULATION_DEPTH 0x0012
#define AL_EAXREVERB_AIR_ABSORPTION_GAINHF 0x0013
#define AL_EAXREVERB_HFREFERENCE 0x0014
#define AL_EAXREVERB_LFREFERENCE 0x0015
#define AL_EAXREVERB_ROOM_ROLLOFF_FACTOR 0x0016
#define AL_EAXREVERB_DECAY_HFLIMIT 0x0017
#endif
typedef void ( ALAPIENTRY *EfxGenEffects )( ALsizei, ALuint * );
typedef void ( ALAPIENTRY *EfxDeleteEffects )( ALsizei, const ALuint * );
typedef void ( ALAPIENTRY *EfxEffecti )( ALuint, ALenum, ALint );
typedef void ( ALAPIENTRY *EfxEffectf )( ALuint, ALenum, ALfloat );
typedef void ( ALAPIENTRY *EfxEffectfv )( ALuint, ALenum, const ALfloat * );
typedef void ( ALAPIENTRY *EfxGenAuxiliaryEffectSlots )( ALsizei, ALuint * );
typedef void ( ALAPIENTRY *EfxDeleteAuxiliaryEffectSlots )( ALsizei, const ALuint * );
typedef void ( ALAPIENTRY *EfxAuxiliaryEffectSloti )( ALuint, ALenum, ALint );
typedef void ( ALAPIENTRY *EfxAuxiliaryEffectSlotf )( ALuint, ALenum, ALfloat );
typedef void ( ALAPIENTRY *EfxSource3i )( ALuint, ALenum, ALint, ALint, ALint );
typedef void ( ALAPIENTRY *EfxGenFilters )( ALsizei, ALuint * );
typedef void ( ALAPIENTRY *EfxDeleteFilters )( ALsizei, const ALuint * );
typedef void ( ALAPIENTRY *EfxFilteri )( ALuint, ALenum, ALint );
typedef void ( ALAPIENTRY *EfxFilterf )( ALuint, ALenum, ALfloat );
// demo sound commands
typedef enum {
SCMD_STATE, // followed by a load game state
@@ -258,7 +329,7 @@ public:
/*
===================================================================================
Encapsulates functionality of a DirectSound buffer.
Encapsulates functionality of a legacy software-mixer output buffer.
===================================================================================
*/
@@ -740,6 +811,10 @@ public:
ALuint AllocOpenALSource( idSoundChannel *chan, bool looping, bool stereo );
void FreeOpenALSource( ALuint handle );
bool InitOpenALEFX( void );
void ShutdownOpenALEFX( void );
void ApplyOpenALReverb( const EAXREVERBPROPERTIES &reverb );
void ApplyOpenALSourceEffects( ALuint source, long occlusion, bool stereo );
#ifdef PREY
virtual int GetSubtitleIndex(const char* soundName);
@@ -789,10 +864,28 @@ public:
EAXGet alEAXGet;
EAXSetBufferMode alEAXSetBufferMode;
EAXGetBufferMode alEAXGetBufferMode;
EfxGenEffects alGenEffects;
EfxDeleteEffects alDeleteEffects;
EfxEffecti alEffecti;
EfxEffectf alEffectf;
EfxEffectfv alEffectfv;
EfxGenAuxiliaryEffectSlots alGenAuxiliaryEffectSlots;
EfxDeleteAuxiliaryEffectSlots alDeleteAuxiliaryEffectSlots;
EfxAuxiliaryEffectSloti alAuxiliaryEffectSloti;
EfxAuxiliaryEffectSlotf alAuxiliaryEffectSlotf;
EfxSource3i alSource3i;
EfxGenFilters alGenFilters;
EfxDeleteFilters alDeleteFilters;
EfxFilteri alFilteri;
EfxFilterf alFilterf;
ALuint openalReverbEffect;
ALuint openalReverbSlot;
ALuint openalOcclusionFilter;
bool openalEFXAvailable;
bool openalEFXEAXReverb;
idEFXFile EFXDatabase;
bool efxloaded;
// latches
static bool useOpenAL;
static bool useEAXReverb;
// mark available during initialization, or through an explicit test
static int EAXAvailable;
@@ -824,7 +917,6 @@ public:
static idCVar s_clipVolumes;
static idCVar s_realTimeDecoding;
static idCVar s_libOpenAL;
static idCVar s_useOpenAL;
static idCVar s_useEAXReverb;
static idCVar s_muteEAXReverb;
static idCVar s_decompressionLimit;
+294 -208
View File
@@ -29,9 +29,9 @@ If you have questions concerning this license or the applicable additional terms
#include "precompiled.h"
#pragma hdrstop
#include <initguid.h>
#include "snd_local.h"
#include <initguid.h>
#include <thread>
#include <atomic>
#include <chrono>
@@ -74,35 +74,17 @@ idCVar idSoundSystemLocal::s_reverbFeedback( "s_reverbFeedback", "0.333", CVAR_S
idCVar idSoundSystemLocal::s_enviroSuitVolumeScale( "s_enviroSuitVolumeScale", "0.9", CVAR_SOUND | CVAR_FLOAT, "" );
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, "OpenAL DLL name/path" );
idCVar idSoundSystemLocal::s_useOpenAL( "s_useOpenAL", "0", CVAR_SOUND | CVAR_BOOL | CVAR_ARCHIVE, "use OpenAL" );
idCVar idSoundSystemLocal::s_useEAXReverb( "s_useEAXReverb", "0", CVAR_SOUND | CVAR_BOOL | CVAR_ARCHIVE, "use EAX reverb" );
idCVar idSoundSystemLocal::s_libOpenAL( "s_libOpenAL", "OpenAL32.dll", CVAR_SOUND | CVAR_ARCHIVE, "OpenAL Soft DLL name/path" );
idCVar idSoundSystemLocal::s_useEAXReverb( "s_useEAXReverb", "1", CVAR_SOUND | CVAR_BOOL | CVAR_ARCHIVE, "use OpenAL EFX/EAX reverb" );
idCVar idSoundSystemLocal::s_muteEAXReverb( "s_muteEAXReverb", "0", CVAR_SOUND | CVAR_BOOL, "mute eax 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_decompressionLimit( "s_decompressionLimit", "6", CVAR_SOUND | CVAR_INTEGER | CVAR_ROM, "specifies maximum uncompressed sample length in seconds" );
#endif
bool idSoundSystemLocal::useOpenAL = false;
bool idSoundSystemLocal::useEAXReverb = false;
int idSoundSystemLocal::EAXAvailable = -1;
idSoundSystemLocal soundSystemLocal;
idSoundSystem *soundSystem = &soundSystemLocal;
// Define EAX 4.0 GUIDs
DEFINE_GUID(EAXPROPERTYID_EAX40_Source,
0xA8FA6881, 0x9FDA, 0x11D2, 0xBA, 0xA0, 0x00, 0xA0, 0xC9, 0x22, 0x31, 0x96);
DEFINE_GUID(EAXPROPERTYID_EAX40_FXSlot0,
0xA8FA6882, 0x9FDA, 0x11D2, 0xBA, 0xA0, 0x00, 0xA0, 0xC9, 0x22, 0x31, 0x96);
static std::thread g_soundAsyncThread;
static std::atomic<bool> g_soundAsyncRunning{ false };
@@ -131,6 +113,163 @@ void StopSoundAsyncThread() {
}
}
static float MillibelToGain( const long millibels ) {
if ( millibels <= -10000 ) {
return 0.0f;
}
if ( millibels >= 0 ) {
return 1.0f;
}
return powf( 10.0f, (float)millibels / 2000.0f );
}
static float ClampALFloat( const float value, const float minValue, const float maxValue ) {
if ( value < minValue ) {
return minValue;
}
if ( value > maxValue ) {
return maxValue;
}
return value;
}
bool idSoundSystemLocal::InitOpenALEFX( void ) {
alGenEffects = (EfxGenEffects)alGetProcAddress( ID_ALCHAR "alGenEffects" );
alDeleteEffects = (EfxDeleteEffects)alGetProcAddress( ID_ALCHAR "alDeleteEffects" );
alEffecti = (EfxEffecti)alGetProcAddress( ID_ALCHAR "alEffecti" );
alEffectf = (EfxEffectf)alGetProcAddress( ID_ALCHAR "alEffectf" );
alEffectfv = (EfxEffectfv)alGetProcAddress( ID_ALCHAR "alEffectfv" );
alGenAuxiliaryEffectSlots = (EfxGenAuxiliaryEffectSlots)alGetProcAddress( ID_ALCHAR "alGenAuxiliaryEffectSlots" );
alDeleteAuxiliaryEffectSlots = (EfxDeleteAuxiliaryEffectSlots)alGetProcAddress( ID_ALCHAR "alDeleteAuxiliaryEffectSlots" );
alAuxiliaryEffectSloti = (EfxAuxiliaryEffectSloti)alGetProcAddress( ID_ALCHAR "alAuxiliaryEffectSloti" );
alAuxiliaryEffectSlotf = (EfxAuxiliaryEffectSlotf)alGetProcAddress( ID_ALCHAR "alAuxiliaryEffectSlotf" );
alSource3i = (EfxSource3i)alGetProcAddress( ID_ALCHAR "alSource3i" );
alGenFilters = (EfxGenFilters)alGetProcAddress( ID_ALCHAR "alGenFilters" );
alDeleteFilters = (EfxDeleteFilters)alGetProcAddress( ID_ALCHAR "alDeleteFilters" );
alFilteri = (EfxFilteri)alGetProcAddress( ID_ALCHAR "alFilteri" );
alFilterf = (EfxFilterf)alGetProcAddress( ID_ALCHAR "alFilterf" );
if ( !alGenEffects || !alDeleteEffects || !alEffecti || !alEffectf || !alEffectfv ||
!alGenAuxiliaryEffectSlots || !alDeleteAuxiliaryEffectSlots || !alAuxiliaryEffectSloti ||
!alAuxiliaryEffectSlotf || !alSource3i || !alGenFilters || !alDeleteFilters ||
!alFilteri || !alFilterf ) {
return false;
}
alGetError();
alGenEffects( 1, &openalReverbEffect );
alGenAuxiliaryEffectSlots( 1, &openalReverbSlot );
alGenFilters( 1, &openalOcclusionFilter );
if ( alGetError() != AL_NO_ERROR ) {
ShutdownOpenALEFX();
return false;
}
openalEFXEAXReverb = alGetEnumValue( ID_ALCHAR "AL_EFFECT_EAXREVERB" ) != 0;
alEffecti( openalReverbEffect, AL_EFFECT_TYPE, openalEFXEAXReverb ? AL_EFFECT_EAXREVERB : AL_EFFECT_REVERB );
alAuxiliaryEffectSlotf( openalReverbSlot, AL_EFFECTSLOT_GAIN, 1.0f );
alAuxiliaryEffectSloti( openalReverbSlot, AL_EFFECTSLOT_EFFECT, openalReverbEffect );
alFilteri( openalOcclusionFilter, AL_FILTER_TYPE, AL_FILTER_LOWPASS );
openalEFXAvailable = alGetError() == AL_NO_ERROR;
return openalEFXAvailable;
}
void idSoundSystemLocal::ShutdownOpenALEFX( void ) {
if ( openalReverbSlot && alAuxiliaryEffectSloti ) {
alAuxiliaryEffectSloti( openalReverbSlot, AL_EFFECTSLOT_EFFECT, AL_EFFECT_NULL );
}
if ( openalOcclusionFilter && alDeleteFilters ) {
alDeleteFilters( 1, &openalOcclusionFilter );
}
if ( openalReverbSlot && alDeleteAuxiliaryEffectSlots ) {
alDeleteAuxiliaryEffectSlots( 1, &openalReverbSlot );
}
if ( openalReverbEffect && alDeleteEffects ) {
alDeleteEffects( 1, &openalReverbEffect );
}
openalReverbEffect = 0;
openalReverbSlot = 0;
openalOcclusionFilter = 0;
openalEFXAvailable = false;
openalEFXEAXReverb = false;
}
void idSoundSystemLocal::ApplyOpenALReverb( const EAXREVERBPROPERTIES &reverb ) {
if ( !openalEFXAvailable ) {
return;
}
const float roomGain = MillibelToGain( reverb.lRoom );
const float roomHFGain = MillibelToGain( reverb.lRoomHF );
const float reflectionsGain = MillibelToGain( reverb.lReflections );
const float lateReverbGain = MillibelToGain( reverb.lReverb );
const ALfloat reflectionsPan[3] = { reverb.vReflectionsPan.x, reverb.vReflectionsPan.y, reverb.vReflectionsPan.z };
const ALfloat lateReverbPan[3] = { reverb.vReverbPan.x, reverb.vReverbPan.y, reverb.vReverbPan.z };
alEffecti( openalReverbEffect, AL_EFFECT_TYPE, openalEFXEAXReverb ? AL_EFFECT_EAXREVERB : AL_EFFECT_REVERB );
if ( !openalEFXEAXReverb ) {
alEffectf( openalReverbEffect, AL_REVERB_DENSITY, ClampALFloat( reverb.flEnvironmentSize / 16.0f, 0.0f, 1.0f ) );
alEffectf( openalReverbEffect, AL_REVERB_DIFFUSION, ClampALFloat( reverb.flEnvironmentDiffusion, 0.0f, 1.0f ) );
alEffectf( openalReverbEffect, AL_REVERB_GAIN, roomGain );
alEffectf( openalReverbEffect, AL_REVERB_GAINHF, roomHFGain );
alEffectf( openalReverbEffect, AL_REVERB_DECAY_TIME, ClampALFloat( reverb.flDecayTime, 0.1f, 20.0f ) );
alEffectf( openalReverbEffect, AL_REVERB_DECAY_HFRATIO, ClampALFloat( reverb.flDecayHFRatio, 0.1f, 2.0f ) );
alEffectf( openalReverbEffect, AL_REVERB_REFLECTIONS_GAIN, reflectionsGain );
alEffectf( openalReverbEffect, AL_REVERB_REFLECTIONS_DELAY, ClampALFloat( reverb.flReflectionsDelay, 0.0f, 0.3f ) );
alEffectf( openalReverbEffect, AL_REVERB_LATE_REVERB_GAIN, lateReverbGain );
alEffectf( openalReverbEffect, AL_REVERB_LATE_REVERB_DELAY, ClampALFloat( reverb.flReverbDelay, 0.0f, 0.1f ) );
alEffectf( openalReverbEffect, AL_REVERB_AIR_ABSORPTION_GAINHF, ClampALFloat( MillibelToGain( (long)( reverb.flAirAbsorptionHF * 1000.0f ) ), 0.892f, 1.0f ) );
alEffectf( openalReverbEffect, AL_REVERB_ROOM_ROLLOFF_FACTOR, ClampALFloat( reverb.flRoomRolloffFactor, 0.0f, 10.0f ) );
alEffecti( openalReverbEffect, AL_REVERB_DECAY_HFLIMIT, ( reverb.ulFlags & EAXREVERBFLAGS_DECAYHFLIMIT ) ? AL_TRUE : AL_FALSE );
alAuxiliaryEffectSloti( openalReverbSlot, AL_EFFECTSLOT_EFFECT, openalReverbEffect );
return;
}
alEffectf( openalReverbEffect, AL_EAXREVERB_DENSITY, ClampALFloat( reverb.flEnvironmentSize / 16.0f, 0.0f, 1.0f ) );
alEffectf( openalReverbEffect, AL_EAXREVERB_DIFFUSION, ClampALFloat( reverb.flEnvironmentDiffusion, 0.0f, 1.0f ) );
alEffectf( openalReverbEffect, AL_EAXREVERB_GAIN, roomGain );
alEffectf( openalReverbEffect, AL_EAXREVERB_GAINHF, roomHFGain );
alEffectf( openalReverbEffect, AL_EAXREVERB_DECAY_TIME, ClampALFloat( reverb.flDecayTime, 0.1f, 20.0f ) );
alEffectf( openalReverbEffect, AL_EAXREVERB_DECAY_HFRATIO, ClampALFloat( reverb.flDecayHFRatio, 0.1f, 2.0f ) );
alEffectf( openalReverbEffect, AL_EAXREVERB_REFLECTIONS_GAIN, reflectionsGain );
alEffectf( openalReverbEffect, AL_EAXREVERB_REFLECTIONS_DELAY, ClampALFloat( reverb.flReflectionsDelay, 0.0f, 0.3f ) );
alEffectf( openalReverbEffect, AL_EAXREVERB_LATE_REVERB_GAIN, lateReverbGain );
alEffectf( openalReverbEffect, AL_EAXREVERB_LATE_REVERB_DELAY, ClampALFloat( reverb.flReverbDelay, 0.0f, 0.1f ) );
alEffectf( openalReverbEffect, AL_EAXREVERB_AIR_ABSORPTION_GAINHF, ClampALFloat( MillibelToGain( (long)( reverb.flAirAbsorptionHF * 1000.0f ) ), 0.892f, 1.0f ) );
alEffectf( openalReverbEffect, AL_EAXREVERB_ROOM_ROLLOFF_FACTOR, ClampALFloat( reverb.flRoomRolloffFactor, 0.0f, 10.0f ) );
if ( openalEFXEAXReverb ) {
alEffectf( openalReverbEffect, AL_EAXREVERB_GAINLF, MillibelToGain( reverb.lRoomLF ) );
alEffectf( openalReverbEffect, AL_EAXREVERB_DECAY_LFRATIO, ClampALFloat( reverb.flDecayLFRatio, 0.1f, 2.0f ) );
alEffectfv( openalReverbEffect, AL_EAXREVERB_REFLECTIONS_PAN, reflectionsPan );
alEffectfv( openalReverbEffect, AL_EAXREVERB_LATE_REVERB_PAN, lateReverbPan );
alEffectf( openalReverbEffect, AL_EAXREVERB_ECHO_TIME, ClampALFloat( reverb.flEchoTime, 0.075f, 0.25f ) );
alEffectf( openalReverbEffect, AL_EAXREVERB_ECHO_DEPTH, ClampALFloat( reverb.flEchoDepth, 0.0f, 1.0f ) );
alEffectf( openalReverbEffect, AL_EAXREVERB_MODULATION_TIME, ClampALFloat( reverb.flModulationTime, 0.04f, 4.0f ) );
alEffectf( openalReverbEffect, AL_EAXREVERB_MODULATION_DEPTH, ClampALFloat( reverb.flModulationDepth, 0.0f, 1.0f ) );
alEffectf( openalReverbEffect, AL_EAXREVERB_HFREFERENCE, ClampALFloat( reverb.flHFReference, 1000.0f, 20000.0f ) );
alEffectf( openalReverbEffect, AL_EAXREVERB_LFREFERENCE, ClampALFloat( reverb.flLFReference, 20.0f, 1000.0f ) );
alEffecti( openalReverbEffect, AL_EAXREVERB_DECAY_HFLIMIT, ( reverb.ulFlags & EAXREVERBFLAGS_DECAYHFLIMIT ) ? AL_TRUE : AL_FALSE );
}
alAuxiliaryEffectSloti( openalReverbSlot, AL_EFFECTSLOT_EFFECT, openalReverbEffect );
}
void idSoundSystemLocal::ApplyOpenALSourceEffects( ALuint source, long occlusion, bool stereo ) {
if ( openalEFXAvailable ) {
alSource3i( source, AL_AUXILIARY_SEND_FILTER, stereo ? 0 : openalReverbSlot, 0, AL_FILTER_NULL );
if ( occlusion < 0 ) {
const float gain = MillibelToGain( occlusion );
alFilterf( openalOcclusionFilter, AL_LOWPASS_GAIN, gain );
alFilterf( openalOcclusionFilter, AL_LOWPASS_GAINHF, gain );
alSourcei( source, AL_DIRECT_FILTER, openalOcclusionFilter );
} else {
alSourcei( source, AL_DIRECT_FILTER, AL_FILTER_NULL );
}
} else if ( alEAXSet ) {
alEAXSet( &EAXPROPERTYID_EAX_Source, EAXSOURCE_OCCLUSION, source, &occlusion, sizeof( occlusion ) );
}
}
/*
===============
SoundReloadSounds_f
@@ -203,9 +342,9 @@ 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( (ALubyte*)"AL_EAX_RAM_SIZE" ) ) - alGetInteger( alGetEnumValue( (ALubyte*)"AL_EAX_RAM_FREE" ) ) ) >> 10 );
#endif
if ( alIsExtensionPresent( ID_ALCHAR "EAX-RAM" ) == AL_TRUE ) {
common->Printf( "%8d kB total OpenAL audio memory used\n", ( alGetInteger( alGetEnumValue( ID_ALCHAR "AL_EAX_RAM_SIZE" ) ) - alGetInteger( alGetEnumValue( ID_ALCHAR "AL_EAX_RAM_FREE" ) ) ) >> 10 );
}
}
/*
@@ -364,6 +503,32 @@ void idSoundSystemLocal::Init() {
finalMixBuffer = (float *) ( ( ( (INT_PTR)realAccum ) + 15 ) & ~15 );
graph = NULL;
openalDevice = NULL;
openalContext = NULL;
openalSourceCount = 0;
alEAXSet = (EAXSet)NULL;
alEAXGet = (EAXGet)NULL;
alEAXSetBufferMode = (EAXSetBufferMode)NULL;
alEAXGetBufferMode = (EAXGetBufferMode)NULL;
alGenEffects = NULL;
alDeleteEffects = NULL;
alEffecti = NULL;
alEffectf = NULL;
alEffectfv = NULL;
alGenAuxiliaryEffectSlots = NULL;
alDeleteAuxiliaryEffectSlots = NULL;
alAuxiliaryEffectSloti = NULL;
alAuxiliaryEffectSlotf = NULL;
alSource3i = NULL;
alGenFilters = NULL;
alDeleteFilters = NULL;
alFilteri = NULL;
alFilterf = NULL;
openalReverbEffect = 0;
openalReverbSlot = 0;
openalOcclusionFilter = 0;
openalEFXAvailable = false;
openalEFXEAXReverb = false;
if ( !s_noSound.GetBool() ) {
idSampleDecoder::Init();
@@ -371,91 +536,81 @@ void idSoundSystemLocal::Init() {
}
// set up openal device and context
common->StartupVariable( "s_useOpenAL", true );
common->StartupVariable( "s_useEAXReverb", true );
if ( idSoundSystemLocal::s_useOpenAL.GetBool() || idSoundSystemLocal::s_useEAXReverb.GetBool() ) {
if ( !s_noSound.GetBool() ) {
if ( !Sys_LoadOpenAL() ) {
idSoundSystemLocal::s_useOpenAL.SetBool( false );
} else {
common->Printf( "Setup OpenAL device and context... " );
openalDevice = alcOpenDevice( NULL );
common->Error( "OpenAL is required but %s could not be loaded", s_libOpenAL.GetString() );
}
common->Printf( "Setup OpenAL device and context... " );
openalDevice = alcOpenDevice( NULL );
if ( openalDevice ) {
openalContext = alcCreateContext( openalDevice, NULL );
alcMakeContextCurrent( openalContext );
common->Printf( "Done.\n" );
// try to obtain EAX extensions
if ( idSoundSystemLocal::s_useEAXReverb.GetBool() && alIsExtensionPresent( ID_ALCHAR "EAX4.0" ) ) {
idSoundSystemLocal::s_useOpenAL.SetBool( true ); // EAX presence causes AL enable
alEAXSet = (EAXSet)alGetProcAddress( ID_ALCHAR "EAXSet" );
alEAXGet = (EAXGet)alGetProcAddress( ID_ALCHAR "EAXGet" );
common->Printf( "OpenAL: found EAX 4.0 extension\n" );
} else {
common->Printf( "OpenAL: EAX 4.0 extension not found\n" );
idSoundSystemLocal::s_useEAXReverb.SetBool( false );
alEAXSet = (EAXSet)NULL;
alEAXGet = (EAXGet)NULL;
}
// 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 );
} else {
alEAXSetBufferMode = (EAXSetBufferMode)NULL;
alEAXGetBufferMode = (EAXGetBufferMode)NULL;
common->Printf( "OpenAL: no EAX-RAM extension\n" );
}
if ( !idSoundSystemLocal::s_useOpenAL.GetBool() ) {
common->Printf( "OpenAL: disabling ( no EAX ). Using legacy mixer.\n" );
alcMakeContextCurrent( NULL );
}
if ( !openalDevice || !openalContext || !alcMakeContextCurrent( openalContext ) ) {
common->Printf( "failed.\n" );
if ( openalContext ) {
alcDestroyContext( openalContext );
openalContext = NULL;
}
if ( openalDevice ) {
alcCloseDevice( openalDevice );
openalDevice = NULL;
} else {
ALuint handle;
openalSourceCount = 0;
while ( openalSourceCount < 256 ) {
alGetError();
alGenSources( 1, &handle );
if ( alGetError() != AL_NO_ERROR ) {
break;
} else {
// store in source array
openalSources[openalSourceCount].handle = handle;
openalSources[openalSourceCount].startTime = 0;
openalSources[openalSourceCount].chan = NULL;
openalSources[openalSourceCount].inUse = false;
openalSources[openalSourceCount].looping = false;
// initialise sources
alSourcef( handle, AL_ROLLOFF_FACTOR, 0.0f );
// found one source
openalSourceCount++;
}
}
common->Printf( "OpenAL: found %s\n", alcGetString( openalDevice, ALC_DEVICE_SPECIFIER ) );
common->Printf( "OpenAL: found %d hardware voices\n", openalSourceCount );
// adjust source count to allow for at least eight stereo sounds to play
openalSourceCount -= 8;
EAXAvailable = 1;
}
common->Error( "OpenAL device/context initialization failed" );
}
common->Printf( "Done.\n" );
if ( idSoundSystemLocal::s_useEAXReverb.GetBool() && InitOpenALEFX() ) {
common->Printf( "OpenAL: found EFX%s reverb\n", openalEFXEAXReverb ? " EAX" : "" );
EAXAvailable = 1;
} else 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: no EFX/EAX reverb extension\n" );
idSoundSystemLocal::s_useEAXReverb.SetBool( false );
alEAXSet = (EAXSet)NULL;
alEAXGet = (EAXGet)NULL;
EAXAvailable = 0;
}
// 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 );
} else {
alEAXSetBufferMode = (EAXSetBufferMode)NULL;
alEAXGetBufferMode = (EAXGetBufferMode)NULL;
common->Printf( "OpenAL: no EAX-RAM extension\n" );
}
ALuint handle;
openalSourceCount = 0;
while ( openalSourceCount < 256 ) {
alGetError();
alGenSources( 1, &handle );
if ( alGetError() != AL_NO_ERROR ) {
break;
}
openalSources[openalSourceCount].handle = handle;
openalSources[openalSourceCount].startTime = 0;
openalSources[openalSourceCount].chan = NULL;
openalSources[openalSourceCount].inUse = false;
openalSources[openalSourceCount].looping = false;
openalSources[openalSourceCount].stereo = false;
alSourcef( handle, AL_ROLLOFF_FACTOR, 0.0f );
openalSourceCount++;
}
common->Printf( "OpenAL: found %s\n", alcGetString( openalDevice, ALC_DEVICE_SPECIFIER ) );
common->Printf( "OpenAL: found %d voices\n", openalSourceCount );
}
useOpenAL = idSoundSystemLocal::s_useOpenAL.GetBool();
useEAXReverb = idSoundSystemLocal::s_useEAXReverb.GetBool();
StartSoundAsyncThread();
@@ -484,13 +639,9 @@ void idSoundSystemLocal::Shutdown() {
EFXDatabase.Clear();
// destroy openal sources
if ( useOpenAL ) {
if ( openalContext ) {
efxloaded = false;
// adjust source count back up to allow for freeing of all resources
openalSourceCount += 8;
for ( ALsizei i = 0; i < openalSourceCount; i++ ) {
// stop source
alSourceStop( openalSources[i].handle );
@@ -514,7 +665,8 @@ void idSoundSystemLocal::Shutdown() {
soundCache = NULL;
// destroy openal device and context
if ( useOpenAL ) {
if ( openalContext ) {
ShutdownOpenALEFX();
alcMakeContextCurrent( NULL );
alcDestroyContext( openalContext );
@@ -547,20 +699,18 @@ bool idSoundSystemLocal::InitHW() {
return false;
}
if ( !useOpenAL ) {
if ( !snd_audio_hw->Initialize() ) {
delete snd_audio_hw;
snd_audio_hw = NULL;
return false;
}
if ( snd_audio_hw->GetNumberOfSpeakers() == 0 ) {
return false;
}
// put the real number in there
s_numberOfSpeakers.SetInteger( snd_audio_hw->GetNumberOfSpeakers() );
if ( !snd_audio_hw->Initialize() ) {
delete snd_audio_hw;
snd_audio_hw = NULL;
return false;
}
if ( snd_audio_hw->GetNumberOfSpeakers() == 0 ) {
return false;
}
// put the real number in there
s_numberOfSpeakers.SetInteger( snd_audio_hw->GetNumberOfSpeakers() );
isInitialized = true;
shutdown = false;
@@ -676,20 +826,9 @@ int idSoundSystemLocal::AsyncUpdate( int inTime ) {
ulong dwCurrentWritePos;
dword dwCurrentBlock;
// If not using openal, get actual playback position from sound hardware
if ( useOpenAL ) {
// here we do it in samples ( overflows in 27 hours or so )
dwCurrentWritePos = idMath::Ftol( (float)Sys_Milliseconds() * 44.1f ) % ( MIXBUFFER_SAMPLES * ROOM_SLICES_IN_BUFFER );
dwCurrentBlock = dwCurrentWritePos / MIXBUFFER_SAMPLES;
} else {
// and here in bytes
// get the current byte position in the buffer where the sound hardware is currently reading
if ( !snd_audio_hw->GetCurrentPosition( &dwCurrentWritePos ) ) {
return 0;
}
// mixBufferSize is in bytes
dwCurrentBlock = dwCurrentWritePos / snd_audio_hw->GetMixBufferSize();
}
// here we do it in samples ( overflows in 27 hours or so )
dwCurrentWritePos = idMath::Ftol( (float)Sys_Milliseconds() * 44.1f ) % ( MIXBUFFER_SAMPLES * ROOM_SLICES_IN_BUFFER );
dwCurrentBlock = dwCurrentWritePos / MIXBUFFER_SAMPLES;
if ( nextWriteBlock == 0xffffffff ) {
nextWriteBlock = dwCurrentBlock;
@@ -699,17 +838,6 @@ int idSoundSystemLocal::AsyncUpdate( int inTime ) {
return 0;
}
// lock the buffer so we can actually write to it
short *fBlock = NULL;
ulong fBlockLen = 0;
if ( !useOpenAL ) {
snd_audio_hw->Lock( (void **)&fBlock, &fBlockLen );
if ( !fBlock ) {
return 0;
}
}
int j;
soundStats.runs++;
soundStats.activeSounds = 0;
@@ -742,37 +870,16 @@ int idSoundSystemLocal::AsyncUpdate( int inTime ) {
soundStats.missedWindow++;
}
if ( useOpenAL ) {
// enable audio hardware caching
alcSuspendContext( openalContext );
} else {
// clear the buffer for all the mixing output
SIMDProcessor->Memset( finalMixBuffer, 0, MIXBUFFER_SAMPLES * sizeof(float) * numSpeakers );
}
// enable audio hardware caching
alcSuspendContext( openalContext );
// let the active sound world mix all the channels in unless muted or avi demo recording
if ( !muted && currentSoundWorld && !currentSoundWorld->fpa[0] ) {
currentSoundWorld->MixLoop( newSoundTime, numSpeakers, finalMixBuffer );
}
if ( useOpenAL ) {
// disable audio hardware caching (this updates ALL settings since last alcSuspendContext)
alcProcessContext( openalContext );
} else {
short *dest = fBlock + nextWriteSamples * numSpeakers;
SIMDProcessor->MixedSoundToSamples( dest, finalMixBuffer, MIXBUFFER_SAMPLES * numSpeakers );
// allow swapping the left / right speaker channels for people with miswired systems
if ( numSpeakers == 2 && s_reverse.GetBool() ) {
for( j = 0; j < MIXBUFFER_SAMPLES; j++ ) {
short temp = dest[j*2];
dest[j*2] = dest[j*2+1];
dest[j*2+1] = temp;
}
}
snd_audio_hw->Unlock( fBlock, fBlockLen );
}
// disable audio hardware caching (this updates ALL settings since last alcSuspendContext)
alcProcessContext( openalContext );
CurrentSoundTime = newSoundTime;
@@ -795,10 +902,6 @@ int idSoundSystemLocal::AsyncUpdateWrite( int inTime ) {
return 0;
}
if ( !useOpenAL ) {
snd_audio_hw->Flush();
}
unsigned int dwCurrentBlock = (unsigned int)( inTime * 44.1f / MIXBUFFER_SAMPLES );
if ( nextWriteBlock == 0xffffffff ) {
@@ -816,38 +919,16 @@ int idSoundSystemLocal::AsyncUpdateWrite( int inTime ) {
int sampleTime = dwCurrentBlock * MIXBUFFER_SAMPLES;
int numSpeakers = snd_audio_hw->GetNumberOfSpeakers();
if ( useOpenAL ) {
// enable audio hardware caching
alcSuspendContext( openalContext );
} else {
// clear the buffer for all the mixing output
SIMDProcessor->Memset( finalMixBuffer, 0, MIXBUFFER_SAMPLES * sizeof(float) * numSpeakers );
}
// enable audio hardware caching
alcSuspendContext( openalContext );
// let the active sound world mix all the channels in unless muted or avi demo recording
if ( !muted && currentSoundWorld && !currentSoundWorld->fpa[0] ) {
currentSoundWorld->MixLoop( sampleTime, numSpeakers, finalMixBuffer );
}
if ( useOpenAL ) {
// disable audio hardware caching (this updates ALL settings since last alcSuspendContext)
alcProcessContext( openalContext );
} else {
short *dest = snd_audio_hw->GetMixBuffer();
SIMDProcessor->MixedSoundToSamples( dest, finalMixBuffer, MIXBUFFER_SAMPLES * numSpeakers );
// allow swapping the left / right speaker channels for people with miswired systems
if ( numSpeakers == 2 && s_reverse.GetBool() ) {
int j;
for( j = 0; j < MIXBUFFER_SAMPLES; j++ ) {
short temp = dest[j*2];
dest[j*2] = dest[j*2+1];
dest[j*2+1] = temp;
}
}
snd_audio_hw->Write( false );
}
// disable audio hardware caching (this updates ALL settings since last alcSuspendContext)
alcProcessContext( openalContext );
// only move to the next block if the write was successful
nextWriteBlock = dwCurrentBlock + 1;
@@ -1288,13 +1369,13 @@ void idSoundSystemLocal::FreeOpenALSource( ALuint handle ) {
if ( openalSources[i].chan ) {
openalSources[i].chan->openalSource = NULL;
}
#if ID_OPENAL
// Reset source EAX ROOM level when freeing stereo source
if ( openalSources[i].stereo && alEAXSet ) {
if ( openalEFXAvailable ) {
ApplyOpenALSourceEffects( openalSources[i].handle, 0, openalSources[i].stereo );
} else 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;
@@ -1395,8 +1476,6 @@ void idSoundSystemLocal::DoEnviroSuit( float* samples, int numSamples, int numSp
float out[10000], *out_p = out + 2;
float in[10000], *in_p = in + 2;
assert( !idSoundSystemLocal::useOpenAL );
if ( !fxList.Num() ) {
for ( int i = 0; i < 6; i++ ) {
SoundFX* fx;
@@ -1471,9 +1550,6 @@ idSoundSystemLocal::EAXAvailable
===============
*/
int idSoundSystemLocal::IsEAXAvailable( void ) {
#if !ID_OPENAL
return -1;
#else
ALCdevice *device;
ALCcontext *context;
@@ -1485,11 +1561,22 @@ int idSoundSystemLocal::IsEAXAvailable( void ) {
EAXAvailable = 2;
return 2;
}
// when dynamically loading the OpenAL subsystem, we need to get a context before alIsExtensionPresent would work
// when dynamically loading the OpenAL subsystem, we need to get a context before extension checks work
device = alcOpenDevice( NULL );
if ( !device ) {
EAXAvailable = 0;
return 0;
}
context = alcCreateContext( device, NULL );
alcMakeContextCurrent( context );
if ( alIsExtensionPresent( ID_ALCHAR "EAX4.0" ) ) {
if ( !context || !alcMakeContextCurrent( context ) ) {
if ( context ) {
alcDestroyContext( context );
}
alcCloseDevice( device );
EAXAvailable = 0;
return 0;
}
if ( alGetProcAddress( ID_ALCHAR "alGenEffects" ) || alIsExtensionPresent( ID_ALCHAR "EAX4.0" ) ) {
alcMakeContextCurrent( NULL );
alcDestroyContext( context );
alcCloseDevice( device );
@@ -1501,7 +1588,6 @@ int idSoundSystemLocal::IsEAXAvailable( void ) {
alcCloseDevice( device );
EAXAvailable = 0;
return 0;
#endif
}
#ifdef PREY
@@ -1662,4 +1748,4 @@ idSoundWorld* idSoundSystemLocal::GetSoundWorldFromId(int worldId) {
idSoundSample* idSoundSystemLocal::FindSample(const idStr& filename) {
return soundCache->FindSound(filename, false);
}
}
+46 -150
View File
@@ -276,7 +276,7 @@ void idSoundWorldLocal::ProcessDemoCommand( idDemoFile *readDemo ) {
readDemo->ReadMat3( axis );
readDemo->ReadInt( listenerId );
readDemo->ReadInt( gameTime );
PlaceListener( origin, axis, listenerId, gameTime, "" );
};
break;
@@ -423,66 +423,63 @@ void idSoundWorldLocal::MixLoop( int current44kHz, int numSpeakers, float *final
// if noclip flying outside the world, leave silence
if ( listenerArea == -1 ) {
if ( idSoundSystemLocal::useOpenAL )
alListenerf( AL_GAIN, 0.0f );
alListenerf( AL_GAIN, 0.0f );
return;
}
// update the listener position and orientation
if ( idSoundSystemLocal::useOpenAL ) {
ALfloat listenerPosition[3];
ALfloat listenerPosition[3];
listenerPosition[0] = -listenerPos.y;
listenerPosition[1] = listenerPos.z;
listenerPosition[2] = -listenerPos.x;
listenerPosition[0] = -listenerPos.y;
listenerPosition[1] = listenerPos.z;
listenerPosition[2] = -listenerPos.x;
ALfloat listenerOrientation[6];
ALfloat listenerOrientation[6];
listenerOrientation[0] = -listenerAxis[0].y;
listenerOrientation[1] = listenerAxis[0].z;
listenerOrientation[2] = -listenerAxis[0].x;
listenerOrientation[0] = -listenerAxis[0].y;
listenerOrientation[1] = listenerAxis[0].z;
listenerOrientation[2] = -listenerAxis[0].x;
listenerOrientation[3] = -listenerAxis[2].y;
listenerOrientation[4] = listenerAxis[2].z;
listenerOrientation[5] = -listenerAxis[2].x;
listenerOrientation[3] = -listenerAxis[2].y;
listenerOrientation[4] = listenerAxis[2].z;
listenerOrientation[5] = -listenerAxis[2].x;
alListenerf( AL_GAIN, 1.0f );
alListenerfv( AL_POSITION, listenerPosition );
alListenerfv( AL_ORIENTATION, listenerOrientation );
alListenerf( AL_GAIN, 1.0f );
alListenerfv( AL_POSITION, listenerPosition );
alListenerfv( AL_ORIENTATION, listenerOrientation );
#if ID_OPENAL
if ( soundSystemLocal.s_useEAXReverb.GetBool() ) {
if ( soundSystemLocal.efxloaded ) {
idSoundEffect *effect = NULL;
int EnvironmentID = -1;
idStr defaultStr( "default" );
idStr listenerAreaStr( listenerArea );
soundSystemLocal.EFXDatabase.FindEffect( listenerAreaStr, &effect, &EnvironmentID );
if (!effect)
soundSystemLocal.EFXDatabase.FindEffect( listenerAreaName, &effect, &EnvironmentID );
if (!effect)
soundSystemLocal.EFXDatabase.FindEffect( defaultStr, &effect, &EnvironmentID );
// 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 ) );
}
if ( soundSystemLocal.s_useEAXReverb.GetBool() ) {
if ( soundSystemLocal.efxloaded ) {
idSoundEffect *effect = NULL;
int EnvironmentID = -1;
idStr defaultStr( "default" );
idStr listenerAreaStr( listenerArea );
soundSystemLocal.EFXDatabase.FindEffect( listenerAreaStr, &effect, &EnvironmentID );
if (!effect)
soundSystemLocal.EFXDatabase.FindEffect( listenerAreaName, &effect, &EnvironmentID );
if (!effect)
soundSystemLocal.EFXDatabase.FindEffect( defaultStr, &effect, &EnvironmentID );
// 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.openalEFXAvailable ) {
soundSystemLocal.ApplyOpenALReverb( EnvironmentParameters );
} else if ( soundSystemLocal.alEAXSet ) {
soundSystemLocal.alEAXSet( &EAXPROPERTYID_EAX_FXSlot0, EAXREVERB_ALLPARAMETERS, 0, &EnvironmentParameters, sizeof( EnvironmentParameters ) );
}
listenerEnvironmentID = EnvironmentID;
}
listenerEnvironmentID = EnvironmentID;
}
}
#endif
}
// debugging option to mute all but a single soundEmitter
@@ -530,9 +527,6 @@ void idSoundWorldLocal::MixLoop( int current44kHz, int numSpeakers, float *final
}
}
if ( !idSoundSystemLocal::useOpenAL && enviroSuitActive ) {
soundSystemLocal.DoEnviroSuit( finalMixBuffer, MIXBUFFER_SAMPLES, numSpeakers );
}
}
//==============================================================================
@@ -1718,7 +1712,7 @@ void idSoundWorldLocal::AddChannelContribution( idSoundEmitterLocal *sound, idSo
//
// allocate and initialize hardware source
//
if ( idSoundSystemLocal::useOpenAL && sound->removeStatus < REMOVE_STATUS_SAMPLEFINISHED ) {
if ( sound->removeStatus < REMOVE_STATUS_SAMPLEFINISHED ) {
if ( !alIsSource( chan->openalSource ) ) {
chan->openalSource = soundSystemLocal.AllocOpenALSource( chan, !chan->leadinSample->hardwareBuffer || !chan->soundShader->entries[0]->hardwareBuffer || looping, chan->leadinSample->objectInfo.nChannels == 2 );
}
@@ -1746,12 +1740,8 @@ void idSoundWorldLocal::AddChannelContribution( idSoundEmitterLocal *sound, idSo
alSourcef( chan->openalSource, AL_MAX_DISTANCE, maxd );
#endif
alSourcef( chan->openalSource, AL_PITCH, ( slowmoActive && !chan->disallowSlow ) ? ( slowmoSpeed ) : ( 1.0f ) );
#if ID_OPENAL
long lOcclusion = ( enviroSuitActive ? -1150 : 0);
if ( soundSystemLocal.alEAXSet ) {
soundSystemLocal.alEAXSet( &EAXPROPERTYID_EAX_Source, EAXSOURCE_OCCLUSION, chan->openalSource, &lOcclusion, sizeof(lOcclusion) );
}
#endif
soundSystemLocal.ApplyOpenALSourceEffects( chan->openalSource, lOcclusion, chan->leadinSample->objectInfo.nChannels == 2 );
if ( ( !looping && chan->leadinSample->hardwareBuffer ) || ( looping && chan->soundShader->entries[0]->hardwareBuffer ) ) {
// handle uncompressed (non streaming) single shot and looping sounds
if ( chan->triggered ) {
@@ -1809,100 +1799,6 @@ void idSoundWorldLocal::AddChannelContribution( idSoundEmitterLocal *sound, idSo
chan->triggered = false;
}
}
} else {
if ( slowmoActive && !chan->disallowSlow ) {
idSlowChannel slow = sound->GetSlowChannel( chan );
slow.AttachSoundChannel( chan );
if ( sample->objectInfo.nChannels == 2 ) {
// need to add a stereo path, but very few samples go through this
memset( alignedInputSamples, 0, sizeof( alignedInputSamples[0] ) * MIXBUFFER_SAMPLES * 2 );
} else {
slow.GatherChannelSamples( offset, MIXBUFFER_SAMPLES, alignedInputSamples );
}
sound->SetSlowChannel( chan, slow );
} else {
sound->ResetSlowChannel( chan );
// if we are getting a stereo sample adjust accordingly
if ( sample->objectInfo.nChannels == 2 ) {
// we should probably check to make sure any looping is also to a stereo sample...
chan->GatherChannelSamples( offset*2, MIXBUFFER_SAMPLES*2, alignedInputSamples );
} else {
chan->GatherChannelSamples( offset, MIXBUFFER_SAMPLES, alignedInputSamples );
}
}
//
// work out the left / right ear values
//
float ears[6];
if ( global || omni ) {
// same for all speakers
for ( int i = 0 ; i < 6 ; i++ ) {
ears[i] = idSoundSystemLocal::s_globalFraction.GetFloat() * volume;
}
ears[3] = idSoundSystemLocal::s_subFraction.GetFloat() * volume; // subwoofer
} else {
CalcEars( numSpeakers, spatializedOriginInMeters, listenerPos, listenerAxis, ears, spatialize );
for ( int i = 0 ; i < 6 ; i++ ) {
ears[i] *= volume;
}
}
// if the mask is 0, it really means do every channel
if ( !mask ) {
mask = 255;
}
// cleared mask bits set the mix volume to zero
for ( int i = 0 ; i < 6 ; i++ ) {
if ( !(mask & ( 1 << i ) ) ) {
ears[i] = 0;
}
}
// if sounds are generally normalized, using a mixing volume over 1.0 will
// almost always cause clipping noise. If samples aren't normalized, there
// is a good call to allow overvolumes
if ( idSoundSystemLocal::s_clipVolumes.GetBool() && !( parms->soundShaderFlags & SSF_UNCLAMPED ) ) {
for ( int i = 0 ; i < 6 ; i++ ) {
if ( ears[i] > 1.0f ) {
ears[i] = 1.0f;
}
}
}
// if this is the very first mixing block, set the lastV
// to the current volume
if ( current44kHz == chan->trigger44kHzTime ) {
for ( j = 0 ; j < 6 ; j++ ) {
chan->lastV[j] = ears[j];
}
}
if ( numSpeakers == 6 ) {
if ( sample->objectInfo.nChannels == 1 ) {
SIMDProcessor->MixSoundSixSpeakerMono( finalMixBuffer, alignedInputSamples, MIXBUFFER_SAMPLES, chan->lastV, ears );
} else {
SIMDProcessor->MixSoundSixSpeakerStereo( finalMixBuffer, alignedInputSamples, MIXBUFFER_SAMPLES, chan->lastV, ears );
}
} else {
if ( sample->objectInfo.nChannels == 1 ) {
SIMDProcessor->MixSoundTwoSpeakerMono( finalMixBuffer, alignedInputSamples, MIXBUFFER_SAMPLES, chan->lastV, ears );
} else {
SIMDProcessor->MixSoundTwoSpeakerStereo( finalMixBuffer, alignedInputSamples, MIXBUFFER_SAMPLES, chan->lastV, ears );
}
}
for ( j = 0 ; j < 6 ; j++ ) {
chan->lastV[j] = ears[j];
}
}
soundSystemLocal.soundStats.activeSounds++;