mirror of
https://github.com/UberGames/ioef.git
synced 2024-11-24 13:11:30 +00:00
- Explicitly set distance attenuation model.
- Mute sounds that exceed a certain distance from the listener.
This commit is contained in:
parent
90208be35a
commit
b57a970034
2 changed files with 137 additions and 64 deletions
4
README
4
README
|
@ -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
|
||||||
|
|
|
@ -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 );
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue