r400 - trunk/code/client

DONOTREPLY at icculus.org DONOTREPLY at icculus.org
Thu Dec 1 13:22:42 EST 2005


Author: tma
Date: 2005-12-01 13:22:42 -0500 (Thu, 01 Dec 2005)
New Revision: 400

Modified:
   trunk/code/client/snd_openal.c
Log:
* Fixed bug where if two looping sounds were added to a single entity they
  would fight for a source and you'd get a horrible distorted sound that was
  each of the two sounds interleaved
* Changed the default of s_alPrecache to 1 -- having it off seems to cause
  problems for some and it doesn't actually improve things much
* Changed a few of the variable names in snd_openal.c to be more sane


Modified: trunk/code/client/snd_openal.c
===================================================================
--- trunk/code/client/snd_openal.c	2005-12-01 18:01:43 UTC (rev 399)
+++ trunk/code/client/snd_openal.c	2005-12-01 18:22:42 UTC (rev 400)
@@ -114,7 +114,7 @@
 // Sound effect storage, data structures
 #define MAX_SFX 4096
 static alSfx_t knownSfx[MAX_SFX];
-static int numSfx;
+static int numSfx = 0;
 
 static sfxHandle_t default_sfx;
 
@@ -150,7 +150,7 @@
 */
 static sfxHandle_t S_AL_BufferFind(const char *filename)
 {
-	// Look it up in the hash table
+	// Look it up in the table
 	sfxHandle_t sfx = -1;
 	int i;
 
@@ -163,7 +163,7 @@
 		}
 	}
 
