Synchronize looping ambient sounds (#2984)

This commit is contained in:
Thilo Schulz 2009-10-23 12:18:49 +00:00
parent c05d9c9f0c
commit d12751f62b

View file

@ -122,10 +122,13 @@ typedef struct alSfx_s
{ {
char filename[MAX_QPATH]; char filename[MAX_QPATH];
ALuint buffer; // OpenAL buffer 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 inMemory; // Sound is stored in memory
qboolean isLocked; // Sound is locked (can not be unloaded) qboolean isLocked; // Sound is locked (can not be unloaded)
int lastUsedTime; // Time last used 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; } alSfx_t;
static qboolean alBuffersInitialised = qfalse; static qboolean alBuffersInitialised = qfalse;
@ -485,7 +488,7 @@ typedef struct src_s
int isActive; // Is this source currently in use? int isActive; // Is this source currently in use?
int isLocked; // This is locked (un-allocatable) int isLocked; // This is locked (un-allocatable)
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 its owner
float curGain; // gain employed if source is within maxdistance. float curGain; // gain employed if source is within maxdistance.
float scaleGain; // Last gain value for this source. 0 if muted. float scaleGain; // Last gain value for this source. 0 if muted.
@ -728,6 +731,45 @@ 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 S_AL_SrcKill
@ -735,37 +777,47 @@ S_AL_SrcKill
*/ */
static void S_AL_SrcKill(srcHandle_t src) static void S_AL_SrcKill(srcHandle_t src)
{ {
src_t *curSource = &srcList[src];
// I'm not touching it. Unlock it first. // I'm not touching it. Unlock it first.
if(srcList[src].isLocked) if(curSource->isLocked)
return; return;
// Stop it if it's playing // Stop it if it's playing
if(srcList[src].isActive) if(curSource->isActive)
qalSourceStop(srcList[src].alSource); qalSourceStop(curSource->alSource);
// Remove the entity association // Remove the entity association and loop master status
if((srcList[src].isLooping) && (srcList[src].entity != -1)) if(curSource->isLooping)
{ {
int ent = srcList[src].entity; curSource->isLooping = qfalse;
entityList[ent].srcAllocated = qfalse;
entityList[ent].srcIndex = -1; if(curSource->entity != -1)
entityList[ent].loopAddedThisFrame = qfalse; {
entityList[ent].startLoopingSound = qfalse; 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 // Remove the buffer
qalSourcei(srcList[src].alSource, AL_BUFFER, 0); qalSourcei(curSource->alSource, AL_BUFFER, 0);
srcList[src].sfx = 0; curSource->sfx = 0;
srcList[src].lastUsedTime = 0; curSource->lastUsedTime = 0;
srcList[src].priority = 0; curSource->priority = 0;
srcList[src].entity = -1; curSource->entity = -1;
srcList[src].channel = -1; curSource->channel = -1;
srcList[src].isActive = qfalse; curSource->isActive = qfalse;
srcList[src].isLocked = qfalse; curSource->isLocked = qfalse;
srcList[src].isLooping = qfalse; curSource->isLooping = qfalse;
srcList[src].isTracking = qfalse; curSource->isTracking = qfalse;
srcList[src].local = qfalse; curSource->local = qfalse;
} }
/* /*
@ -1172,9 +1224,9 @@ void S_AL_SrcUpdate( void )
continue; continue;
// Update source parameters // 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; 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); qalSourcef(curSource->alSource, AL_ROLLOFF_FACTOR, s_alRolloff->value);
if(s_alMinDistance->modified) if(s_alMinDistance->modified)
qalSourcef(curSource->alSource, AL_REFERENCE_DISTANCE, s_alMinDistance->value); qalSourcef(curSource->alSource, AL_REFERENCE_DISTANCE, s_alMinDistance->value);
@ -1193,6 +1245,8 @@ void S_AL_SrcUpdate( void )
qalSourceStop(curSource->alSource); qalSourceStop(curSource->alSource);
qalSourcei(curSource->alSource, AL_BUFFER, 0); qalSourcei(curSource->alSource, AL_BUFFER, 0);
sent->startLoopingSound = qtrue; sent->startLoopingSound = qtrue;
S_AL_NewLoopMaster(curSource);
} }
// The sound hasn't been started yet // The sound hasn't been started yet
@ -1201,6 +1255,28 @@ void S_AL_SrcUpdate( void )
S_AL_SrcSetup(i, sent->loopSfx, sent->loopPriority, S_AL_SrcSetup(i, sent->loopSfx, sent->loopPriority,
entityNum, -1, curSource->local); entityNum, -1, curSource->local);
curSource->isLooping = qtrue; 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); qalSourcei(curSource->alSource, AL_LOOPING, AL_TRUE);
qalSourcePlay(curSource->alSource); qalSourcePlay(curSource->alSource);
@ -1218,9 +1294,14 @@ void S_AL_SrcUpdate( void )
qalSourcei(curSource->alSource, AL_SOURCE_RELATIVE, AL_FALSE); qalSourcei(curSource->alSource, AL_SOURCE_RELATIVE, AL_FALSE);
qalSourcef(curSource->alSource, AL_ROLLOFF_FACTOR, s_alRolloff->value); qalSourcef(curSource->alSource, AL_ROLLOFF_FACTOR, s_alRolloff->value);
} }
// qalSourcef(curSource->alSource, AL_GAIN, curSource->curGain);
} }
else else
S_AL_SrcKill( i ); {
// qalSourcef(curSource->alSource, AL_GAIN, 0.0f);
S_AL_SrcKill(i);
}
continue; continue;
} }