r957 - in trunk: . code/client

DONOTREPLY at icculus.org DONOTREPLY at icculus.org
Fri Nov 3 03:22:49 EST 2006


Author: thilo
Date: 2006-11-03 03:22:38 -0500 (Fri, 03 Nov 2006)
New Revision: 957

Modified:
   trunk/README
   trunk/code/client/snd_openal.c
Log:
- Explicitly set distance attenuation model.
- Mute sounds that exceed a certain distance from the listener.


Modified: trunk/README
===================================================================
--- trunk/README	2006-10-27 12:49:55 UTC (rev 956)
+++ trunk/README	2006-11-03 08:22:38 UTC (rev 957)
@@ -116,8 +116,12 @@
   s_alDopplerSpeed                  - the value passed to alDopplerVelocity
   s_alMinDistance                   - the value of AL_REFERENCE_DISTANCE for
                                       each source
+  s_alMaxDistance                   - the maximum distance before sounds start
+                                      to become inaudible.
   s_alRolloff                       - the value of AL_ROLLOFF_FACTOR for each
                                       source
+  s_alGraceDistance                 - after having passed MaxDistance, length
+                                      until sounds are completely inaudible.
   s_alMaxSpeakerDistance            - ET_SPEAKERS beyond this distance are
                                       culled
   s_alDriver                        - which OpenAL library to use

Modified: trunk/code/client/snd_openal.c
===================================================================
--- trunk/code/client/snd_openal.c	2006-10-27 12:49:55 UTC (rev 956)
+++ trunk/code/client/snd_openal.c	2006-11-03 08:22:38 UTC (rev 957)
@@ -36,7 +36,9 @@
 cvar_t *s_alDopplerFactor;
 cvar_t *s_alDopplerSpeed;
 cvar_t *s_alMinDistance;
+cvar_t *s_alMaxDistance;
 cvar_t *s_alRolloff;
+cvar_t *s_alGraceDistance;
 cvar_t *s_alDriver;
 cvar_t *s_alDevice;
 cvar_t *s_alAvailableDevices;
@@ -464,6 +466,9 @@
 	int							isLooping;	// Is this a looping effect (attached to an entity)
 	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)
 } src_t;
 
@@ -513,6 +518,50 @@
 
 /*
 =================
+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
 =================
 */
@@ -616,41 +665,46 @@
 		int entity, int channel, qboolean local)
 {
 	ALuint buffer;
+	src_t *curSource;
 
 	// Mark the SFX as used, and grab the raw AL buffer
 	S_AL_BufferUse(sfx);
 	buffer = S_AL_BufferGet(sfx);
 
 	// Set up src struct
-	srcList[src].lastUsedTime = Sys_Milliseconds();
-	srcList[src].sfx = sfx;
-	srcList[src].priority = priority;
-	srcList[src].entity = entity;
-	srcList[src].channel = channel;
-	srcList[src].isActive = qtrue;
-	srcList[src].isLocked = qfalse;
-	srcList[src].isLooping = qfalse;
-	srcList[src].isTracking = qfalse;
-	srcList[src].local = local;
+	curSource = &srcList[src];
+	
+	curSource->lastUsedTime = Sys_Milliseconds();
+	curSource->sfx = sfx;
+	curSource->priority = priority;
+	curSource->entity = entity;
+	curSource->channel = channel;
+	curSource->isActive = qtrue;
+	curSource->isLocked = qfalse;
+	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
-	qalSourcei(srcList[src].alSource, AL_BUFFER, buffer);
-	qalSourcef(srcList[src].alSource, AL_PITCH, 1.0f);
-	qalSourcef(srcList[src].alSource, AL_GAIN, s_alGain->value * s_volume->value);
-	qalSourcefv(srcList[src].alSource, AL_POSITION, vec3_origin);
-	qalSourcefv(srcList[src].alSource, AL_VELOCITY, vec3_origin);
-	qalSourcei(srcList[src].alSource, AL_LOOPING, AL_FALSE);
-	qalSourcef(srcList[src].alSource, AL_REFERENCE_DISTANCE, s_alMinDistance->value);
+	qalSourcei(curSource->alSource, AL_BUFFER, buffer);
+	qalSourcef(curSource->alSource, AL_PITCH, 1.0f);
+	qalSourcef(curSource->alSource, AL_GAIN, curSource->curGain);
+	qalSourcefv(curSource->alSource, AL_POSITION, vec3_origin);
+	qalSourcefv(curSource->alSource, AL_VELOCITY, vec3_origin);
+	qalSourcei(curSource->alSource, AL_LOOPING, AL_FALSE);
+	qalSourcef(curSource->alSource, AL_REFERENCE_DISTANCE, s_alMinDistance->value);
 
 	if(local)
 	{
-		qalSourcei(srcList[src].alSource, AL_SOURCE_RELATIVE, AL_TRUE);
-		qalSourcef(srcList[src].alSource, AL_ROLLOFF_FACTOR, 0.0f);
+		qalSourcei(curSource->alSource, AL_SOURCE_RELATIVE, AL_TRUE);
+		qalSourcef(curSource->alSource, AL_ROLLOFF_FACTOR, 0.0f);
 	}
 	else
 	{
-		qalSourcei(srcList[src].alSource, AL_SOURCE_RELATIVE, AL_FALSE);
-		qalSourcef(srcList[src].alSource, AL_ROLLOFF_FACTOR, s_alRolloff->value);
+		qalSourcei(curSource->alSource, AL_SOURCE_RELATIVE, AL_FALSE);
+		qalSourcef(curSource->alSource, AL_ROLLOFF_FACTOR, s_alRolloff->value);
 	}
 }
 
