- Explicitly set distance attenuation model.

- Mute sounds that exceed a certain distance from the listener.
This commit is contained in:
Thilo Schulz 2006-11-03 08:22:38 +00:00
parent 90208be35a
commit b57a970034
2 changed files with 137 additions and 64 deletions

4
README
View file

@ -116,8 +116,12 @@ New cvars
s_alDopplerSpeed - the value passed to alDopplerVelocity s_alDopplerSpeed - the value passed to alDopplerVelocity
s_alMinDistance - the value of AL_REFERENCE_DISTANCE for s_alMinDistance - the value of AL_REFERENCE_DISTANCE for
each source each source
s_alMaxDistance - the maximum distance before sounds start
to become inaudible.
s_alRolloff - the value of AL_ROLLOFF_FACTOR for each s_alRolloff - the value of AL_ROLLOFF_FACTOR for each
source source
s_alGraceDistance - after having passed MaxDistance, length
until sounds are completely inaudible.
s_alMaxSpeakerDistance - ET_SPEAKERS beyond this distance are s_alMaxSpeakerDistance - ET_SPEAKERS beyond this distance are
culled culled
s_alDriver - which OpenAL library to use s_alDriver - which OpenAL library to use

View file

@ -36,7 +36,9 @@ cvar_t *s_alSources;
cvar_t *s_alDopplerFactor; cvar_t *s_alDopplerFactor;
cvar_t *s_alDopplerSpeed; cvar_t *s_alDopplerSpeed;
cvar_t *s_alMinDistance; cvar_t *s_alMinDistance;
cvar_t *s_alMaxDistance;
cvar_t *s_alRolloff; cvar_t *s_alRolloff;
cvar_t *s_alGraceDistance;
cvar_t *s_alDriver; cvar_t *s_alDriver;
cvar_t *s_alDevice; cvar_t *s_alDevice;
cvar_t *s_alAvailableDevices; cvar_t *s_alAvailableDevices;
@ -464,6 +466,9 @@ typedef struct src_s
int isLooping; // Is this a looping effect (attached to an entity) int isLooping; // Is this a looping effect (attached to an entity)
int isTracking; // Is this object tracking it's owner int isTracking; // Is this object tracking it's owner
float curGain; // gain employed if source is within maxdistance.
float scaleGain; // Last gain value for this source. 0 if muted.
qboolean local; // Is this local (relative to the cam) qboolean local; // Is this local (relative to the cam)
} src_t; } src_t;
@ -511,6 +516,50 @@ static void _S_AL_SanitiseVector( vec3_t v, int line )
#define AL_THIRD_PERSON_THRESHOLD_SQ (48.0f*48.0f) #define AL_THIRD_PERSON_THRESHOLD_SQ (48.0f*48.0f)
/*
=================
S_AL_ScaleGain
Adapt the gain if necessary to get a quicker fadeout when the source is too far away.
=================
*/
static void S_AL_ScaleGain(src_t *chksrc, vec3_t origin)
{
float distance;
if(chksrc->local)
distance = VectorLength(origin);
else
distance = Distance(origin, lastListenerOrigin);
// If we exceed a certain distance, scale the gain linearly until the sound
// vanishes into nothingness.
if((distance -= s_alMaxDistance->value) > 0)
{
float scaleFactor;
if(distance >= s_alGraceDistance->value)
scaleFactor = 0.0f;
else
scaleFactor = 1.0f - distance / s_alGraceDistance->value;
scaleFactor *= chksrc->curGain;
if(chksrc->scaleGain != scaleFactor);
{
chksrc->scaleGain = scaleFactor;
// if(scaleFactor > 0.0f)
// Com_Printf("%f\n", scaleFactor);
qalSourcef(chksrc->alSource, AL_GAIN, chksrc->scaleGain);
}
}
else if(chksrc->scaleGain != chksrc->curGain)
{
chksrc->scaleGain = chksrc->curGain;
qalSourcef(chksrc->alSource, AL_GAIN, chksrc->scaleGain);
}
}
/* /*
================= =================
S_AL_HearingThroughEntity S_AL_HearingThroughEntity
@ -616,41 +665,46 @@ static void S_AL_SrcSetup(srcHandle_t src, sfxHandle_t sfx, alSrcPriority_t prio
int entity, int channel, qboolean local) int entity, int channel, qboolean local)
{ {
ALuint buffer; ALuint buffer;
src_t *curSource;
// Mark the SFX as used, and grab the raw AL buffer // Mark the SFX as used, and grab the raw AL buffer
S_AL_BufferUse(sfx); S_AL_BufferUse(sfx);
buffer = S_AL_BufferGet(sfx); buffer = S_AL_BufferGet(sfx);
// Set up src struct // Set up src struct
srcList[src].lastUsedTime = Sys_Milliseconds(); curSource = &srcList[src];
srcList[src].sfx = sfx;
srcList[src].priority = priority; curSource->lastUsedTime = Sys_Milliseconds();
srcList[src].entity = entity; curSource->sfx = sfx;
srcList[src].channel = channel; curSource->priority = priority;
srcList[src].isActive = qtrue; curSource->entity = entity;
srcList[src].isLocked = qfalse; curSource->channel = channel;
srcList[src].isLooping = qfalse; curSource->isActive = qtrue;
srcList[src].isTracking = qfalse; curSource->isLocked = qfalse;
srcList[src].local = local; curSource->isLooping = qfalse;
curSource->isTracking = qfalse;
curSource->curGain = s_alGain->value * s_volume->value;
curSource->scaleGain = curSource->curGain;
curSource->local = local;
// Set up OpenAL source // Set up OpenAL source
qalSourcei(srcList[src].alSource, AL_BUFFER, buffer); qalSourcei(curSource->alSource, AL_BUFFER, buffer);
qalSourcef(srcList[src].alSource, AL_PITCH, 1.0f); qalSourcef(curSource->alSource, AL_PITCH, 1.0f);
qalSourcef(srcList[src].alSource, AL_GAIN, s_alGain->value * s_volume->value); qalSourcef(curSource->alSource, AL_GAIN, curSource->curGain);
qalSourcefv(srcList[src].alSource, AL_POSITION, vec3_origin); qalSourcefv(curSource->alSource, AL_POSITION, vec3_origin);
qalSourcefv(srcList[src].alSource, AL_VELOCITY, vec3_origin); qalSourcefv(curSource->alSource, AL_VELOCITY, vec3_origin);
qalSourcei(srcList[src].alSource, AL_LOOPING, AL_FALSE); qalSourcei(curSource->alSource, AL_LOOPING, AL_FALSE);
qalSourcef(srcList[src].alSource, AL_REFERENCE_DISTANCE, s_alMinDistance->value); qalSourcef(curSource->alSource, AL_REFERENCE_DISTANCE, s_alMinDistance->value);
if(local) if(local)
{ {
qalSourcei(srcList[src].alSource, AL_SOURCE_RELATIVE, AL_TRUE); qalSourcei(curSource->alSource, AL_SOURCE_RELATIVE, AL_TRUE);
qalSourcef(srcList[src].alSource, AL_ROLLOFF_FACTOR, 0.0f); qalSourcef(curSource->alSource, AL_ROLLOFF_FACTOR, 0.0f);
} }
else else
{ {
qalSourcei(srcList[src].alSource, AL_SOURCE_RELATIVE, AL_FALSE); qalSourcei(curSource->alSource, AL_SOURCE_RELATIVE, AL_FALSE);
qalSourcef(srcList[src].alSource, AL_ROLLOFF_FACTOR, s_alRolloff->value); qalSourcef(curSource->alSource, AL_ROLLOFF_FACTOR, s_alRolloff->value);
} }
} }
@ -887,6 +941,7 @@ void S_AL_StartSound( vec3_t origin, int entnum, int entchannel, sfxHandle_t sfx
S_AL_SanitiseVector( sorigin ); S_AL_SanitiseVector( sorigin );
qalSourcefv( srcList[ src ].alSource, AL_POSITION, sorigin ); qalSourcefv( srcList[ src ].alSource, AL_POSITION, sorigin );
S_AL_ScaleGain(&srcList[src], sorigin);
// Start it playing // Start it playing
qalSourcePlay(srcList[src].alSource); qalSourcePlay(srcList[src].alSource);
@ -918,6 +973,7 @@ static void S_AL_SrcLoop( alSrcPriority_t priority, sfxHandle_t sfx,
{ {
int src; int src;
sentity_t *sent = &entityList[ entityNum ]; sentity_t *sent = &entityList[ entityNum ];
src_t *curSource;
// Do we need to allocate a new source for this entity // Do we need to allocate a new source for this entity
if( !sent->srcAllocated ) if( !sent->srcAllocated )
@ -945,28 +1001,33 @@ static void S_AL_SrcLoop( alSrcPriority_t priority, sfxHandle_t sfx,
// If this is not set then the looping sound is removed // If this is not set then the looping sound is removed
sent->loopAddedThisFrame = qtrue; sent->loopAddedThisFrame = qtrue;
curSource = &srcList[src];
// UGH // UGH
// These lines should be called via S_AL_SrcSetup, but we // These lines should be called via S_AL_SrcSetup, but we
// can't call that yet as it buffers sfxes that may change // can't call that yet as it buffers sfxes that may change
// with subsequent calls to S_AL_SrcLoop // with subsequent calls to S_AL_SrcLoop
srcList[ src ].entity = entityNum; curSource->entity = entityNum;
srcList[ src ].isLooping = qtrue; curSource->isLooping = qtrue;
srcList[ src ].isActive = qtrue; curSource->isActive = qtrue;
if( S_AL_HearingThroughEntity( entityNum ) ) if( S_AL_HearingThroughEntity( entityNum ) )
{ {
srcList[ src ].local = qtrue; curSource->local = qtrue;
qalSourcefv( srcList[ src ].alSource, AL_POSITION, vec3_origin ); qalSourcefv( curSource->alSource, AL_POSITION, vec3_origin );
qalSourcefv( srcList[ src ].alSource, AL_VELOCITY, vec3_origin ); qalSourcefv( curSource->alSource, AL_VELOCITY, vec3_origin );
} }
else else
{ {
srcList[ src ].local = qfalse; curSource->local = qfalse;
qalSourcefv( curSource->alSource, AL_POSITION, (ALfloat *)sent->origin );
qalSourcefv( curSource->alSource, AL_VELOCITY, (ALfloat *)velocity );
qalSourcefv( srcList[ src ].alSource, AL_POSITION, (ALfloat *)sent->origin );
qalSourcefv( srcList[ src ].alSource, AL_VELOCITY, (ALfloat *)velocity );
} }
S_AL_ScaleGain(curSource, sent->origin);
} }
/* /*
@ -1028,26 +1089,28 @@ void S_AL_SrcUpdate( void )
int i; int i;
int entityNum; int entityNum;
ALint state; ALint state;
src_t *curSource;
for(i = 0; i < srcCount; i++) for(i = 0; i < srcCount; i++)
{ {
entityNum = srcList[i].entity; entityNum = srcList[i].entity;
curSource = &srcList[i];
if(srcList[i].isLocked) if(curSource->isLocked)
continue; continue;
if(!srcList[i].isActive) if(!curSource->isActive)
continue; continue;
// Update source parameters // Update source parameters
if((s_alGain->modified)||(s_volume->modified)) if((s_alGain->modified)||(s_volume->modified))
qalSourcef(srcList[i].alSource, AL_GAIN, s_alGain->value * s_volume->value); curSource->curGain = s_alGain->value * s_volume->value;
if((s_alRolloff->modified)&&(!srcList[i].local)) if((s_alRolloff->modified)&&(!curSource->local))
qalSourcef(srcList[i].alSource, AL_ROLLOFF_FACTOR, s_alRolloff->value); qalSourcef(curSource->alSource, AL_ROLLOFF_FACTOR, s_alRolloff->value);
if(s_alMinDistance->modified) if(s_alMinDistance->modified)
qalSourcef(srcList[i].alSource, AL_REFERENCE_DISTANCE, s_alMinDistance->value); qalSourcef(curSource->alSource, AL_REFERENCE_DISTANCE, s_alMinDistance->value);
if( srcList[ i ].isLooping ) if(curSource->isLooping)
{ {
sentity_t *sent = &entityList[ entityNum ]; sentity_t *sent = &entityList[ entityNum ];
@ -1055,36 +1118,36 @@ void S_AL_SrcUpdate( void )
if(sent->loopAddedThisFrame) if(sent->loopAddedThisFrame)
{ {
// The sound has changed without an intervening removal // The sound has changed without an intervening removal
if( srcList[ i ].isActive && !sent->startLoopingSound && if(curSource->isActive && !sent->startLoopingSound &&
srcList[ i ].sfx != sent->loopSfx ) curSource->sfx != sent->loopSfx)
{ {
qalSourceStop( srcList[ i ].alSource ); qalSourceStop(curSource->alSource);
qalSourcei( srcList[ i ].alSource, AL_BUFFER, 0 ); qalSourcei(curSource->alSource, AL_BUFFER, 0);
sent->startLoopingSound = qtrue; sent->startLoopingSound = qtrue;
} }
// Ths sound hasn't been started yet // The sound hasn't been started yet
if(sent->startLoopingSound) if(sent->startLoopingSound)
{ {
S_AL_SrcSetup(i, sent->loopSfx, sent->loopPriority, S_AL_SrcSetup(i, sent->loopSfx, sent->loopPriority,
entityNum, -1, srcList[ i ].local ); entityNum, -1, curSource->local);
srcList[ i ].isLooping = qtrue; curSource->isLooping = qtrue;
qalSourcei( srcList[ i ].alSource, AL_LOOPING, AL_TRUE ); qalSourcei(curSource->alSource, AL_LOOPING, AL_TRUE);
qalSourcePlay( srcList[ i ].alSource ); qalSourcePlay(curSource->alSource);
sent->startLoopingSound = qfalse; sent->startLoopingSound = qfalse;
} }
// Update locality // Update locality
if( srcList[ i ].local) if(curSource->local)
{ {
qalSourcei( srcList[ i ].alSource, AL_SOURCE_RELATIVE, AL_TRUE ); qalSourcei(curSource->alSource, AL_SOURCE_RELATIVE, AL_TRUE);
qalSourcef( srcList[ i ].alSource, AL_ROLLOFF_FACTOR, 0.0f ); qalSourcef(curSource->alSource, AL_ROLLOFF_FACTOR, 0.0f);
} }
else else
{ {
qalSourcei( srcList[ i ].alSource, AL_SOURCE_RELATIVE, AL_FALSE ); qalSourcei(curSource->alSource, AL_SOURCE_RELATIVE, AL_FALSE);
qalSourcef( srcList[ i ].alSource, AL_ROLLOFF_FACTOR, s_alRolloff->value ); qalSourcef(curSource->alSource, AL_ROLLOFF_FACTOR, s_alRolloff->value);
} }
} }
else else
@ -1093,20 +1156,23 @@ void S_AL_SrcUpdate( void )
continue; continue;
} }
// Query relativity of source, don't move if it's true
qalGetSourcei( srcList[ i ].alSource, AL_SOURCE_RELATIVE, &state );
// See if it needs to be moved
if( srcList[ i ].isTracking && !state )
qalSourcefv(srcList[i].alSource, AL_POSITION, entityList[entityNum].origin);
// Check if it's done, and flag it // Check if it's done, and flag it
qalGetSourcei(srcList[i].alSource, AL_SOURCE_STATE, &state); qalGetSourcei(curSource->alSource, AL_SOURCE_STATE, &state);
if(state == AL_STOPPED) if(state == AL_STOPPED)
{ {
S_AL_SrcKill(i); S_AL_SrcKill(i);
continue; continue;
} }
// Query relativity of source, don't move if it's true
qalGetSourcei(curSource->alSource, AL_SOURCE_RELATIVE, &state);
// See if it needs to be moved
if(curSource->isTracking && !state)
{
qalSourcefv(curSource->alSource, AL_POSITION, entityList[entityNum].origin);
S_AL_ScaleGain(curSource, entityList[entityNum].origin);
}
} }
} }
@ -1775,7 +1841,9 @@ qboolean S_AL_Init( soundInterface_t *si )
s_alDopplerFactor = Cvar_Get( "s_alDopplerFactor", "1.0", CVAR_ARCHIVE ); s_alDopplerFactor = Cvar_Get( "s_alDopplerFactor", "1.0", CVAR_ARCHIVE );
s_alDopplerSpeed = Cvar_Get( "s_alDopplerSpeed", "2200", CVAR_ARCHIVE ); s_alDopplerSpeed = Cvar_Get( "s_alDopplerSpeed", "2200", CVAR_ARCHIVE );
s_alMinDistance = Cvar_Get( "s_alMinDistance", "120", CVAR_CHEAT ); s_alMinDistance = Cvar_Get( "s_alMinDistance", "120", CVAR_CHEAT );
s_alRolloff = Cvar_Get( "s_alRolloff", "0.8", CVAR_CHEAT ); s_alMaxDistance = Cvar_Get("s_alMaxDistance", "1024", CVAR_CHEAT);
s_alRolloff = Cvar_Get( "s_alRolloff", "2", CVAR_CHEAT);
s_alGraceDistance = Cvar_Get("s_alGraceDistance", "512", CVAR_CHEAT);
s_alMaxSpeakerDistance = Cvar_Get( "s_alMaxSpeakerDistance", "1024", CVAR_ARCHIVE ); s_alMaxSpeakerDistance = Cvar_Get( "s_alMaxSpeakerDistance", "1024", CVAR_ARCHIVE );
s_alDriver = Cvar_Get( "s_alDriver", ALDRIVER_DEFAULT, CVAR_ARCHIVE ); s_alDriver = Cvar_Get( "s_alDriver", ALDRIVER_DEFAULT, CVAR_ARCHIVE );
@ -1787,7 +1855,7 @@ qboolean S_AL_Init( soundInterface_t *si )
return qfalse; return qfalse;
} }
// Device enumeration support (extension currently only exists for windows). // Device enumeration support (extension is implemented reasonably only on Windows right now).
if((enumsupport = qalcIsExtensionPresent(NULL, "ALC_ENUMERATION_EXT"))) if((enumsupport = qalcIsExtensionPresent(NULL, "ALC_ENUMERATION_EXT")))
{ {
char devicenames[1024] = ""; char devicenames[1024] = "";
@ -1863,6 +1931,7 @@ qboolean S_AL_Init( soundInterface_t *si )
S_AL_SrcInit( ); S_AL_SrcInit( );
// Set up OpenAL parameters (doppler, etc) // Set up OpenAL parameters (doppler, etc)
qalDistanceModel(AL_INVERSE_DISTANCE_CLAMPED);
qalDopplerFactor( s_alDopplerFactor->value ); qalDopplerFactor( s_alDopplerFactor->value );
qalDopplerVelocity( s_alDopplerSpeed->value ); qalDopplerVelocity( s_alDopplerSpeed->value );