-	// Not found in hash table?
+	// Not found in table?
 	if(sfx == -1)
 	{
 		alSfx_t *ptr;
@@ -403,7 +403,7 @@
 {
 	sfxHandle_t sfx = S_AL_BufferFind(sample);
 
-	if((s_alPrecache->integer == 1) && (!knownSfx[sfx].inMemory) && (!knownSfx[sfx].isDefault))
+	if( s_alPrecache->integer && (!knownSfx[sfx].inMemory) && (!knownSfx[sfx].isDefault))
 		S_AL_BufferLoad(sfx);
 	knownSfx[sfx].used = Com_Milliseconds();
 
@@ -429,7 +429,7 @@
 
 typedef struct src_s
 {
-	ALuint					source;			// OpenAL source object
+	ALuint					alSource;		// OpenAL source object
 	sfxHandle_t 		sfx;				// Sound effect in use
 
 	int							lastUse;		// Last time used
@@ -450,15 +450,17 @@
 static int srcCount = 0;
 static qboolean alSourcesInitialised = qfalse;
 
-static int ambientCount = 0;
-
 typedef struct sentity_s
 {
-	vec3_t origin;		// Object position
+	vec3_t					origin;
 
-	int has_sfx;		// Associated sound source
-	int sfx;
-	int touched;		// Sound present this update?
+	int							srcAllocated; // If a src_t has been allocated to this entity
+	int							srcIndex;
+
+	qboolean				loopAddedThisFrame;
+	alSrcPriority_t	loopPriority;
+	sfxHandle_t			loopSfx;
+	qboolean				startLoopingSound;
 } sentity_t;
 
 static sentity_t entityList[MAX_GENTITIES];
@@ -479,7 +481,7 @@
 	memset(srcList, 0, sizeof(srcList));
 	srcCount = 0;
 
-	// Cap s_sources to MAX_SRC
+	// Cap s_alSources to MAX_SRC
 	limit = s_alSources->integer;
 	if(limit > MAX_SRC)
 		limit = MAX_SRC;
@@ -489,7 +491,7 @@
 	// Allocate as many sources as possible
 	for(i = 0; i < limit; i++)
 	{
-		qalGenSources(1, &srcList[i].source);
+		qalGenSources(1, &srcList[i].alSource);
 		if((error = qalGetError()) != AL_NO_ERROR)
 			break;
 		srcCount++;
@@ -520,8 +522,8 @@
 		if(srcList[i].isLocked)
 			Com_DPrintf( S_COLOR_YELLOW "WARNING: Source %d is locked\n", i);
 
-		qalSourceStop(srcList[i].source);
-		qalDeleteSources(1, &srcList[i].source);
+		qalSourceStop(srcList[i].alSource);
+		qalDeleteSources(1, &srcList[i].alSource);
 	}
 
 	memset(srcList, 0, sizeof(srcList));
@@ -557,23 +559,23 @@
 	srcList[src].local = local;
 
 	// Set up OpenAL source
-	qalSourcei(srcList[src].source, AL_BUFFER, buffer);
-	qalSourcef(srcList[src].source, AL_PITCH, 1.0f);
-	qalSourcef(srcList[src].source, AL_GAIN, s_alGain->value * s_volume->value);
-	qalSourcefv(srcList[src].source, AL_POSITION, null_vector);
-	qalSourcefv(srcList[src].source, AL_VELOCITY, null_vector);
-	qalSourcei(srcList[src].source, AL_LOOPING, AL_FALSE);
-	qalSourcef(srcList[src].source, AL_REFERENCE_DISTANCE, s_alMinDistance->value);
+	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, null_vector);
+	qalSourcefv(srcList[src].alSource, AL_VELOCITY, null_vector);
+	qalSourcei(srcList[src].alSource, AL_LOOPING, AL_FALSE);
+	qalSourcef(srcList[src].alSource, AL_REFERENCE_DISTANCE, s_alMinDistance->value);
 
 	if(local)
 	{
-		qalSourcei(srcList[src].source, AL_SOURCE_RELATIVE, AL_TRUE);
-		qalSourcef(srcList[src].source, AL_ROLLOFF_FACTOR, 0);
+		qalSourcei(srcList[src].alSource, AL_SOURCE_RELATIVE, AL_TRUE);
+		qalSourcef(srcList[src].alSource, AL_ROLLOFF_FACTOR, 0);
 	}
 	else
 	{
-		qalSourcei(srcList[src].source, AL_SOURCE_RELATIVE, AL_FALSE);
-		qalSourcef(srcList[src].source, AL_ROLLOFF_FACTOR, s_alRolloff->value);
+		qalSourcei(srcList[src].alSource, AL_SOURCE_RELATIVE, AL_FALSE);
+		qalSourcef(srcList[src].alSource, AL_ROLLOFF_FACTOR, s_alRolloff->value);
 	}
 }
 
@@ -590,19 +592,20 @@
 
 	// Stop it if it's playing
 	if(srcList[src].isActive)
-		qalSourceStop(srcList[src].source);
+		qalSourceStop(srcList[src].alSource);
 
 	// Remove the entity association
 	if((srcList[src].isLooping) && (srcList[src].entity != -1))
 	{
 		int ent = srcList[src].entity;
-		entityList[ent].has_sfx = 0;
-		entityList[ent].sfx = -1;
-		entityList[ent].touched = qfalse;
+		entityList[ent].srcAllocated = qfalse;
+		entityList[ent].srcIndex = -1;
+		entityList[ent].loopAddedThisFrame = qfalse;
+		entityList[ent].startLoopingSound = qfalse;
 	}
 
 	// Remove the buffer
-	qalSourcei(srcList[src].source, AL_BUFFER, 0);
+	qalSourcei(srcList[src].alSource, AL_BUFFER, 0);
 
 	srcList[src].sfx = 0;
 	srcList[src].lastUse = 0;
@@ -660,7 +663,10 @@
 
 	// Do we have an empty one?
 	if(empty != -1)
+	{
+		S_AL_SrcKill( empty );
 		return empty;
+	}
 
 	// No. How about an overridable one?
 	if(weakest != -1)
@@ -755,11 +761,9 @@
 	S_AL_SrcSetup(src, sfx, SRCPRI_LOCAL, -1, channel, qtrue);
 
 	// Start it playing
-	qalSourcePlay(srcList[src].source);
+	qalSourcePlay(srcList[src].alSource);
 }
 