@@ -887,6 +941,7 @@
 
 	S_AL_SanitiseVector( sorigin );
 	qalSourcefv( srcList[ src ].alSource, AL_POSITION, sorigin );
+	S_AL_ScaleGain(&srcList[src], sorigin);
 
 	// Start it playing
 	qalSourcePlay(srcList[src].alSource);
@@ -918,6 +973,7 @@
 {
 	int				src;
 	sentity_t	*sent = &entityList[ entityNum ];
+	src_t		*curSource;
 
 	// Do we need to allocate a new source for this entity
 	if( !sent->srcAllocated )
@@ -945,28 +1001,33 @@
 	// If this is not set then the looping sound is removed
 	sent->loopAddedThisFrame = qtrue;
 
+	curSource = &srcList[src];
+
 	// UGH
 	// These lines should be called via S_AL_SrcSetup, but we
 	// can't call that yet as it buffers sfxes that may change
 	// with subsequent calls to S_AL_SrcLoop
-	srcList[ src ].entity = entityNum;
-	srcList[ src ].isLooping = qtrue;
-	srcList[ src ].isActive = qtrue;
+	curSource->entity = entityNum;
+	curSource->isLooping = qtrue;
+	curSource->isActive = qtrue;
 
 	if( S_AL_HearingThroughEntity( entityNum ) )
 	{
-		srcList[ src ].local = qtrue;
+		curSource->local = qtrue;
 
-		qalSourcefv( srcList[ src ].alSource, AL_POSITION, vec3_origin );
-		qalSourcefv( srcList[ src ].alSource, AL_VELOCITY, vec3_origin );
+		qalSourcefv( curSource->alSource, AL_POSITION, vec3_origin );
+		qalSourcefv( curSource->alSource, AL_VELOCITY, vec3_origin );
 	}
 	else
 	{
-		srcList[ src ].local = qfalse;
+		curSource->local = qfalse;
 
-		qalSourcefv( srcList[ src ].alSource, AL_POSITION, (ALfloat *)sent->origin );
-		qalSourcefv( srcList[ src ].alSource, AL_VELOCITY, (ALfloat *)velocity );
+		qalSourcefv( curSource->alSource, AL_POSITION, (ALfloat *)sent->origin );
+		qalSourcefv( curSource->alSource, AL_VELOCITY, (ALfloat *)velocity );
+		
 	}
+
+	S_AL_ScaleGain(curSource, sent->origin);
 }
 
 /*
@@ -1028,63 +1089,65 @@
 	int i;
 	int entityNum;
 	ALint state;
+	src_t *curSource;	
 
 	for(i = 0; i < srcCount; i++)
 	{
 		entityNum = srcList[i].entity;
+		curSource = &srcList[i];
 
-		if(srcList[i].isLocked)
+		if(curSource->isLocked)
 			continue;
 
-		if(!srcList[i].isActive)
+		if(!curSource->isActive)
 			continue;
 
 		// Update source parameters
 		if((s_alGain->modified)||(s_volume->modified))
-			qalSourcef(srcList[i].alSource, AL_GAIN, s_alGain->value * s_volume->value);
-		if((s_alRolloff->modified)&&(!srcList[i].local))
-			qalSourcef(srcList[i].alSource, AL_ROLLOFF_FACTOR, s_alRolloff->value);
+			curSource->curGain = s_alGain->value * s_volume->value;
+		if((s_alRolloff->modified)&&(!curSource->local))
+			qalSourcef(curSource->alSource, AL_ROLLOFF_FACTOR, s_alRolloff->value);
 		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 ];
 
 			// If a looping effect hasn't been touched this frame, kill it
-			if( sent->loopAddedThisFrame )
+			if(sent->loopAddedThisFrame)
 			{
 				// The sound has changed without an intervening removal
-				if( srcList[ i ].isActive && !sent->startLoopingSound &&
-						srcList[ i ].sfx != sent->loopSfx )
+				if(curSource->isActive && !sent->startLoopingSound &&
+						curSource->sfx != sent->loopSfx)
 				{
-					qalSourceStop( srcList[ i ].alSource );
-					qalSourcei( srcList[ i ].alSource, AL_BUFFER, 0 );
+					qalSourceStop(curSource->alSource);
+					qalSourcei(curSource->alSource, AL_BUFFER, 0);
 					sent->startLoopingSound = qtrue;
 				}
 
-				// Ths sound hasn't been started yet
-				if( sent->startLoopingSound )
+				// The sound hasn't been started yet
+				if(sent->startLoopingSound)
 				{
-					S_AL_SrcSetup( i, sent->loopSfx, sent->loopPriority,
-							entityNum, -1, srcList[ i ].local );
-					srcList[ i ].isLooping = qtrue;
-					qalSourcei( srcList[ i ].alSource, AL_LOOPING, AL_TRUE );
-					qalSourcePlay( srcList[ i ].alSource );
+					S_AL_SrcSetup(i, sent->loopSfx, sent->loopPriority,
+							entityNum, -1, curSource->local);
+					curSource->isLooping = qtrue;
+					qalSourcei(curSource->alSource, AL_LOOPING, AL_TRUE);
+					qalSourcePlay(curSource->alSource);
 
 					sent->startLoopingSound = qfalse;
 				}
 
 				// Update locality
-				if( srcList[ i ].local)
+				if(curSource->local)
 				{
-					qalSourcei( srcList[ i ].alSource, AL_SOURCE_RELATIVE, AL_TRUE );
-					qalSourcef( srcList[ i ].alSource, AL_ROLLOFF_FACTOR, 0.0f );
+					qalSourcei(curSource->alSource, AL_SOURCE_RELATIVE, AL_TRUE);
+					qalSourcef(curSource->alSource, AL_ROLLOFF_FACTOR, 0.0f);
 				}
 				else
 				{
-					qalSourcei( srcList[ i ].alSource, AL_SOURCE_RELATIVE, AL_FALSE );
-					qalSourcef( srcList[ i ].alSource, AL_ROLLOFF_FACTOR, s_alRolloff->value );
+					qalSourcei(curSource->alSource, AL_SOURCE_RELATIVE, AL_FALSE);
+					qalSourcef(curSource->alSource, AL_ROLLOFF_FACTOR, s_alRolloff->value);
 				}
 			}
 			else
@@ -1093,20 +1156,23 @@
 			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
-		qalGetSourcei(srcList[i].alSource, AL_SOURCE_STATE, &state);
+		qalGetSourcei(curSource->alSource, AL_SOURCE_STATE, &state);
 		if(state == AL_STOPPED)
 		{
 			S_AL_SrcKill(i);
 			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 @@
 	s_alDopplerFactor = Cvar_Get( "s_alDopplerFactor", "1.0", CVAR_ARCHIVE );
 	s_alDopplerSpeed = Cvar_Get( "s_alDopplerSpeed", "2200", CVAR_ARCHIVE );
 	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_alDriver = Cvar_Get( "s_alDriver", ALDRIVER_DEFAULT, CVAR_ARCHIVE );
@@ -1787,7 +1855,7 @@
 		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")))
 	{
 		char devicenames[1024] = "";
@@ -1863,6 +1931,7 @@
 	S_AL_SrcInit( );
 
 	// Set up OpenAL parameters (doppler, etc)
+	qalDistanceModel(AL_INVERSE_DISTANCE_CLAMPED);
 	qalDopplerFactor( s_alDopplerFactor->value );
 	qalDopplerVelocity( s_alDopplerSpeed->value );
 




More information about the quake3-commits mailing list