From f6613ea144c6ddcbf744b3929d2a175da2b6223d Mon Sep 17 00:00:00 2001 From: tma Date: Thu, 1 Dec 2005 18:22:42 +0000 Subject: * 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 git-svn-id: svn://svn.icculus.org/quake3/trunk@400 edf5b092-35ff-0310-97b2-ce42778d08ea --- code/client/snd_openal.c | 243 +++++++++++++++++++++++------------------------ 1 file changed, 121 insertions(+), 122 deletions(-) (limited to 'code/client/snd_openal.c') diff --git a/code/client/snd_openal.c b/code/client/snd_openal.c index 8e4cbdb..a04ac7e 100644 --- a/code/client/snd_openal.c +++ b/code/client/snd_openal.c @@ -114,7 +114,7 @@ static qboolean alBuffersInitialised = qfalse; // 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 @@ Find a sound effect if loaded, set up a handle otherwise */ 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 @@ static sfxHandle_t S_AL_BufferFind(const char *filename) } } - // Not found in hash table? + // Not found in table? if(sfx == -1) { alSfx_t *ptr; @@ -403,7 +403,7 @@ sfxHandle_t S_AL_RegisterSound( const char *sample, qboolean compressed ) { 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 @@ ALuint S_AL_BufferGet(sfxHandle_t sfx) 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 src_t srcList[MAX_SRC]; 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 srcAllocated; // If a src_t has been allocated to this entity + int srcIndex; - int has_sfx; // Associated sound source - int sfx; - int touched; // Sound present this update? + qboolean loopAddedThisFrame; + alSrcPriority_t loopPriority; + sfxHandle_t loopSfx; + qboolean startLoopingSound; } sentity_t; static sentity_t entityList[MAX_GENTITIES]; @@ -479,7 +481,7 @@ qboolean S_AL_SrcInit( void ) 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 @@ qboolean S_AL_SrcInit( void ) // 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 @@ void S_AL_SrcShutdown( void ) 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 @@ static void S_AL_SrcSetup(srcHandle_t src, sfxHandle_t sfx, alSrcPriority_t prio 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 @@ static void S_AL_SrcKill(srcHandle_t src) // 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 @@ srcHandle_t S_AL_SrcAlloc( alSrcPriority_t priority, int entnum, int channel ) // 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 @@ void S_AL_StartLocalSound(sfxHandle_t sfx, int channel) 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 @@ void S_AL_StartSound( vec3_t origin, int entnum, int entchannel, sfxHandle_t sfx 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 @@ void S_AL_ClearLoopingSounds( qboolean killall ) 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 @@ S_AL_SrcLoop ================= */ 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; - } - 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; + } + + sent->startLoopingSound = 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; - - // Set up the entity - entityList[entnum].has_sfx = qtrue; - entityList[entnum].sfx = src; - need_to_play = qtrue; - } + sent->srcAllocated = qtrue; + sent->srcIndex = src; - // 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); + sent->loopPriority = priority; + sent->loopSfx = sfx; + + // 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 @@ S_AL_StopLoopingSound 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 @@ static 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); - - ent = srcList[i].entity; + qalSourcef(srcList[i].alSource, AL_REFERENCE_DISTANCE, s_alMinDistance->value); - // 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 @@ S_AL_SrcGet static ALuint S_AL_SrcGet(srcHandle_t src) { - return srcList[src].source; + return srcList[src].alSource; } @@ -1042,24 +1057,10 @@ static 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 @@ void S_AL_Respatialize( int entityNum, const vec3_t origin, vec3_t axis[3], int 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 @@ qboolean S_AL_Init( soundInterface_t *si ) } // 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 ); -- cgit v1.2.3