-#define POSITION_SCALE 1.0f
-
 /*
 =================
 S_AL_StartSound
@@ -783,14 +787,14 @@
 	if(origin == NULL)
 	{
 		srcList[src].isTracking = qtrue;
-		VectorScale(entityList[entnum].origin, POSITION_SCALE, sorigin);
+		VectorCopy( entityList[entnum].origin, sorigin );
 	}
 	else
-		VectorScale(origin, POSITION_SCALE, sorigin);
-	qalSourcefv(srcList[src].source, AL_POSITION, sorigin);
+		VectorCopy( origin, sorigin );
+	qalSourcefv(srcList[src].alSource, AL_POSITION, sorigin);
 
 	// Start it playing
-	qalSourcePlay(srcList[src].source);
+	qalSourcePlay(srcList[src].alSource);
 }
 
 /*
@@ -805,7 +809,7 @@
 	for(i = 0; i < srcCount; i++)
 	{
 		if((srcList[i].isLooping) && (srcList[i].entity != -1))
-			entityList[srcList[i].entity].touched = qfalse;
+			entityList[srcList[i].entity].loopAddedThisFrame = qfalse;
 	}
 }
 
@@ -815,56 +819,48 @@
 =================
 */
 static void S_AL_SrcLoop( alSrcPriority_t priority, sfxHandle_t sfx,
-		const vec3_t origin, const vec3_t velocity, int entnum)
+		const vec3_t origin, const vec3_t velocity, int entityNum )
 {
-	int src;
-	qboolean need_to_play = qfalse;
-	vec3_t sorigin;
+	int				src;
+	sentity_t	*sent = &entityList[ entityNum ];
 
-	// Do we need to start a new sound playing?
-	if(!entityList[entnum].has_sfx)
+	// Do we need to allocate a new source for this entity
+	if( !sent->srcAllocated )
 	{
 		// Try to get a channel
-		ambientCount++;
-		src = S_AL_SrcAlloc(priority, entnum, -1);
-		if(src == -1)
+		src = S_AL_SrcAlloc( priority, entityNum, -1 );
+		if( src == -1 )
+		{
+			Com_Printf( S_COLOR_RED "ERROR: Failed to allocate source "
+					"for loop sfx %d on entity %d\n", sfx, entityNum );
 			return;
-		need_to_play = qtrue;
+		}
+
+		sent->startLoopingSound = qtrue;
 	}
-	else if(srcList[entityList[entnum].sfx].sfx != sfx)
-	{
-		// Need to restart. Just re-use this channel
-		src = entityList[entnum].sfx;
-		S_AL_SrcKill(src);
-		need_to_play = qtrue;
-	}
 	else
-		src = entityList[entnum].sfx;
+		src = sent->srcIndex;
 
-	if(need_to_play)
-	{
-		// Set up the effect
-		S_AL_SrcSetup(src, sfx, priority, entnum, -1, qfalse);
-		qalSourcei(srcList[src].source, AL_LOOPING, AL_TRUE);
-		srcList[src].isLooping = qtrue;
+	sent->srcAllocated = qtrue;
+	sent->srcIndex = src;
 
-		// Set up the entity
-		entityList[entnum].has_sfx = qtrue;
-		entityList[entnum].sfx = src;
-		need_to_play = qtrue;
-	}
+	sent->loopPriority = priority;
+	sent->loopSfx = sfx;
 
-	// Set up the position and velocity
-	VectorScale(entityList[entnum].origin, POSITION_SCALE, sorigin);
-	qalSourcefv(srcList[src].source, AL_POSITION, (ALfloat *)sorigin);
-	qalSourcefv(srcList[src].source, AL_VELOCITY, (ALfloat *)velocity);
+	// If this is not set then the looping sound is removed
+	sent->loopAddedThisFrame = qtrue;
 
-	// Flag it
-	entityList[entnum].touched = qtrue;
+	// 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;
 
-	// Play if need be
-	if(need_to_play)
-		qalSourcePlay(srcList[src].source);
+	// Set up the position and velocity
+	qalSourcefv( srcList[ src ].alSource, AL_POSITION, (ALfloat *)sent->origin );
+	qalSourcefv( srcList[ src ].alSource, AL_VELOCITY, (ALfloat *)velocity );
 }
 
 /*
@@ -897,8 +893,8 @@
 static
 void S_AL_StopLoopingSound(int entityNum )
 {
-	if(entityList[entityNum].has_sfx)
-		S_AL_SrcKill(entityList[entityNum].sfx);
+	if(entityList[entityNum].srcAllocated)
+		S_AL_SrcKill(entityList[entityNum].srcIndex);
 }
 
 /*
@@ -912,52 +908,71 @@
 void S_AL_SrcUpdate( void )
 {
 	int i;
-	int ent;
+	int entityNum;
 	ALint state;
 
 	for(i = 0; i < srcCount; i++)
 	{
+		entityNum = srcList[i].entity;
+
 		if(srcList[i].isLocked)
 			continue;
 
 		if(!srcList[i].isActive)
 			continue;
 
-		// Check if it's done, and flag it
-		qalGetSourcei(srcList[i].source, AL_SOURCE_STATE, &state);
-		if(state == AL_STOPPED)
-		{
-			S_AL_SrcKill(i);
-			continue;
-		}
-
 		// Update source parameters
 		if((s_alGain->modified)||(s_volume->modified))
-			qalSourcef(srcList[i].source, AL_GAIN, s_alGain->value * s_volume->value);
+			qalSourcef(srcList[i].alSource, AL_GAIN, s_alGain->value * s_volume->value);
 		if((s_alRolloff->modified)&&(!srcList[i].local))
-			qalSourcef(srcList[i].source, AL_ROLLOFF_FACTOR, s_alRolloff->value);
+			qalSourcef(srcList[i].alSource, AL_ROLLOFF_FACTOR, s_alRolloff->value);
 		if(s_alMinDistance->modified)
-			qalSourcef(srcList[i].source, AL_REFERENCE_DISTANCE, s_alMinDistance->value);
+			qalSourcef(srcList[i].alSource, AL_REFERENCE_DISTANCE, s_alMinDistance->value);
 
-		ent = srcList[i].entity;
-
-		// If a looping effect hasn't been touched this frame, kill it
-		if(srcList[i].isLooping)
+		if( srcList[ i ].isLooping )
 		{
-			if(!entityList[ent].touched)
+			sentity_t *sent = &entityList[ entityNum ];
+
+			// If a looping effect hasn't been touched this frame, kill it
+			if( sent->loopAddedThisFrame )
 			{
-				ambientCount--;
-				S_AL_SrcKill(i);
+				// The sound has changed without an intervening removal
+				if( srcList[ i ].isActive && !sent->startLoopingSound &&
+						srcList[ i ].sfx != sent->loopSfx )
+				{
+					qalSourceStop( srcList[ i ].alSource );
+					qalSourcei( srcList[ i ].alSource, AL_BUFFER, 0 );
+					sent->startLoopingSound = qtrue;
+				}
+
+				// Ths sound hasn't been started yet
+				if( sent->startLoopingSound )
+				{
+					S_AL_SrcSetup( i, sent->loopSfx, sent->loopPriority,
+							entityNum, -1, qfalse );
+					srcList[ i ].isLooping = qtrue;
+					qalSourcei( srcList[ i ].alSource, AL_LOOPING, AL_TRUE );
+					qalSourcePlay( srcList[ i ].alSource );
+
+					sent->startLoopingSound = qfalse;
+				}
 			}
+			else
+				S_AL_SrcKill( i );
+
 			continue;
 		}
 
 		// See if it needs to be moved
 		if(srcList[i].isTracking)
+			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);
+		if(state == AL_STOPPED)
 		{
-			vec3_t sorigin;
-			VectorScale(entityList[ent].origin, POSITION_SCALE, sorigin);
-			qalSourcefv(srcList[i].source, AL_POSITION, entityList[ent].origin);
+			S_AL_SrcKill(i);
+			continue;
 		}
 	}
 }
@@ -983,7 +998,7 @@
 static
 ALuint S_AL_SrcGet(srcHandle_t src)
 {
-	return srcList[src].source;
+	return srcList[src].alSource;
 }
 
 
@@ -1042,24 +1057,10 @@
 void S_AL_RawSamples(int samples, int rate, int width, int channels, const byte *data, float volume)
 {
 	ALuint buffer;
-	ALuint format = AL_FORMAT_STEREO16;
+	ALuint format;
 	ALint state;
 
-	// Work out AL format
-	if(width == 1)
-	{
-		if(channels == 1)
-			format = AL_FORMAT_MONO8;
-		else if(channels == 2)
-			format = AL_FORMAT_STEREO8;
-	}
-	else if(width == 2)
-	{
-		if(channels == 1)
-			format = AL_FORMAT_MONO16;
-		else if(channels == 2)
-			format = AL_FORMAT_STEREO16;
-	}
+	format = S_AL_Format( width, channels );
 
 	// Create the streamSource if necessary
 	if(streamSourceHandle == -1)
@@ -1408,10 +1409,8 @@
 	float velocity[] = {0.0f, 0.0f, 0.0f};
 	float orientation[] = {axis[0][0], axis[0][1], axis[0][2],
 		axis[2][0], axis[2][1], axis[2][2]};
-		vec3_t sorigin;
 
 	// Set OpenAL listener paramaters
-	VectorScale(origin, POSITION_SCALE, sorigin);
 	qalListenerfv(AL_POSITION, (ALfloat *)origin);
 	qalListenerfv(AL_VELOCITY, velocity);
 	qalListenerfv(AL_ORIENTATION, orientation);
@@ -1561,7 +1560,7 @@
 	}
 
 	// New console variables
-	s_alPrecache = Cvar_Get( "s_alPrecache", "0", CVAR_ARCHIVE );
+	s_alPrecache = Cvar_Get( "s_alPrecache", "1", CVAR_ARCHIVE );
 	s_alGain = Cvar_Get( "s_alGain", "0.4", CVAR_ARCHIVE );
 	s_alSources = Cvar_Get( "s_alSources", "64", CVAR_ARCHIVE );
 	s_alDopplerFactor = Cvar_Get( "s_alDopplerFactor", "1.0", CVAR_ARCHIVE );




More information about the quake3-commits mailing list