aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorthilo <thilo@edf5b092-35ff-0310-97b2-ce42778d08ea>2009-10-23 12:18:49 +0000
committerthilo <thilo@edf5b092-35ff-0310-97b2-ce42778d08ea>2009-10-23 12:18:49 +0000
commit54c18d9eb3b1fefad46d6ef497787a05cf17d952 (patch)
tree34b01467d21890eec9909c3426db03fbf7379fcb
parent8cae28cd3d9abcb2e33430aabd914d1525daa5bb (diff)
downloadioquake3-aero-54c18d9eb3b1fefad46d6ef497787a05cf17d952.tar.gz
ioquake3-aero-54c18d9eb3b1fefad46d6ef497787a05cf17d952.zip
Synchronize looping ambient sounds (#2984)
git-svn-id: svn://svn.icculus.org/quake3/trunk@1694 edf5b092-35ff-0310-97b2-ce42778d08ea
-rw-r--r--code/client/snd_openal.c135
1 files changed, 108 insertions, 27 deletions
diff --git a/code/client/snd_openal.c b/code/client/snd_openal.c
index 28ba801..9b6bb47 100644
--- a/code/client/snd_openal.c
+++ b/code/client/snd_openal.c
@@ -122,10 +122,13 @@ typedef struct alSfx_s
{
char filename[MAX_QPATH];
ALuint buffer; // OpenAL buffer
- qboolean isDefault; // Couldn't be loaded - use default FX
+ qboolean isDefault; // Couldn't be loaded - use default FX
qboolean inMemory; // Sound is stored in memory
qboolean isLocked; // Sound is locked (can not be unloaded)
int lastUsedTime; // Time last used
+
+ int loopCnt; // number of loops using this sfx
+ int masterLoopSrc; // All other sources looping this buffer are synced to this master src
} alSfx_t;
static qboolean alBuffersInitialised = qfalse;
@@ -485,7 +488,7 @@ typedef struct src_s
int isActive; // Is this source currently in use?
int isLocked; // This is locked (un-allocatable)
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 its owner
float curGain; // gain employed if source is within maxdistance.
float scaleGain; // Last gain value for this source. 0 if muted.
@@ -730,42 +733,91 @@ static void S_AL_SrcSetup(srcHandle_t src, sfxHandle_t sfx, alSrcPriority_t prio
/*
=================
+S_AL_NewLoopMaster
+Remove given source as loop master if it is the master and hand off master status to another source in this case.
+=================
+*/
+
+static void S_AL_NewLoopMaster(src_t *rmSource)
+{
+ int index;
+ src_t *curSource;
+ alSfx_t *curSfx;
+
+ // Only ambient sources get synced anyways.
+ if(rmSource->priority != SRCPRI_AMBIENT)
+ return;
+
+ curSfx = &knownSfx[rmSource->sfx];
+ curSfx->loopCnt--;
+
+ if(rmSource == &srcList[curSfx->masterLoopSrc] && curSfx->loopCnt)
+ {
+ // Only if rmSource was the master and there is still another loop playing will we
+ // need to find a new master.
+
+ for(index = 0; index < srcCount; index++)
+ {
+ curSource = &srcList[index];
+
+ if(curSource->sfx == rmSource->sfx && curSource != rmSource &&
+ curSource->isActive && curSource->isLooping && curSource->priority == SRCPRI_AMBIENT)
+ {
+ curSfx->masterLoopSrc = index;
+ return;
+ }
+ }
+ }
+}
+
+/*
+=================
S_AL_SrcKill
=================
*/
static void S_AL_SrcKill(srcHandle_t src)
{
+ src_t *curSource = &srcList[src];
+
// I'm not touching it. Unlock it first.
- if(srcList[src].isLocked)
+ if(curSource->isLocked)
return;
// Stop it if it's playing
- if(srcList[src].isActive)
- qalSourceStop(srcList[src].alSource);
+ if(curSource->isActive)
+ qalSourceStop(curSource->alSource);
- // Remove the entity association
- if((srcList[src].isLooping) && (srcList[src].entity != -1))
+ // Remove the entity association and loop master status
+ if(curSource->isLooping)
{
- int ent = srcList[src].entity;
- entityList[ent].srcAllocated = qfalse;
- entityList[ent].srcIndex = -1;
- entityList[ent].loopAddedThisFrame = qfalse;
- entityList[ent].startLoopingSound = qfalse;
+ curSource->isLooping = qfalse;
+
+ if(curSource->entity != -1)
+ {
+ sentity_t *curEnt = &entityList[curSource->entity];
+
+ curEnt->srcAllocated = qfalse;
+ curEnt->srcIndex = -1;
+ curEnt->loopAddedThisFrame = qfalse;
+ curEnt->startLoopingSound = qfalse;
+ }
+
+ S_AL_NewLoopMaster(curSource);
}
// Remove the buffer
- qalSourcei(srcList[src].alSource, AL_BUFFER, 0);
-
- srcList[src].sfx = 0;
- srcList[src].lastUsedTime = 0;
- srcList[src].priority = 0;
- srcList[src].entity = -1;
- srcList[src].channel = -1;
- srcList[src].isActive = qfalse;
- srcList[src].isLocked = qfalse;
- srcList[src].isLooping = qfalse;
- srcList[src].isTracking = qfalse;
- srcList[src].local = qfalse;
+ qalSourcei(curSource->alSource, AL_BUFFER, 0);
+
+ curSource->sfx = 0;
+ curSource->lastUsedTime = 0;
+ curSource->priority = 0;
+ curSource->entity = -1;
+ curSource->channel = -1;
+ curSource->isActive = qfalse;
+ curSource->isLocked = qfalse;
+ curSource->isLooping = qfalse;
+ curSource->isTracking = qfalse;
+ curSource->local = qfalse;
}
/*
@@ -1172,9 +1224,9 @@ void S_AL_SrcUpdate( void )
continue;
// Update source parameters
- if((s_alGain->modified)||(s_volume->modified))
+ if((s_alGain->modified) || (s_volume->modified))
curSource->curGain = s_alGain->value * s_volume->value;
- if((s_alRolloff->modified)&&(!curSource->local))
+ if((s_alRolloff->modified) && (!curSource->local))
qalSourcef(curSource->alSource, AL_ROLLOFF_FACTOR, s_alRolloff->value);
if(s_alMinDistance->modified)
qalSourcef(curSource->alSource, AL_REFERENCE_DISTANCE, s_alMinDistance->value);
@@ -1193,6 +1245,8 @@ void S_AL_SrcUpdate( void )
qalSourceStop(curSource->alSource);
qalSourcei(curSource->alSource, AL_BUFFER, 0);
sent->startLoopingSound = qtrue;
+
+ S_AL_NewLoopMaster(curSource);
}
// The sound hasn't been started yet
@@ -1201,6 +1255,28 @@ void S_AL_SrcUpdate( void )
S_AL_SrcSetup(i, sent->loopSfx, sent->loopPriority,
entityNum, -1, curSource->local);
curSource->isLooping = qtrue;
+
+ if(curSource->priority == SRCPRI_AMBIENT)
+ {
+ alSfx_t *curSfx = &knownSfx[curSource->sfx];
+
+ // If there are other ambient looping sources with the same sound,
+ // make sure the sound of these sources are in sync.
+
+ if(curSfx->loopCnt)
+ {
+ int offset;
+
+ // we already have a master loop playing, get buffer position.
+ qalGetSourcei(srcList[curSfx->masterLoopSrc].alSource, AL_SAMPLE_OFFSET, &offset);
+ qalSourcei(curSource->alSource, AL_SAMPLE_OFFSET, offset);
+ }
+ else
+ curSfx->masterLoopSrc = i; // This is now the new master source.
+
+ curSfx->loopCnt++;
+ }
+
qalSourcei(curSource->alSource, AL_LOOPING, AL_TRUE);
qalSourcePlay(curSource->alSource);
@@ -1218,9 +1294,14 @@ void S_AL_SrcUpdate( void )
qalSourcei(curSource->alSource, AL_SOURCE_RELATIVE, AL_FALSE);
qalSourcef(curSource->alSource, AL_ROLLOFF_FACTOR, s_alRolloff->value);
}
+
+// qalSourcef(curSource->alSource, AL_GAIN, curSource->curGain);
}
else
- S_AL_SrcKill( i );
+ {
+// qalSourcef(curSource->alSource, AL_GAIN, 0.0f);
+ S_AL_SrcKill(i);
+ }
continue;
}